ell.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/6] net: Allow padding in net_domain_list_parse
@ 2022-09-20 13:31 Andrew Zaborowski
  2022-09-20 13:31 ` [PATCH 2/6] unit: Update net_domain_list_parse test Andrew Zaborowski
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Andrew Zaborowski @ 2022-09-20 13:31 UTC (permalink / raw)
  To: ell

The domain name lists in ICMPv6 options may be 0-padded meaning that a
0-byte at the beginning of a domain record (ie. a domain with no labels)
is allowed and should be treated as the end of the list.  Add a boolean
parameter to tell net_domain_list_parse() whether to allow this.

Fixes: 4b1ce9b3e3d0 ("icmp6: Parse RDNSS and DNSSL options")
---
 ell/dhcp6-lease.c | 2 +-
 ell/icmp6.c       | 6 +++---
 ell/net-private.h | 2 +-
 ell/net.c         | 8 +++++++-
 4 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/ell/dhcp6-lease.c b/ell/dhcp6-lease.c
index 978176a..a92cff9 100644
--- a/ell/dhcp6-lease.c
+++ b/ell/dhcp6-lease.c
@@ -312,7 +312,7 @@ struct l_dhcp6_lease *_dhcp6_lease_parse_options(
 			lease->rapid_commit = true;
 			break;
 		case L_DHCP6_OPTION_DOMAIN_LIST:
-			lease->domain_list = net_domain_list_parse(v, l);
+			lease->domain_list = net_domain_list_parse(v, l, false);
 			if (!lease->domain_list)
 				goto error;
 
diff --git a/ell/icmp6.c b/ell/icmp6.c
index a2765ea..5ddc494 100644
--- a/ell/icmp6.c
+++ b/ell/icmp6.c
@@ -1104,11 +1104,11 @@ struct l_icmp6_router *_icmp6_router_parse(const struct nd_router_advert *ra,
 		{
 			struct domain_info *info = &r->domains[n_domains];
 			_auto_(l_free) char **domain_list =
-				net_domain_list_parse(opts + 8, l - 8);
+				net_domain_list_parse(opts + 8, l - 8, true);
 			char **i;
 
-			/* Ignore invalid option */
-			if (!domain_list)
+			/* Ignore malformed option */
+			if (!domain_list || !domain_list[0])
 				break;
 
 			for (i = domain_list; *i; i++) {
diff --git a/ell/net-private.h b/ell/net-private.h
index 39d4d98..a864034 100644
--- a/ell/net-private.h
+++ b/ell/net-private.h
@@ -21,7 +21,7 @@
  */
 
 char *net_domain_name_parse(const uint8_t *raw, size_t raw_len);
-char **net_domain_list_parse(const uint8_t *raw, size_t raw_len);
+char **net_domain_list_parse(const uint8_t *raw, size_t raw_len, bool padded);
 
 static inline const void *net_prefix_from_ipv6(const uint8_t *address,
 						uint8_t prefix_len)
diff --git a/ell/net.c b/ell/net.c
index 378b9f2..aa7fc20 100644
--- a/ell/net.c
+++ b/ell/net.c
@@ -295,7 +295,7 @@ char *net_domain_name_parse(const uint8_t *raw, size_t raw_len)
 /*
  * Parse list of domain names encoded according to RFC 1035 Section 3.1
  */
-char **net_domain_list_parse(const uint8_t *raw, size_t raw_len)
+char **net_domain_list_parse(const uint8_t *raw, size_t raw_len, bool padded)
 {
 	size_t remaining = raw_len;
 	const uint8_t *p = raw;
@@ -305,6 +305,9 @@ char **net_domain_list_parse(const uint8_t *raw, size_t raw_len)
 	struct l_string *growable = NULL;
 
 	while (remaining) {
+		if (padded && p[0] == 0)
+			break;
+
 		r = validate_next_domain_name(p, remaining);
 		if (r < 0)
 			return NULL;
@@ -323,6 +326,9 @@ char **net_domain_list_parse(const uint8_t *raw, size_t raw_len)
 		remaining -= *p + 1;
 
 		if (*p == 0) {
+			if (!growable)
+				break;
+
 			p += 1;
 			ret[nitems++] = l_string_unwrap(growable);
 			growable = NULL;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/6] unit: Update net_domain_list_parse test
  2022-09-20 13:31 [PATCH 1/6] net: Allow padding in net_domain_list_parse Andrew Zaborowski
@ 2022-09-20 13:31 ` Andrew Zaborowski
  2022-09-20 13:31 ` [PATCH 3/6] netconfig: Set .v6_configured when we set an address Andrew Zaborowski
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Andrew Zaborowski @ 2022-09-20 13:31 UTC (permalink / raw)
  To: ell

---
 unit/test-net.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/unit/test-net.c b/unit/test-net.c
index ff5d2b0..f3f1522 100644
--- a/unit/test-net.c
+++ b/unit/test-net.c
@@ -113,11 +113,13 @@ static void test_net_domain_list_parse(const void *data)
 	static const uint8_t l1[] = { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
 					3, 'c', 'o', 'm', 0,
 					4, 't', 'e', 's', 't', 0 };
-	static const uint8_t l2[] = { 0, 0};
+	static const uint8_t l2[] = { 0, 0 };
 	static const uint8_t l3[] = { 4, '.', '=', '2', '3', 0 };
+	static const uint8_t l4[] = { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
+					3, 'c', 'o', 'm', 0, 0 };
 	char **domains;
 
-	domains = net_domain_list_parse(l1, sizeof(l1));
+	domains = net_domain_list_parse(l1, sizeof(l1), false);
 	assert(domains);
 	assert(domains[0]);
 	assert(!strcmp(domains[0], "example.com"));
@@ -126,14 +128,21 @@ static void test_net_domain_list_parse(const void *data)
 	assert(!domains[2]);
 	l_strfreev(domains);
 
-	assert(!net_domain_list_parse(l2, sizeof(l2)));
+	assert(!net_domain_list_parse(l2, sizeof(l2), false));
 
-	domains = net_domain_list_parse(l3, sizeof(l3));
+	domains = net_domain_list_parse(l3, sizeof(l3), false);
 	assert(domains);
 	assert(domains[0]);
 	assert(!strcmp(domains[0], "\\.\\06123"));
 	assert(!domains[1]);
 	l_strfreev(domains);
+
+	domains = net_domain_list_parse(l4, sizeof(l4), true);
+	assert(domains);
+	assert(domains[0]);
+	assert(!strcmp(domains[0], "example.com"));
+	assert(!domains[1]);
+	l_strfreev(domains);
 }
 
 int main(int argc, char *argv[])
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/6] netconfig: Set .v6_configured when we set an address
  2022-09-20 13:31 [PATCH 1/6] net: Allow padding in net_domain_list_parse Andrew Zaborowski
  2022-09-20 13:31 ` [PATCH 2/6] unit: Update net_domain_list_parse test Andrew Zaborowski
