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