feat: wi-fi - join WPA2/WPA3-PSK networks and carry traffic like ethernet

This commit is contained in:
2026-08-06 19:44:35 +02:00
parent a01e63c717
commit bbe1df62fd
40 changed files with 5878 additions and 272 deletions
+26 -1
View File
@@ -596,6 +596,26 @@ namespace montauk::abi {
uint16_t beaconInterval; // TU
};
// Association progress reported in WifiInfo.connState.
static constexpr uint32_t WIFI_CONN_IDLE = 0;
static constexpr uint32_t WIFI_CONN_CONTEXTS_UP = 1;
static constexpr uint32_t WIFI_CONN_AUTHENTICATING = 2;
static constexpr uint32_t WIFI_CONN_AUTHENTICATED = 3;
static constexpr uint32_t WIFI_CONN_ASSOCIATING = 4;
static constexpr uint32_t WIFI_CONN_ASSOCIATED = 5;
static constexpr uint32_t WIFI_CONN_HANDSHAKING = 6;
static constexpr uint32_t WIFI_CONN_CONNECTED = 7;
static constexpr uint32_t WIFI_CONN_FAILED = 8;
// Negative results from SYS_WIFI_CONNECT.
static constexpr int WIFI_ERR_NO_ADAPTER = -1; // no adapter, or not ready
static constexpr int WIFI_ERR_NOT_FOUND = -2; // SSID absent from the scan
static constexpr int WIFI_ERR_NEED_KEY = -3; // encrypted, no passphrase
static constexpr int WIFI_ERR_UNSUPPORTED = -4; // WPA3-SAE, WEP, enterprise
static constexpr int WIFI_ERR_AUTH = -5; // key exchange rejected
static constexpr int WIFI_ERR_TIMEOUT = -6; // AP never answered
static constexpr int WIFI_ERR_FAILED = -7; // anything else
// Adapter status (returned by SYS_WIFI_INFO).
struct WifiInfo {
uint8_t mac[6];
@@ -607,7 +627,12 @@ namespace montauk::abi {
char fwVersion[32];
uint64_t rxPackets;
uint32_t fwErrors;
uint32_t connState; // 0 idle, >0 connection setup in progress
uint32_t connState; // WIFI_CONN_*
uint64_t txPackets;
char ssid[36]; // network joined, empty when disconnected
uint8_t bssid[6];
uint8_t connected; // 1 once the link can carry IP traffic
uint8_t channel;
};
struct ThermalInfo {
+100 -17
View File
@@ -7,8 +7,10 @@
* wifi scan [seconds] scan for a specific duration (default 5, max 20)
* wifi info adapter, firmware and radio status
* wifi debug info plus raw counters, repeated scan detail
* wifi connect <ssid> bring up the firmware contexts for an open network
* wifi disconnect tear those contexts back down
* wifi connect <ssid> [passphrase]
* join a network (WPA2/WPA3-PSK or open)
* wifi status the network currently joined
* wifi disconnect leave it
*
* Copyright (c) 2026 Daniel Hammer
*/
@@ -85,6 +87,21 @@ static const char* state_name(uint8_t state) {
}
}
static const char* conn_state_name(uint32_t s) {
switch (s) {
case abi::WIFI_CONN_IDLE: return "not connected";
case abi::WIFI_CONN_CONTEXTS_UP: return "preparing radio";
case abi::WIFI_CONN_AUTHENTICATING: return "authenticating";
case abi::WIFI_CONN_AUTHENTICATED: return "authenticated";
case abi::WIFI_CONN_ASSOCIATING: return "associating";
case abi::WIFI_CONN_ASSOCIATED: return "associated";
case abi::WIFI_CONN_HANDSHAKING: return "exchanging keys";
case abi::WIFI_CONN_CONNECTED: return "connected";
case abi::WIFI_CONN_FAILED: return "failed";
default: return "unknown";
}
}
// A rough signal-quality bar from the RSSI: -50 dBm and up is excellent,
// -90 dBm and below is unusable.
static void put_signal_bar(int8_t rssi) {
@@ -159,15 +176,50 @@ static void print_info(const abi::WifiInfo& info, bool verbose) {
print(" channels : "); put_u64(info.channels);
print(" usable after regulatory filtering\n");
print(" scanning : "); print(info.scanning ? "yes" : "no"); print("\n");
print(" network : ");
if (info.ssid[0]) {
print(info.ssid);
print(" ("); print(conn_state_name(info.connState)); print(")");
} else {
print(conn_state_name(info.connState));
}
print("\n");
if (info.ssid[0]) {
print(" bssid : "); put_mac(info.bssid); print("\n");
}
if (verbose) {
print(" rx packets : "); put_u64(info.rxPackets); print("\n");
print(" tx packets : "); put_u64(info.txPackets); print("\n");
print(" fw errors : "); put_u64(info.fwErrors); print("\n");
print(" conn state : "); put_u64(info.connState);
print(" (0 = idle)\n");
print(" ("); print(conn_state_name(info.connState)); print(")\n");
}
}
static int cmd_status() {
abi::WifiInfo info;
if (wifi_info(&info) != 0 && !info.present) {
print("wifi: no supported Wi-Fi adapter found.\n");
return 1;
}
if (!info.connected) {
print("Not connected.");
if (info.connState != abi::WIFI_CONN_IDLE) {
print(" Currently "); print(conn_state_name(info.connState)); print(".");
}
print("\n");
return 1;
}
print("Connected to \""); print(info.ssid); print("\"\n");
print(" bssid : "); put_mac(info.bssid); print("\n");
print(" interface : wlan0 ("); put_mac(info.mac); print(")\n");
print(" rx / tx : "); put_u64(info.rxPackets);
print(" / "); put_u64(info.txPackets); print(" packets\n");
print("\nRun \"dhcp\" to pick up an address if you have not already.\n");
return 0;
}
static int cmd_scan(uint32_t seconds, bool verbose) {
abi::WifiInfo info;
if (!require_adapter(info)) return 1;
@@ -317,20 +369,44 @@ static int cmd_connect(const char* ssid, const char* password) {
print("Connecting to \""); print(ssid); print("\"...\n");
int rc = wifi_connect(ssid, password);
if (rc == 0) {
print("Firmware contexts are up.\n");
print("NOTE: the 802.11 authentication exchange is not implemented yet,\n");
print(" so this does not establish a usable link.\n");
print("Connected.\n");
print("Run \"dhcp\" to get an address, then the network is usable\n");
print("just like a wired connection.\n");
return 0;
}
if (rc == -2) {
print("wifi: \""); print(ssid); print("\" is encrypted (WPA2/WPA3).\n");
print(" Only open networks can be joined so far - the key exchange\n");
print(" is not implemented yet. Scanning is unaffected.\n");
return 1;
switch (rc) {
case abi::WIFI_ERR_NOT_FOUND:
print("wifi: \""); print(ssid); print("\" was not found in the last scan.\n");
print(" Run \"wifi scan\" first, and check the SSID spelling.\n");
break;
case abi::WIFI_ERR_NEED_KEY:
print("wifi: \""); print(ssid); print("\" is encrypted and needs a passphrase.\n");
print(" Usage: wifi connect "); print(ssid); print(" <passphrase>\n");
break;
case abi::WIFI_ERR_UNSUPPORTED:
print("wifi: \""); print(ssid); print("\" uses security this driver cannot do.\n");
print(" Supported: open, and WPA2/WPA3-PSK with CCMP or GCMP.\n");
print(" Not supported: WEP, the original WPA (TKIP), WPA3 SAE-only\n");
print(" networks, and 802.1X enterprise. Check klog for the detail.\n");
break;
case abi::WIFI_ERR_AUTH:
print("wifi: the key exchange was rejected - the passphrase is\n");
print(" probably wrong. Check it and try again.\n");
break;
case abi::WIFI_ERR_TIMEOUT:
print("wifi: the access point did not respond in time.\n");
print(" It may be out of range; \"wifi scan\" shows the signal.\n");
break;
case abi::WIFI_ERR_NO_ADAPTER:
print("wifi: the adapter is not ready.\n");
break;
default:
print("wifi: could not connect. See klog for the kernel-side detail.\n");
break;
}
print("wifi: \""); print(ssid); print("\" was not found in the last scan.\n");
print(" Run \"wifi scan\" first, and check the SSID spelling.\n");
return 1;
}
@@ -339,8 +415,9 @@ static void usage() {
print(" scan [seconds] scan and list nearby networks (default 5)\n");
print(" info adapter, firmware and radio status\n");
print(" debug diagnostics plus per-BSS scan detail\n");
print(" connect <ssid> bring up firmware contexts (open networks)\n");
print(" disconnect tear those contexts down\n\n");
print(" connect <ssid> [key] join a network (open or WPA2/WPA3-PSK)\n");
print(" status show the network currently joined\n");
print(" disconnect leave the current network\n\n");
print("With no command, runs a 5 second scan.\n");
}
@@ -363,14 +440,20 @@ extern "C" void _start() {
exit(cmd_info(false));
} else if (streq(cmd, "debug")) {
exit(cmd_debug());
} else if (streq(cmd, "status")) {
exit(cmd_status());
} else if (streq(cmd, "connect")) {
char ssid[40], pass[80];
if (!next_token(&rest, ssid, sizeof(ssid))) {
print("wifi: connect needs an SSID\n");
exit(1);
}
pass[0] = '\0';
next_token(&rest, pass, sizeof(pass));
// Everything after the SSID is the passphrase, spaces and all.
const char* p = skip_spaces(rest);
int n = 0;
while (p[n] && n < (int)sizeof(pass) - 1) { pass[n] = p[n]; n++; }
while (n > 0 && pass[n - 1] == ' ') n--;
pass[n] = '\0';
exit(cmd_connect(ssid, pass));
} else if (streq(cmd, "disconnect")) {
wifi_disconnect();