1 /* 2 * Copyright (c) 1982, 1986, 1989, 1990 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)uipc_syscalls.c 7.24 (Berkeley) 6/3/91 34 * $Id: uipc_syscalls.c,v 1.5 1993/07/17 15:24:42 mycroft Exp $ 35 */ 36 37 #include "param.h" 38 #include "filedesc.h" 39 #include "proc.h" 40 #include "file.h" 41 #include "buf.h" 42 #include "malloc.h" 43 #include "mbuf.h" 44 #include "protosw.h" 45 #include "socket.h" 46 #include "socketvar.h" 47 #ifdef KTRACE 48 #include "ktrace.h" 49 #endif 50 51 /* 52 * System call interface to the socket abstraction. 53 */ 54 55 extern struct fileops socketops; 56 57 struct socket_args { 58 int domain; 59 int type; 60 int protocol; 61 }; 62 63 socket(p, uap, retval) 64 struct proc *p; 65 register struct socket_args *uap; 66 int *retval; 67 { 68 struct filedesc *fdp = p->p_fd; 69 struct socket *so; 70 struct file *fp; 71 int fd, error; 72 73 if (error = falloc(p, &fp, &fd)) 74 return (error); 75 fp->f_flag = FREAD|FWRITE; 76 fp->f_type = DTYPE_SOCKET; 77 fp->f_ops = &socketops; 78 if (error = socreate(uap->domain, &so, uap->type, uap->protocol)) { 79 fdp->fd_ofiles[fd] = 0; 80 ffree(fp); 81 } else { 82 fp->f_data = (caddr_t)so; 83 *retval = fd; 84 } 85 return (error); 86 } 87 88 struct bind_args { 89 int s; 90 caddr_t name; 91 int namelen; 92 }; 93 94 /* ARGSUSED */ 95 bind(p, uap, retval) 96 struct proc *p; 97 register struct bind_args *uap; 98 int *retval; 99 { 100 struct file *fp; 101 struct mbuf *nam; 102 int error; 103 104 if (error = getsock(p->p_fd, uap->s, &fp)) 105 return (error); 106 if (error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME)) 107 return (error); 108 error = sobind((struct socket *)fp->f_data, nam); 109 m_freem(nam); 110 return (error); 111 } 112 113 struct listen_args { 114 int s; 115 int backlog; 116 }; 117 118 /* ARGSUSED */ 119 listen(p, uap, retval) 120 struct proc *p; 121 register struct listen_args *uap; 122 int *retval; 123 { 124 struct file *fp; 125 int error; 126 127 if (error = getsock(p->p_fd, uap->s, &fp)) 128 return (error); 129 return (solisten((struct socket *)fp->f_data, uap->backlog)); 130 } 131 132 #ifdef COMPAT_43 133 struct accept_args { 134 int s; 135 caddr_t name; 136 int *anamelen; 137 int compat_43; 138 }; 139 140 accept(p, uap, retval) 141 struct proc *p; 142 struct accept_args *uap; 143 int *retval; 144 { 145 146 uap->compat_43 = 0; 147 return (accept1(p, uap, retval)); 148 } 149 150 struct oaccept_args { 151 int s; 152 caddr_t name; 153 int *anamelen; 154 int compat_43; 155 }; 156 157 oaccept(p, uap, retval) 158 struct proc *p; 159 struct oaccept_args *uap; 160 int *retval; 161 { 162 163 uap->compat_43 = 1; 164 return (accept1(p, uap, retval)); 165 } 166 #else /* COMPAT_43 */ 167 168 #define accept1 accept 169 #endif 170 171 struct accept1_args { 172 int s; 173 caddr_t name; 174 int *anamelen; 175 #ifdef COMPAT_43 176 int compat_43; 177 #endif 178 }; 179 180 accept1(p, uap, retval) 181 struct proc *p; 182 register struct accept1_args *uap; 183 int *retval; 184 { 185 struct file *fp; 186 struct mbuf *nam; 187 int namelen, error, s; 188 register struct socket *so; 189 190 if (uap->name && (error = copyin((caddr_t)uap->anamelen, 191 (caddr_t)&namelen, sizeof (namelen)))) 192 return (error); 193 if (error = getsock(p->p_fd, uap->s, &fp)) 194 return (error); 195 s = splnet(); 196 so = (struct socket *)fp->f_data; 197 if ((so->so_options & SO_ACCEPTCONN) == 0) { 198 splx(s); 199 return (EINVAL); 200 } 201 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { 202 splx(s); 203 return (EWOULDBLOCK); 204 } 205 while (so->so_qlen == 0 && so->so_error == 0) { 206 if (so->so_state & SS_CANTRCVMORE) { 207 so->so_error = ECONNABORTED; 208 break; 209 } 210 if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 211 netcon, 0)) { 212 splx(s); 213 return (error); 214 } 215 } 216 if (so->so_error) { 217 error = so->so_error; 218 so->so_error = 0; 219 splx(s); 220 return (error); 221 } 222 if (error = falloc(p, &fp, retval)) { 223 splx(s); 224 return (error); 225 } 226 { struct socket *aso = so->so_q; 227 if (soqremque(aso, 1) == 0) 228 panic("accept"); 229 so = aso; 230 } 231 fp->f_type = DTYPE_SOCKET; 232 fp->f_flag = FREAD|FWRITE; 233 fp->f_ops = &socketops; 234 fp->f_data = (caddr_t)so; 235 nam = m_get(M_WAIT, MT_SONAME); 236 (void) soaccept(so, nam); 237 if (uap->name) { 238 #ifdef COMPAT_43 239 if (uap->compat_43) 240 mtod(nam, struct osockaddr *)->sa_family = 241 mtod(nam, struct sockaddr *)->sa_family; 242 #endif 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), (caddr_t)uap->name, 247 (u_int)namelen)) == 0) 248 error = copyout((caddr_t)&namelen, 249 (caddr_t)uap->anamelen, sizeof (*uap->anamelen)); 250 } 251 m_freem(nam); 252 splx(s); 253 return (error); 254 } 255 256 struct connect_args { 257 int s; 258 caddr_t name; 259 int namelen; 260 }; 261 262 /* ARGSUSED */ 263 connect(p, uap, retval) 264 struct proc *p; 265 register struct connect_args *uap; 266 int *retval; 267 { 268 struct file *fp; 269 register struct socket *so; 270 struct mbuf *nam; 271 int error, s; 272 273 if (error = getsock(p->p_fd, uap->s, &fp)) 274 return (error); 275 so = (struct socket *)fp->f_data; 276 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) 277 return (EALREADY); 278 if (error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME)) 279 return (error); 280 error = soconnect(so, nam); 281 if (error) 282 goto bad; 283 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 284 m_freem(nam); 285 return (EINPROGRESS); 286 } 287 s = splnet(); 288 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 289 if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 290 netcon, 0)) 291 break; 292 if (error == 0) { 293 error = so->so_error; 294 so->so_error = 0; 295 } 296 splx(s); 297 bad: 298 so->so_state &= ~SS_ISCONNECTING; 299 m_freem(nam); 300 if (error == ERESTART) 301 error = EINTR; 302 return (error); 303 } 304 305 struct socketpair_args { 306 int domain; 307 int type; 308 int protocol; 309 int *rsv; 310 }; 311 312 socketpair(p, uap, retval) 313 struct proc *p; 314 register struct socketpair_args *uap; 315 int retval[]; 316 { 317 register struct filedesc *fdp = p->p_fd; 318 struct file *fp1, *fp2; 319 struct socket *so1, *so2; 320 int fd, error, sv[2]; 321 322 if (error = socreate(uap->domain, &so1, uap->type, uap->protocol)) 323 return (error); 324 if (error = socreate(uap->domain, &so2, uap->type, uap->protocol)) 325 goto free1; 326 if (error = falloc(p, &fp1, &fd)) 327 goto free2; 328 sv[0] = fd; 329 fp1->f_flag = FREAD|FWRITE; 330 fp1->f_type = DTYPE_SOCKET; 331 fp1->f_ops = &socketops; 332 fp1->f_data = (caddr_t)so1; 333 if (error = falloc(p, &fp2, &fd)) 334 goto free3; 335 fp2->f_flag = FREAD|FWRITE; 336 fp2->f_type = DTYPE_SOCKET; 337 fp2->f_ops = &socketops; 338 fp2->f_data = (caddr_t)so2; 339 sv[1] = fd; 340 if (error = soconnect2(so1, so2)) 341 goto free4; 342 if (uap->type == SOCK_DGRAM) { 343 /* 344 * Datagram socket connection is asymmetric. 345 */ 346 if (error = soconnect2(so2, so1)) 347 goto free4; 348 } 349 error = copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int)); 350 retval[0] = sv[0]; /* XXX ??? */ 351 retval[1] = sv[1]; /* XXX ??? */ 352 return (error); 353 free4: 354 ffree(fp2); 355 fdp->fd_ofiles[sv[1]] = 0; 356 free3: 357 ffree(fp1); 358 fdp->fd_ofiles[sv[0]] = 0; 359 free2: 360 (void)soclose(so2); 361 free1: 362 (void)soclose(so1); 363 return (error); 364 } 365 366 struct sendto_args { 367 int s; 368 caddr_t buf; 369 int len; 370 int flags; 371 caddr_t to; 372 int tolen; 373 }; 374 375 sendto(p, uap, retval) 376 struct proc *p; 377 register struct sendto_args *uap; 378 int *retval; 379 { 380 struct msghdr msg; 381 struct iovec aiov; 382 int error; 383 384 msg.msg_name = uap->to; 385 msg.msg_namelen = uap->tolen; 386 msg.msg_iov = &aiov; 387 msg.msg_iovlen = 1; 388 msg.msg_control = 0; 389 #ifdef COMPAT_43 390 msg.msg_flags = 0; 391 #endif 392 aiov.iov_base = uap->buf; 393 aiov.iov_len = uap->len; 394 return (sendit(p, uap->s, &msg, uap->flags, retval)); 395 } 396 397 #ifdef COMPAT_43 398 struct osend_args { 399 int s; 400 caddr_t buf; 401 int len; 402 int flags; 403 }; 404 405 osend(p, uap, retval) 406 struct proc *p; 407 register struct osend_args *uap; 408 int *retval; 409 { 410 struct msghdr msg; 411 struct iovec aiov; 412 413 msg.msg_name = 0; 414 msg.msg_namelen = 0; 415 msg.msg_iov = &aiov; 416 msg.msg_iovlen = 1; 417 aiov.iov_base = uap->buf; 418 aiov.iov_len = uap->len; 419 msg.msg_control = 0; 420 msg.msg_flags = 0; 421 return (sendit(p, uap->s, &msg, uap->flags, retval)); 422 } 423 424 struct osendmsg_args { 425 int s; 426 caddr_t msg; 427 int flags; 428 }; 429 430 #define MSG_COMPAT 0x8000 431 osendmsg(p, uap, retval) 432 struct proc *p; 433 register struct osendmsg_args *uap; 434 int *retval; 435 { 436 struct msghdr msg; 437 struct iovec aiov[UIO_SMALLIOV], *iov; 438 int error; 439 440 if (error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr))) 441 return (error); 442 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 443 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 444 return (EMSGSIZE); 445 MALLOC(iov, struct iovec *, 446 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 447 M_WAITOK); 448 } else 449 iov = aiov; 450 if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 451 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))) 452 goto done; 453 msg.msg_flags = MSG_COMPAT; 454 msg.msg_iov = iov; 455 error = sendit(p, uap->s, &msg, uap->flags, retval); 456 done: 457 if (iov != aiov) 458 FREE(iov, M_IOV); 459 return (error); 460 } 461 #endif 462 463 struct sendmsg_args { 464 int s; 465 caddr_t msg; 466 int flags; 467 }; 468 469 sendmsg(p, uap, retval) 470 struct proc *p; 471 register struct sendmsg_args *uap; 472 int *retval; 473 { 474 struct msghdr msg; 475 struct iovec aiov[UIO_SMALLIOV], *iov; 476 int error; 477 478 if (error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg))) 479 return (error); 480 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 481 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 482 return (EMSGSIZE); 483 MALLOC(iov, struct iovec *, 484 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 485 M_WAITOK); 486 } else 487 iov = aiov; 488 if (msg.msg_iovlen && 489 (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 490 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) 491 goto done; 492 msg.msg_iov = iov; 493 #ifdef COMPAT_43 494 msg.msg_flags = 0; 495 #endif 496 error = sendit(p, uap->s, &msg, uap->flags, retval); 497 done: 498 if (iov != aiov) 499 FREE(iov, M_IOV); 500 return (error); 501 } 502 503 sendit(p, s, mp, flags, retsize) 504 register struct proc *p; 505 int s; 506 register struct msghdr *mp; 507 int flags, *retsize; 508 { 509 struct file *fp; 510 struct uio auio; 511 register struct iovec *iov; 512 register int i; 513 struct mbuf *to, *control; 514 int len, error; 515 #ifdef KTRACE 516 struct iovec *ktriov = NULL; 517 #endif 518 519 if (error = getsock(p->p_fd, s, &fp)) 520 return (error); 521 auio.uio_iov = mp->msg_iov; 522 auio.uio_iovcnt = mp->msg_iovlen; 523 auio.uio_segflg = UIO_USERSPACE; 524 auio.uio_rw = UIO_WRITE; 525 auio.uio_procp = p; 526 auio.uio_offset = 0; /* XXX */ 527 auio.uio_resid = 0; 528 iov = mp->msg_iov; 529 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 530 if (iov->iov_len < 0) 531 return (EINVAL); 532 if ((auio.uio_resid += iov->iov_len) < 0) 533 return (EINVAL); 534 } 535 if (mp->msg_name) { 536 if (error = sockargs(&to, mp->msg_name, mp->msg_namelen, 537 MT_SONAME)) 538 return (error); 539 } else 540 to = 0; 541 if (mp->msg_control) { 542 if (mp->msg_controllen < sizeof(struct cmsghdr) 543 #ifdef COMPAT_43 544 && mp->msg_flags != MSG_COMPAT 545 #endif 546 ) { 547 error = EINVAL; 548 goto bad; 549 } 550 if (error = sockargs(&control, mp->msg_control, 551 mp->msg_controllen, MT_CONTROL)) 552 goto bad; 553 #ifdef COMPAT_43 554 if (mp->msg_flags == MSG_COMPAT) { 555 register struct cmsghdr *cm; 556 557 M_PREPEND(control, sizeof(*cm), M_WAIT); 558 if (control == 0) { 559 error = ENOBUFS; 560 goto bad; 561 } else { 562 cm = mtod(control, struct cmsghdr *); 563 cm->cmsg_len = control->m_len; 564 cm->cmsg_level = SOL_SOCKET; 565 cm->cmsg_type = SCM_RIGHTS; 566 } 567 } 568 #endif 569 } else 570 control = 0; 571 #ifdef KTRACE 572 if (KTRPOINT(p, KTR_GENIO)) { 573 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 574 575 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 576 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 577 } 578 #endif 579 len = auio.uio_resid; 580 if (error = sosend((struct socket *)fp->f_data, to, &auio, 581 (struct mbuf *)0, control, flags)) { 582 if (auio.uio_resid != len && (error == ERESTART || 583 error == EINTR || error == EWOULDBLOCK)) 584 error = 0; 585 if (error == EPIPE) 586 psignal(p, SIGPIPE); 587 } 588 if (error == 0) 589 *retsize = len - auio.uio_resid; 590 #ifdef KTRACE 591 if (ktriov != NULL) { 592 if (error == 0) 593 ktrgenio(p->p_tracep, s, UIO_WRITE, 594 ktriov, *retsize, error); 595 FREE(ktriov, M_TEMP); 596 } 597 #endif 598 bad: 599 if (to) 600 m_freem(to); 601 return (error); 602 } 603 604 #ifdef COMPAT_43 605 struct orecvfrom_args { 606 int s; 607 caddr_t buf; 608 int len; 609 int flags; 610 caddr_t from; 611 int *fromlenaddr; 612 }; 613 614 orecvfrom(p, uap, retval) 615 struct proc *p; 616 struct orecvfrom_args *uap; 617 int *retval; 618 { 619 620 uap->flags |= MSG_COMPAT; 621 return (recvfrom(p, uap, retval)); 622 } 623 #endif 624 625 struct recvfrom_args { 626 int s; 627 caddr_t buf; 628 int len; 629 int flags; 630 caddr_t from; 631 int *fromlenaddr; 632 }; 633 634 recvfrom(p, uap, retval) 635 struct proc *p; 636 register struct recvfrom_args *uap; 637 int *retval; 638 { 639 struct msghdr msg; 640 struct iovec aiov; 641 int error; 642 643 if (uap->fromlenaddr) { 644 if (error = copyin((caddr_t)uap->fromlenaddr, 645 (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen))) 646 return (error); 647 } else 648 msg.msg_namelen = 0; 649 msg.msg_name = uap->from; 650 msg.msg_iov = &aiov; 651 msg.msg_iovlen = 1; 652 aiov.iov_base = uap->buf; 653 aiov.iov_len = uap->len; 654 msg.msg_control = 0; 655 msg.msg_flags = uap->flags; 656 return (recvit(p, uap->s, &msg, (caddr_t)uap->fromlenaddr, retval)); 657 } 658 659 #ifdef COMPAT_43 660 struct orecv_args { 661 int s; 662 caddr_t buf; 663 int len; 664 int flags; 665 }; 666 667 orecv(p, uap, retval) 668 struct proc *p; 669 register struct orecv_args *uap; 670 int *retval; 671 { 672 struct msghdr msg; 673 struct iovec aiov; 674 675 msg.msg_name = 0; 676 msg.msg_namelen = 0; 677 msg.msg_iov = &aiov; 678 msg.msg_iovlen = 1; 679 aiov.iov_base = uap->buf; 680 aiov.iov_len = uap->len; 681 msg.msg_control = 0; 682 msg.msg_flags = uap->flags; 683 return (recvit(p, uap->s, &msg, (caddr_t)0, retval)); 684 } 685 686 struct orecvmsg_args { 687 int s; 688 struct omsghdr *msg; 689 int flags; 690 }; 691 692 /* 693 * Old recvmsg. This code takes advantage of the fact that the old msghdr 694 * overlays the new one, missing only the flags, and with the (old) access 695 * rights where the control fields are now. 696 */ 697 orecvmsg(p, uap, retval) 698 struct proc *p; 699 register struct orecvmsg_args *uap; 700 int *retval; 701 { 702 struct msghdr msg; 703 struct iovec aiov[UIO_SMALLIOV], *iov; 704 int error; 705 706 if (error = copyin((caddr_t)uap->msg, (caddr_t)&msg, 707 sizeof (struct omsghdr))) 708 return (error); 709 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 710 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 711 return (EMSGSIZE); 712 MALLOC(iov, struct iovec *, 713 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 714 M_WAITOK); 715 } else 716 iov = aiov; 717 msg.msg_flags = uap->flags | MSG_COMPAT; 718 if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 719 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))) 720 goto done; 721 msg.msg_iov = iov; 722 error = recvit(p, uap->s, &msg, (caddr_t)&uap->msg->msg_namelen, retval); 723 724 if (msg.msg_controllen && error == 0) 725 error = copyout((caddr_t)&msg.msg_controllen, 726 (caddr_t)&uap->msg->msg_accrightslen, sizeof (int)); 727 done: 728 if (iov != aiov) 729 FREE(iov, M_IOV); 730 return (error); 731 } 732 #endif 733 734 struct recvmsg_args { 735 int s; 736 struct msghdr *msg; 737 int flags; 738 }; 739 740 recvmsg(p, uap, retval) 741 struct proc *p; 742 register struct recvmsg_args *uap; 743 int *retval; 744 { 745 struct msghdr msg; 746 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 747 register int error; 748 749 if (error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg))) 750 return (error); 751 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 752 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 753 return (EMSGSIZE); 754 MALLOC(iov, struct iovec *, 755 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 756 M_WAITOK); 757 } else 758 iov = aiov; 759 #ifdef COMPAT_43 760 msg.msg_flags = uap->flags &~ MSG_COMPAT; 761 #else 762 msg.msg_flags = uap->flags; 763 #endif 764 uiov = msg.msg_iov; 765 msg.msg_iov = iov; 766 if (error = copyin((caddr_t)uiov, (caddr_t)iov, 767 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))) 768 goto done; 769 if ((error = recvit(p, uap->s, &msg, (caddr_t)0, retval)) == 0) { 770 msg.msg_iov = uiov; 771 error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg)); 772 } 773 done: 774 if (iov != aiov) 775 FREE(iov, M_IOV); 776 return (error); 777 } 778 779 recvit(p, s, mp, namelenp, retsize) 780 register struct proc *p; 781 int s; 782 register struct msghdr *mp; 783 caddr_t namelenp; 784 int *retsize; 785 { 786 struct file *fp; 787 struct uio auio; 788 register struct iovec *iov; 789 register int i; 790 int len, error; 791 struct mbuf *from = 0, *control = 0; 792 #ifdef KTRACE 793 struct iovec *ktriov = NULL; 794 #endif 795 796 if (error = getsock(p->p_fd, s, &fp)) 797 return (error); 798 auio.uio_iov = mp->msg_iov; 799 auio.uio_iovcnt = mp->msg_iovlen; 800 auio.uio_segflg = UIO_USERSPACE; 801 auio.uio_rw = UIO_READ; 802 auio.uio_procp = p; 803 auio.uio_offset = 0; /* XXX */ 804 auio.uio_resid = 0; 805 iov = mp->msg_iov; 806 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 807 if (iov->iov_len < 0) 808 return (EINVAL); 809 if ((auio.uio_resid += iov->iov_len) < 0) 810 return (EINVAL); 811 } 812 #ifdef KTRACE 813 if (KTRPOINT(p, KTR_GENIO)) { 814 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 815 816 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 817 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 818 } 819 #endif 820 len = auio.uio_resid; 821 if (error = soreceive((struct socket *)fp->f_data, &from, &auio, 822 (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, 823 &mp->msg_flags)) { 824 if (auio.uio_resid != len && (error == ERESTART || 825 error == EINTR || error == EWOULDBLOCK)) 826 error = 0; 827 } 828 #ifdef KTRACE 829 if (ktriov != NULL) { 830 if (error == 0) 831 ktrgenio(p->p_tracep, s, UIO_READ, 832 ktriov, len - auio.uio_resid, error); 833 FREE(ktriov, M_TEMP); 834 } 835 #endif 836 if (error) 837 goto out; 838 *retsize = len - auio.uio_resid; 839 if (mp->msg_name) { 840 len = mp->msg_namelen; 841 if (len <= 0 || from == 0) 842 len = 0; 843 else { 844 #ifdef COMPAT_43 845 if (mp->msg_flags & MSG_COMPAT) 846 mtod(from, struct osockaddr *)->sa_family = 847 mtod(from, struct sockaddr *)->sa_family; 848 #endif 849 if (len > from->m_len) 850 len = from->m_len; 851 /* else if len < from->m_len ??? */ 852 if (error = copyout(mtod(from, caddr_t), 853 (caddr_t)mp->msg_name, (unsigned)len)) 854 goto out; 855 } 856 mp->msg_namelen = len; 857 if (namelenp && 858 (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { 859 #ifdef COMPAT_43 860 if (mp->msg_flags & MSG_COMPAT) 861 error = 0; /* old recvfrom didn't check */ 862 else 863 #endif 864 goto out; 865 } 866 } 867 if (mp->msg_control) { 868 #ifdef COMPAT_43 869 /* 870 * We assume that old recvmsg calls won't receive access 871 * rights and other control info, esp. as control info 872 * is always optional and those options didn't exist in 4.3. 873 * If we receive rights, trim the cmsghdr; anything else 874 * is tossed. 875 */ 876 if (control && mp->msg_flags & MSG_COMPAT) { 877 if (mtod(control, struct cmsghdr *)->cmsg_level != 878 SOL_SOCKET || 879 mtod(control, struct cmsghdr *)->cmsg_type != 880 SCM_RIGHTS) { 881 mp->msg_controllen = 0; 882 goto out; 883 } 884 control->m_len -= sizeof (struct cmsghdr); 885 control->m_data += sizeof (struct cmsghdr); 886 } 887 #endif 888 len = mp->msg_controllen; 889 if (len <= 0 || control == 0) 890 len = 0; 891 else { 892 if (len >= control->m_len) 893 len = control->m_len; 894 else 895 mp->msg_flags |= MSG_CTRUNC; 896 error = copyout((caddr_t)mtod(control, caddr_t), 897 (caddr_t)mp->msg_control, (unsigned)len); 898 } 899 mp->msg_controllen = len; 900 } 901 out: 902 if (from) 903 m_freem(from); 904 if (control) 905 m_freem(control); 906 return (error); 907 } 908 909 struct shutdown_args { 910 int s; 911 int how; 912 }; 913 914 /* ARGSUSED */ 915 shutdown(p, uap, retval) 916 struct proc *p; 917 register struct shutdown_args *uap; 918 int *retval; 919 { 920 struct file *fp; 921 int error; 922 923 if (error = getsock(p->p_fd, uap->s, &fp)) 924 return (error); 925 return (soshutdown((struct socket *)fp->f_data, uap->how)); 926 } 927 928 struct setsockopt_args { 929 int s; 930 int level; 931 int name; 932 caddr_t val; 933 int valsize; 934 }; 935 936 /* ARGSUSED */ 937 setsockopt(p, uap, retval) 938 struct proc *p; 939 register struct setsockopt_args *uap; 940 int *retval; 941 { 942 struct file *fp; 943 struct mbuf *m = NULL; 944 int error; 945 946 if (error = getsock(p->p_fd, uap->s, &fp)) 947 return (error); 948 if (uap->valsize > MLEN) 949 return (EINVAL); 950 if (uap->val) { 951 m = m_get(M_WAIT, MT_SOOPTS); 952 if (m == NULL) 953 return (ENOBUFS); 954 if (error = copyin(uap->val, mtod(m, caddr_t), 955 (u_int)uap->valsize)) { 956 (void) m_free(m); 957 return (error); 958 } 959 m->m_len = uap->valsize; 960 } 961 return (sosetopt((struct socket *)fp->f_data, uap->level, 962 uap->name, m)); 963 } 964 965 struct getsockopt_args { 966 int s; 967 int level; 968 int name; 969 caddr_t val; 970 int *avalsize; 971 }; 972 973 /* ARGSUSED */ 974 getsockopt(p, uap, retval) 975 struct proc *p; 976 register struct getsockopt_args *uap; 977 int *retval; 978 { 979 struct file *fp; 980 struct mbuf *m = NULL; 981 int valsize, error; 982 983 if (error = getsock(p->p_fd, uap->s, &fp)) 984 return (error); 985 if (uap->val) { 986 if (error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 987 sizeof (valsize))) 988 return (error); 989 } else 990 valsize = 0; 991 if ((error = sogetopt((struct socket *)fp->f_data, uap->level, 992 uap->name, &m)) == 0 && uap->val && valsize && m != NULL) { 993 if (valsize > m->m_len) 994 valsize = m->m_len; 995 error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); 996 if (error == 0) 997 error = copyout((caddr_t)&valsize, 998 (caddr_t)uap->avalsize, sizeof (valsize)); 999 } 1000 if (m != NULL) 1001 (void) m_free(m); 1002 return (error); 1003 } 1004 1005 /* ARGSUSED */ 1006 pipe(p, uap, retval) 1007 struct proc *p; 1008 struct args *uap; 1009 int retval[]; 1010 { 1011 register struct filedesc *fdp = p->p_fd; 1012 struct file *rf, *wf; 1013 struct socket *rso, *wso; 1014 int fd, error; 1015 1016 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) 1017 return (error); 1018 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) 1019 goto free1; 1020 if (error = falloc(p, &rf, &fd)) 1021 goto free2; 1022 retval[0] = fd; 1023 rf->f_flag = FREAD; 1024 rf->f_type = DTYPE_SOCKET; 1025 rf->f_ops = &socketops; 1026 rf->f_data = (caddr_t)rso; 1027 if (error = falloc(p, &wf, &fd)) 1028 goto free3; 1029 wf->f_flag = FWRITE; 1030 wf->f_type = DTYPE_SOCKET; 1031 wf->f_ops = &socketops; 1032 wf->f_data = (caddr_t)wso; 1033 retval[1] = fd; 1034 if (error = unp_connect2(wso, rso)) 1035 goto free4; 1036 return (0); 1037 free4: 1038 ffree(wf); 1039 fdp->fd_ofiles[retval[1]] = 0; 1040 free3: 1041 ffree(rf); 1042 fdp->fd_ofiles[retval[0]] = 0; 1043 free2: 1044 (void)soclose(wso); 1045 free1: 1046 (void)soclose(rso); 1047 return (error); 1048 } 1049 1050 /* 1051 * Get socket name. 1052 */ 1053 #ifdef COMPAT_43 1054 struct getsockname_args { 1055 int fdes; 1056 caddr_t asa; 1057 int *alen; 1058 int compat_43; 1059 }; 1060 1061 getsockname(p, uap, retval) 1062 struct proc *p; 1063 struct getsockname_args *uap; 1064 int *retval; 1065 { 1066 1067 uap->compat_43 = 0; 1068 return (getsockname1(p, uap, retval)); 1069 } 1070 1071 struct ogetsockname_args { 1072 int fdes; 1073 caddr_t asa; 1074 int *alen; 1075 int compat_43; 1076 }; 1077 1078 ogetsockname(p, uap, retval) 1079 struct proc *p; 1080 struct ogetsockname_args *uap; 1081 int *retval; 1082 { 1083 1084 uap->compat_43 = 1; 1085 return (getsockname1(p, uap, retval)); 1086 } 1087 #else /* COMPAT_43 */ 1088 1089 #define getsockname1 getsockname 1090 #endif 1091 1092 struct getsockname1_args { 1093 int fdes; 1094 caddr_t asa; 1095 int *alen; 1096 #ifdef COMPAT_43 1097 int compat_43; 1098 #endif 1099 }; 1100 1101 /* ARGSUSED */ 1102 getsockname1(p, uap, retval) 1103 struct proc *p; 1104 register struct getsockname1_args *uap; 1105 int *retval; 1106 { 1107 struct file *fp; 1108 register struct socket *so; 1109 struct mbuf *m; 1110 int len, error; 1111 1112 if (error = getsock(p->p_fd, uap->fdes, &fp)) 1113 return (error); 1114 if (error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len))) 1115 return (error); 1116 so = (struct socket *)fp->f_data; 1117 m = m_getclr(M_WAIT, MT_SONAME); 1118 if (m == NULL) 1119 return (ENOBUFS); 1120 if (error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0)) 1121 goto bad; 1122 if (len > m->m_len) 1123 len = m->m_len; 1124 #ifdef COMPAT_43 1125 if (uap->compat_43) 1126 mtod(m, struct osockaddr *)->sa_family = 1127 mtod(m, struct sockaddr *)->sa_family; 1128 #endif 1129 error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 1130 if (error == 0) 1131 error = copyout((caddr_t)&len, (caddr_t)uap->alen, 1132 sizeof (len)); 1133 bad: 1134 m_freem(m); 1135 return (error); 1136 } 1137 1138 /* 1139 * Get name of peer for connected socket. 1140 */ 1141 #ifdef COMPAT_43 1142 struct getpeername_args { 1143 int fdes; 1144 caddr_t asa; 1145 int *alen; 1146 int compat_43; 1147 }; 1148 1149 getpeername(p, uap, retval) 1150 struct proc *p; 1151 struct getpeername_args *uap; 1152 int *retval; 1153 { 1154 1155 uap->compat_43 = 0; 1156 return (getpeername1(p, uap, retval)); 1157 } 1158 1159 struct ogetpeername_args { 1160 int fdes; 1161 caddr_t asa; 1162 int *alen; 1163 int compat_43; 1164 }; 1165 1166 ogetpeername(p, uap, retval) 1167 struct proc *p; 1168 struct ogetpeername_args *uap; 1169 int *retval; 1170 { 1171 1172 uap->compat_43 = 1; 1173 return (getpeername1(p, uap, retval)); 1174 } 1175 #else /* COMPAT_43 */ 1176 1177 #define getpeername1 getpeername 1178 #endif 1179 1180 struct getpeername1_args { 1181 int fdes; 1182 caddr_t asa; 1183 int *alen; 1184 #ifdef COMPAT_43 1185 int compat_43; 1186 #endif 1187 }; 1188 1189 /* ARGSUSED */ 1190 getpeername1(p, uap, retval) 1191 struct proc *p; 1192 register struct getpeername1_args *uap; 1193 int *retval; 1194 { 1195 struct file *fp; 1196 register struct socket *so; 1197 struct mbuf *m; 1198 int len, error; 1199 1200 if (error = getsock(p->p_fd, uap->fdes, &fp)) 1201 return (error); 1202 so = (struct socket *)fp->f_data; 1203 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) 1204 return (ENOTCONN); 1205 m = m_getclr(M_WAIT, MT_SONAME); 1206 if (m == NULL) 1207 return (ENOBUFS); 1208 if (error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len))) 1209 return (error); 1210 if (error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0)) 1211 goto bad; 1212 if (len > m->m_len) 1213 len = m->m_len; 1214 #ifdef COMPAT_43 1215 if (uap->compat_43) 1216 mtod(m, struct osockaddr *)->sa_family = 1217 mtod(m, struct sockaddr *)->sa_family; 1218 #endif 1219 if (error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len)) 1220 goto bad; 1221 error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); 1222 bad: 1223 m_freem(m); 1224 return (error); 1225 } 1226 1227 sockargs(mp, buf, buflen, type) 1228 struct mbuf **mp; 1229 caddr_t buf; 1230 int buflen, type; 1231 { 1232 register struct mbuf *m; 1233 int error; 1234 1235 if ((u_int)buflen > MLEN) { 1236 #ifdef COMPAT_43 1237 if (type == MT_SONAME && (u_int)buflen <= 112) 1238 buflen = MLEN; /* unix domain compat. hack */ 1239 else 1240 #endif 1241 return (EINVAL); 1242 } 1243 m = m_get(M_WAIT, type); 1244 if (m == NULL) 1245 return (ENOBUFS); 1246 m->m_len = buflen; 1247 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen); 1248 if (error) { 1249 (void) m_free(m); 1250 return(error); 1251 } 1252 *mp = m; 1253 if (type == MT_SONAME) { 1254 register struct sockaddr *sa = mtod(m, struct sockaddr *); 1255 1256 #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN 1257 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1258 sa->sa_family = sa->sa_len; 1259 #endif 1260 sa->sa_len = buflen; 1261 } 1262 return (0); 1263 } 1264 1265 getsock(fdp, fdes, fpp) 1266 struct filedesc *fdp; 1267 int fdes; 1268 struct file **fpp; 1269 { 1270 register struct file *fp; 1271 1272 if ((unsigned)fdes >= fdp->fd_nfiles || 1273 (fp = fdp->fd_ofiles[fdes]) == NULL) 1274 return (EBADF); 1275 if (fp->f_type != DTYPE_SOCKET) 1276 return (ENOTSOCK); 1277 *fpp = fp; 1278 return (0); 1279 } 1280