ra: rework route information option handling
authorHans Dedecker <dedeckeh@gmail.com>
Mon, 2 Apr 2018 19:09:16 +0000 (21:09 +0200)
committerHans Dedecker <dedeckeh@gmail.com>
Mon, 2 Apr 2018 19:14:40 +0000 (21:14 +0200)
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>
src/ra.c
src/ra.h

index 84925081a31c2b49513cc68fd87aed0d98be6671..c1f3d0373cf47ca311e297d8ed48e2d25bb853fd 100644 (file)
--- a/src/ra.c
+++ b/src/ra.c
@@ -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;
index e6f7ccbc1677a0d1ce9abffab9a89b8ef5c1427c..9acc8cd971a28a08859a400f454017ebce46b963 100644 (file)
--- a/src/ra.h
+++ b/src/ra.h
@@ -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