From: Neng Chen <[email protected]>
Add support for options IPV6_ADD_MEMBERSHIP and IPV6_ADD_MEMBERSHIP
of the syscall setsockopt(). These options control membership in
multicast groups. Their argument is a pointer to a struct ipv6_mreq,
which is in turn defined as:
struct ipv6_mreq {
/* IPv6 multicast address of group */
struct in6_addr ipv6mr_multiaddr;
/* local IPv6 address of interface */
int ipv6mr_interface;
};
The in6_addr structure consists of fields that are always big-endian
(on any host), so the ipv6_mreq's field ipv6mr_multiaddr doesn't need
any endian conversion, whereas ipv6mr_interface does.
Signed-off-by: Neng Chen <[email protected]>
Signed-off-by: Aleksandar Markovic <[email protected]>
---
linux-user/syscall.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 96cd4bf..b7eb4b7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1892,6 +1892,25 @@ static abi_long do_setsockopt(int sockfd, int level, int
optname,
&pki, sizeof(pki)));
break;
}
+ case IPV6_ADD_MEMBERSHIP:
+ case IPV6_DROP_MEMBERSHIP:
+ {
+ struct ipv6_mreq ipv6mreq;
+
+ if (optlen < sizeof(ipv6mreq)) {
+ return -TARGET_EINVAL;
+ }
+
+ if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) {
+ return -TARGET_EFAULT;
+ }
+
+ ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
+
+ ret = get_errno(setsockopt(sockfd, level, optname,
+ &ipv6mreq, sizeof(ipv6mreq)));
+ break;
+ }
default:
goto unimplemented;
}
--
2.7.4