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 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel