From: Ben N. <in...@bn...> - 2014-03-17 22:20:23
|
A small test program follows: #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stddef.h> int main(void) { int fd; struct ip_mreq m4; struct ipv6_mreq m6; fd = socket(AF_INET6, SOCK_DGRAM, 0); inet_aton("224.0.0.2", &m4.imr_multiaddr); inet_aton("0.0.0.0", &m4.imr_interface); inet_pton(AF_INET6, "ff01::c", &m6.ipv6mr_multiaddr); m6.ipv6mr_interface = 42; setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &m4, 4); setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, &m4, 4); setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &m4, sizeof(m4)); setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, &m4, sizeof(m4)); setsockopt(fd, SOL_IP, IPV6_ADD_MEMBERSHIP, &m6, sizeof(m6)); setsockopt(fd, SOL_IP, IPV6_DROP_MEMBERSHIP, &m6, sizeof(m6)); setsockopt(fd, SOL_IP, IPV6_ADD_MEMBERSHIP, &m6, 4); setsockopt(fd, SOL_IP, IPV6_DROP_MEMBERSHIP, &m6, 4); return 0; } And prints the following output when traced: setsockopt(3, SOL_IP, IP_ADD_MEMBERSHIP, "\340\0\0\2", 4) = -1 EINVAL (Invalid argument) setsockopt(3, SOL_IP, IP_DROP_MEMBERSHIP, "\340\0\0\2", 4) = -1 EINVAL (Invalid argument) setsockopt(3, SOL_IP, IP_ADD_MEMBERSHIP, {imr_multiaddr=inet_addr("224.0.0.2"), imr_interface=inet_addr("0.0.0.0")}, 8) = 0 setsockopt(3, SOL_IP, IP_DROP_MEMBERSHIP, {imr_multiaddr=inet_addr("224.0.0.2"), imr_interface=inet_addr("0.0.0.0")}, 8) = 0 setsockopt(3, SOL_IP, IPV6_ADD_MEMBERSHIP, {ipv6mr_multiaddr=inet_addr("ff01::c"), ipv6mr_interface=42}, 20) = 0 setsockopt(3, SOL_IP, IPV6_DROP_MEMBERSHIP, {ipv6mr_multiaddr=inet_addr("ff01::c"), ipv6mr_interface=42}, 20) = -1 EINVAL (Invalid argument) setsockopt(3, SOL_IP, IPV6_ADD_MEMBERSHIP, "\377\1\0\0", 4) = 0 setsockopt(3, SOL_IP, IPV6_DROP_MEMBERSHIP, "\377\1\0\0", 4) = -1 EINVAL (Invalid argument) * net.c (sys_setsockopt): decode IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IPV6_ADD_MEMBERSHIP and IPV6_DROP_MEMBERSHIP arguments. Signed-off-by: Ben Noordhuis <in...@bn...> --- net.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/net.c b/net.c index a466efe..9cdd44e 100644 --- a/net.c +++ b/net.c @@ -2301,6 +2301,49 @@ static void printicmpfilter(struct tcb *tcp, long addr) } #endif /* ICMP_FILTER */ +#if defined(IP_ADD_MEMBERSHIP) || defined(IP_DROP_MEMBERSHIP) +static void printmreq(struct tcb *tcp, long addr, int len) +{ + struct ip_mreq mreq; + if (len == sizeof(mreq) && umove(tcp, addr, &mreq) == 0) { + tprintf("{imr_multiaddr=inet_addr(\"%s\"),", + inet_ntoa(mreq.imr_multiaddr)); + tprintf(" imr_interface=inet_addr(\"%s\")}", + inet_ntoa(mreq.imr_interface)); + } + else { + printstr(tcp, addr, len); + } +} +#endif /* defined(IP_ADD_MEMBERSHIP) || defined(IP_DROP_MEMBERSHIP) */ + +#if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP) +static void printmreq6(struct tcb *tcp, long addr, int len) +{ +#if HAVE_INET_NTOP + struct ipv6_mreq mreq; + const struct in6_addr *in6; + char text[INET6_ADDRSTRLEN]; + + if (len != sizeof(mreq)) + goto fail; + + if (umove(tcp, addr, &mreq) < 0) + goto fail; + + in6 = &mreq.ipv6mr_multiaddr; + if (inet_ntop(AF_INET6, in6, text, sizeof(text)) != text) + goto fail; + + tprintf("{ipv6mr_multiaddr=inet_ntop(\"%s\"), ipv6mr_interface=%d}", + text, mreq.ipv6mr_interface); + return; +fail: +#endif /* HAVE_INET_NTOP */ + printstr(tcp, addr, len); +} +#endif /* defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP) */ + static int printsockopt(struct tcb *tcp, int level, int name, long addr, int len) { @@ -2327,7 +2370,34 @@ printsockopt(struct tcb *tcp, int level, int name, long addr, int len) break; #ifdef SOL_IP case SOL_IP: - printxval(sockipoptions, name, "IP_???"); + switch (name) { +#ifdef IP_ADD_MEMBERSHIP + case IP_ADD_MEMBERSHIP: + tprints("IP_ADD_MEMBERSHIP, "); + printmreq(tcp, addr, len); + return 0; +#endif +#ifdef IP_DROP_MEMBERSHIP + case IP_DROP_MEMBERSHIP: + tprints("IP_DROP_MEMBERSHIP, "); + printmreq(tcp, addr, len); + return 0; +#endif +#ifdef IPV6_ADD_MEMBERSHIP + case IPV6_ADD_MEMBERSHIP: + tprints("IPV6_ADD_MEMBERSHIP, "); + printmreq6(tcp, addr, len); + return 0; +#endif +#ifdef IPV6_DROP_MEMBERSHIP + case IPV6_DROP_MEMBERSHIP: + tprints("IPV6_DROP_MEMBERSHIP, "); + printmreq6(tcp, addr, len); + return 0; +#endif + default: + printxval(sockipoptions, name, "IP_???"); + } break; #endif #ifdef SOL_IPV6 -- 1.8.5.3 |