[OpenWrt-Devel] [PATCH netifd] interface: add neighbor config support

Hans Dedecker dedeckeh at gmail.com
Sat Apr 13 08:12:14 EDT 2019


On Sat, Apr 13, 2019 at 11:17 AM Paul Oranje <por at oranjevos.nl> wrote:
>
>
> > Op 12 apr. 2019, om 09:56 heeft Alexander Meuris <meurisalexander at gmail.com> het volgende geschreven:
> >
> > From: meurisa <alexander.meuris at technicolor.com>
> >
> > 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
> Out of curiosity: what use-case is served with this change ?
Proxy ARP entries can be usefull in some VPN scenarios while static
ARP entries can be usefull for trouble shooting or if a device is
unable to learn a mac address dynamically whatever the reason may be
>
> >
> > 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 at gmail.com>
> > Signed-off-by: Hans Dedecker <dedeckeh at gmail.com>
> > ---
> > config.c                |  19 +++++-
> > interface-ip.c          | 149 +++++++++++++++++++++++++++++++++++++++++++++++-
> > interface-ip.h          |  20 ++++++-
> > interface.h             |   2 +
> > proto-shell.c           |  27 +++++++++
> > scripts/netifd-proto.sh |  58 +++++++++++++++++++
> > system-dummy.c          |  20 +++++++
> > system-linux.c          |  50 +++++++++++++++-
> > system.h                |   3 +
> > ubus.c                  |  45 +++++++++++++++
> > 10 files changed, 388 insertions(+), 5 deletions(-)
> >
> > diff --git a/config.c b/config.c
> > index be10379..843c53f 100644
> > --- a/config.c
> > +++ b/config.c
> > @@ -144,6 +144,17 @@ config_parse_route(struct uci_section *s, bool v6)
> > }
> >
> > static void
> > +config_parse_neighbor(struct uci_section *s, bool v6)
> > +{
> > +     void *neighbor;
> > +     blob_buf_init(&b,0);
> > +     neighbor = blobmsg_open_array(&b, "neighbor");
> > +     uci_to_blob(&b,s, &neighbor_attr_list);
> > +     blobmsg_close_array(&b, neighbor);
> > +     interface_ip_add_neighbor(NULL, blob_data(b.head), v6);
> > +}
> > +
> > +static void
> > config_parse_rule(struct uci_section *s, bool v6)
> > {
> >       void *rule;
> > @@ -251,7 +262,7 @@ config_init_interfaces(void)
> > }
> >
> > static void
> > -config_init_routes(void)
> > +config_init_ip(void)
> > {
> >       struct interface *iface;
> >       struct uci_element *e;
> > @@ -266,6 +277,10 @@ config_init_routes(void)
> >                       config_parse_route(s, false);
> >               else if (!strcmp(s->type, "route6"))
> >                       config_parse_route(s, true);
> > +             if (!strcmp(s->type, "neighbor"))
> > +                     config_parse_neighbor(s, false);
> > +             else if (!strcmp(s->type, "neighbor6"))
> > +                     config_parse_neighbor(s, true);
> >       }
> >
> >       vlist_for_each_element(&interfaces, iface, node)
> > @@ -417,7 +432,7 @@ config_init_all(void)
> >       device_reset_config();
> >       config_init_devices();
> >       config_init_interfaces();
> > -     config_init_routes();
> > +     config_init_ip();
> >       config_init_rules();
> >       config_init_globals();
> >       config_init_wireless();
> > diff --git a/interface-ip.c b/interface-ip.c
> > index 2a183ac..e996aaa 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;
> > @@ -628,6 +720,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)
> > @@ -1402,6 +1532,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;
> >
> > @@ -1447,7 +1578,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;
> >
> > @@ -1461,6 +1591,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)
> > @@ -1489,6 +1632,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
> > @@ -1499,6 +1643,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();
> > }
> >
> > @@ -1511,6 +1656,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);
> > }
> >
> > @@ -1522,6 +1668,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);
> > }
> > diff --git a/interface-ip.h b/interface-ip.h
> > index 21c6e9b..3f99eb9 100644
> > --- a/interface-ip.h
> > +++ b/interface-ip.h
> > @@ -48,6 +48,9 @@ enum device_addr_flags {
> >
> >       /* route overrides the default route type */
> >       DEVROUTE_TYPE           = (1 << 10),
> > +
> > +     /* neighbor mac address */
> > +     DEVNEIGH_MAC            = (1 << 11),
> > };
> >
> > union if_addr {
> > @@ -106,6 +109,20 @@ struct device_route {
> >       union if_addr source;
> > };
> >
> > +struct device_neighbor {
> > +     struct vlist_node node;
> > +
> > +     bool failed;
> > +     bool proxy;
> > +     bool keep;
> > +     bool enabled;
> > +     bool router;
> > +
> > +     uint8_t macaddr[6];
> > +     enum device_addr_flags flags;
> > +     union if_addr addr;
> > +};
> > +
> > struct device_addr {
> >       struct vlist_node node;
> >       bool enabled;
> > @@ -150,6 +167,7 @@ struct dns_search_domain {
> > };
> >
> > extern const struct uci_blob_param_list route_attr_list;
> > +extern const struct uci_blob_param_list neighbor_attr_list;
> > extern struct list_head prefixes;
> >
> > void interface_ip_init(struct interface *iface);
> > @@ -158,7 +176,7 @@ void interface_add_dns_search_list(struct interface_ip_settings *ip, struct blob
> > void interface_write_resolv_conf(void);
> >
> > void interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6);
> > -
> > +void interface_ip_add_neighbor(struct interface *iface, struct blob_attr *attr, bool v6);
> > void interface_ip_update_start(struct interface_ip_settings *ip);
> > void interface_ip_update_complete(struct interface_ip_settings *ip);
> > void interface_ip_flush(struct interface_ip_settings *ip);
> > diff --git a/interface.h b/interface.h
> > index 6f10484..3c0c9ed 100644
> > --- a/interface.h
> > +++ b/interface.h
> > @@ -84,6 +84,7 @@ struct interface_ip_settings {
> >       struct vlist_tree addr;
> >       struct vlist_tree route;
> >       struct vlist_tree prefix;
> > +     struct vlist_tree neighbor;
> >
> >       struct vlist_simple_tree dns_servers;
> >       struct vlist_simple_tree dns_search;
> > @@ -150,6 +151,7 @@ struct interface {
> >       struct interface_ip_settings proto_ip;
> >       struct interface_ip_settings config_ip;
> >       struct vlist_tree host_routes;
> > +     struct vlist_tree host_neighbors;
> >
> >       int metric;
> >       int dns_metric;
> > diff --git a/proto-shell.c b/proto-shell.c
> > index 47a9568..07ec21a 100644
> > --- a/proto-shell.c
> > +++ b/proto-shell.c
> > @@ -414,6 +414,23 @@ proto_shell_parse_route_list(struct interface *iface, struct blob_attr *attr,
> > }
> >
> > static void
> > +proto_shell_parse_neighbor_list(struct interface *iface, struct blob_attr *attr,
> > +                             bool v6)
> > +{
> > +     struct blob_attr *cur;
> > +     int rem;
> > +
> > +     blobmsg_for_each_attr(cur, attr, rem) {
> > +             if (blobmsg_type(cur) != BLOBMSG_TYPE_TABLE) {
> > +                     DPRINTF("Ignore wrong neighbor type: %d\n", blobmsg_type(cur));
> > +                     continue;
> > +             }
> > +
> > +             interface_ip_add_neighbor(iface, cur, v6);
> > +     }
> > +}
> > +
> > +static void
> > proto_shell_parse_data(struct interface *iface, struct blob_attr *attr)
> > {
> >       struct blob_attr *cur;
> > @@ -456,6 +473,8 @@ enum {
> >       NOTIFY_HOST,
> >       NOTIFY_DNS,
> >       NOTIFY_DNS_SEARCH,
> > +     NOTIFY_NEIGHBORS,
> > +     NOTIFY_NEIGHBORS6,
> >       __NOTIFY_LAST
> > };
> >
> > @@ -477,6 +496,8 @@ static const struct blobmsg_policy notify_attr[__NOTIFY_LAST] = {
> >       [NOTIFY_HOST] = { .name = "host", .type = BLOBMSG_TYPE_STRING },
> >       [NOTIFY_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY },
> >       [NOTIFY_DNS_SEARCH] = { .name = "dns_search", .type = BLOBMSG_TYPE_ARRAY },
> > +     [NOTIFY_NEIGHBORS]= {.name = "neighbor", .type = BLOBMSG_TYPE_ARRAY},
> > +     [NOTIFY_NEIGHBORS6]= {.name = "neighbor6", .type = BLOBMSG_TYPE_ARRAY},
> > };
> >
> > static int
> > @@ -546,6 +567,12 @@ proto_shell_update_link(struct proto_shell_state *state, struct blob_attr *data,
> >       if ((cur = tb[NOTIFY_ROUTES6]) != NULL)
> >               proto_shell_parse_route_list(state->proto.iface, cur, true);
> >
> > +     if ((cur = tb[NOTIFY_NEIGHBORS]) != NULL)
> > +             proto_shell_parse_neighbor_list(state->proto.iface, cur, false);
> > +
> > +     if ((cur = tb[NOTIFY_NEIGHBORS6]) != NULL)
> > +             proto_shell_parse_neighbor_list(state->proto.iface, cur, true);
> > +
> >       if ((cur = tb[NOTIFY_DNS]))
> >               interface_add_dns_server_list(&iface->proto_ip, cur);
> >
> > diff --git a/scripts/netifd-proto.sh b/scripts/netifd-proto.sh
> > index 31df91f..87d337d 100644
> > --- a/scripts/netifd-proto.sh
> > +++ b/scripts/netifd-proto.sh
> > @@ -64,6 +64,8 @@ proto_init_update() {
> >       PROTO_PREFIX6=
> >       PROTO_DNS=
> >       PROTO_DNS_SEARCH=
> > +     PROTO_NEIGHBOR=
> > +     PROTO_NEIGHBOR6=
> >       json_init
> >       json_add_int action 0
> >       [ -n "$ifname" -a "*" != "$ifname" ] && json_add_string "ifname" "$ifname"
> > @@ -133,6 +135,23 @@ proto_add_ipv6_address() {
> >       append PROTO_IP6ADDR "$address/$mask/$preferred/$valid/$offlink/$class"
> > }
> >
> > +proto_add_ipv4_neighbor(){
> > +     local address="$1"
> > +     local mac="$2"
> > +     local proxy="$3"
> > +
> > +     append PROTO_NEIGHBOR "$address/$mac/$proxy"
> > +}
> > +
> > +proto_add_ipv6_neighbor(){
> > +     local address="$1"
> > +     local mac="$2"
> > +     local proxy="$3"
> > +     local router="$4"
> > +
> > +     append PROTO_NEIGHBOR6 "$address/$mac/$proxy/$router"
> > +}
> > +
> > proto_add_ipv4_route() {
> >       local target="$1"
> >       local mask="$2"
> > @@ -218,6 +237,43 @@ _proto_push_string() {
> >       json_add_string "" "$1"
> > }
> >
> > +_proto_push_ipv4_neighbor(){
> > +     local str="$1"
> > +     local address mac proxy
> > +
> > +     address="${str%%/*}"
> > +     str="${str#*/}"
> > +     mac="${str%%/*}"
> > +     str="${str#*/}"
> > +     proxy="${str%%/*}"
> > +
> > +     json_add_object ""
> > +     json_add_string ipaddr "$address"
> > +     [ -n "$mac" ] && json_add_string mac "$mac"
> > +     [ -n "$proxy" ] && json_add_boolean proxy "$proxy"
> > +     json_close_object
> > +}
> > +
> > +_proto_push_ipv6_neighbor(){
> > +     local str="$1"
> > +     local address mac proxy router
> > +
> > +     address="${str%%/*}"
> > +     str="${str#*/}"
> > +     mac="${str%%/*}"
> > +     str="${str#*/}"
> > +     proxy="${str%%/*}"
> > +     str="${str#*/}"
> > +     router="${str%%/*}"
> > +
> > +     json_add_object ""
> > +     json_add_string ipaddr "$address"
> > +     [ -n "$mac" ] && json_add_string mac "$mac"
> > +     [ -n "$proxy" ] && json_add_boolean proxy "$proxy"
> > +     [ -n "$router" ] && json_add_boolean router "$router"
> > +     json_close_object
> > +}
> > +
> > _proto_push_route() {
> >       local str="$1";
> >       local target="${str%%/*}"
> > @@ -277,6 +333,8 @@ proto_send_update() {
> >       _proto_push_array "ip6prefix" "$PROTO_PREFIX6" _proto_push_string
> >       _proto_push_array "dns" "$PROTO_DNS" _proto_push_string
> >       _proto_push_array "dns_search" "$PROTO_DNS_SEARCH" _proto_push_string
> > +     _proto_push_array "neighbor" "$PROTO_NEIGHBOR" _proto_push_ipv4_neighbor
> > +     _proto_push_array "neighbor6" "$PROTO_NEIGHBOR6" _proto_push_ipv6_neighbor
> >       _proto_notify "$interface"
> > }
> >
> > diff --git a/system-dummy.c b/system-dummy.c
> > index 11c8ccc..58fd2d0 100644
> > --- a/system-dummy.c
> > +++ b/system-dummy.c
> > @@ -181,6 +181,26 @@ static int system_route_msg(struct device *dev, struct device_route *route, cons
> >       return 0;
> > }
> >
> > +static int system_neighbor_msg(struct device *dev, struct device_neighbor *neighbor, const char *type)
> > +{
> > +     char addr[64];
> > +     int af = system_get_addr_family(neighbor->flags);
> > +     inet_ntop(af, &neighbor->addr.in , addr, sizeof(addr));
> > +
> > +     D(SYSTEM, "neigh %s %s%s%s %s\n", type, addr, neighbor->proxy ? "proxy " : "",
> > +             (neighbor->flags & DEVNEIGH_MAC) ? format_macaddr(neighbor->macaddr) : "",
> > +             neighbor->router ? "router": "");
> > +}
> > +int system_add_neighbor(struct device *dev, struct device_neighbor *neighbor)
> > +{
> > +     return system_neighbor_msg(dev, neighbor, "add");
> > +}
> > +
> > +int system_del_neighbor(struct device *dev, struct device_neighbor *neighbor)
> > +{
> > +     return system_neighbor_msg(dev, neighbor, "del");
> > +}
> > +
> > int system_add_route(struct device *dev, struct device_route *route)
> > {
> >       return system_route_msg(dev, route, "add");
> > diff --git a/system-linux.c b/system-linux.c
> > index 82e9928..6a0105e 100644
> > --- a/system-linux.c
> > +++ b/system-linux.c
> > @@ -31,6 +31,7 @@
> > #include <netinet/in.h>
> >
> > #include <linux/rtnetlink.h>
> > +#include <linux/neighbour.h>
> > #include <linux/sockios.h>
> > #include <linux/ip.h>
> > #include <linux/if_addr.h>
> > @@ -1023,8 +1024,8 @@ void system_if_clear_state(struct device *dev)
> > {
> >       static char buf[256];
> >       char *bridge;
> > -
> >       device_set_ifindex(dev, system_if_resolve(dev));
> > +
> >       if (dev->external || !dev->ifindex)
> >               return;
> >
> > @@ -1046,6 +1047,8 @@ void system_if_clear_state(struct device *dev)
> >       system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
> >       system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
> >       system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
> > +     system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET);
> > +     system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET6);
> >       system_set_disable_ipv6(dev, "0");
> > }
> >
> > @@ -1930,6 +1933,51 @@ int system_del_address(struct device *dev, struct device_addr *addr)
> >       return system_addr(dev, addr, RTM_DELADDR);
> > }
> >
> > +static int system_neigh(struct device *dev, struct device_neighbor *neighbor, int cmd)
> > +{
> > +     int alen = ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
> > +     unsigned int flags = 0;
> > +     struct ndmsg ndm = {
> > +             .ndm_family = (alen == 4) ? AF_INET : AF_INET6,
> > +             .ndm_ifindex = dev->ifindex,
> > +             .ndm_state = NUD_PERMANENT,
> > +             .ndm_flags = (neighbor->proxy ? NTF_PROXY : 0) | (neighbor->router ? NTF_ROUTER : 0),
> > +     };
> > +     struct nl_msg *msg;
> > +
> > +     if (!dev)
> > +             return 1;
> > +
> > +     if (cmd == RTM_NEWNEIGH)
> > +             flags |= NLM_F_CREATE | NLM_F_REPLACE;
> > +
> > +     msg = nlmsg_alloc_simple(cmd, flags);
> > +
> > +     if (!msg)
> > +             return -1;
> > +
> > +     nlmsg_append(msg, &ndm, sizeof(ndm), 0);
> > +
> > +     nla_put(msg, NDA_DST, alen, &neighbor->addr);
> > +     if (neighbor->flags & DEVNEIGH_MAC)
> > +             nla_put(msg, NDA_LLADDR, sizeof(neighbor->macaddr), &neighbor->macaddr);
> > +
> > +
> > +     return system_rtnl_call(msg);
> > +}
> > +
> > +int system_add_neighbor(struct device *dev, struct device_neighbor *neighbor)
> > +{
> > +     return system_neigh(dev, neighbor, RTM_NEWNEIGH);
> > +}
> > +
> > +int system_del_neighbor(struct device *dev, struct device_neighbor *neighbor)
> > +{
> > +     int rval = system_neigh(dev, neighbor, RTM_DELNEIGH);
> > +     netifd_log_message(L_NOTICE,"return delete %d", rval);
> > +     return rval;
> > +}
> > +
> > static int system_rt(struct device *dev, struct device_route *route, int cmd)
> > {
> >       int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
> > diff --git a/system.h b/system.h
> > index 4d4cf6e..9fefcae 100644
> > --- a/system.h
> > +++ b/system.h
> > @@ -213,6 +213,9 @@ int system_add_route(struct device *dev, struct device_route *route);
> > int system_del_route(struct device *dev, struct device_route *route);
> > int system_flush_routes(void);
> >
> > +int system_add_neighbor(struct device *dev, struct device_neighbor * neighbor);
> > +int system_del_neighbor(struct device *dev, struct device_neighbor * neighbor);
> > +
> > bool system_resolve_rt_type(const char *type, unsigned int *id);
> > bool system_resolve_rt_proto(const char *type, unsigned int *id);
> > bool system_resolve_rt_table(const char *name, unsigned int *id);
> > diff --git a/ubus.c b/ubus.c
> > index 32bc1a3..0e86b61 100644
> > --- a/ubus.c
> > +++ b/ubus.c
> > @@ -459,6 +459,43 @@ interface_ip_dump_address_list(struct interface_ip_settings *ip, bool v6, bool e
> > }
> >
> > static void
> > +interface_ip_dump_neighbor_list(struct interface_ip_settings *ip, bool enabled)
> > +{
> > +     struct device_neighbor *neighbor;
> > +     int buflen = 128;
> > +     char *buf;
> > +     void *r;
> > +     int af;
> > +
> > +     vlist_for_each_element(&ip->neighbor, neighbor, node) {
> > +             if (neighbor->enabled != enabled)
> > +                     continue;
> > +
> > +             if ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4)
> > +                     af = AF_INET;
> > +             else
> > +                     af = AF_INET6;
> > +
> > +             r = blobmsg_open_table(&b, NULL);
> > +
> > +             if (neighbor->flags & DEVNEIGH_MAC)
> > +                     blobmsg_add_string(&b, "mac", format_macaddr(neighbor->macaddr));
> > +
> > +             buf = blobmsg_alloc_string_buffer(&b , "address", buflen);
> > +             inet_ntop(af, &neighbor->addr, buf, buflen);
> > +             blobmsg_add_string_buffer(&b);
> > +
> > +             if (neighbor->proxy)
> > +                     blobmsg_add_u32(&b, "proxy", neighbor->proxy);
> > +
> > +             if (neighbor->router)
> > +                     blobmsg_add_u32(&b, "router", neighbor->router);
> > +
> > +             blobmsg_close_table(&b, r);
> > +     }
> > +}
> > +
> > +static void
> > interface_ip_dump_route_list(struct interface_ip_settings *ip, bool enabled)
> > {
> >       struct device_route *route;
> > @@ -737,6 +774,10 @@ netifd_dump_status(struct interface *iface)
> >               interface_ip_dump_dns_search_list(&iface->config_ip, true);
> >               interface_ip_dump_dns_search_list(&iface->proto_ip, true);
> >               blobmsg_close_array(&b, a);
> > +             a = blobmsg_open_array(&b, "neighbors");
> > +             interface_ip_dump_neighbor_list(&iface->config_ip, true);
> > +             interface_ip_dump_neighbor_list(&iface->proto_ip, true);
> > +             blobmsg_close_array(&b, a);
> >
> >               inactive = blobmsg_open_table(&b, "inactive");
> >               a = blobmsg_open_array(&b, "ipv4-address");
> > @@ -759,6 +800,10 @@ netifd_dump_status(struct interface *iface)
> >               interface_ip_dump_dns_search_list(&iface->config_ip, false);
> >               interface_ip_dump_dns_search_list(&iface->proto_ip, false);
> >               blobmsg_close_array(&b, a);
> > +             a = blobmsg_open_array(&b, "neighbors");
> > +             interface_ip_dump_neighbor_list(&iface->config_ip, false);
> > +             interface_ip_dump_neighbor_list(&iface->proto_ip, false);
> > +             blobmsg_close_array(&b, a);
> >               blobmsg_close_table(&b, inactive);
> >       }
> >
> > --
> > 2.7.4
> >
> >
> > _______________________________________________
> > openwrt-devel mailing list
> > openwrt-devel at lists.openwrt.org
> > https://lists.openwrt.org/mailman/listinfo/openwrt-devel
>

_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list