XR806是一款使用ARMv8-M的Wi-Fi BLE Combo MCU。本文使用XR806開發(fā)板以及基于FreeRTOS的XR806 SDK實(shí)現(xiàn)了自定義發(fā)送802.11 Beacon幀,并進(jìn)行了無線抓包分析以及掃描測試來驗(yàn)證幀的發(fā)送結(jié)果。
環(huán)境配置過程
環(huán)境搭建可以參考官方文檔開發(fā)環(huán)境搭建。本測試中使用的開發(fā)環(huán)境為Ubuntu 22.04。需要注意的是,在下載ARM Toolchain時(shí),由于網(wǎng)站更新,文檔中鏈接已不可用,在其中找到對(duì)應(yīng)的gcc-arm-none-eabi-8-2019-q3-update版本下載即可。
配置好環(huán)境后選取某個(gè)Demo或者Example進(jìn)行編譯,在Ubuntu下,使用的燒錄工具為SDK中tools
目錄下的phoenixMC
可執(zhí)行程序,示例的燒錄命令為
./phoenixMC -c /dev/ttyUSB0 -i ../out/xr_system.img
其他參數(shù)信息可以使用-h
獲取。燒錄好后可以連接串口查看輸出,控制臺(tái)輸出可能會(huì)出現(xiàn)換行不對(duì)齊的情況,此時(shí)需要進(jìn)行換行修正。在本次測試中使用的串口工具為picocom
,需要將輸出的n
轉(zhuǎn)為rn
示例的連接串口命令為
picocom -b 115200 --imap lfcrlf /dev/ttyUSB0
在燒錄時(shí)需要讓開發(fā)板進(jìn)入升級(jí)模式,如果當(dāng)前程序支持upgrade
命令,可以直接發(fā)送upgrade
命令。若不支持,需要短接開發(fā)板上的兩個(gè)觸點(diǎn)或者使用Windows下的燒錄工具,在工具上勾選硬件復(fù)位燒寫模式。
測試過程
通過瀏覽XR806的SDK可以發(fā)現(xiàn),在wlan.h
中提供有APIint wlan_send_raw_frame(struct netif *netif, int type, uint8_t *buffer, int len);
。該API可以支持發(fā)送自定義的802.11幀,只需要提供網(wǎng)絡(luò)接口,幀類型,數(shù)據(jù)幀和長度即可。受esp32-80211-tx啟發(fā),在本測試中基于該API發(fā)送自定義的Beacon幀,達(dá)到同時(shí)存在多個(gè)AP的假象。在IBSS網(wǎng)絡(luò)架構(gòu)中,AP每隔一段時(shí)間就會(huì)向外界發(fā)出一個(gè)Beacon幀用來宣告自己802.11網(wǎng)絡(luò)的存在。平時(shí)Wi-Fi的被動(dòng)掃描也是基于Beacon幀進(jìn)行。
使用API構(gòu)造Beacon
進(jìn)一步瀏覽SDK可以發(fā)現(xiàn),SDK中提供了wlan_construct_beacon
的API,這簡化了我們構(gòu)造Beacon的過程。只要提供beacon的部分字段信息即可,如SA,DA,BSSID,Channel等。具體代碼如下:
#include < stdio.h >
#include < string.h >
#include "net/wlan/wlan.h"
#include "net/wlan/wlan_defs.h"
#include "net/wlan/wlan_ext_req.h"
#include "net/wlan/wlan_frame.h"
#include "common/framework/net_ctrl.h"
#include "common/framework/platform_init.h"
#include "lwip/inet.h"
#define CMD_WLAN_NETIF wlan_netif_get(WLAN_MODE_NONE)
#define BEACON_FRAME_LEN 256
static uint8_t beacon_frame_buf[BEACON_FRAME_LEN];
typedef struct {
uint8_t *data;
uint32_t len;
} frame_data;
static uint8_t beacon_addr[6];
static char beacon_ssid[32];
static uint32_t beacon_len;
static frame_data beacon_frame;
char *ssids[] = {
"1 Hello Wireless World",
"2 from Allwinner XR806",
"3 running on FreeRTOS",
"4 for Jishu Community"
};
uint8_t bssid[4][6] = {
{0xba, 0xde, 0xaf, 0xfe, 0x00, 0x06},
{0xba, 0xde, 0xaf, 0xfe, 0x00, 0x07},
{0xba, 0xde, 0xaf, 0xfe, 0x00, 0x08},
{0xba, 0xde, 0xaf, 0xfe, 0x00, 0x09},
};
#define TOTAL_LINES (sizeof(ssids) / sizeof(char *))
uint8_t line = 0;
static void beacon_frame_create(void)
{
wlan_ap_config_t config;
memset(&config, 0, sizeof(config));
config.field = WLAN_AP_FIELD_SSID;
if (wlan_ap_get_config(&config) != 0) {
printf("get config failedn");
return;
}
printf("ssid:%s,ssid_len: %dn", ssids[line], strlen(ssids[line]));
memcpy(beacon_ssid, ssids[line], strlen(ssids[line]));
memcpy(beacon_addr, bssid[line], IEEE80211_ADDR_LEN);
beacon_len = wlan_construct_beacon(beacon_frame_buf, BEACON_FRAME_LEN, beacon_addr, NULL, beacon_addr,
(uint8_t *)beacon_ssid, strlen(ssids[line]), 1);
if (++line >= TOTAL_LINES)
{
line = 0;
}
beacon_frame.data = beacon_frame_buf;
beacon_frame.len = beacon_len;
printf("beacon_len %dn", beacon_len);
int ret = 0;
ret = wlan_send_raw_frame(CMD_WLAN_NETIF, IEEE80211_FC_STYPE_AUTH, beacon_frame.data, beacon_frame.len);
printf("Send beacon frame: %dn", ret);
}
int main(void)
{
platform_init();
net_switch_mode(WLAN_MODE_HOSTAP);
while(1)
{
OS_MSleep(100 / TOTAL_LINES);
beacon_frame_create();
}
return 0;
}
代碼的基本邏輯為:首先預(yù)定義好需要發(fā)送的SSID及其對(duì)應(yīng)的BSSID,然后在主函數(shù)中先初始化AP模式,然后每100ms發(fā)送一次所有的Beacon。發(fā)送Beacon前需要填充好Beacon幀的內(nèi)容。
測試效果如下:
在代碼中我們使用的SSID列表為
"1 Hello Wireless World",
"2 from Allwinner XR806",
"3 running on FreeRTOS",
"4 for Jishu Community"
上電后程序啟動(dòng),使用手機(jī)掃描Wi-Fi便可以查看到這些AP信息
其中AP-XRADIO為默認(rèn)的AP名稱。
不使用API構(gòu)造Beacon
我們也可以不使用相關(guān)API,而直接填充內(nèi)容。為了演示,在這里將參考項(xiàng)目的實(shí)現(xiàn)遷移過來,具體代碼如下:
#include < stdio.h >
#include < string.h >
#include "net/wlan/wlan.h"
#include "net/wlan/wlan_defs.h"
#include "net/wlan/wlan_ext_req.h"
#include "net/wlan/wlan_frame.h"
#include "common/framework/net_ctrl.h"
#include "common/framework/platform_init.h"
#include "lwip/inet.h"
#define CMD_WLAN_NETIF wlan_netif_get(WLAN_MODE_NONE)
uint8_t beacon_raw[] = {
0x80, 0x00, // 0-1: Frame Control
0x00, 0x00, // 2-3: Duration
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 4-9: Destination address (broadcast)
0xba, 0xde, 0xaf, 0xfe, 0x00, 0x06, // 10-15: Source address
0xba, 0xde, 0xaf, 0xfe, 0x00, 0x06, // 16-21: BSSID
0x00, 0x00, // 22-23: Sequence / fragment number
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 24-31: Timestamp (GETS OVERWRITTEN TO 0 BY HARDWARE)
0x64, 0x00, // 32-33: Beacon interval
0x31, 0x04, // 34-35: Capability info
0x00, 0x00, /* FILL CONTENT HERE */ // 36-38: SSID parameter set, 0x00:length:content
0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, // 39-48: Supported rates
0x03, 0x01, 0x01, // 49-51: DS Parameter set, current channel 1 (= 0x01),
0x05, 0x04, 0x01, 0x02, 0x00, 0x00, // 52-57: Traffic Indication Map
};
char *rick_ssids[] = {
"01 Never gonna give you up",
"02 Never gonna let you down",
"03 Never gonna run around",
"04 and desert you",
"05 Never gonna make you cry",
"06 Never gonna say goodbye",
"07 Never gonna tell a lie",
"08 and hurt you"
};
#define BEACON_SSID_OFFSET 38
#define SRCADDR_OFFSET 10
#define BSSID_OFFSET 16
#define SEQNUM_OFFSET 22
#define TOTAL_LINES (sizeof(rick_ssids) / sizeof(char *))
int main(void)
{
platform_init();
net_switch_mode(WLAN_MODE_HOSTAP);
uint8_t line = 0;
// Keep track of beacon sequence numbers on a per-songline-basis
uint16_t seqnum[TOTAL_LINES] = { 0 };
int ret = 0;
while (1)
{
OS_MSleep(100 / TOTAL_LINES);
// Insert line of Rick Astley's "Never Gonna Give You Up" into beacon packet
printf("%i %i %srn", strlen(rick_ssids[line]), TOTAL_LINES, rick_ssids[line]);
uint8_t beacon_rick[200];
memcpy(beacon_rick, beacon_raw, BEACON_SSID_OFFSET - 1);
beacon_rick[BEACON_SSID_OFFSET - 1] = strlen(rick_ssids[line]);
memcpy(&beacon_rick[BEACON_SSID_OFFSET], rick_ssids[line], strlen(rick_ssids[line]));
memcpy(&beacon_rick[BEACON_SSID_OFFSET + strlen(rick_ssids[line])], &beacon_raw[BEACON_SSID_OFFSET], sizeof(beacon_raw) - BEACON_SSID_OFFSET);
// Last byte of source address / BSSID will be line number - emulate multiple APs broadcasting one song line each
beacon_rick[SRCADDR_OFFSET + 5] = line;
beacon_rick[BSSID_OFFSET + 5] = line;
// Update sequence number
beacon_rick[SEQNUM_OFFSET] = (seqnum[line] & 0x0f) < < 4;
beacon_rick[SEQNUM_OFFSET + 1] = (seqnum[line] & 0xff0) > > 4;
seqnum[line]++;
if (seqnum[line] > 0xfff)
seqnum[line] = 0;
// esp_wifi_80211_tx(WIFI_IF_AP, beacon_rick, sizeof(beacon_raw) + strlen(rick_ssids[line]), false);
ret = wlan_send_raw_frame(CMD_WLAN_NETIF, IEEE80211_FC_STYPE_AUTH, beacon_rick, sizeof(beacon_raw) + strlen(rick_ssids[line]));
printf("Send beacon: %dn", ret);
if (++line >= TOTAL_LINES)
line = 0;
}
return 0;
}
測試效果如下:
使用Netspot工具獲取無線AP列表
可以看到我們定義的SSID列表(Never gonna give you up:)),同時(shí)和默認(rèn)的AP名稱AP-XRADIO。
對(duì)XR806的Beacon進(jìn)行無線抓包分析,如圖所示
可以看出XR806所支持的速率和其他特性。
總結(jié)
本次測試發(fā)送了自定義的Beacon幀,實(shí)際上XR806還支持發(fā)送其他類型的幀,后續(xù)可以進(jìn)一步探索。
-
FreeRTOS
+關(guān)注
關(guān)注
12文章
484瀏覽量
62277 -
Wi-Fi技術(shù)
+關(guān)注
關(guān)注
0文章
58瀏覽量
8421 -
ARMv8
+關(guān)注
關(guān)注
1文章
35瀏覽量
14168 -
Beacon技術(shù)
+關(guān)注
關(guān)注
0文章
6瀏覽量
6275 -
xr806
+關(guān)注
關(guān)注
0文章
14瀏覽量
1327
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論