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 | 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 | 964 | static inline abi_long target_to_host_sockaddr(struct sockaddr *addr, |
947 | 965 | abi_ulong target_addr, |
948 | 966 | socklen_t len) |
... | ... | @@ -1118,6 +1136,7 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, |
1118 | 1136 | { |
1119 | 1137 | abi_long ret; |
1120 | 1138 | int val; |
1139 | + struct ip_mreqn *ip_mreq; | |
1121 | 1140 | |
1122 | 1141 | switch(level) { |
1123 | 1142 | case SOL_TCP: |
... | ... | @@ -1156,6 +1175,17 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, |
1156 | 1175 | } |
1157 | 1176 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); |
1158 | 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 | 1189 | default: |
1160 | 1190 | goto unimplemented; |
1161 | 1191 | } | ... | ... |
linux-user/syscall_defs.h
... | ... | @@ -111,6 +111,21 @@ struct target_sockaddr { |
111 | 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 | 129 | struct target_timeval { |
115 | 130 | abi_long tv_sec; |
116 | 131 | abi_long tv_usec; | ... | ... |