Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程
来源:互联网 发布:鼎金网络投教中心 编辑:程序博客网 时间:2024/04/24 15:20
Android系统中,wpa_supplicant启动是通过“setprop ctrl.start wpa_supplicant”来触发init进程去fork一个子进程来完成的。wpa_supplicant在init配置文件中被定义为一个service。
- service wpa_supplicant /system/bin/wpa_supplicant \
- -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
- -I/system/etc/wifi/wpa_supplicant_overlay.conf \
- -O/data/misc/wifi/sockets \
- -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0
- # we will start as root and wpa_supplicant will switch to user wifi
- # after setting up the capabilities required for WEXT
- # user wifi
- # group wifi inet keystore
- class main
- socket wpa_wlan0 dgram 660 wifi wifi
- disabled
- oneshot
- ctrl_interface=/data/misc/wifi/sockets
- driver_param=use_p2p_group_interface=1p2p_device=1
- update_config=1
- device_name=********
- manufacturer=BROADCOM
- model_name=*********
- model_number=*********
- serial_number=
- device_type=10-0050F204-5
- config_methods=physical_display virtual_push_button
- p2p_listen_reg_class=81
- p2p_listen_channel=11
- p2p_oper_reg_class=81
- p2p_oper_channel=11
- p2p_ssid_postfix=-Android_7006
- persistent_reconnect=1
- network={
- ssid="AP_5D34E3"
- psk="12345678"
- key_mgmt=WPA-PSK
- priority=1
- }
- network={
- ssid="Android-02"
- psk="android.com"
- key_mgmt=WPA-PSK
- priority=2
- }
(1)ctrl_interface知名控制接口Unix域socket的文件名。
(2)update_config表示如果wpa_supplicant运行过程中修改了配置信息,则需要把它们保存到此wpa_supplicant文件中。
(3)从device_name到config_methods都和wpa_supplicant设置有关。
(4)p2p等选项和WiFi P2P有关。
(5)wpa_supplicant运行过程中得到的无线网络信息都会通过”network“配置项保存到配置文件中。如果该信息完整,一旦wpa_supplicant找到该无线网络就会尝试用保存的信息去加入它。(这也是手机能自动加入周围某个曾经的路过的无线网络的原因)。
(6)network项包括的内容比较多。network项展示了该无线网络的ssid、密钥管理方法(key management)、身份认证方法及密码等信息。network中的priority表示无线网络的优先级。其作用是,如果同时存在多个可用的无线网络,wpa_supplicant有限选择priority搞得那一个。
main函数分析[-->main.c::main]
- int main(int argc, char *argv[])
- {
- int c, i;
- struct wpa_interface *ifaces, *iface;
- int iface_count, exitcode = -1;
- struct wpa_params params;
- struct wpa_global *global;
- if (os_program_init())
- return -1;
- os_memset(¶ms, 0, sizeof(params));
- params.wpa_debug_level = MSG_INFO;
- iface = ifaces = os_zalloc(sizeof(struct wpa_interface));
- if (ifaces == NULL)
- return -1;
- iface_count = 1;
- wpa_supplicant_fd_workaround(1); //输入输出重定向到/dev/null设备
- for (;;) {
- c = getopt(argc, argv,
- "b:Bc:C:D:de:f:g:G:hi:I:KLNo:O:p:P:qsTtuvW");
- if (c < 0)
- break;
- switch (c) {
- case 'b':
- iface->bridge_ifname = optarg;
- break;
- case 'B':
- params.daemonize++;
- break;
- case 'c':
- iface->confname = optarg; //指定配置文件名。注意,该参数赋值给了wpa_interface中的变量
- break;
- case 'C':
- iface->ctrl_interface = optarg;
- break;
- case 'D':
- iface->driver = optarg; //指定driver名称。注意,该参数赋值给了wpa_interface中的变量
- break;
- case 'd':
- #ifdef CONFIG_NO_STDOUT_DEBUG
- printf("Debugging disabled with "
- "CONFIG_NO_STDOUT_DEBUG=y build time "
- "option.\n");
- goto out;
- #else /* CONFIG_NO_STDOUT_DEBUG */
- params.wpa_debug_level--;
- break;
- #endif /* CONFIG_NO_STDOUT_DEBUG */
- case 'e':
- params.entropy_file = optarg; //制定初始随机数文件,用于后续随机数的生成
- break;
- #ifdef CONFIG_DEBUG_FILE
- case 'f':
- params.wpa_debug_file_path = optarg;
- break;
- #endif /* CONFIG_DEBUG_FILE */
- case 'g':
- params.ctrl_interface = optarg;
- break;
- case 'G':
- params.ctrl_interface_group = optarg;
- break;
- case 'h':
- usage();
- exitcode = 0;
- goto out;
- case 'i':
- iface->ifname = optarg; //指定网络设备接口名,本例是"wlan0"
- break;
- case 'I':
- iface->confanother = optarg;
- break;
- case 'K':
- params.wpa_debug_show_keys++;
- break;
- case 'L':
- license();
- exitcode = 0;
- goto out;
- case 'o':
- params.override_driver = optarg;
- break;
- case 'O':
- params.override_ctrl_interface = optarg;
- break;
- case 'p':
- iface->driver_param = optarg;
- break;
- case 'P':
- os_free(params.pid_file);
- params.pid_file = os_rel2abs_path(optarg);
- break;
- case 'q':
- params.wpa_debug_level++;
- break;
- #ifdef CONFIG_DEBUG_SYSLOG
- case 's':
- params.wpa_debug_syslog++;
- break;
- #endif /* CONFIG_DEBUG_SYSLOG */
- #ifdef CONFIG_DEBUG_LINUX_TRACING
- case 'T':
- params.wpa_debug_tracing++;
- break;
- #endif /* CONFIG_DEBUG_LINUX_TRACING */
- case 't':
- params.wpa_debug_timestamp++;
- break;
- #ifdef CONFIG_DBUS
- case 'u':
- params.dbus_ctrl_interface = 1;
- break;
- #endif /* CONFIG_DBUS */
- case 'v':
- printf("%s\n", wpa_supplicant_version);
- exitcode = 0;
- goto out;
- case 'W':
- params.wait_for_monitor++;
- break;
- case 'N':
- iface_count++;
- iface = os_realloc_array(ifaces, iface_count,
- sizeof(struct wpa_interface));
- if (iface == NULL)
- goto out;
- ifaces = iface;
- iface = &ifaces[iface_count - 1];
- os_memset(iface, 0, sizeof(*iface));
- break;
- default:
- usage();
- exitcode = 0;
- goto out;
- }
- }
- exitcode = 0;
- global = wpa_supplicant_init(¶ms); //关键函数,根据传入的参数,创建并初始化一个wpa_global对象
- if (global == NULL) {
- wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant");
- exitcode = -1;
- goto out;
- } else {
- wpa_printf(MSG_INFO, "Successfully initialized "
- "wpa_supplicant");
- }
- for (i = 0; exitcode == 0 && i < iface_count; i++) {
- struct wpa_supplicant *wpa_s;
- if ((ifaces[i].confname == NULL &&
- ifaces[i].ctrl_interface == NULL) ||
- ifaces[i].ifname == NULL) {
- if (iface_count == 1 && (params.ctrl_interface ||
- params.dbus_ctrl_interface))
- break;
- usage();
- exitcode = -1;
- break;
- }
- wpa_s = wpa_supplicant_add_iface(global, &ifaces[i]); //关键函数,wpa_supplicant支持操作多个无线网络设备,此处需将它们一一添加到wpa_supplicant中,wpa_supplicant内部将初始化这些设备。
- if (wpa_s == NULL) {
- exitcode = -1;
- break;
- }
- #ifdef CONFIG_P2P
- if (wpa_s->global->p2p == NULL &&
- (wpa_s->drv_flags &
- WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
- wpas_p2p_add_p2pdev_interface(wpa_s) < 0)
- exitcode = -1;
- #endif /* CONFIG_P2P */
- }
- if (exitcode == 0)
- exitcode = wpa_supplicant_run(global); //android平台中,wpa_supplicant通过select或epoll或方式实现多路I/O复用。
- wpa_supplicant_deinit(global);
- out:
- wpa_supplicant_fd_workaround(0);
- os_free(ifaces);
- os_free(params.pid_file);
- os_program_deinit();
- return exitcode;
- }
+ctrl_interface: const char* //控制接口unix域socket地址
+driver:const char* //该接口对应的驱动名
+driver_param:const char* //该接口对应驱动的参数
+ifname:const char* //指定网络接口设备名
+bridge_ifname:const char* //当接口用作桥接设备时,其桥接设备名本例中:
confname = "/data/misc/wifi/wpa_supplicant.conf"
ifname = "wlan0"
driver = "nl80211"
+params:struct wpa_params //运行参数
+ctrl_ifaces:struct ctrl_iface_global_priv* //全局控制接口
+drv_priv:void** //driver wrapper对应的全局上下文信息
+drv_count:size_t //driver wrapper的个数
+socket:int+global:struct wpa_global*
+next:struct wpa_supplicant*
(1)wpa_interface用于描述一个无线设备。该参数在初始化时用到。
(2)wpa_global是一个全局性质的上下文信息。它通过ifaces变量指向一个wpa_supplicant对象。
(3)wpa_supplicant是wpa_supplicant的核心数据结构。一个interface对应一个wpa_supplicant对象,其内部包含非常多的成员变量。
(4)ctrl_iface_global_priv是全局控制接口的信息,内部包含一个用于通信的socket句柄。
wpa_supplicant_init函数分析
[-->wpa_supplicant.c::wpa_supplicant_init]
- struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
- {
- struct wpa_global *global;
- int ret, i;
- if (params == NULL)
- return NULL;
- #ifdef CONFIG_DRIVER_NDIS
- {
- void driver_ndis_init_ops(void);
- driver_ndis_init_ops();
- }
- #endif /* CONFIG_DRIVER_NDIS */
- #ifndef CONFIG_NO_WPA_MSG
- <span style="white-space:pre"> </span>//设置全局回调函数
- wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
- #endif /* CONFIG_NO_WPA_MSG */
- wpa_debug_open_file(params->wpa_debug_file_path);
- if (params->wpa_debug_syslog)
- wpa_debug_open_syslog();
- if (params->wpa_debug_tracing) {
- ret = wpa_debug_open_linux_tracing();
- if (ret) {
- wpa_printf(MSG_ERROR,
- "Failed to enable trace logging");
- return NULL;
- }
- }
- ret = eap_register_methods();<span style="white-space:pre"> </span>//注册EAP方法
- if (ret) {
- wpa_printf(MSG_ERROR, "Failed to register EAP methods");
- if (ret == -2)
- wpa_printf(MSG_ERROR, "Two or more EAP methods used "
- "the same EAP type.");
- return NULL;
- }
- global = os_zalloc(sizeof(*global));
- if (global == NULL)
- return NULL;
- 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;
- if (params->pid_file)
- global->params.pid_file = os_strdup(params->pid_file);
- if (params->ctrl_interface)
- global->params.ctrl_interface =
- os_strdup(params->ctrl_interface);
- if (params->ctrl_interface_group)
- global->params.ctrl_interface_group =
- os_strdup(params->ctrl_interface_group);
- if (params->override_driver)
- global->params.override_driver =
- os_strdup(params->override_driver);
- if (params->override_ctrl_interface)
- 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;
- wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
- <span style="white-space:pre"> </span>//初始化事件循环机制
- if (eloop_init()) {
- wpa_printf(MSG_ERROR, "Failed to initialize event loop");
- wpa_supplicant_deinit(global);
- return NULL;
- }
- <span style="white-space:pre"> </span>//初始化随机数相关资源,用于提升后续随机数生成的随机性
- random_init(params->entropy_file);
- <span style="white-space:pre"> </span>//初始化全局控制接口对象
- 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;
- }
- <span style="white-space:pre"> </span>//wpa_driver是一个全局变量。
- 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;
- }
- <span style="white-space:pre"> </span>//分配全局driver wrapper上下文信息数组
- 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;
- }
wpa_supplicant_init函数的主要功能是初始化wpa_global以及一些与整个程序相关的资源,包括随机数资源、eloop事件循环机制以及设置消息全局回调函数。
(1)wpa_msg_get_ifname_func:有些输出信息中需要打印出网卡接口名。该回调函数用于获取网卡接口名。
(2)wpa_msg_cb_func:除了打印输出信息外,还可通过该回调函数进行一些特殊处理,如把输出信息发送给客户端进行处理。
[-->wpa_debug.c]
- void wpa_msg_register_cb(wpa_msg_cb_func func)
- {
- wpa_msg_cb = func;
- }
- static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL;
- static wpa_msg_cb_func wpa_msg_cb = NULL;
- void wpa_msg_register_cb(wpa_msg_cb_func func)
- {
- wpa_msg_cb = func;
- }
wpa_supplicant_init中列出了三个关键点,分别是eap_register_method函数、eloop_init函数及event loop模块、wpa_drivers数组和driver i/f模块
1、eap_register_method函数
主要根据编译时的配置项来初始化不同的eap方法。
[-->eap-register.c::eap_register_methods]
- int eap_register_methods(void)
- {
- int ret = 0;
- #ifdef EAP_MD5<span style="white-space:pre"> </span>//作为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<span style="white-space:pre"> </span>//作为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;
- }
初始化了wpa_supplicant中事件驱动的核心数据结构体
从事件角度来看,wpa_supplicant的事件驱动机制支持5中类型event:
(1)read event:读事件,例如来自socket的可读事件
(2)write event:写事件
(3)exception event:异常事件
(4)timeout event:定时事件
(5)signal:信号时间,信号时间来源于Kernel。
[-->eloop.c::eloop_run]
- 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 */
- <span style="white-space:pre"> </span>//事件驱动循环
- 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 */
- 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);
- if (res < 0 && errno != EINTR && errno != 0) {
- perror("select");
- goto out;
- }
- #endif /* CONFIG_ELOOP_POLL */
- eloop_process_pending_signals();<span style="white-space:pre"> </span>//先处理信号事件
- /* 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;
- }
3、wpa_drivers数组和driver i/f模块
wpa_drivers是一个全局数组变量,它通过extern方式声明于main.c中,其定义却在drivers.c:
[-->drivers.c::wpa_drivers定义]
- 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
- };
[-->driver_nl80211.c::wpa_driver_nl80211_ops]
- const struct wpa_driver_ops wpa_driver_nl80211_ops = {
- .name = "nl80211",
- .desc = "Linux nl80211/cfg80211",
- .get_bssid = wpa_driver_nl80211_get_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,
- .associate = wpa_driver_nl80211_associate,
- .global_init = nl80211_global_init,
- .global_deinit = nl80211_global_deinit,
- .init2 = wpa_driver_nl80211_init,
- .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
- .driver_cmd = wpa_driver_nl80211_driver_cmd,
- #endif
- };
待续。。。
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程续
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程续
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程续
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程续
- Android4.4 wpa_supplicant深入分析之初识wpa_supplicant
- Android4.4 wpa_supplicant深入分析之初识wpa_supplicant
- Android4.4 wpa_supplicant深入分析之初识wpa_supplicant
- Android4.4 wpa_supplicant深入分析之初识wpa_supplicant
- wpa_supplicant 初始化流程分析
- wpa_supplicant 初始化流程分析
- wpa_supplicant 初始化流程分析
- wpa_supplicant 初始化流程分析
- wpa_supplicant 初始化流程分析
- wpa_supplicant初始化流程分析
- 深度学习笔记5:池化层的实现
- Javascript基础-介绍、实现、输出
- BZOJ1635 [Usaco2007 Jan]Tallest Cow 最高的牛 数列差分
- oracle执行了shutdown某个实例之后,如何重新启动
- 【每周至少一篇 160819】最大子序列和问题的四种求法_Java
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程
- zookeeper运维管理
- hdu 5867 (一到一千的模拟题)
- clipBoardEvent, execCommand等粘贴板相关研究
- Cracer渗透测试网络培训第一期
- 早上学了一下java的随机数,下面把代码复制一下
- canvas的save与restore方法的作用
- 树上路径
- 可乐瓶盖问题