wpa_cli 的使用方法
在Android中有wpa_cli工具能够直接可wpa_supplicant通讯。能够查看一些wifi的信息。
使用方法:wpa_cli -i wlan0 -p /data/misc/wifi/sockets
wpa_cli源码分析
int main(int argc, char *argv[])
{
···
for (;;) {
c = getopt(argc, argv, "a:Bg:G:hi:p:P:s:v");
if (c < 0)
break;
switch (c) {
case 'a':
action_file = optarg;
break;
case 'B':
daemonize = 1;
break;
case 'g':
global = optarg;
break;
case 'G':
ping_interval = atoi(optarg);
break;
case 'h':
usage();
return 0;
case 'v':
printf("%s\n", wpa_cli_version);
return 0;
case 'i':
os_free(ctrl_ifname);
ctrl_ifname = os_strdup(optarg);
break;
case 'p':
ctrl_iface_dir = optarg;
break;
case 'P':
pid_file = optarg;
break;
case 's':
client_socket_dir = optarg;
break;
default:
usage();
return -1;
}
}
···
if (interactive) {
wpa_cli_interactive();
}
···
···
}
在main函数里面主要就是从命令行中读取参数。之后就是调用wpa_cli_interactive进行建立与supplicant通信的socket,通过读取stdin中的命令与用户进行交互。
static void wpa_cli_interactive(void)
{
printf("\nInteractive mode\n\n");
eloop_register_timeout(0, 0, try_connection, NULL, NULL);
eloop_run();
eloop_cancel_timeout(try_connection, NULL, NULL);
cli_txt_list_flush(&p2p_peers);
cli_txt_list_flush(&p2p_groups);
cli_txt_list_flush(&bsses);
cli_txt_list_flush(&ifnames);
cli_txt_list_flush(&networks);
if (edit_started)
edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
os_free(hfile);
eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
wpa_cli_close_connection();
}
在这个函数里面就是注册try_connection。time到后就可以执行。这里面时间为0,也就是马上执行。
继续对try_connection函数进行分析
static void try_connection(void *eloop_ctx, void *timeout_ctx)
{
···
if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
···
}
···
···
done:
start_edit();
}
这里面就是打开socket用来与wpa_supplicant进行通讯,之后调用start_edit()函数
static void start_edit(void)
{
···
if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
eloop_terminate();
return;
}
···
}
这里面注册了三个callback函数:
- wpa_cli_edit_cmd_cb。查找用户输入命令对应的函数,找到后执行,就是将用户指令发送个supplicant
- wpa_cli_edit_eof_cb,用户交互完毕之后调用。用来结束wpa_cli进程
- wpa_cli_edit_completion_cb,用户输入完毕调用函数。
下面主要分析wpa_cli_edit_cmd_cb函数。
static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
{
char *argv[max_args];
int argc;
argc = tokenize_cmd(cmd, argv);
if (argc)
wpa_request(ctrl_conn, argc, argv);
}
这个函数就是获得用户输入的命令,之后调用wpa_request进行处理。
static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
···
cmd = wpa_cli_commands;
while (cmd->cmd) {
if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
{
match = cmd;
if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
/* we have an exact match */
count = 1;
break;
}
count++;
}
cmd++;
}
···
ret = match->handler(ctrl, argc - 1, &argv[1]);
}
这个函数里面主要就进行了上述的两个工作:
1.查找用户输入命令对应的函数
2.调用对应函数的handler
那么handler是如何定义的呢?
通过源码可以找到这些command都对应一个函数。这些函数都被封装到一个机构题里面。结构体内容如下:
static const struct wpa_cli_cmd wpa_cli_commands[] = {
{
"status", wpa_cli_cmd_status, NULL,
cli_cmd_flag_none,
"[verbose] = get current WPA/EAPOL/EAP status" },
{
"ifname", wpa_cli_cmd_ifname, NULL,
cli_cmd_flag_none,
"= get current interface name" },
{
"ping", wpa_cli_cmd_ping, NULL,
cli_cmd_flag_none,
"= pings wpa_supplicant" },
{
"relog", wpa_cli_cmd_relog, NULL,
cli_cmd_flag_none,
"= re-open log-file (allow rolling logs)" },
{
"note", wpa_cli_cmd_note, NULL,
cli_cmd_flag_none,
"<text> = add a note to wpa_supplicant debug log" },
{
"mib", wpa_cli_cmd_mib, NULL,
cli_cmd_flag_none,
"= get MIB variables (dot1x, dot11)" },
{
"help", wpa_cli_cmd_help, wpa_cli_complete_help,
cli_cmd_flag_none,
"[command] = show usage help" },
{
"interface"