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