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