1 /* $OpenBSD: uipc_syscalls.c,v 1.200 2022/08/13 21:01:46 mvs Exp $ */ 2 /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1989, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/filedesc.h> 38 #include <sys/namei.h> 39 #include <sys/pool.h> 40 #include <sys/proc.h> 41 #include <sys/fcntl.h> 42 #include <sys/kernel.h> 43 #include <sys/file.h> 44 #include <sys/vnode.h> 45 #include <sys/ioctl.h> 46 #include <sys/malloc.h> 47 #include <sys/event.h> 48 #include <sys/mbuf.h> 49 #include <sys/protosw.h> 50 #include <sys/socket.h> 51 #include <sys/socketvar.h> 52 #include <sys/signalvar.h> 53 #include <sys/pledge.h> 54 #include <sys/unpcb.h> 55 #include <sys/un.h> 56 #ifdef KTRACE 57 #include <sys/ktrace.h> 58 #endif 59 #include <sys/unistd.h> 60 61 #include <sys/mount.h> 62 #include <sys/syscallargs.h> 63 64 #include <sys/domain.h> 65 #include <netinet/in.h> 66 #include <net/route.h> 67 68 int copyaddrout(struct proc *, struct mbuf *, struct sockaddr *, socklen_t, 69 socklen_t *); 70 71 int 72 sys_socket(struct proc *p, void *v, register_t *retval) 73 { 74 struct sys_socket_args /* { 75 syscallarg(int) domain; 76 syscallarg(int) type; 77 syscallarg(int) protocol; 78 } */ *uap = v; 79 struct filedesc *fdp = p->p_fd; 80 struct socket *so; 81 struct file *fp; 82 int type = SCARG(uap, type); 83 int domain = SCARG(uap, domain); 84 int fd, cloexec, nonblock, fflag, error; 85 unsigned int ss = 0; 86 87 if ((type & SOCK_DNS) && !(domain == AF_INET || domain == AF_INET6)) 88 return (EINVAL); 89 90 if (ISSET(type, SOCK_DNS)) 91 ss |= SS_DNS; 92 error = pledge_socket(p, domain, ss); 93 if (error) 94 return (error); 95 96 type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_DNS); 97 cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0; 98 nonblock = SCARG(uap, type) & SOCK_NONBLOCK; 99 fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0); 100 101 error = socreate(SCARG(uap, domain), &so, type, SCARG(uap, protocol)); 102 if (error) 103 return (error); 104 105 fdplock(fdp); 106 error = falloc(p, &fp, &fd); 107 if (error) { 108 fdpunlock(fdp); 109 soclose(so, MSG_DONTWAIT); 110 } else { 111 fp->f_flag = fflag; 112 fp->f_type = DTYPE_SOCKET; 113 fp->f_ops = &socketops; 114 so->so_state |= ss; 115 fp->f_data = so; 116 fdinsert(fdp, fd, cloexec, fp); 117 fdpunlock(fdp); 118 FRELE(fp, p); 119 *retval = fd; 120 } 121 return (error); 122 } 123 124 static inline int 125 isdnssocket(struct socket *so) 126 { 127 return (so->so_state & SS_DNS); 128 } 129 130 /* For SS_DNS sockets, only allow port DNS (port 53) */ 131 static int 132 dns_portcheck(struct proc *p, struct socket *so, void *nam, size_t namelen) 133 { 134 int error = EINVAL; 135 136 switch (so->so_proto->pr_domain->dom_family) { 137 case AF_INET: 138 if (namelen < sizeof(struct sockaddr_in)) 139 break; 140 if (((struct sockaddr_in *)nam)->sin_port == htons(53)) 141 error = 0; 142 break; 143 #ifdef INET6 144 case AF_INET6: 145 if (namelen < sizeof(struct sockaddr_in6)) 146 break; 147 if (((struct sockaddr_in6 *)nam)->sin6_port == htons(53)) 148 error = 0; 149 #endif 150 } 151 if (error && p->p_p->ps_flags & PS_PLEDGE) 152 return (pledge_fail(p, EPERM, PLEDGE_DNS)); 153 return error; 154 } 155 156 int 157 sys_bind(struct proc *p, void *v, register_t *retval) 158 { 159 struct sys_bind_args /* { 160 syscallarg(int) s; 161 syscallarg(const struct sockaddr *) name; 162 syscallarg(socklen_t) namelen; 163 } */ *uap = v; 164 struct file *fp; 165 struct mbuf *nam; 166 struct socket *so; 167 int error; 168 169 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 170 return (error); 171 so = fp->f_data; 172 error = pledge_socket(p, so->so_proto->pr_domain->dom_family, 173 so->so_state); 174 if (error) 175 goto out; 176 if (so->so_state & SS_YP) { 177 error = ENOTSOCK; 178 goto out; 179 } 180 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 181 MT_SONAME); 182 if (error) 183 goto out; 184 #ifdef KTRACE 185 if (KTRPOINT(p, KTR_STRUCT)) 186 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen)); 187 #endif 188 solock(so); 189 error = sobind(so, nam, p); 190 sounlock(so); 191 m_freem(nam); 192 out: 193 FRELE(fp, p); 194 return (error); 195 } 196 197 int 198 sys_listen(struct proc *p, void *v, register_t *retval) 199 { 200 struct sys_listen_args /* { 201 syscallarg(int) s; 202 syscallarg(int) backlog; 203 } */ *uap = v; 204 struct file *fp; 205 struct socket *so; 206 int error; 207 208 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 209 return (error); 210 so = fp->f_data; 211 if (so->so_state & SS_YP) 212 return ENOTSOCK; 213 solock(so); 214 error = solisten(so, SCARG(uap, backlog)); 215 sounlock(so); 216 FRELE(fp, p); 217 return (error); 218 } 219 220 int 221 sys_accept(struct proc *p, void *v, register_t *retval) 222 { 223 struct sys_accept_args /* { 224 syscallarg(int) s; 225 syscallarg(struct sockaddr *) name; 226 syscallarg(socklen_t *) anamelen; 227 } */ *uap = v; 228 229 return (doaccept(p, SCARG(uap, s), SCARG(uap, name), 230 SCARG(uap, anamelen), SOCK_NONBLOCK_INHERIT, retval)); 231 } 232 233 int 234 sys_accept4(struct proc *p, void *v, register_t *retval) 235 { 236 struct sys_accept4_args /* { 237 syscallarg(int) s; 238 syscallarg(struct sockaddr *) name; 239 syscallarg(socklen_t *) anamelen; 240 syscallarg(socklen_t *) int flags; 241 } */ *uap = v; 242 243 if (SCARG(uap, flags) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 244 return (EINVAL); 245 246 return (doaccept(p, SCARG(uap, s), SCARG(uap, name), 247 SCARG(uap, anamelen), SCARG(uap, flags), retval)); 248 } 249 250 int 251 doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen, 252 int flags, register_t *retval) 253 { 254 struct filedesc *fdp = p->p_fd; 255 struct file *fp, *headfp; 256 struct mbuf *nam; 257 socklen_t namelen; 258 int error, tmpfd; 259 struct socket *head, *so; 260 int cloexec, nflag, persocket; 261 262 cloexec = (flags & SOCK_CLOEXEC) ? UF_EXCLOSE : 0; 263 264 if (name && (error = copyin(anamelen, &namelen, sizeof (namelen)))) 265 return (error); 266 if ((error = getsock(p, sock, &fp)) != 0) 267 return (error); 268 269 headfp = fp; 270 271 fdplock(fdp); 272 error = falloc(p, &fp, &tmpfd); 273 fdpunlock(fdp); 274 if (error) { 275 FRELE(headfp, p); 276 return (error); 277 } 278 279 nam = m_get(M_WAIT, MT_SONAME); 280 281 head = headfp->f_data; 282 solock(head); 283 284 persocket = solock_persocket(head); 285 286 if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) { 287 error = EINVAL; 288 goto out_unlock; 289 } 290 if ((headfp->f_flag & FNONBLOCK) && head->so_qlen == 0) { 291 if (head->so_state & SS_CANTRCVMORE) 292 error = ECONNABORTED; 293 else 294 error = EWOULDBLOCK; 295 goto out_unlock; 296 } 297 while (head->so_qlen == 0 && head->so_error == 0) { 298 if (head->so_state & SS_CANTRCVMORE) { 299 head->so_error = ECONNABORTED; 300 break; 301 } 302 error = sosleep_nsec(head, &head->so_timeo, PSOCK | PCATCH, 303 "netcon", INFSLP); 304 if (error) 305 goto out_unlock; 306 } 307 if (head->so_error) { 308 error = head->so_error; 309 head->so_error = 0; 310 goto out_unlock; 311 } 312 313 /* 314 * Do not sleep after we have taken the socket out of the queue. 315 */ 316 so = TAILQ_FIRST(&head->so_q); 317 318 if (persocket) 319 solock(so); 320 321 if (soqremque(so, 1) == 0) 322 panic("accept"); 323 324 /* Figure out whether the new socket should be non-blocking. */ 325 nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK) 326 : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0); 327 328 /* connection has been removed from the listen queue */ 329 KNOTE(&head->so_rcv.sb_sel.si_note, 0); 330 331 if (persocket) 332 sounlock(head); 333 334 fp->f_type = DTYPE_SOCKET; 335 fp->f_flag = FREAD | FWRITE | nflag; 336 fp->f_ops = &socketops; 337 fp->f_data = so; 338 339 error = soaccept(so, nam); 340 341 if (persocket) 342 sounlock(so); 343 else 344 sounlock(head); 345 346 if (error) 347 goto out; 348 349 if (name != NULL) { 350 error = copyaddrout(p, nam, name, namelen, anamelen); 351 if (error) 352 goto out; 353 } 354 355 fdplock(fdp); 356 fdinsert(fdp, tmpfd, cloexec, fp); 357 fdpunlock(fdp); 358 FRELE(fp, p); 359 *retval = tmpfd; 360 361 m_freem(nam); 362 FRELE(headfp, p); 363 364 return 0; 365 366 out_unlock: 367 sounlock(head); 368 out: 369 fdplock(fdp); 370 fdremove(fdp, tmpfd); 371 fdpunlock(fdp); 372 closef(fp, p); 373 374 m_freem(nam); 375 FRELE(headfp, p); 376 377 return (error); 378 } 379 380 int 381 sys_connect(struct proc *p, void *v, register_t *retval) 382 { 383 struct sys_connect_args /* { 384 syscallarg(int) s; 385 syscallarg(const struct sockaddr *) name; 386 syscallarg(socklen_t) namelen; 387 } */ *uap = v; 388 struct file *fp; 389 struct socket *so; 390 struct mbuf *nam; 391 int error, interrupted = 0; 392 393 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 394 return (error); 395 so = fp->f_data; 396 error = pledge_socket(p, so->so_proto->pr_domain->dom_family, 397 so->so_state); 398 if (error) 399 goto out; 400 if (so->so_state & SS_YP) { 401 error = ENOTSOCK; 402 goto out; 403 } 404 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 405 MT_SONAME); 406 if (error) 407 goto out; 408 #ifdef KTRACE 409 if (KTRPOINT(p, KTR_STRUCT)) 410 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen)); 411 #endif 412 solock(so); 413 if (isdnssocket(so)) { 414 error = dns_portcheck(p, so, mtod(nam, void *), nam->m_len); 415 if (error) 416 goto unlock; 417 } 418 if (so->so_state & SS_ISCONNECTING) { 419 error = EALREADY; 420 goto unlock; 421 } 422 error = soconnect(so, nam); 423 if (error) 424 goto bad; 425 if ((fp->f_flag & FNONBLOCK) && (so->so_state & SS_ISCONNECTING)) { 426 error = EINPROGRESS; 427 goto unlock; 428 } 429 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 430 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH, 431 "netcon2", INFSLP); 432 if (error) { 433 if (error == EINTR || error == ERESTART) 434 interrupted = 1; 435 break; 436 } 437 } 438 if (error == 0) { 439 error = so->so_error; 440 so->so_error = 0; 441 } 442 bad: 443 if (!interrupted) 444 so->so_state &= ~SS_ISCONNECTING; 445 unlock: 446 sounlock(so); 447 m_freem(nam); 448 out: 449 FRELE(fp, p); 450 if (error == ERESTART) 451 error = EINTR; 452 return (error); 453 } 454 455 int 456 sys_socketpair(struct proc *p, void *v, register_t *retval) 457 { 458 struct sys_socketpair_args /* { 459 syscallarg(int) domain; 460 syscallarg(int) type; 461 syscallarg(int) protocol; 462 syscallarg(int *) rsv; 463 } */ *uap = v; 464 struct filedesc *fdp = p->p_fd; 465 struct file *fp1 = NULL, *fp2 = NULL; 466 struct socket *so1, *so2; 467 int type, cloexec, nonblock, fflag, error, sv[2]; 468 469 type = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); 470 cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0; 471 nonblock = SCARG(uap, type) & SOCK_NONBLOCK; 472 fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0); 473 474 error = socreate(SCARG(uap, domain), &so1, type, SCARG(uap, protocol)); 475 if (error) 476 return (error); 477 error = socreate(SCARG(uap, domain), &so2, type, SCARG(uap, protocol)); 478 if (error) 479 goto free1; 480 481 error = soconnect2(so1, so2); 482 if (error != 0) 483 goto free2; 484 485 if ((SCARG(uap, type) & SOCK_TYPE_MASK) == SOCK_DGRAM) { 486 /* 487 * Datagram socket connection is asymmetric. 488 */ 489 error = soconnect2(so2, so1); 490 if (error != 0) 491 goto free2; 492 } 493 fdplock(fdp); 494 if ((error = falloc(p, &fp1, &sv[0])) != 0) 495 goto free3; 496 fp1->f_flag = fflag; 497 fp1->f_type = DTYPE_SOCKET; 498 fp1->f_ops = &socketops; 499 fp1->f_data = so1; 500 if ((error = falloc(p, &fp2, &sv[1])) != 0) 501 goto free4; 502 fp2->f_flag = fflag; 503 fp2->f_type = DTYPE_SOCKET; 504 fp2->f_ops = &socketops; 505 fp2->f_data = so2; 506 error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int)); 507 if (error == 0) { 508 fdinsert(fdp, sv[0], cloexec, fp1); 509 fdinsert(fdp, sv[1], cloexec, fp2); 510 fdpunlock(fdp); 511 #ifdef KTRACE 512 if (KTRPOINT(p, KTR_STRUCT)) 513 ktrfds(p, sv, 2); 514 #endif 515 FRELE(fp1, p); 516 FRELE(fp2, p); 517 return (0); 518 } 519 fdremove(fdp, sv[1]); 520 free4: 521 fdremove(fdp, sv[0]); 522 free3: 523 fdpunlock(fdp); 524 525 if (fp2 != NULL) { 526 closef(fp2, p); 527 so2 = NULL; 528 } 529 if (fp1 != NULL) { 530 closef(fp1, p); 531 so1 = NULL; 532 } 533 free2: 534 if (so2 != NULL) 535 (void)soclose(so2, 0); 536 free1: 537 if (so1 != NULL) 538 (void)soclose(so1, 0); 539 return (error); 540 } 541 542 int 543 sys_sendto(struct proc *p, void *v, register_t *retval) 544 { 545 struct sys_sendto_args /* { 546 syscallarg(int) s; 547 syscallarg(const void *) buf; 548 syscallarg(size_t) len; 549 syscallarg(int) flags; 550 syscallarg(const struct sockaddr *) to; 551 syscallarg(socklen_t) tolen; 552 } */ *uap = v; 553 struct msghdr msg; 554 struct iovec aiov; 555 556 msg.msg_name = (caddr_t)SCARG(uap, to); 557 msg.msg_namelen = SCARG(uap, tolen); 558 msg.msg_iov = &aiov; 559 msg.msg_iovlen = 1; 560 msg.msg_control = NULL; 561 msg.msg_flags = 0; 562 aiov.iov_base = (char *)SCARG(uap, buf); 563 aiov.iov_len = SCARG(uap, len); 564 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); 565 } 566 567 int 568 sys_sendmsg(struct proc *p, void *v, register_t *retval) 569 { 570 struct sys_sendmsg_args /* { 571 syscallarg(int) s; 572 syscallarg(const struct msghdr *) msg; 573 syscallarg(int) flags; 574 } */ *uap = v; 575 struct msghdr msg; 576 struct iovec aiov[UIO_SMALLIOV], *iov; 577 int error; 578 579 error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); 580 if (error) 581 return (error); 582 #ifdef KTRACE 583 if (KTRPOINT(p, KTR_STRUCT)) 584 ktrmsghdr(p, &msg); 585 #endif 586 587 if (msg.msg_iovlen > IOV_MAX) 588 return (EMSGSIZE); 589 if (msg.msg_iovlen > UIO_SMALLIOV) 590 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec), 591 M_IOV, M_WAITOK); 592 else 593 iov = aiov; 594 if (msg.msg_iovlen && 595 (error = copyin(msg.msg_iov, iov, 596 msg.msg_iovlen * sizeof (struct iovec)))) 597 goto done; 598 #ifdef KTRACE 599 if (msg.msg_iovlen && KTRPOINT(p, KTR_STRUCT)) 600 ktriovec(p, iov, msg.msg_iovlen); 601 #endif 602 msg.msg_iov = iov; 603 msg.msg_flags = 0; 604 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 605 done: 606 if (iov != aiov) 607 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen); 608 return (error); 609 } 610 611 int 612 sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize) 613 { 614 struct file *fp; 615 struct uio auio; 616 struct iovec *iov; 617 int i; 618 struct mbuf *to, *control; 619 struct socket *so; 620 size_t len; 621 int error; 622 #ifdef KTRACE 623 struct iovec *ktriov = NULL; 624 int iovlen = 0; 625 #endif 626 627 to = NULL; 628 629 if ((error = getsock(p, s, &fp)) != 0) 630 return (error); 631 so = fp->f_data; 632 if (fp->f_flag & FNONBLOCK) 633 flags |= MSG_DONTWAIT; 634 635 error = pledge_sendit(p, mp->msg_name); 636 if (error) 637 goto bad; 638 639 auio.uio_iov = mp->msg_iov; 640 auio.uio_iovcnt = mp->msg_iovlen; 641 auio.uio_segflg = UIO_USERSPACE; 642 auio.uio_rw = UIO_WRITE; 643 auio.uio_procp = p; 644 auio.uio_offset = 0; /* XXX */ 645 auio.uio_resid = 0; 646 iov = mp->msg_iov; 647 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 648 /* Don't allow sum > SSIZE_MAX */ 649 if (iov->iov_len > SSIZE_MAX || 650 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { 651 error = EINVAL; 652 goto bad; 653 } 654 } 655 if (mp->msg_name) { 656 error = sockargs(&to, mp->msg_name, mp->msg_namelen, 657 MT_SONAME); 658 if (error) 659 goto bad; 660 if (isdnssocket(so)) { 661 error = dns_portcheck(p, so, mtod(to, caddr_t), 662 mp->msg_namelen); 663 if (error) 664 goto bad; 665 } 666 #ifdef KTRACE 667 if (KTRPOINT(p, KTR_STRUCT)) 668 ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen); 669 #endif 670 } 671 if (mp->msg_control) { 672 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) { 673 error = EINVAL; 674 goto bad; 675 } 676 error = sockargs(&control, mp->msg_control, 677 mp->msg_controllen, MT_CONTROL); 678 if (error) 679 goto bad; 680 #ifdef KTRACE 681 if (KTRPOINT(p, KTR_STRUCT) && mp->msg_controllen) 682 ktrcmsghdr(p, mtod(control, char *), 683 mp->msg_controllen); 684 #endif 685 } else 686 control = NULL; 687 #ifdef KTRACE 688 if (KTRPOINT(p, KTR_GENIO)) { 689 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec), 690 M_TEMP, M_WAITOK); 691 iovlen = auio.uio_iovcnt * sizeof (struct iovec); 692 693 memcpy(ktriov, auio.uio_iov, iovlen); 694 } 695 #endif 696 len = auio.uio_resid; 697 error = sosend(so, to, &auio, NULL, control, flags); 698 if (error) { 699 if (auio.uio_resid != len && (error == ERESTART || 700 error == EINTR || error == EWOULDBLOCK)) 701 error = 0; 702 if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) { 703 KERNEL_LOCK(); 704 ptsignal(p, SIGPIPE, STHREAD); 705 KERNEL_UNLOCK(); 706 } 707 } 708 if (error == 0) { 709 *retsize = len - auio.uio_resid; 710 mtx_enter(&fp->f_mtx); 711 fp->f_wxfer++; 712 fp->f_wbytes += *retsize; 713 mtx_leave(&fp->f_mtx); 714 } 715 #ifdef KTRACE 716 if (ktriov != NULL) { 717 if (error == 0) 718 ktrgenio(p, s, UIO_WRITE, ktriov, *retsize); 719 free(ktriov, M_TEMP, iovlen); 720 } 721 #endif 722 bad: 723 FRELE(fp, p); 724 m_freem(to); 725 return (error); 726 } 727 728 int 729 sys_recvfrom(struct proc *p, void *v, register_t *retval) 730 { 731 struct sys_recvfrom_args /* { 732 syscallarg(int) s; 733 syscallarg(void *) buf; 734 syscallarg(size_t) len; 735 syscallarg(int) flags; 736 syscallarg(struct sockaddr *) from; 737 syscallarg(socklen_t *) fromlenaddr; 738 } */ *uap = v; 739 struct msghdr msg; 740 struct iovec aiov; 741 int error; 742 743 if (SCARG(uap, fromlenaddr)) { 744 error = copyin(SCARG(uap, fromlenaddr), 745 &msg.msg_namelen, sizeof (msg.msg_namelen)); 746 if (error) 747 return (error); 748 } else 749 msg.msg_namelen = 0; 750 msg.msg_name = (caddr_t)SCARG(uap, from); 751 msg.msg_iov = &aiov; 752 msg.msg_iovlen = 1; 753 aiov.iov_base = SCARG(uap, buf); 754 aiov.iov_len = SCARG(uap, len); 755 msg.msg_control = NULL; 756 msg.msg_flags = SCARG(uap, flags); 757 return (recvit(p, SCARG(uap, s), &msg, 758 (caddr_t)SCARG(uap, fromlenaddr), retval)); 759 } 760 761 int 762 sys_recvmsg(struct proc *p, void *v, register_t *retval) 763 { 764 struct sys_recvmsg_args /* { 765 syscallarg(int) s; 766 syscallarg(struct msghdr *) msg; 767 syscallarg(int) flags; 768 } */ *uap = v; 769 struct msghdr msg; 770 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 771 int error; 772 773 error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); 774 if (error) 775 return (error); 776 777 if (msg.msg_iovlen > IOV_MAX) 778 return (EMSGSIZE); 779 if (msg.msg_iovlen > UIO_SMALLIOV) 780 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec), 781 M_IOV, M_WAITOK); 782 else 783 iov = aiov; 784 msg.msg_flags = SCARG(uap, flags); 785 if (msg.msg_iovlen > 0) { 786 error = copyin(msg.msg_iov, iov, 787 msg.msg_iovlen * sizeof(struct iovec)); 788 if (error) 789 goto done; 790 } 791 uiov = msg.msg_iov; 792 msg.msg_iov = iov; 793 if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) { 794 msg.msg_iov = uiov; 795 #ifdef KTRACE 796 if (KTRPOINT(p, KTR_STRUCT)) { 797 ktrmsghdr(p, &msg); 798 if (msg.msg_iovlen) 799 ktriovec(p, iov, msg.msg_iovlen); 800 } 801 #endif 802 error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); 803 } 804 done: 805 if (iov != aiov) 806 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen); 807 return (error); 808 } 809 810 int 811 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp, 812 register_t *retsize) 813 { 814 struct file *fp; 815 struct uio auio; 816 struct iovec *iov; 817 int i; 818 size_t len; 819 int error; 820 struct mbuf *from = NULL, *control = NULL; 821 #ifdef KTRACE 822 struct iovec *ktriov = NULL; 823 int iovlen = 0, kmsgflags; 824 #endif 825 826 if ((error = getsock(p, s, &fp)) != 0) 827 return (error); 828 829 auio.uio_iov = mp->msg_iov; 830 auio.uio_iovcnt = mp->msg_iovlen; 831 auio.uio_segflg = UIO_USERSPACE; 832 auio.uio_rw = UIO_READ; 833 auio.uio_procp = p; 834 auio.uio_offset = 0; /* XXX */ 835 auio.uio_resid = 0; 836 iov = mp->msg_iov; 837 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 838 /* Don't allow sum > SSIZE_MAX */ 839 if (iov->iov_len > SSIZE_MAX || 840 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { 841 error = EINVAL; 842 goto out; 843 } 844 } 845 #ifdef KTRACE 846 if (KTRPOINT(p, KTR_GENIO)) { 847 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec), 848 M_TEMP, M_WAITOK); 849 iovlen = auio.uio_iovcnt * sizeof (struct iovec); 850 851 memcpy(ktriov, auio.uio_iov, iovlen); 852 } 853 kmsgflags = mp->msg_flags; 854 #endif 855 len = auio.uio_resid; 856 if (fp->f_flag & FNONBLOCK) 857 mp->msg_flags |= MSG_DONTWAIT; 858 error = soreceive(fp->f_data, &from, &auio, NULL, 859 mp->msg_control ? &control : NULL, 860 &mp->msg_flags, 861 mp->msg_control ? mp->msg_controllen : 0); 862 if (error) { 863 if (auio.uio_resid != len && (error == ERESTART || 864 error == EINTR || error == EWOULDBLOCK)) 865 error = 0; 866 } 867 #ifdef KTRACE 868 if (ktriov != NULL) { 869 if (error == 0) 870 ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid); 871 free(ktriov, M_TEMP, iovlen); 872 } 873 #endif 874 if (error) 875 goto out; 876 *retsize = len - auio.uio_resid; 877 if (mp->msg_name) { 878 socklen_t alen; 879 880 if (from == NULL) 881 alen = 0; 882 else { 883 alen = from->m_len; 884 error = copyout(mtod(from, caddr_t), mp->msg_name, 885 MIN(alen, mp->msg_namelen)); 886 if (error) 887 goto out; 888 #ifdef KTRACE 889 if (KTRPOINT(p, KTR_STRUCT)) 890 ktrsockaddr(p, mtod(from, caddr_t), alen); 891 #endif 892 } 893 mp->msg_namelen = alen; 894 if (namelenp && 895 (error = copyout(&alen, namelenp, sizeof(alen)))) { 896 goto out; 897 } 898 } 899 if (mp->msg_control) { 900 len = mp->msg_controllen; 901 if (len <= 0 || control == NULL) 902 len = 0; 903 else { 904 struct mbuf *m = control; 905 caddr_t cp = mp->msg_control; 906 907 do { 908 i = m->m_len; 909 if (len < i) { 910 mp->msg_flags |= MSG_CTRUNC; 911 i = len; 912 } 913 error = copyout(mtod(m, caddr_t), cp, i); 914 #ifdef KTRACE 915 if (KTRPOINT(p, KTR_STRUCT) && error == 0 && i) { 916 /* msg_flags potentially incorrect */ 917 int rmsgflags = mp->msg_flags; 918 919 mp->msg_flags = kmsgflags; 920 ktrcmsghdr(p, mtod(m, char *), i); 921 mp->msg_flags = rmsgflags; 922 } 923 #endif 924 if (m->m_next) 925 i = ALIGN(i); 926 cp += i; 927 len -= i; 928 if (error != 0 || len <= 0) 929 break; 930 } while ((m = m->m_next) != NULL); 931 len = cp - (caddr_t)mp->msg_control; 932 } 933 mp->msg_controllen = len; 934 } 935 if (!error) { 936 mtx_enter(&fp->f_mtx); 937 fp->f_rxfer++; 938 fp->f_rbytes += *retsize; 939 mtx_leave(&fp->f_mtx); 940 } 941 out: 942 FRELE(fp, p); 943 m_freem(from); 944 m_freem(control); 945 return (error); 946 } 947 948 int 949 sys_shutdown(struct proc *p, void *v, register_t *retval) 950 { 951 struct sys_shutdown_args /* { 952 syscallarg(int) s; 953 syscallarg(int) how; 954 } */ *uap = v; 955 struct file *fp; 956 int error; 957 958 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 959 return (error); 960 error = soshutdown(fp->f_data, SCARG(uap, how)); 961 FRELE(fp, p); 962 return (error); 963 } 964 965 int 966 sys_setsockopt(struct proc *p, void *v, register_t *retval) 967 { 968 struct sys_setsockopt_args /* { 969 syscallarg(int) s; 970 syscallarg(int) level; 971 syscallarg(int) name; 972 syscallarg(const void *) val; 973 syscallarg(socklen_t) valsize; 974 } */ *uap = v; 975 struct file *fp; 976 struct mbuf *m = NULL; 977 struct socket *so; 978 int error; 979 980 981 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 982 return (error); 983 error = pledge_sockopt(p, 1, SCARG(uap, level), SCARG(uap, name)); 984 if (error) 985 goto bad; 986 if (SCARG(uap, valsize) > MCLBYTES) { 987 error = EINVAL; 988 goto bad; 989 } 990 if (SCARG(uap, val)) { 991 m = m_get(M_WAIT, MT_SOOPTS); 992 if (SCARG(uap, valsize) > MLEN) { 993 MCLGET(m, M_DONTWAIT); 994 if ((m->m_flags & M_EXT) == 0) { 995 error = ENOBUFS; 996 goto bad; 997 } 998 } 999 if (m == NULL) { 1000 error = ENOBUFS; 1001 goto bad; 1002 } 1003 error = copyin(SCARG(uap, val), mtod(m, caddr_t), 1004 SCARG(uap, valsize)); 1005 if (error) { 1006 goto bad; 1007 } 1008 m->m_len = SCARG(uap, valsize); 1009 } 1010 so = fp->f_data; 1011 solock(so); 1012 error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m); 1013 sounlock(so); 1014 bad: 1015 m_freem(m); 1016 FRELE(fp, p); 1017 return (error); 1018 } 1019 1020 int 1021 sys_getsockopt(struct proc *p, void *v, register_t *retval) 1022 { 1023 struct sys_getsockopt_args /* { 1024 syscallarg(int) s; 1025 syscallarg(int) level; 1026 syscallarg(int) name; 1027 syscallarg(void *) val; 1028 syscallarg(socklen_t *) avalsize; 1029 } */ *uap = v; 1030 struct file *fp; 1031 struct mbuf *m = NULL; 1032 socklen_t valsize; 1033 struct socket *so; 1034 int error; 1035 1036 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 1037 return (error); 1038 error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name)); 1039 if (error) 1040 goto out; 1041 if (SCARG(uap, val)) { 1042 error = copyin(SCARG(uap, avalsize), 1043 &valsize, sizeof (valsize)); 1044 if (error) 1045 goto out; 1046 } else 1047 valsize = 0; 1048 m = m_get(M_WAIT, MT_SOOPTS); 1049 so = fp->f_data; 1050 solock(so); 1051 error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m); 1052 sounlock(so); 1053 if (error == 0 && SCARG(uap, val) && valsize && m != NULL) { 1054 if (valsize > m->m_len) 1055 valsize = m->m_len; 1056 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize); 1057 if (error == 0) 1058 error = copyout(&valsize, 1059 SCARG(uap, avalsize), sizeof (valsize)); 1060 } 1061 m_free(m); 1062 out: 1063 FRELE(fp, p); 1064 return (error); 1065 } 1066 1067 /* 1068 * Get socket name. 1069 */ 1070 int 1071 sys_getsockname(struct proc *p, void *v, register_t *retval) 1072 { 1073 struct sys_getsockname_args /* { 1074 syscallarg(int) fdes; 1075 syscallarg(struct sockaddr *) asa; 1076 syscallarg(socklen_t *) alen; 1077 } */ *uap = v; 1078 struct file *fp; 1079 struct socket *so; 1080 struct mbuf *m = NULL; 1081 socklen_t len; 1082 int error; 1083 1084 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) 1085 return (error); 1086 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 1087 if (error) 1088 goto bad; 1089 so = fp->f_data; 1090 if (so->so_state & SS_YP) { 1091 error = ENOTSOCK; 1092 goto bad; 1093 } 1094 error = pledge_socket(p, -1, so->so_state); 1095 if (error) 1096 goto bad; 1097 if (so->so_state & SS_YP) { 1098 error = ENOTSOCK; 1099 goto bad; 1100 } 1101 m = m_getclr(M_WAIT, MT_SONAME); 1102 solock(so); 1103 error = pru_sockaddr(so, m); 1104 sounlock(so); 1105 if (error) 1106 goto bad; 1107 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); 1108 bad: 1109 FRELE(fp, p); 1110 m_freem(m); 1111 return (error); 1112 } 1113 1114 /* 1115 * Get name of peer for connected socket. 1116 */ 1117 int 1118 sys_getpeername(struct proc *p, void *v, register_t *retval) 1119 { 1120 struct sys_getpeername_args /* { 1121 syscallarg(int) fdes; 1122 syscallarg(struct sockaddr *) asa; 1123 syscallarg(socklen_t *) alen; 1124 } */ *uap = v; 1125 struct file *fp; 1126 struct socket *so; 1127 struct mbuf *m = NULL; 1128 socklen_t len; 1129 int error; 1130 1131 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) 1132 return (error); 1133 so = fp->f_data; 1134 error = pledge_socket(p, -1, so->so_state); 1135 if (error) 1136 goto bad; 1137 if (so->so_state & SS_YP) { 1138 error = ENOTSOCK; 1139 goto bad; 1140 } 1141 if ((so->so_state & SS_ISCONNECTED) == 0) { 1142 error = ENOTCONN; 1143 goto bad; 1144 } 1145 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 1146 if (error) 1147 goto bad; 1148 m = m_getclr(M_WAIT, MT_SONAME); 1149 solock(so); 1150 error = pru_peeraddr(so, m); 1151 sounlock(so); 1152 if (error) 1153 goto bad; 1154 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); 1155 bad: 1156 FRELE(fp, p); 1157 m_freem(m); 1158 return (error); 1159 } 1160 1161 int 1162 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) 1163 { 1164 struct sockaddr *sa; 1165 struct mbuf *m; 1166 int error; 1167 1168 /* 1169 * We can't allow socket names > UCHAR_MAX in length, since that 1170 * will overflow sa_len. Also, control data more than MCLBYTES in 1171 * length is just too much. 1172 * Memory for sa_len and sa_family must exist. 1173 */ 1174 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) || 1175 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data))) 1176 return (EINVAL); 1177 1178 /* Allocate an mbuf to hold the arguments. */ 1179 m = m_get(M_WAIT, type); 1180 if (buflen > MLEN) { 1181 MCLGET(m, M_WAITOK); 1182 if ((m->m_flags & M_EXT) == 0) { 1183 m_free(m); 1184 return ENOBUFS; 1185 } 1186 } 1187 m->m_len = buflen; 1188 error = copyin(buf, mtod(m, caddr_t), buflen); 1189 if (error) { 1190 (void) m_free(m); 1191 return (error); 1192 } 1193 *mp = m; 1194 if (type == MT_SONAME) { 1195 sa = mtod(m, struct sockaddr *); 1196 sa->sa_len = buflen; 1197 } 1198 return (0); 1199 } 1200 1201 int 1202 getsock(struct proc *p, int fdes, struct file **fpp) 1203 { 1204 struct file *fp; 1205 1206 fp = fd_getfile(p->p_fd, fdes); 1207 if (fp == NULL) 1208 return (EBADF); 1209 if (fp->f_type != DTYPE_SOCKET) { 1210 FRELE(fp, p); 1211 return (ENOTSOCK); 1212 } 1213 *fpp = fp; 1214 1215 return (0); 1216 } 1217 1218 int 1219 sys_setrtable(struct proc *p, void *v, register_t *retval) 1220 { 1221 struct sys_setrtable_args /* { 1222 syscallarg(int) rtableid; 1223 } */ *uap = v; 1224 u_int ps_rtableid = p->p_p->ps_rtableid; 1225 int rtableid, error; 1226 1227 rtableid = SCARG(uap, rtableid); 1228 1229 if (ps_rtableid == rtableid) 1230 return (0); 1231 if (ps_rtableid != 0 && (error = suser(p)) != 0) 1232 return (error); 1233 if (rtableid < 0 || !rtable_exists((u_int)rtableid)) 1234 return (EINVAL); 1235 1236 p->p_p->ps_rtableid = (u_int)rtableid; 1237 return (0); 1238 } 1239 1240 int 1241 sys_getrtable(struct proc *p, void *v, register_t *retval) 1242 { 1243 *retval = (int)p->p_p->ps_rtableid; 1244 return (0); 1245 } 1246 1247 int 1248 copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa, 1249 socklen_t buflen, socklen_t *outlen) 1250 { 1251 int error; 1252 socklen_t namelen = name->m_len; 1253 1254 /* SHOULD COPY OUT A CHAIN HERE */ 1255 error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen)); 1256 if (error == 0) { 1257 #ifdef KTRACE 1258 if (KTRPOINT(p, KTR_STRUCT)) 1259 ktrsockaddr(p, mtod(name, caddr_t), namelen); 1260 #endif 1261 error = copyout(&namelen, outlen, sizeof(*outlen)); 1262 } 1263 1264 return (error); 1265 } 1266 1267 #ifndef SMALL_KERNEL 1268 int 1269 ypsockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) 1270 { 1271 struct sockaddr *sa; 1272 struct mbuf *m; 1273 1274 /* 1275 * We can't allow socket names > UCHAR_MAX in length, since that 1276 * will overflow sa_len. Also, control data more than MCLBYTES in 1277 * length is just too much. 1278 * Memory for sa_len and sa_family must exist. 1279 */ 1280 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) || 1281 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data))) 1282 return (EINVAL); 1283 1284 /* Allocate an mbuf to hold the arguments. */ 1285 m = m_get(M_WAIT, type); 1286 if (buflen > MLEN) { 1287 MCLGET(m, M_WAITOK); 1288 if ((m->m_flags & M_EXT) == 0) { 1289 m_free(m); 1290 return ENOBUFS; 1291 } 1292 } 1293 m->m_len = buflen; 1294 bcopy(buf, mtod(m, caddr_t), buflen); 1295 *mp = m; 1296 if (type == MT_SONAME) { 1297 sa = mtod(m, struct sockaddr *); 1298 sa->sa_len = buflen; 1299 } 1300 return (0); 1301 } 1302 #endif /* SMALL_KERNEL */ 1303 1304 int 1305 sys_ypconnect(struct proc *p, void *v, register_t *retval) 1306 { 1307 #ifdef SMALL_KERNEL 1308 return EAFNOSUPPORT; 1309 #else 1310 struct sys_ypconnect_args /* { 1311 syscallarg(int) type; 1312 } */ *uap = v; 1313 struct nameidata nid; 1314 struct vattr va; 1315 struct uio uio; 1316 struct iovec iov; 1317 struct filedesc *fdp = p->p_fd; 1318 struct socket *so; 1319 struct file *fp; 1320 struct flock fl; 1321 char *name; 1322 struct mbuf *nam = NULL; 1323 int error, fd = -1; 1324 struct ypbinding { 1325 u_short ypbind_port; 1326 int status; 1327 in_addr_t in; 1328 u_short ypserv_udp_port; 1329 u_short garbage; 1330 u_short ypserv_tcp_port; 1331 } __packed data; 1332 struct sockaddr_in ypsin; 1333 1334 if (!domainname[0] || strchr(domainname, '/')) 1335 return EAFNOSUPPORT; 1336 1337 switch (SCARG(uap, type)) { 1338 case SOCK_STREAM: 1339 case SOCK_DGRAM: 1340 break; 1341 default: 1342 return EAFNOSUPPORT; 1343 } 1344 1345 if (p->p_p->ps_flags & PS_CHROOT) 1346 return EACCES; 1347 name = pool_get(&namei_pool, PR_WAITOK); 1348 snprintf(name, MAXPATHLEN, "/var/yp/binding/%s.2", domainname); 1349 NDINIT(&nid, 0, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, name, p); 1350 nid.ni_pledge = PLEDGE_RPATH; 1351 1352 KERNEL_LOCK(); 1353 error = namei(&nid); 1354 pool_put(&namei_pool, name); 1355 if (error) 1356 goto out; 1357 error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p); 1358 if (error) 1359 goto verror; 1360 if (nid.ni_vp->v_type != VREG || va.va_size != sizeof data) { 1361 error = EFTYPE; 1362 goto verror; 1363 } 1364 1365 /* 1366 * Check that a lock is held on the file (hopefully by ypbind), 1367 * otherwise the file might be old 1368 */ 1369 fl.l_start = 0; 1370 fl.l_len = 0; 1371 fl.l_pid = 0; 1372 fl.l_type = F_WRLCK; 1373 fl.l_whence = SEEK_SET; 1374 error = VOP_ADVLOCK(nid.ni_vp, fdp, F_GETLK, &fl, F_POSIX); 1375 if (error) 1376 goto verror; 1377 if (fl.l_type == F_UNLCK) { 1378 error = EOWNERDEAD; 1379 goto verror; 1380 } 1381 1382 iov.iov_base = &data; 1383 iov.iov_len = sizeof data; 1384 uio.uio_iov = &iov; 1385 uio.uio_iovcnt = 1; 1386 uio.uio_offset = 0; 1387 uio.uio_resid = iov.iov_len; 1388 uio.uio_segflg = UIO_SYSSPACE; 1389 uio.uio_rw = UIO_READ; 1390 uio.uio_procp = p; 1391 1392 error = VOP_READ(nid.ni_vp, &uio, 0, p->p_ucred); 1393 if (error) { 1394 verror: 1395 if (nid.ni_vp) 1396 vput(nid.ni_vp); 1397 out: 1398 KERNEL_UNLOCK(); 1399 return (error); 1400 } 1401 vput(nid.ni_vp); 1402 KERNEL_UNLOCK(); 1403 1404 bzero(&ypsin, sizeof ypsin); 1405 ypsin.sin_len = sizeof ypsin; 1406 ypsin.sin_family = AF_INET; 1407 if (SCARG(uap, type) == SOCK_STREAM) 1408 ypsin.sin_port = data.ypserv_tcp_port; 1409 else 1410 ypsin.sin_port = data.ypserv_udp_port; 1411 if (ntohs(ypsin.sin_port) >= IPPORT_RESERVED || ntohs(ypsin.sin_port) == 20) 1412 return EPERM; 1413 memcpy(&ypsin.sin_addr.s_addr, &data.in, sizeof ypsin.sin_addr.s_addr); 1414 1415 error = socreate(AF_INET, &so, SCARG(uap, type), 0); 1416 if (error) 1417 return (error); 1418 1419 error = ypsockargs(&nam, &ypsin, sizeof ypsin, MT_SONAME); 1420 if (error) { 1421 soclose(so, MSG_DONTWAIT); 1422 return (error); 1423 } 1424 1425 #ifdef KTRACE 1426 if (KTRPOINT(p, KTR_STRUCT)) 1427 ktrsockaddr(p, mtod(nam, caddr_t), sizeof(struct sockaddr_in)); 1428 #endif 1429 solock(so); 1430 error = soconnect(so, nam); 1431 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 1432 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH, 1433 "netcon2", INFSLP); 1434 if (error) 1435 break; 1436 } 1437 m_freem(nam); 1438 so->so_state |= SS_YP; /* impose some restrictions */ 1439 sounlock(so); 1440 if (error) { 1441 soclose(so, MSG_DONTWAIT); 1442 return (error); 1443 } 1444 1445 fdplock(fdp); 1446 error = falloc(p, &fp, &fd); 1447 if (error) { 1448 fdpunlock(fdp); 1449 soclose(so, MSG_DONTWAIT); 1450 return (error); 1451 } 1452 1453 fp->f_flag = FREAD | FWRITE | FNONBLOCK; 1454 fp->f_type = DTYPE_SOCKET; 1455 fp->f_ops = &socketops; 1456 fp->f_data = so; 1457 fdinsert(fdp, fd, UF_EXCLOSE, fp); 1458 fdpunlock(fdp); 1459 FRELE(fp, p); 1460 *retval = fd; 1461 return (error); 1462 #endif /* SMALL_KERNEL */ 1463 } 1464