diff --git a/armsrc/appmain.c b/armsrc/appmain.c index f9138411b..b14b938f0 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -3862,6 +3862,7 @@ static void PacketReceived(PacketCommandNG *packet) { reply_ng(CMD_PM5_BWM_CHARGE_EN, ok ? PM3_SUCCESS : PM3_EFAILED, NULL, 0); break; } + case CMD_PM5_BWM_WIFI: { #if defined(WITH_BWM_FORWARD) uint8_t action = packet->data.asBytes[0]; @@ -3869,14 +3870,22 @@ static void PacketReceived(PacketCommandNG *packet) { int res; if (action == BWM_WIFI_ACTION_STOP) { res = bwm_wifi_forward_down(); + reply_ng(CMD_PM5_BWM_WIFI, res, (uint8_t *)&ip, sizeof(ip)); + } else if (action == BWM_WIFI_ACTION_STATUS) { + uint8_t connected = 0; + res = bwm_wifi_forward_status(&connected, &ip); + uint8_t st[5] = { connected, + (uint8_t)(ip & 0xFF), (uint8_t)((ip >> 8) & 0xFF), + (uint8_t)((ip >> 16) & 0xFF), (uint8_t)((ip >> 24) & 0xFF) }; + reply_ng(CMD_PM5_BWM_WIFI, res, st, sizeof(st)); } else { uint16_t port = packet->data.asBytes[1] | (packet->data.asBytes[2] << 8); char *ssid = (char *)&packet->data.asBytes[3]; char *pwd = ssid + strlen(ssid) + 1; char *host = pwd + strlen(pwd) + 1; res = bwm_wifi_forward_up(ssid, pwd, host, port, &ip); + reply_ng(CMD_PM5_BWM_WIFI, res, (uint8_t *)&ip, sizeof(ip)); } - reply_ng(CMD_PM5_BWM_WIFI, res, (uint8_t *)&ip, sizeof(ip)); #else reply_ng(CMD_PM5_BWM_WIFI, PM3_ENOTIMPL, NULL, 0); #endif diff --git a/armsrc/bwm_wifi.c b/armsrc/bwm_wifi.c index 9701eee48..abe081699 100644 --- a/armsrc/bwm_wifi.c +++ b/armsrc/bwm_wifi.c @@ -225,6 +225,23 @@ int bwm_wifi_forward_up(const char *ssid, const char *password, return PM3_SUCCESS; } +int bwm_wifi_forward_status(uint8_t *connected, uint32_t *ip_out) { + const uint32_t TO = 2000; + uint32_t ip = 0; + uint8_t ipb[12]; + uint16_t il = sizeof(ipb); + int r = bwm_cmd(BWM_CMD_GET_WIFI_CFG_IP_ADDR, NULL, 0, ipb, &il, TO); + if (r != PM3_SUCCESS) { + return r; // BWM / UART not responding + } + if (il >= 4) { + ip = (uint32_t)ipb[0] | ((uint32_t)ipb[1] << 8) | ((uint32_t)ipb[2] << 16) | ((uint32_t)ipb[3] << 24); + } + *ip_out = ip; + *connected = (ip != 0) ? 1 : 0; // a lease == a usable connection + return PM3_SUCCESS; +} + int bwm_wifi_forward_down(void) { // Single command: the BWM deinits the TCP server + disconnects the STA and // returns to BLE-only. It persists the disable mode to NVS. diff --git a/armsrc/bwm_wifi.h b/armsrc/bwm_wifi.h index da20fdab1..66ca9e924 100644 --- a/armsrc/bwm_wifi.h +++ b/armsrc/bwm_wifi.h @@ -19,7 +19,7 @@ // After association the STA reports "connected" before DHCP completes, so we // poll GET_IP until a non-zero address appears (or give up). #ifndef BWM_WIFI_DHCP_WAIT_MS -#define BWM_WIFI_DHCP_WAIT_MS 10000 // total time to wait for a DHCP lease +#define BWM_WIFI_DHCP_WAIT_MS 20000 // total time to wait for a DHCP lease #endif #ifndef BWM_WIFI_DHCP_POLL_MS #define BWM_WIFI_DHCP_POLL_MS 500 // gap between GET_IP polls @@ -52,4 +52,10 @@ int bwm_wifi_forward_up(const char *ssid, const char *password, // BLE-only). Persisted on the BWM so it stays off across reboots. int bwm_wifi_forward_down(void); +// Query current forward-mode connection state without reconfiguring. Writes the +// BWM IPv4 (host order, a in low byte; 0 if none) to *ip_out and 1/0 to +// *connected (true == has a DHCP lease). Returns PM3_EFAILED if the BWM/UART +// does not answer. +int bwm_wifi_forward_status(uint8_t *connected, uint32_t *ip_out); + #endif diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index f47e54dd0..0f99c9e16 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -1560,7 +1560,8 @@ static int CmdBWMWifi(const char *Cmd) { "Bring up the BWM in STA + TCP-server mode: join a WiFi network and\n" "start a TCP server so the client can connect over WiFi. PM5 only.", "hw bwmwifi --ssid Home --pwd secret --> port 7777\n" - "hw bwmwifi --ssid Home --pwd secret --port 9000"); + "hw bwmwifi --ssid Home --pwd secret --port 9000\n" + "hw bwmwifi --status --> show connection state + IP"); void *argtable[] = { arg_param_begin, @@ -1569,6 +1570,7 @@ static int CmdBWMWifi(const char *Cmd) { arg_int0(NULL, "port", "", "TCP server listen port (default 7777)"), arg_str0(NULL, "hostname", "", "DHCP hostname (default Proxmark5)"), arg_lit0(NULL, "stop", "tear down WiFi and return to BLE-only"), + arg_lit0(NULL, "status", "show current WiFi connection state + IP"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1591,8 +1593,38 @@ static int CmdBWMWifi(const char *Cmd) { host_len = 9; } bool stop = arg_get_lit(ctx, 5); + bool status = arg_get_lit(ctx, 6); CLIParserFree(ctx); + if (status) { + uint8_t q[1] = { BWM_WIFI_ACTION_STATUS }; + clearCommandBuffer(); + SendCommandNG(CMD_PM5_BWM_WIFI, q, sizeof(q)); + PacketResponseNG r; + if (WaitForResponseTimeout(CMD_PM5_BWM_WIFI, &r, 5000) == false) { + PrintAndLogEx(WARNING, "command timeout (is this a PM5 with a BWM fitted?)"); + return PM3_ETIMEOUT; + } + if (r.status != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "could not query BWM WiFi status (BWM present?)"); + return r.status; + } + uint8_t connected = (r.length >= 1) ? r.data.asBytes[0] : 0; + uint32_t ip = 0; + if (r.length >= 5) { + ip = r.data.asBytes[1] | (r.data.asBytes[2] << 8) | (r.data.asBytes[3] << 16) | ((uint32_t)r.data.asBytes[4] << 24); + } + if (connected && ip) { + PrintAndLogEx(SUCCESS, "BWM WiFi connected, IP " _YELLOW_("%u.%u.%u.%u"), + ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (ip >> 24) & 0xFF); + PrintAndLogEx(HINT, "Connect with: " _YELLOW_("pm3 -p tcp:%u.%u.%u.%u:"), + ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (ip >> 24) & 0xFF); + } else { + PrintAndLogEx(INFO, "BWM WiFi not connected (no IP). If a join is in progress, re-check in a few seconds."); + } + return PM3_SUCCESS; + } + if (stop) { uint8_t off[1] = { BWM_WIFI_ACTION_STOP }; clearCommandBuffer(); @@ -1640,13 +1672,14 @@ static int CmdBWMWifi(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_PM5_BWM_WIFI, data, n); PacketResponseNG resp; - // ARM blocks during the join (WAIT is up to ~15s), so allow a long client timeout - if (WaitForResponseTimeout(CMD_PM5_BWM_WIFI, &resp, 40000) == false) { + // ARM blocks during join + DHCP wait, so allow a long client timeout + if (WaitForResponseTimeout(CMD_PM5_BWM_WIFI, &resp, 60000) == false) { PrintAndLogEx(WARNING, "command timeout (is this a PM5 with a BWM fitted?)"); return PM3_ETIMEOUT; } if (resp.status != PM3_SUCCESS) { PrintAndLogEx(FAILED, "BWM WiFi bring-up failed (check SSID/password and signal)"); + PrintAndLogEx(HINT, "If it may have joined after DHCP, check: " _YELLOW_("hw bwmwifi --status")); return resp.status; } diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index accbb374f..a60d30689 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -860,6 +860,7 @@ typedef struct { // CMD_PM5_BWM_WIFI payload: [action:u8][port:u16 LE][ssid\0][pwd\0][hostname\0] #define BWM_WIFI_ACTION_START 0x00 // join AP + start TCP server #define BWM_WIFI_ACTION_STOP 0x01 // tear down, back to BLE-only +#define BWM_WIFI_ACTION_STATUS 0x02 // query current connection state + IP // For low-frequency tags #define CMD_LF_TI_READ 0x0202 #define CMD_LF_TI_WRITE 0x0203