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; }