summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2012-02-26 17:43:10 +0100
committerFelix Fietkau <nbd@openwrt.org>2012-02-26 17:43:10 +0100
commit73a32ab092ae32ec97e20b61512998c8411b8bd5 (patch)
treef69da571f77133096292198fbd6dec73013aff45
parent05c0ded29cf9dd7716528e61029886550ba1f7ab (diff)
move broadcast address handling to the core
-rw-r--r--interface-ip.c43
-rw-r--r--interface-ip.h3
-rw-r--r--proto.c19
-rw-r--r--system-linux.c9
4 files changed, 52 insertions, 22 deletions
diff --git a/interface-ip.c b/interface-ip.c
index 93e8723..7f10120 100644
--- a/interface-ip.c
+++ b/interface-ip.c
@@ -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;
}
}
diff --git a/interface-ip.h b/interface-ip.h
index f6413ee..e983a84 100644
--- a/interface-ip.h
+++ b/interface-ip.h
@@ -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 81469f9..c100735 100644
--- 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";
diff --git a/system-linux.c b/system-linux.c
index 0a989b0..28029c1 100644
--- a/system-linux.c
+++ b/system-linux.c
@@ -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);
}