Don't always assume routes & addresses are applied
[project/netifd.git] / interface-ip.c
index 59cf828..b1abbc6 100644 (file)
@@ -337,12 +337,12 @@ interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6)
                const char *addr = strtok_r(source, "/", &saveptr);
                const char *mask = strtok_r(NULL, "/", &saveptr);
 
-               if (inet_pton(af, addr, &route->source) < 1) {
+               if (!addr || inet_pton(af, addr, &route->source) < 1) {
                        DPRINTF("Failed to parse route source: %s\n", addr);
                        goto error;
                }
 
-               route->sourcemask = atoi(mask);
+               route->sourcemask = (mask) ? atoi(mask) : ((af == AF_INET6) ? 128 : 32);
        }
 
        if (is_proto_route) {
@@ -480,7 +480,7 @@ interface_update_proto_addr(struct vlist_tree *tree,
        if (a_new && a_old) {
                keep = true;
 
-               if (a_old->flags != a_new->flags)
+               if (a_old->flags != a_new->flags || a_old->failed)
                        keep = false;
 
                if (a_old->valid_until != a_new->valid_until ||
@@ -521,7 +521,8 @@ interface_update_proto_addr(struct vlist_tree *tree,
        if (node_new) {
                a_new->enabled = true;
                if (!(a_new->flags & DEVADDR_EXTERNAL) && (!keep || replace)) {
-                       system_add_address(dev, a_new);
+                       if (system_add_address(dev, a_new))
+                               a_new->failed = true;
 
                        if (!keep) {
                                if ((a_new->flags & DEVADDR_FAMILY) == DEVADDR_INET6)
@@ -575,7 +576,7 @@ interface_update_proto_route(struct vlist_tree *tree,
 
        if (node_old && node_new)
                keep = !memcmp(&route_old->nexthop, &route_new->nexthop, sizeof(route_old->nexthop)) &&
-                       (route_old->table == route_new->table);
+                       (route_old->table == route_new->table) && !route_old->failed;
 
        if (node_old) {
                if (!(route_old->flags & DEVADDR_EXTERNAL) && route_old->enabled && !keep)
@@ -591,7 +592,8 @@ interface_update_proto_route(struct vlist_tree *tree,
                        route_new->metric = iface->metric;
 
                if (!(route_new->flags & DEVADDR_EXTERNAL) && !keep && _enabled)
-                       system_add_route(dev, route_new);
+                       if (system_add_route(dev, route_new))
+                               route_new->failed = true;
 
                route_new->iface = iface;
                route_new->enabled = _enabled;
@@ -648,6 +650,7 @@ interface_set_prefix_address(struct device_prefix_assignment *assignment,
                addr.preferred_until = now;
                if (!addr.valid_until || addr.valid_until - now > 7200)
                        addr.valid_until = now + 7200;
+               system_del_address(l3_downlink, &addr); // Work around dangling prefix routes
                system_add_address(l3_downlink, &addr);
                if (prefix->iface) {
                        if (prefix->iface->ip6table)