全志XR806芯片Wi-Fi测试:自定义发送802.11帧(Beacon篇)

news2025/1/11 15:09:39

XR806是一款使用ARMv8-M的Wi-Fi BLE Combo MCU。本文使用XR806开发板以及基于FreeRTOS的XR806 SDK实现了自定义发送802.11 Beacon帧,并进行了无线抓包分析以及扫描测试来验证帧的发送结果。

环境配置过程

环境搭建可以参考官方文档开发环境搭建。本测试中使用的开发环境为Ubuntu 22.04。需要注意的是,在下载ARM Toolchain时,由于网站更新,文档中链接已不可用,当前可用的下载链接为Downloads | GNU Arm Embedded Toolchain Downloads – Arm Developer,在其中找到对应的gcc-arm-none-eabi-8-2019-q3-update版本下载即可。

配置好环境后选取某个Demo或者Example进行编译,在Ubuntu下,使用的烧录工具为SDK中tools目录下的phoenixMC可执行程序,示例的烧录命令为

./phoenixMC -c /dev/ttyUSB0 -i ../out/xr_system.img

其他参数信息可以使用-h获取。烧录好后可以连接串口查看输出,控制台输出可能会出现换行不对齐的情况,此时需要进行换行修正。在本次测试中使用的串口工具为picocom,需要将输出的\n转为\r\n示例的连接串口命令为

picocom -b 115200 --imap lfcrlf /dev/ttyUSB0

在烧录时需要让开发板进入升级模式,如果当前程序支持upgrade命令,可以直接发送upgrade命令。若不支持,需要短接开发板上的两个触点或者使用Windows下的烧录工具,在工具上勾选硬件复位烧写模式。

微信图片_20231103154808.jpg

测试过程

通过浏览XR806的SDK可以发现,在wlan.h中提供有APIint wlan_send_raw_frame(struct netif *netif, int type, uint8_t *buffer, int len);。该API可以支持发送自定义的802.11帧,只需要提供网络接口,帧类型,数据帧和长度即可。受esp32-80211-tx启发,在本测试中基于该API发送自定义的Beacon帧,达到同时存在多个AP的假象。在IBSS网络架构中,AP每隔一段时间就会向外界发出一个Beacon帧用来宣告自己802.11网络的存在。平时Wi-Fi的被动扫描也是基于Beacon帧进行。

使用API构造BEACON

进一步浏览SDK可以发现,SDK中提供了wlan_construct_beacon的API,这简化了我们构造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 failed\n");
		return;
	}
	printf("ssid:%s,ssid_len: %d\n", 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 %d\n", 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: %d\n", ret);
}


int main(void)
{
	platform_init();
	net_switch_mode(WLAN_MODE_HOSTAP);
	while(1)
	{
		OS_MSleep(100 / TOTAL_LINES);
		beacon_frame_create();
	}
	return 0;
}

代码的基本逻辑为:首先预定义好需要发送的SSID及其对应的BSSID,然后在主函数中先初始化AP模式,然后每100ms发送一次所有的Beacon。发送Beacon前需要填充好Beacon帧的内容。
测试效果如下:
在代码中我们使用的SSID列表为

	"1 Hello Wireless World",
	"2 from Allwinner XR806",
	"3 running on FreeRTOS",
	"4 for Jishu Community"

上电后程序启动,使用手机扫描Wi-Fi便可以查看到这些AP信息
 

scan.jpg


其中AP-XRADIO为默认的AP名称。

不使用API构造BEACON

我们也可以不使用相关API,而直接填充内容。为了演示,在这里将参考项目的实现迁移过来,具体代码如下:

#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 %s\r\n", 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: %d\n", ret);
		if (++line >= TOTAL_LINES)
			line = 0;
	}
	
	return 0;
}

测试效果如下:
使用Netspot工具获取无线AP列表
 

屏幕截图 2023-10-20 191503.png


可以看到我们定义的SSID列表(Never gonna give you up:)),同时和默认的AP名称AP-XRADIO。

对XR806的Beacon进行无线抓包分析,如图所示
 

Screenshot from 2023-10-20 19-26-13.png


可以看出XR806所支持的速率和其他特性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1411938.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序登录获取手机号教程(超详细)

1. 背景介绍&#xff1a; 在我们开发微信小程序时&#xff0c;登录时&#xff0c;需要获取用户手机号作为唯一标识&#xff0c;下面我介绍一下获取手机号的教程。 本篇文章介绍后端获取方法&#xff1a; 前端工作 后端工作 前端 新建Page页面&#xff0c;在xxx.wxml中加入…

What is Rust? Why Rust?

why Rust&#xff1f; 目前&#xff0c;Rust 变得越来越流行。然而&#xff0c;仍然有很多人&#xff08;和公司&#xff01;&#xff09;误解了 Rust 的主张价值是什么&#xff0c;甚至误解了它是什么。在本文中&#xff0c;我们将讨论 Rust 是什么以及为什么它是一种可以增强…

<网络安全>《2 国内主要企业网络安全公司概览(二)》

4 北京天融信科技有限公司(简称天融信) 信息内容LOGO成立日期创始于1995年总部北京市海淀区上地东路1号院3号楼北侧301室背景民营企业是否上市天融信[002212]A股市值99亿主要产品网络安全大数据云服务员工规模6000多人简介天融信科技集团&#xff08;证券代码&#xff1a;0022…

A JSONArray text must start with at 1

A JSONArray text must start with at 1 [character 2 line 1] 起因&#xff1a;String数组转 JSON 后端调用出错 JSONUtil.toList(xx.getTags(), String.class) 数据库对象entity转包装类 方法 &#xff0c;其中数据库字段tags是String类型&#xff0c;在包装类中想转换为 J…

