1 /* $OpenBSD: uipc_syscalls.c,v 1.212 2023/02/10 14:34:17 visa 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(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_rcv.sb_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_rcv.sb_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_locked(&head->so_rcv.sb_klist, 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 sys_sendmmsg(struct proc *p, void *v, register_t *retval) 613 { 614 struct sys_sendmmsg_args /* { 615 syscallarg(int) s; 616 syscallarg(struct mmsghdr *) mmsg; 617 syscallarg(unsigned int) vlen; 618 syscallarg(int) flags; 619 } */ *uap = v; 620 struct mmsghdr mmsg, *mmsgp; 621 struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *uiov; 622 size_t iovlen = UIO_SMALLIOV; 623 register_t retsnd; 624 unsigned int vlen, dgrams; 625 int error = 0, flags, s; 626 627 s = SCARG(uap, s); 628 flags = SCARG(uap, flags); 629 630 /* Arbitrarily capped at 1024 datagrams. */ 631 vlen = SCARG(uap, vlen); 632 if (vlen > 1024) 633 vlen = 1024; 634 635 mmsgp = SCARG(uap, mmsg); 636 for (dgrams = 0; dgrams < vlen; dgrams++) { 637 error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg)); 638 if (error) 639 break; 640 641 #ifdef KTRACE 642 if (KTRPOINT(p, KTR_STRUCT)) 643 ktrmmsghdr(p, &mmsg); 644 #endif 645 646 if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) { 647 error = EMSGSIZE; 648 break; 649 } 650 651 if (mmsg.msg_hdr.msg_iovlen > iovlen) { 652 if (iov != aiov) 653 free(iov, M_IOV, iovlen * 654 sizeof(struct iovec)); 655 656 iovlen = mmsg.msg_hdr.msg_iovlen; 657 iov = mallocarray(iovlen, sizeof(struct iovec), 658 M_IOV, M_WAITOK); 659 } 660 661 if (mmsg.msg_hdr.msg_iovlen > 0) { 662 error = copyin(mmsg.msg_hdr.msg_iov, iov, 663 mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec)); 664 if (error) 665 break; 666 } 667 668 #ifdef KTRACE 669 if (mmsg.msg_hdr.msg_iovlen && KTRPOINT(p, KTR_STRUCT)) 670 ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen); 671 #endif 672 673 uiov = mmsg.msg_hdr.msg_iov; 674 mmsg.msg_hdr.msg_iov = iov; 675 mmsg.msg_hdr.msg_flags = 0; 676 677 error = sendit(p, s, &mmsg.msg_hdr, flags, &retsnd); 678 if (error) 679 break; 680 681 mmsg.msg_hdr.msg_iov = uiov; 682 mmsg.msg_len = retsnd; 683 684 error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg)); 685 if (error) 686 break; 687 } 688 689 if (iov != aiov) 690 free(iov, M_IOV, sizeof(struct iovec) * iovlen); 691 692 *retval = dgrams; 693 694 if (error && dgrams > 0) 695 error = 0; 696 697 return (error); 698 } 699 700 int 701 sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize) 702 { 703 struct file *fp; 704 struct uio auio; 705 struct iovec *iov; 706 int i; 707 struct mbuf *to, *control; 708 struct socket *so; 709 size_t len; 710 int error; 711 #ifdef KTRACE 712 struct iovec *ktriov = NULL; 713 int iovlen = 0; 714 #endif 715 716 to = NULL; 717 718 if ((error = getsock(p, s, &fp)) != 0) 719 return (error); 720 so = fp->f_data; 721 if (fp->f_flag & FNONBLOCK) 722 flags |= MSG_DONTWAIT; 723 724 error = pledge_sendit(p, mp->msg_name); 725 if (error) 726 goto bad; 727 728 auio.uio_iov = mp->msg_iov; 729 auio.uio_iovcnt = mp->msg_iovlen; 730 auio.uio_segflg = UIO_USERSPACE; 731 auio.uio_rw = UIO_WRITE; 732 auio.uio_procp = p; 733 auio.uio_offset = 0; /* XXX */ 734 auio.uio_resid = 0; 735 iov = mp->msg_iov; 736 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 737 /* Don't allow sum > SSIZE_MAX */ 738 if (iov->iov_len > SSIZE_MAX || 739 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { 740 error = EINVAL; 741 goto bad; 742 } 743 } 744 if (mp->msg_name) { 745 error = sockargs(&to, mp->msg_name, mp->msg_namelen, 746 MT_SONAME); 747 if (error) 748 goto bad; 749 if (isdnssocket(so)) { 750 error = dns_portcheck(p, so, mtod(to, caddr_t), 751 mp->msg_namelen); 752 if (error) 753 goto bad; 754 } 755 #ifdef KTRACE 756 if (KTRPOINT(p, KTR_STRUCT)) 757 ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen); 758 #endif 759 } 760 if (mp->msg_control) { 761 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) { 762 error = EINVAL; 763 goto bad; 764 } 765 error = sockargs(&control, mp->msg_control, 766 mp->msg_controllen, MT_CONTROL); 767 if (error) 768 goto bad; 769 #ifdef KTRACE 770 if (KTRPOINT(p, KTR_STRUCT) && mp->msg_controllen) 771 ktrcmsghdr(p, mtod(control, char *), 772 mp->msg_controllen); 773 #endif 774 } else 775 control = NULL; 776 #ifdef KTRACE 777 if (KTRPOINT(p, KTR_GENIO)) { 778 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec), 779 M_TEMP, M_WAITOK); 780 iovlen = auio.uio_iovcnt * sizeof (struct iovec); 781 782 memcpy(ktriov, auio.uio_iov, iovlen); 783 } 784 #endif 785 len = auio.uio_resid; 786 error = sosend(so, to, &auio, NULL, control, flags); 787 if (error) { 788 if (auio.uio_resid != len && (error == ERESTART || 789 error == EINTR || error == EWOULDBLOCK)) 790 error = 0; 791 if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) { 792 KERNEL_LOCK(); 793 ptsignal(p, SIGPIPE, STHREAD); 794 KERNEL_UNLOCK(); 795 } 796 } 797 if (error == 0) { 798 *retsize = len - auio.uio_resid; 799 mtx_enter(&fp->f_mtx); 800 fp->f_wxfer++; 801 fp->f_wbytes += *retsize; 802 mtx_leave(&fp->f_mtx); 803 } 804 #ifdef KTRACE 805 if (ktriov != NULL) { 806 if (error == 0) 807 ktrgenio(p, s, UIO_WRITE, ktriov, *retsize); 808 free(ktriov, M_TEMP, iovlen); 809 } 810 #endif 811 bad: 812 FRELE(fp, p); 813 m_freem(to); 814 return (error); 815 } 816 817 int 818 sys_recvfrom(struct proc *p, void *v, register_t *retval) 819 { 820 struct sys_recvfrom_args /* { 821 syscallarg(int) s; 822 syscallarg(void *) buf; 823 syscallarg(size_t) len; 824 syscallarg(int) flags; 825 syscallarg(struct sockaddr *) from; 826 syscallarg(socklen_t *) fromlenaddr; 827 } */ *uap = v; 828 struct msghdr msg; 829 struct iovec aiov; 830 int error; 831 832 if (SCARG(uap, fromlenaddr)) { 833 error = copyin(SCARG(uap, fromlenaddr), 834 &msg.msg_namelen, sizeof (msg.msg_namelen)); 835 if (error) 836 return (error); 837 } else 838 msg.msg_namelen = 0; 839 msg.msg_name = (caddr_t)SCARG(uap, from); 840 msg.msg_iov = &aiov; 841 msg.msg_iovlen = 1; 842 aiov.iov_base = SCARG(uap, buf); 843 aiov.iov_len = SCARG(uap, len); 844 msg.msg_control = NULL; 845 msg.msg_flags = SCARG(uap, flags); 846 return (recvit(p, SCARG(uap, s), &msg, 847 (caddr_t)SCARG(uap, fromlenaddr), retval)); 848 } 849 850 int 851 sys_recvmsg(struct proc *p, void *v, register_t *retval) 852 { 853 struct sys_recvmsg_args /* { 854 syscallarg(int) s; 855 syscallarg(struct msghdr *) msg; 856 syscallarg(int) flags; 857 } */ *uap = v; 858 struct msghdr msg; 859 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 860 int error; 861 862 error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); 863 if (error) 864 return (error); 865 866 if (msg.msg_iovlen > IOV_MAX) 867 return (EMSGSIZE); 868 if (msg.msg_iovlen > UIO_SMALLIOV) 869 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec), 870 M_IOV, M_WAITOK); 871 else 872 iov = aiov; 873 msg.msg_flags = SCARG(uap, flags); 874 if (msg.msg_iovlen > 0) { 875 error = copyin(msg.msg_iov, iov, 876 msg.msg_iovlen * sizeof(struct iovec)); 877 if (error) 878 goto done; 879 } 880 uiov = msg.msg_iov; 881 msg.msg_iov = iov; 882 if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) { 883 msg.msg_iov = uiov; 884 #ifdef KTRACE 885 if (KTRPOINT(p, KTR_STRUCT)) { 886 ktrmsghdr(p, &msg); 887 if (msg.msg_iovlen) 888 ktriovec(p, iov, msg.msg_iovlen); 889 } 890 #endif 891 error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); 892 } 893 done: 894 if (iov != aiov) 895 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen); 896 return (error); 897 } 898 899 int 900 sys_recvmmsg(struct proc *p, void *v, register_t *retval) 901 { 902 struct sys_recvmmsg_args /* { 903 syscallarg(int) s; 904 syscallarg(struct mmsghdr *) mmsg; 905 syscallarg(unsigned int) vlen; 906 syscallarg(int) flags; 907 syscallarg(struct timespec *) timeout; 908 } */ *uap = v; 909 struct mmsghdr mmsg, *mmsgp; 910 struct timespec ts, now, *timeout; 911 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov = aiov; 912 size_t iovlen = UIO_SMALLIOV; 913 register_t retrec; 914 unsigned int vlen, dgrams; 915 int error = 0, flags, s; 916 917 timeout = SCARG(uap, timeout); 918 if (timeout != NULL) { 919 error = copyin(timeout, &ts, sizeof(ts)); 920 if (error) 921 return (error); 922 #ifdef KTRACE 923 if (KTRPOINT(p, KTR_STRUCT)) 924 ktrreltimespec(p, &ts); 925 #endif 926 if (!timespecisvalid(&ts)) 927 return (EINVAL); 928 929 getnanotime(&now); 930 timespecadd(&now, &ts, &ts); 931 } 932 933 s = SCARG(uap, s); 934 flags = SCARG(uap, flags); 935 936 /* Arbitrarily capped at 1024 datagrams. */ 937 vlen = SCARG(uap, vlen); 938 if (vlen > 1024) 939 vlen = 1024; 940 941 mmsgp = SCARG(uap, mmsg); 942 for (dgrams = 0; dgrams < vlen;) { 943 error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg)); 944 if (error) 945 break; 946 947 if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) { 948 error = EMSGSIZE; 949 break; 950 } 951 952 if (mmsg.msg_hdr.msg_iovlen > iovlen) { 953 if (iov != aiov) 954 free(iov, M_IOV, iovlen * 955 sizeof(struct iovec)); 956 957 iovlen = mmsg.msg_hdr.msg_iovlen; 958 iov = mallocarray(iovlen, sizeof(struct iovec), 959 M_IOV, M_WAITOK); 960 } 961 962 if (mmsg.msg_hdr.msg_iovlen > 0) { 963 error = copyin(mmsg.msg_hdr.msg_iov, iov, 964 mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec)); 965 if (error) 966 break; 967 } 968 969 uiov = mmsg.msg_hdr.msg_iov; 970 mmsg.msg_hdr.msg_iov = iov; 971 mmsg.msg_hdr.msg_flags = flags & ~MSG_WAITFORONE; 972 973 error = recvit(p, s, &mmsg.msg_hdr, NULL, &retrec); 974 if (error) { 975 if (error == EAGAIN && dgrams > 0) 976 error = 0; 977 break; 978 } 979 980 if (flags & MSG_WAITFORONE) 981 flags |= MSG_DONTWAIT; 982 983 mmsg.msg_hdr.msg_iov = uiov; 984 mmsg.msg_len = retrec; 985 #ifdef KTRACE 986 if (KTRPOINT(p, KTR_STRUCT)) { 987 ktrmmsghdr(p, &mmsg); 988 if (mmsg.msg_hdr.msg_iovlen) 989 ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen); 990 } 991 #endif 992 993 error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg)); 994 if (error) 995 break; 996 997 dgrams++; 998 if (mmsg.msg_hdr.msg_flags & MSG_OOB) 999 break; 1000 1001 if (timeout != NULL) { 1002 getnanotime(&now); 1003 timespecsub(&now, &ts, &now); 1004 if (now.tv_sec > 0) 1005 break; 1006 } 1007 } 1008 1009 if (iov != aiov) 1010 free(iov, M_IOV, iovlen * sizeof(struct iovec)); 1011 1012 *retval = dgrams; 1013 1014 /* 1015 * If we succeeded at least once, return 0, hopefully so->so_error 1016 * will catch it next time. 1017 */ 1018 if (error && dgrams > 0) { 1019 struct file *fp; 1020 struct socket *so; 1021 1022 if (getsock(p, s, &fp) == 0) { 1023 so = (struct socket *)fp->f_data; 1024 so->so_error = error; 1025 1026 FRELE(fp, p); 1027 } 1028 error = 0; 1029 } 1030 1031 return (error); 1032 } 1033 1034 int 1035 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp, 1036 register_t *retsize) 1037 { 1038 struct file *fp; 1039 struct uio auio; 1040 struct iovec *iov; 1041 int i; 1042 size_t len; 1043 int error; 1044 struct mbuf *from = NULL, *control = NULL; 1045 #ifdef KTRACE 1046 struct iovec *ktriov = NULL; 1047 int iovlen = 0, kmsgflags; 1048 #endif 1049 1050 if ((error = getsock(p, s, &fp)) != 0) 1051 return (error); 1052 1053 auio.uio_iov = mp->msg_iov; 1054 auio.uio_iovcnt = mp->msg_iovlen; 1055 auio.uio_segflg = UIO_USERSPACE; 1056 auio.uio_rw = UIO_READ; 1057 auio.uio_procp = p; 1058 auio.uio_offset = 0; /* XXX */ 1059 auio.uio_resid = 0; 1060 iov = mp->msg_iov; 1061 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 1062 /* Don't allow sum > SSIZE_MAX */ 1063 if (iov->iov_len > SSIZE_MAX || 1064 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { 1065 error = EINVAL; 1066 goto out; 1067 } 1068 } 1069 #ifdef KTRACE 1070 if (KTRPOINT(p, KTR_GENIO)) { 1071 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec), 1072 M_TEMP, M_WAITOK); 1073 iovlen = auio.uio_iovcnt * sizeof (struct iovec); 1074 1075 memcpy(ktriov, auio.uio_iov, iovlen); 1076 } 1077 kmsgflags = mp->msg_flags; 1078 #endif 1079 len = auio.uio_resid; 1080 if (fp->f_flag & FNONBLOCK) 1081 mp->msg_flags |= MSG_DONTWAIT; 1082 error = soreceive(fp->f_data, &from, &auio, NULL, 1083 mp->msg_control ? &control : NULL, 1084 &mp->msg_flags, 1085 mp->msg_control ? mp->msg_controllen : 0); 1086 if (error) { 1087 if (auio.uio_resid != len && (error == ERESTART || 1088 error == EINTR || error == EWOULDBLOCK)) 1089 error = 0; 1090 } 1091 #ifdef KTRACE 1092 if (ktriov != NULL) { 1093 if (error == 0) 1094 ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid); 1095 free(ktriov, M_TEMP, iovlen); 1096 } 1097 #endif 1098 if (error) 1099 goto out; 1100 *retsize = len - auio.uio_resid; 1101 if (mp->msg_name) { 1102 socklen_t alen; 1103 1104 if (from == NULL) 1105 alen = 0; 1106 else { 1107 alen = from->m_len; 1108 error = copyout(mtod(from, caddr_t), mp->msg_name, 1109 MIN(alen, mp->msg_namelen)); 1110 if (error) 1111 goto out; 1112 #ifdef KTRACE 1113 if (KTRPOINT(p, KTR_STRUCT)) 1114 ktrsockaddr(p, mtod(from, caddr_t), alen); 1115 #endif 1116 } 1117 mp->msg_namelen = alen; 1118 if (namelenp && 1119 (error = copyout(&alen, namelenp, sizeof(alen)))) { 1120 goto out; 1121 } 1122 } 1123 if (mp->msg_control) { 1124 len = mp->msg_controllen; 1125 if (len <= 0 || control == NULL) 1126 len = 0; 1127 else { 1128 struct mbuf *m = control; 1129 caddr_t cp = mp->msg_control; 1130 1131 do { 1132 i = m->m_len; 1133 if (len < i) { 1134 mp->msg_flags |= MSG_CTRUNC; 1135 i = len; 1136 } 1137 error = copyout(mtod(m, caddr_t), cp, i); 1138 #ifdef KTRACE 1139 if (KTRPOINT(p, KTR_STRUCT) && error == 0 && i) { 1140 /* msg_flags potentially incorrect */ 1141 int rmsgflags = mp->msg_flags; 1142 1143 mp->msg_flags = kmsgflags; 1144 ktrcmsghdr(p, mtod(m, char *), i); 1145 mp->msg_flags = rmsgflags; 1146 } 1147 #endif 1148 if (m->m_next) 1149 i = ALIGN(i); 1150 cp += i; 1151 len -= i; 1152 if (error != 0 || len <= 0) 1153 break; 1154 } while ((m = m->m_next) != NULL); 1155 len = cp - (caddr_t)mp->msg_control; 1156 } 1157 mp->msg_controllen = len; 1158 } 1159 if (!error) { 1160 mtx_enter(&fp->f_mtx); 1161 fp->f_rxfer++; 1162 fp->f_rbytes += *retsize; 1163 mtx_leave(&fp->f_mtx); 1164 } 1165 out: 1166 FRELE(fp, p); 1167 m_freem(from); 1168 m_freem(control); 1169 return (error); 1170 } 1171 1172 int 1173 sys_shutdown(struct proc *p, void *v, register_t *retval) 1174 { 1175 struct sys_shutdown_args /* { 1176 syscallarg(int) s; 1177 syscallarg(int) how; 1178 } */ *uap = v; 1179 struct file *fp; 1180 int error; 1181 1182 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 1183 return (error); 1184 error = soshutdown(fp->f_data, SCARG(uap, how)); 1185 FRELE(fp, p); 1186 return (error); 1187 } 1188 1189 int 1190 sys_setsockopt(struct proc *p, void *v, register_t *retval) 1191 { 1192 struct sys_setsockopt_args /* { 1193 syscallarg(int) s; 1194 syscallarg(int) level; 1195 syscallarg(int) name; 1196 syscallarg(const void *) val; 1197 syscallarg(socklen_t) valsize; 1198 } */ *uap = v; 1199 struct file *fp; 1200 struct mbuf *m = NULL; 1201 struct socket *so; 1202 int error; 1203 1204 1205 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 1206 return (error); 1207 error = pledge_sockopt(p, 1, SCARG(uap, level), SCARG(uap, name)); 1208 if (error) 1209 goto bad; 1210 if (SCARG(uap, valsize) > MCLBYTES) { 1211 error = EINVAL; 1212 goto bad; 1213 } 1214 if (SCARG(uap, val)) { 1215 m = m_get(M_WAIT, MT_SOOPTS); 1216 if (SCARG(uap, valsize) > MLEN) { 1217 MCLGET(m, M_DONTWAIT); 1218 if ((m->m_flags & M_EXT) == 0) { 1219 error = ENOBUFS; 1220 goto bad; 1221 } 1222 } 1223 if (m == NULL) { 1224 error = ENOBUFS; 1225 goto bad; 1226 } 1227 error = copyin(SCARG(uap, val), mtod(m, caddr_t), 1228 SCARG(uap, valsize)); 1229 if (error) { 1230 goto bad; 1231 } 1232 m->m_len = SCARG(uap, valsize); 1233 } 1234 so = fp->f_data; 1235 solock(so); 1236 error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m); 1237 sounlock(so); 1238 bad: 1239 m_freem(m); 1240 FRELE(fp, p); 1241 return (error); 1242 } 1243 1244 int 1245 sys_getsockopt(struct proc *p, void *v, register_t *retval) 1246 { 1247 struct sys_getsockopt_args /* { 1248 syscallarg(int) s; 1249 syscallarg(int) level; 1250 syscallarg(int) name; 1251 syscallarg(void *) val; 1252 syscallarg(socklen_t *) avalsize; 1253 } */ *uap = v; 1254 struct file *fp; 1255 struct mbuf *m = NULL; 1256 socklen_t valsize; 1257 struct socket *so; 1258 int error; 1259 1260 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 1261 return (error); 1262 error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name)); 1263 if (error) 1264 goto out; 1265 if (SCARG(uap, val)) { 1266 error = copyin(SCARG(uap, avalsize), 1267 &valsize, sizeof (valsize)); 1268 if (error) 1269 goto out; 1270 } else 1271 valsize = 0; 1272 m = m_get(M_WAIT, MT_SOOPTS); 1273 so = fp->f_data; 1274 error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m); 1275 if (error == 0 && SCARG(uap, val) && valsize && m != NULL) { 1276 if (valsize > m->m_len) 1277 valsize = m->m_len; 1278 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize); 1279 if (error == 0) 1280 error = copyout(&valsize, 1281 SCARG(uap, avalsize), sizeof (valsize)); 1282 } 1283 m_free(m); 1284 out: 1285 FRELE(fp, p); 1286 return (error); 1287 } 1288 1289 /* 1290 * Get socket name. 1291 */ 1292 int 1293 sys_getsockname(struct proc *p, void *v, register_t *retval) 1294 { 1295 struct sys_getsockname_args /* { 1296 syscallarg(int) fdes; 1297 syscallarg(struct sockaddr *) asa; 1298 syscallarg(socklen_t *) alen; 1299 } */ *uap = v; 1300 struct file *fp; 1301 struct socket *so; 1302 struct mbuf *m = NULL; 1303 socklen_t len; 1304 int error; 1305 1306 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) 1307 return (error); 1308 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 1309 if (error) 1310 goto bad; 1311 so = fp->f_data; 1312 if (so->so_state & SS_YP) { 1313 error = ENOTSOCK; 1314 goto bad; 1315 } 1316 error = pledge_socket(p, -1, so->so_state); 1317 if (error) 1318 goto bad; 1319 if (so->so_state & SS_YP) { 1320 error = ENOTSOCK; 1321 goto bad; 1322 } 1323 m = m_getclr(M_WAIT, MT_SONAME); 1324 solock_shared(so); 1325 error = pru_sockaddr(so, m); 1326 sounlock_shared(so); 1327 if (error) 1328 goto bad; 1329 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); 1330 bad: 1331 FRELE(fp, p); 1332 m_freem(m); 1333 return (error); 1334 } 1335 1336 /* 1337 * Get name of peer for connected socket. 1338 */ 1339 int 1340 sys_getpeername(struct proc *p, void *v, register_t *retval) 1341 { 1342 struct sys_getpeername_args /* { 1343 syscallarg(int) fdes; 1344 syscallarg(struct sockaddr *) asa; 1345 syscallarg(socklen_t *) alen; 1346 } */ *uap = v; 1347 struct file *fp; 1348 struct socket *so; 1349 struct mbuf *m = NULL; 1350 socklen_t len; 1351 int error; 1352 1353 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) 1354 return (error); 1355 so = fp->f_data; 1356 error = pledge_socket(p, -1, so->so_state); 1357 if (error) 1358 goto bad; 1359 if (so->so_state & SS_YP) { 1360 error = ENOTSOCK; 1361 goto bad; 1362 } 1363 if ((so->so_state & SS_ISCONNECTED) == 0) { 1364 error = ENOTCONN; 1365 goto bad; 1366 } 1367 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 1368 if (error) 1369 goto bad; 1370 m = m_getclr(M_WAIT, MT_SONAME); 1371 solock_shared(so); 1372 error = pru_peeraddr(so, m); 1373 sounlock_shared(so); 1374 if (error) 1375 goto bad; 1376 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); 1377 bad: 1378 FRELE(fp, p); 1379 m_freem(m); 1380 return (error); 1381 } 1382 1383 int 1384 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) 1385 { 1386 struct sockaddr *sa; 1387 struct mbuf *m; 1388 int error; 1389 1390 /* 1391 * We can't allow socket names > UCHAR_MAX in length, since that 1392 * will overflow sa_len. Also, control data more than MCLBYTES in 1393 * length is just too much. 1394 * Memory for sa_len and sa_family must exist. 1395 */ 1396 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) || 1397 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data))) 1398 return (EINVAL); 1399 1400 /* Allocate an mbuf to hold the arguments. */ 1401 m = m_get(M_WAIT, type); 1402 if (buflen > MLEN) { 1403 MCLGET(m, M_WAITOK); 1404 if ((m->m_flags & M_EXT) == 0) { 1405 m_free(m); 1406 return ENOBUFS; 1407 } 1408 } 1409 m->m_len = buflen; 1410 error = copyin(buf, mtod(m, caddr_t), buflen); 1411 if (error) { 1412 (void) m_free(m); 1413 return (error); 1414 } 1415 *mp = m; 1416 if (type == MT_SONAME) { 1417 sa = mtod(m, struct sockaddr *); 1418 sa->sa_len = buflen; 1419 } 1420 return (0); 1421 } 1422 1423 int 1424 getsock(struct proc *p, int fdes, struct file **fpp) 1425 { 1426 struct file *fp; 1427 1428 fp = fd_getfile(p->p_fd, fdes); 1429 if (fp == NULL) 1430 return (EBADF); 1431 if (fp->f_type != DTYPE_SOCKET) { 1432 FRELE(fp, p); 1433 return (ENOTSOCK); 1434 } 1435 *fpp = fp; 1436 1437 return (0); 1438 } 1439 1440 int 1441 sys_setrtable(struct proc *p, void *v, register_t *retval) 1442 { 1443 struct sys_setrtable_args /* { 1444 syscallarg(int) rtableid; 1445 } */ *uap = v; 1446 u_int ps_rtableid = p->p_p->ps_rtableid; 1447 int rtableid, error; 1448 1449 rtableid = SCARG(uap, rtableid); 1450 1451 if (ps_rtableid == rtableid) 1452 return (0); 1453 if (ps_rtableid != 0 && (error = suser(p)) != 0) 1454 return (error); 1455 if (rtableid < 0 || !rtable_exists((u_int)rtableid)) 1456 return (EINVAL); 1457 1458 p->p_p->ps_rtableid = (u_int)rtableid; 1459 return (0); 1460 } 1461 1462 int 1463 sys_getrtable(struct proc *p, void *v, register_t *retval) 1464 { 1465 *retval = (int)p->p_p->ps_rtableid; 1466 return (0); 1467 } 1468 1469 int 1470 copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa, 1471 socklen_t buflen, socklen_t *outlen) 1472 { 1473 int error; 1474 socklen_t namelen = name->m_len; 1475 1476 /* SHOULD COPY OUT A CHAIN HERE */ 1477 error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen)); 1478 if (error == 0) { 1479 #ifdef KTRACE 1480 if (KTRPOINT(p, KTR_STRUCT)) 1481 ktrsockaddr(p, mtod(name, caddr_t), namelen); 1482 #endif 1483 error = copyout(&namelen, outlen, sizeof(*outlen)); 1484 } 1485 1486 return (error); 1487 } 1488 1489 #ifndef SMALL_KERNEL 1490 int 1491 ypsockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) 1492 { 1493 struct sockaddr *sa; 1494 struct mbuf *m; 1495 1496 /* 1497 * We can't allow socket names > UCHAR_MAX in length, since that 1498 * will overflow sa_len. Also, control data more than MCLBYTES in 1499 * length is just too much. 1500 * Memory for sa_len and sa_family must exist. 1501 */ 1502 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) || 1503 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data))) 1504 return (EINVAL); 1505 1506 /* Allocate an mbuf to hold the arguments. */ 1507 m = m_get(M_WAIT, type); 1508 if (buflen > MLEN) { 1509 MCLGET(m, M_WAITOK); 1510 if ((m->m_flags & M_EXT) == 0) { 1511 m_free(m); 1512 return ENOBUFS; 1513 } 1514 } 1515 m->m_len = buflen; 1516 bcopy(buf, mtod(m, caddr_t), buflen); 1517 *mp = m; 1518 if (type == MT_SONAME) { 1519 sa = mtod(m, struct sockaddr *); 1520 sa->sa_len = buflen; 1521 } 1522 return (0); 1523 } 1524 #endif /* SMALL_KERNEL */ 1525 1526 int 1527 sys_ypconnect(struct proc *p, void *v, register_t *retval) 1528 { 1529 #ifdef SMALL_KERNEL 1530 return EAFNOSUPPORT; 1531 #else 1532 struct sys_ypconnect_args /* { 1533 syscallarg(int) type; 1534 } */ *uap = v; 1535 struct nameidata nid; 1536 struct vattr va; 1537 struct uio uio; 1538 struct iovec iov; 1539 struct filedesc *fdp = p->p_fd; 1540 struct socket *so; 1541 struct file *fp; 1542 struct flock fl; 1543 char *name; 1544 struct mbuf *nam = NULL; 1545 int error, fd = -1; 1546 struct ypbinding { 1547 u_short ypbind_port; 1548 int status; 1549 in_addr_t in; 1550 u_short ypserv_udp_port; 1551 u_short garbage; 1552 u_short ypserv_tcp_port; 1553 } __packed data; 1554 struct sockaddr_in ypsin; 1555 1556 if (!domainname[0] || strchr(domainname, '/')) 1557 return EAFNOSUPPORT; 1558 1559 switch (SCARG(uap, type)) { 1560 case SOCK_STREAM: 1561 case SOCK_DGRAM: 1562 break; 1563 default: 1564 return EAFNOSUPPORT; 1565 } 1566 1567 if (p->p_p->ps_flags & PS_CHROOT) 1568 return EACCES; 1569 name = pool_get(&namei_pool, PR_WAITOK); 1570 snprintf(name, MAXPATHLEN, "/var/yp/binding/%s.2", domainname); 1571 NDINIT(&nid, 0, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, name, p); 1572 nid.ni_pledge = PLEDGE_RPATH; 1573 1574 KERNEL_LOCK(); 1575 error = namei(&nid); 1576 pool_put(&namei_pool, name); 1577 if (error) 1578 goto out; 1579 error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p); 1580 if (error) 1581 goto verror; 1582 if (nid.ni_vp->v_type != VREG || va.va_size != sizeof data) { 1583 error = EFTYPE; 1584 goto verror; 1585 } 1586 1587 /* 1588 * Check that a lock is held on the file (hopefully by ypbind), 1589 * otherwise the file might be old 1590 */ 1591 fl.l_start = 0; 1592 fl.l_len = 0; 1593 fl.l_pid = 0; 1594 fl.l_type = F_WRLCK; 1595 fl.l_whence = SEEK_SET; 1596 error = VOP_ADVLOCK(nid.ni_vp, fdp, F_GETLK, &fl, F_POSIX); 1597 if (error) 1598 goto verror; 1599 if (fl.l_type == F_UNLCK) { 1600 error = EOWNERDEAD; 1601 goto verror; 1602 } 1603 1604 iov.iov_base = &data; 1605 iov.iov_len = sizeof data; 1606 uio.uio_iov = &iov; 1607 uio.uio_iovcnt = 1; 1608 uio.uio_offset = 0; 1609 uio.uio_resid = iov.iov_len; 1610 uio.uio_segflg = UIO_SYSSPACE; 1611 uio.uio_rw = UIO_READ; 1612 uio.uio_procp = p; 1613 1614 error = VOP_READ(nid.ni_vp, &uio, 0, p->p_ucred); 1615 if (error) { 1616 verror: 1617 if (nid.ni_vp) 1618 vput(nid.ni_vp); 1619 out: 1620 KERNEL_UNLOCK(); 1621 return (error); 1622 } 1623 vput(nid.ni_vp); 1624 KERNEL_UNLOCK(); 1625 1626 bzero(&ypsin, sizeof ypsin); 1627 ypsin.sin_len = sizeof ypsin; 1628 ypsin.sin_family = AF_INET; 1629 if (SCARG(uap, type) == SOCK_STREAM) 1630 ypsin.sin_port = data.ypserv_tcp_port; 1631 else 1632 ypsin.sin_port = data.ypserv_udp_port; 1633 if (ntohs(ypsin.sin_port) >= IPPORT_RESERVED || ntohs(ypsin.sin_port) == 20) 1634 return EPERM; 1635 memcpy(&ypsin.sin_addr.s_addr, &data.in, sizeof ypsin.sin_addr.s_addr); 1636 1637 error = socreate(AF_INET, &so, SCARG(uap, type), 0); 1638 if (error) 1639 return (error); 1640 1641 error = ypsockargs(&nam, &ypsin, sizeof ypsin, MT_SONAME); 1642 if (error) { 1643 soclose(so, MSG_DONTWAIT); 1644 return (error); 1645 } 1646 1647 #ifdef KTRACE 1648 if (KTRPOINT(p, KTR_STRUCT)) 1649 ktrsockaddr(p, mtod(nam, caddr_t), sizeof(struct sockaddr_in)); 1650 #endif 1651 solock(so); 1652 1653 /* Secure YP maps require reserved ports */ 1654 if (suser(p) == 0) 1655 sotoinpcb(so)->inp_flags |= INP_LOWPORT; 1656 1657 error = soconnect(so, nam); 1658 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 1659 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH, 1660 "netcon2", INFSLP); 1661 if (error) 1662 break; 1663 } 1664 m_freem(nam); 1665 so->so_state |= SS_YP; /* impose some restrictions */ 1666 sounlock(so); 1667 if (error) { 1668 soclose(so, MSG_DONTWAIT); 1669 return (error); 1670 } 1671 1672 fdplock(fdp); 1673 error = falloc(p, &fp, &fd); 1674 if (error) { 1675 fdpunlock(fdp); 1676 soclose(so, MSG_DONTWAIT); 1677 return (error); 1678 } 1679 1680 fp->f_flag = FREAD | FWRITE | FNONBLOCK; 1681 fp->f_type = DTYPE_SOCKET; 1682 fp->f_ops = &socketops; 1683 fp->f_data = so; 1684 fdinsert(fdp, fd, UF_EXCLOSE, fp); 1685 fdpunlock(fdp); 1686 FRELE(fp, p); 1687 *retval = fd; 1688 return (error); 1689 #endif /* SMALL_KERNEL */ 1690 } 1691