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

下面我们将接上一篇文章继续分析main中第二个关键函数wpa_supplicant_add_iface。

wpa_supplicant_add_iface用于向wpa_supplicant添加接口设备。所谓的添加(add iface),其实就是初始化这些设备。

[wpa_supplicant.c::wpa_supplicant_add_iface]

  1. struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,  
  2.                          struct wpa_interface *iface)  
  3. {  
  4.     struct wpa_supplicant *wpa_s;  
  5.     struct wpa_interface t_iface;  
  6.     struct wpa_ssid *ssid;  
  7.   
  8.     if (global == NULL || iface == NULL)  
  9.         return NULL;  
  10.   
  11.     wpa_s = wpa_supplicant_alloc();  
  12.     if (wpa_s == NULL)  
  13.         return NULL;  
  14.   
  15.     wpa_s->global = global;  
  16.   
  17.     t_iface = *iface;  
  18.     if (global->params.override_driver) {  
  19.         wpa_printf(MSG_DEBUG, "Override interface parameter: driver "  
  20.                "('%s' -> '%s')",  
  21.                iface->driver, global->params.override_driver);  
  22.         t_iface.driver = global->params.override_driver;  
  23.     }  
  24.     if (global->params.override_ctrl_interface) {  
  25.         wpa_printf(MSG_DEBUG, "Override interface parameter: "  
  26.                "ctrl_interface ('%s' -> '%s')",  
  27.                iface->ctrl_interface,  
  28.                global->params.override_ctrl_interface);  
  29.         t_iface.ctrl_interface =  
  30.             global->params.override_ctrl_interface;  
  31.     }  
  32.     if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {  
  33.         wpa_printf(MSG_DEBUG, "Failed to add interface %s",  
  34.                iface->ifname);  
  35.         wpa_supplicant_deinit_iface(wpa_s, 0, 0);  
  36.         return NULL;  
  37.     }  
  38.   
  39.     /* Notify the control interfaces about new iface */  
  40.     if (wpas_notify_iface_added(wpa_s)) {  
  41.         wpa_supplicant_deinit_iface(wpa_s, 1, 0);  
  42.         return NULL;  
  43.     }  
  44.   
  45.     for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)  
  46.         wpas_notify_network_added(wpa_s, ssid);  
  47.   
  48.     wpa_s->next = global->ifaces;  
  49.     global->ifaces = wpa_s;  
  50.   
  51.     wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);  
  52.     wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);  
  53.   
  54.     return wpa_s;  
  55. }  
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
						 struct wpa_interface *iface)
{
	struct wpa_supplicant *wpa_s;
	struct wpa_interface t_iface;
	struct wpa_ssid *ssid;

	if (global == NULL || iface == NULL)
		return NULL;

	wpa_s = wpa_supplicant_alloc();
	if (wpa_s == NULL)
		return NULL;

	wpa_s->global = global;

	t_iface = *iface;
	if (global->params.override_driver) {
		wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
			   "('%s' -> '%s')",
			   iface->driver, global->params.override_driver);
		t_iface.driver = global->params.override_driver;
	}
	if (global->params.override_ctrl_interface) {
		wpa_printf(MSG_DEBUG, "Override interface parameter: "
			   "ctrl_interface ('%s' -> '%s')",
			   iface->ctrl_interface,
			   global->params.override_ctrl_interface);
		t_iface.ctrl_interface =
			global->params.override_ctrl_interface;
	}
	if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
		wpa_printf(MSG_DEBUG, "Failed to add interface %s",
			   iface->ifname);
		wpa_supplicant_deinit_iface(wpa_s, 0, 0);
		return NULL;
	}

	/* Notify the control interfaces about new iface */
	if (wpas_notify_iface_added(wpa_s)) {
		wpa_supplicant_deinit_iface(wpa_s, 1, 0);
		return NULL;
	}

	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
		wpas_notify_network_added(wpa_s, ssid);

	wpa_s->next = global->ifaces;
	global->ifaces = wpa_s;

	wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);

	return wpa_s;
}

wpa_supplicant_add_iface的内容非常丰富,包括两个重要数据结构(wpa_supplicant和wpa_ssid)以及一个关键函数wpa_supplicant_init_iface.

1、wpa_ssid结构体

wpa_ssid用于存储某个无线网络的配置信息(如所支持的安全类型、优先级等)它其实是wpa_supplicant.conf中无线网络配置项在代码中的反映(conf文件中每一个network项都对应一个wpa_ssid对象)。它的一些主要数据成员如下所示:

struct wpa_ssid
+next:struct wpa_ssid*  //所有wpa_ssid对象都保存在一个链表中,头指针保存于另外一个结构体wpa_config的变量中
+pnext:struct wpa_ssid*  //wpa_ssid还可按priority保存在另一个链表中,头指针为wpa_config的pssid变量
+id:int  //每一个无线网络都有一个唯一的编号
+priority:int  //该无线对应的priority值,默认为0
+ssid:8*:此无线网络的ssid(即无线网络名)
+ssid_len:size_t  //ssid变量的长度
+bssid:u8数组  //用于保存bssid,数组长度为ETH_ALEN(值为6)
+bssid_set:  //该无线网络是否设置了bssid变量
+psk:u8数组  //数组长度为32,用于保存WPA中的Pre-Shared Key
+psk_set: int  //是否设置了商数的psk参数
+passphrase:char*  //为WPA设置了ASCII字符密码。
+pairwise_cipher:int  //用于单播数据加密的密钥对类型
+group_cipher: int  //用于组播数据加密的密钥对类型
+key_mgmt:int   //密钥管理类型
+proto:int  //该无线网络支持的安全保护类型
+auth_alg:int  //该无线网络支持的身份验证类型
+scan_ssid:int  //是否利用probe request帧扫描此ssid对应的无线网络
+eapol_flags:int //EAPOL选项
+eap:struct eap_peer_config  //eap peer端设置信息
+proactive_key_caching:int  //
+mode:enum wpas_mode  //
+disabled:int  //
wpa_ssid定义的wpas_mode枚举变量
enum wpas_mode{
WPAS_MODE_INFRA = 0,//代表基础结构网络的STA
WPAS_MODE_IBSS = 1,//代表IBSS网络的模式
WPAS_MODE_AP = 2,代表基础结构网络中的AP
WPAS_MODE_P2P_GO = 3,//P2P相关
WPAS_MODE_GROUP_FORMATION = 4,
}mode;





















上表格中一些数据成员非常重要,下面分别介绍:

(1)安全相关成员变量

1)passphrase:该变量只和WPA/WPA2-PSK模式有关,用于存储我们输入的字符串密码。

2)pairwise_cipher和group_cipher:这两个变量和规范中的cipher suite定义有关。

  1. #define WPA_CIPHER_NONE BIT(0)<span style="white-space:pre">      </span>//不保护  
  2. #define WPA_CIPHER_WEP40 BIT(1)<span style="white-space:pre">     </span>//WEP40  
  3. #define WPA_CIPHER_WEP104 BIT(2)<span style="white-space:pre">    </span>//WEP104  
  4. #define WPA_CIPHER_TKIP BIT(3)<span style="white-space:pre">      </span>//TKIP  
  5. #define WPA_CIPHER_CCMP BIT(4)<span style="white-space:pre">      </span>//CCMP  
#define WPA_CIPHER_NONE BIT(0)<span style="white-space:pre">		</span>//不保护
#define WPA_CIPHER_WEP40 BIT(1)<span style="white-space:pre">		</span>//WEP40
#define WPA_CIPHER_WEP104 BIT(2)<span style="white-space:pre">	</span>//WEP104
#define WPA_CIPHER_TKIP BIT(3)<span style="white-space:pre">		</span>//TKIP
#define WPA_CIPHER_CCMP BIT(4)<span style="white-space:pre">		</span>//CCMP
  1. #define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP)  
  2. #define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | \  
  3.                WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)  
#define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP)
#define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | \
		       WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)
3)key_mgmt:该成员和802.11中的AKM(Authentication and Key Managment,身份验证和密钥管理)suite相关。
  1. #define WPA_KEY_MGMT_IEEE8021X BIT(0)  
  2. #define WPA_KEY_MGMT_PSK BIT(1)  
  3. #define WPA_KEY_MGMT_NONE BIT(2)  
  4. #define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)  
  5. #define WPA_KEY_MGMT_WPA_NONE BIT(4)  
  6. #define WPA_KEY_MGMT_FT_IEEE8021X BIT(5)  
  7. #define WPA_KEY_MGMT_FT_PSK BIT(6)  
  8. #define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)  
  9. #define WPA_KEY_MGMT_PSK_SHA256 BIT(8)  
  10. #define WPA_KEY_MGMT_WPS BIT(9)  
  11. #define WPA_KEY_MGMT_SAE BIT(10)  
  12. #define WPA_KEY_MGMT_FT_SAE BIT(11)  
  13. #define WPA_KEY_MGMT_WAPI_PSK BIT(12)  
  14. #define WPA_KEY_MGMT_WAPI_CERT BIT(13)  
  15. #define WPA_KEY_MGMT_CCKM BIT(14)  
#define WPA_KEY_MGMT_IEEE8021X BIT(0)
#define WPA_KEY_MGMT_PSK BIT(1)
#define WPA_KEY_MGMT_NONE BIT(2)
#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
#define WPA_KEY_MGMT_WPA_NONE BIT(4)
#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5)
#define WPA_KEY_MGMT_FT_PSK BIT(6)
#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
#define WPA_KEY_MGMT_WPS BIT(9)
#define WPA_KEY_MGMT_SAE BIT(10)
#define WPA_KEY_MGMT_FT_SAE BIT(11)
#define WPA_KEY_MGMT_WAPI_PSK BIT(12)
#define WPA_KEY_MGMT_WAPI_CERT BIT(13)
#define WPA_KEY_MGMT_CCKM BIT(14)
  1. #define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X)  
#define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X)
4)proto:代表该无线网络支持的安全协议类型。
  1. #define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN)  
#define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN)
  1. #define WPA_PROTO_WPA BIT(0)  
  2. #define WPA_PROTO_RSN BIT(1)  
  3. #define WPA_PROTO_WAPI BIT(2)  
#define WPA_PROTO_WPA BIT(0)
#define WPA_PROTO_RSN BIT(1)
#define WPA_PROTO_WAPI BIT(2)

5)auth_alg:表示该无线网络所支持的身份验证算法。其可取值如下:

  1. #define WPA_AUTH_ALG_OPEN BIT(0)<span style="white-space:pre">        </span>//open system,如果要使用WPA或RSN,必须选择它  
  2. #define WPA_AUTH_ALG_SHARED BIT(1)<span style="white-space:pre">      </span>//Shard Key算法  
  3. #define WPA_AUTH_ALG_LEAP BIT(2)<span style="white-space:pre">        </span>//LEAP算法,LEAP是思科公司提出的身份验证算法  
  4. #define WPA_AUTH_ALG_FT BIT(3)<span style="white-space:pre">          </span>//和FT有关  
  5. #define WPA_AUTH_ALG_SAE BIT(4)  
#define WPA_AUTH_ALG_OPEN BIT(0)<span style="white-space:pre">		</span>//open system,如果要使用WPA或RSN,必须选择它
#define WPA_AUTH_ALG_SHARED BIT(1)<span style="white-space:pre">		</span>//Shard Key算法
#define WPA_AUTH_ALG_LEAP BIT(2)<span style="white-space:pre">		</span>//LEAP算法,LEAP是思科公司提出的身份验证算法
#define WPA_AUTH_ALG_FT BIT(3)<span style="white-space:pre">			</span>//和FT有关
#define WPA_AUTH_ALG_SAE BIT(4)
6)eapol_flags:和动态WEP Key有关

  1. #define EAPOL_FLAG_REQUIRE_KEY_UNICAST BIT(0)  
  2. #define EAPOL_FLAG_REQUIRE_KEY_BROADCAST BIT(1)  
#define EAPOL_FLAG_REQUIRE_KEY_UNICAST BIT(0)
#define EAPOL_FLAG_REQUIRE_KEY_BROADCAST BIT(1)
(2)其他成员变量

1)proactive_key_caching:该变量和OPC(Opportunistic PMK Caching)技术相关。

2)disable:该变量取值为0(代表该无线网络可用)、1(代表该无线网络被禁止使用,但可通过命令来启用它)、2(表示该无线网络和P2P有关)

3)mode:wpa_ssid结构体内部还定义了一个枚举型变量
2、wpa_supplicant结构体

wpa_supplicant结构体定义的成员变量非常多。详细请参考wpa_supplicant_i.h文件。


wpa_supplicant_init_iface函数分析

  1. static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,  
  2.                      struct wpa_interface *iface)  
  3. {  
  4.     const char *ifname, *driver;  
  5.     struct wpa_driver_capa capa;  
  6.   
  7.     wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "  
  8.            "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,  
  9.            iface->confname ? iface->confname : "N/A",  
  10.            iface->driver ? iface->driver : "default",  
  11.            iface->ctrl_interface ? iface->ctrl_interface : "N/A",  
  12.            iface->bridge_ifname ? iface->bridge_ifname : "N/A");  
  13.   
  14.     if (iface->confname) {  
  15. #ifdef CONFIG_BACKEND_FILE  
  16.         wpa_s->confname = os_rel2abs_path(iface->confname);  
  17.         if (wpa_s->confname == NULL) {  
  18.             wpa_printf(MSG_ERROR, "Failed to get absolute path "  
  19.                    "for configuration file '%s'.",  
  20.                    iface->confname);  
  21.             return -1;  
  22.         }  
  23.         wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",  
  24.                iface->confname, wpa_s->confname);  
  25. #else /* CONFIG_BACKEND_FILE */  
  26.         wpa_s->confname = os_strdup(iface->confname);  
  27. #endif /* CONFIG_BACKEND_FILE */  
  28.         wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);  
  29.         if (wpa_s->conf == NULL) {  
  30.             wpa_printf(MSG_ERROR, "Failed to read or parse "  
  31.                    "configuration '%s'.", wpa_s->confname);  
  32.             return -1;  
  33.         }  
  34.         wpa_s->confanother = os_rel2abs_path(iface->confanother);  
  35.         wpa_config_read(wpa_s->confanother, wpa_s->conf);  
  36.   
  37.         /* 
  38.          * Override ctrl_interface and driver_param if set on command 
  39.          * line. 
  40.          */  
  41.         if (iface->ctrl_interface) {  
  42.             os_free(wpa_s->conf->ctrl_interface);  
  43.             wpa_s->conf->ctrl_interface =  
  44.                 os_strdup(iface->ctrl_interface);  
  45.         }  
  46.   
  47.         if (iface->driver_param) {  
  48.             os_free(wpa_s->conf->driver_param);  
  49.             wpa_s->conf->driver_param =  
  50.                 os_strdup(iface->driver_param);  
  51.         }  
  52.   
  53.         if (iface->p2p_mgmt && !iface->ctrl_interface) {  
  54.             os_free(wpa_s->conf->ctrl_interface);  
  55.             wpa_s->conf->ctrl_interface = NULL;  
  56.         }  
  57.     } else  
  58.         wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,  
  59.                              iface->driver_param);  
  60.   
  61.     if (wpa_s->conf == NULL) {  
  62.         wpa_printf(MSG_ERROR, "\nNo configuration found.");  
  63.         return -1;  
  64.     }  
  65.   
  66.     if (iface->ifname == NULL) {  
  67.         wpa_printf(MSG_ERROR, "\nInterface name is required.");  
  68.         return -1;  
  69.     }  
  70.     if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {  
  71.         wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",  
  72.                iface->ifname);  
  73.         return -1;  
  74.     }  
  75.     os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));  
  76.   
  77.     if (iface->bridge_ifname) {  
  78.         if (os_strlen(iface->bridge_ifname) >=  
  79.             sizeof(wpa_s->bridge_ifname)) {  
  80.             wpa_printf(MSG_ERROR, "\nToo long bridge interface "  
  81.                    "name '%s'.", iface->bridge_ifname);  
  82.             return -1;  
  83.         }  
  84.         os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,  
  85.                sizeof(wpa_s->bridge_ifname));  
  86.     }  
  87.   
  88.     /* RSNA Supplicant Key Management - INITIALIZE */  
  89.     eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);  
  90.     eapol_sm_notify_portValid(wpa_s->eapol, FALSE);  
  91.   
  92.     /* Initialize driver interface and register driver event handler before 
  93.      * L2 receive handler so that association events are processed before 
  94.      * EAPOL-Key packets if both become available for the same select() 
  95.      * call. */  
  96.     driver = iface->driver;  
  97. next_driver:  
  98.     if (wpa_supplicant_set_driver(wpa_s, driver) < 0)  
  99.         return -1;  
  100.   
  101.     wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);  
  102.     if (wpa_s->drv_priv == NULL) {  
  103.         const char *pos;  
  104.         pos = driver ? os_strchr(driver, ',') : NULL;  
  105.         if (pos) {  
  106.             wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "  
  107.                 "driver interface - try next driver wrapper");  
  108.             driver = pos + 1;  
  109.             goto next_driver;  
  110.         }  
  111.         wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "  
  112.             "interface");  
  113.         return -1;  
  114.     }  
  115.     if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {  
  116.         wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "  
  117.             "driver_param '%s'", wpa_s->conf->driver_param);  
  118.         return -1;  
  119.     }  
  120.   
  121.     ifname = wpa_drv_get_ifname(wpa_s);  
  122.     if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {  
  123.         wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "  
  124.             "interface name with '%s'", ifname);  
  125.         os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));  
  126.     }  
  127.   
  128.     if (wpa_supplicant_init_wpa(wpa_s) < 0)  
  129.         return -1;  
  130.   
  131.     wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,  
  132.               wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :  
  133.               NULL);  
  134.     wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);  
  135.   
  136.     if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&  
  137.         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,  
  138.                  wpa_s->conf->dot11RSNAConfigPMKLifetime)) {  
  139.         wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "  
  140.             "dot11RSNAConfigPMKLifetime");  
  141.         return -1;  
  142.     }  
  143.   
  144.     if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&  
  145.         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,  
  146.                  wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {  
  147.         wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "  
  148.             "dot11RSNAConfigPMKReauthThreshold");  
  149.         return -1;  
  150.     }  
  151.   
  152.     if (wpa_s->conf->dot11RSNAConfigSATimeout &&  
  153.         wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,  
  154.                  wpa_s->conf->dot11RSNAConfigSATimeout)) {  
  155.         wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "  
  156.             "dot11RSNAConfigSATimeout");  
  157.         return -1;  
  158.     }  
  159.   
  160.     wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,  
  161.                               &wpa_s->hw.num_modes,  
  162.                               &wpa_s->hw.flags);  
  163.   
  164.     if (wpa_drv_get_capa(wpa_s, &capa) == 0) {  
  165.         wpa_s->drv_capa_known = 1;  
  166.         wpa_s->drv_flags = capa.flags;  
  167.         wpa_s->drv_enc = capa.enc;  
  168.         wpa_s->probe_resp_offloads = capa.probe_resp_offloads;  
  169.         wpa_s->max_scan_ssids = capa.max_scan_ssids;  
  170.         wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;  
  171.         wpa_s->sched_scan_supported = capa.sched_scan_supported;  
  172.         wpa_s->max_match_sets = capa.max_match_sets;  
  173.         wpa_s->max_remain_on_chan = capa.max_remain_on_chan;  
  174.         wpa_s->max_stations = capa.max_stations;  
  175.         wpa_s->extended_capa = capa.extended_capa;  
  176.         wpa_s->extended_capa_mask = capa.extended_capa_mask;  
  177.         wpa_s->extended_capa_len = capa.extended_capa_len;  
  178.         wpa_s->num_multichan_concurrent =  
  179.             capa.num_multichan_concurrent;  
  180.     }  
  181.     if (wpa_s->max_remain_on_chan == 0)  
  182.         wpa_s->max_remain_on_chan = 1000;  
  183.   
  184.     /* 
  185.      * Only take p2p_mgmt parameters when P2P Device is supported. 
  186.      * Doing it here as it determines whether l2_packet_init() will be done 
  187.      * during wpa_supplicant_driver_init(). 
  188.      */  
  189.     if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)  
  190.         wpa_s->p2p_mgmt = iface->p2p_mgmt;  
  191.     else  
  192.         iface->p2p_mgmt = 1;  
  193.   
  194.     if (wpa_s->num_multichan_concurrent == 0)  
  195.         wpa_s->num_multichan_concurrent = 1;  
  196.   
  197.     if (wpa_supplicant_driver_init(wpa_s) < 0)  
  198.         return -1;  
  199.   
  200. #ifdef CONFIG_TDLS  
  201.     if ((!iface->p2p_mgmt ||  
  202.          !(wpa_s->drv_flags &  
  203.            WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&  
  204.         wpa_tdls_init(wpa_s->wpa))  
  205.         return -1;  
  206. #endif /* CONFIG_TDLS */  
  207.   
  208.     if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&  
  209.         wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {  
  210.         wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");  
  211.         return -1;  
  212.     }  
  213.   
  214.     if (wpas_wps_init(wpa_s))  
  215.         return -1;  
  216.   
  217.     if (wpa_supplicant_init_eapol(wpa_s) < 0)  
  218.         return -1;  
  219.     wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);  
  220.   
  221.     wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);  
  222.     if (wpa_s->ctrl_iface == NULL) {  
  223.         wpa_printf(MSG_ERROR,  
  224.                "Failed to initialize control interface '%s'.\n"  
  225.                "You may have another wpa_supplicant process "  
  226.                "already running or the file was\n"  
  227.                "left by an unclean termination of wpa_supplicant "  
  228.                "in which case you will need\n"  
  229.                "to manually remove this file before starting "  
  230.                "wpa_supplicant again.\n",  
  231.                wpa_s->conf->ctrl_interface);  
  232.         return -1;  
  233.     }  
  234.   
  235.     wpa_s->gas = gas_query_init(wpa_s);  
  236.     if (wpa_s->gas == NULL) {  
  237.         wpa_printf(MSG_ERROR, "Failed to initialize GAS query");  
  238.         return -1;  
  239.     }  
  240.   
  241. #ifdef CONFIG_P2P  
  242.     if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {  
  243.         wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");  
  244.         return -1;  
  245.     }  
  246. #endif /* CONFIG_P2P */  
  247.   
  248.     if (wpa_bss_init(wpa_s) < 0)  
  249.         return -1;  
  250.   
  251. #ifdef CONFIG_EAP_PROXY  
  252. {  
  253.     size_t len;  
  254.     wpa_s->mnc_len = eap_proxy_get_imsi(wpa_s->imsi, &len);  
  255.     if (wpa_s->mnc_len > 0) {  
  256.         wpa_s->imsi[len] = '\0';  
  257.         wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",  
  258.                wpa_s->imsi, wpa_s->mnc_len);  
  259.     } else {  
  260.         wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");  
  261.     }  
  262. }  
  263. #endif /* CONFIG_EAP_PROXY */  
  264.   
  265.     if (pcsc_reader_init(wpa_s) < 0)  
  266.         return -1;  
  267.   
  268.     if (wpas_init_ext_pw(wpa_s) < 0)  
  269.         return -1;  
  270.   
  271.     return 0;  
  272. }  
