Android Wi-Fi源码分析之wpa_supplicant初始化(二):wpa_supplicant_init中的三个关键点

一. eap_register.c 中的eap_register_methods分析

路径:external/wpa_supplicant_8/wpa_supplicant/eap_register.c

int eap_register_methods(void)
{
    int ret = 0;

#ifdef EAP_MD5 /*作为supplicant端, 编译时将定义EAP_MD5*/
    if (ret == 0)
        ret = eap_peer_md5_register();
#endif /* EAP_MD5 */

#ifdef EAP_TLS
    if (ret == 0)
        ret = eap_peer_tls_register();
#endif /* EAP_TLS */

#ifdef EAP_UNAUTH_TLS
    if (ret == 0)
        ret = eap_peer_unauth_tls_register();
#endif /* EAP_UNAUTH_TLS */

#ifdef EAP_MSCHAPv2
    if (ret == 0)
        ret = eap_peer_mschapv2_register();
#endif /* EAP_MSCHAPv2 */

#ifdef EAP_PEAP
    if (ret == 0)
        ret = eap_peer_peap_register();
#endif /* EAP_PEAP */

#ifdef EAP_TTLS
    if (ret == 0)
        ret = eap_peer_ttls_register();
#endif /* EAP_TTLS */

#ifdef EAP_GTC
    if (ret == 0)
        ret = eap_peer_gtc_register();
#endif /* EAP_GTC */

#ifdef EAP_OTP
    if (ret == 0)
        ret = eap_peer_otp_register();
#endif /* EAP_OTP */

#ifdef EAP_SIM
    if (ret == 0)
        ret = eap_peer_sim_register();
#endif /* EAP_SIM */

#ifdef EAP_LEAP
    if (ret == 0)
        ret = eap_peer_leap_register();
#endif /* EAP_LEAP */

#ifdef EAP_PSK
    if (ret == 0)
        ret = eap_peer_psk_register();
#endif /* EAP_PSK */

#ifdef EAP_AKA
    if (ret == 0)
        ret = eap_peer_aka_register();
#endif /* EAP_AKA */

#ifdef EAP_AKA_PRIME
    if (ret == 0)
        ret = eap_peer_aka_prime_register();
#endif /* EAP_AKA_PRIME */

#ifdef EAP_FAST
    if (ret == 0)
        ret = eap_peer_fast_register();
#endif /* EAP_FAST */

#ifdef EAP_PAX
    if (ret == 0)
        ret = eap_peer_pax_register();
#endif /* EAP_PAX */

#ifdef EAP_SAKE
    if (ret == 0)
        ret = eap_peer_sake_register();
#endif /* EAP_SAKE */

#ifdef EAP_GPSK
    if (ret == 0)
        ret = eap_peer_gpsk_register();
#endif /* EAP_GPSK */

#ifdef EAP_WSC
    if (ret == 0)
        ret = eap_peer_wsc_register();
#endif /* EAP_WSC */

#ifdef EAP_IKEV2
    if (ret == 0)
        ret = eap_peer_ikev2_register();
#endif /* EAP_IKEV2 */

#ifdef EAP_VENDOR_TEST
    if (ret == 0)
        ret = eap_peer_vendor_test_register();
#endif /* EAP_VENDOR_TEST */

#ifdef EAP_TNC
    if (ret == 0)
        ret = eap_peer_tnc_register();
#endif /* EAP_TNC */

#ifdef EAP_PWD
    if (ret == 0)
        ret = eap_peer_pwd_register();
#endif /* EAP_PWD */

#ifdef EAP_EKE
    if (ret == 0)
        ret = eap_peer_eke_register();
#endif /* EAP_EKE */

#ifdef EAP_SERVER_IDENTITY
    if (ret == 0)
        ret = eap_server_identity_register();
#endif /* EAP_SERVER_IDENTITY */

#ifdef EAP_SERVER_MD5/*作为Authenticator端, 编译时将定义EAP_SERVER_MD5*/
    if (ret == 0)
        ret = eap_server_md5_register();
#endif /* EAP_SERVER_MD5 */

#ifdef EAP_SERVER_TLS
    if (ret == 0)
        ret = eap_server_tls_register();
#endif /* EAP_SERVER_TLS */

#ifdef EAP_SERVER_UNAUTH_TLS
    if (ret == 0)
        ret = eap_server_unauth_tls_register();
#endif /* EAP_SERVER_UNAUTH_TLS */

#ifdef EAP_SERVER_MSCHAPV2
    if (ret == 0)
        ret = eap_server_mschapv2_register();
#endif /* EAP_SERVER_MSCHAPV2 */

#ifdef EAP_SERVER_PEAP
    if (ret == 0)
        ret = eap_server_peap_register();
#endif /* EAP_SERVER_PEAP */

#ifdef EAP_SERVER_TLV
    if (ret == 0)
        ret = eap_server_tlv_register();
#endif /* EAP_SERVER_TLV */

#ifdef EAP_SERVER_GTC
    if (ret == 0)
        ret = eap_server_gtc_register();
#endif /* EAP_SERVER_GTC */

#ifdef EAP_SERVER_TTLS
    if (ret == 0)
        ret = eap_server_ttls_register();
#endif /* EAP_SERVER_TTLS */

#ifdef EAP_SERVER_SIM
    if (ret == 0)
        ret = eap_server_sim_register();
#endif /* EAP_SERVER_SIM */

#ifdef EAP_SERVER_AKA
    if (ret == 0)
        ret = eap_server_aka_register();
#endif /* EAP_SERVER_AKA */

#ifdef EAP_SERVER_AKA_PRIME
    if (ret == 0)
        ret = eap_server_aka_prime_register();
#endif /* EAP_SERVER_AKA_PRIME */

#ifdef EAP_SERVER_PAX
    if (ret == 0)
        ret = eap_server_pax_register();
#endif /* EAP_SERVER_PAX */

#ifdef EAP_SERVER_PSK
    if (ret == 0)
        ret = eap_server_psk_register();
#endif /* EAP_SERVER_PSK */

#ifdef EAP_SERVER_SAKE
    if (ret == 0)
        ret = eap_server_sake_register();
#endif /* EAP_SERVER_SAKE */

#ifdef EAP_SERVER_GPSK
    if (ret == 0)
        ret = eap_server_gpsk_register();
#endif /* EAP_SERVER_GPSK */

#ifdef EAP_SERVER_VENDOR_TEST
    if (ret == 0)
        ret = eap_server_vendor_test_register();
#endif /* EAP_SERVER_VENDOR_TEST */

#ifdef EAP_SERVER_FAST
    if (ret == 0)
        ret = eap_server_fast_register();
#endif /* EAP_SERVER_FAST */

#ifdef EAP_SERVER_WSC
    if (ret == 0)
        ret = eap_server_wsc_register();
#endif /* EAP_SERVER_WSC */

#ifdef EAP_SERVER_IKEV2
    if (ret == 0)
        ret = eap_server_ikev2_register();
#endif /* EAP_SERVER_IKEV2 */

#ifdef EAP_SERVER_TNC
    if (ret == 0)
        ret = eap_server_tnc_register();
#endif /* EAP_SERVER_TNC */

#ifdef EAP_SERVER_PWD
    if (ret == 0)
        ret = eap_server_pwd_register();
#endif /* EAP_SERVER_PWD */

    return ret;
}

