diff options
author | Hans Dedecker <dedeckeh@gmail.com> | 2018-04-02 22:09:16 +0300 |
---|---|---|
committer | Hans Dedecker <dedeckeh@gmail.com> | 2018-04-02 22:14:40 +0300 |
commit | ea189359a1f6ae0ef5fa10de49bad1b1709b7b9d (patch) | |
tree | b658ba26b98740310e1fab9b3d57268fd0a74203 | |
parent | 5cbd305a7a7166e5d4d0cb4050560207dfb66c5f (diff) |
ra: rework route information option handling
Use struct icmpv6_opt_route_info to parse the route information option;
improve route information option sanity checks.
Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
-rw-r--r-- | src/ra.c | 23 | ||||
-rw-r--r-- | src/ra.h | 9 |
2 files changed, 26 insertions, 6 deletions
@@ -410,15 +410,26 @@ bool ra_process(void) uint32_t *mtu = (uint32_t*)&opt->data[2]; ra_conf_mtu(ntohl(*mtu)); } else if (opt->type == ND_OPT_ROUTE_INFORMATION && opt->len <= 3) { + struct icmpv6_opt_route_info *ri = (struct icmpv6_opt_route_info *)opt; + + if (ri->prefix_len > 128) { + continue; + } else if (ri->prefix_len > 64) { + if (ri->len < 2) + continue; + } else if (ri->prefix_len > 0) { + if (ri->len < 1) + continue; + } + entry->router = from.sin6_addr; entry->target = any; - entry->priority = pref_to_priority(opt->data[1]); - entry->length = opt->data[0]; - uint32_t *valid = (uint32_t*)&opt->data[2]; - entry->valid = ntohl(*valid); - memcpy(&entry->target, &opt->data[6], (opt->len - 1) * 8); + entry->priority = pref_to_priority(ri->flags); + entry->length = ri->prefix_len; + entry->valid = ntohl(ri->lifetime); + memcpy(&entry->target, ri->prefix, (ri->len - 1) * 8); - if (entry->length > 128 || IN6_IS_ADDR_LINKLOCAL(&entry->target) + if (IN6_IS_ADDR_LINKLOCAL(&entry->target) || IN6_IS_ADDR_LOOPBACK(&entry->target) || IN6_IS_ADDR_MULTICAST(&entry->target)) continue; @@ -26,6 +26,15 @@ struct icmpv6_opt { uint8_t data[6]; }; +struct icmpv6_opt_route_info { + uint8_t type; + uint8_t len; + uint8_t prefix_len; + uint8_t flags; + uint32_t lifetime; + uint8_t prefix[]; +}; + #define ND_OPT_ROUTE_INFORMATION 24 |