Wifi (OpenBSD): fortifies detection and adds channel to frequency helper

This commit is contained in:
Carter Li
2026-08-20 16:04:00 +08:00
parent b1f2bf3526
commit 8b40117c08
2 changed files with 52 additions and 23 deletions
+16 -1
View File
@@ -19,7 +19,7 @@ struct FFWifiConnection {
double txRate;
uint16_t channel;
uint16_t channelWidth; // MHz
uint16_t frequency; // MHz
uint16_t frequency; // MHz
};
typedef struct FFWifiResult {
@@ -61,3 +61,18 @@ static inline uint16_t ffWifiFreqToChannel(uint16_t frequency) {
return 0;
}
static inline uint16_t ffWifiChannelToFreq(uint16_t channel) {
// Inverse of ffWifiFreqToChannel for the common 2.4 GHz and 5 GHz bands.
// 4.9 GHz and 6 GHz channels overlap numerically, so they are not handled here.
if (channel == 14) {
return 2484;
}
if (channel >= 1 && channel <= 13) {
return (uint16_t) (2407 + 5 * channel);
}
if (channel >= 36 && channel <= 177) { // 5 GHz: 5000 + 5*channel covers 36..177
return (uint16_t) (5000 + 5 * channel);
}
return 0;
}
+36 -22
View File
@@ -1,6 +1,5 @@
#include "wifi.h"
#include "common/io.h"
#include "common/strutil.h"
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -17,12 +16,20 @@ const char* ffDetectWifi(FFlist* result) {
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
if_freenameindex(infs);
return "socket() failed";
}
for (struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == nullptr); ++i) {
if (!ffStrStartsWith(i->if_name, "iwm")) {
continue;
struct ieee80211_nodereq nr = {};
strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname));
int err = 0;
if (ioctl(sock, SIOCG80211NODE, &nr) < 0) {
err = errno;
if (err == ENXIO || err == ENODEV || err == EINVAL || err == ENOTTY) {
continue; // Not a Wi-Fi interface
}
}
FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result);
@@ -37,12 +44,9 @@ const char* ffDetectWifi(FFlist* result) {
item->conn.rxRate = -DBL_MAX;
item->conn.txRate = -DBL_MAX;
item->conn.channel = 0;
item->conn.channelWidth = 0;
item->conn.channelWidth = 0; // not exposed by ieee80211_nodereq
item->conn.frequency = 0;
struct ieee80211_nodereq nr = {};
strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname));
struct ifreq ifr = {};
strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name));
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
@@ -51,31 +55,34 @@ const char* ffDetectWifi(FFlist* result) {
ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down");
}
if (ioctl(sock, SIOCG80211NODE, &nr) < 0) {
ffStrbufSetStatic(&item->conn.status, "Not associated");
continue;
}
if (nr.nr_nwid_len > 0) {
ffStrbufSetStatic(&item->conn.status, "Associated");
ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*) nr.nr_nwid);
} else {
if (err != 0 || nr.nr_nwid_len == 0) {
ffStrbufSetStatic(&item->conn.status, "Not associated");
continue;
}
ffStrbufSetStatic(&item->conn.status, "Associated");
ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*) nr.nr_nwid);
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", nr.nr_bssid[0], nr.nr_bssid[1], nr.nr_bssid[2], nr.nr_bssid[3], nr.nr_bssid[4], nr.nr_bssid[5]);
item->conn.channel = nr.nr_channel;
if (item->conn.channel == 0) {
struct ieee80211chanreq chreq = {};
strlcpy(chreq.i_name, i->if_name, sizeof(chreq.i_name));
if (ioctl(sock, SIOCG80211CHANNEL, &chreq) >= 0) {
item->conn.channel = chreq.i_channel;
}
}
item->conn.frequency = ffWifiChannelToFreq(item->conn.channel);
if (nr.nr_max_rssi) {
item->conn.signalQuality = ((float) nr.nr_rssi / nr.nr_max_rssi) * 100.0;
item->conn.signalQuality = ((double) nr.nr_rssi / (double) nr.nr_max_rssi) * 100.0;
}
if (nr.nr_flags & IEEE80211_NODEREQ_HT) {
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
} else if (nr.nr_flags & IEEE80211_NODEREQ_VHT) {
// VHT implies HT, so test VHT first
if (nr.nr_flags & IEEE80211_NODEREQ_VHT) {
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
} else if (nr.nr_flags & IEEE80211_NODEREQ_HT) {
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_5GHZ) {
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_2GHZ) {
@@ -86,15 +93,22 @@ const char* ffDetectWifi(FFlist* result) {
strlcpy(wpa.i_name, i->if_name, sizeof(wpa.i_name));
if (ioctl(sock, SIOCG80211WPAPARMS, &wpa) >= 0 && wpa.i_enabled) {
if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) {
if (wpa.i_akms & IEEE80211_WPA_AKM_SAE) {
if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) {
ffStrbufSetStatic(&item->conn.security, "WPA2/WPA3");
} else {
ffStrbufSetStatic(&item->conn.security, "WPA3");
}
} else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) {
ffStrbufSetStatic(&item->conn.security, "WPA2");
} else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA1) {
ffStrbufSetStatic(&item->conn.security, "WPA");
} else {
ffStrbufSetStatic(&item->conn.security, "Unknown");
}
} else {
struct ieee80211_nwkey nwkey = {};
strlcpy(nwkey.i_name, i->if_name, sizeof(nwkey.i_name));
if (ioctl(sock, SIOCG80211NWKEY, &nwkey) >= 0) {
if (nwkey.i_wepon) {
ffStrbufSetStatic(&item->conn.security, "WEP");