static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
				     struct wpa_interface *iface)
{
	const char *ifname, *driver;
	struct wpa_driver_capa capa;

	wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
		   "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
		   iface->confname ? iface->confname : "N/A",
		   iface->driver ? iface->driver : "default",
		   iface->ctrl_interface ? iface->ctrl_interface : "N/A",
		   iface->bridge_ifname ? iface->bridge_ifname : "N/A");

	if (iface->confname) {
#ifdef CONFIG_BACKEND_FILE
		wpa_s->confname = os_rel2abs_path(iface->confname);
		if (wpa_s->confname == NULL) {
			wpa_printf(MSG_ERROR, "Failed to get absolute path "
				   "for configuration file '%s'.",
				   iface->confname);
			return -1;
		}
		wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
			   iface->confname, wpa_s->confname);
#else /* CONFIG_BACKEND_FILE */
		wpa_s->confname = os_strdup(iface->confname);
#endif /* CONFIG_BACKEND_FILE */
		wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
		if (wpa_s->conf == NULL) {
			wpa_printf(MSG_ERROR, "Failed to read or parse "
				   "configuration '%s'.", wpa_s->confname);
			return -1;
		}
		wpa_s->confanother = os_rel2abs_path(iface->confanother);
		wpa_config_read(wpa_s->confanother, wpa_s->conf);

		/*
		 * Override ctrl_interface and driver_param if set on command
		 * line.
		 */
		if (iface->ctrl_interface) {
			os_free(wpa_s->conf->ctrl_interface);
			wpa_s->conf->ctrl_interface =
				os_strdup(iface->ctrl_interface);
		}

		if (iface->driver_param) {
			os_free(wpa_s->conf->driver_param);
			wpa_s->conf->driver_param =
				os_strdup(iface->driver_param);
		}

		if (iface->p2p_mgmt && !iface->ctrl_interface) {
			os_free(wpa_s->conf->ctrl_interface);
			wpa_s->conf->ctrl_interface = NULL;
		}
	} else
		wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
						     iface->driver_param);

	if (wpa_s->conf == NULL) {
		wpa_printf(MSG_ERROR, "\nNo configuration found.");
		return -1;
	}

	if (iface->ifname == NULL) {
		wpa_printf(MSG_ERROR, "\nInterface name is required.");
		return -1;
	}
	if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
		wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
			   iface->ifname);
		return -1;
	}
	os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));

	if (iface->bridge_ifname) {
		if (os_strlen(iface->bridge_ifname) >=
		    sizeof(wpa_s->bridge_ifname)) {
			wpa_printf(MSG_ERROR, "\nToo long bridge interface "
				   "name '%s'.", iface->bridge_ifname);
			return -1;
		}
		os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
			   sizeof(wpa_s->bridge_ifname));
	}

	/* RSNA Supplicant Key Management - INITIALIZE */
	eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
	eapol_sm_notify_portValid(wpa_s->eapol, FALSE);

	/* Initialize driver interface and register driver event handler before
	 * L2 receive handler so that association events are processed before
	 * EAPOL-Key packets if both become available for the same select()
	 * call. */
	driver = iface->driver;
