IPv6: fix wrap-arounds in address lifetimes
authorSteven Barth <steven@midlink.org>
Tue, 28 May 2013 17:59:19 +0000 (19:59 +0200)
committerSteven Barth <steven@midlink.org>
Tue, 28 May 2013 17:59:19 +0000 (19:59 +0200)
interface-ip.c
interface.c
proto.c

index 2444cda2128e4505b67186bd1ea85d9839fad17c..47747cbaa568536bd257a210151fc1f392f39e88 100644 (file)
@@ -17,6 +17,7 @@
 #include <stdio.h>
 #include <unistd.h>
 
+#include <limits.h>
 #include <arpa/inet.h>
 
 #include "netifd.h"
@@ -328,8 +329,12 @@ interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6)
                        route->flags |= DEVROUTE_TABLE;
        }
 
-       if ((cur = tb[ROUTE_VALID]) != NULL)
-               route->valid_until = system_get_rtime() + blobmsg_get_u32(cur);
+       if ((cur = tb[ROUTE_VALID]) != NULL) {
+               int64_t valid = blobmsg_get_u32(cur);
+               int64_t valid_until = valid + (int64_t)system_get_rtime();
+               if (valid_until <= LONG_MAX && valid != 0xffffffffLL) // Catch overflow
+                       route->valid_until = valid_until;
+       }
 
        vlist_add(&ip->route, &route->node, route);
        return;
index 42e5a8248c6d37b9382fb8a30c57411e34ccc0a1..2e7a96f206d748748ab9f7690d9a317da852246f 100644 (file)
@@ -508,6 +508,7 @@ interface_init(struct interface *iface, const char *name,
        }
 
        // Set a default exteranl routing table for IPv6 to do source-based-filtering
+
        iface->ip6table = 1000 + ++interface_serial;
        if ((cur = tb[IFACE_ATTR_IP6TABLE])) {
                if (!system_resolve_rt_table(blobmsg_data(cur), &iface->ip6table))
diff --git a/proto.c b/proto.c
index dff5bbb736f684e369aec8661256fe6a6bca61f9..d060d2ed9f435cbb03fe43d3909d5bda95afaaa0 100644 (file)
--- a/proto.c
+++ b/proto.c
@@ -15,6 +15,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <limits.h>
 
 #include <arpa/inet.h>
 #include <netinet/in.h>
@@ -187,15 +188,17 @@ parse_address_item(struct blob_attr *attr, bool v6, bool ext)
        } else {
                time_t now = system_get_rtime();
                if ((cur = tb[ADDR_PREFERRED])) {
-                       uint32_t preferred = blobmsg_get_u32(cur);
-                       if (preferred < UINT32_MAX)
-                               addr->preferred_until = now + preferred;
+                       int64_t preferred = blobmsg_get_u32(cur);
+                       int64_t preferred_until = preferred + (int64_t)now;
+                       if (preferred_until <= LONG_MAX && preferred != 0xffffffffLL)
+                               addr->preferred_until = preferred_until;
                }
 
                if ((cur = tb[ADDR_VALID])) {
-                       uint32_t valid = blobmsg_get_u32(cur);
-                       if (valid < UINT32_MAX)
-                               addr->valid_until = now + valid;
+                       int64_t valid = blobmsg_get_u32(cur);
+                       int64_t valid_until = valid + (int64_t)now;
+                       if (valid_until <= LONG_MAX && valid != 0xffffffffLL)
+                               addr->valid_until = valid_until;
 
                }
 
@@ -283,8 +286,8 @@ parse_prefix_option(struct interface *iface, const char *str, size_t len)
        char *validstr = (!prefstr) ? NULL : strtok_r(NULL, ",", &saveptr);
        char *addstr = (!validstr) ? NULL : strtok_r(NULL, ",", &saveptr);
 
-       uint32_t pref = (!prefstr) ? 0 : strtoul(prefstr, NULL, 10);
-       uint32_t valid = (!validstr) ? 0 : strtoul(validstr, NULL, 10);
+       int64_t pref = (!prefstr) ? 0 : strtoul(prefstr, NULL, 10);
+       int64_t valid = (!validstr) ? 0 : strtoul(validstr, NULL, 10);
 
        uint8_t length = strtoul(lengthstr, NULL, 10), excl_length = 0;
        if (length < 1 || length > 64)
@@ -319,13 +322,13 @@ parse_prefix_option(struct interface *iface, const char *str, size_t len)
 
 
 
-       time_t now = system_get_rtime();
+       int64_t now = system_get_rtime();
        time_t preferred_until = 0;
-       if (prefstr && pref != 0xffffffffU)
+       if (prefstr && pref != 0xffffffffLL && pref + now <= LONG_MAX)
                preferred_until = pref + now;
 
        time_t valid_until = 0;
-       if (validstr && valid != 0xffffffffU)
+       if (validstr && valid != 0xffffffffLL && valid + now <= LONG_MAX)
                valid_until = valid + now;
 
        interface_ip_add_device_prefix(iface, &addr, length,