Message ID | 1556905846-14074-5-git-send-email-aleksandar.markovic@rt-rk.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | linux-user: A set of miscellaneous patches | expand |
On 03/05/2019 19:50, Aleksandar Markovic wrote: > From: Neng Chen <nchen@wavecomp.com> > > Add support for options IPV6_ADD_MEMBERSHIP and IPV6_DROP_MEMPEMBERSHIP > 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 host of any endian), so the ipv6_mreq's field ipv6mr_multiaddr > doesn't need any endian conversion, whereas ipv6mr_interface does. > > Signed-off-by: Neng Chen <nchen@wavecomp.com> > Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com> > --- > 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); The name of this field seems to depend on where it is defined: in netinet/in.h, it's ipv6mr_interface, but in linux/in6.h it's ipv6mr_ifindex. I think you should check "__UAPI_DEF_IPV6_MREQ" to use the good one. > + > + ret = get_errno(setsockopt(sockfd, level, optname, > + &ipv6mreq, sizeof(ipv6mreq))); > + break; > + } > default: > goto unimplemented; > } > Thanks, Laurent
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; }