aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Zaborowski <andrew.zaborowski@intel.com>2022-09-20 15:31:56 +0200
committerDenis Kenzior <denkenz@gmail.com>2022-09-20 10:01:54 -0500
commitc79b047c99cfce63614a615e27ccd09ec4ed2748 (patch)
tree883da24cbea68b9520415468ad2ed016ea22f9b4
parent04fe608a3e67a390c852b3b3bfb95b0b9bbf948d (diff)
net: Allow padding in net_domain_list_parse
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")
-rw-r--r--ell/dhcp6-lease.c2
-rw-r--r--ell/icmp6.c6
-rw-r--r--ell/net-private.h2
-rw-r--r--ell/net.c8
4 files changed, 12 insertions, 6 deletions
diff --git a/ell/dhcp6-lease.c b/ell/dhcp6-lease.c
index 978176ae..a92cff9f 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 a2765ea7..5ddc494d 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 39d4d980..a8640341 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 378b9f20..aa7fc200 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;