«

Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程

时间:2024-3-2 19:04     作者:韩俊     分类: Android


Android系统中,wpa_supplicant启动是通过“setprop ctrl.start wpa_supplicant”来触发init进程去fork一个子进程来完成的。wpa_supplicant在init配置文件中被定义为一个service。

[cpp]
view plaincopy

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

以上众多启动参数中,最重要的是通过“-c“参数制定的wpa_supplicant启动配置文件。

[cpp]
view plaincopy

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]

[cpp]
view plaincopy

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("%sn", 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(&params); //关键函数,根据传入的参数,创建并初始化一个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; }

main函数中重要的数据结构

struct wpa_interface

+confname:const char //该接口对应的配置文件名

+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"








struct wpa_global

+ifaces:struct wpa_supplicant //见下文解释

+params:struct wpa_params //运行参数

+ctrl_ifaces:struct ctrl_iface_global_priv
//全局控制接口

+drv_priv:void** //driver wrapper对应的全局上下文信息

+drv_count:size_t //driver wrapper的个数

struct ctrl_iface_global_priv
struct wpa_supplicant

+global:struct wpa_global

+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]

[cpp]
view plaincopy

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

[cpp]
view plaincopy

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

[cpp]
view plaincopy

<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]

[cpp]
view plaincopy

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;

[cpp]
view plaincopy

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]

[cpp]
view plaincopy

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

2、eloop_init函数及event loop模块

初始化了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]

[cpp]
view plaincopy

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

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

3、wpa_drivers数组和driver i/f模块

wpa_drivers是一个全局数组变量,它通过extern方式声明于main.c中,其定义却在drivers.c:

[-->drivers.c::wpa_drivers定义]

[cpp]
view plaincopy

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_drivers数组成员指向一个wpa_driver_ops类型的对象。wpa_driver_ops是driver i/f模块的核心数据结构,其内部定义了很多函数指针。

[-->driver_nl80211.c::wpa_driver_nl80211_ops]

[cpp]
view plaincopy

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



待续。。。

标签: android

热门推荐