Linux Wlan hostapd框架梳理
官方框架图
这个框架图展示了hostapd的软件架构和主要组件
简单做个说明:
文档获取路径:
- https://w1.fi/wpa_supplicant/devel/
从如上可以梳理个简单流程:
- 驱动事件上报:
驱动事件 → driver i/f → 相应状态机处理 - 控制流:
GUI/cli → ctrl i/f → configuration → 各子系统 - 数据流:
无线数据包 → driver i/f → IEEE 802.11 MLME → Station table
讲个题外内容的框架
源码获取
- git clone git://w1.fi/hostap.git
安装依赖库
- sudo apt-get install libnl-3-dev libnl-genl-3-dev
- sudo apt-get install libssl-dev
编译
- 复制默认配置:cp defconfig .config
- make
备份原hostapd
- sudo cp /usr/sbin/hostapd /usr/sbin/hostapd.bak
替换系统hostapd
- sudo cp hostapd /usr/sbin/
调整日志级别
- 在 hostapd 配置文件(如 /etc/hostapd/hostapd.conf)中设置
等等
梳理了一下繁琐的函数调用,附带解析
hostapd_global_init() //初始化eloop这个全局变量eap_server_register_methods() //注册eap server支持的安全模式,并存放在一个链表里面eloop_init() //初始化全局变量eloop结构体,初始化 eloop(事件循环),用于处理 socket 事件、定时器、信号等random_init();//对各个事件注册eloop_register_read_sock()eloop_sock_table_add_sock()//将相应的handler和data放进sock_table表中,实现注册hostapd_interface_init() //读取配置文件井初始化BSS数据,不会启动实际的驱动程序操作。此函数用于解析全接口(一个或多个BSS共享相同的无线电)的配置文件,并为BSS*接口分配内存。不会启动实际的驱动程序操作。hostapd_init() //分配并初始化每个接口的数据,此函数用于为每个接口分配主要数据结构。config_read_cb()hostapd_config_read() //读取hostapd配置文件hostapd_interface_init_bss() //读取配置文件井初始化BSS数据,不会启动实际的驱动程序操作。这类似于hostapd_interface_init(),但适用于以下情况:配置用于为无线电添加单个BSS,而不是所有BSS。
启用已配置的接口。根据通道配置,这可能会在返回之前完成完全初始化,或者在需要HT co-ex扫描、ACS或DFS等操作来确定通道参数的情况下,使用回调机制完成设置。在这种情况下,接口将从hostapd_global_run()中的eloop上下文启用。
hostapd_driver_init() //获取配置信息保存在iface[i]中,准备驱动程序的接口hostapd_setup_interface() //设置一个接口setup_interface()尽早初始化控制接口,以便允许外部监控可能需要相当长时间的通道设置操作,特别是对于DFS情况。start_ctrl_iface() //初始化ctrl_iface接口,用于和上层用户通信ctrl_iface_init()hostapd_ctrl_iface_init()hostapd_ctrl_iface_path()eloop_register_read_sock() //监听ctrl_interfacehostapd_ctrl_iface_receive()hostapd_set_country() //设置WiFi国家码信息setup_interface2() //将配置信息写入内核hostapd_get_hw_features() //获取无线网卡硬件支持的功能configured_fixed_chan_to_freq() //将配置的固定频道号(channel number)转换为对应的频率(MHz) 的辅助函数。它通常在 AP 初始化或配置解析阶段被调用,确保无线接口的信道设置符合硬件支持的范围hostapd_set_oper_chwidth() //设置无线接口的操作信道宽度hostapd_select_hw_mode() //根据配置设置硬件模式、通道、速率和被动扫描hostapd_setup_interface_complete() //完成接口设置,当先前设置步骤完成时,将调用此函数hostapd_setup_interface_complete_sync() //hostapd_set_current_hw_info() // 更新并验证当前无线接口的硬件信息hostapd_set_freq() hostapd_set_rts()hostapd_setup_bss() //配置每个BSS,此函数用于初始化所有BSS数据结构和资源。当接口初始化时,此函数会循环调用每个BSS。hostapd_if_add() //在内核中为此BSS 创建一个interfacehostapd_setup_encryption() //配置无线接口的加密方式和密钥管理hostapd_setup_wpa_psk() //专门用于 配置 WPA-PSK(预共享密钥)认证hostapd_set_ssid() //Set SSID for the kernel driverhostapd_bss_radius_init() //初始化 RADIUS 客户端功能hostapd_acl_init() //初始化访问控制列表(ACL)hostapd_init_wps() //初始化 Wi-Fi Protected Setup (WPS) ieee802_1x_init() //初始化 IEEE 802.1X 认证框架hostapd_setup_wpa() //初始化 WPA/WPA2/WPA3 安全模块hostapd_drv_set_qos_map() //配置 QoS(服务质量)映射表dhcp_snoop_init() //初始化 DHCP 监听(DHCP Snooping)功能hostapd_start_beacon() //启动 Beacon 帧广播ieee802_11_set_beacon() //wpa_init_keys() //初始化 WPA/WPA2 密钥管理hostapd_start_beacon()hostapd_tx_queue_params() //配置无线接口的传输队列hostapd_set_acl() //动态管理访问控制列表hostapd_driver_commit() //主要用于将无线访问点(AP)的配置更改提交给底层驱动程序hostapd_init_wps_complete() //用于处理 WPS 初始化完成后的操作hostapd_set_state() //用于管理 AP 状态转换的核心函数hostapd_neighbor_set_own_report() //专门用于处理接入点(AP)的邻居802.11k 报告(Neighbor Report)生成和更新ieee802_11_update_beacons() //主要用于当 AP 的配置发生变化时需要更新发送的 Beacon 帧内容hostapd_global_ctrl_iface_init() //负责建立与外部管理实体(如 hostapd_cli、wpa_supplicant 或其他管理工具)通信的基础设施,建立用于管理通信的UNIX域套接字或命名管道hostapd_global_run() //hostapd 的主事件循环函数,负责处理整个 hostapd 进程的事件调度和消息处理tncs_global_init() //tncs初始化(Trusted Network Connect),用于初始化可信网络连接(TNC, Trusted Network Connect)子系统的全局初始化函数,属于802.1X认证框架的一部分os_daemonize() //后台运行eloop_run()eloop_process_pending_signals();//对发生的信号进行处理,会执行eloop_register_signal中注册的信号对应handler函数eloop_sock_table_set_fds();//将表中的socket加入到集合rfds中,socket是在eloop_register_sock中提前注册并绑定handler函数,在hostapd_global_init中eloop_sock_table_set_fds();eloop_sock_table_set_fds();res = select(eloop.max_sock + 1, rfds, wfds, efds,//使用select函数来监听集合中socket的变化eloop_sock_table_dispatch(&eloop.readers, rfds);//执行相应的提前注册的函数,eloop_sock_table_dispatch(&eloop.writers, wfds);eloop_sock_table_dispatch(&eloop.exceptions, efds);
创建AP启动流程
详细的代码启动流程及详细备注(包含启动函数)
重要结构体
- 管理结构体 struct hostapd_data
单个BSS的全局上下文,每个AP对应一个实例
结构体太长了,细则需要自行了解
我列举几个重要的
struct hostapd_bss_config *conf; // BSS配置参数
struct hostapd_config *iconf; // 接口配置
struct hostapd_iface *iface; // 所属物理接口
struct sta_info *sta_list; // 已连接客户端列表
void *drv_priv; // 驱动私有数据
- 管理结构体:struct hostapd_iface
管理物理无线接口,可能包含多个虚拟AP(BSS)
重要成员
struct hostapd_data **bss; // 虚拟AP数组
int num_bss; // 虚拟AP数量
struct hapd_interfaces *interfaces; // 全局接口集合
enum hostapd_iface_state state; // 接口状态
- 管理结构体:struct hapd_interfaces
hostapd全局上下文,管理所有物理接口
重要成员
struct hostapd_iface **iface; // 物理接口数组
size_t count; // 接口数量
char *config_file; // 配置文件路径
void *global_ctrl_priv; // 全局控制接口数据
- 配置结构体:struct hostapd_config
存储所有接口级别的配置参数
重要参数
struct hostapd_bss_config **bss; // 每个BSS的配置
int num_bss; // BSS数量
int beacon_int; // Beacon间隔(ms)
int rts_threshold; // RTS阈值
int fragm_threshold; // 分片阈值
- 配置参数结构体:struct hostapd_bss_config
单个BSS的配置参数
重要成员
char iface[IFNAMSIZ + 1]; // 接口名
char ssid[SSID_MAX_LEN + 1]; // SSID
int ssid_len; // SSID长度
int wpa; // WPA配置标志
char *ctrl_interface; // 控制接口路径
给个结构体管理图
使用一个简单的使用应用层工具来设置ssid说明流程
hostapd进程是一个内核进程还是应用层进程?
- hostapd 是一个运行在用户空间(应用层)的守护进程
为什么感觉内容很少?
- 一下学不了所有内容,都是根据模块和具体的需求去分布了解hostapd内容
- 所以本篇内容仅仅是以创建ap的方式去跟踪学习