301 if (error) 302 break; 303 } 304 if (error == 0) { 305 error = so->so_error; 306 so->so_error = 0; 307 } 308 splx(s); 309bad: 310 so->so_state &= ~SS_ISCONNECTING; 311 m_freem(nam); 312 if (error == ERESTART) 313 error = EINTR; 314 return (error); 315} 316 317int 318socketpair(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); 370free4: 371 ffree(fp2); 372 fdp->fd_ofiles[sv[1]] = 0; 373free3: 374 ffree(fp1); 375 fdp->fd_ofiles[sv[0]] = 0; 376free2: 377 (void)soclose(so2); 378free1: 379 (void)soclose(so1); 380 return (error); 381} 382 383int 384sendit(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 480bad: 481 if (to) 482 m_freem(to); 483 return (error); 484} 485 486int 487sendto(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 516int 517osend(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 541int 542osendmsg(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); 573done: 574 if (iov != aiov) 575 FREE(iov, M_IOV); 576 return (error); 577} 578#endif 579 580int 581sendmsg(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); 614done: 615 if (iov != aiov) 616 FREE(iov, M_IOV); 617 return (error); 618} 619 620int 621recvit(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 } 744out: 745 if (from) 746 m_freem(from); 747 if (control) 748 m_freem(control); 749 return (error); 750} 751 752int 753recvfrom(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 787int 788orecvfrom(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 801int 802orecv(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 */ 831int 832orecvmsg(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)); 868done: 869 if (iov != aiov) 870 FREE(iov, M_IOV); 871 return (error); 872} 873#endif 874 875int 876recvmsg(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 } 916done: 917 if (iov != aiov) 918 FREE(iov, M_IOV); 919 return (error); 920} 921 922/* ARGSUSED */ 923int 924shutdown(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 */ 942int 943setsockopt(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 */ 979int 980getsockopt(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 */ 1020int 1021pipe(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); 1059free4: 1060 ffree(wf); 1061 fdp->fd_ofiles[retval[1]] = 0; 1062free3: 1063 ffree(rf); 1064 fdp->fd_ofiles[retval[0]] = 0; 1065free2: 1066 (void)soclose(wso); 1067free1: 1068 (void)soclose(rso); 1069 return (error); 1070} 1071 1072/* 1073 * Get socket name. 1074 */ 1075/* ARGSUSED */ 1076static int 1077getsockname1(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)); 1116bad: 1117 m_freem(m); 1118 return (error); 1119} 1120 1121int 1122getsockname(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 1132int 1133ogetsockname(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 */ 1147static int 1148getpeername1(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)); 1189bad: 1190 m_freem(m); 1191 return (error); 1192} 1193 1194int 1195getpeername(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 1205int 1206ogetpeername(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 1217int 1218sockargs(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 1257int 1258getsock(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}
| 301 if (error) 302 break; 303 } 304 if (error == 0) { 305 error = so->so_error; 306 so->so_error = 0; 307 } 308 splx(s); 309bad: 310 so->so_state &= ~SS_ISCONNECTING; 311 m_freem(nam); 312 if (error == ERESTART) 313 error = EINTR; 314 return (error); 315} 316 317int 318socketpair(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); 370free4: 371 ffree(fp2); 372 fdp->fd_ofiles[sv[1]] = 0; 373free3: 374 ffree(fp1); 375 fdp->fd_ofiles[sv[0]] = 0; 376free2: 377 (void)soclose(so2); 378free1: 379 (void)soclose(so1); 380 return (error); 381} 382 383int 384sendit(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 480bad: 481 if (to) 482 m_freem(to); 483 return (error); 484} 485 486int 487sendto(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 516int 517osend(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 541int 542osendmsg(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); 573done: 574 if (iov != aiov) 575 FREE(iov, M_IOV); 576 return (error); 577} 578#endif 579 580int 581sendmsg(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); 614done: 615 if (iov != aiov) 616 FREE(iov, M_IOV); 617 return (error); 618} 619 620int 621recvit(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 } 744out: 745 if (from) 746 m_freem(from); 747 if (control) 748 m_freem(control); 749 return (error); 750} 751 752int 753recvfrom(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 787int 788orecvfrom(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 801int 802orecv(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 */ 831int 832orecvmsg(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)); 868done: 869 if (iov != aiov) 870 FREE(iov, M_IOV); 871 return (error); 872} 873#endif 874 875int 876recvmsg(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 } 916done: 917 if (iov != aiov) 918 FREE(iov, M_IOV); 919 return (error); 920} 921 922/* ARGSUSED */ 923int 924shutdown(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 */ 942int 943setsockopt(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 */ 979int 980getsockopt(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 */ 1020int 1021pipe(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); 1059free4: 1060 ffree(wf); 1061 fdp->fd_ofiles[retval[1]] = 0; 1062free3: 1063 ffree(rf); 1064 fdp->fd_ofiles[retval[0]] = 0; 1065free2: 1066 (void)soclose(wso); 1067free1: 1068 (void)soclose(rso); 1069 return (error); 1070} 1071 1072/* 1073 * Get socket name. 1074 */ 1075/* ARGSUSED */ 1076static int 1077getsockname1(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)); 1116bad: 1117 m_freem(m); 1118 return (error); 1119} 1120 1121int 1122getsockname(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 1132int 1133ogetsockname(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 */ 1147static int 1148getpeername1(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)); 1189bad: 1190 m_freem(m); 1191 return (error); 1192} 1193 1194int 1195getpeername(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 1205int 1206ogetpeername(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 1217int 1218sockargs(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 1257int 1258getsock(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}
|