From 73a32ab092ae32ec97e20b61512998c8411b8bd5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 26 Feb 2012 17:43:10 +0100 Subject: [PATCH] move broadcast address handling to the core --- interface-ip.c | 43 +++++++++++++++++++++++++++++++++---------- interface-ip.h | 3 +++ proto.c | 19 ++++++++++++++----- system-linux.c | 9 ++------- 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); } -- 2.25.1