X-Git-Url: http://git.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=device.c;h=26254cc2eb902a9b7b7a2aef97d998fbe3edbeff;hp=43881e5f71a7cfe74350b20394f7e4b9b29aa8dd;hb=62e3cb52941032e13a8ad421454b9bc93382ef75;hpb=abf52371db75eb449f12209ca1b7ffaa9d2baa22 diff --git a/device.c b/device.c index 43881e5..26254cc 100644 --- a/device.c +++ b/device.c @@ -18,11 +18,6 @@ #include #include -#include - -#ifdef linux -#include -#endif #include @@ -32,7 +27,6 @@ static struct list_head devtypes = LIST_HEAD_INIT(devtypes); static struct avl_tree devices; -static bool default_ps = true; static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = { [DEV_ATTR_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING }, @@ -42,6 +36,7 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = { [DEV_ATTR_TXQUEUELEN] = { .name = "txqueuelen", .type = BLOBMSG_TYPE_INT32 }, [DEV_ATTR_ENABLED] = { .name = "enabled", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_IPV6] = { .name = "ipv6", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_IP6SEGMENTROUTING] = { .name = "ip6segmentrouting", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_PROMISC] = { .name = "promisc", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_RPFILTER] = { .name = "rpfilter", .type = BLOBMSG_TYPE_STRING }, [DEV_ATTR_ACCEPTLOCAL] = { .name = "acceptlocal", .type = BLOBMSG_TYPE_BOOL }, @@ -49,8 +44,6 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = { [DEV_ATTR_MLDVERSION] = { .name = "mldversion", .type = BLOBMSG_TYPE_INT32 }, [DEV_ATTR_NEIGHREACHABLETIME] = { .name = "neighreachabletime", .type = BLOBMSG_TYPE_INT32 }, [DEV_ATTR_NEIGHGCSTALETIME] = { .name = "neighgcstaletime", .type = BLOBMSG_TYPE_INT32 }, - [DEV_ATTR_RPS] = { .name = "rps", .type = BLOBMSG_TYPE_BOOL }, - [DEV_ATTR_XPS] = { .name = "xps", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_DADTRANSMITS] = { .name = "dadtransmits", .type = BLOBMSG_TYPE_INT32 }, [DEV_ATTR_MULTICAST_TO_UNICAST] = { .name = "multicast_to_unicast", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_MULTICAST_ROUTER] = { .name = "multicast_router", .type = BLOBMSG_TYPE_INT32 }, @@ -59,6 +52,14 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = { [DEV_ATTR_LEARNING] = { .name ="learning", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_UNICAST_FLOOD] = { .name ="unicast_flood", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_SENDREDIRECTS] = { .name = "sendredirects", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_NEIGHLOCKTIME] = { .name = "neighlocktime", .type = BLOBMSG_TYPE_INT32 }, + [DEV_ATTR_ISOLATE] = { .name = "isolate", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_DROP_V4_UNICAST_IN_L2_MULTICAST] = { .name = "drop_v4_unicast_in_l2_multicast", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_DROP_V6_UNICAST_IN_L2_MULTICAST] = { .name = "drop_v6_unicast_in_l2_multicast", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_DROP_GRATUITOUS_ARP] = { .name = "drop_gratuitous_arp", .type = BLOBMSG_TYPE_BOOL }, + [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 }, }; const struct uci_blob_param_list device_attr_list = { @@ -83,9 +84,6 @@ int device_type_add(struct device_type *devtype) return 0; } -/* Retrieve the device type for the given name. If 'bridge' is true, the type - * must have bridge capabilities - */ struct device_type * device_type_get(const char *tname) { @@ -110,6 +108,31 @@ void device_unlock(void) device_free_unused(NULL); } +static int device_vlan_len(struct kvlist *kv, const void *data) +{ + return sizeof(unsigned int); +} + +void device_vlan_update(bool done) +{ + struct device *dev; + + avl_for_each_element(&devices, dev, avl) { + if (!dev->vlans.update) + continue; + + if (!done) { + if (dev->vlan_aliases.get_len) + kvlist_free(&dev->vlan_aliases); + else + kvlist_init(&dev->vlan_aliases, device_vlan_len); + vlist_update(&dev->vlans); + } else { + vlist_flush(&dev->vlans); + } + } +} + static int set_device_state(struct device *dev, bool state) { if (state) { @@ -119,10 +142,17 @@ static int set_device_state(struct device *dev, bool state) if (!dev->ifindex) return -1; + system_if_get_settings(dev, &dev->orig_settings); + /* Only keep orig settings based on what needs to be set */ + dev->orig_settings.valid_flags = dev->orig_settings.flags; + dev->orig_settings.flags &= dev->settings.flags; + system_if_apply_settings(dev, &dev->settings, dev->settings.flags); + system_if_up(dev); - } - else + } else { system_if_down(dev); + system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags); + } return 0; } @@ -189,7 +219,7 @@ struct device_type simple_device_type = { .free = simple_device_free, }; -static void +void device_merge_settings(struct device *dev, struct device_settings *n) { struct device_settings *os = &dev->orig_settings; @@ -201,9 +231,10 @@ device_merge_settings(struct device *dev, struct device_settings *n) n->txqueuelen = s->flags & DEV_OPT_TXQUEUELEN ? s->txqueuelen : os->txqueuelen; memcpy(n->macaddr, - (s->flags & DEV_OPT_MACADDR ? s->macaddr : os->macaddr), + (s->flags & (DEV_OPT_MACADDR|DEV_OPT_DEFAULT_MACADDR) ? s->macaddr : os->macaddr), sizeof(n->macaddr)); n->ipv6 = s->flags & DEV_OPT_IPV6 ? s->ipv6 : os->ipv6; + n->ip6segmentrouting = s->flags & DEV_OPT_IP6SEGMENTROUTING ? s->ip6segmentrouting : os->ip6segmentrouting; n->promisc = s->flags & DEV_OPT_PROMISC ? s->promisc : os->promisc; n->rpfilter = s->flags & DEV_OPT_RPFILTER ? s->rpfilter : os->rpfilter; n->acceptlocal = s->flags & DEV_OPT_ACCEPTLOCAL ? s->acceptlocal : os->acceptlocal; @@ -217,6 +248,8 @@ device_merge_settings(struct device *dev, struct device_settings *n) s->neigh4gcstaletime : os->neigh4gcstaletime; n->neigh6gcstaletime = s->flags & DEV_OPT_NEIGHGCSTALETIME ? s->neigh6gcstaletime : os->neigh6gcstaletime; + n->neigh4locktime = s->flags & DEV_OPT_NEIGHLOCKTIME ? + s->neigh4locktime : os->neigh4locktime; n->dadtransmits = s->flags & DEV_OPT_DADTRANSMITS ? s->dadtransmits : os->dadtransmits; n->multicast = s->flags & DEV_OPT_MULTICAST ? @@ -228,6 +261,17 @@ device_merge_settings(struct device *dev, struct device_settings *n) n->unicast_flood = s->unicast_flood; n->sendredirects = s->flags & DEV_OPT_SENDREDIRECTS ? s->sendredirects : os->sendredirects; + n->drop_v4_unicast_in_l2_multicast = s->flags & DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST ? + s->drop_v4_unicast_in_l2_multicast : os->drop_v4_unicast_in_l2_multicast; + n->drop_v6_unicast_in_l2_multicast = s->flags & DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST ? + s->drop_v6_unicast_in_l2_multicast : os->drop_v6_unicast_in_l2_multicast; + n->drop_gratuitous_arp = s->flags & DEV_OPT_DROP_GRATUITOUS_ARP ? + s->drop_gratuitous_arp : os->drop_gratuitous_arp; + n->drop_unsolicited_na = s->flags & DEV_OPT_DROP_UNSOLICITED_NA ? + s->drop_unsolicited_na : os->drop_unsolicited_na; + n->arp_accept = s->flags & DEV_OPT_ARP_ACCEPT ? + s->arp_accept : os->arp_accept; + n->auth = s->flags & DEV_OPT_AUTH ? s->auth : os->auth; n->flags = s->flags | os->flags | os->valid_flags; } @@ -271,6 +315,11 @@ device_init_settings(struct device *dev, struct blob_attr **tb) s->flags |= DEV_OPT_IPV6; } + if ((cur = tb[DEV_ATTR_IP6SEGMENTROUTING])) { + s->ip6segmentrouting = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_IP6SEGMENTROUTING; + } + if ((cur = tb[DEV_ATTR_PROMISC])) { s->promisc = blobmsg_get_bool(cur); s->flags |= DEV_OPT_PROMISC; @@ -314,19 +363,10 @@ device_init_settings(struct device *dev, struct blob_attr **tb) s->flags |= DEV_OPT_NEIGHGCSTALETIME; } - if ((cur = tb[DEV_ATTR_RPS])) { - s->rps = blobmsg_get_bool(cur); - s->flags |= DEV_OPT_RPS; + if ((cur = tb[DEV_ATTR_NEIGHLOCKTIME])) { + s->neigh4locktime = blobmsg_get_u32(cur); + s->flags |= DEV_OPT_NEIGHLOCKTIME; } - else - s->rps = default_ps; - - if ((cur = tb[DEV_ATTR_XPS])) { - s->xps = blobmsg_get_bool(cur); - s->flags |= DEV_OPT_XPS; - } - else - s->xps = default_ps; if ((cur = tb[DEV_ATTR_DADTRANSMITS])) { s->dadtransmits = blobmsg_get_u32(cur); @@ -371,6 +411,41 @@ device_init_settings(struct device *dev, struct blob_attr **tb) s->flags |= DEV_OPT_SENDREDIRECTS; } + if ((cur = tb[DEV_ATTR_ISOLATE])) { + s->isolate = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_ISOLATE; + } + + if ((cur = tb[DEV_ATTR_DROP_V4_UNICAST_IN_L2_MULTICAST])) { + s->drop_v4_unicast_in_l2_multicast = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST; + } + + if ((cur = tb[DEV_ATTR_DROP_V6_UNICAST_IN_L2_MULTICAST])) { + s->drop_v6_unicast_in_l2_multicast = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST; + } + + if ((cur = tb[DEV_ATTR_DROP_GRATUITOUS_ARP])) { + s->drop_gratuitous_arp = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_DROP_GRATUITOUS_ARP; + } + + if ((cur = tb[DEV_ATTR_DROP_UNSOLICITED_NA])) { + s->drop_unsolicited_na = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_DROP_UNSOLICITED_NA; + } + + if ((cur = tb[DEV_ATTR_ARP_ACCEPT])) { + s->arp_accept = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_ARP_ACCEPT; + } + + if ((cur = tb[DEV_ATTR_AUTH])) { + s->auth = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_AUTH; + } + device_set_disabled(dev, disabled); } @@ -401,6 +476,21 @@ void device_broadcast_event(struct device *dev, enum device_event ev) safe_list_for_each(&dev->users, device_broadcast_cb, &dev_ev); } +static void +device_fill_default_settings(struct device *dev) +{ + struct device_settings *s = &dev->settings; + struct ether_addr *ea; + + if (!(s->flags & DEV_OPT_MACADDR)) { + ea = config_get_default_macaddr(dev->ifname); + if (ea) { + memcpy(s->macaddr, ea, 6); + s->flags |= DEV_OPT_DEFAULT_MACADDR; + } + } +} + int device_claim(struct device_user *dep) { struct device *dev = dep->dev; @@ -418,6 +508,7 @@ int device_claim(struct device_user *dep) return 0; device_broadcast_event(dev, DEV_EVENT_SETUP); + device_fill_default_settings(dev); if (dev->external) { /* Get ifindex for external claimed devices so a valid */ /* ifindex is in place avoiding possible race conditions */ @@ -473,7 +564,7 @@ int device_check_state(struct device *dev) return dev->type->check_state(dev); } -void device_init_virtual(struct device *dev, struct device_type *type, const char *name) +int device_init_virtual(struct device *dev, struct device_type *type, const char *name) { assert(dev); assert(type); @@ -483,18 +574,27 @@ void device_init_virtual(struct device *dev, struct device_type *type, const cha INIT_SAFE_LIST(&dev->aliases); dev->type = type; - if (name) - device_set_ifname(dev, name); + if (name) { + int ret; + + ret = device_set_ifname(dev, name); + if (ret < 0) + return ret; + } if (!dev->set_state) dev->set_state = set_device_state; + + return 0; } int device_init(struct device *dev, struct device_type *type, const char *ifname) { int ret; - device_init_virtual(dev, type, ifname); + ret = device_init_virtual(dev, type, ifname); + if (ret < 0) + return ret; dev->avl.key = dev->ifname; @@ -503,9 +603,6 @@ int device_init(struct device *dev, struct device_type *type, const char *ifname return ret; system_if_clear_state(dev); - device_check_state(dev); - dev->settings.rps = default_ps; - dev->settings.xps = default_ps; return 0; } @@ -525,10 +622,19 @@ device_create_default(const char *name, bool external) dev->external = external; dev->set_state = simple_device_set_state; - device_init(dev, &simple_device_type, name); + + if (device_init(dev, &simple_device_type, name) < 0) { + device_cleanup(dev); + free(dev); + return NULL; + } + dev->default_config = true; if (external) system_if_apply_settings(dev, &dev->settings, dev->settings.flags); + + device_check_state(dev); + return dev; } @@ -545,13 +651,14 @@ device_get(const char *name, int create) { struct device *dev; - if (strchr(name, '.')) + dev = avl_find_element(&devices, name, dev, avl); + + if (!dev && strchr(name, '.')) return get_vlan_device_chain(name, create); if (name[0] == '@') return device_alias_get(name + 1); - dev = avl_find_element(&devices, name, dev, avl); if (dev) { if (create > 1 && !dev->external) { system_if_apply_settings(dev, &dev->settings, dev->settings.flags); @@ -616,6 +723,28 @@ device_refresh_present(struct device *dev) __device_set_present(dev, state); } +void +device_set_auth_status(struct device *dev, bool value) +{ + if (dev->auth_status == value) + return; + + dev->auth_status = value; + if (!dev->present) + return; + + if (dev->auth_status) { + device_broadcast_event(dev, DEV_EVENT_AUTH_UP); + return; + } + + device_broadcast_event(dev, DEV_EVENT_LINK_DOWN); + if (!dev->link_active) + return; + + device_broadcast_event(dev, DEV_EVENT_LINK_UP); +} + void device_set_present(struct device *dev, bool state) { if (dev->sys_present == state) @@ -634,6 +763,8 @@ void device_set_link(struct device *dev, bool state) netifd_log_message(L_NOTICE, "%s '%s' link is %s\n", dev->type->name, dev->ifname, state ? "up" : "down" ); dev->link_active = state; + if (!state) + dev->auth_status = false; device_broadcast_event(dev, state ? DEV_EVENT_LINK_UP : DEV_EVENT_LINK_DOWN); } @@ -653,10 +784,13 @@ int device_set_ifname(struct device *dev, const char *name) if (!strcmp(dev->ifname, name)) return 0; + if (strlen(name) > sizeof(dev->ifname) - 1) + return -1; + if (dev->avl.key) avl_delete(&devices, &dev->avl); - strncpy(dev->ifname, name, IFNAMSIZ); + strcpy(dev->ifname, name); if (dev->avl.key) ret = avl_insert(&devices, &dev->avl); @@ -720,7 +854,7 @@ void device_add_user(struct device_user *dep, struct device *dev) __device_add_user(dep, dev); } -void +static void device_free(struct device *dev) { __devlock++; @@ -781,9 +915,22 @@ device_init_pending(void) dev->type->config_init(dev); dev->config_pending = false; + device_check_state(dev); } } +bool +device_check_ip6segmentrouting(void) +{ + struct device *dev; + bool ip6segmentrouting = false; + + avl_for_each_element(&devices, dev, avl) + ip6segmentrouting |= dev->settings.ip6segmentrouting; + + return ip6segmentrouting; +} + static enum dev_change_type device_set_config(struct device *dev, struct device_type *type, struct blob_attr *attr) @@ -903,41 +1050,6 @@ device_reset_old(void) } } -void -device_set_default_ps(bool state) -{ - struct device *dev; - - if (state == default_ps) - return; - - default_ps = state; - - avl_for_each_element(&devices, dev, avl) { - struct device_settings *s = &dev->settings; - unsigned int apply_mask = 0; - - if (!(s->flags & DEV_OPT_RPS)) { - s->rps = default_ps; - apply_mask |= DEV_OPT_RPS; - } - - if (!(s->flags & DEV_OPT_XPS)) { - s->xps = default_ps; - apply_mask |= DEV_OPT_XPS; - } - - if (!apply_mask) - continue; - - if (!(dev->external || (dev->present && dev->active)) || - dev->config_pending) - continue; - - system_if_apply_settings(dev, s, apply_mask); - } -} - struct device * device_create(const char *name, struct device_type *type, struct blob_attr *config) @@ -978,6 +1090,8 @@ device_create(const char *name, struct device_type *type, dev->config_pending = false; } + device_check_state(dev); + return dev; } @@ -1008,6 +1122,7 @@ device_dump_status(struct blob_buf *b, struct device *dev) blobmsg_add_u8(b, "up", !!dev->active); blobmsg_add_u8(b, "carrier", !!dev->link_active); + blobmsg_add_u8(b, "auth_status", !!dev->auth_status); if (dev->type->dump_info) dev->type->dump_info(dev, b); @@ -1026,6 +1141,8 @@ device_dump_status(struct blob_buf *b, struct device *dev) blobmsg_add_u32(b, "txqueuelen", st.txqueuelen); if (st.flags & DEV_OPT_IPV6) blobmsg_add_u8(b, "ipv6", st.ipv6); + if (st.flags & DEV_OPT_IP6SEGMENTROUTING) + blobmsg_add_u8(b, "ip6segmentrouting", st.ip6segmentrouting); if (st.flags & DEV_OPT_PROMISC) blobmsg_add_u8(b, "promisc", st.promisc); if (st.flags & DEV_OPT_RPFILTER) @@ -1044,6 +1161,8 @@ device_dump_status(struct blob_buf *b, struct device *dev) blobmsg_add_u32(b, "neigh4gcstaletime", st.neigh4gcstaletime); blobmsg_add_u32(b, "neigh6gcstaletime", st.neigh6gcstaletime); } + if (st.flags & DEV_OPT_NEIGHLOCKTIME) + blobmsg_add_u32(b, "neigh4locktime", st.neigh4locktime); if (st.flags & DEV_OPT_DADTRANSMITS) blobmsg_add_u32(b, "dadtransmits", st.dadtransmits); if (st.flags & DEV_OPT_MULTICAST_TO_UNICAST) @@ -1060,6 +1179,18 @@ device_dump_status(struct blob_buf *b, struct device *dev) blobmsg_add_u8(b, "unicast_flood", st.unicast_flood); if (st.flags & DEV_OPT_SENDREDIRECTS) blobmsg_add_u8(b, "sendredirects", st.sendredirects); + if (st.flags & DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST) + blobmsg_add_u8(b, "drop_v4_unicast_in_l2_multicast", st.drop_v4_unicast_in_l2_multicast); + if (st.flags & DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST) + blobmsg_add_u8(b, "drop_v6_unicast_in_l2_multicast", st.drop_v6_unicast_in_l2_multicast); + if (st.flags & DEV_OPT_DROP_GRATUITOUS_ARP) + blobmsg_add_u8(b, "drop_gratuitous_arp", st.drop_gratuitous_arp); + if (st.flags & DEV_OPT_DROP_UNSOLICITED_NA) + blobmsg_add_u8(b, "drop_unsolicited_na", st.drop_unsolicited_na); + if (st.flags & DEV_OPT_ARP_ACCEPT) + blobmsg_add_u8(b, "arp_accept", st.arp_accept); + if (st.flags & DEV_OPT_AUTH) + blobmsg_add_u8(b, "auth", st.auth); } s = blobmsg_open_table(b, "statistics");