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