wpa_ Brief description of control interface of supplicant

Posted by igoy on Mon, 17 Jan 2022 05:22:19 +0100

catalogue

1 Description

2 reference

2.1 basic description of function

2.2 logic description

3 application processing

3.1 event notification message description

3.2 code examples

1 Description

This paper aims to use WPA_ The API provided by supplicant controls the wifi module to connect hotspots in STA working mode. wpa_ The supplicant program generally runs in the background (. / wpa_supplicant -B -cwpa_0_8.conf -iwlan0). Users make it do various connection operations through the interface provided by it.

2 reference

http://w1.fi/wpa_supplicant/devel/wpa__ctrl_8h.html#a4e48c0a662d9150ea603e75365748b0b

wpa_supplicant-devel.pdf

https://www.kancloud.cn/alex_wsc/android-wifi-nfc-gps/414067

2.1 basic description of function

struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);

Open WPA_ A control interface of supplicant, parameter ctrl_path is usually / var/run/wpa_supplicant/wlan0, wlan0 is the corresponding network node. When successful, the control structure pointer is returned, and a series of subsequent functions take this pointer as a parameter. NULL on failure.

int wpa_ctrl_attach(struct wpa_ctrl *ctrl);

Register an event notification monitor. Returned on success. Returns - 1 on failure. - 2 if timeout. After the function succeeds, you can use wpa_ctrl_pending and wpa_ctrl_recv handles event notifications.

int wpa_ctrl_pending(struct wpa_ctrl *ctrl);

Check whether there is an event notification to be processed. If there is any, it returns 1, if there is no 0, and if there is an error, it returns - 1.

int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);

Receive an event notification to be processed, save the content in the space pointed to by reply, and save the length of the content in reply_ The space pointed to by Len.

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));

Send a command to wpa_supplicant. cmd and cmd_len describes the command. Reply and reply_len is used to save the response of this command. msg_cb is generally NULL. It returns 0 on success, - 1 on error (sending or receiving failure), and - 2 on timeout.

int wpa_ctrl_detach(struct wpa_ctrl *ctrl);

Log off the event notification monitor. Returns 0 on success, - 1 on error, and - 2 on timeout.

void wpa_ctrl_close(struct wpa_ctrl *ctrl);

Close the control interface.

2.2 logic description

wpa_ The results of the supplicant processing command are divided into two types: STATUS information and event notification. The STATUS information can be understood as a quick response to the command, and the results can be obtained immediately, such as "PING", "LIST_NETWORKS", "STATUS", "ADD_NETWORK"

"SET_NETWORK", "ENABLE_NETWORK", "SAVE_CONFIG", etc. when successful, they can be returned immediately and the results can be saved in the corresponding function parameters. The event notification can be understood as an asynchronous event. For example, "ENABLE_NETWORK" is sent. The command can be returned successfully and immediately, but the process of connecting to the hotspot is complex and time-consuming. Whether the connection is successful or not is told to the user through the event notification.

3 application processing

Find out the relationship with wpa_cli related files, and make these files into library files

By viewing the compilation process information and combining with Makefile, we found wpa_cli related source files, and compile these source files into library files. WPA in makefile_ CLI: add a line under $(objs_c)

AR -crv wpa_cli.a $(OBJS_c). The value of AR is determined by the development environment. For example, arm himix100 Linux AR can get the desired library file.

The application uses the WPA generated above_ cli. A and WPA_ WPA in supplicant package_ ctrl. H to control various connection operations.

3.1 event notification message description

The response message of successful or failed hotspot connection depends on the implementation of the driver, such as printing when the user gives an incorrect SSID or password and cannot connect:

WPA: 4-Way Handshake failed - pre-shared key may be incorrect

CTRL-EVENT-DISCONNECTED bssid=ec:41:18:45:06:5a reason=0

Print on successful connection:

CTRL-EVENT-CONNECTED

Sending commands too frequently will lead to message disorder, which may lead to WPA_ 0_ 8. The content of conf is incomplete,

Therefore, it is recommended not to send commands automatically, waiting for the user to call the API through the GUI to send commands or when a function is required.  

3.2 code examples

By function user_wifiConnectAP_func connects the specified wifi hotspot (pu8EncryptType can be NULL) through the thread user_wifiHdlEvent_thread constantly listens for event notifications.

