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.23 1997/03/23 03:36:32 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); 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)); 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); 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 #ifdef KTRACE 424 struct iovec *ktriov = NULL; 425 #endif 426 427 error = getsock(p->p_fd, s, &fp); 428 if (error) 429 return (error); 430 auio.uio_iov = mp->msg_iov; 431 auio.uio_iovcnt = mp->msg_iovlen; 432 auio.uio_segflg = UIO_USERSPACE; 433 auio.uio_rw = UIO_WRITE; 434 auio.uio_procp = p; 435 auio.uio_offset = 0; /* XXX */ 436 auio.uio_resid = 0; 437 iov = mp->msg_iov; 438 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 439 if ((auio.uio_resid += iov->iov_len) < 0) 440 return (EINVAL); 441 } 442 if (mp->msg_name) { 443 error = sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME); 444 if (error) 445 return (error); 446 } else 447 to = 0; 448 if (mp->msg_control) { 449 if (mp->msg_controllen < sizeof(struct cmsghdr) 450 #ifdef COMPAT_OLDSOCK 451 && mp->msg_flags != MSG_COMPAT 452 #endif 453 ) { 454 error = EINVAL; 455 goto bad; 456 } 457 error = sockargs(&control, mp->msg_control, 458 mp->msg_controllen, MT_CONTROL); 459 if (error) 460 goto bad; 461 #ifdef COMPAT_OLDSOCK 462 if (mp->msg_flags == MSG_COMPAT) { 463 register struct cmsghdr *cm; 464 465 M_PREPEND(control, sizeof(*cm), M_WAIT); 466 if (control == 0) { 467 error = ENOBUFS; 468 goto bad; 469 } else { 470 cm = mtod(control, struct cmsghdr *); 471 cm->cmsg_len = control->m_len; 472 cm->cmsg_level = SOL_SOCKET; 473 cm->cmsg_type = SCM_RIGHTS; 474 } 475 } 476 #endif 477 } else 478 control = 0; 479 #ifdef KTRACE 480 if (KTRPOINT(p, KTR_GENIO)) { 481 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 482 483 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 484 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 485 } 486 #endif 487 len = auio.uio_resid; 488 error = sosend((struct socket *)fp->f_data, to, &auio, 489 (struct mbuf *)0, control, flags); 490 if (error) { 491 if (auio.uio_resid != len && (error == ERESTART || 492 error == EINTR || error == EWOULDBLOCK)) 493 error = 0; 494 if (error == EPIPE) 495 psignal(p, SIGPIPE); 496 } 497 if (error == 0) 498 *retsize = len - auio.uio_resid; 499 #ifdef KTRACE 500 if (ktriov != NULL) { 501 if (error == 0) 502 ktrgenio(p->p_tracep, s, UIO_WRITE, 503 ktriov, *retsize, error); 504 FREE(ktriov, M_TEMP); 505 } 506 #endif 507 bad: 508 if (to) 509 m_freem(to); 510 return (error); 511 } 512 513 int 514 sendto(p, uap, retval) 515 struct proc *p; 516 register struct sendto_args /* { 517 int s; 518 caddr_t buf; 519 size_t len; 520 int flags; 521 caddr_t to; 522 int tolen; 523 } */ *uap; 524 int *retval; 525 { 526 struct msghdr msg; 527 struct iovec aiov; 528 529 msg.msg_name = uap->to; 530 msg.msg_namelen = uap->tolen; 531 msg.msg_iov = &aiov; 532 msg.msg_iovlen = 1; 533 msg.msg_control = 0; 534 #ifdef COMPAT_OLDSOCK 535 msg.msg_flags = 0; 536 #endif 537 aiov.iov_base = uap->buf; 538 aiov.iov_len = uap->len; 539 return (sendit(p, uap->s, &msg, uap->flags, retval)); 540 } 541 542 #ifdef COMPAT_OLDSOCK 543 int 544 osend(p, uap, retval) 545 struct proc *p; 546 register struct osend_args /* { 547 int s; 548 caddr_t buf; 549 int len; 550 int flags; 551 } */ *uap; 552 int *retval; 553 { 554 struct msghdr msg; 555 struct iovec aiov; 556 557 msg.msg_name = 0; 558 msg.msg_namelen = 0; 559 msg.msg_iov = &aiov; 560 msg.msg_iovlen = 1; 561 aiov.iov_base = uap->buf; 562 aiov.iov_len = uap->len; 563 msg.msg_control = 0; 564 msg.msg_flags = 0; 565 return (sendit(p, uap->s, &msg, uap->flags, retval)); 566 } 567 568 int 569 osendmsg(p, uap, retval) 570 struct proc *p; 571 register struct osendmsg_args /* { 572 int s; 573 caddr_t msg; 574 int flags; 575 } */ *uap; 576 int *retval; 577 { 578 struct msghdr msg; 579 struct iovec aiov[UIO_SMALLIOV], *iov; 580 int error; 581 582 error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr)); 583 if (error) 584 return (error); 585 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 586 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 587 return (EMSGSIZE); 588 MALLOC(iov, struct iovec *, 589 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 590 M_WAITOK); 591 } else 592 iov = aiov; 593 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 594 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 595 if (error) 596 goto done; 597 msg.msg_flags = MSG_COMPAT; 598 msg.msg_iov = iov; 599 error = sendit(p, uap->s, &msg, uap->flags, retval); 600 done: 601 if (iov != aiov) 602 FREE(iov, M_IOV); 603 return (error); 604 } 605 #endif 606 607 int 608 sendmsg(p, uap, retval) 609 struct proc *p; 610 register struct sendmsg_args /* { 611 int s; 612 caddr_t msg; 613 int flags; 614 } */ *uap; 615 int *retval; 616 { 617 struct msghdr msg; 618 struct iovec aiov[UIO_SMALLIOV], *iov; 619 int error; 620 621 error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); 622 if (error) 623 return (error); 624 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 625 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 626 return (EMSGSIZE); 627 MALLOC(iov, struct iovec *, 628 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 629 M_WAITOK); 630 } else 631 iov = aiov; 632 if (msg.msg_iovlen && 633 (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 634 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) 635 goto done; 636 msg.msg_iov = iov; 637 #ifdef COMPAT_OLDSOCK 638 msg.msg_flags = 0; 639 #endif 640 error = sendit(p, uap->s, &msg, uap->flags, retval); 641 done: 642 if (iov != aiov) 643 FREE(iov, M_IOV); 644 return (error); 645 } 646 647 int 648 recvit(p, s, mp, namelenp, retsize) 649 register struct proc *p; 650 int s; 651 register struct msghdr *mp; 652 caddr_t namelenp; 653 int *retsize; 654 { 655 struct file *fp; 656 struct uio auio; 657 register struct iovec *iov; 658 register int i; 659 int len, error; 660 struct mbuf *m, *from = 0, *control = 0; 661 caddr_t ctlbuf; 662 #ifdef KTRACE 663 struct iovec *ktriov = NULL; 664 #endif 665 666 error = getsock(p->p_fd, s, &fp); 667 if (error) 668 return (error); 669 auio.uio_iov = mp->msg_iov; 670 auio.uio_iovcnt = mp->msg_iovlen; 671 auio.uio_segflg = UIO_USERSPACE; 672 auio.uio_rw = UIO_READ; 673 auio.uio_procp = p; 674 auio.uio_offset = 0; /* XXX */ 675 auio.uio_resid = 0; 676 iov = mp->msg_iov; 677 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 678 if ((auio.uio_resid += iov->iov_len) < 0) 679 return (EINVAL); 680 } 681 #ifdef KTRACE 682 if (KTRPOINT(p, KTR_GENIO)) { 683 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 684 685 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 686 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 687 } 688 #endif 689 len = auio.uio_resid; 690 error = soreceive((struct socket *)fp->f_data, &from, &auio, 691 (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, 692 &mp->msg_flags); 693 if (error) { 694 if (auio.uio_resid != len && (error == ERESTART || 695 error == EINTR || error == EWOULDBLOCK)) 696 error = 0; 697 } 698 #ifdef KTRACE 699 if (ktriov != NULL) { 700 if (error == 0) 701 ktrgenio(p->p_tracep, s, UIO_READ, 702 ktriov, len - auio.uio_resid, error); 703 FREE(ktriov, M_TEMP); 704 } 705 #endif 706 if (error) 707 goto out; 708 *retsize = len - auio.uio_resid; 709 if (mp->msg_name) { 710 len = mp->msg_namelen; 711 if (len <= 0 || from == 0) 712 len = 0; 713 else { 714 #ifdef COMPAT_OLDSOCK 715 if (mp->msg_flags & MSG_COMPAT) 716 mtod(from, struct osockaddr *)->sa_family = 717 mtod(from, struct sockaddr *)->sa_family; 718 #endif 719 if (len > from->m_len) 720 len = from->m_len; 721 /* else if len < from->m_len ??? */ 722 error = copyout(mtod(from, caddr_t), 723 (caddr_t)mp->msg_name, (unsigned)len); 724 if (error) 725 goto out; 726 } 727 mp->msg_namelen = len; 728 if (namelenp && 729 (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { 730 #ifdef COMPAT_OLDSOCK 731 if (mp->msg_flags & MSG_COMPAT) 732 error = 0; /* old recvfrom didn't check */ 733 else 734 #endif 735 goto out; 736 } 737 } 738 if (mp->msg_control) { 739 #ifdef COMPAT_OLDSOCK 740 /* 741 * We assume that old recvmsg calls won't receive access 742 * rights and other control info, esp. as control info 743 * is always optional and those options didn't exist in 4.3. 744 * If we receive rights, trim the cmsghdr; anything else 745 * is tossed. 746 */ 747 if (control && mp->msg_flags & MSG_COMPAT) { 748 if (mtod(control, struct cmsghdr *)->cmsg_level != 749 SOL_SOCKET || 750 mtod(control, struct cmsghdr *)->cmsg_type != 751 SCM_RIGHTS) { 752 mp->msg_controllen = 0; 753 goto out; 754 } 755 control->m_len -= sizeof (struct cmsghdr); 756 control->m_data += sizeof (struct cmsghdr); 757 } 758 #endif 759 len = mp->msg_controllen; 760 m = control; 761 mp->msg_controllen = 0; 762 ctlbuf = (caddr_t) mp->msg_control; 763 764 while (m && len > 0) { 765 unsigned int tocopy; 766 767 if (len >= m->m_len) 768 tocopy = m->m_len; 769 else { 770 mp->msg_flags |= MSG_CTRUNC; 771 tocopy = len; 772 } 773 774 if (error = copyout((caddr_t)mtod(m, caddr_t), 775 ctlbuf, tocopy)) 776 goto out; 777 778 ctlbuf += tocopy; 779 len -= tocopy; 780 m = m->m_next; 781 } 782 mp->msg_controllen = ctlbuf - mp->msg_control; 783 } 784 out: 785 if (from) 786 m_freem(from); 787 if (control) 788 m_freem(control); 789 return (error); 790 } 791 792 int 793 recvfrom(p, uap, retval) 794 struct proc *p; 795 register struct recvfrom_args /* { 796 int s; 797 caddr_t buf; 798 size_t len; 799 int flags; 800 caddr_t from; 801 int *fromlenaddr; 802 } */ *uap; 803 int *retval; 804 { 805 struct msghdr msg; 806 struct iovec aiov; 807 int error; 808 809 if (uap->fromlenaddr) { 810 error = copyin((caddr_t)uap->fromlenaddr, 811 (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen)); 812 if (error) 813 return (error); 814 } else 815 msg.msg_namelen = 0; 816 msg.msg_name = uap->from; 817 msg.msg_iov = &aiov; 818 msg.msg_iovlen = 1; 819 aiov.iov_base = uap->buf; 820 aiov.iov_len = uap->len; 821 msg.msg_control = 0; 822 msg.msg_flags = uap->flags; 823 return (recvit(p, uap->s, &msg, (caddr_t)uap->fromlenaddr, retval)); 824 } 825 826 #ifdef COMPAT_OLDSOCK 827 int 828 orecvfrom(p, uap, retval) 829 struct proc *p; 830 struct recvfrom_args *uap; 831 int *retval; 832 { 833 834 uap->flags |= MSG_COMPAT; 835 return (recvfrom(p, uap, retval)); 836 } 837 #endif 838 839 840 #ifdef COMPAT_OLDSOCK 841 int 842 orecv(p, uap, retval) 843 struct proc *p; 844 register struct orecv_args /* { 845 int s; 846 caddr_t buf; 847 int len; 848 int flags; 849 } */ *uap; 850 int *retval; 851 { 852 struct msghdr msg; 853 struct iovec aiov; 854 855 msg.msg_name = 0; 856 msg.msg_namelen = 0; 857 msg.msg_iov = &aiov; 858 msg.msg_iovlen = 1; 859 aiov.iov_base = uap->buf; 860 aiov.iov_len = uap->len; 861 msg.msg_control = 0; 862 msg.msg_flags = uap->flags; 863 return (recvit(p, uap->s, &msg, (caddr_t)0, retval)); 864 } 865 866 /* 867 * Old recvmsg. This code takes advantage of the fact that the old msghdr 868 * overlays the new one, missing only the flags, and with the (old) access 869 * rights where the control fields are now. 870 */ 871 int 872 orecvmsg(p, uap, retval) 873 struct proc *p; 874 register struct orecvmsg_args /* { 875 int s; 876 struct omsghdr *msg; 877 int flags; 878 } */ *uap; 879 int *retval; 880 { 881 struct msghdr msg; 882 struct iovec aiov[UIO_SMALLIOV], *iov; 883 int error; 884 885 error = copyin((caddr_t)uap->msg, (caddr_t)&msg, 886 sizeof (struct omsghdr)); 887 if (error) 888 return (error); 889 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 890 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 891 return (EMSGSIZE); 892 MALLOC(iov, struct iovec *, 893 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 894 M_WAITOK); 895 } else 896 iov = aiov; 897 msg.msg_flags = uap->flags | MSG_COMPAT; 898 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 899 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 900 if (error) 901 goto done; 902 msg.msg_iov = iov; 903 error = recvit(p, uap->s, &msg, (caddr_t)&uap->msg->msg_namelen, retval); 904 905 if (msg.msg_controllen && error == 0) 906 error = copyout((caddr_t)&msg.msg_controllen, 907 (caddr_t)&uap->msg->msg_accrightslen, sizeof (int)); 908 done: 909 if (iov != aiov) 910 FREE(iov, M_IOV); 911 return (error); 912 } 913 #endif 914 915 int 916 recvmsg(p, uap, retval) 917 struct proc *p; 918 register struct recvmsg_args /* { 919 int s; 920 struct msghdr *msg; 921 int flags; 922 } */ *uap; 923 int *retval; 924 { 925 struct msghdr msg; 926 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 927 register int error; 928 929 error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)); 930 if (error) 931 return (error); 932 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 933 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 934 return (EMSGSIZE); 935 MALLOC(iov, struct iovec *, 936 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 937 M_WAITOK); 938 } else 939 iov = aiov; 940 #ifdef COMPAT_OLDSOCK 941 msg.msg_flags = uap->flags &~ MSG_COMPAT; 942 #else 943 msg.msg_flags = uap->flags; 944 #endif 945 uiov = msg.msg_iov; 946 msg.msg_iov = iov; 947 error = copyin((caddr_t)uiov, (caddr_t)iov, 948 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 949 if (error) 950 goto done; 951 error = recvit(p, uap->s, &msg, (caddr_t)0, retval); 952 if (!error) { 953 msg.msg_iov = uiov; 954 error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg)); 955 } 956 done: 957 if (iov != aiov) 958 FREE(iov, M_IOV); 959 return (error); 960 } 961 962 /* ARGSUSED */ 963 int 964 shutdown(p, uap, retval) 965 struct proc *p; 966 register struct shutdown_args /* { 967 int s; 968 int how; 969 } */ *uap; 970 int *retval; 971 { 972 struct file *fp; 973 int error; 974 975 error = getsock(p->p_fd, uap->s, &fp); 976 if (error) 977 return (error); 978 return (soshutdown((struct socket *)fp->f_data, uap->how)); 979 } 980 981 /* ARGSUSED */ 982 int 983 setsockopt(p, uap, retval) 984 struct proc *p; 985 register struct setsockopt_args /* { 986 int s; 987 int level; 988 int name; 989 caddr_t val; 990 int valsize; 991 } */ *uap; 992 int *retval; 993 { 994 struct file *fp; 995 struct mbuf *m = NULL; 996 int error; 997 998 error = getsock(p->p_fd, uap->s, &fp); 999 if (error) 1000 return (error); 1001 if (uap->valsize > MLEN) 1002 return (EINVAL); 1003 if (uap->val) { 1004 m = m_get(M_WAIT, MT_SOOPTS); 1005 if (m == NULL) 1006 return (ENOBUFS); 1007 error = copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize); 1008 if (error) { 1009 (void) m_free(m); 1010 return (error); 1011 } 1012 m->m_len = uap->valsize; 1013 } 1014 return (sosetopt((struct socket *)fp->f_data, uap->level, 1015 uap->name, m)); 1016 } 1017 1018 /* ARGSUSED */ 1019 int 1020 getsockopt(p, uap, retval) 1021 struct proc *p; 1022 register struct getsockopt_args /* { 1023 int s; 1024 int level; 1025 int name; 1026 caddr_t val; 1027 int *avalsize; 1028 } */ *uap; 1029 int *retval; 1030 { 1031 struct file *fp; 1032 struct mbuf *m = NULL, *m0; 1033 int op, i, valsize, error; 1034 1035 error = getsock(p->p_fd, uap->s, &fp); 1036 if (error) 1037 return (error); 1038 if (uap->val) { 1039 error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 1040 sizeof (valsize)); 1041 if (error) 1042 return (error); 1043 } else 1044 valsize = 0; 1045 if ((error = sogetopt((struct socket *)fp->f_data, uap->level, 1046 uap->name, &m)) == 0 && uap->val && valsize && m != NULL) { 1047 op = 0; 1048 while (m && !error && op < valsize) { 1049 i = min(m->m_len, (valsize - op)); 1050 error = copyout(mtod(m, caddr_t), uap->val, (u_int)i); 1051 op += i; 1052 uap->val += i; 1053 m0 = m; 1054 MFREE(m0,m); 1055 } 1056 valsize = op; 1057 if (error == 0) 1058 error = copyout((caddr_t)&valsize, 1059 (caddr_t)uap->avalsize, sizeof (valsize)); 1060 } 1061 if (m != NULL) 1062 (void) m_free(m); 1063 return (error); 1064 } 1065 1066 #ifdef OLD_PIPE 1067 /* ARGSUSED */ 1068 int 1069 pipe(p, uap, retval) 1070 struct proc *p; 1071 struct pipe_args /* { 1072 int dummy; 1073 } */ *uap; 1074 int retval[]; 1075 { 1076 register struct filedesc *fdp = p->p_fd; 1077 struct file *rf, *wf; 1078 struct socket *rso, *wso; 1079 int fd, error; 1080 1081 error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, p); 1082 if (error) 1083 return (error); 1084 error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, p); 1085 if (error) 1086 goto free1; 1087 error = falloc(p, &rf, &fd); 1088 if (error) 1089 goto free2; 1090 retval[0] = fd; 1091 rf->f_flag = FREAD | FWRITE; 1092 rf->f_type = DTYPE_SOCKET; 1093 rf->f_ops = &socketops; 1094 rf->f_data = (caddr_t)rso; 1095 error = falloc(p, &wf, &fd); 1096 if (error) 1097 goto free3; 1098 wf->f_flag = FREAD | FWRITE; 1099 wf->f_type = DTYPE_SOCKET; 1100 wf->f_ops = &socketops; 1101 wf->f_data = (caddr_t)wso; 1102 retval[1] = fd; 1103 error = unp_connect2(wso, rso); 1104 if (error) 1105 goto free4; 1106 return (0); 1107 free4: 1108 ffree(wf); 1109 fdp->fd_ofiles[retval[1]] = 0; 1110 free3: 1111 ffree(rf); 1112 fdp->fd_ofiles[retval[0]] = 0; 1113 free2: 1114 (void)soclose(wso); 1115 free1: 1116 (void)soclose(rso); 1117 return (error); 1118 } 1119 #endif 1120 /* 1121 * Get socket name. 1122 */ 1123 /* ARGSUSED */ 1124 static int 1125 getsockname1(p, uap, retval, compat) 1126 struct proc *p; 1127 register struct getsockname_args /* { 1128 int fdes; 1129 caddr_t asa; 1130 int *alen; 1131 } */ *uap; 1132 int *retval; 1133 int compat; 1134 { 1135 struct file *fp; 1136 register struct socket *so; 1137 struct mbuf *m; 1138 int len, error; 1139 1140 error = getsock(p->p_fd, uap->fdes, &fp); 1141 if (error) 1142 return (error); 1143 error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 1144 if (error) 1145 return (error); 1146 so = (struct socket *)fp->f_data; 1147 m = m_getclr(M_WAIT, MT_SONAME); 1148 if (m == NULL) 1149 return (ENOBUFS); 1150 error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, m); 1151 if (error) 1152 goto bad; 1153 if (len > m->m_len) 1154 len = m->m_len; 1155 #ifdef COMPAT_OLDSOCK 1156 if (compat) 1157 mtod(m, struct osockaddr *)->sa_family = 1158 mtod(m, struct sockaddr *)->sa_family; 1159 #endif 1160 error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 1161 if (error == 0) 1162 error = copyout((caddr_t)&len, (caddr_t)uap->alen, 1163 sizeof (len)); 1164 bad: 1165 m_freem(m); 1166 return (error); 1167 } 1168 1169 int 1170 getsockname(p, uap, retval) 1171 struct proc *p; 1172 struct getsockname_args *uap; 1173 int *retval; 1174 { 1175 1176 return (getsockname1(p, uap, retval, 0)); 1177 } 1178 1179 #ifdef COMPAT_OLDSOCK 1180 int 1181 ogetsockname(p, uap, retval) 1182 struct proc *p; 1183 struct getsockname_args *uap; 1184 int *retval; 1185 { 1186 1187 return (getsockname1(p, uap, retval, 1)); 1188 } 1189 #endif /* COMPAT_OLDSOCK */ 1190 1191 /* 1192 * Get name of peer for connected socket. 1193 */ 1194 /* ARGSUSED */ 1195 static int 1196 getpeername1(p, uap, retval, compat) 1197 struct proc *p; 1198 register struct getpeername_args /* { 1199 int fdes; 1200 caddr_t asa; 1201 int *alen; 1202 } */ *uap; 1203 int *retval; 1204 int compat; 1205 { 1206 struct file *fp; 1207 register struct socket *so; 1208 struct mbuf *m; 1209 int len, error; 1210 1211 error = getsock(p->p_fd, uap->fdes, &fp); 1212 if (error) 1213 return (error); 1214 so = (struct socket *)fp->f_data; 1215 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) 1216 return (ENOTCONN); 1217 error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 1218 if (error) 1219 return (error); 1220 m = m_getclr(M_WAIT, MT_SONAME); 1221 if (m == NULL) 1222 return (ENOBUFS); 1223 error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, m); 1224 if (error) 1225 goto bad; 1226 if (len > m->m_len) 1227 len = m->m_len; 1228 #ifdef COMPAT_OLDSOCK 1229 if (compat) 1230 mtod(m, struct osockaddr *)->sa_family = 1231 mtod(m, struct sockaddr *)->sa_family; 1232 #endif 1233 error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 1234 if (error) 1235 goto bad; 1236 error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); 1237 bad: 1238 m_freem(m); 1239 return (error); 1240 } 1241 1242 int 1243 getpeername(p, uap, retval) 1244 struct proc *p; 1245 struct getpeername_args *uap; 1246 int *retval; 1247 { 1248 1249 return (getpeername1(p, uap, retval, 0)); 1250 } 1251 1252 #ifdef COMPAT_OLDSOCK 1253 int 1254 ogetpeername(p, uap, retval) 1255 struct proc *p; 1256 struct ogetpeername_args *uap; 1257 int *retval; 1258 { 1259 1260 /* XXX uap should have type `getpeername_args *' to begin with. */ 1261 return (getpeername1(p, (struct getpeername_args *)uap, retval, 1)); 1262 } 1263 #endif /* COMPAT_OLDSOCK */ 1264 1265 int 1266 sockargs(mp, buf, buflen, type) 1267 struct mbuf **mp; 1268 caddr_t buf; 1269 int buflen, type; 1270 { 1271 register struct sockaddr *sa; 1272 register struct mbuf *m; 1273 int error; 1274 1275 if ((u_int)buflen > MLEN) { 1276 #ifdef COMPAT_OLDSOCK 1277 if (type == MT_SONAME && (u_int)buflen <= 112) 1278 buflen = MLEN; /* unix domain compat. hack */ 1279 else 1280 #endif 1281 return (EINVAL); 1282 } 1283 m = m_get(M_WAIT, type); 1284 if (m == NULL) 1285 return (ENOBUFS); 1286 m->m_len = buflen; 1287 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen); 1288 if (error) 1289 (void) m_free(m); 1290 else { 1291 *mp = m; 1292 if (type == MT_SONAME) { 1293 sa = mtod(m, struct sockaddr *); 1294 1295 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1296 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1297 sa->sa_family = sa->sa_len; 1298 #endif 1299 sa->sa_len = buflen; 1300 } 1301 } 1302 return (error); 1303 } 1304 1305 int 1306 getsock(fdp, fdes, fpp) 1307 struct filedesc *fdp; 1308 int fdes; 1309 struct file **fpp; 1310 { 1311 register struct file *fp; 1312 1313 if ((unsigned)fdes >= fdp->fd_nfiles || 1314 (fp = fdp->fd_ofiles[fdes]) == NULL) 1315 return (EBADF); 1316 if (fp->f_type != DTYPE_SOCKET) 1317 return (ENOTSOCK); 1318 *fpp = fp; 1319 return (0); 1320 } 1321