Skip to content

Commit 41d6187

Browse files
committed
Wifi (FreeBSD): use ioctl to improve performance
And support more features
1 parent d4b175b commit 41d6187

File tree

1 file changed

+131
-60
lines changed

1 file changed

+131
-60
lines changed

src/detection/wifi/wifi_bsd.c

+131-60
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,152 @@
11
#include "wifi.h"
2-
#include "common/processing.h"
3-
#include "common/properties.h"
2+
#include "common/io/io.h"
43
#include "util/stringUtils.h"
54

6-
#include <net/if.h>
75
#include <stdio.h>
86
#include <string.h>
7+
#include <stdlib.h>
8+
#include <sys/ioctl.h>
9+
#include <sys/socket.h>
10+
#include <net/if.h>
11+
#include <net/if_media.h>
12+
#include <net80211/ieee80211_ioctl.h>
13+
#include <unistd.h>
914

1015
const char* ffDetectWifi(FFlist* result)
1116
{
1217
struct if_nameindex* infs = if_nameindex();
13-
if(!infs)
18+
if(!infs) {
1419
return "if_nameindex() failed";
20+
}
21+
22+
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
23+
if(sock < 0) {
24+
return "socket() failed";
25+
}
1526

1627
for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i)
1728
{
18-
if (!ffStrStartsWith(i->if_name, "wlan")) continue;
19-
FF_STRBUF_AUTO_DESTROY ifconfig = ffStrbufCreate();
20-
if (ffProcessAppendStdOut(&ifconfig, (char* const[]) {
21-
"ifconfig",
22-
i->if_name,
23-
NULL
24-
}) == NULL)
25-
{
26-
FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
27-
ffStrbufInitS(&item->inf.description, i->if_name);
28-
ffStrbufInit(&item->inf.status);
29-
ffStrbufInit(&item->conn.status);
30-
ffStrbufInit(&item->conn.ssid);
31-
ffStrbufInit(&item->conn.bssid);
32-
ffStrbufInit(&item->conn.protocol);
33-
ffStrbufInit(&item->conn.security);
34-
item->conn.signalQuality = 0.0/0.0;
35-
item->conn.rxRate = 0.0/0.0;
36-
item->conn.txRate = 0.0/0.0;
37-
item->conn.channel = 0;
38-
item->conn.frequency = 0;
39-
40-
ffParsePropLines(ifconfig.chars, "status: ", &item->conn.status);
41-
if (!ffStrbufEqualS(&item->conn.status, "associated"))
42-
continue;
43-
44-
ffParsePropLines(ifconfig.chars, "ssid ", &item->conn.ssid);
45-
if (item->conn.ssid.length)
46-
{
47-
// This doesn't work for quoted SSID values
48-
uint32_t idx = ffStrbufFirstIndexS(&item->conn.ssid, " bssid ");
49-
if (idx < item->conn.ssid.length)
50-
{
51-
ffStrbufSetS(&item->conn.bssid, item->conn.ssid.chars + idx + (uint32_t) strlen(" bssid "));
52-
ffStrbufSubstrBefore(&item->conn.ssid, idx);
53-
}
54-
55-
idx = ffStrbufFirstIndexS(&item->conn.ssid, " channel ");
56-
if (idx < item->conn.ssid.length)
57-
{
58-
const char* pchannel = item->conn.ssid.chars + idx + strlen(" channel ");
59-
sscanf(pchannel, "%hu (%hu MHz %*s)", &item->conn.channel, &item->conn.frequency);
60-
}
61-
62-
ffStrbufSubstrBefore(&item->conn.ssid, idx);
29+
if (!ffStrStartsWith(i->if_name, "wlan")) {
30+
continue;
31+
}
32+
33+
FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
34+
ffStrbufInitS(&item->inf.description, i->if_name);
35+
ffStrbufInit(&item->inf.status);
36+
ffStrbufInit(&item->conn.status);
37+
ffStrbufInit(&item->conn.ssid);
38+
ffStrbufInit(&item->conn.bssid);
39+
ffStrbufInit(&item->conn.protocol);
40+
ffStrbufInit(&item->conn.security);
41+
item->conn.signalQuality = 0.0/0.0;
42+
item->conn.rxRate = 0.0/0.0;
43+
item->conn.txRate = 0.0/0.0;
44+
item->conn.channel = 0;
45+
item->conn.frequency = 0;
46+
47+
char ssid[IEEE80211_NWID_LEN + 1] = {};
48+
struct ieee80211req ireq = {};
49+
strlcpy(ireq.i_name, i->if_name, sizeof(ireq.i_name));
50+
ireq.i_type = IEEE80211_IOC_SSID;
51+
ireq.i_data = ssid;
52+
ireq.i_len = sizeof(ssid) - 1;
53+
54+
if (ioctl(sock, SIOCG80211, &ireq) < 0 || ireq.i_len == 0) {
55+
struct ifreq ifr;
56+
strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name));
57+
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
58+
ffStrbufSetStatic(&item->inf.status, "Unknown");
59+
} else {
60+
ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down");
61+
}
62+
ffStrbufAppendS(&item->conn.status, "Not associated");
63+
continue;
64+
}
65+
66+
ffStrbufSetStatic(&item->inf.status, "Up");
67+
ffStrbufSetStatic(&item->conn.status, "Associated");
68+
ffStrbufAppendNS(&item->conn.ssid, ireq.i_len, ssid);
69+
70+
uint8_t bssid[IEEE80211_ADDR_LEN] = {};
71+
ireq.i_type = IEEE80211_IOC_BSSID;
72+
ireq.i_data = bssid;
73+
ireq.i_len = sizeof(bssid);
74+
75+
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
76+
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X",
77+
bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
78+
}
79+
80+
struct ieee80211_channel curchan = {};
81+
ireq.i_type = IEEE80211_IOC_CURCHAN;
82+
ireq.i_data = &curchan;
83+
ireq.i_len = sizeof(curchan);
84+
85+
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
86+
item->conn.channel = curchan.ic_ieee;
87+
item->conn.frequency = curchan.ic_freq;
88+
89+
if (IEEE80211_IS_CHAN_FHSS(&curchan))
90+
ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)");
91+
if (IEEE80211_IS_CHAN_A(&curchan))
92+
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
93+
if (IEEE80211_IS_CHAN_B(&curchan))
94+
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
95+
if (IEEE80211_IS_CHAN_ANYG(&curchan))
96+
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
97+
if (IEEE80211_IS_CHAN_HT(&curchan))
98+
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
99+
if (IEEE80211_IS_CHAN_VHT(&curchan))
100+
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
101+
}
102+
103+
union {
104+
struct ieee80211req_sta_req req;
105+
uint8_t buf[1024];
106+
} stareq = {};
107+
memcpy(stareq.req.is_u.macaddr, bssid, sizeof(bssid));
108+
ireq.i_type = IEEE80211_IOC_STA_INFO;
109+
ireq.i_data = &stareq;
110+
ireq.i_len = sizeof(stareq);
111+
112+
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
113+
struct ieee80211req_sta_info* sta = stareq.req.info;
114+
if (sta->isi_len != 0) {
115+
item->conn.signalQuality = (sta->isi_rssi >= -50 ? 100 : sta->isi_rssi <= -100 ? 0 : (sta->isi_rssi + 100) * 2);
116+
item->conn.rxRate = sta->isi_txmbps * 0.5;
63117
}
118+
}
64119

