[systemd-devel] [PATCH 13/24] sd-dhcp6-client: Add RA and DHCPv6 Solicit test case

Patrik Flykt patrik.flykt at linux.intel.com
Fri Jun 13 06:45:03 PDT 2014


Copy Router Advertisement functions and data from the previous
test case and verify the created Solicit message. The test will
take some non-trivial time to run due to the DHCPv6 initial delay.
---
 Makefile.am                                |   1 +
 src/libsystemd-network/test-dhcp6-client.c | 181 +++++++++++++++++++++++++++++
 2 files changed, 182 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index f6340dc..87ac728 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2580,6 +2580,7 @@ test_dhcp6_rs_LDADD = \
 
 test_dhcp6_client_SOURCES = \
 	src/systemd/sd-dhcp6-client.h \
+	src/libsystemd-network/dhcp6-icmp6.h \
 	src/libsystemd-network/dhcp6-internal.h \
 	src/libsystemd-network/test-dhcp6-client.c
 
diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c
index b52f407..e8cc07d 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -21,7 +21,12 @@
 
 #include <stdbool.h>
 #include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <netinet/icmp6.h>
 
+#include "socket-util.h"
 #include "macro.h"
 #include "sd-event.h"
 #include "event-util.h"
@@ -36,6 +41,12 @@ static struct ether_addr mac_addr = {
 
 static bool verbose = false;
 
+static sd_event_source *hangcheck;
+static int test_rs_fd[2];
+static int test_dhcp_fd[2];
+static int test_index = 42;
+static sd_event *e_solicit;
+
 static int test_client_basic(sd_event *e) {
         sd_dhcp6_client *client;
 
@@ -128,6 +139,175 @@ static int test_option(sd_event *e) {
         return 0;
 }
 
+static int test_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) {
+        assert_not_reached("Test case should have completed in 2 seconds");
+
+        return 0;
+}
+
+int dhcp_network_icmp6_bind_router_solicitation(int index) {
+        assert(index == 42);
+
+        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, test_rs_fd) < 0)
+                return -errno;
+
+        return test_rs_fd[0];
+}
+
+static int send_ra(uint8_t flags) {
+        uint8_t advertisement[] = {
+                0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x03, 0x04, 0x40, 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,
+                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,
+        };
+
+        advertisement[5] = flags;
+
+        assert(write(test_rs_fd[1], advertisement, sizeof(advertisement)) ==
+               sizeof(advertisement));
+
+        if (verbose)
+                printf("  sent RA with flag 0x%02x\n", flags);
+
+        return 0;
+}
+
+int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
+        return send_ra(ND_RA_FLAG_MANAGED);
+}
+
+int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
+        assert_se(index == test_index);
+
+        if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_dhcp_fd) < 0)
+                return -errno;
+
+        return test_dhcp_fd[0];
+}
+
+static int verify_solicit(DHCP6Message *solicit, uint8_t *option, size_t len) {
+        uint8_t *optval;
+        uint16_t optcode;
+        size_t optlen;
+        bool found_clientid = false, found_iana = false;
+        int r;
+
+        assert_se(solicit->type == DHCP6_SOLICIT);
+
+        while ((r = dhcp6_option_parse(&option, &len,
+                                       &optcode, &optlen, &optval)) >= 0) {
+                switch(optcode) {
+                case DHCP6_OPTION_CLIENTID:
+                        assert_se(!found_clientid);
+                        found_clientid = true;
+
+                        assert_se(optlen == 14);
+
+                        break;
+
+                case DHCP6_OPTION_IA_NA:
+                        assert_se(!found_iana);
+                        found_iana = true;
+
+                        assert_se(optlen == 12);
+
+                        break;
+                }
+        }
+
+        assert_se(r == -ENOMSG);
+        assert_se(found_clientid && found_iana);
+
+        sd_event_exit(e_solicit, 0);
+
+        return 0;
+}
+
+int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
+                                  const void *packet, size_t len) {
+        struct in6_addr mcast =
+                IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
+        DHCP6Message *message;
+        uint8_t *option;
+
+        assert_se(s == test_dhcp_fd[0]);
+        assert_se(server_address);
+        assert_se(packet);
+        assert_se(len > sizeof(DHCP6Message) + 4);
+
+        assert_se(IN6_ARE_ADDR_EQUAL(server_address, &mcast));
+
+        message = (DHCP6Message *)packet;
+        option = (uint8_t *)(message + 1);
+        len -= sizeof(DHCP6Message);
+
+        assert_se(message->transaction_id & 0x00ffffff);
+
+        verify_solicit(message, option, len);
+
+        return len;
+}
+
+static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
+                                   void *userdata) {
+        sd_event *e = userdata;
+
+        assert_se(e);
+
+        if (verbose)
+                printf("  got DHCPv6 event %d\n", event);
+
+        sd_event_exit(e, 0);
+}
+
+static int test_client_solicit(sd_event *e) {
+        sd_dhcp6_client *client;
+        usec_t time_now = now(CLOCK_MONOTONIC);
+
+        if (verbose)
+                printf("* %s\n", __FUNCTION__);
+
+        assert_se(sd_dhcp6_client_new(&client) >= 0);
+        assert_se(client);
+
+        assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
+
+        assert_se(sd_dhcp6_client_set_index(client, test_index) == 0);
+        assert_se(sd_dhcp6_client_set_mac(client, &mac_addr) >= 0);
+
+        assert_se(sd_dhcp6_client_set_callback(client,
+                                               test_client_solicit_cb, e) >= 0);
+
+        assert_se(sd_event_add_time(e, &hangcheck, CLOCK_MONOTONIC,
+                                    time_now + 2 * USEC_PER_SEC, 0,
+                                    test_hangcheck, NULL) >= 0);
+
+        e_solicit = e;
+
+        assert_se(sd_dhcp6_client_start(client) >= 0);
+
+        sd_event_loop(e);
+
+        hangcheck = sd_event_source_unref(hangcheck);
+
+        assert_se(!sd_dhcp6_client_unref(client));
+
+        test_rs_fd[1] = safe_close(test_rs_fd[1]);
+        test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]);
+
+        return 0;
+}
+
 int main(int argc, char *argv[]) {
         _cleanup_event_unref_ sd_event *e;
 
@@ -139,6 +319,7 @@ int main(int argc, char *argv[]) {
 
         test_client_basic(e);
         test_option(e);
+        test_client_solicit(e);
 
         assert_se(!sd_event_unref(e));
 
-- 
1.9.1



More information about the systemd-devel mailing list