interface-ip: mask out host bits in IPv4 route targets
[project/netifd.git] / device.c
index 24175564f8558df03aa54470ac72aaea23fc697c..9a9e24984018ce18885cbdeed44857f5ebbd68ce 100644 (file)
--- a/device.c
+++ b/device.c
 #include "system.h"
 #include "config.h"
 #include "wireless.h"
+#include "ubus.h"
 
 static struct list_head devtypes = LIST_HEAD_INIT(devtypes);
 static struct avl_tree devices;
+static struct blob_buf b;
 
 static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
        [DEV_ATTR_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING },
@@ -61,6 +63,7 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
        [DEV_ATTR_DROP_UNSOLICITED_NA] = { .name = "drop_unsolicited_na", .type = BLOBMSG_TYPE_BOOL },
        [DEV_ATTR_ARP_ACCEPT] = { .name = "arp_accept", .type = BLOBMSG_TYPE_BOOL },
        [DEV_ATTR_AUTH] = { .name = "auth", .type = BLOBMSG_TYPE_BOOL },
+       [DEV_ATTR_AUTH_VLAN] = { .name = "auth_vlan", BLOBMSG_TYPE_ARRAY },
        [DEV_ATTR_SPEED] = { .name = "speed", .type = BLOBMSG_TYPE_INT32 },
        [DEV_ATTR_DUPLEX] = { .name = "duplex", .type = BLOBMSG_TYPE_BOOL },
        [DEV_ATTR_VLAN] = { .name = "vlan", .type = BLOBMSG_TYPE_ARRAY },
@@ -540,6 +543,11 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
                s->autoneg = blobmsg_get_bool(cur);
                s->flags |= DEV_OPT_AUTONEG;
        }
+
+       cur = tb[DEV_ATTR_AUTH_VLAN];
+       free(dev->config_auth_vlans);
+       dev->config_auth_vlans = cur ? blob_memdup(cur) : NULL;
+
        device_set_extra_vlans(dev, tb[DEV_ATTR_VLAN]);
        device_set_disabled(dev, disabled);
 }
@@ -576,10 +584,31 @@ static int device_broadcast_cb(void *ctx, struct safe_list *list)
 
 void device_broadcast_event(struct device *dev, enum device_event ev)
 {
+       static const char * const event_names[] = {
+               [DEV_EVENT_ADD] = "add",
+               [DEV_EVENT_REMOVE] = "remove",
+               [DEV_EVENT_UP] = "up",
+               [DEV_EVENT_DOWN] = "down",
+               [DEV_EVENT_AUTH_UP] = "auth_up",
+               [DEV_EVENT_LINK_UP] = "link_up",
+               [DEV_EVENT_LINK_DOWN] = "link_down",
+               [DEV_EVENT_TOPO_CHANGE] = "topo_change",
+       };
        int dev_ev = ev;
 
        safe_list_for_each(&dev->aliases, device_broadcast_cb, &dev_ev);
        safe_list_for_each(&dev->users, device_broadcast_cb, &dev_ev);
+
+       if (ev >= ARRAY_SIZE(event_names) || !event_names[ev] || !dev->ifname[0])
+               return;
+
+       blob_buf_init(&b, 0);
+       blobmsg_add_string(&b, "name", dev->ifname);
+       blobmsg_add_u8(&b, "auth_status", dev->auth_status);
+       blobmsg_add_u8(&b, "present", dev->present);
+       blobmsg_add_u8(&b, "active", dev->active);
+       blobmsg_add_u8(&b, "link_active", dev->link_active);
+       netifd_ubus_device_notify(event_names[ev], b.head, -1);
 }
 
 static void
@@ -830,8 +859,16 @@ device_refresh_present(struct device *dev)
 }
 
 void
-device_set_auth_status(struct device *dev, bool value)
+device_set_auth_status(struct device *dev, bool value, struct blob_attr *vlans)
 {
+       if (!value)
+               vlans = NULL;
+       else if (!blob_attr_equal(vlans, dev->auth_vlans))
+               device_set_auth_status(dev, false, NULL);
+
+       free(dev->auth_vlans);
+       dev->auth_vlans = vlans ? blob_memdup(vlans) : NULL;
+
        if (dev->auth_status == value)
                return;
 
@@ -966,8 +1003,10 @@ static void
 device_free(struct device *dev)
 {
        __devlock++;
+       free(dev->auth_vlans);
        free(dev->config);
        device_cleanup(dev);
+       free(dev->config_auth_vlans);
        free(dev->extra_vlan);
        dev->type->free(dev);
        __devlock--;