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>
This commit is contained in:
parent
d2272f74f7
commit
353185cd36
1 changed files with 11 additions and 7 deletions
18
dhcpv6.c
18
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)
|
static struct opt_hdr *dhcpv6_opt(struct opt_hdr *o, uint16_t type, size_t *len)
|
||||||
{
|
{
|
||||||
while (*len >= sizeof(struct opt_hdr)) {
|
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;
|
return NULL;
|
||||||
|
|
||||||
*len -= ntohs(o->l) + sizeof(struct opt_hdr);
|
*len -= opt_len;
|
||||||
|
|
||||||
if (o->t == type)
|
if (o->t == type)
|
||||||
return o;
|
return o;
|
||||||
|
|
||||||
o = (struct opt_hdr *)((uint8_t *)(o + 1) + ntohs(o->l));
|
o = (struct opt_hdr *)((uint8_t *)o + opt_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -335,15 +337,17 @@ ia_ta:
|
||||||
size_t ia_len = ntohs(ia->l);
|
size_t ia_len = ntohs(ia->l);
|
||||||
|
|
||||||
if (ia_type == OPT_IA_NA) {
|
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) {
|
} 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))) {
|
while ((ia_addr = dhcpv6_opt(ia_addr, OPT_IAAADR, &ia_len))) {
|
||||||
struct opt_ia_addr *next;
|
struct opt_ia_addr *next;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue