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。

[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. service wpa_supplicant /system/bin/wpa_supplicant \  
  2.     -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \  
  3.     -I/system/etc/wifi/wpa_supplicant_overlay.conf \  
  4.     -O/data/misc/wifi/sockets \  
  5.     -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0  
  6.     #   we will start as root and wpa_supplicant will switch to user wifi  
  7.     #   after setting up the capabilities required for WEXT  
  8.     #   user wifi  
  9.     #   group wifi inet keystore  
  10.     class main  
  11.     socket wpa_wlan0 dgram 660 wifi wifi  
  12.     disabled  
  13.     oneshot  
以上众多启动参数中,最重要的是通过“-c“参数制定的wpa_supplicant启动配置文件。
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. ctrl_interface=/data/misc/wifi/sockets  
  2. driver_param=use_p2p_group_interface=1p2p_device=1  
  3. update_config=1  
  4. device_name=********  
  5. manufacturer=BROADCOM  
  6. model_name=*********  
  7. model_number=*********  
  8. serial_number=  
  9. device_type=10-0050F204-5  
  10. config_methods=physical_display virtual_push_button  
  11. p2p_listen_reg_class=81  
  12. p2p_listen_channel=11  
  13. p2p_oper_reg_class=81  
  14. p2p_oper_channel=11  
  15. p2p_ssid_postfix=-Android_7006  
  16. persistent_reconnect=1  
  17.   
  18. network={  
  19.     ssid="AP_5D34E3"  
  20.     psk="12345678"  
  21.     key_mgmt=WPA-PSK  
  22.     priority=1  
  23. }  
  24.   
  25. network={  
  26.     ssid="Android-02"  
  27.     psk="android.com"  
  28.     key_mgmt=WPA-PSK  
  29.     priority=2  
  30. }  

(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 plain copy
print?在CODE上查看代码片派生到我的代码片
  1. int main(int argc, char *argv[])  
  2. {  
  3.     int c, i;  
  4.     struct wpa_interface *ifaces, *iface;  
  5.     int iface_count, exitcode = -1;  
  6.     struct wpa_params params;  
  7.     struct wpa_global *global;  
  8.   
  9.     if (os_program_init())  
  10.         return -1;  
  11.   
  12.     os_memset(¶ms, 0, sizeof(params));  
  13.     params.wpa_debug_level = MSG_INFO;  
  14.   
  15.     iface = ifaces = os_zalloc(sizeof(struct wpa_interface));  
  16.     if (ifaces == NULL)  
  17.         return -1;  
  18.     iface_count = 1;  
  19.   
  20.     wpa_supplicant_fd_workaround(1);  //输入输出重定向到/dev/null设备  
  21.   
  22.     for (;;) {  
  23.         c = getopt(argc, argv,  
  24.                "b:Bc:C:D:de:f:g:G:hi:I:KLNo:O:p:P:qsTtuvW");  
  25.         if (c < 0)  
  26.             break;  
  27.         switch (c) {  
  28.         case 'b':  
  29.             iface->bridge_ifname = optarg;  
  30.             break;  
  31.         case 'B':  
  32.             params.daemonize++;  
  33.             break;  
  34.         case 'c':  
  35.             iface->confname = optarg;    //指定配置文件名。注意,该参数赋值给了wpa_interface中的变量  
  36.             break;  
  37.         case 'C':  
  38.             iface->ctrl_interface = optarg;  
  39.             break;  
  40.         case 'D':  
  41.             iface->driver = optarg;         //指定driver名称。注意,该参数赋值给了wpa_interface中的变量  
  42.             break;  
  43.         case 'd':  
  44. #ifdef CONFIG_NO_STDOUT_DEBUG  
  45.             printf("Debugging disabled with "  
  46.                    "CONFIG_NO_STDOUT_DEBUG=y build time "  
  47.                    "option.\n");  
  48.             goto out;  
  49. #else /* CONFIG_NO_STDOUT_DEBUG */  
  50.             params.wpa_debug_level--;  
  51.             break;  
  52. #endif /* CONFIG_NO_STDOUT_DEBUG */  
  53.         case 'e':  
  54.             params.entropy_file = optarg;  //制定初始随机数文件,用于后续随机数的生成  
  55.             break;  
  56. #ifdef CONFIG_DEBUG_FILE  
  57.         case 'f':  
  58.             params.wpa_debug_file_path = optarg;  
  59.             break;  
  60. #endif /* CONFIG_DEBUG_FILE */  
  61.         case 'g':  
  62.             params.ctrl_interface = optarg;  
  63.             break;  
  64.         case 'G':  
  65.             params.ctrl_interface_group = optarg;  
  66.             break;  
  67.         case 'h':  
  68.             usage();  
  69.             exitcode = 0;  
  70.             goto out;  
  71.         case 'i':  
  72.             iface->ifname = optarg;  //指定网络设备接口名,本例是"wlan0"  
  73.             break;  
  74.         case 'I':  
  75.             iface->confanother = optarg;  
  76.             break;  
  77.         case 'K':  
  78.             params.wpa_debug_show_keys++;  
  79.             break;  
  80.         case 'L':  
  81.             license();  
  82.             exitcode = 0;  
  83.             goto out;  
  84.         case 'o':  
  85.             params.override_driver = optarg;  
  86.             break;  
  87.         case 'O':  
  88.             params.override_ctrl_interface = optarg;  
  89.             break;  
  90.         case 'p':  
  91.             iface->driver_param = optarg;  
  92.             break;  
  93.         case 'P':  
  94.             os_free(params.pid_file);  
  95.             params.pid_file = os_rel2abs_path(optarg);  
  96.             break;  
  97.         case 'q':  
  98.             params.wpa_debug_level++;  
  99.             break;  
  100. #ifdef CONFIG_DEBUG_SYSLOG  
  101.         case 's':  
  102.             params.wpa_debug_syslog++;  
  103.             break;  
  104. #endif /* CONFIG_DEBUG_SYSLOG */  
  105. #ifdef CONFIG_DEBUG_LINUX_TRACING  
  106.         case 'T':  
  107.             params.wpa_debug_tracing++;  
  108.             break;  
  109. #endif /* CONFIG_DEBUG_LINUX_TRACING */  
  110.         case 't':  
  111.             params.wpa_debug_timestamp++;  
  112.             break;  
  113. #ifdef CONFIG_DBUS  
  114.         case 'u':  
  115.             params.dbus_ctrl_interface = 1;  
  116.             break;  
  117. #endif /* CONFIG_DBUS */  
  118.         case 'v':  
  119.             printf("%s\n", wpa_supplicant_version);  
  120.             exitcode = 0;  
  121.             goto out;  
  122.         case 'W':  
  123.             params.wait_for_monitor++;  
  124.             break;  
  125.         case 'N':  
  126.             iface_count++;  
  127.             iface = os_realloc_array(ifaces, iface_count,  
  128.                          sizeof(struct wpa_interface));  
  129.             if (iface == NULL)  
  130.                 goto out;  
  131.             ifaces = iface;  
  132.             iface = &ifaces[iface_count - 1];   
  133.             os_memset(iface, 0, sizeof(*iface));  
  134.             break;  
  135.         default:  
  136.             usage();  
  137.             exitcode = 0;  
  138.             goto out;  
  139.         }  
  140.     }  
  141.   
  142.     exitcode = 0;  
  143.     global = wpa_supplicant_init(&params);  //关键函数,根据传入的参数,创建并初始化一个wpa_global对象  
  144.     if (global == NULL) {  
  145.         wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant");  
  146.         exitcode = -1;  
  147.         goto out;  
  148.     } else {  
  149.         wpa_printf(MSG_INFO, "Successfully initialized "  
  150.                "wpa_supplicant");  
  151.     }  
  152.   
  153.     for (i = 0; exitcode == 0 && i < iface_count; i++) {  
  154.         struct wpa_supplicant *wpa_s;  
  155.   
  156.         if ((ifaces[i].confname == NULL &&  
  157.              ifaces[i].ctrl_interface == NULL) ||  
  158.             ifaces[i].ifname == NULL) {  
  159.             if (iface_count == 1 && (params.ctrl_interface ||  
  160.                          params.dbus_ctrl_interface))  
  161.                 break;  
  162.             usage();  
  163.             exitcode = -1;  
  164.             break;  
  165.         }  
  166.         wpa_s = wpa_supplicant_add_iface(global, &ifaces[i]);   //关键函数,wpa_supplicant支持操作多个无线网络设备,此处需将它们一一添加到wpa_supplicant中,wpa_supplicant内部将初始化这些设备。  
  167.         if (wpa_s == NULL) {  
  168.             exitcode = -1;  
  169.             break;  
  170.         }  
  171. #ifdef CONFIG_P2P  
  172.         if (wpa_s->global->p2p == NULL &&  
  173.             (wpa_s->drv_flags &  
  174.              WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&  
  175.             wpas_p2p_add_p2pdev_interface(wpa_s) < 0)  
  176.             exitcode = -1;  
  177. #endif /* CONFIG_P2P */  
  178.     }  
  179.   
  180.     if (exitcode == 0)  
  181.         exitcode = wpa_supplicant_run(global);  //android平台中,wpa_supplicant通过select或epoll或方式实现多路I/O复用。  
  182.   
  183.     wpa_supplicant_deinit(global);  
  184.   
  185. out:  
  186.     wpa_supplicant_fd_workaround(0);  
  187.     os_free(ifaces);  
  188.     os_free(params.pid_file);  
  189.   
  190.     os_program_deinit();  
  191.   
  192.     return exitcode;  
  193. }  
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_privstruct 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 plain copy
print?在CODE上查看代码片派生到我的代码片
  1. struct wpa_global * wpa_supplicant_init(struct wpa_params *params)  
  2. {  
  3.     struct wpa_global *global;  
  4.     int ret, i;  
  5.   
  6.     if (params == NULL)  
  7.         return NULL;  
  8.   
  9. #ifdef CONFIG_DRIVER_NDIS  
  10.     {  
  11.         void driver_ndis_init_ops(void);  
  12.         driver_ndis_init_ops();  
  13.     }  
  14. #endif /* CONFIG_DRIVER_NDIS */  
  15.   
  16. #ifndef CONFIG_NO_WPA_MSG  
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. <span style="white-space:pre">    </span>//设置全局回调函数  
  2.     wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);  
  3. #endif /* CONFIG_NO_WPA_MSG */  
  4.   
  5.     wpa_debug_open_file(params->wpa_debug_file_path);  
  6.     if (params->wpa_debug_syslog)  
  7.         wpa_debug_open_syslog();  
  8.     if (params->wpa_debug_tracing) {  
  9.         ret = wpa_debug_open_linux_tracing();  
  10.         if (ret) {  
  11.             wpa_printf(MSG_ERROR,  
  12.                    "Failed to enable trace logging");  
  13.             return NULL;  
  14.         }  
  15.     }  
  16.   
  17.     ret = eap_register_methods();<span style="white-space:pre">   </span>//注册EAP方法  
  18.     if (ret) {  
  19.         wpa_printf(MSG_ERROR, "Failed to register EAP methods");  
  20.         if (ret == -2)  
  21.             wpa_printf(MSG_ERROR, "Two or more EAP methods used "  
  22.                    "the same EAP type.");  
  23.         return NULL;  
  24.     }  
  25.   
  26.     global = os_zalloc(sizeof(*global));  
  27.     if (global == NULL)  
  28.         return NULL;  
  29.     dl_list_init(&global->p2p_srv_bonjour);  
  30.     dl_list_init(&global->p2p_srv_upnp);  
  31.     global->params.daemonize = params->daemonize;  
  32.     global->params.wait_for_monitor = params->wait_for_monitor;  
  33.     global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;  
  34.     if (params->pid_file)  
  35.         global->params.pid_file = os_strdup(params->pid_file);  
  36.     if (params->ctrl_interface)  
  37.         global->params.ctrl_interface =  
  38.             os_strdup(params->ctrl_interface);  
  39.     if (params->ctrl_interface_group)  
  40.         global->params.ctrl_interface_group =  
  41.             os_strdup(params->ctrl_interface_group);  
  42.     if (params->override_driver)  
  43.         global->params.override_driver =  
  44.             os_strdup(params->override_driver);  
  45.     if (params->override_ctrl_interface)  
  46.         global->params.override_ctrl_interface =  
  47.             os_strdup(params->override_ctrl_interface);  
  48.     wpa_debug_level = global->params.wpa_debug_level =  
  49.         params->wpa_debug_level;  
  50.     wpa_debug_show_keys = global->params.wpa_debug_show_keys =  
  51.         params->wpa_debug_show_keys;  
  52.     wpa_debug_timestamp = global->params.wpa_debug_timestamp =  
  53.         params->wpa_debug_timestamp;  
  54.   
  55.     wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);  
  56. <span style="white-space:pre">    </span>//初始化事件循环机制  
  57.     if (eloop_init()) {  
  58.         wpa_printf(MSG_ERROR, "Failed to initialize event loop");  
  59.         wpa_supplicant_deinit(global);  
  60.         return NULL;  
  61.     }  
  62. <span style="white-space:pre">    </span>//初始化随机数相关资源,用于提升后续随机数生成的随机性  
  63.     random_init(params->entropy_file);  
  64. <span style="white-space:pre">    </span>//初始化全局控制接口对象  
  65.     global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);  
  66.     if (global->ctrl_iface == NULL) {  
  67.         wpa_supplicant_deinit(global);  
  68.         return NULL;  
  69.     }  
  70.   
  71.     if (wpas_notify_supplicant_initialized(global)) {  
  72.         wpa_supplicant_deinit(global);  
  73.         return NULL;  
  74.     }  
  75. <span style="white-space:pre">    </span>//wpa_driver是一个全局变量。  
  76.     for (i = 0; wpa_drivers[i]; i++)  
  77.         global->drv_count++;  
  78.     if (global->drv_count == 0) {  
  79.         wpa_printf(MSG_ERROR, "No drivers enabled");  
  80.         wpa_supplicant_deinit(global);  
  81.         return NULL;  
  82.     }  
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. <span style="white-space:pre">    </span>//分配全局driver wrapper上下文信息数组  
  2.     global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));  
  3.     if (global->drv_priv == NULL) {  
  4.         wpa_supplicant_deinit(global);  
  5.         return NULL;  
  6.     }  
  7.   
  8. #ifdef CONFIG_WIFI_DISPLAY  
  9.     if (wifi_display_init(global) < 0) {  
  10.         wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");  
  11.         wpa_supplicant_deinit(global);  
  12.         return NULL;  
  13.     }  
  14. #endif /* CONFIG_WIFI_DISPLAY */  
  15.   
  16.     return global;  
  17. }  