eap_register_methods函数将根据编译配置项来注册所需的eap_methods . MD5身份验证方法对应的注册函数是eap_peer_md5_register, 该函数填充一个名为eap_method的结构体.
路径为:external/wpa_supplicant/8/src/eap_server/eap_i.h
该结构体与RFC4137有较大关系.

二. eloop_init函数及event_loop模块

eloop_init函数仅初始化了wpa_supplicant中事件驱动的核心数据结构体eloop_data .
事件注册API函数:
路径为:\external\wpa_supplicant_8\src\utils\eloop.h

 /* 注册socket事件处理函数, 具体是哪些事件(只能是读, 写或异常)由tybe参数决定
 */
int eloop_register_sock(int sock, eloop_event_type type,
            eloop_sock_handler handler,
            void *eloop_data, void *user_data);
...
 /* 注册socket事件处理函数, 具体是哪些事件(只能是读, 写或异常)由tybe参数决定
 */
int eloop_register_sock(int sock, eloop_event_type type,
            eloop_sock_handler handler,
            void *eloop_data, void *user_data);

...
 /* 注册超时处理函数 */
int eloop_register_timeout(unsigned int secs, unsigned int usecs,
               eloop_timeout_handler handler,
               void *eloop_data, void *user_data);
...
 /* 注册信号处理函数, 具体要处理的信号由sig参数指定 */