65-
ffParsePropLines(ifconfig.chars, "media: ", &item->conn.protocol);
66-
if (item->conn.protocol.length)
67-
{
68-
uint32_t index = ffStrbufFirstIndexS(&item->conn.protocol, " mode ");
69-
if (index == item->conn.protocol.length)
70-
ffStrbufClear(&item->conn.protocol);
71-
else
72-
{
73-
ffStrbufSubstrAfter(&item->conn.protocol, index + strlen(" mode ") - 1);
74-
ffStrbufPrependS(&item->conn.protocol, "802.");
75-
}
120+
ireq.i_type = IEEE80211_IOC_AUTHMODE;
121+
ireq.i_data = NULL;
122+
ireq.i_len = 0;
123+
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
124+
switch (ireq.i_val) {
125+
case IEEE80211_AUTH_NONE:
126+
ffStrbufSetStatic(&item->conn.security, "Insecure");
127+
break;
128+
case IEEE80211_AUTH_OPEN:
129+
ffStrbufSetStatic(&item->conn.security, "Open");
130+
break;
131+
case IEEE80211_AUTH_SHARED:
132+
ffStrbufSetStatic(&item->conn.security, "Shared");
133+
break;
134+
case IEEE80211_AUTH_8021X:
135+
ffStrbufSetStatic(&item->conn.security, "8021X");
136+
break;
137+
case IEEE80211_AUTH_AUTO:
138+
ffStrbufSetStatic(&item->conn.security, "Auto");
139+
break;
140+
case IEEE80211_AUTH_WPA:
141+
ffStrbufSetStatic(&item->conn.security, "WPA");
142+
break;
143+
default:
144+
ffStrbufSetF(&item->conn.security, "Unknown (%d)", ireq.i_val);
145+
break;
76146
}
77147
}
78148
}
79149

150+
if_freenameindex(infs);
80151
return NULL;
81152
}

0 commit comments

Comments
 (0)