@ 2022-09-20 13:31 ` Andrew Zaborowski
  2022-09-20 13:31 ` [PATCH 4/6] netconfig: Handle DNS data from l_icmp6_router Andrew Zaborowski
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Andrew Zaborowski @ 2022-09-20 13:31 UTC (permalink / raw)
  To: ell

The DNS getters won't work without this as they return NULL if
.v6_configured is false.

Fixes: 6adf0f5db455 ("netconfig: Create SLAAC address")
---
 ell/netconfig.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ell/netconfig.c b/ell/netconfig.c
index 7a9ee89..e5c7b51 100644
--- a/ell/netconfig.c
+++ b/ell/netconfig.c
@@ -750,6 +750,7 @@ 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);
 
 	/* TODO: set a renew timeout */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/6] netconfig: Handle DNS data from l_icmp6_router
  2022-09-20 13:31 [PATCH 1/6] net: Allow padding in net_domain_list_parse Andrew Zaborowski
  2022-09-20 13:31 ` [PATCH 2/6] unit: Update net_domain_list_parse test Andrew Zaborowski
  2022-09-20 13:31 ` [PATCH 3/6] netconfig: Set .v6_configured when we set an address Andrew Zaborowski
@ 2022-09-20 13:31 ` Andrew Zaborowski
  2022-09-20 13:32 ` [PATCH 5/6] icmp6,netconfig: Skip SLLAO if RS sent from optimistic address Andrew Zaborowski
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Andrew Zaborowski @ 2022-09-20 13:31 UTC (permalink / raw)
  To: ell

