uipc_syscalls.c revision 1.195
1/* $NetBSD: uipc_syscalls.c,v 1.195 2018/07/31 13:00:13 rjs Exp $ */ 2 3/*- 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * Copyright (c) 1982, 1986, 1989, 1990, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95 61 */ 62 63#include <sys/cdefs.h> 64__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.195 2018/07/31 13:00:13 rjs Exp $"); 65 66#ifdef _KERNEL_OPT 67#include "opt_pipe.h" 68#endif 69 70#define MBUFTYPES 71#include <sys/param.h> 72#include <sys/systm.h> 73#include <sys/filedesc.h> 74#include <sys/proc.h> 75#include <sys/file.h> 76#include <sys/buf.h> 77#include <sys/mbuf.h> 78#include <sys/protosw.h> 79#include <sys/socket.h> 80#include <sys/socketvar.h> 81#include <sys/signalvar.h> 82#include <sys/un.h> 83#include <sys/ktrace.h> 84#include <sys/event.h> 85#include <sys/atomic.h> 86#include <sys/kauth.h> 87 88#include <sys/mount.h> 89#include <sys/syscallargs.h> 90 91/* 92 * System call interface to the socket abstraction. 93 */ 94extern const struct fileops socketops; 95 96static int sockargs_sb(struct sockaddr_big *, const void *, socklen_t); 97 98int 99sys___socket30(struct lwp *l, const struct sys___socket30_args *uap, 100 register_t *retval) 101{ 102 /* { 103 syscallarg(int) domain; 104 syscallarg(int) type; 105 syscallarg(int) protocol; 106 } */ 107 int fd, error; 108 109 error = fsocreate(SCARG(uap, domain), NULL, SCARG(uap, type), 110 SCARG(uap, protocol), &fd); 111 if (error == 0) { 112 *retval = fd; 113 } 114 return error; 115} 116 117int 118sys_bind(struct lwp *l, const struct sys_bind_args *uap, register_t *retval) 119{ 120 /* { 121 syscallarg(int) s; 122 syscallarg(const struct sockaddr *) name; 123 syscallarg(unsigned int) namelen; 124 } */ 125 int error; 126 struct sockaddr_big sb; 127 128 error = sockargs_sb(&sb, SCARG(uap, name), SCARG(uap, namelen)); 129 if (error) 130 return error; 131 132 return do_sys_bind(l, SCARG(uap, s), (struct sockaddr *)&sb); 133} 134 135int 136do_sys_bind(struct lwp *l, int fd, struct sockaddr *nam) 137{ 138 struct socket *so; 139 int error; 140 141 if ((error = fd_getsock(fd, &so)) != 0) 142 return error; 143 error = sobind(so, nam, l); 144 fd_putfile(fd); 145 return error; 146} 147 148int 149sys_listen(struct lwp *l, const struct sys_listen_args *uap, register_t *retval) 150{ 151 /* { 152 syscallarg(int) s; 153 syscallarg(int) backlog; 154 } */ 155 struct socket *so; 156 int error; 157 158 if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) 159 return (error); 160 error = solisten(so, SCARG(uap, backlog), l); 161 fd_putfile(SCARG(uap, s)); 162 return error; 163} 164 165int 166do_sys_accept(struct lwp *l, int sock, struct sockaddr *name, 167 register_t *new_sock, const sigset_t *mask, int flags, int clrflags) 168{ 169 file_t *fp, *fp2; 170 int error, fd; 171 struct socket *so, *so2; 172 short wakeup_state = 0; 173 174 if ((fp = fd_getfile(sock)) == NULL) 175 return EBADF; 176 if (fp->f_type != DTYPE_SOCKET) { 177 fd_putfile(sock); 178 return ENOTSOCK; 179 } 180 if ((error = fd_allocfile(&fp2, &fd)) != 0) { 181 fd_putfile(sock); 182 return error; 183 } 184 *new_sock = fd; 185 so = fp->f_socket; 186 solock(so); 187 188 if (__predict_false(mask)) 189 sigsuspendsetup(l, mask); 190 191 if (!(so->so_proto->pr_flags & PR_LISTEN)) { 192 error = EOPNOTSUPP; 193 goto bad; 194 } 195 if ((so->so_options & SO_ACCEPTCONN) == 0) { 196 error = EINVAL; 197 goto bad; 198 } 199 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { 200 error = EWOULDBLOCK; 201 goto bad; 202 } 203 while (so->so_qlen == 0 && so->so_error == 0) { 204 if (so->so_state & SS_CANTRCVMORE) { 205 so->so_error = ECONNABORTED; 206 break; 207 } 208 if (wakeup_state & SS_RESTARTSYS) { 209 error = ERESTART; 210 goto bad; 211 } 212 error = sowait(so, true, 0); 213 if (error) { 214 goto bad; 215 } 216 wakeup_state = so->so_state; 217 } 218 if (so->so_error) { 219 error = so->so_error; 220 so->so_error = 0; 221 goto bad; 222 } 223 /* connection has been removed from the listen queue */ 224 KNOTE(&so->so_rcv.sb_sel.sel_klist, NOTE_SUBMIT); 225 so2 = TAILQ_FIRST(&so->so_q); 226 if (soqremque(so2, 1) == 0) 227 panic("accept"); 228 fp2->f_type = DTYPE_SOCKET; 229 fp2->f_flag = (fp->f_flag & ~clrflags) | 230 ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)| 231 ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0); 232 fp2->f_ops = &socketops; 233 fp2->f_socket = so2; 234 if (fp2->f_flag & FNONBLOCK) 235 so2->so_state |= SS_NBIO; 236 else 237 so2->so_state &= ~SS_NBIO; 238 error = soaccept(so2, name); 239 so2->so_cred = kauth_cred_dup(so->so_cred); 240 sounlock(so); 241 if (error) { 242 /* an error occurred, free the file descriptor and mbuf */ 243 mutex_enter(&fp2->f_lock); 244 fp2->f_count++; 245 mutex_exit(&fp2->f_lock); 246 closef(fp2); 247 fd_abort(curproc, NULL, fd); 248 } else { 249 fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0); 250 fd_affix(curproc, fp2, fd); 251 } 252 fd_putfile(sock); 253 if (__predict_false(mask)) 254 sigsuspendteardown(l); 255 return error; 256 bad: 257 sounlock(so); 258 fd_putfile(sock); 259 fd_abort(curproc, fp2, fd); 260 if (__predict_false(mask)) 261 sigsuspendteardown(l); 262 return error; 263} 264 265int 266sys_accept(struct lwp *l, const struct sys_accept_args *uap, register_t *retval) 267{ 268 /* { 269 syscallarg(int) s; 270 syscallarg(struct sockaddr *) name; 271 syscallarg(unsigned int *) anamelen; 272 } */ 273 int error, fd; 274 struct sockaddr_big name; 275 276 name.sb_len = UCHAR_MAX; 277 error = do_sys_accept(l, SCARG(uap, s), (struct sockaddr *)&name, 278 retval, NULL, 0, 0); 279 if (error != 0) 280 return error; 281 error = copyout_sockname_sb(SCARG(uap, name), SCARG(uap, anamelen), 282 MSG_LENUSRSPACE, &name); 283 if (error != 0) { 284 fd = (int)*retval; 285 if (fd_getfile(fd) != NULL) 286 (void)fd_close(fd); 287 } 288 return error; 289} 290 291int 292sys_paccept(struct lwp *l, const struct sys_paccept_args *uap, 293 register_t *retval) 294{ 295 /* { 296 syscallarg(int) s; 297 syscallarg(struct sockaddr *) name; 298 syscallarg(unsigned int *) anamelen; 299 syscallarg(const sigset_t *) mask; 300 syscallarg(int) flags; 301 } */ 302 int error, fd; 303 struct sockaddr_big name; 304 sigset_t *mask, amask; 305 306 if (SCARG(uap, mask) != NULL) { 307 error = copyin(SCARG(uap, mask), &amask, sizeof(amask)); 308 if (error) 309 return error; 310 mask = &amask; 311 } else 312 mask = NULL; 313 314 name.sb_len = UCHAR_MAX; 315 error = do_sys_accept(l, SCARG(uap, s), (struct sockaddr *)&name, 316 retval, mask, SCARG(uap, flags), FNONBLOCK); 317 if (error != 0) 318 return error; 319 error = copyout_sockname_sb(SCARG(uap, name), SCARG(uap, anamelen), 320 MSG_LENUSRSPACE, &name); 321 if (error != 0) { 322 fd = (int)*retval; 323 if (fd_getfile(fd) != NULL) 324 (void)fd_close(fd); 325 } 326 return error; 327} 328 329int 330sys_connect(struct lwp *l, const struct sys_connect_args *uap, 331 register_t *retval) 332{ 333 /* { 334 syscallarg(int) s; 335 syscallarg(const struct sockaddr *) name; 336 syscallarg(unsigned int) namelen; 337 } */ 338 int error; 339 struct sockaddr_big sbig; 340 341 error = sockargs_sb(&sbig, SCARG(uap, name), SCARG(uap, namelen)); 342 if (error) 343 return error; 344 return do_sys_connect(l, SCARG(uap, s), (struct sockaddr *)&sbig); 345} 346 347int 348do_sys_connect(struct lwp *l, int fd, struct sockaddr *nam) 349{ 350 struct socket *so; 351 int error; 352 int interrupted = 0; 353 354 if ((error = fd_getsock(fd, &so)) != 0) { 355 return (error); 356 } 357 solock(so); 358 if ((so->so_state & SS_ISCONNECTING) != 0) { 359 error = EALREADY; 360 goto out; 361 } 362 363 error = soconnect(so, nam, l); 364 if (error) 365 goto bad; 366 if ((so->so_state & (SS_NBIO|SS_ISCONNECTING)) == 367 (SS_NBIO|SS_ISCONNECTING)) { 368 error = EINPROGRESS; 369 goto out; 370 } 371 while ((so->so_state & SS_ISCONNECTING) != 0 && so->so_error == 0) { 372 error = sowait(so, true, 0); 373 if (__predict_false((so->so_state & SS_ISABORTING) != 0)) { 374 error = EPIPE; 375 interrupted = 1; 376 break; 377 } 378 if (error) { 379 if (error == EINTR || error == ERESTART) 380 interrupted = 1; 381 break; 382 } 383 } 384 if (error == 0) { 385 error = so->so_error; 386 so->so_error = 0; 387 } 388 bad: 389 if (!interrupted) 390 so->so_state &= ~SS_ISCONNECTING; 391 if (error == ERESTART) 392 error = EINTR; 393 out: 394 sounlock(so); 395 fd_putfile(fd); 396 return error; 397} 398 399static int 400makesocket(struct lwp *l, file_t **fp, int *fd, int flags, int type, 401 int domain, int proto, struct socket *soo) 402{ 403 struct socket *so; 404 int error; 405 406 if ((error = socreate(domain, &so, type, proto, l, soo)) != 0) { 407 return error; 408 } 409 if (flags & SOCK_NONBLOCK) { 410 so->so_state |= SS_NBIO; 411 } 412 413 if ((error = fd_allocfile(fp, fd)) != 0) { 414 soclose(so); 415 return error; 416 } 417 fd_set_exclose(l, *fd, (flags & SOCK_CLOEXEC) != 0); 418 (*fp)->f_flag = FREAD|FWRITE| 419 ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)| 420 ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0); 421 (*fp)->f_type = DTYPE_SOCKET; 422 (*fp)->f_ops = &socketops; 423 (*fp)->f_socket = so; 424 return 0; 425} 426 427int 428sys_socketpair(struct lwp *l, const struct sys_socketpair_args *uap, 429 register_t *retval) 430{ 431 /* { 432 syscallarg(int) domain; 433 syscallarg(int) type; 434 syscallarg(int) protocol; 435 syscallarg(int *) rsv; 436 } */ 437 file_t *fp1, *fp2; 438 struct socket *so1, *so2; 439 int fd, error, sv[2]; 440 proc_t *p = curproc; 441 int flags = SCARG(uap, type) & SOCK_FLAGS_MASK; 442 int type = SCARG(uap, type) & ~SOCK_FLAGS_MASK; 443 int domain = SCARG(uap, domain); 444 int proto = SCARG(uap, protocol); 445 446 error = makesocket(l, &fp1, &fd, flags, type, domain, proto, NULL); 447 if (error) 448 return error; 449 so1 = fp1->f_socket; 450 sv[0] = fd; 451 452 error = makesocket(l, &fp2, &fd, flags, type, domain, proto, so1); 453 if (error) 454 goto out; 455 so2 = fp2->f_socket; 456 sv[1] = fd; 457 458 solock(so1); 459 error = soconnect2(so1, so2); 460 if (error == 0 && type == SOCK_DGRAM) { 461 /* 462 * Datagram socket connection is asymmetric. 463 */ 464 error = soconnect2(so2, so1); 465 } 466 sounlock(so1); 467 468 if (error == 0) 469 error = copyout(sv, SCARG(uap, rsv), sizeof(sv)); 470 if (error == 0) { 471 fd_affix(p, fp2, sv[1]); 472 fd_affix(p, fp1, sv[0]); 473 return 0; 474 } 475 fd_abort(p, fp2, sv[1]); 476 (void)soclose(so2); 477out: 478 fd_abort(p, fp1, sv[0]); 479 (void)soclose(so1); 480 return error; 481} 482 483int 484sys_sendto(struct lwp *l, const struct sys_sendto_args *uap, 485 register_t *retval) 486{ 487 /* { 488 syscallarg(int) s; 489 syscallarg(const void *) buf; 490 syscallarg(size_t) len; 491 syscallarg(int) flags; 492 syscallarg(const struct sockaddr *) to; 493 syscallarg(unsigned int) tolen; 494 } */ 495 struct msghdr msg; 496 struct iovec aiov; 497 498 msg.msg_name = __UNCONST(SCARG(uap, to)); /* XXXUNCONST kills const */ 499 msg.msg_namelen = SCARG(uap, tolen); 500 msg.msg_iov = &aiov; 501 msg.msg_iovlen = 1; 502 msg.msg_control = NULL; 503 msg.msg_flags = 0; 504 aiov.iov_base = __UNCONST(SCARG(uap, buf)); /* XXXUNCONST kills const */ 505 aiov.iov_len = SCARG(uap, len); 506 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), 507 retval); 508} 509 510int 511sys_sendmsg(struct lwp *l, const struct sys_sendmsg_args *uap, 512 register_t *retval) 513{ 514 /* { 515 syscallarg(int) s; 516 syscallarg(const struct msghdr *) msg; 517 syscallarg(int) flags; 518 } */ 519 struct msghdr msg; 520 int error; 521 522 error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); 523 if (error) 524 return (error); 525 526 msg.msg_flags = MSG_IOVUSRSPACE; 527 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), 528 retval); 529} 530 531int 532do_sys_sendmsg_so(struct lwp *l, int s, struct socket *so, file_t *fp, 533 struct msghdr *mp, int flags, register_t *retsize) 534{ 535 536 struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL; 537 struct sockaddr *sa = NULL; 538 struct mbuf *to, *control; 539 struct uio auio; 540 size_t len, iovsz; 541 int i, error; 542 543 ktrkuser("msghdr", mp, sizeof(*mp)); 544 545 /* If the caller passed us stuff in mbufs, we must free them. */ 546 to = (mp->msg_flags & MSG_NAMEMBUF) ? mp->msg_name : NULL; 547 control = (mp->msg_flags & MSG_CONTROLMBUF) ? mp->msg_control : NULL; 548 iovsz = mp->msg_iovlen * sizeof(struct iovec); 549 550 if (mp->msg_flags & MSG_IOVUSRSPACE) { 551 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) { 552 if ((unsigned int)mp->msg_iovlen > IOV_MAX) { 553 error = EMSGSIZE; 554 goto bad; 555 } 556 iov = kmem_alloc(iovsz, KM_SLEEP); 557 } 558 if (mp->msg_iovlen != 0) { 559 error = copyin(mp->msg_iov, iov, iovsz); 560 if (error) 561 goto bad; 562 } 563 auio.uio_iov = iov; 564 } else 565 auio.uio_iov = mp->msg_iov; 566 567 auio.uio_iovcnt = mp->msg_iovlen; 568 auio.uio_rw = UIO_WRITE; 569 auio.uio_offset = 0; /* XXX */ 570 auio.uio_resid = 0; 571 KASSERT(l == curlwp); 572 auio.uio_vmspace = l->l_proc->p_vmspace; 573 574 tiov = auio.uio_iov; 575 for (i = 0; i < auio.uio_iovcnt; i++, tiov++) { 576 /* 577 * Writes return ssize_t because -1 is returned on error. 578 * Therefore, we must restrict the length to SSIZE_MAX to 579 * avoid garbage return values. 580 */ 581 auio.uio_resid += tiov->iov_len; 582 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { 583 error = EINVAL; 584 goto bad; 585 } 586 } 587 588 if (mp->msg_name && to == NULL) { 589 error = sockargs(&to, mp->msg_name, mp->msg_namelen, 590 UIO_USERSPACE, MT_SONAME); 591 if (error) 592 goto bad; 593 } 594 595 if (mp->msg_control) { 596 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) { 597 error = EINVAL; 598 goto bad; 599 } 600 if (control == NULL) { 601 error = sockargs(&control, mp->msg_control, 602 mp->msg_controllen, UIO_USERSPACE, MT_CONTROL); 603 if (error) 604 goto bad; 605 } 606 } 607 608 if (ktrpoint(KTR_GENIO) && iovsz > 0) { 609 ktriov = kmem_alloc(iovsz, KM_SLEEP); 610 memcpy(ktriov, auio.uio_iov, iovsz); 611 } 612 613 if (mp->msg_name) 614 MCLAIM(to, so->so_mowner); 615 if (mp->msg_control) 616 MCLAIM(control, so->so_mowner); 617 618 if (to) { 619 sa = mtod(to, struct sockaddr *); 620 } 621 622 len = auio.uio_resid; 623 error = (*so->so_send)(so, sa, &auio, NULL, control, flags, l); 624 /* Protocol is responsible for freeing 'control' */ 625 control = NULL; 626 627 if (error) { 628 if (auio.uio_resid != len && (error == ERESTART || 629 error == EINTR || error == EWOULDBLOCK)) 630 error = 0; 631 if (error == EPIPE && (fp->f_flag & FNOSIGPIPE) == 0 && 632 (flags & MSG_NOSIGNAL) == 0) { 633 mutex_enter(proc_lock); 634 psignal(l->l_proc, SIGPIPE); 635 mutex_exit(proc_lock); 636 } 637 } 638 if (error == 0) 639 *retsize = len - auio.uio_resid; 640 641bad: 642 if (ktriov != NULL) { 643 ktrgeniov(s, UIO_WRITE, ktriov, *retsize, error); 644 kmem_free(ktriov, iovsz); 645 } 646 647 if (iov != aiov) 648 kmem_free(iov, iovsz); 649 if (to) 650 m_freem(to); 651 if (control) 652 m_freem(control); 653 654 return error; 655} 656 657int 658do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags, 659 register_t *retsize) 660{ 661 int error; 662 struct socket *so; 663 file_t *fp; 664 665 if ((error = fd_getsock1(s, &so, &fp)) != 0) { 666 /* We have to free msg_name and msg_control ourselves */ 667 if (mp->msg_flags & MSG_NAMEMBUF) 668 m_freem(mp->msg_name); 669 if (mp->msg_flags & MSG_CONTROLMBUF) 670 m_freem(mp->msg_control); 671 return error; 672 } 673 error = do_sys_sendmsg_so(l, s, so, fp, mp, flags, retsize); 674 /* msg_name and msg_control freed */ 675 fd_putfile(s); 676 return error; 677} 678 679int 680sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap, 681 register_t *retval) 682{ 683 /* { 684 syscallarg(int) s; 685 syscallarg(void *) buf; 686 syscallarg(size_t) len; 687 syscallarg(int) flags; 688 syscallarg(struct sockaddr *) from; 689 syscallarg(unsigned int *) fromlenaddr; 690 } */ 691 struct msghdr msg; 692 struct iovec aiov; 693 int error; 694 struct mbuf *from; 695 696 msg.msg_name = NULL; 697 msg.msg_iov = &aiov; 698 msg.msg_iovlen = 1; 699 aiov.iov_base = SCARG(uap, buf); 700 aiov.iov_len = SCARG(uap, len); 701 msg.msg_control = NULL; 702 msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS; 703 704 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval); 705 if (error != 0) 706 return error; 707 708 error = copyout_sockname(SCARG(uap, from), SCARG(uap, fromlenaddr), 709 MSG_LENUSRSPACE, from); 710 if (from != NULL) 711 m_free(from); 712 return error; 713} 714 715int 716sys_recvmsg(struct lwp *l, const struct sys_recvmsg_args *uap, 717 register_t *retval) 718{ 719 /* { 720 syscallarg(int) s; 721 syscallarg(struct msghdr *) msg; 722 syscallarg(int) flags; 723 } */ 724 struct msghdr msg; 725 int error; 726 struct mbuf *from, *control; 727 728 error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); 729 if (error) 730 return error; 731 732 msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; 733 734 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, 735 msg.msg_control != NULL ? &control : NULL, retval); 736 if (error != 0) 737 return error; 738 739 if (msg.msg_control != NULL) 740 error = copyout_msg_control(l, &msg, control); 741 742 if (error == 0) 743 error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0, 744 from); 745 if (from != NULL) 746 m_free(from); 747 if (error == 0) { 748 ktrkuser("msghdr", &msg, sizeof(msg)); 749 error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); 750 } 751 752 return error; 753} 754 755int 756sys_sendmmsg(struct lwp *l, const struct sys_sendmmsg_args *uap, 757 register_t *retval) 758{ 759 /* { 760 syscallarg(int) s; 761 syscallarg(struct mmsghdr *) mmsg; 762 syscallarg(unsigned int) vlen; 763 syscallarg(unsigned int) flags; 764 } */ 765 struct mmsghdr mmsg; 766 struct socket *so; 767 file_t *fp; 768 struct msghdr *msg = &mmsg.msg_hdr; 769 int error, s; 770 unsigned int vlen, flags, dg; 771 772 s = SCARG(uap, s); 773 if ((error = fd_getsock1(s, &so, &fp)) != 0) 774 return error; 775 776 vlen = SCARG(uap, vlen); 777 if (vlen > 1024) 778 vlen = 1024; 779 780 flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; 781 782 for (dg = 0; dg < vlen;) { 783 error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg)); 784 if (error) 785 break; 786 787 msg->msg_flags = flags; 788 789 error = do_sys_sendmsg_so(l, s, so, fp, msg, flags, retval); 790 if (error) 791 break; 792 793 ktrkuser("msghdr", msg, sizeof(*msg)); 794 mmsg.msg_len = *retval; 795 error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg)); 796 if (error) 797 break; 798 dg++; 799 800 } 801 802 *retval = dg; 803 if (error) 804 so->so_error = error; 805 806 fd_putfile(s); 807 808 /* 809 * If we succeeded at least once, return 0, hopefully so->so_error 810 * will catch it next time. 811 */ 812 if (dg) 813 return 0; 814 return error; 815} 816 817/* 818 * Adjust for a truncated SCM_RIGHTS control message. 819 * This means closing any file descriptors that aren't present 820 * in the returned buffer. 821 * m is the mbuf holding the (already externalized) SCM_RIGHTS message. 822 */ 823static void 824free_rights(struct mbuf *m) 825{ 826 struct cmsghdr *cm; 827 int *fdv; 828 unsigned int nfds, i; 829 830 KASSERT(sizeof(*cm) <= m->m_len); 831 cm = mtod(m, struct cmsghdr *); 832 833 KASSERT(CMSG_ALIGN(sizeof(*cm)) <= cm->cmsg_len); 834 KASSERT(cm->cmsg_len <= m->m_len); 835 nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) / sizeof(int); 836 fdv = (int *)CMSG_DATA(cm); 837 838 for (i = 0; i < nfds; i++) 839 if (fd_getfile(fdv[i]) != NULL) 840 (void)fd_close(fdv[i]); 841} 842 843void 844free_control_mbuf(struct lwp *l, struct mbuf *control, struct mbuf *uncopied) 845{ 846 struct mbuf *next; 847 struct cmsghdr *cmsg; 848 bool do_free_rights = false; 849 850 while (control != NULL) { 851 cmsg = mtod(control, struct cmsghdr *); 852 if (control == uncopied) 853 do_free_rights = true; 854 if (do_free_rights && cmsg->cmsg_level == SOL_SOCKET 855 && cmsg->cmsg_type == SCM_RIGHTS) 856 free_rights(control); 857 next = control->m_next; 858 m_free(control); 859 control = next; 860 } 861} 862 863/* Copy socket control/CMSG data to user buffer, frees the mbuf */ 864int 865copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control) 866{ 867 int i, len, error = 0; 868 struct cmsghdr *cmsg; 869 struct mbuf *m; 870 char *q; 871 872 len = mp->msg_controllen; 873 if (len <= 0 || control == 0) { 874 mp->msg_controllen = 0; 875 free_control_mbuf(l, control, control); 876 return 0; 877 } 878 879 q = (char *)mp->msg_control; 880 881 for (m = control; m != NULL; ) { 882 cmsg = mtod(m, struct cmsghdr *); 883 i = m->m_len; 884 if (len < i) { 885 mp->msg_flags |= MSG_CTRUNC; 886 if (cmsg->cmsg_level == SOL_SOCKET 887 && cmsg->cmsg_type == SCM_RIGHTS) 888 /* Do not truncate me ... */ 889 break; 890 i = len; 891 } 892 error = copyout(mtod(m, void *), q, i); 893 ktrkuser(mbuftypes[MT_CONTROL], cmsg, cmsg->cmsg_len); 894 if (error != 0) { 895 /* We must free all the SCM_RIGHTS */ 896 m = control; 897 break; 898 } 899 m = m->m_next; 900 if (m) 901 i = ALIGN(i); 902 q += i; 903 len -= i; 904 if (len <= 0) 905 break; 906 } 907 908 free_control_mbuf(l, control, m); 909 910 mp->msg_controllen = q - (char *)mp->msg_control; 911 return error; 912} 913 914int 915do_sys_recvmsg_so(struct lwp *l, int s, struct socket *so, struct msghdr *mp, 916 struct mbuf **from, struct mbuf **control, register_t *retsize) 917{ 918 struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL; 919 struct uio auio; 920 size_t len, iovsz; 921 int i, error; 922 923 ktrkuser("msghdr", mp, sizeof(*mp)); 924 925 *from = NULL; 926 if (control != NULL) 927 *control = NULL; 928 929 iovsz = mp->msg_iovlen * sizeof(struct iovec); 930 931 if (mp->msg_flags & MSG_IOVUSRSPACE) { 932 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) { 933 if ((unsigned int)mp->msg_iovlen > IOV_MAX) { 934 error = EMSGSIZE; 935 goto out; 936 } 937 iov = kmem_alloc(iovsz, KM_SLEEP); 938 } 939 if (mp->msg_iovlen != 0) { 940 error = copyin(mp->msg_iov, iov, iovsz); 941 if (error) 942 goto out; 943 } 944 auio.uio_iov = iov; 945 } else 946 auio.uio_iov = mp->msg_iov; 947 auio.uio_iovcnt = mp->msg_iovlen; 948 auio.uio_rw = UIO_READ; 949 auio.uio_offset = 0; /* XXX */ 950 auio.uio_resid = 0; 951 KASSERT(l == curlwp); 952 auio.uio_vmspace = l->l_proc->p_vmspace; 953 954 tiov = auio.uio_iov; 955 for (i = 0; i < auio.uio_iovcnt; i++, tiov++) { 956 /* 957 * Reads return ssize_t because -1 is returned on error. 958 * Therefore we must restrict the length to SSIZE_MAX to 959 * avoid garbage return values. 960 */ 961 auio.uio_resid += tiov->iov_len; 962 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { 963 error = EINVAL; 964 goto out; 965 } 966 } 967 968 if (ktrpoint(KTR_GENIO) && iovsz > 0) { 969 ktriov = kmem_alloc(iovsz, KM_SLEEP); 970 memcpy(ktriov, auio.uio_iov, iovsz); 971 } 972 973 len = auio.uio_resid; 974 mp->msg_flags &= MSG_USERFLAGS; 975 error = (*so->so_receive)(so, from, &auio, NULL, control, 976 &mp->msg_flags); 977 KASSERT(*from == NULL || (*from)->m_next == NULL); 978 len -= auio.uio_resid; 979 *retsize = len; 980 if (error != 0 && len != 0 981 && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) 982 /* Some data transferred */ 983 error = 0; 984 985 if (ktriov != NULL) { 986 ktrgeniov(s, UIO_READ, ktriov, len, error); 987 kmem_free(ktriov, iovsz); 988 } 989 990 if (error != 0) { 991 m_freem(*from); 992 *from = NULL; 993 if (control != NULL) { 994 free_control_mbuf(l, *control, *control); 995 *control = NULL; 996 } 997 } 998 out: 999 if (iov != aiov) 1000 kmem_free(iov, iovsz); 1001 return error; 1002} 1003 1004 1005int 1006do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, 1007 struct mbuf **from, struct mbuf **control, register_t *retsize) 1008{ 1009 int error; 1010 struct socket *so; 1011 1012 if ((error = fd_getsock(s, &so)) != 0) 1013 return error; 1014 error = do_sys_recvmsg_so(l, s, so, mp, from, control, retsize); 1015 fd_putfile(s); 1016 return error; 1017} 1018 1019int 1020sys_recvmmsg(struct lwp *l, const struct sys_recvmmsg_args *uap, 1021 register_t *retval) 1022{ 1023 /* { 1024 syscallarg(int) s; 1025 syscallarg(struct mmsghdr *) mmsg; 1026 syscallarg(unsigned int) vlen; 1027 syscallarg(unsigned int) flags; 1028 syscallarg(struct timespec *) timeout; 1029 } */ 1030 struct mmsghdr mmsg; 1031 struct socket *so; 1032 struct msghdr *msg = &mmsg.msg_hdr; 1033 int error, s; 1034 struct mbuf *from, *control; 1035 struct timespec ts, now; 1036 unsigned int vlen, flags, dg; 1037 1038 if (SCARG(uap, timeout)) { 1039 if ((error = copyin(SCARG(uap, timeout), &ts, sizeof(ts))) != 0) 1040 return error; 1041 getnanotime(&now); 1042 timespecadd(&now, &ts, &ts); 1043 } 1044 1045 s = SCARG(uap, s); 1046 if ((error = fd_getsock(s, &so)) != 0) 1047 return error; 1048 1049 vlen = SCARG(uap, vlen); 1050 if (vlen > 1024) 1051 vlen = 1024; 1052 1053 from = NULL; 1054 flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; 1055 1056 for (dg = 0; dg < vlen;) { 1057 error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg)); 1058 if (error) 1059 break; 1060 1061 msg->msg_flags = flags & ~MSG_WAITFORONE; 1062 1063 if (from != NULL) { 1064 m_free(from); 1065 from = NULL; 1066 } 1067 1068 error = do_sys_recvmsg_so(l, s, so, msg, &from, 1069 msg->msg_control != NULL ? &control : NULL, retval); 1070 if (error) { 1071 if (error == EAGAIN && dg > 0) 1072 error = 0; 1073 break; 1074 } 1075 1076 if (msg->msg_control != NULL) 1077 error = copyout_msg_control(l, msg, control); 1078 if (error) 1079 break; 1080 1081 error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0, 1082 from); 1083 if (error) 1084 break; 1085 1086 ktrkuser("msghdr", msg, sizeof *msg); 1087 mmsg.msg_len = *retval; 1088 1089 error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg)); 1090 if (error) 1091 break; 1092 1093 dg++; 1094 if (msg->msg_flags & MSG_OOB) 1095 break; 1096 1097 if (SCARG(uap, timeout)) { 1098 getnanotime(&now); 1099 timespecsub(&now, &ts, &now); 1100 if (now.tv_sec > 0) 1101 break; 1102 } 1103 1104 if (flags & MSG_WAITFORONE) 1105 flags |= MSG_DONTWAIT; 1106 1107 } 1108 1109 if (from != NULL) 1110 m_free(from); 1111 1112 *retval = dg; 1113 if (error) 1114 so->so_error = error; 1115 1116 fd_putfile(s); 1117 1118 /* 1119 * If we succeeded at least once, return 0, hopefully so->so_error 1120 * will catch it next time. 1121 */ 1122 if (dg) 1123 return 0; 1124 1125 return error; 1126} 1127 1128int 1129sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, 1130 register_t *retval) 1131{ 1132 /* { 1133 syscallarg(int) s; 1134 syscallarg(int) how; 1135 } */ 1136 struct socket *so; 1137 int error; 1138 1139 if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) 1140 return error; 1141 solock(so); 1142 error = soshutdown(so, SCARG(uap, how)); 1143 sounlock(so); 1144 fd_putfile(SCARG(uap, s)); 1145 return error; 1146} 1147 1148int 1149sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap, 1150 register_t *retval) 1151{ 1152 /* { 1153 syscallarg(int) s; 1154 syscallarg(int) level; 1155 syscallarg(int) name; 1156 syscallarg(const void *) val; 1157 syscallarg(unsigned int) valsize; 1158 } */ 1159 struct sockopt sopt; 1160 struct socket *so; 1161 file_t *fp; 1162 int error; 1163 unsigned int len; 1164 1165 len = SCARG(uap, valsize); 1166 if (len > 0 && SCARG(uap, val) == NULL) 1167 return EINVAL; 1168 1169 if (len > MCLBYTES) 1170 return EINVAL; 1171 1172 if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0) 1173 return (error); 1174 1175 sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len); 1176 1177 if (len > 0) { 1178 error = copyin(SCARG(uap, val), sopt.sopt_data, len); 1179 if (error) 1180 goto out; 1181 } 1182 1183 error = sosetopt(so, &sopt); 1184 if (so->so_options & SO_NOSIGPIPE) 1185 atomic_or_uint(&fp->f_flag, FNOSIGPIPE); 1186 else 1187 atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE); 1188 1189 out: 1190 sockopt_destroy(&sopt); 1191 fd_putfile(SCARG(uap, s)); 1192 return error; 1193} 1194 1195static int 1196getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap, 1197 register_t *retval, bool copyarg) 1198{ 1199 struct sockopt sopt; 1200 struct socket *so; 1201 file_t *fp; 1202 unsigned int valsize, len; 1203 int error; 1204 1205 if (SCARG(uap, val) != NULL) { 1206 error = copyin(SCARG(uap, avalsize), &valsize, sizeof(valsize)); 1207 if (error) 1208 return error; 1209 } else 1210 valsize = 0; 1211 1212 if (valsize > MCLBYTES) 1213 return EINVAL; 1214 1215 if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0) 1216 return error; 1217 1218 sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), valsize); 1219 if (copyarg && valsize > 0) { 1220 error = copyin(SCARG(uap, val), sopt.sopt_data, valsize); 1221 if (error) 1222 goto out; 1223 } 1224 1225 if (fp->f_flag & FNOSIGPIPE) 1226 so->so_options |= SO_NOSIGPIPE; 1227 else 1228 so->so_options &= ~SO_NOSIGPIPE; 1229 1230 error = sogetopt(so, &sopt); 1231 if (error || valsize == 0) 1232 goto out; 1233 1234 len = min(valsize, sopt.sopt_retsize); 1235 error = copyout(sopt.sopt_data, SCARG(uap, val), len); 1236 if (error) 1237 goto out; 1238 1239 error = copyout(&len, SCARG(uap, avalsize), sizeof(len)); 1240 out: 1241 sockopt_destroy(&sopt); 1242 fd_putfile(SCARG(uap, s)); 1243 return error; 1244} 1245 1246int 1247sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap, 1248 register_t *retval) 1249{ 1250 /* { 1251 syscallarg(int) s; 1252 syscallarg(int) level; 1253 syscallarg(int) name; 1254 syscallarg(void *) val; 1255 syscallarg(unsigned int *) avalsize; 1256 } */ 1257 return getsockopt(l, uap, retval, false); 1258} 1259 1260int 1261sys_getsockopt2(struct lwp *l, const struct sys_getsockopt2_args *uap, 1262 register_t *retval) 1263{ 1264 /* { 1265 syscallarg(int) s; 1266 syscallarg(int) level; 1267 syscallarg(int) name; 1268 syscallarg(void *) val; 1269 syscallarg(unsigned int *) avalsize; 1270 } */ 1271 return getsockopt(l, (const struct sys_getsockopt_args *) uap, retval, true); 1272} 1273 1274#ifdef PIPE_SOCKETPAIR 1275 1276int 1277pipe1(struct lwp *l, int *fildes, int flags) 1278{ 1279 file_t *rf, *wf; 1280 struct socket *rso, *wso; 1281 int fd, error; 1282 proc_t *p; 1283 1284 if (flags & ~(O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE)) 1285 return EINVAL; 1286 p = curproc; 1287 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0) 1288 return error; 1289 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso)) != 0) 1290 goto free1; 1291 /* remember this socket pair implements a pipe */ 1292 wso->so_state |= SS_ISAPIPE; 1293 rso->so_state |= SS_ISAPIPE; 1294 if ((error = fd_allocfile(&rf, &fd)) != 0) 1295 goto free2; 1296 fildes[0] = fd; 1297 rf->f_flag = FREAD | flags; 1298 rf->f_type = DTYPE_SOCKET; 1299 rf->f_ops = &socketops; 1300 rf->f_socket = rso; 1301 if ((error = fd_allocfile(&wf, &fd)) != 0) 1302 goto free3; 1303 wf->f_flag = FWRITE | flags; 1304 wf->f_type = DTYPE_SOCKET; 1305 wf->f_ops = &socketops; 1306 wf->f_socket = wso; 1307 fildes[1] = fd; 1308 solock(wso); 1309 error = unp_connect2(wso, rso); 1310 sounlock(wso); 1311 if (error != 0) 1312 goto free4; 1313 fd_affix(p, wf, fildes[1]); 1314 fd_affix(p, rf, fildes[0]); 1315 return (0); 1316 free4: 1317 fd_abort(p, wf, fildes[1]); 1318 free3: 1319 fd_abort(p, rf, fildes[0]); 1320 free2: 1321 (void)soclose(wso); 1322 free1: 1323 (void)soclose(rso); 1324 return error; 1325} 1326#endif /* PIPE_SOCKETPAIR */ 1327 1328/* 1329 * Get peer socket name. 1330 */ 1331int 1332do_sys_getpeername(int fd, struct sockaddr *nam) 1333{ 1334 struct socket *so; 1335 int error; 1336 1337 if ((error = fd_getsock(fd, &so)) != 0) 1338 return error; 1339 1340 solock(so); 1341 if ((so->so_state & SS_ISCONNECTED) == 0) 1342 error = ENOTCONN; 1343 else { 1344 error = (*so->so_proto->pr_usrreqs->pr_peeraddr)(so, nam); 1345 } 1346 sounlock(so); 1347 fd_putfile(fd); 1348 return error; 1349} 1350 1351/* 1352 * Get local socket name. 1353 */ 1354int 1355do_sys_getsockname(int fd, struct sockaddr *nam) 1356{ 1357 struct socket *so; 1358 int error; 1359 1360 if ((error = fd_getsock(fd, &so)) != 0) 1361 return error; 1362 1363 solock(so); 1364 error = (*so->so_proto->pr_usrreqs->pr_sockaddr)(so, nam); 1365 sounlock(so); 1366 fd_putfile(fd); 1367 return error; 1368} 1369 1370int 1371copyout_sockname_sb(struct sockaddr *asa, unsigned int *alen, int flags, 1372 struct sockaddr_big *addr) 1373{ 1374 unsigned int len; 1375 int error; 1376 1377 if (asa == NULL) 1378 /* Assume application not interested */ 1379 return 0; 1380 1381 if (flags & MSG_LENUSRSPACE) { 1382 error = copyin(alen, &len, sizeof(len)); 1383 if (error) 1384 return error; 1385 } else 1386 len = *alen; 1387 1388 if (addr == NULL) { 1389 len = 0; 1390 error = 0; 1391 } else { 1392 if (len > addr->sb_len) 1393 len = addr->sb_len; 1394 /* XXX addr isn't an mbuf... */ 1395 ktrkuser(mbuftypes[MT_SONAME], addr, len); 1396 error = copyout(addr, asa, len); 1397 } 1398 1399 if (error == 0) { 1400 if (flags & MSG_LENUSRSPACE) 1401 error = copyout(&len, alen, sizeof(len)); 1402 else 1403 *alen = len; 1404 } 1405 1406 return error; 1407} 1408 1409int 1410copyout_sockname(struct sockaddr *asa, unsigned int *alen, int flags, 1411 struct mbuf *addr) 1412{ 1413 int len; 1414 int error; 1415 1416 if (asa == NULL) 1417 /* Assume application not interested */ 1418 return 0; 1419 1420 if (flags & MSG_LENUSRSPACE) { 1421 error = copyin(alen, &len, sizeof(len)); 1422 if (error) 1423 return error; 1424 } else 1425 len = *alen; 1426 if (len < 0) 1427 return EINVAL; 1428 1429 if (addr == NULL) { 1430 len = 0; 1431 error = 0; 1432 } else { 1433 if (len > addr->m_len) 1434 len = addr->m_len; 1435 /* Maybe this ought to copy a chain ? */ 1436 ktrkuser(mbuftypes[MT_SONAME], mtod(addr, void *), len); 1437 error = copyout(mtod(addr, void *), asa, len); 1438 } 1439 1440 if (error == 0) { 1441 if (flags & MSG_LENUSRSPACE) 1442 error = copyout(&len, alen, sizeof(len)); 1443 else 1444 *alen = len; 1445 } 1446 1447 return error; 1448} 1449 1450/* 1451 * Get socket name. 1452 */ 1453int 1454sys_getsockname(struct lwp *l, const struct sys_getsockname_args *uap, 1455 register_t *retval) 1456{ 1457 /* { 1458 syscallarg(int) fdes; 1459 syscallarg(struct sockaddr *) asa; 1460 syscallarg(unsigned int *) alen; 1461 } */ 1462 struct sockaddr_big sbig; 1463 int error; 1464 1465 sbig.sb_len = UCHAR_MAX; 1466 error = do_sys_getsockname(SCARG(uap, fdes), (struct sockaddr *)&sbig); 1467 if (error != 0) 1468 return error; 1469 1470 error = copyout_sockname_sb(SCARG(uap, asa), SCARG(uap, alen), 1471 MSG_LENUSRSPACE, &sbig); 1472 return error; 1473} 1474 1475/* 1476 * Get name of peer for connected socket. 1477 */ 1478int 1479sys_getpeername(struct lwp *l, const struct sys_getpeername_args *uap, 1480 register_t *retval) 1481{ 1482 /* { 1483 syscallarg(int) fdes; 1484 syscallarg(struct sockaddr *) asa; 1485 syscallarg(unsigned int *) alen; 1486 } */ 1487 struct sockaddr_big sbig; 1488 int error; 1489 1490 sbig.sb_len = UCHAR_MAX; 1491 error = do_sys_getpeername(SCARG(uap, fdes), (struct sockaddr *)&sbig); 1492 if (error != 0) 1493 return error; 1494 1495 error = copyout_sockname_sb(SCARG(uap, asa), SCARG(uap, alen), 1496 MSG_LENUSRSPACE, &sbig); 1497 return error; 1498} 1499 1500static int 1501sockargs_sb(struct sockaddr_big *sb, const void *name, socklen_t buflen) 1502{ 1503 int error; 1504 1505 /* 1506 * We can't allow socket names > UCHAR_MAX in length, since that 1507 * will overflow sb_len. Further no reasonable buflen is <= 1508 * offsetof(sockaddr_big, sb_data) since it shall be at least 1509 * the size of the preamble sb_len and sb_family members. 1510 */ 1511 if (buflen > UCHAR_MAX || 1512 buflen <= offsetof(struct sockaddr_big, sb_data)) 1513 return EINVAL; 1514 1515 error = copyin(name, (void *)sb, buflen); 1516 if (error) 1517 return error; 1518 1519 ktrkuser(mbuftypes[MT_SONAME], sb, buflen); 1520#if BYTE_ORDER != BIG_ENDIAN 1521 /* 1522 * 4.3BSD compat thing - need to stay, since bind(2), 1523 * connect(2), sendto(2) were not versioned for COMPAT_43. 1524 */ 1525 if (sb->sb_family == 0 && sb->sb_len < AF_MAX) 1526 sb->sb_family = sb->sb_len; 1527#endif 1528 sb->sb_len = buflen; 1529 return 0; 1530} 1531 1532/* 1533 * XXX In a perfect world, we wouldn't pass around socket control 1534 * XXX arguments in mbufs, and this could go away. 1535 */ 1536int 1537sockargs(struct mbuf **mp, const void *bf, size_t buflen, enum uio_seg seg, 1538 int type) 1539{ 1540 struct mbuf *m; 1541 int error; 1542 1543 /* 1544 * We can't allow socket names > UCHAR_MAX in length, since that 1545 * will overflow sa_len. Control data more than a page size in 1546 * length is just too much. 1547 */ 1548 if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE)) 1549 return EINVAL; 1550 1551 /* 1552 * length must greater than sizeof(sa_family) + sizeof(sa_len) 1553 */ 1554 if (type == MT_SONAME && buflen <= 2) 1555 return EINVAL; 1556 1557 /* Allocate an mbuf to hold the arguments. */ 1558 m = m_get(M_WAIT, type); 1559 /* can't claim. don't who to assign it to. */ 1560 if (buflen > MLEN) { 1561 /* 1562 * Won't fit into a regular mbuf, so we allocate just 1563 * enough external storage to hold the argument. 1564 */ 1565 MEXTMALLOC(m, buflen, M_WAITOK); 1566 } 1567 m->m_len = buflen; 1568 if (seg == UIO_USERSPACE) { 1569 error = copyin(bf, mtod(m, void *), buflen); 1570 if (error) { 1571 (void)m_free(m); 1572 return error; 1573 } 1574 } else { 1575 memcpy(mtod(m, void *), bf, buflen); 1576 } 1577 *mp = m; 1578 switch (type) { 1579 case MT_SONAME: 1580 ktrkuser(mbuftypes[type], mtod(m, void *), buflen); 1581 1582 struct sockaddr *sa = mtod(m, struct sockaddr *); 1583#if BYTE_ORDER != BIG_ENDIAN 1584 /* 1585 * 4.3BSD compat thing - need to stay, since bind(2), 1586 * connect(2), sendto(2) were not versioned for COMPAT_43. 1587 */ 1588 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1589 sa->sa_family = sa->sa_len; 1590#endif 1591 sa->sa_len = buflen; 1592 return 0; 1593 case MT_CONTROL: 1594 if (!KTRPOINT(curproc, KTR_USER)) 1595 return 0; 1596 1597 struct msghdr mhdr; 1598 mhdr.msg_control = mtod(m, void *); 1599 mhdr.msg_controllen = buflen; 1600 for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; 1601 cmsg = CMSG_NXTHDR(&mhdr, cmsg)) { 1602 ktrkuser(mbuftypes[type], cmsg, cmsg->cmsg_len); 1603 } 1604 return 0; 1605 default: 1606 return EINVAL; 1607 } 1608} 1609