1 /* $OpenBSD: uipc_syscalls.c,v 1.207 2022/12/07 01:02:28 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 <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_state & SS_CANTRCVMORE) 292 error = ECONNABORTED; 293 else 294 error = EWOULDBLOCK; 295 goto out_unlock; 296 } 297 while (head->so_qlen == 0 && head->so_error == 0) { 298 if (head->so_state & SS_CANTRCVMORE) { 299 head->so_error = ECONNABORTED; 300 break; 301 } 302 error = sosleep_nsec(head, &head->so_timeo, PSOCK | PCATCH, 303 "netcon", INFSLP); 304 if (error) 305 goto out_unlock; 306 } 307 if (head->so_error) { 308 error = head->so_error; 309 head->so_error = 0; 310 goto out_unlock; 311 } 312 313 /* 314 * Do not sleep after we have taken the socket out of the queue. 315 */ 316 so = TAILQ_FIRST(&head->so_q); 317 318 if (persocket) 319 solock(so); 320 321 if (soqremque(so, 1) == 0) 322 panic("accept"); 323 324 /* Figure out whether the new socket should be non-blocking. */ 325 nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK) 326 : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0); 327 328 /* connection has been removed from the listen queue */ 329 KNOTE(&head->so_rcv.sb_sel.si_note, 0); 330 331 if (persocket) 332 sounlock(head); 333 334 fp->f_type = DTYPE_SOCKET; 335 fp->f_flag = FREAD | FWRITE | nflag; 336 fp->f_ops = &socketops; 337 fp->f_data = so; 338 339 error = soaccept(so, nam); 340 341 if (persocket) 342 sounlock(so); 343 else 344 sounlock(head); 345 346 if (error) 347 goto out; 348 349 if (name != NULL) { 350 error = copyaddrout(p, nam, name, namelen, anamelen); 351 if (error) 352 goto out; 353 } 354 355 fdplock(fdp); 356 fdinsert(fdp, tmpfd, cloexec, fp); 357 fdpunlock(fdp); 358 FRELE(fp, p); 359 *retval = tmpfd; 360 361 m_freem(nam); 362 FRELE(headfp, p); 363 364 return 0; 365 366 out_unlock: 367 sounlock(head); 368 out: 369 fdplock(fdp); 370 fdremove(fdp, tmpfd); 371 fdpunlock(fdp); 372 closef(fp, p); 373 374 m_freem(nam); 375 FRELE(headfp, p); 376 377 return (error); 378 } 379 380 int 381 sys_connect(struct proc *p, void *v, register_t *retval) 382 { 383 struct sys_connect_args /* { 384 syscallarg(int) s; 385 syscallarg(const struct sockaddr *) name; 386 syscallarg(socklen_t) namelen; 387 } */ *uap = v; 388 struct file *fp; 389 struct socket *so; 390 struct mbuf *nam; 391 int error, interrupted = 0; 392 393 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 394 return (error); 395 so = fp->f_data; 396 error = pledge_socket(p, so->so_proto->pr_domain->dom_family, 397 so->so_state); 398 if (error) 399 goto out; 400 if (so->so_state & SS_YP) { 401 error = ENOTSOCK; 402 goto out; 403 } 404 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 405 MT_SONAME); 406 if (error) 407 goto out; 408 #ifdef KTRACE 409 if (KTRPOINT(p, KTR_STRUCT)) 410 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen)); 411 #endif 412 solock(so); 413 if (isdnssocket(so)) { 414 error = dns_portcheck(p, so, mtod(nam, void *), nam->m_len); 415 if (error) 416 goto unlock; 417 } 418 if (so->so_state & SS_ISCONNECTING) { 419 error = EALREADY; 420 goto unlock; 421 } 422 error = soconnect(so, nam); 423 if (error) 424 goto bad; 425 if ((fp->f_flag & FNONBLOCK) && (so->so_state & SS_ISCONNECTING)) { 426 error = EINPROGRESS; 427 goto unlock; 428 } 429 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 430 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH, 431 "netcon2", INFSLP); 432 if (error) { 433 if (error == EINTR || error == ERESTART) 434 interrupted = 1; 435 break; 436 } 437 } 438 if (error == 0) { 439 error = so->so_error; 440 so->so_error = 0; 441 } 442 bad: 443 if (!interrupted) 444 so->so_state &= ~SS_ISCONNECTING; 445 unlock: 446 sounlock(so); 447 m_freem(nam); 448 out: 449 FRELE(fp, p); 450 if (error == ERESTART) 451 error = EINTR; 452 return (error); 453 } 454 455 int 456 sys_socketpair(struct proc *p, void *v, register_t *retval) 457 { 458 struct sys_socketpair_args /* { 459 syscallarg(int) domain; 460 syscallarg(int) type; 461 syscallarg(int) protocol; 462 syscallarg(int *) rsv; 463 } */ *uap = v; 464 struct filedesc *fdp = p->p_fd; 465 struct file *fp1 = NULL, *fp2 = NULL; 466 struct socket *so1, *so2; 467 int type, cloexec, nonblock, fflag, error, sv[2]; 468 469 type = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); 470 cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0; 471 nonblock = SCARG(uap, type) & SOCK_NONBLOCK; 472 fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0); 473 474 error = socreate(SCARG(uap, domain), &so1, type, SCARG(uap, protocol)); 475 if (error) 476 return (error); 477 error = socreate(SCARG(uap, domain), &so2, type, SCARG(uap, protocol)); 478 if (error) 479 goto free1; 480 481 error = soconnect2(so1, so2); 482 if (error != 0) 483 goto free2; 484 485 if ((SCARG(uap, type) & SOCK_TYPE_MASK) == SOCK_DGRAM) { 486 /* 487 * Datagram socket connection is asymmetric. 488 */ 489 error = soconnect2(so2, so1); 490 if (error != 0) 491 goto free2; 492 } 493 fdplock(fdp); 494 if ((error = falloc(p, &fp1, &sv[0])) != 0) 495 goto free3; 496 fp1->f_flag = fflag; 497 fp1->f_type = DTYPE_SOCKET; 498 fp1->f_ops = &socketops; 499 fp1->f_data = so1; 500 if ((error = falloc(p, &fp2, &sv[1])) != 0) 501 goto free4; 502 fp2->f_flag = fflag; 503 fp2->f_type = DTYPE_SOCKET; 504 fp2->f_ops = &socketops; 505 fp2->f_data = so2; 506 error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int)); 507 if (error == 0) { 508 fdinsert(fdp, sv[0], cloexec, fp1); 509 fdinsert(fdp, sv[1], cloexec, fp2); 510 fdpunlock(fdp); 511 #ifdef KTRACE 512 if (KTRPOINT(p, KTR_STRUCT)) 513 ktrfds(p, sv, 2); 514 #endif 515 FRELE(fp1, p); 516 FRELE(fp2, p); 517 return (0); 518 } 519 fdremove(fdp, sv[1]); 520 free4: 521 fdremove(fdp, sv[0]); 522 free3: 523 fdpunlock(fdp); 524 525 if (fp2 != NULL) { 526 closef(fp2, p); 527 so2 = NULL; 528 } 529 if (fp1 != NULL) { 530 closef(fp1, p); 531 so1 = NULL; 532 } 533 free2: 534 if (so2 != NULL) 535 (void)soclose(so2, 0); 536 free1: 537 if (so1 != NULL) 538 (void)soclose(so1, 0); 539 return (error); 540 } 541 542 int 543 sys_sendto(struct proc *p, void *v, register_t *retval) 544 { 545 struct sys_sendto_args /* { 546 syscallarg(int) s; 547 syscallarg(const void *) buf; 548 syscallarg(size_t) len; 549 syscallarg(int) flags; 550 syscallarg(const struct sockaddr *) to; 551 syscallarg(socklen_t) tolen; 552 } */ *uap = v; 553 struct msghdr msg; 554 struct iovec aiov; 555 556 msg.msg_name = (caddr_t)SCARG(uap, to); 557 msg.msg_namelen = SCARG(uap, tolen); 558 msg.msg_iov = &aiov; 559 msg.msg_iovlen = 1; 560 msg.msg_control = NULL; 561 msg.msg_flags = 0; 562 aiov.iov_base = (char *)SCARG(uap, buf); 563 aiov.iov_len = SCARG(uap, len); 564 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); 565 } 566 567 int 568 sys_sendmsg(struct proc *p, void *v, register_t *retval) 569 { 570 struct sys_sendmsg_args /* { 571 syscallarg(int) s; 572 syscallarg(const struct msghdr *) msg; 573 syscallarg(int) flags; 574 } */ *uap = v; 575 struct msghdr msg; 576 struct iovec aiov[UIO_SMALLIOV], *iov; 577 int error; 578 579 error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); 580 if (error) 581 return (error); 582 #ifdef KTRACE 583 if (KTRPOINT(p, KTR_STRUCT)) 584 ktrmsghdr(p, &msg); 585 #endif 586 587 if (msg.msg_iovlen > IOV_MAX) 588 return (EMSGSIZE); 589 if (msg.msg_iovlen > UIO_SMALLIOV) 590 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec), 591 M_IOV, M_WAITOK); 592 else 593 iov = aiov; 594 if (msg.msg_iovlen && 595 (error = copyin(msg.msg_iov, iov, 596 msg.msg_iovlen * sizeof (struct iovec)))) 597 goto done; 598 #ifdef KTRACE 599 if (msg.msg_iovlen && KTRPOINT(p, KTR_STRUCT)) 600 ktriovec(p, iov, msg.msg_iovlen); 601 #endif 602 msg.msg_iov = iov; 603 msg.msg_flags = 0; 604 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 605 done: 606 if (iov != aiov) 607 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen); 608 return (error); 609 } 610 611 int 612 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 solock_shared(so); 1275 error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m); 1276 sounlock_shared(so); 1277 if (error == 0 && SCARG(uap, val) && valsize && m != NULL) { 1278 if (valsize > m->m_len) 1279 valsize = m->m_len; 1280 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize); 1281 if (error == 0) 1282 error = copyout(&valsize, 1283 SCARG(uap, avalsize), sizeof (valsize)); 1284 } 1285 m_free(m); 1286 out: 1287 FRELE(fp, p); 1288 return (error); 1289 } 1290 1291 /* 1292 * Get socket name. 1293 */ 1294 int 1295 sys_getsockname(struct proc *p, void *v, register_t *retval) 1296 { 1297 struct sys_getsockname_args /* { 1298 syscallarg(int) fdes; 1299 syscallarg(struct sockaddr *) asa; 1300 syscallarg(socklen_t *) alen; 1301 } */ *uap = v; 1302 struct file *fp; 1303 struct socket *so; 1304 struct mbuf *m = NULL; 1305 socklen_t len; 1306 int error; 1307 1308 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) 1309 return (error); 1310 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 1311 if (error) 1312 goto bad; 1313 so = fp->f_data; 1314 if (so->so_state & SS_YP) { 1315 error = ENOTSOCK; 1316 goto bad; 1317 } 1318 error = pledge_socket(p, -1, so->so_state); 1319 if (error) 1320 goto bad; 1321 if (so->so_state & SS_YP) { 1322 error = ENOTSOCK; 1323 goto bad; 1324 } 1325 m = m_getclr(M_WAIT, MT_SONAME); 1326 solock_shared(so); 1327 error = pru_sockaddr(so, m); 1328 sounlock_shared(so); 1329 if (error) 1330 goto bad; 1331 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); 1332 bad: 1333 FRELE(fp, p); 1334 m_freem(m); 1335 return (error); 1336 } 1337 1338 /* 1339 * Get name of peer for connected socket. 1340 */ 1341 int 1342 sys_getpeername(struct proc *p, void *v, register_t *retval) 1343 { 1344 struct sys_getpeername_args /* { 1345 syscallarg(int) fdes; 1346 syscallarg(struct sockaddr *) asa; 1347 syscallarg(socklen_t *) alen; 1348 } */ *uap = v; 1349 struct file *fp; 1350 struct socket *so; 1351 struct mbuf *m = NULL; 1352 socklen_t len; 1353 int error; 1354 1355 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) 1356 return (error); 1357 so = fp->f_data; 1358 error = pledge_socket(p, -1, so->so_state); 1359 if (error) 1360 goto bad; 1361 if (so->so_state & SS_YP) { 1362 error = ENOTSOCK; 1363 goto bad; 1364 } 1365 if ((so->so_state & SS_ISCONNECTED) == 0) { 1366 error = ENOTCONN; 1367 goto bad; 1368 } 1369 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 1370 if (error) 1371 goto bad; 1372 m = m_getclr(M_WAIT, MT_SONAME); 1373 solock_shared(so); 1374 error = pru_peeraddr(so, m); 1375 sounlock_shared(so); 1376 if (error) 1377 goto bad; 1378 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); 1379 bad: 1380 FRELE(fp, p); 1381 m_freem(m); 1382 return (error); 1383 } 1384 1385 int 1386 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) 1387 { 1388 struct sockaddr *sa; 1389 struct mbuf *m; 1390 int error; 1391 1392 /* 1393 * We can't allow socket names > UCHAR_MAX in length, since that 1394 * will overflow sa_len. Also, control data more than MCLBYTES in 1395 * length is just too much. 1396 * Memory for sa_len and sa_family must exist. 1397 */ 1398 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) || 1399 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data))) 1400 return (EINVAL); 1401 1402 /* Allocate an mbuf to hold the arguments. */ 1403 m = m_get(M_WAIT, type); 1404 if (buflen > MLEN) { 1405 MCLGET(m, M_WAITOK); 1406 if ((m->m_flags & M_EXT) == 0) { 1407 m_free(m); 1408 return ENOBUFS; 1409 } 1410 } 1411 m->m_len = buflen; 1412 error = copyin(buf, mtod(m, caddr_t), buflen); 1413 if (error) { 1414 (void) m_free(m); 1415 return (error); 1416 } 1417 *mp = m; 1418 if (type == MT_SONAME) { 1419 sa = mtod(m, struct sockaddr *); 1420 sa->sa_len = buflen; 1421 } 1422 return (0); 1423 } 1424 1425 int 1426 getsock(struct proc *p, int fdes, struct file **fpp) 1427 { 1428 struct file *fp; 1429 1430 fp = fd_getfile(p->p_fd, fdes); 1431 if (fp == NULL) 1432 return (EBADF); 1433 if (fp->f_type != DTYPE_SOCKET) { 1434 FRELE(fp, p); 1435 return (ENOTSOCK); 1436 } 1437 *fpp = fp; 1438 1439 return (0); 1440 } 1441 1442 int 1443 sys_setrtable(struct proc *p, void *v, register_t *retval) 1444 { 1445 struct sys_setrtable_args /* { 1446 syscallarg(int) rtableid; 1447 } */ *uap = v; 1448 u_int ps_rtableid = p->p_p->ps_rtableid; 1449 int rtableid, error; 1450 1451 rtableid = SCARG(uap, rtableid); 1452 1453 if (ps_rtableid == rtableid) 1454 return (0); 1455 if (ps_rtableid != 0 && (error = suser(p)) != 0) 1456 return (error); 1457 if (rtableid < 0 || !rtable_exists((u_int)rtableid)) 1458 return (EINVAL); 1459 1460 p->p_p->ps_rtableid = (u_int)rtableid; 1461 return (0); 1462 } 1463 1464 int 1465 sys_getrtable(struct proc *p, void *v, register_t *retval) 1466 { 1467 *retval = (int)p->p_p->ps_rtableid; 1468 return (0); 1469 } 1470 1471 int 1472 copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa, 1473 socklen_t buflen, socklen_t *outlen) 1474 { 1475 int error; 1476 socklen_t namelen = name->m_len; 1477 1478 /* SHOULD COPY OUT A CHAIN HERE */ 1479 error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen)); 1480 if (error == 0) { 1481 #ifdef KTRACE 1482 if (KTRPOINT(p, KTR_STRUCT)) 1483 ktrsockaddr(p, mtod(name, caddr_t), namelen); 1484 #endif 1485 error = copyout(&namelen, outlen, sizeof(*outlen)); 1486 } 1487 1488 return (error); 1489 } 1490 1491 #ifndef SMALL_KERNEL 1492 int 1493 ypsockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) 1494 { 1495 struct sockaddr *sa; 1496 struct mbuf *m; 1497 1498 /* 1499 * We can't allow socket names > UCHAR_MAX in length, since that 1500 * will overflow sa_len. Also, control data more than MCLBYTES in 1501 * length is just too much. 1502 * Memory for sa_len and sa_family must exist. 1503 */ 1504 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) || 1505 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data))) 1506 return (EINVAL); 1507 1508 /* Allocate an mbuf to hold the arguments. */ 1509 m = m_get(M_WAIT, type); 1510 if (buflen > MLEN) { 1511 MCLGET(m, M_WAITOK); 1512 if ((m->m_flags & M_EXT) == 0) { 1513 m_free(m); 1514 return ENOBUFS; 1515 } 1516 } 1517 m->m_len = buflen; 1518 bcopy(buf, mtod(m, caddr_t), buflen); 1519 *mp = m; 1520 if (type == MT_SONAME) { 1521 sa = mtod(m, struct sockaddr *); 1522 sa->sa_len = buflen; 1523 } 1524 return (0); 1525 } 1526 #endif /* SMALL_KERNEL */ 1527 1528 int 1529 sys_ypconnect(struct proc *p, void *v, register_t *retval) 1530 { 1531 #ifdef SMALL_KERNEL 1532 return EAFNOSUPPORT; 1533 #else 1534 struct sys_ypconnect_args /* { 1535 syscallarg(int) type; 1536 } */ *uap = v; 1537 struct nameidata nid; 1538 struct vattr va; 1539 struct uio uio; 1540 struct iovec iov; 1541 struct filedesc *fdp = p->p_fd; 1542 struct socket *so; 1543 struct file *fp; 1544 struct flock fl; 1545 char *name; 1546 struct mbuf *nam = NULL; 1547 int error, fd = -1; 1548 struct ypbinding { 1549 u_short ypbind_port; 1550 int status; 1551 in_addr_t in; 1552 u_short ypserv_udp_port; 1553 u_short garbage; 1554 u_short ypserv_tcp_port; 1555 } __packed data; 1556 struct sockaddr_in ypsin; 1557 1558 if (!domainname[0] || strchr(domainname, '/')) 1559 return EAFNOSUPPORT; 1560 1561 switch (SCARG(uap, type)) { 1562 case SOCK_STREAM: 1563 case SOCK_DGRAM: 1564 break; 1565 default: 1566 return EAFNOSUPPORT; 1567 } 1568 1569 if (p->p_p->ps_flags & PS_CHROOT) 1570 return EACCES; 1571 name = pool_get(&namei_pool, PR_WAITOK); 1572 snprintf(name, MAXPATHLEN, "/var/yp/binding/%s.2", domainname); 1573 NDINIT(&nid, 0, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, name, p); 1574 nid.ni_pledge = PLEDGE_RPATH; 1575 1576 KERNEL_LOCK(); 1577 error = namei(&nid); 1578 pool_put(&namei_pool, name); 1579 if (error) 1580 goto out; 1581 error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p); 1582 if (error) 1583 goto verror; 1584 if (nid.ni_vp->v_type != VREG || va.va_size != sizeof data) { 1585 error = EFTYPE; 1586 goto verror; 1587 } 1588 1589 /* 1590 * Check that a lock is held on the file (hopefully by ypbind), 1591 * otherwise the file might be old 1592 */ 1593 fl.l_start = 0; 1594 fl.l_len = 0; 1595 fl.l_pid = 0; 1596 fl.l_type = F_WRLCK; 1597 fl.l_whence = SEEK_SET; 1598 error = VOP_ADVLOCK(nid.ni_vp, fdp, F_GETLK, &fl, F_POSIX); 1599 if (error) 1600 goto verror; 1601 if (fl.l_type == F_UNLCK) { 1602 error = EOWNERDEAD; 1603 goto verror; 1604 } 1605 1606 iov.iov_base = &data; 1607 iov.iov_len = sizeof data; 1608 uio.uio_iov = &iov; 1609 uio.uio_iovcnt = 1; 1610 uio.uio_offset = 0; 1611 uio.uio_resid = iov.iov_len; 1612 uio.uio_segflg = UIO_SYSSPACE; 1613 uio.uio_rw = UIO_READ; 1614 uio.uio_procp = p; 1615 1616 error = VOP_READ(nid.ni_vp, &uio, 0, p->p_ucred); 1617 if (error) { 1618 verror: 1619 if (nid.ni_vp) 1620 vput(nid.ni_vp); 1621 out: 1622 KERNEL_UNLOCK(); 1623 return (error); 1624 } 1625 vput(nid.ni_vp); 1626 KERNEL_UNLOCK(); 1627 1628 bzero(&ypsin, sizeof ypsin); 1629 ypsin.sin_len = sizeof ypsin; 1630 ypsin.sin_family = AF_INET; 1631 if (SCARG(uap, type) == SOCK_STREAM) 1632 ypsin.sin_port = data.ypserv_tcp_port; 1633 else 1634 ypsin.sin_port = data.ypserv_udp_port; 1635 if (ntohs(ypsin.sin_port) >= IPPORT_RESERVED || ntohs(ypsin.sin_port) == 20) 1636 return EPERM; 1637 memcpy(&ypsin.sin_addr.s_addr, &data.in, sizeof ypsin.sin_addr.s_addr); 1638 1639 error = socreate(AF_INET, &so, SCARG(uap, type), 0); 1640 if (error) 1641 return (error); 1642 1643 error = ypsockargs(&nam, &ypsin, sizeof ypsin, MT_SONAME); 1644 if (error) { 1645 soclose(so, MSG_DONTWAIT); 1646 return (error); 1647 } 1648 1649 #ifdef KTRACE 1650 if (KTRPOINT(p, KTR_STRUCT)) 1651 ktrsockaddr(p, mtod(nam, caddr_t), sizeof(struct sockaddr_in)); 1652 #endif 1653 solock(so); 1654 1655 /* Secure YP maps require reserved ports */ 1656 if (suser(p) == 0) 1657 sotoinpcb(so)->inp_flags |= INP_LOWPORT; 1658 1659 error = soconnect(so, nam); 1660 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 1661 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH, 1662 "netcon2", INFSLP); 1663 if (error) 1664 break; 1665 } 1666 m_freem(nam); 1667 so->so_state |= SS_YP; /* impose some restrictions */ 1668 sounlock(so); 1669 if (error) { 1670 soclose(so, MSG_DONTWAIT); 1671 return (error); 1672 } 1673 1674 fdplock(fdp); 1675 error = falloc(p, &fp, &fd); 1676 if (error) { 1677 fdpunlock(fdp); 1678 soclose(so, MSG_DONTWAIT); 1679 return (error); 1680 } 1681 1682 fp->f_flag = FREAD | FWRITE | FNONBLOCK; 1683 fp->f_type = DTYPE_SOCKET; 1684 fp->f_ops = &socketops; 1685 fp->f_data = so; 1686 fdinsert(fdp, fd, UF_EXCLOSE, fp); 1687 fdpunlock(fdp); 1688 FRELE(fp, p); 1689 *retval = fd; 1690 return (error); 1691 #endif /* SMALL_KERNEL */ 1692 } 1693