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