Commit b975b83becfc0d17b490e64a40f5c9c3e69f574f
Committed by
Riku Voipio
1 parent
6f932f91
linux-user: Added IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP flags to setsockopt
linux-user: Added IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP flags to setsockopt Signed-off-by: Lionel Landwerlin <lionel.landwerlin@openwide.fr> Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
Showing
2 changed files
with
45 additions
and
0 deletions
linux-user/syscall.c
| @@ -943,6 +943,24 @@ static abi_long do_select(int n, | @@ -943,6 +943,24 @@ static abi_long do_select(int n, | ||
| 943 | return ret; | 943 | return ret; |
| 944 | } | 944 | } |
| 945 | 945 | ||
| 946 | +static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, | ||
| 947 | + abi_ulong target_addr, | ||
| 948 | + socklen_t len) | ||
| 949 | +{ | ||
| 950 | + struct target_ip_mreqn *target_smreqn; | ||
| 951 | + | ||
| 952 | + target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1); | ||
| 953 | + if (!target_smreqn) | ||
| 954 | + return -TARGET_EFAULT; | ||
| 955 | + mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr; | ||
| 956 | + mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr; | ||
| 957 | + if (len == sizeof(struct target_ip_mreqn)) | ||
| 958 | + mreqn->imr_ifindex = tswapl(target_smreqn->imr_ifindex); | ||
| 959 | + unlock_user(target_smreqn, target_addr, 0); | ||
| 960 | + | ||
| 961 | + return 0; | ||
| 962 | +} | ||
| 963 | + | ||
| 946 | static inline abi_long target_to_host_sockaddr(struct sockaddr *addr, | 964 | static inline abi_long target_to_host_sockaddr(struct sockaddr *addr, |
| 947 | abi_ulong target_addr, | 965 | abi_ulong target_addr, |
| 948 | socklen_t len) | 966 | socklen_t len) |
| @@ -1118,6 +1136,7 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, | @@ -1118,6 +1136,7 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, | ||
| 1118 | { | 1136 | { |
| 1119 | abi_long ret; | 1137 | abi_long ret; |
| 1120 | int val; | 1138 | int val; |
| 1139 | + struct ip_mreqn *ip_mreq; | ||
| 1121 | 1140 | ||
| 1122 | switch(level) { | 1141 | switch(level) { |
| 1123 | case SOL_TCP: | 1142 | case SOL_TCP: |
| @@ -1156,6 +1175,17 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, | @@ -1156,6 +1175,17 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, | ||
| 1156 | } | 1175 | } |
| 1157 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); | 1176 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); |
| 1158 | break; | 1177 | break; |
| 1178 | + case IP_ADD_MEMBERSHIP: | ||
| 1179 | + case IP_DROP_MEMBERSHIP: | ||
| 1180 | + if (optlen < sizeof (struct target_ip_mreq) || | ||
| 1181 | + optlen > sizeof (struct target_ip_mreqn)) | ||
| 1182 | + return -TARGET_EINVAL; | ||
| 1183 | + | ||
| 1184 | + ip_mreq = (struct ip_mreqn *) alloca(optlen); | ||
| 1185 | + target_to_host_ip_mreq(ip_mreq, optval_addr, optlen); | ||
| 1186 | + ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen)); | ||
| 1187 | + break; | ||
| 1188 | + | ||
| 1159 | default: | 1189 | default: |
| 1160 | goto unimplemented; | 1190 | goto unimplemented; |
| 1161 | } | 1191 | } |
linux-user/syscall_defs.h
| @@ -111,6 +111,21 @@ struct target_sockaddr { | @@ -111,6 +111,21 @@ struct target_sockaddr { | ||
| 111 | uint8_t sa_data[14]; | 111 | uint8_t sa_data[14]; |
| 112 | }; | 112 | }; |
| 113 | 113 | ||
| 114 | +struct target_in_addr { | ||
| 115 | + uint32_t s_addr; /* big endian */ | ||
| 116 | +}; | ||
| 117 | + | ||
| 118 | +struct target_ip_mreq { | ||
| 119 | + struct target_in_addr imr_multiaddr; | ||
| 120 | + struct target_in_addr imr_address; | ||
| 121 | +}; | ||
| 122 | + | ||
| 123 | +struct target_ip_mreqn { | ||
| 124 | + struct target_in_addr imr_multiaddr; | ||
| 125 | + struct target_in_addr imr_address; | ||
| 126 | + abi_long imr_ifindex; | ||
| 127 | +}; | ||
| 128 | + | ||
| 114 | struct target_timeval { | 129 | struct target_timeval { |
| 115 | abi_long tv_sec; | 130 | abi_long tv_sec; |
| 116 | abi_long tv_usec; | 131 | abi_long tv_usec; |