[PATCH 1/6] net: Allow padding in net_domain_list_parse

Andrew Zaborowski <[email protected]>
Newsgroups dev.linux.lists.ell
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.