X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=device.c;h=f50fb8505e1b7653659d63ffb895cbf3f2421b98;hp=26b020f3f55674447299ed1c6b1a084c19ec2fa3;hb=b9d1f678c1f705b5635de31d333353a64ff6799d;hpb=c09e944416d76ed162efc55483f987cd537c2c8b diff --git a/device.c b/device.c index 26b020f..f50fb85 100644 --- a/device.c +++ b/device.c @@ -38,6 +38,11 @@ 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_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 }, + [DEV_ATTR_IGMPVERSION] = { .name = "igmpversion", .type = BLOBMSG_TYPE_INT32 }, + [DEV_ATTR_MLDVERSION] = { .name = "mldversion", .type = BLOBMSG_TYPE_INT32 }, }; const struct uci_blob_param_list device_attr_list = { @@ -61,6 +66,14 @@ void device_unlock(void) static int set_device_state(struct device *dev, bool state) { + if (state) { + /* Set ifindex for all devices being enabled so a valid */ + /* ifindex is in place avoiding possible race conditions */ + device_set_ifindex(dev, system_if_resolve(dev)); + if (!dev->ifindex) + return -1; + } + if (dev->external) return 0; @@ -144,6 +157,11 @@ device_merge_settings(struct device *dev, struct device_settings *n) (s->flags & DEV_OPT_MACADDR ? s->macaddr : os->macaddr), sizeof(n->macaddr)); n->ipv6 = s->flags & DEV_OPT_IPV6 ? s->ipv6 : os->ipv6; + 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; + n->igmpversion = s->flags & DEV_OPT_IGMPVERSION ? s->igmpversion : os->igmpversion; + n->mldversion = s->flags & DEV_OPT_MLDVERSION ? s->mldversion : os->mldversion; n->flags = s->flags | os->flags; } @@ -182,6 +200,39 @@ device_init_settings(struct device *dev, struct blob_attr **tb) s->flags |= DEV_OPT_IPV6; } + if ((cur = tb[DEV_ATTR_PROMISC])) { + s->promisc = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_PROMISC; + } + + if ((cur = tb[DEV_ATTR_RPFILTER])) { + if (system_resolve_rpfilter(blobmsg_data(cur), &s->rpfilter)) + s->flags |= DEV_OPT_RPFILTER; + else + DPRINTF("Failed to resolve rpfilter: %s\n", (char *) blobmsg_data(cur)); + } + + if ((cur = tb[DEV_ATTR_ACCEPTLOCAL])) { + s->acceptlocal = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_ACCEPTLOCAL; + } + + if ((cur = tb[DEV_ATTR_IGMPVERSION])) { + s->igmpversion = blobmsg_get_u32(cur); + if (s->igmpversion >= 1 && s->igmpversion <= 3) + s->flags |= DEV_OPT_IGMPVERSION; + else + DPRINTF("Failed to resolve igmpversion: %d\n", blobmsg_get_u32(cur)); + } + + if ((cur = tb[DEV_ATTR_MLDVERSION])) { + s->mldversion = blobmsg_get_u32(cur); + if (s->mldversion >= 1 && s->mldversion <= 2) + s->flags |= DEV_OPT_MLDVERSION; + else + DPRINTF("Failed to resolve mldversion: %d\n", blobmsg_get_u32(cur)); + } + device_set_disabled(dev, disabled); } @@ -535,11 +586,18 @@ device_init_pending(void) } } -static enum dev_change_type -device_reload_config(struct device *dev, struct blob_attr *attr) +enum dev_change_type +device_set_config(struct device *dev, const struct device_type *type, + struct blob_attr *attr) { struct blob_attr *tb[__DEV_ATTR_MAX]; - const struct uci_blob_param_list *cfg = dev->type->config_params; + const struct uci_blob_param_list *cfg = type->config_params; + + if (type != dev->type) + return DEV_CONFIG_RECREATE; + + if (dev->type->reload) + return dev->type->reload(dev, attr); if (uci_blob_check_equal(dev->config, attr, cfg)) return DEV_CONFIG_NO_CHANGE; @@ -558,16 +616,37 @@ device_reload_config(struct device *dev, struct blob_attr *attr) } enum dev_change_type -device_set_config(struct device *dev, const struct device_type *type, - struct blob_attr *attr) +device_apply_config(struct device *dev, const struct device_type *type, + struct blob_attr *config) { - if (type != dev->type) - return DEV_CONFIG_RECREATE; + enum dev_change_type change; - if (dev->type->reload) - return dev->type->reload(dev, attr); + change = device_set_config(dev, type, config); + if (dev->external) { + system_if_apply_settings(dev, &dev->settings, dev->settings.flags); + change = DEV_CONFIG_APPLIED; + } + + switch (change) { + case DEV_CONFIG_RESTART: + case DEV_CONFIG_APPLIED: + D(DEVICE, "Device '%s': config applied\n", dev->ifname); + free(dev->config); + dev->config = config; + if (change == DEV_CONFIG_RESTART && dev->present) { + device_set_present(dev, false); + device_set_present(dev, true); + } + break; + case DEV_CONFIG_NO_CHANGE: + D(DEVICE, "Device '%s': no configuration change\n", dev->ifname); + free(config); + break; + case DEV_CONFIG_RECREATE: + break; + } - return device_reload_config(dev, attr); + return change; } static void @@ -631,30 +710,14 @@ device_create(const char *name, const struct device_type *type, odev = device_get(name, false); if (odev) { odev->current_config = true; - change = device_set_config(odev, type, config); - if (odev->external) { - system_if_apply_settings(odev, &odev->settings, odev->settings.flags); - change = DEV_CONFIG_APPLIED; - } + change = device_apply_config(odev, type, config); switch (change) { - case DEV_CONFIG_RESTART: - case DEV_CONFIG_APPLIED: - D(DEVICE, "Device '%s': config applied\n", odev->ifname); - free(odev->config); - odev->config = config; - if (change == DEV_CONFIG_RESTART && odev->present) { - device_set_present(odev, false); - device_set_present(odev, true); - } - return odev; - case DEV_CONFIG_NO_CHANGE: - D(DEVICE, "Device '%s': no configuration change\n", odev->ifname); - free(config); - return odev; case DEV_CONFIG_RECREATE: D(DEVICE, "Device '%s': recreate device\n", odev->ifname); device_delete(odev); break; + default: + return odev; } } else D(DEVICE, "Create new device '%s' (%s)\n", name, type->name); @@ -717,6 +780,16 @@ 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_PROMISC) + blobmsg_add_u8(b, "promisc", st.promisc); + if (st.flags & DEV_OPT_RPFILTER) + blobmsg_add_u32(b, "rpfilter", st.rpfilter); + if (st.flags & DEV_OPT_ACCEPTLOCAL) + blobmsg_add_u8(b, "acceptlocal", st.acceptlocal); + if (st.flags & DEV_OPT_IGMPVERSION) + blobmsg_add_u32(b, "igmpversion", st.igmpversion); + if (st.flags & DEV_OPT_MLDVERSION) + blobmsg_add_u32(b, "mldversion", st.mldversion); } s = blobmsg_open_table(b, "statistics");