Skip to content

Commit d4ea9df

Browse files
committed
Wifi (NetBSD): add support
Untested
1 parent 08071e6 commit d4ea9df

File tree

2 files changed

+170
-1
lines changed

2 files changed

+170
-1
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ elseif(NetBSD)
797797
src/detection/uptime/uptime_bsd.c
798798
src/detection/users/users_linux.c
799799
src/detection/wallpaper/wallpaper_linux.c
800-
src/detection/wifi/wifi_nosupport.c
800+
src/detection/wifi/wifi_nbsd.c
801801
src/detection/wm/wm_nosupport.c
802802
src/detection/de/de_linux.c
803803
src/detection/wmtheme/wmtheme_linux.c

src/detection/wifi/wifi_nbsd.c

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#include "wifi.h"
2+
#include "common/io/io.h"
3+
#include "util/stringUtils.h"
4+
5+
#define COMPAT_FREEBSD_NET80211 1
6+
#include <sys/ioctl.h>
7+
#include <sys/socket.h>
8+
#include <net/if.h>
9+
#include <net/if_media.h>
10+
#include <net80211/ieee80211.h>
11+
#include <net80211/ieee80211_ioctl.h>
12+
13+
// ieee80211 header of NetBSD is full of mess. Add compatibility macros from FreeBSD
14+
#undef IEEE80211_IS_CHAN_ANYG
15+
#define IEEE80211_IS_CHAN_ANYG(x) (IEEE80211_IS_CHAN_PUREG(x) || IEEE80211_IS_CHAN_G(x))
16+
#undef IEEE80211_IS_CHAN_HT
17+
#define IEEE80211_IS_CHAN_HT(x) (((x)->ic_flags & IEEE80211_CHAN_HT) != 0)
18+
#undef IEEE80211_IS_CHAN_VHT
19+
#define IEEE80211_IS_CHAN_VHT(x) (((x)->ic_flags & IEEE80211_CHAN_VHT) != 0)
20+
21+
const char* ffDetectWifi(FFlist* result)
22+
{
23+
struct if_nameindex* infs = if_nameindex();
24+
if(!infs) {
25+
return "if_nameindex() failed";
26+
}
27+
28+
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
29+
if(sock < 0) {
30+
if_freenameindex(infs);
31+
return "socket() failed";
32+
}
33+
34+
for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i)
35+
{
36+
if (!ffStrStartsWith(i->if_name, "iwm")) {
37+
continue;
38+
}
39+
40+
FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
41+
ffStrbufInitS(&item->inf.description, i->if_name);
42+
ffStrbufInit(&item->inf.status);
43+
ffStrbufInit(&item->conn.status);
44+
ffStrbufInit(&item->conn.ssid);
45+
ffStrbufInit(&item->conn.bssid);
46+
ffStrbufInit(&item->conn.protocol);
47+
ffStrbufInit(&item->conn.security);
48+
item->conn.signalQuality = 0.0/0.0;
49+
item->conn.rxRate = 0.0/0.0;
50+
item->conn.txRate = 0.0/0.0;
51+
item->conn.channel = 0;
52+
item->conn.frequency = 0;
53+
54+
char ssid[IEEE80211_NWID_LEN + 1] = {};
55+
struct ieee80211req ireq = {};
56+
strlcpy(ireq.i_name, i->if_name, sizeof(ireq.i_name));
57+
ireq.i_type = IEEE80211_IOC_SSID;
58+
ireq.i_data = ssid;
59+
ireq.i_len = sizeof(ssid) - 1;
60+
61+
if (ioctl(sock, SIOCG80211, &ireq) < 0 || ireq.i_len == 0) {
62+
struct ifreq ifr;
63+
strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name));
64+
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
65+
ffStrbufSetStatic(&item->inf.status, "Unknown");
66+
} else {
67+
ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down");
68+
}
69+
ffStrbufAppendS(&item->conn.status, "Not associated");
70+
continue;
71+
}
72+
73+
ffStrbufSetStatic(&item->inf.status, "Up");
74+
ffStrbufSetStatic(&item->conn.status, "Associated");
75+
ffStrbufAppendNS(&item->conn.ssid, ireq.i_len, ssid);
76+
77+
uint8_t bssid[IEEE80211_ADDR_LEN] = {};
78+
ireq.i_type = IEEE80211_IOC_BSSID;
79+
ireq.i_data = bssid;
80+
ireq.i_len = sizeof(bssid);
81+
82+
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
83+
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X",
84+
bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
85+
}
86+
87+
struct ieee80211_channel curchan = {};
88+
ireq.i_type = IEEE80211_IOC_CHANNEL;
89+
ireq.i_data = &curchan;
90+
ireq.i_len = sizeof(curchan);
91+
92+
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
93+
// item->conn.channel = curchan.ic_ieee; // No ic_ieee in NetBSD
94+
item->conn.channel = ffWifiFreqToChannel(curchan.ic_freq);
95+
item->conn.frequency = curchan.ic_freq;
96+
97+
if (IEEE80211_IS_CHAN_FHSS(&curchan))
98+
ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)");
99+
if (IEEE80211_IS_CHAN_A(&curchan))
100+
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
101+
if (IEEE80211_IS_CHAN_B(&curchan))
102+
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
103+
if (IEEE80211_IS_CHAN_ANYG(&curchan))
104+
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
105+
106+
if (IEEE80211_IS_CHAN_HT(&curchan))
107+
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
108+
if (IEEE80211_IS_CHAN_VHT(&curchan))
109+
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
110+
#ifdef IEEE80211_IS_CHAN_HE
111+
if (IEEE80211_IS_CHAN_HE(&curchan))
112+
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
113+
#endif
114+
}
115+
116+
union {
117+
struct ieee80211req_sta_req req;
118+
uint8_t buf[1024];
119+
} stareq = {};
120+
memcpy(stareq.req.is_u.macaddr, bssid, sizeof(bssid));
121+
ireq.i_type = IEEE80211_IOC_STA_INFO;
122+
ireq.i_data = &stareq;
123+
ireq.i_len = sizeof(stareq);
124+
125+
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
126+
struct ieee80211req_sta_info* sta = stareq.req.info;
127+
if (sta->isi_len != 0) {
128+
int8_t rssi = (int8_t) sta->isi_rssi; // This is strange
129+
item->conn.signalQuality = (rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2);
130+
131+
if (sta->isi_txrate) {
132+
item->conn.txRate = (double)sta->isi_txrate / 2.0;
133+
}
134+
}
135+
}
136+
137+
ireq.i_type = IEEE80211_IOC_AUTHMODE;
138+
ireq.i_data = NULL;
139+
ireq.i_len = 0;
140+
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
141+
switch (ireq.i_val) {
142+
case IEEE80211_AUTH_NONE:
143+
ffStrbufSetStatic(&item->conn.security, "Insecure");
144+
break;
145+
case IEEE80211_AUTH_OPEN:
146+
ffStrbufSetStatic(&item->conn.security, "Open");
147+
break;
148+
case IEEE80211_AUTH_SHARED:
149+
ffStrbufSetStatic(&item->conn.security, "Shared");
150+
break;
151+
case IEEE80211_AUTH_8021X:
152+
ffStrbufSetStatic(&item->conn.security, "8021X");
153+
break;
154+
case IEEE80211_AUTH_AUTO:
155+
ffStrbufSetStatic(&item->conn.security, "Auto");
156+
break;
157+
case IEEE80211_AUTH_WPA:
158+
ffStrbufSetStatic(&item->conn.security, "WPA");
159+
break;
160+
default:
161+
ffStrbufSetF(&item->conn.security, "Unknown (%d)", ireq.i_val);
162+
break;
163+
}
164+
}
165+
}
166+
167+
if_freenameindex(infs);
168+
return NULL;
169+
}

0 commit comments

Comments
 (0)