|
@@ -2,9 +2,10 @@ let libubus = require("ubus");
|
|
|
import { open, readfile } from "fs";
|
|
|
import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac, phy_open } from "common";
|
|
|
|
|
|
-let ubus = libubus.connect();
|
|
|
+let ubus = libubus.connect(null, 60);
|
|
|
|
|
|
hostapd.data.config = {};
|
|
|
+hostapd.data.pending_config = {};
|
|
|
|
|
|
hostapd.data.file_fields = {
|
|
|
vlan_file: true,
|
|
@@ -122,17 +123,111 @@ function iface_config_macaddr_list(config)
|
|
|
return macaddr_list;
|
|
|
}
|
|
|
|
|
|
-function iface_update_supplicant_macaddr(phy, config)
|
|
|
+function __iface_pending_next(pending, state, ret, data)
|
|
|
{
|
|
|
- let macaddr_list = [];
|
|
|
- for (let i = 0; i < length(config.bss); i++)
|
|
|
- push(macaddr_list, config.bss[i].bssid);
|
|
|
- ubus.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list });
|
|
|
+ let config = pending.config;
|
|
|
+ let phydev = pending.phydev;
|
|
|
+ let phy = pending.phy;
|
|
|
+
|
|
|
+ if (pending.defer)
|
|
|
+ pending.defer.abort();
|
|
|
+ delete pending.defer;
|
|
|
+ switch (state) {
|
|
|
+ case "init":
|
|
|
+ let macaddr_list = [];
|
|
|
+ for (let i = 0; i < length(config.bss); i++)
|
|
|
+ push(macaddr_list, config.bss[i].bssid);
|
|
|
+ pending.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list });
|
|
|
+ return "create_bss";
|
|
|
+ case "create_bss":
|
|
|
+ let bss = config.bss[0];
|
|
|
+ let err = wdev_create(phy, bss.ifname, { mode: "ap" });
|
|
|
+ if (err) {
|
|
|
+ hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ pending.call("wpa_supplicant", "phy_status", { phy: phy });
|
|
|
+ return "check_phy";
|
|
|
+ case "check_phy":
|
|
|
+ let phy_status = data;
|
|
|
+ if (phy_status && phy_status.state == "COMPLETED") {
|
|
|
+ if (iface_add(phy, config, phy_status))
|
|
|
+ return "done";
|
|
|
+
|
|
|
+ hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`);
|
|
|
+ }
|
|
|
+ pending.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true });
|
|
|
+ return "wpas_stopped";
|
|
|
+ case "wpas_stopped":
|
|
|
+ if (!iface_add(phy, config))
|
|
|
+ hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`);
|
|
|
+ pending.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false });
|
|
|
+ return null;
|
|
|
+ case "done":
|
|
|
+ default:
|
|
|
+ delete hostapd.data.pending_config[phy];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function iface_pending_next(ret, data)
|
|
|
+{
|
|
|
+ let pending = true;
|
|
|
+ let cfg = this;
|
|
|
+
|
|
|
+ while (pending) {
|
|
|
+ this.next_state = __iface_pending_next(cfg, this.next_state, ret, data);
|
|
|
+ if (!this.next_state) {
|
|
|
+ __iface_pending_next(cfg, "done");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ pending = !this.defer;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function iface_pending_abort()
|
|
|
+{
|
|
|
+ this.next_state = "done";
|
|
|
+ this.next();
|
|
|
+}
|
|
|
+
|
|
|
+function iface_pending_ubus_call(obj, method, arg)
|
|
|
+{
|
|
|
+ let ubus = hostapd.data.ubus;
|
|
|
+ let pending = this;
|
|
|
+ this.defer = ubus.defer(obj, method, arg, (ret, data) => { delete pending.defer; pending.next(ret, data) });
|
|
|
+}
|
|
|
+
|
|
|
+const iface_pending_proto = {
|
|
|
+ next: iface_pending_next,
|
|
|
+ call: iface_pending_ubus_call,
|
|
|
+ abort: iface_pending_abort,
|
|
|
+};
|
|
|
+
|
|
|
+function iface_pending_init(phydev, config)
|
|
|
+{
|
|
|
+ let phy = phydev.name;
|
|
|
+
|
|
|
+ let pending = proto({
|
|
|
+ next_state: "init",
|
|
|
+ phydev: phydev,
|
|
|
+ phy: phy,
|
|
|
+ config: config,
|
|
|
+ next: iface_pending_next,
|
|
|
+ }, iface_pending_proto);
|
|
|
+
|
|
|
+ hostapd.data.pending_config[phy] = pending;
|
|
|
+ pending.next();
|
|
|
}
|
|
|
|
|
|
function iface_restart(phydev, config, old_config)
|
|
|
{
|
|
|
let phy = phydev.name;
|
|
|
+ let pending = hostapd.data.pending_config[phy];
|
|
|
+
|
|
|
+ if (pending)
|
|
|
+ pending.abort();
|
|
|
|
|
|
hostapd.remove_iface(phy);
|
|
|
iface_remove(old_config);
|
|
@@ -150,26 +245,7 @@ function iface_restart(phydev, config, old_config)
|
|
|
bss.bssid = phydev.macaddr_next();
|
|
|
}
|
|
|
|
|
|
- iface_update_supplicant_macaddr(phy, config);
|
|
|
-
|
|
|
- let bss = config.bss[0];
|
|
|
- let err = wdev_create(phy, bss.ifname, { mode: "ap" });
|
|
|
- if (err)
|
|
|
- hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`);
|
|
|
-
|
|
|
- let ubus = hostapd.data.ubus;
|
|
|
- let phy_status = ubus.call("wpa_supplicant", "phy_status", { phy: phy });
|
|
|
- if (phy_status && phy_status.state == "COMPLETED") {
|
|
|
- if (iface_add(phy, config, phy_status))
|
|
|
- return;
|
|
|
-
|
|
|
- hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`);
|
|
|
- }
|
|
|
-
|
|
|
- ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true });
|
|
|
- if (!iface_add(phy, config))
|
|
|
- hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`);
|
|
|
- ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false });
|
|
|
+ iface_pending_init(phydev, config);
|
|
|
}
|
|
|
|
|
|
function array_to_obj(arr, key, start)
|
|
@@ -274,6 +350,9 @@ function iface_reload_config(phydev, config, old_config)
|
|
|
if (is_equal(old_config.bss, config.bss))
|
|
|
return true;
|
|
|
|
|
|
+ if (hostapd.data.pending_config[phy])
|
|
|
+ return false;
|
|
|
+
|
|
|
if (!old_config.bss || !old_config.bss[0])
|
|
|
return false;
|
|
|
|