diff options
author | meurisa <alexander.meuris@technicolor.com> | 2019-04-12 09:56:28 +0200 |
---|---|---|
committer | Hans Dedecker <dedeckeh@gmail.com> | 2019-04-15 22:31:38 +0200 |
commit | 08989e46b9030671ce57b8872538d40e2ddcbbe0 (patch) | |
tree | c0119c3ca57b572adcfa6462d34411a6e0c2f0ac /interface-ip.c | |
parent | bfd4de3666901070d805878e55b02417fef6277c (diff) |
interface: add neighbor config support
The neighbor or neighbor6 network section makes neighbours
configurable via UCI or proto shell handlers. It allows to
install neighbor proxy entries or static neighbor entries
The neighbor or neighbor6 section has the following types:
interface : declares the logical OpenWrt interface
ipaddr : the ip address of the neighbor
mac : the mac address of the neighbor
proxy : specifies whether the neighbor ia a proxy
entry (can be 1 or 0)
router : specifies whether the neighbor is a router
(can be 1 or 0)
Signed-off-by: Alexander Meuris <meurisalexander@gmail.com>
Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
Diffstat (limited to 'interface-ip.c')
-rw-r--r-- | interface-ip.c | 149 |
1 files changed, 148 insertions, 1 deletions
diff --git a/interface-ip.c b/interface-ip.c index 83f1dfa..22c21d7 100644 --- a/interface-ip.c +++ b/interface-ip.c @@ -20,6 +20,10 @@ #include <arpa/inet.h> #include <netinet/in.h> +#ifdef linux +#include <netinet/ether.h> +#endif + #include "netifd.h" #include "device.h" #include "interface.h" @@ -64,6 +68,28 @@ const struct uci_blob_param_list route_attr_list = { .params = route_attr, }; +enum { + NEIGHBOR_INTERFACE, + NEIGHBOR_ADDRESS, + NEIGHBOR_MAC, + NEIGHBOR_PROXY, + NEIGHBOR_ROUTER, + __NEIGHBOR_MAX +}; + +static const struct blobmsg_policy neighbor_attr[__NEIGHBOR_MAX]={ + [NEIGHBOR_INTERFACE]= { .name = "interface", .type = BLOBMSG_TYPE_STRING}, + [NEIGHBOR_ADDRESS]= { .name = "ipaddr", .type = BLOBMSG_TYPE_STRING}, + [NEIGHBOR_MAC]= { .name = "mac", .type = BLOBMSG_TYPE_STRING}, + [NEIGHBOR_PROXY]= { .name = "proxy", .type = BLOBMSG_TYPE_BOOL}, + [NEIGHBOR_ROUTER]= {.name = "router", .type = BLOBMSG_TYPE_BOOL}, +}; + +const struct uci_blob_param_list neighbor_attr_list = { + .n_params = __NEIGHBOR_MAX, + .params = neighbor_attr, +}; + struct list_head prefixes = LIST_HEAD_INIT(prefixes); static struct device_prefix *ula_prefix = NULL; @@ -299,6 +325,64 @@ interface_set_route_info(struct interface *iface, struct device_route *route) } void +interface_ip_add_neighbor(struct interface *iface, struct blob_attr *attr, bool v6) +{ + struct interface_ip_settings *ip; + struct blob_attr *tb[__NEIGHBOR_MAX], *cur; + struct device_neighbor *neighbor; + int af = v6 ? AF_INET6: AF_INET; + struct ether_addr *ea; + + blobmsg_parse(neighbor_attr, __NEIGHBOR_MAX, tb, blobmsg_data(attr), blobmsg_data_len(attr)); + + if (!iface) { + if ((cur = tb[NEIGHBOR_INTERFACE]) == NULL) + return; + + iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node); + + if (!iface) + return; + + ip = &iface->config_ip; + } else + ip = &iface->proto_ip; + + neighbor = calloc(1,sizeof(*neighbor)); + neighbor->flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4; + + if (!neighbor) + return; + + if ((cur = tb[NEIGHBOR_ADDRESS]) != NULL){ + if (!inet_pton(af, blobmsg_data(cur), &neighbor->addr)) + goto error; + } else + goto error; + + if ((cur = tb[NEIGHBOR_MAC]) != NULL) { + neighbor->flags |= DEVNEIGH_MAC; + ea = ether_aton(blobmsg_data(cur)); + if (!ea) + goto error; + + memcpy(neighbor->macaddr, ea, 6); + } + + if ((cur = tb[NEIGHBOR_PROXY]) != NULL) + neighbor->proxy = blobmsg_get_bool(cur); + + if ((cur = tb[NEIGHBOR_ROUTER]) != NULL) + neighbor->router = blobmsg_get_bool(cur); + + vlist_add(&ip->neighbor, &neighbor->node, neighbor); + return; + +error: + free(neighbor); +} + +void interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6) { struct interface_ip_settings *ip; @@ -429,6 +513,14 @@ addr_cmp(const void *k1, const void *k2, void *ptr) } static int +neighbor_cmp(const void *k1, const void *k2, void *ptr) +{ + const struct device_neighbor *n1 = k1, *n2 = k2; + + return memcmp(&n1->addr, &n2->addr, sizeof(n2->addr)); +} + +static int route_cmp(const void *k1, const void *k2, void *ptr) { const struct device_route *r1 = k1, *r2 = k2; @@ -625,6 +717,44 @@ enable_route(struct interface_ip_settings *ip, struct device_route *route) } static void +interface_update_proto_neighbor(struct vlist_tree *tree, + struct vlist_node * node_new, + struct vlist_node *node_old) +{ + struct device *dev; + struct device_neighbor *neighbor_old, *neighbor_new; + struct interface_ip_settings *ip; + bool keep = false; + + ip = container_of(tree, struct interface_ip_settings, neighbor); + dev = ip->iface->l3_dev.dev; + + neighbor_old = container_of(node_old, struct device_neighbor, node); + neighbor_new = container_of(node_new, struct device_neighbor, node); + + if (node_old && node_new) { + keep = (!memcmp(neighbor_old->macaddr, neighbor_new->macaddr, sizeof(neighbor_old->macaddr)) && + (neighbor_old->proxy == neighbor_new->proxy) && + (neighbor_old->router == neighbor_new->router)); + } + + if (node_old) { + if (!keep && neighbor_old->enabled) + system_del_neighbor(dev, neighbor_old); + + free(neighbor_old); + } + + if (node_new) { + if (!keep && ip->enabled) + if (system_add_neighbor(dev, neighbor_new)) + neighbor_new->failed = true; + + neighbor_new->enabled = ip->enabled; + } +} + +static void interface_update_proto_route(struct vlist_tree *tree, struct vlist_node *node_new, struct vlist_node *node_old) @@ -1394,6 +1524,7 @@ void interface_ip_set_enabled(struct interface_ip_settings *ip, bool enabled) { struct device_addr *addr; struct device_route *route; + struct device_neighbor *neighbor; struct device *dev; struct interface *iface; @@ -1439,7 +1570,6 @@ void interface_ip_set_enabled(struct interface_ip_settings *ip, bool enabled) if (!enable_route(ip, route)) _enabled = false; - if (route->enabled == _enabled) continue; @@ -1453,6 +1583,19 @@ void interface_ip_set_enabled(struct interface_ip_settings *ip, bool enabled) route->enabled = _enabled; } + vlist_for_each_element(&ip->neighbor, neighbor, node) { + if (neighbor->enabled == enabled) + continue; + + if (enabled) { + if(system_add_neighbor(dev, neighbor)) + neighbor->failed = true; + } else + system_del_neighbor(dev, neighbor); + + neighbor->enabled = enabled; + } + struct device_prefix *c; struct device_prefix_assignment *a; list_for_each_entry(c, &prefixes, head) @@ -1481,6 +1624,7 @@ interface_ip_update_start(struct interface_ip_settings *ip) vlist_update(&ip->route); vlist_update(&ip->addr); vlist_update(&ip->prefix); + vlist_update(&ip->neighbor); } void @@ -1491,6 +1635,7 @@ interface_ip_update_complete(struct interface_ip_settings *ip) vlist_flush(&ip->route); vlist_flush(&ip->addr); vlist_flush(&ip->prefix); + vlist_flush(&ip->neighbor); interface_write_resolv_conf(); } @@ -1503,6 +1648,7 @@ interface_ip_flush(struct interface_ip_settings *ip) vlist_simple_flush_all(&ip->dns_search); vlist_flush_all(&ip->route); vlist_flush_all(&ip->addr); + vlist_flush_all(&ip->neighbor); vlist_flush_all(&ip->prefix); } @@ -1514,6 +1660,7 @@ __interface_ip_init(struct interface_ip_settings *ip, struct interface *iface) vlist_simple_init(&ip->dns_search, struct dns_search_domain, node); vlist_simple_init(&ip->dns_servers, struct dns_server, node); vlist_init(&ip->route, route_cmp, interface_update_proto_route); + vlist_init(&ip->neighbor, neighbor_cmp, interface_update_proto_neighbor); vlist_init(&ip->addr, addr_cmp, interface_update_proto_addr); vlist_init(&ip->prefix, prefix_cmp, interface_update_prefix); } |