首先感謝各位兄弟姐妹們的耐心等待。根據今天獲得的消息,本書預計在下週各大網店提供預訂。注意,此處連載的是未經出版社編輯的原始稿件,因此樣子會有些非專業。html
注意,以下是本章目錄,本文節選7.1~7.2.2 7.4~7.4.1.2節,7.5sass
爲了方便讀者深刻學習,本系列連載都會將做者研究過安全
程中所學習的參考文獻列出來網絡
承接第6章介紹的WSC,本章將繼續介紹Wi-Fi Alliance(Wi-Fi聯盟)推出的另一項重要技術規範Wi-Fi P2P。該規範的商品名爲Wi-Fi Direct,它支持多個Wi-Fi設備在沒有AP的狀況下相互鏈接。數據結構
在Android平臺的Wi-Fi相關模塊中,P2P的功能點主要集中在:架構
和WSC同樣,本章的分析擬採用以下方法:併發
下面,先來認識一下P2P。框架
WFA定義的P2P協議文檔全名爲「Wi-Fi Peer-to-Peer(P2P) Technical Specification」,目前的版本爲1.1,全長160頁。P2P技術使得多個Wi-Fi設備在沒有AP的狀況下也能構成一個網絡(P2P Network,也被稱之爲P2P Group)並相互通訊。less
Wi-Fi P2P技術是Wi-Fi Display(也稱之爲Miracast,詳情請參考做者的一篇博文http://blog.csdn.net/innost/article/details/8474683)的基礎。在Miracast應用場景中,一臺支持P2P的智能手機可直接鏈接上一臺支持P2P的智能電視,智能手機隨後將本身的屏幕,或者媒體資源傳送給電視機去顯示或播放。顯然,藉助P2P技術,Wi-Fi設備之間的直接相連將極大拓展Wi-Fi技術的使用場景。socket
注意:根據筆者本身的判斷,隨着支持愈來愈多的設備支持P2P和Miracast,智能終端設備之間的多屏共享和互動功能將很快得以實現。另外,恰逢本章撰寫之際,Google發佈了Android 4.3。在此次發佈盛會上,Google推出了ChromeCast設備。目前,ChromeCast的技術實現細節還不清楚,聽說有多是Google本身定義的Google cast協議(可參考developers.google.com/cast)。
下面先簡單介紹一下P2P的架構。
P2P架構中定義了三個組件,筆者將其稱之爲一個設備,兩種角色。這三個組件分別是:
相信對本書的讀者對上面這三個組件的概念並不陌生。實際上,P2P技術模仿了Infrastructure BSS網絡結構:
最終構成的這個P2P Group組織結構如圖7-1所示:
圖7-1 P2P Group示意圖
圖7-1展現了一個典型P2P Group的構成,其中:
注意:「不支持P2P功能」更準確的定義是指不能處理P2P協議。在P2P網絡中,GO等同於AP,因此Legacy Clients也能搜索到GO並關聯上它。不過,因爲Legacy Clients不能處理P2P協議,因此P2P一些特有功能在這些Legacy Clients中沒法實現。
經過上述介紹讀者會進一步發現P2P Group和Infrastructure BSS的類似性:
這部份內容和Infrastructure BSS中STA利用WSC先協商安全信息而後再關聯至AP的流程徹底同樣。正是這種類似性,使得P2P能充分利用現有的一些技術規範。圖7-2所示爲P2P及其依賴的技術項:
圖7-2 P2P及其依賴的技術項
由圖7-2可知:
在如圖7-2所示的技術項中,P2P Discovery是P2P所特有的,也是其核心。本章將主要圍繞它進行介紹。首先來看P2P Discovery。
提示:
1、P2P Group Operation講得是GO如何管理一個Group,也就是GO的工做職責。這部份內容請讀者自行學習參考資料[2]一節。
2、P2P PowerManagement和P2P設備的電源管理有關,用於節省沒必要要的電力損耗。因爲篇幅關係,本章不擬討論它。請感興趣的讀者自行學習參考資料[3]。
P2P Discovery的目的很簡單,就是使得多個P2P Device可以互相發現並構建一個Group。根據規範,它包括四個主要技術子項:
提示:Group分Persistent(永久性) Group和Temporary(臨時性) Group兩種。咱們舉二個簡單例子來講明兩者的區別:
Temporary Group:當你有份文件要傳給一個同事時,雙方打開手機的Wi-Fi P2P功能,創建一個Group,而後傳輸文件,最後關閉Wi-Fi P2P。在這個過程當中,GO和Client的角色分配由Group Formation來決定,這一次的GO多是你的設備,下一次則多是其餘人的設備。對於這種Group,在創建Group過程當中所涉及的安全配置信息以及和Group相關的信息(之後咱們會見到它)都是臨時的,即下一次再組建Group時,這些安全配置信息都將發生變化。
Persistent Group:在這種Group中,GO由指定設備來扮演,並且安全配置信息及Group相關信息一旦生成,後續就不會再發生變化(除非用戶從新設置)。Persistent Group中的GO多見於固定用途的設備,例如打印機等。如此,除了第一次經過P2P鏈接到打印機時相對麻煩一點(須要利用WSC協商安全配置信息)外,後續使用的話,因爲P2P設備將保存這些安全信息,因此下一次再使用打印機時就能利用這些信息直接和打印機進行關聯了。
因爲篇幅關係,本章將僅介紹上述四個知識點中最爲基礎的Device Discovery和Group Formation,而Service Discovery和P2P Invitation的內容請讀者學習完本章後再仔細研讀P2P規範。
P2P Device Discovery雖然也是利用802.11中的Probe Request和Probe Response幀來搜索周圍的P2P設備,但其步驟卻比Infrastructure BSS中的無線網絡搜索要複雜。舉一個簡單的例子,一個P2P Device除了本身要發送Probe Request幀外,還得接收來自其餘設備的Probe Request幀並回復Probe Response幀。而在Infrastructure BSS中,只有AP會發送Probe Response幀。
爲了加快搜索速度,P2P爲Device Discovery定義了兩個狀態和兩個階段。
P2P Device Discovery的工做流程包含兩個狀態和兩個階段。先來看兩個狀態,它們分別是:
再來看兩個階段,它們分別是:
圖7-3所示爲P2P Device Discovery的流程示意圖。
圖7-3 P2P Device Discovery流程示意圖
圖7-3所示爲兩個P2P Device的Discovery流程,其中:
提示:P2P規範對兩個狀態及兩個階段的描述很是細緻,甚至於對每一個狀態能幹什麼和不能幹什麼都有詳細說明。不過,從如何快速掌握P2P框架的角度來看,筆者以爲這些內容過於囉嗦。
瞭解了Device Discovery的大致工做流程後,下面咱們將經過實例來看看P2P使用到的Probe Request和Probe Response幀。
========================略略略略略略略略==========
在第5章5.2.3中「WifiNative介紹」一節中曾介紹了wpa_supplicant的啓動,在那一節中,讀者會發現wpa_supplicant進程由WifiStateMachine啓動。在Android官方代碼中,雖然Java層有WifiService和WifiP2pService兩個幾乎徹底不一樣的Wifi服務,但兩者都只和Native層的惟一一個wpa_supplicant進程交互。簡單點說,Android原生代碼中,一個wpa_supplicant進程將同時支持WifiService和WifiP2pService。
上述這種設計方法使得wpa_supplicant負擔較重,因此,一些手機廠商會爲WifiService和WifiP2pService各建立一個wpa_supplicant進程,使得它們能各司其職而互不干擾。以筆者的Galaxy Note2爲例,它的,WifiService將和wpa_supplicant進程交互,而WifiP2pService將和一個名爲p2p_supplicant(通過筆者測試,p2p_supplicant實際上就是wpa_supplicant,只不過名字不一樣罷了)的進程交互。
圖7-26所示爲Galaxy Note2 init配置文件中關於p2p_supplicant服務的示意圖:
圖7-26 Galaxy Note2中p2p_supplicant服務配置項
由圖7-26可知:
圖7-27 p2p_supplicant.conf內容
提示:關於init配置文件中wpa_supplicant服務的說明,請讀者參考第4章4.3「wpa_supplicant初始化流程分析」一節。
圖7-27中,p2p_supplicant對於的ctrl_iface路徑爲/data/misc/wifi/sockets。因此,若是要使用wpa_cli和p2p_supplicant交互的話,必須指定正確的ctrl_iface路徑。圖7-28所示爲筆者用wpa_cli測試p2p_supplicant時的示例截圖:
圖7-28 wpa_cli和p2p_supplicant交互
下面來分析wpa_supplicant中和P2P相關的代碼。
注意:以Galaxy Note2爲例,p2p_supplicant就是wpa_supplicant,只是編譯時打開了P2P相關的選項。下面的分析將以wpa_supplicant中和P2P相關的代碼及工做流程爲主。
首先來看WPAS中P2P相關模塊的初始化。該初始化工做咱們在第4章4.3.4中「wpa_supplicant_init_iface分析之五」曾提到過,其對應的函數wpas_p2p_init,立刻來看它
[p2p_supplicant.c::wpas_p2p_init]
int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
{
struct p2p_config p2p; //p2p變量指向一個p2p_config對象,表明P2P模塊的配置信息
unsigned int r; int i;
//①WPA_DRIVER_FLAGS_P2P_CAPABLE:表明Wifi驅動對P2P支持的能力,詳情見下文解釋
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE)) return 0;
if (global->p2p) return 0;
//若是wifi driver能完成P2P功能,就不用勞駕WPAS了
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {......}
//②初始化並設置p2p_config對象
os_memset(&p2p, 0, sizeof(p2p));
p2p.msg_ctx = wpa_s; p2p.cb_ctx = wpa_s;
p2p.p2p_scan = wpas_p2p_scan; //P2P對應的掃描函數
.......//設置一些回調函數
p2p.get_noa = wpas_get_noa; p2p.go_connected = wpas_go_connected;
//設置P2P Device address。
os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
//設置P2P模塊配置信息,包括device name,model name,uuid等
p2p.dev_name = wpa_s->conf->device_name;
p2p.manufacturer = wpa_s->conf->manufacturer;
p2p.model_name = wpa_s->conf->model_name;
p2p.model_number = wpa_s->conf->model_number;
p2p.serial_number = wpa_s->conf->serial_number;
if (wpa_s->wps) {
os_memcpy(p2p.uuid, wpa_s->wps->uuid, 16);
p2p.config_methods = wpa_s->wps->config_methods;
}
//設置Operation Channel信息和listen channel信息
if (wpa_s->conf->p2p_listen_reg_class &&
wpa_s->conf->p2p_listen_channel) {
p2p.reg_class = wpa_s->conf->p2p_listen_reg_class;
p2p.channel = wpa_s->conf->p2p_listen_channel;
} else {......//設置默認值}
......
//設置國家碼
if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
os_memcpy(p2p.country, wpa_s->conf->country, 2);
p2p.country[2] = 0x04;
} else//配置文件中沒有設置國家,因此取值爲"XX\x04"
os_memcpy(p2p.country, "XX\x04", 3);//讀者可回顧圖7-7
//判斷wifi 驅動是否支持配置文件中設置的operationg channel和listen channel
if (wpas_p2p_setup_channels(wpa_s, &p2p.channels)) {......}
os_memcpy(p2p.pri_dev_type, wpa_s->conf->device_type,WPS_DEV_TYPE_LEN);
p2p.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
os_memcpy(p2p.sec_dev_type, wpa_s->conf->sec_device_type,
p2p.num_sec_dev_types * WPS_DEV_TYPE_LEN);
//是否支持concurrent operation
p2p.concurrent_operations = !!(wpa_s->drv_flags&WPA_DRIVER_FLAGS_P2P_CONCURRENT);
p2p.max_peers = 100;//最多能保存100個對端P2P Device信息
//配置文件中沒有設置p2p_ssid_postfix,但P2pStateMachine在initializeP2pSettings函數中
//將設置P2P SSID後綴。以筆者的Galaxy Note2爲例,其P2P SSID後綴爲「Android_4aa9」
if (wpa_s->conf->p2p_ssid_postfix) {......}
p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss;
//③global->p2p指向一個p2p_data結構體,它是WPAS中P2P模塊的表明
global->p2p = p2p_init(&p2p);
......
for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {//拷貝vendor廠商特定的WSC屬性信息
if (wpa_s->conf->wps_vendor_ext[i] == NULL) continue;
p2p_add_wps_vendor_extension(global->p2p, wpa_s->conf->wps_vendor_ext[i]);
}
return 0;
}
由上述代碼可知,wpas_p2p_init的工做很是簡單,主要內容包括:
下面來介紹上述代碼中涉及到的一些知識。
先來看上述代碼中提到的drv_flags變量。WPAS中,Wifi驅動對P2P功能的支持狀況就是由它來表達的。筆者的Galaxy Note2中該變量取值爲0x2EAC0,其表達的含義以下:
[-->driver.h]
#define WPA_DRIVER_FLAGS_AP 0x00000040 //Wifi driver支持AP。它使得P2P設備能扮演GO
/*
標誌標明association成功後,kernel driver須要設置WEP key
這個標誌出現的緣由是因爲kernel API發生了變更,使得只能在關聯成功後才能設置key
*/
#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE 0x00000080
#define WPA_DRIVER_FLAGS_P2P_CONCURRENT 0x00000200 //Wifi驅動支持STA和P2P的併發運行
#define WPA_DRIVER_FLAGS_P2P_CAPABLE 0x00000800 //Wifi驅動支持P2P
/*
7.2.2.1.2「Probe Request幀設置」一節曾提到過說P2P包含Device Address和Interface Address
兩種類型的地址。在實際實現過程當中,這兩個地址分別表明兩個virtual interface。顯然,P2P中第一個和一直
存在的是擁有Device Address的vitural interface。下面這個標誌表示該virtual interface能夠參與
P2P管理(除P2P Group Operation以外的工做)工做以及非P2P相關的工做(例如利用這個virtual
interface 加入到一個BSS)
*/
#define WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P 0x00002000
/*
該標誌主要針對associate操做。當關聯操做失敗後,若是driver支持該選項,則代表driver能處理失敗之
後的各類收尾工做(Key、timeout等工做)。不然,WPAS須要本身處理這些事情
*/
#define WPA_DRIVER_FLAGS_SANE_ERROR_CODES 0x00004000
//下面這個標誌和off channel機制有關。讀者可參考第4章4.3.4中「capability介紹」一節。當802.11
//MAC幀經過off channel發送的話,下面這個標誌表示driver會反饋一個發送狀況(TX Report)消息給WPAS
#define WPA_DRIVER_FLAGS_OFFCHANNEL_TX 0x00008000
//下面這兩個標誌表示kernel中的driver是否能反饋Deauthentication/Disassociation幀
//發送狀況(TX Report)
#define WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS 0x00020000
下面來看wpas_p2p_init中出現的幾個重要數據結構,首先是p2p_config和p2p_data,它們的成員如圖7-29所示:
圖7-29 p2p_config和p2p_data結構示意圖
圖7-29展現了p2p_config和p2p_data兩個數據結構中一些重要的成員。其中:
下面來看另外幾個重要數據結構的內容,如圖7-30所示:
圖7-30 p2p_device及其餘數據結構示意圖
圖7-30展現了五種數據結構,其中:
提示: WPAS中定義了很是多的數據結構類型,這極大增長了初學者的學習難度。根據筆者本身的經驗,建議讀者在學習過程當中先簡單瞭解這些數據結構的名字及做用,而後在具體代碼分析時再結合代碼邏輯來了解這些數據結構及其內部各個成員變量的具體做用。
本章對Wi-Fi P2P進行了詳細介紹,主要內容包括:
最後,但願讀者在本章的基礎上,完成下列的一些任務:
本章參考資料主要是Wifi P2P規範1.1版,讀者可從http://www.doc88.com/p-908280242988.html上下載協議全文。
[1] WiFi P2P第2節「Architectural Overview」
[2] WiFi P2P第3.2節「P2P Group Operation」
[3] WiFi P2P第3.3節「P2P Power Management」
[4] WiFi P2P第3.1節「P2P Discovery」
[5] Part11:Wireless LAN Medium Access Control(MAC) and Phsyical Layer(PHY) Specifications附錄J「Country information element and regulatory classes」
該文檔下載地址爲http://download.csdn.net/download/s_bird0529/2553723。附錄J詳細描述了國家碼和管制信息方面的內容
[6] WiFi P2P第4.2節「Management Frames」
[7] 802.11-2012第8.4.1.11節「Action Field」
該節介紹了Action幀Category字段的取值狀況
[8] WiFi P2P第4.1節「P2P Information Elements」
[9] WiFi P2P附錄A「P2P State Machine」