wpa_supplicant_init函数的主要功能是初始化wpa_global以及一些与整个程序相关的资源,包括随机数资源、eloop事件循环机制以及设置消息全局回调函数。

(1)wpa_msg_get_ifname_func:有些输出信息中需要打印出网卡接口名。该回调函数用于获取网卡接口名。

(2)wpa_msg_cb_func:除了打印输出信息外,还可通过该回调函数进行一些特殊处理,如把输出信息发送给客户端进行处理。

[-->wpa_debug.c]

[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. void wpa_msg_register_cb(wpa_msg_cb_func func)  
  2. {  
  3.     wpa_msg_cb = func;  
  4. }  
  5.   
  6.   
  7. static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL;  
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. static wpa_msg_cb_func wpa_msg_cb = NULL;  
  2.   
  3. void wpa_msg_register_cb(wpa_msg_cb_func func)  
  4. {  
  5.     wpa_msg_cb = func;  
  6. }  

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 plain copy
print?在CODE上查看代码片派生到我的代码片
  1. int eap_register_methods(void)  
  2. {  
  3.     int ret = 0;  
  4.   
  5. #ifdef EAP_MD5<span style="white-space:pre">      </span>//作为supplicant端,编译时将定义EAP_MD5  
  6.     if (ret == 0)  
  7.         ret = eap_peer_md5_register();  
  8. #endif /* EAP_MD5 */  
  9.   
  10. #ifdef EAP_TLS  
  11.     if (ret == 0)  
  12.         ret = eap_peer_tls_register();  
  13. #endif /* EAP_TLS */  
  14.   
  15. #ifdef EAP_UNAUTH_TLS  
  16.     if (ret == 0)  
  17.         ret = eap_peer_unauth_tls_register();  
  18. #endif /* EAP_UNAUTH_TLS */  
  19.   
  20. #ifdef EAP_MSCHAPv2  
  21.     if (ret == 0)  
  22.         ret = eap_peer_mschapv2_register();  
  23. #endif /* EAP_MSCHAPv2 */  
  24.   
  25. #ifdef EAP_PEAP  
  26.     if (ret == 0)  
  27.         ret = eap_peer_peap_register();  
  28. #endif /* EAP_PEAP */  
  29.   
  30. #ifdef EAP_TTLS  
  31.     if (ret == 0)  
  32.         ret = eap_peer_ttls_register();  
  33. #endif /* EAP_TTLS */  
  34.   
  35. #ifdef EAP_GTC  
  36.     if (ret == 0)  
  37.         ret = eap_peer_gtc_register();  
  38. #endif /* EAP_GTC */  
  39.   
  40. #ifdef EAP_OTP  
  41.     if (ret == 0)  
  42.         ret = eap_peer_otp_register();  
  43. #endif /* EAP_OTP */  
  44.   
  45. #ifdef EAP_SIM  
  46.     if (ret == 0)  
  47.         ret = eap_peer_sim_register();  
  48. #endif /* EAP_SIM */  
  49.   
  50. #ifdef EAP_LEAP  
  51.     if (ret == 0)  
  52.         ret = eap_peer_leap_register();  
  53. #endif /* EAP_LEAP */  
  54.   
  55. #ifdef EAP_PSK  
  56.     if (ret == 0)  
  57.         ret = eap_peer_psk_register();  
  58. #endif /* EAP_PSK */  
  59.   
  60. #ifdef EAP_AKA  
  61.     if (ret == 0)  
  62.         ret = eap_peer_aka_register();  
  63. #endif /* EAP_AKA */  
  64.   
  65. #ifdef EAP_AKA_PRIME  
  66.     if (ret == 0)  
  67.         ret = eap_peer_aka_prime_register();  
  68. #endif /* EAP_AKA_PRIME */  
  69.   
  70. #ifdef EAP_FAST  
  71.     if (ret == 0)  
  72.         ret = eap_peer_fast_register();  
  73. #endif /* EAP_FAST */  
  74.   
  75. #ifdef EAP_PAX  
  76.     if (ret == 0)  
  77.         ret = eap_peer_pax_register();  
  78. #endif /* EAP_PAX */  
  79.   
  80. #ifdef EAP_SAKE  
  81.     if (ret == 0)  
  82.         ret = eap_peer_sake_register();  
  83. #endif /* EAP_SAKE */  
  84.   
  85. #ifdef EAP_GPSK  
  86.     if (ret == 0)  
  87.         ret = eap_peer_gpsk_register();  
  88. #endif /* EAP_GPSK */  
  89.   
  90. #ifdef EAP_WSC  
  91.     if (ret == 0)  
  92.         ret = eap_peer_wsc_register();  
  93. #endif /* EAP_WSC */  
  94.   
  95. #ifdef EAP_IKEV2  
  96.     if (ret == 0)  
  97.         ret = eap_peer_ikev2_register();  
  98. #endif /* EAP_IKEV2 */  
  99.   
  100. #ifdef EAP_VENDOR_TEST  
  101.     if (ret == 0)  
  102.         ret = eap_peer_vendor_test_register();  
  103. #endif /* EAP_VENDOR_TEST */  
  104.   
  105. #ifdef EAP_TNC  
  106.     if (ret == 0)  
  107.         ret = eap_peer_tnc_register();  
  108. #endif /* EAP_TNC */  
  109.   
  110. #ifdef EAP_PWD  
  111.     if (ret == 0)  
  112.         ret = eap_peer_pwd_register();  
  113. #endif /* EAP_PWD */  
  114.   
  115. #ifdef EAP_EKE  
  116.     if (ret == 0)  
  117.         ret = eap_peer_eke_register();  
  118. #endif /* EAP_EKE */  
  119.   
  120. #ifdef EAP_SERVER_IDENTITY  
  121.     if (ret == 0)  
  122.         ret = eap_server_identity_register();  
  123. #endif /* EAP_SERVER_IDENTITY */  
  124.   
  125. #ifdef EAP_SERVER_MD5<span style="white-space:pre">           </span>//作为Authenticator端,编译时将定义EAP_SERVER_MD5  
  126.     if (ret == 0)  
  127.         ret = eap_server_md5_register();  
  128. #endif /* EAP_SERVER_MD5 */  
  129.   
  130. #ifdef EAP_SERVER_TLS  
  131.     if (ret == 0)  
  132.         ret = eap_server_tls_register();  
  133. #endif /* EAP_SERVER_TLS */  
  134.   
  135. #ifdef EAP_SERVER_UNAUTH_TLS  
  136.     if (ret == 0)  
  137.         ret = eap_server_unauth_tls_register();  
  138. #endif /* EAP_SERVER_UNAUTH_TLS */  
  139.   
  140. #ifdef EAP_SERVER_MSCHAPV2  
  141.     if (ret == 0)  
  142.         ret = eap_server_mschapv2_register();  
  143. #endif /* EAP_SERVER_MSCHAPV2 */  
  144.   
  145. #ifdef EAP_SERVER_PEAP  
  146.     if (ret == 0)  
  147.         ret = eap_server_peap_register();  
  148. #endif /* EAP_SERVER_PEAP */  
  149.   
  150. #ifdef EAP_SERVER_TLV  
  151.     if (ret == 0)  
  152.         ret = eap_server_tlv_register();  
  153. #endif /* EAP_SERVER_TLV */  
  154.   
  155. #ifdef EAP_SERVER_GTC  
  156.     if (ret == 0)  
  157.         ret = eap_server_gtc_register();  
  158. #endif /* EAP_SERVER_GTC */  
  159.   
  160. #ifdef EAP_SERVER_TTLS  
  161.     if (ret == 0)  
  162.         ret = eap_server_ttls_register();  
  163. #endif /* EAP_SERVER_TTLS */  
  164.   
  165. #ifdef EAP_SERVER_SIM  
  166.     if (ret == 0)  
  167.         ret = eap_server_sim_register();  
  168. #endif /* EAP_SERVER_SIM */  
  169.   
  170. #ifdef EAP_SERVER_AKA  
  171.     if (ret == 0)  
  172.         ret = eap_server_aka_register();  
  173. #endif /* EAP_SERVER_AKA */  
  174.   
  175. #ifdef EAP_SERVER_AKA_PRIME  
  176.     if (ret == 0)  
  177.         ret = eap_server_aka_prime_register();  
  178. #endif /* EAP_SERVER_AKA_PRIME */  
  179.   
  180. #ifdef EAP_SERVER_PAX  
  181.     if (ret == 0)  
  182.         ret = eap_server_pax_register();  
  183. #endif /* EAP_SERVER_PAX */  
  184.   
  185. #ifdef EAP_SERVER_PSK  
  186.     if (ret == 0)  
  187.         ret = eap_server_psk_register();  
  188. #endif /* EAP_SERVER_PSK */  
  189.   
  190. #ifdef EAP_SERVER_SAKE  
  191.     if (ret == 0)  
  192.         ret = eap_server_sake_register();  
  193. #endif /* EAP_SERVER_SAKE */  
  194.   
  195. #ifdef EAP_SERVER_GPSK  
  196.     if (ret == 0)  
  197.         ret = eap_server_gpsk_register();  
  198. #endif /* EAP_SERVER_GPSK */  
  199.   
  200. #ifdef EAP_SERVER_VENDOR_TEST  
  201.     if (ret == 0)  
  202.         ret = eap_server_vendor_test_register();  
  203. #endif /* EAP_SERVER_VENDOR_TEST */  
  204.   
  205. #ifdef EAP_SERVER_FAST  
  206.     if (ret == 0)  
  207.         ret = eap_server_fast_register();  
  208. #endif /* EAP_SERVER_FAST */  
  209.   
  210. #ifdef EAP_SERVER_WSC  
  211.     if (ret == 0)  
  212.         ret = eap_server_wsc_register();  
  213. #endif /* EAP_SERVER_WSC */  
  214.   
  215. #ifdef EAP_SERVER_IKEV2  
  216.     if (ret == 0)  
  217.         ret = eap_server_ikev2_register();  
  218. #endif /* EAP_SERVER_IKEV2 */  
  219.   
  220. #ifdef EAP_SERVER_TNC  
  221.     if (ret == 0)  
  222.         ret = eap_server_tnc_register();  
  223. #endif /* EAP_SERVER_TNC */  
  224.   
  225. #ifdef EAP_SERVER_PWD  
  226.     if (ret == 0)  
  227.         ret = eap_server_pwd_register();  
  228. #endif /* EAP_SERVER_PWD */  
  229.   
  230.     return ret;  
  231. }  
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 plain copy
print?在CODE上查看代码片派生到我的代码片
  1. void eloop_run(void)  
  2. {  
  3. #ifdef CONFIG_ELOOP_POLL  
  4.     int num_poll_fds;  
  5.     int timeout_ms = 0;  
  6. #else /* CONFIG_ELOOP_POLL */  
  7.     fd_set *rfds, *wfds, *efds;  
  8.     struct timeval _tv;  
  9. #endif /* CONFIG_ELOOP_POLL */  
  10.     int res;  
  11.     struct os_time tv, now;  
  12.   
  13. #ifndef CONFIG_ELOOP_POLL  
  14.     rfds = os_malloc(sizeof(*rfds));  
  15.     wfds = os_malloc(sizeof(*wfds));  
  16.     efds = os_malloc(sizeof(*efds));  
  17.     if (rfds == NULL || wfds == NULL || efds == NULL)  
  18.         goto out;  
  19. #endif /* CONFIG_ELOOP_POLL */  
  20. <span style="white-space:pre">    </span>//事件驱动循环  
  21.     while (!eloop.terminate &&  
  22.            (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||  
  23.         eloop.writers.count > 0 || eloop.exceptions.count > 0)) {  
  24.         struct eloop_timeout *timeout;  
  25.         timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,  
  26.                     list);  
  27.         if (timeout) {  
  28.             os_get_time(&now);  
  29.             if (os_time_before(&now, &timeout->time))  
  30.                 os_time_sub(&timeout->time, &now, &tv);  
  31.             else  
  32.                 tv.sec = tv.usec = 0;  
  33. #ifdef CONFIG_ELOOP_POLL  
  34.             timeout_ms = tv.sec * 1000 + tv.usec / 1000;  
  35. #else /* CONFIG_ELOOP_POLL */  
  36.             _tv.tv_sec = tv.sec;  
  37.             _tv.tv_usec = tv.usec;  
  38. #endif /* CONFIG_ELOOP_POLL */  
  39.         }  
  40.   
  41. #ifdef CONFIG_ELOOP_POLL  
  42.         num_poll_fds = eloop_sock_table_set_fds(  
  43.             &eloop.readers, &eloop.writers, &eloop.exceptions,  
  44.             eloop.pollfds, eloop.pollfds_map,  
  45.             eloop.max_pollfd_map);  
  46.         res = poll(eloop.pollfds, num_poll_fds,  
  47.                timeout ? timeout_ms : -1);  
  48.   
  49.         if (res < 0 && errno != EINTR && errno != 0) {  
  50.             perror("poll");  
  51.             goto out;  
  52.         }  
  53. #else /* CONFIG_ELOOP_POLL */  
  54.         eloop_sock_table_set_fds(&eloop.readers, rfds);  
  55.         eloop_sock_table_set_fds(&eloop.writers, wfds);  
  56.         eloop_sock_table_set_fds(&eloop.exceptions, efds);  
  57.         res = select(eloop.max_sock + 1, rfds, wfds, efds,  
  58.                  timeout ? &_tv : NULL);  
  59.         if (res < 0 && errno != EINTR && errno != 0) {  
  60.             perror("select");  
  61.             goto out;  
  62.         }  
  63. #endif /* CONFIG_ELOOP_POLL */  
  64.         eloop_process_pending_signals();<span style="white-space:pre">    </span>//先处理信号事件  
  65.   
  66.         /* check if some registered timeouts have occurred */  
  67.         timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,  
  68.                     list);  
  69.         if (timeout) {  
  70.             os_get_time(&now);  
  71.             if (!os_time_before(&now, &timeout->time)) {  
  72.                 void *eloop_data = timeout->eloop_data;  
  73.                 void *user_data = timeout->user_data;  
  74.                 eloop_timeout_handler handler =  
  75.                     timeout->handler;  
  76.                 eloop_remove_timeout(timeout);  
  77.                 handler(eloop_data, user_data);  
  78.             }  
  79.   
  80.         }  
  81.   
  82.         if (res <= 0)  
  83.             continue;  
  84.   
  85. #ifdef CONFIG_ELOOP_POLL  
  86.         eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,  
  87.                       &eloop.exceptions, eloop.pollfds_map,  
  88.                       eloop.max_pollfd_map);  
  89. #else /* CONFIG_ELOOP_POLL */  
  90.         eloop_sock_table_dispatch(&eloop.readers, rfds);  
  91.         eloop_sock_table_dispatch(&eloop.writers, wfds);  
  92.         eloop_sock_table_dispatch(&eloop.exceptions, efds);  
  93. #endif /* CONFIG_ELOOP_POLL */  
  94.     }  
  95.   
  96.     eloop.terminate = 0;  
  97. out:  
  98. #ifndef CONFIG_ELOOP_POLL  
  99.     os_free(rfds);  
  100.     os_free(wfds);  
  101.     os_free(efds);  
  102. #endif /* CONFIG_ELOOP_POLL */  
  103.     return;  
  104. }  
