From: Dmitry V. Levin Date: Mon, 8 Jun 2015 14:19:46 +0000 (+0000) Subject: net: decode setsockopt() multicast arguments X-Git-Tag: v4.11~506 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7bee462a645a69e042c7262317f40c77d1516d95;p=strace net: decode setsockopt() multicast arguments * configure.ac (AC_CHECK_FUNCS): Add inet_pton. * net.c (print_mreq, print_mreq6): New functions. (print_setsockopt): Use them to decode IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_JOIN_ANYCAST, and IPV6_LEAVE_ANYCAST. * tests/ip_mreq.c: New file. * tests/ip_mreq.expected: Likewise. * tests/ip_mreq.test: New test. * tests/Makefile.am (check_PROGRAMS): Add ip_mreq. (TESTS): Add ip_mreq.test. (EXTRA_DIST): ip_mreq.expected. * tests/.gitignore: Add ip_mreq. Based on patch by Ben Noordhuis . --- diff --git a/configure.ac b/configure.ac index 060a1209..bb8bf46f 100644 --- a/configure.ac +++ b/configure.ac @@ -233,6 +233,7 @@ AC_CHECK_FUNCS(m4_normalize([ fputs_unlocked if_indextoname inet_ntop + inet_pton pipe2 prctl preadv diff --git a/net.c b/net.c index fc325df0..ff7b456c 100644 --- a/net.c +++ b/net.c @@ -1307,6 +1307,64 @@ SYS_FUNC(getsockopt) return 0; } +#ifdef IP_ADD_MEMBERSHIP +static void +print_mreq(struct tcb *tcp, long addr, unsigned int len) +{ + struct ip_mreq mreq; + + if (len < sizeof(mreq)) { + printstr(tcp, addr, len); + return; + } + if (umove(tcp, addr, &mreq) < 0) { + tprintf("%#lx", addr); + return; + } + tprints("{imr_multiaddr=inet_addr("); + print_quoted_string(inet_ntoa(mreq.imr_multiaddr), + 16, QUOTE_0_TERMINATED); + tprints("), imr_interface=inet_addr("); + print_quoted_string(inet_ntoa(mreq.imr_interface), + 16, QUOTE_0_TERMINATED); + tprints(")}"); +} +#endif /* IP_ADD_MEMBERSHIP */ + +#ifdef IPV6_ADD_MEMBERSHIP +static void +print_mreq6(struct tcb *tcp, long addr, unsigned int len) +{ + struct ipv6_mreq mreq; + + if (len < sizeof(mreq)) + goto fail; + + if (umove(tcp, addr, &mreq) < 0) { + tprintf("%#lx", addr); + return; + } + +#ifdef HAVE_INET_NTOP + const struct in6_addr *in6 = &mreq.ipv6mr_multiaddr; + char address[INET6_ADDRSTRLEN]; + + if (!inet_ntop(AF_INET6, in6, address, sizeof(address))) + goto fail; + + tprints("{ipv6mr_multiaddr=inet_pton("); + print_quoted_string(address, sizeof(address), QUOTE_0_TERMINATED); + tprints("), ipv6mr_interface="); + print_ifindex(mreq.ipv6mr_interface); + tprints("}"); + return; +#endif /* HAVE_INET_NTOP */ + +fail: + printstr(tcp, addr, len); +} +#endif /* IPV6_ADD_MEMBERSHIP */ + #ifdef MCAST_JOIN_GROUP static void print_group_req(struct tcb *tcp, long addr, int len) @@ -1420,6 +1478,12 @@ print_setsockopt(struct tcb *tcp, int level, int name, long addr, int len) case SOL_IP: switch (name) { +#ifdef IP_ADD_MEMBERSHIP + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + print_mreq(tcp, addr, len); + goto done; +#endif /* IP_ADD_MEMBERSHIP */ #ifdef MCAST_JOIN_GROUP case MCAST_JOIN_GROUP: case MCAST_LEAVE_GROUP: @@ -1429,6 +1493,23 @@ print_setsockopt(struct tcb *tcp, int level, int name, long addr, int len) } break; + case SOL_IPV6: + switch (name) { +#ifdef IPV6_ADD_MEMBERSHIP + case IPV6_ADD_MEMBERSHIP: + case IPV6_DROP_MEMBERSHIP: +# ifdef IPV6_JOIN_ANYCAST + case IPV6_JOIN_ANYCAST: +# endif +# ifdef IPV6_LEAVE_ANYCAST + case IPV6_LEAVE_ANYCAST: +# endif + print_mreq6(tcp, addr, len); + goto done; +#endif /* IPV6_ADD_MEMBERSHIP */ + } + break; + case SOL_PACKET: switch (name) { #ifdef PACKET_RX_RING diff --git a/tests/.gitignore b/tests/.gitignore index 6903a5ce..c3eada90 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -3,6 +3,7 @@ fanotify_mark getrandom inet-accept-connect-send-recv ioctl +ip_mreq ipc_msg ipc_sem ipc_shm diff --git a/tests/Makefile.am b/tests/Makefile.am index 7ace705b..f1e88205 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -14,6 +14,7 @@ check_PROGRAMS = \ getrandom \ inet-accept-connect-send-recv \ ioctl \ + ip_mreq \ ipc_msg \ ipc_sem \ ipc_shm \ @@ -61,6 +62,7 @@ TESTS = \ getdents.test \ getrandom.test \ ioctl.test \ + ip_mreq.test \ ipc_msg.test \ ipc_shm.test \ ipc_sem.test \ @@ -109,6 +111,7 @@ EXTRA_DIST = init.sh run.sh match.awk \ getdents.out \ getrandom.awk \ ioctl.expected \ + ip_mreq.expected \ ipc.sh \ mmsg.expected \ net.expected \ diff --git a/tests/ip_mreq.c b/tests/ip_mreq.c new file mode 100644 index 00000000..db208b8e --- /dev/null +++ b/tests/ip_mreq.c @@ -0,0 +1,45 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include +#include + +int +main(void) +{ +#if defined IP_ADD_MEMBERSHIP && defined IPV6_ADD_MEMBERSHIP \ + && defined IPV6_JOIN_ANYCAST && defined HAVE_INET_PTON + struct ip_mreq m4; + struct ipv6_mreq m6; + + inet_pton(AF_INET, "224.0.0.3", &m4.imr_multiaddr); + inet_pton(AF_INET, "127.0.0.1", &m4.imr_interface); + inet_pton(AF_INET6, "ff01::c", &m6.ipv6mr_multiaddr); + m6.ipv6mr_interface = 1; + + (void) close(0); + assert(socket(AF_INET, SOCK_DGRAM, 0) == 0); + + assert(setsockopt(0, SOL_IP, IP_ADD_MEMBERSHIP, &m4, 1) == -1); + assert(setsockopt(0, SOL_IP, IP_DROP_MEMBERSHIP, &m4, 1) == -1); + assert(setsockopt(0, SOL_IP, IP_ADD_MEMBERSHIP, &m4, sizeof(m4)) == 0); + assert(setsockopt(0, SOL_IP, IP_DROP_MEMBERSHIP, &m4, sizeof(m4)) == 0); + + assert(setsockopt(0, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &m6, 1) == -1); + assert(setsockopt(0, SOL_IPV6, IPV6_DROP_MEMBERSHIP, &m6, 1) == -1); + assert(setsockopt(0, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &m6, sizeof(m6)) == -1); + assert(setsockopt(0, SOL_IPV6, IPV6_DROP_MEMBERSHIP, &m6, sizeof(m6)) == -1); + + assert(setsockopt(0, SOL_IPV6, IPV6_JOIN_ANYCAST, &m6, 1) == -1); + assert(setsockopt(0, SOL_IPV6, IPV6_LEAVE_ANYCAST, &m6, 1) == -1); + assert(setsockopt(0, SOL_IPV6, IPV6_JOIN_ANYCAST, &m6, sizeof(m6)) == -1); + assert(setsockopt(0, SOL_IPV6, IPV6_LEAVE_ANYCAST, &m6, sizeof(m6)) == -1); + + return 0; +#else + return 77; +#endif +} diff --git a/tests/ip_mreq.expected b/tests/ip_mreq.expected new file mode 100644 index 00000000..e694c73e --- /dev/null +++ b/tests/ip_mreq.expected @@ -0,0 +1,12 @@ +setsockopt\(0, SOL_IP, IP_ADD_MEMBERSHIP, "\\340", 1\) = -1 EINVAL .* +setsockopt\(0, SOL_IP, IP_DROP_MEMBERSHIP, "\\340", 1\) = -1 EINVAL .* +setsockopt\(0, SOL_IP, IP_ADD_MEMBERSHIP, \{imr_multiaddr=inet_addr\("224\.0\.0\.3"\), imr_interface=inet_addr\("127\.0\.0\.1"\)\}, 8\) = 0 +setsockopt\(0, SOL_IP, IP_DROP_MEMBERSHIP, \{imr_multiaddr=inet_addr\("224\.0\.0\.3"\), imr_interface=inet_addr\("127\.0\.0\.1"\)\}, 8\) = 0 +setsockopt\(0, SOL_IPV6, IPV6_ADD_MEMBERSHIP, "\\377", 1\) = -1 ENOPROTOOPT .* +setsockopt\(0, SOL_IPV6, IPV6_DROP_MEMBERSHIP, "\\377", 1\) = -1 ENOPROTOOPT .* +setsockopt\(0, SOL_IPV6, IPV6_ADD_MEMBERSHIP, \{ipv6mr_multiaddr=inet_pton\("ff01::c"\), ipv6mr_interface=if_nametoindex\("lo"\)\}, 20\) = -1 ENOPROTOOPT .* +setsockopt\(0, SOL_IPV6, IPV6_DROP_MEMBERSHIP, \{ipv6mr_multiaddr=inet_pton\("ff01::c"\), ipv6mr_interface=if_nametoindex\("lo"\)\}, 20\) = -1 ENOPROTOOPT .* +setsockopt\(0, SOL_IPV6, IPV6_JOIN_ANYCAST, "\\377", 1\) = -1 ENOPROTOOPT .* +setsockopt\(0, SOL_IPV6, IPV6_LEAVE_ANYCAST, "\\377", 1\) = -1 ENOPROTOOPT .* +setsockopt\(0, SOL_IPV6, IPV6_JOIN_ANYCAST, \{ipv6mr_multiaddr=inet_pton\("ff01::c"\), ipv6mr_interface=if_nametoindex\("lo"\)\}, 20\) = -1 ENOPROTOOPT .* +setsockopt\(0, SOL_IPV6, IPV6_LEAVE_ANYCAST, \{ipv6mr_multiaddr=inet_pton\("ff01::c"\), ipv6mr_interface=if_nametoindex\("lo"\)\}, 20\) = -1 ENOPROTOOPT .* diff --git a/tests/ip_mreq.test b/tests/ip_mreq.test new file mode 100755 index 00000000..d423b1ba --- /dev/null +++ b/tests/ip_mreq.test @@ -0,0 +1,11 @@ +#!/bin/sh + +# Check {IP,IPV6}_{ADD,DROP}_MEMBERSHIP setsockopt decoding. + +. "${srcdir=.}/init.sh" + +run_prog +run_strace -e setsockopt $args +match_grep + +exit 0