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。 android