1 /* $NetBSD: linux_socketcall.c,v 1.1 1995/02/28 23:25:17 fvdl 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 <sys/mount.h> 49 #include <sys/proc.h> 50 #include <sys/vnode.h> 51 #include <sys/device.h> 52 53 #include <sys/syscallargs.h> 54 55 #include <compat/linux/linux_types.h> 56 #include <compat/linux/linux_util.h> 57 #include <compat/linux/linux_syscallargs.h> 58 #include <compat/linux/linux_ioctl.h> 59 #include <compat/linux/linux_socket.h> 60 #include <compat/linux/linux_socketcall.h> 61 #include <compat/linux/linux_sockio.h> 62 63 /* 64 * All the calls in this file are entered via one common system 65 * call in Linux, represented here by linux_socketcall() 66 * Arguments for the various calls are on the user stack. A pointer 67 * to them is the only thing that is passed. It is up to the various 68 * calls to copy them in themselves. To make it look better, they 69 * are copied to structures. 70 */ 71 72 /* 73 * Convert between Linux and BSD socket domain values 74 */ 75 static int 76 linux_to_bsd_domain(ldom) 77 int ldom; 78 { 79 switch (ldom) { 80 case LINUX_AF_UNSPEC: 81 return AF_UNSPEC; 82 case LINUX_AF_UNIX: 83 return AF_LOCAL; 84 case LINUX_AF_INET: 85 return AF_INET; 86 case LINUX_AF_AX25: 87 return AF_CCITT; 88 case LINUX_AF_IPX: 89 return AF_IPX; 90 case LINUX_AF_APPLETALK: 91 return AF_APPLETALK; 92 default: 93 return -1; 94 } 95 } 96 97 static int 98 linux_socket(p, args, retval) 99 struct proc *p; 100 struct linux_socket_args /* { 101 syscallarg(int) domain; 102 syscallarg(int) type; 103 syscallarg(int) protocol; 104 } */ *args; 105 register_t *retval; 106 { 107 struct linux_socket_args lsa; 108 struct socket_args bsa; 109 int error; 110 111 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa))) 112 return error; 113 114 SCARG(&bsa, protocol) = lsa.protocol; 115 SCARG(&bsa, type) = lsa.type; 116 SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain); 117 if (SCARG(&bsa, domain) == -1) 118 return EINVAL; 119 return socket(p, &bsa, retval); 120 } 121 122 static int 123 linux_bind(p, args, retval) 124 struct proc *p; 125 struct linux_bind_args /* { 126 syscallarg(int) s; 127 syscallarg(struct sockaddr *) name; 128 syscallarg(int) namelen; 129 } */ *args; 130 register_t *retval; 131 { 132 struct linux_bind_args lba; 133 struct bind_args bba; 134 int error; 135 136 if ((error = copyin((caddr_t) args, (caddr_t) &lba, sizeof lba))) 137 return error; 138 139 SCARG(&bba, s) = lba.s; 140 SCARG(&bba, name) = (caddr_t) lba.name; 141 SCARG(&bba, namelen) = lba.namelen; 142 143 return bind(p, &bba, retval); 144 } 145 146 static int 147 linux_connect(p, args, retval) 148 struct proc *p; 149 struct linux_connect_args /* { 150 syscallarg(int) s; 151 syscallarg(struct sockaddr *) name; 152 syscallarg(int) namelen; 153 } */ *args; 154 register_t *retval; 155 { 156 struct linux_connect_args lca; 157 struct connect_args bca; 158 int error; 159 160 if ((error = copyin((caddr_t) args, (caddr_t) &lca, sizeof lca))) 161 return error; 162 163 SCARG(&bca, s) = lca.s; 164 SCARG(&bca, name) = (caddr_t) lca.name; 165 SCARG(&bca, namelen) = lca.namelen; 166 167 return connect(p, &bca, retval); 168 } 169 170 static int 171 linux_listen(p, args, retval) 172 struct proc *p; 173 struct linux_listen_args /* { 174 syscallarg(int) s; 175 syscallarg(int) backlog; 176 } */ *args; 177 register *retval; 178 { 179 struct linux_listen_args lla; 180 struct listen_args bla; 181 int error; 182 183 if ((error = copyin((caddr_t) args, (caddr_t) &lla, sizeof lla))) 184 return error; 185 186 SCARG(&bla, s) = lla.s; 187 SCARG(&bla, backlog) = lla.backlog; 188 189 return listen(p, &bla, retval); 190 } 191 192 static int 193 linux_accept(p, args, retval) 194 struct proc *p; 195 struct linux_accept_args /* { 196 syscallarg(int) s; 197 syscallarg(struct sockaddr *) addr; 198 syscallarg(int *) namelen; 199 } */ *args; 200 register_t *retval; 201 { 202 struct linux_accept_args laa; 203 struct compat_43_accept_args baa; 204 int error; 205 206 if ((error = copyin((caddr_t) args, (caddr_t) &laa, sizeof laa))) 207 return error; 208 209 SCARG(&baa, s) = laa.s; 210 SCARG(&baa, name) = (caddr_t) laa.addr; 211 SCARG(&baa, anamelen) = laa.namelen; 212 213 return compat_43_accept(p, &baa, retval); 214 } 215 216 static int 217 linux_getsockname(p, args, retval) 218 struct proc *p; 219 struct linux_getsockname_args /* { 220 syscallarg(int) s; 221 syscallarg(struct sockaddr *) addr; 222 syscallarg(int *) namelen; 223 } */ *args; 224 register_t *retval; 225 { 226 struct linux_getsockname_args lga; 227 struct compat_43_getsockname_args bga; 228 int error; 229 230 if ((error = copyin((caddr_t) args, (caddr_t) &lga, sizeof lga))) 231 return error; 232 233 SCARG(&bga, fdec) = lga.s; 234 SCARG(&bga, asa) = (caddr_t) lga.addr; 235 SCARG(&bga, alen) = lga.namelen; 236 237 return compat_43_getsockname(p, &bga, retval); 238 } 239 240 static int 241 linux_getpeername(p, args, retval) 242 struct proc *p; 243 struct linux_getpeername_args /* { 244 syscallarg(int) s; 245 syscallarg(struct sockaddr *) addr; 246 syscallarg(int *) namelen; 247 } */ *args; 248 register_t *retval; 249 { 250 struct linux_getpeername_args lga; 251 struct compat_43_getpeername_args bga; 252 int error; 253 254 if ((error = copyin((caddr_t) args, (caddr_t) &lga, sizeof lga))) 255 return error; 256 257 SCARG(&bga, fdes) = lga.s; 258 SCARG(&bga, asa) = (caddr_t) lga.addr; 259 SCARG(&bga, alen) = lga.namelen; 260 261 return compat_43_getpeername(p, &bga, retval); 262 } 263 264 static int 265 linux_socketpair(p, args, retval) 266 struct proc *p; 267 struct linux_socketpair_args /* { 268 syscallarg(int) domain; 269 syscallarg(int) type; 270 syscallarg(int) protocol; 271 syscallarg(int *) rsv; 272 } */ *args; 273 register_t *retval; 274 { 275 struct linux_socketpair_args lsa; 276 struct socketpair_args bsa; 277 int error; 278 279 if ((error = copyin((caddr_t) args, &lsa, sizeof lsa))) 280 return error; 281 282 SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain); 283 if (SCARG(&bsa, domain) == -1) 284 return EINVAL; 285 SCARG(&bsa, type) = lsa.type; 286 SCARG(&bsa, protocol) = lsa.protocol; 287 SCARG(&bsa, rsv) = lsa.rsv; 288 289 return socketpair(p, &bsa, retval); 290 } 291 292 static int 293 linux_send(p, args, retval) 294 struct proc *p; 295 struct linux_send_args /* { 296 syscallarg(int) s; 297 syscallarg(void *) msg; 298 syscallarg(int) len; 299 syscallarg(int) flags; 300 } */ *args; 301 register_t *retval; 302 { 303 struct linux_send_args lsa; 304 struct compat_43_send_args bsa; 305 int error; 306 307 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa))) 308 return error; 309 310 SCARG(&bsa, s) = lsa.s; 311 SCARG(&bsa, buf) = lsa.msg; 312 SCARG(&bsa, len) = lsa.len; 313 SCARG(&bsa, flags) = lsa.flags; 314 315 return compat_43_send(p, &bsa, retval); 316 } 317 318 static int 319 linux_recv(p, args, retval) 320 struct proc *p; 321 struct linux_recv_args *args; 322 register_t *retval; 323 { 324 struct linux_recv_args lra; 325 struct compat_43_recv_args bra; 326 int error; 327 328 if ((error = copyin((caddr_t) args, (caddr_t) &lra, sizeof lra))) 329 return error; 330 331 SCARG(&bra, s) = lra.s; 332 SCARG(&bra, buf) = lra.msg; 333 SCARG(&bra, len) = lra.len; 334 SCARG(&bra, flags) = lra.flags; 335 336 return compat_43_recv(p, &bra, retval); 337 } 338 339 static int 340 linux_sendto(p, args, retval) 341 struct proc *p; 342 struct linux_sendto_args /* { 343 syscallarg(int) s; 344 syscallarg(void *) msg; 345 syscallarg(int) len; 346 syscallarg(int) flags; 347 syscallarg(sockaddr *) to; 348 syscallarg(int) tolen; 349 } */ *args; 350 register_t *retval; 351 { 352 struct linux_sendto_args lsa; 353 struct sendto_args bsa; 354 int error; 355 356 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa))) 357 return error; 358 359 SCARG(&bsa, s) = lsa.s; 360 SCARG(&bsa, buf) = lsa.msg; 361 SCARG(&bsa, len) = lsa.len; 362 SCARG(&bsa, flags) = lsa.flags; 363 SCARG(&bsa, to) = (caddr_t) lsa.to; 364 SCARG(&bsa, tolen) = lsa.tolen; 365 366 return sendto(p, &bsa, retval); 367 } 368 369 static int 370 linux_recvfrom(p, args, retval) 371 struct proc *p; 372 struct linux_recvfrom_args /* { 373 syscallarg(int) s; 374 syscallarg(void *) buf; 375 syscallarg(int) len; 376 syscallarg(int) flags; 377 syscallarg(struct sockaddr *) from; 378 syscallarg(int *) fromlen; 379 } */ *args; 380 { 381 struct linux_recvfrom_args lra; 382 struct compat_43_recvfrom_args bra; 383 int error; 384 385 if ((error = copyin((caddr_t) args, (caddr_t) &lra, sizeof lra))) 386 return error; 387 388 SCARG(&bra, s) = lra.s; 389 SCARG(&bra, buf) = lra.buf; 390 SCARG(&bra, len) = lra.len; 391 SCARG(&bra, flags) = lra.flags; 392 SCARG(&bra, from) = (caddr_t) lra.from; 393 SCARG(&bra, fromlenaddr) = lra.fromlen; 394 395 return compat_43_recvfrom(p, &bra, retval); 396 } 397 398 static int 399 linux_shutdown(p, args, retval) 400 struct proc *p; 401 struct linux_shutdown_args /* { 402 syscallarg(int) s; 403 syscallarg(int) how; 404 } */ *args; 405 register_t *retval; 406 { 407 struct linux_shutdown_args lsa; 408 struct shutdown_args bsa; 409 int error; 410 411 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa))) 412 return error; 413 414 SCARG(&bsa, s) = lsa.s; 415 SCARG(&bsa, how) = lsa.how; 416 417 return shutdown(p, &bsa, retval); 418 } 419 420 /* 421 * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET 422 * is different, the rest matches IPPROTO_* on both systems. 423 */ 424 static int 425 linux_to_bsd_sopt_level(llevel) 426 int llevel; 427 { 428 switch (llevel) { 429 case LINUX_SOL_SOCKET: 430 return SOL_SOCKET; 431 default: 432 return llevel; 433 } 434 } 435 436 /* 437 * Convert Linux IP level socket option number to NetBSD values. 438 * Linux only implements IP_TOS and IP_TTL 439 */ 440 static int linux_to_bsd_ip_sockopt(lopt) 441 int lopt; 442 { 443 switch (lopt) { 444 case LINUX_IP_TOS: 445 return IP_TOS; 446 case LINUX_IP_TTL: 447 return IP_TTL; 448 default: 449 return -1; 450 } 451 } 452 453 /* 454 * Convert Linux socket level socket option numbers to NetBSD values. 455 */ 456 static int 457 linux_to_bsd_so_sockopt(lopt) 458 int lopt; 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 * Another reasonably straightforward function: setsockopt(2). Only 492 * the SOL_SOCKET and IPPROTO_IP levels are implemented here. 493 * The level and option numbers are converted; the values passed 494 * are not (yet) converted, the ones currently implemented don't 495 * need conversion, as they are the same on both systems. 496 */ 497 static int 498 linux_setsockopt(p, args, retval) 499 struct proc *p; 500 struct linux_setsockopt_args /* { 501 syscallarg(int) s; 502 syscallarg(int) level; 503 syscallarg(int) optname; 504 syscallarg(void *) optval; 505 syscallarg(int) optlen; 506 } */ *args; 507 register_t *retval; 508 { 509 struct linux_setsockopt_args lsa; 510 struct setsockopt_args bsa; 511 int error, name; 512 513 if ((error = copyin((caddr_t) args, (caddr_t) &lsa, sizeof lsa))) 514 return error; 515 516 SCARG(&bsa, s) = lsa.s; 517 518 SCARG(&bsa, level) = linux_to_bsd_sopt_level(lsa.level); 519 520 switch (SCARG(&bsa, level)) { 521 case SOL_SOCKET: 522 name = linux_to_bsd_so_sockopt(lsa.optname); 523 break; 524 case IPPROTO_IP: 525 name = linux_to_bsd_ip_sockopt(lsa.optname); 526 break; 527 default: 528 return EINVAL; 529 } 530 531 if (name == -1) 532 return EINVAL; 533 SCARG(&bsa, name) = name; 534 SCARG(&bsa, val) = lsa.optval; 535 SCARG(&bsa, valsize) = lsa.optlen; 536 537 return setsockopt(p, &bsa, retval); 538 } 539 540 /* 541 * getsockopt(2) is very much the same as setsockopt(2) (see above) 542 */ 543 static int 544 linux_getsockopt(p, args, retval) 545 struct proc *p; 546 struct linux_getsockopt_args /* { 547 syscallarg(int) s; 548 syscallarg(int) level; 549 syscallarg(int) optname; 550 syscallarg(void *) optval; 551 syscallarg(int) *optlen; 552 } */ *args; 553 register_t *retval; 554 { 555 struct linux_getsockopt_args lga; 556 struct getsockopt_args bga; 557 int error, name; 558 559 if ((error = copyin((caddr_t) args, (caddr_t) &lga, sizeof lga))) 560 return error; 561 562 SCARG(&bga, s) = lga.s; 563 564 SCARG(&bga, level) = linux_to_bsd_sopt_level(lga.level); 565 566 switch (SCARG(&bga, level)) { 567 case SOL_SOCKET: 568 name = linux_to_bsd_so_sockopt(lga.optname); 569 break; 570 case IPPROTO_IP: 571 name = linux_to_bsd_ip_sockopt(lga.optname); 572 break; 573 default: 574 return EINVAL; 575 } 576 577 if (name == -1) 578 return EINVAL; 579 SCARG(&bga, val) = lga.optval; 580 SCARG(&bga, avalsize) = lga.optlen; 581 582 return getsockopt(p, &bga, retval); 583 } 584 585 /* 586 * Entry point to all Linux socket calls. Just check which call to 587 * make and take appropriate action. 588 */ 589 int 590 linux_socketcall(p, uap, retval) 591 struct proc *p; 592 struct linux_socketcall_args /* { 593 syscallarg(int) what; 594 syscallarg(void *) args; 595 } */ *uap; 596 register_t *retval; 597 { 598 switch (SCARG(uap, what)) { 599 case LINUX_SYS_socket: 600 return linux_socket(p, SCARG(uap, args), retval); 601 case LINUX_SYS_bind: 602 return linux_bind(p, SCARG(uap, args), retval); 603 case LINUX_SYS_connect: 604 return linux_connect(p, SCARG(uap, args), retval); 605 case LINUX_SYS_listen: 606 return linux_listen(p, SCARG(uap, args), retval); 607 case LINUX_SYS_accept: 608 return linux_accept(p, SCARG(uap, args), retval); 609 case LINUX_SYS_getsockname: 610 return linux_getsockname(p, SCARG(uap, args), retval); 611 case LINUX_SYS_getpeername: 612 return linux_getpeername(p, SCARG(uap, args), retval); 613 case LINUX_SYS_socketpair: 614 return linux_socketpair(p, SCARG(uap, args), retval); 615 case LINUX_SYS_send: 616 return linux_send(p, SCARG(uap, args), retval); 617 case LINUX_SYS_recv: 618 return linux_recv(p, SCARG(uap, args), retval); 619 case LINUX_SYS_sendto: 620 return linux_sendto(p, SCARG(uap, args), retval); 621 case LINUX_SYS_recvfrom: 622 return linux_recvfrom(p, SCARG(uap, args), retval); 623 case LINUX_SYS_shutdown: 624 return linux_shutdown(p, SCARG(uap, args), retval); 625 case LINUX_SYS_setsockopt: 626 return linux_setsockopt(p, SCARG(uap, args), retval); 627 case LINUX_SYS_getsockopt: 628 return linux_getsockopt(p, SCARG(uap, args), retval); 629 default: 630 return ENOSYS; 631 } 632 } 633