wpa_supplicant_add_iface用于向WPAS添加接口設備。所謂的添加(add iface),其實就是初始化這些設備。該函數代碼如下所示。
**wpa_supplicant.c::wpa_supplicant_add_iface**
~~~
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
struct wpa_interface *iface)
{
struct wpa_supplicant *wpa_s;
struct wpa_interface t_iface;
struct wpa_ssid *ssid;
......
wpa_s = wpa_supplicant_alloc();
......
wpa_s->global = global;
t_iface = *iface;
......// 其他一些處理。本例未涉及它們
// wpa_supplicant_init_iface為重要函數,下面單獨用一節來分析它
if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {......}
......
// 通過dbus通知外界有新的iface加入。本例并未使用DBUS
if (wpas_notify_iface_added(wpa_s)) { ......}
// 通過dbus通知外界有新的無線網絡加入
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
wpas_notify_network_added(wpa_s, ssid);
/*
還記得圖4-7中wpa_global數據結構嗎?wpa_global的ifaces變量指向一個
wpa_supplicant對象,而wpa_supplicant又通過next變量將自己鏈接到一個單向鏈表中。
*/
wpa_s->next = global->ifaces;
global->ifaces = wpa_s;
return wpa_s;
}
~~~
wpa_supplicant_add_iface的內容非常豐富,包括兩個重要數據結構(wpa_supplicant和wpa_ssid)以及一個關鍵函數wpa_supplicant_init_iface。由于這些數據結構涉及較多背景知識,故本節先來介紹它們。
**提示** wpa_supplicant_init_iface內容也比較豐富,本章將在4.3.4節中單獨介紹。
1. wpa_ssid結構體
wpa_ssid用于存儲某個無線網絡的配置信息(如所支持的安全類型、優先級等)。它其實是圖4-6所示wpa_supplicant.conf中無線網絡配置項在代碼中的反映(conf文件中每一個network項都對應一個wpa_ssid對象)。它的一些主要數據成員如圖4-10所示。
:-: 
圖4-10 wpa_ssid數據結構
圖4-10所示中的一些數據成員非常重要,下面分別介紹它們。
**(1)安全相關成員變量及背景知識**
和安全相關的成員變量如下所示。
* **1)passphrase**:該變量只和WPA/WPA2-PSK模式有關,用于存儲我們輸入的字符串密碼。而實際上,規范要求使用的卻是圖4-10中的psk變量。結合3.3.7節中關于key和password的介紹可知,用戶一般只設置字符串形式的password。而WPAS將根據它和ssid進行一定的計算以得到最終使用的PSK。參考資料[3]中有PSK計算方法。
* **2)pairwise_cipher和group_cipher**:這兩個變量和規范中的cipher suite(加密套件)定義有關。cipher suite用于指明數據收發兩方使用的數據加密方法。pairwise_cipher和group_cipher分別代表為該無線網絡設置的單播和組播數據加密方法。標準說明請閱讀參考資料[4]。WPAS中的定義如下。
~~~
// 位于defs.h中
#define WPA_CIPHER_NONE BIT(0) // 不保護。BIT(N)是一個宏,代表1左移N位后的值
#define WPA_CIPHER_WEP40 BIT(1) // WEP40(即5個ASCII字符密碼)
#define WPA_CIPHER_WEP104 BIT(2) // WEP104(即13個ASCII字符密碼)
#define WPA_CIPHER_TKIP BIT(3) // TKIP
#define WPA_CIPHER_CCMP BIT(4) // CCMP
// 系統還定義了兩個宏用于表示默認支持的加密套件類型:(位于config_ssid.h中)
#define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP)
#define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | \
WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)
~~~
* **3)key_mgmt**:該成員和802.11中的AKM suite相關。AKM(Authentication and Key Managment,身份驗證和密鑰管理)suite定義了一套算法用于在Supplicant和Authenticator之間交換身份和密匙信息。標準說明見參考資料[5],WPAS中定義的key_mgmt可取值如下。
~~~
// 位于defs.h中
#define WPA_KEY_MGMT_IEEE8021X BIT(0) // 不同的AKM suite有對應的流程與算法。不詳細介紹
#define WPA_KEY_MGMT_PSK BIT(1)
#define WPA_KEY_MGMT_NONE BIT(2)
#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
#define WPA_KEY_MGMT_WPA_NONE BIT(4)
#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5) // FT(Fast Transition)用于ESS中快速切換BSS
#define WPA_KEY_MGMT_FT_PSK BIT(6)
#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7) // SHA256表示key派生時使用SHA256做算法
#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
#define WPA_KEY_MGMT_WPS BIT(9)
// 位于config_ssid.h中
#define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X)
// 默認的AKM suite
~~~
* **4)proto**:代表該無線網絡支持的安全協議類型。其可取值如下。
~~~
// 位于defs.h中
#define WPA_PROTO_WPA BIT(0)
#define WPA_PROTO_RSN BIT(1) // RSN其實就是WPA2
// 位于config_ssid.h中
#define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN) // 默認支持兩種協議
~~~
* **5)auth_al**g:表示該無線網絡所支持的身份驗證算法,其可取值如下。
~~~
// 位于defs.h中
#define WPA_AUTH_ALG_OPEN BIT(0) // Open System,如果要使用WPA或RSN,必須選擇它
#define WPA_AUTH_ALG_SHARED BIT(1) // Shared Key算法
#define WPA_AUTH_ALG_LEAP BIT(2) // LEAP算法,LEAP是思科公司提出的身份驗證方法
#define WPA_AUTH_ALG_FT BIT(3) // 和FT有關,此處不詳細介紹,讀者可閱讀參考資料[6]
~~~
* **6)eapol_flags**:和動態WEP Key有關(本書不討論,讀者可閱讀參考資料[7]),其取值包括
如下。
~~~
// 位于config_ssid.h中
#define EAPOL_FLAG_REQUIRE_KEY_UNICAST BIT(0)
#define EAPOL_FLAG_REQUIRE_KEY_BROADCAST BIT(1)
~~~
上述變量的取值將影響wpa_supplicant的處理邏輯。本章后續代碼分析將見識到它們的實
際作用。
**(2)其他成員變量及背景知識**
圖4-10中其他三個重要成員變量介紹如下。
* **1)proactive_key_caching**:該變量和OPC(Opportunistic PMK Caching)[^①]技術有關。該技術雖還未正式被標準所接受,但很多無線設備廠商都支持它。其背景情況是,一組AP和一個中心控制器(central controller)共同組建一個所謂的mobility zone(移動區域)。zone中的所有AP都連接到此控制器上。當STA通過zone中的某一個AP(假設是AP_0)加入到無線網絡后,STA和AP0完成802.1X身份驗證時所創建的PMKSA(假設是PMKSA_0)將由controller發送到zone中的其他AP。其他AP將根據此PMSKA_0來生成PMKSA_i。當STA切換到zone中的AP_i時,它將根據PMKSA_0計算PMKID_i(不熟悉的讀者請閱讀3.3.7節RSNA介紹),并試圖和AP_i重新關聯(Reassociation)。如果此AP_i屬于同一個zone,因為之前它已經由controller發送的PMKSA_0計算出了PMKSA_i,所以STA可避過802.1X認證流程而直接進入后續的(如4-Way Handshake)處理流程。802.1X驗證的目的就是得到PMKSA,所以,如果AP_i已經有PMKSA_i,就無須費時費力開展802.1X認證工作了。proactive_key_caching默認值為0,即不支持此功能。另外,OPC功能需要AP支持。關于OPC的信息請閱讀參考資料[8]和[9]。
* **2)disable**:該變量取值為0(代表該無線網絡可用)、1(代表該無線網絡被禁止使用,但可通過命令來啟用它)、2(表示該無線網絡和P2P有關)。
* **3)mode**:wpa_ssid結構體內部還定義了一個枚舉型變量,其可取值如圖4-10底部所示。此處要特別指出的是,基礎結構型網絡中,如果STA和某個AP成功連接的話,STA也稱為Managed STA(對應枚舉值為WPAS_MODE_INFRA)。
2. wpa_supplicant結構體
wpa_supplicant結構體定義的成員變量非常多,圖4-11列出了其中一部分內容。
:-: 
圖4-11 wpa_supplicant結構體
此處先解釋幾個比較簡單的成員變量。
* drv_priv和global_drv_priv:WPAS為driver wrapper一共定義了兩個上下文信息。這是因為driver i/f接口定義了兩個初始化函數(以nl80211 driver為例,它們分別是global_init和init2)。其中,global_init返回值為driver wrapper全局上下文信息,它將保存在wpa_global的drv_priv數組中(見圖4-7)。每個wpa_supplicant都對應有一個driver wrapper對象,故它也需要保存對應的全局上下文信息。init2返回值則是driver wrapper上下文信息,它保存在wpa_supplicant的driv_priv中。
* current_bss:該變量類型為wpa_bss。wpa_bss是無線網絡在wpa_supplicant中的代表。wpa_bss中的成員主要描述了無線網絡的bssid、ssid、頻率(freq,以MHz為單位)、Beacon心跳時間(以TU為單位)、capability信息(網絡性能,見3.3.5節定長字段介紹)、信號強度等。wpa_bss的作用很重要,不過其數據結構相對比較簡單,此處不介紹。以后用到它時再來介紹。
現在,來看wpa_supplicant結構體中其他更有“料”的成員變量。
**(1)安全相關成員變量及背景知識**
wpa_supplicant也定義了一些和安全相關的成員變量。
* pairwise_cipher、group_cipher、key_mgmt、wpa_proto、mgmt_group_cipher:這幾個變量表示該wpa_supplicant最終選擇的安全策略。其中mgmt_group_cipher和IEEE 802.11w(定義了管理幀加密的規范)有關。為節約篇幅,圖4-11中僅列出pairwise_cipher一個變量。
* countermeasures:該變量名可譯為“策略”,和TKIP的MIC(Message Integrity Check,消息完整性校驗)有關。因為TKIP MIC所使用的Michael算法在某些情況下容易被攻破,所以規范特別定義了TKIP MIC countermeasures用于處理這類事情。例如,一旦檢測到60秒內發生兩次以上MIC錯誤,則停止TKIP通信60秒。這部分內容請閱讀參考資料[10]和[11]。
**(2)功能相關成員變量及背景知識**
wpa_supplicant結構體中有一些成員變量和功能相關。
* **sched_scan_timeout**(還有一些相關變量未在圖4-11中列出):該變量和計劃掃描(scheduled scan)功能有關。計劃掃描即定時掃描,需要Kernel(版本必須大于3.0)的Wi-Fi驅動支持。啟用該功能時,需要為驅動設置定時掃描的間隔(以毫秒為單位)。
* **bgscan**(還有其他相關成員變量未在圖4-11中列出):該變量和后臺掃描及漫游(background scan and roaming)技術有關。當STA在ESS(假設該ESS由多個AP共同構成)中移動時,有時候因為信號不好(例如STA離之前所關聯的AP距離過遠等),它需要切換到另外一個距離更近(即信號更好)的AP。這個切換AP的工作就是所謂的漫游。為了增強切換AP時的無縫體驗(掃描過程中,STA不能收發數據幀。從用戶角度來看,相當于網絡不能使用),STA可采用background scan(定時掃描一小段時間或者當網絡空閑時才掃描,這樣可減少對用戶正常使用的干擾)技術來監視周圍AP的信號強度等信息。一旦之前使用的AP信號強度低于某個閾值,STA則可快速切換到某個信號更強的AP。除了background scan外,還有一種on-roam scan也能提升AP切換時的無縫體驗。關于background scan和roaming,請閱讀參考資料[12]和[13]。
* **gas**:該變量是GAS(Generic Advertisement Service,通用廣告服務)的小寫,和802.11u協議有關。該協議規定了不同網絡間互操作的標準,其制定的初衷是希望Wi-Fi網絡能夠像運營商的蜂窩網絡一樣,方便終端設備接入。例如,人們用智能手機可搜索到數十個、甚至上百個無線網絡。在這種情況下如何選擇正確的無線網絡呢?802.11u協議使用GAS和ANQP(AccessNetwork Query Protocol,接入網絡查詢協議)來幫助設備自動選擇合適的無線網絡。其中,GAS是MLME SAP中的一種(見規范6.3.71節),它使得STA在通過認證前(prior to authentication)就可以向AP發送和接收ANQP數據包。STA則使用ANQP協議向AP查詢無線網絡運營商的信息,然后STA根據這些信息來判斷自己可以加入哪一個運營商的無線網絡(例如中國移動手機卡用戶可以連接中國移動架設的無線網絡)。802.11u現在還不是特別完善,詳細信息可閱讀參考資料[14]和[15]。
* **CONFIG_SME**:該變量是一個編譯宏,用于設置WPAS是否支持SME。我們在3.3.6節“802.11 MAC管理實體”中曾介紹過SME(Station Management Entity)。如果該功能支持,則driver wrapper可直接利用SME定義的SAP,而無須使用MLME的SAP了。Android平臺中如果定義了CONFIG_DRIVER_NL80211宏,則CONFIG_SME也將被定義(參考drivers.mk文件)。不過SME的功能是否起作用,還需要看driver是否支持。Galaxy Note 2 wlan driver不支持SME,故本書不討論。
**(3)wpa_states的取值**
wpa_states的取值如下。
* **WPA_DISCONNECTED**:表示當前未連接到任何無線網絡。
* **WPA_INTERFACE_DISABLED**:代表當前此wpa_supplicant所使用的網絡設備被禁用。
* **WPA_INACTIVE**:代表當前此wpa_supplicant沒有可連接的無線網絡。這種情況包括周圍沒有無線網絡,以及有無線網絡,但是因為沒有配置信息(如沒有設置密碼等)而不能發起認證及關聯請求的情況。
* **WPA_SCANNING、WPA_AUTHENTICATING、WPA_ASSOCIATING**:分別表示當前wpa_supplicant正處于掃描無線網絡、身份驗證、關聯過程中。
* **WPA_ASSOCIATED**:表明此wpa_supplicant成功關聯到某個AP。
* **WPA_4WAY_HANDSHAKE**:表明此wpa_supplicant處于四次握手處理過程中。當使用PSK(即WPA/WPA2-Personal)策略時,STA收到第一個EAPOL-Key數據包則進入此狀態。當使用WPA/WPA2-Enterprise方法時,當STA完成和RAIDUS身份驗證后則進入此狀態。
* **WPA_GROUP_HANDSHAKE**:表明STA處于組密鑰握手協議處理過程中。當STA完成四次握手協議并收到組播密鑰交換第一幀數據后即進入此狀態(或者四次握手協議中攜帶了GTK信息,也會進入此狀態。詳情見4.5.5節EAPOL-Key交換流程分析)。
* **WPA_COMPLETED**:所有認證過程完成,wpa_supplicant正式加入某個無線網絡。
介紹完上述幾個重要數據結構后,下面將分析wpa_supplicant_add_iface中一個關鍵函數wpa_supplicant_init_iface。
[^①]:有些書上也叫Opportunisitic Key Caching,簡寫為OKC。
- 前言
- 第1章 準備工作
- 1.1 Android系統架構
- 1.2 工具使用
- 1.2.1 Source Insight的使用
- 1.2.2 Eclipse的使用
- 1.2.3 BusyBox的使用
- 1.3 本書資源下載說明
- 第2章 深入理解Netd
- 2.1 概述
- 2.2 Netd工作流程
- 2.2.1 main函數分析
- 2.2.2 NetlinkManager分析
- 2.2.3 CommandListener分析
- 2.2.4 DnsProxyListener分析
- 2.2.5 MDnsSdListener分析
- 2.3 CommandListener中的命令
- 2.3.1 iptables、tc和ip命令
- 2.3.2 CommandListener構造函數和測試工具ndc
- 2.3.3 InterfaceCmd命令
- 2.3.4 IpFwd和FirewallCmd命令
- 2.3.5 ListTtysCmd和PppdCmd命令
- 2.3.6 BandwidthControlCmd和IdletimerControlCmd命令
- 2.3.7 NatCmd命令
- 2.3.8 TetherCmd和SoftapCmd命令
- 2.3.9 ResolverCmd命令
- 2.4 NetworkManagementService介紹
- 2.4.1 create函數詳解
- 2.4.2 systemReady函數詳解
- 2.5 本章總結和參考資料說明
- 2.5.1 本章總結
- 2.5.2 參考資料說明
- 第3章 Wi-Fi基礎知識
- 3.1 概述
- 3.2 無線電頻譜和802.11協議的發展歷程
- 3.2.1 無線電頻譜知識
- 3.2.2 IEEE 802.11發展歷程
- 3.3 802.11無線網絡技術
- 3.3.1 OSI基本參考模型及相關基本概念
- 3.3.2 802.11知識點導讀
- 3.3.3 802.11組件
- 3.3.4 802.11 Service介紹
- 3.3.5 802.11 MAC服務和幀
- 3.3.6 802.11 MAC管理實體
- 3.3.7 無線網絡安全技術知識點
- 3.4 Linux Wi-Fi編程API介紹
- 3.4.1 Linux Wireless Extensions介紹
- 3.4.2 nl80211介紹
- 3.5 本章總結和參考資料說明
- 3.5.1 本章總結
- 3.5.2 參考資料說明
- 第4章 深入理解wpa_supplicant
- 4.1 概述
- 4.2 初識wpa_supplicant
- 4.2.1 wpa_supplicant架構
- 4.2.2 wpa_supplicant編譯配置
- 4.2.3 wpa_supplicant命令和控制API
- 4.2.4 git的使用
- 4.3 wpa_supplicant初始化流程
- 4.3.1 main函數分析
- 4.3.2 wpa_supplicant_init函數分析
- 4.3.3 wpa_supplicant_add_iface函數分析
- 4.3.4 wpa_supplicant_init_iface函數分析
- 4.4 EAP和EAPOL模塊
- 4.4.1 EAP模塊分析
- 4.4.2 EAPOL模塊分析
- 4.5 wpa_supplicant連接無線網絡分析
- 4.5.1 ADD_NETWORK命令處理
- 4.5.2 SET_NETWORK命令處理
- 4.5.3 ENABLE_NETWORK命令處理
- 4.6 本章總結和參考資料說明
- 4.6.1 本章總結
- 4.6.2 參考資料說明
- 第5章 深入理解WifiService
- 5.1 概述
- 5.2 WifiService的創建及初始化
- 5.2.1 HSM和AsyncChannel介紹
- 5.2.2 WifiService構造函數分析
- 5.2.3 WifiStateMachine介紹
- 5.3 加入無線網絡分析
- 5.3.1 Settings操作Wi-Fi分析
- 5.3.2 WifiService操作Wi-Fi分析
- 5.4 WifiWatchdogStateMachine介紹
- 5.5 Captive Portal Check介紹
- 5.6 本章總結和參考資料說明
- 5.6.1 本章總結
- 5.6.2 參考資料說明
- 第6章 深入理解Wi-Fi Simple Configuration
- 6.1 概述
- 6.2 WSC基礎知識
- 6.2.1 WSC應用場景
- 6.2.2 WSC核心組件及接口
- 6.3 Registration Protocol詳解
- 6.3.1 WSC IE和Attribute介紹
- 6.3.2 802.11管理幀WSC IE設置
- 6.3.3 EAP-WSC介紹
- 6.4 WSC代碼分析
- 6.4.1 Settings中的WSC處理
- 6.4.2 WifiStateMachine的處理
- 6.4.3 wpa_supplicant中的WSC處理
- 6.4.4 EAP-WSC處理流程分析
- 6.5 本章總結和參考資料說明
- 6.5.1 本章總結
- 6.5.2 參考資料說明
- 第7章 深入理解Wi-Fi P2P
- 7.1 概述
- 7.2 P2P基礎知識
- 7.2.1 P2P架構
- 7.2.2 P2P Discovery技術
- 7.2.3 P2P工作流程
- 7.3 WifiP2pSettings和WifiP2pService介紹
- 7.3.1 WifiP2pSettings工作流程
- 7.3.2 WifiP2pService工作流程
- 7.4 wpa_supplicant中的P2P
- 7.4.1 P2P模塊初始化
- 7.4.2 P2P Device Discovery流程分析
- 7.4.3 Provision Discovery流程分析
- 7.4.4 GO Negotiation流程分析
- 7.5 本章總結和參考資料說明
- 7.5.1 本章總結
- 7.5.2 參考資料說明
- 第8章 深入理解NFC
- 8.1 概述
- 8.2 NFC基礎知識
- 8.2.1 NFC概述
- 8.2.2 NFC R/W運行模式
- 8.2.3 NFC P2P運行模式
- 8.2.4 NFC CE運行模式
- 8.2.5 NCI原理
- 8.2.6 NFC相關規范
- 8.3 Android中的NFC
- 8.3.1 NFC應用示例
- 8.3.2 NFC系統模塊
- 8.4 NFC HAL層討論
- 8.5 本章總結和參考資料說明
- 8.5.1 本章總結
- 8.5.2 參考資料說明
- 第9章 深入理解GPS
- 9.1 概述
- 9.2 GPS基礎知識
- 9.2.1 衛星導航基本原理
- 9.2.2 GPS系統組成及原理
- 9.2.3 OMA-SUPL協議
- 9.3 Android中的位置管理
- 9.3.1 LocationManager架構
- 9.3.2 LocationManager應用示例
- 9.3.3 LocationManager系統模塊
- 9.4 本章總結和參考資料說明
- 9.4.1 本章總結
- 9.4.2 參考資料說明
- 附錄