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