DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
promisc.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file promisc.h
6 * @brief Wi-Fi promiscuous (monitor) capture (DETWS_ENABLE_PROMISC) - passive 802.11 sniffing.
7 *
8 * A read-only capture path: instead of joining a network and terminating traffic, listen to
9 * every 802.11 frame on a channel and hand it to a sink. The canonical wiring feeds the sink
10 * into the forwarding plane (services/forward), so captured Wi-Fi frames are bridged to another
11 * interface (e.g. Ethernet) for a wired collector - "capture on Wi-Fi, forward to Ethernet".
12 *
13 * Two host-testable pieces plus the ESP32 radio binding:
14 * - wifi_frame_parse(): decode the 802.11 MAC header (type/subtype, the to/from-DS address
15 * layout -> src / dst / bssid, sequence number, header length). Pure.
16 * - pcap_* : build the classic libpcap global + per-record headers (DLT_IEEE802_11) so a
17 * forwarded frame is a valid PCAP stream a wired Wireshark / tcpdump can read. Pure.
18 * - promisc_begin() / _set_channel() / _end(): esp_wifi_set_promiscuous() bring-up whose rx
19 * callback copies each frame (with RSSI + channel) to the registered sink. ESP32 only.
20 *
21 * Capture is strictly passive (no injection) and fail-closed: the sink is expected to drop, not
22 * block, when its downstream is full, so the live data path is never stalled.
23 *
24 * @author Douglas Quigg (dstroy0)
25 * @date 2026
26 */
27
28#ifndef DETERMINISTICESPASYNCWEBSERVER_PROMISC_H
29#define DETERMINISTICESPASYNCWEBSERVER_PROMISC_H
30
31#include "ServerConfig.h"
32
33#if DETWS_ENABLE_PROMISC
34
35#include "shared_primitives/pcap.h" // det_pcap_* framing + DET_DLT_IEEE802_11
36#include <stddef.h>
37#include <stdint.h>
38
39/** @brief 802.11 frame type (frame-control bits 2-3). */
40enum class WifiFrameType : uint8_t
41{
42 WIFI_FT_MGMT = 0,
43 WIFI_FT_CTRL = 1,
44 WIFI_FT_DATA = 2,
45 WIFI_FT_EXT = 3,
46};
47
48/** @brief Decoded 802.11 MAC header. src / dst / bssid point into the frame (6 bytes) or null. */
49struct WifiFrameInfo
50{
51 WifiFrameType type; ///< WifiFrameType
52 uint8_t subtype; ///< 0..15
53 bool to_ds;
54 bool from_ds;
55 bool protected_frame; ///< the Protected-Frame (WEP/CCMP) bit
56 bool is_qos; ///< QoS data subtype (adds 2 header bytes)
57 uint16_t seq; ///< 12-bit sequence number
58 uint16_t hdr_len; ///< MAC header length (bytes)
59 const uint8_t *dst; ///< destination (receiver) MAC, per the to/from-DS layout
60 const uint8_t *src; ///< source (transmitter) MAC
61 const uint8_t *bssid; ///< BSSID (null for a WDS 4-address frame)
62};
63
64/**
65 * @brief Parse an 802.11 MAC header (IEEE 802.11 §9.2 / §9.3.2, the to/from-DS address rules).
66 * @return true on success; false if @p frame is shorter than the header its bits imply.
67 */
68bool wifi_frame_parse(const uint8_t *frame, uint16_t len, WifiFrameInfo *out);
69
70// libpcap framing lives in shared_primitives/pcap.h: det_pcap_global_header() with
71// DET_DLT_IEEE802_11 + det_pcap_record_header() wrap a captured 802.11 frame as a valid PCAP.
72
73/**
74 * @brief Sink for one captured frame: the raw 802.11 bytes plus radio metadata.
75 * @param frame the 802.11 MAC frame (points into the driver buffer; copy if retained).
76 * @param len frame length in bytes.
77 * @param rssi received signal strength (dBm).
78 * @param channel the channel it was captured on.
79 */
80typedef void (*promisc_sink_fn)(const uint8_t *frame, uint16_t len, int8_t rssi, uint8_t channel);
81
82/**
83 * @brief Start promiscuous capture on @p channel; every frame is delivered to @p sink.
84 *
85 * Requires Wi-Fi to be initialized (e.g. WiFi.mode(WIFI_STA)). Returns immediately.
86 * @return true if capture started; false if @p sink is null or on host builds.
87 */
88bool promisc_begin(uint8_t channel, promisc_sink_fn sink);
89
90/** @brief Retune the capture to a different channel (1..14). */
91void promisc_set_channel(uint8_t channel);
92
93/** @brief Stop promiscuous capture. */
94void promisc_end(void);
95
96#endif // DETWS_ENABLE_PROMISC
97
98#endif // DETERMINISTICESPASYNCWEBSERVER_PROMISC_H
User-facing configuration for DeterministicESPAsyncWebServer.
libpcap file framing - the classic global + per-record headers, link-type agnostic.