int user_wifiConnectAP_func(char *pu8SSID, char *pu8Secret, char *pu8EncryptType)
{
    char au8ReplyBuf[2048] = {"\0"};
    size_t reply_len;
	int ret;
	int i;
	int s32NetId = -1;
	char au8Path[128] = {"\0"};
	
	/* wpa_ctrl_open */
    sprintf(au8Path, "/var/run/wpa_supplicant/wlan0");
	g_pstWpaCtrl = wpa_ctrl_open(au8Path);
	if(g_pstWpaCtrl == NULL)
	{
		printf("\x1b[31m""%s %d, wpa_ctrl_open failed:%s!\n""\x1b[0m", __FILE__, __LINE__, strerror(errno));
		return -1;
	}

    /* wpa_ctrl_request ADD_NETWORK */
	memset(au8ReplyBuf, '\0', sizeof(au8ReplyBuf));
	reply_len = sizeof(au8ReplyBuf)-1;
	ret = wpa_ctrl_request(g_pstWpaCtrl, "ADD_NETWORK", strlen("ADD_NETWORK"), au8ReplyBuf, &reply_len, user_msgCb_func);
	if(ret == 0)
	{
		au8ReplyBuf[reply_len] = '\0';
    }

    s32NetId = atoi(au8ReplyBuf);

	/* wpa_ctrl_request SET_NETWORK */
	char au8SsidBuf[128] = {"\0"};
	snprintf(au8SsidBuf, sizeof(au8SsidBuf)-1, "SET_NETWORK %d ssid \"%s\"", s32NetId, pu8SSID);
	memset(au8ReplyBuf, '\0', sizeof(au8ReplyBuf));
	reply_len = sizeof(au8ReplyBuf)-1;
	ret = wpa_ctrl_request(g_pstWpaCtrl, au8SsidBuf, strlen(au8SsidBuf), au8ReplyBuf, &reply_len, user_msgCb_func);
	if(ret == 0)
	{
		au8ReplyBuf[reply_len] = '\0';
		printf("\x1b[32m""%s %d, reply_len:%d, au8ReplyBuf:%s\n""\x1b[0m", __FILE__, __LINE__, reply_len, au8ReplyBuf);
	}
	else
    {
        return -1;
    }

    /* wpa_ctrl_request SET_NETWORK */
	char au8PskBuf[128] = {"\0"};
	snprintf(au8PskBuf, sizeof(au8PskBuf)-1, "SET_NETWORK %d psk \"%s\"", s32NetId, pu8Secret);
	memset(au8ReplyBuf, '\0', sizeof(au8ReplyBuf));
	reply_len = sizeof(au8ReplyBuf)-1;
	ret = wpa_ctrl_request(g_pstWpaCtrl, au8PskBuf, strlen(au8PskBuf), au8ReplyBuf, &reply_len, user_msgCb_func);
	if(ret == 0)
	{
		au8ReplyBuf[reply_len] = '\0';
		printf("\x1b[32m""%s %d, reply_len:%d, au8ReplyBuf:%s\n""\x1b[0m", __FILE__, __LINE__, reply_len, au8ReplyBuf);
	}
	else
    {
        return -1;
    }

    /* wpa_ctrl_request ENABLE_NETWORK */
	char au8EnableBuf[64] = {"\0"};
	snprintf(au8EnableBuf, sizeof(au8EnableBuf)-1, "ENABLE_NETWORK %d", s32NetId);
	memset(au8ReplyBuf, '\0', sizeof(au8ReplyBuf));
	reply_len = sizeof(au8ReplyBuf)-1;
	ret = wpa_ctrl_request(g_pstWpaCtrl, au8EnableBuf, strlen(au8EnableBuf), au8ReplyBuf, &reply_len, user_msgCb_func);
	if(ret == 0)
	{
		au8ReplyBuf[reply_len] = '\0';
		printf("\x1b[32m""%s %d, reply_len:%d, au8ReplyBuf:%s\n""\x1b[0m", __FILE__, __LINE__, reply_len, au8ReplyBuf);
	}
	else
    {
        return -1;
    }

	return ret;
}

void *user_wifiHdlEvent_thread(void *arg)
{
    char au8ReplyBuf[2048] = {"\0"};
    size_t reply_len;
    int ret;
    char au8Cmdline[64] = {"\0"};

	while(1)
	{
        if(wpa_ctrl_pending(g_pstWpaCtrl) > 0)
        {
            char buf[2048];
            size_t len = sizeof(buf) - 1;
            if(wpa_ctrl_recv(g_pstWpaCtrl, buf, &len) == 0)
            {
                buf[len] = '\0';
                if(strstr(buf, "CTRL-EVENT-CONNECTED") != NULL)
    			{
    			    sprintf(au8Cmdline, "udhcpc -i wlan0 -t 5 -T 2 -A 5 -q");
                    system(au8Cmdline);
                    /* wpa_ctrl_request SAVE_CONFIG */
                    wpa_ctrl_request(g_pstWpaCtrl, "SAVE_CONFIG", strlen("SAVE_CONFIG"), au8ReplyBuf, &reply_len, user_msgCb_func);
    			}
			}
		}
	}
        else
        {
            usleep(100000);
        }
	
	pthread_exit(NULL);
}

Topics: Linux