move broadcast address handling to the core
authorFelix Fietkau <nbd@openwrt.org>
Sun, 26 Feb 2012 16:43:10 +0000 (17:43 +0100)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 26 Feb 2012 16:43:10 +0000 (17:43 +0100)
interface-ip.c
interface-ip.h
proto.c
system-linux.c

index 93e8723be216b9408144970885e7b59f981f2b93..7f10120f878617900ef87f5ae576b8ce343684b4 100644 (file)
@@ -124,28 +124,51 @@ interface_update_proto_addr(struct vlist_tree *tree,
        struct interface_ip_settings *ip;
        struct interface *iface;
        struct device *dev;
-       struct device_addr *addr;
+       struct device_addr *a_new = NULL, *a_old = NULL;
        bool keep = false;
 
        ip = container_of(tree, struct interface_ip_settings, addr);
        iface = ip->iface;
        dev = iface->l3_dev->dev;
 
-       if (node_old && node_new)
+       if (node_new) {
+               a_new = container_of(node_new, struct device_addr, node);
+
+               if ((a_new->flags & DEVADDR_FAMILY) == DEVADDR_INET4 &&
+                   !a_new->broadcast) {
+
+                       uint32_t mask = ~0;
+                       uint32_t *a = (uint32_t *) &a_new->addr;
+
+                       mask >>= a_new->mask;
+                       a_new->broadcast = *a | mask;
+               }
+       }
+
+       if (node_old)
+               a_old = container_of(node_old, struct device_addr, node);
+
+       if (a_new && a_old) {
                keep = true;
 
+               if (a_old->flags != a_new->flags)
+                       keep = false;
+
+               if ((a_new->flags & DEVADDR_FAMILY) == DEVADDR_INET4 &&
+                   a_new->broadcast != a_old->broadcast)
+                       keep = false;
+       }
+
        if (node_old) {
-               addr = container_of(node_old, struct device_addr, node);
-               if (!(addr->flags & DEVADDR_EXTERNAL) && addr->enabled && !keep)
-                       system_del_address(dev, addr);
-               free(addr);
+               if (!(a_old->flags & DEVADDR_EXTERNAL) && a_old->enabled && !keep)
+                       system_del_address(dev, a_old);
+               free(a_old);
        }
 
        if (node_new) {
-               addr = container_of(node_new, struct device_addr, node);
-               if (!(addr->flags & DEVADDR_EXTERNAL) && !keep)
-                       system_add_address(dev, addr);
-               addr->enabled = true;
+               if (!(a_new->flags & DEVADDR_EXTERNAL) && !keep)
+                       system_add_address(dev, a_new);
+               a_new->enabled = true;
        }
 }
 
index f6413ee016fe60a170179e407bb206675403a2e0..e983a840b1b9aaf24cc8e54357aa42d18d5ea5ac 100644 (file)
@@ -27,6 +27,9 @@ struct device_addr {
        enum device_addr_flags flags;
        bool enabled;
 
+       /* ipv4 only */
+       uint32_t broadcast;
+
        /* must be last */
        unsigned int mask;
        union if_addr addr;
diff --git a/proto.c b/proto.c
index 81469f99b6f43db6f356ad91ae6a96ff5ecaf957..c100735785c9652868e53f707744a4c48fd945a3 100644 (file)
--- a/proto.c
+++ b/proto.c
@@ -123,7 +123,8 @@ proto_parse_ip_addr_string(const char *str, bool v6, int mask)
 }
 
 static bool
-parse_addr(struct interface *iface, const char *str, bool v6, int mask, bool ext)
+parse_addr(struct interface *iface, const char *str, bool v6, int mask,
+          bool ext, uint32_t broadcast)
 {
        struct device_addr *addr;
 
@@ -133,6 +134,9 @@ parse_addr(struct interface *iface, const char *str, bool v6, int mask, bool ext
                return false;
        }
 
+       if (broadcast)
+               addr->broadcast = broadcast;
+
        if (ext)
                addr->flags |= DEVADDR_EXTERNAL;
 
@@ -141,7 +145,8 @@ parse_addr(struct interface *iface, const char *str, bool v6, int mask, bool ext
 }
 
 static int
-parse_address_option(struct interface *iface, struct blob_attr *attr, bool v6, int netmask, bool ext)
+parse_address_option(struct interface *iface, struct blob_attr *attr, bool v6,
+                    int netmask, bool ext, uint32_t broadcast)
 {
        struct blob_attr *cur;
        int n_addr = 0;
@@ -152,7 +157,8 @@ parse_address_option(struct interface *iface, struct blob_attr *attr, bool v6, i
                        return -1;
 
                n_addr++;
-               if (!parse_addr(iface, blobmsg_data(cur), v6, netmask, ext))
+               if (!parse_addr(iface, blobmsg_data(cur), v6, netmask, ext,
+                               broadcast))
                        return -1;
        }
 
@@ -188,6 +194,7 @@ proto_apply_ip_settings(struct interface *iface, struct blob_attr *attr, bool ex
        const char *error;
        unsigned int netmask = 32;
        int n_v4 = 0, n_v6 = 0;
+       uint32_t broadcast = 0;
 
        blobmsg_parse(proto_ip_attributes, __OPT_MAX, tb, blob_data(attr), blob_len(attr));
 
@@ -200,10 +207,12 @@ proto_apply_ip_settings(struct interface *iface, struct blob_attr *attr, bool ex
        }
 
        if (tb[OPT_IPADDR])
-               n_v4 = parse_address_option(iface, tb[OPT_IPADDR], false, netmask, ext);
+               n_v4 = parse_address_option(iface, tb[OPT_IPADDR], false,
+                       netmask, ext, broadcast);
 
        if (tb[OPT_IP6ADDR])
-               n_v6 = parse_address_option(iface, tb[OPT_IP6ADDR], true, netmask, ext);
+               n_v6 = parse_address_option(iface, tb[OPT_IP6ADDR], true,
+                       netmask, ext, 0);
 
        if (!n_v4 && !n_v6) {
                error = "NO_ADDRESS";
index 0a989b090a841565559ecb3aa7850a4abc676bb5..28029c1eb19011f8b7f3923c058704535bfd7250 100644 (file)
@@ -823,13 +823,8 @@ static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
 
        nlmsg_append(msg, &ifa, sizeof(ifa), 0);
        nla_put(msg, IFA_LOCAL, alen, &addr->addr);
-       if (v4) {
-               uint32_t mask = ~0;
-               uint32_t *a = (uint32_t *) &addr->addr;
-
-               mask >>= addr->mask;
-               nla_put_u32(msg, IFA_BROADCAST, *a | mask);
-       }
+       if (v4)
+               nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
 
        return system_rtnl_call(msg);
 }