diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2021-09-01 16:00:19 +0200 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2021-09-01 16:49:21 +0200 |
commit | 353185cd3642d62dadfc9d9be020a4f729400e41 (patch) | |
tree | 879404f891fc0ec0497e455435e92236fcbaf49b /dhcpv6.c | |
parent | d2272f74f72469c3d4c2368439f36bb3b348db7c (diff) | |
download | passt-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.c | 18 |
1 files changed, 11 insertions, 7 deletions
@@ -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; |