int eloop_register_signal(int sig, eloop_signal_handler handler,
              void *user_data);



下面来看wpa_supplicant事件驱动机制的运行原理, 代码在eloop_run函数中:
路径为:external\wpa_supplicant_8\src\utils\eloop.c

void eloop_run(void)
{
#ifdef CONFIG_ELOOP_POLL
    int num_poll_fds;
    int timeout_ms = 0;
#else /* CONFIG_ELOOP_POLL */
    fd_set *rfds, *wfds, *efds;
    struct timeval _tv;
#endif /* CONFIG_ELOOP_POLL */
    int res;
    struct os_time tv, now;

#ifndef CONFIG_ELOOP_POLL
    rfds = os_malloc(sizeof(*rfds));
    wfds = os_malloc(sizeof(*wfds));
    efds = os_malloc(sizeof(*efds));
    if (rfds == NULL || wfds == NULL || efds == NULL)
        goto out;
#endif /* CONFIG_ELOOP_POLL */

    /*事件驱动循环*/
    while (!eloop.terminate &&
           (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
        eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
        struct eloop_timeout *timeout;
        /*判断是否有超时事件需要等待*/
        timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
                    list);
        if (timeout) {
            os_get_time(&now);
            if (os_time_before(&now, &timeout->time))
                os_time_sub(&timeout->time, &now, &tv);
            else
                tv.sec = tv.usec = 0;
#ifdef CONFIG_ELOOP_POLL
            timeout_ms = tv.sec * 1000 + tv.usec / 1000;
#else /* CONFIG_ELOOP_POLL */
            _tv.tv_sec = tv.sec;
            _tv.tv_usec = tv.usec;
#endif /* CONFIG_ELOOP_POLL */
        }

#ifdef CONFIG_ELOOP_POLL
        num_poll_fds = eloop_sock_table_set_fds(
            &eloop.readers, &eloop.writers, &eloop.exceptions,
            eloop.pollfds, eloop.pollfds_map,
            eloop.max_pollfd_map);
        res = poll(eloop.pollfds, num_poll_fds,
               timeout ? timeout_ms : -1);

        if (res < 0 && errno != EINTR && errno != 0) {
            perror("poll");
            goto out;
        }
#else /* CONFIG_ELOOP_POLL 将外界设置的读事件添加到对应的fd_set中*/
        eloop_sock_table_set_fds(&eloop.readers, rfds);
        eloop_sock_table_set_fds(&eloop.writers, wfds);
        eloop_sock_table_set_fds(&eloop.exceptions, efds);
        res = select(eloop.max_sock + 1, rfds, wfds, efds,
                 timeout ? &_tv : NULL);/*调用select*/
        if (res < 0 && errno != EINTR && errno != 0) {/*错误处理*/
            perror("select");
            goto out;
        }
#endif /* CONFIG_ELOOP_POLL */
        eloop_process_pending_signals();/*先处理信号事件*/

        /* 判断是否有超时事件发生 check if some registered timeouts have occurred */
        timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
                    list);
        if (timeout) {
            os_get_time(&now);
            if (!os_time_before(&now, &timeout->time)) {
                void *eloop_data = timeout->eloop_data;
                void *user_data = timeout->user_data;
                eloop_timeout_handler handler =
                    timeout->handler;
                eloop_remove_timeout(timeout);/*注意, 超时事件只执行一次*/
                handler(eloop_data, user_data);/*处理超时事件*/
            }

        }

        if (res <= 0)
            continue;

#ifdef CONFIG_ELOOP_POLL
        eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
                      &eloop.exceptions, eloop.pollfds_map,
                      eloop.max_pollfd_map);
