模块框架:

模块说明

一脸懵?别急,我们先从概念上去学习理解
基础框架

概念
- wpa_supplicant是一个在Linux和其他类Unix操作系统上广泛使用的守护进程,用于实现WPA(Wi-Fi Protected Access)客户端功能
- 它的核心作用是让客户端能够安全地连接到受保护的Wi-Fi网络
wpa_supplicant的地位不容小觑
- 在Linux系统中,尤其是在服务器、嵌入式设备或没有图形界面的环境中(即便是在图形界面中,也通常调用的也是wpa_supplicant),wpa_supplicant是连接加密Wi-Fi网络的事实标准工具,并且它提供了稳定、灵活且功能完整的WPA客户端实现
换个角度理解wpa_supplicant
- 在有图形界面的桌面Linux发行版ubuntu中,通常使用 NetworkManager 来管理网络,而NetworkManager在连接Wi-Fi时,其后台会调用 wpa_supplicant的库或直接与之通信来完成WPA认证。对于用户来说,这个过程是透明的,不用手动操作 wpa_supplicant
- wpa_supplicant:一个用于连接WPA\WPA2\WPA3加密的WIFI网络守护进程
- wpa:WIFI Protected Access
- supplicant:像申请者、客户端或者网络中指寻求接入网络的一方
基本用法示例
- 假设无线接口是 wlx40169f83a3a0 :
sudo wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf
-B:在后台运行(Daemon模式)
-i:指定无线接口名
-c:指定配置文件路径 - 使用 wpa_cli 进行交互:
sudo wpa_cli -i wlan0
进入交互模式后,可以输入命令,例如:
scan:扫描可用网络
scan_results:显示扫描结果
add_network:添加一个新网络配置(如0)
set_network 0 ssid ""SSID""
set_network 0 psk ""密码""
enable_network 0:启用该网络配置并尝试连接
status:查看当前连接状态
quit:退出 - 获取IP地址(连接成功后):
sudo dhclient wlan0
或者使用 dhcpcd、ip 等工具
wpa_supplicant的移植替换
-
源码获取及编译
git clone https://w1.fi/hostap.git
在代码目录下,可以看到:
hostapd/ # AP 端程序
wpa_supplicant/ # 客户端程序
src/ # 公共源码
-
编译流程
sudo apt update
sudo apt install build-essential libssl-dev libnl-3-dev libnl-genl-3-dev libdbus-1-dev libreadline-dev pkg-config libncurses5-dev libpcsclite-dev -y
cp defconfig .config
make

-
wpa_supplicant工具替换:
sudo cp wpa_supplicant /sbin/
启动wpa_supplicant进程连接无线网络:
sudo /sbin/wpa_supplicant -i wlx40169f83a3a0 -c /etc/wpa_supplicant/wpa_supplicant.conf -B
-
查看连接和获取ip地址的日志:
tail /var/log/syslog -f

查看网口ip地址:

基础调用流程
下面我以这调命令来理解代码流程:
/sbin/wpa_supplicant -i wlx40169f83a3a0 -c /etc/wpa_supplicant/wpa_supplicant.conf -B
- 进入wpa_supplicant主函数和解析命令行参数

- 该函数用于初始化wpa_supplicant,成功初始化后,返回的数据指针可用于添加和删除网络接口,并最终用于解除wpa_supplicant的初始化状态


- 此函数用于为wpa_supplicant添加新的网络接口,可以在wpa_supplicant_run()函数运行之前被调用,此外,在wpa_supplicant运行期间,新的接口在能够被动态添加,比如出现热插拔网络适配器被插入的时候。


- 这个函数启动主事件循环,并在有任何剩余事件时继续运行,在大多数情况下,这个函数就一直运行,只要wpa_supplicant进程在使用。

注意,当我们使用---B参数时,我们走的是wpa_supplicant_daemon()函数,当不使用-B参数时,我们走的是eloop_run()函数
这里我梳理了下代码调用流程:

代码执行流程:

日志收集
日志收集对于我们分析代码流程有重要的意义:

日志验证
- sudo /sbin/wpa_supplicant -i wlx40169f83a3a0 -c /etc/wpa_supplicant/wpa_supplicant.conf -B -s

- 将日志等级调高,打印更多的日志详情
sudo /sbin/wpa_supplicant -i wlx40169f83a3a0 -c /etc/wpa_supplicant/wpa_supplicant.conf -B -s -d

所以通常情况下,我们最好将日志放由到系统日志,理所当然,当wpa_supplicant需要调试时,我们就主要集中于系统(/var/log/syslog)日志
重要结构体
- 描述要添加的无线接口,表示一个网络接口的配置和状态的结构体


- 存储全局运行参数和配置的结构体


- 全局上下文结构体,地位相当核心

任务有:
跟踪所有网络接口的状态
管理全局配置和参数
协调接口间的交互(如P2P)
提供全局控制接口

- 核心结构体,它代表了一个网络接口的完整状态和配置,所以每个网络接口(如wlan0)都有一个对应的wpa_supplicant实例,这个结构体包含了一个无线网络接口的所有信息

结构体太长,截图了部分常用的:


从结构体嵌套,我们可得到相关结构体的包含情况(局部)
