1 /* $OpenBSD: uipc_syscalls.c,v 1.219 2024/04/25 17:32:53 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, 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 "netacc", 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_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_shared(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 "netcon", 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_shared(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_WAIT); 1218 if ((m->m_flags & M_EXT) == 0) { 1219 error = ENOBUFS; 1220 goto bad; 1221 } 1222 } 1223 error = copyin(SCARG(uap, val), mtod(m, caddr_t), 1224 SCARG(uap, valsize)); 1225 if (error) { 1226 goto bad; 1227 } 1228 m->m_len = SCARG(uap, valsize); 1229 } 1230 so = fp->f_data; 1231 error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m); 1232 bad: 1233 m_freem(m); 1234 FRELE(fp, p); 1235 return (error); 1236 } 1237 1238 int 1239 sys_getsockopt(struct proc *p, void *v, register_t *retval) 1240 { 1241 struct sys_getsockopt_args /* { 1242 syscallarg(int) s; 1243 syscallarg(int) level; 1244 syscallarg(int) name; 1245 syscallarg(void *) val; 1246 syscallarg(socklen_t *) avalsize; 1247 } */ *uap = v; 1248 struct file *fp; 1249 struct mbuf *m = NULL; 1250 socklen_t valsize; 1251 struct socket *so; 1252 int error; 1253 1254 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 1255 return (error); 1256 error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name)); 1257 if (error) 1258 goto out; 1259 if (SCARG(uap, val)) { 1260 error = copyin(SCARG(uap, avalsize), 1261 &valsize, sizeof (valsize)); 1262 if (error) 1263 goto out; 1264 } else 1265 valsize = 0; 1266 m = m_get(M_WAIT, MT_SOOPTS); 1267 so = fp->f_data; 1268 error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m); 1269 if (error == 0 && SCARG(uap, val) && valsize && m != NULL) { 1270 if (valsize > m->m_len) 1271 valsize = m->m_len; 1272 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize); 1273 if (error == 0) 1274 error = copyout(&valsize, 1275 SCARG(uap, avalsize), sizeof (valsize)); 1276 } 1277 m_free(m); 1278 out: 1279 FRELE(fp, p); 1280 return (error); 1281 } 1282 1283 /* 1284 * Get socket name. 1285 */ 1286 int 1287 sys_getsockname(struct proc *p, void *v, register_t *retval) 1288 { 1289 struct sys_getsockname_args /* { 1290 syscallarg(int) fdes; 1291 syscallarg(struct sockaddr *) asa; 1292 syscallarg(socklen_t *) alen; 1293 } */ *uap = v; 1294 struct file *fp; 1295 struct socket *so; 1296 struct mbuf *m = NULL; 1297 socklen_t len; 1298 int error; 1299 1300 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) 1301 return (error); 1302 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 1303 if (error) 1304 goto bad; 1305 so = fp->f_data; 1306 if (so->so_state & SS_YP) { 1307 error = ENOTSOCK; 1308 goto bad; 1309 } 1310 error = pledge_socket(p, -1, so->so_state); 1311 if (error) 1312 goto bad; 1313 if (so->so_state & SS_YP) { 1314 error = ENOTSOCK; 1315 goto bad; 1316 } 1317 m = m_getclr(M_WAIT, MT_SONAME); 1318 solock_shared(so); 1319 error = pru_sockaddr(so, m); 1320 sounlock_shared(so); 1321 if (error) 1322 goto bad; 1323 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); 1324 bad: 1325 FRELE(fp, p); 1326 m_freem(m); 1327 return (error); 1328 } 1329 1330 /* 1331 * Get name of peer for connected socket. 1332 */ 1333 int 1334 sys_getpeername(struct proc *p, void *v, register_t *retval) 1335 { 1336 struct sys_getpeername_args /* { 1337 syscallarg(int) fdes; 1338 syscallarg(struct sockaddr *) asa; 1339 syscallarg(socklen_t *) alen; 1340 } */ *uap = v; 1341 struct file *fp; 1342 struct socket *so; 1343 struct mbuf *m = NULL; 1344 socklen_t len; 1345 int error; 1346 1347 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) 1348 return (error); 1349 so = fp->f_data; 1350 error = pledge_socket(p, -1, so->so_state); 1351 if (error) 1352 goto bad; 1353 if (so->so_state & SS_YP) { 1354 error = ENOTSOCK; 1355 goto bad; 1356 } 1357 if ((so->so_state & SS_ISCONNECTED) == 0) { 1358 error = ENOTCONN; 1359 goto bad; 1360 } 1361 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 1362 if (error) 1363 goto bad; 1364 m = m_getclr(M_WAIT, MT_SONAME); 1365 solock_shared(so); 1366 error = pru_peeraddr(so, m); 1367 sounlock_shared(so); 1368 if (error) 1369 goto bad; 1370 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); 1371 bad: 1372 FRELE(fp, p); 1373 m_freem(m); 1374 return (error); 1375 } 1376 1377 int 1378 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) 1379 { 1380 struct sockaddr *sa; 1381 struct mbuf *m; 1382 int error; 1383 1384 /* 1385 * We can't allow socket names > UCHAR_MAX in length, since that 1386 * will overflow sa_len. Also, control data more than MCLBYTES in 1387 * length is just too much. 1388 * Memory for sa_len and sa_family must exist. 1389 */ 1390 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) || 1391 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data))) 1392 return (EINVAL); 1393 1394 /* Allocate an mbuf to hold the arguments. */ 1395 m = m_get(M_WAIT, type); 1396 if (buflen > MLEN) { 1397 MCLGET(m, M_WAITOK); 1398 if ((m->m_flags & M_EXT) == 0) { 1399 m_free(m); 1400 return ENOBUFS; 1401 } 1402 } 1403 m->m_len = buflen; 1404 error = copyin(buf, mtod(m, caddr_t), buflen); 1405 if (error) { 1406 (void) m_free(m); 1407 return (error); 1408 } 1409 *mp = m; 1410 if (type == MT_SONAME) { 1411 sa = mtod(m, struct sockaddr *); 1412 sa->sa_len = buflen; 1413 } 1414 return (0); 1415 } 1416 1417 int 1418 getsock(struct proc *p, int fdes, struct file **fpp) 1419 { 1420 struct file *fp; 1421 1422 fp = fd_getfile(p->p_fd, fdes); 1423 if (fp == NULL) 1424 return (EBADF); 1425 if (fp->f_type != DTYPE_SOCKET) { 1426 FRELE(fp, p); 1427 return (ENOTSOCK); 1428 } 1429 *fpp = fp; 1430 1431 return (0); 1432 } 1433 1434 int 1435 sys_setrtable(struct proc *p, void *v, register_t *retval) 1436 { 1437 struct sys_setrtable_args /* { 1438 syscallarg(int) rtableid; 1439 } */ *uap = v; 1440 u_int ps_rtableid = p->p_p->ps_rtableid; 1441 int rtableid, error; 1442 1443 rtableid = SCARG(uap, rtableid); 1444 1445 if (ps_rtableid == rtableid) 1446 return (0); 1447 if (ps_rtableid != 0 && (error = suser(p)) != 0) 1448 return (error); 1449 if (rtableid < 0 || !rtable_exists((u_int)rtableid)) 1450 return (EINVAL); 1451 1452 p->p_p->ps_rtableid = (u_int)rtableid; 1453 return (0); 1454 } 1455 1456 int 1457 sys_getrtable(struct proc *p, void *v, register_t *retval) 1458 { 1459 *retval = (int)p->p_p->ps_rtableid; 1460 return (0); 1461 } 1462 1463 int 1464 copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa, 1465 socklen_t buflen, socklen_t *outlen) 1466 { 1467 int error; 1468 socklen_t namelen = name->m_len; 1469 1470 /* SHOULD COPY OUT A CHAIN HERE */ 1471 error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen)); 1472 if (error == 0) { 1473 #ifdef KTRACE 1474 if (KTRPOINT(p, KTR_STRUCT)) 1475 ktrsockaddr(p, mtod(name, caddr_t), namelen); 1476 #endif 1477 error = copyout(&namelen, outlen, sizeof(*outlen)); 1478 } 1479 1480 return (error); 1481 } 1482 1483 #ifndef SMALL_KERNEL 1484 int 1485 ypsockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) 1486 { 1487 struct sockaddr *sa; 1488 struct mbuf *m; 1489 1490 /* 1491 * We can't allow socket names > UCHAR_MAX in length, since that 1492 * will overflow sa_len. Also, control data more than MCLBYTES in 1493 * length is just too much. 1494 * Memory for sa_len and sa_family must exist. 1495 */ 1496 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) || 1497 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data))) 1498 return (EINVAL); 1499 1500 /* Allocate an mbuf to hold the arguments. */ 1501 m = m_get(M_WAIT, type); 1502 if (buflen > MLEN) { 1503 MCLGET(m, M_WAITOK); 1504 if ((m->m_flags & M_EXT) == 0) { 1505 m_free(m); 1506 return ENOBUFS; 1507 } 1508 } 1509 m->m_len = buflen; 1510 bcopy(buf, mtod(m, caddr_t), buflen); 1511 *mp = m; 1512 if (type == MT_SONAME) { 1513 sa = mtod(m, struct sockaddr *); 1514 sa->sa_len = buflen; 1515 } 1516 return (0); 1517 } 1518 #endif /* SMALL_KERNEL */ 1519 1520 int 1521 sys_ypconnect(struct proc *p, void *v, register_t *retval) 1522 { 1523 #ifdef SMALL_KERNEL 1524 return EAFNOSUPPORT; 1525 #else 1526 struct sys_ypconnect_args /* { 1527 syscallarg(int) type; 1528 } */ *uap = v; 1529 struct nameidata nid; 1530 struct vattr va; 1531 struct uio uio; 1532 struct iovec iov; 1533 struct filedesc *fdp = p->p_fd; 1534 struct socket *so; 1535 struct file *fp; 1536 struct flock fl; 1537 char *name; 1538 struct mbuf *nam = NULL; 1539 int error, fd = -1; 1540 struct ypbinding { 1541 u_short ypbind_port; 1542 int status; 1543 in_addr_t in; 1544 u_short ypserv_udp_port; 1545 u_short garbage; 1546 u_short ypserv_tcp_port; 1547 } __packed data; 1548 struct sockaddr_in ypsin; 1549 1550 if (!domainname[0] || strchr(domainname, '/')) 1551 return EAFNOSUPPORT; 1552 1553 switch (SCARG(uap, type)) { 1554 case SOCK_STREAM: 1555 case SOCK_DGRAM: 1556 break; 1557 default: 1558 return EAFNOSUPPORT; 1559 } 1560 1561 if (p->p_p->ps_flags & PS_CHROOT) 1562 return EACCES; 1563 KERNEL_LOCK(); 1564 name = pool_get(&namei_pool, PR_WAITOK); 1565 snprintf(name, MAXPATHLEN, "/var/yp/binding/%s.2", domainname); 1566 NDINIT(&nid, 0, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, name, p); 1567 nid.ni_pledge = PLEDGE_RPATH; 1568 1569 error = namei(&nid); 1570 pool_put(&namei_pool, name); 1571 if (error) 1572 goto out; 1573 error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p); 1574 if (error) 1575 goto verror; 1576 if (nid.ni_vp->v_type != VREG || va.va_size != sizeof data) { 1577 error = EFTYPE; 1578 goto verror; 1579 } 1580 1581 /* 1582 * Check that a lock is held on the file (hopefully by ypbind), 1583 * otherwise the file might be old 1584 */ 1585 fl.l_start = 0; 1586 fl.l_len = 0; 1587 fl.l_pid = 0; 1588 fl.l_type = F_WRLCK; 1589 fl.l_whence = SEEK_SET; 1590 error = VOP_ADVLOCK(nid.ni_vp, fdp, F_GETLK, &fl, F_POSIX); 1591 if (error) 1592 goto verror; 1593 if (fl.l_type == F_UNLCK) { 1594 error = EOWNERDEAD; 1595 goto verror; 1596 } 1597 1598 iov.iov_base = &data; 1599 iov.iov_len = sizeof data; 1600 uio.uio_iov = &iov; 1601 uio.uio_iovcnt = 1; 1602 uio.uio_offset = 0; 1603 uio.uio_resid = iov.iov_len; 1604 uio.uio_segflg = UIO_SYSSPACE; 1605 uio.uio_rw = UIO_READ; 1606 uio.uio_procp = p; 1607 1608 error = VOP_READ(nid.ni_vp, &uio, 0, p->p_ucred); 1609 if (error) { 1610 verror: 1611 if (nid.ni_vp) 1612 vput(nid.ni_vp); 1613 out: 1614 KERNEL_UNLOCK(); 1615 return (error); 1616 } 1617 vput(nid.ni_vp); 1618 KERNEL_UNLOCK(); 1619 1620 bzero(&ypsin, sizeof ypsin); 1621 ypsin.sin_len = sizeof ypsin; 1622 ypsin.sin_family = AF_INET; 1623 if (SCARG(uap, type) == SOCK_STREAM) 1624 ypsin.sin_port = data.ypserv_tcp_port; 1625 else 1626 ypsin.sin_port = data.ypserv_udp_port; 1627 if (ntohs(ypsin.sin_port) >= IPPORT_RESERVED || ntohs(ypsin.sin_port) == 20) 1628 return EPERM; 1629 memcpy(&ypsin.sin_addr.s_addr, &data.in, sizeof ypsin.sin_addr.s_addr); 1630 1631 error = socreate(AF_INET, &so, SCARG(uap, type), 0); 1632 if (error) 1633 return (error); 1634 1635 error = ypsockargs(&nam, &ypsin, sizeof ypsin, MT_SONAME); 1636 if (error) { 1637 soclose(so, MSG_DONTWAIT); 1638 return (error); 1639 } 1640 1641 #ifdef KTRACE 1642 if (KTRPOINT(p, KTR_STRUCT)) 1643 ktrsockaddr(p, mtod(nam, caddr_t), sizeof(struct sockaddr_in)); 1644 #endif 1645 solock(so); 1646 1647 /* Secure YP maps require reserved ports */ 1648 if (suser(p) == 0) 1649 sotoinpcb(so)->inp_flags |= INP_LOWPORT; 1650 1651 error = soconnect(so, nam); 1652 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 1653 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH, 1654 "ypcon", INFSLP); 1655 if (error) 1656 break; 1657 } 1658 m_freem(nam); 1659 so->so_state |= SS_YP; /* impose some restrictions */ 1660 sounlock(so); 1661 if (error) { 1662 soclose(so, MSG_DONTWAIT); 1663 return (error); 1664 } 1665 1666 fdplock(fdp); 1667 error = falloc(p, &fp, &fd); 1668 if (error) { 1669 fdpunlock(fdp); 1670 soclose(so, MSG_DONTWAIT); 1671 return (error); 1672 } 1673 1674 fp->f_flag = FREAD | FWRITE | FNONBLOCK; 1675 fp->f_type = DTYPE_SOCKET; 1676 fp->f_ops = &socketops; 1677 fp->f_data = so; 1678 fdinsert(fdp, fd, UF_EXCLOSE, fp); 1679 fdpunlock(fdp); 1680 FRELE(fp, p); 1681 *retval = fd; 1682 return (error); 1683 #endif /* SMALL_KERNEL */ 1684 } 1685