1 /* $NetBSD: linux_socketcall.c,v 1.12 1995/10/07 06:27:13 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Frank van der Linden 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the NetBSD Project 18 * by Frank van der Linden 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/kernel.h> 36 #include <sys/systm.h> 37 #include <sys/buf.h> 38 #include <sys/malloc.h> 39 #include <sys/ioctl.h> 40 #include <sys/tty.h> 41 #include <sys/file.h> 42 #include <sys/filedesc.h> 43 #include <sys/select.h> 44 #include <sys/socket.h> 45 #include <sys/socketvar.h> 46 #include <net/if.h> 47 #include <netinet/in.h> 48 #include <netinet/tcp.h> 49 #include <sys/mount.h> 50 #include <sys/proc.h> 51 #include <sys/vnode.h> 52 #include <sys/device.h> 53 54 #include <sys/syscallargs.h> 55 56 #include <compat/linux/linux_types.h> 57 #include <compat/linux/linux_util.h> 58 #include <compat/linux/linux_signal.h> 59 #include <compat/linux/linux_syscallargs.h> 60 #include <compat/linux/linux_ioctl.h> 61 #include <compat/linux/linux_socket.h> 62 #include <compat/linux/linux_socketcall.h> 63 #include <compat/linux/linux_sockio.h> 64 65 /* 66 * All the calls in this file are entered via one common system 67 * call in Linux, represented here by linux_socketcall() 68 * Arguments for the various calls are on the user stack. A pointer 69 * to them is the only thing that is passed. It is up to the various 70 * calls to copy them in themselves. To make it look better, they 71 * are copied to structures. 72 */ 73 74 /* 75 * Convert between Linux and BSD socket domain values 76 */ 77 int 78 linux_to_bsd_domain(ldom) 79 int ldom; 80 { 81 82 switch (ldom) { 83 case LINUX_AF_UNSPEC: 84 return AF_UNSPEC; 85 case LINUX_AF_UNIX: 86 return AF_LOCAL; 87 case LINUX_AF_INET: 88 return AF_INET; 89 case LINUX_AF_AX25: 90 return AF_CCITT; 91 case LINUX_AF_IPX: 92 return AF_IPX; 93 case LINUX_AF_APPLETALK: 94 return AF_APPLETALK; 95 default: 96 return -1; 97 } 98 } 99 100 int 101 linux_socket(p, uap, retval) 102 struct proc *p; 103 struct linux_socket_args /* { 104 syscallarg(int) domain; 105 syscallarg(int) type; 106 syscallarg(int) protocol; 107 } */ *uap; 108 register_t *retval; 109 { 110 struct linux_socket_args lsa; 111 struct sys_socket_args bsa; 112 int error; 113 114 if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa))) 115 return error; 116 117 SCARG(&bsa, protocol) = lsa.protocol; 118 SCARG(&bsa, type) = lsa.type; 119 SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain); 120 if (SCARG(&bsa, domain) == -1) 121 return EINVAL; 122 return sys_socket(p, &bsa, retval); 123 } 124 125 int 126 linux_bind(p, uap, retval) 127 struct proc *p; 128 struct linux_bind_args /* { 129 syscallarg(int) s; 130 syscallarg(struct sockaddr *) name; 131 syscallarg(int) namelen; 132 } */ *uap; 133 register_t *retval; 134 { 135 struct linux_bind_args lba; 136 struct sys_bind_args bba; 137 int error; 138 139 if ((error = copyin((caddr_t) uap, (caddr_t) &lba, sizeof lba))) 140 return error; 141 142 SCARG(&bba, s) = lba.s; 143 SCARG(&bba, name) = (caddr_t) lba.name; 144 SCARG(&bba, namelen) = lba.namelen; 145 146 return sys_bind(p, &bba, retval); 147 } 148 149 int 150 linux_connect(p, uap, retval) 151 struct proc *p; 152 struct linux_connect_args /* { 153 syscallarg(int) s; 154 syscallarg(struct sockaddr *) name; 155 syscallarg(int) namelen; 156 } */ *uap; 157 register_t *retval; 158 { 159 struct linux_connect_args lca; 160 struct sys_connect_args bca; 161 int error; 162 163 if ((error = copyin((caddr_t) uap, (caddr_t) &lca, sizeof lca))) 164 return error; 165 166 SCARG(&bca, s) = lca.s; 167 SCARG(&bca, name) = (caddr_t) lca.name; 168 SCARG(&bca, namelen) = lca.namelen; 169 170 return sys_connect(p, &bca, retval); 171 } 172 173 int 174 linux_listen(p, uap, retval) 175 struct proc *p; 176 struct linux_listen_args /* { 177 syscallarg(int) s; 178 syscallarg(int) backlog; 179 } */ *uap; 180 register_t *retval; 181 { 182 struct linux_listen_args lla; 183 struct sys_listen_args bla; 184 int error; 185 186 if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla))) 187 return error; 188 189 SCARG(&bla, s) = lla.s; 190 SCARG(&bla, backlog) = lla.backlog; 191 192 return sys_listen(p, &bla, retval); 193 } 194 195 int 196 linux_accept(p, uap, retval) 197 struct proc *p; 198 struct linux_accept_args /* { 199 syscallarg(int) s; 200 syscallarg(struct sockaddr *) addr; 201 syscallarg(int *) namelen; 202 } */ *uap; 203 register_t *retval; 204 { 205 struct linux_accept_args laa; 206 struct compat_43_sys_accept_args baa; 207 int error; 208 209 if ((error = copyin((caddr_t) uap, (caddr_t) &laa, sizeof laa))) 210 return error; 211 212 SCARG(&baa, s) = laa.s; 213 SCARG(&baa, name) = (caddr_t) laa.addr; 214 SCARG(&baa, anamelen) = laa.namelen; 215 216 return compat_43_sys_accept(p, &baa, retval); 217 } 218 219 int 220 linux_getsockname(p, uap, retval) 221 struct proc *p; 222 struct linux_getsockname_args /* { 223 syscallarg(int) s; 224 syscallarg(struct sockaddr *) addr; 225 syscallarg(int *) namelen; 226 } */ *uap; 227 register_t *retval; 228 { 229 struct linux_getsockname_args lga; 230 struct compat_43_sys_getsockname_args bga; 231 int error; 232 233 if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga))) 234 return error; 235 236 SCARG(&bga, fdec) = lga.s; 237 SCARG(&bga, asa) = (caddr_t) lga.addr; 238 SCARG(&bga, alen) = lga.namelen; 239 240 return compat_43_sys_getsockname(p, &bga, retval); 241 } 242 243 int 244 linux_getpeername(p, uap, retval) 245 struct proc *p; 246 struct linux_getpeername_args /* { 247 syscallarg(int) s; 248 syscallarg(struct sockaddr *) addr; 249 syscallarg(int *) namelen; 250 } */ *uap; 251 register_t *retval; 252 { 253 struct linux_getpeername_args lga; 254 struct compat_43_sys_getpeername_args bga; 255 int error; 256 257 if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga))) 258 return error; 259 260 SCARG(&bga, fdes) = lga.s; 261 SCARG(&bga, asa) = (caddr_t) lga.addr; 262 SCARG(&bga, alen) = lga.namelen; 263 264 return compat_43_sys_getpeername(p, &bga, retval); 265 } 266 267 int 268 linux_socketpair(p, uap, retval) 269 struct proc *p; 270 struct linux_socketpair_args /* { 271 syscallarg(int) domain; 272 syscallarg(int) type; 273 syscallarg(int) protocol; 274 syscallarg(int *) rsv; 275 } */ *uap; 276 register_t *retval; 277 { 278 struct linux_socketpair_args lsa; 279 struct sys_socketpair_args bsa; 280 int error; 281 282 if ((error = copyin((caddr_t) uap, &lsa, sizeof lsa))) 283 return error; 284 285 SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain); 286 if (SCARG(&bsa, domain) == -1) 287 return EINVAL; 288 SCARG(&bsa, type) = lsa.type; 289 SCARG(&bsa, protocol) = lsa.protocol; 290 SCARG(&bsa, rsv) = lsa.rsv; 291 292 return sys_socketpair(p, &bsa, retval); 293 } 294 295 int 296 linux_send(p, uap, retval) 297 struct proc *p; 298 struct linux_send_args /* { 299 syscallarg(int) s; 300 syscallarg(void *) msg; 301 syscallarg(int) len; 302 syscallarg(int) flags; 303 } */ *uap; 304 register_t *retval; 305 { 306 struct linux_send_args lsa; 307 struct compat_43_sys_send_args bsa; 308 int error; 309 310 if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa))) 311 return error; 312 313 SCARG(&bsa, s) = lsa.s; 314 SCARG(&bsa, buf) = lsa.msg; 315 SCARG(&bsa, len) = lsa.len; 316 SCARG(&bsa, flags) = lsa.flags; 317 318 return compat_43_sys_send(p, &bsa, retval); 319 } 320 321 int 322 linux_recv(p, uap, retval) 323 struct proc *p; 324 struct linux_recv_args /* { 325 syscallarg(int) s; 326 syscallarg(void *) msg; 327 syscallarg(int) len; 328 syscallarg(int) flags; 329 } */ *uap; 330 register_t *retval; 331 { 332 struct linux_recv_args lra; 333 struct compat_43_sys_recv_args bra; 334 int error; 335 336 if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra))) 337 return error; 338 339 SCARG(&bra, s) = lra.s; 340 SCARG(&bra, buf) = lra.msg; 341 SCARG(&bra, len) = lra.len; 342 SCARG(&bra, flags) = lra.flags; 343 344 return compat_43_sys_recv(p, &bra, retval); 345 } 346 347 int 348 linux_sendto(p, uap, retval) 349 struct proc *p; 350 struct linux_sendto_args /* { 351 syscallarg(int) s; 352 syscallarg(void *) msg; 353 syscallarg(int) len; 354 syscallarg(int) flags; 355 syscallarg(sockaddr *) to; 356 syscallarg(int) tolen; 357 } */ *uap; 358 register_t *retval; 359 { 360 struct linux_sendto_args lsa; 361 struct sys_sendto_args bsa; 362 int error; 363 364 if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa))) 365 return error; 366 367 SCARG(&bsa, s) = lsa.s; 368 SCARG(&bsa, buf) = lsa.msg; 369 SCARG(&bsa, len) = lsa.len; 370 SCARG(&bsa, flags) = lsa.flags; 371 SCARG(&bsa, to) = (caddr_t) lsa.to; 372 SCARG(&bsa, tolen) = lsa.tolen; 373 374 return sys_sendto(p, &bsa, retval); 375 } 376 377 int 378 linux_recvfrom(p, uap, retval) 379 struct proc *p; 380 struct linux_recvfrom_args /* { 381 syscallarg(int) s; 382 syscallarg(void *) buf; 383 syscallarg(int) len; 384 syscallarg(int) flags; 385 syscallarg(struct sockaddr *) from; 386 syscallarg(int *) fromlen; 387 } */ *uap; 388 register_t *retval; 389 { 390 struct linux_recvfrom_args lra; 391 struct compat_43_sys_recvfrom_args bra; 392 int error; 393 394 if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra))) 395 return error; 396 397 SCARG(&bra, s) = lra.s; 398 SCARG(&bra, buf) = lra.buf; 399 SCARG(&bra, len) = lra.len; 400 SCARG(&bra, flags) = lra.flags; 401 SCARG(&bra, from) = (caddr_t) lra.from; 402 SCARG(&bra, fromlenaddr) = lra.fromlen; 403 404 return compat_43_sys_recvfrom(p, &bra, retval); 405 } 406 407 int 408 linux_shutdown(p, uap, retval) 409 struct proc *p; 410 struct linux_shutdown_args /* { 411 syscallarg(int) s; 412 syscallarg(int) how; 413 } */ *uap; 414 register_t *retval; 415 { 416 struct linux_shutdown_args lsa; 417 struct sys_shutdown_args bsa; 418 int error; 419 420 if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa))) 421 return error; 422 423 SCARG(&bsa, s) = lsa.s; 424 SCARG(&bsa, how) = lsa.how; 425 426 return sys_shutdown(p, &bsa, retval); 427 } 428 429 /* 430 * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET 431 * is different, the rest matches IPPROTO_* on both systems. 432 */ 433 int 434 linux_to_bsd_sopt_level(llevel) 435 int llevel; 436 { 437 438 switch (llevel) { 439 case LINUX_SOL_SOCKET: 440 return SOL_SOCKET; 441 case LINUX_SOL_IP: 442 return IPPROTO_IP; 443 case LINUX_SOL_TCP: 444 return IPPROTO_TCP; 445 case LINUX_SOL_UDP: 446 return IPPROTO_UDP; 447 default: 448 return -1; 449 } 450 } 451 452 /* 453 * Convert Linux socket level socket option numbers to NetBSD values. 454 */ 455 int 456 linux_to_bsd_so_sockopt(lopt) 457 int lopt; 458 { 459 460 switch (lopt) { 461 case LINUX_SO_DEBUG: 462 return SO_DEBUG; 463 case LINUX_SO_REUSEADDR: 464 return SO_REUSEADDR; 465 case LINUX_SO_TYPE: 466 return SO_TYPE; 467 case LINUX_SO_ERROR: 468 return SO_ERROR; 469 case LINUX_SO_DONTROUTE: 470 return SO_DONTROUTE; 471 case LINUX_SO_BROADCAST: 472 return SO_BROADCAST; 473 case LINUX_SO_SNDBUF: 474 return SO_SNDBUF; 475 case LINUX_SO_RCVBUF: 476 return SO_RCVBUF; 477 case LINUX_SO_KEEPALIVE: 478 return SO_KEEPALIVE; 479 case LINUX_SO_OOBINLINE: 480 return SO_OOBINLINE; 481 case LINUX_SO_LINGER: 482 return SO_LINGER; 483 case LINUX_SO_PRIORITY: 484 case LINUX_SO_NO_CHECK: 485 default: 486 return -1; 487 } 488 } 489 490 /* 491 * Convert Linux IP level socket option number to NetBSD values. 492 */ 493 int 494 linux_to_bsd_ip_sockopt(lopt) 495 int lopt; 496 { 497 498 switch (lopt) { 499 case LINUX_IP_TOS: 500 return IP_TOS; 501 case LINUX_IP_TTL: 502 return IP_TTL; 503 case LINUX_IP_MULTICAST_TTL: 504 return IP_MULTICAST_TTL; 505 case LINUX_IP_MULTICAST_LOOP: 506 return IP_MULTICAST_LOOP; 507 case LINUX_IP_MULTICAST_IF: 508 return IP_MULTICAST_IF; 509 case LINUX_IP_ADD_MEMBERSHIP: 510 return IP_ADD_MEMBERSHIP; 511 case LINUX_IP_DROP_MEMBERSHIP: 512 return IP_DROP_MEMBERSHIP; 513 default: 514 return -1; 515 } 516 } 517 518 /* 519 * Convert Linux TCP level socket option number to NetBSD values. 520 */ 521 int 522 linux_to_bsd_tcp_sockopt(lopt) 523 int lopt; 524 { 525 526 switch (lopt) { 527 case LINUX_TCP_NODELAY: 528 return TCP_NODELAY; 529 case LINUX_TCP_MAXSEG: 530 return TCP_MAXSEG; 531 default: 532 return -1; 533 } 534 } 535 536 /* 537 * Convert Linux UDP level socket option number to NetBSD values. 538 */ 539 int 540 linux_to_bsd_udp_sockopt(lopt) 541 int lopt; 542 { 543 544 switch (lopt) { 545 default: 546 return -1; 547 } 548 } 549 550 /* 551 * Another reasonably straightforward function: setsockopt(2). 552 * The level and option numbers are converted; the values passed 553 * are not (yet) converted, the ones currently implemented don't 554 * need conversion, as they are the same on both systems. 555 */ 556 int 557 linux_setsockopt(p, uap, retval) 558 struct proc *p; 559 struct linux_setsockopt_args /* { 560 syscallarg(int) s; 561 syscallarg(int) level; 562 syscallarg(int) optname; 563 syscallarg(void *) optval; 564 syscallarg(int) optlen; 565 } */ *uap; 566 register_t *retval; 567 { 568 struct linux_setsockopt_args lsa; 569 struct sys_setsockopt_args bsa; 570 int error, name; 571 572 if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa))) 573 return error; 574 575 SCARG(&bsa, s) = lsa.s; 576 SCARG(&bsa, level) = linux_to_bsd_sopt_level(lsa.level); 577 SCARG(&bsa, val) = lsa.optval; 578 SCARG(&bsa, valsize) = lsa.optlen; 579 580 switch (SCARG(&bsa, level)) { 581 case SOL_SOCKET: 582 name = linux_to_bsd_so_sockopt(lsa.optname); 583 break; 584 case IPPROTO_IP: 585 name = linux_to_bsd_ip_sockopt(lsa.optname); 586 break; 587 case IPPROTO_TCP: 588 name = linux_to_bsd_tcp_sockopt(lsa.optname); 589 break; 590 case IPPROTO_UDP: 591 name = linux_to_bsd_udp_sockopt(lsa.optname); 592 break; 593 default: 594 return EINVAL; 595 } 596 597 if (name == -1) 598 return EINVAL; 599 SCARG(&bsa, name) = name; 600 601 return sys_setsockopt(p, &bsa, retval); 602 } 603 604 /* 605 * getsockopt(2) is very much the same as setsockopt(2) (see above) 606 */ 607 int 608 linux_getsockopt(p, uap, retval) 609 struct proc *p; 610 struct linux_getsockopt_args /* { 611 syscallarg(int) s; 612 syscallarg(int) level; 613 syscallarg(int) optname; 614 syscallarg(void *) optval; 615 syscallarg(int) *optlen; 616 } */ *uap; 617 register_t *retval; 618 { 619 struct linux_getsockopt_args lga; 620 struct sys_getsockopt_args bga; 621 int error, name; 622 623 if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga))) 624 return error; 625 626 SCARG(&bga, s) = lga.s; 627 SCARG(&bga, level) = linux_to_bsd_sopt_level(lga.level); 628 SCARG(&bga, val) = lga.optval; 629 SCARG(&bga, avalsize) = lga.optlen; 630 631 switch (SCARG(&bga, level)) { 632 case SOL_SOCKET: 633 name = linux_to_bsd_so_sockopt(lga.optname); 634 break; 635 case IPPROTO_IP: 636 name = linux_to_bsd_ip_sockopt(lga.optname); 637 break; 638 case IPPROTO_TCP: 639 name = linux_to_bsd_tcp_sockopt(lga.optname); 640 break; 641 case IPPROTO_UDP: 642 name = linux_to_bsd_udp_sockopt(lga.optname); 643 break; 644 default: 645 return EINVAL; 646 } 647 648 if (name == -1) 649 return EINVAL; 650 SCARG(&bga, name) = name; 651 652 return sys_getsockopt(p, &bga, retval); 653 } 654 655 /* 656 * Entry point to all Linux socket calls. Just check which call to 657 * make and take appropriate action. 658 */ 659 int 660 linux_sys_socketcall(p, v, retval) 661 struct proc *p; 662 void *v; 663 register_t *retval; 664 { 665 struct linux_sys_socketcall_args /* { 666 syscallarg(int) what; 667 syscallarg(void *) args; 668 } */ *uap = v; 669 670 switch (SCARG(uap, what)) { 671 case LINUX_SYS_socket: 672 return linux_socket(p, SCARG(uap, args), retval); 673 case LINUX_SYS_bind: 674 return linux_bind(p, SCARG(uap, args), retval); 675 case LINUX_SYS_connect: 676 return linux_connect(p, SCARG(uap, args), retval); 677 case LINUX_SYS_listen: 678 return linux_listen(p, SCARG(uap, args), retval); 679 case LINUX_SYS_accept: 680 return linux_accept(p, SCARG(uap, args), retval); 681 case LINUX_SYS_getsockname: 682 return linux_getsockname(p, SCARG(uap, args), retval); 683 case LINUX_SYS_getpeername: 684 return linux_getpeername(p, SCARG(uap, args), retval); 685 case LINUX_SYS_socketpair: 686 return linux_socketpair(p, SCARG(uap, args), retval); 687 case LINUX_SYS_send: 688 return linux_send(p, SCARG(uap, args), retval); 689 case LINUX_SYS_recv: 690 return linux_recv(p, SCARG(uap, args), retval); 691 case LINUX_SYS_sendto: 692 return linux_sendto(p, SCARG(uap, args), retval); 693 case LINUX_SYS_recvfrom: 694 return linux_recvfrom(p, SCARG(uap, args), retval); 695 case LINUX_SYS_shutdown: 696 return linux_shutdown(p, SCARG(uap, args), retval); 697 case LINUX_SYS_setsockopt: 698 return linux_setsockopt(p, SCARG(uap, args), retval); 699 case LINUX_SYS_getsockopt: 700 return linux_getsockopt(p, SCARG(uap, args), retval); 701 default: 702 return ENOSYS; 703 } 704 } 705