监听模式
WiFi 混杂模式 — 空口抓包 —
wifi_set_promis_mode()、WiFi 管理帧回调前置阅读:STA 连接
学习目标
- 理解混杂模式与普通模式的区别——网卡接收空口中所有帧(不限目标 MAC)
- 掌握
wifi_set_promis_mode()的配置方法和帧过滤参数 - 掌握
wifi_set_promis_rx_pkt_cb()注册接收回调并解析帧类型 - 能够在 WS63 上捕获周边 WiFi 空口帧并解析管理/数据/控制帧
基本概念
混杂模式 vs 普通模式
| 对比项 | 普通模式 | 混杂模式 |
|---|---|---|
| 接收范围 | 仅目标 MAC 是本机的帧 | 空口中所有帧 |
| CPU 负载 | 正常 | 增加(每帧都进回调) |
| 功耗 | 正常 | 增加约 2~5mA |
| 典型用途 | 正常通信 | 抓包分析、网络调试 |
帧过滤参数 wifi_ptype_filter_stru
5 个独立开关,按需开启以减少中断负载:
| 过滤项 | 说明 |
|---|---|
mdata |
管理数据帧(Management Data) |
udata |
用户数据帧(User Data) |
mmngt |
管理帧(Management)——含 Beacon、Probe |
umngt |
用户管理帧 |
custom_en |
自定义帧 |
典型使用场景
| 场景 | 开启的过滤器 |
|---|---|
| 抓 Beacon(周边 AP 扫描) | mmngt |
| 抓 Probe Request(周边 STA 检测) | mmngt |
| 抓数据帧(分析通信内容) | mdata + udata |
涉及 API
| API | 用途 |
|---|---|
wifi_set_promis_mode(iftype, enable, &filter) |
开启/关闭混杂模式 |
wifi_set_promis_rx_pkt_cb(cb) |
注册帧接收回调 |
wifi_set_mgmt_frame_rx_cb(cb, mode) |
单独的管理帧回调通道 |
案例说明
做什么
WS63 STA 连接后开启混杂模式 → 捕获 Beacon/Probe Request → 解析 SSID/BSSID/RSSI → 串口输出。
案例流程
sequenceDiagram
participant W as WS63
participant AP as 周边 AP
participant S as 周边 STA
W->>W: STA 连接路由器
W->>W: wifi_set_promis_mode 开启
AP->>W: Beacon (SSID=HomeWiFi)
Note over W: callback: 管理帧, Beacon
S->>W: Probe Request (SSID=搜索中)
Note over W: callback: 管理帧, ProbeReq
W->>W: wifi_set_promis_mode 关闭
案例操作指导
第一步:编译
Kconfig 启用 WiFi STA + 混杂模式。
第二步:烧录
第三步:验证
手机在 WS63 附近搜索 WiFi → 串口输出手机的 Probe Request 帧。
关键配置
| 参数 | 推荐值 | 说明 |
|---|---|---|
| 帧过滤 | mdata + mmngt |
不开启 custom_en(减少噪声) |
| 回调耗时 | < 1ms | 不 printf,只解析 MAC header |
| 功耗 | +2~5mA | 射频持续接收 |
代码详解
开启混杂模式
#include "wifi.h"
wifi_ptype_filter_stru filter = {
.mdata = 1, // 管理数据帧
.udata = 0,
.mmngt = 1, // 管理帧(Beacon/Probe)
.umngt = 0,
.custom_en = 0
};
wifi_set_promis_mode(WIFI_IF_TYPE_STA, 1, &filter);
帧接收回调
static void promis_rx_cb(unsigned char *data, int len, int rssi) {
/* 解析 802.11 MAC Header */
uint16_t frame_ctrl = *(uint16_t *)data;
uint8_t type = (frame_ctrl >> 2) & 0x03; // Type
uint8_t subtype = (frame_ctrl >> 4) & 0x0F; // Subtype
/* Type: 00=管理帧, 01=控制帧, 10=数据帧 */
if (type == 0 && subtype == 8) {
printf("Beacon: RSSI=%d\n", rssi);
} else if (type == 0 && subtype == 4) {
printf("ProbeReq: RSSI=%d\n", rssi);
}
}
wifi_set_promis_rx_pkt_cb(promis_rx_cb);