Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android wpa_supplicant源碼分析–連接AP過程

Android wpa_supplicant源碼分析–連接AP過程

編輯:關於Android編程

連接網絡過程

STA連接AP的過程可以參考該文章,http://support.huawei.com/ecommunity/bbs/10232527.html

STA需要認證後才可以接入AP,認證過程分為鏈路認證(associate)和接入認證(authentication),根據AP的加密方式 associate 和 authentication采用的認證方式不同。
上述網頁中列出了各種加密方式的認證方式。
這裡寫圖片描述vc6qwP2jrL2yveJ3cGFfc3VwcGxpY2FudMGsvdNBULXEuf2zzDwvcD4NCjxoMSBpZD0="1鏈路認證associate過程">1、鏈路認證(associate)過程

LOG:
wpa_supplicant: wlan0: State: SCANNING -> ASSOCIATING
wpa_supplicant: wlan0: State: ASSOCIATING -> ASSOCIATED

wpa_supplicant接收到上層命令由掃描過程變為關聯過程,向指定的AP發送 ASSOC 幀,由於此處的認證方式為open,AP在接收到STA的幀後,直接回復STA關聯成功。

1.1 添加associate的radio_work

//選擇網絡(已經在conf中保存), 通過id選取,也可以傳入 “any” 後續還可以加入頻率的設置" freq="
os_strncmp(buf, "SELECT_NETWORK ", 15)
static int wpa_supplicant_ctrl_iface_select_network(struct wpa_supplicant *wpa_s, char *cmd)
{
    //從conf中選取ssid網絡
    struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, id);

    //選擇網絡
    wpa_supplicant_select_network(wpa_s, ssid);
    {
        //太狠了,把conf文件中的其他ssid全部設置disable=1
        for (other_ssid = wpa_s->conf->ssid; other_ssid; other_ssid = other_ssid->next)
            other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;

        wpa_s->current_ssid = ssid;
        wpa_s->reassociate = 1;

        //快速連接,select 的ssid 已經設置為 wpa_s->current_ssid
        wpa_supplicant_fast_associate(wpa_s)
            //直接調用,從掃描結果中選取要連接的bss網絡
            wpas_select_network_from_last_scan(wpa_s, 0, 1)
            {
                //返回要連接的bss網絡(scan), ssid返回conf中的ssid
                struct wpa_bss *selected = wpa_supplicant_pick_network(wpa_s,struct wpa_ssid &ssid(null));
                {
                    //根據priority的優先級匹配bss, 不合適的conf中的ssid網絡已經被disable,不會選取
                    //返回的select 就是要 連接的bss 網絡
                    for (prio = 0; prio < wpa_s->conf->num_prio; prio++)
                        selected = wpa_supplicant_select_bss(wpa_s, wpa_s->conf->pssid[prio], selected_ssid, 0);
                }

                //連接選取的網絡 關聯所需的網絡, 
                //selected-----要連接的bss網絡, ssid----conf中保存的ssid
                if (wpa_supplicant_connect(wpa_s, selected, ssid) < 0)
                    //打了句log就調用關聯函數了,“Request association with ” 這句log挺常見的
                    wpa_supplicant_associate(wpa_s, selected, ssid);
                    {
                        //一個ssid有5中模式,手機連接某個網絡時,mode為 
                        * 0 = infrastructure (Managed) mode, i.e., associate with an AP.
                        * 1 = IBSS (ad-hoc, peer-to-peer)
                        * 2 = AP (access point)
                        * 3 = P2P Group Owner (can be set in the configuration file)
                        * 4 = P2P Group Formation (used internally; not in configuration

                        //將wpas_start_assoc_cb 添加到 radio work中
                        if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1, wpas_start_assoc_cb, cwork) < 0)
                    }

            }
    }
}

1.2 通過驅動發出associate 幀

//真正的連接過程
static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
{
    //認證方法
    int algs = WPA_AUTH_ALG_OPEN;
    //關聯的參數
    struct wpa_driver_associate_params params;

    //關聯所需要的ie域
    u8 wpa_ie[200];
    size_t wpa_ie_len;
    //關聯所需要的ie域,先清除一下
    wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);

    //根據key_mgmt中規定的認證方式,設置參數
    //在conf文件中的key_mgmt在wpa_config_parse_key_mgmt()中會解析成相應的值

    //判斷bss是是夠支持wpa
    if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt))
    {
        //設置相關的wpa_ie
        if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_ie, &wpa_ie_len))
    }
    //判斷bss是否支持 8021x
    else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss && wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)){}

    //判斷bss是否支持WPS
    else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS){}

    //判斷bss是夠為open的網絡
    if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA){}

    //設置wpa_s的狀態為 正在關聯
    wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);


    //填充關聯參數    
    params.wpa_ie = wpa_ie;
    。。。
    params.key_mgmt_suite = wpa_s->key_mgmt;

    //以wpa-psk的加密方式為例,psk密碼最高為32位
    params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
         params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
        params.passphrase = ssid->passphrase;
        if (ssid->psk_set)
            params.psk = ssid->psk;
    }

    //調用驅動的關聯方法,傳入之前設置好的參數params
    ret = wpa_drv_associate(wpa_s, ¶ms);

    //關聯的超時處理,如果超時後還沒有關聯,那就會調用wpa_supplicant_timeout方法,例如將該bss加入 blacklist
    wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
}



