xref: /wlan-dirver/utils/sigma-dut/sta.c (revision 3d96a1e9505bf43c774f692ace6156b821a3ecf8)
1 /*
2  * Sigma Control API DUT (station/AP)
3  * Copyright (c) 2010-2011, Atheros Communications, Inc.
4  * Copyright (c) 2011-2017, Qualcomm Atheros, Inc.
5  * Copyright (c) 2018, The Linux Foundation
6  * All Rights Reserved.
7  * Licensed under the Clear BSD license. See README for more details.
8  */
9 
10 #include "sigma_dut.h"
11 #include <sys/ioctl.h>
12 #include <sys/stat.h>
13 #include <sys/wait.h>
14 #include <ctype.h>
15 #ifdef __linux__
16 #include <regex.h>
17 #include <dirent.h>
18 #include <sys/time.h>
19 #include <netpacket/packet.h>
20 #include <linux/if_ether.h>
21 #ifdef ANDROID
22 #include <cutils/properties.h>
23 #include <android/log.h>
24 #include "keystore_get.h"
25 #else /* ANDROID */
26 #include <ifaddrs.h>
27 #endif /* ANDROID */
28 #include <netdb.h>
29 #endif /* __linux__ */
30 #ifdef __QNXNTO__
31 #include <net/if_dl.h>
32 #endif /* __QNXNTO__ */
33 #include "wpa_ctrl.h"
34 #include "wpa_helpers.h"
35 #include "miracast.h"
36 #include "qca-vendor_copy.h"
37 
38 /* Temporary files for sta_send_addba */
39 #define VI_QOS_TMP_FILE     "/tmp/vi-qos.tmp"
40 #define VI_QOS_FILE         "/tmp/vi-qos.txt"
41 #define VI_QOS_REFFILE      "/etc/vi-qos.txt"
42 
43 /*
44  * MTU for Ethernet need to take into account 8-byte SNAP header
45  * to be added when encapsulating Ethernet frame into 802.11
46  */
47 #ifndef IEEE80211_MAX_DATA_LEN_DMG
48 #define IEEE80211_MAX_DATA_LEN_DMG 7920
49 #endif
50 #ifndef IEEE80211_SNAP_LEN_DMG
51 #define IEEE80211_SNAP_LEN_DMG 8
52 #endif
53 
54 #define NON_PREF_CH_LIST_SIZE 100
55 #define NEIGHBOR_REPORT_SIZE 1000
56 #define DEFAULT_NEIGHBOR_BSSID_INFO "17"
57 #define DEFAULT_NEIGHBOR_PHY_TYPE "1"
58 
59 #define WIL_DEFAULT_BI	100
60 
61 /* default remain on channel time for transmitting frames (milliseconds) */
62 #define WIL_TRANSMIT_FRAME_DEFAULT_ROC 500
63 #define IEEE80211_P2P_ATTR_DEVICE_ID 3
64 #define IEEE80211_P2P_ATTR_GROUP_ID 15
65 
66 /* describes tagged bytes in template frame file */
67 struct template_frame_tag {
68 	int num;
69 	int offset;
70 	size_t len;
71 };
72 
73 extern char *sigma_wpas_ctrl;
74 extern char *sigma_cert_path;
75 extern enum driver_type wifi_chip_type;
76 extern char *sigma_radio_ifname[];
77 
78 #ifdef __linux__
79 #define WIL_WMI_MAX_PAYLOAD	248
80 #define WIL_WMI_ESE_CFG_CMDID	0xa01
81 #define WIL_WMI_BF_TRIG_CMDID	0x83a
82 #define WIL_WMI_UNIT_TEST_CMDID	0x900
83 #define WIL_WMI_P2P_CFG_CMDID	0x910
84 #define WIL_WMI_START_LISTEN_CMDID	0x914
85 #define WIL_WMI_DISCOVERY_STOP_CMDID	0x917
86 
87 struct wil_wmi_header {
88 	uint8_t mid;
89 	uint8_t reserved;
90 	uint16_t cmd;
91 	uint32_t ts;
92 } __attribute__((packed));
93 
94 enum wil_wmi_bf_trig_type {
95 	WIL_WMI_SLS,
96 	WIL_WMI_BRP_RX,
97 	WIL_WMI_BRP_TX,
98 };
99 
100 struct wil_wmi_bf_trig_cmd {
101 	/* enum wil_wmi_bf_trig_type */
102 	uint32_t bf_type;
103 	/* cid when type == WMI_BRP_RX */
104 	uint32_t sta_id;
105 	uint32_t reserved;
106 	/* mac address when type = WIL_WMI_SLS */
107 	uint8_t dest_mac[6];
108 } __attribute__((packed));
109 
110 enum wil_wmi_sched_scheme_advertisment {
111 	WIL_WMI_ADVERTISE_ESE_DISABLED,
112 	WIL_WMI_ADVERTISE_ESE_IN_BEACON,
113 	WIL_WMI_ADVERTISE_ESE_IN_ANNOUNCE_FRAME,
114 };
115 
116 enum wil_wmi_ese_slot_type {
117 	WIL_WMI_ESE_SP,
118 	WIL_WMI_ESE_CBAP,
119 	WIL_WMI_ESE_ANNOUNCE_NO_ACK,
120 };
121 
122 struct wil_wmi_ese_slot {
123 	/* offset from start of BI in microseconds */
124 	uint32_t tbtt_offset;
125 	uint8_t flags;
126 	/* enum wil_wmi_ese_slot_type */
127 	uint8_t slot_type;
128 	/* duration in microseconds */
129 	uint16_t duration;
130 	/* frame exchange sequence duration, microseconds */
131 	uint16_t tx_op;
132 	/* time between 2 blocks for periodic allocation(microseconds) */
133 	uint16_t period;
134 	/* number of blocks in periodic allocation */
135 	uint8_t num_blocks;
136 	/* for semi-active allocations */
137 	uint8_t idle_period;
138 	uint8_t src_aid;
139 	uint8_t dst_aid;
140 	uint32_t reserved;
141 } __attribute__((packed));
142 
143 #define WIL_WMI_MAX_ESE_SLOTS	4
144 struct wil_wmi_ese_cfg {
145 	uint8_t serial_num;
146 	/* wil_wmi_sched_scheme_advertisment */
147 	uint8_t ese_advertisment;
148 	uint16_t flags;
149 	uint8_t num_allocs;
150 	uint8_t reserved[3];
151 	uint64_t start_tbtt;
152 	/* allocations list */
153 	struct wil_wmi_ese_slot slots[WIL_WMI_MAX_ESE_SLOTS];
154 } __attribute__((packed));
155 
156 #define WIL_WMI_UT_FORCE_MCS	6
157 struct wil_wmi_force_mcs {
158 	/* WIL_WMI_UT_HW_SYSAPI */
159 	uint16_t module_id;
160 	/* WIL_WMI_UT_FORCE_MCS */
161 	uint16_t subtype_id;
162 	/* cid (ignored in oob_mode, affects all stations) */
163 	uint32_t cid;
164 	/* 1 to force MCS, 0 to restore default behavior */
165 	uint32_t force_enable;
166 	/* MCS index, 0-12 */
167 	uint32_t mcs;
168 } __attribute__((packed));
169 
170 #define WIL_WMI_UT_HW_SYSAPI 10
171 #define WIL_WMI_UT_FORCE_RSN_IE	0x29
172 struct wil_wmi_force_rsn_ie {
173 	/* WIL_WMI_UT_HW_SYSAPI */
174 	uint16_t module_id;
175 	/* WIL_WMI_UT_FORCE_RSN_IE */
176 	uint16_t subtype_id;
177 	/* 0 = no change, 1 = remove if exists, 2 = add if does not exist */
178 	uint32_t state;
179 } __attribute__((packed));
180 
181 enum wil_wmi_discovery_mode {
182 	WMI_DISCOVERY_MODE_NON_OFFLOAD,
183 	WMI_DISCOVERY_MODE_OFFLOAD,
184 	WMI_DISCOVERY_MODE_PEER2PEER,
185 };
186 
187 struct wil_wmi_p2p_cfg_cmd {
188 	/* enum wil_wmi_discovery_mode */
189 	uint8_t discovery_mode;
190 	/* 0-based (wireless channel - 1) */
191 	uint8_t channel;
192 	/* set to WIL_DEFAULT_BI */
193 	uint16_t bcon_interval;
194 } __attribute__((packed));
195 #endif /* __linux__ */
196 
197 #ifdef ANDROID
198 
199 static int add_ipv6_rule(struct sigma_dut *dut, const char *ifname);
200 
201 #define ANDROID_KEYSTORE_GET 'g'
202 #define ANDROID_KEYSTORE_GET_PUBKEY 'b'
203 
android_keystore_get(char cmd,const char * key,unsigned char * val)204 static int android_keystore_get(char cmd, const char *key, unsigned char *val)
205 {
206 	/* Android 4.3 changed keystore design, so need to use keystore_get() */
207 #ifndef KEYSTORE_MESSAGE_SIZE
208 #define KEYSTORE_MESSAGE_SIZE 65535
209 #endif /* KEYSTORE_MESSAGE_SIZE */
210 
211 	ssize_t len;
212 	uint8_t *value = NULL;
213 
214 	__android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
215 			    "keystore command '%c' key '%s' --> keystore_get",
216 			    cmd, key);
217 
218 	len = keystore_get(key, strlen(key), &value);
219 	if (len < 0) {
220 		__android_log_print(ANDROID_LOG_DEBUG, "sigma_dut",
221 				    "keystore_get() failed");
222 		return -1;
223 	}
224 
225 	if (len > KEYSTORE_MESSAGE_SIZE)
226 		len = KEYSTORE_MESSAGE_SIZE;
227 	memcpy(val, value, len);
228 	free(value);
229 	return len;
230 }
231 #endif /* ANDROID */
232 
233 
234 #ifdef NL80211_SUPPORT
nl80211_sta_set_power_save(struct sigma_dut * dut,const char * intf,enum nl80211_ps_state ps_state)235 static int nl80211_sta_set_power_save(struct sigma_dut *dut,
236 				      const char *intf,
237 				      enum nl80211_ps_state ps_state)
238 {
239 	struct nl_msg *msg;
240 	int ifindex, ret;
241 
242 	ifindex = if_nametoindex(intf);
243 	if (ifindex == 0) {
244 		sigma_dut_print(dut, DUT_MSG_ERROR,
245 				"%s: Index for interface %s not found",
246 				__func__, intf);
247 		return -1;
248 	}
249 
250 	msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
251 			      NL80211_CMD_SET_POWER_SAVE);
252 	if (!msg) {
253 		sigma_dut_print(dut, DUT_MSG_ERROR,
254 				"%s: err in creating nl80211 msg", __func__);
255 		return -1;
256 	}
257 
258 	if (nla_put_u32(msg, NL80211_ATTR_PS_STATE, ps_state)) {
259 		sigma_dut_print(dut, DUT_MSG_ERROR,
260 				"%s: err in populating nl80211 msg", __func__);
261 		nlmsg_free(msg);
262 		return -1;
263 	}
264 
265 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
266 	if (ret) {
267 		sigma_dut_print(dut, DUT_MSG_ERROR,
268 				"%s: err in send_and_recv_msgs, ret=%d (%s)",
269 				__func__, ret, strerror(-ret));
270 		return -1;
271 	}
272 
273 	return 0;
274 }
275 #endif /* NL80211_SUPPORT */
276 
277 
set_power_save_wcn(struct sigma_dut * dut,const char * intf,int ps)278 static int set_power_save_wcn(struct sigma_dut *dut, const char *intf, int ps)
279 {
280 	char buf[100];
281 #ifdef NL80211_SUPPORT
282 	enum nl80211_ps_state ps_state;
283 
284 	ps_state = ps == 1 ? NL80211_PS_ENABLED : NL80211_PS_DISABLED;
285 	if (nl80211_sta_set_power_save(dut, intf, ps_state) == 0)
286 		return 0;
287 #endif /* NL80211_SUPPORT */
288 
289 	snprintf(buf, sizeof(buf), "iwpriv %s setPower %d", intf, ps);
290 	if (system(buf) != 0) {
291 		sigma_dut_print(dut, DUT_MSG_ERROR,
292 				"iwpriv setPower %d failed", ps);
293 		return -1;
294 	}
295 	return 0;
296 }
297 
298 
set_ps(const char * intf,struct sigma_dut * dut,int enabled)299 int set_ps(const char *intf, struct sigma_dut *dut, int enabled)
300 {
301 #ifdef __linux__
302 	char buf[100];
303 
304 	if (wifi_chip_type == DRIVER_WCN) {
305 		if (enabled) {
306 			if (set_power_save_wcn(dut, intf, 1) < 0) {
307 				snprintf(buf, sizeof(buf),
308 					 "iwpriv wlan0 dump 906");
309 				if (system(buf) != 0)
310 					goto set_power_save;
311 			}
312 		} else {
313 			if (set_power_save_wcn(dut, intf, 2) < 0) {
314 				snprintf(buf, sizeof(buf),
315 					 "iwpriv wlan0 dump 905");
316 				if (system(buf) != 0)
317 					goto set_power_save;
318 				snprintf(buf, sizeof(buf),
319 					 "iwpriv wlan0 dump 912");
320 				if (system(buf) != 0)
321 					goto set_power_save;
322 			}
323 		}
324 
325 		return 0;
326 	}
327 
328 set_power_save:
329 	snprintf(buf, sizeof(buf), "./iw dev %s set power_save %s",
330 		 intf, enabled ? "on" : "off");
331 	if (system(buf) != 0) {
332 		snprintf(buf, sizeof(buf), "iw dev %s set power_save %s",
333 			 intf, enabled ? "on" : "off");
334 		if (system(buf) != 0) {
335 			sigma_dut_print(dut, DUT_MSG_ERROR,
336 					"Failed to set power save %s",
337 					enabled ? "on" : "off");
338 			return -1;
339 		}
340 	}
341 
342 	return 0;
343 #else /* __linux__ */
344 	return -1;
345 #endif /* __linux__ */
346 }
347 
348 
349 #ifdef __linux__
350 
wil6210_get_debugfs_dir(struct sigma_dut * dut,char * path,size_t len)351 static int wil6210_get_debugfs_dir(struct sigma_dut *dut, char *path,
352 				   size_t len)
353 {
354 	DIR *dir, *wil_dir;
355 	struct dirent *entry;
356 	int ret = -1;
357 	const char *root_path = "/sys/kernel/debug/ieee80211";
358 
359 	dir = opendir(root_path);
360 	if (!dir)
361 		return -2;
362 
363 	while ((entry = readdir(dir))) {
364 		if (strcmp(entry->d_name, ".") == 0 ||
365 		    strcmp(entry->d_name, "..") == 0)
366 			continue;
367 
368 		if (snprintf(path, len, "%s/%s/wil6210",
369 			     root_path, entry->d_name) >= (int) len) {
370 			ret = -3;
371 			break;
372 		}
373 
374 		wil_dir = opendir(path);
375 		if (wil_dir) {
376 			closedir(wil_dir);
377 			ret = 0;
378 			break;
379 		}
380 	}
381 
382 	closedir(dir);
383 	return ret;
384 }
385 
386 
wil6210_wmi_send(struct sigma_dut * dut,uint16_t command,void * payload,uint16_t length)387 static int wil6210_wmi_send(struct sigma_dut *dut, uint16_t command,
388 			    void *payload, uint16_t length)
389 {
390 	struct {
391 		struct wil_wmi_header hdr;
392 		char payload[WIL_WMI_MAX_PAYLOAD];
393 	} __attribute__((packed)) cmd;
394 	char buf[128], fname[128];
395 	size_t towrite, written;
396 	FILE *f;
397 	int res;
398 
399 	if (length > WIL_WMI_MAX_PAYLOAD) {
400 		sigma_dut_print(dut, DUT_MSG_ERROR,
401 				"payload too large(%u, max %u)",
402 				length, WIL_WMI_MAX_PAYLOAD);
403 		return -1;
404 	}
405 
406 	memset(&cmd.hdr, 0, sizeof(cmd.hdr));
407 	cmd.hdr.cmd = command;
408 	memcpy(cmd.payload, payload, length);
409 
410 	if (wil6210_get_debugfs_dir(dut, buf, sizeof(buf))) {
411 		sigma_dut_print(dut, DUT_MSG_ERROR,
412 				"failed to get wil6210 debugfs dir");
413 		return -1;
414 	}
415 
416 	res = snprintf(fname, sizeof(fname), "%s/wmi_send", buf);
417 	if (res < 0 || res >= sizeof(fname))
418 		return -1;
419 	f = fopen(fname, "wb");
420 	if (!f) {
421 		sigma_dut_print(dut, DUT_MSG_ERROR,
422 				"failed to open: %s", fname);
423 		return -1;
424 	}
425 
426 	towrite = sizeof(cmd.hdr) + length;
427 	written = fwrite(&cmd, 1, towrite, f);
428 	fclose(f);
429 	if (written != towrite) {
430 		sigma_dut_print(dut, DUT_MSG_ERROR,
431 				"failed to send wmi %u", command);
432 		return -1;
433 	}
434 
435 	return 0;
436 }
437 
438 
wil6210_get_sta_info_field(struct sigma_dut * dut,const char * bssid,const char * pattern,unsigned int * field)439 static int wil6210_get_sta_info_field(struct sigma_dut *dut, const char *bssid,
440 				      const char *pattern, unsigned int *field)
441 {
442 	char buf[128], fname[128];
443 	FILE *f;
444 	regex_t re;
445 	regmatch_t m[2];
446 	int rc, ret = -1, res;
447 
448 	if (wil6210_get_debugfs_dir(dut, buf, sizeof(buf))) {
449 		sigma_dut_print(dut, DUT_MSG_ERROR,
450 				"failed to get wil6210 debugfs dir");
451 		return -1;
452 	}
453 
454 	res = snprintf(fname, sizeof(fname), "%s/stations", buf);
455 	if (res < 0 || res >= sizeof(fname))
456 		return -1;
457 	f = fopen(fname, "r");
458 	if (!f) {
459 		sigma_dut_print(dut, DUT_MSG_ERROR,
460 				"failed to open: %s", fname);
461 		return -1;
462 	}
463 
464 	if (regcomp(&re, pattern, REG_EXTENDED)) {
465 		sigma_dut_print(dut, DUT_MSG_ERROR,
466 				"regcomp failed: %s", pattern);
467 		goto out;
468 	}
469 
470 	/*
471 	 * find the entry for the mac address
472 	 * line is of the form: [n] 11:22:33:44:55:66 state AID aid
473 	 */
474 	while (fgets(buf, sizeof(buf), f)) {
475 		if (strcasestr(buf, bssid)) {
476 			/* extract the field (CID/AID/state) */
477 			rc = regexec(&re, buf, 2, m, 0);
478 			if (!rc && (m[1].rm_so >= 0)) {
479 				buf[m[1].rm_eo] = 0;
480 				*field = atoi(&buf[m[1].rm_so]);
481 				ret = 0;
482 				break;
483 			}
484 		}
485 	}
486 
487 	regfree(&re);
488 	if (ret)
489 		sigma_dut_print(dut, DUT_MSG_ERROR,
490 				"could not extract field");
491 
492 out:
493 	fclose(f);
494 
495 	return ret;
496 }
497 
498 
wil6210_get_cid(struct sigma_dut * dut,const char * bssid,unsigned int * cid)499 static int wil6210_get_cid(struct sigma_dut *dut, const char *bssid,
500 			   unsigned int *cid)
501 {
502 	const char *pattern = "\\[([0-9]+)\\]";
503 
504 	return wil6210_get_sta_info_field(dut, bssid, pattern, cid);
505 }
506 
507 
wil6210_send_brp_rx(struct sigma_dut * dut,const char * mac,int l_rx)508 static int wil6210_send_brp_rx(struct sigma_dut *dut, const char *mac,
509 			       int l_rx)
510 {
511 	struct wil_wmi_bf_trig_cmd cmd;
512 	unsigned int cid;
513 
514 	memset(&cmd, 0, sizeof(cmd));
515 
516 	if (wil6210_get_cid(dut, mac, &cid))
517 		return -1;
518 
519 	cmd.bf_type = WIL_WMI_BRP_RX;
520 	cmd.sta_id = cid;
521 	/* training length (l_rx) is ignored, FW always uses length 16 */
522 	return wil6210_wmi_send(dut, WIL_WMI_BF_TRIG_CMDID,
523 				&cmd, sizeof(cmd));
524 }
525 
526 
wil6210_send_sls(struct sigma_dut * dut,const char * mac)527 static int wil6210_send_sls(struct sigma_dut *dut, const char *mac)
528 {
529 	struct wil_wmi_bf_trig_cmd cmd;
530 
531 	memset(&cmd, 0, sizeof(cmd));
532 
533 	if (parse_mac_address(dut, mac, (unsigned char *)&cmd.dest_mac))
534 		return -1;
535 
536 	cmd.bf_type = WIL_WMI_SLS;
537 	return wil6210_wmi_send(dut, WIL_WMI_BF_TRIG_CMDID,
538 				&cmd, sizeof(cmd));
539 }
540 
541 
wil6210_set_ese(struct sigma_dut * dut,int count,struct sigma_ese_alloc * allocs)542 int wil6210_set_ese(struct sigma_dut *dut, int count,
543 		    struct sigma_ese_alloc *allocs)
544 {
545 	struct wil_wmi_ese_cfg cmd = { };
546 	int i;
547 
548 	if (count == 0 || count > WIL_WMI_MAX_ESE_SLOTS)
549 		return -1;
550 
551 	if (dut->ap_bcnint <= 0) {
552 		sigma_dut_print(dut, DUT_MSG_ERROR,
553 				"invalid beacon interval(%d), check test",
554 				dut->ap_bcnint);
555 		return -1;
556 	}
557 
558 	cmd.ese_advertisment = WIL_WMI_ADVERTISE_ESE_IN_BEACON;
559 	cmd.flags = 0x1d;
560 	cmd.num_allocs = count;
561 	for (i = 0; i < count; i++) {
562 		/*
563 		 * Convert percent from BI (BI specified in milliseconds)
564 		 * to absolute duration in microseconds.
565 		 */
566 		cmd.slots[i].duration =
567 			(allocs[i].percent_bi * dut->ap_bcnint * 1000) / 100;
568 		switch (allocs[i].type) {
569 		case ESE_CBAP:
570 			cmd.slots[i].slot_type = WIL_WMI_ESE_CBAP;
571 			break;
572 		case ESE_SP:
573 			cmd.slots[i].slot_type = WIL_WMI_ESE_SP;
574 			break;
575 		default:
576 			sigma_dut_print(dut, DUT_MSG_ERROR,
577 					"invalid slot type(%d) at index %d",
578 					allocs[i].type, i);
579 			return -1;
580 		}
581 		cmd.slots[i].src_aid = allocs[i].src_aid;
582 		cmd.slots[i].dst_aid = allocs[i].dst_aid;
583 		sigma_dut_print(dut, DUT_MSG_INFO,
584 				"slot %d, duration %u, type %d, srcAID %u dstAID %u",
585 				i, cmd.slots[i].duration,
586 				cmd.slots[i].slot_type, cmd.slots[i].src_aid,
587 				cmd.slots[i].dst_aid);
588 	}
589 
590 	return wil6210_wmi_send(dut, WIL_WMI_ESE_CFG_CMDID, &cmd, sizeof(cmd));
591 }
592 
593 
wil6210_set_force_mcs(struct sigma_dut * dut,int force,int mcs)594 int wil6210_set_force_mcs(struct sigma_dut *dut, int force, int mcs)
595 {
596 	struct wil_wmi_force_mcs cmd = { };
597 
598 	cmd.module_id = WIL_WMI_UT_HW_SYSAPI;
599 	cmd.subtype_id = WIL_WMI_UT_FORCE_MCS;
600 	cmd.force_enable = (uint32_t) force;
601 	cmd.mcs = (uint32_t) mcs;
602 
603 	return wil6210_wmi_send(dut, WIL_WMI_UNIT_TEST_CMDID,
604 				&cmd, sizeof(cmd));
605 }
606 
607 
wil6210_force_rsn_ie(struct sigma_dut * dut,int state)608 static int wil6210_force_rsn_ie(struct sigma_dut *dut, int state)
609 {
610 	struct wil_wmi_force_rsn_ie cmd = { };
611 
612 	cmd.module_id = WIL_WMI_UT_HW_SYSAPI;
613 	cmd.subtype_id = WIL_WMI_UT_FORCE_RSN_IE;
614 	cmd.state = (uint32_t) state;
615 
616 	return wil6210_wmi_send(dut, WIL_WMI_UNIT_TEST_CMDID,
617 				&cmd, sizeof(cmd));
618 }
619 
620 
621 /*
622  * this function is also used to configure generic remain-on-channel
623  */
wil6210_p2p_cfg(struct sigma_dut * dut,int freq)624 static int wil6210_p2p_cfg(struct sigma_dut *dut, int freq)
625 {
626 	struct wil_wmi_p2p_cfg_cmd cmd = { };
627 	int channel = freq_to_channel(freq);
628 
629 	if (channel < 0)
630 		return -1;
631 	cmd.discovery_mode = WMI_DISCOVERY_MODE_NON_OFFLOAD;
632 	cmd.channel = channel - 1;
633 	cmd.bcon_interval = WIL_DEFAULT_BI;
634 	cmd.discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER;
635 
636 	return wil6210_wmi_send(dut, WIL_WMI_P2P_CFG_CMDID,
637 				&cmd, sizeof(cmd));
638 }
639 
640 
wil6210_remain_on_channel(struct sigma_dut * dut,int freq)641 static int wil6210_remain_on_channel(struct sigma_dut *dut, int freq)
642 {
643 	int ret = wil6210_p2p_cfg(dut, freq);
644 
645 	if (ret)
646 		return ret;
647 
648 	ret = wil6210_wmi_send(dut, WIL_WMI_START_LISTEN_CMDID, NULL, 0);
649 	if (!ret) {
650 		/*
651 		 * wait a bit to allow FW to setup the radio
652 		 * especially important if we switch channels
653 		 */
654 		usleep(500000);
655 	}
656 
657 	return ret;
658 }
659 
660 
wil6210_stop_discovery(struct sigma_dut * dut)661 static int wil6210_stop_discovery(struct sigma_dut *dut)
662 {
663 	return wil6210_wmi_send(dut, WIL_WMI_DISCOVERY_STOP_CMDID, NULL, 0);
664 }
665 
666 
wil6210_transmit_frame(struct sigma_dut * dut,int freq,int wait_duration,const char * frame,size_t frame_len)667 static int wil6210_transmit_frame(struct sigma_dut *dut, int freq,
668 				  int wait_duration,
669 				  const char *frame, size_t frame_len)
670 {
671 	char buf[128], fname[128];
672 	FILE *f;
673 	int res = 0, r;
674 	size_t written;
675 
676 	if (wil6210_get_debugfs_dir(dut, buf, sizeof(buf))) {
677 		sigma_dut_print(dut, DUT_MSG_ERROR,
678 				"failed to get wil6210 debugfs dir");
679 		return -1;
680 	}
681 	r = snprintf(fname, sizeof(fname), "%s/tx_mgmt", buf);
682 	if (r < 0 || r >= sizeof(fname))
683 		return -1;
684 
685 	if (wil6210_remain_on_channel(dut, freq)) {
686 		sigma_dut_print(dut, DUT_MSG_ERROR,
687 				"failed to listen on channel");
688 		return -1;
689 	}
690 
691 	f = fopen(fname, "wb");
692 	if (!f) {
693 		sigma_dut_print(dut, DUT_MSG_ERROR,
694 				"failed to open: %s", fname);
695 		res = -1;
696 		goto out_stop;
697 	}
698 	written = fwrite(frame, 1, frame_len, f);
699 	fclose(f);
700 
701 	if (written != frame_len) {
702 		sigma_dut_print(dut, DUT_MSG_ERROR,
703 				"failed to transmit frame (got %zd, expected %zd)",
704 				written, frame_len);
705 		res = -1;
706 		goto out_stop;
707 	}
708 
709 	usleep(wait_duration * 1000);
710 
711 out_stop:
712 	wil6210_stop_discovery(dut);
713 	return res;
714 }
715 
716 
find_template_frame_tag(struct template_frame_tag * tags,int total_tags,int tag_num)717 static int find_template_frame_tag(struct template_frame_tag *tags,
718 				   int total_tags, int tag_num)
719 {
720 	int i;
721 
722 	for (i = 0; i < total_tags; i++) {
723 		if (tag_num == tags[i].num)
724 			return i;
725 	}
726 
727 	return -1;
728 }
729 
730 
replace_p2p_attribute(struct sigma_dut * dut,char * buf,size_t len,int id,const char * value,size_t val_len)731 static int replace_p2p_attribute(struct sigma_dut *dut, char *buf, size_t len,
732 				 int id, const char *value, size_t val_len)
733 {
734 	struct wfa_p2p_attribute *attr = (struct wfa_p2p_attribute *) buf;
735 
736 	if (len < 3 + val_len) {
737 		sigma_dut_print(dut, DUT_MSG_ERROR,
738 				"not enough space to replace P2P attribute");
739 		return -1;
740 	}
741 
742 	if (attr->len != val_len) {
743 		sigma_dut_print(dut, DUT_MSG_ERROR,
744 				"attribute length mismatch (need %zu have %hu)",
745 				val_len, attr->len);
746 		return -1;
747 	}
748 
749 	if (attr->id != id) {
750 		sigma_dut_print(dut, DUT_MSG_ERROR,
751 				"incorrect attribute id (expected %d actual %d)",
752 				id, attr->id);
753 		return -1;
754 	}
755 
756 	memcpy(attr->variable, value, val_len);
757 
758 	return 0;
759 }
760 
761 
parse_template_frame_file(struct sigma_dut * dut,const char * fname,char * buf,size_t * length,struct template_frame_tag * tags,size_t * num_tags)762 static int parse_template_frame_file(struct sigma_dut *dut, const char *fname,
763 				     char *buf, size_t *length,
764 				     struct template_frame_tag *tags,
765 				     size_t *num_tags)
766 {
767 	char line[512];
768 	FILE *f;
769 	size_t offset = 0, tag_index = 0;
770 	int num, index;
771 	int in_tag = 0, tag_num = 0, tag_offset = 0;
772 
773 	if (*length < sizeof(struct ieee80211_hdr_3addr)) {
774 		sigma_dut_print(dut, DUT_MSG_ERROR,
775 				"supplied buffer is too small");
776 		return -1;
777 	}
778 
779 	f = fopen(fname, "r");
780 	if (!f) {
781 		sigma_dut_print(dut, DUT_MSG_ERROR,
782 				"failed to open template file %s", fname);
783 		return -1;
784 	}
785 
786 	/*
787 	 * template file format: lines beginning with # are comments and
788 	 * ignored.
789 	 * It is possible to tag bytes in the frame to make it easy
790 	 * to replace fields in the template, espcially if they appear
791 	 * in variable-sized sections (such as IEs)
792 	 * This is done by a line beginning with $NUM where NUM is an integer
793 	 * tag number. It can be followed by space(s) and comment.
794 	 * The next line is considered the tagged bytes. The parser will fill
795 	 * the tag number, offset and length of the tagged bytes.
796 	 * rest of the lines contain frame bytes as sequence of hex digits,
797 	 * 2 digits for each byte. Spaces are allowed between bytes.
798 	 * On bytes lines only hex digits and spaces are allowed
799 	 */
800 	while (!feof(f)) {
801 		if (!fgets(line, sizeof(line), f))
802 			break;
803 		index = 0;
804 		while (isspace((unsigned char) line[index]))
805 			index++;
806 		if (!line[index] || line[index] == '#')
807 			continue;
808 		if (line[index] == '$') {
809 			if (tags) {
810 				index++;
811 				tag_num = strtol(&line[index], NULL, 0);
812 				tag_offset = offset;
813 				in_tag = 1;
814 			}
815 			continue;
816 		}
817 		while (line[index]) {
818 			if (isspace((unsigned char) line[index])) {
819 				index++;
820 				continue;
821 			}
822 			num = hex_byte(&line[index]);
823 			if (num < 0)
824 				break;
825 			buf[offset++] = num;
826 			if (offset == *length)
827 				goto out;
828 			index += 2;
829 		}
830 
831 		if (in_tag) {
832 			if (tag_index < *num_tags) {
833 				tags[tag_index].num = tag_num;
834 				tags[tag_index].offset = tag_offset;
835 				tags[tag_index].len = offset - tag_offset;
836 				tag_index++;
837 			} else {
838 				sigma_dut_print(dut, DUT_MSG_INFO,
839 						"too many tags, tag ignored");
840 			}
841 			in_tag = 0;
842 		}
843 	}
844 
845 	if (num_tags)
846 		*num_tags = tag_index;
847 out:
848 	fclose(f);
849 	if (offset < sizeof(struct ieee80211_hdr_3addr)) {
850 		sigma_dut_print(dut, DUT_MSG_ERROR,
851 				"template frame is too small");
852 		return -1;
853 	}
854 
855 	*length = offset;
856 	return 0;
857 }
858 
859 #endif /* __linux__ */
860 
861 
static_ip_file(int proto,const char * addr,const char * mask,const char * gw)862 static void static_ip_file(int proto, const char *addr, const char *mask,
863 			   const char *gw)
864 {
865 	if (proto) {
866 		FILE *f = fopen("static-ip", "w");
867 		if (f) {
868 			fprintf(f, "%d %s %s %s\n", proto, addr,
869 				mask ? mask : "N/A",
870 				gw ? gw : "N/A");
871 			fclose(f);
872 		}
873 	} else {
874 		unlink("static-ip");
875 	}
876 }
877 
878 
send_neighbor_request(struct sigma_dut * dut,const char * intf,const char * ssid)879 static int send_neighbor_request(struct sigma_dut *dut, const char *intf,
880 				 const char *ssid)
881 {
882 #ifdef __linux__
883 	char buf[100];
884 
885 	snprintf(buf, sizeof(buf), "iwpriv %s neighbor %s",
886 		 intf, ssid);
887 	sigma_dut_print(dut, DUT_MSG_INFO, "Request: %s", buf);
888 
889 	if (system(buf) != 0) {
890 		sigma_dut_print(dut, DUT_MSG_ERROR,
891 				"iwpriv neighbor request failed");
892 		return -1;
893 	}
894 
895 	sigma_dut_print(dut, DUT_MSG_INFO, "iwpriv neighbor request send");
896 
897 	return 0;
898 #else /* __linux__ */
899 	return -1;
900 #endif /* __linux__ */
901 }
902 
903 
send_trans_mgmt_query(struct sigma_dut * dut,const char * intf,struct sigma_cmd * cmd)904 static int send_trans_mgmt_query(struct sigma_dut *dut, const char *intf,
905 				 struct sigma_cmd *cmd)
906 {
907 	const char *val;
908 	int reason_code = 0;
909 	char buf[1024];
910 
911 	/*
912 	 * In the earlier builds we used WNM_QUERY and in later
913 	 * builds used WNM_BSS_QUERY.
914 	 */
915 
916 	val = get_param(cmd, "BTMQuery_Reason_Code");
917 	if (val)
918 		reason_code = atoi(val);
919 
920 	val = get_param(cmd, "Cand_List");
921 	if (val && atoi(val) == 1 && dut->btm_query_cand_list) {
922 		snprintf(buf, sizeof(buf), "WNM_BSS_QUERY %d%s", reason_code,
923 			 dut->btm_query_cand_list);
924 		free(dut->btm_query_cand_list);
925 		dut->btm_query_cand_list = NULL;
926 	} else {
927 		snprintf(buf, sizeof(buf), "WNM_BSS_QUERY %d", reason_code);
928 	}
929 
930 	if (wpa_command(intf, buf) != 0) {
931 		sigma_dut_print(dut, DUT_MSG_ERROR,
932 				"transition management query failed");
933 		return -1;
934 	}
935 
936 	sigma_dut_print(dut, DUT_MSG_DEBUG,
937 			"transition management query sent");
938 
939 	return 0;
940 }
941 
942 
is_ip_addr(const char * str)943 int is_ip_addr(const char *str)
944 {
945 	const char *pos = str;
946 	struct in_addr addr;
947 
948 	while (*pos) {
949 		if (*pos != '.' && (*pos < '0' || *pos > '9'))
950 			return 0;
951 		pos++;
952 	}
953 
954 	return inet_aton(str, &addr);
955 }
956 
957 
get_ip_config(struct sigma_dut * dut,const char * ifname,char * buf,size_t buf_len)958 int get_ip_config(struct sigma_dut *dut, const char *ifname, char *buf,
959 		  size_t buf_len)
960 {
961 	char tmp[256];
962 	char ip[16], mask[15], dns[16], sec_dns[16];
963 	int is_dhcp = 0;
964 	int s;
965 #ifdef ANDROID
966 	char prop[PROPERTY_VALUE_MAX];
967 #else /* ANDROID */
968 	FILE *f;
969 #ifdef __linux__
970 	const char *str_ps;
971 #endif /* __linux__ */
972 #endif /* ANDROID */
973 
974 	ip[0] = '\0';
975 	mask[0] = '\0';
976 	dns[0] = '\0';
977 	sec_dns[0] = '\0';
978 
979 	s = socket(PF_INET, SOCK_DGRAM, 0);
980 	if (s >= 0) {
981 		struct ifreq ifr;
982 		struct sockaddr_in saddr;
983 
984 		memset(&ifr, 0, sizeof(ifr));
985 		strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
986 		if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
987 			sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get "
988 					"%s IP address: %s",
989 					ifname, strerror(errno));
990 		} else {
991 			memcpy(&saddr, &ifr.ifr_addr,
992 			       sizeof(struct sockaddr_in));
993 			strlcpy(ip, inet_ntoa(saddr.sin_addr), sizeof(ip));
994 		}
995 
996 		if (ioctl(s, SIOCGIFNETMASK, &ifr) == 0) {
997 			memcpy(&saddr, &ifr.ifr_addr,
998 			       sizeof(struct sockaddr_in));
999 			strlcpy(mask, inet_ntoa(saddr.sin_addr), sizeof(mask));
1000 		}
1001 		close(s);
1002 	}
1003 
1004 #ifdef ANDROID
1005 	snprintf(tmp, sizeof(tmp), "dhcp.%s.pid", ifname);
1006 	if (property_get(tmp, prop, NULL) != 0 && atoi(prop) > 0) {
1007 		snprintf(tmp, sizeof(tmp), "dhcp.%s.result", ifname);
1008 		if (property_get(tmp, prop, NULL) != 0 &&
1009 		    strcmp(prop, "ok") == 0) {
1010 			snprintf(tmp, sizeof(tmp), "dhcp.%s.ipaddress",
1011 				 ifname);
1012 			if (property_get(tmp, prop, NULL) != 0 &&
1013 			    strcmp(ip, prop) == 0)
1014 				is_dhcp = 1;
1015 		}
1016 	}
1017 
1018 	snprintf(tmp, sizeof(tmp), "dhcp.%s.dns1", ifname);
1019 	if (property_get(tmp, prop, NULL) != 0)
1020 		strlcpy(dns, prop, sizeof(dns));
1021 	else if (property_get("net.dns1", prop, NULL) != 0)
1022 		strlcpy(dns, prop, sizeof(dns));
1023 
1024 	snprintf(tmp, sizeof(tmp), "dhcp.%s.dns2", ifname);
1025 	if (property_get(tmp, prop, NULL) != 0)
1026 		strlcpy(sec_dns, prop, sizeof(sec_dns));
1027 #else /* ANDROID */
1028 #ifdef __linux__
1029 	if (get_driver_type(dut) == DRIVER_OPENWRT)
1030 		str_ps = "ps -w";
1031 	else
1032 		str_ps = "ps ax";
1033 	snprintf(tmp, sizeof(tmp),
1034 		 "%s | grep dhclient | grep -v grep | grep -q %s",
1035 		 str_ps, ifname);
1036 	if (system(tmp) == 0)
1037 		is_dhcp = 1;
1038 	else {
1039 		snprintf(tmp, sizeof(tmp),
1040 			 "%s | grep udhcpc | grep -v grep | grep -q %s",
1041 			 str_ps, ifname);
1042 		if (system(tmp) == 0)
1043 			is_dhcp = 1;
1044 		else {
1045 			snprintf(tmp, sizeof(tmp),
1046 				 "%s | grep dhcpcd | grep -v grep | grep -q %s",
1047 				 str_ps, ifname);
1048 			if (system(tmp) == 0)
1049 				is_dhcp = 1;
1050 		}
1051 	}
1052 #endif /* __linux__ */
1053 
1054 	f = fopen("/etc/resolv.conf", "r");
1055 	if (f) {
1056 		char *pos, *pos2;
1057 
1058 		while (fgets(tmp, sizeof(tmp), f)) {
1059 			if (strncmp(tmp, "nameserver", 10) != 0)
1060 				continue;
1061 			pos = tmp + 10;
1062 			while (*pos == ' ' || *pos == '\t')
1063 				pos++;
1064 			pos2 = pos;
1065 			while (*pos2) {
1066 				if (*pos2 == '\n' || *pos2 == '\r') {
1067 					*pos2 = '\0';
1068 					break;
1069 				}
1070 				pos2++;
1071 			}
1072 			if (!dns[0])
1073 				strlcpy(dns, pos, sizeof(dns));
1074 			else if (!sec_dns[0])
1075 				strlcpy(sec_dns, pos, sizeof(sec_dns));
1076 		}
1077 		fclose(f);
1078 	}
1079 #endif /* ANDROID */
1080 
1081 	snprintf(buf, buf_len, "dhcp,%d,ip,%s,mask,%s,primary-dns,%s",
1082 		 is_dhcp, ip, mask, dns);
1083 	buf[buf_len - 1] = '\0';
1084 
1085 	return 0;
1086 }
1087 
1088 
1089 
1090 
get_ipv6_config(struct sigma_dut * dut,const char * ifname,char * buf,size_t buf_len)1091 int get_ipv6_config(struct sigma_dut *dut, const char *ifname, char *buf,
1092 		    size_t buf_len)
1093 {
1094 #ifdef __linux__
1095 #ifdef ANDROID
1096 	char cmd[200], result[1000], *pos, *end;
1097 	FILE *f;
1098 	size_t len;
1099 
1100 	snprintf(cmd, sizeof(cmd), "ip addr show dev %s scope global", ifname);
1101 	f = popen(cmd, "r");
1102 	if (f == NULL)
1103 		return -1;
1104 	len = fread(result, 1, sizeof(result) - 1, f);
1105 	pclose(f);
1106 	if (len == 0)
1107 		return -1;
1108 	result[len] = '\0';
1109 	sigma_dut_print(dut, DUT_MSG_DEBUG, "%s result: %s\n", cmd, result);
1110 
1111 	pos = strstr(result, "inet6 ");
1112 	if (pos == NULL)
1113 		return -1;
1114 	pos += 6;
1115 	end = strchr(pos, ' ');
1116 	if (end)
1117 		*end = '\0';
1118 	end = strchr(pos, '/');
1119 	if (end)
1120 		*end = '\0';
1121 	snprintf(buf, buf_len, "ip,%s", pos);
1122 	buf[buf_len - 1] = '\0';
1123 	return 0;
1124 #else /* ANDROID */
1125 	struct ifaddrs *ifaddr, *ifa;
1126 	int res, found = 0;
1127 	char host[NI_MAXHOST];
1128 
1129 	if (getifaddrs(&ifaddr) < 0) {
1130 		perror("getifaddrs");
1131 		return -1;
1132 	}
1133 
1134 	for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
1135 		if (strcasecmp(ifname, ifa->ifa_name) != 0)
1136 			continue;
1137 		if (ifa->ifa_addr == NULL ||
1138 		    ifa->ifa_addr->sa_family != AF_INET6)
1139 			continue;
1140 
1141 		res = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6),
1142 				  host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
1143 		if (res != 0) {
1144 			sigma_dut_print(dut, DUT_MSG_DEBUG, "getnameinfo: %s",
1145 					gai_strerror(res));
1146 			continue;
1147 		}
1148 		if (strncmp(host, "fe80::", 6) == 0)
1149 			continue; /* skip link-local */
1150 
1151 		sigma_dut_print(dut, DUT_MSG_DEBUG, "ifaddr: %s", host);
1152 		found = 1;
1153 		break;
1154 	}
1155 
1156 	freeifaddrs(ifaddr);
1157 
1158 	if (found) {
1159 		char *pos;
1160 		pos = strchr(host, '%');
1161 		if (pos)
1162 			*pos = '\0';
1163 		snprintf(buf, buf_len, "ip,%s", host);
1164 		buf[buf_len - 1] = '\0';
1165 		return 0;
1166 	}
1167 
1168 #endif /* ANDROID */
1169 #endif /* __linux__ */
1170 	return -1;
1171 }
1172 
1173 
cmd_sta_get_ip_config(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)1174 static enum sigma_cmd_result cmd_sta_get_ip_config(struct sigma_dut *dut,
1175 						   struct sigma_conn *conn,
1176 						   struct sigma_cmd *cmd)
1177 {
1178 	const char *intf = get_param(cmd, "Interface");
1179 	const char *ifname;
1180 	char buf[200];
1181 	const char *val;
1182 	int type = 1;
1183 
1184 	if (intf == NULL)
1185 		return -1;
1186 
1187 	if (strcmp(intf, get_main_ifname(dut)) == 0)
1188 		ifname = get_station_ifname(dut);
1189 	else
1190 		ifname = intf;
1191 
1192 	/*
1193 	 * UCC may assume the IP address to be available immediately after
1194 	 * association without trying to run sta_get_ip_config multiple times.
1195 	 * Sigma CAPI does not specify this command as a block command that
1196 	 * would wait for the address to become available, but to pass tests
1197 	 * more reliably, it looks like such a wait may be needed here.
1198 	 */
1199 	if (wait_ip_addr(dut, ifname, 15) < 0) {
1200 		sigma_dut_print(dut, DUT_MSG_INFO, "Could not get IP address "
1201 				"for sta_get_ip_config");
1202 		/*
1203 		 * Try to continue anyway since many UCC tests do not really
1204 		 * care about the return value from here..
1205 		 */
1206 	}
1207 
1208 	val = get_param(cmd, "Type");
1209 	if (val)
1210 		type = atoi(val);
1211 	if (type == 2 || dut->last_set_ip_config_ipv6) {
1212 		int i;
1213 
1214 		/*
1215 		 * Since we do not have proper wait for IPv6 addresses, use a
1216 		 * fixed two second delay here as a workaround for UCC script
1217 		 * assuming IPv6 address is available when this command returns.
1218 		 * Some scripts did not use Type,2 properly for IPv6, so include
1219 		 * also the cases where the previous sta_set_ip_config indicated
1220 		 * use of IPv6.
1221 		 */
1222 		sigma_dut_print(dut, DUT_MSG_INFO, "Wait up to extra ten seconds in sta_get_ip_config for IPv6 address");
1223 		for (i = 0; i < 10; i++) {
1224 			sleep(1);
1225 			if (get_ipv6_config(dut, ifname, buf, sizeof(buf)) == 0)
1226 			{
1227 				sigma_dut_print(dut, DUT_MSG_INFO, "Found IPv6 address");
1228 				send_resp(dut, conn, SIGMA_COMPLETE, buf);
1229 #ifdef ANDROID
1230 				sigma_dut_print(dut, DUT_MSG_INFO,
1231 						"Adding IPv6 rule on Android");
1232 				add_ipv6_rule(dut, intf);
1233 #endif /* ANDROID */
1234 
1235 				return 0;
1236 			}
1237 		}
1238 	}
1239 	if (type == 1) {
1240 		if (get_ip_config(dut, ifname, buf, sizeof(buf)) < 0)
1241 			return -2;
1242 	} else if (type == 2) {
1243 		if (get_ipv6_config(dut, ifname, buf, sizeof(buf)) < 0)
1244 			return -2;
1245 	} else {
1246 		send_resp(dut, conn, SIGMA_ERROR,
1247 			  "errorCode,Unsupported address type");
1248 		return 0;
1249 	}
1250 
1251 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
1252 	return 0;
1253 }
1254 
1255 
kill_dhcp_client(struct sigma_dut * dut,const char * ifname)1256 static void kill_dhcp_client(struct sigma_dut *dut, const char *ifname)
1257 {
1258 #ifdef __linux__
1259 	char buf[200];
1260 	char path[128];
1261 	struct stat s;
1262 
1263 #ifdef ANDROID
1264 	snprintf(path, sizeof(path), "/data/misc/dhcp/dhcpcd-%s.pid", ifname);
1265 #else /* ANDROID */
1266 	snprintf(path, sizeof(path), "/var/run/dhclient-%s.pid", ifname);
1267 #endif /* ANDROID */
1268 	if (stat(path, &s) == 0) {
1269 		snprintf(buf, sizeof(buf), "kill `cat %s`", path);
1270 		sigma_dut_print(dut, DUT_MSG_INFO,
1271 				"Kill previous DHCP client: %s", buf);
1272 		if (system(buf) != 0)
1273 			sigma_dut_print(dut, DUT_MSG_INFO,
1274 					"Failed to kill DHCP client");
1275 		unlink(path);
1276 		sleep(1);
1277 	} else {
1278 		snprintf(path, sizeof(path), "/var/run/dhcpcd-%s.pid", ifname);
1279 
1280 		if (stat(path, &s) == 0) {
1281 			snprintf(buf, sizeof(buf), "kill `cat %s`", path);
1282 			sigma_dut_print(dut, DUT_MSG_INFO,
1283 					"Kill previous DHCP client: %s", buf);
1284 			if (system(buf) != 0)
1285 				sigma_dut_print(dut, DUT_MSG_INFO,
1286 						"Failed to kill DHCP client");
1287 			unlink(path);
1288 			sleep(1);
1289 		}
1290 	}
1291 #endif /* __linux__ */
1292 }
1293 
1294 
start_dhcp_client(struct sigma_dut * dut,const char * ifname)1295 static int start_dhcp_client(struct sigma_dut *dut, const char *ifname)
1296 {
1297 #ifdef __linux__
1298 	char buf[200];
1299 
1300 #ifdef ANDROID
1301 	if (access("/system/bin/dhcpcd", F_OK) != -1) {
1302 		snprintf(buf, sizeof(buf),
1303 			 "/system/bin/dhcpcd -b %s", ifname);
1304 	} else if (access("/system/bin/dhcptool", F_OK) != -1) {
1305 		snprintf(buf, sizeof(buf), "/system/bin/dhcptool %s &", ifname);
1306 	} else if (access("/vendor/bin/dhcpcd", F_OK) != -1) {
1307 		snprintf(buf, sizeof(buf), "/vendor/bin/dhcpcd -b %s", ifname);
1308 	} else if (access("/vendor/bin/dhcptool", F_OK) != -1) {
1309 		snprintf(buf, sizeof(buf), "/vendor/bin/dhcptool %s", ifname);
1310 	} else {
1311 		sigma_dut_print(dut, DUT_MSG_ERROR,
1312 				"DHCP client program missing");
1313 		return 0;
1314 	}
1315 #else /* ANDROID */
1316 	snprintf(buf, sizeof(buf),
1317 		 "dhclient -nw -pf /var/run/dhclient-%s.pid %s",
1318 		 ifname, ifname);
1319 #endif /* ANDROID */
1320 	sigma_dut_print(dut, DUT_MSG_INFO, "Start DHCP client: %s", buf);
1321 	if (system(buf) != 0) {
1322 		snprintf(buf, sizeof(buf), "dhcpcd -t 0 %s &", ifname);
1323 		if (system(buf) != 0) {
1324 			sigma_dut_print(dut, DUT_MSG_INFO,
1325 					"Failed to start DHCP client");
1326 #ifndef ANDROID
1327 			return -1;
1328 #endif /* ANDROID */
1329 		}
1330 	}
1331 #endif /* __linux__ */
1332 
1333 	return 0;
1334 }
1335 
1336 
clear_ip_addr(struct sigma_dut * dut,const char * ifname)1337 static int clear_ip_addr(struct sigma_dut *dut, const char *ifname)
1338 {
1339 #ifdef __linux__
1340 	char buf[200];
1341 
1342 	snprintf(buf, sizeof(buf), "ip addr flush dev %s", ifname);
1343 	if (system(buf) != 0) {
1344 		sigma_dut_print(dut, DUT_MSG_INFO,
1345 				"Failed to clear IP addresses");
1346 		return -1;
1347 	}
1348 #endif /* __linux__ */
1349 
1350 	return 0;
1351 }
1352 
1353 
1354 #ifdef ANDROID
add_ipv6_rule(struct sigma_dut * dut,const char * ifname)1355 static int add_ipv6_rule(struct sigma_dut *dut, const char *ifname)
1356 {
1357 	char cmd[200], *result, *pos;
1358 	FILE *fp;
1359 	int tableid;
1360 	size_t len, result_len = 1000;
1361 
1362 	snprintf(cmd, sizeof(cmd), "ip -6 route list table all | grep %s",
1363 		 ifname);
1364 	fp = popen(cmd, "r");
1365 	if (fp == NULL)
1366 		return -1;
1367 
1368 	result = malloc(result_len);
1369 	if (result == NULL) {
1370 		fclose(fp);
1371 		return -1;
1372 	}
1373 
1374 	len = fread(result, 1, result_len - 1, fp);
1375 	fclose(fp);
1376 
1377 	if (len == 0) {
1378 		free(result);
1379 		return -1;
1380 	}
1381 	result[len] = '\0';
1382 
1383 	pos = strstr(result, "table ");
1384 	if (pos == NULL) {
1385 		free(result);
1386 		return -1;
1387 	}
1388 
1389 	pos += strlen("table ");
1390 	tableid = atoi(pos);
1391 	if (tableid != 0) {
1392 		if (system("ip -6 rule del prio 22000") != 0) {
1393 			/* ignore any error */
1394 		}
1395 		snprintf(cmd, sizeof(cmd),
1396 			 "ip -6 rule add from all lookup %d prio 22000",
1397 			 tableid);
1398 		if (system(cmd) != 0) {
1399 			sigma_dut_print(dut, DUT_MSG_INFO,
1400 					"Failed to run %s", cmd);
1401 			free(result);
1402 			return -1;
1403 		}
1404 	} else {
1405 		sigma_dut_print(dut, DUT_MSG_INFO,
1406 				"No Valid Table Id found %s", pos);
1407 		free(result);
1408 		return -1;
1409 	}
1410 	free(result);
1411 
1412 	return 0;
1413 }
1414 #endif /* ANDROID */
1415 
1416 
set_ipv4_addr(struct sigma_dut * dut,const char * ifname,const char * ip,const char * mask)1417 int set_ipv4_addr(struct sigma_dut *dut, const char *ifname,
1418 		  const char *ip, const char *mask)
1419 {
1420 	char buf[200];
1421 
1422 	snprintf(buf, sizeof(buf), "ifconfig %s %s netmask %s",
1423 		 ifname, ip, mask);
1424 	return system(buf) == 0;
1425 }
1426 
1427 
set_ipv4_gw(struct sigma_dut * dut,const char * gw)1428 int set_ipv4_gw(struct sigma_dut *dut, const char *gw)
1429 {
1430 	char buf[200];
1431 
1432 	if (!is_ip_addr(gw)) {
1433 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Invalid gw addr - %s", gw);
1434 		return -1;
1435 	}
1436 
1437 	snprintf(buf, sizeof(buf), "route add default gw %s", gw);
1438 	if (!dut->no_ip_addr_set && system(buf) != 0) {
1439 		snprintf(buf, sizeof(buf), "ip ro re default via %s",
1440 			 gw);
1441 		if (system(buf) != 0)
1442 			return 0;
1443 	}
1444 
1445 	return 1;
1446 }
1447 
1448 
cmd_sta_set_ip_config(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)1449 static enum sigma_cmd_result cmd_sta_set_ip_config(struct sigma_dut *dut,
1450 						   struct sigma_conn *conn,
1451 						   struct sigma_cmd *cmd)
1452 {
1453 	const char *intf = get_param(cmd, "Interface");
1454 	const char *ifname;
1455 	char buf[200];
1456 	const char *val, *ip, *mask, *gw;
1457 	int type = 1;
1458 
1459 	if (intf == NULL)
1460 		return -1;
1461 
1462 	if (strcmp(intf, get_main_ifname(dut)) == 0)
1463 		ifname = get_station_ifname(dut);
1464 	else
1465 		ifname = intf;
1466 
1467 	if (if_nametoindex(ifname) == 0) {
1468 		send_resp(dut, conn, SIGMA_ERROR,
1469 			  "ErrorCode,Unknown interface");
1470 		return 0;
1471 	}
1472 
1473 	val = get_param(cmd, "Type");
1474 	if (val) {
1475 		type = atoi(val);
1476 		if (type < 1 || type > 3) {
1477 			send_resp(dut, conn, SIGMA_ERROR,
1478 				  "ErrorCode,Unsupported address type");
1479 			return 0;
1480 		}
1481 	}
1482 
1483 	dut->last_set_ip_config_ipv6 = 0;
1484 
1485 	val = get_param(cmd, "dhcp");
1486 	if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "true") == 0)) {
1487 		static_ip_file(0, NULL, NULL, NULL);
1488 #ifdef __linux__
1489 		if (type == 2) {
1490 			dut->last_set_ip_config_ipv6 = 1;
1491 			sigma_dut_print(dut, DUT_MSG_INFO, "Using IPv6 "
1492 					"stateless address autoconfiguration");
1493 #ifdef ANDROID
1494 			/*
1495 			 * This sleep is required as the assignment in case of
1496 			 * Android is taking time and is done by the kernel.
1497 			 * The subsequent ping for IPv6 is impacting HS20 test
1498 			 * case.
1499 			 */
1500 			sleep(2);
1501 			add_ipv6_rule(dut, intf);
1502 #endif /* ANDROID */
1503 			/* Assume this happens by default */
1504 			return 1;
1505 		}
1506 		if (type != 3) {
1507 			kill_dhcp_client(dut, ifname);
1508 			if (start_dhcp_client(dut, ifname) < 0)
1509 				return -2;
1510 		} else {
1511 			sigma_dut_print(dut, DUT_MSG_DEBUG,
1512 					"Using FILS HLP DHCPv4 Rapid Commit");
1513 		}
1514 
1515 		return 1;
1516 #endif /* __linux__ */
1517 		return -2;
1518 	}
1519 
1520 	ip = get_param(cmd, "ip");
1521 	if (!ip) {
1522 		send_resp(dut, conn, SIGMA_INVALID,
1523 			  "ErrorCode,Missing IP address");
1524 		return 0;
1525 	}
1526 
1527 	mask = get_param(cmd, "mask");
1528 	if (!mask) {
1529 		send_resp(dut, conn, SIGMA_INVALID,
1530 			  "ErrorCode,Missing subnet mask");
1531 		return 0;
1532 	}
1533 
1534 	if (type == 2) {
1535 		int net = atoi(mask);
1536 
1537 		if ((net < 0 && net > 64) || !is_ipv6_addr(ip))
1538 			return -1;
1539 
1540 		if (dut->no_ip_addr_set) {
1541 			snprintf(buf, sizeof(buf),
1542 				 "sysctl net.ipv6.conf.%s.disable_ipv6=1",
1543 				 ifname);
1544 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
1545 			if (system(buf) != 0) {
1546 				sigma_dut_print(dut, DUT_MSG_DEBUG,
1547 						"Failed to disable IPv6 address before association");
1548 			}
1549 		} else {
1550 			if (set_ipv6_addr(dut, ip, mask, ifname) != 0) {
1551 				send_resp(dut, conn, SIGMA_ERROR,
1552 					  "ErrorCode,Failed to set IPv6 address");
1553 				return 0;
1554 			}
1555 		}
1556 
1557 		dut->last_set_ip_config_ipv6 = 1;
1558 		static_ip_file(6, ip, mask, NULL);
1559 		return 1;
1560 	} else if (type == 1) {
1561 		if (!is_ip_addr(ip) || !is_ip_addr(mask))
1562 			return -1;
1563 	}
1564 
1565 	kill_dhcp_client(dut, ifname);
1566 
1567 	if (!dut->no_ip_addr_set) {
1568 		if (!set_ipv4_addr(dut, ifname, ip, mask)) {
1569 			send_resp(dut, conn, SIGMA_ERROR,
1570 				  "ErrorCode,Failed to set IP address");
1571 			return 0;
1572 		}
1573 	}
1574 
1575 	gw = get_param(cmd, "defaultGateway");
1576 	if (gw) {
1577 		if (set_ipv4_gw(dut, gw) < 1) {
1578 			send_resp(dut, conn, SIGMA_ERROR,
1579 				  "ErrorCode,Failed to set default gateway");
1580 			return 0;
1581 		}
1582 	}
1583 
1584 	val = get_param(cmd, "primary-dns");
1585 	if (val) {
1586 		/* TODO */
1587 		sigma_dut_print(dut, DUT_MSG_INFO, "Ignored primary-dns %s "
1588 				"setting", val);
1589 	}
1590 
1591 	val = get_param(cmd, "secondary-dns");
1592 	if (val) {
1593 		/* TODO */
1594 		sigma_dut_print(dut, DUT_MSG_INFO, "Ignored secondary-dns %s "
1595 				"setting", val);
1596 	}
1597 
1598 	static_ip_file(4, ip, mask, gw);
1599 
1600 	return 1;
1601 }
1602 
1603 
cmd_sta_get_info(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)1604 static enum sigma_cmd_result cmd_sta_get_info(struct sigma_dut *dut,
1605 					      struct sigma_conn *conn,
1606 					      struct sigma_cmd *cmd)
1607 {
1608 	/* const char *intf = get_param(cmd, "Interface"); */
1609 	/* TODO: could report more details here */
1610 	send_resp(dut, conn, SIGMA_COMPLETE, "vendor,Atheros");
1611 	return 0;
1612 }
1613 
1614 
cmd_sta_get_mac_address(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)1615 static enum sigma_cmd_result cmd_sta_get_mac_address(struct sigma_dut *dut,
1616 						     struct sigma_conn *conn,
1617 						     struct sigma_cmd *cmd)
1618 {
1619 	/* const char *intf = get_param(cmd, "Interface"); */
1620 	char addr[20], resp[50];
1621 
1622 	if (dut->dev_role == DEVROLE_STA_CFON)
1623 		return sta_cfon_get_mac_address(dut, conn, cmd);
1624 
1625 	start_sta_mode(dut);
1626 	if (get_wpa_status(get_station_ifname(dut), "address",
1627 			   addr, sizeof(addr)) < 0)
1628 		return -2;
1629 
1630 	snprintf(resp, sizeof(resp), "mac,%s", addr);
1631 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1632 	return 0;
1633 }
1634 
1635 
cmd_sta_is_connected(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)1636 static enum sigma_cmd_result cmd_sta_is_connected(struct sigma_dut *dut,
1637 						  struct sigma_conn *conn,
1638 						  struct sigma_cmd *cmd)
1639 {
1640 	/* const char *intf = get_param(cmd, "Interface"); */
1641 	int connected = 0;
1642 	char result[32];
1643 	if (get_wpa_status(get_station_ifname(dut), "wpa_state", result,
1644 			   sizeof(result)) < 0) {
1645 		sigma_dut_print(dut, DUT_MSG_INFO,
1646 				"Could not get interface %s status",
1647 				get_station_ifname(dut));
1648 		return -2;
1649 	}
1650 
1651 	sigma_dut_print(dut, DUT_MSG_DEBUG, "wpa_state=%s", result);
1652 	if (strncmp(result, "COMPLETED", 9) == 0)
1653 		connected = 1;
1654 
1655 	if (connected)
1656 		send_resp(dut, conn, SIGMA_COMPLETE, "connected,1");
1657 	else
1658 		send_resp(dut, conn, SIGMA_COMPLETE, "connected,0");
1659 
1660 	return 0;
1661 }
1662 
1663 
1664 static enum sigma_cmd_result
cmd_sta_verify_ip_connection(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)1665 cmd_sta_verify_ip_connection(struct sigma_dut *dut, struct sigma_conn *conn,
1666 			     struct sigma_cmd *cmd)
1667 {
1668 	/* const char *intf = get_param(cmd, "Interface"); */
1669 	const char *dst, *timeout;
1670 	int wait_time = 90;
1671 	char buf[100];
1672 	int res;
1673 
1674 	dst = get_param(cmd, "destination");
1675 	if (dst == NULL || !is_ip_addr(dst))
1676 		return -1;
1677 
1678 	timeout = get_param(cmd, "timeout");
1679 	if (timeout) {
1680 		wait_time = atoi(timeout);
1681 		if (wait_time < 1)
1682 			wait_time = 1;
1683 	}
1684 
1685 	/* TODO: force renewal of IP lease if DHCP is enabled */
1686 
1687 	snprintf(buf, sizeof(buf), "ping %s -c 3 -W %d", dst, wait_time);
1688 	res = system(buf);
1689 	sigma_dut_print(dut, DUT_MSG_DEBUG, "ping returned: %d", res);
1690 	if (res == 0)
1691 		send_resp(dut, conn, SIGMA_COMPLETE, "connected,1");
1692 	else if (res == 256)
1693 		send_resp(dut, conn, SIGMA_COMPLETE, "connected,0");
1694 	else
1695 		return -2;
1696 
1697 	return 0;
1698 }
1699 
1700 
cmd_sta_get_bssid(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)1701 static enum sigma_cmd_result cmd_sta_get_bssid(struct sigma_dut *dut,
1702 					       struct sigma_conn *conn,
1703 					       struct sigma_cmd *cmd)
1704 {
1705 	/* const char *intf = get_param(cmd, "Interface"); */
1706 	char bssid[20], resp[50];
1707 
1708 	if (get_wpa_status(get_station_ifname(dut), "bssid",
1709 			   bssid, sizeof(bssid)) < 0)
1710 		strlcpy(bssid, "00:00:00:00:00:00", sizeof(bssid));
1711 
1712 	snprintf(resp, sizeof(resp), "bssid,%s", bssid);
1713 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1714 	return 0;
1715 }
1716 
1717 
1718 #ifdef __SAMSUNG__
add_use_network(const char * ifname)1719 static int add_use_network(const char *ifname)
1720 {
1721 	char buf[100];
1722 
1723 	snprintf(buf, sizeof(buf), "USE_NETWORK ON");
1724 	wpa_command(ifname, buf);
1725 	return 0;
1726 }
1727 #endif /* __SAMSUNG__ */
1728 
1729 
add_network_common(struct sigma_dut * dut,struct sigma_conn * conn,const char * ifname,struct sigma_cmd * cmd)1730 static int add_network_common(struct sigma_dut *dut, struct sigma_conn *conn,
1731 			      const char *ifname, struct sigma_cmd *cmd)
1732 {
1733 	const char *ssid = get_param(cmd, "ssid");
1734 	int id;
1735 	const char *val;
1736 
1737 	if (ssid == NULL)
1738 		return -1;
1739 
1740 	start_sta_mode(dut);
1741 
1742 #ifdef __SAMSUNG__
1743 	add_use_network(ifname);
1744 #endif /* __SAMSUNG__ */
1745 
1746 	id = add_network(ifname);
1747 	if (id < 0)
1748 		return -2;
1749 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding network %d", id);
1750 
1751 	if (set_network_quoted(ifname, id, "ssid", ssid) < 0)
1752 		return -2;
1753 
1754 	dut->infra_network_id = id;
1755 	snprintf(dut->infra_ssid, sizeof(dut->infra_ssid), "%s", ssid);
1756 
1757 	val = get_param(cmd, "program");
1758 	if (!val)
1759 		val = get_param(cmd, "prog");
1760 	if (val && strcasecmp(val, "hs2") == 0) {
1761 		char buf[100];
1762 		snprintf(buf, sizeof(buf), "ENABLE_NETWORK %d no-connect", id);
1763 		wpa_command(ifname, buf);
1764 
1765 		val = get_param(cmd, "prefer");
1766 		if (val && atoi(val) > 0)
1767 			set_network(ifname, id, "priority", "1");
1768 	}
1769 
1770 	return id;
1771 }
1772 
1773 
cmd_sta_set_encryption(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)1774 static enum sigma_cmd_result cmd_sta_set_encryption(struct sigma_dut *dut,
1775 						    struct sigma_conn *conn,
1776 						    struct sigma_cmd *cmd)
1777 {
1778 	const char *intf = get_param(cmd, "Interface");
1779 	const char *ssid = get_param(cmd, "ssid");
1780 	const char *type = get_param(cmd, "encpType");
1781 	const char *ifname;
1782 	char buf[200];
1783 	int id;
1784 
1785 	if (intf == NULL || ssid == NULL)
1786 		return -1;
1787 
1788 	if (strcmp(intf, get_main_ifname(dut)) == 0)
1789 		ifname = get_station_ifname(dut);
1790 	else
1791 		ifname = intf;
1792 
1793 	id = add_network_common(dut, conn, ifname, cmd);
1794 	if (id < 0)
1795 		return id;
1796 
1797 	if (set_network(ifname, id, "key_mgmt", "NONE") < 0)
1798 		return -2;
1799 
1800 	if (type && strcasecmp(type, "wep") == 0) {
1801 		const char *val;
1802 		int i;
1803 
1804 		val = get_param(cmd, "activeKey");
1805 		if (val) {
1806 			int keyid;
1807 			keyid = atoi(val);
1808 			if (keyid < 1 || keyid > 4)
1809 				return -1;
1810 			snprintf(buf, sizeof(buf), "%d", keyid - 1);
1811 			if (set_network(ifname, id, "wep_tx_keyidx", buf) < 0)
1812 				return -2;
1813 		}
1814 
1815 		for (i = 0; i < 4; i++) {
1816 			snprintf(buf, sizeof(buf), "key%d", i + 1);
1817 			val = get_param(cmd, buf);
1818 			if (val == NULL)
1819 				continue;
1820 			snprintf(buf, sizeof(buf), "wep_key%d", i);
1821 			if (set_network(ifname, id, buf, val) < 0)
1822 				return -2;
1823 		}
1824 	}
1825 
1826 	return 1;
1827 }
1828 
1829 
set_akm_suites(struct sigma_dut * dut,const char * ifname,int id,const char * val)1830 static int set_akm_suites(struct sigma_dut *dut, const char *ifname,
1831 			  int id, const char *val)
1832 {
1833 	char key_mgmt[200], *end, *pos;
1834 	const char *in_pos = val;
1835 
1836 	dut->akm_values = 0;
1837 	pos = key_mgmt;
1838 	end = pos + sizeof(key_mgmt);
1839 	while (*in_pos) {
1840 		int res, akm = atoi(in_pos);
1841 		const char *str;
1842 
1843 		if (akm >= 0 && akm < 32)
1844 			dut->akm_values |= 1 << akm;
1845 
1846 		switch (akm) {
1847 		case AKM_WPA_EAP:
1848 			str = "WPA-EAP";
1849 			break;
1850 		case AKM_WPA_PSK:
1851 			str = "WPA-PSK";
1852 			break;
1853 		case AKM_FT_EAP:
1854 			str = "FT-EAP";
1855 			break;
1856 		case AKM_FT_PSK:
1857 			str = "FT-PSK";
1858 			break;
1859 		case AKM_EAP_SHA256:
1860 			str = "WPA-EAP-SHA256";
1861 			break;
1862 		case AKM_PSK_SHA256:
1863 			str = "WPA-PSK-SHA256";
1864 			break;
1865 		case AKM_SAE:
1866 			str = "SAE";
1867 			break;
1868 		case AKM_FT_SAE:
1869 			str = "FT-SAE";
1870 			break;
1871 		case AKM_SUITE_B:
1872 			str = "WPA-EAP-SUITE-B-192";
1873 			break;
1874 		case AKM_FT_SUITE_B:
1875 			str = "FT-EAP-SHA384";
1876 			break;
1877 		case AKM_FILS_SHA256:
1878 			str = "FILS-SHA256";
1879 			break;
1880 		case AKM_FILS_SHA384:
1881 			str = "FILS-SHA384";
1882 			break;
1883 		case AKM_FT_FILS_SHA256:
1884 			str = "FT-FILS-SHA256";
1885 			break;
1886 		case AKM_FT_FILS_SHA384:
1887 			str = "FT-FILS-SHA384";
1888 			break;
1889 		default:
1890 			sigma_dut_print(dut, DUT_MSG_ERROR,
1891 					"Unsupported AKMSuitetype %d", akm);
1892 			return -1;
1893 		}
1894 
1895 		res = snprintf(pos, end - pos, "%s%s",
1896 			       pos == key_mgmt ? "" : " ", str);
1897 		if (res < 0 || res >= end - pos)
1898 			return -1;
1899 		pos += res;
1900 
1901 		in_pos = strchr(in_pos, ';');
1902 		if (!in_pos)
1903 			break;
1904 		while (*in_pos == ';')
1905 			in_pos++;
1906 	}
1907 	sigma_dut_print(dut, DUT_MSG_DEBUG, "AKMSuiteType %s --> %s",
1908 			val, key_mgmt);
1909 	return set_network(ifname, id, "key_mgmt", key_mgmt);
1910 }
1911 
1912 
set_wpa_common(struct sigma_dut * dut,struct sigma_conn * conn,const char * ifname,struct sigma_cmd * cmd)1913 static int set_wpa_common(struct sigma_dut *dut, struct sigma_conn *conn,
1914 			  const char *ifname, struct sigma_cmd *cmd)
1915 {
1916 	const char *val;
1917 	int id;
1918 	int cipher_set = 0;
1919 	int owe;
1920 	int suite_b = 0;
1921 
1922 	id = add_network_common(dut, conn, ifname, cmd);
1923 	if (id < 0)
1924 		return id;
1925 
1926 	val = get_param(cmd, "Type");
1927 	owe = val && strcasecmp(val, "OWE") == 0;
1928 
1929 	val = get_param(cmd, "keyMgmtType");
1930 	if (!val && owe)
1931 		val = "OWE";
1932 	if (val == NULL) {
1933 		/* keyMgmtType is being replaced with AKMSuiteType, so ignore
1934 		 * this missing parameter and assume proto=WPA2. */
1935 		if (set_network(ifname, id, "proto", "WPA2") < 0)
1936 			return ERROR_SEND_STATUS;
1937 	} else if (strcasecmp(val, "wpa") == 0 ||
1938 		   strcasecmp(val, "wpa-psk") == 0) {
1939 		if (set_network(ifname, id, "proto", "WPA") < 0)
1940 			return -2;
1941 	} else if (strcasecmp(val, "wpa2") == 0 ||
1942 		   strcasecmp(val, "wpa2-psk") == 0 ||
1943 		   strcasecmp(val, "wpa2-ft") == 0 ||
1944 		   strcasecmp(val, "wpa2-sha256") == 0) {
1945 		if (set_network(ifname, id, "proto", "WPA2") < 0)
1946 			return -2;
1947 	} else if (strcasecmp(val, "wpa2-wpa-psk") == 0 ||
1948 		   strcasecmp(val, "wpa2-wpa-ent") == 0) {
1949 		if (set_network(ifname, id, "proto", "WPA WPA2") < 0)
1950 			return -2;
1951 	} else if (strcasecmp(val, "SuiteB") == 0) {
1952 		suite_b = 1;
1953 		if (set_network(ifname, id, "proto", "WPA2") < 0)
1954 			return -2;
1955 	} else if (strcasecmp(val, "OWE") == 0) {
1956 	} else {
1957 		send_resp(dut, conn, SIGMA_INVALID, "errorCode,Unrecognized keyMgmtType value");
1958 		return 0;
1959 	}
1960 
1961 	val = get_param(cmd, "encpType");
1962 	if (val) {
1963 		cipher_set = 1;
1964 		if (strcasecmp(val, "tkip") == 0) {
1965 			if (set_network(ifname, id, "pairwise", "TKIP") < 0)
1966 				return -2;
1967 		} else if (strcasecmp(val, "aes-ccmp") == 0) {
1968 			if (set_network(ifname, id, "pairwise", "CCMP") < 0)
1969 				return -2;
1970 		} else if (strcasecmp(val, "aes-ccmp-tkip") == 0) {
1971 			if (set_network(ifname, id, "pairwise",
1972 					"CCMP TKIP") < 0)
1973 				return -2;
1974 		} else if (strcasecmp(val, "aes-gcmp") == 0) {
1975 			if (set_network(ifname, id, "pairwise", "GCMP") < 0)
1976 				return -2;
1977 			if (set_network(ifname, id, "group", "GCMP") < 0)
1978 				return -2;
1979 		} else {
1980 			send_resp(dut, conn, SIGMA_ERROR,
1981 				  "errorCode,Unrecognized encpType value");
1982 			return 0;
1983 		}
1984 	}
1985 
1986 	val = get_param(cmd, "PairwiseCipher");
1987 	if (val) {
1988 		cipher_set = 1;
1989 		/* TODO: Support space separated list */
1990 		if (strcasecmp(val, "AES-GCMP-256") == 0) {
1991 			if (set_network(ifname, id, "pairwise", "GCMP-256") < 0)
1992 				return -2;
1993 		} else if (strcasecmp(val, "AES-CCMP-256") == 0) {
1994 			if (set_network(ifname, id, "pairwise",
1995 					"CCMP-256") < 0)
1996 				return -2;
1997 		} else if (strcasecmp(val, "AES-GCMP-128") == 0) {
1998 			if (set_network(ifname, id, "pairwise",	"GCMP") < 0)
1999 				return -2;
2000 		} else if (strcasecmp(val, "AES-CCMP-128") == 0) {
2001 			if (set_network(ifname, id, "pairwise",	"CCMP") < 0)
2002 				return -2;
2003 		} else {
2004 			send_resp(dut, conn, SIGMA_ERROR,
2005 				  "errorCode,Unrecognized PairwiseCipher value");
2006 			return 0;
2007 		}
2008 	}
2009 
2010 	if (!cipher_set && !owe) {
2011 		send_resp(dut, conn, SIGMA_ERROR,
2012 			  "errorCode,Missing encpType and PairwiseCipher");
2013 		return 0;
2014 	}
2015 
2016 	val = get_param(cmd, "GroupCipher");
2017 	if (val) {
2018 		if (strcasecmp(val, "AES-GCMP-256") == 0) {
2019 			if (set_network(ifname, id, "group", "GCMP-256") < 0)
2020 				return -2;
2021 		} else if (strcasecmp(val, "AES-CCMP-256") == 0) {
2022 			if (set_network(ifname, id, "group", "CCMP-256") < 0)
2023 				return -2;
2024 		} else if (strcasecmp(val, "AES-GCMP-128") == 0) {
2025 			if (set_network(ifname, id, "group", "GCMP") < 0)
2026 				return -2;
2027 		} else if (strcasecmp(val, "AES-CCMP-128") == 0) {
2028 			if (set_network(ifname, id, "group", "CCMP") < 0)
2029 				return -2;
2030 		} else {
2031 			send_resp(dut, conn, SIGMA_ERROR,
2032 				  "errorCode,Unrecognized GroupCipher value");
2033 			return 0;
2034 		}
2035 	}
2036 
2037 	val = get_param(cmd, "GroupMgntCipher");
2038 	if (val) {
2039 		const char *cipher;
2040 
2041 		if (strcasecmp(val, "BIP-GMAC-256") == 0) {
2042 			cipher = "BIP-GMAC-256";
2043 		} else if (strcasecmp(val, "BIP-CMAC-256") == 0) {
2044 			cipher = "BIP-CMAC-256";
2045 		} else if (strcasecmp(val, "BIP-GMAC-128") == 0) {
2046 			cipher = "BIP-GMAC-128";
2047 		} else if (strcasecmp(val, "BIP-CMAC-128") == 0) {
2048 			cipher = "AES-128-CMAC";
2049 		} else {
2050 			send_resp(dut, conn, SIGMA_INVALID,
2051 				  "errorCode,Unsupported GroupMgntCipher");
2052 			return 0;
2053 		}
2054 		if (set_network(ifname, id, "group_mgmt", cipher) < 0) {
2055 			send_resp(dut, conn, SIGMA_INVALID,
2056 				  "errorCode,Failed to set GroupMgntCipher");
2057 			return 0;
2058 		}
2059 	}
2060 
2061 	val = get_param(cmd, "AKMSuiteType");
2062 	if (val && set_akm_suites(dut, ifname, id, val) < 0)
2063 		return ERROR_SEND_STATUS;
2064 
2065 	dut->sta_pmf = STA_PMF_DISABLED;
2066 
2067 	if (dut->program == PROGRAM_OCE) {
2068 		dut->sta_pmf = STA_PMF_OPTIONAL;
2069 		if (set_network(ifname, id, "ieee80211w", "1") < 0)
2070 			return -2;
2071 	}
2072 
2073 	val = get_param(cmd, "PMF");
2074 	if (val) {
2075 		if (strcasecmp(val, "Required") == 0 ||
2076 		    strcasecmp(val, "Forced_Required") == 0) {
2077 			dut->sta_pmf = STA_PMF_REQUIRED;
2078 			if (set_network(ifname, id, "ieee80211w", "2") < 0)
2079 				return -2;
2080 		} else if (strcasecmp(val, "Optional") == 0) {
2081 			dut->sta_pmf = STA_PMF_OPTIONAL;
2082 			if (set_network(ifname, id, "ieee80211w", "1") < 0)
2083 				return -2;
2084 		} else if (strcasecmp(val, "Disabled") == 0 ||
2085 			   strcasecmp(val, "Disable") == 0 ||
2086 			   strcasecmp(val, "Forced_Disabled") == 0) {
2087 			dut->sta_pmf = STA_PMF_DISABLED;
2088 		} else {
2089 			send_resp(dut, conn, SIGMA_INVALID, "errorCode,Unrecognized PMF value");
2090 			return 0;
2091 		}
2092 	} else if (owe || suite_b) {
2093 		dut->sta_pmf = STA_PMF_REQUIRED;
2094 		if (set_network(ifname, id, "ieee80211w", "2") < 0)
2095 			return -2;
2096 	}
2097 
2098 	val = get_param(cmd, "BeaconProtection");
2099 	if (val)
2100 		dut->beacon_prot = atoi(val);
2101 	if (dut->beacon_prot && set_network(ifname, id, "beacon_prot", "1") < 0)
2102 		return ERROR_SEND_STATUS;
2103 
2104 	if (dut->ocvc && set_network(ifname, id, "ocv", "1") < 0)
2105 		return ERROR_SEND_STATUS;
2106 
2107 	return id;
2108 }
2109 
2110 
cmd_sta_set_psk(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)2111 static enum sigma_cmd_result cmd_sta_set_psk(struct sigma_dut *dut,
2112 					     struct sigma_conn *conn,
2113 					     struct sigma_cmd *cmd)
2114 {
2115 	const char *intf = get_param(cmd, "Interface");
2116 	const char *type = get_param(cmd, "Type");
2117 	const char *pmf = get_param(cmd, "PMF");
2118 	const char *network_mode = get_param(cmd, "network_mode");
2119 	const char *akm = get_param(cmd, "AKMSuiteType");
2120 	const char *ifname, *val, *alg;
2121 	int id;
2122 	char buf[50];
2123 	int sae_pwe = -1;
2124 
2125 	if (intf == NULL)
2126 		return -1;
2127 
2128 	if (strcmp(intf, get_main_ifname(dut)) == 0)
2129 		ifname = get_station_ifname(dut);
2130 	else
2131 		ifname = intf;
2132 
2133 	id = set_wpa_common(dut, conn, ifname, cmd);
2134 	if (id < 0)
2135 		return id;
2136 
2137 	val = get_param(cmd, "keyMgmtType");
2138 	alg = get_param(cmd, "micAlg");
2139 
2140 	if (type && strcasecmp(type, "SAE") == 0) {
2141 		if (!akm && val && strcasecmp(val, "wpa2-ft") == 0) {
2142 			if (set_network(ifname, id, "key_mgmt", "FT-SAE") < 0)
2143 				return -2;
2144 		} else if (!akm) {
2145 			if (set_network(ifname, id, "key_mgmt", "SAE") < 0)
2146 				return -2;
2147 		}
2148 		if (wpa_command(ifname, "SET sae_groups ") != 0) {
2149 			sigma_dut_print(dut, DUT_MSG_ERROR,
2150 					"Failed to clear sae_groups to default");
2151 			return -2;
2152 		}
2153 		if (!pmf) {
2154 			dut->sta_pmf = STA_PMF_REQUIRED;
2155 			if (set_network(ifname, id, "ieee80211w", "2") < 0)
2156 				return -2;
2157 		}
2158 	} else if (type && strcasecmp(type, "PSK-SAE") == 0) {
2159 		if (val && strcasecmp(val, "wpa2-ft") == 0) {
2160 			if (set_network(ifname, id, "key_mgmt",
2161 					"FT-SAE FT-PSK") < 0)
2162 				return -2;
2163 		} else if (!akm) {
2164 			if (set_network(ifname, id, "key_mgmt",
2165 					"SAE WPA-PSK") < 0)
2166 				return -2;
2167 		}
2168 		if (wpa_command(ifname, "SET sae_groups ") != 0) {
2169 			sigma_dut_print(dut, DUT_MSG_ERROR,
2170 					"Failed to clear sae_groups to default");
2171 			return -2;
2172 		}
2173 		if (!pmf) {
2174 			dut->sta_pmf = STA_PMF_OPTIONAL;
2175 			if (set_network(ifname, id, "ieee80211w", "1") < 0)
2176 				return -2;
2177 		}
2178 	} else if (alg && strcasecmp(alg, "SHA-256") == 0) {
2179 		if (set_network(ifname, id, "key_mgmt", "WPA-PSK-SHA256") < 0)
2180 			return -2;
2181 	} else if (alg && strcasecmp(alg, "SHA-1") == 0) {
2182 		if (set_network(ifname, id, "key_mgmt", "WPA-PSK") < 0)
2183 			return -2;
2184 	} else if (val && strcasecmp(val, "wpa2-ft") == 0) {
2185 		if (set_network(ifname, id, "key_mgmt", "FT-PSK") < 0)
2186 			return -2;
2187 	} else if (!akm &&
2188 		   ((val && strcasecmp(val, "wpa2-sha256") == 0) ||
2189 		    dut->sta_pmf == STA_PMF_REQUIRED)) {
2190 		if (set_network(ifname, id, "key_mgmt",
2191 				"WPA-PSK WPA-PSK-SHA256") < 0)
2192 			return -2;
2193 	} else if (!akm && dut->sta_pmf == STA_PMF_OPTIONAL) {
2194 		if (set_network(ifname, id, "key_mgmt",
2195 				"WPA-PSK WPA-PSK-SHA256") < 0)
2196 			return -2;
2197 	} else if (!akm) {
2198 		if (set_network(ifname, id, "key_mgmt", "WPA-PSK") < 0)
2199 			return -2;
2200 	}
2201 
2202 	val = get_param(cmd, "passPhrase");
2203 	if (val == NULL)
2204 		return -1;
2205 	if (type && strcasecmp(type, "SAE") == 0) {
2206 		if (set_network_quoted(ifname, id, "sae_password", val) < 0)
2207 			return -2;
2208 	} else {
2209 		if (set_network_quoted(ifname, id, "psk", val) < 0)
2210 			return -2;
2211 	}
2212 
2213 	val = get_param(cmd, "PasswordId");
2214 	if (val && set_network_quoted(ifname, id, "sae_password_id", val) < 0)
2215 		return ERROR_SEND_STATUS;
2216 
2217 	val = get_param(cmd, "ECGroupID");
2218 	if (val) {
2219 		snprintf(buf, sizeof(buf), "SET sae_groups %s", val);
2220 		if (wpa_command(ifname, buf) != 0) {
2221 			sigma_dut_print(dut, DUT_MSG_ERROR,
2222 					"Failed to clear sae_groups");
2223 			return -2;
2224 		}
2225 	}
2226 
2227 	val = get_param(cmd, "InvalidSAEElement");
2228 	if (val) {
2229 		free(dut->sae_commit_override);
2230 		dut->sae_commit_override = strdup(val);
2231 	}
2232 
2233 	val = get_param(cmd, "PMKID_Include");
2234 	if (val) {
2235 		snprintf(buf, sizeof(buf), "SET sae_pmkid_in_assoc %d",
2236 			 get_enable_disable(val));
2237 		wpa_command(intf, buf);
2238 	}
2239 
2240 	val = get_param(cmd, "IgnoreH2E_RSNXE_BSSMemSel");
2241 	if (val) {
2242 		snprintf(buf, sizeof(buf), "SET ignore_sae_h2e_only %d",
2243 			 get_enable_disable(val));
2244 		wpa_command(intf, buf);
2245 	}
2246 
2247 	val = get_param(cmd, "ECGroupID_RGE");
2248 	if (val) {
2249 		snprintf(buf, sizeof(buf), "SET extra_sae_rejected_groups %s",
2250 			 val);
2251 		wpa_command(intf, buf);
2252 	}
2253 
2254 	val = get_param(cmd, "RSNXE_Content");
2255 	if (val) {
2256 		const char *param;
2257 
2258 		if (strncasecmp(val, "AssocReq:", 9) == 0) {
2259 			val += 9;
2260 			param = "rsnxe_override_assoc";
2261 		} else if (strncasecmp(val, "EapolM2:", 8) == 0) {
2262 			val += 8;
2263 			param = "rsnxe_override_eapol";
2264 		} else {
2265 			send_resp(dut, conn, SIGMA_ERROR,
2266 				  "errorCode,Unsupported RSNXE_Content value");
2267 			return STATUS_SENT_ERROR;
2268 		}
2269 		snprintf(buf, sizeof(buf), "SET %s %s", param, val);
2270 		wpa_command(intf, buf);
2271 	}
2272 
2273 	val = get_param(cmd, "sae_pwe");
2274 	if (val) {
2275 		if (strcasecmp(val, "h2e") == 0) {
2276 			dut->sae_pwe = SAE_PWE_H2E;
2277 		} else if (strcasecmp(val, "loop") == 0 ||
2278 			   strcasecmp(val, "looping") == 0) {
2279 			dut->sae_pwe = SAE_PWE_LOOP;
2280 		} else {
2281 			send_resp(dut, conn, SIGMA_ERROR,
2282 				  "errorCode,Unsupported sae_pwe value");
2283 			return STATUS_SENT_ERROR;
2284 		}
2285 	}
2286 
2287 	val = get_param(cmd, "Clear_RSNXE");
2288 	if (val && strcmp(val, "1") == 0 &&
2289 	    (wpa_command(intf, "SET rsnxe_override_assoc ") ||
2290 	     wpa_command(intf, "SET rsnxe_override_eapol "))) {
2291 		send_resp(dut, conn, SIGMA_ERROR,
2292 			  "errorCode,Failed to clear RSNXE");
2293 		return STATUS_SENT_ERROR;
2294 	}
2295 
2296 	if (dut->sae_pwe == SAE_PWE_LOOP && get_param(cmd, "PasswordId"))
2297 		sae_pwe = 3;
2298 	else if (dut->sae_pwe == SAE_PWE_LOOP)
2299 		sae_pwe = 0;
2300 	else if (dut->sae_pwe == SAE_PWE_H2E)
2301 		sae_pwe = 1;
2302 	else if (dut->sae_h2e_default)
2303 		sae_pwe = 2;
2304 	snprintf(buf, sizeof(buf), "SET sae_pwe %d", sae_pwe);
2305 	if (sae_pwe >= 0 && wpa_command(ifname, buf) != 0)
2306 		return ERROR_SEND_STATUS;
2307 
2308 	val = get_param(cmd, "sae_pk");
2309 	if (val && strcmp(val, "0") == 0 &&
2310 	    set_network(ifname, id, "sae_pk", "2") < 0)
2311 		return ERROR_SEND_STATUS;
2312 
2313 	val = get_param(cmd, "sae_pk_only");
2314 	if (val && strcmp(val, "1") == 0 &&
2315 	    set_network(ifname, id, "sae_pk", "1") < 0)
2316 		return ERROR_SEND_STATUS;
2317 
2318 	if (dut->program == PROGRAM_60GHZ && network_mode &&
2319 	    strcasecmp(network_mode, "PBSS") == 0 &&
2320 	    set_network(ifname, id, "pbss", "1") < 0)
2321 		return -2;
2322 
2323 	return 1;
2324 }
2325 
2326 
set_trust_root_system(struct sigma_dut * dut,struct sigma_conn * conn,const char * ifname,int id)2327 static enum sigma_cmd_result set_trust_root_system(struct sigma_dut *dut,
2328 						   struct sigma_conn *conn,
2329 						   const char *ifname, int id)
2330 {
2331 	char buf[200];
2332 
2333 	snprintf(buf, sizeof(buf), "%s/certs", sigma_cert_path);
2334 	if (!file_exists(buf))
2335 		strlcpy(buf, "/system/etc/security/cacerts", sizeof(buf));
2336 	if (!file_exists(buf))
2337 		strlcpy(buf, "/etc/ssl/certs", sizeof(buf));
2338 	if (!file_exists(buf)) {
2339 		char msg[300];
2340 
2341 		snprintf(msg, sizeof(msg),
2342 			 "ErrorCode,trustedRootCA system store (%s) not found",
2343 			 buf);
2344 		send_resp(dut, conn, SIGMA_ERROR, msg);
2345 		return STATUS_SENT_ERROR;
2346 	}
2347 
2348 	if (set_network_quoted(ifname, id, "ca_path", buf) < 0)
2349 		return ERROR_SEND_STATUS;
2350 
2351 	return SUCCESS_SEND_STATUS;
2352 }
2353 
2354 
set_trust_root(struct sigma_dut * dut,struct sigma_conn * conn,const char * ifname,int id,const char * val)2355 static enum sigma_cmd_result set_trust_root(struct sigma_dut *dut,
2356 					    struct sigma_conn *conn,
2357 					    const char *ifname, int id,
2358 					    const char *val)
2359 {
2360 	char buf[200];
2361 #ifdef ANDROID
2362 	unsigned char kvalue[KEYSTORE_MESSAGE_SIZE];
2363 	int length;
2364 #endif /* ANDROID */
2365 
2366 	if (strcmp(val, "DEFAULT") == 0)
2367 		return set_trust_root_system(dut, conn, ifname, id);
2368 
2369 #ifdef ANDROID
2370 	snprintf(buf, sizeof(buf), "CACERT_%s", val);
2371 	length = android_keystore_get(ANDROID_KEYSTORE_GET, buf, kvalue);
2372 	if (length > 0) {
2373 		sigma_dut_print(dut, DUT_MSG_INFO, "Use Android keystore [%s]",
2374 				buf);
2375 		snprintf(buf, sizeof(buf), "keystore://CACERT_%s", val);
2376 		goto ca_cert_selected;
2377 	}
2378 #endif /* ANDROID */
2379 
2380 	snprintf(buf, sizeof(buf), "%s/%s", sigma_cert_path, val);
2381 #ifdef __linux__
2382 	if (!file_exists(buf)) {
2383 		char msg[300];
2384 
2385 		snprintf(msg, sizeof(msg),
2386 			 "ErrorCode,trustedRootCA file (%s) not found", buf);
2387 		send_resp(dut, conn, SIGMA_ERROR, msg);
2388 		return STATUS_SENT_ERROR;
2389 	}
2390 #endif /* __linux__ */
2391 #ifdef ANDROID
2392 ca_cert_selected:
2393 #endif /* ANDROID */
2394 	if (set_network_quoted(ifname, id, "ca_cert", buf) < 0)
2395 		return ERROR_SEND_STATUS;
2396 
2397 	return SUCCESS_SEND_STATUS;
2398 }
2399 
2400 
set_eap_common(struct sigma_dut * dut,struct sigma_conn * conn,const char * ifname,int username_identity,struct sigma_cmd * cmd)2401 static int set_eap_common(struct sigma_dut *dut, struct sigma_conn *conn,
2402 			  const char *ifname, int username_identity,
2403 			  struct sigma_cmd *cmd)
2404 {
2405 	const char *val, *alg, *akm, *trust_root, *domain, *domain_suffix;
2406 	int id;
2407 	char buf[200], buf2[300];
2408 	int erp = 0;
2409 	enum sigma_cmd_result res;
2410 
2411 	id = set_wpa_common(dut, conn, ifname, cmd);
2412 	if (id < 0)
2413 		return id;
2414 
2415 	val = get_param(cmd, "keyMgmtType");
2416 	alg = get_param(cmd, "micAlg");
2417 	akm = get_param(cmd, "AKMSuiteType");
2418 	trust_root = get_param(cmd, "trustedRootCA");
2419 	domain = get_param(cmd, "Domain");
2420 	domain_suffix = get_param(cmd, "DomainSuffix");
2421 
2422 	if (val && strcasecmp(val, "SuiteB") == 0) {
2423 		if (set_network(ifname, id, "key_mgmt", "WPA-EAP-SUITE-B-192") <
2424 		    0)
2425 			return -2;
2426 	} else if (alg && strcasecmp(alg, "SHA-256") == 0) {
2427 		if (set_network(ifname, id, "key_mgmt", "WPA-EAP-SHA256") < 0)
2428 			return -2;
2429 	} else if (alg && strcasecmp(alg, "SHA-1") == 0) {
2430 		if (set_network(ifname, id, "key_mgmt", "WPA-EAP") < 0)
2431 			return -2;
2432 	} else if (val && strcasecmp(val, "wpa2-ft") == 0) {
2433 		if (set_network(ifname, id, "key_mgmt", "FT-EAP") < 0)
2434 			return -2;
2435 	} else if (!akm &&
2436 		   ((val && strcasecmp(val, "wpa2-sha256") == 0) ||
2437 		    dut->sta_pmf == STA_PMF_REQUIRED)) {
2438 		if (set_network(ifname, id, "key_mgmt",
2439 				"WPA-EAP WPA-EAP-SHA256") < 0)
2440 			return -2;
2441 	} else if (akm && atoi(akm) == 14) {
2442 		if (dut->sta_pmf == STA_PMF_OPTIONAL ||
2443 		    dut->sta_pmf == STA_PMF_REQUIRED) {
2444 			if (set_network(ifname, id, "key_mgmt",
2445 					"WPA-EAP-SHA256 FILS-SHA256") < 0)
2446 				return -2;
2447 		} else {
2448 			if (set_network(ifname, id, "key_mgmt",
2449 					"WPA-EAP FILS-SHA256") < 0)
2450 				return -2;
2451 		}
2452 
2453 		erp = 1;
2454 	} else if (akm && atoi(akm) == 15) {
2455 		if (dut->sta_pmf == STA_PMF_OPTIONAL ||
2456 		    dut->sta_pmf == STA_PMF_REQUIRED) {
2457 			if (set_network(ifname, id, "key_mgmt",
2458 					"WPA-EAP-SHA256 FILS-SHA384") < 0)
2459 				return -2;
2460 		} else {
2461 			if (set_network(ifname, id, "key_mgmt",
2462 					"WPA-EAP FILS-SHA384") < 0)
2463 				return -2;
2464 		}
2465 
2466 		erp = 1;
2467 	} else if (!akm && dut->sta_pmf == STA_PMF_OPTIONAL) {
2468 		if (set_network(ifname, id, "key_mgmt",
2469 				"WPA-EAP WPA-EAP-SHA256") < 0)
2470 			return -2;
2471 	} else if (!akm) {
2472 		if (set_network(ifname, id, "key_mgmt", "WPA-EAP") < 0)
2473 			return -2;
2474 	}
2475 
2476 	if (trust_root) {
2477 		if (strcmp(trust_root, "DEFAULT") == 0 && !domain &&
2478 		    !domain_suffix) {
2479 			send_resp(dut, conn, SIGMA_ERROR,
2480 				  "errorCode,trustRootCA DEFAULT used without specifying Domain or DomainSuffix");
2481 			return STATUS_SENT_ERROR;
2482 		}
2483 		res = set_trust_root(dut, conn, ifname, id, trust_root);
2484 		if (res != SUCCESS_SEND_STATUS)
2485 			return res;
2486 	}
2487 
2488 	val = get_param(cmd, "ServerCert");
2489 	if (val) {
2490 		FILE *f;
2491 		char *result = NULL, *pos;
2492 
2493 		snprintf(buf, sizeof(buf), "%s/%s.sha256", sigma_cert_path,
2494 			 val);
2495 		f = fopen(buf, "r");
2496 		if (f) {
2497 			result = fgets(buf, sizeof(buf), f);
2498 			fclose(f);
2499 		}
2500 		if (!result) {
2501 			snprintf(buf2, sizeof(buf2),
2502 				 "ErrorCode,ServerCert hash could not be read from %s",
2503 				 buf);
2504 			send_resp(dut, conn, SIGMA_ERROR, buf2);
2505 			return STATUS_SENT_ERROR;
2506 		}
2507 		pos = strchr(buf, '\n');
2508 		if (pos)
2509 			*pos = '\0';
2510 		pos = strchr(buf, '\r');
2511 		if (pos)
2512 			*pos = '\0';
2513 		snprintf(buf2, sizeof(buf2), "hash://server/sha256/%s", buf);
2514 		if (set_network_quoted(ifname, id, "ca_cert", buf2) < 0)
2515 			return ERROR_SEND_STATUS;
2516 
2517 		snprintf(buf, sizeof(buf), "%s/%s.tod", sigma_cert_path, val);
2518 		if (file_exists(buf)) {
2519 			sigma_dut_print(dut, DUT_MSG_DEBUG,
2520 					"TOD policy enabled for the configured ServerCert hash");
2521 			dut->sta_tod_policy = 1;
2522 		}
2523 	}
2524 
2525 	if (domain &&
2526 	    set_network_quoted(ifname, id, "domain_match", domain) < 0)
2527 		return ERROR_SEND_STATUS;
2528 
2529 	if (domain_suffix &&
2530 	    set_network_quoted(ifname, id, "domain_suffix_match",
2531 			       domain_suffix) < 0)
2532 		return ERROR_SEND_STATUS;
2533 
2534 	if (username_identity) {
2535 		val = get_param(cmd, "username");
2536 		if (val) {
2537 			if (set_network_quoted(ifname, id, "identity", val) < 0)
2538 				return -2;
2539 		}
2540 
2541 		val = get_param(cmd, "password");
2542 		if (val) {
2543 			if (set_network_quoted(ifname, id, "password", val) < 0)
2544 				return -2;
2545 		}
2546 	}
2547 
2548 	if (dut->akm_values &
2549 	    ((1 << AKM_FILS_SHA256) |
2550 	     (1 << AKM_FILS_SHA384) |
2551 	     (1 << AKM_FT_FILS_SHA256) |
2552 	     (1 << AKM_FT_FILS_SHA384)))
2553 		erp = 1;
2554 	if (erp && set_network(ifname, id, "erp", "1") < 0)
2555 		return ERROR_SEND_STATUS;
2556 
2557 	dut->sta_associate_wait_connect = 1;
2558 
2559 	return id;
2560 }
2561 
2562 
set_tls_cipher(const char * ifname,int id,const char * cipher)2563 static int set_tls_cipher(const char *ifname, int id, const char *cipher)
2564 {
2565 	const char *val;
2566 
2567 	if (!cipher)
2568 		return 0;
2569 
2570 	if (strcasecmp(cipher, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384") == 0)
2571 		val = "ECDHE-ECDSA-AES256-GCM-SHA384";
2572 	else if (strcasecmp(cipher,
2573 			    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384") == 0)
2574 		val = "ECDHE-RSA-AES256-GCM-SHA384";
2575 	else if (strcasecmp(cipher, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384") == 0)
2576 		val = "DHE-RSA-AES256-GCM-SHA384";
2577 	else if (strcasecmp(cipher,
2578 			    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256") == 0)
2579 		val = "ECDHE-ECDSA-AES128-GCM-SHA256";
2580 	else
2581 		return -1;
2582 
2583 	/* Need to clear phase1="tls_suiteb=1" to allow cipher enforcement */
2584 	set_network_quoted(ifname, id, "phase1", "");
2585 
2586 	return set_network_quoted(ifname, id, "openssl_ciphers", val);
2587 }
2588 
2589 
cmd_sta_set_eaptls(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)2590 static enum sigma_cmd_result cmd_sta_set_eaptls(struct sigma_dut *dut,
2591 						struct sigma_conn *conn,
2592 						struct sigma_cmd *cmd)
2593 {
2594 	const char *intf = get_param(cmd, "Interface");
2595 	const char *ifname, *val;
2596 	int id;
2597 	char buf[200];
2598 #ifdef ANDROID
2599 	unsigned char kvalue[KEYSTORE_MESSAGE_SIZE];
2600 	int length;
2601 	int jb_or_newer = 0;
2602 	char prop[PROPERTY_VALUE_MAX];
2603 #endif /* ANDROID */
2604 
2605 	if (intf == NULL)
2606 		return -1;
2607 
2608 	if (strcmp(intf, get_main_ifname(dut)) == 0)
2609 		ifname = get_station_ifname(dut);
2610 	else
2611 		ifname = intf;
2612 
2613 	id = set_eap_common(dut, conn, ifname, 1, cmd);
2614 	if (id < 0)
2615 		return id;
2616 
2617 	if (set_network(ifname, id, "eap", "TLS") < 0)
2618 		return -2;
2619 
2620 	if (!get_param(cmd, "username") &&
2621 	    set_network_quoted(ifname, id, "identity",
2622 			       "wifi-user@wifilabs.local") < 0)
2623 		return -2;
2624 
2625 	val = get_param(cmd, "clientCertificate");
2626 	if (val == NULL)
2627 		return -1;
2628 #ifdef ANDROID
2629 	snprintf(buf, sizeof(buf), "USRPKEY_%s", val);
2630 	length = android_keystore_get(ANDROID_KEYSTORE_GET, buf, kvalue);
2631 	if (length < 0) {
2632 		/*
2633 		 * JB started reporting keystore type mismatches, so retry with
2634 		 * the GET_PUBKEY command if the generic GET fails.
2635 		 */
2636 		length = android_keystore_get(ANDROID_KEYSTORE_GET_PUBKEY,
2637 					      buf, kvalue);
2638 	}
2639 
2640 	if (property_get("ro.build.version.release", prop, NULL) != 0) {
2641 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Android release %s", prop);
2642 		if (strncmp(prop, "4.0", 3) != 0)
2643 			jb_or_newer = 1;
2644 	} else
2645 		jb_or_newer = 1; /* assume newer */
2646 
2647 	if (jb_or_newer && length > 0) {
2648 		sigma_dut_print(dut, DUT_MSG_INFO,
2649 				"Use Android keystore [%s]", buf);
2650 		if (set_network(ifname, id, "engine", "1") < 0)
2651 			return -2;
2652 		if (set_network_quoted(ifname, id, "engine_id", "keystore") < 0)
2653 			return -2;
2654 		snprintf(buf, sizeof(buf), "USRPKEY_%s", val);
2655 		if (set_network_quoted(ifname, id, "key_id", buf) < 0)
2656 			return -2;
2657 		snprintf(buf, sizeof(buf), "keystore://USRCERT_%s", val);
2658 		if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
2659 			return -2;
2660 		return 1;
2661 	} else if (length > 0) {
2662 		sigma_dut_print(dut, DUT_MSG_INFO,
2663 				"Use Android keystore [%s]", buf);
2664 		snprintf(buf, sizeof(buf), "keystore://USRPKEY_%s", val);
2665 		if (set_network_quoted(ifname, id, "private_key", buf) < 0)
2666 			return -2;
2667 		snprintf(buf, sizeof(buf), "keystore://USRCERT_%s", val);
2668 		if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
2669 			return -2;
2670 		return 1;
2671 	}
2672 #endif /* ANDROID */
2673 
2674 	snprintf(buf, sizeof(buf), "%s/%s", sigma_cert_path, val);
2675 #ifdef __linux__
2676 	if (!file_exists(buf)) {
2677 		char msg[300];
2678 		snprintf(msg, sizeof(msg), "ErrorCode,clientCertificate file "
2679 			 "(%s) not found", buf);
2680 		send_resp(dut, conn, SIGMA_ERROR, msg);
2681 		return -3;
2682 	}
2683 #endif /* __linux__ */
2684 	if (set_network_quoted(ifname, id, "private_key", buf) < 0)
2685 		return -2;
2686 	if (set_network_quoted(ifname, id, "client_cert", buf) < 0)
2687 		return -2;
2688 
2689 	if (set_network_quoted(ifname, id, "private_key_passwd", "wifi") < 0)
2690 		return -2;
2691 
2692 	val = get_param(cmd, "keyMgmtType");
2693 	if (val && strcasecmp(val, "SuiteB") == 0) {
2694 		val = get_param(cmd, "CertType");
2695 		if (val && strcasecmp(val, "RSA") == 0) {
2696 			if (set_network_quoted(ifname, id, "phase1",
2697 					       "tls_suiteb=1") < 0)
2698 				return -2;
2699 		} else {
2700 			if (set_network_quoted(ifname, id, "openssl_ciphers",
2701 					       "SUITEB192") < 0)
2702 				return -2;
2703 		}
2704 
2705 		val = get_param(cmd, "TLSCipher");
2706 		if (set_tls_cipher(ifname, id, val) < 0) {
2707 			send_resp(dut, conn, SIGMA_ERROR,
2708 				  "ErrorCode,Unsupported TLSCipher value");
2709 			return -3;
2710 		}
2711 	}
2712 
2713 	return 1;
2714 }
2715 
2716 
cmd_sta_set_eapttls(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)2717 static enum sigma_cmd_result cmd_sta_set_eapttls(struct sigma_dut *dut,
2718 						 struct sigma_conn *conn,
2719 						 struct sigma_cmd *cmd)
2720 {
2721 	const char *intf = get_param(cmd, "Interface");
2722 	const char *ifname;
2723 	int id;
2724 
2725 	if (intf == NULL)
2726 		return -1;
2727 
2728 	if (strcmp(intf, get_main_ifname(dut)) == 0)
2729 		ifname = get_station_ifname(dut);
2730 	else
2731 		ifname = intf;
2732 
2733 	id = set_eap_common(dut, conn, ifname, 1, cmd);
2734 	if (id < 0)
2735 		return id;
2736 
2737 	if (set_network(ifname, id, "eap", "TTLS") < 0) {
2738 		send_resp(dut, conn, SIGMA_ERROR,
2739 			  "errorCode,Failed to set TTLS method");
2740 		return 0;
2741 	}
2742 
2743 	if (set_network_quoted(ifname, id, "phase2", "auth=MSCHAPV2") < 0) {
2744 		send_resp(dut, conn, SIGMA_ERROR,
2745 			  "errorCode,Failed to set MSCHAPv2 for TTLS Phase 2");
2746 		return 0;
2747 	}
2748 
2749 	return 1;
2750 }
2751 
2752 
cmd_sta_set_eapsim(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)2753 static enum sigma_cmd_result cmd_sta_set_eapsim(struct sigma_dut *dut,
2754 						struct sigma_conn *conn,
2755 						struct sigma_cmd *cmd)
2756 {
2757 	const char *intf = get_param(cmd, "Interface");
2758 	const char *ifname;
2759 	int id;
2760 
2761 	if (intf == NULL)
2762 		return -1;
2763 
2764 	if (strcmp(intf, get_main_ifname(dut)) == 0)
2765 		ifname = get_station_ifname(dut);
2766 	else
2767 		ifname = intf;
2768 
2769 	id = set_eap_common(dut, conn, ifname, !dut->sim_no_username, cmd);
2770 	if (id < 0)
2771 		return id;
2772 
2773 	if (set_network(ifname, id, "eap", "SIM") < 0)
2774 		return -2;
2775 
2776 	return 1;
2777 }
2778 
2779 
cmd_sta_set_peap(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)2780 static enum sigma_cmd_result cmd_sta_set_peap(struct sigma_dut *dut,
2781 					      struct sigma_conn *conn,
2782 					      struct sigma_cmd *cmd)
2783 {
2784 	const char *intf = get_param(cmd, "Interface");
2785 	const char *ifname, *val;
2786 	int id;
2787 	char buf[100];
2788 
2789 	if (intf == NULL)
2790 		return -1;
2791 
2792 	if (strcmp(intf, get_main_ifname(dut)) == 0)
2793 		ifname = get_station_ifname(dut);
2794 	else
2795 		ifname = intf;
2796 
2797 	id = set_eap_common(dut, conn, ifname, 1, cmd);
2798 	if (id < 0)
2799 		return id;
2800 
2801 	if (set_network(ifname, id, "eap", "PEAP") < 0)
2802 		return -2;
2803 
2804 	val = get_param(cmd, "innerEAP");
2805 	if (val) {
2806 		if (strcasecmp(val, "MSCHAPv2") == 0) {
2807 			if (set_network_quoted(ifname, id, "phase2",
2808 					       "auth=MSCHAPV2") < 0)
2809 				return -2;
2810 		} else if (strcasecmp(val, "GTC") == 0) {
2811 			if (set_network_quoted(ifname, id, "phase2",
2812 					       "auth=GTC") < 0)
2813 				return -2;
2814 		} else
2815 			return -1;
2816 	}
2817 
2818 	val = get_param(cmd, "peapVersion");
2819 	if (val) {
2820 		int ver = atoi(val);
2821 		if (ver < 0 || ver > 1)
2822 			return -1;
2823 		snprintf(buf, sizeof(buf), "peapver=%d", ver);
2824 		if (set_network_quoted(ifname, id, "phase1", buf) < 0)
2825 			return -2;
2826 	}
2827 
2828 	return 1;
2829 }
2830 
2831 
cmd_sta_set_eapfast(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)2832 static enum sigma_cmd_result cmd_sta_set_eapfast(struct sigma_dut *dut,
2833 						 struct sigma_conn *conn,
2834 						 struct sigma_cmd *cmd)
2835 {
2836 	const char *intf = get_param(cmd, "Interface");
2837 	const char *ifname, *val;
2838 	int id;
2839 	char buf[100];
2840 
2841 	if (intf == NULL)
2842 		return -1;
2843 
2844 	if (strcmp(intf, get_main_ifname(dut)) == 0)
2845 		ifname = get_station_ifname(dut);
2846 	else
2847 		ifname = intf;
2848 
2849 	id = set_eap_common(dut, conn, ifname, 1, cmd);
2850 	if (id < 0)
2851 		return id;
2852 
2853 	if (set_network(ifname, id, "eap", "FAST") < 0)
2854 		return -2;
2855 
2856 	val = get_param(cmd, "innerEAP");
2857 	if (val) {
2858 		if (strcasecmp(val, "MSCHAPV2") == 0) {
2859 			if (set_network_quoted(ifname, id, "phase2",
2860 					       "auth=MSCHAPV2") < 0)
2861 				return -2;
2862 		} else if (strcasecmp(val, "GTC") == 0) {
2863 			if (set_network_quoted(ifname, id, "phase2",
2864 					       "auth=GTC") < 0)
2865 				return -2;
2866 		} else
2867 			return -1;
2868 	}
2869 
2870 	val = get_param(cmd, "validateServer");
2871 	if (val) {
2872 		/* TODO */
2873 		sigma_dut_print(dut, DUT_MSG_INFO, "Ignored EAP-FAST "
2874 				"validateServer=%s", val);
2875 	}
2876 
2877 	val = get_param(cmd, "pacFile");
2878 	if (val) {
2879 		snprintf(buf, sizeof(buf), "blob://%s", val);
2880 		if (set_network_quoted(ifname, id, "pac_file", buf) < 0)
2881 			return -2;
2882 	}
2883 
2884 	if (set_network_quoted(ifname, id, "phase1", "fast_provisioning=2") <
2885 	    0)
2886 		return -2;
2887 
2888 	return 1;
2889 }
2890 
2891 
cmd_sta_set_eapaka(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)2892 static enum sigma_cmd_result cmd_sta_set_eapaka(struct sigma_dut *dut,
2893 						struct sigma_conn *conn,
2894 						struct sigma_cmd *cmd)
2895 {
2896 	const char *intf = get_param(cmd, "Interface");
2897 	const char *username = get_param(cmd, "Username");
2898 	const char *ifname;
2899 	int id;
2900 
2901 	if (intf == NULL)
2902 		return -1;
2903 
2904 	if (strcmp(intf, get_main_ifname(dut)) == 0)
2905 		ifname = get_station_ifname(dut);
2906 	else
2907 		ifname = intf;
2908 
2909 	id = set_eap_common(dut, conn, ifname, !dut->sim_no_username, cmd);
2910 	if (id < 0)
2911 		return id;
2912 
2913 	/* RFC 5448: EAP-AKA' MUST use the leading character "6" (ASCII 36
2914 	 * hexadecimal).
2915 	 */
2916 	if (username && username[0] == '6') {
2917 		if (set_network(ifname, id, "eap", "AKA'") < 0)
2918 			return -2;
2919 	} else if (set_network(ifname, id, "eap", "AKA") < 0) {
2920 		return -2;
2921 	}
2922 
2923 	return 1;
2924 }
2925 
2926 
cmd_sta_set_eapakaprime(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)2927 static enum sigma_cmd_result cmd_sta_set_eapakaprime(struct sigma_dut *dut,
2928 						     struct sigma_conn *conn,
2929 						     struct sigma_cmd *cmd)
2930 {
2931 	const char *intf = get_param(cmd, "Interface");
2932 	const char *ifname;
2933 	int id;
2934 
2935 	if (intf == NULL)
2936 		return -1;
2937 
2938 	if (strcmp(intf, get_main_ifname(dut)) == 0)
2939 		ifname = get_station_ifname(dut);
2940 	else
2941 		ifname = intf;
2942 
2943 	id = set_eap_common(dut, conn, ifname, !dut->sim_no_username, cmd);
2944 	if (id < 0)
2945 		return id;
2946 
2947 	if (set_network(ifname, id, "eap", "AKA'") < 0)
2948 		return -2;
2949 
2950 	return 1;
2951 }
2952 
2953 
sta_set_open(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)2954 static int sta_set_open(struct sigma_dut *dut, struct sigma_conn *conn,
2955 			struct sigma_cmd *cmd)
2956 {
2957 	const char *intf = get_param(cmd, "Interface");
2958 	const char *network_mode = get_param(cmd, "network_mode");
2959 	const char *ifname;
2960 	int id;
2961 
2962 	if (strcmp(intf, get_main_ifname(dut)) == 0)
2963 		ifname = get_station_ifname(dut);
2964 	else
2965 		ifname = intf;
2966 
2967 	id = add_network_common(dut, conn, ifname, cmd);
2968 	if (id < 0)
2969 		return id;
2970 
2971 	if (set_network(ifname, id, "key_mgmt", "NONE") < 0)
2972 		return -2;
2973 
2974 	if (dut->program == PROGRAM_60GHZ && network_mode &&
2975 	    strcasecmp(network_mode, "PBSS") == 0 &&
2976 	    set_network(ifname, id, "pbss", "1") < 0)
2977 		return -2;
2978 
2979 	return 1;
2980 }
2981 
2982 
sta_set_owe(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)2983 static enum sigma_cmd_result sta_set_owe(struct sigma_dut *dut,
2984 					 struct sigma_conn *conn,
2985 					 struct sigma_cmd *cmd)
2986 {
2987 	const char *intf = get_param(cmd, "Interface");
2988 	const char *ifname, *val;
2989 	int id;
2990 
2991 	if (intf == NULL)
2992 		return INVALID_SEND_STATUS;
2993 
2994 	if (strcmp(intf, get_main_ifname(dut)) == 0)
2995 		ifname = get_station_ifname(dut);
2996 	else
2997 		ifname = intf;
2998 
2999 	id = set_wpa_common(dut, conn, ifname, cmd);
3000 	if (id < 0)
3001 		return id;
3002 
3003 	if (set_network(ifname, id, "key_mgmt", "OWE") < 0)
3004 		return ERROR_SEND_STATUS;
3005 
3006 	if (dut->owe_ptk_workaround &&
3007 	    set_network(ifname, id, "owe_ptk_workaround", "1") < 0) {
3008 		sigma_dut_print(dut, DUT_MSG_ERROR,
3009 				"Failed to set owe_ptk_workaround to 1");
3010 		return ERROR_SEND_STATUS;
3011 	}
3012 
3013 	val = get_param(cmd, "ECGroupID");
3014 	if (val && strcmp(val, "0") == 0) {
3015 		if (wpa_command(ifname,
3016 				"VENDOR_ELEM_ADD 13 ff23200000783590fb7440e03d5b3b33911f86affdcc6b4411b707846ac4ff08ddc8831ccd") != 0) {
3017 			sigma_dut_print(dut, DUT_MSG_ERROR,
3018 					"Failed to set OWE DH Param element override");
3019 			return ERROR_SEND_STATUS;
3020 		}
3021 	} else if (val && set_network(ifname, id, "owe_group", val) < 0) {
3022 		sigma_dut_print(dut, DUT_MSG_ERROR,
3023 				"Failed to set owe_group");
3024 		return ERROR_SEND_STATUS;
3025 	}
3026 
3027 	return SUCCESS_SEND_STATUS;
3028 }
3029 
3030 
cmd_sta_set_security(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)3031 static enum sigma_cmd_result cmd_sta_set_security(struct sigma_dut *dut,
3032 						  struct sigma_conn *conn,
3033 						  struct sigma_cmd *cmd)
3034 {
3035 	const char *type = get_param(cmd, "Type");
3036 
3037 	if (type == NULL) {
3038 		send_resp(dut, conn, SIGMA_ERROR,
3039 			  "ErrorCode,Missing Type argument");
3040 		return 0;
3041 	}
3042 
3043 	if (strcasecmp(type, "OPEN") == 0)
3044 		return sta_set_open(dut, conn, cmd);
3045 	if (strcasecmp(type, "OWE") == 0)
3046 		return sta_set_owe(dut, conn, cmd);
3047 	if (strcasecmp(type, "PSK") == 0 ||
3048 	    strcasecmp(type, "PSK-SAE") == 0 ||
3049 	    strcasecmp(type, "SAE") == 0)
3050 		return cmd_sta_set_psk(dut, conn, cmd);
3051 	if (strcasecmp(type, "EAPTLS") == 0)
3052 		return cmd_sta_set_eaptls(dut, conn, cmd);
3053 	if (strcasecmp(type, "EAPTTLS") == 0)
3054 		return cmd_sta_set_eapttls(dut, conn, cmd);
3055 	if (strcasecmp(type, "EAPPEAP") == 0)
3056 		return cmd_sta_set_peap(dut, conn, cmd);
3057 	if (strcasecmp(type, "EAPSIM") == 0)
3058 		return cmd_sta_set_eapsim(dut, conn, cmd);
3059 	if (strcasecmp(type, "EAPFAST") == 0)
3060 		return cmd_sta_set_eapfast(dut, conn, cmd);
3061 	if (strcasecmp(type, "EAPAKA") == 0)
3062 		return cmd_sta_set_eapaka(dut, conn, cmd);
3063 	if (strcasecmp(type, "EAPAKAPRIME") == 0)
3064 		return cmd_sta_set_eapakaprime(dut, conn, cmd);
3065 	if (strcasecmp(type, "wep") == 0)
3066 		return cmd_sta_set_encryption(dut, conn, cmd);
3067 
3068 	send_resp(dut, conn, SIGMA_ERROR,
3069 		  "ErrorCode,Unsupported Type value");
3070 	return 0;
3071 }
3072 
3073 
ath6kl_client_uapsd(struct sigma_dut * dut,const char * intf,int uapsd)3074 int ath6kl_client_uapsd(struct sigma_dut *dut, const char *intf, int uapsd)
3075 {
3076 #ifdef __linux__
3077 	/* special handling for ath6kl */
3078 	char path[128], fname[128], *pos;
3079 	ssize_t res;
3080 	FILE *f;
3081 
3082 	res = snprintf(fname, sizeof(fname), "/sys/class/net/%s/phy80211",
3083 		       intf);
3084 	if (res < 0 || res >= sizeof(fname))
3085 		return 0;
3086 	res = readlink(fname, path, sizeof(path));
3087 	if (res < 0)
3088 		return 0; /* not ath6kl */
3089 
3090 	if (res >= (int) sizeof(path))
3091 		res = sizeof(path) - 1;
3092 	path[res] = '\0';
3093 	pos = strrchr(path, '/');
3094 	if (pos == NULL)
3095 		pos = path;
3096 	else
3097 		pos++;
3098 	res = snprintf(fname, sizeof(fname),
3099 		       "/sys/kernel/debug/ieee80211/%s/ath6kl/"
3100 		       "create_qos", pos);
3101 	if (res < 0 || res >= sizeof(fname) || !file_exists(fname))
3102 		return 0; /* not ath6kl */
3103 
3104 	if (uapsd) {
3105 		f = fopen(fname, "w");
3106 		if (f == NULL)
3107 			return -1;
3108 
3109 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Use ath6kl create_qos");
3110 		fprintf(f, "4 2 2 1 2 9999999 9999999 9999999 7777777 0 4 "
3111 			"45000 200 56789000 56789000 5678900 0 0 9999999 "
3112 			"20000 0\n");
3113 		fclose(f);
3114 	} else {
3115 		res = snprintf(fname, sizeof(fname),
3116 			       "/sys/kernel/debug/ieee80211/%s/ath6kl/"
3117 			       "delete_qos", pos);
3118 		if (res < 0 || res >= sizeof(fname))
3119 			return -1;
3120 
3121 		f = fopen(fname, "w");
3122 		if (f == NULL)
3123 			return -1;
3124 
3125 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Use ath6kl delete_qos");
3126 		fprintf(f, "2 4\n");
3127 		fclose(f);
3128 	}
3129 #endif /* __linux__ */
3130 
3131 	return 0;
3132 }
3133 
3134 
cmd_sta_set_uapsd(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)3135 static enum sigma_cmd_result cmd_sta_set_uapsd(struct sigma_dut *dut,
3136 					       struct sigma_conn *conn,
3137 					       struct sigma_cmd *cmd)
3138 {
3139 	const char *intf = get_param(cmd, "Interface");
3140 	/* const char *ssid = get_param(cmd, "ssid"); */
3141 	const char *val;
3142 	int max_sp_len = 4;
3143 	int ac_be = 1, ac_bk = 1, ac_vi = 1, ac_vo = 1;
3144 	char buf[100];
3145 	int ret1, ret2;
3146 
3147 	val = get_param(cmd, "maxSPLength");
3148 	if (val) {
3149 		max_sp_len = atoi(val);
3150 		if (max_sp_len != 0 && max_sp_len != 1 && max_sp_len != 2 &&
3151 		    max_sp_len != 4)
3152 			return -1;
3153 	}
3154 
3155 	val = get_param(cmd, "acBE");
3156 	if (val)
3157 		ac_be = atoi(val);
3158 
3159 	val = get_param(cmd, "acBK");
3160 	if (val)
3161 		ac_bk = atoi(val);
3162 
3163 	val = get_param(cmd, "acVI");
3164 	if (val)
3165 		ac_vi = atoi(val);
3166 
3167 	val = get_param(cmd, "acVO");
3168 	if (val)
3169 		ac_vo = atoi(val);
3170 
3171 	dut->client_uapsd = ac_be || ac_bk || ac_vi || ac_vo;
3172 
3173 	snprintf(buf, sizeof(buf), "P2P_SET client_apsd %d,%d,%d,%d;%d",
3174 		 ac_be, ac_bk, ac_vi, ac_vo, max_sp_len);
3175 	ret1 = wpa_command(intf, buf);
3176 
3177 	snprintf(buf, sizeof(buf), "SET uapsd %d,%d,%d,%d;%d",
3178 		 ac_be, ac_bk, ac_vi, ac_vo, max_sp_len);
3179 	ret2 = wpa_command(intf, buf);
3180 
3181 	if (ret1 && ret2) {
3182 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to set client mode "
3183 				"UAPSD parameters.");
3184 		return -2;
3185 	}
3186 
3187 	if (ath6kl_client_uapsd(dut, intf, dut->client_uapsd) < 0) {
3188 		send_resp(dut, conn, SIGMA_ERROR,
3189 			  "ErrorCode,Failed to set ath6kl QoS parameters");
3190 		return 0;
3191 	}
3192 
3193 	return 1;
3194 }
3195 
3196 
cmd_sta_set_wmm(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)3197 static enum sigma_cmd_result cmd_sta_set_wmm(struct sigma_dut *dut,
3198 					     struct sigma_conn *conn,
3199 					     struct sigma_cmd *cmd)
3200 {
3201 	char buf[1000];
3202 	const char *intf = get_param(cmd, "Interface");
3203 	const char *grp = get_param(cmd, "Group");
3204 	const char *act = get_param(cmd, "Action");
3205 	const char *tid = get_param(cmd, "Tid");
3206 	const char *dir = get_param(cmd, "Direction");
3207 	const char *psb = get_param(cmd, "Psb");
3208 	const char *up = get_param(cmd, "Up");
3209 	const char *fixed = get_param(cmd, "Fixed");
3210 	const char *size = get_param(cmd, "Size");
3211 	const char *msize = get_param(cmd, "Maxsize");
3212 	const char *minsi = get_param(cmd, "Min_srvc_intrvl");
3213 	const char *maxsi = get_param(cmd, "Max_srvc_intrvl");
3214 	const char *inact = get_param(cmd, "Inactivity");
3215 	const char *sus = get_param(cmd, "Suspension");
3216 	const char *mindr = get_param(cmd, "Mindatarate");
3217 	const char *meandr = get_param(cmd, "Meandatarate");
3218 	const char *peakdr = get_param(cmd, "Peakdatarate");
3219 	const char *phyrate = get_param(cmd, "Phyrate");
3220 	const char *burstsize = get_param(cmd, "Burstsize");
3221 	const char *sba = get_param(cmd, "Sba");
3222 	int direction;
3223 	int handle;
3224 	float sba_fv = 0;
3225 	int fixed_int;
3226 	int psb_ts;
3227 
3228 	if (intf == NULL || grp == NULL || act == NULL )
3229 		return -1;
3230 
3231 	if (strcasecmp(act, "addts") == 0) {
3232 		if (tid == NULL || dir == NULL || psb == NULL ||
3233 		    up == NULL || fixed == NULL || size == NULL)
3234 			return -1;
3235 
3236 		/*
3237 		 * Note: Sigma CAPI spec lists uplink, downlink, and bidi as the
3238 		 * possible values, but WMM-AC and V-E test scripts use "UP,
3239 		 * "DOWN", and "BIDI".
3240 		 */
3241 		if (strcasecmp(dir, "uplink") == 0 ||
3242 		    strcasecmp(dir, "up") == 0) {
3243 			direction = 0;
3244 		} else if (strcasecmp(dir, "downlink") == 0 ||
3245 			   strcasecmp(dir, "down") == 0) {
3246 			direction = 1;
3247 		} else if (strcasecmp(dir, "bidi") == 0) {
3248 			direction = 2;
3249 		} else {
3250 			sigma_dut_print(dut, DUT_MSG_ERROR,
3251 					"Direction %s not supported", dir);
3252 			return -1;
3253 		}
3254 
3255 		if (strcasecmp(psb, "legacy") == 0) {
3256 			psb_ts = 0;
3257 		} else if (strcasecmp(psb, "uapsd") == 0) {
3258 			psb_ts = 1;
3259 		} else {
3260 			sigma_dut_print(dut, DUT_MSG_ERROR,
3261 					"PSB %s not supported", psb);
3262 			return -1;
3263 		}
3264 
3265 		if (atoi(tid) < 0 || atoi(tid) > 7) {
3266 			sigma_dut_print(dut, DUT_MSG_ERROR,
3267 					"TID %s not supported", tid);
3268 			return -1;
3269 		}
3270 
3271 		if (strcasecmp(fixed, "true") == 0) {
3272 			fixed_int = 1;
3273 		} else {
3274 			fixed_int = 0;
3275 		}
3276 
3277 		if (sba)
3278 			sba_fv = atof(sba);
3279 
3280 		dut->dialog_token++;
3281 		handle = 7000 + dut->dialog_token;
3282 
3283 		/*
3284 		 * size: convert to hex
3285 		 * maxsi: convert to hex
3286 		 * mindr: convert to hex
3287 		 * meandr: convert to hex
3288 		 * peakdr: convert to hex
3289 		 * burstsize: convert to hex
3290 		 * phyrate: convert to hex
3291 		 * sba: convert to hex with modification
3292 		 * minsi: convert to integer
3293 		 * sus: convert to integer
3294 		 * inact: convert to integer
3295 		 * maxsi: convert to integer
3296 		 */
3297 
3298 		/*
3299 		 * The Nominal MSDU Size field is 2 octets long and contains an
3300 		 * unsigned integer that specifies the nominal size, in octets,
3301 		 * of MSDUs belonging to the traffic under this traffic
3302 		 * specification and is defined in Figure 16. If the Fixed
3303 		 * subfield is set to 1, then the size of the MSDU is fixed and
3304 		 * is indicated by the Size Subfield. If the Fixed subfield is
3305 		 * set to 0, then the size of the MSDU might not be fixed and
3306 		 * the Size indicates the nominal MSDU size.
3307 		 *
3308 		 * The Surplus Bandwidth Allowance Factor field is 2 octets long
3309 		 * and specifies the excess allocation of time (and bandwidth)
3310 		 * over and above the stated rates required to transport an MSDU
3311 		 * belonging to the traffic in this TSPEC. This field is
3312 		 * represented as an unsigned binary number with an implicit
3313 		 * binary point after the leftmost 3 bits. For example, an SBA
3314 		 * of 1.75 is represented as 0x3800. This field is included to
3315 		 * account for retransmissions. As such, the value of this field
3316 		 * must be greater than unity.
3317 		 */
3318 
3319 		snprintf(buf, sizeof(buf),
3320 			 "iwpriv %s addTspec %d %s %d %d %s 0x%X"
3321 			 " 0x%X 0x%X 0x%X"
3322 			 " 0x%X 0x%X 0x%X"
3323 			 " 0x%X %d %d %d %d"
3324 			 " %d %d",
3325 			 intf, handle, tid, direction, psb_ts, up,
3326 			 (unsigned int) ((fixed_int << 15) | atoi(size)),
3327 			 msize ? atoi(msize) : 0,
3328 			 mindr ? atoi(mindr) : 0,
3329 			 meandr ? atoi(meandr) : 0,
3330 			 peakdr ? atoi(peakdr) : 0,
3331 			 burstsize ? atoi(burstsize) : 0,
3332 			 phyrate ? atoi(phyrate) : 0,
3333 			 sba ? ((unsigned int) (((int) sba_fv << 13) |
3334 						(int)((sba_fv - (int) sba_fv) *
3335 						      8192))) : 0,
3336 			 minsi ? atoi(minsi) : 0,
3337 			 sus ? atoi(sus) : 0,
3338 			 0, 0,
3339 			 inact ? atoi(inact) : 0,
3340 			 maxsi ? atoi(maxsi) : 0);
3341 
3342 		if (system(buf) != 0) {
3343 			sigma_dut_print(dut, DUT_MSG_ERROR,
3344 					"iwpriv addtspec request failed");
3345 			send_resp(dut, conn, SIGMA_ERROR,
3346 				  "errorCode,Failed to execute addTspec command");
3347 			return 0;
3348 		}
3349 
3350 		sigma_dut_print(dut, DUT_MSG_INFO,
3351 				"iwpriv addtspec request send");
3352 
3353 		/* Mapping handle to a TID */
3354 		dut->tid_to_handle[atoi(tid)] = handle;
3355 	} else if (strcasecmp(act, "delts") == 0) {
3356 		if (tid == NULL)
3357 			return -1;
3358 
3359 		if (atoi(tid) < 0 || atoi(tid) > 7) {
3360 			sigma_dut_print(dut, DUT_MSG_ERROR,
3361 					"TID %s not supported", tid);
3362 			send_resp(dut, conn, SIGMA_ERROR,
3363 				  "errorCode,Unsupported TID");
3364 			return 0;
3365 		}
3366 
3367 		handle = dut->tid_to_handle[atoi(tid)];
3368 
3369 		if (handle < 7000 || handle > 7255) {
3370 			/* Invalid handle ie no mapping for that TID */
3371 			sigma_dut_print(dut, DUT_MSG_ERROR,
3372 					"handle-> %d not found", handle);
3373 		}
3374 
3375 		snprintf(buf, sizeof(buf), "iwpriv %s delTspec %d",
3376 			 intf, handle);
3377 
3378 		if (system(buf) != 0) {
3379 			sigma_dut_print(dut, DUT_MSG_ERROR,
3380 					"iwpriv deltspec request failed");
3381 			send_resp(dut, conn, SIGMA_ERROR,
3382 				  "errorCode,Failed to execute delTspec command");
3383 			return 0;
3384 		}
3385 
3386 		sigma_dut_print(dut, DUT_MSG_INFO,
3387 				"iwpriv deltspec request send");
3388 
3389 		dut->tid_to_handle[atoi(tid)] = 0;
3390 	} else {
3391 		sigma_dut_print(dut, DUT_MSG_ERROR,
3392 				"Action type %s not supported", act);
3393 		send_resp(dut, conn, SIGMA_ERROR,
3394 			  "errorCode,Unsupported Action");
3395 		return 0;
3396 	}
3397 
3398 	return 1;
3399 }
3400 
3401 
find_network(struct sigma_dut * dut,const char * ssid)3402 static int find_network(struct sigma_dut *dut, const char *ssid)
3403 {
3404 	char list[4096];
3405 	char *pos;
3406 
3407 	sigma_dut_print(dut, DUT_MSG_DEBUG,
3408 			"Search for profile based on SSID: '%s'", ssid);
3409 	if (wpa_command_resp(get_station_ifname(dut), "LIST_NETWORKS",
3410 			     list, sizeof(list)) < 0)
3411 		return -1;
3412 	pos = strstr(list, ssid);
3413 	if (!pos || pos == list || pos[-1] != '\t' || pos[strlen(ssid)] != '\t')
3414 		return -1;
3415 
3416 	while (pos > list && pos[-1] != '\n')
3417 		pos--;
3418 	dut->infra_network_id = atoi(pos);
3419 	snprintf(dut->infra_ssid, sizeof(dut->infra_ssid), "%s", ssid);
3420 	return 0;
3421 }
3422 
3423 
3424 /**
3425  * enum qca_sta_helper_config_params - This helper enum defines the config
3426  * parameters which can be delivered to sta.
3427  */
3428 enum qca_sta_helper_config_params {
3429 	/* For the attribute QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE */
3430 	STA_SET_RSNIE,
3431 
3432 	/* For the attribute QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC */
3433 	STA_SET_LDPC,
3434 
3435 	/* For the attribute QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC */
3436 	STA_SET_TX_STBC,
3437 
3438 	/* For the attribute QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC */
3439 	STA_SET_RX_STBC,
3440 
3441 	/* For the attribute QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION */
3442 	STA_SET_TX_MSDU,
3443 
3444 	/* For the attribute QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION */
3445 	STA_SET_RX_MSDU,
3446 };
3447 
3448 
sta_config_params(struct sigma_dut * dut,const char * intf,enum qca_sta_helper_config_params config_cmd,int value)3449 static int sta_config_params(struct sigma_dut *dut, const char *intf,
3450 			     enum qca_sta_helper_config_params config_cmd,
3451 			     int value)
3452 {
3453 #ifdef NL80211_SUPPORT
3454 	struct nl_msg *msg;
3455 	int ret;
3456 	struct nlattr *params;
3457 	int ifindex;
3458 
3459 	ifindex = if_nametoindex(intf);
3460 	if (ifindex == 0) {
3461 		sigma_dut_print(dut, DUT_MSG_ERROR,
3462 				"%s: Interface %s does not exist",
3463 				__func__, intf);
3464 		return -1;
3465 	}
3466 
3467 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
3468 				    NL80211_CMD_VENDOR)) ||
3469 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
3470 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
3471 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
3472 			QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION) ||
3473 	    !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)))
3474 		goto fail;
3475 
3476 	switch (config_cmd) {
3477 	case STA_SET_RSNIE:
3478 		if (nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE, value))
3479 			goto fail;
3480 		break;
3481 	case STA_SET_LDPC:
3482 		if (nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC, value))
3483 			goto fail;
3484 		break;
3485 	case STA_SET_TX_STBC:
3486 		if (nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC, value))
3487 			goto fail;
3488 		break;
3489 	case STA_SET_RX_STBC:
3490 		if (nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC, value))
3491 			goto fail;
3492 		break;
3493 	case STA_SET_TX_MSDU:
3494 		if (nla_put_u8(msg,
3495 			       QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION,
3496 			       value))
3497 			goto fail;
3498 		break;
3499 	case STA_SET_RX_MSDU:
3500 		if (nla_put_u8(msg,
3501 			       QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION,
3502 			       value))
3503 			goto fail;
3504 		break;
3505 	}
3506 	nla_nest_end(msg, params);
3507 
3508 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
3509 	if (ret) {
3510 		sigma_dut_print(dut, DUT_MSG_ERROR,
3511 				"%s: err in send_and_recv_msgs, ret=%d",
3512 				__func__, ret);
3513 		return ret;
3514 	}
3515 
3516 	return 0;
3517 
3518 fail:
3519 	sigma_dut_print(dut, DUT_MSG_ERROR,
3520 			"%s: err in adding vendor_cmd and vendor_data",
3521 			__func__);
3522 	nlmsg_free(msg);
3523 #endif /* NL80211_SUPPORT */
3524 	return -1;
3525 }
3526 
3527 
cmd_sta_associate(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)3528 static enum sigma_cmd_result cmd_sta_associate(struct sigma_dut *dut,
3529 					       struct sigma_conn *conn,
3530 					       struct sigma_cmd *cmd)
3531 {
3532 #ifdef NL80211_SUPPORT
3533 	const char *intf = get_param(cmd, "Interface");
3534 #endif /* NL80211_SUPPORT */
3535 	const char *ssid = get_param(cmd, "ssid");
3536 	const char *wps_param = get_param(cmd, "WPS");
3537 	const char *bssid = get_param(cmd, "bssid");
3538 	const char *chan = get_param(cmd, "channel");
3539 	const char *network_mode = get_param(cmd, "network_mode");
3540 	const char *ifname = get_station_ifname(dut);
3541 	int wps = 0;
3542 	char buf[1000], extra[50];
3543 	int e;
3544 	enum sigma_cmd_result ret = SUCCESS_SEND_STATUS;
3545 	struct wpa_ctrl *ctrl = NULL;
3546 	int num_network_not_found = 0;
3547 	int num_disconnected = 0;
3548 	int tod = -1;
3549 
3550 	if (ssid == NULL)
3551 		return -1;
3552 
3553 	dut->server_cert_tod = 0;
3554 
3555 	if (dut->rsne_override) {
3556 #ifdef NL80211_SUPPORT
3557 		if (get_driver_type(dut) == DRIVER_WCN) {
3558 			sta_config_params(dut, intf, STA_SET_RSNIE, 1);
3559 			dut->config_rsnie = 1;
3560 		}
3561 #endif /* NL80211_SUPPORT */
3562 		snprintf(buf, sizeof(buf), "TEST_ASSOC_IE %s",
3563 			 dut->rsne_override);
3564 		if (wpa_command(get_station_ifname(dut), buf) < 0) {
3565 			send_resp(dut, conn, SIGMA_ERROR,
3566 				  "ErrorCode,Failed to set DEV_CONFIGURE_IE RSNE override");
3567 			return 0;
3568 		}
3569 	}
3570 
3571 	if (dut->sae_commit_override) {
3572 		snprintf(buf, sizeof(buf), "SET sae_commit_override %s",
3573 			 dut->sae_commit_override);
3574 		if (wpa_command(get_station_ifname(dut), buf) < 0) {
3575 			send_resp(dut, conn, SIGMA_ERROR,
3576 				  "ErrorCode,Failed to set SAE commit override");
3577 			return 0;
3578 		}
3579 	}
3580 #ifdef ANDROID
3581 	if (dut->fils_hlp)
3582 		process_fils_hlp(dut);
3583 #endif /* ANDROID */
3584 
3585 	if (wps_param &&
3586 	    (strcmp(wps_param, "1") == 0 || strcasecmp(wps_param, "On") == 0))
3587 		wps = 1;
3588 
3589 	if (wps) {
3590 		if (dut->program == PROGRAM_60GHZ && network_mode &&
3591 		    strcasecmp(network_mode, "PBSS") == 0 &&
3592 		    set_network(get_station_ifname(dut), dut->infra_network_id,
3593 				"pbss", "1") < 0)
3594 			return -2;
3595 
3596 		if (dut->wps_method == WFA_CS_WPS_NOT_READY) {
3597 			send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS "
3598 				  "parameters not yet set");
3599 			return 0;
3600 		}
3601 		if (dut->wps_method == WFA_CS_WPS_PBC) {
3602 			if (wpa_command(get_station_ifname(dut), "WPS_PBC") < 0)
3603 				return -2;
3604 		} else {
3605 			snprintf(buf, sizeof(buf), "WPS_PIN any %s",
3606 				 dut->wps_pin);
3607 			if (wpa_command(get_station_ifname(dut), buf) < 0)
3608 				return -2;
3609 		}
3610 	} else {
3611 		if (strcmp(ssid, dut->infra_ssid) == 0) {
3612 			sigma_dut_print(dut, DUT_MSG_DEBUG,
3613 					"sta_associate for the most recently added network");
3614 		} else if (find_network(dut, ssid) < 0) {
3615 			sigma_dut_print(dut, DUT_MSG_DEBUG,
3616 					"sta_associate for a previously stored network profile");
3617 			send_resp(dut, conn, SIGMA_ERROR,
3618 				  "ErrorCode,Profile not found");
3619 			return 0;
3620 		}
3621 
3622 		if (bssid &&
3623 		    set_network(get_station_ifname(dut), dut->infra_network_id,
3624 				"bssid", bssid) < 0) {
3625 			send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
3626 				  "Invalid bssid argument");
3627 			return 0;
3628 		}
3629 
3630 		if ((dut->program == PROGRAM_WPA3 &&
3631 		     dut->sta_associate_wait_connect) ||
3632 		    dut->program == PROGRAM_QM) {
3633 			ctrl = open_wpa_mon(get_station_ifname(dut));
3634 			if (!ctrl)
3635 				return ERROR_SEND_STATUS;
3636 		}
3637 
3638 		extra[0] = '\0';
3639 		if (chan)
3640 			snprintf(extra, sizeof(extra), " freq=%u",
3641 				 channel_to_freq(dut, atoi(chan)));
3642 		snprintf(buf, sizeof(buf), "SELECT_NETWORK %d%s",
3643 			 dut->infra_network_id, extra);
3644 		if (wpa_command(get_station_ifname(dut), buf) < 0) {
3645 			sigma_dut_print(dut, DUT_MSG_INFO, "Failed to select "
3646 					"network id %d on %s",
3647 					dut->infra_network_id,
3648 					get_station_ifname(dut));
3649 			ret = ERROR_SEND_STATUS;
3650 			goto done;
3651 		}
3652 	}
3653 
3654 	if (!ctrl)
3655 		return SUCCESS_SEND_STATUS;
3656 
3657 	/* Wait for connection result to be able to store server certificate
3658 	 * hash for trust root override testing
3659 	 * (dev_exec_action,ServerCertTrust). */
3660 
3661 	for (e = 0; e < 20; e++) {
3662 		const char *events[] = {
3663 			"CTRL-EVENT-EAP-PEER-CERT",
3664 			"CTRL-EVENT-EAP-TLS-CERT-ERROR",
3665 			"CTRL-EVENT-DISCONNECTED",
3666 			"CTRL-EVENT-CONNECTED",
3667 			"CTRL-EVENT-NETWORK-NOT-FOUND",
3668 			NULL
3669 		};
3670 		char buf[1024];
3671 		int res;
3672 
3673 		res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
3674 		if (res < 0) {
3675 			send_resp(dut, conn, SIGMA_COMPLETE,
3676 				  "Result,Association did not complete");
3677 			ret = STATUS_SENT_ERROR;
3678 			break;
3679 		}
3680 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Connection event: %s",
3681 				buf);
3682 
3683 		if (strstr(buf, "CTRL-EVENT-EAP-PEER-CERT") &&
3684 		    strstr(buf, " depth=0")) {
3685 			char *pos = strstr(buf, " hash=");
3686 
3687 			if (pos) {
3688 				char *end;
3689 
3690 				if (strstr(buf, " tod=1"))
3691 					tod = 1;
3692 				else if (strstr(buf, " tod=2"))
3693 					tod = 2;
3694 				else
3695 					tod = 0;
3696 				sigma_dut_print(dut, DUT_MSG_DEBUG,
3697 						"Server certificate TOD policy: %d",
3698 						tod);
3699 				dut->server_cert_tod = tod;
3700 
3701 				pos += 6;
3702 				end = strchr(pos, ' ');
3703 				if (end)
3704 					*end = '\0';
3705 				strlcpy(dut->server_cert_hash, pos,
3706 					sizeof(dut->server_cert_hash));
3707 				sigma_dut_print(dut, DUT_MSG_DEBUG,
3708 						"Server certificate hash: %s",
3709 						dut->server_cert_hash);
3710 			}
3711 		}
3712 
3713 		if (strstr(buf, "CTRL-EVENT-EAP-TLS-CERT-ERROR")) {
3714 			send_resp(dut, conn, SIGMA_COMPLETE,
3715 				  "Result,TLS server certificate validation failed");
3716 			ret = STATUS_SENT_ERROR;
3717 			break;
3718 		}
3719 
3720 		if (strstr(buf, "CTRL-EVENT-NETWORK-NOT-FOUND")) {
3721 			num_network_not_found++;
3722 
3723 			if (num_network_not_found > 2) {
3724 				send_resp(dut, conn, SIGMA_COMPLETE,
3725 					  "Result,Network not found");
3726 				ret = STATUS_SENT_ERROR;
3727 				break;
3728 			}
3729 		}
3730 
3731 		if (strstr(buf, "CTRL-EVENT-DISCONNECTED")) {
3732 			num_disconnected++;
3733 
3734 			if (num_disconnected > 2) {
3735 				send_resp(dut, conn, SIGMA_COMPLETE,
3736 					  "Result,Connection failed");
3737 				ret = STATUS_SENT_ERROR;
3738 				break;
3739 			}
3740 		}
3741 
3742 		if (strstr(buf, "CTRL-EVENT-CONNECTED")) {
3743 			if (tod >= 0) {
3744 				sigma_dut_print(dut, DUT_MSG_DEBUG,
3745 						"Network profile TOD policy update: %d -> %d",
3746 						dut->sta_tod_policy, tod);
3747 				dut->sta_tod_policy = tod;
3748 			}
3749 			if (dut->program == PROGRAM_QM) {
3750 				unsigned char iface_mac_addr[ETH_ALEN];
3751 				char ipv6[100];
3752 
3753 				if (get_hwaddr(ifname, iface_mac_addr) < 0) {
3754 					sigma_dut_print(dut, DUT_MSG_ERROR,
3755 							"%s: get_hwaddr %s failed",
3756 							__func__, ifname);
3757 					ret = ERROR_SEND_STATUS;
3758 					break;
3759 				}
3760 
3761 				convert_mac_addr_to_ipv6_lladdr(iface_mac_addr,
3762 								ipv6,
3763 								sizeof(ipv6));
3764 
3765 				if (set_ipv6_addr(dut, ipv6, "64", ifname) !=
3766 				    0) {
3767 					ret = ERROR_SEND_STATUS;
3768 					break;
3769 				}
3770 			}
3771 			break;
3772 		}
3773 	}
3774 done:
3775 	if (ctrl) {
3776 		wpa_ctrl_detach(ctrl);
3777 		wpa_ctrl_close(ctrl);
3778 	}
3779 	return ret;
3780 }
3781 
3782 
run_hs20_osu(struct sigma_dut * dut,const char * params)3783 static int run_hs20_osu(struct sigma_dut *dut, const char *params)
3784 {
3785 	char buf[500], cmd[200];
3786 	int res;
3787 
3788 	/* Use hs20-osu-client file at the current dir, if found; otherwise use
3789 	 * default path */
3790 	res = snprintf(cmd, sizeof(cmd),
3791 		       "%s -w \"%s\" -r hs20-osu-client.res %s%s -dddKt -f Logs/hs20-osu-client.txt",
3792 		       file_exists("./hs20-osu-client") ?
3793 		       "./hs20-osu-client" : "hs20-osu-client",
3794 		       sigma_wpas_ctrl,
3795 		       dut->summary_log ? "-s " : "",
3796 		       dut->summary_log ? dut->summary_log : "");
3797 	if (res < 0 || res >= (int) sizeof(cmd))
3798 		return -1;
3799 
3800 	res = snprintf(buf, sizeof(buf), "%s %s", cmd, params);
3801 	if (res < 0 || res >= (int) sizeof(buf))
3802 		return -1;
3803 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
3804 
3805 	if (system(buf) != 0) {
3806 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to run: %s", buf);
3807 		return -1;
3808 	}
3809 	sigma_dut_print(dut, DUT_MSG_DEBUG,
3810 			"Completed hs20-osu-client operation");
3811 
3812 	return 0;
3813 }
3814 
3815 
download_ppsmo(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,struct sigma_cmd * cmd)3816 static int download_ppsmo(struct sigma_dut *dut,
3817 			  struct sigma_conn *conn,
3818 			  const char *intf,
3819 			  struct sigma_cmd *cmd)
3820 {
3821 	const char *name, *path, *val;
3822 	char url[500], buf[600], fbuf[100];
3823 	char *fqdn = NULL;
3824 
3825 	name = get_param(cmd, "FileName");
3826 	path = get_param(cmd, "FilePath");
3827 	if (name == NULL || path == NULL)
3828 		return -1;
3829 
3830 	if (strcasecmp(path, "VendorSpecific") == 0) {
3831 		snprintf(url, sizeof(url), "PPS/%s", name);
3832 		sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured PPS MO "
3833 				"from the device (%s)", url);
3834 		if (!file_exists(url)) {
3835 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
3836 				  "PPS MO file does not exist");
3837 			return 0;
3838 		}
3839 		snprintf(buf, sizeof(buf), "cp %s pps-tnds.xml", url);
3840 		if (system(buf) != 0) {
3841 			send_resp(dut, conn, SIGMA_ERROR,
3842 				  "errorCode,Failed to copy PPS MO");
3843 			return 0;
3844 		}
3845 	} else if (strncasecmp(path, "http:", 5) != 0 &&
3846 		   strncasecmp(path, "https:", 6) != 0) {
3847 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
3848 			  "Unsupported FilePath value");
3849 		return 0;
3850 	} else {
3851 		snprintf(url, sizeof(url), "%s/%s", path, name);
3852 		sigma_dut_print(dut, DUT_MSG_INFO, "Downloading PPS MO from %s",
3853 				url);
3854 		snprintf(buf, sizeof(buf), "wget -T 10 -t 3 -O pps-tnds.xml '%s'", url);
3855 		remove("pps-tnds.xml");
3856 		if (system(buf) != 0) {
3857 			send_resp(dut, conn, SIGMA_ERROR,
3858 				  "errorCode,Failed to download PPS MO");
3859 			return 0;
3860 		}
3861 	}
3862 
3863 	if (run_hs20_osu(dut, "from_tnds pps-tnds.xml pps.xml") < 0) {
3864 		send_resp(dut, conn, SIGMA_ERROR,
3865 			  "errorCode,Failed to parse downloaded PPSMO");
3866 		return 0;
3867 	}
3868 	unlink("pps-tnds.xml");
3869 
3870 	val = get_param(cmd, "managementTreeURI");
3871 	if (val) {
3872 		const char *pos, *end;
3873 		sigma_dut_print(dut, DUT_MSG_DEBUG, "managementTreeURI: %s",
3874 				val);
3875 		if (strncmp(val, "./Wi-Fi/", 8) != 0) {
3876 			send_resp(dut, conn, SIGMA_ERROR,
3877 				  "errorCode,Invalid managementTreeURI prefix");
3878 			return 0;
3879 		}
3880 		pos = val + 8;
3881 		end = strchr(pos, '/');
3882 		if (end == NULL ||
3883 		    strcmp(end, "/PerProviderSubscription") != 0) {
3884 			send_resp(dut, conn, SIGMA_ERROR,
3885 				  "errorCode,Invalid managementTreeURI postfix");
3886 			return 0;
3887 		}
3888 		if (end - pos >= (int) sizeof(fbuf)) {
3889 			send_resp(dut, conn, SIGMA_ERROR,
3890 				  "errorCode,Too long FQDN in managementTreeURI");
3891 			return 0;
3892 		}
3893 		memcpy(fbuf, pos, end - pos);
3894 		fbuf[end - pos] = '\0';
3895 		fqdn = fbuf;
3896 		sigma_dut_print(dut, DUT_MSG_INFO,
3897 				"FQDN from managementTreeURI: %s", fqdn);
3898 	} else if (run_hs20_osu(dut, "get_fqdn pps.xml") == 0) {
3899 		FILE *f = fopen("pps-fqdn", "r");
3900 		if (f) {
3901 			if (fgets(fbuf, sizeof(fbuf), f)) {
3902 				fbuf[sizeof(fbuf) - 1] = '\0';
3903 				fqdn = fbuf;
3904 				sigma_dut_print(dut, DUT_MSG_DEBUG,
3905 						"Use FQDN %s", fqdn);
3906 			}
3907 			fclose(f);
3908 		}
3909 	}
3910 
3911 	if (fqdn == NULL) {
3912 		send_resp(dut, conn, SIGMA_ERROR,
3913 			  "errorCode,No FQDN specified");
3914 		return 0;
3915 	}
3916 
3917 	mkdir("SP", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
3918 	snprintf(buf, sizeof(buf), "SP/%s", fqdn);
3919 	mkdir(buf, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
3920 
3921 	snprintf(buf, sizeof(buf), "SP/%s/pps.xml", fqdn);
3922 	if (rename("pps.xml", buf) < 0) {
3923 		send_resp(dut, conn, SIGMA_ERROR,
3924 			  "errorCode,Could not move PPS MO");
3925 		return 0;
3926 	}
3927 
3928 	if (strcasecmp(path, "VendorSpecific") == 0) {
3929 		snprintf(buf, sizeof(buf), "cp Certs/ca.pem SP/%s/ca.pem",
3930 			 fqdn);
3931 		if (system(buf)) {
3932 			send_resp(dut, conn, SIGMA_ERROR,
3933 				  "errorCode,Failed to copy OSU CA cert");
3934 			return 0;
3935 		}
3936 
3937 		snprintf(buf, sizeof(buf),
3938 			 "cp Certs/aaa-ca.pem SP/%s/aaa-ca.pem",
3939 			 fqdn);
3940 		if (system(buf)) {
3941 			send_resp(dut, conn, SIGMA_ERROR,
3942 				  "errorCode,Failed to copy AAA CA cert");
3943 			return 0;
3944 		}
3945 	} else {
3946 		snprintf(buf, sizeof(buf),
3947 			 "dl_osu_ca SP/%s/pps.xml SP/%s/ca.pem",
3948 			 fqdn, fqdn);
3949 		if (run_hs20_osu(dut, buf) < 0) {
3950 			send_resp(dut, conn, SIGMA_ERROR,
3951 				  "errorCode,Failed to download OSU CA cert");
3952 			return 0;
3953 		}
3954 
3955 		snprintf(buf, sizeof(buf),
3956 			 "dl_aaa_ca SP/%s/pps.xml SP/%s/aaa-ca.pem",
3957 			 fqdn, fqdn);
3958 		if (run_hs20_osu(dut, buf) < 0) {
3959 			sigma_dut_print(dut, DUT_MSG_INFO,
3960 					"Failed to download AAA CA cert");
3961 		}
3962 	}
3963 
3964 	if (file_exists("next-client-cert.pem")) {
3965 		snprintf(buf, sizeof(buf), "SP/%s/client-cert.pem", fqdn);
3966 		if (rename("next-client-cert.pem", buf) < 0) {
3967 			send_resp(dut, conn, SIGMA_ERROR,
3968 				  "errorCode,Could not move client certificate");
3969 			return 0;
3970 		}
3971 	}
3972 
3973 	if (file_exists("next-client-key.pem")) {
3974 		snprintf(buf, sizeof(buf), "SP/%s/client-key.pem", fqdn);
3975 		if (rename("next-client-key.pem", buf) < 0) {
3976 			send_resp(dut, conn, SIGMA_ERROR,
3977 				  "errorCode,Could not move client key");
3978 			return 0;
3979 		}
3980 	}
3981 
3982 	snprintf(buf, sizeof(buf), "set_pps SP/%s/pps.xml", fqdn);
3983 	if (run_hs20_osu(dut, buf) < 0) {
3984 		send_resp(dut, conn, SIGMA_ERROR,
3985 			  "errorCode,Failed to configure credential from "
3986 			  "PPSMO");
3987 		return 0;
3988 	}
3989 
3990 	return 1;
3991 }
3992 
3993 
download_cert(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,struct sigma_cmd * cmd)3994 static int download_cert(struct sigma_dut *dut,
3995 			 struct sigma_conn *conn,
3996 			 const char *intf,
3997 			 struct sigma_cmd *cmd)
3998 {
3999 	const char *name, *path;
4000 	char url[500], buf[600];
4001 
4002 	name = get_param(cmd, "FileName");
4003 	path = get_param(cmd, "FilePath");
4004 	if (name == NULL || path == NULL)
4005 		return -1;
4006 
4007 	if (strcasecmp(path, "VendorSpecific") == 0) {
4008 		snprintf(url, sizeof(url), "Certs/%s-cert.pem", name);
4009 		sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured client "
4010 				"certificate from the device (%s)", url);
4011 		if (!file_exists(url)) {
4012 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
4013 				  "certificate file does not exist");
4014 			return 0;
4015 		}
4016 		snprintf(buf, sizeof(buf), "cp %s next-client-cert.pem", url);
4017 		if (system(buf) != 0) {
4018 			send_resp(dut, conn, SIGMA_ERROR,
4019 				  "errorCode,Failed to copy client "
4020 				  "certificate");
4021 			return 0;
4022 		}
4023 
4024 		snprintf(url, sizeof(url), "Certs/%s-key.pem", name);
4025 		sigma_dut_print(dut, DUT_MSG_INFO, "Use pre-configured client "
4026 				"private key from the device (%s)", url);
4027 		if (!file_exists(url)) {
4028 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested "
4029 				  "private key file does not exist");
4030 			return 0;
4031 		}
4032 		snprintf(buf, sizeof(buf), "cp %s next-client-key.pem", url);
4033 		if (system(buf) != 0) {
4034 			send_resp(dut, conn, SIGMA_ERROR,
4035 				  "errorCode,Failed to copy client key");
4036 			return 0;
4037 		}
4038 	} else if (strncasecmp(path, "http:", 5) != 0 &&
4039 		   strncasecmp(path, "https:", 6) != 0) {
4040 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
4041 			  "Unsupported FilePath value");
4042 		return 0;
4043 	} else {
4044 		snprintf(url, sizeof(url), "%s/%s.pem", path, name);
4045 		sigma_dut_print(dut, DUT_MSG_INFO, "Downloading client "
4046 				"certificate/key from %s", url);
4047 		snprintf(buf, sizeof(buf),
4048 			 "wget -T 10 -t 3 -O next-client-cert.pem '%s'", url);
4049 		if (system(buf) != 0) {
4050 			send_resp(dut, conn, SIGMA_ERROR,
4051 				  "errorCode,Failed to download client "
4052 				  "certificate");
4053 			return 0;
4054 		}
4055 
4056 		if (system("cp next-client-cert.pem next-client-key.pem") != 0)
4057 		{
4058 			send_resp(dut, conn, SIGMA_ERROR,
4059 				  "errorCode,Failed to copy client key");
4060 			return 0;
4061 		}
4062 	}
4063 
4064 	return 1;
4065 }
4066 
4067 
cmd_sta_preset_testparameters_60ghz(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)4068 static int cmd_sta_preset_testparameters_60ghz(struct sigma_dut *dut,
4069 					       struct sigma_conn *conn,
4070 					       struct sigma_cmd *cmd)
4071 {
4072 	const char *val;
4073 	const char *intf = get_param(cmd, "interface");
4074 
4075 	if (!intf)
4076 		return -1;
4077 
4078 	val = get_param(cmd, "WscIEFragment");
4079 	if (val && strcasecmp(val, "enable") == 0) {
4080 		sigma_dut_print(dut, DUT_MSG_DEBUG,
4081 				"Enable WSC IE fragmentation");
4082 
4083 		dut->wsc_fragment = 1;
4084 		/* set long attributes to force fragmentation */
4085 		if (wpa_command(intf, "SET device_name "
4086 				WPS_LONG_DEVICE_NAME) < 0)
4087 			return -2;
4088 		if (wpa_command(intf, "SET manufacturer "
4089 				WPS_LONG_MANUFACTURER) < 0)
4090 			return -2;
4091 		if (wpa_command(intf, "SET model_name "
4092 				WPS_LONG_MODEL_NAME) < 0)
4093 			return -2;
4094 		if (wpa_command(intf, "SET model_number "
4095 				WPS_LONG_MODEL_NUMBER) < 0)
4096 			return -2;
4097 		if (wpa_command(intf, "SET serial_number "
4098 				WPS_LONG_SERIAL_NUMBER) < 0)
4099 			return -2;
4100 	}
4101 
4102 	val = get_param(cmd, "RSN_IE");
4103 	if (val) {
4104 		if (strcasecmp(val, "disable") == 0)
4105 			dut->force_rsn_ie = FORCE_RSN_IE_REMOVE;
4106 		else if (strcasecmp(val, "enable") == 0)
4107 			dut->force_rsn_ie = FORCE_RSN_IE_ADD;
4108 	}
4109 
4110 	val = get_param(cmd, "WpsVersion");
4111 	if (val)
4112 		dut->wps_forced_version = get_wps_forced_version(dut, val);
4113 
4114 	val = get_param(cmd, "WscEAPFragment");
4115 	if (val && strcasecmp(val, "enable") == 0)
4116 		dut->eap_fragment = 1;
4117 
4118 	return 1;
4119 }
4120 
4121 
cmd_sta_preset_testparameters_hs2_r2(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,struct sigma_cmd * cmd)4122 static int cmd_sta_preset_testparameters_hs2_r2(struct sigma_dut *dut,
4123 						struct sigma_conn *conn,
4124 						const char *intf,
4125 						struct sigma_cmd *cmd)
4126 {
4127 	const char *val;
4128 
4129 	val = get_param(cmd, "FileType");
4130 	if (val && strcasecmp(val, "PPSMO") == 0)
4131 		return download_ppsmo(dut, conn, intf, cmd);
4132 	if (val && strcasecmp(val, "CERT") == 0)
4133 		return download_cert(dut, conn, intf, cmd);
4134 	if (val) {
4135 		send_resp(dut, conn, SIGMA_ERROR,
4136 			  "ErrorCode,Unsupported FileType");
4137 		return 0;
4138 	}
4139 
4140 	return 1;
4141 }
4142 
4143 
cmd_sta_preset_testparameters_oce(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,struct sigma_cmd * cmd)4144 static int cmd_sta_preset_testparameters_oce(struct sigma_dut *dut,
4145 					     struct sigma_conn *conn,
4146 					     const char *intf,
4147 					     struct sigma_cmd *cmd)
4148 {
4149 	const char *val;
4150 	char buf[1000];
4151 	char text[20];
4152 	unsigned char addr[ETH_ALEN];
4153 
4154 	val = get_param(cmd, "OCESupport");
4155 	if (val && strcasecmp(val, "Disable") == 0) {
4156 		if (wpa_command(intf, "SET oce 0") < 0) {
4157 			send_resp(dut, conn, SIGMA_ERROR,
4158 				  "ErrorCode,Failed to disable OCE");
4159 			return 0;
4160 		}
4161 	} else if (val && strcasecmp(val, "Enable") == 0) {
4162 		if (wpa_command(intf, "SET oce 1") < 0) {
4163 			send_resp(dut, conn, SIGMA_ERROR,
4164 				  "ErrorCode,Failed to enable OCE");
4165 			return 0;
4166 		}
4167 	}
4168 
4169 	val = get_param(cmd, "FILScap");
4170 	if (val && (atoi(val) == 1)) {
4171 		if (wpa_command(intf, "SET disable_fils 0") < 0) {
4172 			send_resp(dut, conn, SIGMA_ERROR,
4173 				  "ErrorCode,Failed to enable FILS");
4174 			return 0;
4175 		}
4176 	} else if (val && (atoi(val) == 0)) {
4177 		if (wpa_command(intf, "SET disable_fils 1") < 0) {
4178 			send_resp(dut, conn, SIGMA_ERROR,
4179 				  "ErrorCode,Failed to disable FILS");
4180 			return 0;
4181 		}
4182 	}
4183 
4184 	val = get_param(cmd, "FILSHLP");
4185 	if (val && strcasecmp(val, "Enable") == 0) {
4186 		if (get_wpa_status(get_station_ifname(dut), "address", text,
4187 				   sizeof(text)) < 0)
4188 			return -2;
4189 		hwaddr_aton(text, addr);
4190 		snprintf(buf, sizeof(buf),
4191 			 "FILS_HLP_REQ_ADD ff:ff:ff:ff:ff:ff "
4192 			 "080045100140000040004011399e00000000ffffffff00440043"
4193 			 "012cb30001010600fd4f46410000000000000000000000000000"
4194 			 "000000000000"
4195 			 "%02x%02x%02x%02x%02x%02x"
4196 			 "0000000000000000000000000000000000000000000000000000"
4197 			 "0000000000000000000000000000000000000000000000000000"
4198 			 "0000000000000000000000000000000000000000000000000000"
4199 			 "0000000000000000000000000000000000000000000000000000"
4200 			 "0000000000000000000000000000000000000000000000000000"
4201 			 "0000000000000000000000000000000000000000000000000000"
4202 			 "0000000000000000000000000000000000000000000000000000"
4203 			 "0000000000000000000000000000000000000000638253633501"
4204 			 "013d0701000af549d29b390205dc3c12616e64726f69642d6468"
4205 			 "63702d382e302e30370a0103060f1a1c333a3b2b5000ff00",
4206 			 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
4207 		if (wpa_command(intf, buf)) {
4208 			send_resp(dut, conn, SIGMA_ERROR,
4209 				  "ErrorCode,Failed to add HLP");
4210 			return 0;
4211 		}
4212 		dut->fils_hlp = 1;
4213 	}
4214 
4215 	return 1;
4216 }
4217 
4218 
ath_sta_set_noack(struct sigma_dut * dut,const char * intf,const char * val)4219 static void ath_sta_set_noack(struct sigma_dut *dut, const char *intf,
4220 			      const char *val)
4221 {
4222 	int counter = 0;
4223 	char token[50];
4224 	char *result;
4225 	char *saveptr;
4226 
4227 	strlcpy(token, val, sizeof(token));
4228 	token[sizeof(token) - 1] = '\0';
4229 	result = strtok_r(token, ":", &saveptr);
4230 	while (result) {
4231 		if (strcmp(result, "disable") == 0)
4232 			run_iwpriv(dut, intf, "noackpolicy %d 1 0", counter);
4233 		else
4234 			run_iwpriv(dut, intf, "noackpolicy %d 1 1", counter);
4235 		result = strtok_r(NULL, ":", &saveptr);
4236 		counter++;
4237 	}
4238 }
4239 
4240 
ath_sta_set_rts(struct sigma_dut * dut,const char * intf,const char * val)4241 static void ath_sta_set_rts(struct sigma_dut *dut, const char *intf,
4242 			    const char *val)
4243 {
4244 	char buf[100];
4245 
4246 	snprintf(buf, sizeof(buf), "iwconfig %s rts %s", intf, val);
4247 	if (system(buf) != 0) {
4248 		sigma_dut_print(dut, DUT_MSG_ERROR, "iwconfig RTS failed");
4249 	}
4250 }
4251 
4252 
ath_sta_set_wmm(struct sigma_dut * dut,const char * intf,const char * val)4253 static void ath_sta_set_wmm(struct sigma_dut *dut, const char *intf,
4254 			    const char *val)
4255 {
4256 	if (strcasecmp(val, "off") == 0) {
4257 		run_iwpriv(dut, intf, "wmm 0");
4258 	}
4259 }
4260 
4261 
wcn_sta_set_wmm(struct sigma_dut * dut,const char * intf,const char * val)4262 static int wcn_sta_set_wmm(struct sigma_dut *dut, const char *intf,
4263 			   const char *val)
4264 {
4265 #ifdef NL80211_SUPPORT
4266 	int wmmenable = 1;
4267 
4268 	if (val &&
4269 	    (strcasecmp(val, "off") == 0 || strcmp(val, "0") == 0))
4270 		wmmenable = 0;
4271 
4272 	return wcn_wifi_test_config_set_u8(
4273 		dut, intf, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE,
4274 		wmmenable);
4275 #else /* NL80211_SUPPORT */
4276 	sigma_dut_print(dut, DUT_MSG_ERROR,
4277 			"WMM cannot be changed without NL80211_SUPPORT defined");
4278 	return -1;
4279 #endif /* NL80211_SUPPORT */
4280 }
4281 
4282 
ath_sta_set_sgi(struct sigma_dut * dut,const char * intf,const char * val)4283 static void ath_sta_set_sgi(struct sigma_dut *dut, const char *intf,
4284 			    const char *val)
4285 {
4286 	int sgi20;
4287 
4288 	sgi20 = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
4289 
4290 	run_iwpriv(dut, intf, "shortgi %d", sgi20);
4291 }
4292 
4293 
ath_sta_set_11nrates(struct sigma_dut * dut,const char * intf,const char * val)4294 static void ath_sta_set_11nrates(struct sigma_dut *dut, const char *intf,
4295 				 const char *val)
4296 {
4297 	int rate_code, v;
4298 
4299 	/* Disable Tx Beam forming when using a fixed rate */
4300 	ath_disable_txbf(dut, intf);
4301 
4302 	v = atoi(val);
4303 	if (v < 0 || v > 32) {
4304 		sigma_dut_print(dut, DUT_MSG_ERROR,
4305 				"Invalid Fixed MCS rate: %d", v);
4306 		return;
4307 	}
4308 	rate_code = 0x80 + v;
4309 
4310 	run_iwpriv(dut, intf, "set11NRates 0x%x", rate_code);
4311 
4312 	/* Channel width gets messed up, fix this */
4313 	run_iwpriv(dut, intf, "chwidth %d", dut->chwidth);
4314 }
4315 
4316 
iwpriv_sta_set_amsdu(struct sigma_dut * dut,const char * intf,const char * val)4317 static void iwpriv_sta_set_amsdu(struct sigma_dut *dut, const char *intf,
4318 				 const char *val)
4319 {
4320 	char buf[60];
4321 	int ret;
4322 
4323 	if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)
4324 		snprintf(buf, sizeof(buf), "iwpriv %s amsdu 2", intf);
4325 	else
4326 		snprintf(buf, sizeof(buf), "iwpriv %s amsdu 1", intf);
4327 
4328 	ret = system(buf);
4329 #ifdef NL80211_SUPPORT
4330 	if (ret) {
4331 		int value = (strcasecmp(val, "Enable") == 0) ? 2 : 1;
4332 
4333 		ret = sta_config_params(dut, intf, STA_SET_TX_MSDU, value);
4334 		ret |= sta_config_params(dut, intf, STA_SET_RX_MSDU, value);
4335 	}
4336 #endif /* NL80211_SUPPORT */
4337 	if (ret)
4338 		sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv amsdu failed");
4339 }
4340 
4341 
iwpriv_sta_set_ampdu(struct sigma_dut * dut,const char * intf,int ampdu)4342 static int iwpriv_sta_set_ampdu(struct sigma_dut *dut, const char *intf,
4343 				int ampdu)
4344 {
4345 	char buf[60];
4346 	int maxaggregation = 63;
4347 
4348 	if (ampdu)
4349 		ampdu = maxaggregation;
4350 	snprintf(buf, sizeof(buf), "iwpriv %s ampdu %d", intf, ampdu);
4351 	if (system(buf) != 0) {
4352 		sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv ampdu failed");
4353 		return -1;
4354 	}
4355 
4356 	return 0;
4357 }
4358 
4359 
ath_sta_set_stbc(struct sigma_dut * dut,const char * intf,const char * val)4360 static void ath_sta_set_stbc(struct sigma_dut *dut, const char *intf,
4361 			     const char *val)
4362 {
4363 	run_iwpriv(dut, intf, "tx_stbc %s", val);
4364 	run_iwpriv(dut, intf, "rx_stbc %s", val);
4365 }
4366 
4367 
wcn_sta_set_cts_width(struct sigma_dut * dut,const char * intf,const char * val)4368 static int wcn_sta_set_cts_width(struct sigma_dut *dut, const char *intf,
4369 				  const char *val)
4370 {
4371 	char buf[60];
4372 
4373 	if (strcmp(val, "160") == 0) {
4374 		snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 5", intf);
4375 	} else if (strcmp(val, "80") == 0) {
4376 		snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 3", intf);
4377 	} else if (strcmp(val, "40") == 0) {
4378 		snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 2", intf);
4379 	} else if (strcmp(val, "20") == 0) {
4380 		snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 1", intf);
4381 	} else if (strcasecmp(val, "Auto") == 0) {
4382 		buf[0] = '\0';
4383 	} else {
4384 		sigma_dut_print(dut, DUT_MSG_ERROR,
4385 				"WIDTH/CTS_WIDTH value not supported");
4386 		return -1;
4387 	}
4388 
4389 	if (buf[0] != '\0' && system(buf) != 0) {
4390 		sigma_dut_print(dut, DUT_MSG_ERROR,
4391 				"Failed to set WIDTH/CTS_WIDTH");
4392 		return -1;
4393 	}
4394 
4395 	return 0;
4396 }
4397 
4398 
ath_set_width(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,const char * val)4399 int ath_set_width(struct sigma_dut *dut, struct sigma_conn *conn,
4400 		  const char *intf, const char *val)
4401 {
4402 	if (strcasecmp(val, "Auto") == 0) {
4403 		run_iwpriv(dut, intf, "chwidth 0");
4404 		dut->chwidth = 0;
4405 	} else if (strcasecmp(val, "20") == 0) {
4406 		run_iwpriv(dut, intf, "chwidth 0");
4407 		dut->chwidth = 0;
4408 	} else if (strcasecmp(val, "40") == 0) {
4409 		run_iwpriv(dut, intf, "chwidth 1");
4410 		dut->chwidth = 1;
4411 	} else if (strcasecmp(val, "80") == 0) {
4412 		run_iwpriv(dut, intf, "chwidth 2");
4413 		dut->chwidth = 2;
4414 	} else if (strcasecmp(val, "160") == 0) {
4415 		run_iwpriv(dut, intf, "chwidth 3");
4416 		dut->chwidth = 3;
4417 	} else {
4418 		send_resp(dut, conn, SIGMA_ERROR,
4419 			  "ErrorCode,WIDTH not supported");
4420 		return -1;
4421 	}
4422 
4423 	return 0;
4424 }
4425 
4426 
wcn_sta_set_sp_stream(struct sigma_dut * dut,const char * intf,const char * val)4427 static int wcn_sta_set_sp_stream(struct sigma_dut *dut, const char *intf,
4428 				 const char *val)
4429 {
4430 	char buf[60];
4431 	int sta_nss;
4432 
4433 	if (strcmp(val, "1SS") == 0 || strcmp(val, "1") == 0) {
4434 		snprintf(buf, sizeof(buf), "iwpriv %s nss 1", intf);
4435 		sta_nss = 1;
4436 	} else if (strcmp(val, "2SS") == 0 || strcmp(val, "2") == 0) {
4437 		snprintf(buf, sizeof(buf), "iwpriv %s nss 2", intf);
4438 		sta_nss = 2;
4439 	} else {
4440 		sigma_dut_print(dut, DUT_MSG_ERROR,
4441 				"SP_STREAM value not supported");
4442 		return -1;
4443 	}
4444 
4445 	if (system(buf) != 0) {
4446 		sigma_dut_print(dut, DUT_MSG_ERROR,
4447 				"Failed to set SP_STREAM");
4448 		return -1;
4449 	}
4450 
4451 	dut->sta_nss = sta_nss;
4452 
4453 	return 0;
4454 }
4455 
4456 
wcn_sta_set_stbc(struct sigma_dut * dut,const char * intf,const char * val)4457 static void wcn_sta_set_stbc(struct sigma_dut *dut, const char *intf,
4458 			     const char *val)
4459 {
4460 	char buf[60];
4461 	int ret;
4462 
4463 	snprintf(buf, sizeof(buf), "iwpriv %s tx_stbc %s", intf, val);
4464 	ret = system(buf);
4465 #ifdef NL80211_SUPPORT
4466 	if (ret)
4467 		ret = sta_config_params(dut, intf, STA_SET_TX_STBC,
4468 					strcmp(val, "0") == 0 ? 0 : 1);
4469 #endif /* NL80211_SUPPORT */
4470 	if (ret)
4471 		sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv tx_stbc failed");
4472 
4473 	snprintf(buf, sizeof(buf), "iwpriv %s rx_stbc %s", intf, val);
4474 	ret = system(buf);
4475 #ifdef NL80211_SUPPORT
4476 	if (ret)
4477 		ret = sta_config_params(dut, intf, STA_SET_RX_STBC,
4478 					strcmp(val, "0") == 0 ? 0 : 1);
4479 #endif /* NL80211_SUPPORT */
4480 	if (ret)
4481 		sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv rx_stbc failed");
4482 }
4483 
4484 
mbo_set_cellular_data_capa(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,int capa)4485 static int mbo_set_cellular_data_capa(struct sigma_dut *dut,
4486 				      struct sigma_conn *conn,
4487 				      const char *intf, int capa)
4488 {
4489 	char buf[32];
4490 
4491 	if (capa > 0 && capa < 4) {
4492 		snprintf(buf, sizeof(buf), "SET mbo_cell_capa %d", capa);
4493 		if (wpa_command(intf, buf) < 0) {
4494 			send_resp(dut, conn, SIGMA_ERROR,
4495 				  "ErrorCode, Failed to set cellular data capability");
4496 			return 0;
4497 		}
4498 		return 1;
4499 	}
4500 
4501 	sigma_dut_print(dut, DUT_MSG_ERROR,
4502 			"Invalid Cellular data capability: %d", capa);
4503 	send_resp(dut, conn, SIGMA_INVALID,
4504 		  "ErrorCode,Invalid cellular data capability");
4505 	return 0;
4506 }
4507 
4508 
mbo_set_roaming(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,const char * val)4509 static int mbo_set_roaming(struct sigma_dut *dut, struct sigma_conn *conn,
4510 			   const char *intf, const char *val)
4511 {
4512 	if (strcasecmp(val, "Disable") == 0) {
4513 		if (wpa_command(intf, "SET roaming 0") < 0) {
4514 			send_resp(dut, conn, SIGMA_ERROR,
4515 				  "ErrorCode,Failed to disable roaming");
4516 			return 0;
4517 		}
4518 		return 1;
4519 	}
4520 
4521 	if (strcasecmp(val, "Enable") == 0) {
4522 		if (wpa_command(intf, "SET roaming 1") < 0) {
4523 			send_resp(dut, conn, SIGMA_ERROR,
4524 				  "ErrorCode,Failed to enable roaming");
4525 			return 0;
4526 		}
4527 		return 1;
4528 	}
4529 
4530 	sigma_dut_print(dut, DUT_MSG_ERROR,
4531 			"Invalid value provided for roaming: %s", val);
4532 	send_resp(dut, conn, SIGMA_INVALID,
4533 		  "ErrorCode,Unknown value provided for Roaming");
4534 	return 0;
4535 }
4536 
4537 
mbo_set_assoc_disallow(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,const char * val)4538 static int mbo_set_assoc_disallow(struct sigma_dut *dut,
4539 				  struct sigma_conn *conn,
4540 				  const char *intf, const char *val)
4541 {
4542 	if (strcasecmp(val, "Disable") == 0) {
4543 		if (wpa_command(intf, "SET ignore_assoc_disallow 1") < 0) {
4544 			send_resp(dut, conn, SIGMA_ERROR,
4545 				  "ErrorCode,Failed to disable Assoc_disallow");
4546 			return 0;
4547 		}
4548 		return 1;
4549 	}
4550 
4551 	if (strcasecmp(val, "Enable") == 0) {
4552 		if (wpa_command(intf, "SET ignore_assoc_disallow 0") < 0) {
4553 			send_resp(dut, conn, SIGMA_ERROR,
4554 				  "ErrorCode,Failed to enable Assoc_disallow");
4555 			return 0;
4556 		}
4557 		return 1;
4558 	}
4559 
4560 	sigma_dut_print(dut, DUT_MSG_ERROR,
4561 			"Invalid value provided for Assoc_disallow: %s", val);
4562 	send_resp(dut, conn, SIGMA_INVALID,
4563 		  "ErrorCode,Unknown value provided for Assoc_disallow");
4564 	return 0;
4565 }
4566 
4567 
mbo_set_bss_trans_req(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,const char * val)4568 static int mbo_set_bss_trans_req(struct sigma_dut *dut, struct sigma_conn *conn,
4569 				 const char *intf, const char *val)
4570 {
4571 	if (strcasecmp(val, "Reject") == 0) {
4572 		if (wpa_command(intf, "SET reject_btm_req_reason 1") < 0) {
4573 			send_resp(dut, conn, SIGMA_ERROR,
4574 				  "ErrorCode,Failed to Reject BTM Request");
4575 			return 0;
4576 		}
4577 		return 1;
4578 	}
4579 
4580 	if (strcasecmp(val, "Accept") == 0) {
4581 		if (wpa_command(intf, "SET reject_btm_req_reason 0") < 0) {
4582 			send_resp(dut, conn, SIGMA_ERROR,
4583 				  "ErrorCode,Failed to Accept BTM Request");
4584 			return 0;
4585 		}
4586 		return 1;
4587 	}
4588 
4589 	sigma_dut_print(dut, DUT_MSG_ERROR,
4590 			"Invalid value provided for BSS_Transition: %s", val);
4591 	send_resp(dut, conn, SIGMA_INVALID,
4592 		  "ErrorCode,Unknown value provided for BSS_Transition");
4593 	return 0;
4594 }
4595 
4596 
mbo_set_non_pref_ch_list(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,struct sigma_cmd * cmd)4597 static int mbo_set_non_pref_ch_list(struct sigma_dut *dut,
4598 				    struct sigma_conn *conn,
4599 				    const char *intf,
4600 				    struct sigma_cmd *cmd)
4601 {
4602 	const char *ch, *pref, *op_class, *reason;
4603 	char buf[120];
4604 	int len, ret;
4605 
4606 	pref = get_param(cmd, "Ch_Pref");
4607 	if (!pref)
4608 		return 1;
4609 
4610 	if (strcasecmp(pref, "clear") == 0) {
4611 		free(dut->non_pref_ch_list);
4612 		dut->non_pref_ch_list = NULL;
4613 	} else {
4614 		op_class = get_param(cmd, "Ch_Op_Class");
4615 		if (!op_class) {
4616 			send_resp(dut, conn, SIGMA_INVALID,
4617 				  "ErrorCode,Ch_Op_Class not provided");
4618 			return 0;
4619 		}
4620 
4621 		ch = get_param(cmd, "Ch_Pref_Num");
4622 		if (!ch) {
4623 			send_resp(dut, conn, SIGMA_INVALID,
4624 				  "ErrorCode,Ch_Pref_Num not provided");
4625 			return 0;
4626 		}
4627 
4628 		reason = get_param(cmd, "Ch_Reason_Code");
4629 		if (!reason) {
4630 			send_resp(dut, conn, SIGMA_INVALID,
4631 				  "ErrorCode,Ch_Reason_Code not provided");
4632 			return 0;
4633 		}
4634 
4635 		if (!dut->non_pref_ch_list) {
4636 			dut->non_pref_ch_list =
4637 				calloc(1, NON_PREF_CH_LIST_SIZE);
4638 			if (!dut->non_pref_ch_list) {
4639 				send_resp(dut, conn, SIGMA_ERROR,
4640 					  "ErrorCode,Failed to allocate memory for non_pref_ch_list");
4641 				return 0;
4642 			}
4643 		}
4644 		len = strlen(dut->non_pref_ch_list);
4645 		ret = snprintf(dut->non_pref_ch_list + len,
4646 			       NON_PREF_CH_LIST_SIZE - len,
4647 			       " %s:%s:%s:%s", op_class, ch, pref, reason);
4648 		if (ret > 0 && ret < NON_PREF_CH_LIST_SIZE - len) {
4649 			sigma_dut_print(dut, DUT_MSG_DEBUG, "non_pref_list: %s",
4650 					dut->non_pref_ch_list);
4651 		} else {
4652 			sigma_dut_print(dut, DUT_MSG_ERROR,
4653 					"snprintf failed for non_pref_list, ret = %d",
4654 					ret);
4655 			send_resp(dut, conn, SIGMA_ERROR,
4656 				  "ErrorCode,snprintf failed");
4657 			free(dut->non_pref_ch_list);
4658 			dut->non_pref_ch_list = NULL;
4659 			return 0;
4660 		}
4661 	}
4662 
4663 	ret = snprintf(buf, sizeof(buf), "SET non_pref_chan%s",
4664 		       dut->non_pref_ch_list ? dut->non_pref_ch_list : " ");
4665 	if (ret < 0 || ret >= (int) sizeof(buf)) {
4666 		sigma_dut_print(dut, DUT_MSG_DEBUG,
4667 				"snprintf failed for set non_pref_chan, ret: %d",
4668 				ret);
4669 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,snprint failed");
4670 		return 0;
4671 	}
4672 
4673 	if (wpa_command(intf, buf) < 0) {
4674 		send_resp(dut, conn, SIGMA_ERROR,
4675 			  "ErrorCode,Failed to set non-preferred channel list");
4676 		return 0;
4677 	}
4678 
4679 	return 1;
4680 }
4681 
4682 
4683 #ifdef NL80211_SUPPORT
4684 
sta_set_he_htc_supp(struct sigma_dut * dut,const char * intf,uint8_t cfg)4685 static int sta_set_he_htc_supp(struct sigma_dut *dut, const char *intf,
4686 			       uint8_t cfg)
4687 {
4688 	return wcn_wifi_test_config_set_u8(
4689 		dut, intf, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP,
4690 		cfg);
4691 }
4692 
4693 
sta_set_he_fragmentation(struct sigma_dut * dut,const char * intf,enum he_fragmentation_val frag)4694 static int sta_set_he_fragmentation(struct sigma_dut *dut, const char *intf,
4695 				    enum he_fragmentation_val frag)
4696 {
4697 	return wcn_wifi_test_config_set_u8(
4698 		dut, intf,
4699 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION, frag);
4700 }
4701 
4702 
wcn_set_he_ltf(struct sigma_dut * dut,const char * intf,enum qca_wlan_he_ltf_cfg ltf)4703 int wcn_set_he_ltf(struct sigma_dut *dut, const char *intf,
4704 		   enum qca_wlan_he_ltf_cfg ltf)
4705 {
4706 	return wcn_wifi_test_config_set_u8(
4707 		dut, intf, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF, ltf);
4708 }
4709 
4710 
nlvendor_sta_set_noack(struct sigma_dut * dut,const char * intf,int noack,enum qca_wlan_ac_type ac)4711 static int nlvendor_sta_set_noack(struct sigma_dut *dut, const char *intf,
4712 				  int noack, enum qca_wlan_ac_type ac)
4713 {
4714 	struct nl_msg *msg;
4715 	int ret = 0;
4716 	struct nlattr *params;
4717 	int ifindex;
4718 
4719 	ifindex = if_nametoindex(intf);
4720 	if (ifindex == 0) {
4721 		sigma_dut_print(dut, DUT_MSG_ERROR,
4722 				"%s: Index for interface %s failed",
4723 				__func__, intf);
4724 		return -1;
4725 	}
4726 
4727 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
4728 				    NL80211_CMD_VENDOR)) ||
4729 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
4730 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
4731 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
4732 			QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION) ||
4733 	    !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
4734 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK,
4735 		       noack) ||
4736 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC,
4737 		       ac)) {
4738 		sigma_dut_print(dut, DUT_MSG_ERROR,
4739 				"%s: err in adding vendor_cmd and vendor_data",
4740 				__func__);
4741 		nlmsg_free(msg);
4742 		return -1;
4743 	}
4744 	nla_nest_end(msg, params);
4745 
4746 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
4747 	if (ret) {
4748 		sigma_dut_print(dut, DUT_MSG_ERROR,
4749 				"%s: err in send_and_recv_msgs, ret=%d",
4750 				__func__, ret);
4751 	}
4752 	return ret;
4753 }
4754 
4755 
wcn_sta_set_noack(struct sigma_dut * dut,const char * intf,const char * val)4756 static void wcn_sta_set_noack(struct sigma_dut *dut, const char *intf,
4757 			      const char *val)
4758 {
4759 	int noack, ret;
4760 	char token[100];
4761 	char *result;
4762 	char *saveptr;
4763 	enum qca_wlan_ac_type ac = QCA_WLAN_AC_BE;
4764 
4765 	strlcpy(token, val, sizeof(token));
4766 	token[sizeof(token) - 1] = '\0';
4767 	result = strtok_r(token, ":", &saveptr);
4768 	while (result) {
4769 		noack = strcasecmp(result, "Disable") != 0;
4770 		ret = nlvendor_sta_set_noack(dut, intf, noack, ac);
4771 		if (ret) {
4772 			sigma_dut_print(dut, DUT_MSG_ERROR,
4773 					"nlvendor_sta_set_noack failed for ac:%d, ret:%d",
4774 					ac, ret);
4775 		}
4776 		result = strtok_r(NULL, ":", &saveptr);
4777 		ac++;
4778 	}
4779 }
4780 
4781 
nlvendor_sta_set_phymode(struct sigma_dut * dut,const char * intf,enum qca_wlan_vendor_phy_mode val)4782 static int nlvendor_sta_set_phymode(struct sigma_dut *dut, const char *intf,
4783 				    enum qca_wlan_vendor_phy_mode val)
4784 {
4785 	struct nl_msg *msg;
4786 	struct nlattr *params;
4787 	int ifindex, ret;
4788 
4789 	ifindex = if_nametoindex(intf);
4790 	if (ifindex == 0) {
4791 		sigma_dut_print(dut, DUT_MSG_ERROR,
4792 				"%s: Index for interface %s not found",
4793 				__func__, intf);
4794 		return -1;
4795 	}
4796 
4797 	msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
4798 			      NL80211_CMD_VENDOR);
4799 	if (!msg) {
4800 		sigma_dut_print(dut, DUT_MSG_ERROR,
4801 				"%s: err in adding vendor_cmd", __func__);
4802 		return -1;
4803 	}
4804 
4805 	if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
4806 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
4807 			QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION)) {
4808 		sigma_dut_print(dut, DUT_MSG_ERROR,
4809 				"%s: err in adding vendor_attr", __func__);
4810 		nlmsg_free(msg);
4811 		return -1;
4812 	}
4813 
4814 	params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
4815 	if (!params || nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE,
4816 				   val)) {
4817 		sigma_dut_print(dut, DUT_MSG_ERROR,
4818 				"%s: err in adding vendor_data", __func__);
4819 		nlmsg_free(msg);
4820 		return -1;
4821 	}
4822 
4823 	nla_nest_end(msg, params);
4824 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
4825 	if (ret) {
4826 		sigma_dut_print(dut, DUT_MSG_ERROR,
4827 				"%s: err in send_and_recv_msgs, ret=%d (%s)",
4828 				__func__, ret, strerror(-ret));
4829 		return ret;
4830 	}
4831 
4832 	return 0;
4833 }
4834 
4835 
get_qca_vendor_phymode(const char * val)4836 static enum qca_wlan_vendor_phy_mode get_qca_vendor_phymode(const char *val)
4837 {
4838 	if (strcmp(val, "11a") == 0) {
4839 		/* IEEE80211_MODE_11A */
4840 		return QCA_WLAN_VENDOR_PHY_MODE_11A;
4841 	}
4842 
4843 	if (strcmp(val, "11g") == 0) {
4844 		/* IEEE80211_MODE_11G */
4845 		return QCA_WLAN_VENDOR_PHY_MODE_11G;
4846 	}
4847 
4848 	if (strcmp(val, "11b") == 0) {
4849 		/* IEEE80211_MODE_11B */
4850 		return QCA_WLAN_VENDOR_PHY_MODE_11B;
4851 	}
4852 
4853 	if (strcmp(val, "11n") == 0 ||
4854 		   strcmp(val, "11nl") == 0 ||
4855 		   strcmp(val, "11nl(nabg)") == 0) {
4856 		/* IEEE80211_MODE_11AGN */
4857 		return QCA_WLAN_VENDOR_PHY_MODE_11AGN;
4858 	}
4859 
4860 	if (strcmp(val, "11ng") == 0) {
4861 		/* IEEE80211_MODE_11NG_HT40 */
4862 		return QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40;
4863 	}
4864 
4865 	if (strcmp(val, "AC") == 0 ||
4866 		   strcasecmp(val, "11AC") == 0) {
4867 		/* IEEE80211_MODE_11AC_VHT80 */
4868 		return QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80;
4869 	}
4870 
4871 	if (strcmp(val, "11na") == 0 ||
4872 		   strcasecmp(val, "11an") == 0) {
4873 		/* IEEE80211_MODE_11NA_HT40 */
4874 		return QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40;
4875 	}
4876 
4877 	if (strcmp(val, "11ax") == 0 ||
4878 		   strcmp(val, "auto") == 0) {
4879 		/* IEEE80211_MODE_AUTO */
4880 		return QCA_WLAN_VENDOR_PHY_MODE_AUTO;
4881 	}
4882 
4883 	return -1;
4884 }
4885 
4886 #endif /* NL80211_SUPPORT */
4887 
4888 
get_phymode(const char * val)4889 static int get_phymode(const char *val)
4890 {
4891 	if (strcmp(val, "11a") == 0)
4892 		return 1; /* IEEE80211_MODE_11A */
4893 	if (strcmp(val, "11g") == 0)
4894 		return 3; /* IEEE80211_MODE_11G */
4895 	if (strcmp(val, "11b") == 0)
4896 		return 2; /* IEEE80211_MODE_11B */
4897 	if (strcmp(val, "11n") == 0 ||
4898 	    strcmp(val, "11nl") == 0 ||
4899 	    strcmp(val, "11nl(nabg)") == 0)
4900 		return 22; /* IEEE80211_MODE_11AGN */
4901 	if (strcmp(val, "11ng") == 0)
4902 		return 13; /* IEEE80211_MODE_11NG_HT40 */
4903 	if (strcmp(val, "AC") == 0 ||
4904 	    strcasecmp(val, "11AC") == 0)
4905 		return 19; /* IEEE80211_MODE_11AC_VHT80 */
4906 	if (strcmp(val, "11na") == 0 ||
4907 	    strcasecmp(val, "11an") == 0)
4908 		return 14; /* IEEE80211_MODE_11NA_HT40 */
4909 	if (strcmp(val, "11ax") == 0 ||
4910 	    strcmp(val, "auto") == 0)
4911 		return 0; /* IEEE80211_MODE_AUTO */
4912 	return -1;
4913 }
4914 
4915 
sta_set_phymode(struct sigma_dut * dut,const char * intf,const char * val)4916 static void sta_set_phymode(struct sigma_dut *dut, const char *intf,
4917 			    const char *val)
4918 {
4919 	char buf[100];
4920 	int len, phymode;
4921 #ifdef NL80211_SUPPORT
4922 	enum qca_wlan_vendor_phy_mode qca_phymode;
4923 
4924 	qca_phymode = get_qca_vendor_phymode(val);
4925 	if (qca_phymode == -1) {
4926 		sigma_dut_print(dut, DUT_MSG_DEBUG,
4927 				"Ignoring mode change for mode: %s",
4928 				val);
4929 		return;
4930 	}
4931 
4932 	if (nlvendor_sta_set_phymode(dut, intf, qca_phymode) == 0)
4933 		return;
4934 #endif /* NL80211_SUPPORT */
4935 
4936 	phymode = get_phymode(val);
4937 	if (phymode == -1) {
4938 		sigma_dut_print(dut, DUT_MSG_DEBUG,
4939 				"Ignoring mode change for mode: %s",
4940 				val);
4941 		return;
4942 	}
4943 
4944 	len = snprintf(buf, sizeof(buf), "iwpriv %s setphymode %d", intf,
4945 		       phymode);
4946 	if (len < 0 || len >= sizeof(buf)) {
4947 		sigma_dut_print(dut, DUT_MSG_ERROR,
4948 				"Failed to set phymode");
4949 		return;
4950 	}
4951 
4952 	if (system(buf) != 0)
4953 		sigma_dut_print(dut, DUT_MSG_ERROR,
4954 				"iwpriv setting of phymode failed");
4955 }
4956 
4957 
4958 static enum sigma_cmd_result
cmd_sta_preset_testparameters(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)4959 cmd_sta_preset_testparameters(struct sigma_dut *dut, struct sigma_conn *conn,
4960 			      struct sigma_cmd *cmd)
4961 {
4962 	const char *intf = get_param(cmd, "Interface");
4963 	const char *val;
4964 
4965 	val = get_param(cmd, "FT_DS");
4966 	if (val) {
4967 		if (strcasecmp(val, "Enable") == 0) {
4968 			dut->sta_ft_ds = 1;
4969 		} else if (strcasecmp(val, "Disable") == 0) {
4970 			dut->sta_ft_ds = 0;
4971 		} else {
4972 			send_resp(dut, conn, SIGMA_ERROR,
4973 				  "errorCode,Unsupported value for FT_DS");
4974 			return STATUS_SENT_ERROR;
4975 		}
4976 	}
4977 
4978 	val = get_param(cmd, "Program");
4979 	if (val && (strcasecmp(val, "HS2-R2") == 0 ||
4980 		    strcasecmp(val, "HS2-R3") == 0))
4981 		return cmd_sta_preset_testparameters_hs2_r2(dut, conn, intf,
4982 							    cmd);
4983 
4984 	if (val && strcasecmp(val, "LOC") == 0)
4985 		return loc_cmd_sta_preset_testparameters(dut, conn, cmd);
4986 	if (val && strcasecmp(val, "60GHZ") == 0) {
4987 		val = get_param(cmd, "WPS");
4988 		if (val && strcasecmp(val, "disable") == 0) {
4989 			dut->wps_disable = 1;
4990 			sigma_dut_print(dut, DUT_MSG_INFO, "WPS disabled");
4991 		} else {
4992 			/* wps_disable can have other value from the previous
4993 			 * test, so make sure it has the correct value.
4994 			 */
4995 			dut->wps_disable = 0;
4996 		}
4997 
4998 		val = get_param(cmd, "P2P");
4999 		if (val && strcasecmp(val, "disable") == 0)
5000 			sigma_dut_print(dut, DUT_MSG_INFO, "P2P disabled");
5001 	}
5002 
5003 	if (dut->program == PROGRAM_WPS && dut->band == WPS_BAND_60G)
5004 		return cmd_sta_preset_testparameters_60ghz(dut, conn, cmd);
5005 
5006 #ifdef ANDROID_NAN
5007 	if (val && strcasecmp(val, "NAN") == 0)
5008 		return nan_cmd_sta_preset_testparameters(dut, conn, cmd);
5009 #endif /* ANDROID_NAN */
5010 #ifdef MIRACAST
5011 	if (val && (strcasecmp(val, "WFD") == 0 ||
5012 		    strcasecmp(val, "DisplayR2") == 0))
5013 		return miracast_preset_testparameters(dut, conn, cmd);
5014 #endif /* MIRACAST */
5015 
5016 	if (val &&
5017 	    (strcasecmp(val, "MBO") == 0 || strcasecmp(val, "HE") == 0)) {
5018 		val = get_param(cmd, "Cellular_Data_Cap");
5019 		if (val &&
5020 		    mbo_set_cellular_data_capa(dut, conn, intf, atoi(val)) == 0)
5021 			return 0;
5022 
5023 		val = get_param(cmd, "Ch_Pref");
5024 		if (val && mbo_set_non_pref_ch_list(dut, conn, intf, cmd) == 0)
5025 			return 0;
5026 
5027 		val = get_param(cmd, "BSS_Transition");
5028 		if (val && mbo_set_bss_trans_req(dut, conn, intf, val) == 0)
5029 			return 0;
5030 
5031 		val = get_param(cmd, "Assoc_Disallow");
5032 		if (val && mbo_set_assoc_disallow(dut, conn, intf, val) == 0)
5033 			return 0;
5034 
5035 		val = get_param(cmd, "Roaming");
5036 		if (val && mbo_set_roaming(dut, conn, intf, val) == 0)
5037 			return 0;
5038 
5039 		return 1;
5040 	}
5041 
5042 	if (val && strcasecmp(val, "OCE") == 0)
5043 		return cmd_sta_preset_testparameters_oce(dut, conn, intf, cmd);
5044 
5045 #if 0
5046 	val = get_param(cmd, "Supplicant");
5047 	if (val && strcasecmp(val, "Default") != 0) {
5048 		send_resp(dut, conn, SIGMA_ERROR,
5049 			  "ErrorCode,Only default(Vendor) supplicant "
5050 			  "supported");
5051 		return 0;
5052 	}
5053 #endif
5054 
5055 	val = get_param(cmd, "RTS");
5056 	if (val) {
5057 		switch (get_driver_type(dut)) {
5058 		case DRIVER_ATHEROS:
5059 			ath_sta_set_rts(dut, intf, val);
5060 			break;
5061 		default:
5062 #if 0
5063 			send_resp(dut, conn, SIGMA_ERROR,
5064 				  "ErrorCode,Setting RTS not supported");
5065 			return 0;
5066 #else
5067 			sigma_dut_print(dut, DUT_MSG_DEBUG,
5068 					"Setting RTS not supported");
5069 			break;
5070 #endif
5071 		}
5072 	}
5073 
5074 #if 0
5075 	val = get_param(cmd, "FRGMNT");
5076 	if (val) {
5077 		/* TODO */
5078 		send_resp(dut, conn, SIGMA_ERROR,
5079 			  "ErrorCode,Setting FRGMNT not supported");
5080 		return 0;
5081 	}
5082 #endif
5083 
5084 #if 0
5085 	val = get_param(cmd, "Preamble");
5086 	if (val) {
5087 		/* TODO: Long/Short */
5088 		send_resp(dut, conn, SIGMA_ERROR,
5089 			  "ErrorCode,Setting Preamble not supported");
5090 		return 0;
5091 	}
5092 #endif
5093 
5094 	val = get_param(cmd, "Mode");
5095 	if (val) {
5096 		if (strcmp(val, "11b") == 0 ||
5097 		    strcmp(val, "11g") == 0 ||
5098 		    strcmp(val, "11a") == 0 ||
5099 		    strcmp(val, "11n") == 0 ||
5100 		    strcmp(val, "11ng") == 0 ||
5101 		    strcmp(val, "11nl") == 0 ||
5102 		    strcmp(val, "11nl(nabg)") == 0 ||
5103 		    strcmp(val, "AC") == 0 ||
5104 		    strcmp(val, "11AC") == 0 ||
5105 		    strcmp(val, "11ac") == 0 ||
5106 		    strcmp(val, "11na") == 0 ||
5107 		    strcmp(val, "11an") == 0 ||
5108 		    strcmp(val, "11ax") == 0) {
5109 			/* STA supports all modes by default */
5110 		} else {
5111 			send_resp(dut, conn, SIGMA_ERROR,
5112 				  "ErrorCode,Setting Mode not supported");
5113 			return 0;
5114 		}
5115 
5116 		/* Change the mode only in case of testbed for HE program
5117 		 * and for 11a and 11g modes only. */
5118 		if (dut->program == PROGRAM_HE &&
5119 		    dut->device_type == STA_testbed) {
5120 			sta_set_phymode(dut, intf, val);
5121 		}
5122 	}
5123 
5124 	val = get_param(cmd, "wmm");
5125 	if (val) {
5126 		switch (get_driver_type(dut)) {
5127 		case DRIVER_ATHEROS:
5128 			ath_sta_set_wmm(dut, intf, val);
5129 			break;
5130 		case DRIVER_WCN:
5131 			wcn_sta_set_wmm(dut, intf, val);
5132 			break;
5133 		default:
5134 			sigma_dut_print(dut, DUT_MSG_DEBUG,
5135 					"Setting wmm not supported");
5136 			break;
5137 		}
5138 	}
5139 
5140 	val = get_param(cmd, "Powersave");
5141 	if (val) {
5142 		if (strcmp(val, "0") == 0 || strcasecmp(val, "off") == 0) {
5143 			if (get_driver_type(dut) == DRIVER_WCN) {
5144 				if (set_power_save_wcn(dut, intf, 2) < 0)
5145 					return 0;
5146 			}
5147 
5148 			if (wpa_command(get_station_ifname(dut),
5149 					"P2P_SET ps 0") < 0)
5150 				return -2;
5151 			/* Make sure test modes are disabled */
5152 			wpa_command(get_station_ifname(dut), "P2P_SET ps 98");
5153 			wpa_command(get_station_ifname(dut), "P2P_SET ps 96");
5154 		} else if (strcmp(val, "1") == 0 ||
5155 			   strcasecmp(val, "PSPoll") == 0 ||
5156 			   strcasecmp(val, "on") == 0) {
5157 			if (get_driver_type(dut) == DRIVER_WCN) {
5158 				if (set_power_save_wcn(dut, intf, 1) < 0)
5159 					return 0;
5160 			}
5161 			/* Disable default power save mode */
5162 			wpa_command(get_station_ifname(dut), "P2P_SET ps 0");
5163 			/* Enable PS-Poll test mode */
5164 			if (wpa_command(get_station_ifname(dut),
5165 					"P2P_SET ps 97") < 0 ||
5166 			    wpa_command(get_station_ifname(dut),
5167 					"P2P_SET ps 99") < 0)
5168 				return -2;
5169 		} else if (strcmp(val, "2") == 0 ||
5170 			   strcasecmp(val, "Fast") == 0) {
5171 			/* TODO */
5172 			send_resp(dut, conn, SIGMA_ERROR,
5173 				  "ErrorCode,Powersave=Fast not supported");
5174 			return 0;
5175 		} else if (strcmp(val, "3") == 0 ||
5176 			   strcasecmp(val, "PSNonPoll") == 0) {
5177 			/* Make sure test modes are disabled */
5178 			wpa_command(get_station_ifname(dut), "P2P_SET ps 98");
5179 			wpa_command(get_station_ifname(dut), "P2P_SET ps 96");
5180 
5181 			/* Enable default power save mode */
5182 			if (wpa_command(get_station_ifname(dut),
5183 					"P2P_SET ps 1") < 0)
5184 				return -2;
5185 		} else
5186 			return -1;
5187 	}
5188 
5189 	val = get_param(cmd, "NoAck");
5190 	if (val) {
5191 		switch (get_driver_type(dut)) {
5192 		case DRIVER_ATHEROS:
5193 			ath_sta_set_noack(dut, intf, val);
5194 			break;
5195 #ifdef NL80211_SUPPORT
5196 		case DRIVER_WCN:
5197 			wcn_sta_set_noack(dut, intf, val);
5198 			break;
5199 #endif /* NL80211_SUPPORT */
5200 		default:
5201 			send_resp(dut, conn, SIGMA_ERROR,
5202 				  "ErrorCode,Setting NoAck not supported");
5203 			return 0;
5204 		}
5205 	}
5206 
5207 	val = get_param(cmd, "IgnoreChswitchProhibit");
5208 	if (val) {
5209 		/* TODO: Enabled/disabled */
5210 		if (strcasecmp(val, "Enabled") == 0) {
5211 			send_resp(dut, conn, SIGMA_ERROR,
5212 				  "ErrorCode,Enabling IgnoreChswitchProhibit "
5213 				  "not supported");
5214 			return 0;
5215 		}
5216 	}
5217 
5218 	val = get_param(cmd, "TDLS");
5219 	if (val) {
5220 		if (strcasecmp(val, "Disabled") == 0) {
5221 			if (wpa_command(intf, "SET tdls_disabled 1")) {
5222 				send_resp(dut, conn, SIGMA_ERROR,
5223 					  "ErrorCode,Failed to disable TDLS");
5224 				return 0;
5225 			}
5226 		} else if (strcasecmp(val, "Enabled") == 0) {
5227 			if (wpa_command(intf, "SET tdls_disabled 0")) {
5228 				send_resp(dut, conn, SIGMA_ERROR,
5229 					  "ErrorCode,Failed to enable TDLS");
5230 				return 0;
5231 			}
5232 		} else {
5233 			send_resp(dut, conn, SIGMA_ERROR,
5234 				  "ErrorCode,Unsupported TDLS value");
5235 			return 0;
5236 		}
5237 	}
5238 
5239 	val = get_param(cmd, "TDLSmode");
5240 	if (val) {
5241 		if (strcasecmp(val, "Default") == 0) {
5242 			wpa_command(intf, "SET tdls_testing 0");
5243 		} else if (strcasecmp(val, "APProhibit") == 0) {
5244 			if (wpa_command(intf, "SET tdls_testing 0x400")) {
5245 				send_resp(dut, conn, SIGMA_ERROR,
5246 					  "ErrorCode,Failed to enable ignore "
5247 					  "APProhibit TDLS mode");
5248 				return 0;
5249 			}
5250 		} else if (strcasecmp(val, "HiLoMac") == 0) {
5251 			/* STA should respond with TDLS setup req for a TDLS
5252 			 * setup req */
5253 			if (wpa_command(intf, "SET tdls_testing 0x80")) {
5254 				send_resp(dut, conn, SIGMA_ERROR,
5255 					  "ErrorCode,Failed to enable HiLoMac "
5256 					  "TDLS mode");
5257 				return 0;
5258 			}
5259 		} else if (strcasecmp(val, "WeakSecurity") == 0) {
5260 			/*
5261 			 * Since all security modes are enabled by default when
5262 			 * Sigma control is used, there is no need to do
5263 			 * anything here.
5264 			 */
5265 		} else if (strcasecmp(val, "ExistLink") == 0) {
5266 			/*
5267 			 * Since we allow new TDLS Setup Request even if there
5268 			 * is an existing link, nothing needs to be done for
5269 			 * this.
5270 			 */
5271 		} else {
5272 			/* TODO:
5273 			 * ExistLink: STA should send TDLS setup req even if
5274 			 * direct link already exists
5275 			 */
5276 			send_resp(dut, conn, SIGMA_ERROR,
5277 				  "ErrorCode,Unsupported TDLSmode value");
5278 			return 0;
5279 		}
5280 	}
5281 
5282 	val = get_param(cmd, "FakePubKey");
5283 	if (val && atoi(val) && wpa_command(intf, "SET wps_corrupt_pkhash 1")) {
5284 		send_resp(dut, conn, SIGMA_ERROR,
5285 			  "ErrorCode,Failed to enable FakePubKey");
5286 		return 0;
5287 	}
5288 
5289 #ifdef NL80211_SUPPORT
5290 	val = get_param(cmd, "FrgmntSupport");
5291 	if (val) {
5292 		if (strcasecmp(val, "Enable") == 0) {
5293 			if (sta_set_he_fragmentation(dut, intf,
5294 						     HE_FRAG_LEVEL1)) {
5295 				send_resp(dut, conn, SIGMA_ERROR,
5296 					  "ErrorCode,Failed to enable HE Fragmentation");
5297 				return 0;
5298 			}
5299 		} else if (strcasecmp(val, "Disable") == 0) {
5300 			if (sta_set_he_fragmentation(dut, intf,
5301 						     HE_FRAG_DISABLE)) {
5302 				send_resp(dut, conn, SIGMA_ERROR,
5303 					  "ErrorCode,Failed to disable HE Fragmentation");
5304 				return 0;
5305 			}
5306 		}
5307 	}
5308 #endif /* NL80211_SUPPORT */
5309 
5310 	val = get_param(cmd, "IncludeMSCSDescriptor");
5311 	if (val && strcasecmp(val, "1") == 0) {
5312 		char buf[128];
5313 		int len;
5314 
5315 		len = snprintf(buf, sizeof(buf),
5316 			       "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=60000 frame_classifier=045F%032x",
5317 			       0);
5318 
5319 		if (len < 0 || len >= sizeof(buf)) {
5320 			sigma_dut_print(dut, DUT_MSG_ERROR,
5321 					"Failed to build MSCS Descriptor IE");
5322 			return ERROR_SEND_STATUS;
5323 		}
5324 
5325 		if (wpa_command(intf, buf) != 0) {
5326 			send_resp(dut, conn, SIGMA_ERROR,
5327 				"ErrorCode,Failed to include MSCS descriptor");
5328 			return STATUS_SENT_ERROR;
5329 		}
5330 	}
5331 
5332 	return 1;
5333 }
5334 
5335 
ath_get_radio_name(const char * radio_name)5336 static const char * ath_get_radio_name(const char *radio_name)
5337 {
5338 	if (radio_name == NULL)
5339 		return "wifi0";
5340 	if (strcmp(radio_name, "wifi1") == 0)
5341 		return "wifi1";
5342 	if (strcmp(radio_name, "wifi2") == 0)
5343 		return "wifi2";
5344 	return "wifi0";
5345 }
5346 
5347 
ath_sta_set_txsp_stream(struct sigma_dut * dut,const char * intf,const char * val)5348 static void ath_sta_set_txsp_stream(struct sigma_dut *dut, const char *intf,
5349 				    const char *val)
5350 {
5351 	unsigned int vht_mcsmap = 0;
5352 	int txchainmask = 0;
5353 	const char *basedev = ath_get_radio_name(sigma_radio_ifname[0]);
5354 
5355 	if (strcasecmp(val, "1") == 0 || strcasecmp(val, "1SS") == 0) {
5356 		if (dut->testbed_flag_txsp == 1) {
5357 			vht_mcsmap = 0xfffc;
5358 			dut->testbed_flag_txsp = 0;
5359 		} else {
5360 			vht_mcsmap = 0xfffe;
5361 		}
5362 		txchainmask = 1;
5363 	} else if (strcasecmp(val, "2") == 0 || strcasecmp(val, "2SS") == 0) {
5364 		if (dut->testbed_flag_txsp == 1) {
5365 			vht_mcsmap = 0xfff0;
5366 			dut->testbed_flag_txsp = 0;
5367 		} else {
5368 			vht_mcsmap = 0xfffa;
5369 		}
5370 		txchainmask = 3;
5371 	} else if (strcasecmp(val, "3") == 0 || strcasecmp(val, "3SS") == 0) {
5372 		if (dut->testbed_flag_txsp == 1) {
5373 			vht_mcsmap = 0xffc0;
5374 			dut->testbed_flag_txsp = 0;
5375 		} else {
5376 			vht_mcsmap = 0xffea;
5377 		}
5378 		txchainmask = 7;
5379 	} else if (strcasecmp(val, "4") == 0 || strcasecmp(val, "4SS") == 0) {
5380 		if (dut->testbed_flag_txsp == 1) {
5381 			vht_mcsmap = 0xff00;
5382 			dut->testbed_flag_txsp = 0;
5383 		} else {
5384 			vht_mcsmap = 0xffaa;
5385 		}
5386 		txchainmask = 15;
5387 	} else {
5388 		if (dut->testbed_flag_txsp == 1) {
5389 			vht_mcsmap = 0xffc0;
5390 			dut->testbed_flag_txsp = 0;
5391 		} else {
5392 			vht_mcsmap = 0xffea;
5393 		}
5394 	}
5395 
5396 	if (txchainmask)
5397 		run_iwpriv(dut, basedev, "txchainmask %d", txchainmask);
5398 
5399 	run_iwpriv(dut, intf, "vht_mcsmap 0x%04x", vht_mcsmap);
5400 }
5401 
5402 
ath_sta_set_rxsp_stream(struct sigma_dut * dut,const char * intf,const char * val)5403 static void ath_sta_set_rxsp_stream(struct sigma_dut *dut, const char *intf,
5404 				    const char *val)
5405 {
5406 	unsigned int vht_mcsmap = 0;
5407 	int rxchainmask = 0;
5408 	const char *basedev = ath_get_radio_name(sigma_radio_ifname[0]);
5409 
5410 	if (strcasecmp(val, "1") == 0 || strcasecmp(val, "1SS") == 0) {
5411 		if (dut->testbed_flag_rxsp == 1) {
5412 			vht_mcsmap = 0xfffc;
5413 			dut->testbed_flag_rxsp = 0;
5414 		} else {
5415 			vht_mcsmap = 0xfffe;
5416 		}
5417 		rxchainmask = 1;
5418 	} else if (strcasecmp(val, "2") == 0 || strcasecmp(val, "2SS") == 0) {
5419 		if (dut->testbed_flag_rxsp == 1) {
5420 			vht_mcsmap = 0xfff0;
5421 			dut->testbed_flag_rxsp = 0;
5422 		} else {
5423 			vht_mcsmap = 0xfffa;
5424 		}
5425 		rxchainmask = 3;
5426 	} else if (strcasecmp(val, "3") == 0 || strcasecmp(val, "3SS") == 0) {
5427 		if (dut->testbed_flag_rxsp == 1) {
5428 			vht_mcsmap = 0xffc0;
5429 			dut->testbed_flag_rxsp = 0;
5430 		} else {
5431 			vht_mcsmap = 0xffea;
5432 		}
5433 		rxchainmask = 7;
5434 	} else if (strcasecmp(val, "4") == 0 || strcasecmp(val, "4SS") == 0) {
5435 		if (dut->testbed_flag_rxsp == 1) {
5436 			vht_mcsmap = 0xff00;
5437 			dut->testbed_flag_rxsp = 0;
5438 		} else {
5439 			vht_mcsmap = 0xffaa;
5440 		}
5441 		rxchainmask = 15;
5442 	} else {
5443 		if (dut->testbed_flag_rxsp == 1) {
5444 			vht_mcsmap = 0xffc0;
5445 			dut->testbed_flag_rxsp = 0;
5446 		} else {
5447 			vht_mcsmap = 0xffea;
5448 		}
5449 	}
5450 
5451 	if (rxchainmask)
5452 		run_iwpriv(dut, basedev, "rxchainmask %d", rxchainmask);
5453 
5454 	run_iwpriv(dut, intf, "vht_mcsmap 0x%04x", vht_mcsmap);
5455 }
5456 
5457 
ath_set_zero_crc(struct sigma_dut * dut,const char * val)5458 void ath_set_zero_crc(struct sigma_dut *dut, const char *val)
5459 {
5460 	if (strcasecmp(val, "enable") == 0) {
5461 		if (system("athdiag --set --address=0x2a204 --and=0xbfffffff")
5462 		    != 0) {
5463 			sigma_dut_print(dut, DUT_MSG_ERROR,
5464 					"Disable BB_VHTSIGB_CRC_CALC failed");
5465 		}
5466 
5467 		if (system("athdiag --set --address=0x2a204 --or=0x80000000")
5468 		    != 0) {
5469 			sigma_dut_print(dut, DUT_MSG_ERROR,
5470 					"Enable FORCE_VHT_SIGB_CRC_VALUE_ZERO failed");
5471 		}
5472 	} else {
5473 		if (system("athdiag --set --address=0x2a204 --and=0x7fffffff")
5474 		    != 0) {
5475 			sigma_dut_print(dut, DUT_MSG_ERROR,
5476 					"Disable FORCE_VHT_SIGB_CRC_VALUE_ZERO failed");
5477 		}
5478 
5479 		if (system("athdiag --set --address=0x2a204 --or=0x40000000")
5480 		    != 0) {
5481 			sigma_dut_print(dut, DUT_MSG_ERROR,
5482 					"Enable BB_VHTSIGB_CRC_CALC failed");
5483 		}
5484 	}
5485 }
5486 
5487 
wcn_sta_set_width(struct sigma_dut * dut,const char * intf,const char * val)5488 static int wcn_sta_set_width(struct sigma_dut *dut, const char *intf,
5489 			     const char *val)
5490 {
5491 	char buf[60];
5492 
5493 	if (strcmp(val, "20") == 0) {
5494 		snprintf(buf, sizeof(buf), "iwpriv %s chwidth 0", intf);
5495 		dut->chwidth = 0;
5496 	} else if (strcmp(val, "40") == 0) {
5497 		snprintf(buf, sizeof(buf), "iwpriv %s chwidth 1", intf);
5498 		dut->chwidth = 1;
5499 	} else if (strcmp(val, "80") == 0) {
5500 		snprintf(buf, sizeof(buf), "iwpriv %s chwidth 2", intf);
5501 		dut->chwidth = 2;
5502 	} else if (strcasecmp(val, "Auto") == 0) {
5503 		buf[0] = '\0';
5504 	} else {
5505 		sigma_dut_print(dut, DUT_MSG_ERROR, "WIDTH %s not supported",
5506 				val);
5507 		return -1;
5508 	}
5509 
5510 	if (buf[0] != '\0' && system(buf) != 0) {
5511 		sigma_dut_print(dut, DUT_MSG_ERROR, "iwpriv chwidth failed");
5512 		return -1;
5513 	}
5514 
5515 	return 0;
5516 }
5517 
5518 
nlvendor_sta_set_addba_reject(struct sigma_dut * dut,const char * intf,int addbareject)5519 static int nlvendor_sta_set_addba_reject(struct sigma_dut *dut,
5520 					 const char *intf, int addbareject)
5521 {
5522 #ifdef NL80211_SUPPORT
5523 	return wcn_wifi_test_config_set_u8(
5524 		dut, intf,
5525 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ,
5526 		!addbareject);
5527 #else /* NL80211_SUPPORT */
5528 	sigma_dut_print(dut, DUT_MSG_ERROR,
5529 			"ADDBA_REJECT cannot be set without NL80211_SUPPORT defined");
5530 	return -1;
5531 #endif /* NL80211_SUPPORT */
5532 }
5533 
5534 
sta_set_addba_reject(struct sigma_dut * dut,const char * intf,int addbareject)5535 static int sta_set_addba_reject(struct sigma_dut *dut, const char *intf,
5536 				int addbareject)
5537 {
5538 	int ret;
5539 
5540 	switch (get_driver_type(dut)) {
5541 	case DRIVER_WCN:
5542 		ret = nlvendor_sta_set_addba_reject(dut, intf, addbareject);
5543 		if (ret) {
5544 			sigma_dut_print(dut, DUT_MSG_ERROR,
5545 					"nlvendor_sta_set_addba_reject failed, ret:%d",
5546 					ret);
5547 			return ret;
5548 		}
5549 		break;
5550 	default:
5551 		sigma_dut_print(dut, DUT_MSG_ERROR,
5552 				"errorCode,Unsupported ADDBA_REJECT with the current driver");
5553 		ret = -1;
5554 		break;
5555 	}
5556 
5557 	return ret;
5558 }
5559 
5560 
nlvendor_config_send_addba(struct sigma_dut * dut,const char * intf,int enable)5561 static int nlvendor_config_send_addba(struct sigma_dut *dut, const char *intf,
5562 				      int enable)
5563 {
5564 #ifdef NL80211_SUPPORT
5565 	return wcn_wifi_test_config_set_u8(
5566 		dut, intf, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ,
5567 		enable);
5568 #else /* NL80211_SUPPORT */
5569 	sigma_dut_print(dut, DUT_MSG_ERROR,
5570 			"Disable addba not possible without NL80211_SUPPORT defined");
5571 	return -1;
5572 #endif /* NL80211_SUPPORT */
5573 }
5574 
5575 
5576 #ifdef NL80211_SUPPORT
nl80211_sta_set_rts(struct sigma_dut * dut,const char * intf,int val)5577 static int nl80211_sta_set_rts(struct sigma_dut *dut, const char *intf, int val)
5578 {
5579 	struct nl_msg *msg;
5580 	int ret = 0;
5581 	int ifindex;
5582 
5583 	ifindex = if_nametoindex(intf);
5584 	if (ifindex == 0) {
5585 		sigma_dut_print(dut, DUT_MSG_ERROR,
5586 				"%s: Index for interface %s failed",
5587 				__func__, intf);
5588 		return -1;
5589 	}
5590 
5591 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
5592 				    NL80211_CMD_SET_WIPHY)) ||
5593 	    nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val)) {
5594 		sigma_dut_print(dut, DUT_MSG_ERROR,
5595 				"%s: err in adding RTS threshold",
5596 				__func__);
5597 		nlmsg_free(msg);
5598 		return -1;
5599 	}
5600 
5601 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
5602 	if (ret) {
5603 		sigma_dut_print(dut, DUT_MSG_ERROR,
5604 				"%s: err in send_and_recv_msgs, ret=%d",
5605 				__func__, ret);
5606 	}
5607 	return ret;
5608 }
5609 #endif /* NL80211_SUPPORT */
5610 
5611 
sta_set_rts(struct sigma_dut * dut,const char * intf,int val)5612 static int sta_set_rts(struct sigma_dut *dut, const char *intf, int val)
5613 {
5614 	char buf[100];
5615 
5616 #ifdef NL80211_SUPPORT
5617 	if (nl80211_sta_set_rts(dut, intf, val) == 0)
5618 		return 0;
5619 	sigma_dut_print(dut, DUT_MSG_DEBUG,
5620 			"Fall back to using iwconfig for setting RTS threshold");
5621 #endif /* NL80211_SUPPORT */
5622 
5623 	snprintf(buf, sizeof(buf), "iwconfig %s rts %d", intf, val);
5624 	if (system(buf) != 0) {
5625 		sigma_dut_print(dut, DUT_MSG_ERROR,
5626 				"Failed to set RTS threshold %d", val);
5627 		return -1;
5628 	}
5629 	return 0;
5630 }
5631 
5632 
5633 static enum sigma_cmd_result
cmd_sta_set_wireless_common(const char * intf,struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)5634 cmd_sta_set_wireless_common(const char *intf, struct sigma_dut *dut,
5635 			    struct sigma_conn *conn, struct sigma_cmd *cmd)
5636 {
5637 	const char *val;
5638 	int ampdu = -1, addbareject = -1;
5639 	char buf[128];
5640 	int res;
5641 
5642 	val = get_param(cmd, "40_INTOLERANT");
5643 	if (val) {
5644 		if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
5645 			/* TODO: iwpriv ht40intol through wpa_supplicant */
5646 			send_resp(dut, conn, SIGMA_ERROR,
5647 				  "ErrorCode,40_INTOLERANT not supported");
5648 			return STATUS_SENT_ERROR;
5649 		}
5650 	}
5651 
5652 	val = get_param(cmd, "ADDBA_REJECT");
5653 	if (val) {
5654 		if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
5655 			/* reject any ADDBA with status "decline" */
5656 			ampdu = 0;
5657 			addbareject = 1;
5658 		} else {
5659 			/* accept ADDBA */
5660 			ampdu = 1;
5661 			addbareject = 0;
5662 		}
5663 	}
5664 
5665 	if (addbareject >= 0 &&
5666 	    sta_set_addba_reject(dut, intf, addbareject) < 0) {
5667 		send_resp(dut, conn, SIGMA_ERROR,
5668 			  "ErrorCode,set addba_reject failed");
5669 		return STATUS_SENT_ERROR;
5670 	}
5671 
5672 	val = get_param(cmd, "AMPDU");
5673 	if (val) {
5674 		if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
5675 			/* enable AMPDU Aggregation */
5676 			if (ampdu == 0) {
5677 				send_resp(dut, conn, SIGMA_ERROR,
5678 					  "ErrorCode,Mismatch in "
5679 					  "addba_reject/ampdu - "
5680 					  "not supported");
5681 				return STATUS_SENT_ERROR;
5682 			}
5683 			ampdu = 1;
5684 		} else {
5685 			/* disable AMPDU Aggregation */
5686 			if (ampdu == 1) {
5687 				send_resp(dut, conn, SIGMA_ERROR,
5688 					  "ErrorCode,Mismatch in "
5689 					  "addba_reject/ampdu - "
5690 					  "not supported");
5691 				return STATUS_SENT_ERROR;
5692 			}
5693 			ampdu = 0;
5694 		}
5695 	}
5696 
5697 	if (ampdu >= 0) {
5698 		int ret;
5699 
5700 		sigma_dut_print(dut, DUT_MSG_DEBUG, "%s A-MPDU aggregation",
5701 				ampdu ? "Enabling" : "Disabling");
5702 		snprintf(buf, sizeof(buf), "SET ampdu %d", ampdu);
5703 		if (wpa_command(intf, buf) < 0 &&
5704 		    iwpriv_sta_set_ampdu(dut, intf, ampdu) < 0) {
5705 			send_resp(dut, conn, SIGMA_ERROR,
5706 				  "ErrorCode,set aggr failed");
5707 			return STATUS_SENT_ERROR;
5708 		}
5709 
5710 		if (ampdu == 0) {
5711 			/* Disable sending of addba using nl vendor command */
5712 			ret = nlvendor_config_send_addba(dut, intf, 0);
5713 			if (ret) {
5714 				sigma_dut_print(dut, DUT_MSG_ERROR,
5715 						"Failed to disable addba, ret:%d",
5716 						ret);
5717 			}
5718 		}
5719 	}
5720 
5721 	val = get_param(cmd, "AMSDU");
5722 	if (val) {
5723 		switch (get_driver_type(dut)) {
5724 		case DRIVER_ATHEROS:
5725 		case DRIVER_WCN:
5726 			iwpriv_sta_set_amsdu(dut, intf, val);
5727 			break;
5728 		default:
5729 			if (strcmp(val, "1") == 0 ||
5730 			    strcasecmp(val, "Enable") == 0) {
5731 				/* Enable AMSDU Aggregation */
5732 				send_resp(dut, conn, SIGMA_ERROR,
5733 					  "ErrorCode,AMSDU aggregation not supported");
5734 				return STATUS_SENT_ERROR;
5735 			}
5736 			break;
5737 		}
5738 	}
5739 
5740 	val = get_param(cmd, "STBC_RX");
5741 	if (val) {
5742 		switch (get_driver_type(dut)) {
5743 		case DRIVER_ATHEROS:
5744 			ath_sta_set_stbc(dut, intf, val);
5745 			break;
5746 		case DRIVER_WCN:
5747 			wcn_sta_set_stbc(dut, intf, val);
5748 			break;
5749 		default:
5750 			send_resp(dut, conn, SIGMA_ERROR,
5751 				  "ErrorCode,STBC_RX not supported");
5752 			return STATUS_SENT_ERROR;
5753 		}
5754 	}
5755 
5756 	val = get_param(cmd, "WIDTH");
5757 	if (val) {
5758 		switch (get_driver_type(dut)) {
5759 		case DRIVER_WCN:
5760 			if (wcn_sta_set_width(dut, intf, val) < 0) {
5761 				send_resp(dut, conn, SIGMA_ERROR,
5762 					  "ErrorCode,Failed to set WIDTH");
5763 				return STATUS_SENT_ERROR;
5764 			}
5765 			break;
5766 		case DRIVER_ATHEROS:
5767 			if (ath_set_width(dut, conn, intf, val) < 0)
5768 				return STATUS_SENT_ERROR;
5769 			break;
5770 		default:
5771 			sigma_dut_print(dut, DUT_MSG_ERROR,
5772 					"Setting WIDTH not supported");
5773 			break;
5774 		}
5775 	}
5776 
5777 	val = get_param(cmd, "SMPS");
5778 	if (val) {
5779 		/* TODO: Dynamic/0, Static/1, No Limit/2 */
5780 		send_resp(dut, conn, SIGMA_ERROR,
5781 			  "ErrorCode,SMPS not supported");
5782 		return STATUS_SENT_ERROR;
5783 	}
5784 
5785 	val = get_param(cmd, "TXSP_STREAM");
5786 	if (val) {
5787 		switch (get_driver_type(dut)) {
5788 		case DRIVER_WCN:
5789 			if (wcn_sta_set_sp_stream(dut, intf, val) < 0) {
5790 				send_resp(dut, conn, SIGMA_ERROR,
5791 					  "ErrorCode,Failed to set TXSP_STREAM");
5792 				return STATUS_SENT_ERROR;
5793 			}
5794 			break;
5795 		case DRIVER_ATHEROS:
5796 			ath_sta_set_txsp_stream(dut, intf, val);
5797 			break;
5798 		default:
5799 			sigma_dut_print(dut, DUT_MSG_ERROR,
5800 					"Setting TXSP_STREAM not supported");
5801 			break;
5802 		}
5803 	}
5804 
5805 	val = get_param(cmd, "RXSP_STREAM");
5806 	if (val) {
5807 		switch (get_driver_type(dut)) {
5808 		case DRIVER_WCN:
5809 			if (wcn_sta_set_sp_stream(dut, intf, val) < 0) {
5810 				send_resp(dut, conn, SIGMA_ERROR,
5811 					  "ErrorCode,Failed to set RXSP_STREAM");
5812 				return STATUS_SENT_ERROR;
5813 			}
5814 			break;
5815 		case DRIVER_ATHEROS:
5816 			ath_sta_set_rxsp_stream(dut, intf, val);
5817 			break;
5818 		default:
5819 			sigma_dut_print(dut, DUT_MSG_ERROR,
5820 					"Setting RXSP_STREAM not supported");
5821 			break;
5822 		}
5823 	}
5824 
5825 	val = get_param(cmd, "DYN_BW_SGNL");
5826 	if (val) {
5827 		switch (get_driver_type(dut)) {
5828 		case DRIVER_WCN:
5829 			if (strcasecmp(val, "enable") == 0) {
5830 				snprintf(buf, sizeof(buf),
5831 					 "iwpriv %s cwmenable 1", intf);
5832 				if (system(buf) != 0) {
5833 					sigma_dut_print(dut, DUT_MSG_ERROR,
5834 							"iwpriv cwmenable 1 failed");
5835 					return ERROR_SEND_STATUS;
5836 				}
5837 			} else if (strcasecmp(val, "disable") == 0) {
5838 				snprintf(buf, sizeof(buf),
5839 					 "iwpriv %s cwmenable 0", intf);
5840 				if (system(buf) != 0) {
5841 					sigma_dut_print(dut, DUT_MSG_ERROR,
5842 							"iwpriv cwmenable 0 failed");
5843 					return ERROR_SEND_STATUS;
5844 				}
5845 			} else {
5846 				sigma_dut_print(dut, DUT_MSG_ERROR,
5847 						"Unsupported DYN_BW_SGL");
5848 			}
5849 
5850 			snprintf(buf, sizeof(buf), "iwpriv %s cts_cbw 3", intf);
5851 			if (system(buf) != 0) {
5852 				sigma_dut_print(dut, DUT_MSG_ERROR,
5853 						"Failed to set cts_cbw in DYN_BW_SGNL");
5854 				return ERROR_SEND_STATUS;
5855 			}
5856 			break;
5857 		case DRIVER_ATHEROS:
5858 			novap_reset(dut, intf, 1);
5859 			ath_config_dyn_bw_sig(dut, intf, val);
5860 			break;
5861 		default:
5862 			sigma_dut_print(dut, DUT_MSG_ERROR,
5863 					"Failed to set DYN_BW_SGNL");
5864 			break;
5865 		}
5866 	}
5867 
5868 	val = get_param(cmd, "RTS_FORCE");
5869 	if (val) {
5870 		novap_reset(dut, intf, 1);
5871 		if (strcasecmp(val, "Enable") == 0) {
5872 			if (sta_set_rts(dut, intf, 64) != 0) {
5873 				sigma_dut_print(dut, DUT_MSG_ERROR,
5874 						"Failed to set RTS_FORCE 64");
5875 			}
5876 			res = snprintf(buf, sizeof(buf),
5877 				       "wifitool %s beeliner_fw_test 100 1",
5878 				       intf);
5879 			if (res < 0 || res >= sizeof(buf) || system(buf) != 0) {
5880 				sigma_dut_print(dut, DUT_MSG_ERROR,
5881 						"wifitool beeliner_fw_test 100 1 failed");
5882 			}
5883 		} else if (strcasecmp(val, "Disable") == 0) {
5884 			if (sta_set_rts(dut, intf, 2347) != 0) {
5885 				sigma_dut_print(dut, DUT_MSG_ERROR,
5886 						"Failed to set RTS_FORCE 2347");
5887 			}
5888 		} else {
5889 			send_resp(dut, conn, SIGMA_ERROR,
5890 				  "ErrorCode,RTS_FORCE value not supported");
5891 			return STATUS_SENT_ERROR;
5892 		}
5893 	}
5894 
5895 	val = get_param(cmd, "CTS_WIDTH");
5896 	if (val) {
5897 		switch (get_driver_type(dut)) {
5898 		case DRIVER_WCN:
5899 			if (wcn_sta_set_cts_width(dut, intf, val) < 0) {
5900 				send_resp(dut, conn, SIGMA_ERROR,
5901 					  "ErrorCode,Failed to set CTS_WIDTH");
5902 				return STATUS_SENT_ERROR;
5903 			}
5904 			break;
5905 		case DRIVER_ATHEROS:
5906 			ath_set_cts_width(dut, intf, val);
5907 			break;
5908 		default:
5909 			sigma_dut_print(dut, DUT_MSG_ERROR,
5910 					"Setting CTS_WIDTH not supported");
5911 			break;
5912 		}
5913 	}
5914 
5915 	val = get_param(cmd, "BW_SGNL");
5916 	if (val) {
5917 		if (strcasecmp(val, "Enable") == 0) {
5918 			run_iwpriv(dut, intf, "cwmenable 1");
5919 		} else if (strcasecmp(val, "Disable") == 0) {
5920 			/* TODO: Disable */
5921 		} else {
5922 			send_resp(dut, conn, SIGMA_ERROR,
5923 				  "ErrorCode,BW_SGNL value not supported");
5924 			return STATUS_SENT_ERROR;
5925 		}
5926 	}
5927 
5928 	val = get_param(cmd, "Band");
5929 	if (val) {
5930 		if (strcmp(val, "2.4") == 0 || strcmp(val, "5") == 0) {
5931 			/* STA supports all bands by default */
5932 		} else {
5933 			send_resp(dut, conn, SIGMA_ERROR,
5934 				  "ErrorCode,Unsupported Band");
5935 			return STATUS_SENT_ERROR;
5936 		}
5937 	}
5938 
5939 	val = get_param(cmd, "zero_crc");
5940 	if (val) {
5941 		switch (get_driver_type(dut)) {
5942 		case DRIVER_ATHEROS:
5943 			ath_set_zero_crc(dut, val);
5944 			break;
5945 		default:
5946 			break;
5947 		}
5948 	}
5949 
5950 	return SUCCESS_SEND_STATUS;
5951 }
5952 
5953 
sta_set_force_mcs(struct sigma_dut * dut,int force,int mcs)5954 static int sta_set_force_mcs(struct sigma_dut *dut, int force, int mcs)
5955 {
5956 	switch (get_driver_type(dut)) {
5957 #ifdef __linux__
5958 	case DRIVER_WIL6210:
5959 		return wil6210_set_force_mcs(dut, force, mcs);
5960 #endif /* __linux__ */
5961 	default:
5962 		sigma_dut_print(dut, DUT_MSG_ERROR,
5963 				"Unsupported sta_set_force_mcs with the current driver");
5964 		return -1;
5965 	}
5966 }
5967 
5968 
sta_60g_force_rsn_ie(struct sigma_dut * dut,int state)5969 static int sta_60g_force_rsn_ie(struct sigma_dut *dut, int state)
5970 {
5971 	switch (get_driver_type(dut)) {
5972 #ifdef __linux__
5973 	case DRIVER_WIL6210:
5974 		return wil6210_force_rsn_ie(dut, state);
5975 #endif /* __linux__ */
5976 	default:
5977 		sigma_dut_print(dut, DUT_MSG_ERROR,
5978 				"Unsupported sta_60g_force_rsn_ie with the current driver");
5979 		return -1;
5980 	}
5981 }
5982 
5983 
sta_set_60g_common(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)5984 static int sta_set_60g_common(struct sigma_dut *dut, struct sigma_conn *conn,
5985 			      struct sigma_cmd *cmd)
5986 {
5987 	const char *val;
5988 	char buf[100];
5989 
5990 	val = get_param(cmd, "MSDUSize");
5991 	if (val) {
5992 		int mtu;
5993 
5994 		dut->amsdu_size = atoi(val);
5995 		if (dut->amsdu_size > IEEE80211_MAX_DATA_LEN_DMG ||
5996 		    dut->amsdu_size < IEEE80211_SNAP_LEN_DMG) {
5997 			sigma_dut_print(dut, DUT_MSG_ERROR,
5998 					"MSDUSize %d is above max %d or below min %d",
5999 					dut->amsdu_size,
6000 					IEEE80211_MAX_DATA_LEN_DMG,
6001 					IEEE80211_SNAP_LEN_DMG);
6002 			dut->amsdu_size = 0;
6003 			return ERROR_SEND_STATUS;
6004 		}
6005 
6006 		mtu = dut->amsdu_size - IEEE80211_SNAP_LEN_DMG;
6007 		sigma_dut_print(dut, DUT_MSG_DEBUG,
6008 				"Setting amsdu_size to %d", mtu);
6009 		snprintf(buf, sizeof(buf), "ifconfig %s mtu %d",
6010 			 get_station_ifname(dut), mtu);
6011 
6012 		if (system(buf) != 0) {
6013 			sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set %s",
6014 					buf);
6015 			return ERROR_SEND_STATUS;
6016 		}
6017 	}
6018 
6019 	val = get_param(cmd, "BAckRcvBuf");
6020 	if (val) {
6021 		dut->back_rcv_buf = atoi(val);
6022 		if (dut->back_rcv_buf == 0) {
6023 			sigma_dut_print(dut, DUT_MSG_ERROR,
6024 					"Failed to convert %s or value is 0",
6025 					val);
6026 			return ERROR_SEND_STATUS;
6027 		}
6028 
6029 		sigma_dut_print(dut, DUT_MSG_DEBUG,
6030 				"Setting BAckRcvBuf to %s", val);
6031 	}
6032 
6033 	val = get_param(cmd, "MCS_FixedRate");
6034 	if (val) {
6035 		if (sta_set_force_mcs(dut, 1, atoi(val))) {
6036 			sigma_dut_print(dut, DUT_MSG_ERROR,
6037 					"Failed to force MCS");
6038 			return ERROR_SEND_STATUS;
6039 		}
6040 	}
6041 
6042 	return SUCCESS_SEND_STATUS;
6043 }
6044 
6045 
sta_pcp_start(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)6046 static int sta_pcp_start(struct sigma_dut *dut, struct sigma_conn *conn,
6047 			 struct sigma_cmd *cmd)
6048 {
6049 	int net_id;
6050 	const char *ifname;
6051 	const char *val;
6052 	char buf[100];
6053 
6054 	dut->mode = SIGMA_MODE_STATION;
6055 	ifname = get_main_ifname(dut);
6056 	if (wpa_command(ifname, "PING") != 0) {
6057 		sigma_dut_print(dut, DUT_MSG_ERROR, "Supplicant not running");
6058 		return ERROR_SEND_STATUS;
6059 	}
6060 
6061 	wpa_command(ifname, "FLUSH");
6062 	net_id = add_network_common(dut, conn, ifname, cmd);
6063 	if (net_id < 0) {
6064 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add network");
6065 		return net_id;
6066 	}
6067 
6068 	/* TODO: mode=2 for the AP; in the future, replace for mode PCP */
6069 	if (set_network(ifname, net_id, "mode", "2") < 0) {
6070 		sigma_dut_print(dut, DUT_MSG_ERROR,
6071 				"Failed to set supplicant network mode");
6072 		return ERROR_SEND_STATUS;
6073 	}
6074 
6075 	if (set_network(ifname, net_id, "pbss", "1") < 0)
6076 		return -2;
6077 
6078 	sigma_dut_print(dut, DUT_MSG_DEBUG,
6079 			"Supplicant set network with mode 2. network_id %d",
6080 			net_id);
6081 
6082 	if (set_network(ifname, net_id, "wps_disabled", "0") < 0) {
6083 		sigma_dut_print(dut, DUT_MSG_INFO,
6084 				"Failed to set supplicant to WPS ENABLE");
6085 		return ERROR_SEND_STATUS;
6086 	}
6087 
6088 	val = get_param(cmd, "Security");
6089 	if (val && strcasecmp(val, "OPEN") == 0) {
6090 		dut->ap_key_mgmt = AP_OPEN;
6091 		if (set_network(ifname, net_id, "key_mgmt", "NONE") < 0) {
6092 			sigma_dut_print(dut, DUT_MSG_ERROR,
6093 					"Failed to set supplicant to %s security",
6094 					val);
6095 			return ERROR_SEND_STATUS;
6096 		}
6097 	} else if (val && strcasecmp(val, "WPA2-PSK") == 0) {
6098 		dut->ap_key_mgmt = AP_WPA2_PSK;
6099 		if (set_network(ifname, net_id, "key_mgmt", "WPA-PSK") < 0) {
6100 			sigma_dut_print(dut, DUT_MSG_ERROR,
6101 					"Failed to set supplicant to %s security",
6102 					val);
6103 			return ERROR_SEND_STATUS;
6104 		}
6105 
6106 		if (set_network(ifname, net_id, "proto", "RSN") < 0) {
6107 			sigma_dut_print(dut, DUT_MSG_ERROR,
6108 					"Failed to set supplicant to proto RSN");
6109 			return ERROR_SEND_STATUS;
6110 		}
6111 	} else if (val) {
6112 		sigma_dut_print(dut, DUT_MSG_ERROR,
6113 				"Requested Security %s is not supported on 60GHz",
6114 				val);
6115 		return INVALID_SEND_STATUS;
6116 	}
6117 
6118 	val = get_param(cmd, "Encrypt");
6119 	if (val && strcasecmp(val, "AES-GCMP") == 0) {
6120 		if (set_network(ifname, net_id, "pairwise", "GCMP") < 0) {
6121 			sigma_dut_print(dut, DUT_MSG_ERROR,
6122 					"Failed to set supplicant to pairwise GCMP");
6123 			return ERROR_SEND_STATUS;
6124 		}
6125 		if (set_network(ifname, net_id, "group", "GCMP") < 0) {
6126 			sigma_dut_print(dut, DUT_MSG_ERROR,
6127 					"Failed to set supplicant to group GCMP");
6128 			return ERROR_SEND_STATUS;
6129 		}
6130 	} else if (val) {
6131 		sigma_dut_print(dut, DUT_MSG_ERROR,
6132 				"Requested Encrypt %s is not supported on 60 GHz",
6133 				val);
6134 		return INVALID_SEND_STATUS;
6135 	}
6136 
6137 	val = get_param(cmd, "PSK");
6138 	if (val && set_network_quoted(ifname, net_id, "psk", val) < 0) {
6139 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set psk %s",
6140 				val);
6141 		return ERROR_SEND_STATUS;
6142 	}
6143 
6144 	/* Convert 60G channel to freq */
6145 	switch (dut->ap_channel) {
6146 	case 1:
6147 		val = "58320";
6148 		break;
6149 	case 2:
6150 		val = "60480";
6151 		break;
6152 	case 3:
6153 		val = "62640";
6154 		break;
6155 	default:
6156 		sigma_dut_print(dut, DUT_MSG_ERROR,
6157 				"Failed to configure channel %d. Not supported",
6158 				dut->ap_channel);
6159 		return ERROR_SEND_STATUS;
6160 	}
6161 
6162 	if (set_network(ifname, net_id, "frequency", val) < 0) {
6163 		sigma_dut_print(dut, DUT_MSG_ERROR,
6164 				"Failed to set supplicant network frequency");
6165 		return ERROR_SEND_STATUS;
6166 	}
6167 
6168 	if (dut->eap_fragment) {
6169 		sigma_dut_print(dut, DUT_MSG_DEBUG,
6170 				"Set EAP fragment size to 128 bytes.");
6171 		if (set_network(ifname, net_id, "fragment_size", "128") < 0)
6172 			return ERROR_SEND_STATUS;
6173 	}
6174 
6175 	sigma_dut_print(dut, DUT_MSG_DEBUG,
6176 			"Supplicant set network with frequency");
6177 
6178 	snprintf(buf, sizeof(buf), "SELECT_NETWORK %d", net_id);
6179 	if (wpa_command(ifname, buf) < 0) {
6180 		sigma_dut_print(dut, DUT_MSG_INFO,
6181 				"Failed to select network id %d on %s",
6182 				net_id, ifname);
6183 		return ERROR_SEND_STATUS;
6184 	}
6185 
6186 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Selected network");
6187 
6188 	return SUCCESS_SEND_STATUS;
6189 }
6190 
6191 
wil6210_set_abft_len(struct sigma_dut * dut,int abft_len)6192 static int wil6210_set_abft_len(struct sigma_dut *dut, int abft_len)
6193 {
6194 	char buf[128], fname[128];
6195 	FILE *f;
6196 	int res;
6197 
6198 	if (wil6210_get_debugfs_dir(dut, buf, sizeof(buf))) {
6199 		sigma_dut_print(dut, DUT_MSG_ERROR,
6200 				"failed to get wil6210 debugfs dir");
6201 		return -1;
6202 	}
6203 
6204 	res = snprintf(fname, sizeof(fname), "%s/abft_len", buf);
6205 	if (res < 0 || res >= sizeof(fname))
6206 		return -1;
6207 	f = fopen(fname, "w");
6208 	if (!f) {
6209 		sigma_dut_print(dut, DUT_MSG_ERROR,
6210 				"failed to open: %s", fname);
6211 		return -1;
6212 	}
6213 
6214 	fprintf(f, "%d\n", abft_len);
6215 	fclose(f);
6216 
6217 	return 0;
6218 }
6219 
6220 
sta_set_60g_abft_len(struct sigma_dut * dut,struct sigma_conn * conn,int abft_len)6221 int sta_set_60g_abft_len(struct sigma_dut *dut, struct sigma_conn *conn,
6222 			 int abft_len)
6223 {
6224 	switch (get_driver_type(dut)) {
6225 	case DRIVER_WIL6210:
6226 		return wil6210_set_abft_len(dut, abft_len);
6227 	default:
6228 		sigma_dut_print(dut, DUT_MSG_ERROR,
6229 				"set abft_len not supported");
6230 		return -1;
6231 	}
6232 }
6233 
6234 
sta_set_60g_pcp(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)6235 static int sta_set_60g_pcp(struct sigma_dut *dut, struct sigma_conn *conn,
6236 			    struct sigma_cmd *cmd)
6237 {
6238 	const char *val;
6239 	unsigned int abft_len = 1; /* default is one slot */
6240 
6241 	if (dut->dev_role != DEVROLE_PCP) {
6242 		send_resp(dut, conn, SIGMA_INVALID,
6243 			  "ErrorCode,Invalid DevRole");
6244 		return 0;
6245 	}
6246 
6247 	val = get_param(cmd, "SSID");
6248 	if (val) {
6249 		if (strlen(val) > sizeof(dut->ap_ssid) - 1) {
6250 			send_resp(dut, conn, SIGMA_INVALID,
6251 				  "ErrorCode,Invalid SSID");
6252 			return -1;
6253 		}
6254 
6255 		strlcpy(dut->ap_ssid, val, sizeof(dut->ap_ssid));
6256 	}
6257 
6258 	val = get_param(cmd, "CHANNEL");
6259 	if (val) {
6260 		const char *pos;
6261 
6262 		dut->ap_channel = atoi(val);
6263 		pos = strchr(val, ';');
6264 		if (pos) {
6265 			pos++;
6266 			dut->ap_channel_1 = atoi(pos);
6267 		}
6268 	}
6269 
6270 	switch (dut->ap_channel) {
6271 	case 1:
6272 	case 2:
6273 	case 3:
6274 		break;
6275 	default:
6276 		sigma_dut_print(dut, DUT_MSG_ERROR,
6277 				"Channel %d is not supported", dut->ap_channel);
6278 		send_resp(dut, conn, SIGMA_ERROR,
6279 			  "Requested channel is not supported");
6280 		return -1;
6281 	}
6282 
6283 	val = get_param(cmd, "BCNINT");
6284 	if (val)
6285 		dut->ap_bcnint = atoi(val);
6286 
6287 	val = get_param(cmd, "AllocType");
6288 	if (val) {
6289 		send_resp(dut, conn, SIGMA_ERROR,
6290 			  "ErrorCode,AllocType is not supported yet");
6291 		return -1;
6292 	}
6293 
6294 	val = get_param(cmd, "PercentBI");
6295 	if (val) {
6296 		send_resp(dut, conn, SIGMA_ERROR,
6297 			  "ErrorCode,PercentBI is not supported yet");
6298 		return -1;
6299 	}
6300 
6301 	val = get_param(cmd, "CBAPOnly");
6302 	if (val) {
6303 		send_resp(dut, conn, SIGMA_ERROR,
6304 			  "ErrorCode,CBAPOnly is not supported yet");
6305 		return -1;
6306 	}
6307 
6308 	val = get_param(cmd, "AMPDU");
6309 	if (val) {
6310 		if (strcasecmp(val, "Enable") == 0)
6311 			dut->ap_ampdu = 1;
6312 		else if (strcasecmp(val, "Disable") == 0)
6313 			dut->ap_ampdu = 2;
6314 		else {
6315 			send_resp(dut, conn, SIGMA_ERROR,
6316 				  "ErrorCode,AMPDU value is not Enable nor Disabled");
6317 			return -1;
6318 		}
6319 	}
6320 
6321 	val = get_param(cmd, "AMSDU");
6322 	if (val) {
6323 		if (strcasecmp(val, "Enable") == 0)
6324 			dut->ap_amsdu = 1;
6325 		else if (strcasecmp(val, "Disable") == 0)
6326 			dut->ap_amsdu = 2;
6327 	}
6328 
6329 	val = get_param(cmd, "NumMSDU");
6330 	if (val) {
6331 		send_resp(dut, conn, SIGMA_ERROR,
6332 			  "ErrorCode, NumMSDU is not supported yet");
6333 		return -1;
6334 	}
6335 
6336 	val = get_param(cmd, "ABFTLRang");
6337 	if (val) {
6338 		sigma_dut_print(dut, DUT_MSG_DEBUG,
6339 				"ABFTLRang parameter %s", val);
6340 		if (strcmp(val, "Gt1") == 0)
6341 			abft_len = 2; /* 2 slots in this case */
6342 	}
6343 
6344 	if (sta_set_60g_abft_len(dut, conn, abft_len)) {
6345 		send_resp(dut, conn, SIGMA_ERROR,
6346 			  "ErrorCode, Can't set ABFT length");
6347 		return -1;
6348 	}
6349 
6350 	if (sta_pcp_start(dut, conn, cmd) < 0) {
6351 		send_resp(dut, conn, SIGMA_ERROR,
6352 			  "ErrorCode, Can't start PCP role");
6353 		return -1;
6354 	}
6355 
6356 	return sta_set_60g_common(dut, conn, cmd);
6357 }
6358 
6359 
sta_set_60g_sta(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)6360 static int sta_set_60g_sta(struct sigma_dut *dut, struct sigma_conn *conn,
6361 			   struct sigma_cmd *cmd)
6362 {
6363 	const char *val = get_param(cmd, "DiscoveryMode");
6364 
6365 	if (dut->dev_role != DEVROLE_STA) {
6366 		send_resp(dut, conn, SIGMA_INVALID,
6367 			  "ErrorCode,Invalid DevRole");
6368 		return 0;
6369 	}
6370 
6371 	if (val) {
6372 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Discovery: %s", val);
6373 		/* Ignore Discovery mode till Driver expose API. */
6374 #if 0
6375 		if (strcasecmp(val, "1") == 0) {
6376 			send_resp(dut, conn, SIGMA_INVALID,
6377 				  "ErrorCode,DiscoveryMode 1 not supported");
6378 			return 0;
6379 		}
6380 
6381 		if (strcasecmp(val, "0") == 0) {
6382 			/* OK */
6383 		} else {
6384 			send_resp(dut, conn, SIGMA_INVALID,
6385 				  "ErrorCode,DiscoveryMode not supported");
6386 			return 0;
6387 		}
6388 #endif
6389 	}
6390 
6391 	if (start_sta_mode(dut) != 0)
6392 		return ERROR_SEND_STATUS;
6393 	return sta_set_60g_common(dut, conn, cmd);
6394 }
6395 
6396 
cmd_sta_disconnect(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)6397 static enum sigma_cmd_result cmd_sta_disconnect(struct sigma_dut *dut,
6398 						struct sigma_conn *conn,
6399 						struct sigma_cmd *cmd)
6400 {
6401 	const char *intf = get_param(cmd, "Interface");
6402 	const char *val = get_param(cmd, "maintain_profile");
6403 
6404 	if (dut->program == PROGRAM_OCE ||
6405 	    dut->program == PROGRAM_HE ||
6406 	    (val && atoi(val) == 1)) {
6407 		wpa_command(intf, "DISCONNECT");
6408 		return 1;
6409 	}
6410 
6411 	disconnect_station(dut);
6412 	/* Try to ignore old scan results to avoid HS 2.0R2 test case failures
6413 	 * due to cached results. */
6414 	wpa_command(intf, "SET ignore_old_scan_res 1");
6415 	wpa_command(intf, "BSS_FLUSH");
6416 	return 1;
6417 }
6418 
6419 
cmd_sta_reassoc(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)6420 static enum sigma_cmd_result cmd_sta_reassoc(struct sigma_dut *dut,
6421 					     struct sigma_conn *conn,
6422 					     struct sigma_cmd *cmd)
6423 {
6424 	const char *intf = get_param(cmd, "Interface");
6425 	const char *bssid = get_param(cmd, "bssid");
6426 	const char *val = get_param(cmd, "CHANNEL");
6427 	const char *freq_val = get_param(cmd, "ChnlFreq");
6428 	struct wpa_ctrl *ctrl;
6429 	char buf[1000];
6430 	char result[32];
6431 	int res;
6432 	int chan = 0;
6433 	int freq = 0;
6434 	enum sigma_cmd_result status = STATUS_SENT;
6435 	int fastreassoc = 1;
6436 	int ft_ds = 0;
6437 
6438 	if (bssid == NULL) {
6439 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Missing bssid "
6440 			  "argument");
6441 		return STATUS_SENT_ERROR;
6442 	}
6443 
6444 	if (val)
6445 		chan = atoi(val);
6446 
6447 	if (freq_val)
6448 		freq = atoi(freq_val);
6449 
6450 	if (wifi_chip_type != DRIVER_WCN && wifi_chip_type != DRIVER_AR6003) {
6451 		/* The current network may be from sta_associate or
6452 		 * sta_hs2_associate
6453 		 */
6454 		if (set_network(intf, dut->infra_network_id, "bssid", bssid) <
6455 		    0 ||
6456 		    set_network(intf, 0, "bssid", bssid) < 0)
6457 			return ERROR_SEND_STATUS;
6458 	}
6459 
6460 	ctrl = open_wpa_mon(intf);
6461 	if (ctrl == NULL) {
6462 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
6463 				"wpa_supplicant monitor connection");
6464 		return ERROR_SEND_STATUS;
6465 	}
6466 
6467 	if (get_wpa_status(get_station_ifname(dut), "wpa_state", result,
6468 			   sizeof(result)) < 0 ||
6469 	    strncmp(result, "COMPLETED", 9) != 0) {
6470 		sigma_dut_print(dut, DUT_MSG_DEBUG,
6471 				"sta_reassoc: Not connected");
6472 		fastreassoc = 0;
6473 	} else if (dut->sta_ft_ds) {
6474 		sigma_dut_print(dut, DUT_MSG_DEBUG,
6475 				"sta_reassoc: Use FT-over-DS");
6476 		ft_ds = 1;
6477 	}
6478 
6479 	if (dut->rsne_override) {
6480 #ifdef NL80211_SUPPORT
6481 		if (get_driver_type(dut) == DRIVER_WCN &&
6482 		    dut->config_rsnie == 0) {
6483 			sta_config_params(dut, intf, STA_SET_RSNIE, 1);
6484 			dut->config_rsnie = 1;
6485 		}
6486 #endif /* NL80211_SUPPORT */
6487 		snprintf(buf, sizeof(buf), "TEST_ASSOC_IE %s",
6488 			 dut->rsne_override);
6489 		if (wpa_command(intf, buf) < 0) {
6490 			send_resp(dut, conn, SIGMA_ERROR,
6491 				  "ErrorCode,Failed to set DEV_CONFIGURE_IE RSNE override");
6492 			return 0;
6493 		}
6494 	}
6495 
6496 	if (ft_ds) {
6497 		if (chan || freq) {
6498 			if (!freq)
6499 				freq = channel_to_freq(dut, chan);
6500 			if (!freq) {
6501 				sigma_dut_print(dut, DUT_MSG_ERROR,
6502 						"Invalid channel number provided: %d",
6503 						chan);
6504 				send_resp(dut, conn, SIGMA_INVALID,
6505 					  "ErrorCode,Invalid channel number");
6506 				goto close_mon_conn;
6507 			}
6508 			res = snprintf(buf, sizeof(buf),
6509 				       "SCAN TYPE=ONLY freq=%d", freq);
6510 		} else {
6511 			res = snprintf(buf, sizeof(buf), "SCAN TYPE=ONLY");
6512 		}
6513 		if (res < 0 || res >= (int) sizeof(buf)) {
6514 			send_resp(dut, conn, SIGMA_ERROR,
6515 				  "ErrorCode,snprintf failed");
6516 			goto close_mon_conn;
6517 		}
6518 		if (wpa_command(intf, buf) < 0) {
6519 			sigma_dut_print(dut, DUT_MSG_INFO,
6520 					"Failed to start scan");
6521 			send_resp(dut, conn, SIGMA_ERROR,
6522 				  "ErrorCode,scan failed");
6523 			goto close_mon_conn;
6524 		}
6525 
6526 		res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-SCAN-RESULTS",
6527 					buf, sizeof(buf));
6528 		if (res < 0) {
6529 			sigma_dut_print(dut, DUT_MSG_INFO,
6530 					"Scan did not complete");
6531 			send_resp(dut, conn, SIGMA_ERROR,
6532 				  "ErrorCode,scan did not complete");
6533 			goto close_mon_conn;
6534 		}
6535 
6536 		res = snprintf(buf, sizeof(buf), "FT_DS %s", bssid);
6537 		if (res > 0 && res < (int) sizeof(buf))
6538 			res = wpa_command(intf, buf);
6539 
6540 		if (res < 0 || res >= (int) sizeof(buf)) {
6541 			send_resp(dut, conn, SIGMA_ERROR,
6542 				  "errorCode,FT_DS command failed");
6543 			status = STATUS_SENT_ERROR;
6544 			goto close_mon_conn;
6545 		}
6546 	} else if (wifi_chip_type == DRIVER_WCN && fastreassoc) {
6547 		if (chan || freq) {
6548 			if (!freq)
6549 				freq = channel_to_freq(dut, chan);
6550 			if (!freq) {
6551 				sigma_dut_print(dut, DUT_MSG_ERROR,
6552 						"Invalid channel number provided: %d",
6553 						chan);
6554 				send_resp(dut, conn, SIGMA_INVALID,
6555 					  "ErrorCode,Invalid channel number");
6556 				goto close_mon_conn;
6557 			}
6558 			res = snprintf(buf, sizeof(buf),
6559 				       "SCAN TYPE=ONLY freq=%d", freq);
6560 		} else {
6561 			res = snprintf(buf, sizeof(buf), "SCAN TYPE=ONLY");
6562 		}
6563 		if (res < 0 || res >= (int) sizeof(buf)) {
6564 			send_resp(dut, conn, SIGMA_ERROR,
6565 				  "ErrorCode,snprintf failed");
6566 			goto close_mon_conn;
6567 		}
6568 		if (wpa_command(intf, buf) < 0) {
6569 			sigma_dut_print(dut, DUT_MSG_INFO,
6570 					"Failed to start scan");
6571 			send_resp(dut, conn, SIGMA_ERROR,
6572 				  "ErrorCode,scan failed");
6573 			goto close_mon_conn;
6574 		}
6575 
6576 		res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-SCAN-RESULTS",
6577 					buf, sizeof(buf));
6578 		if (res < 0) {
6579 			sigma_dut_print(dut, DUT_MSG_INFO,
6580 					"Scan did not complete");
6581 			send_resp(dut, conn, SIGMA_ERROR,
6582 				  "ErrorCode,scan did not complete");
6583 			goto close_mon_conn;
6584 		}
6585 
6586 		if (set_network(intf, dut->infra_network_id, "bssid", "any")
6587 		    < 0) {
6588 			sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
6589 					"bssid to any during FASTREASSOC");
6590 			status = ERROR_SEND_STATUS;
6591 			goto close_mon_conn;
6592 		}
6593 		res = snprintf(buf, sizeof(buf), "FASTREASSOC %s %d",
6594 			       bssid, chan);
6595 		if (res < 0 || res >= (int) sizeof(buf) ||
6596 		    wcn_driver_cmd(intf, buf) < 0) {
6597 			send_resp(dut, conn, SIGMA_ERROR,
6598 				  "errorCode,Failed to run FASTREASSOC");
6599 			goto close_mon_conn;
6600 		}
6601 		sigma_dut_print(dut, DUT_MSG_INFO,
6602 				"sta_reassoc: Run %s successful", buf);
6603 	} else if (wpa_command(intf, "REASSOCIATE")) {
6604 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
6605 			  "request reassociation");
6606 		goto close_mon_conn;
6607 	}
6608 
6609 	res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
6610 				buf, sizeof(buf));
6611 	if (res < 0) {
6612 		send_resp(dut, conn, SIGMA_ERROR,
6613 			  "errorCode,Connection did not complete");
6614 		status = STATUS_SENT_ERROR;
6615 		goto close_mon_conn;
6616 	}
6617 	status = SUCCESS_SEND_STATUS;
6618 
6619 close_mon_conn:
6620 	wpa_ctrl_detach(ctrl);
6621 	wpa_ctrl_close(ctrl);
6622 	return status;
6623 }
6624 
6625 
hs2_clear_credentials(const char * intf)6626 static void hs2_clear_credentials(const char *intf)
6627 {
6628 	wpa_command(intf, "REMOVE_CRED all");
6629 }
6630 
6631 
6632 #ifdef __linux__
wil6210_get_aid(struct sigma_dut * dut,const char * bssid,unsigned int * aid)6633 static int wil6210_get_aid(struct sigma_dut *dut, const char *bssid,
6634 			   unsigned int *aid)
6635 {
6636 	const char *pattern = "AID[ \t]+([0-9]+)";
6637 
6638 	return wil6210_get_sta_info_field(dut, bssid, pattern, aid);
6639 }
6640 #endif /* __linux__ */
6641 
6642 
sta_get_aid_60g(struct sigma_dut * dut,const char * bssid,unsigned int * aid)6643 static int sta_get_aid_60g(struct sigma_dut *dut, const char *bssid,
6644 			   unsigned int *aid)
6645 {
6646 	switch (get_driver_type(dut)) {
6647 #ifdef __linux__
6648 	case DRIVER_WIL6210:
6649 		return wil6210_get_aid(dut, bssid, aid);
6650 #endif /* __linux__ */
6651 	default:
6652 		sigma_dut_print(dut, DUT_MSG_ERROR, "get AID not supported");
6653 		return -1;
6654 	}
6655 }
6656 
6657 
sta_get_parameter_60g(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)6658 static int sta_get_parameter_60g(struct sigma_dut *dut, struct sigma_conn *conn,
6659 				 struct sigma_cmd *cmd)
6660 {
6661 	char buf[MAX_CMD_LEN];
6662 	char bss_list[MAX_CMD_LEN];
6663 	const char *parameter = get_param(cmd, "Parameter");
6664 
6665 	if (parameter == NULL)
6666 		return -1;
6667 
6668 	if (strcasecmp(parameter, "AID") == 0) {
6669 		unsigned int aid = 0;
6670 		char bssid[20];
6671 
6672 		if (get_wpa_status(get_station_ifname(dut), "bssid",
6673 				   bssid, sizeof(bssid)) < 0) {
6674 			sigma_dut_print(dut, DUT_MSG_ERROR,
6675 					"could not get bssid");
6676 			return -2;
6677 		}
6678 
6679 		if (sta_get_aid_60g(dut, bssid, &aid))
6680 			return -2;
6681 
6682 		snprintf(buf, sizeof(buf), "aid,%d", aid);
6683 		sigma_dut_print(dut, DUT_MSG_INFO, "%s", buf);
6684 		send_resp(dut, conn, SIGMA_COMPLETE, buf);
6685 		return 0;
6686 	}
6687 
6688 	if (strcasecmp(parameter, "DiscoveredDevList") == 0) {
6689 		char *bss_line;
6690 		char *bss_id = NULL;
6691 		const char *ifname = get_param(cmd, "Interface");
6692 		char *saveptr;
6693 
6694 		if (ifname == NULL) {
6695 			sigma_dut_print(dut, DUT_MSG_INFO,
6696 					"For get DiscoveredDevList need Interface name.");
6697 			return -1;
6698 		}
6699 
6700 		/*
6701 		 * Use "BSS RANGE=ALL MASK=0x2" which provides a list
6702 		 * of BSSIDs in "bssid=<BSSID>\n"
6703 		 */
6704 		if (wpa_command_resp(ifname, "BSS RANGE=ALL MASK=0x2",
6705 				     bss_list,
6706 				     sizeof(bss_list)) < 0) {
6707 			sigma_dut_print(dut, DUT_MSG_ERROR,
6708 					"Failed to get bss list");
6709 			return -1;
6710 		}
6711 
6712 		sigma_dut_print(dut, DUT_MSG_DEBUG,
6713 				"bss list for ifname:%s is:%s",
6714 				ifname, bss_list);
6715 
6716 		snprintf(buf, sizeof(buf), "DeviceList");
6717 		bss_line = strtok_r(bss_list, "\n", &saveptr);
6718 		while (bss_line) {
6719 			if (sscanf(bss_line, "bssid=%ms", &bss_id) > 0 &&
6720 			    bss_id) {
6721 				int len;
6722 
6723 				len = snprintf(buf + strlen(buf),
6724 					       sizeof(buf) - strlen(buf),
6725 					       ",%s", bss_id);
6726 				free(bss_id);
6727 				bss_id = NULL;
6728 				if (len < 0) {
6729 					sigma_dut_print(dut,
6730 							DUT_MSG_ERROR,
6731 							"Failed to read BSSID");
6732 					send_resp(dut, conn, SIGMA_ERROR,
6733 						  "ErrorCode,Failed to read BSS ID");
6734 					return 0;
6735 				}
6736 
6737 				if ((size_t) len >= sizeof(buf) - strlen(buf)) {
6738 					sigma_dut_print(dut,
6739 							DUT_MSG_ERROR,
6740 							"Response buf too small for list");
6741 					send_resp(dut, conn,
6742 						  SIGMA_ERROR,
6743 						  "ErrorCode,Response buf too small for list");
6744 					return 0;
6745 				}
6746 			}
6747 
6748 			bss_line = strtok_r(NULL, "\n", &saveptr);
6749 		}
6750 
6751 		sigma_dut_print(dut, DUT_MSG_INFO, "DiscoveredDevList is %s",
6752 				buf);
6753 		send_resp(dut, conn, SIGMA_COMPLETE, buf);
6754 		return 0;
6755 	}
6756 
6757 	send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
6758 	return 0;
6759 }
6760 
6761 
sta_get_parameter_he(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)6762 static int sta_get_parameter_he(struct sigma_dut *dut, struct sigma_conn *conn,
6763 				struct sigma_cmd *cmd)
6764 {
6765 	char buf[MAX_CMD_LEN];
6766 	const char *parameter = get_param(cmd, "Parameter");
6767 
6768 	if (!parameter)
6769 		return -1;
6770 
6771 	if (strcasecmp(parameter, "RSSI") == 0) {
6772 		char rssi[10];
6773 
6774 		if (get_wpa_signal_poll(dut, get_station_ifname(dut), "RSSI",
6775 					rssi, sizeof(rssi)) < 0) {
6776 			sigma_dut_print(dut, DUT_MSG_ERROR,
6777 					"Could not get RSSI");
6778 			return -2;
6779 		}
6780 
6781 		snprintf(buf, sizeof(buf), "rssi,%s", rssi);
6782 		sigma_dut_print(dut, DUT_MSG_INFO, "RSSI %s", buf);
6783 		send_resp(dut, conn, SIGMA_COMPLETE, buf);
6784 		return 0;
6785 	}
6786 
6787 	send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
6788 	return 0;
6789 }
6790 
6791 
6792 #ifdef NL80211_SUPPORT
6793 
6794 struct station_info {
6795 	uint64_t filled;
6796 	uint32_t beacon_mic_error_count;
6797 	uint32_t beacon_replay_count;
6798 };
6799 
6800 
qca_get_sta_info_handler(struct nl_msg * msg,void * arg)6801 static int qca_get_sta_info_handler(struct nl_msg *msg, void *arg)
6802 {
6803 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
6804 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6805 	struct station_info *data = arg;
6806 	struct nlattr *info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1];
6807 	static struct nla_policy info_policy[
6808 		QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1] = {
6809 		[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT] = {
6810 			.type = NLA_U32
6811 		},
6812 		[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT] = {
6813 			.type = NLA_U32
6814 		},
6815 	};
6816 
6817 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6818 		  genlmsg_attrlen(gnlh, 0), NULL);
6819 
6820 	if (!tb[NL80211_ATTR_VENDOR_DATA])
6821 		return NL_SKIP;
6822 
6823 	if (nla_parse_nested(info, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX,
6824 			     tb[NL80211_ATTR_VENDOR_DATA], info_policy)) {
6825 		return NL_SKIP;
6826 	}
6827 
6828 	if (info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT]) {
6829 		data->filled |=
6830 			BIT_ULL(QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT);
6831 		data->beacon_mic_error_count =
6832 			nla_get_u32(info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT]);
6833 	}
6834 
6835 	if (info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT]) {
6836 		data->filled |=
6837 			BIT_ULL(QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT);
6838 		data->beacon_replay_count =
6839 			nla_get_u32(info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT]);
6840 	}
6841 
6842 	return NL_SKIP;
6843 }
6844 
6845 
qca_nl80211_get_sta_info(struct sigma_dut * dut,const char * intf,struct station_info * sta_data)6846 static int qca_nl80211_get_sta_info(struct sigma_dut *dut, const char *intf,
6847 				    struct station_info *sta_data)
6848 {
6849 	struct nl_msg *msg;
6850 	int ifindex, ret;
6851 
6852 	ifindex = if_nametoindex(intf);
6853 	if (ifindex == 0) {
6854 		sigma_dut_print(dut, DUT_MSG_ERROR,
6855 				"%s: Index for interface %s not found",
6856 				__func__, intf);
6857 		return -1;
6858 	}
6859 
6860 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
6861 				    NL80211_CMD_VENDOR)) ||
6862 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
6863 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
6864 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
6865 			QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO)) {
6866 		sigma_dut_print(dut, DUT_MSG_ERROR,
6867 				"%s: err in adding vendor_cmd", __func__);
6868 		nlmsg_free(msg);
6869 		return -1;
6870 	}
6871 
6872 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg,
6873 				 qca_get_sta_info_handler, sta_data);
6874 	if (ret) {
6875 		sigma_dut_print(dut, DUT_MSG_ERROR,
6876 				"%s: err in send_and_recv_msgs, ret=%d",
6877 				__func__, ret);
6878 	}
6879 	return ret;
6880 }
6881 #endif /* NL80211_SUPPORT */
6882 
6883 
get_bip_mic_error_count(struct sigma_dut * dut,const char * ifname,unsigned int * count)6884 static int get_bip_mic_error_count(struct sigma_dut *dut,
6885 				   const char *ifname,
6886 				   unsigned int *count)
6887 {
6888 #ifdef NL80211_SUPPORT
6889 	struct station_info sta_data;
6890 #endif /* NL80211_SUPPORT */
6891 
6892 	if (get_driver_type(dut) != DRIVER_WCN) {
6893 		sigma_dut_print(dut, DUT_MSG_ERROR,
6894 				"BIP MIC error count not supported");
6895 		return -1;
6896 	}
6897 
6898 #ifdef NL80211_SUPPORT
6899 	if (qca_nl80211_get_sta_info(dut, ifname, &sta_data) != 0 ||
6900 	    !(sta_data.filled &
6901 	      BIT_ULL(QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT))) {
6902 		sigma_dut_print(dut, DUT_MSG_ERROR,
6903 				"BIP MIC error count fetching failed");
6904 		return -1;
6905 	}
6906 
6907 	*count = sta_data.beacon_mic_error_count;
6908 	return 0;
6909 #else /* NL80211_SUPPORT */
6910 	sigma_dut_print(dut, DUT_MSG_ERROR,
6911 			"BIP MIC error count cannot be fetched without NL80211_SUPPORT defined");
6912 	return -1;
6913 #endif /* NL80211_SUPPORT */
6914 }
6915 
6916 
get_cmac_replay_count(struct sigma_dut * dut,const char * ifname,unsigned int * count)6917 static int get_cmac_replay_count(struct sigma_dut *dut, const char *ifname,
6918 				 unsigned int *count)
6919 {
6920 #ifdef NL80211_SUPPORT
6921 	struct station_info sta_data;
6922 #endif /* NL80211_SUPPORT */
6923 
6924 	if (get_driver_type(dut) != DRIVER_WCN) {
6925 		sigma_dut_print(dut, DUT_MSG_ERROR,
6926 				"CMAC reply count not supported");
6927 		return -1;
6928 	}
6929 
6930 #ifdef NL80211_SUPPORT
6931 	if (qca_nl80211_get_sta_info(dut, ifname, &sta_data) != 0 ||
6932 	    !(sta_data.filled &
6933 	      BIT_ULL(QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT))) {
6934 		sigma_dut_print(dut, DUT_MSG_ERROR,
6935 				"CMAC replay count fetching failed");
6936 		return -1;
6937 	}
6938 
6939 	*count = sta_data.beacon_replay_count;
6940 	return 0;
6941 #else /* NL80211_SUPPORT */
6942 	sigma_dut_print(dut, DUT_MSG_ERROR,
6943 			"CMAC replay count cannot be fetched without NL80211_SUPPORT defined");
6944 	return -1;
6945 #endif /* NL80211_SUPPORT */
6946 }
6947 
6948 
sta_get_parameter_wpa3(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)6949 static enum sigma_cmd_result sta_get_parameter_wpa3(struct sigma_dut *dut,
6950 						    struct sigma_conn *conn,
6951 						    struct sigma_cmd *cmd)
6952 {
6953 	char buf[MAX_CMD_LEN];
6954 	const char *ifname = get_param(cmd, "interface");
6955 	const char *parameter = get_param(cmd, "Parameter");
6956 	unsigned int val;
6957 
6958 	if (!ifname || !parameter)
6959 		return INVALID_SEND_STATUS;
6960 
6961 	if (strcasecmp(parameter, "BIPMICErrors") == 0) {
6962 		if (get_bip_mic_error_count(dut, ifname, &val)) {
6963 			send_resp(dut, conn, SIGMA_ERROR,
6964 				  "ErrorCode,Failed to get BIPMICErrors");
6965 			return STATUS_SENT_ERROR;
6966 		}
6967 		snprintf(buf, sizeof(buf), "BIPMICErrors,%d", val);
6968 		sigma_dut_print(dut, DUT_MSG_INFO, "BIPMICErrors %s", buf);
6969 		send_resp(dut, conn, SIGMA_COMPLETE, buf);
6970 		return STATUS_SENT;
6971 	}
6972 
6973 	if (strcasecmp(parameter, "CMACReplays") == 0) {
6974 		if (get_cmac_replay_count(dut, ifname, &val)) {
6975 			send_resp(dut, conn, SIGMA_ERROR,
6976 				  "ErrorCode,Failed to get CMACReplays");
6977 			return STATUS_SENT_ERROR;
6978 		}
6979 		snprintf(buf, sizeof(buf), "CMACReplays,%d", val);
6980 		sigma_dut_print(dut, DUT_MSG_INFO, "CMACReplays %s", buf);
6981 		send_resp(dut, conn, SIGMA_COMPLETE, buf);
6982 		return STATUS_SENT;
6983 	}
6984 
6985 	send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
6986 	return STATUS_SENT_ERROR;
6987 }
6988 
6989 
sta_get_pmk(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)6990 static enum sigma_cmd_result sta_get_pmk(struct sigma_dut *dut,
6991 					 struct sigma_conn *conn,
6992 					 struct sigma_cmd *cmd)
6993 {
6994 	const char *intf = get_param(cmd, "Interface");
6995 	char buf[4096], bssid[20], resp[200], *pos, *tmp;
6996 
6997 	snprintf(buf, sizeof(buf), "PMKSA_GET %d", dut->infra_network_id);
6998 	if (wpa_command_resp(intf, buf, buf, sizeof(buf)) < 0 ||
6999 	    strncmp(buf, "UNKNOWN COMMAND", 15) == 0) {
7000 		send_resp(dut, conn, SIGMA_ERROR,
7001 			  "ErrorCode,PMKSA_GET not supported");
7002 		return STATUS_SENT_ERROR;
7003 	}
7004 
7005 	if (strncmp(buf, "FAIL", 4) == 0 ||
7006 	    get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0) {
7007 		send_resp(dut, conn, SIGMA_ERROR,
7008 			  "ErrorCode,Could not find current network");
7009 		return STATUS_SENT_ERROR;
7010 	}
7011 
7012 	pos = buf;
7013 	while (pos) {
7014 		if (strncmp(pos, bssid, 17) == 0) {
7015 			pos = strchr(pos, ' ');
7016 			if (!pos)
7017 				break;
7018 			pos++;
7019 			pos = strchr(pos, ' ');
7020 			if (!pos)
7021 				break;
7022 			pos++;
7023 			tmp = strchr(pos, ' ');
7024 			if (!tmp)
7025 				break;
7026 			*tmp = '\0';
7027 			break;
7028 		}
7029 		pos = strchr(pos, '\n');
7030 		if (pos)
7031 			pos++;
7032 	}
7033 
7034 	if (!pos) {
7035 		send_resp(dut, conn, SIGMA_ERROR,
7036 			  "ErrorCode,PMK not available");
7037 		return STATUS_SENT_ERROR;
7038 	}
7039 
7040 	snprintf(resp, sizeof(resp), "PMK,%s", pos);
7041 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
7042 	return STATUS_SENT;
7043 }
7044 
7045 
cmd_sta_get_parameter(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)7046 static enum sigma_cmd_result cmd_sta_get_parameter(struct sigma_dut *dut,
7047 						   struct sigma_conn *conn,
7048 						   struct sigma_cmd *cmd)
7049 {
7050 	const char *program = get_param(cmd, "Program");
7051 	const char *parameter = get_param(cmd, "Parameter");
7052 
7053 	if (!parameter)
7054 		return INVALID_SEND_STATUS;
7055 
7056 	if (strcasecmp(parameter, "PMK") == 0)
7057 		return sta_get_pmk(dut, conn, cmd);
7058 
7059 	if (!program)
7060 		return INVALID_SEND_STATUS;
7061 
7062 	if (strcasecmp(program, "P2PNFC") == 0)
7063 		return p2p_cmd_sta_get_parameter(dut, conn, cmd);
7064 
7065 	if (strcasecmp(program, "60ghz") == 0)
7066 		return sta_get_parameter_60g(dut, conn, cmd);
7067 
7068 	if (strcasecmp(program, "he") == 0)
7069 		return sta_get_parameter_he(dut, conn, cmd);
7070 
7071 #ifdef ANDROID_NAN
7072 	if (strcasecmp(program, "NAN") == 0)
7073 		return nan_cmd_sta_get_parameter(dut, conn, cmd);
7074 #endif /* ANDROID_NAN */
7075 
7076 #ifdef MIRACAST
7077 	if (strcasecmp(program, "WFD") == 0 ||
7078 	    strcasecmp(program, "DisplayR2") == 0)
7079 		return miracast_cmd_sta_get_parameter(dut, conn, cmd);
7080 #endif /* MIRACAST */
7081 	if (strcasecmp(program, "WPA3") == 0)
7082 		return sta_get_parameter_wpa3(dut, conn, cmd);
7083 
7084 	send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
7085 	return 0;
7086 }
7087 
7088 
sta_reset_default_ath(struct sigma_dut * dut,const char * intf,const char * type)7089 static void sta_reset_default_ath(struct sigma_dut *dut, const char *intf,
7090 				  const char *type)
7091 {
7092 	char buf[100];
7093 
7094 	if (dut->program == PROGRAM_VHT) {
7095 		run_iwpriv(dut, intf, "chwidth 2");
7096 		run_iwpriv(dut, intf, "mode 11ACVHT80");
7097 		run_iwpriv(dut, intf, "vhtmcs -1");
7098 	}
7099 
7100 	if (dut->program == PROGRAM_HT) {
7101 		run_iwpriv(dut, intf, "chwidth 0");
7102 		run_iwpriv(dut, intf, "mode 11naht40");
7103 		run_iwpriv(dut, intf, "set11NRates 0");
7104 	}
7105 
7106 	if (dut->program == PROGRAM_VHT || dut->program == PROGRAM_HT) {
7107 		run_iwpriv(dut, intf, "powersave 0");
7108 
7109 		/* Reset CTS width */
7110 		snprintf(buf, sizeof(buf), "wifitool %s beeliner_fw_test 54 0",
7111 			 intf);
7112 		if (system(buf) != 0) {
7113 			sigma_dut_print(dut, DUT_MSG_ERROR,
7114 					"wifitool %s beeliner_fw_test 54 0 failed",
7115 					intf);
7116 		}
7117 
7118 		/* Enable Dynamic Bandwidth signalling by default */
7119 		run_iwpriv(dut, intf, "cwmenable 1");
7120 
7121 		snprintf(buf, sizeof(buf), "iwconfig %s rts 2347", intf);
7122 		if (system(buf) != 0) {
7123 			sigma_dut_print(dut, DUT_MSG_ERROR,
7124 					"iwpriv rts failed");
7125 		}
7126 	}
7127 
7128 	if (type && strcasecmp(type, "Testbed") == 0) {
7129 		dut->testbed_flag_txsp = 1;
7130 		dut->testbed_flag_rxsp = 1;
7131 		/* STA has to set spatial stream to 2 per Appendix H */
7132 		run_iwpriv(dut, intf, "vht_mcsmap 0xfff0");
7133 
7134 		/* Disable LDPC per Appendix H */
7135 		run_iwpriv(dut, intf, "ldpc 0");
7136 
7137 		run_iwpriv(dut, intf, "amsdu 1");
7138 
7139 		/* TODO: Disable STBC 2x1 transmit and receive */
7140 		run_iwpriv(dut, intf, "tx_stbc 0");
7141 		run_iwpriv(dut, intf, "rx_stbc 0");
7142 
7143 		/* STA has to disable Short GI per Appendix H */
7144 		run_iwpriv(dut, intf, "shortgi 0");
7145 	}
7146 
7147 	if (type && strcasecmp(type, "DUT") == 0) {
7148 		run_iwpriv(dut, intf, "nss 3");
7149 		dut->sta_nss = 3;
7150 
7151 		run_iwpriv(dut, intf, "shortgi 1");
7152 	}
7153 }
7154 
7155 
7156 #ifdef NL80211_SUPPORT
sta_set_he_mcs(struct sigma_dut * dut,const char * intf,enum he_mcs_config mcs)7157 static int sta_set_he_mcs(struct sigma_dut *dut, const char *intf,
7158 			  enum he_mcs_config mcs)
7159 {
7160 	return wcn_wifi_test_config_set_u8(
7161 		dut, intf, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS, mcs);
7162 }
7163 #endif /* NL80211_SUPPORT */
7164 
7165 
sta_set_action_tx_in_he_tb_ppdu(struct sigma_dut * dut,const char * intf,int enable)7166 static int sta_set_action_tx_in_he_tb_ppdu(struct sigma_dut *dut,
7167 					   const char *intf, int enable)
7168 {
7169 #ifdef NL80211_SUPPORT
7170 	return wcn_wifi_test_config_set_u8(
7171 		dut, intf,
7172 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU,
7173 		enable);
7174 #else /* NL80211_SUPPORT */
7175 	sigma_dut_print(dut, DUT_MSG_ERROR,
7176 			"HE action Tx TB PPDU cannot be set without NL80211_SUPPORT defined");
7177 	return -1;
7178 #endif /* NL80211_SUPPORT */
7179 }
7180 
7181 
sta_set_heconfig_and_wep_tkip(struct sigma_dut * dut,const char * intf,int enable)7182 static int sta_set_heconfig_and_wep_tkip(struct sigma_dut *dut,
7183 					 const char *intf, int enable)
7184 {
7185 #ifdef NL80211_SUPPORT
7186 	return wcn_wifi_test_config_set_u8(
7187 		dut, intf, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE,
7188 		enable);
7189 #else /* NL80211_SUPPORT */
7190 	sigma_dut_print(dut, DUT_MSG_ERROR,
7191 			"HE config enablement cannot be changed without NL80211_SUPPORT defined");
7192 	return -1;
7193 #endif /* NL80211_SUPPORT */
7194 }
7195 
7196 
7197 #ifdef NL80211_SUPPORT
7198 
sta_set_he_testbed_def(struct sigma_dut * dut,const char * intf,int cfg)7199 static int sta_set_he_testbed_def(struct sigma_dut *dut,
7200 				  const char *intf, int cfg)
7201 {
7202 	return wcn_wifi_test_config_set_u8(
7203 		dut, intf,
7204 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS,
7205 		cfg);
7206 }
7207 
7208 
sta_set_2g_vht_supp(struct sigma_dut * dut,const char * intf,int cfg)7209 static int sta_set_2g_vht_supp(struct sigma_dut *dut, const char *intf, int cfg)
7210 {
7211 	return wcn_wifi_test_config_set_u8(
7212 		dut, intf, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT,
7213 		cfg);
7214 }
7215 
7216 #endif /* NL80211_SUPPORT */
7217 
7218 
sta_set_addba_buf_size(struct sigma_dut * dut,const char * intf,int bufsize)7219 int sta_set_addba_buf_size(struct sigma_dut *dut,
7220 			   const char *intf, int bufsize)
7221 {
7222 #ifdef NL80211_SUPPORT
7223 	return wcn_wifi_test_config_set_u16(
7224 		dut, intf,
7225 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE, bufsize);
7226 #else /* NL80211_SUPPORT */
7227 	sigma_dut_print(dut, DUT_MSG_ERROR,
7228 			"AddBA bufsize cannot be changed without NL80211_SUPPORT defined");
7229 	return -1;
7230 #endif /* NL80211_SUPPORT */
7231 }
7232 
7233 
sta_set_tx_beamformee(struct sigma_dut * dut,const char * intf,int enable)7234 static int sta_set_tx_beamformee(struct sigma_dut *dut, const char *intf,
7235 				 int enable)
7236 {
7237 #ifdef NL80211_SUPPORT
7238 	return wcn_wifi_test_config_set_u8(
7239 		dut, intf,
7240 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE,
7241 		enable);
7242 #else /* NL80211_SUPPORT */
7243 	sigma_dut_print(dut, DUT_MSG_ERROR,
7244 			"tx beamformee cannot be changed without NL80211_SUPPORT defined");
7245 	return -1;
7246 #endif /* NL80211_SUPPORT */
7247 }
7248 
7249 
sta_set_beamformee_sts(struct sigma_dut * dut,const char * intf,int val)7250 static int sta_set_beamformee_sts(struct sigma_dut *dut, const char *intf,
7251 				  int val)
7252 {
7253 #ifdef NL80211_SUPPORT
7254 	return wcn_wifi_test_config_set_u8(
7255 		dut, intf,
7256 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS,
7257 		val);
7258 #else /* NL80211_SUPPORT */
7259 	sigma_dut_print(dut, DUT_MSG_ERROR,
7260 			"beamformee sts cannot be changed without NL80211_SUPPORT defined");
7261 	return -1;
7262 #endif /* NL80211_SUPPORT */
7263 }
7264 
7265 
7266 #ifdef NL80211_SUPPORT
sta_set_mac_padding_duration(struct sigma_dut * dut,const char * intf,enum qca_wlan_he_mac_padding_dur val)7267 static int sta_set_mac_padding_duration(struct sigma_dut *dut, const char *intf,
7268 					enum qca_wlan_he_mac_padding_dur val)
7269 {
7270 	return wcn_wifi_test_config_set_u8(
7271 		dut, intf,
7272 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR, val);
7273 }
7274 #endif /* NL80211_SUPPORT */
7275 
7276 
sta_set_tx_su_ppdu_cfg(struct sigma_dut * dut,const char * intf,int val)7277 static int sta_set_tx_su_ppdu_cfg(struct sigma_dut *dut, const char *intf,
7278 				  int val)
7279 {
7280 #ifdef NL80211_SUPPORT
7281 	return wcn_wifi_test_config_set_u8(
7282 		dut, intf, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU,
7283 		val);
7284 #else /* NL80211_SUPPORT */
7285 	sigma_dut_print(dut, DUT_MSG_ERROR,
7286 			"Tx SU PPDU cannot be set without NL80211_SUPPORT defined");
7287 	return -1;
7288 #endif /* NL80211_SUPPORT */
7289 }
7290 
7291 
sta_set_mgmt_data_tx_disable_cfg(struct sigma_dut * dut,const char * intf,int val)7292 static int sta_set_mgmt_data_tx_disable_cfg(struct sigma_dut *dut,
7293 					    const char *intf, int val)
7294 {
7295 #ifdef NL80211_SUPPORT
7296 	return wcn_wifi_test_config_set_u8(
7297 		dut, intf,
7298 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_DATA_MGMT_RSP_TX,
7299 		val);
7300 #else /* NL80211_SUPPORT */
7301 	sigma_dut_print(dut, DUT_MSG_ERROR,
7302 			"Tx disable config cannot be set without NL80211_SUPPORT defined");
7303 	return -1;
7304 #endif /* NL80211_SUPPORT */
7305 }
7306 
7307 
7308 #ifdef NL80211_SUPPORT
sta_set_he_om_ctrl_reset(struct sigma_dut * dut,const char * intf)7309 static int sta_set_he_om_ctrl_reset(struct sigma_dut *dut, const char *intf)
7310 {
7311 	return wcn_wifi_test_config_set_flag(
7312 		dut, intf,
7313 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG);
7314 }
7315 #endif /* NL80211_SUPPORT */
7316 
7317 
sta_set_mu_edca_override(struct sigma_dut * dut,const char * intf,int val)7318 static int sta_set_mu_edca_override(struct sigma_dut *dut, const char *intf,
7319 				    int val)
7320 {
7321 #ifdef NL80211_SUPPORT
7322 	return wcn_wifi_test_config_set_u8(
7323 		dut, intf,
7324 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA, val);
7325 #else /* NL80211_SUPPORT */
7326 	sigma_dut_print(dut, DUT_MSG_ERROR,
7327 			"MU EDCA override cannot be changed without NL80211_SUPPORT defined");
7328 	return -1;
7329 #endif /* NL80211_SUPPORT */
7330 }
7331 
7332 
sta_set_om_ctrl_supp(struct sigma_dut * dut,const char * intf,int val)7333 static int sta_set_om_ctrl_supp(struct sigma_dut *dut, const char *intf,
7334 				int val)
7335 {
7336 #ifdef NL80211_SUPPORT
7337 	return wcn_wifi_test_config_set_u8(
7338 		dut, intf,
7339 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP, val);
7340 #else /* NL80211_SUPPORT */
7341 	sigma_dut_print(dut, DUT_MSG_ERROR,
7342 			"HE OM ctrl cannot be changed without NL80211_SUPPORT defined");
7343 	return -1;
7344 #endif /* NL80211_SUPPORT */
7345 }
7346 
7347 
sta_set_twt_req_support(struct sigma_dut * dut,const char * intf,int val)7348 static int sta_set_twt_req_support(struct sigma_dut *dut, const char *intf,
7349 				   int val)
7350 {
7351 #ifdef NL80211_SUPPORT
7352 	return wcn_wifi_test_config_set_u8(
7353 		dut, intf,
7354 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT, val);
7355 #else /* NL80211_SUPPORT */
7356 	sigma_dut_print(dut, DUT_MSG_ERROR,
7357 			"TWT Request cannot be changed without NL80211_SUPPORT defined");
7358 	return -1;
7359 #endif /* NL80211_SUPPORT */
7360 }
7361 
7362 
sta_set_bss_max_idle_period(struct sigma_dut * dut,const char * intf,int val)7363 static int sta_set_bss_max_idle_period(struct sigma_dut *dut, const char *intf,
7364 				       int val)
7365 {
7366 #ifdef NL80211_SUPPORT
7367 	return wcn_wifi_test_config_set_u16(
7368 		dut, intf,
7369 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD, val);
7370 #else /* NL80211_SUPPORT */
7371 	sigma_dut_print(dut, DUT_MSG_ERROR,
7372 			"BSS max idle period cannot be set without NL80211_SUPPORT defined");
7373 	return -1;
7374 #endif /* NL80211_SUPPORT */
7375 }
7376 
7377 
sta_set_fullbw_ulmumimo(struct sigma_dut * dut,const char * intf,int val)7378 static int sta_set_fullbw_ulmumimo(struct sigma_dut *dut, const char *intf,
7379 				   int val)
7380 {
7381 #ifdef NL80211_SUPPORT
7382 	return wcn_wifi_test_config_set_u8(
7383 		dut, intf,
7384 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO, val);
7385 #else /* NL80211_SUPPORT */
7386 	sigma_dut_print(dut, DUT_MSG_ERROR,
7387 			"Full BW UL MU MIMO cannot be changed without NL80211_SUPPORT defined");
7388 	return -1;
7389 #endif /* NL80211_SUPPORT */
7390 }
7391 
7392 
sta_set_punctured_preamble_rx(struct sigma_dut * dut,const char * intf,int val)7393 static int sta_set_punctured_preamble_rx(struct sigma_dut *dut,
7394 					 const char *intf, int val)
7395 {
7396 #ifdef NL80211_SUPPORT
7397 	return wcn_wifi_test_config_set_u8(
7398 		dut, intf,
7399 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX,
7400 		val);
7401 #else /* NL80211_SUPPORT */
7402 	sigma_dut_print(dut, DUT_MSG_ERROR,
7403 			"Punctured preamble Rx cannot be set without NL80211_SUPPORT defined");
7404 	return -1;
7405 #endif /* NL80211_SUPPORT */
7406 }
7407 
7408 
sta_reset_default_wcn(struct sigma_dut * dut,const char * intf,const char * type)7409 static void sta_reset_default_wcn(struct sigma_dut *dut, const char *intf,
7410 				  const char *type)
7411 {
7412 	char buf[60];
7413 
7414 	if (dut->program == PROGRAM_HE) {
7415 		/* resetting phymode to auto in case of HE program */
7416 		sta_set_phymode(dut, intf, "auto");
7417 
7418 		/* reset the rate to Auto rate */
7419 		snprintf(buf, sizeof(buf), "iwpriv %s set_11ax_rate 0xff",
7420 			 intf);
7421 		if (system(buf) != 0) {
7422 			sigma_dut_print(dut, DUT_MSG_ERROR,
7423 					"iwpriv %s set_11ax_rate 0xff failed",
7424 					intf);
7425 		}
7426 
7427 		/* reset the LDPC setting */
7428 		snprintf(buf, sizeof(buf), "iwpriv %s ldpc 1", intf);
7429 		if (system(buf) != 0) {
7430 			sigma_dut_print(dut, DUT_MSG_ERROR,
7431 					"iwpriv %s ldpc 1 failed", intf);
7432 		}
7433 
7434 		/* reset the power save setting */
7435 		set_power_save_wcn(dut, intf, 2);
7436 
7437 		/* remove all network profiles */
7438 		remove_wpa_networks(intf);
7439 
7440 		/* Configure ADDBA Req/Rsp buffer size to be 64 */
7441 		sta_set_addba_buf_size(dut, intf, 64);
7442 
7443 #ifdef NL80211_SUPPORT
7444 		/* Reset the device HE capabilities to its default supported
7445 		 * configuration. */
7446 		sta_set_he_testbed_def(dut, intf, 0);
7447 
7448 		/* Disable noackpolicy for all AC */
7449 		if (nlvendor_sta_set_noack(dut, intf, 0, QCA_WLAN_AC_ALL)) {
7450 			sigma_dut_print(dut, DUT_MSG_ERROR,
7451 					"Disable of noackpolicy for all AC failed");
7452 		}
7453 #endif /* NL80211_SUPPORT */
7454 
7455 		/* Enable WMM by default */
7456 		if (wcn_sta_set_wmm(dut, intf, "on")) {
7457 			sigma_dut_print(dut, DUT_MSG_ERROR,
7458 					"Enable of WMM in sta_reset_default_wcn failed");
7459 		}
7460 
7461 		/* Disable ADDBA_REJECT by default */
7462 		if (nlvendor_sta_set_addba_reject(dut, intf, 0)) {
7463 			sigma_dut_print(dut, DUT_MSG_ERROR,
7464 					"Disable of addba_reject in sta_reset_default_wcn failed");
7465 		}
7466 
7467 		/* Enable sending of ADDBA by default */
7468 		if (nlvendor_config_send_addba(dut, intf, 1)) {
7469 			sigma_dut_print(dut, DUT_MSG_ERROR,
7470 					"Enable sending of ADDBA in sta_reset_default_wcn failed");
7471 		}
7472 
7473 		/* Enable AMPDU by default */
7474 		iwpriv_sta_set_ampdu(dut, intf, 1);
7475 
7476 #ifdef NL80211_SUPPORT
7477 		if (wcn_set_he_ltf(dut, intf, QCA_WLAN_HE_LTF_AUTO)) {
7478 			sigma_dut_print(dut, DUT_MSG_ERROR,
7479 					"Set LTF config to default in sta_reset_default_wcn failed");
7480 		}
7481 
7482 		/* set the beamformee NSTS(maximum number of
7483 		 * space-time streams) to default DUT config
7484 		 */
7485 		if (sta_set_beamformee_sts(dut, intf, 7)) {
7486 			sigma_dut_print(dut, DUT_MSG_ERROR,
7487 					"Failed to set BeamformeeSTS");
7488 		}
7489 
7490 		if (sta_set_mgmt_data_tx_disable_cfg(dut, intf, 0)) {
7491 			sigma_dut_print(dut, DUT_MSG_ERROR,
7492 					"Failed to reset mgmt/data Tx disable config");
7493 		}
7494 
7495 		if (sta_set_mac_padding_duration(
7496 			    dut, intf,
7497 			    QCA_WLAN_HE_NO_ADDITIONAL_PROCESS_TIME)) {
7498 			sigma_dut_print(dut, DUT_MSG_ERROR,
7499 					"Failed to set MAC padding duration");
7500 		}
7501 
7502 		if (sta_set_mu_edca_override(dut, intf, 0)) {
7503 			sigma_dut_print(dut, DUT_MSG_ERROR,
7504 					"ErrorCode,Failed to set MU EDCA override disable");
7505 		}
7506 
7507 		if (sta_set_om_ctrl_supp(dut, intf, 1)) {
7508 			sigma_dut_print(dut, DUT_MSG_ERROR,
7509 					"Failed to set OM ctrl supp");
7510 		}
7511 
7512 		if (sta_set_bss_max_idle_period(dut, intf, 0)) {
7513 			sigma_dut_print(dut, DUT_MSG_ERROR,
7514 				  "Failed to reset BSS max idle period");
7515 		}
7516 
7517 		if (sta_set_tx_su_ppdu_cfg(dut, intf, 1)) {
7518 			sigma_dut_print(dut, DUT_MSG_ERROR,
7519 					"Failed to set Tx SU PPDU enable");
7520 		}
7521 
7522 		if (sta_set_action_tx_in_he_tb_ppdu(dut, intf, 0)) {
7523 			sigma_dut_print(dut, DUT_MSG_ERROR,
7524 					"failed to send TB PPDU Tx cfg");
7525 		}
7526 
7527 		if (sta_set_he_om_ctrl_reset(dut, intf)) {
7528 			sigma_dut_print(dut, DUT_MSG_ERROR,
7529 					"Failed to set OM ctrl reset");
7530 		}
7531 
7532 		/* +HTC-HE support default on */
7533 		if (sta_set_he_htc_supp(dut, intf, 1)) {
7534 			sigma_dut_print(dut, DUT_MSG_ERROR,
7535 					"Setting of +HTC-HE support failed");
7536 		}
7537 #endif /* NL80211_SUPPORT */
7538 
7539 		if (sta_set_tx_beamformee(dut, intf, 1)) {
7540 			sigma_dut_print(dut, DUT_MSG_ERROR,
7541 					"Set tx beamformee enable by default in sta_reset_default_wcn failed");
7542 		}
7543 
7544 		wpa_command(intf, "SET oce 1");
7545 
7546 		/* Set nss to 1 and MCS 0-7 in case of testbed */
7547 		if (type && strcasecmp(type, "Testbed") == 0) {
7548 #ifdef NL80211_SUPPORT
7549 			int ret;
7550 #endif /* NL80211_SUPPORT */
7551 
7552 			wpa_command(intf, "SET oce 0");
7553 
7554 			snprintf(buf, sizeof(buf), "iwpriv %s nss 1", intf);
7555 			if (system(buf) != 0) {
7556 				sigma_dut_print(dut, DUT_MSG_ERROR,
7557 						"iwpriv %s nss failed", intf);
7558 			}
7559 
7560 #ifdef NL80211_SUPPORT
7561 			ret = sta_set_he_mcs(dut, intf, HE_80_MCS0_7);
7562 			if (ret) {
7563 				sigma_dut_print(dut, DUT_MSG_ERROR,
7564 						"Setting of MCS failed, ret:%d",
7565 						ret);
7566 			}
7567 #endif /* NL80211_SUPPORT */
7568 
7569 			/* Disable STBC as default */
7570 			wcn_sta_set_stbc(dut, intf, "0");
7571 
7572 			/* Disable AMSDU as default */
7573 			iwpriv_sta_set_amsdu(dut, intf, "0");
7574 
7575 #ifdef NL80211_SUPPORT
7576 			/* HE fragmentation default off */
7577 			if (sta_set_he_fragmentation(dut, intf,
7578 						     HE_FRAG_DISABLE)) {
7579 				sigma_dut_print(dut, DUT_MSG_ERROR,
7580 						"Setting of HE fragmentation failed");
7581 			}
7582 
7583 			/* set the beamformee NSTS(maximum number of
7584 			 * space-time streams) to default testbed config
7585 			 */
7586 			if (sta_set_beamformee_sts(dut, intf, 3)) {
7587 				sigma_dut_print(dut, DUT_MSG_ERROR,
7588 						"Failed to set BeamformeeSTS");
7589 			}
7590 
7591 			if (sta_set_punctured_preamble_rx(dut, intf, 0)) {
7592 				sigma_dut_print(dut, DUT_MSG_ERROR,
7593 						"Failed to reset PreamblePunctRx support");
7594 			}
7595 
7596 			/* +HTC-HE support default off */
7597 			if (sta_set_he_htc_supp(dut, intf, 0)) {
7598 				sigma_dut_print(dut, DUT_MSG_ERROR,
7599 						"Setting of +HTC-HE support failed");
7600 			}
7601 
7602 			/* Set device HE capabilities to testbed default
7603 			 * configuration. */
7604 			if (sta_set_he_testbed_def(dut, intf, 1)) {
7605 				sigma_dut_print(dut, DUT_MSG_DEBUG,
7606 						"Failed to set HE defaults");
7607 			}
7608 
7609 			/* Disable VHT support in 2.4 GHz for testbed */
7610 			sta_set_2g_vht_supp(dut, intf, 0);
7611 #endif /* NL80211_SUPPORT */
7612 
7613 			/* Enable WEP/TKIP with HE capability in testbed */
7614 			if (sta_set_heconfig_and_wep_tkip(dut, intf, 1)) {
7615 				sigma_dut_print(dut, DUT_MSG_ERROR,
7616 						"Enabling HE config with WEP/TKIP failed");
7617 			}
7618 		}
7619 
7620 		/* Defaults in case of DUT */
7621 		if (type && strcasecmp(type, "DUT") == 0) {
7622 			/* Enable STBC by default */
7623 			wcn_sta_set_stbc(dut, intf, "1");
7624 
7625 			/* set nss to 2 */
7626 			snprintf(buf, sizeof(buf), "iwpriv %s nss 2", intf);
7627 			if (system(buf) != 0) {
7628 				sigma_dut_print(dut, DUT_MSG_ERROR,
7629 						"iwpriv %s nss 2 failed", intf);
7630 			}
7631 			dut->sta_nss = 2;
7632 
7633 #ifdef NL80211_SUPPORT
7634 			/* Set HE_MCS to 0-11 */
7635 			if (sta_set_he_mcs(dut, intf, HE_80_MCS0_11)) {
7636 				sigma_dut_print(dut, DUT_MSG_ERROR,
7637 						"Setting of MCS failed");
7638 			}
7639 #endif /* NL80211_SUPPORT */
7640 
7641 			/* Disable WEP/TKIP with HE capability in DUT */
7642 			if (sta_set_heconfig_and_wep_tkip(dut, intf, 0)) {
7643 				sigma_dut_print(dut, DUT_MSG_ERROR,
7644 						"Enabling HE config with WEP/TKIP failed");
7645 			}
7646 		}
7647 	}
7648 }
7649 
7650 
sta_set_client_privacy(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,int enable)7651 static int sta_set_client_privacy(struct sigma_dut *dut,
7652 				  struct sigma_conn *conn, const char *intf,
7653 				  int enable)
7654 {
7655 	if (enable &&
7656 	    (wpa_command(intf, "SET mac_addr 1") < 0 ||
7657 	     wpa_command(intf, "SET rand_addr_lifetime 1") < 0 ||
7658 	     (wpa_command(intf, "MAC_RAND_SCAN enable=1 all") < 0 &&
7659 	      wpa_command(intf, "SET preassoc_mac_addr 1") < 0) ||
7660 	     wpa_command(intf, "SET gas_rand_mac_addr 1") < 0 ||
7661 	     wpa_command(intf, "SET gas_rand_addr_lifetime 1") < 0))
7662 		return -1;
7663 
7664 	if (!enable &&
7665 	    (wpa_command(intf, "SET mac_addr 0") < 0 ||
7666 	     (wpa_command(intf, "MAC_RAND_SCAN enable=0 all") < 0 &&
7667 	      wpa_command(intf, "SET preassoc_mac_addr 0") < 0) ||
7668 	     wpa_command(intf, "SET gas_rand_mac_addr 0") < 0))
7669 		return -1;
7670 
7671 	dut->client_privacy = enable;
7672 	return 0;
7673 }
7674 
7675 
cmd_sta_reset_default(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)7676 static enum sigma_cmd_result cmd_sta_reset_default(struct sigma_dut *dut,
7677 						   struct sigma_conn *conn,
7678 						   struct sigma_cmd *cmd)
7679 {
7680 	const char *intf = get_param(cmd, "Interface");
7681 	const char *band = get_param(cmd, "band");
7682 	const char *type;
7683 	const char *program = get_param(cmd, "program");
7684 	const char *dev_role = get_param(cmd, "DevRole");
7685 	char resp[20];
7686 	int ret;
7687 
7688 	if (dut->station_ifname_2g &&
7689 	    strcmp(dut->station_ifname_2g, intf) == 0)
7690 		dut->use_5g = 0;
7691 	else if (dut->station_ifname_5g &&
7692 		 strcmp(dut->station_ifname_5g, intf) == 0)
7693 		dut->use_5g = 1;
7694 
7695 	if (!program)
7696 		program = get_param(cmd, "prog");
7697 	dut->program = sigma_program_to_enum(program);
7698 
7699 	if (dut->program == PROGRAM_WFD && dut->user_config_timeout)
7700 		dut->default_timeout = dut->user_config_timeout;
7701 
7702 	dut->device_type = STA_unknown;
7703 	type = get_param(cmd, "type");
7704 	if (type && strcasecmp(type, "Testbed") == 0)
7705 		dut->device_type = STA_testbed;
7706 	if (type && strcasecmp(type, "DUT") == 0)
7707 		dut->device_type = STA_dut;
7708 
7709 	if (dut->program == PROGRAM_TDLS) {
7710 		/* Clear TDLS testing mode */
7711 		wpa_command(intf, "SET tdls_disabled 0");
7712 		wpa_command(intf, "SET tdls_testing 0");
7713 		dut->no_tpk_expiration = 0;
7714 		if (get_driver_type(dut) == DRIVER_WCN) {
7715 			/* Enable the WCN driver in TDLS Explicit trigger mode
7716 			 */
7717 			wpa_command(intf, "SET tdls_external_control 0");
7718 			wpa_command(intf, "SET tdls_trigger_control 0");
7719 		}
7720 	}
7721 
7722 #ifdef MIRACAST
7723 	if (dut->program == PROGRAM_WFD ||
7724 	    dut->program == PROGRAM_DISPLAYR2)
7725 		miracast_sta_reset_default(dut, conn, cmd);
7726 #endif /* MIRACAST */
7727 
7728 	switch (get_driver_type(dut)) {
7729 	case DRIVER_ATHEROS:
7730 		sta_reset_default_ath(dut, intf, type);
7731 		break;
7732 	case DRIVER_WCN:
7733 		sta_reset_default_wcn(dut, intf, type);
7734 		break;
7735 	default:
7736 		break;
7737 	}
7738 
7739 #ifdef ANDROID_NAN
7740 	if (dut->program == PROGRAM_NAN)
7741 		nan_cmd_sta_reset_default(dut, conn, cmd);
7742 #endif /* ANDROID_NAN */
7743 
7744 	if (dut->program == PROGRAM_LOC &&
7745 	    lowi_cmd_sta_reset_default(dut, conn, cmd) < 0)
7746 		return ERROR_SEND_STATUS;
7747 
7748 	if (dut->program == PROGRAM_HS2_R2 || dut->program == PROGRAM_HS2_R3) {
7749 		unlink("SP/wi-fi.org/pps.xml");
7750 		if (system("rm -r SP/*") != 0) {
7751 		}
7752 		unlink("next-client-cert.pem");
7753 		unlink("next-client-key.pem");
7754 	}
7755 
7756 	/* For WPS program of the 60 GHz band the band type needs to be saved */
7757 	if (dut->program == PROGRAM_WPS) {
7758 		if (band && strcasecmp(band, "60GHz") == 0) {
7759 			dut->band = WPS_BAND_60G;
7760 			/* For 60 GHz enable WPS for WPS TCs */
7761 			dut->wps_disable = 0;
7762 		} else {
7763 			dut->band = WPS_BAND_NON_60G;
7764 		}
7765 	} else if (dut->program == PROGRAM_60GHZ) {
7766 		/* For 60 GHz MAC/PHY TCs WPS must be disabled */
7767 		dut->wps_disable = 1;
7768 	}
7769 
7770 	if (is_60g_sigma_dut(dut)) {
7771 		const char *dev_role = get_param(cmd, "DevRole");
7772 		char buf[256];
7773 
7774 		sigma_dut_print(dut, DUT_MSG_INFO,
7775 				"WPS 60 GHz program, wps_disable = %d",
7776 				dut->wps_disable);
7777 
7778 		if (!dev_role) {
7779 			send_resp(dut, conn, SIGMA_ERROR,
7780 				  "errorCode,Missing DevRole argument");
7781 			return 0;
7782 		}
7783 
7784 		if (strcasecmp(dev_role, "STA") == 0)
7785 			dut->dev_role = DEVROLE_STA;
7786 		else if (strcasecmp(dev_role, "PCP") == 0)
7787 			dut->dev_role = DEVROLE_PCP;
7788 		else {
7789 			send_resp(dut, conn, SIGMA_ERROR,
7790 				  "errorCode,Unknown DevRole");
7791 			return 0;
7792 		}
7793 
7794 		if (dut->device_type == STA_unknown) {
7795 			sigma_dut_print(dut, DUT_MSG_ERROR,
7796 					"Device type is not STA testbed or DUT");
7797 			send_resp(dut, conn, SIGMA_ERROR,
7798 				  "errorCode,Unknown device type");
7799 			return 0;
7800 		}
7801 
7802 		sigma_dut_print(dut, DUT_MSG_DEBUG,
7803 				"Setting msdu_size to MAX: 7912");
7804 		snprintf(buf, sizeof(buf), "ifconfig %s mtu 7912",
7805 			 get_station_ifname(dut));
7806 
7807 		if (system(buf) != 0) {
7808 			sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set %s",
7809 					buf);
7810 			return ERROR_SEND_STATUS;
7811 		}
7812 
7813 		if (sta_set_force_mcs(dut, 0, 1)) {
7814 			sigma_dut_print(dut, DUT_MSG_ERROR,
7815 					"Failed to reset force MCS");
7816 			return ERROR_SEND_STATUS;
7817 		}
7818 	}
7819 
7820 	wpa_command(intf, "WPS_ER_STOP");
7821 	wpa_command(intf, "FLUSH");
7822 	wpa_command(intf, "ERP_FLUSH");
7823 	wpa_command(intf, "SET radio_disabled 0");
7824 
7825 	dut->wps_forced_version = 0;
7826 
7827 	if (dut->wsc_fragment) {
7828 		dut->wsc_fragment = 0;
7829 		wpa_command(intf, "SET device_name Test client");
7830 		wpa_command(intf, "SET manufacturer ");
7831 		wpa_command(intf, "SET model_name ");
7832 		wpa_command(intf, "SET model_number ");
7833 		wpa_command(intf, "SET serial_number ");
7834 	}
7835 	if (is_60g_sigma_dut(dut) && dut->force_rsn_ie) {
7836 		dut->force_rsn_ie = FORCE_RSN_IE_NONE;
7837 		sta_60g_force_rsn_ie(dut, FORCE_RSN_IE_NONE);
7838 	}
7839 
7840 	if (dut->tmp_mac_addr && dut->set_macaddr) {
7841 		dut->tmp_mac_addr = 0;
7842 		if (system(dut->set_macaddr) != 0) {
7843 			sigma_dut_print(dut, DUT_MSG_INFO, "Failed to clear "
7844 					"temporary MAC address");
7845 		}
7846 	}
7847 
7848 	set_ps(intf, dut, 0);
7849 
7850 	if (dut->program == PROGRAM_HS2 || dut->program == PROGRAM_HS2_R2 ||
7851 	    dut->program == PROGRAM_HS2_R3) {
7852 		wpa_command(intf, "SET interworking 1");
7853 		wpa_command(intf, "SET hs20 1");
7854 	}
7855 
7856 	if (dut->program == PROGRAM_HS2_R2 ||
7857 	    dut->program == PROGRAM_HS2_R3 ||
7858 	    dut->program == PROGRAM_OCE) {
7859 		wpa_command(intf, "SET pmf 1");
7860 	} else {
7861 		wpa_command(intf, "SET pmf 0");
7862 	}
7863 
7864 	hs2_clear_credentials(intf);
7865 	wpa_command(intf, "SET hessid 00:00:00:00:00:00");
7866 	wpa_command(intf, "SET access_network_type 15");
7867 
7868 	static_ip_file(0, NULL, NULL, NULL);
7869 	kill_dhcp_client(dut, intf);
7870 	clear_ip_addr(dut, intf);
7871 
7872 	dut->er_oper_performed = 0;
7873 	dut->er_oper_bssid[0] = '\0';
7874 
7875 	if (dut->program == PROGRAM_LOC) {
7876 		/* Disable Interworking by default */
7877 		wpa_command(get_station_ifname(dut), "SET interworking 0");
7878 	}
7879 
7880 	if (dut->program == PROGRAM_MBO || dut->program == PROGRAM_HE) {
7881 		free(dut->non_pref_ch_list);
7882 		dut->non_pref_ch_list = NULL;
7883 		free(dut->btm_query_cand_list);
7884 		dut->btm_query_cand_list = NULL;
7885 		wpa_command(intf, "SET reject_btm_req_reason 0");
7886 		wpa_command(intf, "SET ignore_assoc_disallow 0");
7887 		wpa_command(intf, "SET gas_address3 0");
7888 		wpa_command(intf, "SET roaming 1");
7889 		wpa_command(intf, "SET interworking 1");
7890 	}
7891 
7892 	free(dut->rsne_override);
7893 	dut->rsne_override = NULL;
7894 
7895 	free(dut->sae_commit_override);
7896 	dut->sae_commit_override = NULL;
7897 	wpa_command(intf, "SET sae_pmkid_in_assoc 0");
7898 	dut->sae_pwe = SAE_PWE_DEFAULT;
7899 
7900 	dut->sta_associate_wait_connect = 0;
7901 	dut->server_cert_hash[0] = '\0';
7902 	dut->server_cert_tod = 0;
7903 	dut->sta_tod_policy = 0;
7904 
7905 	dut->dpp_conf_id = -1;
7906 	free(dut->dpp_peer_uri);
7907 	dut->dpp_peer_uri = NULL;
7908 	dut->dpp_local_bootstrap = -1;
7909 	wpa_command(intf, "SET dpp_config_processing 2");
7910 	wpa_command(intf, "SET dpp_mud_url ");
7911 
7912 	wpa_command(intf, "VENDOR_ELEM_REMOVE 13 *");
7913 
7914 	if (dut->program == PROGRAM_OCE) {
7915 		wpa_command(intf, "SET oce 1");
7916 		wpa_command(intf, "SET disable_fils 0");
7917 		wpa_command(intf, "FILS_HLP_REQ_FLUSH");
7918 		dut->fils_hlp = 0;
7919 #ifdef ANDROID
7920 		hlp_thread_cleanup(dut);
7921 #endif /* ANDROID */
7922 	}
7923 
7924 	if (dut->program == PROGRAM_QM)
7925 		wpa_command(intf, "SET interworking 1");
7926 
7927 	dut->akm_values = 0;
7928 	dut->sta_ft_ds = 0;
7929 
7930 #ifdef NL80211_SUPPORT
7931 	if (get_driver_type(dut) == DRIVER_WCN &&
7932 	    dut->config_rsnie == 1) {
7933 		dut->config_rsnie = 0;
7934 		sta_config_params(dut, intf, STA_SET_RSNIE, 0);
7935 	}
7936 #endif /* NL80211_SUPPORT */
7937 
7938 	if (dev_role && strcasecmp(dev_role, "STA-CFON") == 0) {
7939 		dut->dev_role = DEVROLE_STA_CFON;
7940 		return sta_cfon_reset_default(dut, conn, cmd);
7941 	}
7942 
7943 	wpa_command(intf, "SET setband AUTO");
7944 
7945 	ret = wpa_command_resp(intf, "GET_CAPABILITY ocv", resp, sizeof(resp));
7946 	dut->ocvc = ret == 0 && strncmp(resp, "supported", 9) == 0;
7947 
7948 	ret = wpa_command_resp(intf, "GET_CAPABILITY beacon_prot", resp,
7949 			       sizeof(resp));
7950 	dut->beacon_prot = ret == 0 && strncmp(resp, "supported", 9) == 0;
7951 
7952 	if (sta_set_client_privacy(dut, conn, intf,
7953 				   dut->program == PROGRAM_WPA3 &&
7954 				   dut->device_type == STA_dut &&
7955 				   dut->client_privacy_default)) {
7956 		sigma_dut_print(dut, DUT_MSG_ERROR,
7957 				"Failed to set client privacy functionality");
7958 		/* sta_reset_default command is not really supposed to fail,
7959 		 * so allow this to continue. */
7960 	}
7961 
7962 	dut->saquery_oci_freq = 0;
7963 
7964 	if (dut->program != PROGRAM_VHT)
7965 		return cmd_sta_p2p_reset(dut, conn, cmd);
7966 
7967 	return 1;
7968 }
7969 
7970 
cmd_sta_get_events(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)7971 static enum sigma_cmd_result cmd_sta_get_events(struct sigma_dut *dut,
7972 						struct sigma_conn *conn,
7973 						struct sigma_cmd *cmd)
7974 {
7975 	const char *program = get_param(cmd, "Program");
7976 
7977 	if (program == NULL)
7978 		return -1;
7979 #ifdef ANDROID_NAN
7980 	if (strcasecmp(program, "NAN") == 0)
7981 		return nan_cmd_sta_get_events(dut, conn, cmd);
7982 #endif /* ANDROID_NAN */
7983 	send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
7984 	return 0;
7985 }
7986 
7987 
sta_exec_action_url(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)7988 static int sta_exec_action_url(struct sigma_dut *dut, struct sigma_conn *conn,
7989 			       struct sigma_cmd *cmd)
7990 {
7991 	const char *url = get_param(cmd, "url");
7992 	const char *method = get_param(cmd, "method");
7993 	pid_t pid;
7994 	int status;
7995 
7996 	if (!url || !method)
7997 		return -1;
7998 
7999 	/* TODO: Add support for method,post */
8000 	if (strcasecmp(method, "get") != 0) {
8001 		send_resp(dut, conn, SIGMA_ERROR,
8002 			  "ErrorCode,Unsupported method");
8003 		return 0;
8004 	}
8005 
8006 	pid = fork();
8007 	if (pid < 0) {
8008 		perror("fork");
8009 		return -1;
8010 	}
8011 
8012 	if (pid == 0) {
8013 		char * argv[5] = { "wget", "-O", "/dev/null",
8014 				   (char *) url, NULL };
8015 
8016 		execv("/usr/bin/wget", argv);
8017 		perror("execv");
8018 		exit(0);
8019 		return -1;
8020 	}
8021 
8022 	if (waitpid(pid, &status, 0) < 0) {
8023 		perror("waitpid");
8024 		return -1;
8025 	}
8026 
8027 	if (WIFEXITED(status)) {
8028 		const char *errmsg;
8029 
8030 		if (WEXITSTATUS(status) == 0)
8031 			return 1;
8032 		sigma_dut_print(dut, DUT_MSG_INFO, "wget exit status %d",
8033 				WEXITSTATUS(status));
8034 		switch (WEXITSTATUS(status)) {
8035 		case 4:
8036 			errmsg = "errmsg,Network failure";
8037 			break;
8038 		case 8:
8039 			errmsg = "errmsg,Server issued an error response";
8040 			break;
8041 		default:
8042 			errmsg = "errmsg,Unknown failure from wget";
8043 			break;
8044 		}
8045 		send_resp(dut, conn, SIGMA_ERROR, errmsg);
8046 		return 0;
8047 	}
8048 
8049 	send_resp(dut, conn, SIGMA_ERROR, "errmsg,Unknown failure");
8050 	return 0;
8051 }
8052 
8053 
cmd_sta_exec_action(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)8054 static enum sigma_cmd_result cmd_sta_exec_action(struct sigma_dut *dut,
8055 						 struct sigma_conn *conn,
8056 						 struct sigma_cmd *cmd)
8057 {
8058 	const char *program = get_param(cmd, "Prog");
8059 
8060 	if (program && !get_param(cmd, "interface"))
8061 		return -1;
8062 #ifdef ANDROID_NAN
8063 	if (program && strcasecmp(program, "NAN") == 0)
8064 		return nan_cmd_sta_exec_action(dut, conn, cmd);
8065 #endif /* ANDROID_NAN */
8066 
8067 	if (program && strcasecmp(program, "Loc") == 0)
8068 		return loc_cmd_sta_exec_action(dut, conn, cmd);
8069 
8070 	if (get_param(cmd, "url"))
8071 		return sta_exec_action_url(dut, conn, cmd);
8072 
8073 	send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
8074 	return 0;
8075 }
8076 
8077 
cmd_sta_set_11n(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)8078 static enum sigma_cmd_result cmd_sta_set_11n(struct sigma_dut *dut,
8079 					     struct sigma_conn *conn,
8080 					     struct sigma_cmd *cmd)
8081 {
8082 	const char *intf = get_param(cmd, "Interface");
8083 	const char *val, *mcs32, *rate;
8084 
8085 	val = get_param(cmd, "GREENFIELD");
8086 	if (val) {
8087 		if (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0) {
8088 			/* Enable GD */
8089 			send_resp(dut, conn, SIGMA_ERROR,
8090 				  "ErrorCode,GF not supported");
8091 			return 0;
8092 		}
8093 	}
8094 
8095 	val = get_param(cmd, "SGI20");
8096 	if (val) {
8097 		switch (get_driver_type(dut)) {
8098 		case DRIVER_ATHEROS:
8099 			ath_sta_set_sgi(dut, intf, val);
8100 			break;
8101 		default:
8102 			send_resp(dut, conn, SIGMA_ERROR,
8103 				  "ErrorCode,SGI20 not supported");
8104 			return 0;
8105 		}
8106 	}
8107 
8108 	mcs32 = get_param(cmd, "MCS32"); /* HT Duplicate Mode Enable/Disable */
8109 	rate = get_param(cmd, "MCS_FIXEDRATE"); /* Fixed MCS rate (0..31) */
8110 	if (mcs32 && rate) {
8111 		/* TODO */
8112 		send_resp(dut, conn, SIGMA_ERROR,
8113 			  "ErrorCode,MCS32,MCS_FIXEDRATE not supported");
8114 		return 0;
8115 	} else if (mcs32 && !rate) {
8116 		/* TODO */
8117 		send_resp(dut, conn, SIGMA_ERROR,
8118 			  "ErrorCode,MCS32 not supported");
8119 		return 0;
8120 	} else if (!mcs32 && rate) {
8121 		switch (get_driver_type(dut)) {
8122 		case DRIVER_ATHEROS:
8123 			novap_reset(dut, intf, 1);
8124 			ath_sta_set_11nrates(dut, intf, rate);
8125 			break;
8126 		default:
8127 			send_resp(dut, conn, SIGMA_ERROR,
8128 				  "ErrorCode,MCS32_FIXEDRATE not supported");
8129 			return 0;
8130 		}
8131 	}
8132 
8133 	return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
8134 }
8135 
8136 
cmd_set_max_he_mcs(struct sigma_dut * dut,const char * intf,int mcs_config)8137 static void cmd_set_max_he_mcs(struct sigma_dut *dut, const char *intf,
8138 			       int mcs_config)
8139 {
8140 #ifdef NL80211_SUPPORT
8141 	int ret;
8142 
8143 	switch (mcs_config) {
8144 	case HE_80_MCS0_7:
8145 	case HE_80_MCS0_9:
8146 	case HE_80_MCS0_11:
8147 		ret = sta_set_he_mcs(dut, intf, mcs_config);
8148 		if (ret) {
8149 			sigma_dut_print(dut, DUT_MSG_ERROR,
8150 					"cmd_set_max_he_mcs: Setting of MCS:%d failed, ret:%d",
8151 					mcs_config, ret);
8152 		}
8153 		break;
8154 	default:
8155 		sigma_dut_print(dut, DUT_MSG_ERROR,
8156 				"cmd_set_max_he_mcs: Invalid mcs %d",
8157 				mcs_config);
8158 		break;
8159 	}
8160 #else /* NL80211_SUPPORT */
8161 	sigma_dut_print(dut, DUT_MSG_ERROR,
8162 			"max HE MCS cannot be changed without NL80211_SUPPORT defined");
8163 #endif /* NL80211_SUPPORT */
8164 }
8165 
8166 
sta_twt_send_suspend(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)8167 static int sta_twt_send_suspend(struct sigma_dut *dut, struct sigma_conn *conn,
8168 				struct sigma_cmd *cmd)
8169 {
8170 #ifdef NL80211_SUPPORT
8171 	struct nlattr *attr, *attr1;
8172 	struct nl_msg *msg;
8173 	int ifindex, ret;
8174 	const char *intf = get_param(cmd, "Interface");
8175 
8176 	ifindex = if_nametoindex(intf);
8177 	if (ifindex == 0) {
8178 		sigma_dut_print(dut, DUT_MSG_ERROR,
8179 				"%s: Index for interface %s failed",
8180 				__func__, intf);
8181 		return ERROR_SEND_STATUS;
8182 	}
8183 
8184 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
8185 				    NL80211_CMD_VENDOR)) ||
8186 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
8187 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
8188 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
8189 			QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT) ||
8190 	    !(attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
8191 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
8192 		       QCA_WLAN_TWT_SUSPEND) ||
8193 	    !(attr1 = nla_nest_start(msg,
8194 				     QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS)) ||
8195 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID, 0)) {
8196 		sigma_dut_print(dut, DUT_MSG_ERROR,
8197 				"%s: err in adding vendor_cmd and vendor_data",
8198 				__func__);
8199 		nlmsg_free(msg);
8200 		return ERROR_SEND_STATUS;
8201 	}
8202 	nla_nest_end(msg, attr1);
8203 	nla_nest_end(msg, attr);
8204 
8205 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
8206 	if (ret) {
8207 		sigma_dut_print(dut, DUT_MSG_ERROR,
8208 				"%s: err in send_and_recv_msgs, ret=%d",
8209 				__func__, ret);
8210 	}
8211 
8212 	return ret;
8213 #else /* NL80211_SUPPORT */
8214 	sigma_dut_print(dut, DUT_MSG_ERROR,
8215 			"TWT suspend cannot be done without NL80211_SUPPORT defined");
8216 	return ERROR_SEND_STATUS;
8217 #endif /* NL80211_SUPPORT */
8218 }
8219 
8220 
sta_twt_send_nudge(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd,unsigned int suspend_duration)8221 static int sta_twt_send_nudge(struct sigma_dut *dut, struct sigma_conn *conn,
8222 			      struct sigma_cmd *cmd,
8223 			      unsigned int suspend_duration)
8224 {
8225 #ifdef NL80211_SUPPORT
8226 	struct nlattr *attr, *attr1;
8227 	struct nl_msg *msg;
8228 	int ifindex, ret;
8229 	const char *intf = get_param(cmd, "Interface");
8230 	int next_twt_size = 1;
8231 
8232 	ifindex = if_nametoindex(intf);
8233 	if (ifindex == 0) {
8234 		sigma_dut_print(dut, DUT_MSG_ERROR,
8235 				"%s: Index for interface %s failed",
8236 				__func__, intf);
8237 		return ERROR_SEND_STATUS;
8238 	}
8239 
8240 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
8241 				    NL80211_CMD_VENDOR)) ||
8242 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
8243 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
8244 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
8245 			QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT) ||
8246 	    !(attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
8247 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
8248 		       QCA_WLAN_TWT_NUDGE) ||
8249 	    !(attr1 = nla_nest_start(msg,
8250 				     QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS)) ||
8251 	    (suspend_duration &&
8252 	     nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME,
8253 			 suspend_duration)) ||
8254 	    nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE,
8255 			next_twt_size)) {
8256 		sigma_dut_print(dut, DUT_MSG_ERROR,
8257 				"%s: err in adding vendor_cmd and vendor_data",
8258 				__func__);
8259 		nlmsg_free(msg);
8260 		return ERROR_SEND_STATUS;
8261 	}
8262 	nla_nest_end(msg, attr1);
8263 	nla_nest_end(msg, attr);
8264 
8265 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
8266 	if (ret) {
8267 		sigma_dut_print(dut, DUT_MSG_ERROR,
8268 				"%s: err in send_and_recv_msgs, ret=%d",
8269 				__func__, ret);
8270 	}
8271 
8272 	return ret;
8273 #else /* NL80211_SUPPORT */
8274 	sigma_dut_print(dut, DUT_MSG_ERROR,
8275 			"TWT suspend cannot be done without NL80211_SUPPORT defined");
8276 	return ERROR_SEND_STATUS;
8277 #endif /* NL80211_SUPPORT */
8278 }
8279 
8280 
sta_twt_suspend_or_nudge(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)8281 static int sta_twt_suspend_or_nudge(struct sigma_dut *dut,
8282 				    struct sigma_conn *conn,
8283 				    struct sigma_cmd *cmd)
8284 {
8285 	const char *val;
8286 
8287 	val = get_param(cmd, "TWT_SuspendDuration");
8288 	if (val) {
8289 		unsigned int suspend_duration;
8290 
8291 		suspend_duration = atoi(val);
8292 		suspend_duration = suspend_duration * 1000 * 1000;
8293 		return sta_twt_send_nudge(dut, conn, cmd, suspend_duration);
8294 	}
8295 
8296 	return sta_twt_send_suspend(dut, conn, cmd);
8297 }
8298 
8299 
sta_twt_resume(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)8300 static int sta_twt_resume(struct sigma_dut *dut, struct sigma_conn *conn,
8301 			  struct sigma_cmd *cmd)
8302 {
8303 #ifdef NL80211_SUPPORT
8304 	struct nlattr *attr, *attr1;
8305 	struct nl_msg *msg;
8306 	int ifindex, ret;
8307 	const char *intf = get_param(cmd, "Interface");
8308 	int next2_twt_size = 1;
8309 	unsigned int resume_duration = 0;
8310 	const char *val;
8311 
8312 	ifindex = if_nametoindex(intf);
8313 	if (ifindex == 0) {
8314 		sigma_dut_print(dut, DUT_MSG_ERROR,
8315 				"%s: Index for interface %s failed",
8316 				__func__, intf);
8317 		return ERROR_SEND_STATUS;
8318 	}
8319 
8320 	val = get_param(cmd, "TWT_ResumeDuration");
8321 	if (val) {
8322 		resume_duration = atoi(val);
8323 		resume_duration = resume_duration * 1000 * 1000;
8324 	}
8325 
8326 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
8327 				    NL80211_CMD_VENDOR)) ||
8328 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
8329 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
8330 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
8331 			QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT) ||
8332 	    !(attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
8333 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
8334 		       QCA_WLAN_TWT_RESUME) ||
8335 	    !(attr1 = nla_nest_start(msg,
8336 				     QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS)) ||
8337 	    (resume_duration &&
8338 	     nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT2_TWT,
8339 			 resume_duration)) ||
8340 	    nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE,
8341 			next2_twt_size)) {
8342 		sigma_dut_print(dut, DUT_MSG_ERROR,
8343 				"%s: err in adding vendor_cmd and vendor_data",
8344 				__func__);
8345 		nlmsg_free(msg);
8346 		return ERROR_SEND_STATUS;
8347 	}
8348 	nla_nest_end(msg, attr1);
8349 	nla_nest_end(msg, attr);
8350 
8351 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
8352 	if (ret) {
8353 		sigma_dut_print(dut, DUT_MSG_ERROR,
8354 				"%s: err in send_and_recv_msgs, ret=%d",
8355 				__func__, ret);
8356 	}
8357 
8358 	return ret;
8359 #else /* NL80211_SUPPORT */
8360 	sigma_dut_print(dut, DUT_MSG_ERROR,
8361 			"TWT resume cannot be done without NL80211_SUPPORT defined");
8362 	return ERROR_SEND_STATUS;
8363 #endif /* NL80211_SUPPORT */
8364 }
8365 
8366 
8367 #define TWT_REQUEST_CMD     0
8368 #define TWT_SUGGEST_CMD     1
8369 #define TWT_DEMAND_CMD      2
8370 
sta_twt_request(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)8371 static int sta_twt_request(struct sigma_dut *dut, struct sigma_conn *conn,
8372 			   struct sigma_cmd *cmd)
8373 {
8374 #ifdef NL80211_SUPPORT
8375 	struct nlattr *params;
8376 	struct nlattr *attr;
8377 	struct nl_msg *msg;
8378 	int ifindex, ret;
8379 	const char *val;
8380 	const char *intf = get_param(cmd, "Interface");
8381 	int wake_interval_exp = 10, nominal_min_wake_dur = 255,
8382 		wake_interval_mantissa = 512;
8383 	int flow_type = 0, twt_trigger = 0, target_wake_time = 0,
8384 		protection = 0, cmd_type = QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST;
8385 
8386 	ifindex = if_nametoindex(intf);
8387 	if (ifindex == 0) {
8388 		sigma_dut_print(dut, DUT_MSG_ERROR,
8389 				"%s: Index for interface %s failed",
8390 				__func__, intf);
8391 		return -1;
8392 	}
8393 
8394 	val = get_param(cmd, "FlowType");
8395 	if (val) {
8396 		flow_type = atoi(val);
8397 		if (flow_type != 0 && flow_type != 1) {
8398 			sigma_dut_print(dut, DUT_MSG_ERROR,
8399 					"TWT: Invalid FlowType %d", flow_type);
8400 			return -1;
8401 		}
8402 	}
8403 
8404 	val = get_param(cmd, "TWT_Trigger");
8405 	if (val) {
8406 		twt_trigger = atoi(val);
8407 		if (twt_trigger != 0 && twt_trigger != 1) {
8408 			sigma_dut_print(dut, DUT_MSG_ERROR,
8409 					"TWT: Invalid TWT_Trigger %d",
8410 					twt_trigger);
8411 			return -1;
8412 		}
8413 	}
8414 
8415 	val = get_param(cmd, "Protection");
8416 	if (val) {
8417 		protection = atoi(val);
8418 		if (protection != 0 && protection != 1) {
8419 			sigma_dut_print(dut, DUT_MSG_ERROR,
8420 					"TWT: Invalid Protection %d",
8421 					protection);
8422 			return -1;
8423 		}
8424 	}
8425 
8426 	val = get_param(cmd, "SetupCommand");
8427 	if (val) {
8428 		cmd_type = atoi(val);
8429 		if (cmd_type == TWT_REQUEST_CMD)
8430 			cmd_type = QCA_WLAN_VENDOR_TWT_SETUP_REQUEST;
8431 		else if (cmd_type == TWT_SUGGEST_CMD)
8432 			cmd_type = QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST;
8433 		else if (cmd_type == TWT_DEMAND_CMD)
8434 			cmd_type = QCA_WLAN_VENDOR_TWT_SETUP_DEMAND;
8435 		else
8436 			sigma_dut_print(dut, DUT_MSG_ERROR,
8437 					"Default suggest is used for cmd %d",
8438 					cmd_type);
8439 	}
8440 
8441 	val = get_param(cmd, "TargetWakeTime");
8442 	if (val)
8443 		target_wake_time = atoi(val);
8444 
8445 	val = get_param(cmd, "WakeIntervalMantissa");
8446 	if (val)
8447 		wake_interval_mantissa = atoi(val);
8448 
8449 	val = get_param(cmd, "WakeIntervalExp");
8450 	if (val)
8451 		wake_interval_exp = atoi(val);
8452 
8453 	val = get_param(cmd, "NominalMinWakeDur");
8454 	if (val)
8455 		nominal_min_wake_dur = atoi(val);
8456 
8457 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
8458 				    NL80211_CMD_VENDOR)) ||
8459 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
8460 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
8461 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
8462 			QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT) ||
8463 	    !(attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
8464 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
8465 		       QCA_WLAN_TWT_SET) ||
8466 	    !(params = nla_nest_start(
8467 		      msg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS)) ||
8468 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP,
8469 		       wake_interval_exp) ||
8470 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE, cmd_type) ||
8471 	    (twt_trigger &&
8472 	     nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER)) ||
8473 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE,
8474 		       flow_type) ||
8475 	    (protection &&
8476 	     nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION)) ||
8477 	    nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME,
8478 			target_wake_time) ||
8479 	    nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION,
8480 			nominal_min_wake_dur) ||
8481 	    nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA,
8482 			wake_interval_mantissa)) {
8483 		sigma_dut_print(dut, DUT_MSG_ERROR,
8484 				"%s: err in adding vendor_cmd and vendor_data",
8485 				__func__);
8486 		nlmsg_free(msg);
8487 		return -1;
8488 	}
8489 	nla_nest_end(msg, params);
8490 	nla_nest_end(msg, attr);
8491 
8492 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
8493 	if (ret) {
8494 		sigma_dut_print(dut, DUT_MSG_ERROR,
8495 				"%s: err in send_and_recv_msgs, ret=%d",
8496 				__func__, ret);
8497 	}
8498 
8499 	return ret;
8500 #else /* NL80211_SUPPORT */
8501 	sigma_dut_print(dut, DUT_MSG_ERROR,
8502 			"TWT request cannot be done without NL80211_SUPPORT defined");
8503 	return -1;
8504 #endif /* NL80211_SUPPORT */
8505 }
8506 
8507 
sta_twt_teardown(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)8508 static int sta_twt_teardown(struct sigma_dut *dut, struct sigma_conn *conn,
8509 			    struct sigma_cmd *cmd)
8510 {
8511  #ifdef NL80211_SUPPORT
8512 	struct nlattr *params;
8513 	struct nlattr *attr;
8514 	int ifindex, ret;
8515 	struct nl_msg *msg;
8516 	const char *intf = get_param(cmd, "Interface");
8517 
8518 	ifindex = if_nametoindex(intf);
8519 	if (ifindex == 0) {
8520 		sigma_dut_print(dut, DUT_MSG_ERROR,
8521 				"%s: Index for interface %s failed",
8522 				__func__, intf);
8523 		return -1;
8524 	}
8525 
8526 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
8527 				    NL80211_CMD_VENDOR)) ||
8528 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
8529 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
8530 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
8531 			QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT) ||
8532 	    !(attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
8533 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
8534 		       QCA_WLAN_TWT_TERMINATE) ||
8535 	    !(params = nla_nest_start(
8536 		      msg,
8537 		      QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS)) ||
8538 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE, 0)) {
8539 		sigma_dut_print(dut, DUT_MSG_ERROR,
8540 				"%s: err in adding vendor_cmd and vendor_data",
8541 				__func__);
8542 		nlmsg_free(msg);
8543 		return -1;
8544 	}
8545 	nla_nest_end(msg, params);
8546 	nla_nest_end(msg, attr);
8547 
8548 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
8549 	if (ret) {
8550 		sigma_dut_print(dut, DUT_MSG_ERROR,
8551 				"%s: err in send_and_recv_msgs, ret=%d",
8552 				__func__, ret);
8553 	}
8554 
8555 	return ret;
8556 #else /* NL80211_SUPPORT */
8557 	sigma_dut_print(dut, DUT_MSG_ERROR,
8558 			"TWT teardown cannot be done without NL80211_SUPPORT defined");
8559 	return -1;
8560 #endif /* NL80211_SUPPORT */
8561 }
8562 
8563 
sta_transmit_omi(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)8564 static int sta_transmit_omi(struct sigma_dut *dut, struct sigma_conn *conn,
8565 			    struct sigma_cmd *cmd)
8566 {
8567 #ifdef NL80211_SUPPORT
8568 	struct nlattr *params;
8569 	struct nlattr *attr;
8570 	struct nlattr *attr1;
8571 	struct nl_msg *msg;
8572 	int ifindex, ret;
8573 	const char *val;
8574 	const char *intf = get_param(cmd, "Interface");
8575 	uint8_t rx_nss = 0xFF, ch_bw = 0xFF, tx_nsts = 0xFF, ulmu_dis = 0,
8576 		ulmu_data_dis = 0;
8577 
8578 	ifindex = if_nametoindex(intf);
8579 	if (ifindex == 0) {
8580 		sigma_dut_print(dut, DUT_MSG_ERROR,
8581 				"%s: Index for interface %s failed",
8582 				__func__, intf);
8583 		return -1;
8584 	}
8585 	val = get_param(cmd, "OMCtrl_RxNSS");
8586 	if (val)
8587 		rx_nss = atoi(val);
8588 
8589 	val = get_param(cmd, "OMCtrl_ChnlWidth");
8590 	if (val)
8591 		ch_bw = atoi(val);
8592 
8593 	val = get_param(cmd, "OMCtrl_ULMUDisable");
8594 	if (val)
8595 		ulmu_dis = atoi(val);
8596 
8597 	val = get_param(cmd, "OMCtrl_TxNSTS");
8598 	if (val)
8599 		tx_nsts = atoi(val);
8600 
8601 	val = get_param(cmd, "OMCtrl_ULMUDataDisable");
8602 	if (val)
8603 		ulmu_data_dis = atoi(val);
8604 
8605 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
8606 				    NL80211_CMD_VENDOR)) ||
8607 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
8608 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
8609 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
8610 			QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION) ||
8611 	    !(attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
8612 	    !(params = nla_nest_start(
8613 		      msg, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX)) ||
8614 	    !(attr1 = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
8615 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS, rx_nss) ||
8616 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW, ch_bw) ||
8617 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS, tx_nsts) ||
8618 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE,
8619 		       ulmu_data_dis) ||
8620 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE,
8621 		       ulmu_dis)) {
8622 		sigma_dut_print(dut, DUT_MSG_ERROR,
8623 				"%s: err in adding vendor_cmd and vendor_data",
8624 				__func__);
8625 		nlmsg_free(msg);
8626 		return -1;
8627 	}
8628 	nla_nest_end(msg, attr1);
8629 	nla_nest_end(msg, params);
8630 	nla_nest_end(msg, attr);
8631 
8632 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
8633 	if (ret) {
8634 		sigma_dut_print(dut, DUT_MSG_ERROR,
8635 				"%s: err in send_and_recv_msgs, ret=%d",
8636 				__func__, ret);
8637 	}
8638 
8639 	return ret;
8640 #else /* NL80211_SUPPORT */
8641 	sigma_dut_print(dut, DUT_MSG_ERROR,
8642 			"OMI TX cannot be processed without NL80211_SUPPORT defined");
8643 	return -1;
8644 #endif /* NL80211_SUPPORT */
8645 }
8646 
8647 
8648 static enum sigma_cmd_result
cmd_sta_set_wireless_vht(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)8649 cmd_sta_set_wireless_vht(struct sigma_dut *dut, struct sigma_conn *conn,
8650 			 struct sigma_cmd *cmd)
8651 {
8652 	const char *intf = get_param(cmd, "Interface");
8653 	const char *val;
8654 	const char *program;
8655 	int tkip = -1;
8656 	int wep = -1;
8657 	int iwpriv_status;
8658 
8659 	program = get_param(cmd, "Program");
8660 	val = get_param(cmd, "SGI80");
8661 	if (val) {
8662 		int sgi80;
8663 
8664 		sgi80 = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
8665 		run_iwpriv(dut, intf, "shortgi %d", sgi80);
8666 	}
8667 
8668 	val = get_param(cmd, "TxBF");
8669 	if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)) {
8670 		switch (get_driver_type(dut)) {
8671 		case DRIVER_WCN:
8672 			if (sta_set_tx_beamformee(dut, intf, 1)) {
8673 				send_resp(dut, conn, SIGMA_ERROR,
8674 					  "ErrorCode,Failed to set TX beamformee enable");
8675 				return STATUS_SENT_ERROR;
8676 			}
8677 			break;
8678 		case DRIVER_ATHEROS:
8679 			if (run_iwpriv(dut, intf, "vhtsubfee 1") < 0) {
8680 				send_resp(dut, conn, SIGMA_ERROR,
8681 					  "ErrorCode,Setting vhtsubfee failed");
8682 				return STATUS_SENT_ERROR;
8683 			}
8684 			if (run_iwpriv(dut, intf, "vhtsubfer 1") < 0) {
8685 				send_resp(dut, conn, SIGMA_ERROR,
8686 					  "ErrorCode,Setting vhtsubfer failed");
8687 				return STATUS_SENT_ERROR;
8688 			}
8689 			break;
8690 		default:
8691 			sigma_dut_print(dut, DUT_MSG_ERROR,
8692 					"Unsupported driver type");
8693 			break;
8694 		}
8695 	}
8696 
8697 	val = get_param(cmd, "MU_TxBF");
8698 	if (val && (strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0)) {
8699 		switch (get_driver_type(dut)) {
8700 		case DRIVER_ATHEROS:
8701 			ath_sta_set_txsp_stream(dut, intf, "1SS");
8702 			ath_sta_set_rxsp_stream(dut, intf, "1SS");
8703 			run_iwpriv(dut, intf, "vhtmubfee 1");
8704 			run_iwpriv(dut, intf, "vhtmubfer 1");
8705 			break;
8706 		case DRIVER_WCN:
8707 			if (wcn_sta_set_sp_stream(dut, intf, "1SS") < 0) {
8708 				send_resp(dut, conn, SIGMA_ERROR,
8709 					  "ErrorCode,Failed to set RX/TXSP_STREAM");
8710 				return STATUS_SENT_ERROR;
8711 			}
8712 			break;
8713 		default:
8714 			sigma_dut_print(dut, DUT_MSG_ERROR,
8715 					"Setting SP_STREAM not supported");
8716 			break;
8717 		}
8718 	}
8719 
8720 	val = get_param(cmd, "LDPC");
8721 	if (val) {
8722 		int ldpc;
8723 
8724 		ldpc = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
8725 		iwpriv_status = run_iwpriv(dut, intf, "ldpc %d", ldpc);
8726 		if (iwpriv_status)
8727 			sta_config_params(dut, intf, STA_SET_LDPC, ldpc);
8728 	}
8729 
8730 	val = get_param(cmd, "BCC");
8731 	if (val) {
8732 		int bcc;
8733 
8734 		bcc = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
8735 		/* use LDPC iwpriv itself to set bcc coding, bcc coding
8736 		 * is mutually exclusive to bcc */
8737 		iwpriv_status = run_iwpriv(dut, intf, "ldpc %d", !bcc);
8738 		if (iwpriv_status)
8739 			sta_config_params(dut, intf, STA_SET_LDPC, !bcc);
8740 	}
8741 
8742 	val = get_param(cmd, "MaxHE-MCS_1SS_RxMapLTE80");
8743 	if (val && dut->sta_nss == 1)
8744 		cmd_set_max_he_mcs(dut, intf, atoi(val));
8745 
8746 	val = get_param(cmd, "MaxHE-MCS_2SS_RxMapLTE80");
8747 	if (val && dut->sta_nss == 2)
8748 		cmd_set_max_he_mcs(dut, intf, atoi(val));
8749 
8750 	val = get_param(cmd, "MCS_FixedRate");
8751 	if (val) {
8752 #ifdef NL80211_SUPPORT
8753 		int mcs, ratecode = 0;
8754 		enum he_mcs_config mcs_config;
8755 		int ret;
8756 		char buf[60];
8757 
8758 		ratecode = (0x07 & dut->sta_nss) << 5;
8759 		mcs = atoi(val);
8760 		/* Add the MCS to the ratecode */
8761 		if (mcs >= 0 && mcs <= 11) {
8762 			ratecode += mcs;
8763 			if (dut->device_type == STA_testbed &&
8764 			    mcs > 7 && mcs <= 11) {
8765 				if (mcs <= 9)
8766 					mcs_config = HE_80_MCS0_9;
8767 				else
8768 					mcs_config = HE_80_MCS0_11;
8769 				ret = sta_set_he_mcs(dut, intf, mcs_config);
8770 				if (ret) {
8771 					sigma_dut_print(dut, DUT_MSG_ERROR,
8772 							"MCS_FixedRate: mcs setting failed, mcs:%d, mcs_config %d, ret:%d",
8773 							mcs, mcs_config, ret);
8774 				}
8775 			}
8776 			snprintf(buf, sizeof(buf),
8777 				 "iwpriv %s set_11ax_rate 0x%03x",
8778 				 intf, ratecode);
8779 			if (system(buf) != 0) {
8780 				sigma_dut_print(dut, DUT_MSG_ERROR,
8781 						"MCS_FixedRate: iwpriv setting of 11ax rates 0x%03x failed",
8782 						ratecode);
8783 			}
8784 		} else {
8785 			sigma_dut_print(dut, DUT_MSG_ERROR,
8786 					"MCS_FixedRate: HE MCS %d not supported",
8787 					mcs);
8788 		}
8789 #else /* NL80211_SUPPORT */
8790 		sigma_dut_print(dut, DUT_MSG_ERROR,
8791 				"MCS_FixedRate cannot be changed without NL80211_SUPPORT defined");
8792 #endif /* NL80211_SUPPORT */
8793 	}
8794 
8795 	val = get_param(cmd, "opt_md_notif_ie");
8796 	if (val) {
8797 		char *result = NULL;
8798 		char delim[] = ";";
8799 		char token[30];
8800 		int value, config_val = 0;
8801 		char *saveptr;
8802 
8803 		strlcpy(token, val, sizeof(token));
8804 		result = strtok_r(token, delim, &saveptr);
8805 
8806 		/* Extract the NSS information */
8807 		if (result) {
8808 			value = atoi(result);
8809 			switch (value) {
8810 			case 1:
8811 				config_val = 1;
8812 				break;
8813 			case 2:
8814 				config_val = 3;
8815 				break;
8816 			case 3:
8817 				config_val = 7;
8818 				break;
8819 			case 4:
8820 				config_val = 15;
8821 				break;
8822 			default:
8823 				config_val = 3;
8824 				break;
8825 			}
8826 
8827 			run_iwpriv(dut, intf, "rxchainmask %d", config_val);
8828 			run_iwpriv(dut, intf, "txchainmask %d", config_val);
8829 
8830 		}
8831 
8832 		/* Extract the channel width information */
8833 		result = strtok_r(NULL, delim, &saveptr);
8834 		if (result) {
8835 			value = atoi(result);
8836 			switch (value) {
8837 			case 20:
8838 				config_val = 0;
8839 				break;
8840 			case 40:
8841 				config_val = 1;
8842 				break;
8843 			case 80:
8844 				config_val = 2;
8845 				break;
8846 			case 160:
8847 				config_val = 3;
8848 				break;
8849 			default:
8850 				config_val = 2;
8851 				break;
8852 			}
8853 
8854 			dut->chwidth = config_val;
8855 
8856 			run_iwpriv(dut, intf, "chwidth %d", config_val);
8857 		}
8858 
8859 		run_iwpriv(dut, intf, "opmode_notify 1");
8860 	}
8861 
8862 	val = get_param(cmd, "nss_mcs_cap");
8863 	if (val) {
8864 		int nss, mcs;
8865 		char token[20];
8866 		char *result = NULL;
8867 		unsigned int vht_mcsmap = 0;
8868 		char *saveptr;
8869 
8870 		strlcpy(token, val, sizeof(token));
8871 		result = strtok_r(token, ";", &saveptr);
8872 		if (!result) {
8873 			sigma_dut_print(dut, DUT_MSG_ERROR,
8874 					"NSS not specified");
8875 			send_resp(dut, conn, SIGMA_ERROR,
8876 				  "errorCode,NSS not specified");
8877 			return STATUS_SENT_ERROR;
8878 		}
8879 		nss = atoi(result);
8880 
8881 		run_iwpriv(dut, intf, "nss %d", nss);
8882 		dut->sta_nss = nss;
8883 
8884 		result = strtok_r(NULL, ";", &saveptr);
8885 		if (result == NULL) {
8886 			sigma_dut_print(dut, DUT_MSG_ERROR,
8887 					"MCS not specified");
8888 			send_resp(dut, conn, SIGMA_ERROR,
8889 				  "errorCode,MCS not specified");
8890 			return STATUS_SENT_ERROR;
8891 		}
8892 		result = strtok_r(result, "-", &saveptr);
8893 		result = strtok_r(NULL, "-", &saveptr);
8894 		if (!result) {
8895 			sigma_dut_print(dut, DUT_MSG_ERROR,
8896 					"MCS not specified");
8897 			send_resp(dut, conn, SIGMA_ERROR,
8898 				  "errorCode,MCS not specified");
8899 			return STATUS_SENT_ERROR;
8900 		}
8901 		mcs = atoi(result);
8902 
8903 		if (program && strcasecmp(program, "HE") == 0) {
8904 #ifdef NL80211_SUPPORT
8905 			enum he_mcs_config mcs_config;
8906 			int ret;
8907 
8908 			if (mcs >= 0 && mcs <= 7) {
8909 				mcs_config = HE_80_MCS0_7;
8910 			} else if (mcs > 7 && mcs <= 9) {
8911 				mcs_config = HE_80_MCS0_9;
8912 			} else if (mcs > 9 && mcs <= 11) {
8913 				mcs_config = HE_80_MCS0_11;
8914 			} else {
8915 				sigma_dut_print(dut, DUT_MSG_ERROR,
8916 						"nss_mcs_cap: HE: Invalid mcs: %d",
8917 						mcs);
8918 				send_resp(dut, conn, SIGMA_ERROR,
8919 					  "errorCode,Invalid MCS");
8920 				return STATUS_SENT_ERROR;
8921 			}
8922 
8923 			ret = sta_set_he_mcs(dut, intf, mcs_config);
8924 			if (ret) {
8925 				sigma_dut_print(dut, DUT_MSG_ERROR,
8926 						"nss_mcs_cap: HE: Setting of MCS failed, mcs_config: %d, ret: %d",
8927 						mcs_config, ret);
8928 				send_resp(dut, conn, SIGMA_ERROR,
8929 					  "errorCode,Failed to set MCS");
8930 				return STATUS_SENT_ERROR;
8931 			}
8932 #else /* NL80211_SUPPORT */
8933 			sigma_dut_print(dut, DUT_MSG_ERROR,
8934 					"nss_mcs_cap: HE: MCS cannot be changed without NL80211_SUPPORT defined");
8935 #endif /* NL80211_SUPPORT */
8936 		} else {
8937 			run_iwpriv(dut, intf, "vhtmcs %d", mcs);
8938 
8939 			switch (nss) {
8940 			case 1:
8941 				switch (mcs) {
8942 				case 7:
8943 					vht_mcsmap = 0xfffc;
8944 					break;
8945 				case 8:
8946 					vht_mcsmap = 0xfffd;
8947 					break;
8948 				case 9:
8949 					vht_mcsmap = 0xfffe;
8950 					break;
8951 				default:
8952 					vht_mcsmap = 0xfffe;
8953 					break;
8954 				}
8955 				break;
8956 			case 2:
8957 				switch (mcs) {
8958 				case 7:
8959 					vht_mcsmap = 0xfff0;
8960 					break;
8961 				case 8:
8962 					vht_mcsmap = 0xfff5;
8963 					break;
8964 				case 9:
8965 					vht_mcsmap = 0xfffa;
8966 					break;
8967 				default:
8968 					vht_mcsmap = 0xfffa;
8969 					break;
8970 				}
8971 				break;
8972 			case 3:
8973 				switch (mcs) {
8974 				case 7:
8975 					vht_mcsmap = 0xffc0;
8976 					break;
8977 				case 8:
8978 					vht_mcsmap = 0xffd5;
8979 					break;
8980 				case 9:
8981 					vht_mcsmap = 0xffea;
8982 					break;
8983 				default:
8984 					vht_mcsmap = 0xffea;
8985 					break;
8986 				}
8987 				break;
8988 			default:
8989 				vht_mcsmap = 0xffea;
8990 				break;
8991 			}
8992 			run_iwpriv(dut, intf, "vht_mcsmap 0x%04x", vht_mcsmap);
8993 		}
8994 	}
8995 
8996 	/* UNSUPPORTED: val = get_param(cmd, "Tx_lgi_rate"); */
8997 
8998 	val = get_param(cmd, "Vht_tkip");
8999 	if (val)
9000 		tkip = strcmp(val, "1") == 0 ||	strcasecmp(val, "Enable") == 0;
9001 
9002 	val = get_param(cmd, "Vht_wep");
9003 	if (val)
9004 		wep = strcmp(val, "1") == 0 || strcasecmp(val, "Enable") == 0;
9005 
9006 	if (tkip != -1 || wep != -1) {
9007 		if ((tkip == 1 && wep != 0) || (wep == 1 && tkip != 0)) {
9008 			run_iwpriv(dut, intf, "htweptkip 1");
9009 		} else if ((tkip == 0 && wep != 1) || (wep == 0 && tkip != 1)) {
9010 			run_iwpriv(dut, intf, "htweptkip 0");
9011 		} else {
9012 			send_resp(dut, conn, SIGMA_ERROR,
9013 				  "ErrorCode,mixed mode of VHT TKIP/WEP not supported");
9014 			return STATUS_SENT_ERROR;
9015 		}
9016 	}
9017 
9018 	val = get_param(cmd, "txBandwidth");
9019 	if (val) {
9020 		switch (get_driver_type(dut)) {
9021 		case DRIVER_WCN:
9022 			if (wcn_sta_set_width(dut, intf, val) < 0) {
9023 				send_resp(dut, conn, SIGMA_ERROR,
9024 					  "ErrorCode,Failed to set txBandwidth");
9025 				return STATUS_SENT_ERROR;
9026 			}
9027 			break;
9028 		case DRIVER_ATHEROS:
9029 			if (ath_set_width(dut, conn, intf, val) < 0) {
9030 				send_resp(dut, conn, SIGMA_ERROR,
9031 					  "ErrorCode,Failed to set txBandwidth");
9032 				return STATUS_SENT_ERROR;
9033 			}
9034 			break;
9035 		default:
9036 			sigma_dut_print(dut, DUT_MSG_ERROR,
9037 					"Setting txBandwidth not supported");
9038 			break;
9039 		}
9040 	}
9041 
9042 	val = get_param(cmd, "BeamformeeSTS");
9043 	if (val) {
9044 		if (sta_set_tx_beamformee(dut, intf, 1)) {
9045 			send_resp(dut, conn, SIGMA_ERROR,
9046 					"ErrorCode,Failed to set TX beamformee enable");
9047 			return STATUS_SENT_ERROR;
9048 		}
9049 
9050 		if (sta_set_beamformee_sts(dut, intf, atoi(val))) {
9051 			send_resp(dut, conn, SIGMA_ERROR,
9052 				  "ErrorCode,Failed to set BeamformeeSTS");
9053 			return STATUS_SENT_ERROR;
9054 		}
9055 	}
9056 
9057 	val = get_param(cmd, "Trig_MAC_Padding_Dur");
9058 	if (val) {
9059 #ifdef NL80211_SUPPORT
9060 		enum qca_wlan_he_mac_padding_dur set_val;
9061 
9062 		switch (atoi(val)) {
9063 		case 16:
9064 			set_val = QCA_WLAN_HE_16US_OF_PROCESS_TIME;
9065 			break;
9066 		case 8:
9067 			set_val = QCA_WLAN_HE_8US_OF_PROCESS_TIME;
9068 			break;
9069 		default:
9070 			set_val = QCA_WLAN_HE_NO_ADDITIONAL_PROCESS_TIME;
9071 			break;
9072 		}
9073 		if (sta_set_mac_padding_duration(dut, intf, set_val)) {
9074 			send_resp(dut, conn, SIGMA_ERROR,
9075 				  "ErrorCode,Failed to set MAC padding duration");
9076 			return STATUS_SENT_ERROR;
9077 		}
9078 #else /* NL80211_SUPPORT */
9079 		sigma_dut_print(dut, DUT_MSG_ERROR,
9080 				"MAC padding duration cannot be changed without NL80211_SUPPORT defined");
9081 #endif /* NL80211_SUPPORT */
9082 	}
9083 
9084 	val = get_param(cmd, "TWT_ReqSupport");
9085 	if (val) {
9086 		int set_val;
9087 
9088 		if (strcasecmp(val, "Enable") == 0) {
9089 			set_val = 1;
9090 		} else if (strcasecmp(val, "Disable") == 0) {
9091 			set_val = 0;
9092 		} else {
9093 			send_resp(dut, conn, SIGMA_ERROR,
9094 				  "ErrorCode,Invalid TWT_ReqSupport");
9095 			return STATUS_SENT_ERROR;
9096 		}
9097 
9098 		if (sta_set_twt_req_support(dut, intf, set_val)) {
9099 			sigma_dut_print(dut, DUT_MSG_ERROR,
9100 					"Failed to set TWT req support %d",
9101 					set_val);
9102 			send_resp(dut, conn, SIGMA_ERROR,
9103 				  "ErrorCode,Failed to set TWT_ReqSupport");
9104 			return STATUS_SENT_ERROR;
9105 		}
9106 	}
9107 
9108 	val = get_param(cmd, "PreamblePunctRx");
9109 	if (val && get_driver_type(dut) == DRIVER_WCN) {
9110 		int set_val;
9111 
9112 		if (strcasecmp(val, "Enable") == 0) {
9113 			set_val = 1;
9114 		} else if (strcasecmp(val, "Disable") == 0) {
9115 			set_val = 0;
9116 		} else {
9117 			send_resp(dut, conn, SIGMA_ERROR,
9118 				  "ErrorCode,Invalid PreamblePunctRx");
9119 			return STATUS_SENT_ERROR;
9120 		}
9121 
9122 		if (sta_set_punctured_preamble_rx(dut, intf, set_val)) {
9123 			sigma_dut_print(dut, DUT_MSG_ERROR,
9124 					"Failed to set PreamblePunctRx support %d",
9125 					set_val);
9126 			send_resp(dut, conn, SIGMA_ERROR,
9127 				  "ErrorCode,Failed to set PreamblePunctRx");
9128 			return STATUS_SENT_ERROR;
9129 		}
9130 	}
9131 
9132 	val = get_param(cmd, "FullBW_ULMUMIMO");
9133 	if (val) {
9134 		int set_val;
9135 
9136 		if (strcasecmp(val, "Enable") == 0) {
9137 			set_val = 1;
9138 		} else if (strcasecmp(val, "Disable") == 0) {
9139 			set_val = 0;
9140 		} else {
9141 			send_resp(dut, conn, SIGMA_ERROR,
9142 				  "ErrorCode,Invalid FullBW_ULMUMIMO");
9143 			return STATUS_SENT_ERROR;
9144 		}
9145 
9146 		if (sta_set_fullbw_ulmumimo(dut, intf, set_val)) {
9147 			sigma_dut_print(dut, DUT_MSG_ERROR,
9148 					"Failed to set FullBW_ULMUMIMO %d",
9149 					set_val);
9150 			send_resp(dut, conn, SIGMA_ERROR,
9151 				  "ErrorCode,Failed to set FullBW_ULMUMIMO");
9152 			return STATUS_SENT_ERROR;
9153 		}
9154 	}
9155 
9156 	val = get_param(cmd, "TWTInfoFrameTx");
9157 	if (val) {
9158 		if (strcasecmp(val, "Enable") == 0) {
9159 			/* No-op */
9160 		} else if (strcasecmp(val, "Disable") == 0) {
9161 			/* No-op */
9162 		} else {
9163 			send_resp(dut, conn, SIGMA_ERROR,
9164 				  "ErrorCode,Invalid TWTInfoFrameTx");
9165 			return STATUS_SENT_ERROR;
9166 		}
9167 	}
9168 
9169 	val = get_param(cmd, "MU_EDCA");
9170 	if (val && (strcasecmp(val, "Override") == 0)) {
9171 		if (sta_set_mu_edca_override(dut, intf, 1)) {
9172 			send_resp(dut, conn, SIGMA_ERROR,
9173 				  "ErrorCode,Failed to set MU EDCA override");
9174 			return STATUS_SENT_ERROR;
9175 		}
9176 	}
9177 
9178 	val = get_param(cmd, "OMControl");
9179 	if (val) {
9180 		int set_val = 1;
9181 
9182 		if (strcasecmp(val, "Enable") == 0)
9183 			set_val = 1;
9184 		else if (strcasecmp(val, "Disable") == 0)
9185 			set_val = 0;
9186 
9187 		if (sta_set_om_ctrl_supp(dut, intf, set_val)) {
9188 			send_resp(dut, conn, SIGMA_ERROR,
9189 				  "ErrorCode,Failed to set OM ctrl supp");
9190 			return STATUS_SENT_ERROR;
9191 		}
9192 	}
9193 
9194 	val = get_param(cmd, "BSSMaxIdlePeriod");
9195 	if (val && sta_set_bss_max_idle_period(dut, intf, atoi(val))) {
9196 		send_resp(dut, conn, SIGMA_ERROR,
9197 			  "ErrorCode,Failed to set BSS max idle period");
9198 		return STATUS_SENT_ERROR;
9199 	}
9200 
9201 	val = get_param(cmd, "ADDBAResp_BufSize");
9202 	if (val) {
9203 		int buf_size;
9204 
9205 		if (strcasecmp(val, "gt64") == 0)
9206 			buf_size = 256;
9207 		else
9208 			buf_size = 64;
9209 		if (get_driver_type(dut) == DRIVER_WCN &&
9210 		    sta_set_addba_buf_size(dut, intf, buf_size)) {
9211 			send_resp(dut, conn, SIGMA_ERROR,
9212 				  "ErrorCode,set addbaresp_buff_size failed");
9213 			return STATUS_SENT_ERROR;
9214 		}
9215 	}
9216 
9217 	val = get_param(cmd, "ADDBAReq_BufSize");
9218 	if (val) {
9219 		int buf_size;
9220 
9221 		if (strcasecmp(val, "gt64") == 0)
9222 			buf_size = 256;
9223 		else
9224 			buf_size = 64;
9225 		if (get_driver_type(dut) == DRIVER_WCN &&
9226 		    sta_set_addba_buf_size(dut, intf, buf_size)) {
9227 			send_resp(dut, conn, SIGMA_ERROR,
9228 				  "ErrorCode,set addbareq_buff_size failed");
9229 			return STATUS_SENT_ERROR;
9230 		}
9231 	}
9232 
9233 	return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
9234 }
9235 
9236 
sta_set_wireless_60g(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)9237 static int sta_set_wireless_60g(struct sigma_dut *dut,
9238 				struct sigma_conn *conn,
9239 				struct sigma_cmd *cmd)
9240 {
9241 	const char *dev_role = get_param(cmd, "DevRole");
9242 
9243 	if (!dev_role) {
9244 		send_resp(dut, conn, SIGMA_INVALID,
9245 			  "ErrorCode,DevRole not specified");
9246 		return 0;
9247 	}
9248 
9249 	if (strcasecmp(dev_role, "PCP") == 0)
9250 		return sta_set_60g_pcp(dut, conn, cmd);
9251 	if (strcasecmp(dev_role, "STA") == 0)
9252 		return sta_set_60g_sta(dut, conn, cmd);
9253 	send_resp(dut, conn, SIGMA_INVALID,
9254 		  "ErrorCode,DevRole not supported");
9255 	return 0;
9256 }
9257 
9258 
sta_set_wireless_oce(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)9259 static int sta_set_wireless_oce(struct sigma_dut *dut, struct sigma_conn *conn,
9260 				struct sigma_cmd *cmd)
9261 {
9262 	int status;
9263 	const char *intf = get_param(cmd, "Interface");
9264 	const char *val = get_param(cmd, "DevRole");
9265 
9266 	if (val && strcasecmp(val, "STA-CFON") == 0) {
9267 		status = sta_cfon_set_wireless(dut, conn, cmd);
9268 		if (status)
9269 			return status;
9270 	}
9271 	return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
9272 }
9273 
9274 
9275 static enum sigma_cmd_result
sta_set_wireless_wpa3(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)9276 sta_set_wireless_wpa3(struct sigma_dut *dut, struct sigma_conn *conn,
9277 		      struct sigma_cmd *cmd)
9278 {
9279 	const char *intf = get_param(cmd, "Interface");
9280 	const char *val;
9281 
9282 	val = get_param(cmd, "ocvc");
9283 	if (val)
9284 		dut->ocvc = atoi(val);
9285 
9286 	val = get_param(cmd, "ClientPrivacy");
9287 	if (val && dut->client_privacy != atoi(val) &&
9288 	    sta_set_client_privacy(dut, conn, intf, atoi(val))) {
9289 		send_resp(dut, conn, SIGMA_ERROR,
9290 			  "errorCode,Failed to configure random MAC address use");
9291 		return STATUS_SENT_ERROR;
9292 	}
9293 
9294 	return cmd_sta_set_wireless_common(intf, dut, conn, cmd);
9295 }
9296 
9297 
cmd_sta_set_wireless(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)9298 static enum sigma_cmd_result cmd_sta_set_wireless(struct sigma_dut *dut,
9299 						  struct sigma_conn *conn,
9300 						  struct sigma_cmd *cmd)
9301 {
9302 	const char *val;
9303 
9304 	val = get_param(cmd, "Program");
9305 	if (val) {
9306 		if (strcasecmp(val, "11n") == 0)
9307 			return cmd_sta_set_11n(dut, conn, cmd);
9308 		if (strcasecmp(val, "VHT") == 0 || strcasecmp(val, "HE") == 0)
9309 			return cmd_sta_set_wireless_vht(dut, conn, cmd);
9310 		if (strcasecmp(val, "60ghz") == 0)
9311 			return sta_set_wireless_60g(dut, conn, cmd);
9312 		if (strcasecmp(val, "OCE") == 0)
9313 			return sta_set_wireless_oce(dut, conn, cmd);
9314 		/* sta_set_wireless in WPS program is only used for 60G */
9315 		if (is_60g_sigma_dut(dut))
9316 			return sta_set_wireless_60g(dut, conn, cmd);
9317 		if (strcasecmp(val, "WPA3") == 0)
9318 			return sta_set_wireless_wpa3(dut, conn, cmd);
9319 		send_resp(dut, conn, SIGMA_ERROR,
9320 			  "ErrorCode,Program value not supported");
9321 	} else {
9322 		send_resp(dut, conn, SIGMA_ERROR,
9323 			  "ErrorCode,Program argument not available");
9324 	}
9325 
9326 	return 0;
9327 }
9328 
9329 
ath_sta_inject_frame(struct sigma_dut * dut,const char * intf,int tid)9330 static void ath_sta_inject_frame(struct sigma_dut *dut, const char *intf,
9331 				 int tid)
9332 {
9333 	char buf[100];
9334 	int tid_to_dscp [] = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0 };
9335 
9336 	if (tid < 0 ||
9337 	    tid >= (int) (sizeof(tid_to_dscp) / sizeof(tid_to_dscp[0]))) {
9338 		sigma_dut_print(dut, DUT_MSG_ERROR, "Unsupported TID: %d", tid);
9339 		return;
9340 	}
9341 
9342 	/*
9343 	 * Two ways to ensure that addba request with a
9344 	 * non zero TID could be sent out. EV 117296
9345 	 */
9346 	snprintf(buf, sizeof(buf),
9347 		 "ping -c 8 -Q %d `arp -a | grep wlan0 | awk '{print $2}' | tr -d '()'`",
9348 		 tid);
9349 	if (system(buf) != 0) {
9350 		sigma_dut_print(dut, DUT_MSG_ERROR,
9351 				"Ping did not send out");
9352 	}
9353 
9354 	snprintf(buf, sizeof(buf),
9355 		 "iwconfig %s | grep Access | awk '{print $6}' > %s",
9356 		 intf, VI_QOS_TMP_FILE);
9357 	if (system(buf) != 0)
9358 		return;
9359 
9360 	snprintf(buf, sizeof(buf),
9361 		 "ifconfig %s | grep HWaddr | cut -b 39-56 >> %s",
9362 		 intf, VI_QOS_TMP_FILE);
9363 	if (system(buf) != 0)
9364 		sigma_dut_print(dut, DUT_MSG_ERROR, "HWaddr matching failed");
9365 
9366 	snprintf(buf,sizeof(buf), "sed -n '3,$p' %s >> %s",
9367 		 VI_QOS_REFFILE, VI_QOS_TMP_FILE);
9368 	if (system(buf) != 0) {
9369 		sigma_dut_print(dut, DUT_MSG_ERROR,
9370 				"VI_QOS_TEMP_FILE generation error failed");
9371 	}
9372 	snprintf(buf, sizeof(buf), "sed '5 c %x' %s > %s",
9373 		 tid_to_dscp[tid], VI_QOS_TMP_FILE, VI_QOS_FILE);
9374 	if (system(buf) != 0) {
9375 		sigma_dut_print(dut, DUT_MSG_ERROR,
9376 				"VI_QOS_FILE generation failed");
9377 	}
9378 
9379 	snprintf(buf, sizeof(buf), "sed '5 c %x' %s > %s",
9380 		 tid_to_dscp[tid], VI_QOS_TMP_FILE, VI_QOS_FILE);
9381 	if (system(buf) != 0) {
9382 		sigma_dut_print(dut, DUT_MSG_ERROR,
9383 				"VI_QOS_FILE generation failed");
9384 	}
9385 
9386 	snprintf(buf, sizeof(buf), "ethinject %s %s", intf, VI_QOS_FILE);
9387 	if (system(buf) != 0) {
9388 	}
9389 }
9390 
9391 
ath_sta_send_addba(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)9392 static int ath_sta_send_addba(struct sigma_dut *dut, struct sigma_conn *conn,
9393 			      struct sigma_cmd *cmd)
9394 {
9395 	const char *intf = get_param(cmd, "Interface");
9396 	const char *val;
9397 	int tid = 0;
9398 	char buf[100];
9399 
9400 	val = get_param(cmd, "TID");
9401 	if (val) {
9402 		tid = atoi(val);
9403 		if (tid)
9404 			ath_sta_inject_frame(dut, intf, tid);
9405 	}
9406 
9407 	/* Command sequence for ADDBA request on Peregrine based devices */
9408 	run_iwpriv(dut, intf, "setaddbaoper 1");
9409 
9410 	snprintf(buf, sizeof(buf), "wifitool %s senddelba 1 %d 1 4", intf, tid);
9411 	if (system(buf) != 0) {
9412 		sigma_dut_print(dut, DUT_MSG_ERROR,
9413 				"wifitool senddelba failed");
9414 	}
9415 
9416 	snprintf(buf, sizeof(buf), "wifitool %s sendaddba 1 %d 64", intf, tid);
9417 	if (system(buf) != 0) {
9418 		sigma_dut_print(dut, DUT_MSG_ERROR,
9419 				"wifitool sendaddba failed");
9420 	}
9421 
9422 	/* UNSUPPORTED: val = get_param(cmd, "Dest_mac"); */
9423 
9424 	return 1;
9425 }
9426 
9427 
9428 #ifdef __linux__
9429 
wil6210_send_addba(struct sigma_dut * dut,const char * dest_mac,int agg_size)9430 static int wil6210_send_addba(struct sigma_dut *dut, const char *dest_mac,
9431 			      int agg_size)
9432 {
9433 	char dir[128], buf[128];
9434 	FILE *f;
9435 	regex_t re;
9436 	regmatch_t m[2];
9437 	int rc, ret = -1, vring_id, found, res;
9438 
9439 	if (wil6210_get_debugfs_dir(dut, dir, sizeof(dir))) {
9440 		sigma_dut_print(dut, DUT_MSG_ERROR,
9441 				"failed to get wil6210 debugfs dir");
9442 		return -1;
9443 	}
9444 
9445 	res = snprintf(buf, sizeof(buf), "%s/vrings", dir);
9446 	if (res < 0 || res >= sizeof(buf))
9447 		return -1;
9448 	f = fopen(buf, "r");
9449 	if (!f) {
9450 		sigma_dut_print(dut, DUT_MSG_ERROR, "failed to open: %s", buf);
9451 		/* newer wil6210 driver renamed file to "rings" */
9452 		res = snprintf(buf, sizeof(buf), "%s/rings", dir);
9453 		if (res < 0 || res >= sizeof(buf))
9454 			return -1;
9455 		f = fopen(buf, "r");
9456 		if (!f) {
9457 			sigma_dut_print(dut, DUT_MSG_ERROR,
9458 					"failed to open: %s", buf);
9459 			return -1;
9460 		}
9461 	}
9462 
9463 	/* can be either VRING tx... or RING... */
9464 	if (regcomp(&re, "RING tx_[ \t]*([0-9]+)", REG_EXTENDED)) {
9465 		sigma_dut_print(dut, DUT_MSG_ERROR, "regcomp failed");
9466 		goto out;
9467 	}
9468 
9469 	/* find TX VRING for the mac address */
9470 	found = 0;
9471 	while (fgets(buf, sizeof(buf), f)) {
9472 		if (strcasestr(buf, dest_mac)) {
9473 			found = 1;
9474 			break;
9475 		}
9476 	}
9477 
9478 	if (!found) {
9479 		sigma_dut_print(dut, DUT_MSG_ERROR,
9480 				"no TX VRING for %s", dest_mac);
9481 		goto out;
9482 	}
9483 
9484 	/* extract VRING ID, "VRING tx_<id> = {" */
9485 	if (!fgets(buf, sizeof(buf), f)) {
9486 		sigma_dut_print(dut, DUT_MSG_ERROR,
9487 				"no VRING start line for %s", dest_mac);
9488 		goto out;
9489 	}
9490 
9491 	rc = regexec(&re, buf, 2, m, 0);
9492 	regfree(&re);
9493 	if (rc || m[1].rm_so < 0) {
9494 		sigma_dut_print(dut, DUT_MSG_ERROR,
9495 				"no VRING TX ID for %s", dest_mac);
9496 		goto out;
9497 	}
9498 	buf[m[1].rm_eo] = 0;
9499 	vring_id = atoi(&buf[m[1].rm_so]);
9500 
9501 	/* send the addba command */
9502 	fclose(f);
9503 	res = snprintf(buf, sizeof(buf), "%s/back", dir);
9504 	if (res < 0 || res >= sizeof(buf))
9505 		return -1;
9506 	f = fopen(buf, "w");
9507 	if (!f) {
9508 		sigma_dut_print(dut, DUT_MSG_ERROR,
9509 				"failed to open: %s", buf);
9510 		return -1;
9511 	}
9512 
9513 	fprintf(f, "add %d %d\n", vring_id, agg_size);
9514 
9515 	ret = 0;
9516 
9517 out:
9518 	fclose(f);
9519 
9520 	return ret;
9521 }
9522 
9523 
send_addba_60g(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd,const char * mac_param)9524 int send_addba_60g(struct sigma_dut *dut, struct sigma_conn *conn,
9525 		   struct sigma_cmd *cmd, const char *mac_param)
9526 {
9527 	const char *val;
9528 	int tid = 0;
9529 
9530 	val = get_param(cmd, "TID");
9531 	if (val) {
9532 		tid = atoi(val);
9533 		if (tid != 0) {
9534 			sigma_dut_print(dut, DUT_MSG_ERROR,
9535 					"Ignore TID %d for send_addba use TID 0 for 60g since only 0 required on TX",
9536 					tid);
9537 		}
9538 	}
9539 
9540 	val = get_param(cmd, mac_param);
9541 	if (!val) {
9542 		sigma_dut_print(dut, DUT_MSG_ERROR,
9543 				"Currently not supporting addba for 60G without Dest_mac");
9544 		return ERROR_SEND_STATUS;
9545 	}
9546 
9547 	if (wil6210_send_addba(dut, val, dut->back_rcv_buf))
9548 		return -1;
9549 
9550 	return 1;
9551 }
9552 
9553 #endif /* __linux__ */
9554 
9555 
wcn_sta_send_addba(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)9556 static int wcn_sta_send_addba(struct sigma_dut *dut, struct sigma_conn *conn,
9557 			      struct sigma_cmd *cmd)
9558 {
9559 #ifdef NL80211_SUPPORT
9560 	const char *intf = get_param(cmd, "Interface");
9561 	const char *val;
9562 	int tid = -1;
9563 	int bufsize = 64;
9564 	struct nl_msg *msg;
9565 	int ret = 0;
9566 	struct nlattr *params;
9567 	int ifindex;
9568 
9569 	val = get_param(cmd, "TID");
9570 	if (val)
9571 		tid = atoi(val);
9572 
9573 	if (tid == -1) {
9574 		send_resp(dut, conn, SIGMA_ERROR,
9575 			  "ErrorCode,sta_send_addba tid invalid");
9576 		return 0;
9577 	}
9578 
9579 	/* UNSUPPORTED: val = get_param(cmd, "Dest_mac"); */
9580 
9581 	ifindex = if_nametoindex(intf);
9582 	if (ifindex == 0) {
9583 		sigma_dut_print(dut, DUT_MSG_ERROR,
9584 				"%s: Index for interface %s failed",
9585 				__func__, intf);
9586 		send_resp(dut, conn, SIGMA_ERROR,
9587 			  "ErrorCode,sta_send_addba interface invalid");
9588 		return 0;
9589 	}
9590 
9591 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
9592 				    NL80211_CMD_VENDOR)) ||
9593 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
9594 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
9595 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
9596 			QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION) ||
9597 	    !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
9598 	    nla_put_u8(msg,
9599 		       QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION,
9600 		       QCA_WLAN_ADD_BA) ||
9601 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID,
9602 		       tid) ||
9603 	    nla_put_u16(msg,
9604 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE,
9605 			bufsize)) {
9606 		sigma_dut_print(dut, DUT_MSG_ERROR,
9607 				"%s: err in adding vendor_cmd and vendor_data",
9608 				__func__);
9609 		nlmsg_free(msg);
9610 		send_resp(dut, conn, SIGMA_ERROR,
9611 			  "ErrorCode,sta_send_addba err in adding vendor_cmd and vendor_data");
9612 		return 0;
9613 	}
9614 	nla_nest_end(msg, params);
9615 
9616 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
9617 	if (ret) {
9618 		sigma_dut_print(dut, DUT_MSG_ERROR,
9619 				"%s: err in send_and_recv_msgs, ret=%d",
9620 				__func__, ret);
9621 		if (ret == -EOPNOTSUPP)
9622 			return 1;
9623 		send_resp(dut, conn, SIGMA_ERROR,
9624 			  "ErrorCode,sta_send_addba err in send_and_recv_msgs");
9625 		return 0;
9626 	}
9627 #else /* NL80211_SUPPORT */
9628 	sigma_dut_print(dut, DUT_MSG_ERROR,
9629 			"sta_send_addba not supported without NL80211_SUPPORT defined");
9630 #endif /* NL80211_SUPPORT */
9631 
9632 	return 1;
9633 }
9634 
9635 
cmd_sta_send_addba(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)9636 static enum sigma_cmd_result cmd_sta_send_addba(struct sigma_dut *dut,
9637 						struct sigma_conn *conn,
9638 						struct sigma_cmd *cmd)
9639 {
9640 	switch (get_driver_type(dut)) {
9641 	case DRIVER_ATHEROS:
9642 		return ath_sta_send_addba(dut, conn, cmd);
9643 	case DRIVER_WCN:
9644 		return wcn_sta_send_addba(dut, conn, cmd);
9645 #ifdef __linux__
9646 	case DRIVER_WIL6210:
9647 		return send_addba_60g(dut, conn, cmd, "Dest_mac");
9648 #endif /* __linux__ */
9649 	default:
9650 		/*
9651 		 * There is no driver specific implementation for other drivers.
9652 		 * Ignore the command and report COMPLETE since the following
9653 		 * throughput test operation will end up sending ADDBA anyway.
9654 		 */
9655 		return 1;
9656 	}
9657 }
9658 
9659 
inject_eth_frame(int s,const void * data,size_t len,unsigned short ethtype,char * dst,char * src)9660 int inject_eth_frame(int s, const void *data, size_t len,
9661 		     unsigned short ethtype, char *dst, char *src)
9662 {
9663 	struct iovec iov[4] = {
9664 		{
9665 			.iov_base = dst,
9666 			.iov_len = ETH_ALEN,
9667 		},
9668 		{
9669 			.iov_base = src,
9670 			.iov_len = ETH_ALEN,
9671 		},
9672 		{
9673 			.iov_base = &ethtype,
9674 			.iov_len = sizeof(unsigned short),
9675 		},
9676 		{
9677 			.iov_base = (void *) data,
9678 			.iov_len = len,
9679 		}
9680 	};
9681 	struct msghdr msg = {
9682 		.msg_name = NULL,
9683 		.msg_namelen = 0,
9684 		.msg_iov = iov,
9685 		.msg_iovlen = 4,
9686 		.msg_control = NULL,
9687 		.msg_controllen = 0,
9688 		.msg_flags = 0,
9689 	};
9690 
9691 	return sendmsg(s, &msg, 0);
9692 }
9693 
9694 #if defined(__linux__) || defined(__QNXNTO__)
9695 
inject_frame(int s,const void * data,size_t len,int encrypt)9696 int inject_frame(int s, const void *data, size_t len, int encrypt)
9697 {
9698 #define	IEEE80211_RADIOTAP_F_WEP	0x04
9699 #define	IEEE80211_RADIOTAP_F_FRAG	0x08
9700 	unsigned char rtap_hdr[] = {
9701 		0x00, 0x00, /* radiotap version */
9702 		0x0e, 0x00, /* radiotap length */
9703 		0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */
9704 		IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */
9705 		0x00,       /* padding */
9706 		0x00, 0x00, /* RX and TX flags to indicate that */
9707 		0x00, 0x00, /* this is the injected frame directly */
9708 	};
9709 	struct iovec iov[2] = {
9710 		{
9711 			.iov_base = &rtap_hdr,
9712 			.iov_len = sizeof(rtap_hdr),
9713 		},
9714 		{
9715 			.iov_base = (void *) data,
9716 			.iov_len = len,
9717 		}
9718 	};
9719 	struct msghdr msg = {
9720 		.msg_name = NULL,
9721 		.msg_namelen = 0,
9722 		.msg_iov = iov,
9723 		.msg_iovlen = 2,
9724 		.msg_control = NULL,
9725 		.msg_controllen = 0,
9726 		.msg_flags = 0,
9727 	};
9728 
9729 	if (encrypt)
9730 		rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;
9731 
9732 	return sendmsg(s, &msg, 0);
9733 }
9734 
9735 
open_monitor(const char * ifname)9736 int open_monitor(const char *ifname)
9737 {
9738 #ifdef __QNXNTO__
9739 	struct sockaddr_dl ll;
9740 	int s;
9741 
9742 	memset(&ll, 0, sizeof(ll));
9743 	ll.sdl_family = AF_LINK;
9744 	ll.sdl_index = if_nametoindex(ifname);
9745 	if (ll.sdl_index == 0) {
9746 		perror("if_nametoindex");
9747 		return -1;
9748 	}
9749 	s = socket(PF_INET, SOCK_RAW, 0);
9750 #else /* __QNXNTO__ */
9751 	struct sockaddr_ll ll;
9752 	int s;
9753 
9754 	memset(&ll, 0, sizeof(ll));
9755 	ll.sll_family = AF_PACKET;
9756 	ll.sll_ifindex = if_nametoindex(ifname);
9757 	if (ll.sll_ifindex == 0) {
9758 		perror("if_nametoindex");
9759 		return -1;
9760 	}
9761 	s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
9762 #endif /* __QNXNTO__ */
9763 	if (s < 0) {
9764 		perror("socket[PF_PACKET,SOCK_RAW]");
9765 		return -1;
9766 	}
9767 
9768 	if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
9769 		perror("monitor socket bind");
9770 		close(s);
9771 		return -1;
9772 	}
9773 
9774 	return s;
9775 }
9776 
9777 
hex2num(char c)9778 static int hex2num(char c)
9779 {
9780 	if (c >= '0' && c <= '9')
9781 		return c - '0';
9782 	if (c >= 'a' && c <= 'f')
9783 		return c - 'a' + 10;
9784 	if (c >= 'A' && c <= 'F')
9785 		return c - 'A' + 10;
9786 	return -1;
9787 }
9788 
9789 
hwaddr_aton(const char * txt,unsigned char * addr)9790 int hwaddr_aton(const char *txt, unsigned char *addr)
9791 {
9792 	int i;
9793 
9794 	for (i = 0; i < 6; i++) {
9795 		int a, b;
9796 
9797 		a = hex2num(*txt++);
9798 		if (a < 0)
9799 			return -1;
9800 		b = hex2num(*txt++);
9801 		if (b < 0)
9802 			return -1;
9803 		*addr++ = (a << 4) | b;
9804 		if (i < 5 && *txt++ != ':')
9805 			return -1;
9806 	}
9807 
9808 	return 0;
9809 }
9810 
9811 #endif /* defined(__linux__) || defined(__QNXNTO__) */
9812 
9813 
9814 #ifdef NL80211_SUPPORT
nl80211_send_frame_cmd(struct sigma_dut * dut,const char * intf,const u8 * data,size_t data_len,int freq)9815 static int nl80211_send_frame_cmd(struct sigma_dut *dut, const char *intf,
9816 				  const u8 *data, size_t data_len, int freq)
9817 {
9818 	struct nl_msg *msg;
9819 	int ret = 0;
9820 	int ifindex;
9821 
9822 	ifindex = if_nametoindex(intf);
9823 	if (ifindex == 0) {
9824 		sigma_dut_print(dut, DUT_MSG_ERROR,
9825 				"%s: Index for interface %s failed",
9826 				__func__, intf);
9827 		return -1;
9828 	}
9829 
9830 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
9831 				    NL80211_CMD_FRAME)) ||
9832 	    (freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
9833 	    nla_put(msg, NL80211_ATTR_FRAME, data_len, data)) {
9834 		sigma_dut_print(dut, DUT_MSG_ERROR,
9835 				"%s: Error in adding NL80211_CMD_FRAME",
9836 				__func__);
9837 		nlmsg_free(msg);
9838 		return -1;
9839 	}
9840 
9841 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
9842 	if (ret) {
9843 		sigma_dut_print(dut, DUT_MSG_ERROR,
9844 				"nl80211: Frame command failed: ret=%d (%s) req=%u",
9845 				ret, strerror(-ret), freq);
9846 		return -1;
9847 	}
9848 
9849 	return 0;
9850 }
9851 #endif /* NL80211_SUPPORT */
9852 
9853 
9854 enum send_frame_type {
9855 	DISASSOC, DEAUTH, SAQUERY, AUTH, ASSOCREQ, REASSOCREQ, DLS_REQ
9856 };
9857 enum send_frame_protection {
9858 	CORRECT_KEY, INCORRECT_KEY, UNPROTECTED
9859 };
9860 
9861 
sta_inject_frame(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,enum send_frame_type frame,enum send_frame_protection protected,const char * dest,int use_monitor)9862 static int sta_inject_frame(struct sigma_dut *dut, struct sigma_conn *conn,
9863 			    const char *intf, enum send_frame_type frame,
9864 			    enum send_frame_protection protected,
9865 			    const char *dest, int use_monitor)
9866 {
9867 #ifdef __linux__
9868 	unsigned char buf[1000], *pos;
9869 	int s, res;
9870 	char bssid[20], addr[20];
9871 	char result[32], ssid[100];
9872 	size_t ssid_len;
9873 
9874 	if (get_wpa_status(get_station_ifname(dut), "wpa_state", result,
9875 			   sizeof(result)) < 0 ||
9876 	    strncmp(result, "COMPLETED", 9) != 0) {
9877 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Not connected");
9878 		return 0;
9879 	}
9880 
9881 	if (get_wpa_status(get_station_ifname(dut), "bssid",
9882 			   bssid, sizeof(bssid)) < 0) {
9883 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
9884 			  "current BSSID");
9885 		return 0;
9886 	}
9887 
9888 	if (get_wpa_status(get_station_ifname(dut), "address",
9889 			   addr, sizeof(addr)) < 0) {
9890 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
9891 			  "own MAC address");
9892 		return 0;
9893 	}
9894 
9895 	if (get_wpa_status(get_station_ifname(dut), "ssid", ssid, sizeof(ssid))
9896 	    < 0) {
9897 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not get "
9898 			  "current SSID");
9899 		return 0;
9900 	}
9901 	ssid_len = strlen(ssid);
9902 
9903 	pos = buf;
9904 
9905 	/* Frame Control */
9906 	switch (frame) {
9907 	case DISASSOC:
9908 		*pos++ = 0xa0;
9909 		break;
9910 	case DEAUTH:
9911 		*pos++ = 0xc0;
9912 		break;
9913 	case SAQUERY:
9914 		*pos++ = 0xd0;
9915 		break;
9916 	case AUTH:
9917 		*pos++ = 0xb0;
9918 		break;
9919 	case ASSOCREQ:
9920 		*pos++ = 0x00;
9921 		break;
9922 	case REASSOCREQ:
9923 		*pos++ = 0x20;
9924 		break;
9925 	case DLS_REQ:
9926 		*pos++ = 0xd0;
9927 		break;
9928 	}
9929 
9930 	if (protected == INCORRECT_KEY)
9931 		*pos++ = 0x40; /* Set Protected field to 1 */
9932 	else
9933 		*pos++ = 0x00;
9934 
9935 	/* Duration */
9936 	*pos++ = 0x00;
9937 	*pos++ = 0x00;
9938 
9939 	/* addr1 = DA (current AP) */
9940 	hwaddr_aton(bssid, pos);
9941 	pos += 6;
9942 	/* addr2 = SA (own address) */
9943 	hwaddr_aton(addr, pos);
9944 	pos += 6;
9945 	/* addr3 = BSSID (current AP) */
9946 	hwaddr_aton(bssid, pos);
9947 	pos += 6;
9948 
9949 	/* Seq# (to be filled by driver/mac80211) */
9950 	*pos++ = 0x00;
9951 	*pos++ = 0x00;
9952 
9953 	if (protected == INCORRECT_KEY) {
9954 		/* CCMP parameters */
9955 		memcpy(pos, "\x61\x01\x00\x20\x00\x10\x00\x00", 8);
9956 		pos += 8;
9957 	}
9958 
9959 	if (protected == INCORRECT_KEY) {
9960 		switch (frame) {
9961 		case DEAUTH:
9962 			/* Reason code (encrypted) */
9963 			memcpy(pos, "\xa7\x39", 2);
9964 			pos += 2;
9965 			break;
9966 		case DISASSOC:
9967 			/* Reason code (encrypted) */
9968 			memcpy(pos, "\xa7\x39", 2);
9969 			pos += 2;
9970 			break;
9971 		case SAQUERY:
9972 			/* Category|Action|TransID (encrypted) */
9973 			memcpy(pos, "\x6f\xbd\xe9\x4d", 4);
9974 			pos += 4;
9975 			break;
9976 		default:
9977 			return -1;
9978 		}
9979 
9980 		/* CCMP MIC */
9981 		memcpy(pos, "\xc8\xd8\x3b\x06\x5d\xb7\x25\x68", 8);
9982 		pos += 8;
9983 	} else {
9984 		switch (frame) {
9985 		case DEAUTH:
9986 			/* reason code = 8 */
9987 			*pos++ = 0x08;
9988 			*pos++ = 0x00;
9989 			break;
9990 		case DISASSOC:
9991 			/* reason code = 8 */
9992 			*pos++ = 0x08;
9993 			*pos++ = 0x00;
9994 			break;
9995 		case SAQUERY:
9996 			/* Category - SA Query */
9997 			*pos++ = 0x08;
9998 			/* SA query Action - Request */
9999 			*pos++ = 0x00;
10000 			/* Transaction ID */
10001 			*pos++ = 0x12;
10002 			*pos++ = 0x34;
10003 			if (dut->saquery_oci_freq) {
10004 				/* OCI IE - Extended ID */
10005 				*pos++ = 0xFF;
10006 				*pos++ = 0x04;
10007 				*pos++ = 0x36;
10008 				/* Operating Class */
10009 				*pos++ = 0x74;
10010 				/* Primary Channel */
10011 				*pos++ = freq_to_channel(dut->saquery_oci_freq);
10012 				/* Frequency Segment 1 Channel Number */
10013 				*pos++ = 0x00;
10014 			}
10015 			break;
10016 		case AUTH:
10017 			/* Auth Alg (Open) */
10018 			*pos++ = 0x00;
10019 			*pos++ = 0x00;
10020 			/* Seq# */
10021 			*pos++ = 0x01;
10022 			*pos++ = 0x00;
10023 			/* Status code */
10024 			*pos++ = 0x00;
10025 			*pos++ = 0x00;
10026 			break;
10027 		case ASSOCREQ:
10028 			/* Capability Information */
10029 			*pos++ = 0x31;
10030 			*pos++ = 0x04;
10031 			/* Listen Interval */
10032 			*pos++ = 0x0a;
10033 			*pos++ = 0x00;
10034 			/* SSID */
10035 			*pos++ = 0x00;
10036 			*pos++ = ssid_len;
10037 			memcpy(pos, ssid, ssid_len);
10038 			pos += ssid_len;
10039 			/* Supported Rates */
10040 			memcpy(pos, "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24",
10041 			       10);
10042 			pos += 10;
10043 			/* Extended Supported Rates */
10044 			memcpy(pos, "\x32\x04\x30\x48\x60\x6c", 6);
10045 			pos += 6;
10046 			/* RSN */
10047 			memcpy(pos, "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00"
10048 			       "\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\xc0"
10049 			       "\x00\x00\x00\x00\x0f\xac\x06", 28);
10050 			pos += 28;
10051 			break;
10052 		case REASSOCREQ:
10053 			/* Capability Information */
10054 			*pos++ = 0x31;
10055 			*pos++ = 0x04;
10056 			/* Listen Interval */
10057 			*pos++ = 0x0a;
10058 			*pos++ = 0x00;
10059 			/* Current AP */
10060 			hwaddr_aton(bssid, pos);
10061 			pos += 6;
10062 			/* SSID */
10063 			*pos++ = 0x00;
10064 			*pos++ = ssid_len;
10065 			memcpy(pos, ssid, ssid_len);
10066 			pos += ssid_len;
10067 			/* Supported Rates */
10068 			memcpy(pos, "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24",
10069 			       10);
10070 			pos += 10;
10071 			/* Extended Supported Rates */
10072 			memcpy(pos, "\x32\x04\x30\x48\x60\x6c", 6);
10073 			pos += 6;
10074 			/* RSNE - Group and Pairwise ciphers */
10075 			memcpy(pos,
10076 			       "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04",
10077 			       14);
10078 			pos += 14;
10079 			/* RSNE - AKM Suite count */
10080 			*pos++ = 0x01;
10081 			*pos++ = 0x00;
10082 			/* RSNE - AKM Suites */
10083 			if (dut->program == PROGRAM_WPA3)
10084 				memcpy(pos, "\x00\x0f\xac\x08", 4);
10085 			else
10086 				memcpy(pos, "\x00\x0f\xac\x02", 4);
10087 			pos += 4;
10088 			/* RSNE - Capabilities */
10089 			*pos++ = 0xc0;
10090 			if (dut->ocvc)
10091 				*pos++ = 0x40;
10092 			else
10093 				*pos++ = 0x00;
10094 			/* RSNE - PMKID list and Group Management Ciphers */
10095 			memcpy(pos, "\x00\x00\x00\x0f\xac\x06", 6);
10096 			pos += 6;
10097 			break;
10098 		case DLS_REQ:
10099 			/* Category - DLS */
10100 			*pos++ = 0x02;
10101 			/* DLS Action - Request */
10102 			*pos++ = 0x00;
10103 			/* Destination MACAddress */
10104 			if (dest)
10105 				hwaddr_aton(dest, pos);
10106 			else
10107 				memset(pos, 0, 6);
10108 			pos += 6;
10109 			/* Source MACAddress */
10110 			hwaddr_aton(addr, pos);
10111 			pos += 6;
10112 			/* Capability Information */
10113 			*pos++ = 0x10; /* Privacy */
10114 			*pos++ = 0x06; /* QoS */
10115 			/* DLS Timeout Value */
10116 			*pos++ = 0x00;
10117 			*pos++ = 0x01;
10118 			/* Supported rates */
10119 			*pos++ = 0x01;
10120 			*pos++ = 0x08;
10121 			*pos++ = 0x0c; /* 6 Mbps */
10122 			*pos++ = 0x12; /* 9 Mbps */
10123 			*pos++ = 0x18; /* 12 Mbps */
10124 			*pos++ = 0x24; /* 18 Mbps */
10125 			*pos++ = 0x30; /* 24 Mbps */
10126 			*pos++ = 0x48; /* 36 Mbps */
10127 			*pos++ = 0x60; /* 48 Mbps */
10128 			*pos++ = 0x6c; /* 54 Mbps */
10129 			/* TODO: Extended Supported Rates */
10130 			/* TODO: HT Capabilities */
10131 			break;
10132 		}
10133 	}
10134 
10135 	if (use_monitor) {
10136 		s = open_monitor("sigmadut");
10137 		if (s < 0) {
10138 			send_resp(dut, conn, SIGMA_ERROR,
10139 				  "errorCode,Failed to open monitor socket");
10140 			return 0;
10141 		}
10142 
10143 		res = inject_frame(s, buf, pos - buf, protected == CORRECT_KEY);
10144 		if (res < 0) {
10145 			send_resp(dut, conn, SIGMA_ERROR,
10146 				  "errorCode,Failed to inject frame");
10147 			close(s);
10148 			return 0;
10149 		}
10150 		if (res < pos - buf) {
10151 			send_resp(dut, conn, SIGMA_ERROR,
10152 				  "errorCode,Only partial frame sent");
10153 			close(s);
10154 			return 0;
10155 		}
10156 
10157 		close(s);
10158 	} else {
10159 #ifdef NL80211_SUPPORT
10160 		int freq;
10161 		char freq_str[10];
10162 
10163 		if (get_wpa_status(get_station_ifname(dut), "freq",
10164 				   freq_str, sizeof(freq_str)) < 0) {
10165 			send_resp(dut, conn, SIGMA_ERROR,
10166 				  "errorCode,Could not get current operating frequency");
10167 			return 0;
10168 		}
10169 		freq = atoi(freq_str);
10170 
10171 		if (nl80211_send_frame_cmd(dut, intf, buf, pos - buf, freq)) {
10172 			send_resp(dut, conn, SIGMA_ERROR,
10173 				  "errorCode,Failed to inject frame");
10174 			return 0;
10175 		}
10176 #else /* NL80211_SUPPORT */
10177 		send_resp(dut, conn, SIGMA_ERROR,
10178 			  "errorCode,Failed to inject frame (no NL80211_SUPPORT)");
10179 		return 0;
10180 #endif /* NL80211_SUPPORT */
10181 	}
10182 
10183 	return 1;
10184 #else /* __linux__ */
10185 	send_resp(dut, conn, SIGMA_ERROR, "errorCode,sta_send_frame not "
10186 		  "yet supported");
10187 	return 0;
10188 #endif /* __linux__ */
10189 }
10190 
10191 
cmd_sta_send_frame_tdls(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)10192 static int cmd_sta_send_frame_tdls(struct sigma_dut *dut,
10193 				   struct sigma_conn *conn,
10194 				   struct sigma_cmd *cmd)
10195 {
10196 	const char *intf = get_param(cmd, "Interface");
10197 	const char *sta, *val;
10198 	unsigned char addr[ETH_ALEN];
10199 	char buf[100];
10200 
10201 	if (!intf)
10202 		return -1;
10203 
10204 	sta = get_param(cmd, "peer");
10205 	if (sta == NULL)
10206 		sta = get_param(cmd, "station");
10207 	if (sta == NULL) {
10208 		send_resp(dut, conn, SIGMA_ERROR,
10209 			  "ErrorCode,Missing peer address");
10210 		return 0;
10211 	}
10212 	if (hwaddr_aton(sta, addr) < 0) {
10213 		send_resp(dut, conn, SIGMA_ERROR,
10214 			  "ErrorCode,Invalid peer address");
10215 		return 0;
10216 	}
10217 
10218 	val = get_param(cmd, "type");
10219 	if (val == NULL)
10220 		return -1;
10221 
10222 	if (strcasecmp(val, "DISCOVERY") == 0) {
10223 		snprintf(buf, sizeof(buf), "TDLS_DISCOVER %s", sta);
10224 		if (wpa_command(intf, buf) < 0) {
10225 			send_resp(dut, conn, SIGMA_ERROR,
10226 				  "ErrorCode,Failed to send TDLS discovery");
10227 			return 0;
10228 		}
10229 		return 1;
10230 	}
10231 
10232 	if (strcasecmp(val, "SETUP") == 0) {
10233 		int status = 0, timeout = 0;
10234 
10235 		val = get_param(cmd, "Status");
10236 		if (val)
10237 			status = atoi(val);
10238 
10239 		val = get_param(cmd, "Timeout");
10240 		if (val)
10241 			timeout = atoi(val);
10242 
10243 		if (status != 0 && status != 37) {
10244 			send_resp(dut, conn, SIGMA_ERROR,
10245 				  "ErrorCode,Unsupported status value");
10246 			return 0;
10247 		}
10248 
10249 		if (timeout != 0 && timeout != 301) {
10250 			send_resp(dut, conn, SIGMA_ERROR,
10251 				  "ErrorCode,Unsupported timeout value");
10252 			return 0;
10253 		}
10254 
10255 		if (status && timeout) {
10256 			send_resp(dut, conn, SIGMA_ERROR,
10257 				  "ErrorCode,Unsupported timeout+status "
10258 				  "combination");
10259 			return 0;
10260 		}
10261 
10262 		if (status == 37 &&
10263 		    wpa_command(intf, "SET tdls_testing 0x200")) {
10264 			send_resp(dut, conn, SIGMA_ERROR,
10265 				  "ErrorCode,Failed to enable "
10266 				  "decline setup response test mode");
10267 			return 0;
10268 		}
10269 
10270 		if (timeout == 301) {
10271 			int res;
10272 			if (dut->no_tpk_expiration)
10273 				res = wpa_command(intf,
10274 						  "SET tdls_testing 0x108");
10275 			else
10276 				res = wpa_command(intf,
10277 						  "SET tdls_testing 0x8");
10278 			if (res) {
10279 				send_resp(dut, conn, SIGMA_ERROR,
10280 					  "ErrorCode,Failed to set short TPK "
10281 					  "lifetime");
10282 				return 0;
10283 			}
10284 		}
10285 
10286 		snprintf(buf, sizeof(buf), "TDLS_SETUP %s", sta);
10287 		if (wpa_command(intf, buf) < 0) {
10288 			send_resp(dut, conn, SIGMA_ERROR,
10289 				  "ErrorCode,Failed to send TDLS setup");
10290 			return 0;
10291 		}
10292 		return 1;
10293 	}
10294 
10295 	if (strcasecmp(val, "TEARDOWN") == 0) {
10296 		snprintf(buf, sizeof(buf), "TDLS_TEARDOWN %s", sta);
10297 		if (wpa_command(intf, buf) < 0) {
10298 			send_resp(dut, conn, SIGMA_ERROR,
10299 				  "ErrorCode,Failed to send TDLS teardown");
10300 			return 0;
10301 		}
10302 		return 1;
10303 	}
10304 
10305 	send_resp(dut, conn, SIGMA_ERROR,
10306 		  "ErrorCode,Unsupported TDLS frame");
10307 	return 0;
10308 }
10309 
10310 
sta_ap_known(const char * ifname,const char * bssid)10311 static int sta_ap_known(const char *ifname, const char *bssid)
10312 {
10313 	char buf[4096];
10314 
10315 	snprintf(buf, sizeof(buf), "BSS MASK=1 %s", bssid);
10316 	if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0)
10317 		return 0;
10318 	if (strncmp(buf, "id=", 3) != 0)
10319 		return 0;
10320 	return 1;
10321 }
10322 
10323 
sta_scan_ap(struct sigma_dut * dut,const char * ifname,const char * bssid)10324 static int sta_scan_ap(struct sigma_dut *dut, const char *ifname,
10325 		       const char *bssid)
10326 {
10327 	int res;
10328 	struct wpa_ctrl *ctrl;
10329 	char buf[256];
10330 
10331 	if (sta_ap_known(ifname, bssid))
10332 		return 0;
10333 	sigma_dut_print(dut, DUT_MSG_DEBUG,
10334 			"AP not in BSS table - start scan");
10335 
10336 	ctrl = open_wpa_mon(ifname);
10337 	if (ctrl == NULL) {
10338 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
10339 				"wpa_supplicant monitor connection");
10340 		return -1;
10341 	}
10342 
10343 	if (wpa_command(ifname, "SCAN") < 0) {
10344 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to start scan");
10345 		wpa_ctrl_detach(ctrl);
10346 		wpa_ctrl_close(ctrl);
10347 		return -1;
10348 	}
10349 
10350 	res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-SCAN-RESULTS",
10351 				buf, sizeof(buf));
10352 
10353 	wpa_ctrl_detach(ctrl);
10354 	wpa_ctrl_close(ctrl);
10355 
10356 	if (res < 0) {
10357 		sigma_dut_print(dut, DUT_MSG_INFO, "Scan did not complete");
10358 		return -1;
10359 	}
10360 
10361 	if (sta_ap_known(ifname, bssid))
10362 		return 0;
10363 	sigma_dut_print(dut, DUT_MSG_INFO, "AP not in BSS table");
10364 	return -1;
10365 }
10366 
10367 
cmd_sta_send_frame_hs2_neighadv(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd,const char * intf)10368 static int cmd_sta_send_frame_hs2_neighadv(struct sigma_dut *dut,
10369 					   struct sigma_conn *conn,
10370 					   struct sigma_cmd *cmd,
10371 					   const char *intf)
10372 {
10373 	char buf[200];
10374 
10375 	snprintf(buf, sizeof(buf), "ndsend 2001:DB8::1 %s", intf);
10376 	if (system(buf) != 0) {
10377 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to run "
10378 			  "ndsend");
10379 		return 0;
10380 	}
10381 
10382 	return 1;
10383 }
10384 
10385 
cmd_sta_send_frame_hs2_neighsolreq(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd,const char * intf)10386 static int cmd_sta_send_frame_hs2_neighsolreq(struct sigma_dut *dut,
10387 					      struct sigma_conn *conn,
10388 					      struct sigma_cmd *cmd,
10389 					      const char *intf)
10390 {
10391 	char buf[200];
10392 	const char *ip = get_param(cmd, "SenderIP");
10393 
10394 	if (!ip)
10395 		return 0;
10396 
10397 	snprintf(buf, sizeof(buf), "ndisc6 -nm %s %s -r 4", ip, intf);
10398 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
10399 	if (system(buf) == 0) {
10400 		sigma_dut_print(dut, DUT_MSG_INFO,
10401 				"Neighbor Solicitation got a response "
10402 				"for %s@%s", ip, intf);
10403 	}
10404 
10405 	return 1;
10406 }
10407 
10408 
cmd_sta_send_frame_hs2_arpprobe(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd,const char * ifname)10409 static int cmd_sta_send_frame_hs2_arpprobe(struct sigma_dut *dut,
10410 					   struct sigma_conn *conn,
10411 					   struct sigma_cmd *cmd,
10412 					   const char *ifname)
10413 {
10414 	char buf[200];
10415 	const char *ip = get_param(cmd, "SenderIP");
10416 
10417 	if (ip == NULL) {
10418 		send_resp(dut, conn, SIGMA_ERROR,
10419 			  "ErrorCode,Missing SenderIP parameter");
10420 		return 0;
10421 	}
10422 	snprintf(buf, sizeof(buf), "arping -I %s -D %s -c 4", ifname, ip);
10423 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
10424 	if (system(buf) != 0) {
10425 		sigma_dut_print(dut, DUT_MSG_INFO, "arping DAD got a response "
10426 				"for %s@%s", ip, ifname);
10427 	}
10428 
10429 	return 1;
10430 }
10431 
10432 
cmd_sta_send_frame_hs2_arpannounce(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd,const char * ifname)10433 static int cmd_sta_send_frame_hs2_arpannounce(struct sigma_dut *dut,
10434 					      struct sigma_conn *conn,
10435 					      struct sigma_cmd *cmd,
10436 					      const char *ifname)
10437 {
10438 	char buf[200];
10439 	char ip[16];
10440 	int s;
10441 	struct ifreq ifr;
10442 	struct sockaddr_in saddr;
10443 
10444 	s = socket(PF_INET, SOCK_DGRAM, 0);
10445 	if (s < 0) {
10446 		perror("socket");
10447 		return -1;
10448 	}
10449 
10450 	memset(&ifr, 0, sizeof(ifr));
10451 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
10452 	if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
10453 		sigma_dut_print(dut, DUT_MSG_INFO,
10454 				"Failed to get %s IP address: %s",
10455 				ifname, strerror(errno));
10456 		close(s);
10457 		return -1;
10458 	}
10459 	close(s);
10460 
10461 	memcpy(&saddr, &ifr.ifr_addr, sizeof(struct sockaddr_in));
10462 	strlcpy(ip, inet_ntoa(saddr.sin_addr), sizeof(ip));
10463 
10464 	snprintf(buf, sizeof(buf), "arping -I %s -s %s %s -c 4", ifname, ip,
10465 		 ip);
10466 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
10467 	if (system(buf) != 0) {
10468 	}
10469 
10470 	return 1;
10471 }
10472 
10473 
cmd_sta_send_frame_hs2_arpreply(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd,const char * ifname)10474 static int cmd_sta_send_frame_hs2_arpreply(struct sigma_dut *dut,
10475 					   struct sigma_conn *conn,
10476 					   struct sigma_cmd *cmd,
10477 					   const char *ifname)
10478 {
10479 	char buf[200], addr[20];
10480 	char dst[ETH_ALEN], src[ETH_ALEN];
10481 	short ethtype = htons(ETH_P_ARP);
10482 	char *pos;
10483 	int s, res;
10484 	const char *val;
10485 	struct sockaddr_in taddr;
10486 
10487 	val = get_param(cmd, "dest");
10488 	if (val)
10489 		hwaddr_aton(val, (unsigned char *) dst);
10490 
10491 	val = get_param(cmd, "DestIP");
10492 	if (val)
10493 		inet_aton(val, &taddr.sin_addr);
10494 	else
10495 		return -2;
10496 
10497 	if (get_wpa_status(get_station_ifname(dut), "address", addr,
10498 			   sizeof(addr)) < 0)
10499 		return -2;
10500 	hwaddr_aton(addr, (unsigned char *) src);
10501 
10502 	pos = buf;
10503 	*pos++ = 0x00;
10504 	*pos++ = 0x01;
10505 	*pos++ = 0x08;
10506 	*pos++ = 0x00;
10507 	*pos++ = 0x06;
10508 	*pos++ = 0x04;
10509 	*pos++ = 0x00;
10510 	*pos++ = 0x02;
10511 	memcpy(pos, src, ETH_ALEN);
10512 	pos += ETH_ALEN;
10513 	memcpy(pos, &taddr.sin_addr, 4);
10514 	pos += 4;
10515 	memcpy(pos, dst, ETH_ALEN);
10516 	pos += ETH_ALEN;
10517 	memcpy(pos, &taddr.sin_addr, 4);
10518 	pos += 4;
10519 
10520 	s = open_monitor(get_station_ifname(dut));
10521 	if (s < 0) {
10522 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to open "
10523 			  "monitor socket");
10524 		return 0;
10525 	}
10526 
10527 	res = inject_eth_frame(s, buf, pos - buf, ethtype, dst, src);
10528 	if (res < 0) {
10529 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to "
10530 			  "inject frame");
10531 		close(s);
10532 		return 0;
10533 	}
10534 
10535 	close(s);
10536 
10537 	return 1;
10538 }
10539 
10540 
cmd_sta_send_frame_hs2_dls_req(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd,const char * intf,const char * dest)10541 static int cmd_sta_send_frame_hs2_dls_req(struct sigma_dut *dut,
10542 					  struct sigma_conn *conn,
10543 					  struct sigma_cmd *cmd,
10544 					  const char *intf, const char *dest)
10545 {
10546 	char buf[100];
10547 
10548 	if (if_nametoindex("sigmadut") == 0) {
10549 		snprintf(buf, sizeof(buf),
10550 			 "iw dev %s interface add sigmadut type monitor",
10551 			 get_station_ifname(dut));
10552 		if (system(buf) != 0 ||
10553 		    if_nametoindex("sigmadut") == 0) {
10554 			sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add "
10555 					"monitor interface with '%s'", buf);
10556 			return -2;
10557 		}
10558 	}
10559 
10560 	if (system("ifconfig sigmadut up") != 0) {
10561 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
10562 				"monitor interface up");
10563 		return -2;
10564 	}
10565 
10566 	return sta_inject_frame(dut, conn, intf, DLS_REQ, UNPROTECTED, dest, 1);
10567 }
10568 
10569 
cmd_sta_send_frame_hs2(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)10570 static int cmd_sta_send_frame_hs2(struct sigma_dut *dut,
10571 				  struct sigma_conn *conn,
10572 				  struct sigma_cmd *cmd)
10573 {
10574 	const char *intf = get_param(cmd, "Interface");
10575 	const char *dest = get_param(cmd, "Dest");
10576 	const char *type = get_param(cmd, "FrameName");
10577 	const char *val;
10578 	char buf[200], *pos, *end;
10579 	int count, count2;
10580 
10581 	if (type == NULL)
10582 		type = get_param(cmd, "Type");
10583 
10584 	if (intf == NULL || dest == NULL || type == NULL)
10585 		return -1;
10586 
10587 	if (strcasecmp(type, "NeighAdv") == 0)
10588 		return cmd_sta_send_frame_hs2_neighadv(dut, conn, cmd, intf);
10589 
10590 	if (strcasecmp(type, "NeighSolicitReq") == 0)
10591 		return cmd_sta_send_frame_hs2_neighsolreq(dut, conn, cmd, intf);
10592 
10593 	if (strcasecmp(type, "ARPProbe") == 0)
10594 		return cmd_sta_send_frame_hs2_arpprobe(dut, conn, cmd, intf);
10595 
10596 	if (strcasecmp(type, "ARPAnnounce") == 0)
10597 		return cmd_sta_send_frame_hs2_arpannounce(dut, conn, cmd, intf);
10598 
10599 	if (strcasecmp(type, "ARPReply") == 0)
10600 		return cmd_sta_send_frame_hs2_arpreply(dut, conn, cmd, intf);
10601 
10602 	if (strcasecmp(type, "DLS-request") == 0 ||
10603 	    strcasecmp(type, "DLSrequest") == 0)
10604 		return cmd_sta_send_frame_hs2_dls_req(dut, conn, cmd, intf,
10605 						      dest);
10606 
10607 	if (strcasecmp(type, "ANQPQuery") != 0 &&
10608 	    strcasecmp(type, "Query") != 0) {
10609 		send_resp(dut, conn, SIGMA_ERROR,
10610 			  "ErrorCode,Unsupported HS 2.0 send frame type");
10611 		return 0;
10612 	}
10613 
10614 	if (sta_scan_ap(dut, intf, dest) < 0) {
10615 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not find "
10616 			  "the requested AP");
10617 		return 0;
10618 	}
10619 
10620 	pos = buf;
10621 	end = buf + sizeof(buf);
10622 	count = 0;
10623 	pos += snprintf(pos, end - pos, "ANQP_GET %s ", dest);
10624 
10625 	val = get_param(cmd, "ANQP_CAP_LIST");
10626 	if (val && atoi(val)) {
10627 		pos += snprintf(pos, end - pos, "%s257", count > 0 ? "," : "");
10628 		count++;
10629 	}
10630 
10631 	val = get_param(cmd, "VENUE_NAME");
10632 	if (val && atoi(val)) {
10633 		pos += snprintf(pos, end - pos, "%s258", count > 0 ? "," : "");
10634 		count++;
10635 	}
10636 
10637 	val = get_param(cmd, "NETWORK_AUTH_TYPE");
10638 	if (val && atoi(val)) {
10639 		pos += snprintf(pos, end - pos, "%s260", count > 0 ? "," : "");
10640 		count++;
10641 	}
10642 
10643 	val = get_param(cmd, "ROAMING_CONS");
10644 	if (val && atoi(val)) {
10645 		pos += snprintf(pos, end - pos, "%s261", count > 0 ? "," : "");
10646 		count++;
10647 	}
10648 
10649 	val = get_param(cmd, "IP_ADDR_TYPE_AVAILABILITY");
10650 	if (val && atoi(val)) {
10651 		pos += snprintf(pos, end - pos, "%s262", count > 0 ? "," : "");
10652 		count++;
10653 	}
10654 
10655 	val = get_param(cmd, "NAI_REALM_LIST");
10656 	if (val && atoi(val)) {
10657 		pos += snprintf(pos, end - pos, "%s263", count > 0 ? "," : "");
10658 		count++;
10659 	}
10660 
10661 	val = get_param(cmd, "3GPP_INFO");
10662 	if (val && atoi(val)) {
10663 		pos += snprintf(pos, end - pos, "%s264", count > 0 ? "," : "");
10664 		count++;
10665 	}
10666 
10667 	val = get_param(cmd, "DOMAIN_LIST");
10668 	if (val && atoi(val)) {
10669 		pos += snprintf(pos, end - pos, "%s268", count > 0 ? "," : "");
10670 		count++;
10671 	}
10672 
10673 	val = get_param(cmd, "Venue_URL");
10674 	if (val && atoi(val)) {
10675 		pos += snprintf(pos, end - pos, "%s277", count > 0 ? "," : "");
10676 		count++;
10677 	}
10678 
10679 	val = get_param(cmd, "Advice_Of_Charge");
10680 	if (val && atoi(val)) {
10681 		pos += snprintf(pos, end - pos, "%s278", count > 0 ? "," : "");
10682 		count++;
10683 	}
10684 
10685 	if (count && wpa_command(intf, buf)) {
10686 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,ANQP_GET failed");
10687 		return 0;
10688 	}
10689 
10690 	pos = buf;
10691 	end = buf + sizeof(buf);
10692 	count2 = 0;
10693 	pos += snprintf(pos, end - pos, "HS20_ANQP_GET %s ", dest);
10694 
10695 	val = get_param(cmd, "HS_CAP_LIST");
10696 	if (val && atoi(val)) {
10697 		pos += snprintf(pos, end - pos, "%s2", count2 > 0 ? "," : "");
10698 		count2++;
10699 	}
10700 
10701 	val = get_param(cmd, "OPER_NAME");
10702 	if (val && atoi(val)) {
10703 		pos += snprintf(pos, end - pos, "%s3", count2 > 0 ? "," : "");
10704 		count2++;
10705 	}
10706 
10707 	val = get_param(cmd, "WAN_METRICS");
10708 	if (!val)
10709 		val = get_param(cmd, "WAN_MAT");
10710 	if (!val)
10711 		val = get_param(cmd, "WAN_MET");
10712 	if (val && atoi(val)) {
10713 		pos += snprintf(pos, end - pos, "%s4", count2 > 0 ? "," : "");
10714 		count2++;
10715 	}
10716 
10717 	val = get_param(cmd, "CONNECTION_CAPABILITY");
10718 	if (val && atoi(val)) {
10719 		pos += snprintf(pos, end - pos, "%s5", count2 > 0 ? "," : "");
10720 		count2++;
10721 	}
10722 
10723 	val = get_param(cmd, "OP_CLASS");
10724 	if (val && atoi(val)) {
10725 		pos += snprintf(pos, end - pos, "%s7", count2 > 0 ? "," : "");
10726 		count2++;
10727 	}
10728 
10729 	val = get_param(cmd, "OSU_PROVIDER_LIST");
10730 	if (val && atoi(val)) {
10731 		pos += snprintf(pos, end - pos, "%s8", count2 > 0 ? "," : "");
10732 		count2++;
10733 	}
10734 
10735 	val = get_param(cmd, "OPER_ICON_METADATA");
10736 	if (!val)
10737 		val = get_param(cmd, "OPERATOR_ICON_METADATA");
10738 	if (val && atoi(val)) {
10739 		pos += snprintf(pos, end - pos, "%s12", count2 > 0 ? "," : "");
10740 		count2++;
10741 	}
10742 
10743 	if (count && count2) {
10744 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before sending out "
10745 				"second query");
10746 		sleep(1);
10747 	}
10748 
10749 	if (count2 && wpa_command(intf, buf)) {
10750 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,HS20_ANQP_GET "
10751 			  "failed");
10752 		return 0;
10753 	}
10754 
10755 	val = get_param(cmd, "NAI_HOME_REALM_LIST");
10756 	if (val) {
10757 		if (count || count2) {
10758 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before "
10759 					"sending out second query");
10760 			sleep(1);
10761 		}
10762 
10763 		if (strcmp(val, "1") == 0)
10764 			val = "mail.example.com";
10765 		snprintf(buf, end - pos,
10766 			 "HS20_GET_NAI_HOME_REALM_LIST %s realm=%s",
10767 			 dest, val);
10768 		if (wpa_command(intf, buf)) {
10769 			send_resp(dut, conn, SIGMA_ERROR,
10770 				  "ErrorCode,HS20_GET_NAI_HOME_REALM_LIST "
10771 				  "failed");
10772 			return 0;
10773 		}
10774 	}
10775 
10776 	val = get_param(cmd, "ICON_REQUEST");
10777 	if (val) {
10778 		if (count || count2) {
10779 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Wait before "
10780 					"sending out second query");
10781 			sleep(1);
10782 		}
10783 
10784 		snprintf(buf, end - pos,
10785 			 "HS20_ICON_REQUEST %s %s", dest, val);
10786 		if (wpa_command(intf, buf)) {
10787 			send_resp(dut, conn, SIGMA_ERROR,
10788 				  "ErrorCode,HS20_ICON_REQUEST failed");
10789 			return 0;
10790 		}
10791 	}
10792 
10793 	return 1;
10794 }
10795 
10796 
ath_sta_send_frame_vht(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)10797 static int ath_sta_send_frame_vht(struct sigma_dut *dut,
10798 				  struct sigma_conn *conn,
10799 				  struct sigma_cmd *cmd)
10800 {
10801 	const char *val;
10802 	const char *ifname;
10803 	int chwidth, nss;
10804 
10805 	val = get_param(cmd, "framename");
10806 	if (!val)
10807 		return -1;
10808 	sigma_dut_print(dut, DUT_MSG_DEBUG, "framename is %s", val);
10809 
10810 	/* Command sequence to generate Op mode notification */
10811 	if (val && strcasecmp(val, "Op_md_notif_frm") == 0) {
10812 		ifname = get_station_ifname(dut);
10813 
10814 		/* Disable STBC */
10815 		run_iwpriv(dut, ifname, "tx_stbc 0");
10816 
10817 		/* Extract Channel width */
10818 		val = get_param(cmd, "Channel_width");
10819 		if (val) {
10820 			switch (atoi(val)) {
10821 			case 20:
10822 				chwidth = 0;
10823 				break;
10824 			case 40:
10825 				chwidth = 1;
10826 				break;
10827 			case 80:
10828 				chwidth = 2;
10829 				break;
10830 			case 160:
10831 				chwidth = 3;
10832 				break;
10833 			default:
10834 				chwidth = 2;
10835 				break;
10836 			}
10837 
10838 			run_iwpriv(dut, ifname, "chwidth %d", chwidth);
10839 		}
10840 
10841 		/* Extract NSS */
10842 		val = get_param(cmd, "NSS");
10843 		if (val) {
10844 			switch (atoi(val)) {
10845 			case 1:
10846 				nss = 1;
10847 				break;
10848 			case 2:
10849 				nss = 3;
10850 				break;
10851 			case 3:
10852 				nss = 7;
10853 				break;
10854 			default:
10855 				/* We do not support NSS > 3 */
10856 				nss = 3;
10857 				break;
10858 			}
10859 			run_iwpriv(dut, ifname, "rxchainmask %d", nss);
10860 		}
10861 
10862 		/* Opmode notify */
10863 		run_iwpriv(dut, ifname, "opmode_notify 1");
10864 	}
10865 
10866 	return 1;
10867 }
10868 
10869 
wcn_sta_set_pmf_config(struct sigma_dut * dut,const char * intf,enum send_frame_protection protected)10870 static int wcn_sta_set_pmf_config(struct sigma_dut *dut, const char *intf,
10871 				  enum send_frame_protection protected)
10872 {
10873 #ifdef NL80211_SUPPORT
10874 	return wcn_wifi_test_config_set_u8(
10875 		dut, intf, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PMF_PROTECTION,
10876 		protected);
10877 #else /* NL80211_SUPPORT */
10878 	sigma_dut_print(dut, DUT_MSG_ERROR,
10879 			"PMF config cannot be set without NL80211_SUPPORT defined");
10880 	return -1;
10881 #endif /* NL80211_SUPPORT */
10882 }
10883 
10884 
cmd_sta_send_frame_vht(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)10885 static int cmd_sta_send_frame_vht(struct sigma_dut *dut,
10886 				  struct sigma_conn *conn,
10887 				  struct sigma_cmd *cmd)
10888 {
10889 	switch (get_driver_type(dut)) {
10890 	case DRIVER_ATHEROS:
10891 		return ath_sta_send_frame_vht(dut, conn, cmd);
10892 	default:
10893 		send_resp(dut, conn, SIGMA_ERROR,
10894 			  "errorCode,Unsupported sta_set_frame(VHT) with the current driver");
10895 		return 0;
10896 	}
10897 }
10898 
10899 
wcn_sta_send_disassoc(struct sigma_dut * dut,const char * intf)10900 static int wcn_sta_send_disassoc(struct sigma_dut *dut, const char *intf)
10901 {
10902 #ifdef NL80211_SUPPORT
10903 	return wcn_wifi_test_config_set_flag(
10904 		dut, intf, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISASSOC_TX);
10905 #else /* NL80211_SUPPORT */
10906 	sigma_dut_print(dut, DUT_MSG_ERROR,
10907 			"Disassoc Tx cannot be done without NL80211_SUPPORT defined");
10908 	return -1;
10909 #endif /* NL80211_SUPPORT */
10910 }
10911 
10912 
wcn_sta_send_frame_he(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)10913 static int wcn_sta_send_frame_he(struct sigma_dut *dut, struct sigma_conn *conn,
10914 				 struct sigma_cmd *cmd)
10915 {
10916 	const char *val;
10917 	const char *intf = get_param(cmd, "Interface");
10918 	enum send_frame_protection protected;
10919 	const char *pmf;
10920 
10921 	if (!intf)
10922 		return -1;
10923 
10924 	val = get_param(cmd, "framename");
10925 	if (!val)
10926 		return -1;
10927 	sigma_dut_print(dut, DUT_MSG_DEBUG, "framename is %s", val);
10928 
10929 	pmf = get_param(cmd, "PMFProtected");
10930 	if (!pmf)
10931 		pmf = get_param(cmd, "Protected");
10932 	if (pmf) {
10933 		if (strcasecmp(pmf, "Correct-key") == 0 ||
10934 		    strcasecmp(pmf, "CorrectKey") == 0) {
10935 			protected = CORRECT_KEY;
10936 		} else if (strcasecmp(pmf, "IncorrectKey") == 0) {
10937 			protected = INCORRECT_KEY;
10938 		} else if (strcasecmp(pmf, "Unprotected") == 0) {
10939 			protected = UNPROTECTED;
10940 		} else {
10941 			send_resp(dut, conn, SIGMA_ERROR,
10942 				  "errorCode,Unsupported PMFProtected");
10943 			return STATUS_SENT_ERROR;
10944 		}
10945 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Config PMF protection %d",
10946 				protected);
10947 		wcn_sta_set_pmf_config(dut, intf, protected);
10948 	}
10949 
10950 	/* Command sequence to generate Op mode notification */
10951 	if (val && strcasecmp(val, "action") == 0) {
10952 		val = get_param(cmd, "PPDUTxType");
10953 		if (val && strcasecmp(val, "TB") == 0) {
10954 			if (sta_set_action_tx_in_he_tb_ppdu(dut, intf, 1)) {
10955 				sigma_dut_print(dut, DUT_MSG_ERROR,
10956 						"failed to send TB PPDU Tx cfg");
10957 				send_resp(dut, conn, SIGMA_ERROR,
10958 					  "ErrorCode,set TB PPDU Tx cfg failed");
10959 				return 0;
10960 			}
10961 			return 1;
10962 		}
10963 
10964 		sigma_dut_print(dut, DUT_MSG_ERROR,
10965 				"Action Tx type is not defined");
10966 
10967 		return SUCCESS_SEND_STATUS;
10968 	}
10969 
10970 	if (strcasecmp(val, "disassoc") == 0)
10971 		wcn_sta_send_disassoc(dut, intf);
10972 
10973 	return 1;
10974 }
10975 
10976 
cmd_sta_send_frame_he(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)10977 static int cmd_sta_send_frame_he(struct sigma_dut *dut,
10978 				 struct sigma_conn *conn,
10979 				 struct sigma_cmd *cmd)
10980 {
10981 	switch (get_driver_type(dut)) {
10982 	case DRIVER_WCN:
10983 		return wcn_sta_send_frame_he(dut, conn, cmd);
10984 	default:
10985 		send_resp(dut, conn, SIGMA_ERROR,
10986 			  "errorCode,Unsupported sta_set_frame(HE) with the current driver");
10987 		return 0;
10988 	}
10989 }
10990 
10991 
10992 #ifdef __linux__
10993 
10994 static int
wil6210_send_p2p_frame_60g(struct sigma_dut * dut,struct sigma_cmd * cmd,const char * frame_name,const char * dest_mac)10995 wil6210_send_p2p_frame_60g(struct sigma_dut *dut, struct sigma_cmd *cmd,
10996 			   const char *frame_name, const char *dest_mac)
10997 {
10998 	int isprobereq = strcasecmp(frame_name, "probereq") == 0;
10999 	const char *ssid = get_param(cmd, "ssid");
11000 	const char *countstr = get_param(cmd, "count");
11001 	const char *channelstr = get_param(cmd, "channel");
11002 	const char *group_id = get_param(cmd, "groupid");
11003 	const char *client_id = get_param(cmd, "clientmac");
11004 	int count, channel, freq, i;
11005 	const char *fname;
11006 	char frame[1024], src_mac[20], group_id_attr[25],
11007 		device_macstr[3 * ETH_ALEN], client_mac[ETH_ALEN];
11008 	const char *group_ssid;
11009 	const int group_ssid_prefix_len = 9;
11010 	struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) frame;
11011 	size_t framelen = sizeof(frame);
11012 	struct template_frame_tag tags[2];
11013 	size_t tags_total = ARRAY_SIZE(tags);
11014 	int tag_index, len, dst_len;
11015 
11016 	if (!countstr || !channelstr) {
11017 		sigma_dut_print(dut, DUT_MSG_ERROR,
11018 				"Missing argument: count, channel");
11019 		return -1;
11020 	}
11021 	if (isprobereq && !ssid) {
11022 		sigma_dut_print(dut, DUT_MSG_ERROR,
11023 				"Missing argument: ssid");
11024 		return -1;
11025 	}
11026 	if (!isprobereq && (!group_id || !client_id)) {
11027 		sigma_dut_print(dut, DUT_MSG_ERROR,
11028 				"Missing argument: group_id, client_id");
11029 		return -1;
11030 	}
11031 
11032 	count = atoi(countstr);
11033 	channel = atoi(channelstr);
11034 	freq = channel_to_freq(dut, channel);
11035 
11036 	if (!freq) {
11037 		sigma_dut_print(dut, DUT_MSG_ERROR,
11038 				"invalid channel: %s", channelstr);
11039 		return -1;
11040 	}
11041 
11042 	if (isprobereq) {
11043 		if (strcasecmp(ssid, "wildcard") == 0) {
11044 			fname = "probe_req_wildcard.txt";
11045 		} else if (strcasecmp(ssid, "P2P_Wildcard") == 0) {
11046 			fname = "probe_req_P2P_Wildcard.txt";
11047 		} else {
11048 			sigma_dut_print(dut, DUT_MSG_ERROR,
11049 					"invalid probe request type");
11050 			return -1;
11051 		}
11052 	} else {
11053 		fname = "P2P_device_discovery_req.txt";
11054 	}
11055 
11056 	if (parse_template_frame_file(dut, fname, frame, &framelen,
11057 				      tags, &tags_total)) {
11058 		sigma_dut_print(dut, DUT_MSG_ERROR,
11059 				"invalid frame template: %s", fname);
11060 		return -1;
11061 	}
11062 
11063 	if (get_wpa_status(get_station_ifname(dut), "address",
11064 			   src_mac, sizeof(src_mac)) < 0 ||
11065 	    parse_mac_address(dut, src_mac, &hdr->addr2[0]) ||
11066 	    parse_mac_address(dut, dest_mac, &hdr->addr1[0]))
11067 		return -1;
11068 	/* Use wildcard BSSID, since we are in PBSS */
11069 	memset(&hdr->addr3, 0xFF, ETH_ALEN);
11070 
11071 	if (!isprobereq) {
11072 		tag_index = find_template_frame_tag(tags, tags_total, 1);
11073 		if (tag_index < 0) {
11074 			sigma_dut_print(dut, DUT_MSG_ERROR,
11075 					"can't find device id attribute");
11076 			return -1;
11077 		}
11078 		if (parse_mac_address(dut, client_id,
11079 				      (unsigned char *) client_mac)) {
11080 			sigma_dut_print(dut, DUT_MSG_ERROR,
11081 					"invalid client_id: %s", client_id);
11082 			return -1;
11083 		}
11084 		if (replace_p2p_attribute(dut, &frame[tags[tag_index].offset],
11085 					  framelen - tags[tag_index].offset,
11086 					  IEEE80211_P2P_ATTR_DEVICE_ID,
11087 					  client_mac, ETH_ALEN)) {
11088 			sigma_dut_print(dut, DUT_MSG_ERROR,
11089 					"fail to replace device id attribute");
11090 			return -1;
11091 		}
11092 
11093 		/*
11094 		 * group_id arg contains device MAC address followed by
11095 		 * space and SSID (DIRECT-somessid).
11096 		 * group id attribute contains device address (6 bytes)
11097 		 * followed by SSID prefix DIRECT-XX (9 bytes)
11098 		 */
11099 		if (strlen(group_id) < sizeof(device_macstr)) {
11100 			sigma_dut_print(dut, DUT_MSG_ERROR,
11101 					"group_id arg too short");
11102 			return -1;
11103 		}
11104 		memcpy(device_macstr, group_id, sizeof(device_macstr));
11105 		device_macstr[sizeof(device_macstr) - 1] = '\0';
11106 		if (parse_mac_address(dut, device_macstr,
11107 				      (unsigned char *) group_id_attr)) {
11108 			sigma_dut_print(dut, DUT_MSG_ERROR,
11109 					"fail to parse device address from group_id");
11110 			return -1;
11111 		}
11112 		group_ssid = strchr(group_id, ' ');
11113 		if (!group_ssid) {
11114 			sigma_dut_print(dut, DUT_MSG_ERROR,
11115 					"invalid group_id arg, no ssid");
11116 			return -1;
11117 		}
11118 		group_ssid++;
11119 		len = strlen(group_ssid);
11120 		if (len < group_ssid_prefix_len) {
11121 			sigma_dut_print(dut, DUT_MSG_ERROR,
11122 					"group_id SSID too short");
11123 			return -1;
11124 		}
11125 		dst_len = sizeof(group_id_attr) - ETH_ALEN;
11126 		if (len > dst_len) {
11127 			sigma_dut_print(dut, DUT_MSG_ERROR,
11128 					"group_id SSID (%s) too long",
11129 					group_ssid);
11130 			return -1;
11131 		}
11132 
11133 		memcpy(group_id_attr + ETH_ALEN, group_ssid, len);
11134 		tag_index = find_template_frame_tag(tags, tags_total, 2);
11135 		if (tag_index < 0) {
11136 			sigma_dut_print(dut, DUT_MSG_ERROR,
11137 					"can't find group id attribute");
11138 			return -1;
11139 		}
11140 		if (replace_p2p_attribute(dut, &frame[tags[tag_index].offset],
11141 					  framelen - tags[tag_index].offset,
11142 					  IEEE80211_P2P_ATTR_GROUP_ID,
11143 					  group_id_attr,
11144 					  sizeof(group_id_attr))) {
11145 			sigma_dut_print(dut, DUT_MSG_ERROR,
11146 					"fail to replace group id attribute");
11147 			return -1;
11148 		}
11149 	}
11150 
11151 	for (i = 0; i < count; i++) {
11152 		if (wil6210_transmit_frame(dut, freq,
11153 					   WIL_TRANSMIT_FRAME_DEFAULT_ROC,
11154 					   frame, framelen)) {
11155 			sigma_dut_print(dut, DUT_MSG_ERROR,
11156 					"fail to transmit probe request frame");
11157 			return -1;
11158 		}
11159 	}
11160 
11161 	return 0;
11162 }
11163 
11164 
wil6210_send_frame_60g(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)11165 int wil6210_send_frame_60g(struct sigma_dut *dut, struct sigma_conn *conn,
11166 			   struct sigma_cmd *cmd)
11167 {
11168 	const char *frame_name = get_param(cmd, "framename");
11169 	const char *mac = get_param(cmd, "dest_mac");
11170 
11171 	if (!frame_name || !mac) {
11172 		sigma_dut_print(dut, DUT_MSG_ERROR,
11173 				"framename and dest_mac must be provided");
11174 		return -1;
11175 	}
11176 
11177 	if (strcasecmp(frame_name, "brp") == 0) {
11178 		const char *l_rx = get_param(cmd, "L-RX");
11179 		int l_rx_i;
11180 
11181 		if (!l_rx) {
11182 			sigma_dut_print(dut, DUT_MSG_ERROR,
11183 					"L-RX must be provided");
11184 			return -1;
11185 		}
11186 		l_rx_i = atoi(l_rx);
11187 
11188 		sigma_dut_print(dut, DUT_MSG_INFO,
11189 				"dev_send_frame: BRP-RX, dest_mac %s, L-RX %s",
11190 				mac, l_rx);
11191 		if (l_rx_i != 16) {
11192 			sigma_dut_print(dut, DUT_MSG_ERROR,
11193 					"unsupported L-RX: %s", l_rx);
11194 			return -1;
11195 		}
11196 
11197 		if (wil6210_send_brp_rx(dut, mac, l_rx_i))
11198 			return -1;
11199 	} else if (strcasecmp(frame_name, "ssw") == 0) {
11200 		sigma_dut_print(dut, DUT_MSG_INFO,
11201 				"dev_send_frame: SLS, dest_mac %s", mac);
11202 		if (wil6210_send_sls(dut, mac))
11203 			return -1;
11204 	} else if ((strcasecmp(frame_name, "probereq") == 0) ||
11205 		   (strcasecmp(frame_name, "devdiscreq") == 0)) {
11206 		sigma_dut_print(dut, DUT_MSG_INFO,
11207 				"dev_send_frame: %s, dest_mac %s", frame_name,
11208 				mac);
11209 		if (wil6210_send_p2p_frame_60g(dut, cmd, frame_name, mac))
11210 			return -1;
11211 	} else {
11212 		sigma_dut_print(dut, DUT_MSG_ERROR,
11213 				"unsupported frame type: %s", frame_name);
11214 		return -1;
11215 	}
11216 
11217 	return 1;
11218 }
11219 
11220 #endif /* __linux__ */
11221 
11222 
cmd_sta_send_frame_60g(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)11223 static int cmd_sta_send_frame_60g(struct sigma_dut *dut,
11224 				  struct sigma_conn *conn,
11225 				  struct sigma_cmd *cmd)
11226 {
11227 	switch (get_driver_type(dut)) {
11228 #ifdef __linux__
11229 	case DRIVER_WIL6210:
11230 		return wil6210_send_frame_60g(dut, conn, cmd);
11231 #endif /* __linux__ */
11232 	default:
11233 		send_resp(dut, conn, SIGMA_ERROR,
11234 			  "errorCode,Unsupported sta_set_frame(60G) with the current driver");
11235 		return 0;
11236 	}
11237 }
11238 
11239 
mbo_send_anqp_query(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,struct sigma_cmd * cmd)11240 static int mbo_send_anqp_query(struct sigma_dut *dut, struct sigma_conn *conn,
11241 			       const char *intf, struct sigma_cmd *cmd)
11242 {
11243 	const char *val, *addr;
11244 	char buf[100];
11245 
11246 	addr = get_param(cmd, "DestMac");
11247 	if (!addr) {
11248 		send_resp(dut, conn, SIGMA_INVALID,
11249 			  "ErrorCode,AP MAC address is missing");
11250 		return 0;
11251 	}
11252 
11253 	val = get_param(cmd, "ANQPQuery_ID");
11254 	if (!val) {
11255 		send_resp(dut, conn, SIGMA_INVALID,
11256 			  "ErrorCode,Missing ANQPQuery_ID");
11257 		return 0;
11258 	}
11259 
11260 	if (strcasecmp(val, "NeighborReportReq") == 0) {
11261 		snprintf(buf, sizeof(buf), "ANQP_GET %s 272", addr);
11262 	} else if (strcasecmp(val, "QueryListWithCellPref") == 0) {
11263 		snprintf(buf, sizeof(buf), "ANQP_GET %s 272,mbo:2", addr);
11264 	} else {
11265 		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid ANQPQuery_ID: %s",
11266 				val);
11267 		send_resp(dut, conn, SIGMA_INVALID,
11268 			  "ErrorCode,Invalid ANQPQuery_ID");
11269 		return 0;
11270 	}
11271 
11272 	/* Set gas_address3 field to IEEE 802.11-2012 standard compliant form
11273 	 * (Address3 = Wildcard BSSID when sent to not-associated AP;
11274 	 * if associated, AP BSSID).
11275 	 */
11276 	if (wpa_command(intf, "SET gas_address3 1") < 0) {
11277 		send_resp(dut, conn, SIGMA_ERROR,
11278 			  "ErrorCode,Failed to set gas_address3");
11279 		return 0;
11280 	}
11281 
11282 	if (wpa_command(intf, buf) < 0) {
11283 		send_resp(dut, conn, SIGMA_ERROR,
11284 			  "ErrorCode,Failed to send ANQP query");
11285 		return 0;
11286 	}
11287 
11288 	return 1;
11289 }
11290 
11291 
mbo_cmd_sta_send_frame(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,struct sigma_cmd * cmd)11292 static int mbo_cmd_sta_send_frame(struct sigma_dut *dut,
11293 				  struct sigma_conn *conn,
11294 				  const char *intf,
11295 				  struct sigma_cmd *cmd)
11296 {
11297 	const char *val = get_param(cmd, "FrameName");
11298 
11299 	if (val && strcasecmp(val, "ANQPQuery") == 0)
11300 		return mbo_send_anqp_query(dut, conn, intf, cmd);
11301 
11302 	return 2;
11303 }
11304 
11305 
cmd_sta_send_frame_wpa3(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,struct sigma_cmd * cmd)11306 static enum sigma_cmd_result cmd_sta_send_frame_wpa3(struct sigma_dut *dut,
11307 						     struct sigma_conn *conn,
11308 						     const char *intf,
11309 						     struct sigma_cmd *cmd)
11310 {
11311 	const char *val = get_param(cmd, "framename");
11312 
11313 	if (!val)
11314 		return INVALID_SEND_STATUS;
11315 
11316 	if (strcasecmp(val, "SAQueryReq") == 0) {
11317 		val = get_param(cmd, "OCIChannel");
11318 
11319 		if (!val) {
11320 			send_resp(dut, conn, SIGMA_ERROR,
11321 				  "errorCode,OCIChannel not present");
11322 			return STATUS_SENT_ERROR;
11323 		}
11324 
11325 		dut->saquery_oci_freq = channel_to_freq(dut, atoi(val));
11326 		if (!dut->saquery_oci_freq) {
11327 			send_resp(dut, conn, SIGMA_ERROR,
11328 				  "errorCode,Invalid OCIChannel number");
11329 			return STATUS_SENT_ERROR;
11330 		}
11331 
11332 		return sta_inject_frame(dut, conn, intf, SAQUERY, CORRECT_KEY,
11333 					NULL, 0);
11334 	}
11335 
11336 	if (strcasecmp(val, "reassocreq") == 0)
11337 		return sta_inject_frame(dut, conn, intf, REASSOCREQ,
11338 					CORRECT_KEY, NULL, 0);
11339 
11340 	if (strcasecmp(val, "ANQPQuery") == 0) {
11341 		char buf[50];
11342 		const char *dest = get_param(cmd, "DestMac");
11343 		const char *chan = get_param(cmd, "channel");
11344 		const char *freq_str = get_param(cmd, "ChnlFreq");
11345 		int len, freq;
11346 
11347 		if (freq_str)
11348 			freq = atoi(freq_str);
11349 		else
11350 			freq = chan ? channel_to_freq(dut, atoi(chan)) : 0;
11351 
11352 		if (!dest || !freq)
11353 			return INVALID_SEND_STATUS;
11354 
11355 		len = snprintf(buf, sizeof(buf), "ANQP_GET %s freq=%d 257",
11356 			       dest, freq);
11357 		if (len < 0 || len >= sizeof(buf)) {
11358 			sigma_dut_print(dut, DUT_MSG_ERROR,
11359 					"Failed to allocate buf");
11360 			return ERROR_SEND_STATUS;
11361 		}
11362 
11363 		if (wpa_command(intf, buf) != 0) {
11364 			send_resp(dut, conn, SIGMA_ERROR,
11365 				  "ErrorCode,Failed to send ANQP Query frame");
11366 			return STATUS_SENT_ERROR;
11367 		}
11368 
11369 		sigma_dut_print(dut, DUT_MSG_DEBUG,
11370 				"ANQP Query sent: %s", buf);
11371 
11372 		return SUCCESS_SEND_STATUS;
11373 	}
11374 
11375 	send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported framename");
11376 	return STATUS_SENT_ERROR;
11377 }
11378 
11379 
11380 static enum sigma_cmd_result
cmd_sta_send_frame_mscs(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,struct sigma_cmd * cmd)11381 cmd_sta_send_frame_mscs(struct sigma_dut *dut, struct sigma_conn *conn,
11382 			const char *intf, struct sigma_cmd *cmd)
11383 {
11384 	char buf[128], *pos;
11385 	const char *val, *classifier_type = "04", *type;
11386 	int len, rem_len;
11387 	u8 up_bitmap;
11388 
11389 	val = get_param(cmd, "FrameName");
11390 	type = get_param(cmd, "Request_Type");
11391 	if (!val || !type || strcasecmp(val, "MSCSReq") != 0) {
11392 		sigma_dut_print(dut, DUT_MSG_ERROR,
11393 				"%s: frame name or type not valid", __func__);
11394 		return INVALID_SEND_STATUS;
11395 	}
11396 
11397 	rem_len = sizeof(buf);
11398 	pos = buf;
11399 	if (strcasecmp(type, "add") == 0) {
11400 		len = snprintf(pos, rem_len, "MSCS add");
11401 	} else if (strcasecmp(type, "update") == 0) {
11402 		len = snprintf(pos, rem_len, "MSCS change");
11403 	} else if (strcasecmp(type, "remove") == 0) {
11404 		if (wpa_command(intf, "MSCS remove") != 0) {
11405 			send_resp(dut, conn, SIGMA_ERROR,
11406 				  "ErrorCode,Failed to send MSCS frame req");
11407 			return STATUS_SENT_ERROR;
11408 		}
11409 		return SUCCESS_SEND_STATUS;
11410 	} else {
11411 		sigma_dut_print(dut, DUT_MSG_ERROR,
11412 				"%s: request type invalid", __func__);
11413 		return INVALID_SEND_STATUS;
11414 	}
11415 
11416 	if (len < 0 || len >= rem_len)
11417 		goto fail;
11418 
11419 	pos += len;
11420 	rem_len -= len;
11421 
11422 	val = get_param(cmd, "User_Priority_Bitmap");
11423 	if (!val) {
11424 		sigma_dut_print(dut, DUT_MSG_ERROR,
11425 				"%s: user priority bitmap empty", __func__);
11426 		return INVALID_SEND_STATUS;
11427 	}
11428 
11429 	switch (atoi(val)) {
11430 	case 0:
11431 		up_bitmap = 0x00;
11432 		break;
11433 	case 1:
11434 		up_bitmap = 0xF0;
11435 		break;
11436 	case 2:
11437 		up_bitmap = 0xF6;
11438 		break;
11439 	default:
11440 		sigma_dut_print(dut, DUT_MSG_ERROR,
11441 				"%s: Unknown User_Priority_Bitmap value %d",
11442 				__func__, atoi(val));
11443 		return INVALID_SEND_STATUS;
11444 	}
11445 
11446 	len = snprintf(pos, rem_len, " up_bitmap=%02x", up_bitmap);
11447 	if (len < 0 || len >= rem_len)
11448 		goto fail;
11449 
11450 	pos += len;
11451 	rem_len -= len;
11452 
11453 	val = get_param(cmd, "User_Priority_Limit");
11454 	if (!val) {
11455 		sigma_dut_print(dut, DUT_MSG_ERROR,
11456 				"%s: invalid user priority limit", __func__);
11457 		return INVALID_SEND_STATUS;
11458 	}
11459 
11460 	len = snprintf(pos, rem_len, " up_limit=%s", val);
11461 	if (len < 0 || len >= rem_len)
11462 		goto fail;
11463 
11464 	pos += len;
11465 	rem_len -= len;
11466 
11467 	val = get_param(cmd, "Stream_Timeout");
11468 	if (!val)
11469 		val = get_param(cmd, "Stream_Timtout");
11470 	if (!val) {
11471 		sigma_dut_print(dut, DUT_MSG_ERROR,
11472 				"%s: invalid stream timeout", __func__);
11473 		return INVALID_SEND_STATUS;
11474 	}
11475 
11476 	len = snprintf(pos, rem_len, " stream_timeout=%s", val);
11477 	if (len < 0 || len >= rem_len)
11478 		goto fail;
11479 
11480 	pos += len;
11481 	rem_len -= len;
11482 
11483 	val = get_param(cmd, "TCLAS_Mask");
11484 	if (!val) {
11485 		sigma_dut_print(dut, DUT_MSG_ERROR,
11486 				"%s: invalid tclas mask", __func__);
11487 		return INVALID_SEND_STATUS;
11488 	}
11489 
11490 	len = snprintf(pos, rem_len, " frame_classifier=%s%lx%032x",
11491 		       classifier_type, strtol(val, NULL, 2), 0);
11492 	if (len < 0 || len >= rem_len)
11493 		goto fail;
11494 
11495 	if (wpa_command(intf, buf) != 0) {
11496 		send_resp(dut, conn, SIGMA_ERROR,
11497 			  "ErrorCode,Failed to send MSCS frame req");
11498 		return STATUS_SENT_ERROR;
11499 	}
11500 
11501 	sigma_dut_print(dut, DUT_MSG_DEBUG,
11502 			"MSCS frame request sent: %s", buf);
11503 
11504 	return SUCCESS_SEND_STATUS;
11505 fail:
11506 	sigma_dut_print(dut, DUT_MSG_ERROR,
11507 			"Failed to create MSCS frame req");
11508 	return ERROR_SEND_STATUS;
11509 }
11510 
11511 
cmd_sta_send_frame(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)11512 enum sigma_cmd_result cmd_sta_send_frame(struct sigma_dut *dut,
11513 					 struct sigma_conn *conn,
11514 					 struct sigma_cmd *cmd)
11515 {
11516 	const char *intf = get_param(cmd, "Interface");
11517 	const char *val;
11518 	enum send_frame_type frame;
11519 	enum send_frame_protection protected;
11520 	char buf[100];
11521 	unsigned char addr[ETH_ALEN];
11522 	int res;
11523 
11524 	if (!intf)
11525 		return -1;
11526 
11527 	val = get_param(cmd, "program");
11528 	if (val == NULL)
11529 		val = get_param(cmd, "frame");
11530 	if (val && strcasecmp(val, "TDLS") == 0)
11531 		return cmd_sta_send_frame_tdls(dut, conn, cmd);
11532 	if (val && (strcasecmp(val, "HS2") == 0 ||
11533 		    strcasecmp(val, "HS2-R2") == 0 ||
11534 		    strcasecmp(val, "HS2-R3") == 0))
11535 		return cmd_sta_send_frame_hs2(dut, conn, cmd);
11536 	if (val && strcasecmp(val, "VHT") == 0)
11537 		return cmd_sta_send_frame_vht(dut, conn, cmd);
11538 	if (val && strcasecmp(val, "HE") == 0)
11539 		return cmd_sta_send_frame_he(dut, conn, cmd);
11540 	if (val && strcasecmp(val, "LOC") == 0)
11541 		return loc_cmd_sta_send_frame(dut, conn, cmd);
11542 	if (val && strcasecmp(val, "60GHz") == 0)
11543 		return cmd_sta_send_frame_60g(dut, conn, cmd);
11544 	if (val && strcasecmp(val, "MBO") == 0) {
11545 		res = mbo_cmd_sta_send_frame(dut, conn, intf, cmd);
11546 		if (res != 2)
11547 			return res;
11548 	}
11549 	if (val && strcasecmp(val, "WPA3") == 0)
11550 		return cmd_sta_send_frame_wpa3(dut, conn, intf, cmd);
11551 	if (val && strcasecmp(val, "QM") == 0)
11552 		return cmd_sta_send_frame_mscs(dut, conn, intf, cmd);
11553 
11554 	val = get_param(cmd, "TD_DISC");
11555 	if (val) {
11556 		if (hwaddr_aton(val, addr) < 0)
11557 			return -1;
11558 		snprintf(buf, sizeof(buf), "TDLS_DISCOVER %s", val);
11559 		if (wpa_command(intf, buf) < 0) {
11560 			send_resp(dut, conn, SIGMA_ERROR,
11561 				  "ErrorCode,Failed to send TDLS discovery");
11562 			return 0;
11563 		}
11564 		return 1;
11565 	}
11566 
11567 	val = get_param(cmd, "TD_Setup");
11568 	if (val) {
11569 		if (hwaddr_aton(val, addr) < 0)
11570 			return -1;
11571 		snprintf(buf, sizeof(buf), "TDLS_SETUP %s", val);
11572 		if (wpa_command(intf, buf) < 0) {
11573 			send_resp(dut, conn, SIGMA_ERROR,
11574 				  "ErrorCode,Failed to start TDLS setup");
11575 			return 0;
11576 		}
11577 		return 1;
11578 	}
11579 
11580 	val = get_param(cmd, "TD_TearDown");
11581 	if (val) {
11582 		if (hwaddr_aton(val, addr) < 0)
11583 			return -1;
11584 		snprintf(buf, sizeof(buf), "TDLS_TEARDOWN %s", val);
11585 		if (wpa_command(intf, buf) < 0) {
11586 			send_resp(dut, conn, SIGMA_ERROR,
11587 				  "ErrorCode,Failed to tear down TDLS link");
11588 			return 0;
11589 		}
11590 		return 1;
11591 	}
11592 
11593 	val = get_param(cmd, "TD_ChannelSwitch");
11594 	if (val) {
11595 		/* TODO */
11596 		send_resp(dut, conn, SIGMA_ERROR,
11597 			  "ErrorCode,TD_ChannelSwitch not yet supported");
11598 		return 0;
11599 	}
11600 
11601 	val = get_param(cmd, "TD_NF");
11602 	if (val) {
11603 		/* TODO */
11604 		send_resp(dut, conn, SIGMA_ERROR,
11605 			  "ErrorCode,TD_NF not yet supported");
11606 		return 0;
11607 	}
11608 
11609 	val = get_param(cmd, "PMFFrameType");
11610 	if (val == NULL)
11611 		val = get_param(cmd, "FrameName");
11612 	if (val == NULL)
11613 		val = get_param(cmd, "Type");
11614 	if (val == NULL)
11615 		return -1;
11616 	if (strcasecmp(val, "disassoc") == 0)
11617 		frame = DISASSOC;
11618 	else if (strcasecmp(val, "deauth") == 0)
11619 		frame = DEAUTH;
11620 	else if (strcasecmp(val, "saquery") == 0)
11621 		frame = SAQUERY;
11622 	else if (strcasecmp(val, "auth") == 0)
11623 		frame = AUTH;
11624 	else if (strcasecmp(val, "assocreq") == 0)
11625 		frame = ASSOCREQ;
11626 	else if (strcasecmp(val, "reassocreq") == 0)
11627 		frame = REASSOCREQ;
11628 	else if (strcasecmp(val, "neigreq") == 0) {
11629 		sigma_dut_print(dut, DUT_MSG_INFO, "Got neighbor request");
11630 
11631 		val = get_param(cmd, "ssid");
11632 		if (val == NULL)
11633 			return -1;
11634 
11635 		res = send_neighbor_request(dut, intf, val);
11636 		if (res) {
11637 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
11638 				  "Failed to send neighbor report request");
11639 			return 0;
11640 		}
11641 
11642 		return 1;
11643 	} else if (strcasecmp(val, "transmgmtquery") == 0 ||
11644 		   strcasecmp(val, "BTMQuery") == 0) {
11645 		sigma_dut_print(dut, DUT_MSG_DEBUG,
11646 				"Got Transition Management Query");
11647 
11648 		res = send_trans_mgmt_query(dut, intf, cmd);
11649 		if (res) {
11650 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
11651 				  "Failed to send Transition Management Query");
11652 			return 0;
11653 		}
11654 
11655 		return 1;
11656 	} else {
11657 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
11658 			  "PMFFrameType");
11659 		return 0;
11660 	}
11661 
11662 	val = get_param(cmd, "PMFProtected");
11663 	if (val == NULL)
11664 		val = get_param(cmd, "Protected");
11665 	if (val == NULL)
11666 		return -1;
11667 	if (strcasecmp(val, "Correct-key") == 0 ||
11668 	    strcasecmp(val, "CorrectKey") == 0)
11669 		protected = CORRECT_KEY;
11670 	else if (strcasecmp(val, "IncorrectKey") == 0)
11671 		protected = INCORRECT_KEY;
11672 	else if (strcasecmp(val, "Unprotected") == 0)
11673 		protected = UNPROTECTED;
11674 	else {
11675 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
11676 			  "PMFProtected");
11677 		return 0;
11678 	}
11679 
11680 	if (protected != UNPROTECTED &&
11681 	    (frame == AUTH || frame == ASSOCREQ || frame == REASSOCREQ)) {
11682 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Impossible "
11683 			  "PMFProtected for auth/assocreq/reassocreq");
11684 		return 0;
11685 	}
11686 
11687 	if (if_nametoindex("sigmadut") == 0) {
11688 		snprintf(buf, sizeof(buf),
11689 			 "iw dev %s interface add sigmadut type monitor",
11690 			 get_station_ifname(dut));
11691 		if (system(buf) != 0 ||
11692 		    if_nametoindex("sigmadut") == 0) {
11693 			sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to add "
11694 					"monitor interface with '%s'", buf);
11695 			return -2;
11696 		}
11697 	}
11698 
11699 	if (system("ifconfig sigmadut up") != 0) {
11700 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to set "
11701 				"monitor interface up");
11702 		return -2;
11703 	}
11704 
11705 	return sta_inject_frame(dut, conn, intf, frame, protected, NULL, 1);
11706 }
11707 
11708 
cmd_sta_set_parameter_hs2(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd,const char * ifname)11709 static int cmd_sta_set_parameter_hs2(struct sigma_dut *dut,
11710 				     struct sigma_conn *conn,
11711 				     struct sigma_cmd *cmd,
11712 				     const char *ifname)
11713 {
11714 	char buf[200];
11715 	const char *val;
11716 
11717 	val = get_param(cmd, "ClearARP");
11718 	if (val && atoi(val) == 1) {
11719 		snprintf(buf, sizeof(buf), "ip neigh flush dev %s", ifname);
11720 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
11721 		if (system(buf) != 0) {
11722 			send_resp(dut, conn, SIGMA_ERROR,
11723 				  "errorCode,Failed to clear ARP cache");
11724 			return 0;
11725 		}
11726 	}
11727 
11728 	return 1;
11729 }
11730 
11731 
cmd_sta_set_parameter(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)11732 int cmd_sta_set_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
11733 			  struct sigma_cmd *cmd)
11734 {
11735 	const char *intf = get_param(cmd, "Interface");
11736 	const char *val;
11737 
11738 	if (intf == NULL)
11739 		return -1;
11740 
11741 	val = get_param(cmd, "program");
11742 	if (val && (strcasecmp(val, "HS2") == 0 ||
11743 		    strcasecmp(val, "HS2-R2") == 0 ||
11744 		    strcasecmp(val, "HS2-R3") == 0))
11745 		return cmd_sta_set_parameter_hs2(dut, conn, cmd, intf);
11746 
11747 	return -1;
11748 }
11749 
11750 
cmd_sta_set_macaddr(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)11751 static enum sigma_cmd_result cmd_sta_set_macaddr(struct sigma_dut *dut,
11752 						 struct sigma_conn *conn,
11753 						 struct sigma_cmd *cmd)
11754 {
11755 	const char *intf = get_param(cmd, "Interface");
11756 	const char *mac = get_param(cmd, "MAC");
11757 
11758 	if (intf == NULL || mac == NULL)
11759 		return -1;
11760 
11761 	sigma_dut_print(dut, DUT_MSG_INFO, "Change local MAC address for "
11762 			"interface %s to %s", intf, mac);
11763 
11764 	if (dut->set_macaddr) {
11765 		char buf[128];
11766 		int res;
11767 		if (strcasecmp(mac, "default") == 0) {
11768 			res = snprintf(buf, sizeof(buf), "%s",
11769 				       dut->set_macaddr);
11770 			dut->tmp_mac_addr = 0;
11771 		} else {
11772 			res = snprintf(buf, sizeof(buf), "%s %s",
11773 				       dut->set_macaddr, mac);
11774 			dut->tmp_mac_addr = 1;
11775 		}
11776 		if (res < 0 || res >= (int) sizeof(buf))
11777 			return -1;
11778 		if (system(buf) != 0) {
11779 			send_resp(dut, conn, SIGMA_ERROR,
11780 				  "errorCode,Failed to set MAC "
11781 				  "address");
11782 			return 0;
11783 		}
11784 		return 1;
11785 	}
11786 
11787 	if (strcasecmp(mac, "default") == 0)
11788 		return 1;
11789 
11790 	send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
11791 		  "command");
11792 	return 0;
11793 }
11794 
11795 
iwpriv_tdlsoffchnmode(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,int val)11796 static int iwpriv_tdlsoffchnmode(struct sigma_dut *dut,
11797 				 struct sigma_conn *conn, const char *intf,
11798 				 int val)
11799 {
11800 	char buf[200];
11801 	int res;
11802 
11803 	res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsoffchnmode %d",
11804 		       intf, val);
11805 	if (res < 0 || res >= (int) sizeof(buf))
11806 		return -1;
11807 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
11808 	if (system(buf) != 0) {
11809 		send_resp(dut, conn, SIGMA_ERROR,
11810 			  "errorCode,Failed to configure offchannel mode");
11811 		return 0;
11812 	}
11813 
11814 	return 1;
11815 }
11816 
11817 
off_chan_val(enum sec_ch_offset off)11818 static int off_chan_val(enum sec_ch_offset off)
11819 {
11820 	switch (off) {
11821 	case SEC_CH_NO:
11822 		return 0;
11823 	case SEC_CH_40ABOVE:
11824 		return 40;
11825 	case SEC_CH_40BELOW:
11826 		return -40;
11827 	}
11828 
11829 	return 0;
11830 }
11831 
11832 
iwpriv_set_offchan(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,int off_ch_num,enum sec_ch_offset sec)11833 static int iwpriv_set_offchan(struct sigma_dut *dut, struct sigma_conn *conn,
11834 			      const char *intf, int off_ch_num,
11835 			      enum sec_ch_offset sec)
11836 {
11837 	char buf[200];
11838 	int res;
11839 
11840 	res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsoffchan %d",
11841 		       intf, off_ch_num);
11842 	if (res < 0 || res >= (int) sizeof(buf))
11843 		return -1;
11844 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
11845 	if (system(buf) != 0) {
11846 		send_resp(dut, conn, SIGMA_ERROR,
11847 			  "errorCode,Failed to set offchan");
11848 		return 0;
11849 	}
11850 
11851 	res = snprintf(buf, sizeof(buf), "iwpriv %s tdlsecchnoffst %d",
11852 		       intf, off_chan_val(sec));
11853 	if (res < 0 || res >= (int) sizeof(buf))
11854 		return -1;
11855 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
11856 	if (system(buf) != 0) {
11857 		send_resp(dut, conn, SIGMA_ERROR,
11858 			  "errorCode,Failed to set sec chan offset");
11859 		return 0;
11860 	}
11861 
11862 	return 1;
11863 }
11864 
11865 
tdls_set_offchannel_offset(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,int off_ch_num,enum sec_ch_offset sec)11866 static int tdls_set_offchannel_offset(struct sigma_dut *dut,
11867 				      struct sigma_conn *conn,
11868 				      const char *intf, int off_ch_num,
11869 				      enum sec_ch_offset sec)
11870 {
11871 	char buf[200];
11872 	int res;
11873 
11874 	res = snprintf(buf, sizeof(buf), "DRIVER TDLSOFFCHANNEL %d",
11875 		       off_ch_num);
11876 	if (res < 0 || res >= (int) sizeof(buf))
11877 		return -1;
11878 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
11879 
11880 	if (wpa_command(intf, buf) < 0) {
11881 		send_resp(dut, conn, SIGMA_ERROR,
11882 			  "ErrorCode,Failed to set offchan");
11883 		return 0;
11884 	}
11885 	res = snprintf(buf, sizeof(buf), "DRIVER TDLSSECONDARYCHANNELOFFSET %d",
11886 		       off_chan_val(sec));
11887 	if (res < 0 || res >= (int) sizeof(buf))
11888 		return -1;
11889 
11890 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
11891 
11892 	if (wpa_command(intf, buf) < 0) {
11893 		send_resp(dut, conn, SIGMA_ERROR,
11894 			  "ErrorCode,Failed to set sec chan offset");
11895 		return 0;
11896 	}
11897 
11898 	return 1;
11899 }
11900 
11901 
tdls_set_offchannel_mode(struct sigma_dut * dut,struct sigma_conn * conn,const char * intf,int val)11902 static int tdls_set_offchannel_mode(struct sigma_dut *dut,
11903 				    struct sigma_conn *conn,
11904 				    const char *intf, int val)
11905 {
11906 	char buf[200];
11907 	int res;
11908 
11909 	res = snprintf(buf, sizeof(buf), "DRIVER TDLSOFFCHANNELMODE %d",
11910 		       val);
11911 	if (res < 0 || res >= (int) sizeof(buf))
11912 		return -1;
11913 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Run: %s", buf);
11914 
11915 	if (wpa_command(intf, buf) < 0) {
11916 		send_resp(dut, conn, SIGMA_ERROR,
11917 			"ErrorCode,Failed to configure offchannel mode");
11918 		return 0;
11919 	}
11920 
11921 	return 1;
11922 }
11923 
11924 
cmd_sta_set_rfeature_tdls(const char * intf,struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)11925 static int cmd_sta_set_rfeature_tdls(const char *intf, struct sigma_dut *dut,
11926 				     struct sigma_conn *conn,
11927 				     struct sigma_cmd *cmd)
11928 {
11929 	const char *val;
11930 	enum {
11931 		CHSM_NOT_SET,
11932 		CHSM_ENABLE,
11933 		CHSM_DISABLE,
11934 		CHSM_REJREQ,
11935 		CHSM_UNSOLRESP
11936 	} chsm = CHSM_NOT_SET;
11937 	int off_ch_num = -1;
11938 	enum sec_ch_offset sec_ch = SEC_CH_NO;
11939 	int res;
11940 
11941 	val = get_param(cmd, "Uapsd");
11942 	if (val) {
11943 		char buf[100];
11944 		if (strcasecmp(val, "Enable") == 0)
11945 			snprintf(buf, sizeof(buf), "SET ps 99");
11946 		else if (strcasecmp(val, "Disable") == 0)
11947 			snprintf(buf, sizeof(buf), "SET ps 98");
11948 		else {
11949 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,"
11950 				  "Unsupported uapsd parameter value");
11951 			return 0;
11952 		}
11953 		if (wpa_command(intf, buf)) {
11954 			send_resp(dut, conn, SIGMA_ERROR,
11955 				  "ErrorCode,Failed to change U-APSD "
11956 				  "powersave mode");
11957 			return 0;
11958 		}
11959 	}
11960 
11961 	val = get_param(cmd, "TPKTIMER");
11962 	if (val && strcasecmp(val, "DISABLE") == 0) {
11963 		if (wpa_command(intf, "SET tdls_testing 0x100")) {
11964 			send_resp(dut, conn, SIGMA_ERROR,
11965 				  "ErrorCode,Failed to enable no TPK "
11966 				  "expiration test mode");
11967 			return 0;
11968 		}
11969 		dut->no_tpk_expiration = 1;
11970 	}
11971 
11972 	val = get_param(cmd, "ChSwitchMode");
11973 	if (val) {
11974 		if (strcasecmp(val, "Enable") == 0 ||
11975 		    strcasecmp(val, "Initiate") == 0)
11976 			chsm = CHSM_ENABLE;
11977 		else if (strcasecmp(val, "Disable") == 0 ||
11978 		    strcasecmp(val, "passive") == 0)
11979 			chsm = CHSM_DISABLE;
11980 		else if (strcasecmp(val, "RejReq") == 0)
11981 			chsm = CHSM_REJREQ;
11982 		else if (strcasecmp(val, "UnSolResp") == 0)
11983 			chsm = CHSM_UNSOLRESP;
11984 		else {
11985 			send_resp(dut, conn, SIGMA_ERROR,
11986 				  "ErrorCode,Unknown ChSwitchMode value");
11987 			return 0;
11988 		}
11989 	}
11990 
11991 	val = get_param(cmd, "OffChNum");
11992 	if (val) {
11993 		off_ch_num = atoi(val);
11994 		if (off_ch_num == 0) {
11995 			send_resp(dut, conn, SIGMA_ERROR,
11996 				  "ErrorCode,Invalid OffChNum");
11997 			return 0;
11998 		}
11999 	}
12000 
12001 	val = get_param(cmd, "SecChOffset");
12002 	if (val) {
12003 		if (strcmp(val, "20") == 0)
12004 			sec_ch = SEC_CH_NO;
12005 		else if (strcasecmp(val, "40above") == 0)
12006 			sec_ch = SEC_CH_40ABOVE;
12007 		else if (strcasecmp(val, "40below") == 0)
12008 			sec_ch = SEC_CH_40BELOW;
12009 		else {
12010 			send_resp(dut, conn, SIGMA_ERROR,
12011 				  "ErrorCode,Unknown SecChOffset value");
12012 			return 0;
12013 		}
12014 	}
12015 
12016 	if (chsm == CHSM_NOT_SET) {
12017 		/* no offchannel changes requested */
12018 		return 1;
12019 	}
12020 
12021 	if (strcmp(intf, get_main_ifname(dut)) != 0 &&
12022 	    strcmp(intf, get_station_ifname(dut)) != 0) {
12023 		send_resp(dut, conn, SIGMA_ERROR,
12024 			  "ErrorCode,Unknown interface");
12025 		return 0;
12026 	}
12027 
12028 	switch (chsm) {
12029 	case CHSM_NOT_SET:
12030 		res = 1;
12031 		break;
12032 	case CHSM_ENABLE:
12033 		if (off_ch_num < 0) {
12034 			send_resp(dut, conn, SIGMA_ERROR,
12035 				  "ErrorCode,Missing OffChNum argument");
12036 			return 0;
12037 		}
12038 		if (wifi_chip_type == DRIVER_WCN) {
12039 			res = tdls_set_offchannel_offset(dut, conn, intf,
12040 							 off_ch_num, sec_ch);
12041 		} else {
12042 			res = iwpriv_set_offchan(dut, conn, intf, off_ch_num,
12043 						 sec_ch);
12044 		}
12045 		if (res != 1)
12046 			return res;
12047 		if (wifi_chip_type == DRIVER_WCN)
12048 			res = tdls_set_offchannel_mode(dut, conn, intf, 1);
12049 		else
12050 			res = iwpriv_tdlsoffchnmode(dut, conn, intf, 1);
12051 		break;
12052 	case CHSM_DISABLE:
12053 		if (wifi_chip_type == DRIVER_WCN)
12054 			res = tdls_set_offchannel_mode(dut, conn, intf, 2);
12055 		else
12056 			res = iwpriv_tdlsoffchnmode(dut, conn, intf, 2);
12057 		break;
12058 	case CHSM_REJREQ:
12059 		if (wifi_chip_type == DRIVER_WCN)
12060 			res = tdls_set_offchannel_mode(dut, conn, intf, 3);
12061 		else
12062 			res = iwpriv_tdlsoffchnmode(dut, conn, intf, 3);
12063 		break;
12064 	case CHSM_UNSOLRESP:
12065 		if (off_ch_num < 0) {
12066 			send_resp(dut, conn, SIGMA_ERROR,
12067 				  "ErrorCode,Missing OffChNum argument");
12068 			return 0;
12069 		}
12070 		if (wifi_chip_type == DRIVER_WCN) {
12071 			res = tdls_set_offchannel_offset(dut, conn, intf,
12072 							 off_ch_num, sec_ch);
12073 		} else {
12074 			res = iwpriv_set_offchan(dut, conn, intf, off_ch_num,
12075 						 sec_ch);
12076 		}
12077 		if (res != 1)
12078 			return res;
12079 		if (wifi_chip_type == DRIVER_WCN)
12080 			res = tdls_set_offchannel_mode(dut, conn, intf, 4);
12081 		else
12082 			res = iwpriv_tdlsoffchnmode(dut, conn, intf, 4);
12083 		break;
12084 	}
12085 
12086 	return res;
12087 }
12088 
12089 
ath_sta_set_rfeature_vht(const char * intf,struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)12090 static int ath_sta_set_rfeature_vht(const char *intf, struct sigma_dut *dut,
12091 				    struct sigma_conn *conn,
12092 				    struct sigma_cmd *cmd)
12093 {
12094 	const char *val;
12095 	char *token = NULL, *result;
12096 
12097 	novap_reset(dut, intf, 1);
12098 
12099 	val = get_param(cmd, "nss_mcs_opt");
12100 	if (val) {
12101 		/* String (nss_operating_mode; mcs_operating_mode) */
12102 		int nss, mcs;
12103 		char *saveptr;
12104 
12105 		token = strdup(val);
12106 		if (!token)
12107 			return 0;
12108 		result = strtok_r(token, ";", &saveptr);
12109 		if (!result) {
12110 			sigma_dut_print(dut, DUT_MSG_ERROR,
12111 				"VHT NSS not specified");
12112 			goto failed;
12113 		}
12114 		if (strcasecmp(result, "def") != 0) {
12115 			nss = atoi(result);
12116 			if (nss == 4)
12117 				ath_disable_txbf(dut, intf);
12118 			if (run_iwpriv(dut, intf, "nss %d", nss) < 0)
12119 				goto failed;
12120 
12121 		}
12122 
12123 		result = strtok_r(NULL, ";", &saveptr);
12124 		if (!result) {
12125 			sigma_dut_print(dut, DUT_MSG_ERROR,
12126 				"VHT MCS not specified");
12127 			goto failed;
12128 		}
12129 		if (strcasecmp(result, "def") == 0) {
12130 			if (run_iwpriv(dut, intf, "set11NRates 0") < 0)
12131 				goto failed;
12132 		} else {
12133 			mcs = atoi(result);
12134 			if (run_iwpriv(dut, intf, "vhtmcs %d", mcs) < 0)
12135 				goto failed;
12136 		}
12137 		/* Channel width gets messed up, fix this */
12138 		run_iwpriv(dut, intf, "chwidth %d", dut->chwidth);
12139 	}
12140 
12141 	free(token);
12142 	return 1;
12143 failed:
12144 	free(token);
12145 	return 0;
12146 }
12147 
12148 
cmd_sta_set_rfeature_vht(const char * intf,struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)12149 static int cmd_sta_set_rfeature_vht(const char *intf, struct sigma_dut *dut,
12150 				    struct sigma_conn *conn,
12151 				    struct sigma_cmd *cmd)
12152 {
12153 	switch (get_driver_type(dut)) {
12154 	case DRIVER_ATHEROS:
12155 		return ath_sta_set_rfeature_vht(intf, dut, conn, cmd);
12156 	default:
12157 		send_resp(dut, conn, SIGMA_ERROR,
12158 			  "errorCode,Unsupported sta_set_rfeature(VHT) with the current driver");
12159 		return 0;
12160 	}
12161 }
12162 
12163 
12164 static enum sigma_cmd_result
wcn_sta_set_rfeature_he(const char * intf,struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)12165 wcn_sta_set_rfeature_he(const char *intf, struct sigma_dut *dut,
12166 			struct sigma_conn *conn, struct sigma_cmd *cmd)
12167 {
12168 	const char *val;
12169 	char *token = NULL, *result;
12170 	char buf[60];
12171 
12172 	val = get_param(cmd, "nss_mcs_opt");
12173 	if (val) {
12174 		/* String (nss_operating_mode; mcs_operating_mode) */
12175 		int nss, mcs, ratecode;
12176 		char *saveptr;
12177 
12178 		token = strdup(val);
12179 		if (!token)
12180 			return ERROR_SEND_STATUS;
12181 
12182 		result = strtok_r(token, ";", &saveptr);
12183 		if (!result) {
12184 			sigma_dut_print(dut, DUT_MSG_ERROR,
12185 					"HE NSS not specified");
12186 			goto failed;
12187 		}
12188 		nss = 1;
12189 		if (strcasecmp(result, "def") != 0)
12190 			nss = atoi(result);
12191 
12192 		result = strtok_r(NULL, ";", &saveptr);
12193 		if (!result) {
12194 			sigma_dut_print(dut, DUT_MSG_ERROR,
12195 					"HE MCS not specified");
12196 			goto failed;
12197 		}
12198 		mcs = 7;
12199 		if (strcasecmp(result, "def") != 0)
12200 			mcs = atoi(result);
12201 
12202 		ratecode = 0x20; /* for nss:1 MCS 0 */
12203 		if (nss == 2) {
12204 			ratecode = 0x40; /* for nss:2 MCS 0 */
12205 		} else if (nss > 2) {
12206 			sigma_dut_print(dut, DUT_MSG_ERROR,
12207 					"HE NSS %d not supported", nss);
12208 			goto failed;
12209 		}
12210 
12211 		snprintf(buf, sizeof(buf), "iwpriv %s nss %d", intf, nss);
12212 		if (system(buf) != 0) {
12213 			sigma_dut_print(dut, DUT_MSG_ERROR,
12214 					"nss_mcs_opt: iwpriv %s nss %d failed",
12215 					intf, nss);
12216 			goto failed;
12217 		}
12218 		dut->sta_nss = nss;
12219 
12220 		/* Add the MCS to the ratecode */
12221 		if (mcs >= 0 && mcs <= 11) {
12222 			ratecode += mcs;
12223 #ifdef NL80211_SUPPORT
12224 			if (dut->device_type == STA_testbed) {
12225 				enum he_mcs_config mcs_config;
12226 				int ret;
12227 
12228 				if (mcs <= 7)
12229 					mcs_config = HE_80_MCS0_7;
12230 				else if (mcs <= 9)
12231 					mcs_config = HE_80_MCS0_9;
12232 				else
12233 					mcs_config = HE_80_MCS0_11;
12234 				ret = sta_set_he_mcs(dut, intf, mcs_config);
12235 				if (ret) {
12236 					sigma_dut_print(dut, DUT_MSG_ERROR,
12237 							"nss_mcs_opt: mcs setting failed, mcs:%d, mcs_config %d, ret:%d",
12238 							mcs, mcs_config, ret);
12239 					goto failed;
12240 				}
12241 			}
12242 #endif /* NL80211_SUPPORT */
12243 		} else {
12244 			sigma_dut_print(dut, DUT_MSG_ERROR,
12245 					"HE MCS %d not supported", mcs);
12246 			goto failed;
12247 		}
12248 		snprintf(buf, sizeof(buf), "iwpriv %s set_11ax_rate 0x%03x",
12249 			 intf, ratecode);
12250 		if (system(buf) != 0) {
12251 			sigma_dut_print(dut, DUT_MSG_ERROR,
12252 					"iwpriv setting of 11ax rates failed");
12253 			goto failed;
12254 		}
12255 		free(token);
12256 	}
12257 
12258 	val = get_param(cmd, "GI");
12259 	if (val) {
12260 		int fix_rate_sgi;
12261 
12262 		if (strcmp(val, "0.8") == 0) {
12263 			snprintf(buf, sizeof(buf), "iwpriv %s shortgi 9", intf);
12264 			fix_rate_sgi = 1;
12265 		} else if (strcmp(val, "1.6") == 0) {
12266 			snprintf(buf, sizeof(buf), "iwpriv %s shortgi 10",
12267 				 intf);
12268 			fix_rate_sgi = 2;
12269 		} else if (strcmp(val, "3.2") == 0) {
12270 			snprintf(buf, sizeof(buf), "iwpriv %s shortgi 11",
12271 				 intf);
12272 			fix_rate_sgi = 3;
12273 		} else {
12274 			send_resp(dut, conn, SIGMA_ERROR,
12275 				  "errorCode,GI value not supported");
12276 			return STATUS_SENT_ERROR;
12277 		}
12278 		if (system(buf) != 0) {
12279 			send_resp(dut, conn, SIGMA_ERROR,
12280 				  "errorCode,Failed to set shortgi");
12281 			return STATUS_SENT_ERROR;
12282 		}
12283 		snprintf(buf, sizeof(buf), "iwpriv %s shortgi %d",
12284 				intf, fix_rate_sgi);
12285 		if (system(buf) != 0) {
12286 			send_resp(dut, conn, SIGMA_ERROR,
12287 				  "errorCode,Failed to set fix rate shortgi");
12288 			return STATUS_SENT_ERROR;
12289 		}
12290 	}
12291 
12292 	val = get_param(cmd, "LTF");
12293 	if (val) {
12294 #ifdef NL80211_SUPPORT
12295 		if (strcmp(val, "3.2") == 0) {
12296 			wcn_set_he_ltf(dut, intf, QCA_WLAN_HE_LTF_1X);
12297 		} if (strcmp(val, "6.4") == 0) {
12298 			wcn_set_he_ltf(dut, intf, QCA_WLAN_HE_LTF_2X);
12299 		} else if (strcmp(val, "12.8") == 0) {
12300 			wcn_set_he_ltf(dut, intf, QCA_WLAN_HE_LTF_4X);
12301 		} else {
12302 			send_resp(dut, conn, SIGMA_ERROR,
12303 				  "errorCode, LTF value not supported");
12304 			return STATUS_SENT_ERROR;
12305 		}
12306 #else /* NL80211_SUPPORT */
12307 		sigma_dut_print(dut, DUT_MSG_ERROR,
12308 				"LTF cannot be set without NL80211_SUPPORT defined");
12309 		return ERROR_SEND_STATUS;
12310 #endif /* NL80211_SUPPORT */
12311 	}
12312 
12313 	val = get_param(cmd, "TxSUPPDU");
12314 	if (val) {
12315 		int set_val = 1;
12316 
12317 		if (strcasecmp(val, "Enable") == 0)
12318 			set_val = 1;
12319 		else if (strcasecmp(val, "Disable") == 0)
12320 			set_val = 0;
12321 
12322 		if (sta_set_tx_su_ppdu_cfg(dut, intf, set_val)) {
12323 			send_resp(dut, conn, SIGMA_ERROR,
12324 				  "ErrorCode,Failed to set Tx SU PPDU config");
12325 			return STATUS_SENT_ERROR;
12326 		}
12327 	}
12328 
12329 	val = get_param(cmd, "Mgmt_Data_TX_Resp_Frame");
12330 	if (val) {
12331 		int set_val = 0;
12332 
12333 		if (strcasecmp(val, "Enable") == 0)
12334 			set_val = 0;
12335 		else if (strcasecmp(val, "Disable") == 0)
12336 			set_val = 1;
12337 
12338 		if (sta_set_mgmt_data_tx_disable_cfg(dut, intf, set_val)) {
12339 			send_resp(dut, conn, SIGMA_ERROR,
12340 				  "ErrorCode,Failed to set mgmt/data Tx disable config");
12341 			return STATUS_SENT_ERROR;
12342 		}
12343 	}
12344 
12345 	val = get_param(cmd, "TWT_Setup");
12346 	if (val) {
12347 		if (strcasecmp(val, "Request") == 0) {
12348 			if (sta_twt_request(dut, conn, cmd)) {
12349 				send_resp(dut, conn, SIGMA_ERROR,
12350 					  "ErrorCode,TWT setup failed");
12351 				return STATUS_SENT_ERROR;
12352 			}
12353 		} else if (strcasecmp(val, "Teardown") == 0) {
12354 			if (sta_twt_teardown(dut, conn, cmd)) {
12355 				send_resp(dut, conn, SIGMA_ERROR,
12356 					  "ErrorCode,TWT teardown failed");
12357 				return STATUS_SENT_ERROR;
12358 			}
12359 		}
12360 	}
12361 
12362 	val = get_param(cmd, "TWT_Operation");
12363 	if (val) {
12364 		if (strcasecmp(val, "Suspend") == 0) {
12365 			if (sta_twt_suspend_or_nudge(dut, conn, cmd)) {
12366 				send_resp(dut, conn, SIGMA_ERROR,
12367 					  "ErrorCode,TWT suspend failed");
12368 				return STATUS_SENT_ERROR;
12369 			}
12370 		} else if (strcasecmp(val, "Resume") == 0) {
12371 			if (sta_twt_resume(dut, conn, cmd)) {
12372 				send_resp(dut, conn, SIGMA_ERROR,
12373 					  "ErrorCode,TWT resume failed");
12374 				return STATUS_SENT_ERROR;
12375 			}
12376 		}
12377 	}
12378 
12379 	val = get_param(cmd, "transmitOMI");
12380 	if (val && sta_transmit_omi(dut, conn, cmd)) {
12381 		send_resp(dut, conn, SIGMA_ERROR,
12382 			  "ErrorCode,sta_transmit_omi failed");
12383 		return STATUS_SENT_ERROR;
12384 	}
12385 
12386 	val = get_param(cmd, "Powersave");
12387 	if (val) {
12388 		int ps;
12389 
12390 		if (strcasecmp(val, "off") == 0) {
12391 			ps = 2;
12392 		} else if (strcasecmp(val, "on") == 0) {
12393 			ps = 1;
12394 		} else {
12395 			sigma_dut_print(dut, DUT_MSG_ERROR,
12396 					"Unsupported Powersave value '%s'",
12397 					val);
12398 			return INVALID_SEND_STATUS;
12399 		}
12400 		if (set_power_save_wcn(dut, intf, ps) < 0)
12401 			return ERROR_SEND_STATUS;
12402 	}
12403 
12404 	val = get_param(cmd, "MU_EDCA");
12405 	if (val) {
12406 		if (strcasecmp(val, "Override") == 0) {
12407 			if (sta_set_mu_edca_override(dut, intf, 1)) {
12408 				send_resp(dut, conn, SIGMA_ERROR,
12409 					  "errorCode,MU EDCA override set failed");
12410 				return STATUS_SENT;
12411 			}
12412 		} else if (strcasecmp(val, "Disable") == 0) {
12413 			if (sta_set_mu_edca_override(dut, intf, 0)) {
12414 				send_resp(dut, conn, SIGMA_ERROR,
12415 					  "errorCode,MU EDCA override disable failed");
12416 				return STATUS_SENT;
12417 			}
12418 		}
12419 	}
12420 
12421 	val = get_param(cmd, "Ch_Pref");
12422 	if (val && mbo_set_non_pref_ch_list(dut, conn, intf, cmd) == 0)
12423 		return STATUS_SENT;
12424 
12425 	val = get_param(cmd, "Cellular_Data_Cap");
12426 	if (val && mbo_set_cellular_data_capa(dut, conn, intf, atoi(val)) == 0)
12427 		return STATUS_SENT;
12428 
12429 	return SUCCESS_SEND_STATUS;
12430 
12431 failed:
12432 	free(token);
12433 	return ERROR_SEND_STATUS;
12434 }
12435 
12436 
12437 static enum sigma_cmd_result
cmd_sta_set_rfeature_he(const char * intf,struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)12438 cmd_sta_set_rfeature_he(const char *intf, struct sigma_dut *dut,
12439 			struct sigma_conn *conn, struct sigma_cmd *cmd)
12440 {
12441 	switch (get_driver_type(dut)) {
12442 	case DRIVER_WCN:
12443 		return wcn_sta_set_rfeature_he(intf, dut, conn, cmd);
12444 	default:
12445 		send_resp(dut, conn, SIGMA_ERROR,
12446 			  "errorCode,Unsupported sta_set_rfeature(HE) with the current driver");
12447 		return STATUS_SENT_ERROR;
12448 	}
12449 }
12450 
12451 
cmd_sta_set_power_save_he(const char * intf,struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)12452 static int cmd_sta_set_power_save_he(const char *intf, struct sigma_dut *dut,
12453 				     struct sigma_conn *conn,
12454 				     struct sigma_cmd *cmd)
12455 {
12456 	const char *val;
12457 
12458 	val = get_param(cmd, "powersave");
12459 	if (val) {
12460 		int ps;
12461 
12462 		if (strcasecmp(val, "off") == 0) {
12463 			ps = 2;
12464 		} else if (strcasecmp(val, "on") == 0) {
12465 			ps = 1;
12466 		} else {
12467 			sigma_dut_print(dut, DUT_MSG_ERROR,
12468 					"Unsupported power save config");
12469 			return -1;
12470 		}
12471 		if (set_power_save_wcn(dut, intf, ps) < 0)
12472 			return 0;
12473 		return 1;
12474 	}
12475 
12476 	send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported command");
12477 
12478 	return 0;
12479 }
12480 
12481 
btm_query_candidate_list(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)12482 static int btm_query_candidate_list(struct sigma_dut *dut,
12483 				    struct sigma_conn *conn,
12484 				    struct sigma_cmd *cmd)
12485 {
12486 	const char *bssid, *info, *op_class, *ch, *phy_type, *pref;
12487 	int len, ret;
12488 	char buf[10];
12489 
12490 	/*
12491 	 * Neighbor Report elements format:
12492 	 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
12493 	 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
12494 	 * eg: neighbor=aa:bb:cc:dd:ee:ff,17,81,6,1,030101
12495 	 */
12496 
12497 	bssid = get_param(cmd, "Nebor_BSSID");
12498 	if (!bssid) {
12499 		send_resp(dut, conn, SIGMA_INVALID,
12500 			  "errorCode,Nebor_BSSID is missing");
12501 		return 0;
12502 	}
12503 
12504 	info = get_param(cmd, "Nebor_Bssid_Info");
12505 	if (!info) {
12506 		sigma_dut_print(dut, DUT_MSG_INFO,
12507 				"Using default value for Nebor_Bssid_Info: %s",
12508 				DEFAULT_NEIGHBOR_BSSID_INFO);
12509 		info = DEFAULT_NEIGHBOR_BSSID_INFO;
12510 	}
12511 
12512 	op_class = get_param(cmd, "Nebor_Op_Class");
12513 	if (!op_class) {
12514 		send_resp(dut, conn, SIGMA_INVALID,
12515 			  "errorCode,Nebor_Op_Class is missing");
12516 		return 0;
12517 	}
12518 
12519 	ch = get_param(cmd, "Nebor_Op_Ch");
12520 	if (!ch) {
12521 		send_resp(dut, conn, SIGMA_INVALID,
12522 			  "errorCode,Nebor_Op_Ch is missing");
12523 		return 0;
12524 	}
12525 
12526 	phy_type = get_param(cmd, "Nebor_Phy_Type");
12527 	if (!phy_type) {
12528 		sigma_dut_print(dut, DUT_MSG_INFO,
12529 				"Using default value for Nebor_Phy_Type: %s",
12530 				DEFAULT_NEIGHBOR_PHY_TYPE);
12531 		phy_type = DEFAULT_NEIGHBOR_PHY_TYPE;
12532 	}
12533 
12534 	/* Parse optional subelements */
12535 	buf[0] = '\0';
12536 	pref = get_param(cmd, "Nebor_Pref");
12537 	if (pref) {
12538 		/* hexdump for preferrence subelement */
12539 		ret = snprintf(buf, sizeof(buf), ",0301%02x", atoi(pref));
12540 		if (ret < 0 || ret >= (int) sizeof(buf)) {
12541 			sigma_dut_print(dut, DUT_MSG_ERROR,
12542 					"snprintf failed for optional subelement ret: %d",
12543 					ret);
12544 			send_resp(dut, conn, SIGMA_ERROR,
12545 				  "errorCode,snprintf failed for subelement");
12546 			return 0;
12547 		}
12548 	}
12549 
12550 	if (!dut->btm_query_cand_list) {
12551 		dut->btm_query_cand_list = calloc(1, NEIGHBOR_REPORT_SIZE);
12552 		if (!dut->btm_query_cand_list) {
12553 			send_resp(dut, conn, SIGMA_ERROR,
12554 				  "errorCode,Failed to allocate memory for btm_query_cand_list");
12555 			return 0;
12556 		}
12557 	}
12558 
12559 	len = strlen(dut->btm_query_cand_list);
12560 	ret = snprintf(dut->btm_query_cand_list + len,
12561 		       NEIGHBOR_REPORT_SIZE - len, " neighbor=%s,%s,%s,%s,%s%s",
12562 		       bssid, info, op_class, ch, phy_type, buf);
12563 	if (ret < 0 || ret >= NEIGHBOR_REPORT_SIZE - len) {
12564 		sigma_dut_print(dut, DUT_MSG_ERROR,
12565 				"snprintf failed for neighbor report list ret: %d",
12566 				ret);
12567 		send_resp(dut, conn, SIGMA_ERROR,
12568 			  "errorCode,snprintf failed for neighbor report");
12569 		free(dut->btm_query_cand_list);
12570 		dut->btm_query_cand_list = NULL;
12571 		return 0;
12572 	}
12573 
12574 	return 1;
12575 }
12576 
12577 
sta_extract_60g_ese(struct sigma_dut * dut,struct sigma_cmd * cmd,struct sigma_ese_alloc * allocs,int * allocs_size)12578 int sta_extract_60g_ese(struct sigma_dut *dut, struct sigma_cmd *cmd,
12579 			struct sigma_ese_alloc *allocs, int *allocs_size)
12580 {
12581 	int max_count = *allocs_size;
12582 	int count = 0, i;
12583 	const char *val;
12584 
12585 	do {
12586 		val = get_param_indexed(cmd, "AllocID", count);
12587 		if (val)
12588 			count++;
12589 	} while (val);
12590 
12591 	if (count == 0 || count > max_count) {
12592 		sigma_dut_print(dut, DUT_MSG_ERROR,
12593 				"Invalid number of allocations(%d)", count);
12594 		return -1;
12595 	}
12596 
12597 	for (i = 0; i < count; i++) {
12598 		val = get_param_indexed(cmd, "PercentBI", i);
12599 		if (!val) {
12600 			sigma_dut_print(dut, DUT_MSG_ERROR,
12601 					"Missing PercentBI parameter at index %d",
12602 					i);
12603 			return -1;
12604 		}
12605 		allocs[i].percent_bi = atoi(val);
12606 
12607 		val = get_param_indexed(cmd, "SrcAID", i);
12608 		if (val)
12609 			allocs[i].src_aid = strtol(val, NULL, 0);
12610 		else
12611 			allocs[i].src_aid = ESE_BCAST_AID;
12612 
12613 		val = get_param_indexed(cmd, "DestAID", i);
12614 		if (val)
12615 			allocs[i].dst_aid = strtol(val, NULL, 0);
12616 		else
12617 			allocs[i].dst_aid = ESE_BCAST_AID;
12618 
12619 		allocs[i].type = ESE_CBAP;
12620 		sigma_dut_print(dut, DUT_MSG_INFO,
12621 				"Alloc %d PercentBI %d SrcAID %d DstAID %d",
12622 				i, allocs[i].percent_bi, allocs[i].src_aid,
12623 				allocs[i].dst_aid);
12624 	}
12625 
12626 	*allocs_size = count;
12627 	return 0;
12628 }
12629 
12630 
sta_set_60g_ese(struct sigma_dut * dut,int count,struct sigma_ese_alloc * allocs)12631 static int sta_set_60g_ese(struct sigma_dut *dut, int count,
12632 			   struct sigma_ese_alloc *allocs)
12633 {
12634 	switch (get_driver_type(dut)) {
12635 #ifdef __linux__
12636 	case DRIVER_WIL6210:
12637 		if (wil6210_set_ese(dut, count, allocs))
12638 			return -1;
12639 		return 1;
12640 #endif /* __linux__ */
12641 	default:
12642 		sigma_dut_print(dut, DUT_MSG_ERROR,
12643 				"Unsupported sta_set_60g_ese with the current driver");
12644 		return -1;
12645 	}
12646 }
12647 
12648 
cmd_sta_set_rfeature_60g(const char * intf,struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)12649 static int cmd_sta_set_rfeature_60g(const char *intf, struct sigma_dut *dut,
12650 				    struct sigma_conn *conn,
12651 				    struct sigma_cmd *cmd)
12652 {
12653 	const char *val;
12654 
12655 	val = get_param(cmd, "ExtSchIE");
12656 	if (val && !strcasecmp(val, "Enable")) {
12657 		struct sigma_ese_alloc allocs[MAX_ESE_ALLOCS];
12658 		int count = MAX_ESE_ALLOCS;
12659 
12660 		if (sta_extract_60g_ese(dut, cmd, allocs, &count))
12661 			return -1;
12662 		return sta_set_60g_ese(dut, count, allocs);
12663 	}
12664 
12665 	val = get_param(cmd, "MCS_FixedRate");
12666 	if (val) {
12667 		int sta_mcs = atoi(val);
12668 
12669 		sigma_dut_print(dut, DUT_MSG_INFO, "Force STA MCS to %d",
12670 				sta_mcs);
12671 		wil6210_set_force_mcs(dut, 1, sta_mcs);
12672 
12673 		return SUCCESS_SEND_STATUS;
12674 	}
12675 
12676 	send_resp(dut, conn, SIGMA_ERROR,
12677 		  "errorCode,Invalid sta_set_rfeature(60G)");
12678 	return STATUS_SENT;
12679 }
12680 
12681 
wcn_sta_override_oci(struct sigma_dut * dut,const char * intf,const char * oci_frametype,uint32_t oci_freq)12682 static int wcn_sta_override_oci(struct sigma_dut *dut, const char *intf,
12683 				const char *oci_frametype, uint32_t oci_freq)
12684 {
12685 #ifdef NL80211_SUPPORT
12686 	struct nl_msg *msg;
12687 	int ret = 0;
12688 	struct nlattr *params;
12689 	struct nlattr *attr;
12690 	int ifindex;
12691 	u8 frame_type;
12692 
12693 	ifindex = if_nametoindex(intf);
12694 	if (ifindex == 0) {
12695 		sigma_dut_print(dut, DUT_MSG_ERROR,
12696 				"%s: Index for interface %s failed",
12697 				__func__, intf);
12698 		return -1;
12699 	}
12700 
12701 	if (strcasecmp(oci_frametype, "SAQueryReq") == 0) {
12702 		frame_type = QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_REQ;
12703 	} else if (strcasecmp(oci_frametype, "SAQueryResp") == 0) {
12704 		frame_type = QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_RESP;
12705 	} else if (strcasecmp(oci_frametype, "Reassocreq") == 0) {
12706 		frame_type = QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FT_REASSOC_REQ;
12707 	} else {
12708 		sigma_dut_print(dut, DUT_MSG_ERROR, "%s: Unknown frametype %s",
12709 				__func__, oci_frametype);
12710 		return -1;
12711 	}
12712 
12713 
12714 	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
12715 				    NL80211_CMD_VENDOR)) ||
12716 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
12717 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
12718 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
12719 			QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION) ||
12720 	    !(attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
12721 	    !(params = nla_nest_start(
12722 		      msg,
12723 		      QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE)) ||
12724 	    nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE,
12725 		       frame_type) ||
12726 	    nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY,
12727 			oci_freq)) {
12728 		sigma_dut_print(dut, DUT_MSG_ERROR,
12729 				"%s: err in adding vendor_cmd and vendor_data",
12730 				__func__);
12731 		nlmsg_free(msg);
12732 		return -1;
12733 	}
12734 	nla_nest_end(msg, params);
12735 	nla_nest_end(msg, attr);
12736 
12737 	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
12738 	if (ret) {
12739 		sigma_dut_print(dut, DUT_MSG_ERROR,
12740 				"%s: err in send_and_recv_msgs, ret=%d",
12741 				__func__, ret);
12742 	}
12743 	return ret;
12744 #else /* NL80211_SUPPORT */
12745 	sigma_dut_print(dut, DUT_MSG_ERROR,
12746 			"OCI override not possible without NL80211_SUPPORT defined");
12747 	return -1;
12748 #endif /* NL80211_SUPPORT */
12749 }
12750 
12751 
wcn_sta_ignore_csa(struct sigma_dut * dut,const char * intf,uint8_t ignore_csa)12752 static int wcn_sta_ignore_csa(struct sigma_dut *dut, const char *intf,
12753 			      uint8_t ignore_csa)
12754 {
12755 #ifdef NL80211_SUPPORT
12756 	return wcn_wifi_test_config_set_u8(
12757 		dut, intf,
12758 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_CSA, ignore_csa);
12759 #else /* NL80211_SUPPORT */
12760 	sigma_dut_print(dut, DUT_MSG_ERROR,
12761 			"IgnoreCSA can't be set without NL80211_SUPPORT defined");
12762 	return -1;
12763 #endif /* NL80211_SUPPORT */
12764 }
12765 
12766 
wcn_sta_set_rsnxe_used(struct sigma_dut * dut,const char * intf,uint8_t rsnxe_used)12767 static int wcn_sta_set_rsnxe_used(struct sigma_dut *dut, const char *intf,
12768 				  uint8_t rsnxe_used)
12769 {
12770 #ifdef NL80211_SUPPORT
12771 	return wcn_wifi_test_config_set_u8(
12772 		dut, intf,
12773 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FT_REASSOCREQ_RSNXE_USED,
12774 		rsnxe_used);
12775 #else /* NL80211_SUPPORT */
12776 	sigma_dut_print(dut, DUT_MSG_ERROR,
12777 			"RSNXE_Used can't be set without NL80211_SUPPORT defined");
12778 	return -1;
12779 #endif /* NL80211_SUPPORT */
12780 }
12781 
12782 
wcn_sta_ignore_sa_query_timeout(struct sigma_dut * dut,const char * intf,uint8_t ignore_sa_query_timeout)12783 static int wcn_sta_ignore_sa_query_timeout(struct sigma_dut *dut,
12784 					   const char *intf,
12785 					   uint8_t ignore_sa_query_timeout)
12786 {
12787 #ifdef NL80211_SUPPORT
12788 	return wcn_wifi_test_config_set_u8(
12789 		dut, intf,
12790 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT,
12791 		ignore_sa_query_timeout);
12792 #else /* NL80211_SUPPORT */
12793 	sigma_dut_print(dut, DUT_MSG_ERROR,
12794 			"Ignore SA Query timeout can't be set without NL80211_SUPPORT defined");
12795 	return -1;
12796 #endif /* NL80211_SUPPORT */
12797 }
12798 
12799 
12800 static enum sigma_cmd_result
cmd_sta_set_rfeature_wpa3(const char * intf,struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)12801 cmd_sta_set_rfeature_wpa3(const char *intf, struct sigma_dut *dut,
12802 			  struct sigma_conn *conn,
12803 			  struct sigma_cmd *cmd)
12804 {
12805 	const char *val, *oci_chan, *oci_frametype;
12806 
12807 	val = get_param(cmd, "ReassocReq_RSNXE_Used");
12808 	if (val && atoi(val) == 1) {
12809 		if (wifi_chip_type == DRIVER_WCN) {
12810 			if (wcn_sta_set_rsnxe_used(dut, intf, 1)) {
12811 				send_resp(dut, conn, SIGMA_ERROR,
12812 					  "errorCode,Failed to set ft_rsnxe_used");
12813 				return STATUS_SENT_ERROR;
12814 			}
12815 			return SUCCESS_SEND_STATUS;
12816 		} else if (wpa_command(intf, "SET ft_rsnxe_used 1") < 0) {
12817 			send_resp(dut, conn, SIGMA_ERROR,
12818 				  "errorCode,Failed to set ft_rsnxe_used");
12819 			return STATUS_SENT_ERROR;
12820 		}
12821 		return SUCCESS_SEND_STATUS;
12822 	}
12823 
12824 	oci_chan = get_param(cmd, "OCIChannel");
12825 	oci_frametype = get_param(cmd, "OCIFrameType");
12826 	if (oci_chan && oci_frametype) {
12827 		unsigned int oci_freq = channel_to_freq(dut, atoi(oci_chan));
12828 		char buf[100];
12829 
12830 		if (!oci_freq) {
12831 			send_resp(dut, conn, SIGMA_ERROR,
12832 				  "errorCode,Invalid OCIChannel number");
12833 			return STATUS_SENT_ERROR;
12834 		}
12835 
12836 		if (wifi_chip_type == DRIVER_WCN &&
12837 		    (strcasecmp(oci_frametype, "SAQueryReq") == 0 ||
12838 		     strcasecmp(oci_frametype, "SAQueryResp") == 0 ||
12839 		     strcasecmp(oci_frametype, "Reassocreq") == 0)) {
12840 			if (wcn_sta_override_oci(dut, intf, oci_frametype,
12841 						 oci_freq)) {
12842 				send_resp(dut, conn, SIGMA_ERROR,
12843 					  "errorCode,Failed to override OCI");
12844 				return STATUS_SENT_ERROR;
12845 			}
12846 			return SUCCESS_SEND_STATUS;
12847 		}
12848 
12849 		if (strcasecmp(oci_frametype, "eapolM2") == 0) {
12850 			snprintf(buf, sizeof(buf),
12851 				 "SET oci_freq_override_eapol %d", oci_freq);
12852 		} else if (strcasecmp(oci_frametype, "SAQueryReq") == 0) {
12853 			snprintf(buf, sizeof(buf),
12854 				 "SET oci_freq_override_saquery_req %d",
12855 				 oci_freq);
12856 		} else if (strcasecmp(oci_frametype, "SAQueryResp") == 0) {
12857 			snprintf(buf, sizeof(buf),
12858 				 "SET oci_freq_override_saquery_resp %d",
12859 				 oci_freq);
12860 		} else if (strcasecmp(oci_frametype, "GrpKeyM2") == 0) {
12861 			snprintf(buf, sizeof(buf),
12862 				 "SET oci_freq_override_eapol_g2 %d",
12863 				 oci_freq);
12864 		} else if (strcasecmp(oci_frametype, "Reassocreq") == 0) {
12865 			snprintf(buf, sizeof(buf),
12866 				 "SET oci_freq_override_ft_assoc %d",
12867 				 oci_freq);
12868 		} else {
12869 			send_resp(dut, conn, SIGMA_ERROR,
12870 				  "errorCode,Unsupported OCIFrameType");
12871 			return STATUS_SENT_ERROR;
12872 		}
12873 		if (wpa_command(intf, buf) < 0) {
12874 			send_resp(dut, conn, SIGMA_ERROR,
12875 				  "errorCode,Failed to set oci_freq_override");
12876 			return STATUS_SENT_ERROR;
12877 		}
12878 		return SUCCESS_SEND_STATUS;
12879 	}
12880 
12881 	val = get_param(cmd, "IgnoreCSA");
12882 	if (val && atoi(val) == 1) {
12883 		if (wifi_chip_type == DRIVER_WCN) {
12884 			if (wcn_sta_ignore_csa(dut, intf, 1)) {
12885 				send_resp(dut, conn, SIGMA_ERROR,
12886 					  "errorCode,Failed to set ignore CSA");
12887 				return STATUS_SENT_ERROR;
12888 			}
12889 			return SUCCESS_SEND_STATUS;
12890 		}
12891 	}
12892 
12893 	val = get_param(cmd, "Deauth_Per_SAQueryResp");
12894 	if (val && atoi(val) == 0) {
12895 		if (wifi_chip_type == DRIVER_WCN) {
12896 			if (wcn_sta_ignore_sa_query_timeout(dut, intf, 1)) {
12897 				send_resp(dut, conn, SIGMA_ERROR,
12898 					  "errorCode,Failed to set ignore SA Query timeout");
12899 				return STATUS_SENT_ERROR;
12900 			}
12901 			return SUCCESS_SEND_STATUS;
12902 		}
12903 	}
12904 
12905 	send_resp(dut, conn, SIGMA_ERROR,
12906 		  "errorCode,Unsupported WPA3 rfeature");
12907 	return STATUS_SENT_ERROR;
12908 }
12909 
12910 
cmd_sta_set_rfeature(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)12911 static enum sigma_cmd_result cmd_sta_set_rfeature(struct sigma_dut *dut,
12912 						  struct sigma_conn *conn,
12913 						  struct sigma_cmd *cmd)
12914 {
12915 	const char *intf = get_param(cmd, "Interface");
12916 	const char *prog = get_param(cmd, "Prog");
12917 	const char *val;
12918 
12919 	if (intf == NULL || prog == NULL)
12920 		return -1;
12921 
12922 	/* BSS Transition candidate list for BTM query */
12923 	val = get_param(cmd, "Nebor_BSSID");
12924 	if (val && btm_query_candidate_list(dut, conn, cmd) == 0)
12925 		return 0;
12926 
12927 	if (strcasecmp(prog, "TDLS") == 0)
12928 		return cmd_sta_set_rfeature_tdls(intf, dut, conn, cmd);
12929 
12930 	if (strcasecmp(prog, "VHT") == 0)
12931 		return cmd_sta_set_rfeature_vht(intf, dut, conn, cmd);
12932 
12933 	if (strcasecmp(prog, "HE") == 0)
12934 		return cmd_sta_set_rfeature_he(intf, dut, conn, cmd);
12935 
12936 	if (strcasecmp(prog, "MBO") == 0) {
12937 		val = get_param(cmd, "Cellular_Data_Cap");
12938 		if (val &&
12939 		    mbo_set_cellular_data_capa(dut, conn, intf, atoi(val)) == 0)
12940 			return 0;
12941 
12942 		val = get_param(cmd, "Ch_Pref");
12943 		if (val && mbo_set_non_pref_ch_list(dut, conn, intf, cmd) == 0)
12944 			return 0;
12945 
12946 		return 1;
12947 	}
12948 
12949 	if (strcasecmp(prog, "60GHz") == 0)
12950 		return cmd_sta_set_rfeature_60g(intf, dut, conn, cmd);
12951 
12952 	if (strcasecmp(prog, "WPA3") == 0)
12953 		return cmd_sta_set_rfeature_wpa3(intf, dut, conn, cmd);
12954 
12955 	send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported Prog");
12956 	return 0;
12957 }
12958 
12959 
cmd_sta_set_radio(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)12960 static enum sigma_cmd_result cmd_sta_set_radio(struct sigma_dut *dut,
12961 					       struct sigma_conn *conn,
12962 					       struct sigma_cmd *cmd)
12963 {
12964 	const char *intf = get_param(cmd, "Interface");
12965 	const char *mode = get_param(cmd, "Mode");
12966 	int res;
12967 
12968 	if (intf == NULL || mode == NULL)
12969 		return -1;
12970 
12971 	if (strcasecmp(mode, "On") == 0)
12972 		res = wpa_command(intf, "SET radio_disabled 0");
12973 	else if (strcasecmp(mode, "Off") == 0)
12974 		res = wpa_command(intf, "SET radio_disabled 1");
12975 	else
12976 		return -1;
12977 
12978 	if (res) {
12979 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to change "
12980 			  "radio mode");
12981 		return 0;
12982 	}
12983 
12984 	return 1;
12985 }
12986 
12987 
cmd_sta_set_pwrsave(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)12988 static enum sigma_cmd_result cmd_sta_set_pwrsave(struct sigma_dut *dut,
12989 						 struct sigma_conn *conn,
12990 						 struct sigma_cmd *cmd)
12991 {
12992 	const char *intf = get_param(cmd, "Interface");
12993 	const char *mode = get_param(cmd, "Mode");
12994 	const char *prog = get_param(cmd, "program");
12995 	const char *powersave = get_param(cmd, "powersave");
12996 	int res = 0;
12997 
12998 	if (intf == NULL)
12999 		return -1;
13000 
13001 	if (prog && strcasecmp(prog, "60GHz") == 0) {
13002 		/*
13003 		 * The CAPI mode parameter does not exist in 60G
13004 		 * unscheduled PS.
13005 		 */
13006 		if (powersave && strcasecmp(powersave, "unscheduled") == 0)
13007 			res = set_ps(intf, dut, 1);
13008 	} else if (prog && get_driver_type(dut) == DRIVER_WCN &&
13009 		   strcasecmp(prog, "HE") == 0) {
13010 		return cmd_sta_set_power_save_he(intf, dut, conn, cmd);
13011 	} else {
13012 		if (mode == NULL)
13013 			return -1;
13014 
13015 		if (strcasecmp(mode, "On") == 0)
13016 			res = set_ps(intf, dut, 1);
13017 		else if (strcasecmp(mode, "Off") == 0)
13018 			res = set_ps(intf, dut, 0);
13019 		else
13020 			return -1;
13021 	}
13022 
13023 	if (res) {
13024 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to change "
13025 			  "power save mode");
13026 		return 0;
13027 	}
13028 
13029 	return 1;
13030 }
13031 
13032 
cmd_sta_bssid_pool(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)13033 static enum sigma_cmd_result cmd_sta_bssid_pool(struct sigma_dut *dut,
13034 						struct sigma_conn *conn,
13035 						struct sigma_cmd *cmd)
13036 {
13037 	const char *intf = get_param(cmd, "Interface");
13038 	const char *val, *bssid;
13039 	int res;
13040 	char *buf;
13041 	size_t buf_len;
13042 
13043 	val = get_param(cmd, "BSSID_FILTER");
13044 	if (val == NULL)
13045 		return -1;
13046 
13047 	bssid = get_param(cmd, "BSSID_List");
13048 	if (atoi(val) == 0 || bssid == NULL) {
13049 		/* Disable BSSID filter */
13050 		if (wpa_command(intf, "SET bssid_filter ")) {
13051 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed "
13052 				  "to disable BSSID filter");
13053 			return 0;
13054 		}
13055 
13056 		return 1;
13057 	}
13058 
13059 	buf_len = 100 + strlen(bssid);
13060 	buf = malloc(buf_len);
13061 	if (buf == NULL)
13062 		return -1;
13063 
13064 	snprintf(buf, buf_len, "SET bssid_filter %s", bssid);
13065 	res = wpa_command(intf, buf);
13066 	free(buf);
13067 	if (res) {
13068 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to enable "
13069 			  "BSSID filter");
13070 		return 0;
13071 	}
13072 
13073 	return 1;
13074 }
13075 
13076 
cmd_sta_reset_parm(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)13077 static enum sigma_cmd_result cmd_sta_reset_parm(struct sigma_dut *dut,
13078 						struct sigma_conn *conn,
13079 						struct sigma_cmd *cmd)
13080 {
13081 	const char *intf = get_param(cmd, "Interface");
13082 	const char *val;
13083 
13084 	/* TODO: ARP */
13085 
13086 	val = get_param(cmd, "HS2_CACHE_PROFILE");
13087 	if (val && strcasecmp(val, "All") == 0)
13088 		hs2_clear_credentials(intf);
13089 
13090 	return 1;
13091 }
13092 
13093 
cmd_sta_get_key(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)13094 static enum sigma_cmd_result cmd_sta_get_key(struct sigma_dut *dut,
13095 					     struct sigma_conn *conn,
13096 					     struct sigma_cmd *cmd)
13097 {
13098 	const char *intf = get_param(cmd, "Interface");
13099 	const char *key_type = get_param(cmd, "KeyType");
13100 	char buf[100], resp[200];
13101 
13102 	if (key_type == NULL)
13103 		return -1;
13104 
13105 	if (strcasecmp(key_type, "GTK") == 0) {
13106 		if (wpa_command_resp(intf, "GET gtk", buf, sizeof(buf)) < 0 ||
13107 		    strncmp(buf, "FAIL", 4) == 0) {
13108 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
13109 				  "not fetch current GTK");
13110 			return 0;
13111 		}
13112 		snprintf(resp, sizeof(resp), "KeyValue,%s", buf);
13113 		send_resp(dut, conn, SIGMA_COMPLETE, resp);
13114 		return 0;
13115 	} else {
13116 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Unsupported "
13117 			  "KeyType");
13118 		return 0;
13119 	}
13120 
13121 	return 1;
13122 }
13123 
13124 
hs2_set_policy(struct sigma_dut * dut)13125 static int hs2_set_policy(struct sigma_dut *dut)
13126 {
13127 #ifdef ANDROID
13128 	system("ip rule del prio 23000");
13129 	if (system("ip rule add from all lookup main prio 23000") != 0) {
13130 		sigma_dut_print(dut, DUT_MSG_ERROR,
13131 				"Failed to run:ip rule add from all lookup main prio");
13132 		return -1;
13133 	}
13134 	if (system("ip route flush cache") != 0) {
13135 		sigma_dut_print(dut, DUT_MSG_ERROR,
13136 				"Failed to run ip route flush cache");
13137 		return -1;
13138 	}
13139 	return 1;
13140 #else /* ANDROID */
13141 	return 0;
13142 #endif /* ANDROID */
13143 }
13144 
13145 
cmd_sta_hs2_associate(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)13146 static enum sigma_cmd_result cmd_sta_hs2_associate(struct sigma_dut *dut,
13147 						   struct sigma_conn *conn,
13148 						   struct sigma_cmd *cmd)
13149 {
13150 	const char *intf = get_param(cmd, "Interface");
13151 	const char *val = get_param(cmd, "Ignore_blacklist");
13152 	const char *band = get_param(cmd, "Band");
13153 	struct wpa_ctrl *ctrl;
13154 	int res, r;
13155 	char bssid[20], ssid[40], resp[100], buf[100], blacklisted[100];
13156 	int tries = 0;
13157 	int ignore_blacklist = 0;
13158 	const char *events[] = {
13159 		"CTRL-EVENT-CONNECTED",
13160 		"INTERWORKING-BLACKLISTED",
13161 		"INTERWORKING-NO-MATCH",
13162 		NULL
13163 	};
13164 
13165 	start_sta_mode(dut);
13166 
13167 	if (band) {
13168 		if (strcmp(band, "2.4") == 0) {
13169 			wpa_command(intf, "SET setband 2G");
13170 		} else if (strcmp(band, "5") == 0) {
13171 			wpa_command(intf, "SET setband 5G");
13172 		} else {
13173 			send_resp(dut, conn, SIGMA_ERROR,
13174 				  "errorCode,Unsupported band");
13175 			return 0;
13176 		}
13177 	}
13178 
13179 	blacklisted[0] = '\0';
13180 	if (val && atoi(val))
13181 		ignore_blacklist = 1;
13182 
13183 try_again:
13184 	ctrl = open_wpa_mon(intf);
13185 	if (ctrl == NULL) {
13186 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
13187 				"wpa_supplicant monitor connection");
13188 		return -2;
13189 	}
13190 
13191 	tries++;
13192 	if (wpa_command(intf, "INTERWORKING_SELECT auto")) {
13193 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to start "
13194 			  "Interworking connection");
13195 		wpa_ctrl_detach(ctrl);
13196 		wpa_ctrl_close(ctrl);
13197 		return 0;
13198 	}
13199 
13200 	buf[0] = '\0';
13201 	while (1) {
13202 		char *pos;
13203 		res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
13204 		pos = strstr(buf, "INTERWORKING-BLACKLISTED");
13205 		if (!pos)
13206 			break;
13207 		pos += 25;
13208 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Found blacklisted AP: %s",
13209 				pos);
13210 		if (!blacklisted[0])
13211 			memcpy(blacklisted, pos, strlen(pos) + 1);
13212 	}
13213 
13214 	if (ignore_blacklist && blacklisted[0]) {
13215 		char *end;
13216 		end = strchr(blacklisted, ' ');
13217 		if (end)
13218 			*end = '\0';
13219 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Try to connect to a blacklisted network: %s",
13220 				blacklisted);
13221 		r = snprintf(buf, sizeof(buf), "INTERWORKING_CONNECT %s",
13222 			     blacklisted);
13223 		if (r < 0 || r >= sizeof(buf) || wpa_command(intf, buf)) {
13224 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to start Interworking connection to blacklisted network");
13225 			wpa_ctrl_detach(ctrl);
13226 			wpa_ctrl_close(ctrl);
13227 			return 0;
13228 		}
13229 		res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
13230 					buf, sizeof(buf));
13231 	}
13232 
13233 	wpa_ctrl_detach(ctrl);
13234 	wpa_ctrl_close(ctrl);
13235 
13236 	if (res < 0) {
13237 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
13238 			  "connect");
13239 		return 0;
13240 	}
13241 
13242 	if (strstr(buf, "INTERWORKING-NO-MATCH") ||
13243 	    strstr(buf, "INTERWORKING-BLACKLISTED")) {
13244 		if (tries < 2) {
13245 			sigma_dut_print(dut, DUT_MSG_INFO, "No match found - try again to verify no APs were missed in the scan");
13246 			goto try_again;
13247 		}
13248 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,No network with "
13249 			  "matching credentials found");
13250 		return 0;
13251 	}
13252 
13253 	if (get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0 ||
13254 	    get_wpa_status(intf, "ssid", ssid, sizeof(ssid)) < 0) {
13255 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
13256 			  "get current BSSID/SSID");
13257 		return 0;
13258 	}
13259 
13260 	snprintf(resp, sizeof(resp), "SSID,%s,BSSID,%s", ssid, bssid);
13261 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
13262 	hs2_set_policy(dut);
13263 	return 0;
13264 }
13265 
13266 
cmd_sta_hs2_venue_info(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)13267 static enum sigma_cmd_result cmd_sta_hs2_venue_info(struct sigma_dut *dut,
13268 						    struct sigma_conn *conn,
13269 						    struct sigma_cmd *cmd)
13270 {
13271 	const char *intf = get_param(cmd, "Interface");
13272 	const char *display = get_param(cmd, "Display");
13273 	struct wpa_ctrl *ctrl;
13274 	char buf[300], params[400], *pos;
13275 	char bssid[20];
13276 	int info_avail = 0;
13277 	unsigned int old_timeout;
13278 	int res;
13279 
13280 	if (get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0) {
13281 		send_resp(dut, conn, SIGMA_ERROR,
13282 			  "ErrorCode,Could not get current BSSID");
13283 		return 0;
13284 	}
13285 	ctrl = open_wpa_mon(intf);
13286 	if (!ctrl) {
13287 		sigma_dut_print(dut, DUT_MSG_ERROR,
13288 				"Failed to open wpa_supplicant monitor connection");
13289 		return -2;
13290 	}
13291 
13292 	snprintf(buf, sizeof(buf), "ANQP_GET %s 277", bssid);
13293 	wpa_command(intf, buf);
13294 
13295 	res = get_wpa_cli_event(dut, ctrl, "GAS-QUERY-DONE", buf, sizeof(buf));
13296 	if (res < 0) {
13297 		send_resp(dut, conn, SIGMA_ERROR,
13298 			  "ErrorCode,Could not complete GAS query");
13299 		goto fail;
13300 	}
13301 
13302 	old_timeout = dut->default_timeout;
13303 	dut->default_timeout = 2;
13304 	res = get_wpa_cli_event(dut, ctrl, "RX-VENUE-URL", buf, sizeof(buf));
13305 	dut->default_timeout = old_timeout;
13306 	if (res < 0)
13307 		goto done;
13308 	pos = strchr(buf, ' ');
13309 	if (!pos)
13310 		goto done;
13311 	pos++;
13312 	pos = strchr(pos, ' ');
13313 	if (!pos)
13314 		goto done;
13315 	pos++;
13316 	info_avail = 1;
13317 	snprintf(params, sizeof(params), "browser %s", pos);
13318 
13319 	if (display && strcasecmp(display, "Yes") == 0) {
13320 		pid_t pid;
13321 
13322 		pid = fork();
13323 		if (pid < 0) {
13324 			perror("fork");
13325 			return -1;
13326 		}
13327 
13328 		if (pid == 0) {
13329 			run_hs20_osu(dut, params);
13330 			exit(0);
13331 		}
13332 	}
13333 
13334 done:
13335 	snprintf(buf, sizeof(buf), "Info_available,%s",
13336 		 info_avail ? "Yes" : "No");
13337 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
13338 fail:
13339 	wpa_ctrl_detach(ctrl);
13340 	wpa_ctrl_close(ctrl);
13341 	return 0;
13342 }
13343 
13344 
sta_add_credential_uname_pwd(struct sigma_dut * dut,struct sigma_conn * conn,const char * ifname,struct sigma_cmd * cmd)13345 static int sta_add_credential_uname_pwd(struct sigma_dut *dut,
13346 					struct sigma_conn *conn,
13347 					const char *ifname,
13348 					struct sigma_cmd *cmd)
13349 {
13350 	const char *val;
13351 	int id;
13352 
13353 	id = add_cred(ifname);
13354 	if (id < 0)
13355 		return -2;
13356 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
13357 
13358 	val = get_param(cmd, "prefer");
13359 	if (val && atoi(val) > 0)
13360 		set_cred(ifname, id, "priority", "1");
13361 
13362 	val = get_param(cmd, "REALM");
13363 	if (val && set_cred_quoted(ifname, id, "realm", val) < 0) {
13364 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
13365 			  "realm");
13366 		return 0;
13367 	}
13368 
13369 	val = get_param(cmd, "HOME_FQDN");
13370 	if (val && set_cred_quoted(ifname, id, "domain", val) < 0) {
13371 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
13372 			  "home_fqdn");
13373 		return 0;
13374 	}
13375 
13376 	val = get_param(cmd, "Username");
13377 	if (val && set_cred_quoted(ifname, id, "username", val) < 0) {
13378 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
13379 			  "username");
13380 		return 0;
13381 	}
13382 
13383 	val = get_param(cmd, "Password");
13384 	if (val && set_cred_quoted(ifname, id, "password", val) < 0) {
13385 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
13386 			  "password");
13387 		return 0;
13388 	}
13389 
13390 	val = get_param(cmd, "ROOT_CA");
13391 	if (val) {
13392 		char fname[200];
13393 		snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
13394 #ifdef __linux__
13395 		if (!file_exists(fname)) {
13396 			char msg[300];
13397 			snprintf(msg, sizeof(msg), "ErrorCode,ROOT_CA "
13398 				 "file (%s) not found", fname);
13399 			send_resp(dut, conn, SIGMA_ERROR, msg);
13400 			return 0;
13401 		}
13402 #endif /* __linux__ */
13403 		if (set_cred_quoted(ifname, id, "ca_cert", fname) < 0) {
13404 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
13405 				  "not set root CA");
13406 			return 0;
13407 		}
13408 	}
13409 
13410 	return 1;
13411 }
13412 
13413 
update_devdetail_imsi(struct sigma_dut * dut,const char * imsi)13414 static int update_devdetail_imsi(struct sigma_dut *dut, const char *imsi)
13415 {
13416 	FILE *in, *out;
13417 	char buf[500];
13418 	int found = 0;
13419 
13420 	in = fopen("devdetail.xml", "r");
13421 	if (in == NULL)
13422 		return -1;
13423 	out = fopen("devdetail.xml.tmp", "w");
13424 	if (out == NULL) {
13425 		fclose(in);
13426 		return -1;
13427 	}
13428 
13429 	while (fgets(buf, sizeof(buf), in)) {
13430 		char *pos = strstr(buf, "<IMSI>");
13431 		if (pos) {
13432 			sigma_dut_print(dut, DUT_MSG_INFO, "Updated DevDetail IMSI to %s",
13433 					imsi);
13434 			pos += 6;
13435 			*pos = '\0';
13436 			fprintf(out, "%s%s</IMSI>\n", buf, imsi);
13437 			found++;
13438 		} else {
13439 			fprintf(out, "%s", buf);
13440 		}
13441 	}
13442 
13443 	fclose(out);
13444 	fclose(in);
13445 	if (found)
13446 		rename("devdetail.xml.tmp", "devdetail.xml");
13447 	else
13448 		unlink("devdetail.xml.tmp");
13449 
13450 	return 0;
13451 }
13452 
13453 
sta_add_credential_sim(struct sigma_dut * dut,struct sigma_conn * conn,const char * ifname,struct sigma_cmd * cmd)13454 static int sta_add_credential_sim(struct sigma_dut *dut,
13455 				  struct sigma_conn *conn,
13456 				  const char *ifname, struct sigma_cmd *cmd)
13457 {
13458 	const char *val, *imsi = NULL;
13459 	int id;
13460 	char buf[200];
13461 	int res;
13462 	const char *pos;
13463 	size_t mnc_len;
13464 	char plmn_mcc[4];
13465 	char plmn_mnc[4];
13466 
13467 	id = add_cred(ifname);
13468 	if (id < 0)
13469 		return -2;
13470 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
13471 
13472 	val = get_param(cmd, "prefer");
13473 	if (val && atoi(val) > 0)
13474 		set_cred(ifname, id, "priority", "1");
13475 
13476 	val = get_param(cmd, "PLMN_MCC");
13477 	if (val == NULL) {
13478 		send_resp(dut, conn, SIGMA_ERROR,
13479 			  "errorCode,Missing PLMN_MCC");
13480 		return 0;
13481 	}
13482 	if (strlen(val) != 3) {
13483 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Invalid MCC");
13484 		return 0;
13485 	}
13486 	snprintf(plmn_mcc, sizeof(plmn_mcc), "%s", val);
13487 
13488 	val = get_param(cmd, "PLMN_MNC");
13489 	if (val == NULL) {
13490 		send_resp(dut, conn, SIGMA_ERROR,
13491 			  "errorCode,Missing PLMN_MNC");
13492 		return 0;
13493 	}
13494 	if (strlen(val) != 2 && strlen(val) != 3) {
13495 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Invalid MNC");
13496 		return 0;
13497 	}
13498 	snprintf(plmn_mnc, sizeof(plmn_mnc), "%s", val);
13499 
13500 	val = get_param(cmd, "IMSI");
13501 	if (val == NULL) {
13502 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Missing SIM "
13503 			  "IMSI");
13504 		return 0;
13505 	}
13506 
13507 	imsi = pos = val;
13508 
13509 	if (strncmp(plmn_mcc, pos, 3) != 0) {
13510 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,MCC mismatch");
13511 		return 0;
13512 	}
13513 	pos += 3;
13514 
13515 	mnc_len = strlen(plmn_mnc);
13516 	if (mnc_len < 2) {
13517 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,MNC not set");
13518 		return 0;
13519 	}
13520 
13521 	if (strncmp(plmn_mnc, pos, mnc_len) != 0) {
13522 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,MNC mismatch");
13523 		return 0;
13524 	}
13525 	pos += mnc_len;
13526 
13527 	res = snprintf(buf, sizeof(buf), "%s%s-%s",plmn_mcc, plmn_mnc, pos);
13528 	if (res < 0 || res >= (int) sizeof(buf))
13529 		return -1;
13530 	if (set_cred_quoted(ifname, id, "imsi", buf) < 0) {
13531 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
13532 			  "not set IMSI");
13533 		return 0;
13534 	}
13535 
13536 	val = get_param(cmd, "Password");
13537 	if (val && set_cred_quoted(ifname, id, "milenage", val) < 0) {
13538 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
13539 			  "not set password");
13540 		return 0;
13541 	}
13542 
13543 	if (dut->program == PROGRAM_HS2_R2 || dut->program == PROGRAM_HS2_R3) {
13544 		/*
13545 		 * Set provisioning_sp for the test cases where SIM/USIM
13546 		 * provisioning is used.
13547 		 */
13548 		if (val && set_cred_quoted(ifname, id, "provisioning_sp",
13549 					   "wi-fi.org") < 0) {
13550 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
13551 				  "not set provisioning_sp");
13552 			return 0;
13553 		}
13554 
13555 		update_devdetail_imsi(dut, imsi);
13556 	}
13557 
13558 	return 1;
13559 }
13560 
13561 
sta_add_credential_cert(struct sigma_dut * dut,struct sigma_conn * conn,const char * ifname,struct sigma_cmd * cmd)13562 static int sta_add_credential_cert(struct sigma_dut *dut,
13563 				   struct sigma_conn *conn,
13564 				   const char *ifname,
13565 				   struct sigma_cmd *cmd)
13566 {
13567 	const char *val;
13568 	int id;
13569 
13570 	id = add_cred(ifname);
13571 	if (id < 0)
13572 		return -2;
13573 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Adding credential %d", id);
13574 
13575 	val = get_param(cmd, "prefer");
13576 	if (val && atoi(val) > 0)
13577 		set_cred(ifname, id, "priority", "1");
13578 
13579 	val = get_param(cmd, "REALM");
13580 	if (val && set_cred_quoted(ifname, id, "realm", val) < 0) {
13581 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
13582 			  "realm");
13583 		return 0;
13584 	}
13585 
13586 	val = get_param(cmd, "HOME_FQDN");
13587 	if (val && set_cred_quoted(ifname, id, "domain", val) < 0) {
13588 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
13589 			  "home_fqdn");
13590 		return 0;
13591 	}
13592 
13593 	val = get_param(cmd, "Username");
13594 	if (val && set_cred_quoted(ifname, id, "username", val) < 0) {
13595 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not set "
13596 			  "username");
13597 		return 0;
13598 	}
13599 
13600 	val = get_param(cmd, "clientCertificate");
13601 	if (val) {
13602 		char fname[200];
13603 		snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
13604 #ifdef __linux__
13605 		if (!file_exists(fname)) {
13606 			char msg[300];
13607 			snprintf(msg, sizeof(msg),
13608 				 "ErrorCode,clientCertificate "
13609 				 "file (%s) not found", fname);
13610 			send_resp(dut, conn, SIGMA_ERROR, msg);
13611 			return 0;
13612 		}
13613 #endif /* __linux__ */
13614 		if (set_cred_quoted(ifname, id, "client_cert", fname) < 0) {
13615 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
13616 				  "not set client_cert");
13617 			return 0;
13618 		}
13619 		if (set_cred_quoted(ifname, id, "private_key", fname) < 0) {
13620 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
13621 				  "not set private_key");
13622 			return 0;
13623 		}
13624 	}
13625 
13626 	val = get_param(cmd, "ROOT_CA");
13627 	if (val) {
13628 		char fname[200];
13629 		snprintf(fname, sizeof(fname), "%s/%s", sigma_cert_path, val);
13630 #ifdef __linux__
13631 		if (!file_exists(fname)) {
13632 			char msg[300];
13633 			snprintf(msg, sizeof(msg), "ErrorCode,ROOT_CA "
13634 				 "file (%s) not found", fname);
13635 			send_resp(dut, conn, SIGMA_ERROR, msg);
13636 			return 0;
13637 		}
13638 #endif /* __linux__ */
13639 		if (set_cred_quoted(ifname, id, "ca_cert", fname) < 0) {
13640 			send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could "
13641 				  "not set root CA");
13642 			return 0;
13643 		}
13644 	}
13645 
13646 	return 1;
13647 }
13648 
13649 
cmd_sta_add_credential(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)13650 static enum sigma_cmd_result cmd_sta_add_credential(struct sigma_dut *dut,
13651 						    struct sigma_conn *conn,
13652 						    struct sigma_cmd *cmd)
13653 {
13654 	const char *intf = get_param(cmd, "Interface");
13655 	const char *type;
13656 
13657 	start_sta_mode(dut);
13658 
13659 	type = get_param(cmd, "Type");
13660 	if (!type)
13661 		return -1;
13662 
13663 	if (strcasecmp(type, "uname_pwd") == 0)
13664 		return sta_add_credential_uname_pwd(dut, conn, intf, cmd);
13665 
13666 	if (strcasecmp(type, "sim") == 0)
13667 		return sta_add_credential_sim(dut, conn, intf, cmd);
13668 
13669 	if (strcasecmp(type, "cert") == 0)
13670 		return sta_add_credential_cert(dut, conn, intf, cmd);
13671 
13672 	send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported credential "
13673 		  "type");
13674 	return 0;
13675 }
13676 
13677 
cmd_sta_scan(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)13678 static enum sigma_cmd_result cmd_sta_scan(struct sigma_dut *dut,
13679 					  struct sigma_conn *conn,
13680 					  struct sigma_cmd *cmd)
13681 {
13682 	const char *intf = get_param(cmd, "Interface");
13683 	const char *val, *bssid, *ssid, *scan_freq, *short_ssid;
13684 	char buf[4096], scan_res[20];
13685 	char ssid_hex[65];
13686 	int wildcard_ssid = 0;
13687 	int res;
13688 	enum sigma_cmd_result status;
13689 	struct wpa_ctrl *ctrl = NULL;
13690 
13691 	start_sta_mode(dut);
13692 
13693 	val = get_param(cmd, "GetParameter");
13694 	if (val && strcmp(val, "SSID_BSSID") == 0) {
13695 		if (get_wpa_ssid_bssid(dut, get_station_ifname(dut),
13696 				       buf, sizeof(buf)) < 0) {
13697 			sigma_dut_print(dut, DUT_MSG_ERROR,
13698 					"Could not get ssid bssid");
13699 			return ERROR_SEND_STATUS;
13700 		}
13701 
13702 		sigma_dut_print(dut, DUT_MSG_INFO, "%s", buf);
13703 		send_resp(dut, conn, SIGMA_COMPLETE, buf);
13704 		return STATUS_SENT;
13705 	}
13706 
13707 	val = get_param(cmd, "HESSID");
13708 	if (val) {
13709 		res = snprintf(buf, sizeof(buf), "SET hessid %s", val);
13710 		if (res < 0 || res >= (int) sizeof(buf))
13711 			return -1;
13712 		wpa_command(intf, buf);
13713 	}
13714 
13715 	val = get_param(cmd, "ACCS_NET_TYPE");
13716 	if (val) {
13717 		res = snprintf(buf, sizeof(buf), "SET access_network_type %s",
13718 			       val);
13719 		if (res < 0 || res >= (int) sizeof(buf))
13720 			return -1;
13721 		wpa_command(intf, buf);
13722 	}
13723 
13724 	bssid = get_param(cmd, "Bssid");
13725 	ssid = get_param(cmd, "Ssid");
13726 
13727 	if (ssid && strcasecmp(ssid, "ZeroLength") == 0 &&
13728 	    dut->device_type == STA_testbed) {
13729 		ssid = NULL;
13730 		wildcard_ssid = 1;
13731 	}
13732 
13733 	if (ssid) {
13734 		if (2 * strlen(ssid) >= sizeof(ssid_hex)) {
13735 			send_resp(dut, conn, SIGMA_ERROR,
13736 				  "ErrorCode,Too long SSID");
13737 			return 0;
13738 		}
13739 		ascii2hexstr(ssid, ssid_hex);
13740 	}
13741 
13742 	short_ssid = get_param(cmd, "ShortSSID");
13743 	if (short_ssid) {
13744 		uint32_t short_ssid_hex;
13745 
13746 		short_ssid_hex = strtoul(short_ssid, NULL, 16);
13747 		short_ssid_hex = ((short_ssid_hex & 0xFF) << 24) |
13748 			(((short_ssid_hex >> 8) & 0xFF) << 16) |
13749 			(((short_ssid_hex >> 16) & 0xFF) << 8) |
13750 			((short_ssid_hex >> 24) & 0xFF);
13751 
13752 		res = snprintf(buf, sizeof(buf),
13753 			       "VENDOR_ELEM_ADD 14 ff053a%08x",
13754 			       short_ssid_hex);
13755 		if (res < 0 || res >= (int) sizeof(buf) ||
13756 		    wpa_command(intf, buf)) {
13757 			send_resp(dut, conn, SIGMA_ERROR,
13758 				  "errorCode,Failed to add short SSID");
13759 			return STATUS_SENT_ERROR;
13760 		}
13761 	}
13762 
13763 	scan_freq = get_param(cmd, "ChnlFreq");
13764 	if (scan_freq) {
13765 		if (strcasecmp(scan_freq, "2G") == 0)
13766 			scan_freq = "2412-2462";
13767 		else if (strcasecmp(scan_freq, "5G") == 0)
13768 			scan_freq = "5180-5925";
13769 	}
13770 
13771 	val = get_param(cmd, "WaitCompletion");
13772 	if (val && atoi(val) == 1) {
13773 		ctrl = open_wpa_mon(intf);
13774 		if (!ctrl) {
13775 			send_resp(dut, conn, SIGMA_ERROR,
13776 				  "errorCode,Failed to open monitor socket");
13777 			return STATUS_SENT_ERROR;
13778 		}
13779 	}
13780 
13781 	res = snprintf(buf, sizeof(buf), "SCAN%s%s%s%s%s%s%s",
13782 			bssid ? " bssid=": "",
13783 			bssid ? bssid : "",
13784 			ssid ? " ssid " : "",
13785 			ssid ? ssid_hex : "",
13786 			wildcard_ssid ? " wildcard_ssid=1" : "",
13787 			scan_freq ? " freq=" : "",
13788 			scan_freq ? scan_freq : "");
13789 	if (res < 0 || res >= (int) sizeof(buf)) {
13790 		send_resp(dut, conn, SIGMA_ERROR,
13791 			  "errorCode,Could not build scan command");
13792 		status = STATUS_SENT_ERROR;
13793 		goto remove_s_ssid;
13794 	}
13795 
13796 	res = wpa_command_resp(intf, buf, scan_res, sizeof(scan_res));
13797 	if (strncmp(scan_res, "FAIL-BUSY", 9) == 0) {
13798 		sigma_dut_print(dut, DUT_MSG_DEBUG,
13799 				"Scan request rejected with busy status, abort ongoing scan and try again");
13800 		wpa_command(intf, "ABORT_SCAN");
13801 		res = wpa_command(intf, buf);
13802 	}
13803 
13804 	if (res < 0) {
13805 		send_resp(dut, conn, SIGMA_ERROR, "errorCode,Could not start "
13806 			  "scan");
13807 		status = STATUS_SENT_ERROR;
13808 	} else {
13809 		status = SUCCESS_SEND_STATUS;
13810 	}
13811 
13812 remove_s_ssid:
13813 	if (short_ssid && wpa_command(intf, "VENDOR_ELEM_REMOVE 14 *"))
13814 		sigma_dut_print(dut, DUT_MSG_ERROR,
13815 				"Failed to delete vendor element");
13816 
13817 	if (ctrl) {
13818 		if (status == SUCCESS_SEND_STATUS) {
13819 			res = get_wpa_cli_event(dut, ctrl,
13820 						"CTRL-EVENT-SCAN-RESULTS",
13821 						buf, sizeof(buf));
13822 			if (res < 0) {
13823 				send_resp(dut, conn, SIGMA_ERROR,
13824 					  "ErrorCode,scan did not complete");
13825 				status = STATUS_SENT_ERROR;
13826 			}
13827 		}
13828 
13829 		wpa_ctrl_detach(ctrl);
13830 		wpa_ctrl_close(ctrl);
13831 	}
13832 
13833 	return status;
13834 }
13835 
13836 
cmd_sta_scan_bss(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)13837 static enum sigma_cmd_result cmd_sta_scan_bss(struct sigma_dut *dut,
13838 					      struct sigma_conn *conn,
13839 					      struct sigma_cmd *cmd)
13840 {
13841 	const char *intf = get_param(cmd, "Interface");
13842 	const char *bssid;
13843 	char buf[4096], *pos;
13844 	int freq, chan;
13845 	char *ssid;
13846 	char resp[100];
13847 	int res;
13848 	struct wpa_ctrl *ctrl;
13849 
13850 	bssid = get_param(cmd, "BSSID");
13851 	if (!bssid) {
13852 		send_resp(dut, conn, SIGMA_INVALID,
13853 			  "errorCode,BSSID argument is missing");
13854 		return 0;
13855 	}
13856 
13857 	ctrl = open_wpa_mon(intf);
13858 	if (!ctrl) {
13859 		sigma_dut_print(dut, DUT_MSG_ERROR,
13860 				"Failed to open wpa_supplicant monitor connection");
13861 		return -1;
13862 	}
13863 
13864 	if (wpa_command(intf, "SCAN TYPE=ONLY")) {
13865 		send_resp(dut, conn, SIGMA_ERROR,
13866 			  "errorCode,Could not start scan");
13867 		wpa_ctrl_detach(ctrl);
13868 		wpa_ctrl_close(ctrl);
13869 		return 0;
13870 	}
13871 
13872 	res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-SCAN-RESULTS",
13873 				buf, sizeof(buf));
13874 
13875 	wpa_ctrl_detach(ctrl);
13876 	wpa_ctrl_close(ctrl);
13877 
13878 	if (res < 0) {
13879 		send_resp(dut, conn, SIGMA_ERROR,
13880 			  "errorCode,Scan did not complete");
13881 		return 0;
13882 	}
13883 
13884 	snprintf(buf, sizeof(buf), "BSS %s", bssid);
13885 	if (wpa_command_resp(intf, buf, buf, sizeof(buf)) < 0 ||
13886 	    strncmp(buf, "id=", 3) != 0) {
13887 		send_resp(dut, conn, SIGMA_ERROR,
13888 			  "errorCode,Specified BSSID not found");
13889 		return 0;
13890 	}
13891 
13892 	pos = strstr(buf, "\nfreq=");
13893 	if (!pos) {
13894 		send_resp(dut, conn, SIGMA_ERROR,
13895 			  "errorCode,Channel not found");
13896 		return 0;
13897 	}
13898 	freq = atoi(pos + 6);
13899 	chan = freq_to_channel(freq);
13900 
13901 	pos = strstr(buf, "\nssid=");
13902 	if (!pos) {
13903 		send_resp(dut, conn, SIGMA_ERROR,
13904 			  "errorCode,SSID not found");
13905 		return 0;
13906 	}
13907 	ssid = pos + 6;
13908 	pos = strchr(ssid, '\n');
13909 	if (pos)
13910 		*pos = '\0';
13911 	snprintf(resp, sizeof(resp), "ssid,%s,bsschannel,%d", ssid, chan);
13912 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
13913 	return 0;
13914 }
13915 
13916 
cmd_sta_set_systime(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)13917 static enum sigma_cmd_result cmd_sta_set_systime(struct sigma_dut *dut,
13918 						 struct sigma_conn *conn,
13919 						 struct sigma_cmd *cmd)
13920 {
13921 #ifdef __linux__
13922 	struct timeval tv;
13923 	struct tm tm;
13924 	time_t t;
13925 	const char *val;
13926 	int v;
13927 
13928 	wpa_command(get_station_ifname(dut), "PMKSA_FLUSH");
13929 
13930 	memset(&tm, 0, sizeof(tm));
13931 	val = get_param(cmd, "seconds");
13932 	if (val)
13933 		tm.tm_sec = atoi(val);
13934 	val = get_param(cmd, "minutes");
13935 	if (val)
13936 		tm.tm_min = atoi(val);
13937 	val = get_param(cmd, "hours");
13938 	if (val)
13939 		tm.tm_hour = atoi(val);
13940 	val = get_param(cmd, "date");
13941 	if (val)
13942 		tm.tm_mday = atoi(val);
13943 	val = get_param(cmd, "month");
13944 	if (val) {
13945 		v = atoi(val);
13946 		if (v < 1 || v > 12) {
13947 			send_resp(dut, conn, SIGMA_INVALID,
13948 				  "errorCode,Invalid month");
13949 			return 0;
13950 		}
13951 		tm.tm_mon = v - 1;
13952 	}
13953 	val = get_param(cmd, "year");
13954 	if (val) {
13955 		int year = atoi(val);
13956 #ifdef ANDROID
13957 		if (year > 2035)
13958 			year = 2035; /* years beyond 2035 not supported */
13959 #endif /* ANDROID */
13960 		tm.tm_year = year - 1900;
13961 	}
13962 	t = mktime(&tm);
13963 	if (t == (time_t) -1) {
13964 		send_resp(dut, conn, SIGMA_ERROR,
13965 			  "errorCode,Invalid date or time");
13966 		return 0;
13967 	}
13968 
13969 	memset(&tv, 0, sizeof(tv));
13970 	tv.tv_sec = t;
13971 
13972 	if (settimeofday(&tv, NULL) < 0) {
13973 		sigma_dut_print(dut, DUT_MSG_INFO, "settimeofday failed: %s",
13974 				strerror(errno));
13975 		send_resp(dut, conn, SIGMA_ERROR,
13976 			  "errorCode,Failed to set time");
13977 		return 0;
13978 	}
13979 
13980 	return 1;
13981 #endif /* __linux__ */
13982 
13983 	return -1;
13984 }
13985 
13986 
cmd_sta_osu(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)13987 static enum sigma_cmd_result cmd_sta_osu(struct sigma_dut *dut,
13988 					 struct sigma_conn *conn,
13989 					 struct sigma_cmd *cmd)
13990 {
13991 	const char *intf = get_param(cmd, "Interface");
13992 	const char *name, *osu_ssid, *val;
13993 	int prod_ess_assoc = 1;
13994 	char buf[300], bssid[100], ssid[100];
13995 	int res;
13996 	struct wpa_ctrl *ctrl;
13997 
13998 	name = get_param(cmd, "osuFriendlyName");
13999 	osu_ssid = get_param(cmd, "osu_ssid");
14000 
14001 	val = get_param(cmd, "ProdESSAssoc");
14002 	if (val)
14003 		prod_ess_assoc = atoi(val);
14004 
14005 	kill_dhcp_client(dut, intf);
14006 	if (start_dhcp_client(dut, intf) < 0)
14007 		return -2;
14008 
14009 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Trigger OSU");
14010 	mkdir("Logs", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
14011 	res = snprintf(buf, sizeof(buf),
14012 		       "%s %s%s%s %s%s%s signup osu-ca.pem",
14013 		       prod_ess_assoc ? "" : "-N",
14014 		       name ? "-O'" : "", name ? name : "",
14015 		       name ? "'" : "",
14016 		       osu_ssid ? "-o'" : "", osu_ssid ? osu_ssid : "",
14017 		       osu_ssid ? "'" : "");
14018 
14019 	hs2_set_policy(dut);
14020 	if (run_hs20_osu(dut, buf) < 0) {
14021 		FILE *f;
14022 
14023 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to complete OSU");
14024 
14025 		f = fopen("hs20-osu-client.res", "r");
14026 		if (f) {
14027 			char resp[400], res[300], *pos;
14028 			if (!fgets(res, sizeof(res), f))
14029 				res[0] = '\0';
14030 			pos = strchr(res, '\n');
14031 			if (pos)
14032 				*pos = '\0';
14033 			fclose(f);
14034 			sigma_dut_summary(dut, "hs20-osu-client provisioning failed: %s",
14035 					  res);
14036 			snprintf(resp, sizeof(resp), "notify-send '%s'", res);
14037 			if (system(resp) != 0) {
14038 			}
14039 			snprintf(resp, sizeof(resp),
14040 				 "SSID,,BSSID,,failureReason,%s", res);
14041 			send_resp(dut, conn, SIGMA_COMPLETE, resp);
14042 			return 0;
14043 		}
14044 
14045 		send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
14046 		return 0;
14047 	}
14048 
14049 	if (!prod_ess_assoc)
14050 		goto report;
14051 
14052 	ctrl = open_wpa_mon(intf);
14053 	if (ctrl == NULL) {
14054 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
14055 				"wpa_supplicant monitor connection");
14056 		return -1;
14057 	}
14058 
14059 	res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-CONNECTED",
14060 				buf, sizeof(buf));
14061 
14062 	wpa_ctrl_detach(ctrl);
14063 	wpa_ctrl_close(ctrl);
14064 
14065 	if (res < 0) {
14066 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to connect to "
14067 				"network after OSU");
14068 		send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
14069 		return 0;
14070 	}
14071 
14072 report:
14073 	if (get_wpa_status(intf, "bssid", bssid, sizeof(bssid)) < 0 ||
14074 	    get_wpa_status(intf, "ssid", ssid, sizeof(ssid)) < 0) {
14075 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get BSSID/SSID");
14076 		send_resp(dut, conn, SIGMA_COMPLETE, "SSID,,BSSID,");
14077 		return 0;
14078 	}
14079 
14080 	snprintf(buf, sizeof(buf), "SSID,%s,BSSID,%s", ssid, bssid);
14081 	send_resp(dut, conn, SIGMA_COMPLETE, buf);
14082 	return 0;
14083 }
14084 
14085 
cmd_sta_policy_update(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)14086 static enum sigma_cmd_result cmd_sta_policy_update(struct sigma_dut *dut,
14087 						   struct sigma_conn *conn,
14088 						   struct sigma_cmd *cmd)
14089 {
14090 	const char *val;
14091 	int timeout = 120;
14092 
14093 	val = get_param(cmd, "PolicyUpdate");
14094 	if (val == NULL || atoi(val) == 0)
14095 		return 1; /* No operation requested */
14096 
14097 	val = get_param(cmd, "Timeout");
14098 	if (val)
14099 		timeout = atoi(val);
14100 
14101 	if (timeout) {
14102 		/* TODO: time out the command and return
14103 		 * PolicyUpdateStatus,TIMEOUT if needed. */
14104 	}
14105 
14106 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Trigger policy update");
14107 	mkdir("Logs", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
14108 	if (run_hs20_osu(dut, "pol_upd fqdn=wi-fi.org") < 0) {
14109 		send_resp(dut, conn, SIGMA_COMPLETE, "PolicyUpdateStatus,FAIL");
14110 		return 0;
14111 	}
14112 
14113 	send_resp(dut, conn, SIGMA_COMPLETE, "PolicyUpdateStatus,SUCCESS");
14114 	return 0;
14115 }
14116 
14117 
cmd_sta_er_config(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)14118 static enum sigma_cmd_result cmd_sta_er_config(struct sigma_dut *dut,
14119 					       struct sigma_conn *conn,
14120 					       struct sigma_cmd *cmd)
14121 {
14122 	struct wpa_ctrl *ctrl;
14123 	const char *intf = get_param(cmd, "Interface");
14124 	const char *bssid = get_param(cmd, "Bssid");
14125 	const char *ssid = get_param(cmd, "SSID");
14126 	const char *security = get_param(cmd, "Security");
14127 	const char *passphrase = get_param(cmd, "Passphrase");
14128 	const char *pin = get_param(cmd, "PIN");
14129 	char buf[1000];
14130 	char ssid_hex[200], passphrase_hex[200];
14131 	const char *keymgmt, *cipher;
14132 
14133 	if (intf == NULL)
14134 		intf = get_main_ifname(dut);
14135 
14136 	if (!bssid) {
14137 		send_resp(dut, conn, SIGMA_ERROR,
14138 			  "ErrorCode,Missing Bssid argument");
14139 		return 0;
14140 	}
14141 
14142 	if (!ssid) {
14143 		send_resp(dut, conn, SIGMA_ERROR,
14144 			  "ErrorCode,Missing SSID argument");
14145 		return 0;
14146 	}
14147 
14148 	if (!security) {
14149 		send_resp(dut, conn, SIGMA_ERROR,
14150 			  "ErrorCode,Missing Security argument");
14151 		return 0;
14152 	}
14153 
14154 	if (!passphrase) {
14155 		send_resp(dut, conn, SIGMA_ERROR,
14156 			  "ErrorCode,Missing Passphrase argument");
14157 		return 0;
14158 	}
14159 
14160 	if (!pin) {
14161 		send_resp(dut, conn, SIGMA_ERROR,
14162 			  "ErrorCode,Missing PIN argument");
14163 		return 0;
14164 	}
14165 
14166 	if (2 * strlen(ssid) >= sizeof(ssid_hex) ||
14167 	    2 * strlen(passphrase) >= sizeof(passphrase_hex)) {
14168 		send_resp(dut, conn, SIGMA_ERROR,
14169 			  "ErrorCode,Too long SSID/passphrase");
14170 		return 0;
14171 	}
14172 
14173 	ctrl = open_wpa_mon(intf);
14174 	if (ctrl == NULL) {
14175 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
14176 				"wpa_supplicant monitor connection");
14177 		return -2;
14178 	}
14179 
14180 	if (strcasecmp(security, "wpa2-psk") == 0) {
14181 		keymgmt = "WPA2PSK";
14182 		cipher = "CCMP";
14183 	} else {
14184 		wpa_ctrl_detach(ctrl);
14185 		wpa_ctrl_close(ctrl);
14186 		send_resp(dut, conn, SIGMA_ERROR,
14187 			  "ErrorCode,Unsupported Security value");
14188 		return 0;
14189 	}
14190 
14191 	ascii2hexstr(ssid, ssid_hex);
14192 	ascii2hexstr(passphrase, passphrase_hex);
14193 	snprintf(buf, sizeof(buf), "WPS_REG %s %s %s %s %s %s",
14194 		 bssid, pin, ssid_hex, keymgmt, cipher, passphrase_hex);
14195 
14196 	if (wpa_command(intf, buf) < 0) {
14197 		wpa_ctrl_detach(ctrl);
14198 		wpa_ctrl_close(ctrl);
14199 		send_resp(dut, conn, SIGMA_ERROR,
14200 			  "ErrorCode,Failed to start registrar");
14201 		return 0;
14202 	}
14203 
14204 	snprintf(dut->er_oper_bssid, sizeof(dut->er_oper_bssid), "%s", bssid);
14205 	dut->er_oper_performed = 1;
14206 
14207 	return wps_connection_event(dut, conn, ctrl, intf, 0);
14208 }
14209 
14210 
14211 static enum sigma_cmd_result
cmd_sta_wps_connect_pw_token(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)14212 cmd_sta_wps_connect_pw_token(struct sigma_dut *dut, struct sigma_conn *conn,
14213 			     struct sigma_cmd *cmd)
14214 {
14215 	struct wpa_ctrl *ctrl;
14216 	const char *intf = get_param(cmd, "Interface");
14217 	const char *bssid = get_param(cmd, "Bssid");
14218 	char buf[100];
14219 
14220 	if (!bssid) {
14221 		send_resp(dut, conn, SIGMA_ERROR,
14222 			  "ErrorCode,Missing Bssid argument");
14223 		return 0;
14224 	}
14225 
14226 	ctrl = open_wpa_mon(intf);
14227 	if (ctrl == NULL) {
14228 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
14229 				"wpa_supplicant monitor connection");
14230 		return -2;
14231 	}
14232 
14233 	snprintf(buf, sizeof(buf), "WPS_NFC %s", bssid);
14234 
14235 	if (wpa_command(intf, buf) < 0) {
14236 		wpa_ctrl_detach(ctrl);
14237 		wpa_ctrl_close(ctrl);
14238 		send_resp(dut, conn, SIGMA_ERROR,
14239 			  "ErrorCode,Failed to start registrar");
14240 		return 0;
14241 	}
14242 
14243 	return wps_connection_event(dut, conn, ctrl, intf, 0);
14244 }
14245 
14246 
cmd_start_wps_registration(struct sigma_dut * dut,struct sigma_conn * conn,struct sigma_cmd * cmd)14247 static enum sigma_cmd_result cmd_start_wps_registration(struct sigma_dut *dut,
14248 							struct sigma_conn *conn,
14249 							struct sigma_cmd *cmd)
14250 {
14251 	struct wpa_ctrl *ctrl;
14252 	const char *intf = get_param(cmd, "Interface");
14253 	const char *network_mode = get_param(cmd, "network_mode");
14254 	const char *config_method = get_param(cmd, "WPSConfigMethod");
14255 	const char *role;
14256 	int res;
14257 	char buf[256];
14258 	const char *events[] = {
14259 		"CTRL-EVENT-CONNECTED",
14260 		"WPS-OVERLAP-DETECTED",
14261 		"WPS-TIMEOUT",
14262 		"WPS-FAIL",
14263 		NULL
14264 	};
14265 	int id = 0;
14266 
14267 	/* 60G WPS tests do not pass Interface parameter */
14268 	if (!intf)
14269 		intf = get_main_ifname(dut);
14270 
14271 	if (dut->mode == SIGMA_MODE_AP)
14272 		return ap_wps_registration(dut, conn, cmd);
14273 
14274 	if (config_method) {
14275 		/* WFA_CS_WPS_PIN_KEYPAD mode is set when using the
14276 		 * sta_wps_enter_pin before calling start_wps_registration. */
14277 		if (strcasecmp(config_method, "PBC") == 0)
14278 			dut->wps_method = WFA_CS_WPS_PBC;
14279 	}
14280 	if (dut->wps_method == WFA_CS_WPS_NOT_READY) {
14281 		send_resp(dut, conn, SIGMA_ERROR,
14282 			  "ErrorCode,WPS parameters not yet set");
14283 		return STATUS_SENT;
14284 	}
14285 
14286 	/* Make sure WPS is enabled (also for STA mode) */
14287 	dut->wps_disable = 0;
14288 
14289 	if (dut->band == WPS_BAND_60G && network_mode &&
14290 	    strcasecmp(network_mode, "PBSS") == 0) {
14291 		sigma_dut_print(dut, DUT_MSG_DEBUG,
14292 				"Set PBSS network mode, network id %d", id);
14293 		if (set_network(get_station_ifname(dut), id, "pbss", "1") < 0)
14294 			return -2;
14295 	}
14296 
14297 	if (dut->force_rsn_ie) {
14298 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Force RSN_IE: %d",
14299 				dut->force_rsn_ie);
14300 		if (sta_60g_force_rsn_ie(dut, dut->force_rsn_ie) < 0) {
14301 			sigma_dut_print(dut, DUT_MSG_INFO,
14302 					"Failed to force RSN_IE");
14303 			return ERROR_SEND_STATUS;
14304 		}
14305 	}
14306 
14307 	ctrl = open_wpa_mon(intf);
14308 	if (!ctrl) {
14309 		sigma_dut_print(dut, DUT_MSG_ERROR,
14310 				"Failed to open wpa_supplicant monitor connection");
14311 		return -2;
14312 	}
14313 
14314 	role = get_param(cmd, "WpsRole");
14315 	if (!role) {
14316 		send_resp(dut, conn, SIGMA_INVALID,
14317 			  "ErrorCode,WpsRole not provided");
14318 		goto fail;
14319 	}
14320 
14321 	if (strcasecmp(role, "Enrollee") != 0) {
14322 		/* Registrar role for STA not supported */
14323 		send_resp(dut, conn, SIGMA_ERROR,
14324 			  "ErrorCode,Unsupported WpsRole value");
14325 		goto fail;
14326 	}
14327 
14328 	if (is_60g_sigma_dut(dut)) {
14329 		if (dut->wps_method == WFA_CS_WPS_PBC)
14330 			snprintf(buf, sizeof(buf), "WPS_PBC");
14331 		else /* WFA_CS_WPS_PIN_KEYPAD */
14332 			snprintf(buf, sizeof(buf), "WPS_PIN any %s",
14333 				 dut->wps_pin);
14334 		if (wpa_command(intf, buf) < 0) {
14335 			send_resp(dut, conn, SIGMA_ERROR,
14336 				  "ErrorCode,Failed to start WPS");
14337 			goto fail;
14338 		}
14339 		res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
14340 		if (res < 0) {
14341 			send_resp(dut, conn, SIGMA_ERROR,
14342 				  "ErrorCode,WPS connection did not complete");
14343 			goto fail;
14344 		}
14345 		if (strstr(buf, "WPS-TIMEOUT")) {
14346 			send_resp(dut, conn, SIGMA_COMPLETE, "WpsState,NoPeer");
14347 		} else if (strstr(buf, "WPS-OVERLAP-DETECTED")) {
14348 			send_resp(dut, conn, SIGMA_COMPLETE,
14349 				  "WpsState,OverlapSession");
14350 		} else if (strstr(buf, "CTRL-EVENT-CONNECTED")) {
14351 			send_resp(dut, conn, SIGMA_COMPLETE,
14352 				  "WpsState,Successful");
14353 		} else {
14354 			send_resp(dut, conn, SIGMA_COMPLETE,
14355 				  "WpsState,Failure");
14356 		}
14357 	} else {
14358 		if (dut->wps_method == WFA_CS_WPS_PBC) {
14359 			if (wpa_command(intf, "WPS_PBC") < 0) {
14360 				send_resp(dut, conn, SIGMA_ERROR,
14361 					  "ErrorCode,Failed to enable PBC");
14362 				goto fail;
14363 			}
14364 		} else {
14365 			/* TODO: PIN method */
14366 			send_resp(dut, conn, SIGMA_ERROR,
14367 				  "ErrorCode,Unsupported WpsConfigMethod value");
14368 			goto fail;
14369 		}
14370 		res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
14371 		if (res < 0) {
14372 			send_resp(dut, conn, SIGMA_ERROR,
14373 				  "ErrorCode,WPS connection did not complete");
14374 			goto fail;
14375 		}
14376 		if (strstr(buf, "WPS-TIMEOUT")) {
14377 			send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,NoPeer");
14378 		} else if (strstr(buf, "WPS-OVERLAP-DETECTED")) {
14379 			send_resp(dut, conn, SIGMA_ERROR,
14380 				  "ErrorCode,OverlapSession");
14381 		} else if (strstr(buf, "CTRL-EVENT-CONNECTED")) {
14382 			send_resp(dut, conn, SIGMA_COMPLETE, "Successful");
14383 		} else {
14384 			send_resp(dut, conn, SIGMA_ERROR,
14385 				  "ErrorCode,WPS operation failed");
14386 		}
14387 	}
14388 
14389 fail:
14390 	wpa_ctrl_detach(ctrl);
14391 	wpa_ctrl_close(ctrl);
14392 	return 0;
14393 }
14394 
14395 
req_intf(struct sigma_cmd * cmd)14396 static int req_intf(struct sigma_cmd *cmd)
14397 {
14398 	return get_param(cmd, "interface") == NULL ? -1 : 0;
14399 }
14400 
14401 
sta_register_cmds(void)14402 void sta_register_cmds(void)
14403 {
14404 	sigma_dut_reg_cmd("sta_get_ip_config", req_intf,
14405 			  cmd_sta_get_ip_config);
14406 	sigma_dut_reg_cmd("sta_set_ip_config", req_intf,
14407 			  cmd_sta_set_ip_config);
14408 	sigma_dut_reg_cmd("sta_get_info", req_intf, cmd_sta_get_info);
14409 	sigma_dut_reg_cmd("sta_get_mac_address", req_intf,
14410 			  cmd_sta_get_mac_address);
14411 	sigma_dut_reg_cmd("sta_is_connected", req_intf, cmd_sta_is_connected);
14412 	sigma_dut_reg_cmd("sta_verify_ip_connection", req_intf,
14413 			  cmd_sta_verify_ip_connection);
14414 	sigma_dut_reg_cmd("sta_get_bssid", req_intf, cmd_sta_get_bssid);
14415 	sigma_dut_reg_cmd("sta_set_encryption", req_intf,
14416 			  cmd_sta_set_encryption);
14417 	sigma_dut_reg_cmd("sta_set_psk", req_intf, cmd_sta_set_psk);
14418 	sigma_dut_reg_cmd("sta_set_eaptls", req_intf, cmd_sta_set_eaptls);
14419 	sigma_dut_reg_cmd("sta_set_eapttls", req_intf, cmd_sta_set_eapttls);
14420 	sigma_dut_reg_cmd("sta_set_eapsim", req_intf, cmd_sta_set_eapsim);
14421 	sigma_dut_reg_cmd("sta_set_peap", req_intf, cmd_sta_set_peap);
14422 	sigma_dut_reg_cmd("sta_set_eapfast", req_intf, cmd_sta_set_eapfast);
14423 	sigma_dut_reg_cmd("sta_set_eapaka", req_intf, cmd_sta_set_eapaka);
14424 	sigma_dut_reg_cmd("sta_set_eapakaprime", req_intf,
14425 			  cmd_sta_set_eapakaprime);
14426 	sigma_dut_reg_cmd("sta_set_security", req_intf, cmd_sta_set_security);
14427 	sigma_dut_reg_cmd("sta_set_uapsd", req_intf, cmd_sta_set_uapsd);
14428 	/* TODO: sta_set_ibss */
14429 	/* TODO: sta_set_mode */
14430 	sigma_dut_reg_cmd("sta_set_wmm", req_intf, cmd_sta_set_wmm);
14431 	sigma_dut_reg_cmd("sta_associate", req_intf, cmd_sta_associate);
14432 	/* TODO: sta_up_load */
14433 	sigma_dut_reg_cmd("sta_preset_testparameters", req_intf,
14434 			  cmd_sta_preset_testparameters);
14435 	/* TODO: sta_set_system */
14436 	sigma_dut_reg_cmd("sta_set_11n", req_intf, cmd_sta_set_11n);
14437 	/* TODO: sta_set_rifs_test */
14438 	sigma_dut_reg_cmd("sta_set_wireless", req_intf, cmd_sta_set_wireless);
14439 	sigma_dut_reg_cmd("sta_send_addba", req_intf, cmd_sta_send_addba);
14440 	/* TODO: sta_send_coexist_mgmt */
14441 	sigma_dut_reg_cmd("sta_disconnect", req_intf, cmd_sta_disconnect);
14442 	sigma_dut_reg_cmd("sta_reassoc", req_intf, cmd_sta_reassoc);
14443 	sigma_dut_reg_cmd("sta_reassociate", req_intf, cmd_sta_reassoc);
14444 	sigma_dut_reg_cmd("sta_reset_default", req_intf,
14445 			  cmd_sta_reset_default);
14446 	sigma_dut_reg_cmd("sta_send_frame", req_intf, cmd_sta_send_frame);
14447 	sigma_dut_reg_cmd("sta_set_macaddr", req_intf, cmd_sta_set_macaddr);
14448 	sigma_dut_reg_cmd("sta_set_rfeature", req_intf, cmd_sta_set_rfeature);
14449 	sigma_dut_reg_cmd("sta_set_radio", req_intf, cmd_sta_set_radio);
14450 	sigma_dut_reg_cmd("sta_set_pwrsave", req_intf, cmd_sta_set_pwrsave);
14451 	sigma_dut_reg_cmd("sta_set_power_save", req_intf, cmd_sta_set_pwrsave);
14452 	sigma_dut_reg_cmd("sta_bssid_pool", req_intf, cmd_sta_bssid_pool);
14453 	sigma_dut_reg_cmd("sta_reset_parm", req_intf, cmd_sta_reset_parm);
14454 	sigma_dut_reg_cmd("sta_get_key", req_intf, cmd_sta_get_key);
14455 	sigma_dut_reg_cmd("sta_hs2_associate", req_intf,
14456 			  cmd_sta_hs2_associate);
14457 	sigma_dut_reg_cmd("sta_hs2_venue_info", req_intf,
14458 			  cmd_sta_hs2_venue_info);
14459 	sigma_dut_reg_cmd("sta_add_credential", req_intf,
14460 			  cmd_sta_add_credential);
14461 	sigma_dut_reg_cmd("sta_scan", req_intf, cmd_sta_scan);
14462 	sigma_dut_reg_cmd("sta_scan_bss", req_intf, cmd_sta_scan_bss);
14463 	sigma_dut_reg_cmd("sta_set_systime", NULL, cmd_sta_set_systime);
14464 	sigma_dut_reg_cmd("sta_osu", req_intf, cmd_sta_osu);
14465 	sigma_dut_reg_cmd("sta_policy_update", req_intf, cmd_sta_policy_update);
14466 	sigma_dut_reg_cmd("sta_er_config", NULL, cmd_sta_er_config);
14467 	sigma_dut_reg_cmd("sta_wps_connect_pw_token", req_intf,
14468 			  cmd_sta_wps_connect_pw_token);
14469 	sigma_dut_reg_cmd("sta_exec_action", NULL, cmd_sta_exec_action);
14470 	sigma_dut_reg_cmd("sta_get_events", req_intf, cmd_sta_get_events);
14471 	sigma_dut_reg_cmd("sta_get_parameter", req_intf, cmd_sta_get_parameter);
14472 	sigma_dut_reg_cmd("start_wps_registration", NULL,
14473 			  cmd_start_wps_registration);
14474 }
14475