mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-20 18:05:54 +08:00
添加智能灯固件代码
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS "simple_sniffer_example_main.c"
|
||||
"cmd_sniffer.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,61 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config SNIFFER_STORE_HISTORY
|
||||
bool "Store command history into flash"
|
||||
default y
|
||||
help
|
||||
Linenoise line editing library provides functions to save and load command history.
|
||||
If this option is enabled, initalizes a FAT filesystem and uses it to store command history.
|
||||
|
||||
choice SNIFFER_PCAP_DESTINATION
|
||||
prompt "Select destination to store pcap file"
|
||||
default SNIFFER_PCAP_DESTINATION_SD if IDF_TARGET_ESP32
|
||||
default SNIFFER_PCAP_DESTINATION_JTAG if IDF_TARGET_ESP32S2
|
||||
help
|
||||
Select where to store the pcap file.
|
||||
Currently support storing files to SD card or to host via JTAG interface.
|
||||
config SNIFFER_PCAP_DESTINATION_SD
|
||||
bool "SD Card"
|
||||
help
|
||||
Store pcap file to SD card.
|
||||
config SNIFFER_PCAP_DESTINATION_JTAG
|
||||
bool "JTAG (App Trace)"
|
||||
help
|
||||
Store pcap file to host via JTAG interface.
|
||||
endchoice
|
||||
|
||||
if SNIFFER_PCAP_DESTINATION_SD
|
||||
config SNIFFER_MOUNT_POINT
|
||||
string "SD card mount point in the filesystem"
|
||||
default "/sdcard"
|
||||
help
|
||||
Specify the mount point in the VFS (Virtual File System) for SD card.
|
||||
|
||||
config SNIFFER_PCAP_FILE_NAME_MAX_LEN
|
||||
int "Max name length of pcap file"
|
||||
default 32
|
||||
help
|
||||
Specify maximum name length of pcap file.
|
||||
endif
|
||||
|
||||
config SNIFFER_WORK_QUEUE_LEN
|
||||
int "Length of sniffer work queue"
|
||||
default 128
|
||||
help
|
||||
The sniffer callback function should not do heavy work, so we put all heavy IO operation to another task.
|
||||
The task gets some basic info of sniffer packet via queue.
|
||||
Here you should specify the length of queue.
|
||||
|
||||
config SNIFFER_TASK_STACK_SIZE
|
||||
int "Stack size of sniffer task"
|
||||
default 4096
|
||||
help
|
||||
Stack size of sniffer task.
|
||||
|
||||
config SNIFFER_TASK_PRIORITY
|
||||
int "Priority of sniffer task"
|
||||
default 2
|
||||
help
|
||||
Priority of sniffer task.
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,395 @@
|
||||
/* cmd_sniffer example.
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "cmd_sniffer.h"
|
||||
#include "pcap.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define SNIFFER_DEFAULT_FILE_NAME "esp-sniffer"
|
||||
#define SNIFFER_FILE_NAME_MAX_LEN CONFIG_SNIFFER_PCAP_FILE_NAME_MAX_LEN
|
||||
#define SNIFFER_DEFAULT_CHANNEL (1)
|
||||
#define SNIFFER_PAYLOAD_FCS_LEN (4)
|
||||
#define SNIFFER_PROCESS_PACKET_TIMEOUT_MS (100)
|
||||
#define SNIFFER_PROCESS_APPTRACE_TIMEOUT_US (100)
|
||||
#define SNIFFER_APPTRACE_RETRY (10)
|
||||
|
||||
static const char *SNIFFER_TAG = "cmd_sniffer";
|
||||
#define SNIFFER_CHECK(a, str, goto_tag, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (!(a)) \
|
||||
{ \
|
||||
ESP_LOGE(SNIFFER_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
||||
goto goto_tag; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef struct {
|
||||
char *filter_name;
|
||||
uint32_t filter_val;
|
||||
} wlan_filter_table_t;
|
||||
|
||||
typedef struct {
|
||||
bool is_running;
|
||||
sniffer_intf_t interf;
|
||||
uint32_t channel;
|
||||
uint32_t filter;
|
||||
#if CONFIG_SNIFFER_PCAP_DESTINATION_SD
|
||||
char filename[SNIFFER_FILE_NAME_MAX_LEN];
|
||||
#endif
|
||||
pcap_handle_t pcap;
|
||||
TaskHandle_t task;
|
||||
QueueHandle_t work_queue;
|
||||
SemaphoreHandle_t sem_task_over;
|
||||
} sniffer_runtime_t;
|
||||
|
||||
typedef struct {
|
||||
void *payload;
|
||||
uint32_t length;
|
||||
uint32_t seconds;
|
||||
uint32_t microseconds;
|
||||
} sniffer_packet_info_t;
|
||||
|
||||
static sniffer_runtime_t snf_rt = {0};
|
||||
static wlan_filter_table_t wifi_filter_hash_table[SNIFFER_WLAN_FILTER_MAX] = {0};
|
||||
|
||||
static uint32_t hash_func(const char *str, uint32_t max_num)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
char *p = (char *)str;
|
||||
while (*p) {
|
||||
ret += *p;
|
||||
p++;
|
||||
}
|
||||
return ret % max_num;
|
||||
}
|
||||
|
||||
static void create_wifi_filter_hashtable(void)
|
||||
{
|
||||
char *wifi_filter_keys[SNIFFER_WLAN_FILTER_MAX] = {"mgmt", "data", "ctrl", "misc", "mpdu", "ampdu"};
|
||||
uint32_t wifi_filter_values[SNIFFER_WLAN_FILTER_MAX] = {WIFI_PROMIS_FILTER_MASK_MGMT, WIFI_PROMIS_FILTER_MASK_DATA,
|
||||
WIFI_PROMIS_FILTER_MASK_CTRL, WIFI_PROMIS_FILTER_MASK_MISC,
|
||||
WIFI_PROMIS_FILTER_MASK_DATA_MPDU, WIFI_PROMIS_FILTER_MASK_DATA_AMPDU
|
||||
};
|
||||
for (int i = 0; i < SNIFFER_WLAN_FILTER_MAX; i++) {
|
||||
uint32_t idx = hash_func(wifi_filter_keys[i], SNIFFER_WLAN_FILTER_MAX);
|
||||
while (wifi_filter_hash_table[idx].filter_name) {
|
||||
idx++;
|
||||
if (idx >= SNIFFER_WLAN_FILTER_MAX) {
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
wifi_filter_hash_table[idx].filter_name = wifi_filter_keys[i];
|
||||
wifi_filter_hash_table[idx].filter_val = wifi_filter_values[i];
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t search_wifi_filter_hashtable(const char *key)
|
||||
{
|
||||
uint32_t len = strlen(key);
|
||||
uint32_t start_idx = hash_func(key, SNIFFER_WLAN_FILTER_MAX);
|
||||
uint32_t idx = start_idx;
|
||||
while (strncmp(wifi_filter_hash_table[idx].filter_name, key, len)) {
|
||||
idx++;
|
||||
if (idx >= SNIFFER_WLAN_FILTER_MAX) {
|
||||
idx = 0;
|
||||
}
|
||||
/* wrong key */
|
||||
if (idx == start_idx) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return wifi_filter_hash_table[idx].filter_val;
|
||||
}
|
||||
|
||||
static void wifi_sniffer_cb(void *recv_buf, wifi_promiscuous_pkt_type_t type)
|
||||
{
|
||||
sniffer_packet_info_t packet_info;
|
||||
wifi_promiscuous_pkt_t *sniffer = (wifi_promiscuous_pkt_t *)recv_buf;
|
||||
/* prepare packet_info */
|
||||
packet_info.seconds = sniffer->rx_ctrl.timestamp / 1000000U;
|
||||
packet_info.microseconds = sniffer->rx_ctrl.timestamp % 1000000U;
|
||||
packet_info.length = sniffer->rx_ctrl.sig_len;
|
||||
/* For now, the sniffer only dumps the length of the MISC type frame */
|
||||
if (type != WIFI_PKT_MISC && !sniffer->rx_ctrl.rx_state) {
|
||||
packet_info.length -= SNIFFER_PAYLOAD_FCS_LEN;
|
||||
void *backup = malloc(packet_info.length);
|
||||
if (backup) {
|
||||
memcpy(backup, sniffer->payload, packet_info.length);
|
||||
packet_info.payload = backup;
|
||||
if (snf_rt.work_queue) {
|
||||
/* send packet_info */
|
||||
if (xQueueSend(snf_rt.work_queue, &packet_info, pdMS_TO_TICKS(SNIFFER_PROCESS_PACKET_TIMEOUT_MS)) != pdTRUE) {
|
||||
ESP_LOGE(SNIFFER_TAG, "sniffer work queue full");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(SNIFFER_TAG, "No enough memory for promiscuous packet");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sniffer_task(void *parameters)
|
||||
{
|
||||
sniffer_packet_info_t packet_info;
|
||||
sniffer_runtime_t *sniffer = (sniffer_runtime_t *)parameters;
|
||||
|
||||
while (sniffer->is_running) {
|
||||
/* receive paclet info from queue */
|
||||
if (xQueueReceive(sniffer->work_queue, &packet_info, pdMS_TO_TICKS(SNIFFER_PROCESS_PACKET_TIMEOUT_MS)) != pdTRUE) {
|
||||
continue;
|
||||
}
|
||||
if (pcap_capture_packet(sniffer->pcap, packet_info.payload, packet_info.length,
|
||||
packet_info.seconds, packet_info.microseconds) != ESP_OK) {
|
||||
ESP_LOGW(SNIFFER_TAG, "save captured packet failed");
|
||||
}
|
||||
free(packet_info.payload);
|
||||
}
|
||||
/* notify that sniffer task is over */
|
||||
xSemaphoreGive(sniffer->sem_task_over);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static esp_err_t sniffer_stop(sniffer_runtime_t *sniffer)
|
||||
{
|
||||
SNIFFER_CHECK(sniffer->is_running, "sniffer is already stopped", err);
|
||||
|
||||
switch (sniffer->interf) {
|
||||
case SNIFFER_INTF_WLAN:
|
||||
/* Disable wifi promiscuous mode */
|
||||
SNIFFER_CHECK(esp_wifi_set_promiscuous(false) == ESP_OK, "stop wifi promiscuous failed", err);
|
||||
break;
|
||||
default:
|
||||
SNIFFER_CHECK(false, "unsupported interface", err);
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(SNIFFER_TAG, "stop WiFi promiscuous ok");
|
||||
|
||||
/* stop sniffer local task */
|
||||
sniffer->is_running = false;
|
||||
/* wait for task over */
|
||||
xSemaphoreTake(sniffer->sem_task_over, portMAX_DELAY);
|
||||
vSemaphoreDelete(sniffer->sem_task_over);
|
||||
sniffer->sem_task_over = NULL;
|
||||
/* make sure to free all resources in the left items */
|
||||
UBaseType_t left_items = uxQueueMessagesWaiting(sniffer->work_queue);
|
||||
sniffer_packet_info_t packet_info;
|
||||
while (left_items--) {
|
||||
xQueueReceive(sniffer->work_queue, &packet_info, pdMS_TO_TICKS(SNIFFER_PROCESS_PACKET_TIMEOUT_MS));
|
||||
free(packet_info.payload);
|
||||
}
|
||||
vQueueDelete(sniffer->work_queue);
|
||||
sniffer->work_queue = NULL;
|
||||
/* stop pcap session */
|
||||
SNIFFER_CHECK(pcap_deinit(sniffer->pcap) == ESP_OK, "stop pcap session failed", err);
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
|
||||
static int trace_writefun(void *cookie, const char *buf, int len)
|
||||
{
|
||||
return esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, buf, len, SNIFFER_PROCESS_APPTRACE_TIMEOUT_US) == ESP_OK ? len : -1;
|
||||
}
|
||||
|
||||
static int trace_closefun(void *cookie)
|
||||
{
|
||||
return esp_apptrace_flush(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TMO_INFINITE) == ESP_OK ? 0 : -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static esp_err_t sniffer_start(sniffer_runtime_t *sniffer)
|
||||
{
|
||||
pcap_config_t pcap_config;
|
||||
wifi_promiscuous_filter_t wifi_filter;
|
||||
|
||||
switch (sniffer->interf) {
|
||||
case SNIFFER_INTF_WLAN:
|
||||
pcap_config.link_type = PCAP_LINK_TYPE_802_11;
|
||||
break;
|
||||
default:
|
||||
SNIFFER_CHECK(false, "unsupported interface", err);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Create file to write, binary format */
|
||||
#if CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
|
||||
pcap_config.fp = funopen("trace", NULL, trace_writefun, NULL, trace_closefun);
|
||||
#elif CONFIG_SNIFFER_PCAP_DESTINATION_SD
|
||||
pcap_config.fp = fopen(sniffer->filename, "wb");
|
||||
#else
|
||||
#error "pcap file destination hasn't specified"
|
||||
#endif
|
||||
SNIFFER_CHECK(pcap_config.fp, "open file failed", err);
|
||||
ESP_LOGI(SNIFFER_TAG, "open file successfully");
|
||||
|
||||
/* init a pcap session */
|
||||
SNIFFER_CHECK(pcap_init(&pcap_config, &sniffer->pcap) == ESP_OK, "init pcap session failed", err);
|
||||
|
||||
sniffer->is_running = true;
|
||||
sniffer->work_queue = xQueueCreate(CONFIG_SNIFFER_WORK_QUEUE_LEN, sizeof(sniffer_packet_info_t));
|
||||
SNIFFER_CHECK(sniffer->work_queue, "create work queue failed", err_queue);
|
||||
sniffer->sem_task_over = xSemaphoreCreateBinary();
|
||||
SNIFFER_CHECK(sniffer->sem_task_over, "create sem failed", err_sem);
|
||||
SNIFFER_CHECK(xTaskCreate(sniffer_task, "snifferT", CONFIG_SNIFFER_TASK_STACK_SIZE,
|
||||
sniffer, CONFIG_SNIFFER_TASK_PRIORITY, &sniffer->task) == pdTRUE,
|
||||
"create task failed", err_task);
|
||||
|
||||
switch (sniffer->interf) {
|
||||
case SNIFFER_INTF_WLAN:
|
||||
/* Start WiFi Promicuous Mode */
|
||||
wifi_filter.filter_mask = sniffer->filter;
|
||||
esp_wifi_set_promiscuous_filter(&wifi_filter);
|
||||
esp_wifi_set_promiscuous_rx_cb(wifi_sniffer_cb);
|
||||
SNIFFER_CHECK(esp_wifi_set_promiscuous(true) == ESP_OK, "start wifi promiscuous failed", err_start);
|
||||
esp_wifi_set_channel(sniffer->channel, WIFI_SECOND_CHAN_NONE);
|
||||
ESP_LOGI(SNIFFER_TAG, "start WiFi promiscuous ok");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
err_start:
|
||||
vTaskDelete(sniffer->task);
|
||||
sniffer->task = NULL;
|
||||
err_task:
|
||||
vSemaphoreDelete(sniffer->sem_task_over);
|
||||
sniffer->sem_task_over = NULL;
|
||||
err_sem:
|
||||
vQueueDelete(sniffer->work_queue);
|
||||
sniffer->work_queue = NULL;
|
||||
err_queue:
|
||||
sniffer->is_running = false;
|
||||
pcap_deinit(sniffer->pcap);
|
||||
err:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_str *file;
|
||||
struct arg_str *interface;
|
||||
struct arg_str *filter;
|
||||
struct arg_int *channel;
|
||||
struct arg_lit *stop;
|
||||
struct arg_end *end;
|
||||
} sniffer_args;
|
||||
|
||||
static int do_sniffer_cmd(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&sniffer_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, sniffer_args.end, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check whether or not to stop sniffer: "--stop" option */
|
||||
if (sniffer_args.stop->count) {
|
||||
/* stop sniffer */
|
||||
sniffer_stop(&snf_rt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check interface: "-i" option */
|
||||
snf_rt.interf = SNIFFER_INTF_WLAN;
|
||||
if (sniffer_args.interface->count) {
|
||||
if (!strncmp(sniffer_args.interface->sval[0], "wlan", 4)) {
|
||||
snf_rt.interf = SNIFFER_INTF_WLAN;
|
||||
} else {
|
||||
ESP_LOGE(SNIFFER_TAG, "unsupported interface %s", sniffer_args.interface->sval[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check channel: "-c" option */
|
||||
snf_rt.channel = SNIFFER_DEFAULT_CHANNEL;
|
||||
if (sniffer_args.channel->count) {
|
||||
snf_rt.channel = sniffer_args.channel->ival[0];
|
||||
}
|
||||
|
||||
#if CONFIG_SNIFFER_PCAP_DESTINATION_SD
|
||||
/* set pcap file name: "-f" option */
|
||||
int len = snprintf(snf_rt.filename, sizeof(snf_rt.filename), "%s/%s.pcap", CONFIG_SNIFFER_MOUNT_POINT, SNIFFER_DEFAULT_FILE_NAME);
|
||||
if (sniffer_args.file->count) {
|
||||
len = snprintf(snf_rt.filename, sizeof(snf_rt.filename), "%s/%s.pcap", CONFIG_SNIFFER_MOUNT_POINT, sniffer_args.file->sval[0]);
|
||||
}
|
||||
if (len >= sizeof(snf_rt.filename)) {
|
||||
ESP_LOGW(SNIFFER_TAG, "pcap file name too long, try to enlarge memory in menuconfig");
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
|
||||
uint32_t retry = 0;
|
||||
/* wait until apptrace communication established or timeout */
|
||||
while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX) && (retry < SNIFFER_APPTRACE_RETRY)) {
|
||||
retry++;
|
||||
ESP_LOGW(SNIFFER_TAG, "waiting for apptrace established");
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
if (retry >= SNIFFER_APPTRACE_RETRY) {
|
||||
ESP_LOGE(SNIFFER_TAG, "waiting for apptrace established timeout");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check filter setting: "-F" option */
|
||||
switch (snf_rt.interf) {
|
||||
case SNIFFER_INTF_WLAN:
|
||||
if (sniffer_args.filter->count) {
|
||||
for (int i = 0; i < sniffer_args.filter->count; i++) {
|
||||
snf_rt.filter += search_wifi_filter_hashtable(sniffer_args.filter->sval[i]);
|
||||
}
|
||||
/* When filter conditions are all wrong */
|
||||
if (snf_rt.filter == 0) {
|
||||
snf_rt.filter = WIFI_PROMIS_FILTER_MASK_ALL;
|
||||
}
|
||||
} else {
|
||||
snf_rt.filter = WIFI_PROMIS_FILTER_MASK_ALL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* start sniffer */
|
||||
sniffer_start(&snf_rt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void register_sniffer(void)
|
||||
{
|
||||
sniffer_args.file = arg_str0("f", "file", "<file>",
|
||||
"name of the file storing the packets in pcap format");
|
||||
sniffer_args.interface = arg_str0("i", "interface", "<wlan>",
|
||||
"which interface to capture packet");
|
||||
sniffer_args.filter = arg_strn("F", "filter", "<mgmt|data|ctrl|misc|mpdu|ampdu>", 0, 6, "filter parameters");
|
||||
sniffer_args.channel = arg_int0("c", "channel", "<channel>", "communication channel to use");
|
||||
sniffer_args.stop = arg_lit0(NULL, "stop", "stop running sniffer");
|
||||
sniffer_args.end = arg_end(1);
|
||||
const esp_console_cmd_t sniffer_cmd = {
|
||||
.command = "sniffer",
|
||||
.help = "Capture specific packet and store in pcap format",
|
||||
.hint = NULL,
|
||||
.func = &do_sniffer_cmd,
|
||||
.argtable = &sniffer_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&sniffer_cmd));
|
||||
|
||||
create_wifi_filter_hashtable();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/* cmd_sniffer example — declarations of command registration functions.
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Supported Sniffer Interface
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SNIFFER_INTF_WLAN = 0, /*!< WLAN interface */
|
||||
} sniffer_intf_t;
|
||||
|
||||
/**
|
||||
* @brief WLAN Sniffer Filter
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SNIFFER_WLAN_FILTER_MGMT = 0, /*!< MGMT */
|
||||
SNIFFER_WLAN_FILTER_CTRL, /*!< CTRL */
|
||||
SNIFFER_WLAN_FILTER_DATA, /*!< DATA */
|
||||
SNIFFER_WLAN_FILTER_MISC, /*!< MISC */
|
||||
SNIFFER_WLAN_FILTER_MPDU, /*!< MPDU */
|
||||
SNIFFER_WLAN_FILTER_AMPDU, /*!< AMPDU */
|
||||
SNIFFER_WLAN_FILTER_MAX
|
||||
} sniffer_wlan_filter_t;
|
||||
|
||||
void register_sniffer(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,4 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
@@ -0,0 +1,213 @@
|
||||
/* Sniffer example.
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "linenoise/linenoise.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#if CONFIG_SNIFFER_PCAP_DESTINATION_SD
|
||||
#include "driver/sdmmc_host.h"
|
||||
#include "driver/sdspi_host.h"
|
||||
#endif
|
||||
#include "nvs_flash.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
#include "cmd_system.h"
|
||||
#include "cmd_sniffer.h"
|
||||
|
||||
#if CONFIG_SNIFFER_STORE_HISTORY
|
||||
#define HISTORY_MOUNT_POINT "/data"
|
||||
#define HISTORY_FILE_PATH HISTORY_MOUNT_POINT "/history.txt"
|
||||
#endif
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
#if CONFIG_SNIFFER_STORE_HISTORY
|
||||
/* Initialize filesystem for command history store */
|
||||
static void initialize_filesystem(void)
|
||||
{
|
||||
static wl_handle_t wl_handle;
|
||||
const esp_vfs_fat_mount_config_t mount_config = {
|
||||
.max_files = 4,
|
||||
.format_if_mount_failed = true
|
||||
};
|
||||
esp_err_t err = esp_vfs_fat_spiflash_mount(HISTORY_MOUNT_POINT, "storage", &mount_config, &wl_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void initialize_nvs(void)
|
||||
{
|
||||
esp_err_t err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(err);
|
||||
}
|
||||
|
||||
/* Initialize wifi with tcp/ip adapter */
|
||||
static void initialize_wifi(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
|
||||
}
|
||||
|
||||
#if CONFIG_SNIFFER_PCAP_DESTINATION_SD
|
||||
static struct {
|
||||
struct arg_str *device;
|
||||
struct arg_end *end;
|
||||
} mount_args;
|
||||
|
||||
/** 'mount' command */
|
||||
static int mount(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&mount_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, mount_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
/* mount sd card */
|
||||
if (!strncmp(mount_args.device->sval[0], "sd", 2)) {
|
||||
ESP_LOGI(TAG, "Initializing SD card");
|
||||
ESP_LOGI(TAG, "Using SDMMC peripheral");
|
||||
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
|
||||
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
|
||||
|
||||
gpio_set_pull_mode(15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1-line modes
|
||||
gpio_set_pull_mode(2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes
|
||||
gpio_set_pull_mode(4, GPIO_PULLUP_ONLY); // D1, needed in 4-line mode only
|
||||
gpio_set_pull_mode(12, GPIO_PULLUP_ONLY); // D2, needed in 4-line mode only
|
||||
gpio_set_pull_mode(13, GPIO_PULLUP_ONLY); // D3, needed in 4- and 1-line modes
|
||||
|
||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = true,
|
||||
.max_files = 4,
|
||||
.allocation_unit_size = 16 * 1024
|
||||
};
|
||||
|
||||
// initialize SD card and mount FAT filesystem.
|
||||
sdmmc_card_t *card;
|
||||
esp_err_t ret = esp_vfs_fat_sdmmc_mount(CONFIG_SNIFFER_MOUNT_POINT, &host, &slot_config, &mount_config, &card);
|
||||
if (ret != ESP_OK) {
|
||||
if (ret == ESP_FAIL) {
|
||||
ESP_LOGE(TAG, "Failed to mount filesystem. "
|
||||
"If you want the card to be formatted, set format_if_mount_failed = true.");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to initialize the card (%s). "
|
||||
"Make sure SD card lines have pull-up resistors in place.",
|
||||
esp_err_to_name(ret));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* print card info if mount successfully */
|
||||
sdmmc_card_print_info(stdout, card);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_mount(void)
|
||||
{
|
||||
mount_args.device = arg_str1(NULL, NULL, "<sd>", "choose a proper device to mount/unmount");
|
||||
mount_args.end = arg_end(1);
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "mount",
|
||||
.help = "mount the filesystem",
|
||||
.hint = NULL,
|
||||
.func = &mount,
|
||||
.argtable = &mount_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
static int unmount(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&mount_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, mount_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
/* unmount sd card */
|
||||
if (!strncmp(mount_args.device->sval[0], "sd", 2)) {
|
||||
if (esp_vfs_fat_sdmmc_unmount() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Card unmount failed");
|
||||
return -1;
|
||||
}
|
||||
ESP_LOGI(TAG, "Card unmounted");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_unmount(void)
|
||||
{
|
||||
mount_args.device = arg_str1(NULL, NULL, "<sd>", "choose a proper device to mount/unmount");
|
||||
mount_args.end = arg_end(1);
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "unmount",
|
||||
.help = "unmount the filesystem",
|
||||
.hint = NULL,
|
||||
.func = &unmount,
|
||||
.argtable = &mount_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
#endif // CONFIG_SNIFFER_PCAP_DESTINATION_SD
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
initialize_nvs();
|
||||
|
||||
/* Initialize WiFi */
|
||||
initialize_wifi();
|
||||
esp_console_repl_t *repl = NULL;
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
#if CONFIG_SNIFFER_STORE_HISTORY
|
||||
initialize_filesystem();
|
||||
repl_config.history_save_path = HISTORY_FILE_PATH;
|
||||
#endif
|
||||
repl_config.prompt = "sniffer>";
|
||||
// init console REPL environment
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
|
||||
|
||||
/* Register commands */
|
||||
#if CONFIG_SNIFFER_PCAP_DESTINATION_SD
|
||||
register_mount();
|
||||
register_unmount();
|
||||
#endif
|
||||
register_sniffer();
|
||||
register_system();
|
||||
|
||||
printf("\n =======================================================\n");
|
||||
printf(" | Steps to sniffer WiFi packets |\n");
|
||||
printf(" | |\n");
|
||||
printf(" | 1. Enter 'help' to check all commands' usage |\n");
|
||||
printf(" | 2. Enter 'mount <device>' to mount filesystem |\n");
|
||||
printf(" | 3. Enter 'sniffer' to start capture packets |\n");
|
||||
printf(" | 4. Enter 'unmount <device>' to unmount filesystem |\n");
|
||||
printf(" | |\n");
|
||||
printf(" =======================================================\n\n");
|
||||
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(repl));
|
||||
}
|
||||
Reference in New Issue
Block a user