//驅動的關聯函數
wpa_s->driver->associate(wpa_s->drv_priv, params)
static int wpa_driver_nl80211_associate(void *priv, struct wpa_driver_associate_params *params)
{
    //進入判斷,直接調用鏈接的函數
    if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)){
        return wpa_driver_nl80211_connect(drv, params);
        {
            //調用發送關聯幀的函數
            int ret = wpa_driver_nl80211_try_connect(drv, params);
            {
                //想組合好的幀發送到驅動中
                ret = send_and_recv_msgs(drv, msg, NULL, NULL);
                wpa_printf(MSG_DEBUG, "nl80211: Connect request send successfully");
            }
        }
    }
}

1.3 關聯成功

//接收到驅動上傳的ASSOC的event

mlme_event_connect(drv, cmd,
                   tb[NL80211_ATTR_STATUS_CODE],
                   tb[NL80211_ATTR_MAC],
                   tb[NL80211_ATTR_REQ_IE],
                   tb[NL80211_ATTR_RESP_IE]);
{
    //調用event處理函數
    wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
    {
        wpa_supplicant_event_assoc(wpa_s, data);
        {
            //設置wpa_s的狀態
            wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);

            /*設置超時10s,等待AP發送 EAPOL包 Timeout for receiving the first EAPOL packet */
            wpa_supplicant_req_auth_timeout(wpa_s, 10, 0);
        }
    }
}

2、接入認證(authentication)(WPA-PSK為例)

采用PSK認證時,需要與AP交換4次信息,生成需要的密鑰,俗稱4次握手
https://en.wikipedia.org/wiki/IEEE_802.11i-2004
wiki圖片:
這裡寫圖片描述

對用的相應的log為

wpa_supplicant: wlan0: State: ASSOCIATED -> 4WAY_HANDSHAKE
wpa_supplicant: wlan0: State: 4WAY_HANDSHAKE -> 4WAY_HANDSHAKE
wpa_supplicant: wlan0: State: 4WAY_HANDSHAKE -> GROUP_HANDSHAKE
wpa_supplicant: wlan0: State: GROUP_HANDSHAKE -> COMPLETED

4次握手的第一幀是由AP發起的,wpa_supplicant在收到後,會根據幀中的信息,判定需要的加密方式,並采用相應的處理函數。
wpa_supplicant支持的加密方式如下圖
圖片:

這裡寫圖片描述

L2_packet的4次握手過程:

//處理接收到 L2 EAPOL FRAME 用作auth過程
wpa_supplicant_rx_eapol()
{
    //打印一些log
    wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
    //做一些判斷,然後通過 eapol_sm_rx_eapol 處理接收到 frame(8021x認證的會通過此路徑)
    if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
        eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)

    //wpa加密方式的通過此路徑
    if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
        wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
        {
            //這個應該會設置 wap的狀態,具體還不他清楚。。
            eapol_sm_notify_lower_layer_success(sm->eapol, 0);
            //依次調用握手處理函數 共4次,第一次 /* 1/4 4-Way Handshake */
            wpa_supplicant_process_1_of_4(sm, src_addr, key, ver, key_data, key_data_len);
            {
                //發送第二次握手信息到AP
                wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, kde, kde_len, ptk))
            }

            //再次受到L2 packet 處理/* 3/4 4-Way Handshake */
            wpa_supplicant_process_3_of_4(sm, key, ver, key_data, key_data_len);
            {
                //發送第四次握手
                wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,&sm->ptk))
                //設置wpa_s狀態  wlan0: State: 4WAY_HANDSHAKE -> GROUP_HANDSHAKE
                wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
                //這一部分的代碼變化還是挺大的,4.4的和6.0就不一樣 
                //這裡會設置狀態為 complete
                wpa_supplicant_key_neg_complete(sm, sm->bssid, key_info & WPA_KEY_INFO_SECURE);

                //設置rekey的offload,具體由驅動還是芯片處理,需要繼續看
                wpa_sm_set_rekey_offload(sm);               

                //至此整個連接過程完畢
            }
        }
}

3 流程圖

這裡寫圖片描述

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved