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