eloop_run中的while循环是wpa_supplicant进程的运行中枢。

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

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

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

[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. struct wpa_driver_ops *wpa_drivers[] =  
  2. {  
  3. #ifdef CONFIG_DRIVER_NL80211  
  4.     &wpa_driver_nl80211_ops,  
  5. #endif /* CONFIG_DRIVER_NL80211 */  
  6. #ifdef CONFIG_DRIVER_WEXT  
  7.     &wpa_driver_wext_ops,  
  8. #endif /* CONFIG_DRIVER_WEXT */  
  9. #ifdef CONFIG_DRIVER_HOSTAP  
  10.     &wpa_driver_hostap_ops,  
  11. #endif /* CONFIG_DRIVER_HOSTAP */  
  12. #ifdef CONFIG_DRIVER_MADWIFI  
  13.     &wpa_driver_madwifi_ops,  
  14. #endif /* CONFIG_DRIVER_MADWIFI */  
  15. #ifdef CONFIG_DRIVER_BSD  
  16.     &wpa_driver_bsd_ops,  
  17. #endif /* CONFIG_DRIVER_BSD */  
  18. #ifdef CONFIG_DRIVER_OPENBSD  
  19.     &wpa_driver_openbsd_ops,  
  20. #endif /* CONFIG_DRIVER_OPENBSD */  
  21. #ifdef CONFIG_DRIVER_NDIS  
  22.     &wpa_driver_ndis_ops,  
  23. #endif /* CONFIG_DRIVER_NDIS */  
  24. #ifdef CONFIG_DRIVER_WIRED  
  25.     &wpa_driver_wired_ops,  
  26. #endif /* CONFIG_DRIVER_WIRED */  
  27. #ifdef CONFIG_DRIVER_TEST  
  28.     &wpa_driver_test_ops,  
  29. #endif /* CONFIG_DRIVER_TEST */  
  30. #ifdef CONFIG_DRIVER_ROBOSWITCH  
  31.     &wpa_driver_roboswitch_ops,  
  32. #endif /* CONFIG_DRIVER_ROBOSWITCH */  
  33. #ifdef CONFIG_DRIVER_ATHEROS  
  34.     &wpa_driver_atheros_ops,  
  35. #endif /* CONFIG_DRIVER_ATHEROS */  
  36. #ifdef CONFIG_DRIVER_NONE  
  37.     &wpa_driver_none_ops,  
  38. #endif /* CONFIG_DRIVER_NONE */  
  39.     NULL  
  40. };  
wpa_drivers数组成员指向一个wpa_driver_ops类型的对象。wpa_driver_ops是driver i/f模块的核心数据结构,其内部定义了很多函数指针。

[-->driver_nl80211.c::wpa_driver_nl80211_ops]

[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. const struct wpa_driver_ops wpa_driver_nl80211_ops = {  
  2.     .name = "nl80211",  
  3.     .desc = "Linux nl80211/cfg80211",  
  4.     .get_bssid = wpa_driver_nl80211_get_bssid,  
  5.     .get_ssid = wpa_driver_nl80211_get_ssid,  
  6.     .set_key = driver_nl80211_set_key,  
  7.     .scan2 = driver_nl80211_scan2,  
  8.     .sched_scan = wpa_driver_nl80211_sched_scan,  
  9.     .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,  
  10.     .get_scan_results2 = wpa_driver_nl80211_get_scan_results,  
  11.     .deauthenticate = driver_nl80211_deauthenticate,  
  12.     .authenticate = driver_nl80211_authenticate,  
  13.     .associate = wpa_driver_nl80211_associate,  
  14.     .global_init = nl80211_global_init,  
  15.     .global_deinit = nl80211_global_deinit,  
  16.     .init2 = wpa_driver_nl80211_init,  
  17.     .deinit = driver_nl80211_deinit,  
  18.     .get_capa = wpa_driver_nl80211_get_capa,  
  19.     .set_operstate = wpa_driver_nl80211_set_operstate,  
  20.     .set_supp_port = wpa_driver_nl80211_set_supp_port,  
  21.     .set_country = wpa_driver_nl80211_set_country,  
  22.     .set_ap = wpa_driver_nl80211_set_ap,  
  23.     .set_acl = wpa_driver_nl80211_set_acl,  
  24.     .if_add = wpa_driver_nl80211_if_add,  
  25.     .if_remove = driver_nl80211_if_remove,  
  26.     .send_mlme = driver_nl80211_send_mlme,  
  27.     .get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data,  
  28.     .sta_add = wpa_driver_nl80211_sta_add,  
  29.     .sta_remove = driver_nl80211_sta_remove,  
  30.     .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,  
  31.     .sta_set_flags = wpa_driver_nl80211_sta_set_flags,  
  32. #ifdef HOSTAPD  
  33.     .hapd_init = i802_init,  
  34.     .hapd_deinit = i802_deinit,  
  35.     .set_wds_sta = i802_set_wds_sta,  
  36. #endif /* HOSTAPD */  
  37. #if defined(HOSTAPD) || defined(CONFIG_AP)  
  38.     .get_seqnum = i802_get_seqnum,  
  39.     .flush = i802_flush,  
  40.     .get_inact_sec = i802_get_inact_sec,  
  41.     .sta_clear_stats = i802_sta_clear_stats,  
  42.     .set_rts = i802_set_rts,  
  43.     .set_frag = i802_set_frag,  
  44.     .set_tx_queue_params = i802_set_tx_queue_params,  
  45.     .set_sta_vlan = driver_nl80211_set_sta_vlan,  
  46.     .sta_deauth = i802_sta_deauth,  
  47.     .sta_disassoc = i802_sta_disassoc,  
  48. #endif /* HOSTAPD || CONFIG_AP */  
  49.     .read_sta_data = driver_nl80211_read_sta_data,  
  50.     .set_freq = i802_set_freq,  
  51.     .send_action = driver_nl80211_send_action,  
  52.     .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait,  
  53.     .remain_on_channel = wpa_driver_nl80211_remain_on_channel,  
  54.     .cancel_remain_on_channel =  
  55.     wpa_driver_nl80211_cancel_remain_on_channel,  
  56.     .probe_req_report = driver_nl80211_probe_req_report,  
  57.     .deinit_ap = wpa_driver_nl80211_deinit_ap,  
  58.     .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,  
  59.     .resume = wpa_driver_nl80211_resume,  
  60.     .send_ft_action = nl80211_send_ft_action,  
  61.     .signal_monitor = nl80211_signal_monitor,  
  62.     .signal_poll = nl80211_signal_poll,  
  63.     .send_frame = nl80211_send_frame,  
  64.     .shared_freq = wpa_driver_nl80211_shared_freq,  
  65.     .set_param = nl80211_set_param,  
  66.     .get_radio_name = nl80211_get_radio_name,  
  67.     .add_pmkid = nl80211_add_pmkid,  
  68.     .remove_pmkid = nl80211_remove_pmkid,  
  69.     .flush_pmkid = nl80211_flush_pmkid,  
  70.     .set_rekey_info = nl80211_set_rekey_info,  
  71.     .poll_client = nl80211_poll_client,  
  72.     .set_p2p_powersave = nl80211_set_p2p_powersave,  
  73.     .start_dfs_cac = nl80211_start_radar_detection,  
  74.     .stop_ap = wpa_driver_nl80211_stop_ap,  
  75. #ifdef CONFIG_TDLS  
  76.     .send_tdls_mgmt = nl80211_send_tdls_mgmt,  
  77.     .tdls_oper = nl80211_tdls_oper,  
  78. #endif /* CONFIG_TDLS */  
  79.     .update_ft_ies = wpa_driver_nl80211_update_ft_ies,  
  80.     .get_mac_addr = wpa_driver_nl80211_get_macaddr,  
  81.     .get_survey = wpa_driver_nl80211_get_survey,  
  82. #ifdef ANDROID_P2P  
  83.     .set_noa = wpa_driver_set_p2p_noa,  
  84.     .get_noa = wpa_driver_get_p2p_noa,  
  85.     .set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie,  
  86. #endif  
  87. #ifdef ANDROID  
  88.     .driver_cmd = wpa_driver_nl80211_driver_cmd,  
  89. #endif  
  90. };  

待续。。。


0 0
原创粉丝点击