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