路径: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函数仅初始化了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进程的运行中枢.
路径: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 };