#else /* CONFIG_ELOOP_POLL 处理读/写/异常事件 */
        eloop_sock_table_dispatch(&eloop.readers, rfds);
        eloop_sock_table_dispatch(&eloop.writers, wfds);
        eloop_sock_table_dispatch(&eloop.exceptions, efds);
#endif /* CONFIG_ELOOP_POLL */
    }

    eloop.terminate = 0;
out:
#ifndef CONFIG_ELOOP_POLL
    os_free(rfds);
    os_free(wfds);
    os_free(efds);
#endif /* CONFIG_ELOOP_POLL */
    return;
}

eloop_run中的while循环是wpa_supplicant进程的运行中枢.

三. wpa_driver_ops数组和driver i/f模块

路径:external\wpa_supplicant_8\src\drivers\drivers.c

struct wpa_driver_ops *wpa_drivers[] =
{
#ifdef CONFIG_DRIVER_NL80211
    &wpa_driver_nl80211_ops,
#endif /* CONFIG_DRIVER_NL80211 */
#ifdef CONFIG_DRIVER_WEXT
    &wpa_driver_wext_ops,
#endif /* CONFIG_DRIVER_WEXT */
#ifdef CONFIG_DRIVER_HOSTAP
    &wpa_driver_hostap_ops,
#endif /* CONFIG_DRIVER_HOSTAP */
#ifdef CONFIG_DRIVER_MADWIFI
    &wpa_driver_madwifi_ops,
#endif /* CONFIG_DRIVER_MADWIFI */
#ifdef CONFIG_DRIVER_BSD
    &wpa_driver_bsd_ops,
#endif /* CONFIG_DRIVER_BSD */
#ifdef CONFIG_DRIVER_OPENBSD
    &wpa_driver_openbsd_ops,
#endif /* CONFIG_DRIVER_OPENBSD */
#ifdef CONFIG_DRIVER_NDIS
    &wpa_driver_ndis_ops,
#endif /* CONFIG_DRIVER_NDIS */
#ifdef CONFIG_DRIVER_WIRED
    &wpa_driver_wired_ops,
#endif /* CONFIG_DRIVER_WIRED */
#ifdef CONFIG_DRIVER_TEST
    &wpa_driver_test_ops,
#endif /* CONFIG_DRIVER_TEST */
#ifdef CONFIG_DRIVER_ROBOSWITCH
    &wpa_driver_roboswitch_ops,
#endif /* CONFIG_DRIVER_ROBOSWITCH */
#ifdef CONFIG_DRIVER_ATHEROS
    &wpa_driver_atheros_ops,
#endif /* CONFIG_DRIVER_ATHEROS */
#ifdef CONFIG_DRIVER_NONE
    &wpa_driver_none_ops,
#endif /* CONFIG_DRIVER_NONE */
    NULL
};

wpa_driver_ops结构体是driver i/f模块的核心数据结构, 其内部是通过定义指针的方法使wpa_supplicant与上层的使用者和具体的driver相隔离.该数组包含多少个driver对象由编译控制选项来控制(如宏:CONFIG_DRIVER_NL80211), 可以在android.cfg中修改.
路径为:external\wpa_supplicant_8\src\drivers\driver_nl80211.c



