From: Neng Chen <nc...@wavecomp.com> Add support for the option IPV6_ADD_MEMBERSHIP of the syscall setsockopt(). This option controls membership in multicast groups. Argument is a pointer to a struct ipv6_mreq, which is in turn defined in a platform-inedependant manner in the Linux kernel file include/uapi/linux/in6.h as:
The <netinet/in.h> header defines the ipv6_mreq structure, which includes the following members: struct in6_addr ipv6mr_multiaddr /* IPv6 multicast address */ unsigned int ipv6mr_interface /* local interface index */ struct ipv6_mreq { /* IPv6 multicast address of group */ struct in6_addr ipv6mr_multiaddr; /* local IPv6 address of interface */ int ipv6mr_ifindex; }; The <netinet/in.h> header also defines the in6_addr structure, which a union of the following structure: struct in6_addr { union { __u8 u6_addr8[16]; __be16 u6_addr16[8]; __be32 u6_addr32[4]; } in6_u; The emulation behavior of IPV6_ADD_MEMBERSHIP is devised based on the definitions above. Signed-off-by: Neng Chen <nc...@wavecomp.com> Signed-off-by: Aleksandar Markovic <amarko...@wavecomp.com> --- linux-user/syscall.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 96cd4bf..b47a45d 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1892,6 +1892,24 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, &pki, sizeof(pki))); break; } + case IPV6_ADD_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