1 /* $NetBSD: linux_socket.c,v 1.97 2008/07/03 14:07:09 njoly Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden and Eric Haszlakiewicz. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Functions in multiarch: 34 * linux_sys_socketcall : linux_socketcall.c 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.97 2008/07/03 14:07:09 njoly Exp $"); 39 40 #if defined(_KERNEL_OPT) 41 #include "opt_inet.h" 42 #endif /* defined(_KERNEL_OPT) */ 43 44 #include <sys/param.h> 45 #include <sys/kernel.h> 46 #include <sys/systm.h> 47 #include <sys/buf.h> 48 #include <sys/malloc.h> 49 #include <sys/ioctl.h> 50 #include <sys/tty.h> 51 #include <sys/file.h> 52 #include <sys/filedesc.h> 53 #include <sys/select.h> 54 #include <sys/socket.h> 55 #include <sys/socketvar.h> 56 #include <sys/domain.h> 57 #include <net/if.h> 58 #include <net/if_dl.h> 59 #include <net/if_types.h> 60 #include <netinet/in.h> 61 #include <netinet/tcp.h> 62 #include <sys/mount.h> 63 #include <sys/proc.h> 64 #include <sys/vnode.h> 65 #include <sys/device.h> 66 #include <sys/protosw.h> 67 #include <sys/mbuf.h> 68 #include <sys/syslog.h> 69 #include <sys/exec.h> 70 #include <sys/kauth.h> 71 #include <sys/syscallargs.h> 72 #include <sys/ktrace.h> 73 74 #include <lib/libkern/libkern.h> 75 76 #ifdef INET6 77 #include <netinet/ip6.h> 78 #include <netinet6/ip6_var.h> 79 #endif 80 81 #include <compat/sys/socket.h> 82 #include <compat/sys/sockio.h> 83 84 #include <compat/linux/common/linux_types.h> 85 #include <compat/linux/common/linux_util.h> 86 #include <compat/linux/common/linux_signal.h> 87 #include <compat/linux/common/linux_ioctl.h> 88 #include <compat/linux/common/linux_socket.h> 89 #if !defined(__alpha__) && !defined(__amd64__) 90 #include <compat/linux/common/linux_socketcall.h> 91 #endif 92 #include <compat/linux/common/linux_sockio.h> 93 #include <compat/linux/common/linux_ipc.h> 94 #include <compat/linux/common/linux_sem.h> 95 96 #include <compat/linux/linux_syscallargs.h> 97 98 #ifdef DEBUG_LINUX 99 #define DPRINTF(a) uprintf a 100 #else 101 #define DPRINTF(a) 102 #endif 103 104 /* 105 * The calls in this file are entered either via the linux_socketcall() 106 * interface or, on the Alpha, as individual syscalls. The 107 * linux_socketcall function does any massaging of arguments so that all 108 * the calls in here need not think that they are anything other 109 * than a normal syscall. 110 */ 111 112 static int linux_to_bsd_domain(int); 113 static int bsd_to_linux_domain(int); 114 int linux_to_bsd_sopt_level(int); 115 int linux_to_bsd_so_sockopt(int); 116 int linux_to_bsd_ip_sockopt(int); 117 int linux_to_bsd_tcp_sockopt(int); 118 int linux_to_bsd_udp_sockopt(int); 119 int linux_getifconf(struct lwp *, register_t *, void *); 120 int linux_getifhwaddr(struct lwp *, register_t *, u_int, void *); 121 static int linux_get_sa(struct lwp *, int, struct mbuf **, 122 const struct osockaddr *, unsigned int); 123 static int linux_sa_put(struct osockaddr *osa); 124 static int linux_to_bsd_msg_flags(int); 125 static int bsd_to_linux_msg_flags(int); 126 127 static const int linux_to_bsd_domain_[LINUX_AF_MAX] = { 128 AF_UNSPEC, 129 AF_UNIX, 130 AF_INET, 131 AF_CCITT, /* LINUX_AF_AX25 */ 132 AF_IPX, 133 AF_APPLETALK, 134 -1, /* LINUX_AF_NETROM */ 135 -1, /* LINUX_AF_BRIDGE */ 136 -1, /* LINUX_AF_ATMPVC */ 137 AF_CCITT, /* LINUX_AF_X25 */ 138 AF_INET6, 139 -1, /* LINUX_AF_ROSE */ 140 AF_DECnet, 141 -1, /* LINUX_AF_NETBEUI */ 142 -1, /* LINUX_AF_SECURITY */ 143 pseudo_AF_KEY, 144 AF_ROUTE, /* LINUX_AF_NETLINK */ 145 -1, /* LINUX_AF_PACKET */ 146 -1, /* LINUX_AF_ASH */ 147 -1, /* LINUX_AF_ECONET */ 148 -1, /* LINUX_AF_ATMSVC */ 149 AF_SNA, 150 /* rest up to LINUX_AF_MAX-1 is not allocated */ 151 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 152 }; 153 154 static const int bsd_to_linux_domain_[AF_MAX] = { 155 LINUX_AF_UNSPEC, 156 LINUX_AF_UNIX, 157 LINUX_AF_INET, 158 -1, /* AF_IMPLINK */ 159 -1, /* AF_PUP */ 160 -1, /* AF_CHAOS */ 161 -1, /* AF_NS */ 162 -1, /* AF_ISO */ 163 -1, /* AF_ECMA */ 164 -1, /* AF_DATAKIT */ 165 LINUX_AF_AX25, /* AF_CCITT */ 166 LINUX_AF_SNA, 167 LINUX_AF_DECnet, 168 -1, /* AF_DLI */ 169 -1, /* AF_LAT */ 170 -1, /* AF_HYLINK */ 171 LINUX_AF_APPLETALK, 172 LINUX_AF_NETLINK, 173 -1, /* AF_LINK */ 174 -1, /* AF_XTP */ 175 -1, /* AF_COIP */ 176 -1, /* AF_CNT */ 177 -1, /* pseudo_AF_RTIP */ 178 LINUX_AF_IPX, 179 LINUX_AF_INET6, 180 -1, /* pseudo_AF_PIP */ 181 -1, /* AF_ISDN */ 182 -1, /* AF_NATM */ 183 -1, /* AF_ARP */ 184 LINUX_pseudo_AF_KEY, 185 -1, /* pseudo_AF_HDRCMPLT */ 186 }; 187 188 static const struct { 189 int bfl; 190 int lfl; 191 } bsd_to_linux_msg_flags_[] = { 192 {MSG_OOB, LINUX_MSG_OOB}, 193 {MSG_PEEK, LINUX_MSG_PEEK}, 194 {MSG_DONTROUTE, LINUX_MSG_DONTROUTE}, 195 {MSG_EOR, LINUX_MSG_EOR}, 196 {MSG_TRUNC, LINUX_MSG_TRUNC}, 197 {MSG_CTRUNC, LINUX_MSG_CTRUNC}, 198 {MSG_WAITALL, LINUX_MSG_WAITALL}, 199 {MSG_DONTWAIT, LINUX_MSG_DONTWAIT}, 200 {MSG_BCAST, 0}, /* not supported, clear */ 201 {MSG_MCAST, 0}, /* not supported, clear */ 202 {-1, /* not supp */ LINUX_MSG_PROBE}, 203 {-1, /* not supp */ LINUX_MSG_FIN}, 204 {-1, /* not supp */ LINUX_MSG_SYN}, 205 {-1, /* not supp */ LINUX_MSG_CONFIRM}, 206 {-1, /* not supp */ LINUX_MSG_RST}, 207 {-1, /* not supp */ LINUX_MSG_ERRQUEUE}, 208 {-1, /* not supp */ LINUX_MSG_NOSIGNAL}, 209 {-1, /* not supp */ LINUX_MSG_MORE}, 210 }; 211 212 /* 213 * Convert between Linux and BSD socket domain values 214 */ 215 static int 216 linux_to_bsd_domain(int ldom) 217 { 218 if (ldom < 0 || ldom >= LINUX_AF_MAX) 219 return (-1); 220 221 return linux_to_bsd_domain_[ldom]; 222 } 223 224 /* 225 * Convert between BSD and Linux socket domain values 226 */ 227 static int 228 bsd_to_linux_domain(int bdom) 229 { 230 if (bdom < 0 || bdom >= AF_MAX) 231 return (-1); 232 233 return bsd_to_linux_domain_[bdom]; 234 } 235 236 static int 237 linux_to_bsd_msg_flags(int lflag) 238 { 239 int i, lfl, bfl; 240 int bflag = 0; 241 242 if (lflag == 0) 243 return (0); 244 245 for(i = 0; i < __arraycount(bsd_to_linux_msg_flags_); i++) { 246 bfl = bsd_to_linux_msg_flags_[i].bfl; 247 lfl = bsd_to_linux_msg_flags_[i].lfl; 248 249 if (lfl == 0) 250 continue; 251 252 if (lflag & lfl) { 253 if (bfl < 0) 254 return (-1); 255 256 bflag |= bfl; 257 } 258 } 259 260 return (bflag); 261 } 262 263 static int 264 bsd_to_linux_msg_flags(int bflag) 265 { 266 int i, lfl, bfl; 267 int lflag = 0; 268 269 if (bflag == 0) 270 return (0); 271 272 for(i = 0; i < __arraycount(bsd_to_linux_msg_flags_); i++) { 273 bfl = bsd_to_linux_msg_flags_[i].bfl; 274 lfl = bsd_to_linux_msg_flags_[i].lfl; 275 276 if (bfl <= 0) 277 continue; 278 279 if (bflag & bfl) { 280 if (lfl < 0) 281 return (-1); 282 283 lflag |= lfl; 284 } 285 } 286 287 return (lflag); 288 } 289 290 int 291 linux_sys_socket(struct lwp *l, const struct linux_sys_socket_args *uap, register_t *retval) 292 { 293 /* { 294 syscallarg(int) domain; 295 syscallarg(int) type; 296 syscallarg(int) protocol; 297 } */ 298 struct sys___socket30_args bsa; 299 int error; 300 301 SCARG(&bsa, protocol) = SCARG(uap, protocol); 302 SCARG(&bsa, type) = SCARG(uap, type); 303 SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain)); 304 if (SCARG(&bsa, domain) == -1) 305 return EINVAL; 306 error = sys___socket30(l, &bsa, retval); 307 308 #ifdef INET6 309 /* 310 * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by 311 * default and some apps depend on this. So, set V6ONLY to 0 312 * for Linux apps if the sysctl value is set to 1. 313 */ 314 if (!error && ip6_v6only && SCARG(&bsa, domain) == PF_INET6) { 315 struct socket *so; 316 317 if (fd_getsock(*retval, &so) == 0) { 318 struct mbuf *m; 319 320 m = m_get(M_WAIT, MT_SOOPTS); 321 m->m_len = sizeof(int); 322 *mtod(m, int *) = 0; 323 324 /* ignore error */ 325 (void) sosetopt(so, IPPROTO_IPV6, IPV6_V6ONLY, m); 326 327 fd_putfile(*retval); 328 } 329 } 330 #endif 331 332 return (error); 333 } 334 335 int 336 linux_sys_socketpair(struct lwp *l, const struct linux_sys_socketpair_args *uap, register_t *retval) 337 { 338 /* { 339 syscallarg(int) domain; 340 syscallarg(int) type; 341 syscallarg(int) protocol; 342 syscallarg(int *) rsv; 343 } */ 344 struct sys_socketpair_args bsa; 345 346 SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain)); 347 if (SCARG(&bsa, domain) == -1) 348 return EINVAL; 349 SCARG(&bsa, type) = SCARG(uap, type); 350 SCARG(&bsa, protocol) = SCARG(uap, protocol); 351 SCARG(&bsa, rsv) = SCARG(uap, rsv); 352 353 return sys_socketpair(l, &bsa, retval); 354 } 355 356 int 357 linux_sys_sendto(struct lwp *l, const struct linux_sys_sendto_args *uap, register_t *retval) 358 { 359 /* { 360 syscallarg(int) s; 361 syscallarg(void *) msg; 362 syscallarg(int) len; 363 syscallarg(int) flags; 364 syscallarg(struct osockaddr *) to; 365 syscallarg(int) tolen; 366 } */ 367 struct msghdr msg; 368 struct iovec aiov; 369 struct mbuf *nam; 370 int bflags; 371 int error; 372 373 /* Translate message flags. */ 374 bflags = linux_to_bsd_msg_flags(SCARG(uap, flags)); 375 if (bflags < 0) 376 /* Some supported flag */ 377 return EINVAL; 378 379 msg.msg_flags = 0; 380 msg.msg_name = NULL; 381 msg.msg_control = NULL; 382 383 if (SCARG(uap, tolen)) { 384 /* Read in and convert the sockaddr */ 385 error = linux_get_sa(l, SCARG(uap, s), &nam, SCARG(uap, to), 386 SCARG(uap, tolen)); 387 if (error) 388 return (error); 389 msg.msg_flags |= MSG_NAMEMBUF; 390 msg.msg_name = nam; 391 msg.msg_namelen = SCARG(uap, tolen); 392 } 393 394 msg.msg_iov = &aiov; 395 msg.msg_iovlen = 1; 396 aiov.iov_base = __UNCONST(SCARG(uap, msg)); 397 aiov.iov_len = SCARG(uap, len); 398 399 return do_sys_sendmsg(l, SCARG(uap, s), &msg, bflags, retval); 400 } 401 402 int 403 linux_sys_sendmsg(struct lwp *l, const struct linux_sys_sendmsg_args *uap, register_t *retval) 404 { 405 /* { 406 syscallarg(int) s; 407 syscallarg(struct msghdr *) msg; 408 syscallarg(u_int) flags; 409 } */ 410 struct msghdr msg; 411 int error; 412 int bflags; 413 struct mbuf *nam; 414 u_int8_t *control; 415 struct mbuf *ctl_mbuf = NULL; 416 417 msg.msg_flags = MSG_IOVUSRSPACE; 418 419 /* 420 * Translate message flags. 421 */ 422 bflags = linux_to_bsd_msg_flags(SCARG(uap, flags)); 423 if (bflags < 0) 424 /* Some supported flag */ 425 return EINVAL; 426 427 if (msg.msg_name) { 428 /* Read in and convert the sockaddr */ 429 error = linux_get_sa(l, SCARG(uap, s), &nam, msg.msg_name, 430 msg.msg_namelen); 431 if (error) 432 return (error); 433 msg.msg_flags |= MSG_NAMEMBUF; 434 msg.msg_name = nam; 435 } 436 437 /* 438 * Handle cmsg if there is any. 439 */ 440 if (CMSG_FIRSTHDR(&msg)) { 441 struct linux_cmsghdr l_cmsg, *l_cc; 442 struct cmsghdr *cmsg; 443 ssize_t resid = msg.msg_controllen; 444 size_t clen, cidx = 0, cspace; 445 446 ctl_mbuf = m_get(M_WAIT, MT_CONTROL); 447 clen = MLEN; 448 control = mtod(ctl_mbuf, void *); 449 450 l_cc = LINUX_CMSG_FIRSTHDR(&msg); 451 do { 452 error = copyin(l_cc, &l_cmsg, sizeof(l_cmsg)); 453 if (error) 454 goto done; 455 456 /* 457 * Sanity check the control message length. 458 */ 459 if (l_cmsg.cmsg_len > resid 460 || l_cmsg.cmsg_len < sizeof l_cmsg) { 461 error = EINVAL; 462 goto done; 463 } 464 465 /* 466 * Refuse unsupported control messages, and 467 * translate fields as appropriate. 468 */ 469 switch (l_cmsg.cmsg_level) { 470 case LINUX_SOL_SOCKET: 471 /* It only differs on some archs */ 472 if (LINUX_SOL_SOCKET != SOL_SOCKET) 473 l_cmsg.cmsg_level = SOL_SOCKET; 474 475 switch(l_cmsg.cmsg_type) { 476 case LINUX_SCM_RIGHTS: 477 /* Linux SCM_RIGHTS is same as NetBSD */ 478 break; 479 480 default: 481 /* other types not supported */ 482 error = EINVAL; 483 goto done; 484 } 485 break; 486 default: 487 /* pray and leave intact */ 488 break; 489 } 490 491 cspace = CMSG_SPACE(l_cmsg.cmsg_len - sizeof(l_cmsg)); 492 493 /* Check the buffer is big enough */ 494 if (__predict_false(cidx + cspace > clen)) { 495 u_int8_t *nc; 496 497 clen = cidx + cspace; 498 if (clen >= PAGE_SIZE) { 499 error = EINVAL; 500 goto done; 501 } 502 nc = realloc(clen <= MLEN ? NULL : control, 503 clen, M_TEMP, M_WAITOK); 504 if (!nc) { 505 error = ENOMEM; 506 goto done; 507 } 508 if (cidx <= MLEN) 509 /* Old buffer was in mbuf... */ 510 memcpy(nc, control, cidx); 511 control = nc; 512 } 513 514 /* Copy header */ 515 cmsg = (void *)&control[cidx]; 516 cmsg->cmsg_len = l_cmsg.cmsg_len + LINUX_CMSG_ALIGN_DELTA; 517 cmsg->cmsg_level = l_cmsg.cmsg_level; 518 cmsg->cmsg_type = l_cmsg.cmsg_type; 519 520 /* Zero are between header and data */ 521 memset(cmsg + 1, 0, 522 CMSG_ALIGN(sizeof(cmsg)) - sizeof(cmsg)); 523 524 /* Copyin the data */ 525 error = copyin(LINUX_CMSG_DATA(l_cc), 526 CMSG_DATA(control), 527 l_cmsg.cmsg_len - sizeof(l_cmsg)); 528 if (error) 529 goto done; 530 531 resid -= LINUX_CMSG_ALIGN(l_cmsg.cmsg_len); 532 cidx += cspace; 533 } while ((l_cc = LINUX_CMSG_NXTHDR(&msg, l_cc)) && resid > 0); 534 535 /* If we allocated a buffer, attach to mbuf */ 536 if (cidx > MLEN) { 537 MEXTADD(ctl_mbuf, control, clen, M_MBUF, NULL, NULL); 538 ctl_mbuf->m_flags |= M_EXT_RW; 539 } 540 control = NULL; 541 ctl_mbuf->m_len = cidx; 542 543 msg.msg_control = ctl_mbuf; 544 msg.msg_flags |= MSG_CONTROLMBUF; 545 } 546 547 error = do_sys_sendmsg(l, SCARG(uap, s), &msg, bflags, retval); 548 /* Freed internally */ 549 ctl_mbuf = NULL; 550 551 done: 552 if (ctl_mbuf != NULL) { 553 if (control != NULL && control != mtod(ctl_mbuf, void *)) 554 free(control, M_MBUF); 555 m_free(ctl_mbuf); 556 } 557 return (error); 558 } 559 560 int 561 linux_sys_recvfrom(struct lwp *l, const struct linux_sys_recvfrom_args *uap, register_t *retval) 562 { 563 /* { 564 syscallarg(int) s; 565 syscallarg(void *) buf; 566 syscallarg(int) len; 567 syscallarg(int) flags; 568 syscallarg(struct osockaddr *) from; 569 syscallarg(int *) fromlenaddr; 570 } */ 571 int error; 572 struct sys_recvfrom_args bra; 573 574 SCARG(&bra, s) = SCARG(uap, s); 575 SCARG(&bra, buf) = SCARG(uap, buf); 576 SCARG(&bra, len) = SCARG(uap, len); 577 SCARG(&bra, flags) = SCARG(uap, flags); 578 SCARG(&bra, from) = (struct sockaddr *) SCARG(uap, from); 579 SCARG(&bra, fromlenaddr) = (socklen_t *)SCARG(uap, fromlenaddr); 580 581 if ((error = sys_recvfrom(l, &bra, retval))) 582 return (error); 583 584 if (SCARG(uap, from) && (error = linux_sa_put(SCARG(uap, from)))) 585 return (error); 586 587 return (0); 588 } 589 590 static int 591 linux_copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control) 592 { 593 int dlen, error = 0; 594 struct cmsghdr *cmsg; 595 struct linux_cmsghdr linux_cmsg; 596 struct mbuf *m; 597 char *q, *q_end; 598 599 if (mp->msg_controllen <= 0 || control == 0) { 600 mp->msg_controllen = 0; 601 free_control_mbuf(l, control, control); 602 return 0; 603 } 604 605 q = (char *)mp->msg_control; 606 q_end = q + mp->msg_controllen; 607 608 for (m = control; m != NULL; ) { 609 cmsg = mtod(m, struct cmsghdr *); 610 611 /* 612 * Fixup cmsg. We handle two things: 613 * 0. different sizeof cmsg_len. 614 * 1. different values for level/type on some archs 615 * 2. different alignment of CMSG_DATA on some archs 616 */ 617 linux_cmsg.cmsg_len = cmsg->cmsg_len - LINUX_CMSG_ALIGN_DELTA; 618 linux_cmsg.cmsg_level = cmsg->cmsg_level; 619 linux_cmsg.cmsg_type = cmsg->cmsg_type; 620 621 dlen = q_end - q; 622 if (linux_cmsg.cmsg_len > dlen) { 623 /* Not enough room for the parameter */ 624 dlen -= sizeof linux_cmsg; 625 if (dlen <= 0) 626 /* Discard if header wont fit */ 627 break; 628 mp->msg_flags |= MSG_CTRUNC; 629 if (linux_cmsg.cmsg_level == SOL_SOCKET 630 && linux_cmsg.cmsg_type == SCM_RIGHTS) 631 /* Do not truncate me ... */ 632 break; 633 } else 634 dlen = linux_cmsg.cmsg_len - sizeof linux_cmsg; 635 636 switch (linux_cmsg.cmsg_level) { 637 case SOL_SOCKET: 638 linux_cmsg.cmsg_level = LINUX_SOL_SOCKET; 639 switch (linux_cmsg.cmsg_type) { 640 case SCM_RIGHTS: 641 /* Linux SCM_RIGHTS is same as NetBSD */ 642 break; 643 644 default: 645 /* other types not supported */ 646 error = EINVAL; 647 goto done; 648 } 649 /* machine dependant ! */ 650 break; 651 default: 652 /* pray and leave intact */ 653 break; 654 } 655 656 /* There can be padding between the header and data... */ 657 error = copyout(&linux_cmsg, q, sizeof *cmsg); 658 if (error != 0) { 659 error = copyout(CCMSG_DATA(cmsg), q + sizeof linux_cmsg, 660 dlen); 661 } 662 if (error != 0) { 663 /* We must free all the SCM_RIGHTS */ 664 m = control; 665 break; 666 } 667 m = m->m_next; 668 if (m == NULL || q + LINUX_CMSG_ALIGN(dlen) > q_end) { 669 q += dlen; 670 break; 671 } 672 q += LINUX_CMSG_ALIGN(dlen); 673 } 674 675 done: 676 free_control_mbuf(l, control, m); 677 678 mp->msg_controllen = q - (char *)mp->msg_control; 679 return error; 680 } 681 682 int 683 linux_sys_recvmsg(struct lwp *l, const struct linux_sys_recvmsg_args *uap, register_t *retval) 684 { 685 /* { 686 syscallarg(int) s; 687 syscallarg(struct msghdr *) msg; 688 syscallarg(u_int) flags; 689 } */ 690 struct msghdr msg; 691 int error; 692 struct mbuf *from, *control; 693 694 error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); 695 if (error) 696 return (error); 697 698 msg.msg_flags = linux_to_bsd_msg_flags(SCARG(uap, flags)); 699 if (msg.msg_flags < 0) { 700 /* Some unsupported flag */ 701 return (EINVAL); 702 } 703 msg.msg_flags |= MSG_IOVUSRSPACE; 704 705 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, 706 msg.msg_control != NULL ? &control : NULL, retval); 707 if (error != 0) 708 return error; 709 710 if (msg.msg_control != NULL) 711 error = linux_copyout_msg_control(l, &msg, control); 712 713 if (error == 0 && from != 0) { 714 mtod(from, struct osockaddr *)->sa_family = 715 bsd_to_linux_domain(mtod(from, struct sockaddr *)->sa_family); 716 error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0, 717 from); 718 } else 719 msg.msg_namelen = 0; 720 721 if (from != NULL) 722 m_free(from); 723 724 if (error == 0) { 725 msg.msg_flags = bsd_to_linux_msg_flags(msg.msg_flags); 726 if (msg.msg_flags < 0) 727 /* Some flag unsupported by Linux */ 728 error = EINVAL; 729 else 730 error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); 731 } 732 733 return (error); 734 } 735 736 /* 737 * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET 738 * is different, the rest matches IPPROTO_* on both systems. 739 */ 740 int 741 linux_to_bsd_sopt_level(int llevel) 742 { 743 744 switch (llevel) { 745 case LINUX_SOL_SOCKET: 746 return SOL_SOCKET; 747 case LINUX_SOL_IP: 748 return IPPROTO_IP; 749 case LINUX_SOL_TCP: 750 return IPPROTO_TCP; 751 case LINUX_SOL_UDP: 752 return IPPROTO_UDP; 753 default: 754 return -1; 755 } 756 } 757 758 /* 759 * Convert Linux socket level socket option numbers to NetBSD values. 760 */ 761 int 762 linux_to_bsd_so_sockopt(int lopt) 763 { 764 765 switch (lopt) { 766 case LINUX_SO_DEBUG: 767 return SO_DEBUG; 768 case LINUX_SO_REUSEADDR: 769 /* 770 * Linux does not implement SO_REUSEPORT, but allows reuse of a 771 * host:port pair through SO_REUSEADDR even if the address is not a 772 * multicast-address. Effectively, this means that we should use 773 * SO_REUSEPORT to allow Linux applications to not exit with 774 * EADDRINUSE 775 */ 776 return SO_REUSEPORT; 777 case LINUX_SO_TYPE: 778 return SO_TYPE; 779 case LINUX_SO_ERROR: 780 return SO_ERROR; 781 case LINUX_SO_DONTROUTE: 782 return SO_DONTROUTE; 783 case LINUX_SO_BROADCAST: 784 return SO_BROADCAST; 785 case LINUX_SO_SNDBUF: 786 return SO_SNDBUF; 787 case LINUX_SO_RCVBUF: 788 return SO_RCVBUF; 789 case LINUX_SO_KEEPALIVE: 790 return SO_KEEPALIVE; 791 case LINUX_SO_OOBINLINE: 792 return SO_OOBINLINE; 793 case LINUX_SO_LINGER: 794 return SO_LINGER; 795 case LINUX_SO_PRIORITY: 796 case LINUX_SO_NO_CHECK: 797 default: 798 return -1; 799 } 800 } 801 802 /* 803 * Convert Linux IP level socket option number to NetBSD values. 804 */ 805 int 806 linux_to_bsd_ip_sockopt(int lopt) 807 { 808 809 switch (lopt) { 810 case LINUX_IP_TOS: 811 return IP_TOS; 812 case LINUX_IP_TTL: 813 return IP_TTL; 814 case LINUX_IP_MULTICAST_TTL: 815 return IP_MULTICAST_TTL; 816 case LINUX_IP_MULTICAST_LOOP: 817 return IP_MULTICAST_LOOP; 818 case LINUX_IP_MULTICAST_IF: 819 return IP_MULTICAST_IF; 820 case LINUX_IP_ADD_MEMBERSHIP: 821 return IP_ADD_MEMBERSHIP; 822 case LINUX_IP_DROP_MEMBERSHIP: 823 return IP_DROP_MEMBERSHIP; 824 default: 825 return -1; 826 } 827 } 828 829 /* 830 * Convert Linux TCP level socket option number to NetBSD values. 831 */ 832 int 833 linux_to_bsd_tcp_sockopt(int lopt) 834 { 835 836 switch (lopt) { 837 case LINUX_TCP_NODELAY: 838 return TCP_NODELAY; 839 case LINUX_TCP_MAXSEG: 840 return TCP_MAXSEG; 841 default: 842 return -1; 843 } 844 } 845 846 /* 847 * Convert Linux UDP level socket option number to NetBSD values. 848 */ 849 int 850 linux_to_bsd_udp_sockopt(int lopt) 851 { 852 853 switch (lopt) { 854 default: 855 return -1; 856 } 857 } 858 859 /* 860 * Another reasonably straightforward function: setsockopt(2). 861 * The level and option numbers are converted; the values passed 862 * are not (yet) converted, the ones currently implemented don't 863 * need conversion, as they are the same on both systems. 864 */ 865 int 866 linux_sys_setsockopt(struct lwp *l, const struct linux_sys_setsockopt_args *uap, register_t *retval) 867 { 868 /* { 869 syscallarg(int) s; 870 syscallarg(int) level; 871 syscallarg(int) optname; 872 syscallarg(void *) optval; 873 syscallarg(int) optlen; 874 } */ 875 struct sys_setsockopt_args bsa; 876 int name; 877 878 SCARG(&bsa, s) = SCARG(uap, s); 879 SCARG(&bsa, level) = linux_to_bsd_sopt_level(SCARG(uap, level)); 880 SCARG(&bsa, val) = SCARG(uap, optval); 881 SCARG(&bsa, valsize) = SCARG(uap, optlen); 882 883 /* 884 * Linux supports only SOL_SOCKET for AF_LOCAL domain sockets 885 * and returns EOPNOTSUPP for other levels 886 */ 887 if (SCARG(&bsa, level) != SOL_SOCKET) { 888 struct socket *so; 889 int error, family; 890 891 /* fd_getsock() will use the descriptor for us */ 892 if ((error = fd_getsock(SCARG(&bsa, s), &so)) != 0) 893 return error; 894 family = so->so_proto->pr_domain->dom_family; 895 fd_putfile(SCARG(&bsa, s)); 896 897 if (family == AF_LOCAL) 898 return EOPNOTSUPP; 899 } 900 901 switch (SCARG(&bsa, level)) { 902 case SOL_SOCKET: 903 name = linux_to_bsd_so_sockopt(SCARG(uap, optname)); 904 break; 905 case IPPROTO_IP: 906 name = linux_to_bsd_ip_sockopt(SCARG(uap, optname)); 907 break; 908 case IPPROTO_TCP: 909 name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname)); 910 break; 911 case IPPROTO_UDP: 912 name = linux_to_bsd_udp_sockopt(SCARG(uap, optname)); 913 break; 914 default: 915 return EINVAL; 916 } 917 918 if (name == -1) 919 return EINVAL; 920 SCARG(&bsa, name) = name; 921 922 return sys_setsockopt(l, &bsa, retval); 923 } 924 925 /* 926 * getsockopt(2) is very much the same as setsockopt(2) (see above) 927 */ 928 int 929 linux_sys_getsockopt(struct lwp *l, const struct linux_sys_getsockopt_args *uap, register_t *retval) 930 { 931 /* { 932 syscallarg(int) s; 933 syscallarg(int) level; 934 syscallarg(int) optname; 935 syscallarg(void *) optval; 936 syscallarg(int *) optlen; 937 } */ 938 struct sys_getsockopt_args bga; 939 int name; 940 941 SCARG(&bga, s) = SCARG(uap, s); 942 SCARG(&bga, level) = linux_to_bsd_sopt_level(SCARG(uap, level)); 943 SCARG(&bga, val) = SCARG(uap, optval); 944 SCARG(&bga, avalsize) = (socklen_t *)SCARG(uap, optlen); 945 946 switch (SCARG(&bga, level)) { 947 case SOL_SOCKET: 948 name = linux_to_bsd_so_sockopt(SCARG(uap, optname)); 949 break; 950 case IPPROTO_IP: 951 name = linux_to_bsd_ip_sockopt(SCARG(uap, optname)); 952 break; 953 case IPPROTO_TCP: 954 name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname)); 955 break; 956 case IPPROTO_UDP: 957 name = linux_to_bsd_udp_sockopt(SCARG(uap, optname)); 958 break; 959 default: 960 return EINVAL; 961 } 962 963 if (name == -1) 964 return EINVAL; 965 SCARG(&bga, name) = name; 966 967 return sys_getsockopt(l, &bga, retval); 968 } 969 970 int 971 linux_getifconf(struct lwp *l, register_t *retval, void *data) 972 { 973 struct linux_ifreq ifr, *ifrp; 974 struct ifconf *ifc = data; 975 struct ifnet *ifp; 976 struct ifaddr *ifa; 977 struct sockaddr *sa; 978 struct osockaddr *osa; 979 int space, error = 0; 980 const int sz = (int)sizeof(ifr); 981 982 ifrp = (struct linux_ifreq *)ifc->ifc_req; 983 if (ifrp == NULL) 984 space = 0; 985 else 986 space = ifc->ifc_len; 987 988 IFNET_FOREACH(ifp) { 989 (void)strncpy(ifr.ifr_name, ifp->if_xname, 990 sizeof(ifr.ifr_name)); 991 if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') 992 return ENAMETOOLONG; 993 if (IFADDR_EMPTY(ifp)) 994 continue; 995 IFADDR_FOREACH(ifa, ifp) { 996 sa = ifa->ifa_addr; 997 if (sa->sa_family != AF_INET || 998 sa->sa_len > sizeof(*osa)) 999 continue; 1000 memcpy(&ifr.ifr_addr, sa, sa->sa_len); 1001 osa = (struct osockaddr *)&ifr.ifr_addr; 1002 osa->sa_family = sa->sa_family; 1003 if (space >= sz) { 1004 error = copyout(&ifr, ifrp, sz); 1005 if (error != 0) 1006 return error; 1007 ifrp++; 1008 } 1009 space -= sz; 1010 } 1011 } 1012 1013 if (ifrp != NULL) 1014 ifc->ifc_len -= space; 1015 else 1016 ifc->ifc_len = -space; 1017 1018 return 0; 1019 } 1020 1021 int 1022 linux_getifhwaddr(struct lwp *l, register_t *retval, u_int fd, 1023 void *data) 1024 { 1025 /* Not the full structure, just enough to map what we do here */ 1026 struct linux_ifreq lreq; 1027 file_t *fp; 1028 struct ifaddr *ifa; 1029 struct ifnet *ifp; 1030 struct sockaddr_dl *sadl; 1031 int error, found; 1032 int index, ifnum; 1033 1034 /* 1035 * We can't emulate this ioctl by calling sys_ioctl() to run 1036 * SIOCGIFCONF, because the user buffer is not of the right 1037 * type to take those results. We can't use kernel buffers to 1038 * receive the results, as the implementation of sys_ioctl() 1039 * and ifconf() [which implements SIOCGIFCONF] use 1040 * copyin()/copyout() which will fail on kernel addresses. 1041 * 1042 * So, we must duplicate code from sys_ioctl() and ifconf(). Ugh. 1043 */ 1044 1045 if ((fp = fd_getfile(fd)) == NULL) 1046 return (EBADF); 1047 1048 KERNEL_LOCK(1, NULL); 1049 1050 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 1051 error = EBADF; 1052 goto out; 1053 } 1054 1055 error = copyin(data, &lreq, sizeof(lreq)); 1056 if (error) 1057 goto out; 1058 lreq.ifr_name[LINUX_IFNAMSIZ-1] = '\0'; /* just in case */ 1059 1060 /* 1061 * Try real interface name first, then fake "ethX" 1062 */ 1063 found = 0; 1064 IFNET_FOREACH(ifp) { 1065 if (found) 1066 break; 1067 if (strcmp(lreq.ifr_name, ifp->if_xname)) 1068 /* not this interface */ 1069 continue; 1070 found=1; 1071 if (IFADDR_EMPTY(ifp)) { 1072 error = ENODEV; 1073 goto out; 1074 } 1075 IFADDR_FOREACH(ifa, ifp) { 1076 sadl = satosdl(ifa->ifa_addr); 1077 /* only return ethernet addresses */ 1078 /* XXX what about FDDI, etc. ? */ 1079 if (sadl->sdl_family != AF_LINK || 1080 sadl->sdl_type != IFT_ETHER) 1081 continue; 1082 memcpy(&lreq.ifr_hwaddr.sa_data, CLLADDR(sadl), 1083 MIN(sadl->sdl_alen, 1084 sizeof(lreq.ifr_hwaddr.sa_data))); 1085 lreq.ifr_hwaddr.sa_family = 1086 sadl->sdl_family; 1087 error = copyout(&lreq, data, sizeof(lreq)); 1088 goto out; 1089 } 1090 } 1091 1092 if (strncmp(lreq.ifr_name, "eth", 3) == 0) { 1093 for (ifnum = 0, index = 3; 1094 lreq.ifr_name[index] != '\0' && index < LINUX_IFNAMSIZ; 1095 index++) { 1096 ifnum *= 10; 1097 ifnum += lreq.ifr_name[index] - '0'; 1098 } 1099 1100 error = EINVAL; /* in case we don't find one */ 1101 found = 0; 1102 IFNET_FOREACH(ifp) { 1103 if (found) 1104 break; 1105 memcpy(lreq.ifr_name, ifp->if_xname, 1106 MIN(LINUX_IFNAMSIZ, IFNAMSIZ)); 1107 IFADDR_FOREACH(ifa, ifp) { 1108 sadl = satosdl(ifa->ifa_addr); 1109 /* only return ethernet addresses */ 1110 /* XXX what about FDDI, etc. ? */ 1111 if (sadl->sdl_family != AF_LINK || 1112 sadl->sdl_type != IFT_ETHER) 1113 continue; 1114 if (ifnum--) 1115 /* not the reqested iface */ 1116 continue; 1117 memcpy(&lreq.ifr_hwaddr.sa_data, 1118 CLLADDR(sadl), 1119 MIN(sadl->sdl_alen, 1120 sizeof(lreq.ifr_hwaddr.sa_data))); 1121 lreq.ifr_hwaddr.sa_family = 1122 sadl->sdl_family; 1123 error = copyout(&lreq, data, sizeof(lreq)); 1124 found = 1; 1125 break; 1126 } 1127 } 1128 } else { 1129 /* unknown interface, not even an "eth*" name */ 1130 error = ENODEV; 1131 } 1132 1133 out: 1134 KERNEL_UNLOCK_ONE(NULL); 1135 fd_putfile(fd); 1136 return error; 1137 } 1138 1139 int 1140 linux_ioctl_socket(struct lwp *l, const struct linux_sys_ioctl_args *uap, register_t *retval) 1141 { 1142 /* { 1143 syscallarg(int) fd; 1144 syscallarg(u_long) com; 1145 syscallarg(void *) data; 1146 } */ 1147 u_long com; 1148 int error = 0, isdev = 0, dosys = 1; 1149 struct sys_ioctl_args ia; 1150 file_t *fp; 1151 struct vnode *vp; 1152 int (*ioctlf)(file_t *, u_long, void *); 1153 struct ioctl_pt pt; 1154 1155 if ((fp = fd_getfile(SCARG(uap, fd))) == NULL) 1156 return (EBADF); 1157 1158 if (fp->f_type == DTYPE_VNODE) { 1159 vp = (struct vnode *)fp->f_data; 1160 isdev = vp->v_type == VCHR; 1161 } 1162 1163 /* 1164 * Don't try to interpret socket ioctl calls that are done 1165 * on a device filedescriptor, just pass them through, to 1166 * emulate Linux behaviour. Use PTIOCLINUX so that the 1167 * device will only handle these if it's prepared to do 1168 * so, to avoid unexpected things from happening. 1169 */ 1170 if (isdev) { 1171 dosys = 0; 1172 ioctlf = fp->f_ops->fo_ioctl; 1173 pt.com = SCARG(uap, com); 1174 pt.data = SCARG(uap, data); 1175 error = ioctlf(fp, PTIOCLINUX, &pt); 1176 /* 1177 * XXX hack: if the function returns EJUSTRETURN, 1178 * it has stuffed a sysctl return value in pt.data. 1179 */ 1180 if (error == EJUSTRETURN) { 1181 retval[0] = (register_t)pt.data; 1182 error = 0; 1183 } 1184 goto out; 1185 } 1186 1187 com = SCARG(uap, com); 1188 retval[0] = 0; 1189 1190 switch (com) { 1191 case LINUX_SIOCGIFCONF: 1192 error = linux_getifconf(l, retval, SCARG(uap, data)); 1193 dosys = 0; 1194 break; 1195 case LINUX_SIOCGIFFLAGS: 1196 SCARG(&ia, com) = OSIOCGIFFLAGS; 1197 break; 1198 case LINUX_SIOCSIFFLAGS: 1199 SCARG(&ia, com) = OSIOCSIFFLAGS; 1200 break; 1201 case LINUX_SIOCGIFADDR: 1202 SCARG(&ia, com) = OOSIOCGIFADDR; 1203 break; 1204 case LINUX_SIOCGIFDSTADDR: 1205 SCARG(&ia, com) = OOSIOCGIFDSTADDR; 1206 break; 1207 case LINUX_SIOCGIFBRDADDR: 1208 SCARG(&ia, com) = OOSIOCGIFBRDADDR; 1209 break; 1210 case LINUX_SIOCGIFNETMASK: 1211 SCARG(&ia, com) = OOSIOCGIFNETMASK; 1212 break; 1213 case LINUX_SIOCADDMULTI: 1214 SCARG(&ia, com) = OSIOCADDMULTI; 1215 break; 1216 case LINUX_SIOCDELMULTI: 1217 SCARG(&ia, com) = OSIOCDELMULTI; 1218 break; 1219 case LINUX_SIOCGIFHWADDR: 1220 error = linux_getifhwaddr(l, retval, SCARG(uap, fd), 1221 SCARG(uap, data)); 1222 dosys = 0; 1223 break; 1224 default: 1225 error = EINVAL; 1226 } 1227 1228 out: 1229 fd_putfile(SCARG(uap, fd)); 1230 1231 if (error ==0 && dosys) { 1232 SCARG(&ia, fd) = SCARG(uap, fd); 1233 SCARG(&ia, data) = SCARG(uap, data); 1234 error = sys_ioctl(curlwp, &ia, retval); 1235 } 1236 1237 return error; 1238 } 1239 1240 int 1241 linux_sys_connect(struct lwp *l, const struct linux_sys_connect_args *uap, register_t *retval) 1242 { 1243 /* { 1244 syscallarg(int) s; 1245 syscallarg(const struct sockaddr *) name; 1246 syscallarg(int) namelen; 1247 } */ 1248 int error; 1249 struct mbuf *nam; 1250 1251 error = linux_get_sa(l, SCARG(uap, s), &nam, SCARG(uap, name), 1252 SCARG(uap, namelen)); 1253 if (error) 1254 return (error); 1255 1256 error = do_sys_connect(l, SCARG(uap, s), nam); 1257 1258 if (error == EISCONN) { 1259 struct socket *so; 1260 int state, prflags, nbio; 1261 1262 /* fd_getsock() will use the descriptor for us */ 1263 if (fd_getsock(SCARG(uap, s), &so) != 0) 1264 return EISCONN; 1265 1266 solock(so); 1267 state = so->so_state; 1268 nbio = so->so_nbio; 1269 prflags = so->so_proto->pr_flags; 1270 sounlock(so); 1271 fd_putfile(SCARG(uap, s)); 1272 /* 1273 * We should only let this call succeed once per 1274 * non-blocking connect; however we don't have 1275 * a convenient place to keep that state.. 1276 */ 1277 if (nbio && (state & SS_ISCONNECTED) && 1278 (prflags & PR_CONNREQUIRED)) 1279 return 0; 1280 } 1281 1282 return (error); 1283 } 1284 1285 int 1286 linux_sys_bind(struct lwp *l, const struct linux_sys_bind_args *uap, register_t *retval) 1287 { 1288 /* { 1289 syscallarg(int) s; 1290 syscallarg(const struct osockaddr *) name; 1291 syscallarg(int) namelen; 1292 } */ 1293 int error; 1294 struct mbuf *nam; 1295 1296 error = linux_get_sa(l, SCARG(uap, s), &nam, SCARG(uap, name), 1297 SCARG(uap, namelen)); 1298 if (error) 1299 return (error); 1300 1301 return do_sys_bind(l, SCARG(uap, s), nam); 1302 } 1303 1304 int 1305 linux_sys_getsockname(struct lwp *l, const struct linux_sys_getsockname_args *uap, register_t *retval) 1306 { 1307 /* { 1308 syscallarg(int) fdes; 1309 syscallarg(void *) asa; 1310 syscallarg(int *) alen; 1311 } */ 1312 int error; 1313 1314 if ((error = sys_getsockname(l, (const void *)uap, retval)) != 0) 1315 return (error); 1316 1317 if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa)))) 1318 return (error); 1319 1320 return (0); 1321 } 1322 1323 int 1324 linux_sys_getpeername(struct lwp *l, const struct linux_sys_getpeername_args *uap, register_t *retval) 1325 { 1326 /* { 1327 syscallarg(int) fdes; 1328 syscallarg(void *) asa; 1329 syscallarg(int *) alen; 1330 } */ 1331 int error; 1332 1333 if ((error = sys_getpeername(l, (const void *)uap, retval)) != 0) 1334 return (error); 1335 1336 if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa)))) 1337 return (error); 1338 1339 return (0); 1340 } 1341 1342 /* 1343 * Copy the osockaddr structure pointed to by osa to mbuf, adjust 1344 * family and convert to sockaddr. 1345 */ 1346 static int 1347 linux_get_sa(struct lwp *l, int s, struct mbuf **mp, 1348 const struct osockaddr *osa, unsigned int salen) 1349 { 1350 int error, bdom; 1351 struct sockaddr *sa; 1352 struct osockaddr *kosa; 1353 struct mbuf *m; 1354 1355 if (salen == 1 || salen > UCHAR_MAX) { 1356 DPRINTF(("bad osa=%p salen=%d\n", osa, salen)); 1357 return EINVAL; 1358 } 1359 1360 /* We'll need the address in an mbuf later, so copy into one here */ 1361 m = m_get(M_WAIT, MT_SONAME); 1362 if (salen > MLEN) 1363 MEXTMALLOC(m, salen, M_WAITOK); 1364 1365 m->m_len = salen; 1366 1367 if (salen == 0) { 1368 *mp = m; 1369 return 0; 1370 } 1371 1372 kosa = mtod(m, void *); 1373 if ((error = copyin(osa, kosa, salen))) { 1374 DPRINTF(("error %d copying osa %p len %d\n", 1375 error, osa, salen)); 1376 goto bad; 1377 } 1378 1379 ktrkuser("linux sockaddr", kosa, salen); 1380 1381 bdom = linux_to_bsd_domain(kosa->sa_family); 1382 if (bdom == -1) { 1383 DPRINTF(("bad linux family=%d\n", kosa->sa_family)); 1384 error = EINVAL; 1385 goto bad; 1386 } 1387 1388 /* 1389 * If the family is unspecified, use address family of the socket. 1390 * This avoid triggering strict family checks in netinet/in_pcb.c et.al. 1391 */ 1392 if (bdom == AF_UNSPEC) { 1393 struct socket *so; 1394 1395 /* fd_getsock() will use the descriptor for us */ 1396 if ((error = fd_getsock(s, &so)) != 0) 1397 goto bad; 1398 1399 bdom = so->so_proto->pr_domain->dom_family; 1400 fd_putfile(s); 1401 1402 DPRINTF(("AF_UNSPEC family adjusted to %d\n", bdom)); 1403 } 1404 1405 #ifdef INET6 1406 /* 1407 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, 1408 * which lacks the scope id compared with RFC2553 one. If we detect 1409 * the situation, reject the address and write a message to system log. 1410 * 1411 * Still accept addresses for which the scope id is not used. 1412 */ 1413 if (bdom == AF_INET6 && salen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) { 1414 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)kosa; 1415 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) && 1416 (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || 1417 IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) || 1418 IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) || 1419 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || 1420 IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { 1421 struct proc *p = l->l_proc; 1422 int uid = l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1; 1423 1424 log(LOG_DEBUG, 1425 "pid %d (%s), uid %d: obsolete pre-RFC2553 " 1426 "sockaddr_in6 rejected", 1427 p->p_pid, p->p_comm, uid); 1428 error = EINVAL; 1429 goto bad; 1430 } 1431 salen = sizeof (struct sockaddr_in6); 1432 sin6->sin6_scope_id = 0; 1433 } 1434 #endif 1435 1436 if (bdom == AF_INET) 1437 salen = sizeof(struct sockaddr_in); 1438 1439 sa = (struct sockaddr *) kosa; 1440 sa->sa_family = bdom; 1441 sa->sa_len = salen; 1442 m->m_len = salen; 1443 ktrkuser("new sockaddr", kosa, salen); 1444 1445 #ifdef DEBUG_LINUX 1446 DPRINTF(("family %d, len = %d [ ", sa->sa_family, sa->sa_len)); 1447 for (bdom = 0; bdom < sizeof(sa->sa_data); bdom++) 1448 DPRINTF(("%02x ", (unsigned char) sa->sa_data[bdom])); 1449 DPRINTF(("\n")); 1450 #endif 1451 1452 *mp = m; 1453 return 0; 1454 1455 bad: 1456 m_free(m); 1457 return error; 1458 } 1459 1460 static int 1461 linux_sa_put(struct osockaddr *osa) 1462 { 1463 struct sockaddr sa; 1464 struct osockaddr *kosa; 1465 int error, bdom, len; 1466 1467 /* 1468 * Only read/write the sockaddr family and length part, the rest is 1469 * not changed. 1470 */ 1471 len = sizeof(sa.sa_len) + sizeof(sa.sa_family); 1472 1473 error = copyin(osa, &sa, len); 1474 if (error) 1475 return (error); 1476 1477 bdom = bsd_to_linux_domain(sa.sa_family); 1478 if (bdom == -1) 1479 return (EINVAL); 1480 1481 /* Note: we convert from sockaddr to osockaddr here, too */ 1482 kosa = (struct osockaddr *) &sa; 1483 kosa->sa_family = bdom; 1484 error = copyout(kosa, osa, len); 1485 if (error) 1486 return (error); 1487 1488 return (0); 1489 } 1490 1491 #ifndef __amd64__ 1492 int 1493 linux_sys_recv(struct lwp *l, const struct linux_sys_recv_args *uap, register_t *retval) 1494 { 1495 /* { 1496 syscallarg(int) s; 1497 syscallarg(void *) buf; 1498 syscallarg(int) len; 1499 syscallarg(int) flags; 1500 } */ 1501 struct sys_recvfrom_args bra; 1502 1503 1504 SCARG(&bra, s) = SCARG(uap, s); 1505 SCARG(&bra, buf) = SCARG(uap, buf); 1506 SCARG(&bra, len) = (size_t) SCARG(uap, len); 1507 SCARG(&bra, flags) = SCARG(uap, flags); 1508 SCARG(&bra, from) = NULL; 1509 SCARG(&bra, fromlenaddr) = NULL; 1510 1511 return (sys_recvfrom(l, &bra, retval)); 1512 } 1513 1514 int 1515 linux_sys_send(struct lwp *l, const struct linux_sys_send_args *uap, register_t *retval) 1516 { 1517 /* { 1518 syscallarg(int) s; 1519 syscallarg(void *) buf; 1520 syscallarg(int) len; 1521 syscallarg(int) flags; 1522 } */ 1523 struct sys_sendto_args bsa; 1524 1525 SCARG(&bsa, s) = SCARG(uap, s); 1526 SCARG(&bsa, buf) = SCARG(uap, buf); 1527 SCARG(&bsa, len) = SCARG(uap, len); 1528 SCARG(&bsa, flags) = SCARG(uap, flags); 1529 SCARG(&bsa, to) = NULL; 1530 SCARG(&bsa, tolen) = 0; 1531 1532 return (sys_sendto(l, &bsa, retval)); 1533 } 1534 #endif 1535 1536 int 1537 linux_sys_accept(struct lwp *l, const struct linux_sys_accept_args *uap, register_t *retval) 1538 { 1539 /* { 1540 syscallarg(int) s; 1541 syscallarg(struct osockaddr *) name; 1542 syscallarg(int *) anamelen; 1543 } */ 1544 int error; 1545 struct sys_accept_args baa; 1546 1547 SCARG(&baa, s) = SCARG(uap, s); 1548 SCARG(&baa, name) = (struct sockaddr *) SCARG(uap, name); 1549 SCARG(&baa, anamelen) = (unsigned int *) SCARG(uap, anamelen); 1550 1551 if ((error = sys_accept(l, &baa, retval))) 1552 return (error); 1553 1554 if (SCARG(uap, name) && (error = linux_sa_put(SCARG(uap, name)))) 1555 return (error); 1556 1557 return (0); 1558 } 1559