Commit 3532fa7402cda16f7b95261b0339c58630051f0b
1 parent
480c1cdb
mips socket calls (initial patch by Raphael Rigo)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2006 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
409 additions
and
81 deletions
linux-user/socket.h
0 → 100644
| 1 | + | ||
| 2 | +#if defined(TARGET_MIPS) | ||
| 3 | + // MIPS special values for constants | ||
| 4 | + | ||
| 5 | + /* | ||
| 6 | + * For setsockopt(2) | ||
| 7 | + * | ||
| 8 | + * This defines are ABI conformant as far as Linux supports these ... | ||
| 9 | + */ | ||
| 10 | + #define TARGET_SOL_SOCKET 0xffff | ||
| 11 | + | ||
| 12 | + #define TARGET_SO_DEBUG 0x0001 /* Record debugging information. */ | ||
| 13 | + #define TARGET_SO_REUSEADDR 0x0004 /* Allow reuse of local addresses. */ | ||
| 14 | + #define TARGET_SO_KEEPALIVE 0x0008 /* Keep connections alive and send | ||
| 15 | + SIGPIPE when they die. */ | ||
| 16 | + #define TARGET_SO_DONTROUTE 0x0010 /* Don't do local routing. */ | ||
| 17 | + #define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of | ||
| 18 | + broadcast messages. */ | ||
| 19 | + #define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable | ||
| 20 | + socket to transmit pending data. */ | ||
| 21 | + #define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. */ | ||
| 22 | + #if 0 | ||
| 23 | + To add: #define TARGET_SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ | ||
| 24 | + #endif | ||
| 25 | + | ||
| 26 | + #define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */ | ||
| 27 | + #define TARGET_SO_STYLE SO_TYPE /* Synonym */ | ||
| 28 | + #define TARGET_SO_ERROR 0x1007 /* get error status and clear */ | ||
| 29 | + #define TARGET_SO_SNDBUF 0x1001 /* Send buffer size. */ | ||
| 30 | + #define TARGET_SO_RCVBUF 0x1002 /* Receive buffer. */ | ||
| 31 | + #define TARGET_SO_SNDLOWAT 0x1003 /* send low-water mark */ | ||
| 32 | + #define TARGET_SO_RCVLOWAT 0x1004 /* receive low-water mark */ | ||
| 33 | + #define TARGET_SO_SNDTIMEO 0x1005 /* send timeout */ | ||
| 34 | + #define TARGET_SO_RCVTIMEO 0x1006 /* receive timeout */ | ||
| 35 | + #define TARGET_SO_ACCEPTCONN 0x1009 | ||
| 36 | + | ||
| 37 | + /* linux-specific, might as well be the same as on i386 */ | ||
| 38 | + #define TARGET_SO_NO_CHECK 11 | ||
| 39 | + #define TARGET_SO_PRIORITY 12 | ||
| 40 | + #define TARGET_SO_BSDCOMPAT 14 | ||
| 41 | + | ||
| 42 | + #define TARGET_SO_PASSCRED 17 | ||
| 43 | + #define TARGET_SO_PEERCRED 18 | ||
| 44 | + | ||
| 45 | + /* Security levels - as per NRL IPv6 - don't actually do anything */ | ||
| 46 | + #define TARGET_SO_SECURITY_AUTHENTICATION 22 | ||
| 47 | + #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23 | ||
| 48 | + #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24 | ||
| 49 | + | ||
| 50 | + #define TARGET_SO_BINDTODEVICE 25 | ||
| 51 | + | ||
| 52 | + /* Socket filtering */ | ||
| 53 | + #define TARGET_SO_ATTACH_FILTER 26 | ||
| 54 | + #define TARGET_SO_DETACH_FILTER 27 | ||
| 55 | + | ||
| 56 | + #define TARGET_SO_PEERNAME 28 | ||
| 57 | + #define TARGET_SO_TIMESTAMP 29 | ||
| 58 | + #define SCM_TIMESTAMP SO_TIMESTAMP | ||
| 59 | + | ||
| 60 | + #define TARGET_SO_PEERSEC 30 | ||
| 61 | + #define TARGET_SO_SNDBUFFORCE 31 | ||
| 62 | + #define TARGET_SO_RCVBUFFORCE 33 | ||
| 63 | + | ||
| 64 | + /** sock_type - Socket types | ||
| 65 | + * | ||
| 66 | + * Please notice that for binary compat reasons MIPS has to | ||
| 67 | + * override the enum sock_type in include/linux/net.h, so | ||
| 68 | + * we define ARCH_HAS_SOCKET_TYPES here. | ||
| 69 | + * | ||
| 70 | + * @SOCK_DGRAM - datagram (conn.less) socket | ||
| 71 | + * @SOCK_STREAM - stream (connection) socket | ||
| 72 | + * @SOCK_RAW - raw socket | ||
| 73 | + * @SOCK_RDM - reliably-delivered message | ||
| 74 | + * @SOCK_SEQPACKET - sequential packet socket | ||
| 75 | + * @SOCK_PACKET - linux specific way of getting packets at the dev level. | ||
| 76 | + * For writing rarp and other similar things on the user level. | ||
| 77 | + */ | ||
| 78 | + enum sock_type { | ||
| 79 | + TARGET_SOCK_DGRAM = 1, | ||
| 80 | + TARGET_SOCK_STREAM = 2, | ||
| 81 | + TARGET_SOCK_RAW = 3, | ||
| 82 | + TARGET_SOCK_RDM = 4, | ||
| 83 | + TARGET_SOCK_SEQPACKET = 5, | ||
| 84 | + TARGET_SOCK_DCCP = 6, | ||
| 85 | + TARGET_SOCK_PACKET = 10, | ||
| 86 | + }; | ||
| 87 | + | ||
| 88 | + #define TARGET_SOCK_MAX (SOCK_PACKET + 1) | ||
| 89 | + | ||
| 90 | +#else | ||
| 91 | + | ||
| 92 | + /* For setsockopt(2) */ | ||
| 93 | + #define TARGET_SOL_SOCKET 1 | ||
| 94 | + | ||
| 95 | + #define TARGET_SO_DEBUG 1 | ||
| 96 | + #define TARGET_SO_REUSEADDR 2 | ||
| 97 | + #define TARGET_SO_TYPE 3 | ||
| 98 | + #define TARGET_SO_ERROR 4 | ||
| 99 | + #define TARGET_SO_DONTROUTE 5 | ||
| 100 | + #define TARGET_SO_BROADCAST 6 | ||
| 101 | + #define TARGET_SO_SNDBUF 7 | ||
| 102 | + #define TARGET_SO_RCVBUF 8 | ||
| 103 | + #define TARGET_SO_SNDBUFFORCE 32 | ||
| 104 | + #define TARGET_SO_RCVBUFFORCE 33 | ||
| 105 | + #define TARGET_SO_KEEPALIVE 9 | ||
| 106 | + #define TARGET_SO_OOBINLINE 10 | ||
| 107 | + #define TARGET_SO_NO_CHECK 11 | ||
| 108 | + #define TARGET_SO_PRIORITY 12 | ||
| 109 | + #define TARGET_SO_LINGER 13 | ||
| 110 | + #define TARGET_SO_BSDCOMPAT 14 | ||
| 111 | + /* To add :#define TARGET_SO_REUSEPORT 15 */ | ||
| 112 | + #define TARGET_SO_PASSCRED 16 | ||
| 113 | + #define TARGET_SO_PEERCRED 17 | ||
| 114 | + #define TARGET_SO_RCVLOWAT 18 | ||
| 115 | + #define TARGET_SO_SNDLOWAT 19 | ||
| 116 | + #define TARGET_SO_RCVTIMEO 20 | ||
| 117 | + #define TARGET_SO_SNDTIMEO 21 | ||
| 118 | + | ||
| 119 | + /* Security levels - as per NRL IPv6 - don't actually do anything */ | ||
| 120 | + #define TARGET_SO_SECURITY_AUTHENTICATION 22 | ||
| 121 | + #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23 | ||
| 122 | + #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24 | ||
| 123 | + | ||
| 124 | + #define TARGET_SO_BINDTODEVICE 25 | ||
| 125 | + | ||
| 126 | + /* Socket filtering */ | ||
| 127 | + #define TARGET_SO_ATTACH_FILTER 26 | ||
| 128 | + #define TARGET_SO_DETACH_FILTER 27 | ||
| 129 | + | ||
| 130 | + #define TARGET_SO_PEERNAME 28 | ||
| 131 | + #define TARGET_SO_TIMESTAMP 29 | ||
| 132 | + #define TARGET_SCM_TIMESTAMP TARGET_SO_TIMESTAMP | ||
| 133 | + | ||
| 134 | + #define TARGET_SO_ACCEPTCONN 30 | ||
| 135 | + | ||
| 136 | + #define TARGET_SO_PEERSEC 31 | ||
| 137 | + | ||
| 138 | +#endif |
linux-user/syscall.c
| @@ -446,7 +446,7 @@ static inline void target_to_host_cmsg(struct msghdr *msgh, | @@ -446,7 +446,7 @@ static inline void target_to_host_cmsg(struct msghdr *msgh, | ||
| 446 | cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type); | 446 | cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type); |
| 447 | cmsg->cmsg_len = CMSG_LEN(len); | 447 | cmsg->cmsg_len = CMSG_LEN(len); |
| 448 | 448 | ||
| 449 | - if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { | 449 | + if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { |
| 450 | gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); | 450 | gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); |
| 451 | memcpy(data, target_data, len); | 451 | memcpy(data, target_data, len); |
| 452 | } else { | 452 | } else { |
| @@ -490,7 +490,7 @@ static inline void host_to_target_cmsg(struct target_msghdr *target_msgh, | @@ -490,7 +490,7 @@ static inline void host_to_target_cmsg(struct target_msghdr *target_msgh, | ||
| 490 | target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type); | 490 | target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type); |
| 491 | target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len)); | 491 | target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len)); |
| 492 | 492 | ||
| 493 | - if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { | 493 | + if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { |
| 494 | gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); | 494 | gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); |
| 495 | memcpy(target_data, data, len); | 495 | memcpy(target_data, data, len); |
| 496 | } else { | 496 | } else { |
| @@ -552,38 +552,74 @@ static long do_setsockopt(int sockfd, int level, int optname, | @@ -552,38 +552,74 @@ static long do_setsockopt(int sockfd, int level, int optname, | ||
| 552 | goto unimplemented; | 552 | goto unimplemented; |
| 553 | } | 553 | } |
| 554 | break; | 554 | break; |
| 555 | - case SOL_SOCKET: | 555 | + case TARGET_SOL_SOCKET: |
| 556 | switch (optname) { | 556 | switch (optname) { |
| 557 | /* Options with 'int' argument. */ | 557 | /* Options with 'int' argument. */ |
| 558 | - case SO_DEBUG: | ||
| 559 | - case SO_REUSEADDR: | ||
| 560 | - case SO_TYPE: | ||
| 561 | - case SO_ERROR: | ||
| 562 | - case SO_DONTROUTE: | ||
| 563 | - case SO_BROADCAST: | ||
| 564 | - case SO_SNDBUF: | ||
| 565 | - case SO_RCVBUF: | ||
| 566 | - case SO_KEEPALIVE: | ||
| 567 | - case SO_OOBINLINE: | ||
| 568 | - case SO_NO_CHECK: | ||
| 569 | - case SO_PRIORITY: | 558 | + case TARGET_SO_DEBUG: |
| 559 | + optname = SO_DEBUG; | ||
| 560 | + break; | ||
| 561 | + case TARGET_SO_REUSEADDR: | ||
| 562 | + optname = SO_REUSEADDR; | ||
| 563 | + break; | ||
| 564 | + case TARGET_SO_TYPE: | ||
| 565 | + optname = SO_TYPE; | ||
| 566 | + break; | ||
| 567 | + case TARGET_SO_ERROR: | ||
| 568 | + optname = SO_ERROR; | ||
| 569 | + break; | ||
| 570 | + case TARGET_SO_DONTROUTE: | ||
| 571 | + optname = SO_DONTROUTE; | ||
| 572 | + break; | ||
| 573 | + case TARGET_SO_BROADCAST: | ||
| 574 | + optname = SO_BROADCAST; | ||
| 575 | + break; | ||
| 576 | + case TARGET_SO_SNDBUF: | ||
| 577 | + optname = SO_SNDBUF; | ||
| 578 | + break; | ||
| 579 | + case TARGET_SO_RCVBUF: | ||
| 580 | + optname = SO_RCVBUF; | ||
| 581 | + break; | ||
| 582 | + case TARGET_SO_KEEPALIVE: | ||
| 583 | + optname = SO_KEEPALIVE; | ||
| 584 | + break; | ||
| 585 | + case TARGET_SO_OOBINLINE: | ||
| 586 | + optname = SO_OOBINLINE; | ||
| 587 | + break; | ||
| 588 | + case TARGET_SO_NO_CHECK: | ||
| 589 | + optname = SO_NO_CHECK; | ||
| 590 | + break; | ||
| 591 | + case TARGET_SO_PRIORITY: | ||
| 592 | + optname = SO_PRIORITY; | ||
| 593 | + break; | ||
| 570 | #ifdef SO_BSDCOMPAT | 594 | #ifdef SO_BSDCOMPAT |
| 571 | - case SO_BSDCOMPAT: | ||
| 572 | -#endif | ||
| 573 | - case SO_PASSCRED: | ||
| 574 | - case SO_TIMESTAMP: | ||
| 575 | - case SO_RCVLOWAT: | ||
| 576 | - case SO_RCVTIMEO: | ||
| 577 | - case SO_SNDTIMEO: | ||
| 578 | - if (optlen < sizeof(uint32_t)) | ||
| 579 | - return -EINVAL; | ||
| 580 | - | ||
| 581 | - val = tget32(optval); | ||
| 582 | - ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); | 595 | + case TARGET_SO_BSDCOMPAT: |
| 596 | + optname = SO_BSDCOMPAT; | ||
| 597 | + break; | ||
| 598 | +#endif | ||
| 599 | + case TARGET_SO_PASSCRED: | ||
| 600 | + optname = SO_PASSCRED; | ||
| 601 | + break; | ||
| 602 | + case TARGET_SO_TIMESTAMP: | ||
| 603 | + optname = SO_TIMESTAMP; | ||
| 604 | + break; | ||
| 605 | + case TARGET_SO_RCVLOWAT: | ||
| 606 | + optname = SO_RCVLOWAT; | ||
| 607 | + break; | ||
| 608 | + case TARGET_SO_RCVTIMEO: | ||
| 609 | + optname = SO_RCVTIMEO; | ||
| 610 | + break; | ||
| 611 | + case TARGET_SO_SNDTIMEO: | ||
| 612 | + optname = SO_SNDTIMEO; | ||
| 613 | + break; | ||
| 583 | break; | 614 | break; |
| 584 | default: | 615 | default: |
| 585 | goto unimplemented; | 616 | goto unimplemented; |
| 586 | } | 617 | } |
| 618 | + if (optlen < sizeof(uint32_t)) | ||
| 619 | + return -EINVAL; | ||
| 620 | + | ||
| 621 | + val = tget32(optval); | ||
| 622 | + ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val))); | ||
| 587 | break; | 623 | break; |
| 588 | default: | 624 | default: |
| 589 | unimplemented: | 625 | unimplemented: |
| @@ -599,13 +635,14 @@ static long do_getsockopt(int sockfd, int level, int optname, | @@ -599,13 +635,14 @@ static long do_getsockopt(int sockfd, int level, int optname, | ||
| 599 | int len, lv, val, ret; | 635 | int len, lv, val, ret; |
| 600 | 636 | ||
| 601 | switch(level) { | 637 | switch(level) { |
| 602 | - case SOL_SOCKET: | 638 | + case TARGET_SOL_SOCKET: |
| 639 | + level = SOL_SOCKET; | ||
| 603 | switch (optname) { | 640 | switch (optname) { |
| 604 | - case SO_LINGER: | ||
| 605 | - case SO_RCVTIMEO: | ||
| 606 | - case SO_SNDTIMEO: | ||
| 607 | - case SO_PEERCRED: | ||
| 608 | - case SO_PEERNAME: | 641 | + case TARGET_SO_LINGER: |
| 642 | + case TARGET_SO_RCVTIMEO: | ||
| 643 | + case TARGET_SO_SNDTIMEO: | ||
| 644 | + case TARGET_SO_PEERCRED: | ||
| 645 | + case TARGET_SO_PEERNAME: | ||
| 609 | /* These don't just return a single integer */ | 646 | /* These don't just return a single integer */ |
| 610 | goto unimplemented; | 647 | goto unimplemented; |
| 611 | default: | 648 | default: |
| @@ -711,6 +748,94 @@ static void unlock_iovec(struct iovec *vec, target_ulong target_addr, | @@ -711,6 +748,94 @@ static void unlock_iovec(struct iovec *vec, target_ulong target_addr, | ||
| 711 | unlock_user (target_vec, target_addr, 0); | 748 | unlock_user (target_vec, target_addr, 0); |
| 712 | } | 749 | } |
| 713 | 750 | ||
| 751 | +static long do_socket(int domain, int type, int protocol) | ||
| 752 | +{ | ||
| 753 | +#if defined(TARGET_MIPS) | ||
| 754 | + switch(type) { | ||
| 755 | + case TARGET_SOCK_DGRAM: | ||
| 756 | + type = SOCK_DGRAM; | ||
| 757 | + break; | ||
| 758 | + case TARGET_SOCK_STREAM: | ||
| 759 | + type = SOCK_STREAM; | ||
| 760 | + break; | ||
| 761 | + case TARGET_SOCK_RAW: | ||
| 762 | + type = SOCK_RAW; | ||
| 763 | + break; | ||
| 764 | + case TARGET_SOCK_RDM: | ||
| 765 | + type = SOCK_RDM; | ||
| 766 | + break; | ||
| 767 | + case TARGET_SOCK_SEQPACKET: | ||
| 768 | + type = SOCK_SEQPACKET; | ||
| 769 | + break; | ||
| 770 | + case TARGET_SOCK_PACKET: | ||
| 771 | + type = SOCK_PACKET; | ||
| 772 | + break; | ||
| 773 | + } | ||
| 774 | +#endif | ||
| 775 | + return get_errno(socket(domain, type, protocol)); | ||
| 776 | +} | ||
| 777 | + | ||
| 778 | +static long do_bind(int sockfd, target_ulong target_addr, | ||
| 779 | + socklen_t addrlen) | ||
| 780 | +{ | ||
| 781 | + void *addr = alloca(addrlen); | ||
| 782 | + | ||
| 783 | + target_to_host_sockaddr(addr, target_addr, addrlen); | ||
| 784 | + return get_errno(bind(sockfd, addr, addrlen)); | ||
| 785 | +} | ||
| 786 | + | ||
| 787 | +static long do_connect(int sockfd, target_ulong target_addr, | ||
| 788 | + socklen_t addrlen) | ||
| 789 | +{ | ||
| 790 | + void *addr = alloca(addrlen); | ||
| 791 | + | ||
| 792 | + target_to_host_sockaddr(addr, target_addr, addrlen); | ||
| 793 | + return get_errno(connect(sockfd, addr, addrlen)); | ||
| 794 | +} | ||
| 795 | + | ||
| 796 | +static long do_sendrecvmsg(int fd, target_ulong target_msg, | ||
| 797 | + int flags, int send) | ||
| 798 | +{ | ||
| 799 | + long ret; | ||
| 800 | + struct target_msghdr *msgp; | ||
| 801 | + struct msghdr msg; | ||
| 802 | + int count; | ||
| 803 | + struct iovec *vec; | ||
| 804 | + target_ulong target_vec; | ||
| 805 | + | ||
| 806 | + lock_user_struct(msgp, target_msg, 1); | ||
| 807 | + if (msgp->msg_name) { | ||
| 808 | + msg.msg_namelen = tswap32(msgp->msg_namelen); | ||
| 809 | + msg.msg_name = alloca(msg.msg_namelen); | ||
| 810 | + target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), | ||
| 811 | + msg.msg_namelen); | ||
| 812 | + } else { | ||
| 813 | + msg.msg_name = NULL; | ||
| 814 | + msg.msg_namelen = 0; | ||
| 815 | + } | ||
| 816 | + msg.msg_controllen = 2 * tswapl(msgp->msg_controllen); | ||
| 817 | + msg.msg_control = alloca(msg.msg_controllen); | ||
| 818 | + msg.msg_flags = tswap32(msgp->msg_flags); | ||
| 819 | + | ||
| 820 | + count = tswapl(msgp->msg_iovlen); | ||
| 821 | + vec = alloca(count * sizeof(struct iovec)); | ||
| 822 | + target_vec = tswapl(msgp->msg_iov); | ||
| 823 | + lock_iovec(vec, target_vec, count, send); | ||
| 824 | + msg.msg_iovlen = count; | ||
| 825 | + msg.msg_iov = vec; | ||
| 826 | + | ||
| 827 | + if (send) { | ||
| 828 | + target_to_host_cmsg(&msg, msgp); | ||
| 829 | + ret = get_errno(sendmsg(fd, &msg, flags)); | ||
| 830 | + } else { | ||
| 831 | + ret = get_errno(recvmsg(fd, &msg, flags)); | ||
| 832 | + if (!is_error(ret)) | ||
| 833 | + host_to_target_cmsg(msgp, &msg); | ||
| 834 | + } | ||
| 835 | + unlock_iovec(vec, target_vec, count, !send); | ||
| 836 | + return ret; | ||
| 837 | +} | ||
| 838 | + | ||
| 714 | static long do_socketcall(int num, target_ulong vptr) | 839 | static long do_socketcall(int num, target_ulong vptr) |
| 715 | { | 840 | { |
| 716 | long ret; | 841 | long ret; |
| @@ -722,8 +847,7 @@ static long do_socketcall(int num, target_ulong vptr) | @@ -722,8 +847,7 @@ static long do_socketcall(int num, target_ulong vptr) | ||
| 722 | int domain = tgetl(vptr); | 847 | int domain = tgetl(vptr); |
| 723 | int type = tgetl(vptr + n); | 848 | int type = tgetl(vptr + n); |
| 724 | int protocol = tgetl(vptr + 2 * n); | 849 | int protocol = tgetl(vptr + 2 * n); |
| 725 | - | ||
| 726 | - ret = get_errno(socket(domain, type, protocol)); | 850 | + ret = do_socket(domain, type, protocol); |
| 727 | } | 851 | } |
| 728 | break; | 852 | break; |
| 729 | case SOCKOP_bind: | 853 | case SOCKOP_bind: |
| @@ -731,10 +855,7 @@ static long do_socketcall(int num, target_ulong vptr) | @@ -731,10 +855,7 @@ static long do_socketcall(int num, target_ulong vptr) | ||
| 731 | int sockfd = tgetl(vptr); | 855 | int sockfd = tgetl(vptr); |
| 732 | target_ulong target_addr = tgetl(vptr + n); | 856 | target_ulong target_addr = tgetl(vptr + n); |
| 733 | socklen_t addrlen = tgetl(vptr + 2 * n); | 857 | socklen_t addrlen = tgetl(vptr + 2 * n); |
| 734 | - void *addr = alloca(addrlen); | ||
| 735 | - | ||
| 736 | - target_to_host_sockaddr(addr, target_addr, addrlen); | ||
| 737 | - ret = get_errno(bind(sockfd, addr, addrlen)); | 858 | + ret = do_bind(sockfd, target_addr, addrlen); |
| 738 | } | 859 | } |
| 739 | break; | 860 | break; |
| 740 | case SOCKOP_connect: | 861 | case SOCKOP_connect: |
| @@ -742,17 +863,13 @@ static long do_socketcall(int num, target_ulong vptr) | @@ -742,17 +863,13 @@ static long do_socketcall(int num, target_ulong vptr) | ||
| 742 | int sockfd = tgetl(vptr); | 863 | int sockfd = tgetl(vptr); |
| 743 | target_ulong target_addr = tgetl(vptr + n); | 864 | target_ulong target_addr = tgetl(vptr + n); |
| 744 | socklen_t addrlen = tgetl(vptr + 2 * n); | 865 | socklen_t addrlen = tgetl(vptr + 2 * n); |
| 745 | - void *addr = alloca(addrlen); | ||
| 746 | - | ||
| 747 | - target_to_host_sockaddr(addr, target_addr, addrlen); | ||
| 748 | - ret = get_errno(connect(sockfd, addr, addrlen)); | 866 | + ret = do_connect(sockfd, target_addr, addrlen); |
| 749 | } | 867 | } |
| 750 | break; | 868 | break; |
| 751 | case SOCKOP_listen: | 869 | case SOCKOP_listen: |
| 752 | { | 870 | { |
| 753 | int sockfd = tgetl(vptr); | 871 | int sockfd = tgetl(vptr); |
| 754 | int backlog = tgetl(vptr + n); | 872 | int backlog = tgetl(vptr + n); |
| 755 | - | ||
| 756 | ret = get_errno(listen(sockfd, backlog)); | 873 | ret = get_errno(listen(sockfd, backlog)); |
| 757 | } | 874 | } |
| 758 | break; | 875 | break; |
| @@ -895,46 +1012,14 @@ static long do_socketcall(int num, target_ulong vptr) | @@ -895,46 +1012,14 @@ static long do_socketcall(int num, target_ulong vptr) | ||
| 895 | { | 1012 | { |
| 896 | int fd; | 1013 | int fd; |
| 897 | target_ulong target_msg; | 1014 | target_ulong target_msg; |
| 898 | - struct target_msghdr *msgp; | ||
| 899 | - struct msghdr msg; | ||
| 900 | - int flags, count; | ||
| 901 | - struct iovec *vec; | ||
| 902 | - target_ulong target_vec; | ||
| 903 | - int send = (num == SOCKOP_sendmsg); | ||
| 904 | - | ||
| 905 | - target_msg = tgetl(vptr + n); | ||
| 906 | - lock_user_struct(msgp, target_msg, 1); | ||
| 907 | - if (msgp->msg_name) { | ||
| 908 | - msg.msg_namelen = tswap32(msgp->msg_namelen); | ||
| 909 | - msg.msg_name = alloca(msg.msg_namelen); | ||
| 910 | - target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), | ||
| 911 | - msg.msg_namelen); | ||
| 912 | - } else { | ||
| 913 | - msg.msg_name = NULL; | ||
| 914 | - msg.msg_namelen = 0; | ||
| 915 | - } | ||
| 916 | - msg.msg_controllen = 2 * tswapl(msgp->msg_controllen); | ||
| 917 | - msg.msg_control = alloca(msg.msg_controllen); | ||
| 918 | - msg.msg_flags = tswap32(msgp->msg_flags); | ||
| 919 | - | ||
| 920 | - count = tswapl(msgp->msg_iovlen); | ||
| 921 | - vec = alloca(count * sizeof(struct iovec)); | ||
| 922 | - target_vec = tswapl(msgp->msg_iov); | ||
| 923 | - lock_iovec(vec, target_vec, count, send); | ||
| 924 | - msg.msg_iovlen = count; | ||
| 925 | - msg.msg_iov = vec; | 1015 | + int flags; |
| 926 | 1016 | ||
| 927 | fd = tgetl(vptr); | 1017 | fd = tgetl(vptr); |
| 1018 | + target_msg = tgetl(vptr + n); | ||
| 928 | flags = tgetl(vptr + 2 * n); | 1019 | flags = tgetl(vptr + 2 * n); |
| 929 | - if (send) { | ||
| 930 | - target_to_host_cmsg(&msg, msgp); | ||
| 931 | - ret = get_errno(sendmsg(fd, &msg, flags)); | ||
| 932 | - } else { | ||
| 933 | - ret = get_errno(recvmsg(fd, &msg, flags)); | ||
| 934 | - if (!is_error(ret)) | ||
| 935 | - host_to_target_cmsg(msgp, &msg); | ||
| 936 | - } | ||
| 937 | - unlock_iovec(vec, target_vec, count, !send); | 1020 | + |
| 1021 | + ret = do_sendrecvmsg(fd, target_msg, flags, | ||
| 1022 | + (num == SOCKOP_sendmsg)); | ||
| 938 | } | 1023 | } |
| 939 | break; | 1024 | break; |
| 940 | case SOCKOP_setsockopt: | 1025 | case SOCKOP_setsockopt: |
| @@ -967,6 +1052,22 @@ static long do_socketcall(int num, target_ulong vptr) | @@ -967,6 +1052,22 @@ static long do_socketcall(int num, target_ulong vptr) | ||
| 967 | return ret; | 1052 | return ret; |
| 968 | } | 1053 | } |
| 969 | 1054 | ||
| 1055 | +/* XXX: suppress this function and call directly the related socket | ||
| 1056 | + functions */ | ||
| 1057 | +static long do_socketcallwrapper(int num, long arg1, long arg2, long arg3, | ||
| 1058 | + long arg4, long arg5, long arg6) | ||
| 1059 | +{ | ||
| 1060 | + target_long args[6]; | ||
| 1061 | + | ||
| 1062 | + tputl(args, arg1); | ||
| 1063 | + tputl(args+1, arg2); | ||
| 1064 | + tputl(args+2, arg3); | ||
| 1065 | + tputl(args+3, arg4); | ||
| 1066 | + tputl(args+4, arg5); | ||
| 1067 | + tputl(args+5, arg6); | ||
| 1068 | + | ||
| 1069 | + return do_socketcall(num, (target_ulong) args); | ||
| 1070 | +} | ||
| 970 | 1071 | ||
| 971 | #define N_SHM_REGIONS 32 | 1072 | #define N_SHM_REGIONS 32 |
| 972 | 1073 | ||
| @@ -2616,6 +2717,93 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2616,6 +2717,93 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 2616 | case TARGET_NR_socketcall: | 2717 | case TARGET_NR_socketcall: |
| 2617 | ret = do_socketcall(arg1, arg2); | 2718 | ret = do_socketcall(arg1, arg2); |
| 2618 | break; | 2719 | break; |
| 2720 | + | ||
| 2721 | +#ifdef TARGET_NR_accept | ||
| 2722 | + case TARGET_NR_accept: | ||
| 2723 | + ret = do_socketcallwrapper(SOCKOP_accept, arg1, arg2, arg3, arg4, arg5, arg6); | ||
| 2724 | + break; | ||
| 2725 | +#endif | ||
| 2726 | +#ifdef TARGET_NR_bind | ||
| 2727 | + case TARGET_NR_bind: | ||
| 2728 | + ret = do_bind(arg1, arg2, arg3); | ||
| 2729 | + break; | ||
| 2730 | +#endif | ||
| 2731 | +#ifdef TARGET_NR_connect | ||
| 2732 | + case TARGET_NR_connect: | ||
| 2733 | + ret = do_connect(arg1, arg2, arg3); | ||
| 2734 | + break; | ||
| 2735 | +#endif | ||
| 2736 | +#ifdef TARGET_NR_getpeername | ||
| 2737 | + case TARGET_NR_getpeername: | ||
| 2738 | + ret = do_socketcallwrapper(SOCKOP_getpeername, arg1, arg2, arg3, arg4, arg5, arg6); | ||
| 2739 | + break; | ||
| 2740 | +#endif | ||
| 2741 | +#ifdef TARGET_NR_getsockname | ||
| 2742 | + case TARGET_NR_getsockname: | ||
| 2743 | + ret = do_socketcallwrapper(SOCKOP_getsockname, arg1, arg2, arg3, arg4, arg5, arg6); | ||
| 2744 | + break; | ||
| 2745 | +#endif | ||
| 2746 | +#ifdef TARGET_NR_getsockopt | ||
| 2747 | + case TARGET_NR_getsockopt: | ||
| 2748 | + ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5); | ||
| 2749 | + break; | ||
| 2750 | +#endif | ||
| 2751 | +#ifdef TARGET_NR_listen | ||
| 2752 | + case TARGET_NR_listen: | ||
| 2753 | + ret = do_socketcallwrapper(SOCKOP_listen, arg1, arg2, arg3, arg4, arg5, arg6); | ||
| 2754 | + break; | ||
| 2755 | +#endif | ||
| 2756 | +#ifdef TARGET_NR_recv | ||
| 2757 | + case TARGET_NR_recv: | ||
| 2758 | + ret = do_socketcallwrapper(SOCKOP_recv, arg1, arg2, arg3, arg4, arg5, arg6); | ||
| 2759 | + break; | ||
| 2760 | +#endif | ||
| 2761 | +#ifdef TARGET_NR_recvfrom | ||
| 2762 | + case TARGET_NR_recvfrom: | ||
| 2763 | + ret = do_socketcallwrapper(SOCKOP_recvfrom, arg1, arg2, arg3, arg4, arg5, arg6); | ||
| 2764 | + break; | ||
| 2765 | +#endif | ||
| 2766 | +#ifdef TARGET_NR_recvmsg | ||
| 2767 | + case TARGET_NR_recvmsg: | ||
| 2768 | + ret = do_sendrecvmsg(arg1, arg2, arg3, 0); | ||
| 2769 | + break; | ||
| 2770 | +#endif | ||
| 2771 | +#ifdef TARGET_NR_send | ||
| 2772 | + case TARGET_NR_send: | ||
| 2773 | + ret = do_socketcallwrapper(SOCKOP_send, arg1, arg2, arg3, arg4, arg5, arg6); | ||
| 2774 | + break; | ||
| 2775 | +#endif | ||
| 2776 | +#ifdef TARGET_NR_sendmsg | ||
| 2777 | + case TARGET_NR_sendmsg: | ||
| 2778 | + ret = do_sendrecvmsg(arg1, arg2, arg3, 1); | ||
| 2779 | + break; | ||
| 2780 | +#endif | ||
| 2781 | +#ifdef TARGET_NR_sendto | ||
| 2782 | + case TARGET_NR_sendto: | ||
| 2783 | + ret = do_socketcallwrapper(SOCKOP_sendto, arg1, arg2, arg3, arg4, arg5, arg6); | ||
| 2784 | + break; | ||
| 2785 | +#endif | ||
| 2786 | +#ifdef TARGET_NR_shutdown | ||
| 2787 | + case TARGET_NR_shutdown: | ||
| 2788 | + ret = do_socketcallwrapper(SOCKOP_shutdown, arg1, arg2, arg3, arg4, arg5, arg6); | ||
| 2789 | + break; | ||
| 2790 | +#endif | ||
| 2791 | +#ifdef TARGET_NR_socket | ||
| 2792 | + case TARGET_NR_socket: | ||
| 2793 | + ret = do_socket(arg1, arg2, arg3); | ||
| 2794 | + break; | ||
| 2795 | +#endif | ||
| 2796 | +#ifdef TARGET_NR_socketpair | ||
| 2797 | + case TARGET_NR_socketpair: | ||
| 2798 | + ret = do_socketcallwrapper(SOCKOP_socketpair, arg1, arg2, arg3, arg4, arg5, arg6); | ||
| 2799 | + break; | ||
| 2800 | +#endif | ||
| 2801 | +#ifdef TARGET_NR_setsockopt | ||
| 2802 | + case TARGET_NR_setsockopt: | ||
| 2803 | + ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5); | ||
| 2804 | + break; | ||
| 2805 | +#endif | ||
| 2806 | + | ||
| 2619 | case TARGET_NR_syslog: | 2807 | case TARGET_NR_syslog: |
| 2620 | goto unimplemented; | 2808 | goto unimplemented; |
| 2621 | case TARGET_NR_setitimer: | 2809 | case TARGET_NR_setitimer: |
linux-user/syscall_defs.h
| @@ -1502,3 +1502,5 @@ struct target_sysinfo { | @@ -1502,3 +1502,5 @@ struct target_sysinfo { | ||
| 1502 | unsigned int mem_unit; /* Memory unit size in bytes */ | 1502 | unsigned int mem_unit; /* Memory unit size in bytes */ |
| 1503 | char _f[20-2*sizeof(target_long)-sizeof(int)]; /* Padding: libc5 uses this.. */ | 1503 | char _f[20-2*sizeof(target_long)-sizeof(int)]; /* Padding: libc5 uses this.. */ |
| 1504 | }; | 1504 | }; |
| 1505 | + | ||
| 1506 | +#include "socket.h" |