【wpa_supplicant】Day 2命令及控制
作者:互联网
文章目录
命令
WPAS对外通过控制接口模块与客户端通信。在Android平台中,WPAS的客户端是位于Framework中的WifiService。用户在Settings界面进行Wi-Fi相关的操作最终都会经由WifiService通过发送命令的方式转交给wpa_supplicant去执行。
WPAS定义了许多命令,常见的:
- PING:心跳检测命令。客户端用它判断WPAS是否工作正常。WPAS收到”PING”命令后需要回复“PONG”。
- MIB:客户端用该命令获取设备的MIB信息。
- STATUS:客户端用该命令来获取WPAS的工作状态。
- ADD_NETWORK:为WPAS添加一个新的无线网络。它将返回此新无线网络的id(从0开始)。注意:此network id非常重要,客户端后续将通过它来指明自己想操作的无线网络。
- SET_NETWORK :network id是无线网络的id。此命令用于设置指定无线网络的信息。其中variable为参数名,value为参数的值。
- ENABLE_NETWORK:使能某个无线网络。此命令最终将促使WPAS发起一系列操作以加入该无线网络。
除了接收来自Client的命令外,WPAS也会主动给Client发送命令。例如,WPAS需用户为某个无线网络输入密码。这类命令称之为Interactive Request,其格式如下。
WPAS向客户端发送的命令遵循以下格式:
CTRL-REQ-<field name>-<network id>-<human readable text>
如 CTRL-REQ-PASSWORD-0-Passwork needed for SSID test-network 这条命令表示需要用户为0号网络输入密码。
客户端处理完后,需回复
CTRL-RSP-<field name>-<network id>-<value>
目前支持的field包括PASSWORD、IDENTITY(EAP中的identity或者用户名)、PIN等
/** Interactive request for identity/password/pin */
#define WPA_CTRL_REQ "CTRL-REQ-"
/** Response to identity/password/pin request */
#define WPA_CTRL_RSP "CTRL-RSP-"
最后,WPAS还可通过形如“CTRL-EVENT--
提示:除了“CTRL-EVENT-XXX”之外,WPAS还支持形如“WPA:XXX”和“WPS-XXX”的通知事件。这些事件和WPA和WPS有关
控制
Android平台中WifiService是WPAS的客户端,它和WPAS交互时必须使用wpa_supplicant提供的API。这些API声明于wpa_ctrl.h中,其用法如下:
//必须包含此头文件,链接时需包含libwpa_client.so动态库
#include “wpa_ctrl.h”
客户端使用wpa_ctrl时首先要分配控制对象。下面两个API用于创建和销毁控制对象wpa_ctrl:
//创建一个wpa控制端对象wpa_ctrl。Android平台中,参数ctrl_path代表unix域socket的位置
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);
void wpa_ctrl_close(struct wpa_ctrl *ctrl);//注销wpa_ctrl控制对象
/**
* wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd
* @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used.
* Returns: Pointer to abstract control interface data or %NULL on failure
*
* This function is used to open a control interface to wpa_supplicant/hostapd.
* ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path
* is configured in wpa_supplicant/hostapd and other programs using the control
* interface need to use matching path configuration.
*/
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);
/**
* wpa_ctrl_open2 - Open a control interface to wpa_supplicant/hostapd
* @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used.
* @cli_path: Path for client UNIX domain sockets; ignored if UDP socket
* is used.
* Returns: Pointer to abstract control interface data or %NULL on failure
*
* This function is used to open a control interface to wpa_supplicant/hostapd
* when the socket path for client need to be specified explicitly. Default
* ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd and client
* socket path is /tmp.
*/
struct wpa_ctrl * wpa_ctrl_open2(const char *ctrl_path, const char *cli_path);
/**
* wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd
* @ctrl: Control interface data from wpa_ctrl_open()
*
* This function is used to close a control interface.
*/
void wpa_ctrl_close(struct wpa_ctrl *ctrl);
这两个函数的实现涉及到unix domain socket,相关知识可以看下这个 Linux下的socket演示程序
下面这个函数用于发送命令给WPAS
//客户端发送命令给wpa_supplicant,回复的消息保存在reply中
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,void (*msg_cb)(char *msg, size_t len));
msg_cb是一个回调函数,该参数的设置和WPAS中C/S通信机制的设计有关:
从Client角度来看,它发送给WPAS的命令所对应的回复属于solicited event(意为有请求的事件),而前面所提到的CTRL-EVENT事件(用于通知事件)对应为unsolicited event(意为未请求的事件)。当Client在等待某个命令的回复时,WPAS同时可能有些通知事件要发送给客户端,这些通知事件不是该命令的回复,所以不能通过wpa_ctrl_request的reply参数返回。为了防止丢失这些通知事件,wpa_cli设计了一个msg_cb回调用于客户端在等待命令回复的时候处理那些unsolicited event。
这种一个函数完成两样完全不同的功能的设计实在有些特别,所以wpa_supplicant规定只有打开通知事件监听功能的wpa_ctrl对象才能在wpa_ctrl_request中通过msg_cb获取通知事件。而打开通知事件监听功能相关的API如下所示
//打开通知事件监听功能
int wpa_ctrl_attach(struct wpa_ctrl *ctrl);
//打开通知事件监听功能的wpa_ctrl对象能直接调用下面的函数来接收unsolicited event
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);
如果客户端并不发送命令,而只是想接收Unsolicited event的话,可通过wpa_ctrl_recv函数来达到此目的。
综上所述,单独使用wpa_ctrl_recv和wpa_ctrl_request都不方便
所以,一种常见的用法是:客户端创建两个wpa_ctrl对象来简化自己的逻辑处理:
一个打开了通知事件监听功能的wpa_ctrl对象将只通过wpa_ctrl_recv来接收通知事件。
另外一个wpa_ctrl专职用于发送命令和接收回复。由于没有调用wpa_ctrl_attach,故它不会收到通知事件。
按书上的说法,WifiService startSupplicant时会这么做,但实际上jni方式的调用已经淘汰了,(不知道从哪个安卓大版本开始)用上了HAL,创建两个wpa_ctrl对象的手法也仅在 wpa_cli 中使用了。
标签:ctrl,supplicant,WPAS,Day,path,wpa,客户端 来源: https://blog.csdn.net/AngryDog1024/article/details/122067147