summaryrefslogtreecommitdiff
path: root/interface-ip.c
diff options
context:
space:
mode:
authormeurisa <alexander.meuris@technicolor.com>2019-04-12 09:56:28 +0200
committerHans Dedecker <dedeckeh@gmail.com>2019-04-15 22:31:38 +0200
commit08989e46b9030671ce57b8872538d40e2ddcbbe0 (patch)
treec0119c3ca57b572adcfa6462d34411a6e0c2f0ac /interface-ip.c
parentbfd4de3666901070d805878e55b02417fef6277c (diff)
downloadnetifd-08989e46b9030671ce57b8872538d40e2ddcbbe0.tar.gz
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.c149
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);
}