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