Skip to content

Commit

Permalink
add new wifi-scanning code
Browse files Browse the repository at this point in the history
Signed-off-by: John Crispin <john@phrozen.org>
  • Loading branch information
blogic committed Jan 25, 2022
1 parent 8f5beb1 commit f926153
Showing 1 changed file with 173 additions and 9 deletions.
182 changes: 173 additions & 9 deletions command/cmd_wifiscan.uc
Original file line number Diff line number Diff line change
@@ -1,13 +1,177 @@
{%
let verbose = args.verbose ? true : false;
let active = args.active ? true : false;
ctx.call("wifi", "scan", { active });
system("sleep 5");
let scan = ctx.call("wifi", "scan_dump", {verbose});
let verbose = args?.verbose ? true : false;
let active = args?.active ? true : false;
let nl = require("nl80211");
let def = nl.const;

const SCAN_FLAG_AP = (1<<2);
const frequency_list_2g = [ 2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484 ];
const frequency_list_5g = { '3': [ 5180, 5260, 5500, 5580, 5660, 5745 ],
'2': [ 5180, 5220, 5260, 5300, 5500, 5540,
5580, 5620, 5660, 5745, 5785, 5825,
5865, 5920, 5960 ],
'1': [ 5180, 5200, 5220, 5240, 5260, 5280,
5300, 5320, 5500, 5520, 5540, 5560,
5580, 5600, 5620, 5640, 5660, 5680,
5700, 5720, 5745, 5765, 5785, 5805,
5825, 5845, 5865, 5885 ],
};
const frequency_offset = { '80': 30, '40': 10 };
const frequency_width = { '80': 3, '40': 20, '20': 1 };
const IFTYPE_STATION = 2;
const IFTYPE_AP = 3;
const IFTYPE_MESH = 7;

function iface_get(wdev) {
let params = { dev: wdev };
let res = nl.request(def.NL80211_CMD_GET_INTERFACE, wdev ? null : def.NLM_F_DUMP, wdev ? params : null);

if (res === false)
warn("Unable to lookup interface: " + nl.error() + "\n");
return res || [];
}

function iface_find(wiphy, types, ifaces) {
if (!ifaces)
ifaces = iface_get();
for (let iface in ifaces) {
if (iface.wiphy != wiphy)
continue;
if (iface.iftype in types)
return iface;
}
return;
}

function scan_trigger(wdev, frequency, width) {
let params = { dev: wdev, scan_flags: SCAN_FLAG_AP };

if (frequency && type(frequency) == 'array') {
params.scan_frequencies = frequency;
}
else if (frequency && width) {
params.wiphy_freq = frequency;
params.center_freq1 = frequency + frequency_offset[width];
params.channel_width = frequency_width[width];
}

if (active)
params.scan_ssids = [ '' ];

//printf("%.J\n", params);
let res = nl.request(def.NL80211_CMD_TRIGGER_SCAN, 0, params);

if (res === false)
die("Unable to trigger scan: " + nl.error() + "\n");

res = nl.waitfor([
def.NL80211_CMD_NEW_SCAN_RESULTS,
def.NL80211_CMD_SCAN_ABORTED
], (frequency && width) ? 500 : 5000);

if (!res)
warn("Netlink error while awaiting scan results: " + nl.error() + "\n");

else if (res.cmd == def.NL80211_CMD_SCAN_ABORTED)
warn("Scan aborted by kernel\n");
}

function trigger_scan_width(wdev, freqs, width) {
for (let freq in freqs)
scan_trigger(wdev, freq, width);
}

function phy_get(wdev) {
let res = nl.request(def.NL80211_CMD_GET_WIPHY, def.NLM_F_DUMP, { split_wiphy_dump: true });

if (res === false)
warn("Unable to lookup phys: " + nl.error() + "\n");

return res;
}

function phy_get_frequencies(phy) {
let freqs = [];

for (let band in phy.wiphy_bands) {
for (let freq in band?.freqs || [])
if (!freq.disabled)
push(freqs, freq.freq);
}
return freqs;
}

let phys = phy_get();
let ifaces = iface_get();

function intersect(list, filter) {
let res = [];

for (let item in list)
if (index(filter, item) >= 0)
push(res, item);
return res;
}

function wifi_scan() {
let scan = [];

for (let phy in phys) {
let iface = iface_find(phy.wiphy, [ IFTYPE_STATION, IFTYPE_AP ], ifaces);
if (!iface) {
warn('no valid interface found for phy' + phy.wiphy + '\n');
break;
}

let freqs = phy_get_frequencies(phy);
if (length(intersect(freqs, frequency_list_2g)))
scan_trigger(iface.dev, frequency_list_2g);

let freqs_5g = intersect(freqs, frequency_list_5g[iface.channel_width]);
if (length(freqs_5g))
trigger_scan_width(iface.dev, freqs_5g, iface.channel_width);
let res = nl.request(def.NL80211_CMD_GET_SCAN, def.NLM_F_DUMP, { dev: iface.dev });
for (let bss in res) {
bss = bss.bss;
let res = {
bssid: bss.bssid,
tsf: +bss.tsf,
frequency: +bss.frequency,
signal: +bss.signal_mbm / 100,
last_seen: +bss.seen_ms_ago,
capability: +bss.capability,
};

for (let ie in bss.beacon_ies) {
switch (ie.type) {
case 0:
case 114:
res.ssid = ie.data;
break;
case 0x3d:
res.ht_oper = b64enc(ie.data);
break;
case 0xc0:
res.vht_oper = b64enc(ie.data);
break;
}
}

push(scan, res);
}
// printf("%.J\n", nl.request(def.NL80211_CMD_GET_SCAN, def.NLM_F_DUMP, { dev: iface.dev }));
}
printf("%.J\n", scan);
return scan;
}

let scan = wifi_scan();

result_json({
"error": 0,
"text": "Success",
"resultCode": 1,
scan: scan.scan
error: 0,
text: "Success",
resultCode: 1,
scan,
});
%}

0 comments on commit f926153

Please sign in to comment.