Track the lists of DNSes and search domains based on Router Advertisement
options parsed by l_icmp6_client.  Return them in
l_netconfig_get_dns_list, l_netconfig_get_domain_names.
---
 ell/netconfig.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 154 insertions(+), 6 deletions(-)

diff --git a/ell/netconfig.c b/ell/netconfig.c
index e5c7b51..765703b 100644
--- a/ell/netconfig.c
+++ b/ell/netconfig.c
@@ -98,6 +98,8 @@ struct l_netconfig {
 		NETCONFIG_V6_METHOD_DHCP,
 		NETCONFIG_V6_METHOD_SLAAC,
 	} v6_auto_method;
+	struct l_queue *slaac_dnses;
+	struct l_queue *slaac_domains;
 
 	/* These objects, if not NULL, are owned by @addresses and @routes */
 	struct l_rtnl_address *v4_address;
@@ -151,6 +153,8 @@ static struct l_queue *addr_wait_list;
 static unsigned int rtnl_id;
 
 static const unsigned int max_icmp6_routes = 100;
+static const unsigned int max_icmp6_dnses = 10;
+static const unsigned int max_icmp6_domains = 10;
 
 static void netconfig_update_cleanup(struct l_netconfig *nc)
 {
@@ -681,6 +685,16 @@ static bool netconfig_match(const void *a, const void *b)
 	return a == b;
 }
 
