wpa_supplicant(轉)

wpa_supplicant代碼初探收藏

 這幾天在嘗試把wpa_supplicant移植到windows ce上,替換微軟的WZC。先把源代碼down下來,瞭解了一下大致的結構。

 

 wpa_supplicant運行的整個核心就是eloop_run函數。這個函數負責處理應用程序的請求和數據鏈路層發來的EAPOL數據。eloop的針對不同的平臺有好幾個實現版本,我這裏只討論針對WIN32eloop_win.c版本。

 外部需要通過調用eloop_register_event或者eloop_register_read_sock來註冊一個回調函數,並綁定了一個相應的事件。eloop會等待每一個事件的發生,並在事件發生時調用相應的回調函數進行處理。

 

 所有與平臺相關的網絡驅動程序接口,都被通過wpa_driver_ops結構抽象成統一的接口,不管你是WEXT或者NDIS。因此也實現了平臺無關性。

 

 此外,wpa_supplicant與應用層通信的方式多種多樣,有pipesocket,你也可以實現自己的方式。只需要實現幾個基本的函數就可以了:

  wpa_supplicant_global_ctrl_iface_init

  wpa_supplicant_global_ctrl_iface_deinit

  wpa_supplicant_ctrl_iface_init

  wpa_supplicant_ctrl_iface_deinit

  wpa_supplicant_ctrl_iface_wait

 比如我在CE上就把wpa_supplicant作爲一個stream device或者service來運行,上層應用通過文件系統接口來與之進行交互。

 

 

初始化過程:

 

1. 初始化wpa_supplicant,調用下面這個函數:

struct wpa_global * wpa_supplicant_init(struct wpa_params *params)

其中,通過struct wpa_params中的參數可以進行相關配置。

 

2. 通過調用wpa_supplicant_add_iface來將ctrl interfacedriver綁定起來。

 

3. 執行wpa_supplicant_run

 

 

 

 

本來以爲這個東西只有在Atheros的平臺上用的,突然發現Ralink的平臺也可以用,甚至還看到還有老美把這個東西往android上移植。看來是個好東西,學習一下。
官方的模塊框圖


一般來說很多模塊可以根據需要選用的
EAP methods EAP state machine
如果你不需要支持wpa-enterprise那麼這兩個模塊都不需要編譯。
wpa_cliGUI
這兩個可以不要,直接寫個控制腳本,把用戶的參數變爲配置文件,重啓wpa_supplicant
driver event
driver event
無線驅動和本程序通訊的接口,一般高級的無線驅動都支持WEXT就是驅動裏面通過wireless_send_event把一些狀態信息發到本程序處理。
driver i/f
一些ioctl接口,同樣用於無線驅動和本程序之間傳遞信息。
EAPOL state machine
負責處理PTK 4-way HSGTK 2-way HS
l2_package
EAPOL
pre auth都要通過這個接口收發包。
configuration
負責處理用戶配置文件的模塊
大致流程(For WPAPSK):程序是哪些?
1           讀取配置文件
2           初始化配置參數,驅動函數wrapper
3           
讓驅動scan當前所有bssid(包括wpa APnon-wpa AP)
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
配置文件的寫法
一般這樣寫可以兼容WPAWPA2 CCMPTKIP
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 interfaceEAPOL 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這個eventauth timeout

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報文。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章