#include "wifi.h"
#include "common/processing.h"
#include "util/stringUtils.h"
#import <CoreWLAN/CoreWLAN.h>
static bool queryIpconfig(const char* ifName, FFstrbuf* result)
{
return ffProcessAppendStdOut(result, (char* const[]) {
"/usr/sbin/ipconfig",
"getsummary",
(char* const) ifName,
NULL
}) == NULL;
}
static bool getWifiInfoByIpconfig(FFstrbuf* ipconfig, const char* prefix, FFstrbuf* result)
{
const char* start = memmem(ipconfig->chars, ipconfig->length, prefix, strlen(prefix));
if (!start) return false;
start += strlen(prefix);
const char* end = strchr(start, '\n');
if (!end) return false;
ffStrbufSetNS(result, (uint32_t) (end - start), start);
return true;
}
const char* ffDetectWifi(FFlist* result)
{
NSArray<CWInterface*>* interfaces = CWWiFiClient.sharedWiFiClient.interfaces;
if (!interfaces)
return "CWWiFiClient.sharedWiFiClient.interfaces is nil";
for (CWInterface* inf in interfaces)
{
FFWifiResult* item = (FFWifiResult*)ffListAdd(result);
ffStrbufInit(&item->inf.description);
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;
ffStrbufAppendS(&item->inf.description, inf.interfaceName.UTF8String);
ffStrbufSetStatic(&item->inf.status, inf.powerOn ? "Power On" : "Power Off");
if(!inf.powerOn)
continue;
ffStrbufSetStatic(&item->conn.status, inf.interfaceMode != kCWInterfaceModeNone ? "Active" : "Inactive");
if(inf.interfaceMode == kCWInterfaceModeNone)
continue;
FF_STRBUF_AUTO_DESTROY ipconfig = ffStrbufCreate();
if (inf.ssid) ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String);
else if (ipconfig.length || (queryIpconfig(item->inf.description.chars, &ipconfig)))
getWifiInfoByIpconfig(&ipconfig, "\n SSID : ", &item->conn.ssid);
else
ffStrbufSetStatic(&item->conn.ssid, "<unknown ssid>");
if (inf.bssid)
ffStrbufAppendS(&item->conn.bssid, inf.bssid.UTF8String);
else if (ipconfig.length || (queryIpconfig(item->inf.description.chars, &ipconfig)))
getWifiInfoByIpconfig(&ipconfig, "\n BSSID : ", &item->conn.bssid);
switch(inf.activePHYMode)
{
case kCWPHYModeNone:
ffStrbufSetStatic(&item->conn.protocol, "none");
break;
case kCWPHYMode11a:
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
break;
case kCWPHYMode11b:
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
break;
case kCWPHYMode11g:
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
break;
case kCWPHYMode11n:
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
break;
case kCWPHYMode11ac:
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
break;
case 6 :
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
break;
case 7 :
ffStrbufSetStatic(&item->conn.protocol, "802.11be (Wi-Fi 7)");
break;
default:
if (inf.activePHYMode < 8)
ffStrbufAppendF(&item->conn.protocol, "Unknown (%ld)", inf.activePHYMode);
break;
}
item->conn.signalQuality = (double) (inf.rssiValue >= -50 ? 100 : inf.rssiValue <= -100 ? 0 : (inf.rssiValue + 100) * 2);
item->conn.txRate = inf.transmitRate;
switch(inf.security)
{
case kCWSecurityNone:
ffStrbufSetStatic(&item->conn.security, "Insecure");
break;
case kCWSecurityWEP:
ffStrbufSetStatic(&item->conn.security, "WEP");
break;
case kCWSecurityWPAPersonal:
ffStrbufSetStatic(&item->conn.security, "WPA Personal");
break;
case kCWSecurityWPAPersonalMixed:
ffStrbufSetStatic(&item->conn.security, "WPA Persional Mixed");
break;
case kCWSecurityWPA2Personal:
ffStrbufSetStatic(&item->conn.security, "WPA2 Personal");
break;
case kCWSecurityPersonal:
ffStrbufSetStatic(&item->conn.security, "Personal");
break;
case kCWSecurityDynamicWEP:
ffStrbufSetStatic(&item->conn.security, "Dynamic WEP");
break;
case kCWSecurityWPAEnterprise:
ffStrbufSetStatic(&item->conn.security, "WPA Enterprise");
break;
case kCWSecurityWPAEnterpriseMixed:
ffStrbufSetStatic(&item->conn.security, "WPA Enterprise Mixed");
break;
case kCWSecurityWPA2Enterprise:
ffStrbufSetStatic(&item->conn.security, "WPA2 Enterprise");
break;
case kCWSecurityEnterprise:
ffStrbufSetStatic(&item->conn.security, "Enterprise");
break;
case 11 :
ffStrbufSetStatic(&item->conn.security, "WPA3 Personal");
break;
case 12 :
ffStrbufSetStatic(&item->conn.security, "WPA3 Enterprise");
break;
case 13 :
ffStrbufSetStatic(&item->conn.security, "WPA3 Transition");
break;
case 14 :
ffStrbufSetStatic(&item->conn.security, "OWE");
break;
case 15 :
ffStrbufSetStatic(&item->conn.security, "OWE Transition");
break;
case kCWSecurityUnknown:
if (ipconfig.length || (queryIpconfig(item->inf.description.chars, &ipconfig)))
getWifiInfoByIpconfig(&ipconfig, "\n Security : ", &item->conn.security);
break;
default:
ffStrbufAppendF(&item->conn.security, "Unknown (%ld)", inf.security);
break;
}
item->conn.channel = (uint16_t) inf.wlanChannel.channelNumber;
switch (inf.wlanChannel.channelBand)
{
case kCWChannelBand2GHz: item->conn.frequency = 2400; break;
case kCWChannelBand5GHz: item->conn.frequency = 5400; break;
case 3 : item->conn.frequency = 6400; break;
default: item->conn.frequency = 0; break;
}
}
return NULL;
}