3. Driver Event模块(windows篇)
wpa_supplicant通过Driver Event模块获取无线驱动的相关事件,并执行相应的操作。
无线驱动的主要事件如网络连接成功(或称关联成功,wpa_supplicant可以开始WPA认证过程);断开网络(wpa_supplicant是否准备重新连接,重新开始WPA认证);扫描结束事件(准备获取驱动的扫描结果);网卡移除事件;网卡插入事件等等。
Driver Event模块的设计分两层功能。
1. 下层负责实现底层无线驱动(或者称OS内核)事件的获取。与无线驱动(OS)事件相关代码实现在src/drivers/目录下。这部分的功能与不同操作系统相关。
其功能包括:
1)驱动事件获取的初始化工作;
2)OS层的事件回调处理,
3)驱动事件的类型转换,即把不同OS下的事件类型转换成统一的WPA Event类型,以便wpa_supplicant处理;
4)通知wpa_supplicant Event Loop模块进行处理。
2. 上层负责wpa_supplicant真正处理相关的wpa事件。在接收到事件通知之后,最终调用wpa_supplicant_event()函数进行事件处理。WPA Event事件处理代码在wpa_supplicant/evnet.c中实现。
本节的代码分析主要是与无线驱动事件(OS相关)功能的分析。与supplicant中WPA认证功能关系不大。WPA Event的处理在以后分析核心功能时具体分析。
3.1 Windows系统Driver Event模块的功能
Windows系统无线驱动是NDIS Miniport驱动,Driver Event模块具体功能如下:
1. 采用WMI技术获取驱动事件。
2. 支持轮询方式或者异步方式的事件获取。
3. 异步方式的事件通知回调处理。
4. 异步方式下通知Event Loop主线程,通过管道技术传递事件信息,由主线程从管道中读取事件信息处理。
3.2 NDIS Driver Event的编译配置说明
ifdef CONFIG_DRIVER_NDIS
DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDIS
DRV_WPA_OBJS += src/drivers/driver_ndis.c
ifdef CONFIG_NDIS_EVENTS_INTEGRATED
DRV_WPA_OBJS += src/drivers/driver_ndis_.c
endif
ifndef CONFIG_L2_PACKET
CONFIG_L2_PACKET=pcap
endif
CONFIG_WINPCAP=y
ifdef CONFIG_USE_NDISUIO
DRV_WPA_CFLAGS += -DCONFIG_USE_NDISUIO
endif
endif
配置CONFIG_NDIS_EVENTS_INTEGRATED使其支持事件的异步处理。否则采用轮询的方式。
3.3 Driver Event模块的初始化
3.3.1 wpa_supplicant初始化Driver Event(window系统)
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail,
drv->ifname, drv->adapter_desc);
if (drv->events == NULL) {
wpa_driver_ndis_deinit(drv);
return NULL;
}
eloop_register_event(drv->event_avail, sizeof(drv->event_avail),
wpa_driver_ndis_event_pipe_cb, drv, NULL);
#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
wpa_supplicant在软件初始化阶段调用ndis_evnets_init()完成获取NDIS无线驱动事件的相关初始化设置,并调用eloop_register_event注册一个事件处理函数。
3.3.2 ndis_events_init()函数
应用层获取驱动事件的初始化配置在ndis_events_init()函数中实现.
struct ndis_events_data *
ndis_events_init(HANDLE *read_pipe, HANDLE *event_avail,
const char *ifname, const char *desc)
{
HRESULT hr;
IWbemObjectSink *pSink;
struct ndis_events_data *events;
events = os_zalloc(sizeof(*events));
if (events == NULL) {
wpa_printf(MSG_ERROR, "