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