summaryrefslogtreecommitdiffhomepage
path: root/interface-ip.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2012-05-23 22:36:19 +0200
committerFelix Fietkau <nbd@openwrt.org>2012-05-23 22:36:19 +0200
commitbb05211c9c2abbda5866c44ad86994fabf9247e0 (patch)
tree9f5319b6de54580601b64d003326201f82599b54 /interface-ip.c
parent9aac5923811e0240526f2ef58d6e352bff195740 (diff)
preserve subnet routes on interface update by not putting them in the route vlist
Diffstat (limited to 'interface-ip.c')
-rw-r--r--interface-ip.c46
1 files changed, 28 insertions, 18 deletions
diff --git a/interface-ip.c b/interface-ip.c
index 0558b6c..e09a74f 100644
--- a/interface-ip.c
+++ b/interface-ip.c
@@ -253,6 +253,30 @@ route_cmp(const void *k1, const void *k2, void *ptr)
}
static void
+interface_handle_subnet_route(struct interface *iface, struct device_addr *addr, bool add)
+{
+ struct device *dev = iface->l3_dev.dev;
+ struct device_route route;
+
+ route.iface = iface;
+ route.flags = addr->flags;
+ route.mask = addr->mask;
+ memcpy(&route.addr, &addr->addr, sizeof(route.addr));
+ clear_if_addr(&route.addr, route.mask);
+
+ if (add) {
+ route.flags |= DEVADDR_KERNEL;
+ system_del_route(dev, &route);
+
+ route.flags &= ~DEVADDR_KERNEL;
+ route.metric = iface->metric;
+ system_add_route(dev, &route);
+ } else {
+ system_del_route(dev, &route);
+ }
+}
+
+static void
interface_update_proto_addr(struct vlist_tree *tree,
struct vlist_node *node_new,
struct vlist_node *node_old)
@@ -262,7 +286,6 @@ interface_update_proto_addr(struct vlist_tree *tree,
struct device *dev;
struct device_addr *a_new = NULL, *a_old = NULL;
bool keep = false;
- struct device_route *route;
ip = container_of(tree, struct interface_ip_settings, addr);
iface = ip->iface;
@@ -297,8 +320,10 @@ interface_update_proto_addr(struct vlist_tree *tree,
}
if (node_old) {
- if (!(a_old->flags & DEVADDR_EXTERNAL) && a_old->enabled && !keep)
+ if (!(a_old->flags & DEVADDR_EXTERNAL) && a_old->enabled && !keep) {
+ interface_handle_subnet_route(iface, a_old, false);
system_del_address(dev, a_old);
+ }
free(a_old);
}
@@ -307,24 +332,9 @@ interface_update_proto_addr(struct vlist_tree *tree,
if (!(a_new->flags & DEVADDR_EXTERNAL) && !keep) {
system_add_address(dev, a_new);
if (iface->metric)
- goto replace_route;
+ interface_handle_subnet_route(iface, a_new, true);
}
}
- return;
-
-replace_route:
- route = calloc(1, sizeof(*route));
- route->iface = iface;
- route->flags = a_new->flags | DEVADDR_KERNEL;
- route->mask = a_new->mask;
- memcpy(&route->addr, &a_new->addr, sizeof(route->addr));
- clear_if_addr(&route->addr, route->mask);
-
- system_del_route(dev, route);
-
- route->flags &= ~DEVADDR_KERNEL;
- route->metric = iface->metric;
- vlist_add(&ip->route, &route->node, &route->flags);
}
static bool