Files
wlan-ucentral-schema/command/cmd_wifiscan7.uc
John Crispin 52afdf8f1d fix wifi-scan on wifi-7 devices
Signed-off-by: John Crispin <john@phrozen.org>
2025-04-30 07:59:29 +02:00

154 lines
3.2 KiB
Ucode

import * as libubus from 'ubus';
import * as nl from 'nl80211';
let def = nl.const;
let scan = [];
if (!args)
args = {
active: true,
verbose: true,
override_dfs: true,
information_elements: true,
};
let ubus = libubus.connect();
function frequency_to_channel(freq) {
/* see 802.11-2007 17.3.8.3.2 and Annex J */
if (freq == 2484)
return 14;
else if (freq < 2484)
return (freq - 2407) / 5;
else if (freq >= 4910 && freq <= 4980)
return (freq - 4000) / 5;
else if (freq < 5935) /* DMG band lower limit */
return (freq - 5000) / 5;
else if (freq == 5935)
return 2;
else if (freq >= 5955 && freq <= 7115)
return ((freq - 5955) / 5) + 1;
else if (freq >= 58320 && freq <= 64800)
return (freq - 56160) / 2160;
return 0;
}
function override_dfs() {
if (!args?.override_dfs)
return;
for (let obj in ubus.list()) {
if (split(obj, '.')[0] != 'hostapd')
continue;
let status = ubus.call(obj, 'get_status');
if (!status)
continue;
if (status.freq < 5180 || status.freq > 5960)
continue;
ubus.call(obj, 'switch_chan', { freq: 5180, bcn_count: 10 });
sleep(5000);
break;
}
}
function trigger_scan() {
for (let obj in ubus.list()) {
let dev = split(obj, '.')[1];
if (split(obj, '.')[0] != 'hostapd' || !dev)
continue;
system(`iw dev ${dev} scan ap-force ${args.active ? "ssid ''" : "passive"}`);
printf('scan complete\n');
let res = nl.request(def.NL80211_CMD_GET_SCAN, def.NLM_F_DUMP, { dev });
for (let bss in res) {
bss = bss.bss;
let res = {
bssid: bss.bssid,
frequency: +bss.frequency,
channel: frequency_to_channel(+bss.frequency),
signal: +bss.signal_mbm / 100,
};
if (args.verbose) {
res.tsf = +bss.tsf;
res.last_seen = +bss.seen_ms_ago;
res.capability = +bss.capability;
res.ies = [];
}
for (let ie in bss.beacon_ies) {
switch (ie.type) {
case 0:
res.ssid = ie.data;
break;
case 11:
res.sta_count = ord(ie.data, 1) * 256 + ord(ie.data, 0);
res.ch_util = ord(ie.data, 2);
break;
case 114:
if (verbose)
res.meshid = ie.data;
break;
case 0x3d:
if (verbose)
res.ht_oper = b64enc(ie.data);
break;
case 0xc0:
if (verbose)
res.vht_oper = b64enc(ie.data);
break;
case 0xdd:
let oui = hexenc(substr(ie.data, 0, 3));
let type = ord(ie.data, 3);
let data = substr(ie.data, 4);
switch (oui) {
case '48d017':
res.tip_oui = true;
switch(type) {
case 1:
if (data)
res.tip_serial = data;
break;
case 2:
if (data)
res.tip_name = data;
break;
case 3:
if (data)
res.tip_network_id = data;
break;
}
break;
}
break;
default:
if (args.verbose)
push(res.ies, { type: ie.type, data: b64enc(ie.data) });
break;
}
}
if (args.periodic && !args.information_elements)
delete res.ies;
push(scan, res);
}
return;
}
}
override_dfs();
trigger_scan();
if (args.periodic) {
ctx.call('ucentral', 'send', {
method: 'wifiscan',
params: { data: scan }
});
return;
}
result_json({
error: 0,
text: "Success",
resultCode: 1,
scan,
});