[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