wpa_supplicant代码初探收藏

wpa_supplicant代码初探收藏linux

 这几天在尝试把wpa_supplicant移植到windows ce上,替换微软的WZC。先把源代码down下来,了解了一下大体的结构。android

 

 wpa_supplicant运行的整个核心就是eloop_run函数。这个函数负责处理应用程序的请求和数据链路层发来的EAPOL数据。eloop的针对不一样的平台有好几个实现版本,我这里只讨论针对WIN32的eloop_win.c版本。windows

 外部须要经过调用eloop_register_event或者eloop_register_read_sock来注册一个回调函数,并绑定了一个相应的事件。eloop会等待每个事件的发生,并在事件发生时调用相应的回调函数进行处理。数组

 

 全部与平台相关的网络驱动程序接口,都被经过wpa_driver_ops结构抽象成统一的接口,无论你是WEXT或者NDIS。所以也实现了平台无关性。sass

 

 此外,wpa_supplicant与应用层通讯的方式多种多样,有pipe、socket,你也能够实现本身的方式。只须要实现几个基本的函数就能够了:网络

 wpa_supplicant_global_ctrl_iface_init数据结构

 wpa_supplicant_global_ctrl_iface_deinitapp

 wpa_supplicant_ctrl_iface_initless

 wpa_supplicant_ctrl_iface_deinitsocket

 wpa_supplicant_ctrl_iface_wait

 好比我在CE上就把wpa_supplicant做为一个stream device或者service来运行,上层应用经过文件系统接口来与之进行交互。

 

 

初始化过程:

 

1. 初始化wpa_supplicant,调用下面这个函数:

struct wpa_global *wpa_supplicant_init(struct wpa_params *params)

其中,经过structwpa_params中的参数能够进行相关配置。

 

2. 经过调用wpa_supplicant_add_iface来将ctrl interface和driver绑定起来。

 

3. 执行wpa_supplicant_run。

 

 

 

 

原本觉得这个东西只有在Atheros的平台上用的,忽然发现Ralink的平台也能够用,甚至还看到还有老美把这个东西往android上移植。看来是个好东西,学习一下。
官方的模块框图


通常来讲不少模块能够根据须要选用的
EAP methods EAP state machine
若是你不须要支持wpa-enterprise那么这两个模块都不须要编译。
wpa_cli和GUI
这两个能够不要,直接写个控制脚本,把用户的参数变为配置文件,重启wpa_supplicant
driver event
driver event 无线驱动和本程序通信的接口,通常高级的无线驱动都支持WEXT就是驱动里面经过wireless_send_event把一些状态信息发到本程序处理。
driver i/f
一些ioctl接口,一样用于无线驱动和本程序之间传递信息。
EAPOL state machine
负责处理PTK 4-way HS和GTK 2-way HS
l2_package
EAPOL和pre auth都要经过这个接口收发包。
configuration
负责处理用户配置文件的模块
大体流程(For WPAPSK):程序是哪些?
1           读取配置文件
2           初始化配置参数,驱动函数wrapper
3           让驱动scan当前全部bssid(包括wpa AP和non-wpaAP)
4           检查扫描的参数是否和用户设置的相符
5           若是相符,设置associate request ie 通知驱动进行auth assoc步骤
4           Four-way handshake for PTK
5           Two-way handshake for GTK
6           接收AP发出的指令,按期更换GTK

这个程序和madwifi通讯主要经过wirelessEXT,其实就是netlink,在madwifi驱动中会调用wireless_event_send这个函数把相关的东西发到wpa_supplicant

WPAPSK配置文件的写法
通常这样写能够兼容WPA和WPA2CCMP和TKIP
network={
    ssid="myssid "
    key_mgmt=WPA-PSK
    proto=WPA RSN
    pairwise=TKIP CCMP
    psk="myasciipsk"
}

