Commit b975b83becfc0d17b490e64a40f5c9c3e69f574f

Authored by Lionel Landwerlin
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>
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;
... ...