mirror of
https://github.com/openwrt/openwrt.git
synced 2024-11-23 18:05:20 +08:00
wifi-scripts: add multi-radio config support
Emit one wifi-device section per wiphy radio Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
cb60bee04d
commit
04fb05914e
@ -29,7 +29,7 @@ drv_mac80211_init_device_config() {
|
||||
config_add_string path phy 'macaddr:macaddr'
|
||||
config_add_string tx_burst
|
||||
config_add_string distance
|
||||
config_add_int beacon_int chanbw frag rts
|
||||
config_add_int radio beacon_int chanbw frag rts
|
||||
config_add_int rxantenna txantenna txpower min_tx_power
|
||||
config_add_int num_global_macaddr multiple_bssid
|
||||
config_add_boolean noscan ht_coex acs_exclude_dfs background_radar
|
||||
@ -556,7 +556,7 @@ mac80211_hostapd_setup_bss() {
|
||||
}
|
||||
[ "$staidx" -gt 0 -o "$start_disabled" -eq 1 ] && append hostapd_cfg "start_disabled=1" "$N"
|
||||
|
||||
cat >> /var/run/hostapd-$phy.conf <<EOF
|
||||
cat >> /var/run/hostapd-$phy$vif_phy_suffix.conf <<EOF
|
||||
$hostapd_cfg
|
||||
bssid=$macaddr
|
||||
${default_macaddr:+#default_macaddr}
|
||||
@ -576,7 +576,7 @@ mac80211_generate_mac() {
|
||||
local phy="$1"
|
||||
local id="${macidx:-0}"
|
||||
|
||||
wdev_tool "$phy" get_macaddr id=$id num_global=$num_global_macaddr mbssid=${multiple_bssid:-0}
|
||||
wdev_tool "$phy$phy_suffix" get_macaddr id=$id num_global=$num_global_macaddr mbssid=${multiple_bssid:-0}
|
||||
}
|
||||
|
||||
get_board_phy_name() (
|
||||
@ -679,7 +679,7 @@ mac80211_prepare_vif() {
|
||||
monitor) prefix=mon;;
|
||||
esac
|
||||
|
||||
mac80211_set_ifname "$phy" "$prefix"
|
||||
mac80211_set_ifname "$phy$vif_phy_suffix" "$prefix"
|
||||
}
|
||||
|
||||
append active_ifnames "$ifname"
|
||||
@ -880,7 +880,12 @@ mac80211_set_vif_txpower() {
|
||||
json_get_vars vif_txpower
|
||||
json_select ..
|
||||
|
||||
[ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00"
|
||||
set_default vif_txpower "$txpower"
|
||||
if [ -n "$vif_txpower" ]; then
|
||||
iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00"
|
||||
else
|
||||
iw dev "$ifname" set txpower auto
|
||||
fi
|
||||
}
|
||||
|
||||
wpa_supplicant_init_config() {
|
||||
@ -920,11 +925,13 @@ wpa_supplicant_add_interface() {
|
||||
|
||||
wpa_supplicant_set_config() {
|
||||
local phy="$1"
|
||||
local radio="$2"
|
||||
local prev
|
||||
|
||||
json_set_namespace wpa_supp prev
|
||||
json_close_array
|
||||
json_add_string phy "$phy"
|
||||
json_add_int radio "$radio"
|
||||
json_add_int num_global_macaddr "$num_global_macaddr"
|
||||
json_add_boolean defer 1
|
||||
local data="$(json_dump)"
|
||||
@ -947,13 +954,16 @@ wpa_supplicant_set_config() {
|
||||
}
|
||||
|
||||
hostapd_set_config() {
|
||||
local phy="$1"
|
||||
local radio="$2"
|
||||
|
||||
[ -n "$hostapd_ctrl" ] || {
|
||||
ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null
|
||||
ubus_call hostapd config_set '{ "phy": "'"$phy"'", "radio": '"$radio"', "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null
|
||||
return 0;
|
||||
}
|
||||
|
||||
ubus wait_for hostapd
|
||||
local hostapd_res="$(ubus_call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")"
|
||||
local hostapd_res="$(ubus_call hostapd config_set "{ \"phy\": \"$phy\", \"radio\": $radio, \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")"
|
||||
ret="$?"
|
||||
[ "$ret" != 0 -o -z "$hostapd_res" ] && {
|
||||
wireless_setup_failed HOSTAPD_START_FAILED
|
||||
@ -965,10 +975,11 @@ hostapd_set_config() {
|
||||
|
||||
wpa_supplicant_start() {
|
||||
local phy="$1"
|
||||
local radio="$2"
|
||||
|
||||
[ -n "$wpa_supp_init" ] || return 0
|
||||
|
||||
ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "num_global_macaddr": '"$num_global_macaddr"' }' > /dev/null
|
||||
ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "radio": '"$radio"', "num_global_macaddr": '"$num_global_macaddr"' }' > /dev/null
|
||||
}
|
||||
|
||||
mac80211_setup_supplicant() {
|
||||
@ -1073,18 +1084,23 @@ drv_mac80211_cleanup() {
|
||||
}
|
||||
|
||||
mac80211_reset_config() {
|
||||
local phy="$1"
|
||||
hostapd_conf_file="/var/run/hostapd-$phy$vif_phy_suffix.conf"
|
||||
ubus_call hostapd config_set '{ "phy": "'"$phy"'", "radio": '"$radio"', "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null
|
||||
ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "radio": '"$radio"', "config": [] }' > /dev/null
|
||||
wdev_tool "$phy$phy_suffix" set_config '{}'
|
||||
}
|
||||
|
||||
hostapd_conf_file="/var/run/hostapd-$phy.conf"
|
||||
ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null
|
||||
ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null
|
||||
wdev_tool "$phy" set_config '{}'
|
||||
mac80211_set_suffix() {
|
||||
[ "$radio" = "-1" ] && radio=
|
||||
phy_suffix="${radio:+:$radio}"
|
||||
vif_phy_suffix="${radio:+.$radio}"
|
||||
set_default radio -1
|
||||
}
|
||||
|
||||
drv_mac80211_setup() {
|
||||
json_select config
|
||||
json_get_vars \
|
||||
phy macaddr path \
|
||||
radio phy macaddr path \
|
||||
country chanbw distance \
|
||||
txpower \
|
||||
rxantenna txantenna \
|
||||
@ -1094,6 +1110,8 @@ drv_mac80211_setup() {
|
||||
json_get_values scan_list scan_list
|
||||
json_select ..
|
||||
|
||||
mac80211_set_suffix
|
||||
|
||||
json_select data && {
|
||||
json_get_var prev_rxantenna rxantenna
|
||||
json_get_var prev_txantenna txantenna
|
||||
@ -1120,7 +1138,7 @@ drv_mac80211_setup() {
|
||||
}
|
||||
}
|
||||
|
||||
hostapd_conf_file="/var/run/hostapd-$phy.conf"
|
||||
hostapd_conf_file="/var/run/hostapd-$phy$vif_phy_suffix.conf"
|
||||
|
||||
macidx=0
|
||||
staidx=0
|
||||
@ -1139,17 +1157,11 @@ drv_mac80211_setup() {
|
||||
[ "$rxantenna" = "all" ] && rxantenna=0xffffffff
|
||||
|
||||
[ "$rxantenna" = "$prev_rxantenna" -a "$txantenna" = "$prev_txantenna" ] || mac80211_reset_config "$phy"
|
||||
wireless_set_data phy="$phy" txantenna="$txantenna" rxantenna="$rxantenna"
|
||||
wireless_set_data phy="$phy" radio="$radio" txantenna="$txantenna" rxantenna="$rxantenna"
|
||||
|
||||
iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1
|
||||
iw phy "$phy" set distance "$distance" >/dev/null 2>&1
|
||||
|
||||
if [ -n "$txpower" ]; then
|
||||
iw phy "$phy" set txpower fixed "${txpower%%.*}00"
|
||||
else
|
||||
iw phy "$phy" set txpower auto
|
||||
fi
|
||||
|
||||
[ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}"
|
||||
[ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}"
|
||||
|
||||
@ -1177,13 +1189,13 @@ drv_mac80211_setup() {
|
||||
for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif
|
||||
for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif
|
||||
|
||||
[ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy"
|
||||
[ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy"
|
||||
[ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy" "$radio"
|
||||
[ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy" "$radio"
|
||||
|
||||
[ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy"
|
||||
[ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy" "$radio"
|
||||
|
||||
json_set_namespace wdev_uc prev
|
||||
wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames
|
||||
wdev_tool "$phy$phy_suffix" set_config "$(json_dump)" $active_ifnames
|
||||
json_set_namespace "$prev"
|
||||
|
||||
for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower
|
||||
@ -1210,19 +1222,15 @@ list_phy_interfaces() {
|
||||
|
||||
drv_mac80211_teardown() {
|
||||
json_select data
|
||||
json_get_vars phy
|
||||
json_get_vars phy radio
|
||||
json_select ..
|
||||
[ -n "$phy" ] || {
|
||||
echo "Bug: PHY is undefined for device '$1'"
|
||||
return 1
|
||||
}
|
||||
|
||||
mac80211_set_suffix
|
||||
mac80211_reset_config "$phy"
|
||||
|
||||
for wdev in $(list_phy_interfaces "$phy"); do
|
||||
ip link set dev "$wdev" down
|
||||
iw dev "$wdev" del
|
||||
done
|
||||
}
|
||||
|
||||
add_driver mac80211
|
||||
|
@ -14,10 +14,12 @@ let commit;
|
||||
|
||||
let config = uci.cursor().get_all("wireless") ?? {};
|
||||
|
||||
function radio_exists(path, macaddr, phy) {
|
||||
function radio_exists(path, macaddr, phy, radio) {
|
||||
for (let name, s in config) {
|
||||
if (s[".type"] != "wifi-device")
|
||||
continue;
|
||||
if (radio != null && int(s.radio) != radio)
|
||||
continue;
|
||||
if (s.macaddr & lc(s.macaddr) == lc(macaddr))
|
||||
return true;
|
||||
if (s.phy == phy)
|
||||
@ -34,55 +36,61 @@ for (let phy_name, phy in board.wlan) {
|
||||
if (!info || !length(info.bands))
|
||||
continue;
|
||||
|
||||
while (config[`radio${idx}`])
|
||||
idx++;
|
||||
let name = "radio" + idx++;
|
||||
let radios = length(info.radios) > 0 ? info.radios : [{ bands: info.bands }];
|
||||
for (let radio in radios) {
|
||||
while (config[`radio${idx}`])
|
||||
idx++;
|
||||
let name = "radio" + idx;
|
||||
|
||||
let s = "wireless." + name;
|
||||
let si = "wireless.default_" + name;
|
||||
let s = "wireless." + name;
|
||||
let si = "wireless.default_" + name;
|
||||
|
||||
let band_name = filter(bands_order, (b) => info.bands[b])[0];
|
||||
if (!band_name)
|
||||
continue;
|
||||
let band_name = filter(bands_order, (b) => radio.bands[b])[0];
|
||||
if (!band_name)
|
||||
continue;
|
||||
|
||||
let band = info.bands[band_name];
|
||||
let channel = band.default_channel ?? "auto";
|
||||
let band = info.bands[band_name];
|
||||
let rband = radio.bands[band_name];
|
||||
let channel = rband.default_channel ?? "auto";
|
||||
|
||||
let width = band.max_width;
|
||||
if (band_name == "2G")
|
||||
width = 20;
|
||||
else if (width > 80)
|
||||
width = 80;
|
||||
let width = band.max_width;
|
||||
if (band_name == "2G")
|
||||
width = 20;
|
||||
else if (width > 80)
|
||||
width = 80;
|
||||
|
||||
let htmode = filter(htmode_order, (m) => band[lc(m)])[0];
|
||||
if (htmode)
|
||||
htmode += width;
|
||||
else
|
||||
htmode = "NOHT";
|
||||
let htmode = filter(htmode_order, (m) => band[lc(m)])[0];
|
||||
if (htmode)
|
||||
htmode += width;
|
||||
else
|
||||
htmode = "NOHT";
|
||||
|
||||
if (!phy.path)
|
||||
continue;
|
||||
if (!phy.path)
|
||||
continue;
|
||||
|
||||
let macaddr = trim(readfile(`/sys/class/ieee80211/${phy_name}/macaddress`));
|
||||
if (radio_exists(phy.path, macaddr, phy_name))
|
||||
continue;
|
||||
let macaddr = trim(readfile(`/sys/class/ieee80211/${phy_name}/macaddress`));
|
||||
if (radio_exists(phy.path, macaddr, phy_name, radio.index))
|
||||
continue;
|
||||
|
||||
let id = `phy='${phy_name}'`;
|
||||
if (match(phy_name, /^phy[0-9]/))
|
||||
id = `path='${phy.path}'`;
|
||||
let id = `phy='${phy_name}'`;
|
||||
if (match(phy_name, /^phy[0-9]/))
|
||||
id = `path='${phy.path}'`;
|
||||
|
||||
band_name = lc(band_name);
|
||||
band_name = lc(band_name);
|
||||
|
||||
let country, defaults, num_global_macaddr;
|
||||
if (board.wlan.defaults) {
|
||||
defaults = board.wlan.defaults.ssids?.[band_name]?.ssid ? board.wlan.defaults.ssids?.[band_name] : board.wlan.defaults.ssids?.all;
|
||||
country = board.wlan.defaults.country;
|
||||
if (!country && band_name != '2g')
|
||||
defaults = null;
|
||||
num_global_macaddr = board.wlan.defaults.ssids?.[band_name]?.mac_count;
|
||||
}
|
||||
let country, defaults, num_global_macaddr;
|
||||
if (board.wlan.defaults) {
|
||||
defaults = board.wlan.defaults.ssids?.[band_name]?.ssid ? board.wlan.defaults.ssids?.[band_name] : board.wlan.defaults.ssids?.all;
|
||||
country = board.wlan.defaults.country;
|
||||
if (!country && band_name != '2g')
|
||||
defaults = null;
|
||||
num_global_macaddr = board.wlan.defaults.ssids?.[band_name]?.mac_count;
|
||||
}
|
||||
|
||||
print(`set ${s}=wifi-device
|
||||
if (length(info.radios) > 0)
|
||||
id += `\nset ${s}.radio='${radio.index}'`;
|
||||
|
||||
print(`set ${s}=wifi-device
|
||||
set ${s}.type='mac80211'
|
||||
set ${s}.${id}
|
||||
set ${s}.band='${band_name}'
|
||||
@ -101,7 +109,9 @@ set ${si}.encryption='${defaults?.encryption || "none"}'
|
||||
set ${si}.key='${defaults?.key || ""}'
|
||||
|
||||
`);
|
||||
commit = true;
|
||||
config[name] = {};
|
||||
commit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (commit)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as nl80211 from "nl80211";
|
||||
import * as rtnl from "rtnl";
|
||||
import { readfile, glob, basename, readlink } from "fs";
|
||||
import { readfile, glob, basename, readlink, open } from "fs";
|
||||
|
||||
const iftypes = {
|
||||
ap: nl80211.const.NL80211_IFTYPE_AP,
|
||||
@ -74,6 +74,14 @@ function find_reusable_wdev(phyidx)
|
||||
return null;
|
||||
}
|
||||
|
||||
function wdev_set_radio_mask(name, mask)
|
||||
{
|
||||
nl80211.request(nl80211.const.NL80211_CMD_SET_INTERFACE, 0, {
|
||||
dev: name,
|
||||
vif_radio_mask: mask
|
||||
});
|
||||
}
|
||||
|
||||
function wdev_create(phy, name, data)
|
||||
{
|
||||
let phyidx = int(readfile(`/sys/class/ieee80211/${phy}/index`));
|
||||
@ -93,24 +101,24 @@ function wdev_create(phy, name, data)
|
||||
req["4addr"] = data["4addr"];
|
||||
if (data.macaddr)
|
||||
req.mac = data.macaddr;
|
||||
if (data.radio != null && data.radio >= 0)
|
||||
req.vif_radio_mask = 1 << data.radio;
|
||||
|
||||
nl80211.error();
|
||||
|
||||
let reuse_ifname = find_reusable_wdev(phyidx);
|
||||
if (reuse_ifname &&
|
||||
(reuse_ifname == name ||
|
||||
rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false))
|
||||
nl80211.request(
|
||||
nl80211.const.NL80211_CMD_SET_INTERFACE, 0, {
|
||||
wiphy: phyidx,
|
||||
dev: name,
|
||||
iftype: iftypes[data.mode],
|
||||
});
|
||||
else
|
||||
rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false)) {
|
||||
req.dev = req.ifname;
|
||||
delete req.ifname;
|
||||
nl80211.request(nl80211.const.NL80211_CMD_SET_INTERFACE, 0, req);
|
||||
} else {
|
||||
nl80211.request(
|
||||
nl80211.const.NL80211_CMD_NEW_INTERFACE,
|
||||
nl80211.const.NLM_F_CREATE,
|
||||
req);
|
||||
}
|
||||
|
||||
let error = nl80211.error();
|
||||
if (error)
|
||||
@ -190,7 +198,8 @@ const phy_proto = {
|
||||
},
|
||||
|
||||
macaddr_generate: function(data) {
|
||||
let phy = this.name;
|
||||
let phy = this.phy;
|
||||
let radio_idx = this.radio;
|
||||
let idx = int(data.id ?? 0);
|
||||
let mbssid = int(data.mbssid ?? 0) > 0;
|
||||
let num_global = int(data.num_global ?? 1);
|
||||
@ -200,22 +209,30 @@ const phy_proto = {
|
||||
if (!base_addr)
|
||||
return null;
|
||||
|
||||
if (!idx && !mbssid)
|
||||
return base_addr;
|
||||
|
||||
let base_mask = phy_sysfs_file(phy, "address_mask");
|
||||
if (!base_mask)
|
||||
return null;
|
||||
|
||||
if (base_mask == "00:00:00:00:00:00" && idx >= num_global) {
|
||||
if (base_mask == "00:00:00:00:00:00" &&
|
||||
(radio_idx > 0 || idx >= num_global)) {
|
||||
let addrs = split(phy_sysfs_file(phy, "addresses"), "\n");
|
||||
|
||||
if (idx < length(addrs))
|
||||
return addrs[idx];
|
||||
if (radio_idx != null) {
|
||||
if (radio_idx && radio_idx < length(addrs))
|
||||
base_addr = addrs[radio_idx];
|
||||
else
|
||||
idx += radio_idx * 16;
|
||||
} else {
|
||||
if (idx < length(addrs))
|
||||
return addrs[idx];
|
||||
|
||||
base_mask = "ff:ff:ff:ff:ff:ff";
|
||||
base_mask = "ff:ff:ff:ff:ff:ff";
|
||||
}
|
||||
}
|
||||
|
||||
if (!idx && !mbssid)
|
||||
return base_addr;
|
||||
|
||||
let addr = macaddr_split(base_addr);
|
||||
let mask = macaddr_split(base_mask);
|
||||
let type;
|
||||
@ -275,27 +292,55 @@ const phy_proto = {
|
||||
}
|
||||
},
|
||||
|
||||
wdev_add: function(name, data) {
|
||||
let phydev = this;
|
||||
wdev_create(this.phy, name, {
|
||||
...data,
|
||||
radio: this.radio,
|
||||
});
|
||||
},
|
||||
|
||||
for_each_wdev: function(cb) {
|
||||
let wdevs = glob(`/sys/class/ieee80211/${this.name}/device/net/*`);
|
||||
wdevs = map(wdevs, (arg) => basename(arg));
|
||||
let wdevs = nl80211.request(
|
||||
nl80211.const.NL80211_CMD_GET_INTERFACE,
|
||||
nl80211.const.NLM_F_DUMP,
|
||||
{ wiphy: this.idx }
|
||||
);
|
||||
|
||||
let mac_wdev = {};
|
||||
for (let wdev in wdevs) {
|
||||
if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != this.name)
|
||||
if (wdev.iftype == nl80211.const.NL80211_IFTYPE_AP_VLAN)
|
||||
continue;
|
||||
if (this.radio != null && wdev.vif_radio_mask != null &&
|
||||
!(wdev.vif_radio_mask & (1 << this.radio)))
|
||||
continue;
|
||||
mac_wdev[wdev.mac] = wdev;
|
||||
}
|
||||
|
||||
for (let wdev in wdevs) {
|
||||
if (!mac_wdev[wdev.mac])
|
||||
continue;
|
||||
|
||||
cb(wdev);
|
||||
cb(wdev.ifname);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function phy_open(phy)
|
||||
function phy_open(phy, radio)
|
||||
{
|
||||
let phyidx = readfile(`/sys/class/ieee80211/${phy}/index`);
|
||||
if (!phyidx)
|
||||
return null;
|
||||
|
||||
let name = phy;
|
||||
if (radio === "" || radio < 0)
|
||||
radio = null;
|
||||
if (radio != null)
|
||||
name += "." + radio;
|
||||
|
||||
return proto({
|
||||
name: phy,
|
||||
idx: int(phyidx)
|
||||
phy, name, radio,
|
||||
idx: int(phyidx),
|
||||
}, phy_proto);
|
||||
}
|
||||
|
||||
@ -365,9 +410,9 @@ function is_equal(val1, val2) {
|
||||
|
||||
function vlist_new(cb) {
|
||||
return proto({
|
||||
cb: cb,
|
||||
data: {}
|
||||
}, vlist_proto);
|
||||
cb: cb,
|
||||
data: {}
|
||||
}, vlist_proto);
|
||||
}
|
||||
|
||||
export { wdev_remove, wdev_create, wdev_set_mesh_params, wdev_set_up, is_equal, vlist_new, phy_is_fullmac, phy_open };
|
||||
export { wdev_remove, wdev_create, wdev_set_mesh_params, wdev_set_radio_mask, wdev_set_up, is_equal, vlist_new, phy_is_fullmac, phy_open };
|
||||
|
@ -1,13 +1,13 @@
|
||||
#!/usr/bin/env ucode
|
||||
'use strict';
|
||||
import { vlist_new, is_equal, wdev_create, wdev_set_mesh_params, wdev_remove, wdev_set_up, phy_open } from "/usr/share/hostap/common.uc";
|
||||
import { vlist_new, is_equal, wdev_set_mesh_params, wdev_remove, wdev_set_up, phy_open } from "/usr/share/hostap/common.uc";
|
||||
import { readfile, writefile, basename, readlink, glob } from "fs";
|
||||
let libubus = require("ubus");
|
||||
|
||||
let keep_devices = {};
|
||||
let phy = shift(ARGV);
|
||||
let phy_name = shift(ARGV);
|
||||
let command = shift(ARGV);
|
||||
let phydev;
|
||||
let phy, phydev;
|
||||
|
||||
function iface_stop(wdev)
|
||||
{
|
||||
@ -30,7 +30,7 @@ function iface_start(wdev)
|
||||
wdev_config[key] = wdev[key];
|
||||
if (!wdev_config.macaddr && wdev.mode != "monitor")
|
||||
wdev_config.macaddr = phydev.macaddr_next();
|
||||
wdev_create(phy, ifname, wdev_config);
|
||||
phydev.wdev_add(ifname, wdev_config);
|
||||
wdev_set_up(ifname, true);
|
||||
let htmode = wdev.htmode || "NOHT";
|
||||
if (wdev.freq)
|
||||
@ -85,20 +85,15 @@ function delete_ifname(config)
|
||||
delete config[key].ifname;
|
||||
}
|
||||
|
||||
function add_existing(phy, config)
|
||||
function add_existing(phydev, config)
|
||||
{
|
||||
let wdevs = glob(`/sys/class/ieee80211/${phy}/device/net/*`);
|
||||
wdevs = map(wdevs, (arg) => basename(arg));
|
||||
for (let wdev in wdevs) {
|
||||
phydev.for_each_wdev((wdev) => {
|
||||
if (config[wdev])
|
||||
continue;
|
||||
|
||||
if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != phy)
|
||||
continue;
|
||||
return;
|
||||
|
||||
if (trim(readfile(`/sys/class/net/${wdev}/operstate`)) == "down")
|
||||
config[wdev] = {};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function usage()
|
||||
@ -114,7 +109,7 @@ Commands:
|
||||
|
||||
const commands = {
|
||||
set_config: function(args) {
|
||||
let statefile = `/var/run/wdev-${phy}.json`;
|
||||
let statefile = `/var/run/wdev-${phy_name}.json`;
|
||||
|
||||
let new_config = shift(args);
|
||||
for (let dev in ARGV)
|
||||
@ -137,12 +132,12 @@ const commands = {
|
||||
if (type(old_config) == "object")
|
||||
config.data = old_config;
|
||||
|
||||
add_existing(phy, config.data);
|
||||
add_existing(phydev, config.data);
|
||||
add_ifname(config.data);
|
||||
drop_inactive(config.data);
|
||||
|
||||
let ubus = libubus.connect();
|
||||
let data = ubus.call("hostapd", "config_get_macaddr_list", { phy: phy });
|
||||
let data = ubus.call("hostapd", "config_get_macaddr_list", { phy: phydev.name, radio: phydev.radio ?? -1 });
|
||||
let macaddr_list = [];
|
||||
if (type(data) == "object" && data.macaddr)
|
||||
macaddr_list = data.macaddr;
|
||||
@ -166,7 +161,7 @@ const commands = {
|
||||
|
||||
let macaddr = phydev.macaddr_generate(data);
|
||||
if (!macaddr) {
|
||||
warn(`Could not get MAC address for phy ${phy}\n`);
|
||||
warn(`Could not get MAC address for phy ${phy_name}\n`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -174,12 +169,14 @@ const commands = {
|
||||
},
|
||||
};
|
||||
|
||||
if (!phy || !command | !commands[command])
|
||||
if (!phy_name || !command | !commands[command])
|
||||
usage();
|
||||
|
||||
phydev = phy_open(phy);
|
||||
let phy_split = split(phy_name, ":");
|
||||
phydev = phy_open(phy_split[0], phy_split[1]);
|
||||
phy = phydev.phy;
|
||||
if (!phydev) {
|
||||
warn(`PHY ${phy} does not exist\n`);
|
||||
warn(`PHY ${phy_name} does not exist\n`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,15 @@ function freq_to_channel(freq) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function freq_range_match(ranges, freq) {
|
||||
freq *= 1000;
|
||||
for (let range in ranges) {
|
||||
if (freq >= range[0] && freq <= range[1])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function wiphy_detect() {
|
||||
let phys = nl.request(nl.const.NL80211_CMD_GET_WIPHY, nl.const.NLM_F_DUMP, { split_wiphy_dump: true });
|
||||
if (!phys)
|
||||
@ -88,8 +97,27 @@ function wiphy_detect() {
|
||||
antenna_rx: phy.wiphy_antenna_avail_rx,
|
||||
antenna_tx: phy.wiphy_antenna_avail_tx,
|
||||
bands: {},
|
||||
radios: []
|
||||
};
|
||||
|
||||
for (let radio in phy.radios) {
|
||||
// S1G is not supported yet
|
||||
radio.freq_ranges = filter(radio.freq_ranges,
|
||||
(range) => range.end > 2000000
|
||||
);
|
||||
|
||||
if (!length(radio.freq_ranges))
|
||||
continue;
|
||||
|
||||
push(info.radios, {
|
||||
index: radio.index,
|
||||
freq_ranges: map(radio.freq_ranges,
|
||||
(range) => [ range.start, range.end ]
|
||||
),
|
||||
bands: {}
|
||||
});
|
||||
}
|
||||
|
||||
let bands = info.bands;
|
||||
for (let band in phy.wiphy_bands) {
|
||||
if (!band || !band.freqs)
|
||||
@ -160,6 +188,25 @@ function wiphy_detect() {
|
||||
if (eht_phy_cap && he_phy_cap & 2)
|
||||
push(modes, "EHT40");
|
||||
|
||||
for (let radio in info.radios) {
|
||||
let freq_match = filter(band.freqs,
|
||||
(freq) => freq_range_match(radio.freq_ranges, freq.freq)
|
||||
);
|
||||
if (!length(freq_match))
|
||||
continue;
|
||||
|
||||
let radio_band = {};
|
||||
radio.bands[band_name] = radio_band;
|
||||
|
||||
freq_match = filter(freq_match,
|
||||
(freq) => !freq.disabled
|
||||
);
|
||||
|
||||
let freq = freq_match[0];
|
||||
if (freq)
|
||||
radio_band.default_channel = freq_to_channel(freq.freq);
|
||||
}
|
||||
|
||||
for (let freq in band.freqs) {
|
||||
if (freq.disabled)
|
||||
continue;
|
||||
|
@ -1,6 +1,6 @@
|
||||
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";
|
||||
import { wdev_remove, is_equal, vlist_new, phy_is_fullmac, phy_open, wdev_set_radio_mask } from "common";
|
||||
|
||||
let ubus = libubus.connect(null, 60);
|
||||
|
||||
@ -56,7 +56,7 @@ function iface_remove(cfg)
|
||||
wdev_remove(bss.ifname);
|
||||
}
|
||||
|
||||
function iface_gen_config(phy, config, start_disabled)
|
||||
function iface_gen_config(config, start_disabled)
|
||||
{
|
||||
let str = `data:
|
||||
${join("\n", config.radio.data)}
|
||||
@ -117,7 +117,7 @@ function iface_freq_info(iface, config, params)
|
||||
|
||||
function iface_add(phy, config, phy_status)
|
||||
{
|
||||
let config_inline = iface_gen_config(phy, config, !!phy_status);
|
||||
let config_inline = iface_gen_config(config, !!phy_status);
|
||||
|
||||
let bss = config.bss[0];
|
||||
let ret = hostapd.add_iface(`bss_config=${phy}:${config_inline}`);
|
||||
@ -148,12 +148,16 @@ function iface_config_macaddr_list(config)
|
||||
return macaddr_list;
|
||||
}
|
||||
|
||||
function iface_update_supplicant_macaddr(phy, config)
|
||||
function iface_update_supplicant_macaddr(phydev, config)
|
||||
{
|
||||
let macaddr_list = [];
|
||||
for (let i = 0; i < length(config.bss); i++)
|
||||
push(macaddr_list, config.bss[i].bssid);
|
||||
ubus.defer("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list });
|
||||
ubus.defer("wpa_supplicant", "phy_set_macaddr_list", {
|
||||
phy: phydev.name,
|
||||
radio: phydev.radio ?? -1,
|
||||
macaddr: macaddr_list
|
||||
});
|
||||
}
|
||||
|
||||
function __iface_pending_next(pending, state, ret, data)
|
||||
@ -168,19 +172,22 @@ function __iface_pending_next(pending, state, ret, data)
|
||||
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 });
|
||||
iface_update_supplicant_macaddr(phydev, config);
|
||||
return "create_bss";
|
||||
case "create_bss":
|
||||
let err = wdev_create(phy, bss.ifname, { mode: "ap" });
|
||||
let err = phydev.wdev_add(bss.ifname, {
|
||||
mode: "ap",
|
||||
radio: phydev.radio,
|
||||
});
|
||||
if (err) {
|
||||
hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
pending.call("wpa_supplicant", "phy_status", { phy: phy });
|
||||
pending.call("wpa_supplicant", "phy_status", {
|
||||
phy: phydev.phy,
|
||||
radio: phydev.radio,
|
||||
});
|
||||
return "check_phy";
|
||||
case "check_phy":
|
||||
let phy_status = data;
|
||||
@ -190,12 +197,20 @@ function __iface_pending_next(pending, state, ret, data)
|
||||
|
||||
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 });
|
||||
pending.call("wpa_supplicant", "phy_set_state", {
|
||||
phy: phydev.phy,
|
||||
radio: phydev.radio,
|
||||
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 });
|
||||
pending.call("wpa_supplicant", "phy_set_state", {
|
||||
phy: phydev.phy,
|
||||
radio: phydev.radio,
|
||||
stop: false
|
||||
});
|
||||
return null;
|
||||
case "done":
|
||||
default:
|
||||
@ -210,9 +225,14 @@ function iface_pending_next(ret, data)
|
||||
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");
|
||||
try {
|
||||
this.next_state = __iface_pending_next(cfg, this.next_state, ret, data);
|
||||
if (!this.next_state) {
|
||||
__iface_pending_next(cfg, "done");
|
||||
return;
|
||||
}
|
||||
} catch(e) {
|
||||
hostapd.printf(`Exception: ${e}\n${e.stacktrace[0].context}`);
|
||||
return;
|
||||
}
|
||||
pending = !this.defer;
|
||||
@ -398,7 +418,7 @@ function get_config_bss(config, idx)
|
||||
return hostapd.bss[ifname];
|
||||
}
|
||||
|
||||
function iface_reload_config(phydev, config, old_config)
|
||||
function iface_reload_config(name, phydev, config, old_config)
|
||||
{
|
||||
let phy = phydev.name;
|
||||
|
||||
@ -408,13 +428,13 @@ function iface_reload_config(phydev, config, old_config)
|
||||
if (is_equal(old_config.bss, config.bss))
|
||||
return true;
|
||||
|
||||
if (hostapd.data.pending_config[phy])
|
||||
if (hostapd.data.pending_config[name])
|
||||
return false;
|
||||
|
||||
if (!old_config.bss || !old_config.bss[0])
|
||||
return false;
|
||||
|
||||
let iface = hostapd.interfaces[phy];
|
||||
let iface = hostapd.interfaces[name];
|
||||
let iface_name = old_config.bss[0].ifname;
|
||||
if (!iface) {
|
||||
hostapd.printf(`Could not find previous interface ${iface_name}`);
|
||||
@ -509,7 +529,7 @@ function iface_reload_config(phydev, config, old_config)
|
||||
return false;
|
||||
|
||||
let ifname = old_config.bss[i].ifname;
|
||||
hostapd.printf(`Remove bss '${ifname}' on phy '${phy}'`);
|
||||
hostapd.printf(`Remove bss '${ifname}' on phy '${name}'`);
|
||||
prev_bss.delete();
|
||||
wdev_remove(ifname);
|
||||
}
|
||||
@ -574,13 +594,13 @@ function iface_reload_config(phydev, config, old_config)
|
||||
|
||||
let addr = phydev.macaddr_next(i);
|
||||
if (!addr) {
|
||||
hostapd.printf(`Failed to generate mac address for phy ${phy}`);
|
||||
hostapd.printf(`Failed to generate mac address for phy ${name}`);
|
||||
return false;
|
||||
}
|
||||
bsscfg.bssid = addr;
|
||||
}
|
||||
|
||||
let config_inline = iface_gen_config(phy, config);
|
||||
let config_inline = iface_gen_config(config);
|
||||
|
||||
// Step 7: fill in the gaps with new interfaces
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
@ -590,17 +610,17 @@ function iface_reload_config(phydev, config, old_config)
|
||||
if (bss)
|
||||
continue;
|
||||
|
||||
hostapd.printf(`Add bss ${ifname} on phy ${phy}`);
|
||||
hostapd.printf(`Add bss ${ifname} on phy ${name}`);
|
||||
bss_list[i] = iface.add_bss(config_inline, i);
|
||||
if (!bss_list[i]) {
|
||||
hostapd.printf(`Failed to add new bss ${ifname} on phy ${phy}`);
|
||||
hostapd.printf(`Failed to add new bss ${ifname} on phy ${name}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 8: update interface bss order
|
||||
if (!iface.set_bss_order(bss_list)) {
|
||||
hostapd.printf(`Failed to update BSS order on phy '${phy}'`);
|
||||
hostapd.printf(`Failed to update BSS order on phy '${name}'`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -631,7 +651,7 @@ function iface_reload_config(phydev, config, old_config)
|
||||
if (is_equal(config.bss[i], bss_list_cfg[i]))
|
||||
continue;
|
||||
|
||||
hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${phy}'`);
|
||||
hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${name}'`);
|
||||
if (bss.set_config(config_inline, i) < 0) {
|
||||
hostapd.printf(`Failed to set config for bss ${ifname}`);
|
||||
return false;
|
||||
@ -641,35 +661,36 @@ function iface_reload_config(phydev, config, old_config)
|
||||
return true;
|
||||
}
|
||||
|
||||
function iface_set_config(phy, config)
|
||||
function iface_set_config(name, config)
|
||||
{
|
||||
let old_config = hostapd.data.config[phy];
|
||||
let old_config = hostapd.data.config[name];
|
||||
|
||||
hostapd.data.config[phy] = config;
|
||||
hostapd.data.config[name] = config;
|
||||
|
||||
if (!config) {
|
||||
hostapd.remove_iface(phy);
|
||||
hostapd.remove_iface(name);
|
||||
return iface_remove(old_config);
|
||||
}
|
||||
|
||||
let phydev = phy_open(phy);
|
||||
let phy = config.phy;
|
||||
let phydev = phy_open(phy, config.radio_idx);
|
||||
if (!phydev) {
|
||||
hostapd.printf(`Failed to open phy ${phy}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
let ret = iface_reload_config(phydev, config, old_config);
|
||||
let ret = iface_reload_config(name, phydev, config, old_config);
|
||||
if (ret) {
|
||||
iface_update_supplicant_macaddr(phy, config);
|
||||
hostapd.printf(`Reloaded settings for phy ${phy}`);
|
||||
iface_update_supplicant_macaddr(phydev, config);
|
||||
hostapd.printf(`Reloaded settings for phy ${name}`);
|
||||
return 0;
|
||||
}
|
||||
} catch (e) {
|
||||
hostapd.printf(`Error reloading config: ${e}\n${e.stacktrace[0].context}`);
|
||||
hostapd.printf(`Error reloading config: ${e}\n${e.stacktrace[0].context}`);
|
||||
}
|
||||
|
||||
hostapd.printf(`Restart interface for phy ${phy}`);
|
||||
hostapd.printf(`Restart interface for phy ${name}`);
|
||||
let ret = iface_restart(phydev, config, old_config);
|
||||
|
||||
return ret;
|
||||
@ -688,13 +709,18 @@ function config_add_bss(config, name)
|
||||
return bss;
|
||||
}
|
||||
|
||||
function iface_load_config(filename)
|
||||
function iface_load_config(phy, radio, filename)
|
||||
{
|
||||
let f = open(filename, "r");
|
||||
if (!f)
|
||||
return null;
|
||||
|
||||
if (radio < 0)
|
||||
radio = null;
|
||||
|
||||
let config = {
|
||||
phy,
|
||||
radio_idx: radio,
|
||||
radio: {
|
||||
data: []
|
||||
},
|
||||
@ -769,6 +795,17 @@ function ex_wrap(func) {
|
||||
};
|
||||
}
|
||||
|
||||
function phy_name(phy, radio)
|
||||
{
|
||||
if (!phy)
|
||||
return null;
|
||||
|
||||
if (radio != null && radio >= 0)
|
||||
phy += "." + radio;
|
||||
|
||||
return phy;
|
||||
}
|
||||
|
||||
function bss_config(bss_name) {
|
||||
for (let phy, config in hostapd.data.config) {
|
||||
if (!config)
|
||||
@ -784,12 +821,13 @@ let main_obj = {
|
||||
reload: {
|
||||
args: {
|
||||
phy: "",
|
||||
radio: 0,
|
||||
},
|
||||
call: ex_wrap(function(req) {
|
||||
let phy_list = req.args.phy ? [ req.args.phy ] : keys(hostapd.data.config);
|
||||
let phy_list = req.args.phy ? [ phy_name(req.args.phy, req.args.radio) ] : keys(hostapd.data.config);
|
||||
for (let phy_name in phy_list) {
|
||||
let phy = hostapd.data.config[phy_name];
|
||||
let config = iface_load_config(phy.orig_file);
|
||||
let config = iface_load_config(phy.phy, radio, phy.orig_file);
|
||||
iface_set_config(phy_name, config);
|
||||
}
|
||||
|
||||
@ -799,6 +837,7 @@ let main_obj = {
|
||||
apsta_state: {
|
||||
args: {
|
||||
phy: "",
|
||||
radio: 0,
|
||||
up: true,
|
||||
frequency: 0,
|
||||
sec_chan_offset: 0,
|
||||
@ -806,10 +845,10 @@ let main_obj = {
|
||||
csa_count: 0,
|
||||
},
|
||||
call: ex_wrap(function(req) {
|
||||
if (req.args.up == null || !req.args.phy)
|
||||
let phy = phy_name(req.args.phy, req.args.radio);
|
||||
if (req.args.up == null || !phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
let phy = req.args.phy;
|
||||
let config = hostapd.data.config[phy];
|
||||
if (!config || !config.bss || !config.bss[0] || !config.bss[0].ifname)
|
||||
return 0;
|
||||
@ -845,10 +884,11 @@ let main_obj = {
|
||||
},
|
||||
config_get_macaddr_list: {
|
||||
args: {
|
||||
phy: ""
|
||||
phy: "",
|
||||
radio: 0,
|
||||
},
|
||||
call: ex_wrap(function(req) {
|
||||
let phy = req.args.phy;
|
||||
let phy = phy_name(req.args.phy, req.args.radio);
|
||||
if (!phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
@ -867,31 +907,34 @@ let main_obj = {
|
||||
config_set: {
|
||||
args: {
|
||||
phy: "",
|
||||
radio: 0,
|
||||
config: "",
|
||||
prev_config: "",
|
||||
},
|
||||
call: ex_wrap(function(req) {
|
||||
let phy = req.args.phy;
|
||||
let radio = req.args.radio;
|
||||
let name = phy_name(phy, radio);
|
||||
let file = req.args.config;
|
||||
let prev_file = req.args.prev_config;
|
||||
|
||||
if (!phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
if (prev_file && !hostapd.data.config[phy]) {
|
||||
let config = iface_load_config(prev_file);
|
||||
if (prev_file && !hostapd.data.config[name]) {
|
||||
let config = iface_load_config(phy, radio, prev_file);
|
||||
if (config)
|
||||
config.radio.data = [];
|
||||
hostapd.data.config[phy] = config;
|
||||
hostapd.data.config[name] = config;
|
||||
}
|
||||
|
||||
let config = iface_load_config(file);
|
||||
let config = iface_load_config(phy, radio, file);
|
||||
|
||||
hostapd.printf(`Set new config for phy ${phy}: ${file}`);
|
||||
iface_set_config(phy, config);
|
||||
hostapd.printf(`Set new config for phy ${name}: ${file}`);
|
||||
iface_set_config(name, config);
|
||||
|
||||
if (hostapd.data.auth_obj)
|
||||
hostapd.data.auth_obj.notify("reload", { phy });
|
||||
hostapd.data.auth_obj.notify("reload", { phy, radio });
|
||||
|
||||
return {
|
||||
pid: hostapd.getpid()
|
||||
@ -975,10 +1018,18 @@ function bss_event(type, name, data) {
|
||||
return {
|
||||
shutdown: function() {
|
||||
for (let phy in hostapd.data.config)
|
||||
iface_set_config(phy, null);
|
||||
iface_set_config(phy);
|
||||
hostapd.udebug_set(null);
|
||||
hostapd.ubus.disconnect();
|
||||
},
|
||||
bss_create: function(phy, name, obj) {
|
||||
phy = hostapd.data.config[phy];
|
||||
if (!phy)
|
||||
return;
|
||||
|
||||
if (phy.radio_idx != null && phy.radio_idx >= 0)
|
||||
wdev_set_radio_mask(name, 1 << phy.radio_idx);
|
||||
},
|
||||
bss_add: function(phy, name, obj) {
|
||||
bss_event("add", name);
|
||||
},
|
||||
|
@ -37,7 +37,7 @@ function iface_start(phydev, iface, macaddr_list)
|
||||
|
||||
wpas.data.iface_phy[ifname] = phy;
|
||||
wdev_remove(ifname);
|
||||
let ret = wdev_create(phy, ifname, wdev_config);
|
||||
let ret = phydev.wdev_add(ifname, wdev_config);
|
||||
if (ret)
|
||||
wpas.printf(`Failed to create device ${ifname}: ${ret}`);
|
||||
wdev_set_up(ifname, true);
|
||||
@ -61,22 +61,27 @@ function iface_cb(new_if, old_if)
|
||||
iface_stop(old_if);
|
||||
}
|
||||
|
||||
function prepare_config(config)
|
||||
function prepare_config(config, radio)
|
||||
{
|
||||
config.config_data = readfile(config.config);
|
||||
|
||||
return { config: config };
|
||||
return { config };
|
||||
}
|
||||
|
||||
function set_config(phy_name, num_global_macaddr, config_list)
|
||||
function set_config(config_name, phy_name, radio, num_global_macaddr, config_list)
|
||||
{
|
||||
let phy = wpas.data.config[phy_name];
|
||||
let phy = wpas.data.config[config_name];
|
||||
|
||||
if (radio < 0)
|
||||
radio = null;
|
||||
|
||||
if (!phy) {
|
||||
phy = vlist_new(iface_cb, false);
|
||||
wpas.data.config[phy_name] = phy;
|
||||
phy.name = phy_name;
|
||||
wpas.data.config[config_name] = phy;
|
||||
}
|
||||
|
||||
phy.radio = radio;
|
||||
phy.num_global_macaddr = num_global_macaddr;
|
||||
|
||||
let values = [];
|
||||
@ -94,7 +99,7 @@ function start_pending(phy_name)
|
||||
if (!phy || !phy.data)
|
||||
return;
|
||||
|
||||
let phydev = phy_open(phy_name);
|
||||
let phydev = phy_open(phy.name, phy.radio);
|
||||
if (!phydev) {
|
||||
wpas.printf(`Could not open phy ${phy_name}`);
|
||||
return;
|
||||
@ -107,17 +112,30 @@ function start_pending(phy_name)
|
||||
iface_start(phydev, phy.data[ifname]);
|
||||
}
|
||||
|
||||
function phy_name(phy, radio)
|
||||
{
|
||||
if (!phy)
|
||||
return null;
|
||||
|
||||
if (radio != null && radio >= 0)
|
||||
phy += "." + radio;
|
||||
|
||||
return phy;
|
||||
}
|
||||
|
||||
let main_obj = {
|
||||
phy_set_state: {
|
||||
args: {
|
||||
phy: "",
|
||||
radio: 0,
|
||||
stop: true,
|
||||
},
|
||||
call: function(req) {
|
||||
if (!req.args.phy || req.args.stop == null)
|
||||
let name = phy_name(req.args.phy, req.args.radio);
|
||||
if (!name || req.args.stop == null)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
let phy = wpas.data.config[req.args.phy];
|
||||
let phy = wpas.data.config[name];
|
||||
if (!phy)
|
||||
return libubus.STATUS_NOT_FOUND;
|
||||
|
||||
@ -126,7 +144,7 @@ let main_obj = {
|
||||
for (let ifname in phy.data)
|
||||
iface_stop(phy.data[ifname]);
|
||||
} else {
|
||||
start_pending(req.args.phy);
|
||||
start_pending(name);
|
||||
}
|
||||
} catch (e) {
|
||||
wpas.printf(`Error chaging state: ${e}\n${e.stacktrace[0].context}`);
|
||||
@ -138,10 +156,11 @@ let main_obj = {
|
||||
phy_set_macaddr_list: {
|
||||
args: {
|
||||
phy: "",
|
||||
radio: 0,
|
||||
macaddr: [],
|
||||
},
|
||||
call: function(req) {
|
||||
let phy = req.args.phy;
|
||||
let phy = phy_name(req.args.phy, req.args.radio);
|
||||
if (!phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
@ -151,13 +170,15 @@ let main_obj = {
|
||||
},
|
||||
phy_status: {
|
||||
args: {
|
||||
phy: ""
|
||||
phy: "",
|
||||
radio: 0,
|
||||
},
|
||||
call: function(req) {
|
||||
if (!req.args.phy)
|
||||
let phy = phy_name(req.args.phy, req.args.radio);
|
||||
if (!phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
let phy = wpas.data.config[req.args.phy];
|
||||
phy = wpas.data.config[phy];
|
||||
if (!phy)
|
||||
return libubus.STATUS_NOT_FOUND;
|
||||
|
||||
@ -187,21 +208,23 @@ let main_obj = {
|
||||
config_set: {
|
||||
args: {
|
||||
phy: "",
|
||||
radio: 0,
|
||||
num_global_macaddr: 0,
|
||||
config: [],
|
||||
defer: true,
|
||||
},
|
||||
call: function(req) {
|
||||
if (!req.args.phy)
|
||||
let phy = phy_name(req.args.phy, req.args.radio);
|
||||
if (!phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
wpas.printf(`Set new config for phy ${req.args.phy}`);
|
||||
wpas.printf(`Set new config for phy ${phy}`);
|
||||
try {
|
||||
if (req.args.config)
|
||||
set_config(req.args.phy, req.args.num_global_macaddr, req.args.config);
|
||||
set_config(phy, req.args.phy, req.args.radio, req.args.num_global_macaddr, req.args.config);
|
||||
|
||||
if (!req.args.defer)
|
||||
start_pending(req.args.phy);
|
||||
start_pending(phy);
|
||||
} catch (e) {
|
||||
wpas.printf(`Error loading config: ${e}\n${e.stacktrace[0].context}`);
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
Loading…
Reference in New Issue
Block a user