local phy="$1"
local id="${macidx:-0}"
- local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)"
- local mask="$(cat /sys/class/ieee80211/${phy}/address_mask)"
-
- [ "$mask" = "00:00:00:00:00:00" ] && {
- mask="ff:ff:ff:ff:ff:ff";
-
- [ "$(wc -l < /sys/class/ieee80211/${phy}/addresses)" -gt $id ] && {
- addr="$(mac80211_get_addr "$phy" "$id")"
- [ -n "$addr" ] && {
- echo "$addr"
- return
- }
- }
- }
-
- local oIFS="$IFS"; IFS=":"; set -- $mask; IFS="$oIFS"
-
- local mask1=$1
- local mask6=$6
-
- local oIFS="$IFS"; IFS=":"; set -- $ref; IFS="$oIFS"
-
- macidx=$(($id + 1))
- [ "$((0x$mask1))" -gt 0 ] && {
- b1="0x$1"
- [ "$id" -gt 0 ] && \
- b1=$(($b1 ^ ((($id - !($b1 & 2)) << 2)) | 0x2))
- printf "%02x:%s:%s:%s:%s:%s" $b1 $2 $3 $4 $5 $6
- return
- }
-
- [ "$((0x$mask6))" -lt 255 ] && {
- printf "%s:%s:%s:%s:%s:%02x" $1 $2 $3 $4 $5 $(( 0x$6 ^ $id ))
- return
- }
-
- off2=$(( (0x$6 + $id) / 0x100 ))
- printf "%s:%s:%s:%s:%02x:%02x" \
- $1 $2 $3 $4 \
- $(( (0x$5 + $off2) % 0x100 )) \
- $(( (0x$6 + $id) % 0x100 ))
+ wdev_tool "$phy" get_macaddr id=$id
}
get_board_phy_name() (
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" '{}'
+ wdev_tool "$phy" set_config '{}'
}
drv_mac80211_setup() {
[ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy"
json_set_namespace wdev_uc prev
- wdev_tool "$phy" "$(json_dump)" $active_ifnames
+ wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames
json_set_namespace "$prev"
for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower
return null;
}
+function phy_sysfs_file(phy, name)
+{
+ return trim(readfile(`/sys/class/ieee80211/${phy}/${name}`));
+}
+
+function macaddr_split(str)
+{
+ return map(split(str, ":"), (val) => hex(val));
+}
+
+function macaddr_join(addr)
+{
+ return join(":", map(addr, (val) => sprintf("%02x", val)));
+}
+
+function wdev_generate_macaddr(phy, data)
+{
+ let idx = int(data.id ?? 0);
+ let mbssid = int(data.mbssid ?? 0) > 0;
+ let num_global = int(data.num_global ?? 1);
+ let use_global = !mbssid && idx < num_global;
+
+ let base_addr = phy_sysfs_file(phy, "macaddress");
+ 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) {
+ let addrs = split(phy_sysfs_file(phy, "addresses"), "\n");
+
+ if (idx < length(addrs))
+ return addrs[idx];
+
+ base_mask = "ff:ff:ff:ff:ff:ff";
+ }
+
+ let addr = macaddr_split(base_addr);
+ let mask = macaddr_split(base_mask);
+ let type;
+
+ if (mbssid)
+ type = "b5";
+ else if (use_global)
+ type = "add";
+ else if (mask[0] > 0)
+ type = "b1";
+ else if (mask[5] < 0xff)
+ type = "b5";
+ else
+ type = "add";
+
+ switch (type) {
+ case "b1":
+ if (!(addr[0] & 2))
+ idx--;
+ addr[0] |= 2;
+ addr[0] ^= idx << 2;
+ break;
+ case "b5":
+ if (mbssid)
+ addr[0] |= 2;
+ addr[5] ^= idx;
+ break;
+ default:
+ for (let i = 5; i > 0; i--) {
+ addr[i] += idx;
+ if (addr[i] < 256)
+ break;
+ addr[i] %= 256;
+ }
+ break;
+ }
+
+ return macaddr_join(addr);
+}
+
const vlist_proto = {
update: function(values, arg) {
let data = this.data;
}, vlist_proto);
}
-export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac };
+export { wdev_remove, wdev_create, wdev_generate_macaddr, is_equal, vlist_new, phy_is_fullmac };
#!/usr/bin/env ucode
'use strict';
-import { vlist_new, is_equal, wdev_create, wdev_remove } from "/usr/share/hostap/common.uc";
+import { vlist_new, is_equal, wdev_create, wdev_remove, wdev_generate_macaddr } from "/usr/share/hostap/common.uc";
import { readfile, writefile, basename, readlink, glob } from "fs";
let keep_devices = {};
let phy = shift(ARGV);
-let new_config = shift(ARGV);
+
const mesh_params = [
"mesh_retry_timeout", "mesh_confirm_timeout", "mesh_holding_timeout", "mesh_max_peer_links",
"mesh_max_retries", "mesh_ttl", "mesh_element_ttl", "mesh_hwmp_max_preq_retries",
}
}
+function usage()
+{
+ warn(`Usage: ${basename(sourcepath())} <phy> <command> [<arguments>]
-let statefile = `/var/run/wdev-${phy}.json`;
-
-for (let dev in ARGV)
- keep_devices[dev] = true;
-
-if (!phy || !new_config) {
- warn(`Usage: ${basename(sourcepath())} <phy> <config> [<device]...]\n`);
+Commands:
+ set_config <config> [<device]...] - set phy configuration
+ get_macaddr <id> - get phy MAC address for vif index <id>
+`);
exit(1);
}
-if (!readfile(`/sys/class/ieee80211/${phy}/index`)) {
- warn(`PHY ${phy} does not exist\n`);
- exit(1);
-}
+const commands = {
+ set_config: function(args) {
+ let statefile = `/var/run/wdev-${phy}.json`;
-new_config = json(new_config);
-if (!new_config) {
- warn("Invalid configuration\n");
- exit(1);
-}
+ let new_config = shift(args);
+ for (let dev in ARGV)
+ keep_devices[dev] = true;
+
+ if (!new_config)
+ usage();
+
+ new_config = json(new_config);
+ if (!new_config) {
+ warn("Invalid configuration\n");
+ exit(1);
+ }
-let old_config = readfile(statefile);
-if (old_config)
- old_config = json(old_config);
+ let old_config = readfile(statefile);
+ if (old_config)
+ old_config = json(old_config);
-let config = vlist_new(iface_cb);
-if (type(old_config) == "object")
- config.data = old_config;
+ let config = vlist_new(iface_cb);
+ if (type(old_config) == "object")
+ config.data = old_config;
-add_existing(phy, config.data);
-add_ifname(config.data);
-drop_inactive(config.data);
+ add_existing(phy, config.data);
+ add_ifname(config.data);
+ drop_inactive(config.data);
-add_ifname(new_config);
-config.update(new_config);
+ add_ifname(new_config);
+ config.update(new_config);
+
+ drop_inactive(config.data);
+ delete_ifname(config.data);
+ writefile(statefile, sprintf("%J", config.data));
+ },
+ get_macaddr: function(args) {
+ let data = {};
+
+ for (let arg in args) {
+ arg = split(arg, "=", 2);
+ data[arg[0]] = arg[1];
+ }
+
+ let macaddr = wdev_generate_macaddr(phy, data);
+ if (!macaddr) {
+ warn(`Could not get MAC address for phy ${phy}\n`);
+ exit(1);
+ }
+
+ print(macaddr + "\n");
+ },
+};
+
+let command = shift(ARGV);
+
+if (!phy || !command | !commands[command])
+ usage();
+
+if (!readfile(`/sys/class/ieee80211/${phy}/index`)) {
+ warn(`PHY ${phy} does not exist\n`);
+ exit(1);
+}
-drop_inactive(config.data);
-delete_ifname(config.data);
-writefile(statefile, sprintf("%J", config.data));
+commands[command](ARGV);