summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/network/networkd-link.c158
-rw-r--r--src/network/networkd-network-gperf.gperf1
-rw-r--r--src/network/networkd.h6
3 files changed, 165 insertions, 0 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 5b2dabc0d0..5ab7aa7d19 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -125,6 +125,8 @@ static void link_free(Link *link) {
sd_ipv4ll_unref(link->ipv4ll);
+ sd_dhcp6_client_unref(link->dhcp6_client);
+
hashmap_remove(link->manager->links, &link->ifindex);
free(link->ifname);
@@ -233,6 +235,16 @@ static int link_stop_clients(Link *link) {
}
}
+ if (link->network->dhcp6) {
+ assert(link->dhcp6_client);
+
+ k = sd_dhcp6_client_stop(link->dhcp6_client);
+ if (k < 0) {
+ log_warning_link(link, "Could not stop DHCPv6 client: %s", strerror(-r));
+ r = k;
+ }
+ }
+
return r;
}
@@ -1277,6 +1289,104 @@ static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
}
}
+static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
+ Link *link = userdata;
+
+ assert(link);
+ assert(link->network);
+ assert(link->manager);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return;
+
+ switch(event) {
+ case DHCP6_EVENT_STOP:
+ case DHCP6_EVENT_RESEND_EXPIRE:
+ case DHCP6_EVENT_RETRANS_MAX:
+ case DHCP6_EVENT_IP_ACQUIRE:
+ log_debug_link(link, "DHCPv6 event %d", event);
+
+ break;
+
+ default:
+ if (event < 0)
+ log_warning_link(link, "DHCPv6 error: %s",
+ strerror(-event));
+ else
+ log_warning_link(link, "DHCPv6 unknown event: %d",
+ event);
+ return;
+ }
+}
+
+static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
+ Link *link = userdata;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(link->manager);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return;
+
+ switch(event) {
+ case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
+ case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
+ return;
+
+ case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
+ case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
+ break;
+
+ default:
+ if (event < 0)
+ log_warning_link(link, "ICMPv6 error: %s",
+ strerror(-event));
+ else
+ log_warning_link(link, "ICMPv6 unknown event: %d",
+ event);
+
+ return;
+ }
+
+ if (link->dhcp6_client)
+ return;
+
+ r = sd_dhcp6_client_new(&link->dhcp6_client);
+ if (r < 0)
+ return;
+
+ r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0);
+ if (r < 0) {
+ link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+ return;
+ }
+
+ r = sd_dhcp6_client_set_mac(link->dhcp6_client, &link->mac);
+ if (r < 0) {
+ link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+ return;
+ }
+
+ r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex);
+ if (r < 0) {
+ link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+ return;
+ }
+
+ r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler,
+ link);
+ if (r < 0) {
+ link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+ return;
+ }
+
+ r = sd_dhcp6_client_start(link->dhcp6_client);
+ if (r < 0)
+ link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+}
+
static int link_acquire_conf(Link *link) {
int r;
@@ -1311,6 +1421,18 @@ static int link_acquire_conf(Link *link) {
}
}
+ if (link->network->dhcp6) {
+ assert(link->icmp6_router_discovery);
+
+ log_debug_link(link, "discovering IPv6 routers");
+
+ r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery);
+ if (r < 0) {
+ log_warning_link(link, "could not start IPv6 router discovery");
+ return r;
+ }
+ }
+
return 0;
}
@@ -1793,6 +1915,32 @@ static int link_configure(Link *link) {
return r;
}
+ if (link->network->dhcp6) {
+ r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
+ if (r < 0)
+ return r;
+
+ r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery,
+ NULL, 0);
+ if (r < 0)
+ return r;
+
+ r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery,
+ &link->mac);
+ if (r < 0)
+ return r;
+
+ r = sd_icmp6_nd_set_index(link->icmp6_router_discovery,
+ link->ifindex);
+ if (r < 0)
+ return r;
+
+ r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery,
+ icmp6_router_handler, link);
+ if (r < 0)
+ return r;
+ }
+
if (link_has_carrier(link->flags, link->kernel_operstate)) {
r = link_acquire_conf(link);
if (r < 0)
@@ -2134,6 +2282,16 @@ int link_update(Link *link, sd_rtnl_message *m) {
return r;
}
}
+
+ if (link->dhcp6_client) {
+ r = sd_dhcp6_client_set_mac(link->dhcp6_client,
+ &link->mac);
+ if (r < 0) {
+ log_warning_link(link, "Could not update MAC address in DHCPv6 client: %s",
+ strerror(-r));
+ return r;
+ }
+ }
}
}
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 5e21805eea..469e028687 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -33,6 +33,7 @@ Network.VXLAN, config_parse_netdev, 0,
Network.DHCP, config_parse_bool, 0, offsetof(Network, dhcp)
Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server)
Network.IPv4LL, config_parse_bool, 0, offsetof(Network, ipv4ll)
+Network.DHCPv6, config_parse_bool, 0, offsetof(Network, dhcp6)
Network.Address, config_parse_address, 0, 0
Network.Gateway, config_parse_gateway, 0, 0
Network.DNS, config_parse_dns, 0, offsetof(Network, dns)
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 7069a11d4c..b7b1d903b2 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -29,6 +29,8 @@
#include "sd-dhcp-client.h"
#include "sd-dhcp-server.h"
#include "sd-ipv4ll.h"
+#include "sd-icmp6-nd.h"
+#include "sd-dhcp6-client.h"
#include "udev.h"
#include "rtnl-util.h"
@@ -159,6 +161,7 @@ struct Network {
bool dhcp_domainname;
bool dhcp_critical;
bool ipv4ll;
+ bool dhcp6;
bool dhcp_server;
@@ -263,6 +266,9 @@ struct Link {
LIST_HEAD(Address, pool_addresses);
sd_dhcp_server *dhcp_server;
+
+ sd_icmp6_nd *icmp6_router_discovery;
+ sd_dhcp6_client *dhcp6_client;
};
struct AddressPool {