aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Zaborowski <andrew.zaborowski@intel.com>2022-10-04 00:28:44 +0200
committerDenis Kenzior <denkenz@gmail.com>2022-10-04 12:43:09 -0500
commitc2623e6598a328f57e809c3fd1cd232028f174e7 (patch)
tree775ba2e724e99fe2983bd9ec891ca206967beb89
parentfc7b878ecdb73e530b3ad71040ea89d471f6d6e2 (diff)
netconfig: Enable stateless DHCP mode
When using SLAAC, if the "Other" bit in Router Advertisements is set, start DHCP6 in stateless mode and use the DNS entries from the lease object created by l_dhcp6_client. If there is DNS information in the RA then emit the CONFIGURE event immediately after we've generated the addresses as before. If there's no DNS information, wait for the l_dhcp6_client LEASE_OBTAINED event before we emit CONFIGURE and set netconfig->v6_configured.
-rw-r--r--ell/netconfig.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/ell/netconfig.c b/ell/netconfig.c
index fe5bf40f..e54e2f9a 100644
--- a/ell/netconfig.c
+++ b/ell/netconfig.c
@@ -96,8 +96,9 @@ struct l_netconfig {
bool have_lla;
enum {
NETCONFIG_V6_METHOD_UNSET,
- NETCONFIG_V6_METHOD_DHCP,
- NETCONFIG_V6_METHOD_SLAAC,
+ NETCONFIG_V6_METHOD_DHCP, /* Managed bit set in RA */
+ NETCONFIG_V6_METHOD_SLAAC_DHCP, /* Other bit set in RA */
+ NETCONFIG_V6_METHOD_SLAAC, /* Neither flag set in RA */
} v6_auto_method;
struct l_queue *slaac_dnses;
struct l_queue *slaac_domains;
@@ -624,13 +625,17 @@ static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client,
if (L_WARN_ON(nc->v6_configured))
break;
- netconfig_add_dhcp6_address(nc);
- netconfig_set_dhcp6_address_lifetimes(nc, false);
+ if (nc->v6_auto_method == NETCONFIG_V6_METHOD_DHCP) {
+ netconfig_add_dhcp6_address(nc);
+ netconfig_set_dhcp6_address_lifetimes(nc, false);
+ }
+
nc->v6_configured = true;
netconfig_emit_event(nc, AF_INET6, L_NETCONFIG_EVENT_CONFIGURE);
break;
case L_DHCP6_CLIENT_EVENT_IP_CHANGED:
- if (L_WARN_ON(!nc->v6_configured))
+ if (L_WARN_ON(!nc->v6_configured ||
+ nc->v6_auto_method != NETCONFIG_V6_METHOD_DHCP))
break;
netconfig_remove_dhcp6_address(nc, false);
@@ -639,7 +644,8 @@ static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client,
netconfig_emit_event(nc, AF_INET6, L_NETCONFIG_EVENT_UPDATE);
break;
case L_DHCP6_CLIENT_EVENT_LEASE_EXPIRED:
- if (L_WARN_ON(!nc->v6_configured))
+ if (L_WARN_ON(!nc->v6_configured ||
+ nc->v6_auto_method != NETCONFIG_V6_METHOD_DHCP))
break;
netconfig_remove_dhcp6_address(nc, true);
@@ -658,13 +664,19 @@ static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client,
if (L_WARN_ON(!nc->v6_configured))
break;
- netconfig_set_dhcp6_address_lifetimes(nc, true);
+ if (nc->v6_auto_method == NETCONFIG_V6_METHOD_DHCP)
+ netconfig_set_dhcp6_address_lifetimes(nc, true);
+
netconfig_emit_event(nc, AF_INET6, L_NETCONFIG_EVENT_UPDATE);
break;
case L_DHCP6_CLIENT_EVENT_NO_LEASE:
if (L_WARN_ON(nc->v6_configured))
break;
+ if (nc->v6_auto_method == NETCONFIG_V6_METHOD_SLAAC_DHCP &&
+ !l_queue_isempty(nc->slaac_dnses))
+ break;
+
/*
* The requested address is no longer available, try to restart
* the client.
@@ -699,7 +711,9 @@ static bool netconfig_match_str(const void *a, const void *b)
static bool netconfig_check_start_dhcp6(struct l_netconfig *nc)
{
/* Don't start DHCPv6 until we get an RA with the managed bit set */
- if (nc->ra_timeout || nc->v6_auto_method != NETCONFIG_V6_METHOD_DHCP)
+ if (nc->ra_timeout || !L_IN_SET(nc->v6_auto_method,
+ NETCONFIG_V6_METHOD_DHCP,
+ NETCONFIG_V6_METHOD_SLAAC_DHCP))
return true;
/* Don't start DHCPv6 while waiting for the link-local address */
@@ -765,8 +779,13 @@ static void netconfig_add_slaac_address(struct l_netconfig *nc,
l_queue_push_tail(nc->addresses.current, nc->v6_address);
l_queue_push_tail(nc->addresses.added, nc->v6_address);
- nc->v6_configured = true;
- netconfig_emit_event(nc, AF_INET6, L_NETCONFIG_EVENT_CONFIGURE);
+
+ if (nc->v6_auto_method == NETCONFIG_V6_METHOD_SLAAC ||
+ nc->slaac_dnses) {
+ nc->v6_configured = true;
+ netconfig_emit_event(nc, AF_INET6, L_NETCONFIG_EVENT_CONFIGURE);
+ } else
+ netconfig_emit_event(nc, AF_INET6, L_NETCONFIG_EVENT_UPDATE);
/* TODO: set a renew timeout */
}
@@ -1202,6 +1221,7 @@ process_nondefault_routes:
if (nc->v6_auto_method == NETCONFIG_V6_METHOD_UNSET &&
l_icmp6_router_get_managed(r)) {
nc->v6_auto_method = NETCONFIG_V6_METHOD_DHCP;
+ l_dhcp6_client_set_stateless(nc->dhcp6_client, false);
if (!netconfig_check_start_dhcp6(nc)) {
netconfig_emit_event(nc, AF_INET6,
@@ -1213,12 +1233,17 @@ process_nondefault_routes:
}
/*
- * DHCP not available according to this router, check if any of the
- * prefixes allow SLAAC.
+ * Stateful DHCP not available according to this router, check if
+ * any of the prefixes allow SLAAC.
*/
if (nc->v6_auto_method == NETCONFIG_V6_METHOD_UNSET &&
r->n_ac_prefixes) {
- nc->v6_auto_method = NETCONFIG_V6_METHOD_SLAAC;
+ if (l_icmp6_router_get_other(r)) {
+ nc->v6_auto_method = NETCONFIG_V6_METHOD_SLAAC_DHCP;
+ l_dhcp6_client_set_stateless(nc->dhcp6_client, true);
+ netconfig_check_start_dhcp6(nc);
+ } else
+ nc->v6_auto_method = NETCONFIG_V6_METHOD_SLAAC;
/*
* Do this first so that any changes are included in the
@@ -2188,7 +2213,7 @@ LIB_EXPORT void l_netconfig_unconfigure(struct l_netconfig *netconfig)
L_NETCONFIG_EVENT_UNCONFIGURE);
}
- if (netconfig->v6_configured) {
+ if (netconfig->v6_address) {
netconfig_remove_dhcp6_address(netconfig, false);
netconfig->v6_configured = false;
}