wpa_supplicant初始化關鍵函數

1. wpa_supplicant_init()網絡

初始化成功後,返回的wpa_global指針可用於添加刪除接口,最後,deinit wpa_supplicant。數據結構

傳入的參數爲命令行輸入的接口無關的參數wpa_params。dom

1、main() 
一、 wpa_supplicant的入口函數在external\wpa_supplicant\main.c裏面,入口main()。 
 
二、 main()函數裏申明的結構體中,socket

        wpa_global爲最重要的結構體,是wpa_supplicant的全局數據結構;ide

        wpa_interface結構體是wpa_supplicant_add_iface()函數爲wpa_supplicant增長網絡接口時要用到的接口配置選項,該函數的具體功能在函數申明(external\wpa_supplicant\wpa_supplicant.c)時有具體的解釋;函數

        wpa_params結構體是wpa_supplicant_init()函數爲初始化wpa_supplicant時要使用的參數,該函數的具體功能在函數申明(external\wpa_supplicant\wpa_supplicant.c)時有具體的解釋。oop

三、 main()函數主要作了四個工做: 
    a、根據命令行參數設置wpa_params結構體; 
    b、調用wpa_supplicant_init()函數初始化wpa_supplicant; 
    c、調用wpa_supplicant_add_iface()函數爲wpa_supplicant增長網絡接口;spa

    d、調用wpa_supplicant_run()讓wpa_supplicant跑起來。命令行

2、wpa_supplicant_init () 
一、 該函數位於external\wpa_supplicant\wpa_supplicant.c文件下,用於初始化wpa_supplicant。 debug

二、 調用eap_peer_register_methods()註冊eap方法,EAP(Extensible Authentication Protocol)是可擴展身份驗證協議的簡稱。代碼中的解釋爲:This function is called at program initialization to register all EAP peer methods that were linked in statically。 
三、 經過main()函數中傳入的參數初始化global結構體。

四、 調用eloop_init()將初始化好的global結構體傳給eloop結構體,該結構體是一個全局變量,存儲了不少event loop循環須要使用的信息。

五、 調用wpa_supplicant_global_ctrl_iface_init()函數創建global控制接口,該函數創建一個socket,而後與初始化global結構體時給出的params.ctrl.interface參數進行鏈接,鏈接成功以後註冊到eloop循環中,從而創建兩個進程之間的通訊。這是wpa_supplicant與外部進程創建的第一個通訊通道,主要用於增長或刪除網絡接口。 
六、 調用wpa_supplicant_dbus_ctrl_iface_init()函數創建dbus進程間通信接口,該函數首先經過調用dbus_bus_get()函數得到系統總線引用,而後調用integrate_with_eloop()告訴dbus 設置eloop循環相關的處理函數(好比增長刪除之類,dbus的socket也是在這些處理函數中創建的),以後調用dbus_connection_register_object_path()函數爲dbus接口註冊消息處理函數,最後調用dbus_bus_request_name()函數將該dbus註冊爲消息服務bus。函數在退出以前經過調用eloop_register_timeout()函數將處理函數添加進入eloop循環,注意這個註冊是採用timeout的形式,緣由多是不想太早初始化這個dbus,由於這個時候eloop尚未啓動,若是過早初始化,會致使別的進程使用,會出問題。這是wpa_supplicant與外部進程創建的第二個通訊通道,主要用於處理dbus通訊。

七、 調用wpa_supplicant_daemon()函數將該守護進程的pid寫入pid_file中。

3、wpa_supplicant_add_iface() 
一、該函數爲wpa_supplicant增長網絡接口,而且支持熱插拔。 
二、調用wpa_supplicant_init_iface()函數: 

    a、調用wpa_supplicant_set_driver()函數設置驅動函數;

    b、讀取配置文件信息,保存到結構體wpa_s->confname中,再分析配置參數,將分析結果保存到wpa_s->conf中; 

    c、檢查命令行參數中是否設置了wpa_s->conf,若是設置,就用命令行設置的參數覆蓋以上b中用配置文件設置的參數;

    d、拷貝網絡接口名稱和橋接口名稱到wpa_s結構體。 