next_driver:
	if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
		return -1;

	wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
	if (wpa_s->drv_priv == NULL) {
		const char *pos;
		pos = driver ? os_strchr(driver, ',') : NULL;
		if (pos) {
			wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
				"driver interface - try next driver wrapper");
			driver = pos + 1;
			goto next_driver;
		}
		wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
			"interface");
		return -1;
	}
	if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
		wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
			"driver_param '%s'", wpa_s->conf->driver_param);
		return -1;
	}

	ifname = wpa_drv_get_ifname(wpa_s);
	if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
		wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
			"interface name with '%s'", ifname);
		os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
	}

	if (wpa_supplicant_init_wpa(wpa_s) < 0)
		return -1;

	wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
			  wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
			  NULL);
	wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);

	if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
	    wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
			     wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
		wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
			"dot11RSNAConfigPMKLifetime");
		return -1;
	}

	if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
	    wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
			     wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
		wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
			"dot11RSNAConfigPMKReauthThreshold");
		return -1;
	}

	if (wpa_s->conf->dot11RSNAConfigSATimeout &&
	    wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
			     wpa_s->conf->dot11RSNAConfigSATimeout)) {
		wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
			"dot11RSNAConfigSATimeout");
		return -1;
	}

	wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
						      &wpa_s->hw.num_modes,
						      &wpa_s->hw.flags);

	if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
		wpa_s->drv_capa_known = 1;
		wpa_s->drv_flags = capa.flags;
		wpa_s->drv_enc = capa.enc;
		wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
		wpa_s->max_scan_ssids = capa.max_scan_ssids;
		wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
		wpa_s->sched_scan_supported = capa.sched_scan_supported;
		wpa_s->max_match_sets = capa.max_match_sets;
		wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
		wpa_s->max_stations = capa.max_stations;
		wpa_s->extended_capa = capa.extended_capa;
		wpa_s->extended_capa_mask = capa.extended_capa_mask;
		wpa_s->extended_capa_len = capa.extended_capa_len;
		wpa_s->num_multichan_concurrent =
			capa.num_multichan_concurrent;
	}
	if (wpa_s->max_remain_on_chan == 0)
		wpa_s->max_remain_on_chan = 1000;

	/*
	 * Only take p2p_mgmt parameters when P2P Device is supported.
	 * Doing it here as it determines whether l2_packet_init() will be done
	 * during wpa_supplicant_driver_init().
	 */
	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
		wpa_s->p2p_mgmt = iface->p2p_mgmt;
	else
		iface->p2p_mgmt = 1;

	if (wpa_s->num_multichan_concurrent == 0)
		wpa_s->num_multichan_concurrent = 1;

	if (wpa_supplicant_driver_init(wpa_s) < 0)
		return -1;

#ifdef CONFIG_TDLS
	if ((!iface->p2p_mgmt ||
	     !(wpa_s->drv_flags &
	       WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
	    wpa_tdls_init(wpa_s->wpa))
		return -1;
#endif /* CONFIG_TDLS */

	if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
	    wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
		wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
		return -1;
	}

	if (wpas_wps_init(wpa_s))
		return -1;

	if (wpa_supplicant_init_eapol(wpa_s) < 0)
		return -1;
	wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);

	wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
	if (wpa_s->ctrl_iface == NULL) {
		wpa_printf(MSG_ERROR,
			   "Failed to initialize control interface '%s'.\n"
			   "You may have another wpa_supplicant process "
			   "already running or the file was\n"
			   "left by an unclean termination of wpa_supplicant "
			   "in which case you will need\n"
			   "to manually remove this file before starting "
			   "wpa_supplicant again.\n",
			   wpa_s->conf->ctrl_interface);
		return -1;
	}

	wpa_s->gas = gas_query_init(wpa_s);
	if (wpa_s->gas == NULL) {
		wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
		return -1;
	}

#ifdef CONFIG_P2P
	if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
		wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
		return -1;
	}
#endif /* CONFIG_P2P */

	if (wpa_bss_init(wpa_s) < 0)
		return -1;

