linux-user: Add support for setsockopt() options IPV6_<ADD|DROP>_MEMBERSHIP
Add support for the option IPV6_<ADD|DROP>_MEMBERSHIP of the syscall setsockopt(). This option controls membership in multicast groups. Argument is a pointer to a struct ipv6_mreq. The glibc <netinet/in.h> header defines the ipv6_mreq structure, which includes the following members: struct in6_addr ipv6mr_multiaddr; unsigned int ipv6mr_interface; Whereas the kernel in its <linux/in6.h> header defines following members of the same structure: struct in6_addr ipv6mr_multiaddr; int ipv6mr_ifindex; POSIX defines ipv6mr_interface [1]. __UAPI_DEF_IVP6_MREQ appears in kernel headers with v3.12: cfd280c91253 net: sync some IP headers with glibc Without __UAPI_DEF_IVP6_MREQ, kernel defines ipv6mr_ifindex, and this is explained in cfd280c91253: "If you include the kernel headers first you get those, and if you include the glibc headers first you get those, and the following patch arranges a coordination and synchronization between the two." So before 3.12, a program can't include both <netinet/in.h> and <linux/in6.h>. In linux-user/syscall.c, we only include <netinet/in.h> (glibc) and not <linux/in6.h> (kernel headers), so ipv6mr_interface is the one to use. [1] http://pubs.opengroup.org/onlinepubs/009695399/basedefs/netinet/in.h.html Signed-off-by: Neng Chen <nchen@wavecomp.com> Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <1560953834-29584-2-git-send-email-aleksandar.markovic@rt-rk.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
parent
f31dddd2fc
commit
22bf4ee903
@ -1892,6 +1892,25 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
|
|||||||
&pki, sizeof(pki)));
|
&pki, sizeof(pki)));
|
||||||
break;
|
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:
|
default:
|
||||||
goto unimplemented;
|
goto unimplemented;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user