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