Merge branch 'feature/eth_sniffer_example' into 'master'

Add Ethernet sniffer example

Closes IDF-259

See merge request espressif/esp-idf!13548
This commit is contained in:
David Čermák
2021-05-28 13:47:53 +00:00
6 changed files with 528 additions and 43 deletions

View File

@@ -4,19 +4,23 @@
## Overview ## Overview
This example demonstrates basic usage of WiFi sniffer mode by saving packets into SD card with pcap format. We can send pcap file to host via JTAG interface as well. This example demonstrates basic usage of WiFi and Ethernet sniffer mode by saving packets into SD card with pcap format. There is also an option to send pcap file to host via JTAG interface.
For more information about pcap, please go to [wikipedia](https://en.wikipedia.org/wiki/Pcap). For more information about pcap, please go to [wikipedia](https://en.wikipedia.org/wiki/Pcap).
This example is based on console component. For more information about console, please refer to [console guide](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/console.html). This example is based on console component. For more information about console, please refer to [console guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/console.html).
## How to use example ## How to use example
### Hardware Required ### Hardware Required
To run this example, you should have one ESP32 dev board integrated with a SD card slot (e.g [ESP-WROVER-KIT](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/modules-and-boards.html#esp-wrover-kit-v4-1)) or just connect [ESP32-DevKitC](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/modules-and-boards.html#esp32-devkitc-v4) to a SD card breakout board. To run this example with WiFi interface, you should have one ESP32 dev board integrated with a SD card slot (e.g. [ESP-WROVER-KIT](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/modules-and-boards.html#esp-wrover-kit-v4-1)) or just connect [ESP32-DevKitC](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/modules-and-boards.html#esp32-devkitc-v4) to a SD card breakout board. To run this example with Ethernet interface option, you should have one ESP32 dev board with physical layer Ethernet support (e.g. [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-ethernet-kit.html#)) or connect SPI-Ethernet module (e.g. DM9051) to your dev board.
If you want to send packets to host, make sure to connect ESP32 to some kind of [JTAG adapter](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/index.html#jtag-debugging-selecting-jtag-adapter). If you want to send packets to host, make sure to connect ESP32 to some kind of [JTAG adapter](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/index.html#jtag-debugging-selecting-jtag-adapter).
#### Ethernet Pin Assignment
See common pin assignments for Ethernet from [ethernet examples folder](../../ethernet/README.md#common-pin-assignments).
### Configure the project ### Configure the project
Open the project configuration menu (`idf.py menuconfig`). Then go into `Example Configuration` menu. Open the project configuration menu (`idf.py menuconfig`). Then go into `Example Configuration` menu.
@@ -24,12 +28,17 @@ Open the project configuration menu (`idf.py menuconfig`). Then go into `Example
- Check `Store command history in flash` if you want to save command history into flash (recommend). - Check `Store command history in flash` if you want to save command history into flash (recommend).
- Select where to save the pcap file in `Select destination to store pcap file` menu item. - Select where to save the pcap file in `Select destination to store pcap file` menu item.
- `SD Card` means saving packets (pcap format) into the SD card you plug in. The default SD card work mode is set to SDMMC for target ESP32 and ESP32S3, but SPI is the only choice for other targets. - `SD Card` means saving packets (pcap format) into the SD card you plug in. The default SD card work mode is set to SDMMC for target ESP32 and ESP32S3, but SPI is the only choice for other targets.
- `JTAG (App Trace)` means sending packets (pcap format) to host via JTAG interface. This feature depends on [app trace component](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/app_trace.html), Component config -> Application Lelvel Tracing -> Data Destination -> Trace memory should be enabled to choose `JTAG (App Trace)` as destination. - `JTAG (App Trace)` means sending packets (pcap format) to host via JTAG interface. This feature depends on [app trace component](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/app_trace.html), Component config -> Application Level Tracing -> Data Destination -> Trace memory should be enabled to choose `JTAG (App Trace)` as destination.
- Set the mount point in your filesystem in `SD card mount point in the filesystem` menu item. This configuration only takes effect when you choose to save packets into SD card. - Set the mount point in your filesystem in `SD card mount point in the filesystem` menu item. This configuration only takes effect when you choose to save packets into SD card.
- Set max name length of pcap file in `Max name length of pcap file` menu item. - Set max name length of pcap file in `Max name length of pcap file` menu item.
- Set the length of sniffer work queue in `Length of sniffer work queue` menu item. - Set the length of sniffer work queue in `Length of sniffer work queue` menu item.
- Set the stack size of the sniffer task in `Stack size of sniffer task` menu item. - Set the stack size of the sniffer task in `Stack size of sniffer task` menu item.
- Set the priority of the sniffer task `Length of sniffer work queue` menu item. - Set the priority of the sniffer task in `Length of sniffer work queue` menu item.
- Select Ethernet Type
- `No Ethernet` means your board does not have Ethernet.
- `Internal EMAC` means ESP32 EMAC is used in conjunction with with selected PHY.
- `DM9051 Module`, `W5500 Module` or `KSZ8851SNL Module` means that SPI-Ethernet module is used with its own EMAC and PHY.
- For more information related to Ethernet configurations see common configuration of Ethernet from [ethernet examples folder](../../ethernet/README.md#common-configurations).
### Build and Flash ### Build and Flash
@@ -47,20 +56,20 @@ See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/l
### `sniffer` Command Usage ### `sniffer` Command Usage
> sniffer [-f <file>][-i ] [-F <mgmt|data|ctrl|misc|mpdu|ampdu>]... [-c <channel>][--stop] > sniffer [-f <file>][-i <wlan|eth0|eth1|...>] [-F <mgmt|data|ctrl|misc|mpdu|ampdu>]... [-c <channel>][--stop]
> Capture specific packet and store in pcap format > Capture specific packet and store in pcap format
> -f, --file=<file> name of the file storing the packets in pcap format > -f, --file=<file> name of the file storing the packets in pcap format
> -i, --interface=<wlan> which interface to capture packet > -i, --interface=<wlan|eth0|eth1|...> which interface to capture packet
> -F, --filter=<mgmt|data|ctrl|misc|mpdu|ampdu> filter parameters > -F, --filter=<mgmt|data|ctrl|misc|mpdu|ampdu> filter parameters
> -c, --channel=<channel> communication channel to use > -c, --channel=<channel> communication channel to use
> --stop stop running sniffer > --stop stop running sniffer
The `sniffer` command support some important options as follow: The `sniffer` command support some important options as follow:
* `-f`: Specify the name of file who will store the packets, default value is `sniffer`, and the resulting file name will be like “snifferX.pcap”, here X shows the files order. * `-f`: Specify the name of file which will store the packets, default value is `sniffer`, and the resulting file name will be like “snifferX.pcap”, here X shows the files order.
* `-i`: Specify the interface to sniffer packets, currently only support `wlan` * `-i`: Specify the interface to sniffer packets, currently support `wlan` and `eth0`
* `-c` :Specify the channel to sniffer packet * `-c` :Specify the channel to sniffer packet at `wlan` interface
* `-F`: Specify the filter condition, currently only support following filter conditions, you can select any number of them * `-F`: Specify the filter condition at `wlan` interface, currently only support following filter conditions, you can select any number of them
* mgmt: Management packets * mgmt: Management packets
* data: Data packets * data: Data packets
* ctrl: Control packets * ctrl: Control packets
@@ -75,7 +84,7 @@ The `sniffer` command support some important options as follow:
======================================================= =======================================================
| Steps to sniffer WiFi packets | | Steps to sniffer WiFi packets |
| | | |
| 1. Enter 'help' to check all commands' usage | | 1. Enter 'help' to check all commands usage |
| 2. Enter 'mount <device>' to mount filesystem | | 2. Enter 'mount <device>' to mount filesystem |
| 3. Enter 'sniffer' to start capture packets | | 3. Enter 'sniffer' to start capture packets |
| 4. Enter 'unmount <device>' to unmount filesystem | | 4. Enter 'unmount <device>' to unmount filesystem |

View File

@@ -22,6 +22,7 @@
#include "pcap.h" #include "pcap.h"
static const char *PCAP_TAG = "pcap"; static const char *PCAP_TAG = "pcap";
#define PCAP_CHECK(a, str, goto_tag, ...) \ #define PCAP_CHECK(a, str, goto_tag, ...) \
do \ do \
{ \ { \
@@ -92,9 +93,11 @@ esp_err_t pcap_deinit(pcap_handle_t handle)
{ {
PCAP_CHECK(handle, "pcap handle is NULL", err); PCAP_CHECK(handle, "pcap handle is NULL", err);
pcap_runtime_t *pcap_rt = (pcap_runtime_t *)handle; pcap_runtime_t *pcap_rt = (pcap_runtime_t *)handle;
PCAP_CHECK(pcap_rt->file, "pcap file is NULL", err);
PCAP_CHECK(fclose(pcap_rt->file) == 0, "close pcap file failed", err); if (pcap_rt->file != NULL) {
pcap_rt->file = NULL; fclose(pcap_rt->file);
pcap_rt->file = NULL;
}
free(pcap_rt); free(pcap_rt);
ESP_LOGD(PCAP_TAG, "pcap deinit OK"); ESP_LOGD(PCAP_TAG, "pcap deinit OK");
return ESP_OK; return ESP_OK;
@@ -107,7 +110,7 @@ esp_err_t pcap_init(pcap_config_t *config, pcap_handle_t *handle)
{ {
PCAP_CHECK(config, "config is NULL", err); PCAP_CHECK(config, "config is NULL", err);
PCAP_CHECK(handle, "pcap handle is NULL", err); PCAP_CHECK(handle, "pcap handle is NULL", err);
pcap_runtime_t *pcap_rt = calloc(sizeof(pcap_runtime_t), 1); pcap_runtime_t *pcap_rt = calloc(1, sizeof(pcap_runtime_t));
PCAP_CHECK(pcap_rt, "calloc pcap runtime failed", err); PCAP_CHECK(pcap_rt, "calloc pcap runtime failed", err);
pcap_rt->file = config->fp; pcap_rt->file = config->fp;
/* Write Pcap File header */ /* Write Pcap File header */

View File

@@ -73,4 +73,190 @@ menu "Example Configuration"
help help
Priority of sniffer task. Priority of sniffer task.
config SNIFFER_USE_SPI_ETHERNET
bool
choice SNIFFER_ETHERNET_TYPE
prompt "Ethernet Type"
default SNIFFER_NO_ETHERNET
help
Select which kind of Ethernet will be used in the example.
config SNIFFER_NO_ETHERNET
bool "No Ethernet"
help
No Ethernet.
config SNIFFER_USE_INTERNAL_ETHERNET
depends on IDF_TARGET_ESP32
select ETH_USE_ESP32_EMAC
bool "Internal EMAC"
help
Select internal Ethernet MAC controller.
config SNIFFER_USE_DM9051
bool "DM9051 Module"
select SNIFFER_USE_SPI_ETHERNET
select ETH_USE_SPI_ETHERNET
select ETH_SPI_ETHERNET_DM9051
help
Select external SPI-Ethernet module (DM9051).
config SNIFFER_USE_W5500
bool "W5500 Module"
select SNIFFER_USE_SPI_ETHERNET
select ETH_USE_SPI_ETHERNET
select ETH_SPI_ETHERNET_W5500
help
Select external SPI-Ethernet module (W5500).
config SNIFFER_USE_KSZ8851SNL
bool "KSZ8851SNL Module"
select SNIFFER_USE_SPI_ETHERNET
select ETH_USE_SPI_ETHERNET
select ETH_SPI_ETHERNET_KSZ8851SNL
help
Select external SPI-Ethernet module (KSZ8851SNL).
endchoice # SNIFFER_ETHERNET_TYPE
if SNIFFER_USE_INTERNAL_ETHERNET
choice SNIFFER_ETH_PHY_MODEL
prompt "Ethernet PHY Device"
default SNIFFER_ETH_PHY_IP101
help
Select the Ethernet PHY device to use in the example.
config SNIFFER_ETH_PHY_IP101
bool "IP101"
help
IP101 is a single port 10/100 MII/RMII/TP/Fiber Fast Ethernet Transceiver.
Goto http://www.icplus.com.tw/pp-IP101G.html for more information about it.
config SNIFFER_ETH_PHY_RTL8201
bool "RTL8201/SR8201"
help
RTL8201F/SR8201F is a single port 10/100Mb Ethernet Transceiver with auto MDIX.
Goto http://www.corechip-sz.com/productsview.asp?id=22 for more information about it.
config SNIFFER_ETH_PHY_LAN8720
bool "LAN8720"
help
LAN8720A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX Support.
Goto https://www.microchip.com/LAN8720A for more information about it.
config SNIFFER_ETH_PHY_DP83848
bool "DP83848"
help
DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver.
Goto http://www.ti.com/product/DP83848J for more information about it.
config SNIFFER_ETH_PHY_KSZ8041
bool "KSZ8041"
help
The KSZ8041 is a single supply 10Base-T/100Base-TX Physical Layer Transceiver.
Goto https://www.microchip.com/wwwproducts/en/KSZ8041 for more information about it.
config SNIFFER_ETH_PHY_KSZ8081
bool "KSZ8081"
help
The KSZ8081 is a single supply 10Base-T/100Base-TX Physical Layer Transceiver.
Goto https://www.microchip.com/wwwproducts/en/KSZ8081 for more information about it.
endchoice # SNIFFER_ETH_PHY_MODEL
config SNIFFER_ETH_MDC_GPIO
int "SMI MDC GPIO number"
default 23
help
Set the GPIO number used by SMI MDC.
config SNIFFER_ETH_MDIO_GPIO
int "SMI MDIO GPIO number"
default 18
help
Set the GPIO number used by SMI MDIO.
endif # SNIFFER_USE_INTERNAL_ETHERNET
if SNIFFER_USE_SPI_ETHERNET
config SNIFFER_ETH_SPI_HOST
int "SPI Host Number"
range 0 2
default 1
help
Set the SPI host used to communicate with the SPI Ethernet Controller.
config SNIFFER_ETH_SPI_SCLK_GPIO
int "SPI SCLK GPIO number"
range 0 34 if IDF_TARGET_ESP32
range 0 46 if IDF_TARGET_ESP32S2
range 0 19 if IDF_TARGET_ESP32C3
default 18 if IDF_TARGET_ESP32
default 20 if IDF_TARGET_ESP32S2
default 6 if IDF_TARGET_ESP32C3
help
Set the GPIO number used by SPI SCLK.
config SNIFFER_ETH_SPI_MOSI_GPIO
int "SPI MOSI GPIO number"
range 0 34 if IDF_TARGET_ESP32
range 0 46 if IDF_TARGET_ESP32S2
range 0 19 if IDF_TARGET_ESP32C3
default 23 if IDF_TARGET_ESP32
default 19 if IDF_TARGET_ESP32S2
default 7 if IDF_TARGET_ESP32C3
help
Set the GPIO number used by SPI MOSI.
config SNIFFER_ETH_SPI_MISO_GPIO
int "SPI MISO GPIO number"
range 0 34 if IDF_TARGET_ESP32
range 0 46 if IDF_TARGET_ESP32S2
range 0 19 if IDF_TARGET_ESP32C3
default 19 if IDF_TARGET_ESP32
default 18 if IDF_TARGET_ESP32S2
default 2 if IDF_TARGET_ESP32C3
help
Set the GPIO number used by SPI MISO.
config SNIFFER_ETH_SPI_CS_GPIO
int "SPI CS GPIO number"
range 0 34 if IDF_TARGET_ESP32
range 0 46 if IDF_TARGET_ESP32S2
range 0 19 if IDF_TARGET_ESP32C3
default 16 if IDF_TARGET_ESP32
default 21 if IDF_TARGET_ESP32S2
default 10 if IDF_TARGET_ESP32C3
help
Set the GPIO number used by SPI CS.
config SNIFFER_ETH_SPI_CLOCK_MHZ
int "SPI clock speed (MHz)"
range 5 80
default 12 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32C3
default 36 if IDF_TARGET_ESP32S2
help
Set the clock speed (MHz) of SPI interface.
config SNIFFER_ETH_SPI_INT_GPIO
int "Interrupt GPIO number"
default 17 if IDF_TARGET_ESP32
default 4 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3
help
Set the GPIO number used by the SPI Ethernet module interrupt line.
endif # SNIFFER_USE_SPI_ETHERNET
if !SNIFFER_NO_ETHERNET
config SNIFFER_ETH_PHY_RST_GPIO
int "PHY Reset GPIO number"
default 5
help
Set the GPIO number used to reset PHY chip.
Set to -1 to disable PHY chip hardware reset.
config SNIFFER_ETH_PHY_ADDR
int "PHY Address"
range 0 31
default 1
help
Set PHY address according your board schematic.
endif # !SNIFFER_NO_ETHERNET
endmenu endmenu

View File

@@ -11,6 +11,9 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/queue.h" #include "freertos/queue.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#ifdef CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
#include "freertos/timers.h"
#endif // CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
#include <sys/unistd.h> #include <sys/unistd.h>
#include <sys/fcntl.h> #include <sys/fcntl.h>
#include "esp_log.h" #include "esp_log.h"
@@ -29,6 +32,10 @@
#define SNIFFER_PROCESS_APPTRACE_TIMEOUT_US (100) #define SNIFFER_PROCESS_APPTRACE_TIMEOUT_US (100)
#define SNIFFER_APPTRACE_RETRY (10) #define SNIFFER_APPTRACE_RETRY (10)
#define SNIFFER_RX_FCS_ERR (0X41) #define SNIFFER_RX_FCS_ERR (0X41)
#define SNIFFER_MAX_ETH_INTFS (3)
#define SNIFFER_DECIMAL_NUM (10)
#define TRACE_TIMER_FLUSH_INT_MS (1000)
static const char *SNIFFER_TAG = "cmd_sniffer"; static const char *SNIFFER_TAG = "cmd_sniffer";
#define SNIFFER_CHECK(a, str, goto_tag, ...) \ #define SNIFFER_CHECK(a, str, goto_tag, ...) \
@@ -49,15 +56,20 @@ typedef struct {
typedef struct { typedef struct {
bool is_running; bool is_running;
sniffer_intf_t interf; sniffer_intf_t interf;
uint32_t interf_num;
uint32_t channel; uint32_t channel;
uint32_t filter; uint32_t filter;
#if CONFIG_SNIFFER_PCAP_DESTINATION_SD #if CONFIG_SNIFFER_PCAP_DESTINATION_SD
char filename[SNIFFER_FILE_NAME_MAX_LEN]; char filename[SNIFFER_FILE_NAME_MAX_LEN];
#endif #endif
#ifdef CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
TimerHandle_t trace_flush_timer; /*!< Timer handle for Trace buffer flush */
#endif // CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
pcap_handle_t pcap; pcap_handle_t pcap;
TaskHandle_t task; TaskHandle_t task;
QueueHandle_t work_queue; QueueHandle_t work_queue;
SemaphoreHandle_t sem_task_over; SemaphoreHandle_t sem_task_over;
esp_eth_handle_t eth_handles[SNIFFER_MAX_ETH_INTFS];
} sniffer_runtime_t; } sniffer_runtime_t;
typedef struct { typedef struct {
@@ -120,6 +132,25 @@ static uint32_t search_wifi_filter_hashtable(const char *key)
return wifi_filter_hash_table[idx].filter_val; return wifi_filter_hash_table[idx].filter_val;
} }
static void queue_packet(void *recv_packet, sniffer_packet_info_t *packet_info)
{
/* Copy a packet from Link Layer driver and queue the copy to be processed by sniffer task */
void *packet_to_queue = malloc(packet_info->length);
if (packet_to_queue) {
memcpy(packet_to_queue, recv_packet, packet_info->length);
packet_info->payload = packet_to_queue;
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");
free(packet_info->payload);
}
}
} else {
ESP_LOGE(SNIFFER_TAG, "No enough memory for promiscuous packet");
}
}
static void wifi_sniffer_cb(void *recv_buf, wifi_promiscuous_pkt_type_t type) static void wifi_sniffer_cb(void *recv_buf, wifi_promiscuous_pkt_type_t type)
{ {
sniffer_packet_info_t packet_info; sniffer_packet_info_t packet_info;
@@ -132,29 +163,37 @@ static void wifi_sniffer_cb(void *recv_buf, wifi_promiscuous_pkt_type_t type)
/* For now, the sniffer only dumps the length of the MISC type frame */ /* For now, the sniffer only dumps the length of the MISC type frame */
if (type != WIFI_PKT_MISC && !sniffer->rx_ctrl.rx_state) { if (type != WIFI_PKT_MISC && !sniffer->rx_ctrl.rx_state) {
packet_info.length -= SNIFFER_PAYLOAD_FCS_LEN; packet_info.length -= SNIFFER_PAYLOAD_FCS_LEN;
void *backup = malloc(packet_info.length); queue_packet(recv_buf, &packet_info);
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 esp_err_t eth_sniffer_cb(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv)
{
sniffer_packet_info_t packet_info;
struct timeval tv_now;
// ESP32 Ethernet MAC provides hardware time stamping for incoming frames in its Linked List Descriptors (see TMR, section 10.8.2).
// However, this information is not currently accessible via Ethernet driver => do at least software time stamping
gettimeofday(&tv_now, NULL);
packet_info.seconds = tv_now.tv_sec;
packet_info.microseconds = tv_now.tv_usec;
packet_info.length = length;
queue_packet(buffer, &packet_info);
free(buffer);
return ESP_OK;
}
static void sniffer_task(void *parameters) static void sniffer_task(void *parameters)
{ {
sniffer_packet_info_t packet_info; sniffer_packet_info_t packet_info;
sniffer_runtime_t *sniffer = (sniffer_runtime_t *)parameters; sniffer_runtime_t *sniffer = (sniffer_runtime_t *)parameters;
while (sniffer->is_running) { while (sniffer->is_running) {
/* receive paclet info from queue */ /* receive packet info from queue */
if (xQueueReceive(sniffer->work_queue, &packet_info, pdMS_TO_TICKS(SNIFFER_PROCESS_PACKET_TIMEOUT_MS)) != pdTRUE) { if (xQueueReceive(sniffer->work_queue, &packet_info, pdMS_TO_TICKS(SNIFFER_PROCESS_PACKET_TIMEOUT_MS)) != pdTRUE) {
continue; continue;
} }
@@ -171,6 +210,8 @@ static void sniffer_task(void *parameters)
static esp_err_t sniffer_stop(sniffer_runtime_t *sniffer) static esp_err_t sniffer_stop(sniffer_runtime_t *sniffer)
{ {
bool eth_set_promiscuous;
SNIFFER_CHECK(sniffer->is_running, "sniffer is already stopped", err); SNIFFER_CHECK(sniffer->is_running, "sniffer is already stopped", err);
switch (sniffer->interf) { switch (sniffer->interf) {
@@ -178,11 +219,18 @@ static esp_err_t sniffer_stop(sniffer_runtime_t *sniffer)
/* Disable wifi promiscuous mode */ /* Disable wifi promiscuous mode */
SNIFFER_CHECK(esp_wifi_set_promiscuous(false) == ESP_OK, "stop wifi promiscuous failed", err); SNIFFER_CHECK(esp_wifi_set_promiscuous(false) == ESP_OK, "stop wifi promiscuous failed", err);
break; break;
case SNIFFER_INTF_ETH:
/* Disable Ethernet Promiscuous Mode */
eth_set_promiscuous = false;
SNIFFER_CHECK(esp_eth_ioctl(sniffer->eth_handles[sniffer->interf_num], ETH_CMD_S_PROMISCUOUS, &eth_set_promiscuous) == ESP_OK,
"stop Ethernet promiscuous failed", err);
esp_eth_update_input_path(sniffer->eth_handles[sniffer->interf_num], NULL, NULL);
break;
default: default:
SNIFFER_CHECK(false, "unsupported interface", err); SNIFFER_CHECK(false, "unsupported interface", err);
break; break;
} }
ESP_LOGI(SNIFFER_TAG, "stop WiFi promiscuous ok"); ESP_LOGI(SNIFFER_TAG, "stop promiscuous ok");
/* stop sniffer local task */ /* stop sniffer local task */
sniffer->is_running = false; sniffer->is_running = false;
@@ -199,6 +247,13 @@ static esp_err_t sniffer_stop(sniffer_runtime_t *sniffer)
} }
vQueueDelete(sniffer->work_queue); vQueueDelete(sniffer->work_queue);
sniffer->work_queue = NULL; sniffer->work_queue = NULL;
#if CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
if (sniffer->trace_flush_timer != NULL) {
xTimerDelete(sniffer->trace_flush_timer, pdMS_TO_TICKS(100));
sniffer->trace_flush_timer = NULL;
}
#endif // CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
/* stop pcap session */ /* stop pcap session */
SNIFFER_CHECK(pcap_deinit(sniffer->pcap) == ESP_OK, "stop pcap session failed", err); SNIFFER_CHECK(pcap_deinit(sniffer->pcap) == ESP_OK, "stop pcap session failed", err);
return ESP_OK; return ESP_OK;
@@ -216,17 +271,28 @@ static int trace_closefun(void *cookie)
{ {
return esp_apptrace_flush(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TMO_INFINITE) == ESP_OK ? 0 : -1; return esp_apptrace_flush(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TMO_INFINITE) == ESP_OK ? 0 : -1;
} }
#endif
void pcap_flush_apptrace_timer_cb(TimerHandle_t pxTimer)
{
esp_apptrace_flush(ESP_APPTRACE_DEST_TRAX, pdMS_TO_TICKS(10));
}
#endif // CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
static esp_err_t sniffer_start(sniffer_runtime_t *sniffer) static esp_err_t sniffer_start(sniffer_runtime_t *sniffer)
{ {
pcap_config_t pcap_config; pcap_config_t pcap_config;
wifi_promiscuous_filter_t wifi_filter; wifi_promiscuous_filter_t wifi_filter;
bool eth_set_promiscuous;
SNIFFER_CHECK(sniffer->is_running == false, "sniffer is already running", err);
switch (sniffer->interf) { switch (sniffer->interf) {
case SNIFFER_INTF_WLAN: case SNIFFER_INTF_WLAN:
pcap_config.link_type = PCAP_LINK_TYPE_802_11; pcap_config.link_type = PCAP_LINK_TYPE_802_11;
break; break;
case SNIFFER_INTF_ETH:
pcap_config.link_type = PCAP_LINK_TYPE_ETHERNET;
break;
default: default:
SNIFFER_CHECK(false, "unsupported interface", err); SNIFFER_CHECK(false, "unsupported interface", err);
break; break;
@@ -235,6 +301,19 @@ static esp_err_t sniffer_start(sniffer_runtime_t *sniffer)
/* Create file to write, binary format */ /* Create file to write, binary format */
#if CONFIG_SNIFFER_PCAP_DESTINATION_JTAG #if CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
pcap_config.fp = funopen("trace", NULL, trace_writefun, NULL, trace_closefun); pcap_config.fp = funopen("trace", NULL, trace_writefun, NULL, trace_closefun);
/* Ethernet Link layer traffic amount may be much less than on Wi-Fi (no link management msgs.) and trace data is sent to listener
only after filling trace buffer. Hence the trace buffer might not be filled prior listener's timeout. This condition is resolved by
flushing the trace buffer periodically. */
if(pcap_config.link_type == PCAP_LINK_TYPE_ETHERNET) {
int timer_id = 0xFEED;
sniffer->trace_flush_timer = xTimerCreate("flush_apptrace_timer",
pdMS_TO_TICKS(TRACE_TIMER_FLUSH_INT_MS),
pdTRUE, (void *) timer_id,
pcap_flush_apptrace_timer_cb);
SNIFFER_CHECK(sniffer->trace_flush_timer, "pcap xTimerCreate failed", err);
SNIFFER_CHECK(xTimerStart(sniffer->trace_flush_timer, 0) == pdPASS, "pcap xTimerStart failed", err_timer_start);
}
#elif CONFIG_SNIFFER_PCAP_DESTINATION_SD #elif CONFIG_SNIFFER_PCAP_DESTINATION_SD
pcap_config.fp = fopen(sniffer->filename, "wb"); pcap_config.fp = fopen(sniffer->filename, "wb");
#else #else
@@ -257,7 +336,7 @@ static esp_err_t sniffer_start(sniffer_runtime_t *sniffer)
switch (sniffer->interf) { switch (sniffer->interf) {
case SNIFFER_INTF_WLAN: case SNIFFER_INTF_WLAN:
/* Start WiFi Promicuous Mode */ /* Start WiFi Promiscuous Mode */
wifi_filter.filter_mask = sniffer->filter; wifi_filter.filter_mask = sniffer->filter;
esp_wifi_set_promiscuous_filter(&wifi_filter); esp_wifi_set_promiscuous_filter(&wifi_filter);
esp_wifi_set_promiscuous_rx_cb(wifi_sniffer_cb); esp_wifi_set_promiscuous_rx_cb(wifi_sniffer_cb);
@@ -265,6 +344,14 @@ static esp_err_t sniffer_start(sniffer_runtime_t *sniffer)
esp_wifi_set_channel(sniffer->channel, WIFI_SECOND_CHAN_NONE); esp_wifi_set_channel(sniffer->channel, WIFI_SECOND_CHAN_NONE);
ESP_LOGI(SNIFFER_TAG, "start WiFi promiscuous ok"); ESP_LOGI(SNIFFER_TAG, "start WiFi promiscuous ok");
break; break;
case SNIFFER_INTF_ETH:
/* Start Ethernet Promiscuous Mode */
eth_set_promiscuous = true;
SNIFFER_CHECK(esp_eth_ioctl(sniffer->eth_handles[sniffer->interf_num], ETH_CMD_S_PROMISCUOUS, &eth_set_promiscuous) == ESP_OK,
"start Ethernet promiscuous failed", err_start);
esp_eth_update_input_path(sniffer->eth_handles[sniffer->interf_num], eth_sniffer_cb, NULL);
ESP_LOGI(SNIFFER_TAG, "start Ethernet promiscuous ok");
break;
default: default:
break; break;
} }
@@ -281,6 +368,11 @@ err_sem:
err_queue: err_queue:
sniffer->is_running = false; sniffer->is_running = false;
pcap_deinit(sniffer->pcap); pcap_deinit(sniffer->pcap);
#ifdef CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
err_timer_start:
xTimerDelete(sniffer->trace_flush_timer, pdMS_TO_TICKS(100));
sniffer->trace_flush_timer = NULL;
#endif // CONFIG_SNIFFER_PCAP_DESTINATION_JTAG
err: err:
return ESP_FAIL; return ESP_FAIL;
} }
@@ -294,9 +386,24 @@ static struct {
struct arg_end *end; struct arg_end *end;
} sniffer_args; } sniffer_args;
esp_err_t sniffer_reg_eth_intf(esp_eth_handle_t eth_handle)
{
int32_t i = 0;
while ((snf_rt.eth_handles[i] != NULL) && (i < SNIFFER_MAX_ETH_INTFS)) {
i++;
}
SNIFFER_CHECK(i < SNIFFER_MAX_ETH_INTFS, "maximum num. of eth interfaces registered", err);
snf_rt.eth_handles[i] = eth_handle;
return ESP_OK;
err:
return ESP_FAIL;
}
static int do_sniffer_cmd(int argc, char **argv) static int do_sniffer_cmd(int argc, char **argv)
{ {
int nerrors = arg_parse(argc, argv, (void **)&sniffer_args); int nerrors = arg_parse(argc, argv, (void **)&sniffer_args);
if (nerrors != 0) { if (nerrors != 0) {
arg_print_errors(stderr, sniffer_args.end, argv[0]); arg_print_errors(stderr, sniffer_args.end, argv[0]);
return 0; return 0;
@@ -310,20 +417,48 @@ static int do_sniffer_cmd(int argc, char **argv)
} }
/* Check interface: "-i" option */ /* Check interface: "-i" option */
snf_rt.interf = SNIFFER_INTF_WLAN;
if (sniffer_args.interface->count) { if (sniffer_args.interface->count) {
if (!strncmp(sniffer_args.interface->sval[0], "wlan", 4)) { if (!strncmp(sniffer_args.interface->sval[0], "wlan", 4)) {
snf_rt.interf = SNIFFER_INTF_WLAN; snf_rt.interf = SNIFFER_INTF_WLAN;
} else if (!strncmp(sniffer_args.interface->sval[0], "eth", 3)
&& strlen(sniffer_args.interface->sval[0]) >= 4) {
char *end_ptr = NULL;
const char *eth_num_str_start = sniffer_args.interface->sval[0] + 3;
int32_t eth_intf_num = strtol(eth_num_str_start, &end_ptr, SNIFFER_DECIMAL_NUM);
if ((eth_intf_num >= 0) && (eth_intf_num < SNIFFER_MAX_ETH_INTFS)
&& (eth_num_str_start != end_ptr) && (snf_rt.eth_handles[eth_intf_num] != NULL)) {
snf_rt.interf = SNIFFER_INTF_ETH;
snf_rt.interf_num = eth_intf_num;
} else {
ESP_LOGE(SNIFFER_TAG, "unsupported interface %s", sniffer_args.interface->sval[0]);
return 1;
}
} else { } else {
ESP_LOGE(SNIFFER_TAG, "unsupported interface %s", sniffer_args.interface->sval[0]); ESP_LOGE(SNIFFER_TAG, "unsupported interface %s", sniffer_args.interface->sval[0]);
return 1; return 1;
} }
} }
else {
snf_rt.interf = SNIFFER_INTF_WLAN;
ESP_LOGW(SNIFFER_TAG, "sniffing interface set to wlan by default");
}
/* Check channel: "-c" option */ /* Check channel: "-c" option */
snf_rt.channel = SNIFFER_DEFAULT_CHANNEL; switch (snf_rt.interf) {
if (sniffer_args.channel->count) { case SNIFFER_INTF_WLAN:
snf_rt.channel = sniffer_args.channel->ival[0]; snf_rt.channel = SNIFFER_DEFAULT_CHANNEL;
if (sniffer_args.channel->count) {
snf_rt.channel = sniffer_args.channel->ival[0];
}
break;
case SNIFFER_INTF_ETH:
if (sniffer_args.channel->count) {
ESP_LOGW(SNIFFER_TAG, "'channel' option is not available for Ethernet");
}
break;
default:
break;
} }
#if CONFIG_SNIFFER_PCAP_DESTINATION_SD #if CONFIG_SNIFFER_PCAP_DESTINATION_SD
@@ -354,6 +489,7 @@ static int do_sniffer_cmd(int argc, char **argv)
switch (snf_rt.interf) { switch (snf_rt.interf) {
case SNIFFER_INTF_WLAN: case SNIFFER_INTF_WLAN:
if (sniffer_args.filter->count) { if (sniffer_args.filter->count) {
snf_rt.filter = 0;
for (int i = 0; i < sniffer_args.filter->count; i++) { for (int i = 0; i < sniffer_args.filter->count; i++) {
snf_rt.filter += search_wifi_filter_hashtable(sniffer_args.filter->sval[i]); snf_rt.filter += search_wifi_filter_hashtable(sniffer_args.filter->sval[i]);
} }
@@ -365,6 +501,10 @@ static int do_sniffer_cmd(int argc, char **argv)
snf_rt.filter = WIFI_PROMIS_FILTER_MASK_ALL; snf_rt.filter = WIFI_PROMIS_FILTER_MASK_ALL;
} }
break; break;
case SNIFFER_INTF_ETH:
if (sniffer_args.filter->count) {
ESP_LOGW(SNIFFER_TAG, "'filter' option is not available for Ethernet");
}
default: default:
break; break;
} }
@@ -379,7 +519,7 @@ void register_sniffer(void)
{ {
sniffer_args.file = arg_str0("f", "file", "<file>", sniffer_args.file = arg_str0("f", "file", "<file>",
"name of the file storing the packets in pcap format"); "name of the file storing the packets in pcap format");
sniffer_args.interface = arg_str0("i", "interface", "<wlan>", sniffer_args.interface = arg_str0("i", "interface", "<wlan|eth0|eth1|...>",
"which interface to capture packet"); "which interface to capture packet");
sniffer_args.filter = arg_strn("F", "filter", "<mgmt|data|ctrl|misc|mpdu|ampdu|fcsfail>", 0, 7, "filter parameters"); sniffer_args.filter = arg_strn("F", "filter", "<mgmt|data|ctrl|misc|mpdu|ampdu|fcsfail>", 0, 7, "filter parameters");
sniffer_args.channel = arg_int0("c", "channel", "<channel>", "communication channel to use"); sniffer_args.channel = arg_int0("c", "channel", "<channel>", "communication channel to use");

View File

@@ -17,7 +17,9 @@ extern "C" {
* *
*/ */
typedef enum { typedef enum {
SNIFFER_INTF_WLAN = 0, /*!< WLAN interface */ SNIFFER_INTF_UNKNOWN = 0,
SNIFFER_INTF_WLAN, /*!< WLAN interface */
SNIFFER_INTF_ETH, /*!< Ethernet interface */
} sniffer_intf_t; } sniffer_intf_t;
/** /**
@@ -36,6 +38,7 @@ typedef enum {
} sniffer_wlan_filter_t; } sniffer_wlan_filter_t;
void register_sniffer(void); void register_sniffer(void);
esp_err_t sniffer_reg_eth_intf(esp_eth_handle_t eth_handle);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -12,7 +12,6 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#include "linenoise/linenoise.h" #include "linenoise/linenoise.h"
#include "argtable3/argtable3.h" #include "argtable3/argtable3.h"
#include "esp_netif.h"
#include "esp_console.h" #include "esp_console.h"
#include "esp_event.h" #include "esp_event.h"
#include "esp_vfs_fat.h" #include "esp_vfs_fat.h"
@@ -28,6 +27,9 @@
#include "sdmmc_cmd.h" #include "sdmmc_cmd.h"
#include "cmd_system.h" #include "cmd_system.h"
#include "cmd_sniffer.h" #include "cmd_sniffer.h"
#if CONFIG_ETH_USE_SPI_ETHERNET
#include "driver/spi_master.h"
#endif // CONFIG_ETH_USE_SPI_ETHERNET
#if CONFIG_SNIFFER_STORE_HISTORY #if CONFIG_SNIFFER_STORE_HISTORY
#define HISTORY_MOUNT_POINT "/data" #define HISTORY_MOUNT_POINT "/data"
@@ -83,14 +85,148 @@ static void initialize_nvs(void)
/* Initialize wifi with tcp/ip adapter */ /* Initialize wifi with tcp/ip adapter */
static void initialize_wifi(void) 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(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg)); ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
} }
#ifndef CONFIG_SNIFFER_NO_ETHERNET
/** Event handler for Ethernet events */
static void eth_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
uint8_t mac_addr[6] = {0};
/* we can get the ethernet driver handle from event data */
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
printf("\n");
ESP_LOGI(TAG, "Ethernet Link Up");
ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x\n",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
break;
case ETHERNET_EVENT_DISCONNECTED:
printf("\n");
ESP_LOGI(TAG, "Ethernet Link Down");
break;
case ETHERNET_EVENT_START:
printf("\n");
ESP_LOGI(TAG, "Ethernet Started");
break;
case ETHERNET_EVENT_STOP:
printf("\n");
ESP_LOGI(TAG, "Ethernet Stopped");
break;
default:
break;
}
}
static void initialize_eth(void)
{
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = CONFIG_SNIFFER_ETH_PHY_ADDR;
phy_config.reset_gpio_num = CONFIG_SNIFFER_ETH_PHY_RST_GPIO;
#if CONFIG_SNIFFER_USE_INTERNAL_ETHERNET
mac_config.smi_mdc_gpio_num = CONFIG_SNIFFER_ETH_MDC_GPIO;
mac_config.smi_mdio_gpio_num = CONFIG_SNIFFER_ETH_MDIO_GPIO;
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
#if CONFIG_SNIFFER_ETH_PHY_IP101
esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
#elif CONFIG_SNIFFER_ETH_PHY_RTL8201
esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config);
#elif CONFIG_SNIFFER_ETH_PHY_LAN8720
esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config);
#elif CONFIG_SNIFFER_ETH_PHY_DP83848
esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config);
#elif CONFIG_SNIFFER_ETH_PHY_KSZ8041
esp_eth_phy_t *phy = esp_eth_phy_new_ksz8041(&phy_config);
#elif CONFIG_SNIFFER_ETH_PHY_KSZ8081
esp_eth_phy_t *phy = esp_eth_phy_new_ksz8081(&phy_config);
#endif
#elif CONFIG_ETH_USE_SPI_ETHERNET
gpio_install_isr_service(0);
spi_device_handle_t spi_handle = NULL;
spi_bus_config_t buscfg = {
.miso_io_num = CONFIG_SNIFFER_ETH_SPI_MISO_GPIO,
.mosi_io_num = CONFIG_SNIFFER_ETH_SPI_MOSI_GPIO,
.sclk_io_num = CONFIG_SNIFFER_ETH_SPI_SCLK_GPIO,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
};
ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_SNIFFER_ETH_SPI_HOST, &buscfg, 1));
#if CONFIG_SNIFFER_USE_KSZ8851SNL
spi_device_interface_config_t devcfg = {
.mode = 0,
.clock_speed_hz = CONFIG_SNIFFER_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
.spics_io_num = CONFIG_SNIFFER_ETH_SPI_CS_GPIO,
.queue_size = 20
};
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_SNIFFER_ETH_SPI_HOST, &devcfg, &spi_handle));
/* KSZ8851SNL ethernet driver is based on spi driver */
eth_ksz8851snl_config_t ksz8851snl_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_handle);
ksz8851snl_config.int_gpio_num = CONFIG_SNIFFER_ETH_SPI_INT_GPIO;
esp_eth_mac_t *mac = esp_eth_mac_new_ksz8851snl(&ksz8851snl_config, &mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_ksz8851snl(&phy_config);
#elif CONFIG_SNIFFER_USE_DM9051
spi_device_interface_config_t devcfg = {
.command_bits = 1,
.address_bits = 7,
.mode = 0,
.clock_speed_hz = CONFIG_SNIFFER_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
.spics_io_num = CONFIG_SNIFFER_ETH_SPI_CS_GPIO,
.queue_size = 20
};
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_SNIFFER_ETH_SPI_HOST, &devcfg, &spi_handle));
/* dm9051 ethernet driver is based on spi driver */
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
dm9051_config.int_gpio_num = CONFIG_SNIFFER_ETH_SPI_INT_GPIO;
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
#elif CONFIG_SNIFFER_USE_W5500
spi_device_interface_config_t devcfg = {
.command_bits = 16, // Actually it's the address phase in W5500 SPI frame
.address_bits = 8, // Actually it's the control phase in W5500 SPI frame
.mode = 0,
.clock_speed_hz = CONFIG_SNIFFER_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
.spics_io_num = CONFIG_SNIFFER_ETH_SPI_CS_GPIO,
.queue_size = 20
};
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_SNIFFER_ETH_SPI_HOST, &devcfg, &spi_handle));
/* w5500 ethernet driver is based on spi driver */
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
w5500_config.int_gpio_num = CONFIG_SNIFFER_ETH_SPI_INT_GPIO;
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);
#endif
#endif // CONFIG_ETH_USE_SPI_ETHERNET
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
esp_eth_handle_t eth_handle = NULL;
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &eth_handle));
#if !CONFIG_SNIFFER_USE_INTERNAL_ETHERNET
/* The SPI Ethernet module might doesn't have a burned factory MAC address, we cat to set it manually.
02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.
*/
ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
0x02, 0x00, 0x00, 0x12, 0x34, 0x56
}));
#endif
/* start Ethernet driver state machine */
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
/* Register Ethernet interface to could be used by sniffer */
ESP_ERROR_CHECK(sniffer_reg_eth_intf(eth_handle));
}
#endif // CONFIG_SNIFFER_NO_ETHERNET
#if CONFIG_SNIFFER_PCAP_DESTINATION_SD #if CONFIG_SNIFFER_PCAP_DESTINATION_SD
static struct { static struct {
struct arg_str *device; struct arg_str *device;
@@ -226,8 +362,16 @@ void app_main(void)
{ {
initialize_nvs(); initialize_nvs();
/*--- Initialize Network ---*/
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* Initialize WiFi */ /* Initialize WiFi */
initialize_wifi(); initialize_wifi();
#ifndef CONFIG_SNIFFER_NO_ETHERNET
/* Initialize Ethernet */
initialize_eth();
#endif
/*--- Initialize Console ---*/
esp_console_repl_t *repl = NULL; esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
#if CONFIG_SNIFFER_STORE_HISTORY #if CONFIG_SNIFFER_STORE_HISTORY
@@ -256,7 +400,7 @@ void app_main(void)
printf("\n =======================================================\n"); printf("\n =======================================================\n");
printf(" | Steps to sniffer WiFi packets |\n"); printf(" | Steps to sniffer WiFi packets |\n");
printf(" | |\n"); printf(" | |\n");
printf(" | 1. Enter 'help' to check all commands' usage |\n"); printf(" | 1. Enter 'help' to check all commands usage |\n");
printf(" | 2. Enter 'mount <device>' to mount filesystem |\n"); printf(" | 2. Enter 'mount <device>' to mount filesystem |\n");
printf(" | 3. Enter 'sniffer' to start capture packets |\n"); printf(" | 3. Enter 'sniffer' to start capture packets |\n");
printf(" | 4. Enter 'unmount <device>' to unmount filesystem |\n"); printf(" | 4. Enter 'unmount <device>' to unmount filesystem |\n");