还有,笔者在分析hostapd 源代码的时候,hostapd/supplicant 开发文档也提供了大量的有用信息,各位读者也可以参考。(http://w1.fi/wpa_supplicant/devel/)
一、几个重要的数据结构
此次分析hostapd 源代码,发现了其中出现频率最高的两个数据结构——struct hostapd_iface 和struct hostapd_data。其实很简单,hostapd_iface 结构体描述了一个物理接口(比如wlan0),hostapd_data 则描述一个BSS。这两个数据结构几乎贯穿所有的源代码,所以一定要搞清楚这两个数据结构。
- struct hostapd_iface (src/ap/hostapd.h)。在这个数据结构中,主要有以下字段:
- struct hostapd_config: 保存对网络接口的配置(从配置文件hostapd.conf中加载)
- sizt_t num_bss: 此接口下辖的BSS 个数
- struct hostapd_data **bss:BSS 列表,描述各BSS 的配置
- struct hostapd_data (src/ap/hostapd.h)。在这个数据结构中,主要有以下字段:
- struct hostapd_bss_config *conf:保存BSS 的配置信息(从配置文件hostapd.conf 中加载)
- u8 own_addr[ETH_ALEN]:表示此BSS 的BSSID (ETH_ALEN 为6,u8 其实是unsigned char)
- struct wpa_driver_ops *driver:指向一组驱动程序接口,用来和内核交互。(这里是用的nl80211)
说到这里,也许有人会问,实际源文件中有数十个字段,难道只知道这些就足够了吗?我的答案是肯定的——是的,只需要知道这么多。
二、hostapd 初始化
首先,我们打开hostapd/main.c,并找到主程序入口main()。直接跳转到大概659 行。看到如下代码:
很明显, 这是对每个网络接口( 或者干脆叫物理网卡也行) 的初始化。然后找到hostapd_interface_init 的定义(大概从main.c 的第234 行开始),我们看到了如下的一句话:
嗯,看来,真正的初始化工作是在hostapd_init 函数中进行,并返回一个描述网络接口的结构体(struct hostapd_iface)。然后我们再深一层的挖掘,找到hostapd_init 的定义(从src/ap/hostapd.c 的第1416 行起)。我们先看那句
这个其实就是读取hostapd 的配置文件hostapd.conf 中的配置信息,并保存到hostapd_conf的结构体中去。之后紧接着就是为每个BSS 分配内存空间:
OK,到这里,网络接口和每个BSS 的基本初始化(即为它们分配内存)的工作结束了。回到main,跳转到第715 行,我们看到了这句话:
从字面上理解,那就是“初始化每个网络接口的驱动程序”和“设置每个网络接口”。好吧,我们先看hostapd_driver_init 函数是如何定义的。最关键的是在第185 行到第204 行。代码如下:
那么,问题来了,hapd_init 是怎么定义的呢?由于笔者分析的hostapd 是基于nl80211 的,所以hapd_init 指向nl80211 的初始化函数i802_init(定义在src/drivers/nl80211_driver.c 中,本文只分析hostapd 在用户空间的工作原理,至于内核空间是如何工作的,不在本文讨论之列。有兴趣的读者可以查找有关Netlink 和mac80211 的资料。笔者以后也会推出关于mac80211 的学习笔记)。好了,驱动程序初始化完了,下面我们看如何设置每个网络接口。hostapd_setup_interface 函数定义在src/ap/hostapd.c,打开这个文件,跳到大概1315 行,里面就一句setup_interface……好吧,找到大概第1040 行,就是这个函数的定义。里面有一段话是这么说的:
还好有注释,就是确保每个BSS 都使用和物理网卡(我喜欢称呼BSS 为虚拟网卡)同一套驱动程序接口。然后直接看return 吧,哎?怎么又有个setup_interface2?好吧,去看
看setup_interface2 是怎么回事……找到大概第1113 行,就是它的定义了。这里面主要是设置网卡的硬件模式( a,g,n 等等), 再看return , 我去, 咋还有个hostapd_setup_interface_complete 呢?( 程序作者真磨叽) 好吧,既然说了complete,那应该就是最后一步了吧?那我就硬着头皮继续看看——跳到大概1162 行,就找到了它的定义。这个过程里面主要是设置网卡的信道,速率(根据硬件模式),RTS 参数等等。最后通过hostapd_setup_bss 函数配置每个BSS 。那我们就再看看
hostapd_setup_bss 是怎么个回事吧( 无语) — — 再跳到大概687 行, 就找到了hostapd_setup_bss 的定义。这个函数需要两个参数,第一个是hostapd_data 结构
体,描述一个BSS 的配置信息,第二个参数first 则用来表示这个BSS 是否为第一个BSS(通常,第一个BSS 就是wlan0)。先看第一部分代码:
再看第二部分:
啊,终于是return 0 了。好了,重新回到main。至此,网络接口和每个BSS 的初始化工作完成了。
未完待续……下一篇将详细讲解hostapd的工作机制。