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