【idea】idea中编译内存不足(java: java.lang.0ut0fMemoryError: Java heap space)的解决方法

问题 在编译一个较大的idea项目时候&#xff0c;有时候会显示内存不足&#xff0c;导致项目编译失败 原因 编译项目时实际也是启动了jvm进行的&#xff0c;所以需要分配对应的内存大小。 这个大小在idea中有一个默认的配置&#xff0c;大小是700M。 对于一个大型的项目这个大…

大数据Doris(五十九):SQL函数之字符串函数(三)

文章目录 SQL函数之字符串函数(三) 一、​​​​​​​NULL_OR_EMPTY (VARCHAR str)

Redis 高可用之集群

1、简介 在之前的文章里&#xff0c;通过主从复制和哨兵机制实现Redis 高可用架构&#xff0c;但是由于架构比较复杂&#xff0c;难以维护&#xff0c;引入集群架构模式&#xff0c;一个集群可以有多个 master &#xff0c;一个master 可以有多个slave&#xff0c;集群支持故障…

Unity制作右键菜单(自适应分辨率)

一、需求 右键触发打开菜单&#xff0c;左键在内部可选择选项&#xff0c;左键单击菜单范围外关闭。难点在于屏幕坐标系&#xff0c;鼠标位置&#xff0c;UI位置之间的关系。 二、理论 前置知识&#xff1a; unity中&#xff0c;用RectTransform对象的position.x和position.y表…

nginx详细资料

nginx简介 1、nginx产生 Nginx同Apache一样都是Web服务器。基于REST架构风格&#xff0c;以统一资源描述符(Uniform Resources Identifier ) URI或者统一资源定位符&#xff08;Uniform Resources Locator&#xff09;URL作为沟通一句&#xff0c;通过HTTP协议提供各种网络服务…

Vue自定义成功弹窗H5实现类似于小程序的效果

效果图: <div class="father"><div class="success-box" v-if="isSuccess"><img src="../../assets/insure/success-logo.png" alt=""><span>{{ successTitle }}</span></div> </d…

单片机之keil软件环境搭建

简介 Keil提供了包括C编译器、宏汇编、链接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案&#xff0c;通过一个集成开发环境&#xff08;μVision&#xff09;将这些部分组合在一起。     目前软件对中文的支持不友好&#xff0c;不建议安装网上的一些汉化包…

14.java集合

文章目录 概念Collection 接口概念示例 Iterator 迭代器基本操作&#xff1a;并发修改异常增强循环遍历数组&#xff1a;遍历集合&#xff1a;遍历字符串&#xff1a;限制 list接口ListIteratorArrayList创建 ArrayList&#xff1a;添加元素&#xff1a;获取元素&#xff1a;修…

瑞丽杂志引领潮流,VOSS眼镜概念店开启奢华新纪元

近日&#xff0c;由《瑞丽》杂志社举办的2023第4届瑞丽轻奢品牌大赛&#xff0c;以“轻奢•悦藏”为主题的大赛已圆满结束&#xff0c;VOSS眼镜荣获&#xff1a;2023瑞丽轻奢品牌大赛「轻奢时尚风格奖」&#xff0c;作为眼镜行业唯一获此奖项的品牌&#xff0c;VOSS眼镜对此表示…

仓储管理系统——软件工程报告(详细设计)④

详细设计 一、系统功能模块的划分 根据系统的功能性需求&#xff0c;本文将部队仓库管理系统分为以下六大模块&#xff1a;系统管理模 块、基础数据模块、出入库管理模块、库存管理模块、仓库信息管理模块、作业管理模 块&#xff0c;每个模块内部又分为很多小功能模块&#…

java数据结构与算法刷题-----LeetCode769. 最多能完成排序的块

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 解题思路 这道题可以理解为&#xff0c;只能保证块内有序的情况下&#xf…

力扣 | 141. 环形链表

快慢指针的使用&#xff01; import java.util.HashSet; import java.util.Set;public class _141_linked_list_cycle {// 哈希查找// 时间复杂度&#xff1a;O(n)// 空间复杂度&#xff1a;O(n)public boolean hasCycle1(ListNode head) {Set<ListNode> set new HashSe…

2-SAT问题相关理论和算法

前言 SAT 问题简介 SAT是可满足性、适定性(Satisfiability)问题的简称。一般形式为k-适定性问题或k-可满足性问题&#xff0c;简称 k-SAT。 何为布尔可满足性问题&#xff1f;给定一条真值表达式&#xff0c;包含逻辑变量、逻辑与、逻辑或以及非运算符&#xff0c;如&#x…

uniapp app更新

uniapp app更新 这个版本要随之增加&#xff0c;不然刚更新时直接用app, 新包增加的那些页面跳转会有问题&#xff0c;不能跳新的页面 //app更新检测 updataApp(){const that this;uni.showLoading({title:加载中...})plus.runtime.getProperty(plus.runtime.appid, functio…

JS进阶-高阶技巧

深浅拷贝 首先浅拷贝和深拷贝只针对引用类型 • 浅拷贝 开发中我们经常需要复制一个对象。如果直接用赋值会有下面问题&#xff1a; 这好比有同学来pink老师这里拷视频&#xff0c;竟然用的是剪切…气人不 浅拷贝&#xff1a;拷贝的是地址 1. 拷贝对象&#xff1a;Object…

塑料透光率测定仪评估塑料质量

塑料透光率是指光线通过塑料材料的能力&#xff0c;是评估塑料质量的重要指标之一。透光率越高&#xff0c;塑料的质量通常越好。为了确保生产出的塑料制品具有良好的透光性&#xff0c;对塑料透光率的检测非常重要。 一、塑料透光率检测方法 塑料透光率检测通常采用两种方法…