kern_sendfile.c revision 14093
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.13 1996/01/28 23:41:40 dyson Exp $ 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 register struct socket *so; 171 172 if (uap->name) { 173 error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, 174 sizeof (namelen)); 175 if(error) 176 return (error); 177 } 178 error = getsock(p->p_fd, uap->s, &fp); 179 if (error) 180 return (error); 181 s = splnet(); 182 so = (struct socket *)fp->f_data; 183 if ((so->so_options & SO_ACCEPTCONN) == 0) { 184 splx(s); 185 return (EINVAL); 186 } 187 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { 188 splx(s); 189 return (EWOULDBLOCK); 190 } 191 while (so->so_qlen == 0 && so->so_error == 0) { 192 if (so->so_state & SS_CANTRCVMORE) { 193 so->so_error = ECONNABORTED; 194 break; 195 } 196 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 197 "accept", 0); 198 if (error) { 199 splx(s); 200 return (error); 201 } 202 } 203 if (so->so_error) { 204 error = so->so_error; 205 so->so_error = 0; 206 splx(s); 207 return (error); 208 } 209 error = falloc(p, &fp, retval); 210 if (error) { 211 splx(s); 212 return (error); 213 } 214 { struct socket *aso = so->so_q; 215 if (soqremque(aso, 1) == 0) 216 panic("accept"); 217 so = aso; 218 } 219 fp->f_type = DTYPE_SOCKET; 220 fp->f_flag = FREAD|FWRITE; 221 fp->f_ops = &socketops; 222 fp->f_data = (caddr_t)so; 223 nam = m_get(M_WAIT, MT_SONAME); 224 (void) soaccept(so, nam); 225 if (uap->name) { 226#ifdef COMPAT_OLDSOCK 227 if (compat) 228 mtod(nam, struct osockaddr *)->sa_family = 229 mtod(nam, struct sockaddr *)->sa_family; 230#endif 231 if (namelen > nam->m_len) 232 namelen = nam->m_len; 233 /* SHOULD COPY OUT A CHAIN HERE */ 234 error = copyout(mtod(nam, caddr_t), (caddr_t)uap->name, 235 (u_int)namelen); 236 if (!error) 237 error = copyout((caddr_t)&namelen, 238 (caddr_t)uap->anamelen, sizeof (*uap->anamelen)); 239 } 240 m_freem(nam); 241 splx(s); 242 return (error); 243} 244 245int 246accept(p, uap, retval) 247 struct proc *p; 248 struct accept_args *uap; 249 int *retval; 250{ 251 252 return (accept1(p, uap, retval, 0)); 253} 254 255#ifdef COMPAT_OLDSOCK 256int 257oaccept(p, uap, retval) 258 struct proc *p; 259 struct accept_args *uap; 260 int *retval; 261{ 262 263 return (accept1(p, uap, retval, 1)); 264} 265#endif /* COMPAT_OLDSOCK */ 266 267/* ARGSUSED */ 268int 269connect(p, uap, retval) 270 struct proc *p; 271 register struct connect_args /* { 272 int s; 273 caddr_t name; 274 int namelen; 275 } */ *uap; 276 int *retval; 277{ 278 struct file *fp; 279 register struct socket *so; 280 struct mbuf *nam; 281 int error, s; 282 283 error = getsock(p->p_fd, uap->s, &fp); 284 if (error) 285 return (error); 286 so = (struct socket *)fp->f_data; 287 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) 288 return (EALREADY); 289 error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME); 290 if (error) 291 return (error); 292 error = soconnect(so, nam); 293 if (error) 294 goto bad; 295 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 296 m_freem(nam); 297 return (EINPROGRESS); 298 } 299 s = splnet(); 300 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 301 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 302 "connec", 0); 303 if (error) 304 break; 305 } 306 if (error == 0) { 307 error = so->so_error; 308 so->so_error = 0; 309 } 310 splx(s); 311bad: 312 so->so_state &= ~SS_ISCONNECTING; 313 m_freem(nam); 314 if (error == ERESTART) 315 error = EINTR; 316 return (error); 317} 318 319int 320socketpair(p, uap, retval) 321 struct proc *p; 322 register struct socketpair_args /* { 323 int domain; 324 int type; 325 int protocol; 326 int *rsv; 327 } */ *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, p); 336 if (error) 337 return (error); 338 error = socreate(uap->domain, &so2, uap->type, uap->protocol, p); 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); 372free4: 373 ffree(fp2); 374 fdp->fd_ofiles[sv[1]] = 0; 375free3: 376 ffree(fp1); 377 fdp->fd_ofiles[sv[0]] = 0; 378free2: 379 (void)soclose(so2); 380free1: 381 (void)soclose(so1); 382 return (error); 383} 384 385int 386sendit(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 482bad: 483 if (to) 484 m_freem(to); 485 return (error); 486} 487 488int 489sendto(p, uap, retval) 490 struct proc *p; 491 register struct sendto_args /* { 492 int s; 493 caddr_t buf; 494 size_t len; 495 int flags; 496 caddr_t to; 497 int tolen; 498 } */ *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 518int 519osend(p, uap, retval) 520 struct proc *p; 521 register struct osend_args /* { 522 int s; 523 caddr_t buf; 524 int len; 525 int flags; 526 } */ *uap; 527 int *retval; 528{ 529 struct msghdr msg; 530 struct iovec aiov; 531 532 msg.msg_name = 0; 533 msg.msg_namelen = 0; 534 msg.msg_iov = &aiov; 535 msg.msg_iovlen = 1; 536 aiov.iov_base = uap->buf; 537 aiov.iov_len = uap->len; 538 msg.msg_control = 0; 539 msg.msg_flags = 0; 540 return (sendit(p, uap->s, &msg, uap->flags, retval)); 541} 542 543int 544osendmsg(p, uap, retval) 545 struct proc *p; 546 register struct osendmsg_args /* { 547 int s; 548 caddr_t msg; 549 int flags; 550 } */ *uap; 551 int *retval; 552{ 553 struct msghdr msg; 554 struct iovec aiov[UIO_SMALLIOV], *iov; 555 int error; 556 557 error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr)); 558 if (error) 559 return (error); 560 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 561 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 562 return (EMSGSIZE); 563 MALLOC(iov, struct iovec *, 564 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 565 M_WAITOK); 566 } else 567 iov = aiov; 568 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 569 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 570 if (error) 571 goto done; 572 msg.msg_flags = MSG_COMPAT; 573 msg.msg_iov = iov; 574 error = sendit(p, uap->s, &msg, uap->flags, retval); 575done: 576 if (iov != aiov) 577 FREE(iov, M_IOV); 578 return (error); 579} 580#endif 581 582int 583sendmsg(p, uap, retval) 584 struct proc *p; 585 register struct sendmsg_args /* { 586 int s; 587 caddr_t msg; 588 int flags; 589 } */ *uap; 590 int *retval; 591{ 592 struct msghdr msg; 593 struct iovec aiov[UIO_SMALLIOV], *iov; 594 int error; 595 596 error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); 597 if (error) 598 return (error); 599 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 600 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 601 return (EMSGSIZE); 602 MALLOC(iov, struct iovec *, 603 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 604 M_WAITOK); 605 } else 606 iov = aiov; 607 if (msg.msg_iovlen && 608 (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 609 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) 610 goto done; 611 msg.msg_iov = iov; 612#ifdef COMPAT_OLDSOCK 613 msg.msg_flags = 0; 614#endif 615 error = sendit(p, uap->s, &msg, uap->flags, retval); 616done: 617 if (iov != aiov) 618 FREE(iov, M_IOV); 619 return (error); 620} 621 622int 623recvit(p, s, mp, namelenp, retsize) 624 register struct proc *p; 625 int s; 626 register struct msghdr *mp; 627 caddr_t namelenp; 628 int *retsize; 629{ 630 struct file *fp; 631 struct uio auio; 632 register struct iovec *iov; 633 register int i; 634 int len, error; 635 struct mbuf *from = 0, *control = 0; 636#ifdef KTRACE 637 struct iovec *ktriov = NULL; 638#endif 639 640 error = getsock(p->p_fd, s, &fp); 641 if (error) 642 return (error); 643 auio.uio_iov = mp->msg_iov; 644 auio.uio_iovcnt = mp->msg_iovlen; 645 auio.uio_segflg = UIO_USERSPACE; 646 auio.uio_rw = UIO_READ; 647 auio.uio_procp = p; 648 auio.uio_offset = 0; /* XXX */ 649 auio.uio_resid = 0; 650 iov = mp->msg_iov; 651 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 652 if ((auio.uio_resid += iov->iov_len) < 0) 653 return (EINVAL); 654 } 655#ifdef KTRACE 656 if (KTRPOINT(p, KTR_GENIO)) { 657 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 658 659 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 660 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 661 } 662#endif 663 len = auio.uio_resid; 664 error = soreceive((struct socket *)fp->f_data, &from, &auio, 665 (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, 666 &mp->msg_flags); 667 if (error) { 668 if (auio.uio_resid != len && (error == ERESTART || 669 error == EINTR || error == EWOULDBLOCK)) 670 error = 0; 671 } 672#ifdef KTRACE 673 if (ktriov != NULL) { 674 if (error == 0) 675 ktrgenio(p->p_tracep, s, UIO_READ, 676 ktriov, len - auio.uio_resid, error); 677 FREE(ktriov, M_TEMP); 678 } 679#endif 680 if (error) 681 goto out; 682 *retsize = len - auio.uio_resid; 683 if (mp->msg_name) { 684 len = mp->msg_namelen; 685 if (len <= 0 || from == 0) 686 len = 0; 687 else { 688#ifdef COMPAT_OLDSOCK 689 if (mp->msg_flags & MSG_COMPAT) 690 mtod(from, struct osockaddr *)->sa_family = 691 mtod(from, struct sockaddr *)->sa_family; 692#endif 693 if (len > from->m_len) 694 len = from->m_len; 695 /* else if len < from->m_len ??? */ 696 error = copyout(mtod(from, caddr_t), 697 (caddr_t)mp->msg_name, (unsigned)len); 698 if (error) 699 goto out; 700 } 701 mp->msg_namelen = len; 702 if (namelenp && 703 (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { 704#ifdef COMPAT_OLDSOCK 705 if (mp->msg_flags & MSG_COMPAT) 706 error = 0; /* old recvfrom didn't check */ 707 else 708#endif 709 goto out; 710 } 711 } 712 if (mp->msg_control) { 713#ifdef COMPAT_OLDSOCK 714 /* 715 * We assume that old recvmsg calls won't receive access 716 * rights and other control info, esp. as control info 717 * is always optional and those options didn't exist in 4.3. 718 * If we receive rights, trim the cmsghdr; anything else 719 * is tossed. 720 */ 721 if (control && mp->msg_flags & MSG_COMPAT) { 722 if (mtod(control, struct cmsghdr *)->cmsg_level != 723 SOL_SOCKET || 724 mtod(control, struct cmsghdr *)->cmsg_type != 725 SCM_RIGHTS) { 726 mp->msg_controllen = 0; 727 goto out; 728 } 729 control->m_len -= sizeof (struct cmsghdr); 730 control->m_data += sizeof (struct cmsghdr); 731 } 732#endif 733 len = mp->msg_controllen; 734 if (len <= 0 || control == 0) 735 len = 0; 736 else { 737 if (len >= control->m_len) 738 len = control->m_len; 739 else 740 mp->msg_flags |= MSG_CTRUNC; 741 error = copyout((caddr_t)mtod(control, caddr_t), 742 (caddr_t)mp->msg_control, (unsigned)len); 743 } 744 mp->msg_controllen = len; 745 } 746out: 747 if (from) 748 m_freem(from); 749 if (control) 750 m_freem(control); 751 return (error); 752} 753 754int 755recvfrom(p, uap, retval) 756 struct proc *p; 757 register struct recvfrom_args /* { 758 int s; 759 caddr_t buf; 760 size_t len; 761 int flags; 762 caddr_t from; 763 int *fromlenaddr; 764 } */ *uap; 765 int *retval; 766{ 767 struct msghdr msg; 768 struct iovec aiov; 769 int error; 770 771 if (uap->fromlenaddr) { 772 error = copyin((caddr_t)uap->fromlenaddr, 773 (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen)); 774 if (error) 775 return (error); 776 } else 777 msg.msg_namelen = 0; 778 msg.msg_name = uap->from; 779 msg.msg_iov = &aiov; 780 msg.msg_iovlen = 1; 781 aiov.iov_base = uap->buf; 782 aiov.iov_len = uap->len; 783 msg.msg_control = 0; 784 msg.msg_flags = uap->flags; 785 return (recvit(p, uap->s, &msg, (caddr_t)uap->fromlenaddr, retval)); 786} 787 788#ifdef COMPAT_OLDSOCK 789int 790orecvfrom(p, uap, retval) 791 struct proc *p; 792 struct recvfrom_args *uap; 793 int *retval; 794{ 795 796 uap->flags |= MSG_COMPAT; 797 return (recvfrom(p, uap, retval)); 798} 799#endif 800 801 802#ifdef COMPAT_OLDSOCK 803int 804orecv(p, uap, retval) 805 struct proc *p; 806 register struct orecv_args /* { 807 int s; 808 caddr_t buf; 809 int len; 810 int flags; 811 } */ *uap; 812 int *retval; 813{ 814 struct msghdr msg; 815 struct iovec aiov; 816 817 msg.msg_name = 0; 818 msg.msg_namelen = 0; 819 msg.msg_iov = &aiov; 820 msg.msg_iovlen = 1; 821 aiov.iov_base = uap->buf; 822 aiov.iov_len = uap->len; 823 msg.msg_control = 0; 824 msg.msg_flags = uap->flags; 825 return (recvit(p, uap->s, &msg, (caddr_t)0, retval)); 826} 827 828/* 829 * Old recvmsg. This code takes advantage of the fact that the old msghdr 830 * overlays the new one, missing only the flags, and with the (old) access 831 * rights where the control fields are now. 832 */ 833int 834orecvmsg(p, uap, retval) 835 struct proc *p; 836 register struct orecvmsg_args /* { 837 int s; 838 struct omsghdr *msg; 839 int flags; 840 } */ *uap; 841 int *retval; 842{ 843 struct msghdr msg; 844 struct iovec aiov[UIO_SMALLIOV], *iov; 845 int error; 846 847 error = copyin((caddr_t)uap->msg, (caddr_t)&msg, 848 sizeof (struct omsghdr)); 849 if (error) 850 return (error); 851 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 852 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 853 return (EMSGSIZE); 854 MALLOC(iov, struct iovec *, 855 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 856 M_WAITOK); 857 } else 858 iov = aiov; 859 msg.msg_flags = uap->flags | MSG_COMPAT; 860 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 861 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 862 if (error) 863 goto done; 864 msg.msg_iov = iov; 865 error = recvit(p, uap->s, &msg, (caddr_t)&uap->msg->msg_namelen, retval); 866 867 if (msg.msg_controllen && error == 0) 868 error = copyout((caddr_t)&msg.msg_controllen, 869 (caddr_t)&uap->msg->msg_accrightslen, sizeof (int)); 870done: 871 if (iov != aiov) 872 FREE(iov, M_IOV); 873 return (error); 874} 875#endif 876 877int 878recvmsg(p, uap, retval) 879 struct proc *p; 880 register struct recvmsg_args /* { 881 int s; 882 struct msghdr *msg; 883 int flags; 884 } */ *uap; 885 int *retval; 886{ 887 struct msghdr msg; 888 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 889 register int error; 890 891 error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)); 892 if (error) 893 return (error); 894 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 895 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 896 return (EMSGSIZE); 897 MALLOC(iov, struct iovec *, 898 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 899 M_WAITOK); 900 } else 901 iov = aiov; 902#ifdef COMPAT_OLDSOCK 903 msg.msg_flags = uap->flags &~ MSG_COMPAT; 904#else 905 msg.msg_flags = uap->flags; 906#endif 907 uiov = msg.msg_iov; 908 msg.msg_iov = iov; 909 error = copyin((caddr_t)uiov, (caddr_t)iov, 910 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 911 if (error) 912 goto done; 913 error = recvit(p, uap->s, &msg, (caddr_t)0, retval); 914 if (!error) { 915 msg.msg_iov = uiov; 916 error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg)); 917 } 918done: 919 if (iov != aiov) 920 FREE(iov, M_IOV); 921 return (error); 922} 923 924/* ARGSUSED */ 925int 926shutdown(p, uap, retval) 927 struct proc *p; 928 register struct shutdown_args /* { 929 int s; 930 int how; 931 } */ *uap; 932 int *retval; 933{ 934 struct file *fp; 935 int error; 936 937 error = getsock(p->p_fd, uap->s, &fp); 938 if (error) 939 return (error); 940 return (soshutdown((struct socket *)fp->f_data, uap->how)); 941} 942 943/* ARGSUSED */ 944int 945setsockopt(p, uap, retval) 946 struct proc *p; 947 register struct setsockopt_args /* { 948 int s; 949 int level; 950 int name; 951 caddr_t val; 952 int valsize; 953 } */ *uap; 954 int *retval; 955{ 956 struct file *fp; 957 struct mbuf *m = NULL; 958 int error; 959 960 error = getsock(p->p_fd, uap->s, &fp); 961 if (error) 962 return (error); 963 if (uap->valsize > MLEN) 964 return (EINVAL); 965 if (uap->val) { 966 m = m_get(M_WAIT, MT_SOOPTS); 967 if (m == NULL) 968 return (ENOBUFS); 969 error = copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize); 970 if (error) { 971 (void) m_free(m); 972 return (error); 973 } 974 m->m_len = uap->valsize; 975 } 976 return (sosetopt((struct socket *)fp->f_data, uap->level, 977 uap->name, m)); 978} 979 980/* ARGSUSED */ 981int 982getsockopt(p, uap, retval) 983 struct proc *p; 984 register struct getsockopt_args /* { 985 int s; 986 int level; 987 int name; 988 caddr_t val; 989 int *avalsize; 990 } */ *uap; 991 int *retval; 992{ 993 struct file *fp; 994 struct mbuf *m = NULL; 995 int valsize, error; 996 997 error = getsock(p->p_fd, uap->s, &fp); 998 if (error) 999 return (error); 1000 if (uap->val) { 1001 error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 1002 sizeof (valsize)); 1003 if (error) 1004 return (error); 1005 } else 1006 valsize = 0; 1007 if ((error = sogetopt((struct socket *)fp->f_data, uap->level, 1008 uap->name, &m)) == 0 && uap->val && valsize && m != NULL) { 1009 if (valsize > m->m_len) 1010 valsize = m->m_len; 1011 error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); 1012 if (error == 0) 1013 error = copyout((caddr_t)&valsize, 1014 (caddr_t)uap->avalsize, sizeof (valsize)); 1015 } 1016 if (m != NULL) 1017 (void) m_free(m); 1018 return (error); 1019} 1020 1021#ifdef OLD_PIPE 1022/* ARGSUSED */ 1023int 1024pipe(p, uap, retval) 1025 struct proc *p; 1026 struct pipe_args /* { 1027 int dummy; 1028 } */ *uap; 1029 int retval[]; 1030{ 1031 register struct filedesc *fdp = p->p_fd; 1032 struct file *rf, *wf; 1033 struct socket *rso, *wso; 1034 int fd, error; 1035 1036 error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, p); 1037 if (error) 1038 return (error); 1039 error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, p); 1040 if (error) 1041 goto free1; 1042 error = falloc(p, &rf, &fd); 1043 if (error) 1044 goto free2; 1045 retval[0] = fd; 1046 rf->f_flag = FREAD | FWRITE; 1047 rf->f_type = DTYPE_SOCKET; 1048 rf->f_ops = &socketops; 1049 rf->f_data = (caddr_t)rso; 1050 error = falloc(p, &wf, &fd); 1051 if (error) 1052 goto free3; 1053 wf->f_flag = FREAD | FWRITE; 1054 wf->f_type = DTYPE_SOCKET; 1055 wf->f_ops = &socketops; 1056 wf->f_data = (caddr_t)wso; 1057 retval[1] = fd; 1058 error = unp_connect2(wso, rso); 1059 if (error) 1060 goto free4; 1061 return (0); 1062free4: 1063 ffree(wf); 1064 fdp->fd_ofiles[retval[1]] = 0; 1065free3: 1066 ffree(rf); 1067 fdp->fd_ofiles[retval[0]] = 0; 1068free2: 1069 (void)soclose(wso); 1070free1: 1071 (void)soclose(rso); 1072 return (error); 1073} 1074#endif 1075/* 1076 * Get socket name. 1077 */ 1078/* ARGSUSED */ 1079static int 1080getsockname1(p, uap, retval, compat) 1081 struct proc *p; 1082 register struct getsockname_args /* { 1083 int fdes; 1084 caddr_t asa; 1085 int *alen; 1086 } */ *uap; 1087 int *retval; 1088 int compat; 1089{ 1090 struct file *fp; 1091 register struct socket *so; 1092 struct mbuf *m; 1093 int len, error; 1094 1095 error = getsock(p->p_fd, uap->fdes, &fp); 1096 if (error) 1097 return (error); 1098 error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 1099 if (error) 1100 return (error); 1101 so = (struct socket *)fp->f_data; 1102 m = m_getclr(M_WAIT, MT_SONAME); 1103 if (m == NULL) 1104 return (ENOBUFS); 1105 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); 1106 if (error) 1107 goto bad; 1108 if (len > m->m_len) 1109 len = m->m_len; 1110#ifdef COMPAT_OLDSOCK 1111 if (compat) 1112 mtod(m, struct osockaddr *)->sa_family = 1113 mtod(m, struct sockaddr *)->sa_family; 1114#endif 1115 error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 1116 if (error == 0) 1117 error = copyout((caddr_t)&len, (caddr_t)uap->alen, 1118 sizeof (len)); 1119bad: 1120 m_freem(m); 1121 return (error); 1122} 1123 1124int 1125getsockname(p, uap, retval) 1126 struct proc *p; 1127 struct getsockname_args *uap; 1128 int *retval; 1129{ 1130 1131 return (getsockname1(p, uap, retval, 0)); 1132} 1133 1134#ifdef COMPAT_OLDSOCK 1135int 1136ogetsockname(p, uap, retval) 1137 struct proc *p; 1138 struct getsockname_args *uap; 1139 int *retval; 1140{ 1141 1142 return (getsockname1(p, uap, retval, 1)); 1143} 1144#endif /* COMPAT_OLDSOCK */ 1145 1146/* 1147 * Get name of peer for connected socket. 1148 */ 1149/* ARGSUSED */ 1150static int 1151getpeername1(p, uap, retval, compat) 1152 struct proc *p; 1153 register struct getpeername_args /* { 1154 int fdes; 1155 caddr_t asa; 1156 int *alen; 1157 } */ *uap; 1158 int *retval; 1159 int compat; 1160{ 1161 struct file *fp; 1162 register struct socket *so; 1163 struct mbuf *m; 1164 int len, error; 1165 1166 error = getsock(p->p_fd, uap->fdes, &fp); 1167 if (error) 1168 return (error); 1169 so = (struct socket *)fp->f_data; 1170 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) 1171 return (ENOTCONN); 1172 error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 1173 if (error) 1174 return (error); 1175 m = m_getclr(M_WAIT, MT_SONAME); 1176 if (m == NULL) 1177 return (ENOBUFS); 1178 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0); 1179 if (error) 1180 goto bad; 1181 if (len > m->m_len) 1182 len = m->m_len; 1183#ifdef COMPAT_OLDSOCK 1184 if (compat) 1185 mtod(m, struct osockaddr *)->sa_family = 1186 mtod(m, struct sockaddr *)->sa_family; 1187#endif 1188 error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 1189 if (error) 1190 goto bad; 1191 error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); 1192bad: 1193 m_freem(m); 1194 return (error); 1195} 1196 1197int 1198getpeername(p, uap, retval) 1199 struct proc *p; 1200 struct getpeername_args *uap; 1201 int *retval; 1202{ 1203 1204 return (getpeername1(p, uap, retval, 0)); 1205} 1206 1207#ifdef COMPAT_OLDSOCK 1208int 1209ogetpeername(p, uap, retval) 1210 struct proc *p; 1211 struct ogetpeername_args *uap; 1212 int *retval; 1213{ 1214 1215 /* XXX uap should have type `getpeername_args *' to begin with. */ 1216 return (getpeername1(p, (struct getpeername_args *)uap, retval, 1)); 1217} 1218#endif /* COMPAT_OLDSOCK */ 1219 1220int 1221sockargs(mp, buf, buflen, type) 1222 struct mbuf **mp; 1223 caddr_t buf; 1224 int buflen, type; 1225{ 1226 register struct sockaddr *sa; 1227 register struct mbuf *m; 1228 int error; 1229 1230 if ((u_int)buflen > MLEN) { 1231#ifdef COMPAT_OLDSOCK 1232 if (type == MT_SONAME && (u_int)buflen <= 112) 1233 buflen = MLEN; /* unix domain compat. hack */ 1234 else 1235#endif 1236 return (EINVAL); 1237 } 1238 m = m_get(M_WAIT, type); 1239 if (m == NULL) 1240 return (ENOBUFS); 1241 m->m_len = buflen; 1242 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen); 1243 if (error) 1244 (void) m_free(m); 1245 else { 1246 *mp = m; 1247 if (type == MT_SONAME) { 1248 sa = mtod(m, struct sockaddr *); 1249 1250#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1251 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1252 sa->sa_family = sa->sa_len; 1253#endif 1254 sa->sa_len = buflen; 1255 } 1256 } 1257 return (error); 1258} 1259 1260int 1261getsock(fdp, fdes, fpp) 1262 struct filedesc *fdp; 1263 int fdes; 1264 struct file **fpp; 1265{ 1266 register struct file *fp; 1267 1268 if ((unsigned)fdes >= fdp->fd_nfiles || 1269 (fp = fdp->fd_ofiles[fdes]) == NULL) 1270 return (EBADF); 1271 if (fp->f_type != DTYPE_SOCKET) 1272 return (ENOTSOCK); 1273 *fpp = fp; 1274 return (0); 1275} 1276