chiark / gitweb /
test-icmp6-nd: Add test cases for prefixes
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Tue, 20 Jan 2015 17:36:02 +0000 (19:36 +0200)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Tue, 27 Jan 2015 07:35:24 +0000 (09:35 +0200)
Add test cases that feeds an Router Advertisement to the ICMPv6 code
and verify that the correct prefix lengths are returned given an IPv6
address.

Enhance the prefix verification test by adding a shorter prefix and
check that the intended prefix lengths are now updated.

src/libsystemd-network/test-icmp6-rs.c

index 9d50c57..8ba2110 100644 (file)
@@ -34,6 +34,9 @@ static bool verbose = false;
 static sd_event_source *test_hangcheck;
 static int test_fd[2];
 
+typedef int (*send_ra_t)(uint8_t flags);
+static send_ra_t send_ra_function;
+
 static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
                              void *userdata) {
         assert_se(false);
@@ -50,6 +53,191 @@ int dhcp_network_icmp6_bind_router_solicitation(int index) {
         return test_fd[0];
 }
 
+static int send_ra_short_prefix(uint8_t flags) {
+        uint8_t advertisement[] = {
+                0x86, 0x00, 0xbe, 0xd7, 0x40, 0xc0, 0x00, 0xb4,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+                0x03, 0x04, 0x34, 0xc0, 0x00, 0x00, 0x01, 0xf4,
+                0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
+                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+        };
+
+        assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
+               sizeof(advertisement));
+
+        return 0;
+}
+
+static void test_short_prefix_cb(sd_icmp6_nd *nd, int event, void *userdata) {
+        sd_event *e = userdata;
+        struct {
+                struct in6_addr addr;
+                uint8_t prefixlen;
+                bool success;
+        } addrs[] = {
+                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+                  52, true },
+                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+                  64, false },
+                { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+                  60, true },
+                { { { { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x9d, 0xab, 0xcd,
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+                  64, true },
+                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xed,
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
+                  52, true },
+        };
+        uint8_t prefixlen;
+        unsigned int i;
+
+        for (i = 0; i < ELEMENTSOF(addrs); i++) {
+                printf("  %s prefix %02x%02x:%02x%02x:%02x%02x:%02x%02x",
+                        __FUNCTION__,
+                        addrs[i].addr.s6_addr[0], addrs[i].addr.s6_addr[1],
+                        addrs[i].addr.s6_addr[2], addrs[i].addr.s6_addr[3],
+                        addrs[i].addr.s6_addr[4], addrs[i].addr.s6_addr[5],
+                        addrs[i].addr.s6_addr[6], addrs[i].addr.s6_addr[7]);
+
+                if (addrs[i].success) {
+                        assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
+                                                                &prefixlen) >= 0);
+                        assert_se(addrs[i].prefixlen == prefixlen);
+                        printf("/%d onlink\n", prefixlen);
+                } else {
+                        assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
+                                                                &prefixlen) == -EADDRNOTAVAIL);
+                        printf("/128 offlink\n");
+                }
+        }
+
+        sd_event_exit(e, 0);
+}
+
+static int send_ra_prefixes(uint8_t flags) {
+        uint8_t advertisement[] = {
+                0x86, 0x00, 0xbe, 0xd7, 0x40, 0xc0, 0x00, 0xb4,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x03, 0x04, 0x3f, 0xc0, 0x00, 0x00, 0x01, 0xf4,
+                0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
+                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x03, 0x04, 0x40, 0x00, 0x00, 0x00, 0x02, 0x58,
+                0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x00,
+                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x03, 0x04, 0x3c, 0x80, 0x00, 0x00, 0x03, 0x84,
+                0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00,
+                0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x03, 0x84,
+                0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00,
+                0x20, 0x01, 0x0d, 0xb8, 0x00, 0x9d, 0xab, 0xcd,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+                0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+                0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
+                0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53
+        };
+
+        assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
+               sizeof(advertisement));
+
+        return 0;
+}
+
+static void test_prefixes_cb(sd_icmp6_nd *nd, int event, void *userdata) {
+        sd_event *e = userdata;
+        struct {
+                struct in6_addr addr;
+                uint8_t prefixlen;
+                bool success;
+        } addrs[] = {
+                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+                  63, true },
+                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+                  64, false },
+                { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+                  60, true },
+                { { { { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x9d, 0xab, 0xcd,
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+                  64, true },
+                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xed,
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
+                  63, false },
+        };
+        uint8_t prefixlen;
+        unsigned int i;
+
+        for (i = 0; i < ELEMENTSOF(addrs); i++) {
+                printf("  %s prefix %02x%02x:%02x%02x:%02x%02x:%02x%02x",
+                        __FUNCTION__,
+                        addrs[i].addr.s6_addr[0], addrs[i].addr.s6_addr[1],
+                        addrs[i].addr.s6_addr[2], addrs[i].addr.s6_addr[3],
+                        addrs[i].addr.s6_addr[4], addrs[i].addr.s6_addr[5],
+                        addrs[i].addr.s6_addr[6], addrs[i].addr.s6_addr[7]);
+
+                if (addrs[i].success) {
+                        assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
+                                                                &prefixlen) >= 0);
+                        assert_se(addrs[i].prefixlen == prefixlen);
+                        printf("/%d onlink\n", prefixlen);
+                } else {
+                        assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
+                                                                &prefixlen) == -EADDRNOTAVAIL);
+                        printf("/128 offlink\n");
+                }
+        }
+
+        send_ra_function = send_ra_short_prefix;
+        assert_se(sd_icmp6_nd_set_callback(nd, test_short_prefix_cb, e) >= 0);
+        assert_se(sd_icmp6_nd_stop(nd) >= 0);
+        assert_se(sd_icmp6_router_solicitation_start(nd) >= 0);
+}
+
+static void test_prefixes(void) {
+        sd_event *e;
+        sd_icmp6_nd *nd;
+
+        if (verbose)
+                printf("* %s\n", __FUNCTION__);
+
+        send_ra_function = send_ra_prefixes;
+
+        assert_se(sd_event_new(&e) >= 0);
+
+        assert_se(sd_icmp6_nd_new(&nd) >= 0);
+        assert_se(nd);
+
+        assert_se(sd_icmp6_nd_attach_event(nd, e, 0) >= 0);
+
+        assert_se(sd_icmp6_nd_set_index(nd, 42) >= 0);
+        assert_se(sd_icmp6_nd_set_mac(nd, &mac_addr) >= 0);
+        assert_se(sd_icmp6_nd_set_callback(nd, test_prefixes_cb, e) >= 0);
+
+        assert_se(sd_icmp6_router_solicitation_start(nd) >= 0);
+
+        sd_event_loop(e);
+
+        nd = sd_icmp6_nd_unref(nd);
+        assert_se(!nd);
+
+        close(test_fd[1]);
+
+        sd_event_unref(e);
+}
+
 static int send_ra(uint8_t flags) {
         uint8_t advertisement[] = {
                 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
@@ -79,7 +267,7 @@ static int send_ra(uint8_t flags) {
 }
 
 int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
-        return send_ra(0);
+        return send_ra_function(0);
 }
 
 static void test_rs_done(sd_icmp6_nd *nd, int event, void *userdata) {
@@ -113,13 +301,18 @@ static void test_rs_done(sd_icmp6_nd *nd, int event, void *userdata) {
         sd_event_exit(e, 0);
 }
 
-static void test_rs(sd_event *e) {
-        usec_t time_now = now(clock_boottime_or_monotonic());
+static void test_rs(void) {
+        sd_event *e;
         sd_icmp6_nd *nd;
+        usec_t time_now = now(clock_boottime_or_monotonic());
 
         if (verbose)
                 printf("* %s\n", __FUNCTION__);
 
+        send_ra_function = send_ra;
+
+        assert_se(sd_event_new(&e) >= 0);
+
         assert_se(sd_icmp6_nd_new(&nd) >= 0);
         assert_se(nd);
 
@@ -147,18 +340,18 @@ static void test_rs(sd_event *e) {
         assert_se(!nd);
 
         close(test_fd[1]);
+
+        sd_event_unref(e);
 }
 
 int main(int argc, char *argv[]) {
-        sd_event *e;
-
-        assert_se(sd_event_new(&e) >= 0);
 
         log_set_max_level(LOG_DEBUG);
         log_parse_environment();
         log_open();
 
-        test_rs(e);
+        test_rs();
+        test_prefixes();
 
         return 0;
 }