aboutgitcodebugslistschat
path: root/dhcpv6.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2021-09-01 16:00:19 +0200
committerStefano Brivio <sbrivio@redhat.com>2021-09-01 16:49:21 +0200
commit353185cd3642d62dadfc9d9be020a4f729400e41 (patch)
tree879404f891fc0ec0497e455435e92236fcbaf49b /dhcpv6.c
parentd2272f74f72469c3d4c2368439f36bb3b348db7c (diff)
downloadpasst-353185cd3642d62dadfc9d9be020a4f729400e41.tar
passt-353185cd3642d62dadfc9d9be020a4f729400e41.tar.gz
passt-353185cd3642d62dadfc9d9be020a4f729400e41.tar.bz2
passt-353185cd3642d62dadfc9d9be020a4f729400e41.tar.lz
passt-353185cd3642d62dadfc9d9be020a4f729400e41.tar.xz
passt-353185cd3642d62dadfc9d9be020a4f729400e41.tar.zst
passt-353185cd3642d62dadfc9d9be020a4f729400e41.zip
dhcpv6: Fix parsing for IA_ADDR suboptions of IA_NA/IA_TA
Once we're past the IA_NA or IA_TA option itself, before we start looking for IA_ADDR suboptions, we need to subtract the length of the option we parsed so far, otherwise we might end up reading past the end of the message, or miss some parts. While at it, streamline calculations in dhcpv6_opt(). Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'dhcpv6.c')
-rw-r--r--dhcpv6.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/dhcpv6.c b/dhcpv6.c
index f982cde..c4f7a9a 100644
--- a/dhcpv6.c
+++ b/dhcpv6.c
@@ -295,15 +295,17 @@ static struct resp_not_on_link_t {
static struct opt_hdr *dhcpv6_opt(struct opt_hdr *o, uint16_t type, size_t *len)
{
while (*len >= sizeof(struct opt_hdr)) {
- if (ntohs(o->l) > *len)
+ unsigned int opt_len = ntohs(o->l) + sizeof(struct opt_hdr);
+
+ if (opt_len > *len)
return NULL;
- *len -= ntohs(o->l) + sizeof(struct opt_hdr);
+ *len -= opt_len;
if (o->t == type)
return o;
- o = (struct opt_hdr *)((uint8_t *)(o + 1) + ntohs(o->l));
+ o = (struct opt_hdr *)((uint8_t *)o + opt_len);
}
return NULL;
@@ -335,15 +337,17 @@ ia_ta:
size_t ia_len = ntohs(ia->l);
if (ia_type == OPT_IA_NA) {
- struct opt_ia_na *opts = (struct opt_ia_na *)ia + 1;
+ struct opt_ia_na *subopt = (struct opt_ia_na *)ia + 1;
- ia_addr = (struct opt_hdr *)opts;
+ ia_addr = (struct opt_hdr *)subopt;
} else if (ia_type == OPT_IA_TA) {
- struct opt_ia_ta *opts = (struct opt_ia_ta *)ia + 1;
+ struct opt_ia_ta *subopt = (struct opt_ia_ta *)ia + 1;
- ia_addr = (struct opt_hdr *)opts;
+ ia_addr = (struct opt_hdr *)subopt;
}
+ ia_len -= sizeof(struct opt_ia_na) - sizeof(struct opt_hdr);
+
while ((ia_addr = dhcpv6_opt(ia_addr, OPT_IAAADR, &ia_len))) {
struct opt_ia_addr *next;