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