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