wpa_supplicnt 一般通过如下参数进行启动:
wpa_supplicant -Dnl80211 -iwlan0 -c/etc/wpa_supplicant.conf
其中比较主要的是-c参数, 指定启动配置文件。配置文件的模板路径为 wpa_supplicant/wpa_supplicant.conf
, 官网有对该文件参数的详细描述 。
主要的参数含义:
network={
ssid="simple"
psk="very secret passphrase"
priority=5
}
分析完命令的启动参数,下面进入命令的源码的分析,一步一步剖析, 入口函数: main
int main(int argc, char *argv[])
{
int c, i;
// 重要的数据结构1
struct wpa_interface *ifaces, *iface;
int iface_count, exitcode = -1;
struct wpa_params params;
// 重要的数据结构2
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;
//输入输出重定向到/dev/null
wpa_supplicant_fd_workaround(1);
//参数解析
for (;;) {
c = getopt(argc, argv,
"b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
if (c < 0)
break;
switch (c) {
...
// -c 指定的配置文件wpa_supplicant.conf
case 'c':
iface->confname = optarg;
break;
...
// -D 驱动名称
case 'D':
iface->driver = optarg;
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;
...
//网络接口名称
case 'i':
iface->ifname = optarg;
break;
default:
usage();
exitcode = 0;
goto out;
}
}
exitcode = 0;
//主要函数1 : 创建并初始化一个global
global = wpa_supplicant_init(¶ms);
// fst 初始化
fst_global_init()
#if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
if (!fst_global_add_ctrl(fst_ctrl_cli))
wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
#endif
for (i = 0; exitcode == 0 && i < iface_count; i++) {
struct wpa_supplicant *wpa_s;
// 主要函数2 : 支持多个无线网络设备,
wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL);
}
#ifdef CONFIG_MATCH_IFACE
if (exitcode == 0)
exitcode = wpa_supplicant_init_match(global);
#endif /* CONFIG_MATCH_IFACE */
// 启动, wpa_supplicant 通过epoll 方式实现多路I/O复用
if (exitcode == 0)
exitcode = wpa_supplicant_run(global);
// 释放相关资源
wpa_supplicant_deinit(global);
fst_global_deinit();
out:
wpa_supplicant_fd_workaround(0);
os_free(ifaces);
#ifdef CONFIG_MATCH_IFACE
os_free(params.match_ifaces);
#endif /* CONFIG_MATCH_IFACE */
os_free(params.pid_file);
os_program_deinit();
return exitcode;
}
main 函数中出现的几个重要的数据接口和主要函数做进一步分析 :
首先看下wpa_interface数据接口,每个变量名有相应的注释,比较好明白意思
/**
* struct wpa_interface - Parameters for wpa_supplicant_add_iface()
*/
struct wpa_interface {
/**
* confname - Configuration name (file or profile) name
*
* This can also be %NULL when a configuration file is not used. In
* that case, ctrl_interface must be set to allow the interface to be
* configured.
*/
// 配置文件名,也就是-c 指定的wpa_supplicant.conf
const char *confname;
/**
* confanother - Additional configuration name (file or profile) name
*
* This can also be %NULL when the additional configuration file is not
* used.
*/
const char *confanother;
/**
* ctrl_interface - Control interface parameter
*
* If a configuration file is not used, this variable can be used to
* set the ctrl_interface parameter that would have otherwise been read
* from the configuration file. If both confname and ctrl_interface are
* set, ctrl_interface is used to override the value from configuration
* file.
*/
// 控制接口unix socket 地址,配置文件中ctrl_interface指定的
const char *ctrl_interface;
/**
* driver - Driver interface name, or %NULL to use the default driver
*/
//驱动接口,代表nl80211
const char *driver;
/**
* driver_param - Driver interface parameters
*
* If a configuration file is not used, this variable can be used to
* set the driver_param parameters that would have otherwise been read
* from the configuration file. If both confname and driver_param are
* set, driver_param is used to override the value from configuration
* file.
*/
const char *driver_param;
/**
* ifname - Interface name
*/
//网络接口设备,代表wlan0
const char *ifname;
/**
* bridge_ifname - Optional bridge interface name
*
* If the driver interface (ifname) is included in a Linux bridge
* device, the bridge interface may need to be used for receiving EAPOL
* frames. This can be enabled by setting this variable to enable
* receiving of EAPOL frames from an additional interface.
*/
const char *bridge_ifname;
/**
* p2p_mgmt - Interface used for P2P management (P2P Device operations)
*
* Indicates whether wpas_p2p_init() must be called for this interface.
* This is used only when the driver supports a dedicated P2P Device
* interface that is not a network interface.
*/
int p2p_mgmt;
};
/**
* struct wpa_global - Internal, global data for all %wpa_supplicant interfaces
*
* This structure is initialized by calling wpa_supplicant_init() when starting
* %wpa_supplicant.
*/
struct wpa_global {
//核心数据结构
struct wpa_supplicant *ifaces;
//运行时参数
struct wpa_params params;
//全局控制接口
struct ctrl_iface_global_priv *ctrl_iface;
//dbug通信, 暂时用不到
struct wpas_dbus_priv *dbus;
struct wpas_binder_priv *binder;
//driver wrapper上下文信息
void **drv_priv;
//driver wrapper个数
size_t drv_count;
struct os_time suspend_time;
struct p2p_data *p2p;
struct wpa_supplicant *p2p_init_wpa_s;
struct wpa_supplicant *p2p_group_formation;
struct wpa_supplicant *p2p_invite_group;
u8 p2p_dev_addr[ETH_ALEN];
struct os_reltime p2p_go_wait_client;
struct dl_list p2p_srv_bonjour; /* struct p2p_srv_bonjour */
struct dl_list p2p_srv_upnp; /* struct p2p_srv_upnp */
int p2p_disabled;
int cross_connection;
struct wpa_freq_range_list p2p_disallow_freq;
struct wpa_freq_range_list p2p_go_avoid_freq;
enum wpa_conc_pref {
WPA_CONC_PREF_NOT_SET,
WPA_CONC_PREF_STA,
WPA_CONC_PREF_P2P
} conc_pref;
unsigned int p2p_per_sta_psk:1;
unsigned int p2p_fail_on_wps_complete:1;
unsigned int p2p_24ghz_social_channels:1;
unsigned int pending_p2ps_group:1;
unsigned int pending_group_iface_for_p2ps:1;
unsigned int pending_p2ps_group_freq;
#ifdef CONFIG_WIFI_DISPLAY
int wifi_display;
#define MAX_WFD_SUBELEMS 10
struct wpabuf *wfd_subelem[MAX_WFD_SUBELEMS];
#endif /* CONFIG_WIFI_DISPLAY */
struct psk_list_entry *add_psk; /* From group formation */
};
下一篇文章会继续针对关键函数wpa_supplicant_init 进行分析。