三、調用wpa_supplicant_init_iface2()函數: 
    a、調用wpa_supplicant_init_eapol()函數初始化eapol,該認證採用狀態機的風格,在eloop循環中,設置定時器來定時更新eapol的認證狀態,實現接入網絡的認證;

    b、調用wpa_drv_init()函數初始化網絡驅動,該函數進一步調用在上述中由wpa_supplicant_set_driver()函數加載的驅動的.init函數,因爲wpa_supplicant須要和內核進行socket通訊,這個socket的創建和註冊到eloop循環就在這個地方;這是wpa_supplicant與外部進程創建的第三個通訊通道,主要用於與kernel交換數據; 

    c、調用wpa_drv_get_ifname()函數得到網絡接口名稱; 

    d、調用wpa_supplicant_init_wpa()函數初始化wpa;

    e、調用wpa_supplicant_driver_init()函數初始化驅動接口,該函數會調用l2_packet_init()函數創建與802.1x進行報文通信的socket,並註冊到eloop循環中,這是wpa_supplicant與外部進程創建的第四個通訊通道,主要用於處理802.1x報文;最後調用wpa_supplicant_req_scan()函數在指定時間以後發起scan; 

    f、調用wpa_supplicant_ctrl_iface_init()函數初始化控制接口,該函數創建與HAL層通訊的socket,並註冊到eloop循環,這是wpa_supplicant與外部進程創建的第五個通訊通道,主要用於接受WIFI HAL層的控制。  
4、wpa_supplicant_run() 
一、該函數主要功能是啓動eloop循環;

二、註冊結束函數和從新配置函數;

三、調用eloop_run()進入循環,該循環經過select()機制,檢測socket信號量並處理,並處理定時事件。

/**
 * wpa_supplicant_init - Initialize %wpa_supplicant
 * @params: Parameters for %wpa_supplicant
 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
 *
 * This function is used to initialize %wpa_supplicant. After successful
 * initialization, the returned data pointer can be used to add and remove
 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
 */
struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
{
    struct wpa_global *global;
    int ret, i;
……
#ifndef CONFIG_NO_WPA_MSG
    wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);// 註冊回調函數,獲取當前ifname
#endif /* CONFIG_NO_WPA_MSG */

……
    ret = eap_register_methods();// 註冊eap(Extensible Authentication Protocol)方法。
    
    global = os_zalloc(sizeof(*global));
    dl_list_init(&global->p2p_srv_bonjour);
    dl_list_init(&global->p2p_srv_upnp);
    global->params.daemonize = params->daemonize;
    global->params.wait_for_monitor = params->wait_for_monitor;
    global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
    global->params.pid_file = os_strdup(params->pid_file);
    global->params.ctrl_interface = os_strdup(params->ctrl_interface);
    global->params.override_driver = os_strdup(params->override_driver);
    global->params.override_ctrl_interface = os_strdup(params->override_ctrl_interface);
    wpa_debug_level = global->params.wpa_debug_level = params->wpa_debug_level;
    wpa_debug_show_keys = global->params.wpa_debug_show_keys = params->wpa_debug_show_keys;
    wpa_debug_timestamp = global->params.wpa_debug_timestamp = params->wpa_debug_timestamp;

    if (eloop_init()) {
        wpa_printf(MSG_ERROR, "Failed to initialize event loop");
        wpa_supplicant_deinit(global);
        return NULL;
    }

    random_init(params->entropy_file);

    global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);// 
    if (global->ctrl_iface == NULL) {
        wpa_supplicant_deinit(global);
        return NULL;
    }

    if (wpas_notify_supplicant_initialized(global)) {
        wpa_supplicant_deinit(global);
        return NULL;
    }

    for (i = 0; wpa_drivers[i]; i++)
        global->drv_count++;
    if (global->drv_count == 0) {
        wpa_printf(MSG_ERROR, "No drivers enabled");
        wpa_supplicant_deinit(global);
        return NULL;
    }
    global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
    if (global->drv_priv == NULL) {
        wpa_supplicant_deinit(global);
        return NULL;
    }

#ifdef CONFIG_WIFI_DISPLAY
    if (wifi_display_init(global) < 0) {
        wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
        wpa_supplicant_deinit(global);
        return NULL;
    }
#endif /* CONFIG_WIFI_DISPLAY */

    return global;
}
相關文章
相關標籤/搜索