]> granicus.if.org Git - strace/commitdiff
net: decode setsockopt() multicast arguments
authorDmitry V. Levin <ldv@altlinux.org>
Mon, 8 Jun 2015 14:19:46 +0000 (14:19 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 8 Jun 2015 23:02:27 +0000 (23:02 +0000)
* 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 <info@bnoordhuis.nl>.

configure.ac
net.c
tests/.gitignore
tests/Makefile.am
tests/ip_mreq.c [new file with mode: 0644]
tests/ip_mreq.expected [new file with mode: 0644]
tests/ip_mreq.test [new file with mode: 0755]

index 060a1209394cb02db4828cd85031a045c017309a..bb8bf46f79b491fdf39831c211aae5c4c0b4839f 100644 (file)
@@ -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 fc325df013c4b77f5bb8d682f5e546fe7f2b28ba..ff7b456c6f89d0ea471abe29693035d3d1fd4f53 100644 (file)
--- 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
index 6903a5cef7959fca31529a9a351189e32c867642..c3eada90b8b72c6c03a172214e8967bd8c4995db 100644 (file)
@@ -3,6 +3,7 @@ fanotify_mark
 getrandom
 inet-accept-connect-send-recv
 ioctl
+ip_mreq
 ipc_msg
 ipc_sem
 ipc_shm
index 7ace705b422f5e4ddc373d789a5cdafcc0192397..f1e882050744c0327112a994fc6a7fe51b48292d 100644 (file)
@@ -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 (file)
index 0000000..db208b8
--- /dev/null
@@ -0,0 +1,45 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <assert.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+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 (file)
index 0000000..e694c73
--- /dev/null
@@ -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 (executable)
index 0000000..d423b1b
--- /dev/null
@@ -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