fix refcount bugs when dev->set_state fails
[project/netifd.git] / interface-ip.c
index baa8b0e..2d7a2d0 100644 (file)
 #include "ubus.h"
 #include "system.h"
 
 #include "ubus.h"
 #include "system.h"
 
+static int
+addr_cmp(const void *k1, const void *k2, void *ptr)
+{
+       return memcmp(k1, k2, sizeof(struct device_addr) -
+                     offsetof(struct device_addr, mask));
+}
+
+static int
+route_cmp(const void *k1, const void *k2, void *ptr)
+{
+       return memcmp(k1, k2, sizeof(struct device_route) -
+                     offsetof(struct device_route, mask));
+}
+
 static void
 interface_update_proto_addr(struct vlist_tree *tree,
                            struct vlist_node *node_new,
 static void
 interface_update_proto_addr(struct vlist_tree *tree,
                            struct vlist_node *node_new,
@@ -20,17 +34,19 @@ interface_update_proto_addr(struct vlist_tree *tree,
        struct device_addr *addr;
 
        iface = container_of(tree, struct interface, proto_addr);
        struct device_addr *addr;
 
        iface = container_of(tree, struct interface, proto_addr);
-       dev = iface->l3_iface->dev;
+       dev = iface->l3_dev->dev;
 
        if (node_old) {
                addr = container_of(node_old, struct device_addr, node);
 
        if (node_old) {
                addr = container_of(node_old, struct device_addr, node);
-               system_del_address(dev, addr);
+               if (!(addr->flags & DEVADDR_EXTERNAL))
+                       system_del_address(dev, addr);
                free(addr);
        }
 
        if (node_new) {
                addr = container_of(node_new, struct device_addr, node);
                free(addr);
        }
 
        if (node_new) {
                addr = container_of(node_new, struct device_addr, node);
-               system_add_address(dev, addr);
+               if (!(addr->flags & DEVADDR_EXTERNAL))
+                       system_add_address(dev, addr);
        }
 }
 
        }
 }
 
@@ -44,26 +60,27 @@ interface_update_proto_route(struct vlist_tree *tree,
        struct device_route *route;
 
        iface = container_of(tree, struct interface, proto_route);
        struct device_route *route;
 
        iface = container_of(tree, struct interface, proto_route);
-       dev = iface->l3_iface->dev;
+       dev = iface->l3_dev->dev;
 
        if (node_old) {
                route = container_of(node_old, struct device_route, node);
 
        if (node_old) {
                route = container_of(node_old, struct device_route, node);
-               system_del_route(dev, route);
+               if (!(route->flags & DEVADDR_EXTERNAL))
+                       system_del_route(dev, route);
                free(route);
        }
 
        if (node_new) {
                route = container_of(node_new, struct device_route, node);
                free(route);
        }
 
        if (node_new) {
                route = container_of(node_new, struct device_route, node);
-               system_add_route(dev, route);
+               if (!(route->flags & DEVADDR_EXTERNAL))
+                       system_add_route(dev, route);
        }
 }
 
 void
 interface_ip_init(struct interface *iface)
 {
        }
 }
 
 void
 interface_ip_init(struct interface *iface)
 {
-       vlist_init(&iface->proto_route, interface_update_proto_route,
-                  struct device_route, node, mask, addr);
-       vlist_init(&iface->proto_addr, interface_update_proto_addr,
-                  struct device_addr, node, mask, addr);
+       vlist_init(&iface->proto_route, route_cmp, interface_update_proto_route,
+                  struct device_route, node, mask);
+       vlist_init(&iface->proto_addr, addr_cmp, interface_update_proto_addr,
+                  struct device_addr, node, mask);
 }
 }
-