#ifdef CONFIG_EAP_PROXY
{
	size_t len;
	wpa_s->mnc_len = eap_proxy_get_imsi(wpa_s->imsi, &len);
	if (wpa_s->mnc_len > 0) {
		wpa_s->imsi[len] = '\0';
		wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
			   wpa_s->imsi, wpa_s->mnc_len);
	} else {
		wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
	}
}
#endif /* CONFIG_EAP_PROXY */

	if (pcsc_reader_init(wpa_s) < 0)
		return -1;

	if (wpas_init_ext_pw(wpa_s) < 0)
		return -1;

	return 0;
}
1、init_iface初始化的第一个工作是解析运行时配置文件。其中,wpa_s->confname的值为“/data/misc/wifi/wpa_supplicant.conf”,解析函数是wpa_config_read。

  1. struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)  
  2. {  
  3.     FILE *f;  
  4.     char buf[512], *pos;  
  5.     int errors = 0, line = 0;  
  6.     struct wpa_ssid *ssid, *tail = NULL, *head = NULL;  
  7.     struct wpa_cred *cred, *cred_tail = NULL, *cred_head = NULL;  
  8.     struct wpa_config *config;  
  9.     int id = 0;  
  10.     int cred_id = 0;  
  11.   
  12.     if (name == NULL)  
  13.         return NULL;  
  14.     if (cfgp)  
  15.         config = cfgp;  
  16.     else  
  17.         config = wpa_config_alloc_empty(NULL, NULL);  
  18.     if (config == NULL) {  
  19.         wpa_printf(MSG_ERROR, "Failed to allocate config file "  
  20.                "structure");  
  21.         return NULL;  
  22.     }  
  23.     head = config->ssid;  
  24.     cred_head = config->cred;  
  25.   
  26.     wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);  
  27.     f = fopen(name, "r");  
  28.     if (f == NULL) {  
  29.         wpa_printf(MSG_ERROR, "Failed to open config file '%s', "  
  30.                "error: %s", name, strerror(errno));  
  31.         os_free(config);  
  32.         return NULL;  
  33.     }  
  34.   
  35.     while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {  
  36.         if (os_strcmp(pos, "network={") == 0) {  
  37.             ssid = wpa_config_read_network(f, &line, id++);  
  38.             if (ssid == NULL) {  
  39.                 wpa_printf(MSG_ERROR, "Line %d: failed to "  
  40.                        "parse network block.", line);  
  41.                 errors++;  
  42.                 continue;  
  43.             }  
  44.             if (head == NULL) {  
  45.                 head = tail = ssid;  
  46.             } else {  
  47.                 tail->next = ssid;  
  48.                 tail = ssid;  
  49.             }  
  50.             if (wpa_config_add_prio_network(config, ssid)) {  
  51.                 wpa_printf(MSG_ERROR, "Line %d: failed to add "  
  52.                        "network block to priority list.",  
  53.                        line);  
  54.                 errors++;  
  55.                 continue;  
  56.             }  
  57.         } else if (os_strcmp(pos, "cred={") == 0) {  
  58.             cred = wpa_config_read_cred(f, &line, cred_id++);  
  59.             if (cred == NULL) {  
  60.                 wpa_printf(MSG_ERROR, "Line %d: failed to "  
  61.                        "parse cred block.", line);  
  62.                 errors++;  
  63.                 continue;  
  64.             }  
  65.             if (cred_head == NULL) {  
  66.                 cred_head = cred_tail = cred;  
  67.             } else {  
  68.                 cred_tail->next = cred;  
  69.                 cred_tail = cred;  
  70.             }  
  71. #ifndef CONFIG_NO_CONFIG_BLOBS  
  72.         } else if (os_strncmp(pos, "blob-base64-", 12) == 0) {  
  73.             if (wpa_config_process_blob(config, f, &line, pos + 12)  
  74.                 < 0) {  
  75.                 wpa_printf(MSG_ERROR, "Line %d: failed to "  
  76.                        "process blob.", line);  
  77.                 errors++;  
  78.                 continue;  
  79.             }  
  80. #endif /* CONFIG_NO_CONFIG_BLOBS */  
  81.         } else if (wpa_config_process_global(config, pos, line) < 0) {  
  82.             wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "  
  83.                    "line '%s'.", line, pos);  
  84.             errors++;  
  85.             continue;  
  86.         }  
  87.     }  
  88.   
  89.     fclose(f);  
  90.   
  91.     config->ssid = head;  
  92.     wpa_config_debug_dump_networks(config);  
  93.     config->cred = cred_head;  
  94.   
  95. #ifndef WPA_IGNORE_CONFIG_ERRORS  
  96.     if (errors) {  
  97.         wpa_config_free(config);  
  98.         config = NULL;  
  99.         head = NULL;  
  100.     }  
  101. #endif /* WPA_IGNORE_CONFIG_ERRORS */  
  102.   
  103.     return config;  
  104. }  
struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
{
	FILE *f;
	char buf[512], *pos;
	int errors = 0, line = 0;
	struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
	struct wpa_cred *cred, *cred_tail = NULL, *cred_head = NULL;
	struct wpa_config *config;
	int id = 0;
	int cred_id = 0;

	if (name == NULL)
		return NULL;
	if (cfgp)
		config = cfgp;
	else
		config = wpa_config_alloc_empty(NULL, NULL);
	if (config == NULL) {
		wpa_printf(MSG_ERROR, "Failed to allocate config file "
			   "structure");
		return NULL;
	}
	head = config->ssid;
	cred_head = config->cred;

	wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
	f = fopen(name, "r");
	if (f == NULL) {
		wpa_printf(MSG_ERROR, "Failed to open config file '%s', "
			   "error: %s", name, strerror(errno));
		os_free(config);
		return NULL;
	}

	while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {
		if (os_strcmp(pos, "network={") == 0) {
			ssid = wpa_config_read_network(f, &line, id++);
			if (ssid == NULL) {
				wpa_printf(MSG_ERROR, "Line %d: failed to "
					   "parse network block.", line);
				errors++;
				continue;
			}
			if (head == NULL) {
				head = tail = ssid;
			} else {
				tail->next = ssid;
				tail = ssid;
			}
			if (wpa_config_add_prio_network(config, ssid)) {
				wpa_printf(MSG_ERROR, "Line %d: failed to add "
					   "network block to priority list.",
					   line);
				errors++;
				continue;
			}
		} else if (os_strcmp(pos, "cred={") == 0) {
			cred = wpa_config_read_cred(f, &line, cred_id++);
			if (cred == NULL) {
				wpa_printf(MSG_ERROR, "Line %d: failed to "
					   "parse cred block.", line);
				errors++;
				continue;
			}
			if (cred_head == NULL) {
				cred_head = cred_tail = cred;
			} else {
				cred_tail->next = cred;
				cred_tail = cred;
			}
#ifndef CONFIG_NO_CONFIG_BLOBS
		} else if (os_strncmp(pos, "blob-base64-", 12) == 0) {
			if (wpa_config_process_blob(config, f, &line, pos + 12)
			    < 0) {
				wpa_printf(MSG_ERROR, "Line %d: failed to "
					   "process blob.", line);
				errors++;
				continue;
			}
#endif /* CONFIG_NO_CONFIG_BLOBS */
		} else if (wpa_config_process_global(config, pos, line) < 0) {
			wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "
				   "line '%s'.", line, pos);
			errors++;
			continue;
		}
	}

	fclose(f);

	config->ssid = head;
	wpa_config_debug_dump_networks(config);
	config->cred = cred_head;

