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