X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=wireless.c;h=34603372903b14ea12c88236ce111587ccdac2fc;hp=273d54bd93d510664ddfb2943c730b59a4368328;hb=c317cccbef29bc4ec441ee89778f763618c5b4b4;hpb=5c2cc14f85df74d971979b45265173f067f1e971 diff --git a/wireless.c b/wireless.c index 273d54b..3460337 100644 --- a/wireless.c +++ b/wireless.c @@ -40,7 +40,7 @@ enum { static const struct blobmsg_policy vif_policy[__VIF_ATTR_MAX] = { [VIF_ATTR_DISABLED] = { .name = "disabled", .type = BLOBMSG_TYPE_BOOL }, - [VIF_ATTR_NETWORK] = { .name = "network", .type = BLOBMSG_TYPE_STRING }, + [VIF_ATTR_NETWORK] = { .name = "network", .type = BLOBMSG_TYPE_ARRAY }, }; static const struct uci_blob_param_list vif_param = { @@ -57,24 +57,37 @@ put_container(struct blob_buf *buf, struct blob_attr *attr, const char *name) } static void -vif_config_add_bridge(struct blob_buf *buf, const char *network, bool prepare) +vif_config_add_bridge(struct blob_buf *buf, struct blob_attr *networks, bool prepare) { struct interface *iface; - struct device *dev; + struct device *dev = NULL; + struct blob_attr *cur; + const char *network; + int rem; - if (!network) + if (!networks) return; - iface = vlist_find(&interfaces, network, iface, node); - if (!iface) - return; + blobmsg_for_each_attr(cur, networks, rem) { + network = blobmsg_data(cur); + + iface = vlist_find(&interfaces, network, iface, node); + if (!iface) + continue; + + dev = iface->main_dev.dev; + if (!dev) + return; + + if (dev->type != &bridge_device_type) + return; + } - dev = iface->main_dev.dev; if (!dev) return; - if (dev->type != &bridge_device_type) - return; + if (dev->hotplug_ops && dev->hotplug_ops->prepare) + dev->hotplug_ops->prepare(dev); blobmsg_add_string(buf, "bridge", dev->ifname); } @@ -167,6 +180,7 @@ wireless_device_free_state(struct wireless_device *wdev) { struct wireless_interface *vif; + uloop_timeout_cancel(&wdev->timeout); wireless_complete_kill_request(wdev); free(wdev->data); wdev->data = NULL; @@ -180,15 +194,22 @@ wireless_device_free_state(struct wireless_device *wdev) static void wireless_interface_handle_link(struct wireless_interface *vif, bool up) { struct interface *iface; + struct blob_attr *cur; + const char *network; + int rem; if (!vif->network || !vif->ifname) return; - iface = vlist_find(&interfaces, vif->network, iface, node); - if (!iface) - return; + blobmsg_for_each_attr(cur, vif->network, rem) { + network = blobmsg_data(cur); + + iface = vlist_find(&interfaces, network, iface, node); + if (!iface) + continue; - interface_handle_link(iface, vif->ifname, up); + interface_handle_link(iface, vif->ifname, up); + } } static void @@ -197,6 +218,7 @@ wireless_device_setup_cancel(struct wireless_device *wdev) if (wdev->cancel) return; + D(WIRELESS, "Cancel wireless device '%s' setup\n", wdev->name); wdev->cancel = true; uloop_timeout_set(&wdev->timeout, 10 * 1000); } @@ -246,6 +268,33 @@ __wireless_device_set_up(struct wireless_device *wdev) } static void +wireless_device_free(struct wireless_device *wdev) +{ + vlist_flush_all(&wdev->interfaces); + avl_delete(&wireless_devices.avl, &wdev->node.avl); + free(wdev->config); + free(wdev); +} + +static void +wdev_handle_config_change(struct wireless_device *wdev) +{ + enum interface_config_state state = wdev->config_state; + + wdev->config_state = IFC_NORMAL; + switch(state) { + case IFC_NORMAL: + case IFC_RELOAD: + if (wdev->autostart) + __wireless_device_set_up(wdev); + break; + case IFC_REMOVE: + wireless_device_free(wdev); + break; + } +} + +static void wireless_device_mark_down(struct wireless_device *wdev) { struct wireless_interface *vif; @@ -257,11 +306,10 @@ wireless_device_mark_down(struct wireless_device *wdev) wireless_process_kill_all(wdev, SIGTERM, true); + wdev->cancel = false; wdev->state = IFS_DOWN; wireless_device_free_state(wdev); - - if (wdev->autostart) - __wireless_device_set_up(wdev); + wdev_handle_config_change(wdev); } static void @@ -311,6 +359,9 @@ __wireless_device_set_down(struct wireless_device *wdev) static void wireless_device_retry_setup(struct wireless_device *wdev) { + if (wdev->state == IFS_TEARDOWN || wdev->state == IFS_DOWN || wdev->cancel) + return; + if (--wdev->retry < 0) wdev->autostart = false; @@ -342,33 +393,6 @@ wireless_device_set_down(struct wireless_device *wdev) } static void -wireless_device_free(struct wireless_device *wdev) -{ - vlist_flush_all(&wdev->interfaces); - free(wdev->config); - free(wdev); -} - -static void -wdev_handle_config_change(struct wireless_device *wdev) -{ - enum interface_config_state state = wdev->config_state; - - wdev->config_state = IFC_NORMAL; - switch(state) { - case IFC_NORMAL: - break; - case IFC_RELOAD: - if (wdev->autostart) - __wireless_device_set_up(wdev); - break; - case IFC_REMOVE: - wireless_device_free(wdev); - break; - } -} - -static void wdev_set_config_state(struct wireless_device *wdev, enum interface_config_state s) { enum interface_config_state old_state = wdev->config_state; @@ -488,7 +512,7 @@ wireless_interface_init_config(struct wireless_interface *vif) blobmsg_parse(vif_policy, __VIF_ATTR_MAX, tb, blob_data(vif->config), blob_len(vif->config)); if ((cur = tb[VIF_ATTR_NETWORK])) - vif->network = blobmsg_data(cur); + vif->network = cur; } static void @@ -645,7 +669,7 @@ wireless_interface_status(struct wireless_interface *iface, struct blob_buf *b) { void *i; - i = blobmsg_open_table(b, iface->name); + i = blobmsg_open_table(b, NULL); if (iface->section) blobmsg_add_string(b, "section", iface->section); if (iface->ifname) @@ -665,10 +689,10 @@ wireless_device_status(struct wireless_device *wdev, struct blob_buf *b) blobmsg_add_u8(b, "up", wdev->state == IFS_UP); blobmsg_add_u8(b, "pending", wdev->state == IFS_SETUP || wdev->state == IFS_TEARDOWN); blobmsg_add_u8(b, "autostart", wdev->autostart); - i = blobmsg_open_table(b, "interfaces"); + i = blobmsg_open_array(b, "interfaces"); vlist_for_each_element(&wdev->interfaces, iface, node) wireless_interface_status(iface, b); - blobmsg_close_table(b, i); + blobmsg_close_array(b, i); blobmsg_close_table(b, c); } @@ -762,7 +786,7 @@ wireless_device_process_kill_all(struct wireless_device *wdev, struct blob_attr signal = blobmsg_get_u32(cur); if ((cur = tb[KILL_ATTR_IMMEDIATE])) - immediate = blobmsg_get_u32(cur); + immediate = blobmsg_get_bool(cur); if (wdev->state != IFS_TEARDOWN || wdev->kill_request) return UBUS_STATUS_PERMISSION_DENIED;