From 41d6187f11c8124027e80f4691601c7057750e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 22 Mar 2025 22:34:08 +0800 Subject: [PATCH] Wifi (FreeBSD): use ioctl to improve performance And support more features --- src/detection/wifi/wifi_bsd.c | 185 +++++++++++++++++++++++----------- 1 file changed, 128 insertions(+), 57 deletions(-) diff --git a/src/detection/wifi/wifi_bsd.c b/src/detection/wifi/wifi_bsd.c index e070b1e50..a11ffa38f 100644 --- a/src/detection/wifi/wifi_bsd.c +++ b/src/detection/wifi/wifi_bsd.c @@ -1,81 +1,152 @@ #include "wifi.h" -#include "common/processing.h" -#include "common/properties.h" +#include "common/io/io.h" #include "util/stringUtils.h" -#include #include #include +#include +#include +#include +#include +#include +#include +#include const char* ffDetectWifi(FFlist* result) { struct if_nameindex* infs = if_nameindex(); - if(!infs) + if(!infs) { return "if_nameindex() failed"; + } + + FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0); + if(sock < 0) { + return "socket() failed"; + } for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i) { - if (!ffStrStartsWith(i->if_name, "wlan")) continue; - FF_STRBUF_AUTO_DESTROY ifconfig = ffStrbufCreate(); - if (ffProcessAppendStdOut(&ifconfig, (char* const[]) { - "ifconfig", - i->if_name, - NULL - }) == NULL) - { - FFWifiResult* item = (FFWifiResult*) ffListAdd(result); - ffStrbufInitS(&item->inf.description, i->if_name); - ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->conn.status); - ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.bssid); - ffStrbufInit(&item->conn.protocol); - ffStrbufInit(&item->conn.security); - item->conn.signalQuality = 0.0/0.0; - item->conn.rxRate = 0.0/0.0; - item->conn.txRate = 0.0/0.0; - item->conn.channel = 0; - item->conn.frequency = 0; + if (!ffStrStartsWith(i->if_name, "wlan")) { + continue; + } - ffParsePropLines(ifconfig.chars, "status: ", &item->conn.status); - if (!ffStrbufEqualS(&item->conn.status, "associated")) - continue; + FFWifiResult* item = (FFWifiResult*) ffListAdd(result); + ffStrbufInitS(&item->inf.description, i->if_name); + ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->conn.status); + ffStrbufInit(&item->conn.ssid); + ffStrbufInit(&item->conn.bssid); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); + item->conn.signalQuality = 0.0/0.0; + item->conn.rxRate = 0.0/0.0; + item->conn.txRate = 0.0/0.0; + item->conn.channel = 0; + item->conn.frequency = 0; - ffParsePropLines(ifconfig.chars, "ssid ", &item->conn.ssid); - if (item->conn.ssid.length) - { - // This doesn't work for quoted SSID values - uint32_t idx = ffStrbufFirstIndexS(&item->conn.ssid, " bssid "); - if (idx < item->conn.ssid.length) - { - ffStrbufSetS(&item->conn.bssid, item->conn.ssid.chars + idx + (uint32_t) strlen(" bssid ")); - ffStrbufSubstrBefore(&item->conn.ssid, idx); - } + char ssid[IEEE80211_NWID_LEN + 1] = {}; + struct ieee80211req ireq = {}; + strlcpy(ireq.i_name, i->if_name, sizeof(ireq.i_name)); + ireq.i_type = IEEE80211_IOC_SSID; + ireq.i_data = ssid; + ireq.i_len = sizeof(ssid) - 1; - idx = ffStrbufFirstIndexS(&item->conn.ssid, " channel "); - if (idx < item->conn.ssid.length) - { - const char* pchannel = item->conn.ssid.chars + idx + strlen(" channel "); - sscanf(pchannel, "%hu (%hu MHz %*s)", &item->conn.channel, &item->conn.frequency); - } - - ffStrbufSubstrBefore(&item->conn.ssid, idx); + if (ioctl(sock, SIOCG80211, &ireq) < 0 || ireq.i_len == 0) { + struct ifreq ifr; + strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name)); + if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { + ffStrbufSetStatic(&item->inf.status, "Unknown"); + } else { + ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down"); } + ffStrbufAppendS(&item->conn.status, "Not associated"); + continue; + } - ffParsePropLines(ifconfig.chars, "media: ", &item->conn.protocol); - if (item->conn.protocol.length) - { - uint32_t index = ffStrbufFirstIndexS(&item->conn.protocol, " mode "); - if (index == item->conn.protocol.length) - ffStrbufClear(&item->conn.protocol); - else - { - ffStrbufSubstrAfter(&item->conn.protocol, index + strlen(" mode ") - 1); - ffStrbufPrependS(&item->conn.protocol, "802."); - } + ffStrbufSetStatic(&item->inf.status, "Up"); + ffStrbufSetStatic(&item->conn.status, "Associated"); + ffStrbufAppendNS(&item->conn.ssid, ireq.i_len, ssid); + + uint8_t bssid[IEEE80211_ADDR_LEN] = {}; + ireq.i_type = IEEE80211_IOC_BSSID; + ireq.i_data = bssid; + ireq.i_len = sizeof(bssid); + + if (ioctl(sock, SIOCG80211, &ireq) >= 0) { + ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + } + + struct ieee80211_channel curchan = {}; + ireq.i_type = IEEE80211_IOC_CURCHAN; + ireq.i_data = &curchan; + ireq.i_len = sizeof(curchan); + + if (ioctl(sock, SIOCG80211, &ireq) >= 0) { + item->conn.channel = curchan.ic_ieee; + item->conn.frequency = curchan.ic_freq; + + if (IEEE80211_IS_CHAN_FHSS(&curchan)) + ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)"); + if (IEEE80211_IS_CHAN_A(&curchan)) + ffStrbufSetStatic(&item->conn.protocol, "802.11a"); + if (IEEE80211_IS_CHAN_B(&curchan)) + ffStrbufSetStatic(&item->conn.protocol, "802.11b"); + if (IEEE80211_IS_CHAN_ANYG(&curchan)) + ffStrbufSetStatic(&item->conn.protocol, "802.11g"); + if (IEEE80211_IS_CHAN_HT(&curchan)) + ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)"); + if (IEEE80211_IS_CHAN_VHT(&curchan)) + ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)"); + } + + union { + struct ieee80211req_sta_req req; + uint8_t buf[1024]; + } stareq = {}; + memcpy(stareq.req.is_u.macaddr, bssid, sizeof(bssid)); + ireq.i_type = IEEE80211_IOC_STA_INFO; + ireq.i_data = &stareq; + ireq.i_len = sizeof(stareq); + + if (ioctl(sock, SIOCG80211, &ireq) >= 0) { + struct ieee80211req_sta_info* sta = stareq.req.info; + if (sta->isi_len != 0) { + item->conn.signalQuality = (sta->isi_rssi >= -50 ? 100 : sta->isi_rssi <= -100 ? 0 : (sta->isi_rssi + 100) * 2); + item->conn.rxRate = sta->isi_txmbps * 0.5; + } + } + + ireq.i_type = IEEE80211_IOC_AUTHMODE; + ireq.i_data = NULL; + ireq.i_len = 0; + if (ioctl(sock, SIOCG80211, &ireq) >= 0) { + switch (ireq.i_val) { + case IEEE80211_AUTH_NONE: + ffStrbufSetStatic(&item->conn.security, "Insecure"); + break; + case IEEE80211_AUTH_OPEN: + ffStrbufSetStatic(&item->conn.security, "Open"); + break; + case IEEE80211_AUTH_SHARED: + ffStrbufSetStatic(&item->conn.security, "Shared"); + break; + case IEEE80211_AUTH_8021X: + ffStrbufSetStatic(&item->conn.security, "8021X"); + break; + case IEEE80211_AUTH_AUTO: + ffStrbufSetStatic(&item->conn.security, "Auto"); + break; + case IEEE80211_AUTH_WPA: + ffStrbufSetStatic(&item->conn.security, "WPA"); + break; + default: + ffStrbufSetF(&item->conn.security, "Unknown (%d)", ireq.i_val); + break; } } } + if_freenameindex(infs); return NULL; }