Android wpa_supplicant源码分析--bss扫描结果
来源:互联网 发布:2d图像转3d算法 编辑:程序博客网 时间:2024/06/05 01:10
1 扫描方式
手机扫描结果的获取有两种方式:被动和主动
1,AP隔固定时间会发送Beacon帧,Beacon帧中有AP的SSID BSSID等基本信息,手机接收到Beacon帧就认为搜索到该AP创建的网络
2,手机主动发出probe request帧,AP接收到probe request帧后会发送probe response帧,手机接收到response帧后,就认为扫描到该网络。
在手机wlan界面中,点击刷新既采用的第二种方式(当然扫描结果中也会包含部分方式1中扫描到的网络)
2 扫描结果在wap_s中的存储
为了提高处理效率,驱动在接收到相关扫描结果时,是不会对帧中的信息进行解析的,80211管理帧的构成请查阅相关资料。帧传递到wpa_s时会经过强制类型转换成struct wpa_scan_res,帧头会转换成结构体总的元素,帧的载荷会作为ie(information element信息元素)存储在紧跟结构体后面的内存中,wpa_s中有专门方法获取ie域中的相关信息。
存储驱动上报的扫描结果的结构体
struct wpa_scan_res { unsigned int flags; //BSS/IBSS标记 u8 bssid[ETH_ALEN]; int freq; u16 beacon_int; //beacon间隔 u16 caps; int qual; int noise; int level; u64 tsf; //时间戳 //时间,单位ms,用于计算update time, unsigned int age; //struct wpa_scan_results中存储的featch time减去age就是update time size_t ie_len; size_t beacon_ie_len; //紧跟的IE(information element)数据长度,例如ssid,p2p一类的 //数据组成为type(4 u8),element长度(u8),element内容 //在每个res结构体指针后(res+1)通过比对每个element的type类型获取};
一个扫描结果被认为是一个bss网络,经初步解析后会转变为wpa_bss的结构体,该结构体的信息包含了一些ie中的信息,因此包含的信息更加的的详细。wpa_bss会存储在struct wpa_supplicant结构体的链表bss和bss_id中。
存储一个bss的结构体
struct wpa_bss { struct dl_list list; //bssid的链表 struct dl_list list_id; //内部id的链表 unsigned int id; //id unsigned int scan_miss_count; //扫描结果中不包含该bss的次数 unsigned int last_update_idx; //上次扫描更新(不懂) unsigned int flags; //标记BSS/IBSS (WPA_BSS_*) u8 bssid[ETH_ALEN]; //bssid,mac地址 u8 hessid[ETH_ALEN]; //16进制ssid? u8 ssid[32]; size_t ssid_len; //网络名,最长32个字符 int freq; //网络信道 u16 beacon_int; //beacon间隔,AP设置,一般为100ms /** Capability information field in host byte order */ u16 caps; //Capability,AP设置 int qual; //信号质量,怎么确定? int noise; //背景噪声 int level; //信号强度 db u64 tsf; //Timestamp of last Beacon/Probe Response frame */ struct os_reltime last_update; //上次由Beacon or Probe Response RX更新的时间 struct wpa_bss_anqp *anqp; //ANQP与安全相关 size_t ie_len; //Probe Response中IE域的长度 size_t beacon_ie_len; //Beacon IE field};
3 bss列表初始化
每隔10秒都会刷新一下struct wpa_supplicant中的bss列表
int wpa_bss_init(struct wpa_supplicant *wpa_s){ //更新对应连的链表wpa_s->bss wpa_s->bss_id //使用eloop_register_timeout注册超时函数,时间为10秒 wpa_bss_timeout{ //通过对比当前的时间与wpa_s bss链表中每个bss存储的时间 //删除掉超过bss_expiration_age(默认值180)秒未更新(未扫描到)的bss wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age); //使用eloop_register_timeout注册超时函数wpa_bss_timeout,时间为10秒 //这样每隔10秒都会调用wpa_bss_flush_by_age更新时间 }}
4 wpa_s->bss链表更新
接收到扫描结果时:更新bss按如下顺序调用
wpa_bss_update_start(wpa_s);//每次只能更新一次扫描结果wpa_bss_update_scan_res(wpa_s, scan_res->res[i], &scan_res->fetch_time);wpa_bss_update_end(wpa_s, info, new_scan);
在end函数中会对wpas中的bss链表做一次更新,
如果当前bss正在使用 || 包含在扫描结果中,则不作处理
如果当前bss的更新次数(last_update_idx)< 整个bss链表的更新次数(last_update_idx),说明是首次没有扫描到,那么计数器+1
如果没有扫描的次数超过了 wpa_s->conf->bss_expiration_scan_count,该值一般为2,那么会从链表中删除该bss
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s, struct wpa_scan_res *res, struct os_reltime *fetch_time){ //获取ie中存储的ssid,如果ssid长度大于32,直接return u8* ssid = wpa_scan_get_ie(res, WLAN_EID_SSID); //获取p2p信息,如果ssid前缀为“DIRECT-”, 是P2P listen discovery results,直接return。 p2p = wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE); //查询wpa_s中的bss列表是否有该bss,需要bssid和ssid全部一致 bss = wpa_bss_get(wpa_s, res->bssid, ssid + 2, ssid[1]); //无,直接添加 bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res, fetch_time); //添加过程 { //分配内存 bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len); //将ssid信息复制到bss中 os_memcpy(bss->ssid, ssid, ssid_len); //将res后面的ie空间和beacon ie拷贝到bss后的内存 os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); //从ie中获取hessid wpa_bss_set_hessid(bss); //将bss添加到wpa_s对应链表中中 dl_list_add_tail(&wpa_s->bss, &bss->list); dl_list_add_tail(&wpa_s->bss_id, &bss->list_id); //向上发送bss添加的event wpas_notify_bss_added(wpa_s, bss->bssid, bss->id); } //有,更新信息,主要更新信号值和后面的ie域 bss = wpa_bss_update(wpa_s, bss, res, fetch_time); //将bss添加到wpa_s->last_scan_res中}
5 获取扫描结果bss
wpa_s定义了多种方式获取bss链表中的元素,通过bssid匹配,ssid匹配,获取id等等(id的含义等再详细看看代码,目前还不清楚)
struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)通过bssid获取bssid结构体struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s, const u8 *bssid)获取最后一次更新bss。 获取钱会与wpa_s->bssid_filter比对,如果该bss包含在filter中,则返回NULL,该filter通过上层的SET命令设置。struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s, const u8 *dev_addr)通过P2P Device Addr 获取bss,P2P Device Addr存储处在bss指针后的ie域中。struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id)通过identifier获取bssstruct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s, unsigned int idf, unsigned int idl)给定id的最小值idf和最大值idl,获取这个范围的bss
当FMKS获取扫描结果时,就是获取的bss(wpa_s->bss)链表的元素。通常使用的命令有
‘SCAN_RESULTS’获取所有的扫描结果和“BSS RANGE=5- MASK=0x29d87”获取一部分id(>5)范围的扫描结果。
6 获取帧信息ie域
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)通过ie的类型获取对应的iestruct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, u32 vendor_type)通过type获取ieconst u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type)每一个vendor ie都有对应的type,通过每个type获取对应的ieconst u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, u32 vendor_type)根据type从beacon ie域中获取信息struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss, u32 vendor_type)获取beacon中的ie
7 其他方法
刷新:wpa_bss_flush(struct wpa_supplicant *wpa_s) 除了wpa_s正在使用(连接,关联)的bss,删除掉wpa_s->bss所有的bss元素清除bss数据:wpa_bss_deinit(struct wpa_supplicant *wpa_s) 去掉超时函数wpa_bss_timeout 清除不在使用的bss wpa_bss_flush。 获取速率int wpa_bss_get_max_rate(const struct wpa_bss *bss)获取maximum legacy TX rate,存储在ie域中int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates)获取支持速率的长度
- Android wpa_supplicant源码分析--bss扫描结果
- Android wpa_supplicant源码分析–扫描scan过程
- [Android源码解析]蓝牙扫描结果反馈的分析
- Android wpa_supplicant源码分析--conf配置文件
- Android wpa_supplicant源码分析--运行方式
- Android wpa_supplicant源码分析--conf配置文件
- Android wpa_supplicant源码分析--conf配置文件
- hostapd wpa_supplicant madwifi详细分析(十五)——supplicant扫描结果排序规则
- wpa_supplicant 源码分析
- wpa_supplicant源码分析整理
- wpa_supplicant源码分析
- Android wpa_supplicant源码分析--启动之全局初始化
- Android wpa_supplicant源码分析--启动之网络接口初始化
- Android wpa_supplicant源码分析---内核通信Netlink简介
- Android wpa_supplicant源码分析---nl80211内核通信Generic Netlink
- Android wpa_supplicant源码分析–连接AP过程
- Android Wi-Fi源码分析之wpa_supplicant初始化(一)
- android wpa_supplicant 流程分析
- Spring boot学习笔记(2) 配置文件
- Android实现手势解锁
- mdev_笔记
- 第一章、Hadoop之生态体系
- Linux 终端 使用
- Android wpa_supplicant源码分析--bss扫描结果
- Single Number II
- nodejs异步编程
- 理解Python中的with…as…语法
- 动态规划-3015-十进制转二进制
- Word2010 Error:The name in the end tag of the element must match the element type in the start tag.
- 喵帕斯喵喵
- ListNode示例
- 数据库进阶系列之一:漫谈数据库索引