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