[systemd-devel] [PATCH 04/24] sd-dhcp6-client: Initialize Router Solicitation on startup

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


Try DHCPv6 if router solicitation times out as a link without routers
may use DHCPv6 according to RFC 4862 section 5.5.2.
---
 src/libsystemd-network/sd-dhcp6-client.c | 70 +++++++++++++++++++++++++++++++-
 src/systemd/sd-dhcp6-client.h            |  1 +
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 5063d4a..fbf3211 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -27,6 +27,8 @@
 
 #include "sd-dhcp6-client.h"
 #include "dhcp6-protocol.h"
+#include "dhcp6-internal.h"
+#include "icmp6-nd.h"
 
 struct sd_dhcp6_client {
         RefCount n_ref;
@@ -36,6 +38,7 @@ struct sd_dhcp6_client {
         int event_priority;
         int index;
         struct ether_addr mac_addr;
+        icmp6_nd *ra;
         sd_dhcp6_client_cb_t cb;
         void *userdata;
 };
@@ -103,6 +106,30 @@ static sd_dhcp6_client *client_stop(sd_dhcp6_client *client, int error) {
         return client;
 }
 
+static void dhcp6_receive_router_advertisment(icmp6_nd *nd, int event,
+                                              void *userdata)
+{
+        sd_dhcp6_client *client = userdata;
+
+        if (event < 0) {
+                log_dhcp6_client(client, "Router Advertisment failed with "
+                                 "%d %s", event, strerror(-event));
+                client_notify(client, event);
+                return;
+        }
+
+        switch (event) {
+        case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
+        case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
+                client_stop(client, DHCP6_EVENT_NO_STATEFUL_CONFIGURATION);
+                return;
+
+        case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
+        case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
+                break;
+        }
+}
+
 int sd_dhcp6_client_stop(sd_dhcp6_client *client)
 {
         client_stop(client, DHCP6_EVENT_STOP);
@@ -112,13 +139,50 @@ int sd_dhcp6_client_stop(sd_dhcp6_client *client)
 
 int sd_dhcp6_client_start(sd_dhcp6_client *client)
 {
-        int r = 0;
+        _cleanup_icmp6_nd_free_ icmp6_nd *nd = NULL;
+        int r;
+        struct ether_addr *mac_addr = NULL;
+        struct ether_addr unset = { };
 
         assert_return(client, -EINVAL);
         assert_return(client->event, -EINVAL);
         assert_return(client->index > 0, -EINVAL);
 
-        return r;
+        r = icmp6_nd_new(&nd);
+        if (r < 0)
+                return r;
+
+        r = icmp6_nd_attach_event(nd, client->event, client->event_priority);
+        if (r < 0)
+                return r;
+
+        r = icmp6_nd_set_index(nd, client->index);
+        if (r < 0)
+                return r;
+
+        if (memcmp(&client->mac_addr, &unset, sizeof(unset)))
+                mac_addr = &client->mac_addr;
+
+        r = icmp6_nd_set_mac(nd, mac_addr);
+        if (r < 0)
+                return r;
+
+        r = icmp6_nd_set_callback(nd, dhcp6_receive_router_advertisment,
+                                  client);
+        if (r < 0)
+                return r;
+
+        r = icmp6_router_solicitation_start(nd);
+        if (r < 0)
+                return r;
+
+        client->ra = icmp6_nd_unref(client->ra);
+        client->ra = nd;
+        nd = NULL;
+
+        client->state = DHCP6_STATE_RS;
+
+        return 0;
 }
 
 int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event,
@@ -171,6 +235,8 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
 
                 sd_dhcp6_client_detach_event(client);
 
+                client->ra = icmp6_nd_unref(client->ra);
+
                 free(client);
 
                 return NULL;
diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
index 4965011..c64ad16 100644
--- a/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/sd-dhcp6-client.h
@@ -28,6 +28,7 @@
 
 enum {
         DHCP6_EVENT_STOP                        = 0,
+        DHCP6_EVENT_NO_STATEFUL_CONFIGURATION   = 10,
 };
 
 typedef struct sd_dhcp6_client sd_dhcp6_client;
-- 
1.9.1



More information about the systemd-devel mailing list