xref: /wlan-dirver/utils/sigma-dut/wlantest.c (revision f722271e7b368f3d96d247dac8ee42a11e89ad0d)
1cd4e3c3eSJouni Malinen /*
2cd4e3c3eSJouni Malinen  * Sigma Control API DUT (wlantest)
3cd4e3c3eSJouni Malinen  * Copyright (c) 2010-2011, Atheros Communications, Inc.
49d7e31d5SJouni Malinen  * Copyright (c) 2011-2013, 2017, Qualcomm Atheros, Inc.
5cd4e3c3eSJouni Malinen  * All Rights Reserved.
6cd4e3c3eSJouni Malinen  * Licensed under the Clear BSD license. See README for more details.
7cd4e3c3eSJouni Malinen  */
8cd4e3c3eSJouni Malinen 
9cd4e3c3eSJouni Malinen #include "sigma_dut.h"
10cd4e3c3eSJouni Malinen #include <sys/un.h>
11cd4e3c3eSJouni Malinen #include "wlantest_ctrl.h"
12cd4e3c3eSJouni Malinen 
13cd4e3c3eSJouni Malinen 
14cd4e3c3eSJouni Malinen #ifndef ETH_ALEN
15cd4e3c3eSJouni Malinen #define ETH_ALEN 6
16cd4e3c3eSJouni Malinen #endif
17cd4e3c3eSJouni Malinen 
18cd4e3c3eSJouni Malinen int hwaddr_aton(const char *txt, unsigned char *addr);
19cd4e3c3eSJouni Malinen 
20cd4e3c3eSJouni Malinen 
attr_get(u8 * buf,size_t buflen,enum wlantest_ctrl_attr attr,size_t * len)21cd4e3c3eSJouni Malinen static u8 * attr_get(u8 *buf, size_t buflen, enum wlantest_ctrl_attr attr,
22cd4e3c3eSJouni Malinen 		     size_t *len)
23cd4e3c3eSJouni Malinen {
24cd4e3c3eSJouni Malinen 	u8 *pos = buf;
25cd4e3c3eSJouni Malinen 
26cd4e3c3eSJouni Malinen 	while (pos + 8 <= buf + buflen) {
27cd4e3c3eSJouni Malinen 		enum wlantest_ctrl_attr a;
28cd4e3c3eSJouni Malinen 		size_t alen;
29cd4e3c3eSJouni Malinen 		a = WPA_GET_BE32(pos);
30cd4e3c3eSJouni Malinen 		pos += 4;
31cd4e3c3eSJouni Malinen 		alen = WPA_GET_BE32(pos);
32cd4e3c3eSJouni Malinen 		pos += 4;
33cd4e3c3eSJouni Malinen 		if (pos + alen > buf + buflen)
34cd4e3c3eSJouni Malinen 			return NULL;
35cd4e3c3eSJouni Malinen 		if (a == attr) {
36cd4e3c3eSJouni Malinen 			*len = alen;
37cd4e3c3eSJouni Malinen 			return pos;
38cd4e3c3eSJouni Malinen 		}
39cd4e3c3eSJouni Malinen 		pos += alen;
40cd4e3c3eSJouni Malinen 	}
41cd4e3c3eSJouni Malinen 
42cd4e3c3eSJouni Malinen 	return NULL;
43cd4e3c3eSJouni Malinen }
44cd4e3c3eSJouni Malinen 
45cd4e3c3eSJouni Malinen 
attr_hdr_add(u8 * pos,u8 * end,enum wlantest_ctrl_attr attr,size_t len)46cd4e3c3eSJouni Malinen static u8 * attr_hdr_add(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
47cd4e3c3eSJouni Malinen 			 size_t len)
48cd4e3c3eSJouni Malinen {
49cd4e3c3eSJouni Malinen 	if (pos == NULL || end - pos < (int) (8 + len))
50cd4e3c3eSJouni Malinen 		return NULL;
51cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, attr);
52cd4e3c3eSJouni Malinen 	pos += 4;
53cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, len);
54cd4e3c3eSJouni Malinen 	pos += 4;
55cd4e3c3eSJouni Malinen 	return pos;
56cd4e3c3eSJouni Malinen }
57cd4e3c3eSJouni Malinen 
58cd4e3c3eSJouni Malinen 
attr_add_str(u8 * pos,u8 * end,enum wlantest_ctrl_attr attr,const char * str)59cd4e3c3eSJouni Malinen static u8 * attr_add_str(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
60cd4e3c3eSJouni Malinen 			 const char *str)
61cd4e3c3eSJouni Malinen {
62cd4e3c3eSJouni Malinen 	size_t len = strlen(str);
63cd4e3c3eSJouni Malinen 
64cd4e3c3eSJouni Malinen 	if (pos == NULL || end - pos < (int) (8 + len))
65cd4e3c3eSJouni Malinen 		return NULL;
66cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, attr);
67cd4e3c3eSJouni Malinen 	pos += 4;
68cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, len);
69cd4e3c3eSJouni Malinen 	pos += 4;
70cd4e3c3eSJouni Malinen 	memcpy(pos, str, len);
71cd4e3c3eSJouni Malinen 	pos += len;
72cd4e3c3eSJouni Malinen 	return pos;
73cd4e3c3eSJouni Malinen }
74cd4e3c3eSJouni Malinen 
75cd4e3c3eSJouni Malinen 
attr_add_be32(u8 * pos,u8 * end,enum wlantest_ctrl_attr attr,u32 val)76cd4e3c3eSJouni Malinen static u8 * attr_add_be32(u8 *pos, u8 *end, enum wlantest_ctrl_attr attr,
77cd4e3c3eSJouni Malinen 			  u32 val)
78cd4e3c3eSJouni Malinen {
79cd4e3c3eSJouni Malinen 	if (pos == NULL || end - pos < 12)
80cd4e3c3eSJouni Malinen 		return NULL;
81cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, attr);
82cd4e3c3eSJouni Malinen 	pos += 4;
83cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, 4);
84cd4e3c3eSJouni Malinen 	pos += 4;
85cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, val);
86cd4e3c3eSJouni Malinen 	pos += 4;
87cd4e3c3eSJouni Malinen 	return pos;
88cd4e3c3eSJouni Malinen }
89cd4e3c3eSJouni Malinen 
90cd4e3c3eSJouni Malinen 
open_wlantest(void)91cd4e3c3eSJouni Malinen static int open_wlantest(void)
92cd4e3c3eSJouni Malinen {
93cd4e3c3eSJouni Malinen 	int s;
94cd4e3c3eSJouni Malinen 	struct sockaddr_un addr;
95cd4e3c3eSJouni Malinen 
96cd4e3c3eSJouni Malinen 	s = socket(AF_UNIX, SOCK_SEQPACKET, 0);
97cd4e3c3eSJouni Malinen 	if (s < 0) {
98cd4e3c3eSJouni Malinen 		perror("socket");
99cd4e3c3eSJouni Malinen 		return -1;
100cd4e3c3eSJouni Malinen 	}
101cd4e3c3eSJouni Malinen 
102cd4e3c3eSJouni Malinen 	memset(&addr, 0, sizeof(addr));
103cd4e3c3eSJouni Malinen 	addr.sun_family = AF_UNIX;
104b8fc5cc8SPeng Xu 	strlcpy(addr.sun_path + 1, WLANTEST_SOCK_NAME,
105cd4e3c3eSJouni Malinen 		sizeof(addr.sun_path) - 1);
106cd4e3c3eSJouni Malinen 	if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
107cd4e3c3eSJouni Malinen 		perror("connect");
108cd4e3c3eSJouni Malinen 		close(s);
109cd4e3c3eSJouni Malinen 		return -1;
110cd4e3c3eSJouni Malinen 	}
111cd4e3c3eSJouni Malinen 
112cd4e3c3eSJouni Malinen 	return s;
113cd4e3c3eSJouni Malinen }
114cd4e3c3eSJouni Malinen 
115cd4e3c3eSJouni Malinen 
cmd_send_and_recv(int s,const u8 * cmd,size_t cmd_len,u8 * resp,size_t max_resp_len)116cd4e3c3eSJouni Malinen static int cmd_send_and_recv(int s, const u8 *cmd, size_t cmd_len,
117cd4e3c3eSJouni Malinen 			     u8 *resp, size_t max_resp_len)
118cd4e3c3eSJouni Malinen {
119cd4e3c3eSJouni Malinen 	int res;
120cd4e3c3eSJouni Malinen 	enum wlantest_ctrl_cmd cmd_resp;
121cd4e3c3eSJouni Malinen 
122cd4e3c3eSJouni Malinen 	if (send(s, cmd, cmd_len, 0) < 0)
123cd4e3c3eSJouni Malinen 		return -1;
124cd4e3c3eSJouni Malinen 	res = recv(s, resp, max_resp_len, 0);
125cd4e3c3eSJouni Malinen 	if (res < 4)
126cd4e3c3eSJouni Malinen 		return -1;
127cd4e3c3eSJouni Malinen 
128cd4e3c3eSJouni Malinen 	cmd_resp = WPA_GET_BE32(resp);
129cd4e3c3eSJouni Malinen 	if (cmd_resp == WLANTEST_CTRL_SUCCESS)
130cd4e3c3eSJouni Malinen 		return res;
131cd4e3c3eSJouni Malinen 
132cd4e3c3eSJouni Malinen 	return -1;
133cd4e3c3eSJouni Malinen }
134cd4e3c3eSJouni Malinen 
135cd4e3c3eSJouni Malinen 
cmd_simple(int s,enum wlantest_ctrl_cmd cmd)136cd4e3c3eSJouni Malinen static int cmd_simple(int s, enum wlantest_ctrl_cmd cmd)
137cd4e3c3eSJouni Malinen {
138cd4e3c3eSJouni Malinen 	u8 buf[4];
139cd4e3c3eSJouni Malinen 	int res;
140cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(buf, cmd);
141cd4e3c3eSJouni Malinen 	res = cmd_send_and_recv(s, buf, sizeof(buf), buf, sizeof(buf));
142cd4e3c3eSJouni Malinen 	return res < 0 ? -1 : 0;
143cd4e3c3eSJouni Malinen }
144cd4e3c3eSJouni Malinen 
145cd4e3c3eSJouni Malinen 
run_wlantest_simple(struct sigma_dut * dut,struct sigma_conn * conn,enum wlantest_ctrl_cmd cmd)146cd4e3c3eSJouni Malinen static int run_wlantest_simple(struct sigma_dut *dut, struct sigma_conn *conn,
147cd4e3c3eSJouni Malinen 			       enum wlantest_ctrl_cmd cmd)
148cd4e3c3eSJouni Malinen {
149cd4e3c3eSJouni Malinen 	int s, ret;
150cd4e3c3eSJouni Malinen 
151cd4e3c3eSJouni Malinen 	s = open_wlantest();
152cd4e3c3eSJouni Malinen 	if (s < 0) {
153cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
154cd4e3c3eSJouni Malinen 			  "available");
155cd4e3c3eSJouni Malinen 		return 0;
156cd4e3c3eSJouni Malinen 	}
157cd4e3c3eSJouni Malinen 
158cd4e3c3eSJouni Malinen 	ret = cmd_simple(s, cmd);
159cd4e3c3eSJouni Malinen 	close(s);
160cd4e3c3eSJouni Malinen 
161cd4e3c3eSJouni Malinen 	return ret < 0 ? -2 : 1;
162cd4e3c3eSJouni Malinen }
163cd4e3c3eSJouni Malinen 
164cd4e3c3eSJouni Malinen 
cmd_wlantest_version(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)165*f722271eSJouni Malinen static enum sigma_cmd_result cmd_wlantest_version(struct sigma_dut *dut,
166*f722271eSJouni Malinen 						  struct sigma_conn *conn,
167cd4e3c3eSJouni Malinen 						  struct sigma_cmd *cmd)
168cd4e3c3eSJouni Malinen {
169cd4e3c3eSJouni Malinen 	int s;
170cd4e3c3eSJouni Malinen 	u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
171cd4e3c3eSJouni Malinen 	u8 buf[4];
172cd4e3c3eSJouni Malinen 	char *version;
173cd4e3c3eSJouni Malinen 	size_t len;
174cd4e3c3eSJouni Malinen 	int rlen;
175cd4e3c3eSJouni Malinen 	char *rbuf;
176cd4e3c3eSJouni Malinen 
177cd4e3c3eSJouni Malinen 	s = open_wlantest();
178cd4e3c3eSJouni Malinen 	if (s < 0) {
179cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
180cd4e3c3eSJouni Malinen 			  "available");
181cd4e3c3eSJouni Malinen 		return 0;
182cd4e3c3eSJouni Malinen 	}
183cd4e3c3eSJouni Malinen 
184cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(buf, WLANTEST_CTRL_VERSION);
185cd4e3c3eSJouni Malinen 	rlen = cmd_send_and_recv(s, buf, sizeof(buf), resp, sizeof(resp));
186cd4e3c3eSJouni Malinen 	close(s);
187cd4e3c3eSJouni Malinen 	if (rlen < 0)
188cd4e3c3eSJouni Malinen 		return -2;
189cd4e3c3eSJouni Malinen 
190cd4e3c3eSJouni Malinen 	version = (char *) attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_VERSION,
191cd4e3c3eSJouni Malinen 				    &len);
192cd4e3c3eSJouni Malinen 	if (version == NULL)
193cd4e3c3eSJouni Malinen 		return -2;
194cd4e3c3eSJouni Malinen 
195cd4e3c3eSJouni Malinen 	rbuf = malloc(9 + len);
196cd4e3c3eSJouni Malinen 	if (rbuf == NULL)
197cd4e3c3eSJouni Malinen 		return -2;
198cd4e3c3eSJouni Malinen 	memcpy(rbuf, "version,", 8);
199cd4e3c3eSJouni Malinen 	memcpy(rbuf + 8, version, len);
200cd4e3c3eSJouni Malinen 	rbuf[8 + len] = '\0';
201cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, rbuf);
202cd4e3c3eSJouni Malinen 	free(rbuf);
203cd4e3c3eSJouni Malinen 	return 0;
204cd4e3c3eSJouni Malinen }
205cd4e3c3eSJouni Malinen 
206cd4e3c3eSJouni Malinen 
cmd_wlantest_set_channel(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)207*f722271eSJouni Malinen enum sigma_cmd_result cmd_wlantest_set_channel(struct sigma_dut *dut,
208*f722271eSJouni Malinen 					       struct sigma_conn *conn,
209cd4e3c3eSJouni Malinen 					       struct sigma_cmd *cmd)
210cd4e3c3eSJouni Malinen {
211cd4e3c3eSJouni Malinen 	char buf[100];
212cd4e3c3eSJouni Malinen 	const char *chan;
213cd4e3c3eSJouni Malinen 
214cd4e3c3eSJouni Malinen 	if (dut->sniffer_ifname == NULL) {
215cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Sniffer "
216cd4e3c3eSJouni Malinen 			  "interface not available");
217cd4e3c3eSJouni Malinen 		return 0;
218cd4e3c3eSJouni Malinen 	}
219cd4e3c3eSJouni Malinen 
220cd4e3c3eSJouni Malinen 	chan = get_param(cmd, "channel");
221cd4e3c3eSJouni Malinen 	if (chan == NULL)
222cd4e3c3eSJouni Malinen 		return -1;
223cd4e3c3eSJouni Malinen 
224cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "iw dev %s set type monitor",
225cd4e3c3eSJouni Malinen 		 dut->sniffer_ifname);
226cd4e3c3eSJouni Malinen 	if (system(buf) != 0) {
227cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "ifconfig %s down",
228cd4e3c3eSJouni Malinen 			 dut->sniffer_ifname);
229cd4e3c3eSJouni Malinen 		if (system(buf) != 0) {
230cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO,
231cd4e3c3eSJouni Malinen 					"Failed to run '%s'", buf);
232cd4e3c3eSJouni Malinen 			return -2;
233cd4e3c3eSJouni Malinen 		}
234cd4e3c3eSJouni Malinen 
235cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "iw dev %s set type monitor",
236cd4e3c3eSJouni Malinen 			 dut->sniffer_ifname);
237cd4e3c3eSJouni Malinen 		if (system(buf) != 0) {
238cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO,
239cd4e3c3eSJouni Malinen 					"Failed to run '%s'", buf);
240cd4e3c3eSJouni Malinen 			return -2;
241cd4e3c3eSJouni Malinen 		}
242cd4e3c3eSJouni Malinen 	}
243cd4e3c3eSJouni Malinen 
244cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "iw dev %s set channel %d HT20",
245cd4e3c3eSJouni Malinen 		 dut->sniffer_ifname, atoi(chan));
246cd4e3c3eSJouni Malinen 	if (system(buf) != 0) {
247cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to run '%s'", buf);
248cd4e3c3eSJouni Malinen 		return -2;
249cd4e3c3eSJouni Malinen 	}
250cd4e3c3eSJouni Malinen 
251cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "ifconfig %s up", dut->sniffer_ifname);
252cd4e3c3eSJouni Malinen 	if (system(buf) != 0) {
253cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to run '%s'", buf);
254cd4e3c3eSJouni Malinen 		return -2;
255cd4e3c3eSJouni Malinen 	}
256cd4e3c3eSJouni Malinen 
257cd4e3c3eSJouni Malinen 	dut->mode = SIGMA_MODE_SNIFFER;
258cd4e3c3eSJouni Malinen 
259cd4e3c3eSJouni Malinen 	return 1;
260cd4e3c3eSJouni Malinen }
261cd4e3c3eSJouni Malinen 
262cd4e3c3eSJouni Malinen 
cmd_wlantest_flush(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)263*f722271eSJouni Malinen static enum sigma_cmd_result cmd_wlantest_flush(struct sigma_dut *dut,
264*f722271eSJouni Malinen 						struct sigma_conn *conn,
265cd4e3c3eSJouni Malinen 						struct sigma_cmd *cmd)
266cd4e3c3eSJouni Malinen {
267cd4e3c3eSJouni Malinen 	return run_wlantest_simple(dut, conn, WLANTEST_CTRL_FLUSH);
268cd4e3c3eSJouni Malinen }
269cd4e3c3eSJouni Malinen 
270cd4e3c3eSJouni Malinen 
cmd_wlantest_send_frame(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)271*f722271eSJouni Malinen enum sigma_cmd_result cmd_wlantest_send_frame(struct sigma_dut *dut,
272*f722271eSJouni Malinen 					      struct sigma_conn *conn,
273cd4e3c3eSJouni Malinen 					      struct sigma_cmd *cmd)
274cd4e3c3eSJouni Malinen {
275cd4e3c3eSJouni Malinen 	u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
276cd4e3c3eSJouni Malinen 	u8 buf[100], *end, *pos;
277cd4e3c3eSJouni Malinen 	int rlen;
278cd4e3c3eSJouni Malinen 	enum wlantest_inject_frame frame;
279cd4e3c3eSJouni Malinen 	enum wlantest_inject_protection prot;
280cd4e3c3eSJouni Malinen 	const char *val;
281cd4e3c3eSJouni Malinen 	int s;
282cd4e3c3eSJouni Malinen 
283cd4e3c3eSJouni Malinen 	/* wlantest_send_frame,PMFFrameType,disassoc,PMFProtected,Unprotected,sender,AP,bssid,00:11:22:33:44:55,stationID,00:66:77:88:99:aa */
284cd4e3c3eSJouni Malinen 
285cd4e3c3eSJouni Malinen 	if (dut->mode == SIGMA_MODE_STATION) {
286cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert "
287cd4e3c3eSJouni Malinen 				"wlantest_send_frame to sta_send_frame");
288cd4e3c3eSJouni Malinen 		return cmd_sta_send_frame(dut, conn, cmd);
289cd4e3c3eSJouni Malinen 	}
290cd4e3c3eSJouni Malinen 
291cd4e3c3eSJouni Malinen 	if (dut->mode == SIGMA_MODE_AP) {
292cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Convert "
293cd4e3c3eSJouni Malinen 				"wlantest_send_frame to ap_send_frame");
294cd4e3c3eSJouni Malinen 		return cmd_ap_send_frame(dut, conn, cmd);
295cd4e3c3eSJouni Malinen 	}
296cd4e3c3eSJouni Malinen 
297cd4e3c3eSJouni Malinen 	pos = buf;
298cd4e3c3eSJouni Malinen 	end = buf + sizeof(buf);
299cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, WLANTEST_CTRL_INJECT);
300cd4e3c3eSJouni Malinen 	pos += 4;
301cd4e3c3eSJouni Malinen 
302cd4e3c3eSJouni Malinen 	val = get_param(cmd, "Type");
303cd4e3c3eSJouni Malinen 	if (val == NULL)
304cd4e3c3eSJouni Malinen 		val = get_param(cmd, "PMFFrameType");
305cd4e3c3eSJouni Malinen 	if (val == NULL)
306cd4e3c3eSJouni Malinen 		return -1;
307cd4e3c3eSJouni Malinen 	if (strcasecmp(val, "disassoc") == 0)
308cd4e3c3eSJouni Malinen 		frame = WLANTEST_FRAME_DISASSOC;
309cd4e3c3eSJouni Malinen 	else if (strcasecmp(val, "deauth") == 0)
310cd4e3c3eSJouni Malinen 		frame = WLANTEST_FRAME_DEAUTH;
311cd4e3c3eSJouni Malinen 	else if (strcasecmp(val, "saquery") == 0)
312cd4e3c3eSJouni Malinen 		frame = WLANTEST_FRAME_SAQUERYREQ;
313cd4e3c3eSJouni Malinen 	else if (strcasecmp(val, "auth") == 0)
314cd4e3c3eSJouni Malinen 		frame = WLANTEST_FRAME_AUTH;
315cd4e3c3eSJouni Malinen 	else if (strcasecmp(val, "assocreq") == 0)
316cd4e3c3eSJouni Malinen 		frame = WLANTEST_FRAME_ASSOCREQ;
317cd4e3c3eSJouni Malinen 	else if (strcasecmp(val, "reassocreq") == 0)
318cd4e3c3eSJouni Malinen 		frame = WLANTEST_FRAME_REASSOCREQ;
319cd4e3c3eSJouni Malinen 	else {
320cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
321cd4e3c3eSJouni Malinen 			  "PMFFrameType");
322cd4e3c3eSJouni Malinen 		return 0;
323cd4e3c3eSJouni Malinen 	}
324cd4e3c3eSJouni Malinen 	pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_FRAME, frame);
325cd4e3c3eSJouni Malinen 
326cd4e3c3eSJouni Malinen 	val = get_param(cmd, "Protected");
327cd4e3c3eSJouni Malinen 	if (val == NULL)
328cd4e3c3eSJouni Malinen 		val = get_param(cmd, "PMFProtected");
329cd4e3c3eSJouni Malinen 	if (val == NULL)
330cd4e3c3eSJouni Malinen 		return -1;
331cd4e3c3eSJouni Malinen 	if (strcasecmp(val, "CorrectKey") == 0)
332cd4e3c3eSJouni Malinen 		prot = WLANTEST_INJECT_PROTECTED;
333cd4e3c3eSJouni Malinen 	else if (strcasecmp(val, "IncorrectKey") == 0)
334cd4e3c3eSJouni Malinen 		prot = WLANTEST_INJECT_INCORRECT_KEY;
335cd4e3c3eSJouni Malinen 	else if (strcasecmp(val, "Unprotected") == 0)
336cd4e3c3eSJouni Malinen 		prot = WLANTEST_INJECT_UNPROTECTED;
337cd4e3c3eSJouni Malinen 	else {
338cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
339cd4e3c3eSJouni Malinen 			  "PMFProtected");
340cd4e3c3eSJouni Malinen 		return 0;
341cd4e3c3eSJouni Malinen 	}
342cd4e3c3eSJouni Malinen 	pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_PROTECTION, prot);
343cd4e3c3eSJouni Malinen 
344cd4e3c3eSJouni Malinen 	val = get_param(cmd, "sender");
345cd4e3c3eSJouni Malinen 	if (val == NULL)
346cd4e3c3eSJouni Malinen 		return -1;
347cd4e3c3eSJouni Malinen 	if (strcasecmp(val, "ap") == 0) {
348cd4e3c3eSJouni Malinen 		pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
349cd4e3c3eSJouni Malinen 				    1);
350cd4e3c3eSJouni Malinen 	} else if (strcasecmp(val, "sta") == 0) {
351cd4e3c3eSJouni Malinen 		pos = attr_add_be32(pos, end, WLANTEST_ATTR_INJECT_SENDER_AP,
352cd4e3c3eSJouni Malinen 				    0);
353cd4e3c3eSJouni Malinen 	} else {
354cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
355cd4e3c3eSJouni Malinen 			  "sender");
356cd4e3c3eSJouni Malinen 		return 0;
357cd4e3c3eSJouni Malinen 	}
358cd4e3c3eSJouni Malinen 
359cd4e3c3eSJouni Malinen 	val = get_param(cmd, "bssid");
360cd4e3c3eSJouni Malinen 	if (val == NULL)
361cd4e3c3eSJouni Malinen 		return -1;
362cd4e3c3eSJouni Malinen 	pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
363cd4e3c3eSJouni Malinen 	if (hwaddr_aton(val, pos) < 0) {
364cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid bssid");
365cd4e3c3eSJouni Malinen 		return 0;
366cd4e3c3eSJouni Malinen 	}
367cd4e3c3eSJouni Malinen 	pos += ETH_ALEN;
368cd4e3c3eSJouni Malinen 
369cd4e3c3eSJouni Malinen 	val = get_param(cmd, "stationID");
370cd4e3c3eSJouni Malinen 	if (val == NULL)
371cd4e3c3eSJouni Malinen 		return -1;
372cd4e3c3eSJouni Malinen 	pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
373cd4e3c3eSJouni Malinen 	if (hwaddr_aton(val, pos) < 0) {
374cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID,
375cd4e3c3eSJouni Malinen 			  "errorCode,Invalid stationID");
376cd4e3c3eSJouni Malinen 		return 0;
377cd4e3c3eSJouni Malinen 	}
378cd4e3c3eSJouni Malinen 	pos += ETH_ALEN;
379cd4e3c3eSJouni Malinen 
380cd4e3c3eSJouni Malinen 	s = open_wlantest();
381cd4e3c3eSJouni Malinen 	if (s < 0) {
382cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
383cd4e3c3eSJouni Malinen 			  "available");
384cd4e3c3eSJouni Malinen 		return 0;
385cd4e3c3eSJouni Malinen 	}
386cd4e3c3eSJouni Malinen 	rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
387cd4e3c3eSJouni Malinen 	close(s);
388cd4e3c3eSJouni Malinen 	if (rlen < 0)
389cd4e3c3eSJouni Malinen 		return -2;
390cd4e3c3eSJouni Malinen 	return 1;
391cd4e3c3eSJouni Malinen }
392cd4e3c3eSJouni Malinen 
393cd4e3c3eSJouni Malinen 
394*f722271eSJouni Malinen static enum sigma_cmd_result
cmd_wlantest_add_passphrase(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)395*f722271eSJouni Malinen cmd_wlantest_add_passphrase(struct sigma_dut *dut, struct sigma_conn *conn,
396cd4e3c3eSJouni Malinen 			    struct sigma_cmd *cmd)
397cd4e3c3eSJouni Malinen {
398cd4e3c3eSJouni Malinen 	u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
399cd4e3c3eSJouni Malinen 	u8 buf[100], *end, *pos;
400cd4e3c3eSJouni Malinen 	int rlen;
401cd4e3c3eSJouni Malinen 	const char *val;
402cd4e3c3eSJouni Malinen 	int s;
403cd4e3c3eSJouni Malinen 
404cd4e3c3eSJouni Malinen 	pos = buf;
405cd4e3c3eSJouni Malinen 	end = buf + sizeof(buf);
406cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, WLANTEST_CTRL_ADD_PASSPHRASE);
407cd4e3c3eSJouni Malinen 	pos += 4;
408cd4e3c3eSJouni Malinen 
409cd4e3c3eSJouni Malinen 	val = get_param(cmd, "passphrase");
410cd4e3c3eSJouni Malinen 	if (val) {
411cd4e3c3eSJouni Malinen 		if (strlen(val) < 8 || strlen(val) > 63)
412cd4e3c3eSJouni Malinen 			return -1;
413cd4e3c3eSJouni Malinen 		pos = attr_add_str(pos, end, WLANTEST_ATTR_PASSPHRASE, val);
414cd4e3c3eSJouni Malinen 	} else {
415cd4e3c3eSJouni Malinen 		val = get_param(cmd, "wepkey");
416cd4e3c3eSJouni Malinen 		if (!val)
417cd4e3c3eSJouni Malinen 			return -1;
418cd4e3c3eSJouni Malinen 		pos = attr_add_str(pos, end, WLANTEST_ATTR_WEPKEY, val);
419cd4e3c3eSJouni Malinen 	}
420cd4e3c3eSJouni Malinen 	val = get_param(cmd, "bssid");
421cd4e3c3eSJouni Malinen 	if (val) {
422cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
423cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
424cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
425cd4e3c3eSJouni Malinen 				  "errorCode,Invalid bssid");
426cd4e3c3eSJouni Malinen 			return 0;
427cd4e3c3eSJouni Malinen 		}
428cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
429cd4e3c3eSJouni Malinen 	}
430cd4e3c3eSJouni Malinen 
431cd4e3c3eSJouni Malinen 	s = open_wlantest();
432cd4e3c3eSJouni Malinen 	if (s < 0) {
433cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
434cd4e3c3eSJouni Malinen 			  "available");
435cd4e3c3eSJouni Malinen 		return 0;
436cd4e3c3eSJouni Malinen 	}
437cd4e3c3eSJouni Malinen 	rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
438cd4e3c3eSJouni Malinen 	close(s);
439cd4e3c3eSJouni Malinen 	if (rlen < 0)
440cd4e3c3eSJouni Malinen 		return -2;
441cd4e3c3eSJouni Malinen 	return 1;
442cd4e3c3eSJouni Malinen }
443cd4e3c3eSJouni Malinen 
444cd4e3c3eSJouni Malinen 
445*f722271eSJouni Malinen static enum sigma_cmd_result
cmd_wlantest_clear_sta_counters(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)446*f722271eSJouni Malinen cmd_wlantest_clear_sta_counters(struct sigma_dut *dut, struct sigma_conn *conn,
447cd4e3c3eSJouni Malinen 				struct sigma_cmd *cmd)
448cd4e3c3eSJouni Malinen {
449cd4e3c3eSJouni Malinen 	u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
450cd4e3c3eSJouni Malinen 	u8 buf[100], *end, *pos;
451cd4e3c3eSJouni Malinen 	int rlen;
452cd4e3c3eSJouni Malinen 	const char *val;
453cd4e3c3eSJouni Malinen 	int s;
454cd4e3c3eSJouni Malinen 
455cd4e3c3eSJouni Malinen 	pos = buf;
456cd4e3c3eSJouni Malinen 	end = buf + sizeof(buf);
457cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_STA_COUNTERS);
458cd4e3c3eSJouni Malinen 	pos += 4;
459cd4e3c3eSJouni Malinen 
460cd4e3c3eSJouni Malinen 	val = get_param(cmd, "bssid");
461cd4e3c3eSJouni Malinen 	if (val == NULL)
462cd4e3c3eSJouni Malinen 		return -1;
463cd4e3c3eSJouni Malinen 	if (val) {
464cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
465cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
466cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
467cd4e3c3eSJouni Malinen 				  "errorCode,Invalid bssid");
468cd4e3c3eSJouni Malinen 			return 0;
469cd4e3c3eSJouni Malinen 		}
470cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
471cd4e3c3eSJouni Malinen 	}
472cd4e3c3eSJouni Malinen 
473cd4e3c3eSJouni Malinen 	val = get_param(cmd, "stationID");
474cd4e3c3eSJouni Malinen 	if (val == NULL)
475cd4e3c3eSJouni Malinen 		return -1;
476cd4e3c3eSJouni Malinen 	if (val) {
477cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
478cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
479cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
480cd4e3c3eSJouni Malinen 				  "errorCode,Invalid stationID");
481cd4e3c3eSJouni Malinen 			return 0;
482cd4e3c3eSJouni Malinen 		}
483cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
484cd4e3c3eSJouni Malinen 	}
485cd4e3c3eSJouni Malinen 
486cd4e3c3eSJouni Malinen 	s = open_wlantest();
487cd4e3c3eSJouni Malinen 	if (s < 0) {
488cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
489cd4e3c3eSJouni Malinen 			  "available");
490cd4e3c3eSJouni Malinen 		return 0;
491cd4e3c3eSJouni Malinen 	}
492cd4e3c3eSJouni Malinen 	rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
493cd4e3c3eSJouni Malinen 	close(s);
494cd4e3c3eSJouni Malinen 	if (rlen < 0)
495cd4e3c3eSJouni Malinen 		return -2;
496cd4e3c3eSJouni Malinen 	return 1;
497cd4e3c3eSJouni Malinen }
498cd4e3c3eSJouni Malinen 
499cd4e3c3eSJouni Malinen 
500*f722271eSJouni Malinen static enum sigma_cmd_result
cmd_wlantest_clear_bss_counters(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)501*f722271eSJouni Malinen cmd_wlantest_clear_bss_counters(struct sigma_dut *dut, struct sigma_conn *conn,
502cd4e3c3eSJouni Malinen 				struct sigma_cmd *cmd)
503cd4e3c3eSJouni Malinen {
504cd4e3c3eSJouni Malinen 	u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
505cd4e3c3eSJouni Malinen 	u8 buf[100], *end, *pos;
506cd4e3c3eSJouni Malinen 	int rlen;
507cd4e3c3eSJouni Malinen 	const char *val;
508cd4e3c3eSJouni Malinen 	int s;
509cd4e3c3eSJouni Malinen 
510cd4e3c3eSJouni Malinen 	pos = buf;
511cd4e3c3eSJouni Malinen 	end = buf + sizeof(buf);
512cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_BSS_COUNTERS);
513cd4e3c3eSJouni Malinen 	pos += 4;
514cd4e3c3eSJouni Malinen 
515cd4e3c3eSJouni Malinen 	val = get_param(cmd, "bssid");
516cd4e3c3eSJouni Malinen 	if (val == NULL)
517cd4e3c3eSJouni Malinen 		return -1;
518cd4e3c3eSJouni Malinen 	if (val) {
519cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
520cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
521cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
522cd4e3c3eSJouni Malinen 				  "errorCode,Invalid bssid");
523cd4e3c3eSJouni Malinen 			return 0;
524cd4e3c3eSJouni Malinen 		}
525cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
526cd4e3c3eSJouni Malinen 	}
527cd4e3c3eSJouni Malinen 
528cd4e3c3eSJouni Malinen 	s = open_wlantest();
529cd4e3c3eSJouni Malinen 	if (s < 0) {
530cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
531cd4e3c3eSJouni Malinen 			  "available");
532cd4e3c3eSJouni Malinen 		return 0;
533cd4e3c3eSJouni Malinen 	}
534cd4e3c3eSJouni Malinen 	rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
535cd4e3c3eSJouni Malinen 	close(s);
536cd4e3c3eSJouni Malinen 	if (rlen < 0)
537cd4e3c3eSJouni Malinen 		return -2;
538cd4e3c3eSJouni Malinen 	return 1;
539cd4e3c3eSJouni Malinen }
540cd4e3c3eSJouni Malinen 
541cd4e3c3eSJouni Malinen 
542*f722271eSJouni Malinen static enum sigma_cmd_result
cmd_wlantest_clear_tdls_counters(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)543*f722271eSJouni Malinen cmd_wlantest_clear_tdls_counters(struct sigma_dut *dut, struct sigma_conn *conn,
544cd4e3c3eSJouni Malinen 				 struct sigma_cmd *cmd)
545cd4e3c3eSJouni Malinen {
546cd4e3c3eSJouni Malinen 	u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
547cd4e3c3eSJouni Malinen 	u8 buf[100], *end, *pos;
548cd4e3c3eSJouni Malinen 	int rlen;
549cd4e3c3eSJouni Malinen 	const char *val;
550cd4e3c3eSJouni Malinen 	int s;
551cd4e3c3eSJouni Malinen 
552cd4e3c3eSJouni Malinen 	pos = buf;
553cd4e3c3eSJouni Malinen 	end = buf + sizeof(buf);
554cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, WLANTEST_CTRL_CLEAR_TDLS_COUNTERS);
555cd4e3c3eSJouni Malinen 	pos += 4;
556cd4e3c3eSJouni Malinen 
557cd4e3c3eSJouni Malinen 	val = get_param(cmd, "bssid");
558cd4e3c3eSJouni Malinen 	if (val == NULL)
559cd4e3c3eSJouni Malinen 		return -1;
560cd4e3c3eSJouni Malinen 	if (val) {
561cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
562cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
563cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
564cd4e3c3eSJouni Malinen 				  "errorCode,Invalid bssid");
565cd4e3c3eSJouni Malinen 			return 0;
566cd4e3c3eSJouni Malinen 		}
567cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
568cd4e3c3eSJouni Malinen 	}
569cd4e3c3eSJouni Malinen 
570cd4e3c3eSJouni Malinen 	val = get_param(cmd, "stationID");
571cd4e3c3eSJouni Malinen 	if (val == NULL)
572cd4e3c3eSJouni Malinen 		return -1;
573cd4e3c3eSJouni Malinen 	if (val) {
574cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
575cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
576cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
577cd4e3c3eSJouni Malinen 				  "errorCode,Invalid stationID");
578cd4e3c3eSJouni Malinen 			return 0;
579cd4e3c3eSJouni Malinen 		}
580cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
581cd4e3c3eSJouni Malinen 	}
582cd4e3c3eSJouni Malinen 
583cd4e3c3eSJouni Malinen 	val = get_param(cmd, "stationID2");
584cd4e3c3eSJouni Malinen 	if (val == NULL)
585cd4e3c3eSJouni Malinen 		return -1;
586cd4e3c3eSJouni Malinen 	if (val) {
587cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA2_ADDR,
588cd4e3c3eSJouni Malinen 				   ETH_ALEN);
589cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
590cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
591cd4e3c3eSJouni Malinen 				  "errorCode,Invalid stationID2");
592cd4e3c3eSJouni Malinen 			return 0;
593cd4e3c3eSJouni Malinen 		}
594cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
595cd4e3c3eSJouni Malinen 	}
596cd4e3c3eSJouni Malinen 
597cd4e3c3eSJouni Malinen 	s = open_wlantest();
598cd4e3c3eSJouni Malinen 	if (s < 0) {
599cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
600cd4e3c3eSJouni Malinen 			  "available");
601cd4e3c3eSJouni Malinen 		return 0;
602cd4e3c3eSJouni Malinen 	}
603cd4e3c3eSJouni Malinen 	rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
604cd4e3c3eSJouni Malinen 	close(s);
605cd4e3c3eSJouni Malinen 	if (rlen < 0)
606cd4e3c3eSJouni Malinen 		return -2;
607cd4e3c3eSJouni Malinen 	return 1;
608cd4e3c3eSJouni Malinen }
609cd4e3c3eSJouni Malinen 
610cd4e3c3eSJouni Malinen 
611cd4e3c3eSJouni Malinen struct sta_counters {
612cd4e3c3eSJouni Malinen 	const char *name;
613cd4e3c3eSJouni Malinen 	enum wlantest_sta_counter num;
614cd4e3c3eSJouni Malinen };
615cd4e3c3eSJouni Malinen 
616cd4e3c3eSJouni Malinen static const struct sta_counters sta_counters[] = {
617cd4e3c3eSJouni Malinen 	{ "auth_tx", WLANTEST_STA_COUNTER_AUTH_TX },
618cd4e3c3eSJouni Malinen 	{ "auth_rx", WLANTEST_STA_COUNTER_AUTH_RX },
619cd4e3c3eSJouni Malinen 	{ "assocreq_tx", WLANTEST_STA_COUNTER_ASSOCREQ_TX },
620cd4e3c3eSJouni Malinen 	{ "reassocreq_tx", WLANTEST_STA_COUNTER_REASSOCREQ_TX },
621cd4e3c3eSJouni Malinen 	{ "ptk_learned", WLANTEST_STA_COUNTER_PTK_LEARNED },
622cd4e3c3eSJouni Malinen 	{ "valid_deauth_tx", WLANTEST_STA_COUNTER_VALID_DEAUTH_TX },
623cd4e3c3eSJouni Malinen 	{ "valid_deauth_rx", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX },
624cd4e3c3eSJouni Malinen 	{ "invalid_deauth_tx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX },
625cd4e3c3eSJouni Malinen 	{ "invalid_deauth_rx", WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX },
626cd4e3c3eSJouni Malinen 	{ "valid_disassoc_tx", WLANTEST_STA_COUNTER_VALID_DISASSOC_TX },
627cd4e3c3eSJouni Malinen 	{ "valid_disassoc_rx", WLANTEST_STA_COUNTER_VALID_DISASSOC_RX },
628cd4e3c3eSJouni Malinen 	{ "invalid_disassoc_tx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX },
629cd4e3c3eSJouni Malinen 	{ "invalid_disassoc_rx", WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX },
630cd4e3c3eSJouni Malinen 	{ "valid_saqueryreq_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX },
631cd4e3c3eSJouni Malinen 	{ "valid_saqueryreq_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX },
632cd4e3c3eSJouni Malinen 	{ "invalid_saqueryreq_tx",
633cd4e3c3eSJouni Malinen 	  WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX },
634cd4e3c3eSJouni Malinen 	{ "invalid_saqueryreq_rx",
635cd4e3c3eSJouni Malinen 	  WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX },
636cd4e3c3eSJouni Malinen 	{ "valid_saqueryresp_tx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX },
637cd4e3c3eSJouni Malinen 	{ "valid_saqueryresp_rx", WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX },
638cd4e3c3eSJouni Malinen 	{ "invalid_saqueryresp_tx",
639cd4e3c3eSJouni Malinen 	  WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX },
640cd4e3c3eSJouni Malinen 	{ "invalid_saqueryresp_rx",
641cd4e3c3eSJouni Malinen 	  WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX },
642cd4e3c3eSJouni Malinen 	{ "ping_ok", WLANTEST_STA_COUNTER_PING_OK },
643cd4e3c3eSJouni Malinen 	{ "assocresp_comeback", WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK },
644cd4e3c3eSJouni Malinen 	{ "reassocresp_comeback", WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK },
645cd4e3c3eSJouni Malinen 	{ "ping_ok_first_assoc", WLANTEST_STA_COUNTER_PING_OK_FIRST_ASSOC },
646cd4e3c3eSJouni Malinen 	{ "valid_deauth_rx_ack", WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK },
647cd4e3c3eSJouni Malinen 	{ "valid_disassoc_rx_ack",
648cd4e3c3eSJouni Malinen 	  WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK },
649cd4e3c3eSJouni Malinen 	{ "invalid_deauth_rx_ack",
650cd4e3c3eSJouni Malinen 	  WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK },
651cd4e3c3eSJouni Malinen 	{ "invalid_disassoc_rx_ack",
652cd4e3c3eSJouni Malinen 	  WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK },
653cd4e3c3eSJouni Malinen 	{ "deauth_rx_asleep", WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP },
654cd4e3c3eSJouni Malinen 	{ "deauth_rx_awake", WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE },
655cd4e3c3eSJouni Malinen 	{ "disassoc_rx_asleep", WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP },
656cd4e3c3eSJouni Malinen 	{ "disassoc_rx_awake", WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE },
657cd4e3c3eSJouni Malinen 	{ "prot_data_tx", WLANTEST_STA_COUNTER_PROT_DATA_TX },
658cd4e3c3eSJouni Malinen 	{ "deauth_rx_rc6", WLANTEST_STA_COUNTER_DEAUTH_RX_RC6 },
659cd4e3c3eSJouni Malinen 	{ "deauth_rx_rc7", WLANTEST_STA_COUNTER_DEAUTH_RX_RC7 },
660cd4e3c3eSJouni Malinen 	{ "disassoc_rx_rc6", WLANTEST_STA_COUNTER_DISASSOC_RX_RC6 },
661cd4e3c3eSJouni Malinen 	{ "disassoc_rx_rc7", WLANTEST_STA_COUNTER_DISASSOC_RX_RC7 },
662cd4e3c3eSJouni Malinen 	{ NULL, 0 }
663cd4e3c3eSJouni Malinen };
664cd4e3c3eSJouni Malinen 
665*f722271eSJouni Malinen static enum sigma_cmd_result
cmd_wlantest_get_sta_counter(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)666*f722271eSJouni Malinen cmd_wlantest_get_sta_counter(struct sigma_dut *dut, struct sigma_conn *conn,
667cd4e3c3eSJouni Malinen 			     struct sigma_cmd *cmd)
668cd4e3c3eSJouni Malinen {
669cd4e3c3eSJouni Malinen 	u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
670cd4e3c3eSJouni Malinen 	u8 buf[100], *end, *pos;
671cd4e3c3eSJouni Malinen 	int rlen;
672cd4e3c3eSJouni Malinen 	const char *val;
673cd4e3c3eSJouni Malinen 	int s, i;
674cd4e3c3eSJouni Malinen 	char ret[100];
675cd4e3c3eSJouni Malinen 	size_t len;
676cd4e3c3eSJouni Malinen 
677cd4e3c3eSJouni Malinen 	pos = buf;
678cd4e3c3eSJouni Malinen 	end = buf + sizeof(buf);
679cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_STA_COUNTER);
680cd4e3c3eSJouni Malinen 	pos += 4;
681cd4e3c3eSJouni Malinen 
682cd4e3c3eSJouni Malinen 	val = get_param(cmd, "bssid");
683cd4e3c3eSJouni Malinen 	if (val == NULL)
684cd4e3c3eSJouni Malinen 		return -1;
685cd4e3c3eSJouni Malinen 	if (val) {
686cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
687cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
688cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
689cd4e3c3eSJouni Malinen 				  "errorCode,Invalid bssid");
690cd4e3c3eSJouni Malinen 			return 0;
691cd4e3c3eSJouni Malinen 		}
692cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
693cd4e3c3eSJouni Malinen 	}
694cd4e3c3eSJouni Malinen 
695cd4e3c3eSJouni Malinen 	val = get_param(cmd, "stationID");
696cd4e3c3eSJouni Malinen 	if (val == NULL)
697cd4e3c3eSJouni Malinen 		return -1;
698cd4e3c3eSJouni Malinen 	if (val) {
699cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
700cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
701cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
702cd4e3c3eSJouni Malinen 				  "errorCode,Invalid stationID");
703cd4e3c3eSJouni Malinen 			return 0;
704cd4e3c3eSJouni Malinen 		}
705cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
706cd4e3c3eSJouni Malinen 	}
707cd4e3c3eSJouni Malinen 
708cd4e3c3eSJouni Malinen 	val = get_param(cmd, "field");
709cd4e3c3eSJouni Malinen 	if (val == NULL)
710cd4e3c3eSJouni Malinen 		return -1;
711cd4e3c3eSJouni Malinen 	for (i = 0; sta_counters[i].name; i++) {
712cd4e3c3eSJouni Malinen 		if (strcasecmp(sta_counters[i].name, val) == 0)
713cd4e3c3eSJouni Malinen 			break;
714cd4e3c3eSJouni Malinen 	}
715cd4e3c3eSJouni Malinen 	if (sta_counters[i].name == NULL) {
716cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid field");
717cd4e3c3eSJouni Malinen 		return 0;
718cd4e3c3eSJouni Malinen 	}
719cd4e3c3eSJouni Malinen 	pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_COUNTER,
720cd4e3c3eSJouni Malinen 			    sta_counters[i].num);
721cd4e3c3eSJouni Malinen 
722cd4e3c3eSJouni Malinen 	s = open_wlantest();
723cd4e3c3eSJouni Malinen 	if (s < 0) {
724cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
725cd4e3c3eSJouni Malinen 			  "available");
726cd4e3c3eSJouni Malinen 		return 0;
727cd4e3c3eSJouni Malinen 	}
728cd4e3c3eSJouni Malinen 	rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
729cd4e3c3eSJouni Malinen 	close(s);
730cd4e3c3eSJouni Malinen 
731cd4e3c3eSJouni Malinen 
732cd4e3c3eSJouni Malinen 	pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
733cd4e3c3eSJouni Malinen 	if (pos == NULL || len != 4)
734cd4e3c3eSJouni Malinen 		return -2;
735cd4e3c3eSJouni Malinen 	snprintf(ret, sizeof(ret), "counter,%u", WPA_GET_BE32(pos));
736cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, ret);
737cd4e3c3eSJouni Malinen 	return 0;
738cd4e3c3eSJouni Malinen }
739cd4e3c3eSJouni Malinen 
740cd4e3c3eSJouni Malinen 
741cd4e3c3eSJouni Malinen struct bss_counters {
742cd4e3c3eSJouni Malinen 	const char *name;
743cd4e3c3eSJouni Malinen 	enum wlantest_bss_counter num;
744cd4e3c3eSJouni Malinen };
745cd4e3c3eSJouni Malinen 
746cd4e3c3eSJouni Malinen static const struct bss_counters bss_counters[] = {
747cd4e3c3eSJouni Malinen 	{ "valid_bip_mmie", WLANTEST_BSS_COUNTER_VALID_BIP_MMIE },
748cd4e3c3eSJouni Malinen 	{ "invalid_bip_mmie", WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE },
749cd4e3c3eSJouni Malinen 	{ "missing_bip_mmie", WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE },
750cd4e3c3eSJouni Malinen 	{ "bip_deauth", WLANTEST_BSS_COUNTER_BIP_DEAUTH },
751cd4e3c3eSJouni Malinen 	{ "bip_disassoc", WLANTEST_BSS_COUNTER_BIP_DISASSOC },
752cd4e3c3eSJouni Malinen 	{ NULL, 0 }
753cd4e3c3eSJouni Malinen };
754cd4e3c3eSJouni Malinen 
755*f722271eSJouni Malinen static enum sigma_cmd_result
cmd_wlantest_get_bss_counter(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)756*f722271eSJouni Malinen cmd_wlantest_get_bss_counter(struct sigma_dut *dut, struct sigma_conn *conn,
757cd4e3c3eSJouni Malinen 			     struct sigma_cmd *cmd)
758cd4e3c3eSJouni Malinen {
759cd4e3c3eSJouni Malinen 	u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
760cd4e3c3eSJouni Malinen 	u8 buf[100], *end, *pos;
761cd4e3c3eSJouni Malinen 	int rlen;
762cd4e3c3eSJouni Malinen 	const char *val;
763cd4e3c3eSJouni Malinen 	int s, i;
764cd4e3c3eSJouni Malinen 	char ret[100];
765cd4e3c3eSJouni Malinen 	size_t len;
766cd4e3c3eSJouni Malinen 
767cd4e3c3eSJouni Malinen 	pos = buf;
768cd4e3c3eSJouni Malinen 	end = buf + sizeof(buf);
769cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_BSS_COUNTER);
770cd4e3c3eSJouni Malinen 	pos += 4;
771cd4e3c3eSJouni Malinen 
772cd4e3c3eSJouni Malinen 	val = get_param(cmd, "bssid");
773cd4e3c3eSJouni Malinen 	if (val == NULL)
774cd4e3c3eSJouni Malinen 		return -1;
775cd4e3c3eSJouni Malinen 	if (val) {
776cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
777cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
778cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
779cd4e3c3eSJouni Malinen 				  "errorCode,Invalid bssid");
780cd4e3c3eSJouni Malinen 			return 0;
781cd4e3c3eSJouni Malinen 		}
782cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
783cd4e3c3eSJouni Malinen 	}
784cd4e3c3eSJouni Malinen 
785cd4e3c3eSJouni Malinen 	val = get_param(cmd, "field");
786cd4e3c3eSJouni Malinen 	if (val == NULL)
787cd4e3c3eSJouni Malinen 		return -1;
788cd4e3c3eSJouni Malinen 	for (i = 0; bss_counters[i].name; i++) {
789cd4e3c3eSJouni Malinen 		if (strcasecmp(bss_counters[i].name, val) == 0)
790cd4e3c3eSJouni Malinen 			break;
791cd4e3c3eSJouni Malinen 	}
792cd4e3c3eSJouni Malinen 	if (bss_counters[i].name == NULL) {
793cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid field");
794cd4e3c3eSJouni Malinen 		return 0;
795cd4e3c3eSJouni Malinen 	}
796cd4e3c3eSJouni Malinen 	pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_COUNTER,
797cd4e3c3eSJouni Malinen 			    bss_counters[i].num);
798cd4e3c3eSJouni Malinen 
799cd4e3c3eSJouni Malinen 	s = open_wlantest();
800cd4e3c3eSJouni Malinen 	if (s < 0) {
801cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
802cd4e3c3eSJouni Malinen 			  "available");
803cd4e3c3eSJouni Malinen 		return 0;
804cd4e3c3eSJouni Malinen 	}
805cd4e3c3eSJouni Malinen 	rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
806cd4e3c3eSJouni Malinen 	close(s);
807cd4e3c3eSJouni Malinen 
808cd4e3c3eSJouni Malinen 	pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
809cd4e3c3eSJouni Malinen 	if (pos == NULL || len != 4)
810cd4e3c3eSJouni Malinen 		return -2;
811cd4e3c3eSJouni Malinen 	snprintf(ret, sizeof(ret), "counter,%u", WPA_GET_BE32(pos));
812cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, ret);
813cd4e3c3eSJouni Malinen 	return 0;
814cd4e3c3eSJouni Malinen }
815cd4e3c3eSJouni Malinen 
816cd4e3c3eSJouni Malinen 
817cd4e3c3eSJouni Malinen struct tdls_counters {
818cd4e3c3eSJouni Malinen 	const char *name;
819cd4e3c3eSJouni Malinen 	enum wlantest_tdls_counter num;
820cd4e3c3eSJouni Malinen };
821cd4e3c3eSJouni Malinen 
822cd4e3c3eSJouni Malinen static const struct tdls_counters tdls_counters[] = {
823cd4e3c3eSJouni Malinen 	{ "valid_direct_link", WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK },
824cd4e3c3eSJouni Malinen 	{ "invalid_direct_link", WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK },
825cd4e3c3eSJouni Malinen 	{ "valid_ap_path", WLANTEST_TDLS_COUNTER_VALID_AP_PATH },
826cd4e3c3eSJouni Malinen 	{ "invalid_ap_path", WLANTEST_TDLS_COUNTER_INVALID_AP_PATH },
827cd4e3c3eSJouni Malinen 	{ "setup_req", WLANTEST_TDLS_COUNTER_SETUP_REQ },
828cd4e3c3eSJouni Malinen 	{ "setup_resp_ok", WLANTEST_TDLS_COUNTER_SETUP_RESP_OK },
829cd4e3c3eSJouni Malinen 	{ "setup_resp_fail", WLANTEST_TDLS_COUNTER_SETUP_RESP_FAIL },
830cd4e3c3eSJouni Malinen 	{ "setup_conf_ok", WLANTEST_TDLS_COUNTER_SETUP_CONF_OK },
831cd4e3c3eSJouni Malinen 	{ "setup_conf_fail", WLANTEST_TDLS_COUNTER_SETUP_CONF_FAIL },
832cd4e3c3eSJouni Malinen 	{ "teardown", WLANTEST_TDLS_COUNTER_TEARDOWN },
833cd4e3c3eSJouni Malinen 	{ NULL, 0 }
834cd4e3c3eSJouni Malinen };
835cd4e3c3eSJouni Malinen 
836*f722271eSJouni Malinen static enum sigma_cmd_result
cmd_wlantest_get_tdls_counter(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)837*f722271eSJouni Malinen cmd_wlantest_get_tdls_counter(struct sigma_dut *dut, struct sigma_conn *conn,
838cd4e3c3eSJouni Malinen 			      struct sigma_cmd *cmd)
839cd4e3c3eSJouni Malinen {
840cd4e3c3eSJouni Malinen 	u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
841cd4e3c3eSJouni Malinen 	u8 buf[100], *end, *pos;
842cd4e3c3eSJouni Malinen 	int rlen;
843cd4e3c3eSJouni Malinen 	const char *val;
844cd4e3c3eSJouni Malinen 	int s, i;
845cd4e3c3eSJouni Malinen 	char ret[100];
846cd4e3c3eSJouni Malinen 	size_t len;
847cd4e3c3eSJouni Malinen 
848cd4e3c3eSJouni Malinen 	pos = buf;
849cd4e3c3eSJouni Malinen 	end = buf + sizeof(buf);
850cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_TDLS_COUNTER);
851cd4e3c3eSJouni Malinen 	pos += 4;
852cd4e3c3eSJouni Malinen 
853cd4e3c3eSJouni Malinen 	val = get_param(cmd, "bssid");
854cd4e3c3eSJouni Malinen 	if (val == NULL)
855cd4e3c3eSJouni Malinen 		return -1;
856cd4e3c3eSJouni Malinen 	if (val) {
857cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
858cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
859cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
860cd4e3c3eSJouni Malinen 				  "errorCode,Invalid bssid");
861cd4e3c3eSJouni Malinen 			return 0;
862cd4e3c3eSJouni Malinen 		}
863cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
864cd4e3c3eSJouni Malinen 	}
865cd4e3c3eSJouni Malinen 
866cd4e3c3eSJouni Malinen 	val = get_param(cmd, "stationID");
867cd4e3c3eSJouni Malinen 	if (val == NULL)
868cd4e3c3eSJouni Malinen 		return -1;
869cd4e3c3eSJouni Malinen 	if (val) {
870cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
871cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
872cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
873cd4e3c3eSJouni Malinen 				  "errorCode,Invalid stationID");
874cd4e3c3eSJouni Malinen 			return 0;
875cd4e3c3eSJouni Malinen 		}
876cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
877cd4e3c3eSJouni Malinen 	}
878cd4e3c3eSJouni Malinen 
879cd4e3c3eSJouni Malinen 	val = get_param(cmd, "stationID2");
880cd4e3c3eSJouni Malinen 	if (val == NULL)
881cd4e3c3eSJouni Malinen 		return -1;
882cd4e3c3eSJouni Malinen 	if (val) {
883cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA2_ADDR,
884cd4e3c3eSJouni Malinen 				   ETH_ALEN);
885cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
886cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
887cd4e3c3eSJouni Malinen 				  "errorCode,Invalid stationID");
888cd4e3c3eSJouni Malinen 			return 0;
889cd4e3c3eSJouni Malinen 		}
890cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
891cd4e3c3eSJouni Malinen 	}
892cd4e3c3eSJouni Malinen 
893cd4e3c3eSJouni Malinen 	val = get_param(cmd, "field");
894cd4e3c3eSJouni Malinen 	if (val == NULL)
895cd4e3c3eSJouni Malinen 		return -1;
896cd4e3c3eSJouni Malinen 	for (i = 0; tdls_counters[i].name; i++) {
897cd4e3c3eSJouni Malinen 		if (strcasecmp(tdls_counters[i].name, val) == 0)
898cd4e3c3eSJouni Malinen 			break;
899cd4e3c3eSJouni Malinen 	}
900cd4e3c3eSJouni Malinen 	if (tdls_counters[i].name == NULL) {
901cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid field");
902cd4e3c3eSJouni Malinen 		return 0;
903cd4e3c3eSJouni Malinen 	}
904cd4e3c3eSJouni Malinen 	pos = attr_add_be32(pos, end, WLANTEST_ATTR_TDLS_COUNTER,
905cd4e3c3eSJouni Malinen 			    tdls_counters[i].num);
906cd4e3c3eSJouni Malinen 
907cd4e3c3eSJouni Malinen 	s = open_wlantest();
908cd4e3c3eSJouni Malinen 	if (s < 0) {
909cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
910cd4e3c3eSJouni Malinen 			  "available");
911cd4e3c3eSJouni Malinen 		return 0;
912cd4e3c3eSJouni Malinen 	}
913cd4e3c3eSJouni Malinen 	rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
914cd4e3c3eSJouni Malinen 	close(s);
915cd4e3c3eSJouni Malinen 
916cd4e3c3eSJouni Malinen 
917cd4e3c3eSJouni Malinen 	pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
918cd4e3c3eSJouni Malinen 	if (pos == NULL || len != 4)
919cd4e3c3eSJouni Malinen 		return -2;
920cd4e3c3eSJouni Malinen 	snprintf(ret, sizeof(ret), "counter,%u", WPA_GET_BE32(pos));
921cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, ret);
922cd4e3c3eSJouni Malinen 	return 0;
923cd4e3c3eSJouni Malinen }
924cd4e3c3eSJouni Malinen 
925cd4e3c3eSJouni Malinen 
926cd4e3c3eSJouni Malinen struct sta_infos {
927cd4e3c3eSJouni Malinen 	const char *name;
928cd4e3c3eSJouni Malinen 	enum wlantest_sta_info num;
929cd4e3c3eSJouni Malinen };
930cd4e3c3eSJouni Malinen 
931cd4e3c3eSJouni Malinen static const struct sta_infos sta_infos[] = {
932cd4e3c3eSJouni Malinen 	{ "proto", WLANTEST_STA_INFO_PROTO },
933cd4e3c3eSJouni Malinen 	{ "pairwise", WLANTEST_STA_INFO_PAIRWISE },
934cd4e3c3eSJouni Malinen 	{ "key_mgmt", WLANTEST_STA_INFO_KEY_MGMT },
935cd4e3c3eSJouni Malinen 	{ "rsn_capab", WLANTEST_STA_INFO_RSN_CAPAB },
936cd4e3c3eSJouni Malinen 	{ "state", WLANTEST_STA_INFO_STATE },
937cd4e3c3eSJouni Malinen 	{ NULL, 0 }
938cd4e3c3eSJouni Malinen };
939cd4e3c3eSJouni Malinen 
cmd_wlantest_info_sta(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)940*f722271eSJouni Malinen static enum sigma_cmd_result cmd_wlantest_info_sta(struct sigma_dut *dut,
941cd4e3c3eSJouni Malinen 						   struct sigma_conn *conn,
942cd4e3c3eSJouni Malinen 						   struct sigma_cmd *cmd)
943cd4e3c3eSJouni Malinen {
944cd4e3c3eSJouni Malinen 	u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
945cd4e3c3eSJouni Malinen 	u8 buf[100], *end, *pos;
946cd4e3c3eSJouni Malinen 	int rlen;
947cd4e3c3eSJouni Malinen 	const char *val;
948cd4e3c3eSJouni Malinen 	int s, i;
949cd4e3c3eSJouni Malinen 	char ret[120];
950cd4e3c3eSJouni Malinen 	size_t len;
951cd4e3c3eSJouni Malinen 	char info[100];
952cd4e3c3eSJouni Malinen 
953cd4e3c3eSJouni Malinen 	pos = buf;
954cd4e3c3eSJouni Malinen 	end = buf + sizeof(buf);
955cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_STA);
956cd4e3c3eSJouni Malinen 	pos += 4;
957cd4e3c3eSJouni Malinen 
958cd4e3c3eSJouni Malinen 	val = get_param(cmd, "bssid");
959cd4e3c3eSJouni Malinen 	if (val == NULL)
960cd4e3c3eSJouni Malinen 		return -1;
961cd4e3c3eSJouni Malinen 	if (val) {
962cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
963cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
964cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
965cd4e3c3eSJouni Malinen 				  "errorCode,Invalid bssid");
966cd4e3c3eSJouni Malinen 			return 0;
967cd4e3c3eSJouni Malinen 		}
968cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
969cd4e3c3eSJouni Malinen 	}
970cd4e3c3eSJouni Malinen 
971cd4e3c3eSJouni Malinen 	val = get_param(cmd, "stationID");
972cd4e3c3eSJouni Malinen 	if (val == NULL)
973cd4e3c3eSJouni Malinen 		return -1;
974cd4e3c3eSJouni Malinen 	if (val) {
975cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
976cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
977cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
978cd4e3c3eSJouni Malinen 				  "errorCode,Invalid stationID");
979cd4e3c3eSJouni Malinen 			return 0;
980cd4e3c3eSJouni Malinen 		}
981cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
982cd4e3c3eSJouni Malinen 	}
983cd4e3c3eSJouni Malinen 
984cd4e3c3eSJouni Malinen 	val = get_param(cmd, "field");
985cd4e3c3eSJouni Malinen 	if (val == NULL)
986cd4e3c3eSJouni Malinen 		return -1;
987cd4e3c3eSJouni Malinen 	for (i = 0; sta_infos[i].name; i++) {
988cd4e3c3eSJouni Malinen 		if (strcasecmp(sta_infos[i].name, val) == 0)
989cd4e3c3eSJouni Malinen 			break;
990cd4e3c3eSJouni Malinen 	}
991cd4e3c3eSJouni Malinen 	if (sta_infos[i].name == NULL) {
992cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid field");
993cd4e3c3eSJouni Malinen 		return 0;
994cd4e3c3eSJouni Malinen 	}
995cd4e3c3eSJouni Malinen 	pos = attr_add_be32(pos, end, WLANTEST_ATTR_STA_INFO,
996cd4e3c3eSJouni Malinen 			    sta_infos[i].num);
997cd4e3c3eSJouni Malinen 
998cd4e3c3eSJouni Malinen 	s = open_wlantest();
999cd4e3c3eSJouni Malinen 	if (s < 0) {
1000cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
1001cd4e3c3eSJouni Malinen 			  "available");
1002cd4e3c3eSJouni Malinen 		return 0;
1003cd4e3c3eSJouni Malinen 	}
1004cd4e3c3eSJouni Malinen 	rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1005cd4e3c3eSJouni Malinen 	close(s);
1006cd4e3c3eSJouni Malinen 
1007cd4e3c3eSJouni Malinen 
1008cd4e3c3eSJouni Malinen 	pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1009cd4e3c3eSJouni Malinen 	if (pos == NULL)
1010cd4e3c3eSJouni Malinen 		return -2;
1011cd4e3c3eSJouni Malinen 	if (len >= sizeof(info))
1012cd4e3c3eSJouni Malinen 		len = sizeof(info) - 1;
1013cd4e3c3eSJouni Malinen 	memcpy(info, pos, len);
1014cd4e3c3eSJouni Malinen 	info[len] = '\0';
1015cd4e3c3eSJouni Malinen 	snprintf(ret, sizeof(ret), "info,%s", info);
1016cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, ret);
1017cd4e3c3eSJouni Malinen 	return 0;
1018cd4e3c3eSJouni Malinen }
1019cd4e3c3eSJouni Malinen 
1020cd4e3c3eSJouni Malinen 
1021cd4e3c3eSJouni Malinen struct bss_infos {
1022cd4e3c3eSJouni Malinen 	const char *name;
1023cd4e3c3eSJouni Malinen 	enum wlantest_bss_info num;
1024cd4e3c3eSJouni Malinen };
1025cd4e3c3eSJouni Malinen 
1026cd4e3c3eSJouni Malinen static const struct bss_infos bss_infos[] = {
1027cd4e3c3eSJouni Malinen 	{ "proto", WLANTEST_BSS_INFO_PROTO },
1028cd4e3c3eSJouni Malinen 	{ "pairwise", WLANTEST_BSS_INFO_PAIRWISE },
1029cd4e3c3eSJouni Malinen 	{ "group", WLANTEST_BSS_INFO_GROUP },
1030cd4e3c3eSJouni Malinen 	{ "group_mgmt", WLANTEST_BSS_INFO_GROUP_MGMT },
1031cd4e3c3eSJouni Malinen 	{ "key_mgmt", WLANTEST_BSS_INFO_KEY_MGMT },
1032cd4e3c3eSJouni Malinen 	{ "rsn_capab", WLANTEST_BSS_INFO_RSN_CAPAB },
1033cd4e3c3eSJouni Malinen 	{ NULL, 0 }
1034cd4e3c3eSJouni Malinen };
1035cd4e3c3eSJouni Malinen 
cmd_wlantest_info_bss(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)1036*f722271eSJouni Malinen static enum sigma_cmd_result cmd_wlantest_info_bss(struct sigma_dut *dut,
1037cd4e3c3eSJouni Malinen 						   struct sigma_conn *conn,
1038cd4e3c3eSJouni Malinen 						   struct sigma_cmd *cmd)
1039cd4e3c3eSJouni Malinen {
1040cd4e3c3eSJouni Malinen 	u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
1041cd4e3c3eSJouni Malinen 	u8 buf[100], *end, *pos;
1042cd4e3c3eSJouni Malinen 	int rlen;
1043cd4e3c3eSJouni Malinen 	const char *val;
1044cd4e3c3eSJouni Malinen 	int s, i;
1045cd4e3c3eSJouni Malinen 	char ret[120];
1046cd4e3c3eSJouni Malinen 	size_t len;
1047cd4e3c3eSJouni Malinen 	char info[100];
1048cd4e3c3eSJouni Malinen 
1049cd4e3c3eSJouni Malinen 	pos = buf;
1050cd4e3c3eSJouni Malinen 	end = buf + sizeof(buf);
1051cd4e3c3eSJouni Malinen 	WPA_PUT_BE32(pos, WLANTEST_CTRL_INFO_BSS);
1052cd4e3c3eSJouni Malinen 	pos += 4;
1053cd4e3c3eSJouni Malinen 
1054cd4e3c3eSJouni Malinen 	val = get_param(cmd, "bssid");
1055cd4e3c3eSJouni Malinen 	if (val == NULL)
1056cd4e3c3eSJouni Malinen 		return -1;
1057cd4e3c3eSJouni Malinen 	if (val) {
1058cd4e3c3eSJouni Malinen 		pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
1059cd4e3c3eSJouni Malinen 		if (hwaddr_aton(val, pos) < 0) {
1060cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID,
1061cd4e3c3eSJouni Malinen 				  "errorCode,Invalid bssid");
1062cd4e3c3eSJouni Malinen 			return 0;
1063cd4e3c3eSJouni Malinen 		}
1064cd4e3c3eSJouni Malinen 		pos += ETH_ALEN;
1065cd4e3c3eSJouni Malinen 	}
1066cd4e3c3eSJouni Malinen 
1067cd4e3c3eSJouni Malinen 	val = get_param(cmd, "field");
1068cd4e3c3eSJouni Malinen 	if (val == NULL)
1069cd4e3c3eSJouni Malinen 		return -1;
1070cd4e3c3eSJouni Malinen 	for (i = 0; bss_infos[i].name; i++) {
1071cd4e3c3eSJouni Malinen 		if (strcasecmp(bss_infos[i].name, val) == 0)
1072cd4e3c3eSJouni Malinen 			break;
1073cd4e3c3eSJouni Malinen 	}
1074cd4e3c3eSJouni Malinen 	if (bss_infos[i].name == NULL) {
1075cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_INVALID, "errorCode,Invalid field");
1076cd4e3c3eSJouni Malinen 		return 0;
1077cd4e3c3eSJouni Malinen 	}
1078cd4e3c3eSJouni Malinen 	pos = attr_add_be32(pos, end, WLANTEST_ATTR_BSS_INFO,
1079cd4e3c3eSJouni Malinen 			    bss_infos[i].num);
1080cd4e3c3eSJouni Malinen 
1081cd4e3c3eSJouni Malinen 	s = open_wlantest();
1082cd4e3c3eSJouni Malinen 	if (s < 0) {
1083cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,wlantest not "
1084cd4e3c3eSJouni Malinen 			  "available");
1085cd4e3c3eSJouni Malinen 		return 0;
1086cd4e3c3eSJouni Malinen 	}
1087cd4e3c3eSJouni Malinen 	rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
1088cd4e3c3eSJouni Malinen 	close(s);
1089cd4e3c3eSJouni Malinen 
1090cd4e3c3eSJouni Malinen 
1091cd4e3c3eSJouni Malinen 	pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_INFO, &len);
1092cd4e3c3eSJouni Malinen 	if (pos == NULL)
1093cd4e3c3eSJouni Malinen 		return -2;
1094cd4e3c3eSJouni Malinen 	if (len >= sizeof(info))
1095cd4e3c3eSJouni Malinen 		len = sizeof(info) - 1;
1096cd4e3c3eSJouni Malinen 	memcpy(info, pos, len);
1097cd4e3c3eSJouni Malinen 	info[len] = '\0';
1098cd4e3c3eSJouni Malinen 	snprintf(ret, sizeof(ret), "info,%s", info);
1099cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, ret);
1100cd4e3c3eSJouni Malinen 	return 0;
1101cd4e3c3eSJouni Malinen }
1102cd4e3c3eSJouni Malinen 
1103cd4e3c3eSJouni Malinen 
wlantest_register_cmds(void)1104cd4e3c3eSJouni Malinen void wlantest_register_cmds(void)
1105cd4e3c3eSJouni Malinen {
1106cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_version", NULL, cmd_wlantest_version);
1107cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_set_channel", NULL,
1108cd4e3c3eSJouni Malinen 			  cmd_wlantest_set_channel);
1109cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_flush", NULL, cmd_wlantest_flush);
1110cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_send_frame", NULL,
1111cd4e3c3eSJouni Malinen 			  cmd_wlantest_send_frame);
1112cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_add_passphrase", NULL,
1113cd4e3c3eSJouni Malinen 			  cmd_wlantest_add_passphrase);
1114cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_clear_sta_counters", NULL,
1115cd4e3c3eSJouni Malinen 			  cmd_wlantest_clear_sta_counters);
1116cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_clear_bss_counters", NULL,
1117cd4e3c3eSJouni Malinen 			  cmd_wlantest_clear_bss_counters);
1118cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_clear_tdls_counters", NULL,
1119cd4e3c3eSJouni Malinen 			  cmd_wlantest_clear_tdls_counters);
1120cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_get_sta_counter", NULL,
1121cd4e3c3eSJouni Malinen 			  cmd_wlantest_get_sta_counter);
1122cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_get_bss_counter", NULL,
1123cd4e3c3eSJouni Malinen 			  cmd_wlantest_get_bss_counter);
1124cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_get_tdls_counter", NULL,
1125cd4e3c3eSJouni Malinen 			  cmd_wlantest_get_tdls_counter);
1126cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_info_sta", NULL, cmd_wlantest_info_sta);
1127cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("wlantest_info_bss", NULL, cmd_wlantest_info_bss);
1128cd4e3c3eSJouni Malinen }
1129