WPAS中,WSC的處理就不像在App及Framework WifiService中那么簡單。先來看WSC的初始化流程。
**1、WSC模塊初始化**
WSC模塊的初始化工作位于wpa_supplicant_init_iface(不熟悉的讀者請參考4.3.4節“wpa_supplicant_init_iface分析之五”)函數的最后幾行中,相關代碼如下所示。
**wpa_supplicant.c::wpa_supplicant_init_iface**
~~~
static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,struct wpa_interface *iface)
{
......// 其他代碼。可參考4.3.4節“wpa_supplicant_init_iface分析之五”
// 調用wpas_wps_init函數初始化WSC相關模塊
if (wpas_wps_init(wpa_s))
return -1;
if (wpa_supplicant_init_eapol(wpa_s) < 0)
return -1;
wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
......
}
~~~
注意,在WPAS代碼中WSC稱為WPS2。為了行文方便,以后將不再區分WPS和WSC。
wpas_wps_init的代碼如下所示。
**wps_supplicant.c::wpas_wps_init**
~~~
int wpas_wps_init(struct wpa_supplicant *wpa_s)
{
struct wps_context *wps; // wps_context是WPS模塊的核心數據結構
// wps_registrar_config代表Registrar的配置信息
struct wps_registrar_config rcfg;
struct hostapd_hw_modes *modes;
u16 m;
wps = os_zalloc(sizeof(*wps));
......
/*
設置兩個重要的回調函數。其中,cred_cb在EAP-WSC模塊解析credential屬性集時使用。后面將見到其用法。
event_cb用于通知WSC模塊發生的一些事件。例如“WSC-SUCCESS”就在wpa_supplicant_wps_event
中處理。
*/
wps->cred_cb = wpa_supplicant_wps_cred;
wps->event_cb = wpa_supplicant_wps_event;
wps->cb_ctx = wpa_s;
// 初始化設備信息,這些信息來自圖6-33中的配置
wps->dev.device_name = wpa_s->conf->device_name;
wps->dev.manufacturer = wpa_s->conf->manufacturer;
wps->dev.model_name = wpa_s->conf->model_name;
wps->dev.model_number = wpa_s->conf->model_number;
wps->dev.serial_number = wpa_s->conf->serial_number;
wps->config_methods = // 將字符串描述的WSC方法轉換成對應的標志位
wps_config_methods_str2bin(wpa_s->conf->config_methods);
......// 配置參數檢查,Label和Display不能同時配置。即設備不能同時使用靜態PIN碼和動態PIN碼
/*
WSC規范新增了Virtual Push Button和Virtual Display兩種方法,wps_fix_config_methods
函數將判斷設備是否支持Push Button或者Display。如果二者支持,需要為WSC添加對應的Virtual
方法。下面這個函數僅在CONFIG_WPS2宏被定義的情況下有實際作用。
*/
wps->config_methods = wps_fix_config_methods(wps->config_methods);
wps->dev.config_methods = wps->config_methods;
os_memcpy(wps->dev.pri_dev_type, wpa_s->conf->device_type, WPS_DEV_TYPE_LEN);
wps->dev.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
os_memcpy(wps->dev.sec_dev_type, wpa_s->conf->sec_device_type,
WPS_DEV_TYPE_LEN * wps->dev.num_sec_dev_types);
wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);
modes = wpa_s->hw.modes;
// 設置RF Bands相關信息
if (modes) {
for (m = 0; m < wpa_s->hw.num_modes; m++) {
if (modes[m].mode == HOSTAPD_MODE_IEEE80211B ||
modes[m].mode == HOSTAPD_MODE_IEEE80211G){
wps->dev.rf_bands |= WPS_RF_24GHZ;
}
else if (modes[m].mode == HOSTAPD_MODE_IEEE80211A){
wps->dev.rf_bands |= WPS_RF_50GHZ;
}
}
}
if (wps->dev.rf_bands == 0)
wps->dev.rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ;
os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN);
wpas_wps_set_uuid(wpa_s, wps); // 設置uuid,如果沒有配置的話,則利用MAC地址生成UUID
// STA默認支持的認證算法和加密算法
// 結合前面介紹的理論知識,讀者能想起來對應的Attribute是什么嗎
wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
os_memset(&rcfg, 0, sizeof(rcfg));
rcfg.new_psk_cb = wpas_wps_new_psk_cb;
rcfg.pin_needed_cb = wpas_wps_pin_needed_cb;
rcfg.set_sel_reg_cb = wpas_wps_set_sel_reg_cb;
rcfg.cb_ctx = wpa_s;
/*
創建一個wps_registrar對象,該對象代表Registrar。不過Enrollee中用不到它,故此處不開展
分析。感興趣的讀者請在學完本章后再自行研究相關內容。
*/
wps->registrar = wps_registrar_init(wps, &rcfg);
......
wpa_s->wps = wps;
return 0;
}
~~~
圖6-33為Galaxy Note 2中wpa_supplicant.conf的配置文件。
:-: 
圖6-33 wpa_supplicant.conf示例
下面來看WPS_PIN命令的處理流程。
**2、WPS_PIN命令處理**
根據前文介紹,WifiStateMachine將發送"WPS_PIN any"命令給WPAS以觸發WSC的工作流程。該命令的處理代碼如下所示。
**ctrl_iface.c::wpa_supplicant_ctrl_iface_wps_pin**
~~~
static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, char *cmd,char *buf, size_t buflen)
{
u8 bssid[ETH_ALEN], *_bssid = bssid;
char *pin; int ret;
/*
cmd傳入此函數時已經將“WPS_PIN any”中的“WPS_PIN ”(注意右邊引號前的空格)子串忽略了,
所以cmd的取值是“any”。
*/
pin = os_strchr(cmd, ' ');
if (pin) *pin++ = '\0';
if (os_strcmp(cmd, "any") == 0)
_bssid = NULL;
......
if (pin) {
// 上層沒有傳入PIN碼,故略去此段代碼
}
// 啟動WPS流程。詳情見下文
ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
......
done:
ret = os_snprintf(buf, buflen, "%08d", ret); // 將PIN碼轉成字符串返回給WifiStateMachine
return ret;
}
~~~
上述代碼中,wpas_wps_start_pin函數將被調用以開始WPS流程。調用該函數時,相關的參數取值情況是:_bssid為NULL,DEV_PW_DEFAULT值為0。
來看wpas_wps_start_pin的代碼,如下所示。
**wps_supplicant.c::wpas_wps_start_pin**
~~~
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,const char *pin, int p2p_group, u16 dev_pw_id)
{
struct wpa_ssid *ssid;
char val[128];
unsigned int rpin = 0;
wpas_clear_wps(wpa_s); // 清空之前的WPS信息
/*
wpas_wps_add_network將創建一個wpa_ssid對象,它用于保存一個無線網絡的配置信息。
在wpas_wps_add_network中,該網絡的key_mgmt將被為WPA_KEY_MGMT_WPS。另外,每一個wpa_ssid對象
都有一個類型為eap_peer_config的成員,該成員用于保存EAP Supplicant的配置信息。對于WPS來說,
該配置信息的Method被設置為EAP-WSC,identity被設為“WFA-SimpleConfig-Enrollee-1-0”。
wpas_wps_add_network函數比較簡單,請讀者自行研究。
*/
ssid = wpas_wps_add_network(wpa_s, 0, bssid);
......
ssid->temporary = 1;
ssid->p2p_group = p2p_group;
......// CONFIG_P2P的處理
if (pin){
os_snprintf(val, sizeof(val), "\"pin=%s dev_pw_id=%u\"",pin, dev_pw_id);
}else {
/*
生成一個隨機PIN碼。WSC對PIN碼格式有所規定。PIN碼一共包含8個數字,最后一個數字(即最右邊的
一個數字是前7個數字的校驗和)。
*/
rpin = wps_generate_pin();
// 以圖6-2為例,PIN碼為“01308204”,所以下面val的值為“pin=01308204 dev_pw_id=0”
os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u\"",rpin, dev_pw_id);
}
// 將value值保存到wpa_ssid中eap成員變量的phase1中
wpa_config_set(ssid, "phase1", val, 0);
if (wpa_s->wps_fragment_size)
ssid->eap.fragment_size = wpa_s->wps_fragment_size;
// 注冊一個WSC超時任務,超時時間是120秒。該時間也是由WSC規范規定的
eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, wpa_s, NULL);
// 重新關聯并發起掃描。該函數比較簡單,請讀者自行研究。該函數內部將發起掃描請求
wpas_wps_reassoc(wpa_s, ssid, bssid);
return rpin;
}
~~~
由上述代碼可知,wpas_wps_start_pin添加了一個潛在的和WPS相關的無線網絡配置項。接下來的工作自然是需要掃描周圍的無線網絡以搜索那些支持WSC功能的AP。這一工作正是屬于前文介紹的WSC Discovery Phase。
**3、發起掃描請求**
根據前文對WSC基礎知識的介紹,STA發起掃描請求時需要在Probe Request幀中添加WSC IE。WPAS中,掃描工作的代碼在wpa_supplicant_scan函數中,我們重點關注其中和WSC相關的部分,如下所示。
**scan.c::wpa_supplicant_scan**
~~~
static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx){
......// 該函數的詳情請參考4.5.3節“無線網絡掃描流程分析”
wpa_supplicant_optimize_freqs(wpa_s, ¶ms);
// 下面這個函數將處理WSC IE
extra_ie = wpa_supplicant_extra_ies(wpa_s, ¶ms);
}
~~~
**scan.c::wpa_supplicant_extra_ies**
~~~
static struct wpabuf *wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params){
struct wpabuf *extra_ie = NULL;
#ifdef CONFIG_WPS // 處理WPS
int wps = 0;
enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
#endif /* CONFIG_WPS */
#ifdef CONFIG_WPS
/*
wpas_wps_in_use判斷是否需要在Probe Request中添加WSC IE。WPAS的判斷標準比較簡單,
就是查詢所有的wpa_ssid對象,判斷它們的key_mgmt是否設置了WPA_KEY_MGMT_WPS。如果有,
表明搜索的時候需要支持WSC IE。我們在介紹“WPS_PIN命令處理”時曾說過,WPAS將添加一個
wpa_ssid對象,并設置key_mgmt為WPA_KEY_MGMT_WPS。
wpas_wps_in_use的返回值也有含義,返回1表明使用PIN方法,返回2表明使用PBC方法。
wpas_wps_in_use函數比較簡單,請讀者自行閱讀。
*/
wps = wpas_wps_in_use(wpa_s, &req_type);
if (wps) {
struct wpabuf *wps_ie;
// 構造Probe Request中的WSC IE
wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev,
wpa_s->wps->uuid, req_type, 0, NULL);
if (wps_ie) {
if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0)
wpabuf_put_buf(extra_ie, wps_ie);
wpabuf_free(wps_ie);
}
}
......// CONFIG_P2P處理
#endif /* CONFIG_WPS */
return extra_ie;
}
~~~
wps_build_probe_req_ie用于構造WSC IE,讀者可簡單了解一下該函數,相關代碼如下所示。
**wps.c::wps_build_probe_req_ie**
~~~
struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev,
const u8 *uuid, enum wps_request_type req_type,unsigned int num_req_dev_types,
const u8 *req_dev_types)
{
struct wpabuf *ie;
ie = wpabuf_alloc(500);
......
if (wps_build_version(ie) ||wps_build_req_type(ie, req_type) ||
wps_build_config_methods(ie, dev->config_methods) ||wps_build_uuid_e(ie, uuid) ||
wps_build_primary_dev_type(dev, ie) || wps_build_rf_bands(dev, ie) ||
wps_build_assoc_state(NULL, ie) || wps_build_config_error(ie, WPS_CFG_NO_ERROR) ||
wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT) ||
#ifdef CONFIG_WPS2 // WPS2即WSC
wps_build_manufacturer(dev, ie) || wps_build_model_name(dev, ie) ||
wps_build_model_number(dev, ie) || wps_build_dev_name(dev, ie) ||
wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) ||
#endif /* CONFIG_WPS2 */
wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types)
||wps_build_secondary_dev_type(dev, ie)) {
......
// 錯誤處理
}
......
return wps_ie_encapsulate(ie);
}
~~~
最后,WPAS將發送攜帶了WSC IE的Probe Request幀。對于Galaxy Note 2來說,其發送的WSC IE信息可參考圖6-18。
**4、處理掃描結果**
發送掃描請求后,WPAS下一步的工作就是處理搜索到的掃描結果。這部分的流程在4.5.3節掃描結果處理流程中有詳細分析。在該流程中,和WSC相關的工作如下。
* wpa_supplicant_get_scan_results:獲取掃描結果。該函數內部將對搜索到的AP進行排序,它對WSC有特殊處理。
* wpa_supplicant_pick_network:選擇合適的AP作為目標AP。如果使用WSC的話,該函數將優先選擇支持WSC的AP。
下面將分別介紹上述兩個函數中和WSC處理相關的流程。
**①、wpa_supplicant_get_scan_results處理**
代碼如下。
**scan.c::wpa_supplicant_get_scan_results**
~~~
struct wpa_scan_results * wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,struct scan_info *info, int new_scan)
{
......
// 獲取掃描結果
scan_res = wpa_drv_get_scan_results2(wpa_s);
#ifdef CONFIG_WPS
// WPAS當前處于WPS處理過程中,設置排序函數為wpa_scan_result_wps_compar
if (wpas_wps_in_progress(wpa_s)) compar = wpa_scan_result_wps_compar;
#endif /* CONFIG_WPS */
// 利用qsort函數對掃描結果進行升序排序。排序時將使用compar函數將較兩個元素A、B的大小
// compar返回負數,表示A < B,compar返回0,表示A=B,compar返回正數,表示A > B
qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),compar);
......// 更新BSS
return scan_res;
}
struct wpa_scan_results * wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,struct scan_info *info, int new_scan)
{
......
// 獲取掃描結果
scan_res = wpa_drv_get_scan_results2(wpa_s);
#ifdef CONFIG_WPS
// WPAS當前處于WPS處理過程中,設置排序函數為wpa_scan_result_wps_compar
if (wpas_wps_in_progress(wpa_s)) compar = wpa_scan_result_wps_compar;
#endif /* CONFIG_WPS */
// 利用qsort函數對掃描結果進行升序排序。排序時將使用compar函數將較兩個元素A、B的大小
// compar返回負數,表示A < B,compar返回0,表示A=B,compar返回正數,表示A > B
qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),compar);
......// 更新BSS
return scan_res;
}
~~~
由上述代碼可知,當WPAS正處于WPS處理流程中,搜索到的AP將通過qsort以及wpa_scan_result_wps_compar進行排序比較。wpa_scan_result_wps_compar的代碼如下所示。
**scan.c::wpa_scan_result_wps_compar**
~~~
static int wpa_scan_result_wps_compar(const void *a, const void *b)
{
struct wpa_scan_res **_wa = (void *) a;
struct wpa_scan_res **_wb = (void *) b;
struct wpa_scan_res *wa = *_wa;
struct wpa_scan_res *wb = *_wb;
int uses_wps_a, uses_wps_b;
struct wpabuf *wps_a, *wps_b;
int res;
/*
wpa_scan_get_vendor_ie返回值的類型為u8*,它指向wpa_scan_res中指定IE(此處是
WSC IE)所在的內存位置。如果wpa_scan_res中沒有WSC IE,則返回為空。
*/
uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL;
uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL;
// 無線網絡A支持WPS,而B不支持,則返回-1。這樣,在“排座位”的時候,A將排在前面(A < B)
if (uses_wps_a && !uses_wps_b) return -1;
// 無線網絡A不支持WPS,而B支持,則B排在前面(B < A)
if (!uses_wps_a && uses_wps_b) return 1;
// 如果無線網絡A和B均支持WPS,則還需要進一步判斷
if (uses_wps_a && uses_wps_b) {
/*
wpa_scan_get_vendor_ie_multi將從拷貝指定IE的內容復制到一塊新的內存中,該內存地址即
wpa_scan_get_vendor_ie_multi的返回值。
*/
wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE);
wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE);
/*
如果周圍有多個支持WPS的無線網絡,則設置Selected Registrar屬性(而且值為1)的AP
將位于前排。
*/
res = wps_ap_priority_compar(wps_a, wps_b);
wpabuf_free(wps_a); // 釋放wpa_scan_get_vendor_ie_multi創建的新內存
wpabuf_free(wps_b);
if (res)
return res;
}
// 對于沒有WSC支持的AP,其排座順序僅考慮它們的信號強度和質量
if (wb->level == wa->level)
return wb->qual - wa->qual;
return wb->level - wa->level;
}
~~~
根據上面的代碼可知,WSC的AP掃描結果“排座”規則如下。
* 支持WSC功能的AP排在不支持WSC的AP之前。
* 對于兩個同時支持WSC功能的AP來說,Selected Regsitrar值為1的AP排在前面。
* 對于不支持WSC的AP來說,信號強度和質量好的AP排在前面。
當掃描結果排完序后,WPAS的下一步工作就是從眾多搜索到的AP中挑選一個作為目標AP以發起關聯請求。該工作由wpa_supplicant_pick_network完成。
**2、wpa_supplicant_pick_network處理**
wpa_supplicant_pick_nework的代碼比較簡單,如下所示。
**events.c::wpa_supplicant_pick_nework**
~~~
static struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res, struct wpa_ssid **selected_ssid)
{
struct wpa_bss *selected = NULL; int prio;
while (selected == NULL) { // 按照優先級搜索掃描結果
for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
selected = wpa_supplicant_select_bss(wpa_s, scan_res, wpa_s->conf->pssid[prio],
selected_ssid);
if (selected)
break;
}
......// 其他處理
}
return selected;
}
~~~
wpa_supplicant_select_bss內部將通過調用wpa_scan_res_match的函數來選取一個合適的無線網絡。該函數的代碼如下所示。
**events.c::wpa_scan_res_match**
~~~
static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
int i, struct wpa_scan_res *bss,struct wpa_ssid *group)
{
const u8 *ssid_; u8 wpa_ie_len, rsn_ie_len, ssid_len;
int wpa; struct wpa_blacklist *e;
const u8 *ie; struct wpa_ssid *ssid;
ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
ssid_ = ie ? ie + 2 : (u8 *) "";
ssid_len = ie ? ie[1] : 0;
......
for (ssid = group; ssid; ssid = ssid->pnext) {
int check_ssid = wpa ? 1 : (ssid->ssid_len != 0);
......
#ifdef CONFIG_WPS
if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) continue;
/*
通過“WPS_PIN any”命令創建的wpa_ssid還沒有設置ssid。wpas_wps_ssid_wildcard_ok
用于判斷是否需要進行ssid檢查。該函數內部將利用下文代碼中提到的wps_is_addr_authorized函數。
由于筆者測試用的AP僅支持WPS,所以wpas_wps_ssid_wildcard_ok返回非零值。這樣,if條件生效,
check_ssid被設置為0。
*/
if (wpa && ssid->ssid_len == 0 &&
wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) check_ssid = 0;
......
#endif /* CONFIG_WPS */
......// 其他判斷
// 該函數內部先調用wpas_wps_ssid_bss_match函數以判斷是否有合適的AP,如果有則選中它
if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss)) continue;
......// 其他判斷。例如檢查wpa_ssid中的ssid是否匹配搜索結果中的ssid。如果不匹配,則不能選擇該AP
return ssid;
}
return NULL;
}
~~~
直接來看wpas_wps_ssid_bss_match函數,代碼如下所示。
**wpa_supplicant.c::wpas_wps_ssid_bss_match**
~~~
int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,struct wpa_ssid *ssid,
struct wpa_scan_res *bss)
{
struct wpabuf *wps_ie;
if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
return -1;
// 獲取該WSC IE信息
wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
......
// PBC處理
}
// 判斷eap_peer_config設置的identity是否為“WFA-SimpleConfig-Enrollee-1-0”
if (eap_is_wps_pin_enrollee(&ssid->eap)) {
.......
/*
筆者使用的AP沒有包含AuthorizedMACs子屬性,并且該AP也不支持WSC。所以下面這個函數將返回1,
如此,if判斷失敗。讀者可參考圖6-19。
*/
// AP返回的Probe Response幀信息
if (!wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
......
else {
wpa_printf(MSG_DEBUG, " selected based on WPS IE "
"(Authorized MAC or Active PIN)");
}
wpabuf_free(wps_ie);
return 1; // 選中
}
......
return -1;
}
~~~
總之,在周圍空間有很多無線網絡的情況下,筆者測試WSC時使用的AP將會被選中作為目標AP。接下來的流程就和4.5.3節關聯無線網絡處理流程分析的內容一樣,STA將關聯到目標AP。對于非WSC來說,AP和STA將開展4-Way Handshake流程,而對于WSC來說,AP和STA將開展EAP-WSC流程。
馬上來看EAP-WSC處理流程,它也是整個WSC流程的核心內容。
- 前言
- 第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 參考資料說明
- 附錄