ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
promisc.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4#ifndef PROTOCORE_PROMISC_H
5#define PROTOCORE_PROMISC_H
6
7#include "protocore_config.h" // the entry point: protocore_types.h for the widths
8
10
11/**
12 * @file promisc.h
13 * @brief Wi-Fi promiscuous (monitor) capture (PROTOCORE_ENABLE_PROMISC) - passive 802.11 sniffing.
14 *
15 * A read-only capture path: instead of joining a network and terminating traffic, listen to
16 * every 802.11 frame on a channel and hand it to a sink. The canonical wiring feeds the sink
17 * into the forwarding plane (network_drivers/network/forward), so captured Wi-Fi frames are bridged to another
18 * interface (e.g. Ethernet) for a wired collector - "capture on Wi-Fi, forward to Ethernet".
19 *
20 * Two host-testable pieces plus the ESP32 radio binding:
21 * - wifi_frame_parse(): decode the 802.11 MAC header (type/subtype, the to/from-DS address
22 * layout -> src / dst / bssid, sequence number, header length). Pure.
23 * - pcap_* : build the classic libpcap global + per-record headers (DLT_IEEE802_11) so a
24 * forwarded frame is a valid PCAP stream a wired Wireshark / tcpdump can read. Pure.
25 * - protocore_promisc_begin() / _set_channel() / _end(): monitor-mode bring-up whose rx
26 * callback copies each frame (with RSSI + channel) to the registered sink. ESP32 only.
27 *
28 * Capture is strictly passive (no injection) and fail-closed: the sink is expected to drop, not
29 * block, when its downstream is full, so the live data path is never stalled.
30 *
31 * @c work is PROTOCORE_PROMISC_BORROW bytes the CALLER took, at an address it knows. It is not held past the call, so
32 * nothing here aliases it. How those bytes are carved is this module's and is never named here.
33 *
34 * @author Douglas Quigg (dstroy0)
35 * @date 2026
36 */
37
38/** @brief 802.11 frame type (frame-control bits 2-3). */
46
47/** @brief Decoded 802.11 MAC header. src / dst / bssid point into the frame (6 bytes) or null. */
48typedef struct
49{
50 WifiFrameType type; ///< WifiFrameType
51 uint8_t subtype; ///< 0..15
54 proto_bool protected_frame; ///< the Protected-Frame (WEP/CCMP) bit
55 proto_bool is_qos; ///< QoS data subtype (adds 2 header bytes)
56 uint16_t seq; ///< 12-bit sequence number
57 uint16_t hdr_len; ///< MAC header length (bytes)
58 const uint8_t *dst; ///< destination (receiver) MAC, per the to/from-DS layout
59 const uint8_t *src; ///< source (transmitter) MAC
60 const uint8_t *bssid; ///< BSSID (null for a WDS 4-address frame)
62
63/**
64 * @brief Sink for one captured frame: the raw 802.11 bytes plus radio metadata.
65 * @param frame the 802.11 MAC frame (points into the driver buffer; copy if retained).
66 * @param len frame length in bytes.
67 * @param rssi received signal strength (dBm).
68 * @param channel the channel it was captured on.
69 */
70typedef void (*protocore_promisc_sink_fn)(const uint8_t *frame, uint16_t len, int8_t rssi, uint8_t channel);
71
72/** @brief Dispatch table. Addressed by offset, so the layout is asserted below. */
73typedef struct
74{
75 proto_bool (*wifi_frame_parse)(uint8_t *, const uint8_t *, uint16_t, WifiFrameInfo *);
76 proto_bool (*begin)(uint8_t *, uint8_t, protocore_promisc_sink_fn);
77 void (*set_channel)(uint8_t *, uint8_t);
78 void (*end)(uint8_t *);
79} PromiscNs;
80PROTOCORE_NS_LAYOUT(PromiscNs, wifi_frame_parse, begin, set_channel, end);
81
82/**
83 * @brief Parse an 802.11 MAC header (IEEE 802.11 §9.2 / §9.3.2, the .
84 * @param work PROTOCORE_PROMISC_BORROW bytes the caller took. Not held past the call.
85 * @param frame Frame
86 * @param len Len
87 * @param out Out
88 * @return PROTO_TRUE on success.
89 */
90proto_bool protocore_promisc_wifi_frame_parse(uint8_t *work, const uint8_t *frame, uint16_t len, WifiFrameInfo *out);
91/**
92 * @brief Start promiscuous capture on channel; every frame is delivered to .
93 * @param work PROTOCORE_PROMISC_BORROW bytes the caller took. Not held past the call.
94 * @param channel Channel
95 * @param sink Sink
96 * @return PROTO_TRUE on success.
97 */
98proto_bool protocore_promisc_begin(uint8_t *work, uint8_t channel, protocore_promisc_sink_fn sink);
99/**
100 * @brief Retune the capture to a different channel (1..14).
101 * @param work PROTOCORE_PROMISC_BORROW bytes the caller took. Not held past the call.
102 * @param channel Channel
103 */
104void protocore_promisc_set_channel(uint8_t *work, uint8_t channel);
105/**
106 * @brief Stop promiscuous capture.
107 * @param work PROTOCORE_PROMISC_BORROW bytes the caller took. Not held past the call.
108 */
109void protocore_promisc_end(uint8_t *work);
110
111/**
112 * @brief Sink for one captured frame: the raw 802.11 bytes plus radio metadata.
113 * @param frame the 802.11 MAC frame (points into the driver buffer; copy if retained).
114 * @param len frame length in bytes.
115 * @param rssi received signal strength (dBm).
116 * @param channel the channel it was captured on.
117 */
118typedef void (*protocore_promisc_sink_fn)(const uint8_t *frame, uint16_t len, int8_t rssi, uint8_t channel);
119/**
120 * @brief The PROTOCORE_PROMISC_BORROW bytes this module's state lives in.
121 *
122 * Stated beside the namespace rather than on it: an entry takes a borrow, and this is where
123 * that borrow comes from. Taken once from the end of the pool, which no mark and no release
124 * walks, so the state lasts the life of the program.
125 *
126 * @return the span.
127 */
129
130/** @brief Module namespace. */
135
137
138#endif // PROTOCORE_PROMISC_H
PROTO_ENUM_PACKED
Application protocol spoken on a listener port or connection slot.
#define PROTOCORE_NS_LAYOUT(T,...)
Pin every dispatch slot of a table that is nothing but function pointers.
#define PROTOCORE_NS
Storage for a dispatch table. The const is load bearing.
enum PROTO_ENUM_PACKED WifiFrameType
802.11 frame type (frame-control bits 2-3).
proto_bool protocore_promisc_begin(uint8_t *work, uint8_t channel, protocore_promisc_sink_fn sink)
Start promiscuous capture on channel; every frame is delivered to .
void protocore_promisc_set_channel(uint8_t *work, uint8_t channel)
Retune the capture to a different channel (1..14).
void protocore_promisc_end(uint8_t *work)
Stop promiscuous capture.
PROTOCORE_NS PromiscNs Promisc PROTOCORE_UNUSED
Module namespace.
Definition promisc.h:131
uint8_t * protocore_promisc_span(void)
The PROTOCORE_PROMISC_BORROW bytes this module's state lives in.
@ WIFI_FT_DATA
Definition promisc.h:43
@ WIFI_FT_MGMT
Definition promisc.h:41
@ WIFI_FT_EXT
Definition promisc.h:44
@ WIFI_FT_CTRL
Definition promisc.h:42
proto_bool protocore_promisc_wifi_frame_parse(uint8_t *work, const uint8_t *frame, uint16_t len, WifiFrameInfo *out)
Parse an 802.11 MAC header (IEEE 802.11 §9.2 / §9.3.2, the .
void(* protocore_promisc_sink_fn)(const uint8_t *frame, uint16_t len, int8_t rssi, uint8_t channel)
Sink for one captured frame: the raw 802.11 bytes plus radio metadata.
Definition promisc.h:70
Dispatch table. Addressed by offset, so the layout is asserted below.
Definition promisc.h:74
proto_bool(* wifi_frame_parse)(uint8_t *, const uint8_t *, uint16_t, WifiFrameInfo *)
Definition promisc.h:75
Decoded 802.11 MAC header. src / dst / bssid point into the frame (6 bytes) or null.
Definition promisc.h:49
const uint8_t * src
source (transmitter) MAC
Definition promisc.h:59
uint16_t hdr_len
MAC header length (bytes)
Definition promisc.h:57
proto_bool from_ds
Definition promisc.h:53
uint16_t seq
12-bit sequence number
Definition promisc.h:56
const uint8_t * dst
destination (receiver) MAC, per the to/from-DS layout
Definition promisc.h:58
proto_bool is_qos
QoS data subtype (adds 2 header bytes)
Definition promisc.h:55
const uint8_t * bssid
BSSID (null for a WDS 4-address frame)
Definition promisc.h:60
proto_bool protected_frame
the Protected-Frame (WEP/CCMP) bit
Definition promisc.h:54
WifiFrameType type
WifiFrameType.
Definition promisc.h:50
proto_bool to_ds
Definition promisc.h:52
uint8_t subtype
0..15
Definition promisc.h:51
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97