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