一、环境介绍
- 硬件环境:Freescale IMX283
- 软件环境:Linux
- WI-FI驱动:rtl8192eu
- Wpa_supplicant版本:2.6
二、wpa_supplicant_add_iface() 代码实现
wpa_supplicant的main函数中的调用代码如下:
struct wpa_supplicant *wpa_s;
wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL);
if (wpa_s == NULL) {
exitcode = -1;
break;
}
其函数原型为:
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
struct wpa_interface *iface,
struct wpa_supplicant *parent);
其中参数为 global 为 wpa_supplicant_init() 的返回值, iface 为 struct wpa_interface *ifaces 结构, parent 为 此处NULL;
2.1 重要结构体 struct wpa_interface
struct wpa_interface 的参数成员及说明如下:
成员 | 类型 | 说明 |
confname | const char * | 配置文件,wpa_supplicant.conf |
confanother | const char * | 暂时不用 |
ctrl_interface | const char * | 控制接口文件 |
driver | const char * | 底层驱动选择,如wext、nl80211等; |
driver_param | const char * | 驱动参数,这里暂时不用 |
ifname | const char * | 网络节点名称,如wlan0 |
bridge_ifname | const char * | 桥接时使用,如br0,较少使用 |
p2p_mgmt | int | p2p管理,暂时没用 |
2.2 wpa_supplicant_add_iface 函数逻辑
main函数中调用 wpa_supplicant_add_iface ,增加一个网络接口,这个函数内容比较丰富。
/**
* wpa_supplicant_add_iface - Add a new network interface
* @global: Pointer to global data from wpa_supplicant_init()
* @iface: Interface configuration options
* @parent: Parent interface or %NULL to assign new interface as parent
* Returns: Pointer to the created interface or %NULL on failure
*
* This function is used to add new network interfaces for %wpa_supplicant.
* This can be called before wpa_supplicant_run() to add interfaces before the
* main event loop has been started. In addition, new interfaces can be added
* dynamically while %wpa_supplicant is already running. This could happen,
* e.g., when a hotplug network adapter is inserted.
*/
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
struct wpa_interface *iface,
struct wpa_supplicant *parent)
{
struct wpa_supplicant *wpa_s;
struct wpa_interface t_iface;
struct wpa_ssid *ssid;
if (global == NULL || iface == NULL)
return NULL;
/* 申请wpa_supplicant结构 */
wpa_s = wpa_supplicant_alloc(parent);
if (wpa_s == NULL)
return NULL;
wpa_s->global = global; //global 由 wpa_supplicant_init() 返回
t_iface = *iface; // 将ifcace的内容赋值到局部变量t_iface中
/* 如果配置了override_driver,则用override_driver 覆盖通过-D传递的指定驱动 */
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;
}
/* 如果配置了 override_ctrl_interface ,则用 override_ctrl_interface 覆盖通过-g传递的指定接口文件 */
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;
}
/* 主要是通过conf文件,t_ifcace的内容初始化 wpa_s */
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;
}
/* p2p 方面内容 暂时未用 */
if (iface->p2p_mgmt == 0) {
/* 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; // global的ifaces指针指向 wpa_s
wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); //wpa_s->wpa_state 设置为断开状态
#ifdef CONFIG_P2P
if (wpa_s->global->p2p == NULL &&
!wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
wpas_p2p_add_p2pdev_interface(
wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
wpa_printf(MSG_INFO,
"P2P: Failed to enable P2P Device interface");
/* Try to continue without. P2P will be disabled. */
}
#endif /* CONFIG_P2P */
return wpa_s;
}
三、代码逻辑及过程详述
提炼一下上述整个过程:
wpa_supplicant_add_iface()
|- wpa_supplicant_alloc()
|- wpa_supplicant_init_iface()
|- wpa_supplicant_set_state()
上述红色部分的过程将展开讲述下,以逐步建立对 wpa_supplicant 的理解,其中最为重要的wpa_supplicant_init_iface();
3.1 wpa_supplicant_init_iface()
该代码主要是通过配置文件进行初始化网络接口相关配置,这个函数的实现下一章节进行阐述;这个接口将对struct wpa_supplicant 结构 wpa_s 进行初始化操作。
3.2 wpa_supplicant_set_state()
/**
* wpa_supplicant_set_state - Set current connection state
* @wpa_s: Pointer to wpa_supplicant data
* @state: The new connection state
*
* This function is called whenever the connection state changes, e.g.,
* association is completed for WPA/WPA2 4-Way Handshake is started.
*/
void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
enum wpa_states state)
{
……
else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING || state == WPA_ASSOCIATED) {
wpa_s->new_connection = 1;
wpa_drv_set_operstate(wpa_s, 0);
#ifndef IEEE8021X_EAPOL
wpa_drv_set_supp_port(wpa_s, 0);
#endif /* IEEE8021X_EAPOL */
sme_sched_obss_scan(wpa_s, 0);
}
wpa_s->wpa_state = state;
……
if (wpa_s->wpa_state != old_state) {
wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
/*
* Notify the P2P Device interface about a state change in one
* of the interfaces.
*/
wpas_p2p_indicate_state_change(wpa_s);
if (wpa_s->wpa_state == WPA_COMPLETED ||
old_state == WPA_COMPLETED)
wpas_notify_auth_changed(wpa_s);
}
}