const struct wpa_driver_ops wpa_driver_nl80211_ops = { .name = "nl80211",/*driver wrapper的名称*/ .desc = "Linux nl80211/cfg80211",/*描述信息*/ .get_bssid = wpa_driver_nl80211_get_bssid,/*获取bssid*/ .get_ssid = wpa_driver_nl80211_get_ssid, .set_key = driver_nl80211_set_key, .scan2 = driver_nl80211_scan2,/*扫描函数*/ .sched_scan = wpa_driver_nl80211_sched_scan, .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan, .get_scan_results2 = wpa_driver_nl80211_get_scan_results,/*获取扫描结果*/ .deauthenticate = driver_nl80211_deauthenticate, .authenticate = driver_nl80211_authenticate,/*触发authenticate操作*/ .associate = wpa_driver_nl80211_associate,/*触发associate操作*/ /* driver wrapper全局变量初始化函数, 该函数的返回值保存在wpa_global成员 * 变量drv_pri数组中*/ .global_init = nl80211_global_init, .global_deinit = nl80211_global_deinit, .init2 = wpa_driver_nl80211_init,/*driver wrapper初始化函数*/ .deinit = driver_nl80211_deinit, .get_capa = wpa_driver_nl80211_get_capa, .set_operstate = wpa_driver_nl80211_set_operstate, .set_supp_port = wpa_driver_nl80211_set_supp_port, .set_country = wpa_driver_nl80211_set_country, .set_ap = wpa_driver_nl80211_set_ap, .set_acl = wpa_driver_nl80211_set_acl, .if_add = wpa_driver_nl80211_if_add, .if_remove = driver_nl80211_if_remove, .send_mlme = driver_nl80211_send_mlme, .get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data, .sta_add = wpa_driver_nl80211_sta_add, .sta_remove = driver_nl80211_sta_remove, .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol, .sta_set_flags = wpa_driver_nl80211_sta_set_flags, #ifdef HOSTAPD .hapd_init = i802_init, .hapd_deinit = i802_deinit, .set_wds_sta = i802_set_wds_sta, #endif /* HOSTAPD */ #if defined(HOSTAPD) || defined(CONFIG_AP) .get_seqnum = i802_get_seqnum, .flush = i802_flush, .get_inact_sec = i802_get_inact_sec, .sta_clear_stats = i802_sta_clear_stats, .set_rts = i802_set_rts, .set_frag = i802_set_frag, .set_tx_queue_params = i802_set_tx_queue_params, .set_sta_vlan = driver_nl80211_set_sta_vlan, .sta_deauth = i802_sta_deauth, .sta_disassoc = i802_sta_disassoc, #endif /* HOSTAPD || CONFIG_AP */ .read_sta_data = driver_nl80211_read_sta_data, .set_freq = i802_set_freq, .send_action = driver_nl80211_send_action, .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait, .remain_on_channel = wpa_driver_nl80211_remain_on_channel, .cancel_remain_on_channel = wpa_driver_nl80211_cancel_remain_on_channel, .probe_req_report = driver_nl80211_probe_req_report, .deinit_ap = wpa_driver_nl80211_deinit_ap, .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli, .resume = wpa_driver_nl80211_resume, .send_ft_action = nl80211_send_ft_action, .signal_monitor = nl80211_signal_monitor, .signal_poll = nl80211_signal_poll, .send_frame = nl80211_send_frame, .shared_freq = wpa_driver_nl80211_shared_freq, .set_param = nl80211_set_param, .get_radio_name = nl80211_get_radio_name, .add_pmkid = nl80211_add_pmkid, .remove_pmkid = nl80211_remove_pmkid, .flush_pmkid = nl80211_flush_pmkid, .set_rekey_info = nl80211_set_rekey_info, .poll_client = nl80211_poll_client, .set_p2p_powersave = nl80211_set_p2p_powersave, .start_dfs_cac = nl80211_start_radar_detection, .stop_ap = wpa_driver_nl80211_stop_ap, #ifdef CONFIG_TDLS .send_tdls_mgmt = nl80211_send_tdls_mgmt, .tdls_oper = nl80211_tdls_oper, #endif /* CONFIG_TDLS */ .update_ft_ies = wpa_driver_nl80211_update_ft_ies, .get_mac_addr = wpa_driver_nl80211_get_macaddr, .get_survey = wpa_driver_nl80211_get_survey, #ifdef ANDROID_P2P .set_noa = wpa_driver_set_p2p_noa, .get_noa = wpa_driver_get_p2p_noa, .set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie, #endif #ifdef ANDROID /*Android平台在这里; 该函数用于处理和具体驱动相关的命令*/ .driver_cmd = wpa_driver_nl80211_driver_cmd, #endif }; 

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/u013256622/article/details/72912096
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