[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