uipc_syscalls.c revision 1.119
1/* $NetBSD: uipc_syscalls.c,v 1.119 2007/09/06 01:21:00 rmind Exp $ */ 2 3/* 4 * Copyright (c) 1982, 1986, 1989, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95 32 */ 33 34#include <sys/cdefs.h> 35__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.119 2007/09/06 01:21:00 rmind Exp $"); 36 37#include "opt_pipe.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/filedesc.h> 42#include <sys/proc.h> 43#include <sys/file.h> 44#include <sys/buf.h> 45#include <sys/malloc.h> 46#include <sys/mbuf.h> 47#include <sys/protosw.h> 48#include <sys/socket.h> 49#include <sys/socketvar.h> 50#include <sys/signalvar.h> 51#include <sys/un.h> 52#include <sys/ktrace.h> 53#include <sys/event.h> 54 55#include <sys/mount.h> 56#include <sys/syscallargs.h> 57 58#include <uvm/uvm_extern.h> 59 60/* 61 * System call interface to the socket abstraction. 62 */ 63extern const struct fileops socketops; 64 65int 66sys___socket30(struct lwp *l, void *v, register_t *retval) 67{ 68 struct sys___socket30_args /* { 69 syscallarg(int) domain; 70 syscallarg(int) type; 71 syscallarg(int) protocol; 72 } */ *uap = v; 73 74 struct filedesc *fdp; 75 struct socket *so; 76 struct file *fp; 77 int fd, error; 78 79 fdp = l->l_proc->p_fd; 80 /* falloc() will use the desciptor for us */ 81 if ((error = falloc(l, &fp, &fd)) != 0) 82 return (error); 83 fp->f_flag = FREAD|FWRITE; 84 fp->f_type = DTYPE_SOCKET; 85 fp->f_ops = &socketops; 86 error = socreate(SCARG(uap, domain), &so, SCARG(uap, type), 87 SCARG(uap, protocol), l); 88 if (error) { 89 FILE_UNUSE(fp, l); 90 fdremove(fdp, fd); 91 ffree(fp); 92 } else { 93 fp->f_data = so; 94 FILE_SET_MATURE(fp); 95 FILE_UNUSE(fp, l); 96 *retval = fd; 97 } 98 return (error); 99} 100 101/* ARGSUSED */ 102int 103sys_bind(struct lwp *l, void *v, register_t *retval) 104{ 105 struct sys_bind_args /* { 106 syscallarg(int) s; 107 syscallarg(const struct sockaddr *) name; 108 syscallarg(unsigned int) namelen; 109 } */ *uap = v; 110 struct mbuf *nam; 111 int error; 112 113 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 114 MT_SONAME); 115 if (error) 116 return error; 117 118 return do_sys_bind(l, SCARG(uap, s), nam); 119} 120 121int 122do_sys_bind(struct lwp *l, int s, struct mbuf *nam) 123{ 124 struct file *fp; 125 int error; 126 127 /* getsock() will use the descriptor for us */ 128 if ((error = getsock(l->l_proc->p_fd, s, &fp)) != 0) { 129 m_freem(nam); 130 return (error); 131 } 132 MCLAIM(nam, ((struct socket *)fp->f_data)->so_mowner); 133 error = sobind(fp->f_data, nam, l); 134 m_freem(nam); 135 FILE_UNUSE(fp, l); 136 return error; 137} 138 139/* ARGSUSED */ 140int 141sys_listen(struct lwp *l, void *v, register_t *retval) 142{ 143 struct sys_listen_args /* { 144 syscallarg(int) s; 145 syscallarg(int) backlog; 146 } */ *uap = v; 147 struct file *fp; 148 int error; 149 150 /* getsock() will use the descriptor for us */ 151 if ((error = getsock(l->l_proc->p_fd, SCARG(uap, s), &fp)) != 0) 152 return (error); 153 error = solisten(fp->f_data, SCARG(uap, backlog)); 154 FILE_UNUSE(fp, l); 155 return error; 156} 157 158int 159do_sys_accept(struct lwp *l, int sock, struct mbuf **name, register_t *new_sock) 160{ 161 struct filedesc *fdp; 162 struct file *fp; 163 struct mbuf *nam; 164 int error, s, fd; 165 struct socket *so; 166 int fflag; 167 168 fdp = l->l_proc->p_fd; 169 170 /* getsock() will use the descriptor for us */ 171 if ((error = getsock(fdp, sock, &fp)) != 0) 172 return (error); 173 s = splsoftnet(); 174 so = (struct socket *)fp->f_data; 175 FILE_UNUSE(fp, l); 176 if (!(so->so_proto->pr_flags & PR_LISTEN)) { 177 splx(s); 178 return (EOPNOTSUPP); 179 } 180 if ((so->so_options & SO_ACCEPTCONN) == 0) { 181 splx(s); 182 return (EINVAL); 183 } 184 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { 185 splx(s); 186 return (EWOULDBLOCK); 187 } 188 while (so->so_qlen == 0 && so->so_error == 0) { 189 if (so->so_state & SS_CANTRCVMORE) { 190 so->so_error = ECONNABORTED; 191 break; 192 } 193 error = tsleep(&so->so_timeo, PSOCK | PCATCH, 194 netcon, 0); 195 if (error) { 196 splx(s); 197 return (error); 198 } 199 } 200 if (so->so_error) { 201 error = so->so_error; 202 so->so_error = 0; 203 splx(s); 204 return (error); 205 } 206 fflag = fp->f_flag; 207 /* falloc() will use the descriptor for us */ 208 if ((error = falloc(l, &fp, &fd)) != 0) { 209 splx(s); 210 return (error); 211 } 212 *new_sock = fd; 213 214 /* connection has been removed from the listen queue */ 215 KNOTE(&so->so_rcv.sb_sel.sel_klist, 0); 216 217 { struct socket *aso = TAILQ_FIRST(&so->so_q); 218 if (soqremque(aso, 1) == 0) 219 panic("accept"); 220 so = aso; 221 } 222 fp->f_type = DTYPE_SOCKET; 223 fp->f_flag = fflag; 224 fp->f_ops = &socketops; 225 fp->f_data = so; 226 nam = m_get(M_WAIT, MT_SONAME); 227 error = soaccept(so, nam); 228 229 if (error) { 230 /* an error occurred, free the file descriptor and mbuf */ 231 m_freem(nam); 232 fdremove(fdp, fd); 233 closef(fp, l); 234 } else { 235 FILE_SET_MATURE(fp); 236 FILE_UNUSE(fp, l); 237 *name = nam; 238 } 239 splx(s); 240 return (error); 241} 242 243int 244sys_accept(struct lwp *l, void *v, register_t *retval) 245{ 246 struct sys_accept_args /* { 247 syscallarg(int) s; 248 syscallarg(struct sockaddr *) name; 249 syscallarg(unsigned int *) anamelen; 250 } */ *uap = v; 251 int error; 252 struct mbuf *name; 253 254 error = do_sys_accept(l, SCARG(uap, s), &name, retval); 255 if (error != 0) 256 return error; 257 258 error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen), 259 MSG_LENUSRSPACE, name); 260 if (name != NULL) 261 m_free(name); 262 if (error != 0) 263 fdrelease(l, *retval); 264 return error; 265} 266 267/* ARGSUSED */ 268int 269sys_connect(struct lwp *l, void *v, register_t *retval) 270{ 271 struct sys_connect_args /* { 272 syscallarg(int) s; 273 syscallarg(const struct sockaddr *) name; 274 syscallarg(unsigned int) namelen; 275 } */ *uap = v; 276 int error; 277 struct mbuf *nam; 278 279 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 280 MT_SONAME); 281 if (error) 282 return error; 283 return do_sys_connect(l, SCARG(uap, s), nam); 284} 285 286int 287do_sys_connect(struct lwp *l, int s, struct mbuf *nam) 288{ 289 struct file *fp; 290 struct socket *so; 291 int error; 292 int interrupted = 0; 293 294 /* getsock() will use the descriptor for us */ 295 if ((error = getsock(l->l_proc->p_fd, s, &fp)) != 0) { 296 m_freem(nam); 297 return (error); 298 } 299 so = fp->f_data; 300 MCLAIM(nam, so->so_mowner); 301 if (so->so_state & SS_ISCONNECTING) { 302 error = EALREADY; 303 goto out; 304 } 305 306 error = soconnect(so, nam, l); 307 if (error) 308 goto bad; 309 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 310 error = EINPROGRESS; 311 goto out; 312 } 313 s = splsoftnet(); 314 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 315 error = tsleep(&so->so_timeo, PSOCK | PCATCH, 316 netcon, 0); 317 if (error) { 318 if (error == EINTR || error == ERESTART) 319 interrupted = 1; 320 break; 321 } 322 } 323 if (error == 0) { 324 error = so->so_error; 325 so->so_error = 0; 326 } 327 splx(s); 328 bad: 329 if (!interrupted) 330 so->so_state &= ~SS_ISCONNECTING; 331 if (error == ERESTART) 332 error = EINTR; 333 out: 334 FILE_UNUSE(fp, l); 335 m_freem(nam); 336 return (error); 337} 338 339int 340sys_socketpair(struct lwp *l, void *v, register_t *retval) 341{ 342 struct sys_socketpair_args /* { 343 syscallarg(int) domain; 344 syscallarg(int) type; 345 syscallarg(int) protocol; 346 syscallarg(int *) rsv; 347 } */ *uap = v; 348 struct filedesc *fdp; 349 struct file *fp1, *fp2; 350 struct socket *so1, *so2; 351 int fd, error, sv[2]; 352 353 fdp = l->l_proc->p_fd; 354 error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type), 355 SCARG(uap, protocol), l); 356 if (error) 357 return (error); 358 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type), 359 SCARG(uap, protocol), l); 360 if (error) 361 goto free1; 362 /* falloc() will use the descriptor for us */ 363 if ((error = falloc(l, &fp1, &fd)) != 0) 364 goto free2; 365 sv[0] = fd; 366 fp1->f_flag = FREAD|FWRITE; 367 fp1->f_type = DTYPE_SOCKET; 368 fp1->f_ops = &socketops; 369 fp1->f_data = so1; 370 if ((error = falloc(l, &fp2, &fd)) != 0) 371 goto free3; 372 fp2->f_flag = FREAD|FWRITE; 373 fp2->f_type = DTYPE_SOCKET; 374 fp2->f_ops = &socketops; 375 fp2->f_data = so2; 376 sv[1] = fd; 377 if ((error = soconnect2(so1, so2)) != 0) 378 goto free4; 379 if (SCARG(uap, type) == SOCK_DGRAM) { 380 /* 381 * Datagram socket connection is asymmetric. 382 */ 383 if ((error = soconnect2(so2, so1)) != 0) 384 goto free4; 385 } 386 error = copyout(sv, SCARG(uap, rsv), 2 * sizeof(int)); 387 FILE_SET_MATURE(fp1); 388 FILE_SET_MATURE(fp2); 389 FILE_UNUSE(fp1, l); 390 FILE_UNUSE(fp2, l); 391 return (error); 392 free4: 393 FILE_UNUSE(fp2, l); 394 ffree(fp2); 395 fdremove(fdp, sv[1]); 396 free3: 397 FILE_UNUSE(fp1, l); 398 ffree(fp1); 399 fdremove(fdp, sv[0]); 400 free2: 401 (void)soclose(so2); 402 free1: 403 (void)soclose(so1); 404 return (error); 405} 406 407int 408sys_sendto(struct lwp *l, void *v, register_t *retval) 409{ 410 struct sys_sendto_args /* { 411 syscallarg(int) s; 412 syscallarg(const void *) buf; 413 syscallarg(size_t) len; 414 syscallarg(int) flags; 415 syscallarg(const struct sockaddr *) to; 416 syscallarg(unsigned int) tolen; 417 } */ *uap = v; 418 struct msghdr msg; 419 struct iovec aiov; 420 421 msg.msg_name = __UNCONST(SCARG(uap, to)); /* XXXUNCONST kills const */ 422 msg.msg_namelen = SCARG(uap, tolen); 423 msg.msg_iov = &aiov; 424 msg.msg_iovlen = 1; 425 msg.msg_control = 0; 426 msg.msg_flags = 0; 427 aiov.iov_base = __UNCONST(SCARG(uap, buf)); /* XXXUNCONST kills const */ 428 aiov.iov_len = SCARG(uap, len); 429 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 430} 431 432int 433sys_sendmsg(struct lwp *l, void *v, register_t *retval) 434{ 435 struct sys_sendmsg_args /* { 436 syscallarg(int) s; 437 syscallarg(const struct msghdr *) msg; 438 syscallarg(int) flags; 439 } */ *uap = v; 440 struct msghdr msg; 441 int error; 442 443 error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); 444 if (error) 445 return (error); 446 447 msg.msg_flags = MSG_IOVUSRSPACE; 448 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 449} 450 451int 452do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags, 453 register_t *retsize) 454{ 455 struct file *fp; 456 struct uio auio; 457 int i, len, error, iovlen; 458 struct mbuf *to, *control; 459 struct socket *so; 460 struct iovec *tiov; 461 struct iovec aiov[UIO_SMALLIOV], *iov = aiov; 462 struct iovec *ktriov = NULL; 463 464 ktrkuser("msghdr", mp, sizeof *mp); 465 466 /* If the caller passed us stuff in mbufs, we must free them */ 467 if (mp->msg_flags & MSG_NAMEMBUF) 468 to = mp->msg_name; 469 else 470 to = NULL; 471 472 if (mp->msg_flags & MSG_CONTROLMBUF) 473 control = mp->msg_control; 474 else 475 control = NULL; 476 477 if (mp->msg_flags & MSG_IOVUSRSPACE) { 478 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) { 479 if ((unsigned int)mp->msg_iovlen > IOV_MAX) { 480 error = EMSGSIZE; 481 goto bad; 482 } 483 iov = malloc(sizeof(struct iovec) * mp->msg_iovlen, 484 M_IOV, M_WAITOK); 485 } 486 if (mp->msg_iovlen != 0) { 487 error = copyin(mp->msg_iov, iov, 488 (size_t)(mp->msg_iovlen * sizeof(struct iovec))); 489 if (error) 490 goto bad; 491 } 492 mp->msg_iov = iov; 493 } 494 495 auio.uio_iov = mp->msg_iov; 496 auio.uio_iovcnt = mp->msg_iovlen; 497 auio.uio_rw = UIO_WRITE; 498 auio.uio_offset = 0; /* XXX */ 499 auio.uio_resid = 0; 500 KASSERT(l == curlwp); 501 auio.uio_vmspace = l->l_proc->p_vmspace; 502 503 for (i = 0, tiov = mp->msg_iov; i < mp->msg_iovlen; i++, tiov++) { 504#if 0 505 /* cannot happen; iov_len is unsigned */ 506 if (tiov->iov_len < 0) { 507 error = EINVAL; 508 goto bad; 509 } 510#endif 511 /* 512 * Writes return ssize_t because -1 is returned on error. 513 * Therefore, we must restrict the length to SSIZE_MAX to 514 * avoid garbage return values. 515 */ 516 auio.uio_resid += tiov->iov_len; 517 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { 518 error = EINVAL; 519 goto bad; 520 } 521 } 522 523 if (mp->msg_name && to == NULL) { 524 error = sockargs(&to, mp->msg_name, mp->msg_namelen, 525 MT_SONAME); 526 if (error) 527 goto bad; 528 } 529 530 if (mp->msg_control) { 531 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) { 532 error = EINVAL; 533 goto bad; 534 } 535 if (control == NULL) { 536 error = sockargs(&control, mp->msg_control, 537 mp->msg_controllen, MT_CONTROL); 538 if (error) 539 goto bad; 540 } 541 } 542 543 if (ktrpoint(KTR_GENIO)) { 544 iovlen = auio.uio_iovcnt * sizeof(struct iovec); 545 ktriov = malloc(iovlen, M_TEMP, M_WAITOK); 546 memcpy(ktriov, auio.uio_iov, iovlen); 547 } 548 549 /* getsock() will use the descriptor for us */ 550 if ((error = getsock(l->l_proc->p_fd, s, &fp)) != 0) 551 goto bad; 552 so = (struct socket *)fp->f_data; 553 554 if (mp->msg_name) 555 MCLAIM(to, so->so_mowner); 556 if (mp->msg_control) 557 MCLAIM(control, so->so_mowner); 558 559 len = auio.uio_resid; 560 error = (*so->so_send)(so, to, &auio, NULL, control, flags, l); 561 /* Protocol is responsible for freeing 'control' */ 562 control = NULL; 563 564 FILE_UNUSE(fp, l); 565 566 if (error) { 567 if (auio.uio_resid != len && (error == ERESTART || 568 error == EINTR || error == EWOULDBLOCK)) 569 error = 0; 570 if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) { 571 mutex_enter(&proclist_mutex); 572 psignal(l->l_proc, SIGPIPE); 573 mutex_exit(&proclist_mutex); 574 } 575 } 576 if (error == 0) 577 *retsize = len - auio.uio_resid; 578 579bad: 580 if (ktriov != NULL) { 581 ktrgeniov(s, UIO_WRITE, ktriov, *retsize, error); 582 free(ktriov, M_TEMP); 583 } 584 585 if (iov != aiov) 586 free(iov, M_IOV); 587 if (to) 588 m_freem(to); 589 if (control != NULL) 590 m_freem(control); 591 592 return (error); 593} 594 595int 596sys_recvfrom(struct lwp *l, void *v, register_t *retval) 597{ 598 struct sys_recvfrom_args /* { 599 syscallarg(int) s; 600 syscallarg(void *) buf; 601 syscallarg(size_t) len; 602 syscallarg(int) flags; 603 syscallarg(struct sockaddr *) from; 604 syscallarg(unsigned int *) fromlenaddr; 605 } */ *uap = v; 606 struct msghdr msg; 607 struct iovec aiov; 608 int error; 609 struct mbuf *from; 610 611 msg.msg_name = NULL;; 612 msg.msg_iov = &aiov; 613 msg.msg_iovlen = 1; 614 aiov.iov_base = SCARG(uap, buf); 615 aiov.iov_len = SCARG(uap, len); 616 msg.msg_control = NULL; 617 msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS; 618 619 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval); 620 if (error != 0) 621 return error; 622 623 error = copyout_sockname(SCARG(uap, from), SCARG(uap, fromlenaddr), 624 MSG_LENUSRSPACE, from); 625 if (from != NULL) 626 m_free(from); 627 return error; 628} 629 630int 631sys_recvmsg(struct lwp *l, void *v, register_t *retval) 632{ 633 struct sys_recvmsg_args /* { 634 syscallarg(int) s; 635 syscallarg(struct msghdr *) msg; 636 syscallarg(int) flags; 637 } */ *uap = v; 638 struct msghdr msg; 639 int error; 640 struct mbuf *from, *control; 641 642 error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); 643 if (error) 644 return (error); 645 646 msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; 647 648 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, 649 msg.msg_control != NULL ? &control : NULL, retval); 650 if (error != 0) 651 return error; 652 653 if (msg.msg_control != NULL) 654 error = copyout_msg_control(l, &msg, control); 655 656 if (error == 0) 657 error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0, 658 from); 659 if (from != NULL) 660 m_free(from); 661 if (error == 0) { 662 ktrkuser("msghdr", &msg, sizeof msg); 663 error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); 664 } 665 666 return (error); 667} 668 669/* 670 * Adjust for a truncated SCM_RIGHTS control message. 671 * This means closing any file descriptors that aren't present 672 * in the returned buffer. 673 * m is the mbuf holding the (already externalized) SCM_RIGHTS message. 674 */ 675static void 676free_rights(struct mbuf *m, struct lwp *l) 677{ 678 int nfd; 679 int i; 680 int *fdv; 681 682 nfd = m->m_len < CMSG_SPACE(sizeof(int)) ? 0 683 : (m->m_len - CMSG_SPACE(sizeof(int))) / sizeof(int) + 1; 684 fdv = (int *) CMSG_DATA(mtod(m,struct cmsghdr *)); 685 for (i = 0; i < nfd; i++) 686 fdrelease(l, fdv[i]); 687} 688 689void 690free_control_mbuf(struct lwp *l, struct mbuf *control, struct mbuf *uncopied) 691{ 692 struct mbuf *next; 693 struct cmsghdr *cmsg; 694 bool do_free_rights = false; 695 696 while (control != NULL) { 697 cmsg = mtod(control, struct cmsghdr *); 698 if (control == uncopied) 699 do_free_rights = true; 700 if (do_free_rights && cmsg->cmsg_level == SOL_SOCKET 701 && cmsg->cmsg_type == SCM_RIGHTS) 702 free_rights(control, l); 703 next = control->m_next; 704 m_free(control); 705 control = next; 706 } 707} 708 709/* Copy socket control/CMSG data to user buffer, frees the mbuf */ 710int 711copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control) 712{ 713 int i, len, error = 0; 714 struct cmsghdr *cmsg; 715 struct mbuf *m; 716 char *q; 717 718 len = mp->msg_controllen; 719 if (len <= 0 || control == 0) { 720 mp->msg_controllen = 0; 721 free_control_mbuf(l, control, control); 722 return 0; 723 } 724 725 q = (char *)mp->msg_control; 726 727 for (m = control; m != NULL; ) { 728 cmsg = mtod(m, struct cmsghdr *); 729 i = m->m_len; 730 if (len < i) { 731 mp->msg_flags |= MSG_CTRUNC; 732 if (cmsg->cmsg_level == SOL_SOCKET 733 && cmsg->cmsg_type == SCM_RIGHTS) 734 /* Do not truncate me ... */ 735 break; 736 i = len; 737 } 738 error = copyout(mtod(m, void *), q, i); 739 ktrkuser("msgcontrol", mtod(m, void *), i); 740 if (error != 0) { 741 /* We must free all the SCM_RIGHTS */ 742 m = control; 743 break; 744 } 745 m = m->m_next; 746 if (m) 747 i = ALIGN(i); 748 q += i; 749 len -= i; 750 if (len <= 0) 751 break; 752 } 753 754 free_control_mbuf(l, control, m); 755 756 mp->msg_controllen = q - (char *)mp->msg_control; 757 return error; 758} 759 760int 761do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from, 762 struct mbuf **control, register_t *retsize) 763{ 764 struct file *fp; 765 struct uio auio; 766 struct iovec aiov[UIO_SMALLIOV], *iov = aiov; 767 struct iovec *tiov; 768 int i, len, error, iovlen; 769 struct socket *so; 770 struct iovec *ktriov; 771 772 ktrkuser("msghdr", mp, sizeof *mp); 773 774 *from = NULL; 775 if (control != NULL) 776 *control = NULL; 777 778 /* getsock() will use the descriptor for us */ 779 if ((error = getsock(l->l_proc->p_fd, s, &fp)) != 0) 780 return (error); 781 so = (struct socket *)fp->f_data; 782 783 if (mp->msg_flags & MSG_IOVUSRSPACE) { 784 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) { 785 if ((unsigned int)mp->msg_iovlen > IOV_MAX) { 786 error = EMSGSIZE; 787 goto out; 788 } 789 iov = malloc(sizeof(struct iovec) * mp->msg_iovlen, 790 M_IOV, M_WAITOK); 791 } 792 if (mp->msg_iovlen != 0) { 793 error = copyin(mp->msg_iov, iov, 794 (size_t)(mp->msg_iovlen * sizeof(struct iovec))); 795 if (error) 796 goto out; 797 } 798 auio.uio_iov = iov; 799 } else 800 auio.uio_iov = mp->msg_iov; 801 auio.uio_iovcnt = mp->msg_iovlen; 802 auio.uio_rw = UIO_READ; 803 auio.uio_offset = 0; /* XXX */ 804 auio.uio_resid = 0; 805 KASSERT(l == curlwp); 806 auio.uio_vmspace = l->l_proc->p_vmspace; 807 808 tiov = auio.uio_iov; 809 for (i = 0; i < mp->msg_iovlen; i++, tiov++) { 810#if 0 811 /* cannot happen iov_len is unsigned */ 812 if (tiov->iov_len < 0) { 813 error = EINVAL; 814 goto out; 815 } 816#endif 817 /* 818 * Reads return ssize_t because -1 is returned on error. 819 * Therefore we must restrict the length to SSIZE_MAX to 820 * avoid garbage return values. 821 */ 822 auio.uio_resid += tiov->iov_len; 823 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { 824 error = EINVAL; 825 goto out; 826 } 827 } 828 829 ktriov = NULL; 830 if (ktrpoint(KTR_GENIO)) { 831 iovlen = auio.uio_iovcnt * sizeof(struct iovec); 832 ktriov = malloc(iovlen, M_TEMP, M_WAITOK); 833 memcpy(ktriov, auio.uio_iov, iovlen); 834 } 835 836 len = auio.uio_resid; 837 mp->msg_flags &= MSG_USERFLAGS; 838 error = (*so->so_receive)(so, from, &auio, NULL, control, 839 &mp->msg_flags); 840 len -= auio.uio_resid; 841 *retsize = len; 842 if (error != 0 && len != 0 843 && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) 844 /* Some data transferred */ 845 error = 0; 846 847 if (ktriov != NULL) { 848 ktrgeniov(s, UIO_READ, ktriov, len, error); 849 free(ktriov, M_TEMP); 850 } 851 852 if (error != 0) { 853 m_freem(*from); 854 *from = NULL; 855 if (control != NULL) { 856 free_control_mbuf(l, *control, *control); 857 *control = NULL; 858 } 859 } 860 out: 861 if (iov != aiov) 862 free(iov, M_TEMP); 863 FILE_UNUSE(fp, l); 864 return (error); 865} 866 867 868/* ARGSUSED */ 869int 870sys_shutdown(struct lwp *l, void *v, register_t *retval) 871{ 872 struct sys_shutdown_args /* { 873 syscallarg(int) s; 874 syscallarg(int) how; 875 } */ *uap = v; 876 struct proc *p; 877 struct file *fp; 878 int error; 879 880 p = l->l_proc; 881 /* getsock() will use the descriptor for us */ 882 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 883 return (error); 884 error = soshutdown((struct socket *)fp->f_data, SCARG(uap, how)); 885 FILE_UNUSE(fp, l); 886 return (error); 887} 888 889/* ARGSUSED */ 890int 891sys_setsockopt(struct lwp *l, void *v, register_t *retval) 892{ 893 struct sys_setsockopt_args /* { 894 syscallarg(int) s; 895 syscallarg(int) level; 896 syscallarg(int) name; 897 syscallarg(const void *) val; 898 syscallarg(unsigned int) valsize; 899 } */ *uap = v; 900 struct proc *p; 901 struct file *fp; 902 struct mbuf *m; 903 struct socket *so; 904 int error; 905 unsigned int len; 906 907 p = l->l_proc; 908 m = NULL; 909 /* getsock() will use the descriptor for us */ 910 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 911 return (error); 912 so = (struct socket *)fp->f_data; 913 len = SCARG(uap, valsize); 914 if (len > MCLBYTES) { 915 error = EINVAL; 916 goto out; 917 } 918 if (SCARG(uap, val)) { 919 m = m_get(M_WAIT, MT_SOOPTS); 920 MCLAIM(m, so->so_mowner); 921 if (len > MLEN) 922 m_clget(m, M_WAIT); 923 error = copyin(SCARG(uap, val), mtod(m, void *), len); 924 if (error) { 925 (void) m_free(m); 926 goto out; 927 } 928 m->m_len = SCARG(uap, valsize); 929 } 930 error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m); 931 out: 932 FILE_UNUSE(fp, l); 933 return (error); 934} 935 936/* ARGSUSED */ 937int 938sys_getsockopt(struct lwp *l, void *v, register_t *retval) 939{ 940 struct sys_getsockopt_args /* { 941 syscallarg(int) s; 942 syscallarg(int) level; 943 syscallarg(int) name; 944 syscallarg(void *) val; 945 syscallarg(unsigned int *) avalsize; 946 } */ *uap = v; 947 struct file *fp; 948 struct mbuf *m; 949 unsigned int op, i, valsize; 950 int error; 951 952 m = NULL; 953 /* getsock() will use the descriptor for us */ 954 if ((error = getsock(l->l_proc->p_fd, SCARG(uap, s), &fp)) != 0) 955 return (error); 956 if (SCARG(uap, val)) { 957 error = copyin(SCARG(uap, avalsize), 958 &valsize, sizeof(valsize)); 959 if (error) 960 goto out; 961 } else 962 valsize = 0; 963 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level), 964 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize && 965 m != NULL) { 966 op = 0; 967 while (m && !error && op < valsize) { 968 i = min(m->m_len, (valsize - op)); 969 error = copyout(mtod(m, void *), SCARG(uap, val), i); 970 op += i; 971 SCARG(uap, val) = ((uint8_t *)SCARG(uap, val)) + i; 972 m = m_free(m); 973 } 974 valsize = op; 975 if (error == 0) 976 error = copyout(&valsize, 977 SCARG(uap, avalsize), sizeof(valsize)); 978 } 979 if (m != NULL) 980 (void) m_freem(m); 981 out: 982 FILE_UNUSE(fp, l); 983 return (error); 984} 985 986#ifdef PIPE_SOCKETPAIR 987/* ARGSUSED */ 988int 989sys_pipe(struct lwp *l, void *v, register_t *retval) 990{ 991 struct filedesc *fdp; 992 struct file *rf, *wf; 993 struct socket *rso, *wso; 994 int fd, error; 995 996 fdp = l->l_proc->p_fd; 997 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l)) != 0) 998 return (error); 999 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l)) != 0) 1000 goto free1; 1001 /* remember this socket pair implements a pipe */ 1002 wso->so_state |= SS_ISAPIPE; 1003 rso->so_state |= SS_ISAPIPE; 1004 /* falloc() will use the descriptor for us */ 1005 if ((error = falloc(l, &rf, &fd)) != 0) 1006 goto free2; 1007 retval[0] = fd; 1008 rf->f_flag = FREAD; 1009 rf->f_type = DTYPE_SOCKET; 1010 rf->f_ops = &socketops; 1011 rf->f_data = rso; 1012 if ((error = falloc(l, &wf, &fd)) != 0) 1013 goto free3; 1014 wf->f_flag = FWRITE; 1015 wf->f_type = DTYPE_SOCKET; 1016 wf->f_ops = &socketops; 1017 wf->f_data = wso; 1018 retval[1] = fd; 1019 if ((error = unp_connect2(wso, rso, PRU_CONNECT2)) != 0) 1020 goto free4; 1021 FILE_SET_MATURE(rf); 1022 FILE_SET_MATURE(wf); 1023 FILE_UNUSE(rf, l); 1024 FILE_UNUSE(wf, l); 1025 return (0); 1026 free4: 1027 FILE_UNUSE(wf, l); 1028 ffree(wf); 1029 fdremove(fdp, retval[1]); 1030 free3: 1031 FILE_UNUSE(rf, l); 1032 ffree(rf); 1033 fdremove(fdp, retval[0]); 1034 free2: 1035 (void)soclose(wso); 1036 free1: 1037 (void)soclose(rso); 1038 return (error); 1039} 1040#endif /* PIPE_SOCKETPAIR */ 1041 1042/* 1043 * Get socket name. 1044 */ 1045/* ARGSUSED */ 1046int 1047do_sys_getsockname(struct lwp *l, int fd, int which, struct mbuf **nam) 1048{ 1049 struct file *fp; 1050 struct socket *so; 1051 struct mbuf *m; 1052 int error; 1053 1054 /* getsock() will use the descriptor for us */ 1055 if ((error = getsock(l->l_proc->p_fd, fd, &fp)) != 0) 1056 return error; 1057 so = (struct socket *)fp->f_data; 1058 1059 if (which == PRU_PEERADDR 1060 && (so->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING)) == 0) { 1061 error = ENOTCONN; 1062 goto bad; 1063 } 1064 1065 m = m_getclr(M_WAIT, MT_SONAME); 1066 *nam = m; 1067 MCLAIM(m, so->so_mowner); 1068 error = (*so->so_proto->pr_usrreq)(so, which, (struct mbuf *)0, 1069 m, (struct mbuf *)0, (struct lwp *)0); 1070 if (error != 0) 1071 m_free(m); 1072 bad: 1073 FILE_UNUSE(fp, l); 1074 return error; 1075} 1076 1077int 1078copyout_sockname(struct sockaddr *asa, unsigned int *alen, int flags, 1079 struct mbuf *addr) 1080{ 1081 int len; 1082 int error; 1083 1084 if (asa == NULL) 1085 /* Assume application not interested */ 1086 return 0; 1087 1088 if (flags & MSG_LENUSRSPACE) { 1089 error = copyin(alen, &len, sizeof(len)); 1090 if (error) 1091 return error; 1092 } else 1093 len = *alen; 1094 if (len < 0) 1095 return EINVAL; 1096 1097 if (addr == NULL) { 1098 len = 0; 1099 error = 0; 1100 } else { 1101 if (len > addr->m_len) 1102 len = addr->m_len; 1103 /* Maybe this ought to copy a chain ? */ 1104 ktrkuser("sockname", mtod(addr, void *), len); 1105 error = copyout(mtod(addr, void *), asa, len); 1106 } 1107 1108 if (error == 0) { 1109 if (flags & MSG_LENUSRSPACE) 1110 error = copyout(&len, alen, sizeof(len)); 1111 else 1112 *alen = len; 1113 } 1114 1115 return error; 1116} 1117 1118/* 1119 * Get socket name. 1120 */ 1121/* ARGSUSED */ 1122int 1123sys_getsockname(struct lwp *l, void *v, register_t *retval) 1124{ 1125 struct sys_getsockname_args /* { 1126 syscallarg(int) fdes; 1127 syscallarg(struct sockaddr *) asa; 1128 syscallarg(unsigned int *) alen; 1129 } */ *uap = v; 1130 struct mbuf *m; 1131 int error; 1132 1133 error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_SOCKADDR, &m); 1134 if (error != 0) 1135 return error; 1136 1137 error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen), 1138 MSG_LENUSRSPACE, m); 1139 if (m != NULL) 1140 m_free(m); 1141 return error; 1142} 1143 1144/* 1145 * Get name of peer for connected socket. 1146 */ 1147/* ARGSUSED */ 1148int 1149sys_getpeername(struct lwp *l, void *v, register_t *retval) 1150{ 1151 struct sys_getpeername_args /* { 1152 syscallarg(int) fdes; 1153 syscallarg(struct sockaddr *) asa; 1154 syscallarg(unsigned int *) alen; 1155 } */ *uap = v; 1156 struct mbuf *m; 1157 int error; 1158 1159 error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_PEERADDR, &m); 1160 if (error != 0) 1161 return error; 1162 1163 error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen), 1164 MSG_LENUSRSPACE, m); 1165 if (m != NULL) 1166 m_free(m); 1167 return error; 1168} 1169 1170/* 1171 * XXX In a perfect world, we wouldn't pass around socket control 1172 * XXX arguments in mbufs, and this could go away. 1173 */ 1174int 1175sockargs(struct mbuf **mp, const void *bf, size_t buflen, int type) 1176{ 1177 struct sockaddr *sa; 1178 struct mbuf *m; 1179 int error; 1180 1181 /* 1182 * We can't allow socket names > UCHAR_MAX in length, since that 1183 * will overflow sa_len. Control data more than a page size in 1184 * length is just too much. 1185 */ 1186 if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE)) 1187 return (EINVAL); 1188 1189 /* Allocate an mbuf to hold the arguments. */ 1190 m = m_get(M_WAIT, type); 1191 /* can't claim. don't who to assign it to. */ 1192 if (buflen > MLEN) { 1193 /* 1194 * Won't fit into a regular mbuf, so we allocate just 1195 * enough external storage to hold the argument. 1196 */ 1197 MEXTMALLOC(m, buflen, M_WAITOK); 1198 } 1199 m->m_len = buflen; 1200 error = copyin(bf, mtod(m, void *), buflen); 1201 if (error) { 1202 (void) m_free(m); 1203 return (error); 1204 } 1205 ktrkuser("sockargs", mtod(m, void *), buflen); 1206 *mp = m; 1207 if (type == MT_SONAME) { 1208 sa = mtod(m, struct sockaddr *); 1209#if BYTE_ORDER != BIG_ENDIAN 1210 /* 1211 * 4.3BSD compat thing - need to stay, since bind(2), 1212 * connect(2), sendto(2) were not versioned for COMPAT_43. 1213 */ 1214 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1215 sa->sa_family = sa->sa_len; 1216#endif 1217 sa->sa_len = buflen; 1218 } 1219 return (0); 1220} 1221 1222int 1223getsock(struct filedesc *fdp, int fdes, struct file **fpp) 1224{ 1225 struct file *fp; 1226 1227 if ((fp = fd_getfile(fdp, fdes)) == NULL) 1228 return (EBADF); 1229 1230 FILE_USE(fp); 1231 1232 if (fp->f_type != DTYPE_SOCKET) { 1233 FILE_UNUSE(fp, NULL); 1234 return (ENOTSOCK); 1235 } 1236 *fpp = fp; 1237 return (0); 1238} 1239