编译方法:
Makefile须要读取一个.config文件,这个文件里面包含交叉编译路径设置,模块配置选项。
参考配置文件For wpapsk madwifi
#*******************************************************
CROSS_COMPILE=/opt/mips-linux-
CC=${CROSS_COMPILE}gcc
CONFIG_DRIVER_MADWIFI=y
CFLAGS += -I../src/802_11/madwifi/madwifi
CONFIG_DRIVER_WIRED=y
CONFIG_IEEE8021X_EAPOL=y
CONFIG_BACKEND=file
#*******************************************************

启动方法(Atheros Driver):
#建立无线interface模式设置为managed
wlaconfig ath create wlandev wifi0 wlanmode sta
#设置ath0到自动模式,这样scan的时候会扫全部的频道2.4g 5g 11nagb。
iwpriv ath0 mode auto
#设置好配置文件,启动wpa_supplicant
wpa_supplicant –i ath0 –b br0 –c /tmp/supplicant.conf -B
主要参数含义:
ath0是无线interface,经过这个参数,函数就能够经过iotcl调用无线驱动中的接口。
br0 是bridge interface,EAPOL L2 package都经过这个接口收发。
-c 表示配置文件
-B daemonlise

源码关键函数
wpa_supplicant_add_iface
       wpa_supplicant_init_iface
wpa_supplicant_set_driver
              wpa_config_read
wpa_supplicant_init_iface2
       wpa_supplicant_init_eapol
       wpa_drv_init
       wpa_drv_set_param
       wpa_supplicant_init_wpa
       wpa_supplicant_driver_init
             wpa_supplicant_req_scan // trigger scan state

wpa_supplicant_scan

wpa_supplicant_set_suites
wpa_sm_set_assoc_wpa_ie_default  //add wpa rsn ie in associate req

有时候AP会被加到blackList中,主要缘由能够参考下面的代码。主要是收到deauth这个event和authtimeout

wpa_supplicant_event_disassoc
wpa_blacklist_add

wpa_supplicant_timeout
wpa_blacklist_add
什么时候会从黑名单中删除

 

 

 


wpa_supplicant 初始化流程分析

(如下分析基于 wpa_supplicant 0.5.10 版本)

1. 启动命令

wpa supplicant 在启动时,启动命令能够带有不少参数,目前咱们的启动命令以下:
wpa_supplicant /system/bin/wpa_supplicant -Dwext -ieth0 -c/data/wifi/wpa_supplicant.conf -f/data/wifi/wpa_log.txt

wpa_supplicant对于启动命令带的参数,用了两个数据结构来保存,
一个是 wpa_params, 另外一个是wpa_interface.
这主要是考虑到wpa_supplicant是能够同时支持多个网络接口的。
wpa_params数据结构主要记录与网络接口无关的一些参数设置。
而每个网络接口就用一个wpa_interface数据结构来记录。
在启动命令行中,能够用-N来指定将要描述一个新的网络接口,对于一个新的网络接口,能够用下面六个参数描述:
-i<ifname> : 网络接口名称
-c<conf>: 配置文件名称
-C<ctrl_intf>: 控制接口名称
-D<driver>: 驱动类型
-p<driver_param>: 驱动参数
-b<br_ifname>: 桥接口名称

2. wpa_supplicant 初始化流程
2.1. main()函数:

在这个函数中,主要作了四件事。
a. 解析命令行传进的参数。
b. 调用wpa_supplicant_init()函数,作wpa_supplicant的初始化工做。
c. 调用wpa_supplicant_add_iface()函数,增长网络接口。
d. 调用wpa_supplicant_run()函数,让wpa_supplicant真正的run起来。

2.2. wpa_supplicant_init()函数:
a.
打开debug 文件。
b. 注册EAP peer方法。
c. 申请wpa_global内存,该数据结构做为统领其余数据结构的一个核心, 主要包括四个部分:
wpa_supplicant *ifaces   /*每一个网络接口都有一个对应的wpa_supplicant数据结构,该指针指向最近加入的一个,在wpa_supplicant数据结构中有指针指向next*/
wpa_params params   /*启动命令行中带的通用的参数*/
ctrl_iface_global_priv *ctrl_iface  /*global 的控制接口*/
ctrl_iface_dbus_priv *dbus_ctrl_iface  /*dbus 的控制接口*/
d. 设置wpa_global中的wpa_params中的参数。
e. 调用eloop_init函数将全局变量eloop中的user_data指针指向wpa_global。
f. 调用wpa_supplicant_global_ctrl_iface_init函数初始化global 控制接口。
g. 调用wpa_supplicant_dbus_ctrl_iface_init函数初始化dbus 控制接口。
h. 将该daemon的pid写入pid_file中。
 
