1 /* $NetBSD: linux_socket.c,v 1.29 2001/03/29 10:37:37 fvdl Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Functions in multiarch: 41 * linux_sys_socketcall : linux_socketcall.c 42 */ 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 <net/if.h> 57 #include <net/if_dl.h> 58 #include <net/if_types.h> 59 #include <netinet/in.h> 60 #include <netinet/tcp.h> 61 #include <sys/mount.h> 62 #include <sys/proc.h> 63 #include <sys/vnode.h> 64 #include <sys/device.h> 65 #include <sys/protosw.h> 66 67 #include <sys/syscallargs.h> 68 69 #include <compat/linux/common/linux_types.h> 70 #include <compat/linux/common/linux_util.h> 71 #include <compat/linux/common/linux_signal.h> 72 #include <compat/linux/common/linux_ioctl.h> 73 #include <compat/linux/common/linux_socket.h> 74 #include <compat/linux/common/linux_socketcall.h> 75 #include <compat/linux/common/linux_sockio.h> 76 77 #include <compat/linux/linux_syscallargs.h> 78 79 /* 80 * The calls in this file are entered either via the linux_socketcall() 81 * interface or, on the Alpha, as individual syscalls. The 82 * linux_socketcall function does any massaging of arguments so that all 83 * the calls in here need not think that they are anything other 84 * than a normal syscall. 85 */ 86 87 int linux_to_bsd_domain __P((int)); 88 int linux_to_bsd_sopt_level __P((int)); 89 int linux_to_bsd_so_sockopt __P((int)); 90 int linux_to_bsd_ip_sockopt __P((int)); 91 int linux_to_bsd_tcp_sockopt __P((int)); 92 int linux_to_bsd_udp_sockopt __P((int)); 93 int linux_getifhwaddr __P((struct proc *, register_t *, u_int, void *)); 94 95 /* 96 * Convert between Linux and BSD socket domain values 97 */ 98 int 99 linux_to_bsd_domain(ldom) 100 int ldom; 101 { 102 103 switch (ldom) { 104 case LINUX_AF_UNSPEC: 105 return AF_UNSPEC; 106 case LINUX_AF_UNIX: 107 return AF_LOCAL; 108 case LINUX_AF_INET: 109 return AF_INET; 110 case LINUX_AF_AX25: 111 return AF_CCITT; 112 case LINUX_AF_IPX: 113 return AF_IPX; 114 case LINUX_AF_APPLETALK: 115 return AF_APPLETALK; 116 case LINUX_AF_X25: 117 return AF_CCITT; 118 case LINUX_AF_INET6: 119 return AF_INET6; 120 case LINUX_AF_DECnet: 121 return AF_DECnet; 122 case LINUX_AF_NETLINK: 123 return AF_ROUTE; 124 /* NETROM, BRIDGE, ATMPVC, ROSE, NETBEUI, SECURITY, */ 125 /* pseudo_AF_KEY, PACKET, ASH, ECONET, ATMSVC, SNA */ 126 default: 127 return -1; 128 } 129 } 130 131 int 132 linux_sys_socket(p, v, retval) 133 struct proc *p; 134 void *v; 135 register_t *retval; 136 { 137 struct linux_sys_socket_args /* { 138 syscallarg(int) domain; 139 syscallarg(int) type; 140 syscallarg(int) protocol; 141 } */ *uap = v; 142 struct sys_socket_args bsa; 143 144 SCARG(&bsa, protocol) = SCARG(uap, protocol); 145 SCARG(&bsa, type) = SCARG(uap, type); 146 SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain)); 147 if (SCARG(&bsa, domain) == -1) 148 return EINVAL; 149 return sys_socket(p, &bsa, retval); 150 } 151 152 int 153 linux_sys_socketpair(p, v, retval) 154 struct proc *p; 155 void *v; 156 register_t *retval; 157 { 158 struct linux_sys_socketpair_args /* { 159 syscallarg(int) domain; 160 syscallarg(int) type; 161 syscallarg(int) protocol; 162 syscallarg(int *) rsv; 163 } */ *uap = v; 164 struct sys_socketpair_args bsa; 165 166 SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain)); 167 if (SCARG(&bsa, domain) == -1) 168 return EINVAL; 169 SCARG(&bsa, type) = SCARG(uap, type); 170 SCARG(&bsa, protocol) = SCARG(uap, protocol); 171 SCARG(&bsa, rsv) = SCARG(uap, rsv); 172 173 return sys_socketpair(p, &bsa, retval); 174 } 175 176 int 177 linux_sys_sendto(p, v, retval) 178 struct proc *p; 179 void *v; 180 register_t *retval; 181 { 182 struct linux_sys_sendto_args /* { 183 syscallarg(int) s; 184 syscallarg(void *) msg; 185 syscallarg(int) len; 186 syscallarg(int) flags; 187 syscallarg(sockaddr *) to; 188 syscallarg(int) tolen; 189 } */ *uap = v; 190 struct sys_sendto_args bsa; 191 192 SCARG(&bsa, s) = SCARG(uap, s); 193 SCARG(&bsa, buf) = SCARG(uap, msg); 194 SCARG(&bsa, len) = SCARG(uap, len); 195 SCARG(&bsa, flags) = SCARG(uap, flags); 196 SCARG(&bsa, to) = (void *) SCARG(uap, to); 197 SCARG(&bsa, tolen) = SCARG(uap, tolen); 198 199 return sys_sendto(p, &bsa, retval); 200 } 201 202 int 203 linux_sys_recvfrom(p, v, retval) 204 struct proc *p; 205 void *v; 206 register_t *retval; 207 { 208 struct linux_sys_recvfrom_args /* { 209 syscallarg(int) s; 210 syscallarg(void *) buf; 211 syscallarg(int) len; 212 syscallarg(int) flags; 213 syscallarg(struct sockaddr *) from; 214 syscallarg(int *) fromlen; 215 } */ *uap = v; 216 struct compat_43_sys_recvfrom_args bra; 217 218 SCARG(&bra, s) = SCARG(uap, s); 219 SCARG(&bra, buf) = SCARG(uap, buf); 220 SCARG(&bra, len) = SCARG(uap, len); 221 SCARG(&bra, flags) = SCARG(uap, flags); 222 SCARG(&bra, from) = (caddr_t) SCARG(uap, from); 223 SCARG(&bra, fromlenaddr) = SCARG(uap, fromlen); 224 225 return compat_43_sys_recvfrom(p, &bra, retval); 226 } 227 228 /* 229 * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET 230 * is different, the rest matches IPPROTO_* on both systems. 231 */ 232 int 233 linux_to_bsd_sopt_level(llevel) 234 int llevel; 235 { 236 237 switch (llevel) { 238 case LINUX_SOL_SOCKET: 239 return SOL_SOCKET; 240 case LINUX_SOL_IP: 241 return IPPROTO_IP; 242 case LINUX_SOL_TCP: 243 return IPPROTO_TCP; 244 case LINUX_SOL_UDP: 245 return IPPROTO_UDP; 246 default: 247 return -1; 248 } 249 } 250 251 /* 252 * Convert Linux socket level socket option numbers to NetBSD values. 253 */ 254 int 255 linux_to_bsd_so_sockopt(lopt) 256 int lopt; 257 { 258 259 switch (lopt) { 260 case LINUX_SO_DEBUG: 261 return SO_DEBUG; 262 case LINUX_SO_REUSEADDR: 263 return SO_REUSEADDR; 264 case LINUX_SO_TYPE: 265 return SO_TYPE; 266 case LINUX_SO_ERROR: 267 return SO_ERROR; 268 case LINUX_SO_DONTROUTE: 269 return SO_DONTROUTE; 270 case LINUX_SO_BROADCAST: 271 return SO_BROADCAST; 272 case LINUX_SO_SNDBUF: 273 return SO_SNDBUF; 274 case LINUX_SO_RCVBUF: 275 return SO_RCVBUF; 276 case LINUX_SO_KEEPALIVE: 277 return SO_KEEPALIVE; 278 case LINUX_SO_OOBINLINE: 279 return SO_OOBINLINE; 280 case LINUX_SO_LINGER: 281 return SO_LINGER; 282 case LINUX_SO_PRIORITY: 283 case LINUX_SO_NO_CHECK: 284 default: 285 return -1; 286 } 287 } 288 289 /* 290 * Convert Linux IP level socket option number to NetBSD values. 291 */ 292 int 293 linux_to_bsd_ip_sockopt(lopt) 294 int lopt; 295 { 296 297 switch (lopt) { 298 case LINUX_IP_TOS: 299 return IP_TOS; 300 case LINUX_IP_TTL: 301 return IP_TTL; 302 case LINUX_IP_MULTICAST_TTL: 303 return IP_MULTICAST_TTL; 304 case LINUX_IP_MULTICAST_LOOP: 305 return IP_MULTICAST_LOOP; 306 case LINUX_IP_MULTICAST_IF: 307 return IP_MULTICAST_IF; 308 case LINUX_IP_ADD_MEMBERSHIP: 309 return IP_ADD_MEMBERSHIP; 310 case LINUX_IP_DROP_MEMBERSHIP: 311 return IP_DROP_MEMBERSHIP; 312 default: 313 return -1; 314 } 315 } 316 317 /* 318 * Convert Linux TCP level socket option number to NetBSD values. 319 */ 320 int 321 linux_to_bsd_tcp_sockopt(lopt) 322 int lopt; 323 { 324 325 switch (lopt) { 326 case LINUX_TCP_NODELAY: 327 return TCP_NODELAY; 328 case LINUX_TCP_MAXSEG: 329 return TCP_MAXSEG; 330 default: 331 return -1; 332 } 333 } 334 335 /* 336 * Convert Linux UDP level socket option number to NetBSD values. 337 */ 338 int 339 linux_to_bsd_udp_sockopt(lopt) 340 int lopt; 341 { 342 343 switch (lopt) { 344 default: 345 return -1; 346 } 347 } 348 349 /* 350 * Another reasonably straightforward function: setsockopt(2). 351 * The level and option numbers are converted; the values passed 352 * are not (yet) converted, the ones currently implemented don't 353 * need conversion, as they are the same on both systems. 354 */ 355 int 356 linux_sys_setsockopt(p, v, retval) 357 struct proc *p; 358 void *v; 359 register_t *retval; 360 { 361 struct linux_sys_setsockopt_args /* { 362 syscallarg(int) s; 363 syscallarg(int) level; 364 syscallarg(int) optname; 365 syscallarg(void *) optval; 366 syscallarg(int) optlen; 367 } */ *uap = v; 368 struct sys_setsockopt_args bsa; 369 int name; 370 371 SCARG(&bsa, s) = SCARG(uap, s); 372 SCARG(&bsa, level) = linux_to_bsd_sopt_level(SCARG(uap, level)); 373 SCARG(&bsa, val) = SCARG(uap, optval); 374 SCARG(&bsa, valsize) = SCARG(uap, optlen); 375 376 switch (SCARG(&bsa, level)) { 377 case SOL_SOCKET: 378 name = linux_to_bsd_so_sockopt(SCARG(uap, optname)); 379 break; 380 case IPPROTO_IP: 381 name = linux_to_bsd_ip_sockopt(SCARG(uap, optname)); 382 break; 383 case IPPROTO_TCP: 384 name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname)); 385 break; 386 case IPPROTO_UDP: 387 name = linux_to_bsd_udp_sockopt(SCARG(uap, optname)); 388 break; 389 default: 390 return EINVAL; 391 } 392 393 if (name == -1) 394 return EINVAL; 395 SCARG(&bsa, name) = name; 396 397 return sys_setsockopt(p, &bsa, retval); 398 } 399 400 /* 401 * getsockopt(2) is very much the same as setsockopt(2) (see above) 402 */ 403 int 404 linux_sys_getsockopt(p, v, retval) 405 struct proc *p; 406 void *v; 407 register_t *retval; 408 { 409 struct linux_sys_getsockopt_args /* { 410 syscallarg(int) s; 411 syscallarg(int) level; 412 syscallarg(int) optname; 413 syscallarg(void *) optval; 414 syscallarg(int *) optlen; 415 } */ *uap = v; 416 struct sys_getsockopt_args bga; 417 int name; 418 419 SCARG(&bga, s) = SCARG(uap, s); 420 SCARG(&bga, level) = linux_to_bsd_sopt_level(SCARG(uap, level)); 421 SCARG(&bga, val) = SCARG(uap, optval); 422 SCARG(&bga, avalsize) = SCARG(uap, optlen); 423 424 switch (SCARG(&bga, level)) { 425 case SOL_SOCKET: 426 name = linux_to_bsd_so_sockopt(SCARG(uap, optname)); 427 break; 428 case IPPROTO_IP: 429 name = linux_to_bsd_ip_sockopt(SCARG(uap, optname)); 430 break; 431 case IPPROTO_TCP: 432 name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname)); 433 break; 434 case IPPROTO_UDP: 435 name = linux_to_bsd_udp_sockopt(SCARG(uap, optname)); 436 break; 437 default: 438 return EINVAL; 439 } 440 441 if (name == -1) 442 return EINVAL; 443 SCARG(&bga, name) = name; 444 445 return sys_getsockopt(p, &bga, retval); 446 } 447 448 #define IF_NAME_LEN 16 449 450 int 451 linux_getifhwaddr(p, retval, fd, data) 452 struct proc *p; 453 register_t *retval; 454 u_int fd; 455 void *data; 456 { 457 /* Not the full structure, just enough to map what we do here */ 458 struct linux_ifreq { 459 char if_name[IF_NAME_LEN]; 460 struct osockaddr hwaddr; 461 } lreq; 462 struct filedesc *fdp; 463 struct file *fp; 464 struct ifaddr *ifa; 465 struct ifnet *ifp; 466 struct sockaddr_dl *sadl; 467 int error, found; 468 int index, ifnum; 469 470 /* 471 * We can't emulate this ioctl by calling sys_ioctl() to run 472 * SIOCGIFCONF, because the user buffer is not of the right 473 * type to take those results. We can't use kernel buffers to 474 * receive the results, as the implementation of sys_ioctl() 475 * and ifconf() [which implements SIOCGIFCONF] use 476 * copyin()/copyout() which will fail on kernel addresses. 477 * 478 * So, we must duplicate code from sys_ioctl() and ifconf(). Ugh. 479 */ 480 481 fdp = p->p_fd; 482 if (fd >= fdp->fd_nfiles || 483 (fp = fdp->fd_ofiles[fd]) == NULL || 484 (fp->f_iflags & FIF_WANTCLOSE) != 0) 485 return (EBADF); 486 487 FILE_USE(fp); 488 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 489 error = EBADF; 490 goto out; 491 } 492 493 error = copyin(data, (caddr_t)&lreq, sizeof(lreq)); 494 if (error) 495 goto out; 496 lreq.if_name[IF_NAME_LEN-1] = '\0'; /* just in case */ 497 498 /* 499 * Try real interface name first, then fake "ethX" 500 */ 501 for (ifp = ifnet.tqh_first, found = 0; 502 ifp != 0 && !found; 503 ifp = ifp->if_list.tqe_next) { 504 if (strcmp(lreq.if_name, ifp->if_xname)) 505 /* not this interface */ 506 continue; 507 found=1; 508 if ((ifa = ifp->if_addrlist.tqh_first) != 0) { 509 for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) { 510 sadl = (struct sockaddr_dl *)ifa->ifa_addr; 511 /* only return ethernet addresses */ 512 /* XXX what about FDDI, etc. ? */ 513 if (sadl->sdl_family != AF_LINK || 514 sadl->sdl_type != IFT_ETHER) 515 continue; 516 memcpy((caddr_t)&lreq.hwaddr.sa_data, 517 LLADDR(sadl), 518 MIN(sadl->sdl_alen, 519 sizeof(lreq.hwaddr.sa_data))); 520 lreq.hwaddr.sa_family = 521 sadl->sdl_family; 522 error = copyout((caddr_t)&lreq, data, 523 sizeof(lreq)); 524 goto out; 525 } 526 } else { 527 error = ENODEV; 528 goto out; 529 } 530 } 531 532 if (lreq.if_name[0] == 'e' && 533 lreq.if_name[1] == 't' && 534 lreq.if_name[2] == 'h') { 535 for (ifnum = 0, index = 3; 536 lreq.if_name[index] != '\0' && index < IF_NAME_LEN; 537 index++) { 538 ifnum *= 10; 539 ifnum += lreq.if_name[index] - '0'; 540 } 541 542 error = EINVAL; /* in case we don't find one */ 543 for (ifp = ifnet.tqh_first, found = 0; 544 ifp != 0 && !found; 545 ifp = ifp->if_list.tqe_next) { 546 memcpy(lreq.if_name, ifp->if_xname, 547 MIN(IF_NAME_LEN, IFNAMSIZ)); 548 if ((ifa = ifp->if_addrlist.tqh_first) == 0) 549 /* no addresses on this interface */ 550 continue; 551 else 552 for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) { 553 sadl = (struct sockaddr_dl *)ifa->ifa_addr; 554 /* only return ethernet addresses */ 555 /* XXX what about FDDI, etc. ? */ 556 if (sadl->sdl_family != AF_LINK || 557 sadl->sdl_type != IFT_ETHER) 558 continue; 559 if (ifnum--) 560 /* not the reqested iface */ 561 continue; 562 memcpy((caddr_t)&lreq.hwaddr.sa_data, 563 LLADDR(sadl), 564 MIN(sadl->sdl_alen, 565 sizeof(lreq.hwaddr.sa_data))); 566 lreq.hwaddr.sa_family = 567 sadl->sdl_family; 568 error = copyout((caddr_t)&lreq, data, 569 sizeof(lreq)); 570 found = 1; 571 break; 572 } 573 } 574 } else { 575 /* unknown interface, not even an "eth*" name */ 576 error = ENODEV; 577 } 578 579 out: 580 FILE_UNUSE(fp, p); 581 return error; 582 } 583 #undef IF_NAME_LEN 584 585 int 586 linux_ioctl_socket(p, uap, retval) 587 struct proc *p; 588 struct linux_sys_ioctl_args /* { 589 syscallarg(int) fd; 590 syscallarg(u_long) com; 591 syscallarg(caddr_t) data; 592 } */ *uap; 593 register_t *retval; 594 { 595 u_long com; 596 int error = 0, isdev = 0, dosys = 1; 597 struct sys_ioctl_args ia; 598 struct file *fp; 599 struct filedesc *fdp; 600 struct vnode *vp; 601 int (*ioctlf) __P((struct file *, u_long, caddr_t, struct proc *)); 602 struct ioctl_pt pt; 603 604 fdp = p->p_fd; 605 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 606 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || 607 (fp->f_iflags & FIF_WANTCLOSE) != 0) 608 return (EBADF); 609 610 FILE_USE(fp); 611 612 if (fp->f_type == DTYPE_VNODE) { 613 vp = (struct vnode *)fp->f_data; 614 isdev = vp->v_type == VCHR; 615 } 616 617 /* 618 * Don't try to interpret socket ioctl calls that are done 619 * on a device filedescriptor, just pass them through, to 620 * emulate Linux behaviour. Use PTIOCLINUX so that the 621 * device will only handle these if it's prepared to do 622 * so, to avoid unexpected things from happening. 623 */ 624 if (isdev) { 625 dosys = 0; 626 ioctlf = fp->f_ops->fo_ioctl; 627 pt.com = SCARG(uap, com); 628 pt.data = SCARG(uap, data); 629 error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p); 630 /* 631 * XXX hack: if the function returns EJUSTRETURN, 632 * it has stuffed a sysctl return value in pt.data. 633 */ 634 if (error == EJUSTRETURN) { 635 retval[0] = (register_t)pt.data; 636 error = 0; 637 } 638 goto out; 639 } 640 641 com = SCARG(uap, com); 642 retval[0] = 0; 643 644 switch (com) { 645 case LINUX_SIOCGIFCONF: 646 SCARG(&ia, com) = OSIOCGIFCONF; 647 break; 648 case LINUX_SIOCGIFFLAGS: 649 SCARG(&ia, com) = SIOCGIFFLAGS; 650 break; 651 case LINUX_SIOCSIFFLAGS: 652 SCARG(&ia, com) = SIOCSIFFLAGS; 653 break; 654 case LINUX_SIOCGIFADDR: 655 SCARG(&ia, com) = OSIOCGIFADDR; 656 break; 657 case LINUX_SIOCGIFDSTADDR: 658 SCARG(&ia, com) = OSIOCGIFDSTADDR; 659 break; 660 case LINUX_SIOCGIFBRDADDR: 661 SCARG(&ia, com) = OSIOCGIFBRDADDR; 662 break; 663 case LINUX_SIOCGIFNETMASK: 664 SCARG(&ia, com) = OSIOCGIFNETMASK; 665 break; 666 case LINUX_SIOCADDMULTI: 667 SCARG(&ia, com) = SIOCADDMULTI; 668 break; 669 case LINUX_SIOCDELMULTI: 670 SCARG(&ia, com) = SIOCDELMULTI; 671 break; 672 case LINUX_SIOCGIFHWADDR: 673 error = linux_getifhwaddr(p, retval, SCARG(uap, fd), 674 SCARG(uap, data)); 675 dosys = 0; 676 break; 677 default: 678 error = EINVAL; 679 } 680 681 out: 682 FILE_UNUSE(fp, p); 683 684 if (error ==0 && dosys) { 685 SCARG(&ia, fd) = SCARG(uap, fd); 686 SCARG(&ia, data) = SCARG(uap, data); 687 error = sys_ioctl(p, &ia, retval); 688 } 689 690 return error; 691 } 692 693 int 694 linux_sys_connect(p, v, retval) 695 struct proc *p; 696 void *v; 697 register_t *retval; 698 { 699 int error; 700 701 struct sys_connect_args /* { 702 syscallarg(int) s; 703 syscallarg(const struct sockaddr *) name; 704 syscallarg(unsigned int) namelen; 705 } */ *uap = v; 706 707 error = sys_connect (p, v, retval); 708 709 if (error == EISCONN) { 710 struct file *fp; 711 struct socket *so; 712 int s, state, prflags; 713 714 /* getsock() will use the descriptor for us */ 715 if (getsock(p->p_fd, SCARG(uap, s), &fp) != 0) 716 return EISCONN; 717 718 s = splsoftnet(); 719 so = (struct socket *)fp->f_data; 720 state = so->so_state; 721 prflags = so->so_proto->pr_flags; 722 splx(s); 723 FILE_UNUSE(fp, p); 724 /* 725 * We should only let this call succeed once per 726 * non-blocking connect; however we don't have 727 * a convenient place to keep that state.. 728 */ 729 if ((state & SS_NBIO) && (state & SS_ISCONNECTED) && 730 (prflags & PR_CONNREQUIRED)) 731 return 0; 732 } 733 734 return error; 735 } 736