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