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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值