#ifndef WPA_IGNORE_CONFIG_ERRORS
	if (errors) {
		wpa_config_free(config);
		config = NULL;
		head = NULL;
	}
#endif /* WPA_IGNORE_CONFIG_ERRORS */

	return config;
}
wpa_config和wpa_ssid这两个数据结构都是配置文件中的信息在代码中的实现。
2、wpa_supplicant_set_driver将根据nl80211找到wpa_driver数组中nl80211指定的driver对象wpa_driver_nl80211_ops,然后调用其global_init函数。

global_init是wpa_driver_ops结构体重的一个类型为函数指针的成员变量。

  1. static void * nl80211_global_init(void)  
  2. {  
  3.     struct nl80211_global *global;  
  4.     struct netlink_config *cfg;  
  5.   
  6.     global = os_zalloc(sizeof(*global));  
  7.     if (global == NULL)  
  8.         return NULL;  
  9.     global->ioctl_sock = -1;  
  10.     dl_list_init(&global->interfaces);  
  11.     global->if_add_ifindex = -1;  
  12.   
  13.     cfg = os_zalloc(sizeof(*cfg));  
  14.     if (cfg == NULL)  
  15.         goto err;  
  16.   
  17.     cfg->ctx = global;  
  18.     cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;  
  19.     cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;  
  20.     global->netlink = netlink_init(cfg);  
  21.     if (global->netlink == NULL) {  
  22.         os_free(cfg);  
  23.         goto err;  
  24.     }  
  25.   
  26.     if (wpa_driver_nl80211_init_nl_global(global) < 0)  
  27.         goto err;  
  28.   
  29.     global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);  
  30.     if (global->ioctl_sock < 0) {  
  31.         perror("socket(PF_INET,SOCK_DGRAM)");  
  32.         goto err;  
  33.     }  
  34.   
  35.     return global;  
  36.   
  37. err:  
  38.     nl80211_global_deinit(global);  
  39.     return NULL;  
  40. }  
static void * nl80211_global_init(void)
{
	struct nl80211_global *global;
	struct netlink_config *cfg;

	global = os_zalloc(sizeof(*global));
	if (global == NULL)
		return NULL;
	global->ioctl_sock = -1;
	dl_list_init(&global->interfaces);
	global->if_add_ifindex = -1;

	cfg = os_zalloc(sizeof(*cfg));
	if (cfg == NULL)
		goto err;

	cfg->ctx = global;
	cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
	cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
	global->netlink = netlink_init(cfg);
	if (global->netlink == NULL) {
		os_free(cfg);
		goto err;
	}

	if (wpa_driver_nl80211_init_nl_global(global) < 0)
		goto err;

	global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
	if (global->ioctl_sock < 0) {
		perror("socket(PF_INET,SOCK_DGRAM)");
		goto err;
	}

	return global;

err:
	nl80211_global_deinit(global);
	return NULL;
}
  1. static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)  
  2. {  
  3.     int ret;  
  4.   
  5.     global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);  
  6.     if (global->nl_cb == NULL) {  
  7.         wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "  
  8.                "callbacks");  
  9.         return -1;  
  10.     }  
  11.   
  12.     global->nl = nl_create_handle(global->nl_cb, "nl");  
  13.     if (global->nl == NULL)  
  14.         goto err;  
  15.   
  16.     global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");  
  17.     if (global->nl80211_id < 0) {  
  18.         wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "  
  19.                "found");  
  20.         goto err;  
  21.     }  
  22.   
  23.     global->nl_event = nl_create_handle(global->nl_cb, "event");  
  24.     if (global->nl_event == NULL)  
  25.         goto err;  
  26.   
  27.     ret = nl_get_multicast_id(global, "nl80211""scan");  
  28.     if (ret >= 0)  
  29.         ret = nl_socket_add_membership(global->nl_event, ret);  
  30.     if (ret < 0) {  
  31.         wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "  
  32.                "membership for scan events: %d (%s)",  
  33.                ret, strerror(-ret));  
  34.         goto err;  
  35.     }  
  36.   
  37.     ret = nl_get_multicast_id(global, "nl80211""mlme");  
  38.     if (ret >= 0)  
  39.         ret = nl_socket_add_membership(global->nl_event, ret);  
  40.     if (ret < 0) {  
  41.         wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "  
  42.                "membership for mlme events: %d (%s)",  
  43.                ret, strerror(-ret));  
  44.         goto err;  
  45.     }  
  46.   
  47.     ret = nl_get_multicast_id(global, "nl80211""regulatory");  
  48.     if (ret >= 0)  
  49.         ret = nl_socket_add_membership(global->nl_event, ret);  
  50.     if (ret < 0) {  
  51.         wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "  
  52.                "membership for regulatory events: %d (%s)",  
  53.                ret, strerror(-ret));  
  54.         /* Continue without regulatory events */  
  55.     }  
  56.   
  57.     nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,  
  58.           no_seq_check, NULL);  
  59.     nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,  
  60.           process_global_event, global);  
  61.   
  62.     eloop_register_read_sock(nl_socket_get_fd(global->nl_event),  
  63.                  wpa_driver_nl80211_event_receive,  
  64.                  global->nl_cb, global->nl_event);  
  65.   
  66.     return 0;  
  67.   
  68. err:  
  69.     nl_destroy_handles(&global->nl_event);  
  70.     nl_destroy_handles(&global->nl);  
  71.     nl_cb_put(global->nl_cb);  
  72.     global->nl_cb = NULL;  
  73.     return -1;  
  74. }  