+static bool netconfig_match_addr(const void *a, const void *b)
+{
+	return memcmp(a, b, 16) == 0;
+}
+
+static bool netconfig_match_str(const void *a, const void *b)
+{
+	return strcmp(a, b) == 0;
+}
+
 static bool netconfig_check_start_dhcp6(struct l_netconfig *nc)
 {
 	/* Don't start DHCPv6 until we get an RA with the managed bit set */
@@ -809,6 +823,88 @@ static void netconfig_set_slaac_address_lifetimes(struct l_netconfig *nc,
 		l_queue_push_tail(nc->addresses.updated, nc->v6_address);
 }
 
+static bool netconfig_process_slaac_dns_info(struct l_netconfig *nc,
+						const struct l_icmp6_router *r)
+{
+	bool updated = false;
+	unsigned int i;
+	unsigned int n_dns = l_queue_length(nc->slaac_dnses);
+	unsigned int n_domains = l_queue_length(nc->slaac_domains);
+
+	for (i = 0; i < r->n_dns; i++) {
+		const struct dns_info *info = &r->dns_list[i];
+
+		/*
+		 * For simplicity don't track lifetimes (TODO), add entries
+		 * when the lifetime is non-zero, remove them when the
+		 * lifetime is zero.  We have no API to add time-limited
+		 * entries to the system either.
+		 *
+		 * RFC8106 Section 5.1: "A value of zero means that the RDNSS
+		 * addresses MUST no longer be used."
+		 */
+		if (info->lifetime) {
+			if (n_dns >= max_icmp6_dnses)
+				continue;
+
+			if (l_queue_find(nc->slaac_dnses, netconfig_match_addr,
+						info->address))
+				continue;
+
+			l_queue_push_tail(nc->slaac_dnses,
+						l_memdup(info->address, 16));
+			n_dns++;
+		} else {
+			void *addr = l_queue_remove_if(nc->slaac_dnses,
+							netconfig_match_addr,
+							info->address);
+
+			if (!addr)
+				continue;
+
+			l_free(addr);
+			n_dns--;
+		}
+
+		updated = true;
+	}
+
+	for (i = 0; i < r->n_domains; i++) {
+		const struct domain_info *info = &r->domains[i];
+
+		/*
+		 * RFC8106 Section 5.2: "A value of zero means that the DNSSL
+		 * domain names MUST no longer be used."
+		 */
+		if (info->lifetime) {
+			if (n_domains >= max_icmp6_domains)
+				continue;
+
+			if (l_queue_find(nc->slaac_domains, netconfig_match_str,
+						info->domain))
+				continue;
+
+			l_queue_push_tail(nc->slaac_domains,
+						l_strdup(info->domain));
+			n_domains++;
+		} else {
+			void *str = l_queue_remove_if(nc->slaac_domains,
+							netconfig_match_str,
+							info->domain);
+
+			if (!str)
+				continue;
+
+			l_free(str);
+			n_domains--;
+		}
+
+		updated = true;
+	}
+
+	return updated;
+}
+
 static uint64_t now;
 
 static bool netconfig_check_route_expired(void *data, void *user_data)
@@ -1027,6 +1123,7 @@ static void netconfig_icmp6_event_handler(struct l_icmp6_client *client,
 	const struct l_icmp6_router *r;
 	struct netconfig_route_data *default_rd;
 	unsigned int i;
+	bool dns_updated = false;
 
 	if (event != L_ICMP6_CLIENT_EVENT_ROUTER_FOUND)
 		return;
@@ -1122,6 +1219,14 @@ process_nondefault_routes:
 			r->n_ac_prefixes) {
 		nc->v6_auto_method = NETCONFIG_V6_METHOD_SLAAC;
 
+		/*
+		 * Do this first so that any changes are included in the
+		 * CONFIGURE event emitted next.
+		 */
+		nc->slaac_dnses = l_queue_new();
+		nc->slaac_domains = l_queue_new();
+		netconfig_process_slaac_dns_info(nc, r);
+
 		/*
 		 * The DAD for the link-local address may be still running
 		 * but again we can generate the global address already and
@@ -1156,6 +1261,7 @@ process_nondefault_routes:
 	 * and allows us to extend its lifetime.
 	 */
 	netconfig_set_slaac_address_lifetimes(nc, r);
+	dns_updated = netconfig_process_slaac_dns_info(nc, r);
 
 emit_event:
 	/*
@@ -1168,7 +1274,8 @@ emit_event:
 			!l_queue_isempty(nc->routes.updated) ||
 			!l_queue_isempty(nc->routes.removed) ||
 			!l_queue_isempty(nc->routes.expired) ||
-			!l_queue_isempty(nc->addresses.updated))
+			!l_queue_isempty(nc->addresses.updated) ||
+			dns_updated)
 		netconfig_emit_event(nc, AF_INET6, L_NETCONFIG_EVENT_UPDATE);
 }
 
@@ -2007,6 +2114,8 @@ LIB_EXPORT void l_netconfig_stop(struct l_netconfig *netconfig)
 	l_queue_clear(netconfig->routes.current,
 			(l_queue_destroy_func_t) l_rtnl_route_free);
 	l_queue_clear(netconfig->icmp_route_data, l_free);
+	l_queue_clear(netconfig->slaac_dnses, l_free);
+	l_queue_clear(netconfig->slaac_domains, l_free);
 	netconfig->v4_address = NULL;
 	netconfig->v4_subnet_route = NULL;
 	netconfig->v4_default_route = NULL;
@@ -2255,9 +2364,31 @@ append_v6:
 
 	if (netconfig->v6_dns_override)
 		netconfig_strv_cat(&ret, netconfig->v6_dns_override, false);
-	else if ((v6_lease =
-			l_dhcp6_client_get_lease(netconfig->dhcp6_client)))
+	else if (netconfig->v6_auto_method == NETCONFIG_V6_METHOD_DHCP &&
+			(v6_lease = l_dhcp6_client_get_lease(
+						netconfig->dhcp6_client)))
 		netconfig_strv_cat(&ret, l_dhcp6_lease_get_dns(v6_lease), true);
+	else if (netconfig->v6_auto_method == NETCONFIG_V6_METHOD_SLAAC &&
+			!l_queue_isempty(netconfig->slaac_dnses)) {
+		unsigned int dest_len = l_strv_length(ret);
+		unsigned int src_len = l_queue_length(netconfig->slaac_dnses);
+		char **i;
+		const struct l_queue_entry *entry;
+
+		ret = l_realloc(ret, sizeof(char *) * (dest_len + src_len + 1));
+		i = ret + dest_len;
+
+		for (entry = l_queue_get_entries(netconfig->slaac_dnses);
+				entry; entry = entry->next) {
+			char addr_str[INET6_ADDRSTRLEN];
+
+			if (inet_ntop(AF_INET6, entry->data, addr_str,
+					sizeof(addr_str)))
+				*i++ = l_strdup(addr_str);
+		}
+
+		*i = NULL;
+	}
 
 done:
 	return ret;
@@ -2288,13 +2419,30 @@ append_v6:
 	if (!netconfig->v6_configured)
 		goto done;
 
-	if (netconfig->v6_dns_override)
+	if (netconfig->v6_domain_names_override)
 		netconfig_strv_cat(&ret, netconfig->v6_domain_names_override,
 					false);
-	else if ((v6_lease =
-			l_dhcp6_client_get_lease(netconfig->dhcp6_client)))
+	else if (netconfig->v6_auto_method == NETCONFIG_V6_METHOD_DHCP &&
+			(v6_lease = l_dhcp6_client_get_lease(
+						netconfig->dhcp6_client)))
 		netconfig_strv_cat(&ret, l_dhcp6_lease_get_domains(v6_lease),
 					true);
+	else if (netconfig->v6_auto_method == NETCONFIG_V6_METHOD_SLAAC &&
+			!l_queue_isempty(netconfig->slaac_domains)) {
+		unsigned int dest_len = l_strv_length(ret);
+		unsigned int src_len = l_queue_length(netconfig->slaac_domains);
+		char **i;
+		const struct l_queue_entry *entry;
+
+		ret = l_realloc(ret, sizeof(char *) * (dest_len + src_len + 1));
+		i = ret + dest_len;
+
+		for (entry = l_queue_get_entries(netconfig->slaac_domains);
+				entry; entry = entry->next)
+			*i++ = l_strdup(entry->data);
+
+		*i = NULL;
+	}
 
 done:
 	return ret;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/6] icmp6,netconfig: Skip SLLAO if RS sent from optimistic address
  2022-09-20 13:31 [PATCH 1/6] net: Allow padding in net_domain_list_parse Andrew Zaborowski
                   ` (2 preceding siblings ...)
  2022-09-20 13:31 ` [PATCH 4/6] netconfig: Handle DNS data from l_icmp6_router Andrew Zaborowski
@ 2022-09-20 13:32 ` Andrew Zaborowski
  2022-09-20 13:32 ` [PATCH 6/6] netconfig: Handle missing optimistic_dad /proc file Andrew Zaborowski
  2022-09-20 15:06 ` [PATCH 1/6] net: Allow padding in net_domain_list_parse Denis Kenzior
  5 siblings, 0 replies; 7+ messages in thread
From: Andrew Zaborowski @ 2022-09-20 13:32 UTC (permalink / raw)
  To: ell

Make sure we don't include de Source Link-Local Address Option in our
Router Solicitations until the source link-local address completes DAD.
Extand the recently added l_icmp6_client_set_link_local_address() with a
parameter to tell us whether the address is optimistic.  Don't change
the l_dhcp6_client_set_link_local_address signature to avoid breaking
existing users.
---
 ell/dhcp6.c     |  2 +-
 ell/icmp6.c     | 29 +++++++++++++++++++++--------
 ell/icmp6.h     |  3 ++-
 ell/netconfig.c | 30 ++++++++++++++++++++++++++----
 4 files changed, 50 insertions(+), 14 deletions(-)

diff --git a/ell/dhcp6.c b/ell/dhcp6.c
index e234eb0..2792ff2 100644
--- a/ell/dhcp6.c
+++ b/ell/dhcp6.c
@@ -1623,7 +1623,7 @@ LIB_EXPORT bool l_dhcp6_client_set_link_local_address(
 		return false;
 
 	if (!client->nora)
-		l_icmp6_client_set_link_local_address(client->icmp6, ll);
+		l_icmp6_client_set_link_local_address(client->icmp6, ll, false);
 
 	return true;
 }
diff --git a/ell/icmp6.c b/ell/icmp6.c
index 5ddc494..f087ba3 100644
--- a/ell/icmp6.c
+++ b/ell/icmp6.c
@@ -206,7 +206,8 @@ static uint16_t icmp6_checksum(const struct iovec *iov, unsigned int iov_len)
 
 static int icmp6_send_router_solicitation(int s, int ifindex,
 					const uint8_t src_mac[static 6],
-					const struct in6_addr *src_ip)
+					const struct in6_addr *src_ip,
+					bool src_ip_optimistic)
 {
 	struct nd_router_solicit rs = {
 		.nd_rs_type = ND_ROUTER_SOLICIT,
@@ -247,11 +248,17 @@ static int icmp6_send_router_solicitation(int s, int ifindex,
 
 	memcpy(&ip_hdr.ip6_src, src_ip, 16);
 
-	if (l_memeqzero(src_ip, 16)) {
+	if (l_memeqzero(src_ip, 16) || src_ip_optimistic) {
 		/*
-		 * radvd will discard and warn about RSs from the unspecified
-		 * address with the SLLAO, omit that option by dropping the
-		 * last two iov buffers.
+		 * RFC 4429 Section 3.2: "A node MUST NOT send a Router
+		 * Solicitation with a SLLAO from an Optimistic Address.
+		 * Router Solicitations SHOULD be sent from a non-Optimistic
+		 * or the Unspecified Address; however, they MAY be sent from
+		 * an Optimistic Address as long as the SLLAO is not included."
+		 *
+		 * Additionally radvd will also discard and warn about RSs
+		 * from the unspecified address with the SLLAO.  Omit that
+		 * option by dropping the last two iov buffers.
 		 */
 		msg.msg_iovlen -= 2;
 		ip_hdr.ip6_plen = htons(ntohs(ip_hdr.ip6_plen) - rs_sllao_size);
@@ -347,6 +354,7 @@ struct l_icmp6_client {
 	uint64_t retransmit_time;
 	struct l_io *io;
 	struct in6_addr src_ip;
+	bool src_ip_optimistic;
 
 	struct l_icmp6_router *ra;
 	struct l_netlink *rtnl;
@@ -547,7 +555,8 @@ static void icmp6_client_timeout_send(struct l_timeout *timeout,
 
 	r = icmp6_send_router_solicitation(l_io_get_fd(client->io),
 						client->ifindex, client->mac,
-						&client->src_ip);
+						&client->src_ip,
+						client->src_ip_optimistic);
 	if (r < 0) {
 		CLIENT_DEBUG("Error sending Router Solicitation: %s",
 				strerror(-r));
@@ -766,7 +775,7 @@ LIB_EXPORT bool l_icmp6_client_set_route_priority(
 
 LIB_EXPORT bool l_icmp6_client_set_link_local_address(
 						struct l_icmp6_client *client,
-						const char *ll)
+						const char *ll, bool optimistic)
 {
 	if (unlikely(!client))
 		return false;
@@ -777,7 +786,11 @@ LIB_EXPORT bool l_icmp6_client_set_link_local_address(
 	 * is fine.  Once we have a confirmed link-local address we use that
 	 * as the source address.
 	 */
-	return inet_pton(AF_INET6, ll, &client->src_ip) == 1;
+	if (inet_pton(AF_INET6, ll, &client->src_ip) != 1)
+		return false;
+
+	client->src_ip_optimistic = optimistic;
+	return true;
 }
 
 struct l_icmp6_router *_icmp6_router_new()
diff --git a/ell/icmp6.h b/ell/icmp6.h
index ffbb8a8..ad3d661 100644
--- a/ell/icmp6.h
+++ b/ell/icmp6.h
@@ -66,7 +66,8 @@ bool l_icmp6_client_set_rtnl(struct l_icmp6_client *client,
 bool l_icmp6_client_set_route_priority(struct l_icmp6_client *client,
 						uint32_t priority);
 bool l_icmp6_client_set_link_local_address(struct l_icmp6_client *client,
-						const char *ll);
+						const char *ll,
+						bool optimistic);
 
 char *l_icmp6_router_get_address(const struct l_icmp6_router *r);
 bool l_icmp6_router_get_managed(const struct l_icmp6_router *r);
diff --git a/ell/netconfig.c b/ell/netconfig.c
index 765703b..c558cad 100644
--- a/ell/netconfig.c
+++ b/ell/netconfig.c
@@ -93,6 +93,7 @@ struct l_netconfig {
 	unsigned int orig_optimistic_dad;
 	uint8_t mac[ETH_ALEN];
 	struct l_timeout *ra_timeout;
+	bool have_lla;
 	enum {
 		NETCONFIG_V6_METHOD_UNSET,
 		NETCONFIG_V6_METHOD_DHCP,
@@ -702,7 +703,7 @@ static bool netconfig_check_start_dhcp6(struct l_netconfig *nc)
 		return true;
 
 	/* Don't start DHCPv6 while waiting for the link-local address */
-	if (l_queue_find(addr_wait_list, netconfig_match, nc))
+	if (!nc->have_lla)
 		return true;
 
 	return l_dhcp6_client_start(nc->dhcp6_client);
@@ -1844,6 +1845,7 @@ static void netconfig_ifaddr_ipv6_added(struct l_netconfig *nc,
 {
 	struct in6_addr in6;
 	_auto_(l_free) char *ip = NULL;
+	bool new_lla;
 
 	if ((ifa->ifa_flags & IFA_F_TENTATIVE) &&
 			!(ifa->ifa_flags & IFA_F_OPTIMISTIC))
@@ -1858,16 +1860,28 @@ static void netconfig_ifaddr_ipv6_added(struct l_netconfig *nc,
 	if (!IN6_IS_ADDR_LINKLOCAL(&in6))
 		return;
 
-	netconfig_addr_wait_unregister(nc, true);
+	new_lla = !nc->have_lla;
+	nc->have_lla = true;
+
+	if (!(ifa->ifa_flags & IFA_F_TENTATIVE))
+		netconfig_addr_wait_unregister(nc, true);
+	else if (nc->ifaddr6_dump_cmd_id) {
+		struct l_netlink *rtnl = l_rtnl_get();
+		unsigned int cmd_id = nc->ifaddr6_dump_cmd_id;
+
+		nc->ifaddr6_dump_cmd_id = 0;
+		l_netlink_cancel(rtnl, cmd_id);
+	}
 
 	l_dhcp6_client_set_link_local_address(nc->dhcp6_client, ip);
-	l_icmp6_client_set_link_local_address(nc->icmp6_client, ip);
+	l_icmp6_client_set_link_local_address(nc->icmp6_client, ip,
+					!!(ifa->ifa_flags & IFA_F_OPTIMISTIC));
 
 	/*
 	 * Only now that we have a link-local address see if we can start
 	 * actual DHCPv6 setup.
 	 */
-	if (netconfig_check_start_dhcp6(nc))
+	if (new_lla && netconfig_check_start_dhcp6(nc))
 		return;
 
 	netconfig_emit_event(nc, AF_INET6, L_NETCONFIG_EVENT_FAILED);
@@ -2022,6 +2036,13 @@ configure_ipv6:
 	 * before we start the dump, instead of after it ends, to eliminate
 	 * the possibility of missing an RTM_NEWADDR between the end of
 	 * the dump command and registering for the events.
+	 *
+	 * We stay on that list until we receive a non-tentative LL address.
+	 * Note that we may set .have_lla earlier, specifically when we
+	 * receive a tentative LL address that is also optimistic.  We will
+	 * however stay on addr_wait_list because we want to notify
+	 * l_icmp6_client again when the LL address completes DAD and becomes
+	 * non-tentative.
 	 */
 	if (!addr_wait_list) {
 		addr_wait_list = l_queue_new();
@@ -2041,6 +2062,7 @@ configure_ipv6:
 		goto unregister;
 
 	l_queue_push_tail(addr_wait_list, netconfig);
+	netconfig->have_lla = false;
 
 	if (!l_net_get_mac_address(netconfig->ifindex, netconfig->mac))
 		goto unregister;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 6/6] netconfig: Handle missing optimistic_dad /proc file
  2022-09-20 13:31 [PATCH 1/6] net: Allow padding in net_domain_list_parse Andrew Zaborowski
                   ` (3 preceding siblings ...)
  2022-09-20 13:32 ` [PATCH 5/6] icmp6,netconfig: Skip SLLAO if RS sent from optimistic address Andrew Zaborowski
@ 2022-09-20 13:32 ` Andrew Zaborowski
  2022-09-20 15:06 ` [PATCH 1/6] net: Allow padding in net_domain_list_parse Denis Kenzior
  5 siblings, 0 replies; 7+ messages in thread
From: Andrew Zaborowski @ 2022-09-20 13:32 UTC (permalink / raw)
  To: ell

Handle netconfig_proc_read_ipv6_uint_setting(..., "optimistic_dad")
failures more cleanly in case CONFIG_IPV6_OPTIMISTIC_DAD has not been
enabled in the kernel config.  This commit makes no noticeable
difference to the user.
---
 ell/netconfig.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/ell/netconfig.c b/ell/netconfig.c
index c558cad..fe5bf40 100644
--- a/ell/netconfig.c
+++ b/ell/netconfig.c
@@ -90,7 +90,7 @@ struct l_netconfig {
 	struct l_queue *icmp_route_data;
 	struct l_acd *acd;
 	unsigned int orig_disable_ipv6;
-	unsigned int orig_optimistic_dad;
+	long orig_optimistic_dad;
 	uint8_t mac[ETH_ALEN];
 	struct l_timeout *ra_timeout;
 	bool have_lla;
@@ -2010,7 +2010,8 @@ configure_ipv6:
 		netconfig_proc_read_ipv6_uint_setting(netconfig,
 							"optimistic_dad");
 
-	if (!!netconfig->orig_optimistic_dad != optimistic_dad)
+	if (netconfig->orig_optimistic_dad >= 0 &&
+			!!netconfig->orig_optimistic_dad != optimistic_dad)
 		netconfig_proc_write_ipv6_uint_setting(netconfig,
 							"optimistic_dad",
 							optimistic_dad ? 1 : 0);
@@ -2160,7 +2161,8 @@ LIB_EXPORT void l_netconfig_stop(struct l_netconfig *netconfig)
 
 	optimistic_dad = netconfig->optimistic_dad_enabled &&
 		!netconfig->v6_static_addr;
-	if (!!netconfig->orig_optimistic_dad != optimistic_dad)
+	if (netconfig->orig_optimistic_dad >= 0 &&
+			!!netconfig->orig_optimistic_dad != optimistic_dad)
 		netconfig_proc_write_ipv6_uint_setting(netconfig,
 						"optimistic_dad",
 						netconfig->orig_optimistic_dad);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/6] net: Allow padding in net_domain_list_parse
  2022-09-20 13:31 [PATCH 1/6] net: Allow padding in net_domain_list_parse Andrew Zaborowski
                   ` (4 preceding siblings ...)
  2022-09-20 13:32 ` [PATCH 6/6] netconfig: Handle missing optimistic_dad /proc file Andrew Zaborowski
@ 2022-09-20 15:06 ` Denis Kenzior
  5 siblings, 0 replies; 7+ messages in thread
From: Denis Kenzior @ 2022-09-20 15:06 UTC (permalink / raw)
  To: Andrew Zaborowski, ell

Hi Andrew,

On 9/20/22 08:31, Andrew Zaborowski wrote:
> The domain name lists in ICMPv6 options may be 0-padded meaning that a
> 0-byte at the beginning of a domain record (ie. a domain with no labels)
> is allowed and should be treated as the end of the list.  Add a boolean
> parameter to tell net_domain_list_parse() whether to allow this.
> 
> Fixes: 4b1ce9b3e3d0 ("icmp6: Parse RDNSS and DNSSL options")
> ---
>   ell/dhcp6-lease.c | 2 +-
>   ell/icmp6.c       | 6 +++---
>   ell/net-private.h | 2 +-
>   ell/net.c         | 8 +++++++-
>   4 files changed, 12 insertions(+), 6 deletions(-)
> 

All applied, thanks.

Regards,
-Denis


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-09-20 15:22 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-20 13:31 [PATCH 1/6] net: Allow padding in net_domain_list_parse Andrew Zaborowski
2022-09-20 13:31 ` [PATCH 2/6] unit: Update net_domain_list_parse test Andrew Zaborowski
2022-09-20 13:31 ` [PATCH 3/6] netconfig: Set .v6_configured when we set an address Andrew Zaborowski
2022-09-20 13:31 ` [PATCH 4/6] netconfig: Handle DNS data from l_icmp6_router Andrew Zaborowski
2022-09-20 13:32 ` [PATCH 5/6] icmp6,netconfig: Skip SLLAO if RS sent from optimistic address Andrew Zaborowski
2022-09-20 13:32 ` [PATCH 6/6] netconfig: Handle missing optimistic_dad /proc file Andrew Zaborowski
2022-09-20 15:06 ` [PATCH 1/6] net: Allow padding in net_domain_list_parse Denis Kenzior

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).