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