2.3. wpa_supplicant_add_iface()函数:
该函数根据启动命令行中带有的参数增长网络接口, 有几个就增长几个。
a. 由于wpa_supplicant是与网络接口对应的重要的数据结构,因此,首先分配一个wpa_supplicant数据结构的内存。
b. 调用wpa_supplicant_init_iface() 函数来作网络接口的初始工做,主要包括:
设置驱动类型,默认是wext;
读取配置文件,并将其中的信息设置到wpa_supplicant数据结构中的conf 指针指向的数据结构,它是一个wpa_config类型;
命令行设置的控制接口ctrl_interface和驱动参数driver_param覆盖配置文件里设置,命令行中的优先;
拷贝网络接口名称和桥接口名称到wpa_config数据结构;
对于网络配置块有两个链表描述它,一个是 config->ssid,它按照配置文件中的顺序依次挂载在这个链表上,还有一个是pssid,它是一个二级指针,指向一个指针数组,该指针数组 按照优先级从高到底的顺序依次保存wpa_ssid指针,相同优先级的在同一链表中挂载。
c. 调用wpa_supplicant_init_iface2() 函数,主要包括:
调用wpa_supplicant_init_eapol()函数来初始化eapol;
调用相应类型的driver的init()函数;
设置driver的param参数;
调用wpa_drv_get_ifname()函数得到网络接口的名称,对于wext类型的driver,没有这个接口函数;
调用wpa_supplicant_init_wpa()函数来初始化wpa,并作相应的初始化工做;
调用wpa_supplicant_driver_init()函数,来初始化driver接口参数;在该函数的最后,会
wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
wpa_supplicant_req_scan(wpa_s, interface_count, 100000);

来主动发起scan,
调用wpa_supplicant_ctrl_iface_init()函数,来初始化控制接口;对于UNIX SOCKET这种方式,其本地socket文件是由配置文件里的ctrl_interface参数指定的路径加上网络接口名称;

2.4. wpa_supplicant_run()函数:
初始化完成以后,让wpa_supplicant的main event loop run起来。
在wpa_supplicant中,有许多与外界通讯的socket,它们都是须要注册到eloop event模块中的,具体地说,就是在eloop_sock_table中增长一项记录,其中包括了sock_fd, handle, eloop_data, user_data。
eloop event模块就是将这些socket组织起来,统一管理,而后在eloop_run中利用select机制来管理socket的通讯。

3. wpa_supplicant 的对外接口分析
对于wpa_supplicant模块的对外接口,主要有如下几种:
3.1. global control interface: 用于配置(增长或删除)网络接口。
3.2. ctrl interface: 与其余外部模块交互的控制接口。
例如,在初始化时,android 平台的wifi.c中的 wifi_connect_to_supplicant函数调用wpa_ctrl_open函数建立两个socket,一个是ctrl interface,另外一个就是monitor interface,monitor interface这个接口用于监测从wpa_supplicant发出的event事件。
这两个socket建立成功后,monitor interface 会发送ATTACH到wpa_supplicant模块,wpa_supplicant模块收到后,会将该客户端的socket信息记录下来,用于之后发送事件时用(因为用的是DGRAM的方式)。
3.3. socket for ioctl: 发送命令到kernel space。
3.4. socket (netlink) for interact between kernel and userspace(AF_NETLINK, NETLINK_ROUTE): 接受kernel发送上来的event。
3.5. socket for l2 packet(PF_PACKET): 处理802.1x报文。

相关文章
相关标签/搜索