看在android5.1平台上看了将近半个月的wpa_supplicant子系统,还是希望能将最近的一些所学整理成文档发表到博客(在学博客过程其实也是对自己的思路的一个在整理),有误地方欢迎指正交流。
wpa_supplicant是一个开源的软件项目,它实现了Station对无线网络进行管理和控制的功能。wpa_supplicant是Android用户空间中无线网络的核心模块,所有Framework中和Wifi相关的操作最终都将有wpa_supplicant来完成。另外,wpa_supplicant对802.11、802.1X以及android Alliance定义的一些规范都有极好的支持。
其内部模块构成如下图:
WPA_supplicant中所有工作都围绕事件(event loop模块)展开。WPA_supplicant的运行机制比较简单,它是基于事件驱动,所有事件都是由主线程完成。
event loop模块下方的driver i/f接口模块用于隔离和底层驱动直接交互的driver控制模块,也正式这种隔离作用是WPA_supplicant中的其他模块能最大程度的保持平台以及驱动的无关性。
EAP、EAOOL为状态机,除此之外WPA_supplicant还定义了自己的状态机WPA/WPA2。WPA_ supplicant中实现了多种EAP方法。如EAP method模块。另外还包含了crypto和TLS模块用于支持EAP方法。
EAP以及EAPOL的消息都属于LLC层数据,所以I2_packet用于接收EAP、EAPOL消息。
WPA_supplicant支持较多的配置参数,这些参数的处理主要在configuration模块中完成。
WPA_supplicant是C/S架构中的服务端,它通过ctrl i/f端口向客户端提供通信接口。
WPA_Supplicant的初始化过程
WPA_Supplicant入口函数位于main.c文件中,路径见3.1章节。
先来看其入口函数main函数:
在这个函数中主要做了做了四件工作:
1)调用os_program_init()函数给wpa_supplicant进程分配权限以及结构体的初始化,解析命令行参数。
2)通过wpa_supplicant_init()函数,初始化struct wpa_global *global局部结构体(结构体详解见后文)同时传递给static struct eloop_data eloop全局结构体初始化事件循环机制。
3)for循环中调用wpa_supplicant_add_iface()函数注册一个或者多个网络接口。
4)调用wpa_supplicant_run()函数启动wpa_supplicant主事件循环机制,如果失败跳转到out或者通过goto跳转到out。
main函数中出现了几个重要的结构体和两个关键函数,先来看下main函数主要的数据
如图2所示:
wpa_interface用于描述一个无线网路设备,参数在wpa_supplicant_add_iface()函数调用
wpa_global是一个全局性质的上下文信息。它通过ifaces变量指向一个wpa_supplicant结构体,该结构体的初始化主要通过调用wpa_supplicant_init()函数实现。
wpa_supplicant结构体是WPA_Supplicant的核心数据结构,一个interface对应一个结构体wap_supplicant。
ctrl_iface_global_priv是全局控制接口的信息,内部包含一个socket句柄。
下面来分析下wpa_supplicant_init()函数和wpa_supplicant_add_iface()函数。
wpa_supplicant_init()函数
wpa_supplicant_init()函数流程如下图3:
wpa_supplicant_init()函数实现的功能是:先分配struct wpa_global *global这个局部指向结构体的内存空间;然后通过main函数传递进来的params参数填充global指向的内嵌结构体对象struct wpa_params;然后调用eloop_init()函数初始化eloop事件循环机制;最后设置消息全局回调函数(共2个)。
比较重要的函数:
wpa_msg_register_ifname_cb()函数:该函数为回调函数,用于获取有需要输出打印网卡接口名的网卡接口名。
wpa_supplicant_global_ctrl_iface_init()函数:初始化全局接口对象。
eap_register_methods()函数:主要将根据编译配置选项来注册锁需要的EAP methold,EAP methold方法见图1所示。
eloop_init()函数:见下文分析。
eloop_init()函数:的主要功能是初始化了WPA_Supplicant中事件驱动的核心数据结构体eloop_data。WPA_Supplicant事件驱动主要支持5中类型的event:
1)read event:读事件