espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
12.88k stars 7.08k forks source link

Promiscuous mode doesn't receive UDP packets (IDFGH-13138) #14078

Open evoon opened 5 days ago

evoon commented 5 days ago

Answers checklist.

General issue report

Hello, I have a question regarding the promiscuous mode. A PC is connected to an OPEN Wi-Fi, sending broadcast UDP packets 10 times per second, through the Wi-Fi interface. I can observe them well on another PC set in monitor mode with wireshark (not connected to the Wi-Fi). Yet, the ESP32 doesn't get them. It only gets some other packets sent by the APs and devices around, but not our UDP data packets.

Code used :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sdkconfig.h"
#include "esp_console.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "esp_err.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_system.h"
#include "esp_wifi_he_types.h"

static const char *TAG = "monitor";

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);
}

static void wifi_sniffer_cb(void *recv_buf, wifi_promiscuous_pkt_type_t type) {
    wifi_promiscuous_pkt_t* pkt = (wifi_promiscuous_pkt_t*)recv_buf;
    wifi_pkt_rx_ctrl_t ctrl = pkt->rx_ctrl;
    if (pkt->payload[0] != 0x88) {
        return;
    }
    ESP_LOGI(TAG, "Payload =");
    for (int i = 0; i < ctrl.sig_len; i++) {
        printf("%2x ", pkt->payload[i]);
    }
    printf("\n\n");
}

static void initialize_wifi(void) {
    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));
    ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
    ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(wifi_sniffer_cb));
    ESP_ERROR_CHECK(esp_wifi_start());
}

void app_main(void) {
    initialize_nvs();
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    initialize_wifi();
}

The objective is to catch the UDP packets without being connected to the Wi-Fi. payload[0] != 0x88 is used to filter (i.e. let only) the QoS Data packets come through (I have verified on wireshark that the UDP packets have this 0x88 at the beginning of the frame, after the radiotap header). I also see that DNS packets are absent. Yet, all ARP packets are catched. And ARP packets are about the same length as UDP ones (observed on Wireshark).

Here is what the packet i want to capture looks like :

Screenshot from 2024-06-26 14-19-34

There are not a lot of frames that start with 0x88, so I don't think it happens because I print the payload at the same time as the sniffing, nor a buffer issue.

Channel and BW is the same between the ARP packets i can receive and the UDP packets I can't receive.

I feel like there is some pre-filtering in the TCP/IP stack.

Many thanks, evoon

MaxwellAlan commented 4 days ago

Hi @evoon

plz check the sniffer channel and bandwidth.

Thanks.