1 /* $OpenBSD: uipc_syscalls.c,v 1.186 2020/06/10 13:24:57 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/proc.h> 39 #include <sys/fcntl.h> 40 #include <sys/file.h> 41 #include <sys/ioctl.h> 42 #include <sys/malloc.h> 43 #include <sys/event.h> 44 #include <sys/mbuf.h> 45 #include <sys/protosw.h> 46 #include <sys/socket.h> 47 #include <sys/socketvar.h> 48 #include <sys/signalvar.h> 49 #include <sys/pledge.h> 50 #include <sys/unpcb.h> 51 #include <sys/un.h> 52 #ifdef KTRACE 53 #include <sys/ktrace.h> 54 #endif 55 56 #include <sys/mount.h> 57 #include <sys/syscallargs.h> 58 59 #include <sys/domain.h> 60 #include <netinet/in.h> 61 #include <net/route.h> 62 63 int copyaddrout(struct proc *, struct mbuf *, struct sockaddr *, socklen_t, 64 socklen_t *); 65 66 int 67 sys_socket(struct proc *p, void *v, register_t *retval) 68 { 69 struct sys_socket_args /* { 70 syscallarg(int) domain; 71 syscallarg(int) type; 72 syscallarg(int) protocol; 73 } */ *uap = v; 74 struct filedesc *fdp = p->p_fd; 75 struct socket *so; 76 struct file *fp; 77 int type = SCARG(uap, type); 78 int domain = SCARG(uap, domain); 79 int fd, cloexec, nonblock, fflag, error; 80 unsigned int ss = 0; 81 82 if ((type & SOCK_DNS) && !(domain == AF_INET || domain == AF_INET6)) 83 return (EINVAL); 84 85 if (ISSET(type, SOCK_DNS)) 86 ss |= SS_DNS; 87 error = pledge_socket(p, domain, ss); 88 if (error) 89 return (error); 90 91 type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_DNS); 92 cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0; 93 nonblock = SCARG(uap, type) & SOCK_NONBLOCK; 94 fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0); 95 96 error = socreate(SCARG(uap, domain), &so, type, SCARG(uap, protocol)); 97 if (error) 98 return (error); 99 100 fdplock(fdp); 101 error = falloc(p, &fp, &fd); 102 if (error) { 103 fdpunlock(fdp); 104 soclose(so, MSG_DONTWAIT); 105 } else { 106 fp->f_flag = fflag; 107 fp->f_type = DTYPE_SOCKET; 108 fp->f_ops = &socketops; 109 so->so_state |= ss; 110 fp->f_data = so; 111 fdinsert(fdp, fd, cloexec, fp); 112 fdpunlock(fdp); 113 FRELE(fp, p); 114 *retval = fd; 115 } 116 return (error); 117 } 118 119 static inline int 120 isdnssocket(struct socket *so) 121 { 122 return (so->so_state & SS_DNS); 123 } 124 125 /* For SS_DNS sockets, only allow port DNS (port 53) */ 126 static int 127 dns_portcheck(struct proc *p, struct socket *so, void *nam, u_int *namelen) 128 { 129 int error = EINVAL; 130 131 switch (so->so_proto->pr_domain->dom_family) { 132 case AF_INET: 133 if (*namelen < sizeof(struct sockaddr_in)) 134 break; 135 if (((struct sockaddr_in *)nam)->sin_port == htons(53)) 136 error = 0; 137 break; 138 #ifdef INET6 139 case AF_INET6: 140 if (*namelen < sizeof(struct sockaddr_in6)) 141 break; 142 if (((struct sockaddr_in6 *)nam)->sin6_port == htons(53)) 143 error = 0; 144 #endif 145 } 146 if (error && p->p_p->ps_flags & PS_PLEDGE) 147 return (pledge_fail(p, EPERM, PLEDGE_DNS)); 148 return error; 149 } 150 151 int 152 sys_bind(struct proc *p, void *v, register_t *retval) 153 { 154 struct sys_bind_args /* { 155 syscallarg(int) s; 156 syscallarg(const struct sockaddr *) name; 157 syscallarg(socklen_t) namelen; 158 } */ *uap = v; 159 struct file *fp; 160 struct mbuf *nam; 161 struct socket *so; 162 int s, error; 163 164 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 165 return (error); 166 so = fp->f_data; 167 error = pledge_socket(p, so->so_proto->pr_domain->dom_family, 168 so->so_state); 169 if (error) 170 goto out; 171 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 172 MT_SONAME); 173 if (error) 174 goto out; 175 #ifdef KTRACE 176 if (KTRPOINT(p, KTR_STRUCT)) 177 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen)); 178 #endif 179 s = solock(so); 180 error = sobind(so, nam, p); 181 sounlock(so, s); 182 m_freem(nam); 183 out: 184 FRELE(fp, p); 185 return (error); 186 } 187 188 int 189 sys_listen(struct proc *p, void *v, register_t *retval) 190 { 191 struct sys_listen_args /* { 192 syscallarg(int) s; 193 syscallarg(int) backlog; 194 } */ *uap = v; 195 struct file *fp; 196 struct socket *so; 197 int error; 198 199 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 200 return (error); 201 so = fp->f_data; 202 error = solisten(so, SCARG(uap, backlog)); 203 FRELE(fp, p); 204 return (error); 205 } 206 207 int 208 sys_accept(struct proc *p, void *v, register_t *retval) 209 { 210 struct sys_accept_args /* { 211 syscallarg(int) s; 212 syscallarg(struct sockaddr *) name; 213 syscallarg(socklen_t *) anamelen; 214 } */ *uap = v; 215 216 return (doaccept(p, SCARG(uap, s), SCARG(uap, name), 217 SCARG(uap, anamelen), SOCK_NONBLOCK_INHERIT, retval)); 218 } 219 220 int 221 sys_accept4(struct proc *p, void *v, register_t *retval) 222 { 223 struct sys_accept4_args /* { 224 syscallarg(int) s; 225 syscallarg(struct sockaddr *) name; 226 syscallarg(socklen_t *) anamelen; 227 syscallarg(socklen_t *) int flags; 228 } */ *uap = v; 229 230 if (SCARG(uap, flags) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 231 return (EINVAL); 232 233 return (doaccept(p, SCARG(uap, s), SCARG(uap, name), 234 SCARG(uap, anamelen), SCARG(uap, flags), retval)); 235 } 236 237 int 238 doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen, 239 int flags, register_t *retval) 240 { 241 struct filedesc *fdp = p->p_fd; 242 struct file *fp, *headfp; 243 struct mbuf *nam; 244 socklen_t namelen; 245 int error, s, tmpfd; 246 struct socket *head, *so; 247 int cloexec, nflag; 248 249 cloexec = (flags & SOCK_CLOEXEC) ? UF_EXCLOSE : 0; 250 251 if (name && (error = copyin(anamelen, &namelen, sizeof (namelen)))) 252 return (error); 253 if ((error = getsock(p, sock, &fp)) != 0) 254 return (error); 255 256 headfp = fp; 257 258 fdplock(fdp); 259 error = falloc(p, &fp, &tmpfd); 260 fdpunlock(fdp); 261 if (error) { 262 FRELE(headfp, p); 263 return (error); 264 } 265 266 nam = m_get(M_WAIT, MT_SONAME); 267 268 head = headfp->f_data; 269 s = solock(head); 270 if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) { 271 error = EINVAL; 272 goto out; 273 } 274 if ((headfp->f_flag & FNONBLOCK) && head->so_qlen == 0) { 275 if (head->so_state & SS_CANTRCVMORE) 276 error = ECONNABORTED; 277 else 278 error = EWOULDBLOCK; 279 goto out; 280 } 281 while (head->so_qlen == 0 && head->so_error == 0) { 282 if (head->so_state & SS_CANTRCVMORE) { 283 head->so_error = ECONNABORTED; 284 break; 285 } 286 error = sosleep_nsec(head, &head->so_timeo, PSOCK | PCATCH, 287 "netcon", INFSLP); 288 if (error) 289 goto out; 290 } 291 if (head->so_error) { 292 error = head->so_error; 293 head->so_error = 0; 294 goto out; 295 } 296 297 /* 298 * Do not sleep after we have taken the socket out of the queue. 299 */ 300 so = TAILQ_FIRST(&head->so_q); 301 if (soqremque(so, 1) == 0) 302 panic("accept"); 303 304 /* Figure out whether the new socket should be non-blocking. */ 305 nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK) 306 : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0); 307 308 /* connection has been removed from the listen queue */ 309 KNOTE(&head->so_rcv.sb_sel.si_note, NOTE_SUBMIT); 310 311 fp->f_type = DTYPE_SOCKET; 312 fp->f_flag = FREAD | FWRITE | nflag; 313 fp->f_ops = &socketops; 314 fp->f_data = so; 315 error = soaccept(so, nam); 316 if (!error && name != NULL) 317 error = copyaddrout(p, nam, name, namelen, anamelen); 318 out: 319 if (!error) { 320 sounlock(head, s); 321 fdplock(fdp); 322 fdinsert(fdp, tmpfd, cloexec, fp); 323 fdpunlock(fdp); 324 FRELE(fp, p); 325 *retval = tmpfd; 326 } else { 327 sounlock(head, s); 328 fdplock(fdp); 329 fdremove(fdp, tmpfd); 330 fdpunlock(fdp); 331 closef(fp, p); 332 } 333 334 m_freem(nam); 335 FRELE(headfp, p); 336 return (error); 337 } 338 339 int 340 sys_connect(struct proc *p, void *v, register_t *retval) 341 { 342 struct sys_connect_args /* { 343 syscallarg(int) s; 344 syscallarg(const struct sockaddr *) name; 345 syscallarg(socklen_t) namelen; 346 } */ *uap = v; 347 struct file *fp; 348 struct socket *so; 349 struct mbuf *nam = NULL; 350 int error, s, interrupted = 0; 351 352 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 353 return (error); 354 so = fp->f_data; 355 s = solock(so); 356 if (so->so_state & SS_ISCONNECTING) { 357 error = EALREADY; 358 goto out; 359 } 360 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 361 MT_SONAME); 362 if (error) 363 goto out; 364 error = pledge_socket(p, so->so_proto->pr_domain->dom_family, 365 so->so_state); 366 if (error) 367 goto out; 368 #ifdef KTRACE 369 if (KTRPOINT(p, KTR_STRUCT)) 370 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen)); 371 #endif 372 373 if (isdnssocket(so)) { 374 u_int namelen = nam->m_len; 375 error = dns_portcheck(p, so, mtod(nam, void *), &namelen); 376 if (error) 377 goto out; 378 nam->m_len = namelen; 379 } 380 381 error = soconnect(so, nam); 382 if (error) 383 goto bad; 384 if ((fp->f_flag & FNONBLOCK) && (so->so_state & SS_ISCONNECTING)) { 385 error = EINPROGRESS; 386 goto out; 387 } 388 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 389 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH, 390 "netcon2", INFSLP); 391 if (error) { 392 if (error == EINTR || error == ERESTART) 393 interrupted = 1; 394 break; 395 } 396 } 397 if (error == 0) { 398 error = so->so_error; 399 so->so_error = 0; 400 } 401 bad: 402 if (!interrupted) 403 so->so_state &= ~SS_ISCONNECTING; 404 out: 405 sounlock(so, s); 406 FRELE(fp, p); 407 m_freem(nam); 408 if (error == ERESTART) 409 error = EINTR; 410 return (error); 411 } 412 413 int 414 sys_socketpair(struct proc *p, void *v, register_t *retval) 415 { 416 struct sys_socketpair_args /* { 417 syscallarg(int) domain; 418 syscallarg(int) type; 419 syscallarg(int) protocol; 420 syscallarg(int *) rsv; 421 } */ *uap = v; 422 struct filedesc *fdp = p->p_fd; 423 struct file *fp1 = NULL, *fp2 = NULL; 424 struct socket *so1, *so2; 425 int type, cloexec, nonblock, fflag, error, sv[2]; 426 427 type = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); 428 cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0; 429 nonblock = SCARG(uap, type) & SOCK_NONBLOCK; 430 fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0); 431 432 error = socreate(SCARG(uap, domain), &so1, type, SCARG(uap, protocol)); 433 if (error) 434 return (error); 435 error = socreate(SCARG(uap, domain), &so2, type, SCARG(uap, protocol)); 436 if (error) 437 goto free1; 438 439 error = soconnect2(so1, so2); 440 if (error != 0) 441 goto free2; 442 443 if ((SCARG(uap, type) & SOCK_TYPE_MASK) == SOCK_DGRAM) { 444 /* 445 * Datagram socket connection is asymmetric. 446 */ 447 error = soconnect2(so2, so1); 448 if (error != 0) 449 goto free2; 450 } 451 fdplock(fdp); 452 if ((error = falloc(p, &fp1, &sv[0])) != 0) 453 goto free3; 454 fp1->f_flag = fflag; 455 fp1->f_type = DTYPE_SOCKET; 456 fp1->f_ops = &socketops; 457 fp1->f_data = so1; 458 if ((error = falloc(p, &fp2, &sv[1])) != 0) 459 goto free4; 460 fp2->f_flag = fflag; 461 fp2->f_type = DTYPE_SOCKET; 462 fp2->f_ops = &socketops; 463 fp2->f_data = so2; 464 error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int)); 465 if (error == 0) { 466 #ifdef KTRACE 467 if (KTRPOINT(p, KTR_STRUCT)) 468 ktrfds(p, sv, 2); 469 #endif 470 fdinsert(fdp, sv[0], cloexec, fp1); 471 fdinsert(fdp, sv[1], cloexec, fp2); 472 fdpunlock(fdp); 473 FRELE(fp1, p); 474 FRELE(fp2, p); 475 return (0); 476 } 477 fdremove(fdp, sv[1]); 478 free4: 479 fdremove(fdp, sv[0]); 480 free3: 481 fdpunlock(fdp); 482 483 if (fp2 != NULL) { 484 closef(fp2, p); 485 so2 = NULL; 486 } 487 if (fp1 != NULL) { 488 closef(fp1, p); 489 so1 = NULL; 490 } 491 free2: 492 if (so2 != NULL) 493 (void)soclose(so2, 0); 494 free1: 495 if (so1 != NULL) 496 (void)soclose(so1, 0); 497 return (error); 498 } 499 500 int 501 sys_sendto(struct proc *p, void *v, register_t *retval) 502 { 503 struct sys_sendto_args /* { 504 syscallarg(int) s; 505 syscallarg(const void *) buf; 506 syscallarg(size_t) len; 507 syscallarg(int) flags; 508 syscallarg(const struct sockaddr *) to; 509 syscallarg(socklen_t) tolen; 510 } */ *uap = v; 511 struct msghdr msg; 512 struct iovec aiov; 513 514 msg.msg_name = (caddr_t)SCARG(uap, to); 515 msg.msg_namelen = SCARG(uap, tolen); 516 msg.msg_iov = &aiov; 517 msg.msg_iovlen = 1; 518 msg.msg_control = 0; 519 msg.msg_flags = 0; 520 aiov.iov_base = (char *)SCARG(uap, buf); 521 aiov.iov_len = SCARG(uap, len); 522 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); 523 } 524 525 int 526 sys_sendmsg(struct proc *p, void *v, register_t *retval) 527 { 528 struct sys_sendmsg_args /* { 529 syscallarg(int) s; 530 syscallarg(const struct msghdr *) msg; 531 syscallarg(int) flags; 532 } */ *uap = v; 533 struct msghdr msg; 534 struct iovec aiov[UIO_SMALLIOV], *iov; 535 int error; 536 537 error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); 538 if (error) 539 return (error); 540 #ifdef KTRACE 541 if (KTRPOINT(p, KTR_STRUCT)) 542 ktrmsghdr(p, &msg); 543 #endif 544 545 if (msg.msg_iovlen > IOV_MAX) 546 return (EMSGSIZE); 547 if (msg.msg_iovlen > UIO_SMALLIOV) 548 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec), 549 M_IOV, M_WAITOK); 550 else 551 iov = aiov; 552 if (msg.msg_iovlen && 553 (error = copyin(msg.msg_iov, iov, 554 msg.msg_iovlen * sizeof (struct iovec)))) 555 goto done; 556 #ifdef KTRACE 557 if (msg.msg_iovlen && KTRPOINT(p, KTR_STRUCT)) 558 ktriovec(p, iov, msg.msg_iovlen); 559 #endif 560 msg.msg_iov = iov; 561 msg.msg_flags = 0; 562 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 563 done: 564 if (iov != aiov) 565 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen); 566 return (error); 567 } 568 569 int 570 sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize) 571 { 572 struct file *fp; 573 struct uio auio; 574 struct iovec *iov; 575 int i; 576 struct mbuf *to, *control; 577 struct socket *so; 578 size_t len; 579 int error; 580 #ifdef KTRACE 581 struct iovec *ktriov = NULL; 582 int iovlen = 0; 583 #endif 584 585 to = NULL; 586 587 if ((error = getsock(p, s, &fp)) != 0) 588 return (error); 589 so = fp->f_data; 590 if (fp->f_flag & FNONBLOCK) 591 flags |= MSG_DONTWAIT; 592 593 error = pledge_sendit(p, mp->msg_name); 594 if (error) 595 goto bad; 596 597 auio.uio_iov = mp->msg_iov; 598 auio.uio_iovcnt = mp->msg_iovlen; 599 auio.uio_segflg = UIO_USERSPACE; 600 auio.uio_rw = UIO_WRITE; 601 auio.uio_procp = p; 602 auio.uio_offset = 0; /* XXX */ 603 auio.uio_resid = 0; 604 iov = mp->msg_iov; 605 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 606 /* Don't allow sum > SSIZE_MAX */ 607 if (iov->iov_len > SSIZE_MAX || 608 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { 609 error = EINVAL; 610 goto bad; 611 } 612 } 613 if (mp->msg_name) { 614 error = sockargs(&to, mp->msg_name, mp->msg_namelen, 615 MT_SONAME); 616 if (error) 617 goto bad; 618 if (isdnssocket(so)) { 619 u_int namelen = mp->msg_namelen; 620 error = dns_portcheck(p, so, mtod(to, caddr_t), 621 &namelen); 622 if (error) 623 goto bad; 624 mp->msg_namelen = namelen; 625 } 626 #ifdef KTRACE 627 if (KTRPOINT(p, KTR_STRUCT)) 628 ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen); 629 #endif 630 } 631 if (mp->msg_control) { 632 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) { 633 error = EINVAL; 634 goto bad; 635 } 636 error = sockargs(&control, mp->msg_control, 637 mp->msg_controllen, MT_CONTROL); 638 if (error) 639 goto bad; 640 #ifdef KTRACE 641 if (KTRPOINT(p, KTR_STRUCT) && mp->msg_controllen) 642 ktrcmsghdr(p, mtod(control, char *), 643 mp->msg_controllen); 644 #endif 645 } else 646 control = 0; 647 #ifdef KTRACE 648 if (KTRPOINT(p, KTR_GENIO)) { 649 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec), 650 M_TEMP, M_WAITOK); 651 iovlen = auio.uio_iovcnt * sizeof (struct iovec); 652 653 memcpy(ktriov, auio.uio_iov, iovlen); 654 } 655 #endif 656 len = auio.uio_resid; 657 error = sosend(so, to, &auio, NULL, control, flags); 658 if (error) { 659 if (auio.uio_resid != len && (error == ERESTART || 660 error == EINTR || error == EWOULDBLOCK)) 661 error = 0; 662 if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) { 663 KERNEL_LOCK(); 664 ptsignal(p, SIGPIPE, STHREAD); 665 KERNEL_UNLOCK(); 666 } 667 } 668 if (error == 0) { 669 *retsize = len - auio.uio_resid; 670 mtx_enter(&fp->f_mtx); 671 fp->f_wxfer++; 672 fp->f_wbytes += *retsize; 673 mtx_leave(&fp->f_mtx); 674 } 675 #ifdef KTRACE 676 if (ktriov != NULL) { 677 if (error == 0) 678 ktrgenio(p, s, UIO_WRITE, ktriov, *retsize); 679 free(ktriov, M_TEMP, iovlen); 680 } 681 #endif 682 bad: 683 FRELE(fp, p); 684 m_freem(to); 685 return (error); 686 } 687 688 int 689 sys_recvfrom(struct proc *p, void *v, register_t *retval) 690 { 691 struct sys_recvfrom_args /* { 692 syscallarg(int) s; 693 syscallarg(void *) buf; 694 syscallarg(size_t) len; 695 syscallarg(int) flags; 696 syscallarg(struct sockaddr *) from; 697 syscallarg(socklen_t *) fromlenaddr; 698 } */ *uap = v; 699 struct msghdr msg; 700 struct iovec aiov; 701 int error; 702 703 if (SCARG(uap, fromlenaddr)) { 704 error = copyin(SCARG(uap, fromlenaddr), 705 &msg.msg_namelen, sizeof (msg.msg_namelen)); 706 if (error) 707 return (error); 708 } else 709 msg.msg_namelen = 0; 710 msg.msg_name = (caddr_t)SCARG(uap, from); 711 msg.msg_iov = &aiov; 712 msg.msg_iovlen = 1; 713 aiov.iov_base = SCARG(uap, buf); 714 aiov.iov_len = SCARG(uap, len); 715 msg.msg_control = 0; 716 msg.msg_flags = SCARG(uap, flags); 717 return (recvit(p, SCARG(uap, s), &msg, 718 (caddr_t)SCARG(uap, fromlenaddr), retval)); 719 } 720 721 int 722 sys_recvmsg(struct proc *p, void *v, register_t *retval) 723 { 724 struct sys_recvmsg_args /* { 725 syscallarg(int) s; 726 syscallarg(struct msghdr *) msg; 727 syscallarg(int) flags; 728 } */ *uap = v; 729 struct msghdr msg; 730 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 731 int error; 732 733 error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); 734 if (error) 735 return (error); 736 737 if (msg.msg_iovlen > IOV_MAX) 738 return (EMSGSIZE); 739 if (msg.msg_iovlen > UIO_SMALLIOV) 740 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec), 741 M_IOV, M_WAITOK); 742 else 743 iov = aiov; 744 msg.msg_flags = SCARG(uap, flags); 745 if (msg.msg_iovlen > 0) { 746 error = copyin(msg.msg_iov, iov, 747 msg.msg_iovlen * sizeof(struct iovec)); 748 if (error) 749 goto done; 750 } 751 uiov = msg.msg_iov; 752 msg.msg_iov = iov; 753 if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) { 754 msg.msg_iov = uiov; 755 #ifdef KTRACE 756 if (KTRPOINT(p, KTR_STRUCT)) { 757 ktrmsghdr(p, &msg); 758 if (msg.msg_iovlen) 759 ktriovec(p, iov, msg.msg_iovlen); 760 } 761 #endif 762 error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); 763 } 764 done: 765 if (iov != aiov) 766 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen); 767 return (error); 768 } 769 770 int 771 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp, 772 register_t *retsize) 773 { 774 struct file *fp; 775 struct uio auio; 776 struct iovec *iov; 777 int i; 778 size_t len; 779 int error; 780 struct mbuf *from = NULL, *control = NULL; 781 #ifdef KTRACE 782 struct iovec *ktriov = NULL; 783 int iovlen = 0; 784 #endif 785 786 if ((error = getsock(p, s, &fp)) != 0) 787 return (error); 788 789 auio.uio_iov = mp->msg_iov; 790 auio.uio_iovcnt = mp->msg_iovlen; 791 auio.uio_segflg = UIO_USERSPACE; 792 auio.uio_rw = UIO_READ; 793 auio.uio_procp = p; 794 auio.uio_offset = 0; /* XXX */ 795 auio.uio_resid = 0; 796 iov = mp->msg_iov; 797 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 798 /* Don't allow sum > SSIZE_MAX */ 799 if (iov->iov_len > SSIZE_MAX || 800 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { 801 error = EINVAL; 802 goto out; 803 } 804 } 805 #ifdef KTRACE 806 if (KTRPOINT(p, KTR_GENIO)) { 807 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec), 808 M_TEMP, M_WAITOK); 809 iovlen = auio.uio_iovcnt * sizeof (struct iovec); 810 811 memcpy(ktriov, auio.uio_iov, iovlen); 812 } 813 #endif 814 len = auio.uio_resid; 815 if (fp->f_flag & FNONBLOCK) 816 mp->msg_flags |= MSG_DONTWAIT; 817 error = soreceive(fp->f_data, &from, &auio, NULL, 818 mp->msg_control ? &control : NULL, 819 &mp->msg_flags, 820 mp->msg_control ? mp->msg_controllen : 0); 821 if (error) { 822 if (auio.uio_resid != len && (error == ERESTART || 823 error == EINTR || error == EWOULDBLOCK)) 824 error = 0; 825 } 826 #ifdef KTRACE 827 if (ktriov != NULL) { 828 if (error == 0) 829 ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid); 830 free(ktriov, M_TEMP, iovlen); 831 } 832 #endif 833 if (error) 834 goto out; 835 *retsize = len - auio.uio_resid; 836 if (mp->msg_name) { 837 socklen_t alen; 838 839 if (from == NULL) 840 alen = 0; 841 else { 842 alen = from->m_len; 843 error = copyout(mtod(from, caddr_t), mp->msg_name, 844 MIN(alen, mp->msg_namelen)); 845 if (error) 846 goto out; 847 #ifdef KTRACE 848 if (KTRPOINT(p, KTR_STRUCT)) 849 ktrsockaddr(p, mtod(from, caddr_t), alen); 850 #endif 851 } 852 mp->msg_namelen = alen; 853 if (namelenp && 854 (error = copyout(&alen, namelenp, sizeof(alen)))) { 855 goto out; 856 } 857 } 858 if (mp->msg_control) { 859 len = mp->msg_controllen; 860 if (len <= 0 || control == NULL) 861 len = 0; 862 else { 863 struct mbuf *m = control; 864 caddr_t cp = mp->msg_control; 865 866 do { 867 i = m->m_len; 868 if (len < i) { 869 mp->msg_flags |= MSG_CTRUNC; 870 i = len; 871 } 872 error = copyout(mtod(m, caddr_t), cp, i); 873 #ifdef KTRACE 874 if (KTRPOINT(p, KTR_STRUCT) && error == 0 && i) 875 ktrcmsghdr(p, mtod(m, char *), i); 876 #endif 877 if (m->m_next) 878 i = ALIGN(i); 879 cp += i; 880 len -= i; 881 if (error != 0 || len <= 0) 882 break; 883 } while ((m = m->m_next) != NULL); 884 len = cp - (caddr_t)mp->msg_control; 885 } 886 mp->msg_controllen = len; 887 } 888 if (!error) { 889 mtx_enter(&fp->f_mtx); 890 fp->f_rxfer++; 891 fp->f_rbytes += *retsize; 892 mtx_leave(&fp->f_mtx); 893 } 894 out: 895 FRELE(fp, p); 896 m_freem(from); 897 m_freem(control); 898 return (error); 899 } 900 901 int 902 sys_shutdown(struct proc *p, void *v, register_t *retval) 903 { 904 struct sys_shutdown_args /* { 905 syscallarg(int) s; 906 syscallarg(int) how; 907 } */ *uap = v; 908 struct file *fp; 909 int error; 910 911 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 912 return (error); 913 error = soshutdown(fp->f_data, SCARG(uap, how)); 914 FRELE(fp, p); 915 return (error); 916 } 917 918 int 919 sys_setsockopt(struct proc *p, void *v, register_t *retval) 920 { 921 struct sys_setsockopt_args /* { 922 syscallarg(int) s; 923 syscallarg(int) level; 924 syscallarg(int) name; 925 syscallarg(const void *) val; 926 syscallarg(socklen_t) valsize; 927 } */ *uap = v; 928 struct file *fp; 929 struct mbuf *m = NULL; 930 struct socket *so; 931 int s, error; 932 933 934 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 935 return (error); 936 error = pledge_sockopt(p, 1, SCARG(uap, level), SCARG(uap, name)); 937 if (error) 938 goto bad; 939 if (SCARG(uap, valsize) > MCLBYTES) { 940 error = EINVAL; 941 goto bad; 942 } 943 if (SCARG(uap, val)) { 944 m = m_get(M_WAIT, MT_SOOPTS); 945 if (SCARG(uap, valsize) > MLEN) { 946 MCLGET(m, M_DONTWAIT); 947 if ((m->m_flags & M_EXT) == 0) { 948 error = ENOBUFS; 949 goto bad; 950 } 951 } 952 if (m == NULL) { 953 error = ENOBUFS; 954 goto bad; 955 } 956 error = copyin(SCARG(uap, val), mtod(m, caddr_t), 957 SCARG(uap, valsize)); 958 if (error) { 959 goto bad; 960 } 961 m->m_len = SCARG(uap, valsize); 962 } 963 so = fp->f_data; 964 s = solock(so); 965 error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m); 966 sounlock(so, s); 967 bad: 968 m_freem(m); 969 FRELE(fp, p); 970 return (error); 971 } 972 973 int 974 sys_getsockopt(struct proc *p, void *v, register_t *retval) 975 { 976 struct sys_getsockopt_args /* { 977 syscallarg(int) s; 978 syscallarg(int) level; 979 syscallarg(int) name; 980 syscallarg(void *) val; 981 syscallarg(socklen_t *) avalsize; 982 } */ *uap = v; 983 struct file *fp; 984 struct mbuf *m = NULL; 985 socklen_t valsize; 986 struct socket *so; 987 int s, error; 988 989 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) 990 return (error); 991 error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name)); 992 if (error) 993 goto out; 994 if (SCARG(uap, val)) { 995 error = copyin(SCARG(uap, avalsize), 996 &valsize, sizeof (valsize)); 997 if (error) 998 goto out; 999 } else 1000 valsize = 0; 1001 m = m_get(M_WAIT, MT_SOOPTS); 1002 so = fp->f_data; 1003 s = solock(so); 1004 error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m); 1005 sounlock(so, s); 1006 if (error == 0 && SCARG(uap, val) && valsize && m != NULL) { 1007 if (valsize > m->m_len) 1008 valsize = m->m_len; 1009 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize); 1010 if (error == 0) 1011 error = copyout(&valsize, 1012 SCARG(uap, avalsize), sizeof (valsize)); 1013 } 1014 m_free(m); 1015 out: 1016 FRELE(fp, p); 1017 return (error); 1018 } 1019 1020 /* 1021 * Get socket name. 1022 */ 1023 int 1024 sys_getsockname(struct proc *p, void *v, register_t *retval) 1025 { 1026 struct sys_getsockname_args /* { 1027 syscallarg(int) fdes; 1028 syscallarg(struct sockaddr *) asa; 1029 syscallarg(socklen_t *) alen; 1030 } */ *uap = v; 1031 struct file *fp; 1032 struct socket *so; 1033 struct mbuf *m = NULL; 1034 socklen_t len; 1035 int error, s; 1036 1037 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) 1038 return (error); 1039 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 1040 if (error) 1041 goto bad; 1042 so = fp->f_data; 1043 error = pledge_socket(p, -1, so->so_state); 1044 if (error) 1045 goto bad; 1046 m = m_getclr(M_WAIT, MT_SONAME); 1047 s = solock(so); 1048 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0, p); 1049 sounlock(so, s); 1050 if (error) 1051 goto bad; 1052 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); 1053 bad: 1054 FRELE(fp, p); 1055 m_freem(m); 1056 return (error); 1057 } 1058 1059 /* 1060 * Get name of peer for connected socket. 1061 */ 1062 int 1063 sys_getpeername(struct proc *p, void *v, register_t *retval) 1064 { 1065 struct sys_getpeername_args /* { 1066 syscallarg(int) fdes; 1067 syscallarg(struct sockaddr *) asa; 1068 syscallarg(socklen_t *) alen; 1069 } */ *uap = v; 1070 struct file *fp; 1071 struct socket *so; 1072 struct mbuf *m = NULL; 1073 socklen_t len; 1074 int error, s; 1075 1076 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0) 1077 return (error); 1078 so = fp->f_data; 1079 error = pledge_socket(p, -1, so->so_state); 1080 if (error) 1081 goto bad; 1082 if ((so->so_state & SS_ISCONNECTED) == 0) { 1083 error = ENOTCONN; 1084 goto bad; 1085 } 1086 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 1087 if (error) 1088 goto bad; 1089 m = m_getclr(M_WAIT, MT_SONAME); 1090 s = solock(so); 1091 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0, p); 1092 sounlock(so, s); 1093 if (error) 1094 goto bad; 1095 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen)); 1096 bad: 1097 FRELE(fp, p); 1098 m_freem(m); 1099 return (error); 1100 } 1101 1102 int 1103 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) 1104 { 1105 struct sockaddr *sa; 1106 struct mbuf *m; 1107 int error; 1108 1109 /* 1110 * We can't allow socket names > UCHAR_MAX in length, since that 1111 * will overflow sa_len. Also, control data more than MCLBYTES in 1112 * length is just too much. 1113 * Memory for sa_len and sa_family must exist. 1114 */ 1115 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) || 1116 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data))) 1117 return (EINVAL); 1118 1119 /* Allocate an mbuf to hold the arguments. */ 1120 m = m_get(M_WAIT, type); 1121 if (buflen > MLEN) { 1122 MCLGET(m, M_WAITOK); 1123 if ((m->m_flags & M_EXT) == 0) { 1124 m_free(m); 1125 return ENOBUFS; 1126 } 1127 } 1128 m->m_len = buflen; 1129 error = copyin(buf, mtod(m, caddr_t), buflen); 1130 if (error) { 1131 (void) m_free(m); 1132 return (error); 1133 } 1134 *mp = m; 1135 if (type == MT_SONAME) { 1136 sa = mtod(m, struct sockaddr *); 1137 sa->sa_len = buflen; 1138 } 1139 return (0); 1140 } 1141 1142 int 1143 getsock(struct proc *p, int fdes, struct file **fpp) 1144 { 1145 struct file *fp; 1146 1147 fp = fd_getfile(p->p_fd, fdes); 1148 if (fp == NULL) 1149 return (EBADF); 1150 if (fp->f_type != DTYPE_SOCKET) { 1151 FRELE(fp, p); 1152 return (ENOTSOCK); 1153 } 1154 *fpp = fp; 1155 1156 return (0); 1157 } 1158 1159 int 1160 sys_setrtable(struct proc *p, void *v, register_t *retval) 1161 { 1162 struct sys_setrtable_args /* { 1163 syscallarg(int) rtableid; 1164 } */ *uap = v; 1165 int rtableid, error; 1166 1167 rtableid = SCARG(uap, rtableid); 1168 1169 if (p->p_p->ps_rtableid == (u_int)rtableid) 1170 return (0); 1171 if (p->p_p->ps_rtableid != 0 && (error = suser(p)) != 0) 1172 return (error); 1173 if (rtableid < 0 || !rtable_exists((u_int)rtableid)) 1174 return (EINVAL); 1175 1176 p->p_p->ps_rtableid = (u_int)rtableid; 1177 return (0); 1178 } 1179 1180 int 1181 sys_getrtable(struct proc *p, void *v, register_t *retval) 1182 { 1183 *retval = (int)p->p_p->ps_rtableid; 1184 return (0); 1185 } 1186 1187 int 1188 copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa, 1189 socklen_t buflen, socklen_t *outlen) 1190 { 1191 int error; 1192 socklen_t namelen = name->m_len; 1193 1194 /* SHOULD COPY OUT A CHAIN HERE */ 1195 error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen)); 1196 if (error == 0) { 1197 #ifdef KTRACE 1198 if (KTRPOINT(p, KTR_STRUCT)) 1199 ktrsockaddr(p, mtod(name, caddr_t), namelen); 1200 #endif 1201 error = copyout(&namelen, outlen, sizeof(*outlen)); 1202 } 1203 1204 return (error); 1205 } 1206