1 /* $NetBSD: linux_socket.c,v 1.30 2001/06/14 20:32:43 thorpej 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 ((fp = fd_getfile(fdp, fd)) == NULL) 483 return (EBADF); 484 485 FILE_USE(fp); 486 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 487 error = EBADF; 488 goto out; 489 } 490 491 error = copyin(data, (caddr_t)&lreq, sizeof(lreq)); 492 if (error) 493 goto out; 494 lreq.if_name[IF_NAME_LEN-1] = '\0'; /* just in case */ 495 496 /* 497 * Try real interface name first, then fake "ethX" 498 */ 499 for (ifp = ifnet.tqh_first, found = 0; 500 ifp != 0 && !found; 501 ifp = ifp->if_list.tqe_next) { 502 if (strcmp(lreq.if_name, ifp->if_xname)) 503 /* not this interface */ 504 continue; 505 found=1; 506 if ((ifa = ifp->if_addrlist.tqh_first) != 0) { 507 for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) { 508 sadl = (struct sockaddr_dl *)ifa->ifa_addr; 509 /* only return ethernet addresses */ 510 /* XXX what about FDDI, etc. ? */ 511 if (sadl->sdl_family != AF_LINK || 512 sadl->sdl_type != IFT_ETHER) 513 continue; 514 memcpy((caddr_t)&lreq.hwaddr.sa_data, 515 LLADDR(sadl), 516 MIN(sadl->sdl_alen, 517 sizeof(lreq.hwaddr.sa_data))); 518 lreq.hwaddr.sa_family = 519 sadl->sdl_family; 520 error = copyout((caddr_t)&lreq, data, 521 sizeof(lreq)); 522 goto out; 523 } 524 } else { 525 error = ENODEV; 526 goto out; 527 } 528 } 529 530 if (lreq.if_name[0] == 'e' && 531 lreq.if_name[1] == 't' && 532 lreq.if_name[2] == 'h') { 533 for (ifnum = 0, index = 3; 534 lreq.if_name[index] != '\0' && index < IF_NAME_LEN; 535 index++) { 536 ifnum *= 10; 537 ifnum += lreq.if_name[index] - '0'; 538 } 539 540 error = EINVAL; /* in case we don't find one */ 541 for (ifp = ifnet.tqh_first, found = 0; 542 ifp != 0 && !found; 543 ifp = ifp->if_list.tqe_next) { 544 memcpy(lreq.if_name, ifp->if_xname, 545 MIN(IF_NAME_LEN, IFNAMSIZ)); 546 if ((ifa = ifp->if_addrlist.tqh_first) == 0) 547 /* no addresses on this interface */ 548 continue; 549 else 550 for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) { 551 sadl = (struct sockaddr_dl *)ifa->ifa_addr; 552 /* only return ethernet addresses */ 553 /* XXX what about FDDI, etc. ? */ 554 if (sadl->sdl_family != AF_LINK || 555 sadl->sdl_type != IFT_ETHER) 556 continue; 557 if (ifnum--) 558 /* not the reqested iface */ 559 continue; 560 memcpy((caddr_t)&lreq.hwaddr.sa_data, 561 LLADDR(sadl), 562 MIN(sadl->sdl_alen, 563 sizeof(lreq.hwaddr.sa_data))); 564 lreq.hwaddr.sa_family = 565 sadl->sdl_family; 566 error = copyout((caddr_t)&lreq, data, 567 sizeof(lreq)); 568 found = 1; 569 break; 570 } 571 } 572 } else { 573 /* unknown interface, not even an "eth*" name */ 574 error = ENODEV; 575 } 576 577 out: 578 FILE_UNUSE(fp, p); 579 return error; 580 } 581 #undef IF_NAME_LEN 582 583 int 584 linux_ioctl_socket(p, uap, retval) 585 struct proc *p; 586 struct linux_sys_ioctl_args /* { 587 syscallarg(int) fd; 588 syscallarg(u_long) com; 589 syscallarg(caddr_t) data; 590 } */ *uap; 591 register_t *retval; 592 { 593 u_long com; 594 int error = 0, isdev = 0, dosys = 1; 595 struct sys_ioctl_args ia; 596 struct file *fp; 597 struct filedesc *fdp; 598 struct vnode *vp; 599 int (*ioctlf) __P((struct file *, u_long, caddr_t, struct proc *)); 600 struct ioctl_pt pt; 601 602 fdp = p->p_fd; 603 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) 604 return (EBADF); 605 606 FILE_USE(fp); 607 608 if (fp->f_type == DTYPE_VNODE) { 609 vp = (struct vnode *)fp->f_data; 610 isdev = vp->v_type == VCHR; 611 } 612 613 /* 614 * Don't try to interpret socket ioctl calls that are done 615 * on a device filedescriptor, just pass them through, to 616 * emulate Linux behaviour. Use PTIOCLINUX so that the 617 * device will only handle these if it's prepared to do 618 * so, to avoid unexpected things from happening. 619 */ 620 if (isdev) { 621 dosys = 0; 622 ioctlf = fp->f_ops->fo_ioctl; 623 pt.com = SCARG(uap, com); 624 pt.data = SCARG(uap, data); 625 error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p); 626 /* 627 * XXX hack: if the function returns EJUSTRETURN, 628 * it has stuffed a sysctl return value in pt.data. 629 */ 630 if (error == EJUSTRETURN) { 631 retval[0] = (register_t)pt.data; 632 error = 0; 633 } 634 goto out; 635 } 636 637 com = SCARG(uap, com); 638 retval[0] = 0; 639 640 switch (com) { 641 case LINUX_SIOCGIFCONF: 642 SCARG(&ia, com) = OSIOCGIFCONF; 643 break; 644 case LINUX_SIOCGIFFLAGS: 645 SCARG(&ia, com) = SIOCGIFFLAGS; 646 break; 647 case LINUX_SIOCSIFFLAGS: 648 SCARG(&ia, com) = SIOCSIFFLAGS; 649 break; 650 case LINUX_SIOCGIFADDR: 651 SCARG(&ia, com) = OSIOCGIFADDR; 652 break; 653 case LINUX_SIOCGIFDSTADDR: 654 SCARG(&ia, com) = OSIOCGIFDSTADDR; 655 break; 656 case LINUX_SIOCGIFBRDADDR: 657 SCARG(&ia, com) = OSIOCGIFBRDADDR; 658 break; 659 case LINUX_SIOCGIFNETMASK: 660 SCARG(&ia, com) = OSIOCGIFNETMASK; 661 break; 662 case LINUX_SIOCADDMULTI: 663 SCARG(&ia, com) = SIOCADDMULTI; 664 break; 665 case LINUX_SIOCDELMULTI: 666 SCARG(&ia, com) = SIOCDELMULTI; 667 break; 668 case LINUX_SIOCGIFHWADDR: 669 error = linux_getifhwaddr(p, retval, SCARG(uap, fd), 670 SCARG(uap, data)); 671 dosys = 0; 672 break; 673 default: 674 error = EINVAL; 675 } 676 677 out: 678 FILE_UNUSE(fp, p); 679 680 if (error ==0 && dosys) { 681 SCARG(&ia, fd) = SCARG(uap, fd); 682 SCARG(&ia, data) = SCARG(uap, data); 683 error = sys_ioctl(p, &ia, retval); 684 } 685 686 return error; 687 } 688 689 int 690 linux_sys_connect(p, v, retval) 691 struct proc *p; 692 void *v; 693 register_t *retval; 694 { 695 int error; 696 697 struct sys_connect_args /* { 698 syscallarg(int) s; 699 syscallarg(const struct sockaddr *) name; 700 syscallarg(unsigned int) namelen; 701 } */ *uap = v; 702 703 error = sys_connect (p, v, retval); 704 705 if (error == EISCONN) { 706 struct file *fp; 707 struct socket *so; 708 int s, state, prflags; 709 710 /* getsock() will use the descriptor for us */ 711 if (getsock(p->p_fd, SCARG(uap, s), &fp) != 0) 712 return EISCONN; 713 714 s = splsoftnet(); 715 so = (struct socket *)fp->f_data; 716 state = so->so_state; 717 prflags = so->so_proto->pr_flags; 718 splx(s); 719 FILE_UNUSE(fp, p); 720 /* 721 * We should only let this call succeed once per 722 * non-blocking connect; however we don't have 723 * a convenient place to keep that state.. 724 */ 725 if ((state & SS_NBIO) && (state & SS_ISCONNECTED) && 726 (prflags & PR_CONNREQUIRED)) 727 return 0; 728 } 729 730 return error; 731 } 732