static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
{
	int ret;

	global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
	if (global->nl_cb == NULL) {
		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
			   "callbacks");
		return -1;
	}

	global->nl = nl_create_handle(global->nl_cb, "nl");
	if (global->nl == NULL)
		goto err;

	global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");
	if (global->nl80211_id < 0) {
		wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "
			   "found");
		goto err;
	}

	global->nl_event = nl_create_handle(global->nl_cb, "event");
	if (global->nl_event == NULL)
		goto err;

	ret = nl_get_multicast_id(global, "nl80211", "scan");
	if (ret >= 0)
		ret = nl_socket_add_membership(global->nl_event, ret);
	if (ret < 0) {
		wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
			   "membership for scan events: %d (%s)",
			   ret, strerror(-ret));
		goto err;
	}

	ret = nl_get_multicast_id(global, "nl80211", "mlme");
	if (ret >= 0)
		ret = nl_socket_add_membership(global->nl_event, ret);
	if (ret < 0) {
		wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
			   "membership for mlme events: %d (%s)",
			   ret, strerror(-ret));
		goto err;
	}

	ret = nl_get_multicast_id(global, "nl80211", "regulatory");
	if (ret >= 0)
		ret = nl_socket_add_membership(global->nl_event, ret);
	if (ret < 0) {
		wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
			   "membership for regulatory events: %d (%s)",
			   ret, strerror(-ret));
		/* Continue without regulatory events */
	}

	nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
		  no_seq_check, NULL);
	nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
		  process_global_event, global);

	eloop_register_read_sock(nl_socket_get_fd(global->nl_event),
				 wpa_driver_nl80211_event_receive,
				 global->nl_cb, global->nl_event);

	return 0;

err:
	nl_destroy_handles(&global->nl_event);
	nl_destroy_handles(&global->nl);
	nl_cb_put(global->nl_cb);
	global->nl_cb = NULL;
	return -1;
}
3、wpa_drv_init函数处理单个driver。内部调用init2函数。
  1. static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,  
  2.                       void *global_priv)  
  3. {  
  4.     struct wpa_driver_nl80211_data *drv;  
  5.     struct rfkill_config *rcfg;  
  6.     struct i802_bss *bss;  
  7.   
  8.     if (global_priv == NULL)  
  9.         return NULL;  
  10.     drv = os_zalloc(sizeof(*drv));  
  11.     if (drv == NULL)  
  12.         return NULL;  
  13.     drv->global = global_priv;  
  14.     drv->ctx = ctx;  
  15.     bss = &drv->first_bss;  
  16.     bss->drv = drv;  
  17.     bss->ctx = ctx;  
  18.   
  19.     os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));  
  20.     drv->monitor_ifidx = -1;  
  21.     drv->monitor_sock = -1;  
  22.     drv->eapol_tx_sock = -1;  
  23.     drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;  
  24.   
  25.     if (wpa_driver_nl80211_init_nl(drv)) {  
  26.         os_free(drv);  
  27.         return NULL;  
  28.     }  
  29.   
  30.     if (nl80211_init_bss(bss))  
  31.         goto failed;  
  32.   
  33.     rcfg = os_zalloc(sizeof(*rcfg));  
  34.     if (rcfg == NULL)  
  35.         goto failed;  
  36.     rcfg->ctx = drv;  
  37.     os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));  
  38.     rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;  
  39.     rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;  
  40.     drv->rfkill = rfkill_init(rcfg);  
  41.     if (drv->rfkill == NULL) {  
  42.         wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");  
  43.         os_free(rcfg);  
  44.     }  
  45.   
  46.     if (wpa_driver_nl80211_finish_drv_init(drv))  
  47.         goto failed;  
  48.   
  49.     drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);  
  50.     if (drv->eapol_tx_sock < 0)  
  51.         goto failed;  
  52.   
  53.     if (drv->data_tx_status) {  
  54.         int enabled = 1;  
  55.   
  56.         if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,  
  57.                    &enabled, sizeof(enabled)) < 0) {  
  58.             wpa_printf(MSG_DEBUG,  
  59.                 "nl80211: wifi status sockopt failed\n");  
  60.             drv->data_tx_status = 0;  
  61.             if (!drv->use_monitor)  
  62.                 drv->capa.flags &=  
  63.                     ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;  
  64.         } else {  
  65.             eloop_register_read_sock(drv->eapol_tx_sock,  
  66.                 wpa_driver_nl80211_handle_eapol_tx_status,  
  67.                 drv, NULL);  
  68.         }  
  69.     }  
  70.   
  71.     if (drv->global) {  
  72.         dl_list_add(&drv->global->interfaces, &drv->list);  
  73.         drv->in_interface_list = 1;  
  74.     }  
  75.   
  76.     return bss;  
  77.   
  78. failed:  
  79.     wpa_driver_nl80211_deinit(bss);  
  80.     return NULL;  
  81. }  
static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
				      void *global_priv)
{
	struct wpa_driver_nl80211_data *drv;
	struct rfkill_config *rcfg;
	struct i802_bss *bss;

	if (global_priv == NULL)
		return NULL;
	drv = os_zalloc(sizeof(*drv));
	if (drv == NULL)
		return NULL;
	drv->global = global_priv;
	drv->ctx = ctx;
	bss = &drv->first_bss;
	bss->drv = drv;
	bss->ctx = ctx;

	os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
	drv->monitor_ifidx = -1;
	drv->monitor_sock = -1;
	drv->eapol_tx_sock = -1;
	drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;

	if (wpa_driver_nl80211_init_nl(drv)) {
		os_free(drv);
		return NULL;
	}

	if (nl80211_init_bss(bss))
		goto failed;

	rcfg = os_zalloc(sizeof(*rcfg));
	if (rcfg == NULL)
		goto failed;
	rcfg->ctx = drv;
	os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
	rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
	rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
	drv->rfkill = rfkill_init(rcfg);
	if (drv->rfkill == NULL) {
		wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
		os_free(rcfg);
	}

	if (wpa_driver_nl80211_finish_drv_init(drv))
		goto failed;

	drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
	if (drv->eapol_tx_sock < 0)
		goto failed;

	if (drv->data_tx_status) {
		int enabled = 1;

		if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,
			       &enabled, sizeof(enabled)) < 0) {
			wpa_printf(MSG_DEBUG,
				"nl80211: wifi status sockopt failed\n");
			drv->data_tx_status = 0;
			if (!drv->use_monitor)
				drv->capa.flags &=
					~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
		} else {
			eloop_register_read_sock(drv->eapol_tx_sock,
				wpa_driver_nl80211_handle_eapol_tx_status,
				drv, NULL);
		}
	}

	if (drv->global) {
		dl_list_add(&drv->global->interfaces, &drv->list);
		drv->in_interface_list = 1;
	}

	return bss;

failed:
	wpa_driver_nl80211_deinit(bss);
	return NULL;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值