xref: /wlan-dirver/utils/sigma-dut/p2p.c (revision 0dae51c57b99cb76e65e3cf676abd412ea196f69)
1cd4e3c3eSJouni Malinen /*
2cd4e3c3eSJouni Malinen  * Sigma Control API DUT (station/AP)
3cd4e3c3eSJouni Malinen  * Copyright (c) 2010-2011, Atheros Communications, Inc.
49c381f59SAmarnath Hullur Subramanyam  * Copyright (c) 2011-2017, Qualcomm Atheros, Inc.
5cd4e3c3eSJouni Malinen  * All Rights Reserved.
6cd4e3c3eSJouni Malinen  * Licensed under the Clear BSD license. See README for more details.
7cd4e3c3eSJouni Malinen  */
8cd4e3c3eSJouni Malinen 
9cd4e3c3eSJouni Malinen #include "sigma_dut.h"
10cd4e3c3eSJouni Malinen #include <sys/stat.h>
11cd4e3c3eSJouni Malinen #include "wpa_ctrl.h"
12cd4e3c3eSJouni Malinen #include "wpa_helpers.h"
139c381f59SAmarnath Hullur Subramanyam #include "miracast.h"
14cd4e3c3eSJouni Malinen 
15cd4e3c3eSJouni Malinen 
16cd4e3c3eSJouni Malinen int run_system(struct sigma_dut *dut, const char *cmd)
17cd4e3c3eSJouni Malinen {
18cd4e3c3eSJouni Malinen 	int res;
19cd4e3c3eSJouni Malinen 
20cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Running '%s'", cmd);
21cd4e3c3eSJouni Malinen 	res = system(cmd);
22cd4e3c3eSJouni Malinen 	if (res < 0) {
23cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Failed to execute "
24cd4e3c3eSJouni Malinen 				"command '%s'", cmd);
25cd4e3c3eSJouni Malinen 	}
26cd4e3c3eSJouni Malinen 	return res;
27cd4e3c3eSJouni Malinen }
28cd4e3c3eSJouni Malinen 
29cd4e3c3eSJouni Malinen 
305f793f0dSAdil Saeed Musthafa int run_system_wrapper(struct sigma_dut *dut, const char *cmd, ...)
315f793f0dSAdil Saeed Musthafa {
325f793f0dSAdil Saeed Musthafa 	va_list ap;
335f793f0dSAdil Saeed Musthafa 	char *buf;
345f793f0dSAdil Saeed Musthafa 	int bytes_required;
355f793f0dSAdil Saeed Musthafa 	int res;
365f793f0dSAdil Saeed Musthafa 
375f793f0dSAdil Saeed Musthafa 	va_start(ap, cmd);
385f793f0dSAdil Saeed Musthafa 	bytes_required = vsnprintf(NULL, 0, cmd, ap);
395f793f0dSAdil Saeed Musthafa 	bytes_required += 1;
405f793f0dSAdil Saeed Musthafa 	va_end(ap);
415f793f0dSAdil Saeed Musthafa 	buf = malloc(bytes_required);
425f793f0dSAdil Saeed Musthafa 	if (!buf) {
435f793f0dSAdil Saeed Musthafa 		printf("ERROR!! No memory\n");
445f793f0dSAdil Saeed Musthafa 		return -1;
455f793f0dSAdil Saeed Musthafa 	}
465f793f0dSAdil Saeed Musthafa 	va_start(ap, cmd);
475f793f0dSAdil Saeed Musthafa 	vsnprintf(buf, bytes_required, cmd, ap);
485f793f0dSAdil Saeed Musthafa 	va_end(ap);
495f793f0dSAdil Saeed Musthafa 	res = run_system(dut, buf);
505f793f0dSAdil Saeed Musthafa 	free(buf);
515f793f0dSAdil Saeed Musthafa 	return res;
525f793f0dSAdil Saeed Musthafa }
535f793f0dSAdil Saeed Musthafa 
545f793f0dSAdil Saeed Musthafa 
559e390a52SDanny Segal static int get_60g_freq(int chan)
569e390a52SDanny Segal {
579e390a52SDanny Segal 	int freq = 0;
589e390a52SDanny Segal 
599e390a52SDanny Segal 	switch(chan) {
609e390a52SDanny Segal 	case 1:
619e390a52SDanny Segal 		freq = 58320;
629e390a52SDanny Segal 		break;
639e390a52SDanny Segal 	case 2:
649e390a52SDanny Segal 		freq = 60480;
659e390a52SDanny Segal 		break;
669e390a52SDanny Segal 	case 3:
679e390a52SDanny Segal 		freq = 62640;
689e390a52SDanny Segal 		break;
699e390a52SDanny Segal 	case 4:
709e390a52SDanny Segal 		/* freq = 64800; Not supported in Sparrow 2.0 */
719e390a52SDanny Segal 		break;
729e390a52SDanny Segal 	default:
739e390a52SDanny Segal 		break;
749e390a52SDanny Segal 	}
759e390a52SDanny Segal 
769e390a52SDanny Segal 	return freq;
779e390a52SDanny Segal }
789e390a52SDanny Segal 
799e390a52SDanny Segal 
80091e253dSPurushottam Kushwaha #define GO_IP_ADDR "192.168.43.1"
81091e253dSPurushottam Kushwaha #define START_IP_RANGE "192.168.43.10"
82091e253dSPurushottam Kushwaha #define END_IP_RANGE "192.168.43.100"
83091e253dSPurushottam Kushwaha #define FLUSH_IP_ADDR "0.0.0.0"
84091e253dSPurushottam Kushwaha 
8589b37cdcSAmarnath Hullur Subramanyam void start_dhcp(struct sigma_dut *dut, const char *group_ifname, int go)
86091e253dSPurushottam Kushwaha {
87091e253dSPurushottam Kushwaha #ifdef __linux__
88091e253dSPurushottam Kushwaha 	char buf[200];
89091e253dSPurushottam Kushwaha 
90091e253dSPurushottam Kushwaha 	if (go) {
91091e253dSPurushottam Kushwaha 		snprintf(buf, sizeof(buf), "ifconfig %s %s", group_ifname,
92091e253dSPurushottam Kushwaha 			 GO_IP_ADDR);
93091e253dSPurushottam Kushwaha 		run_system(dut, buf);
94091e253dSPurushottam Kushwaha 		snprintf(buf, sizeof(buf),
95091e253dSPurushottam Kushwaha 			 "/system/bin/dnsmasq -x /data/dnsmasq.pid --no-resolv --no-poll --dhcp-range=%s,%s,1h",
96091e253dSPurushottam Kushwaha 			 START_IP_RANGE, END_IP_RANGE);
97091e253dSPurushottam Kushwaha 	} else {
98091e253dSPurushottam Kushwaha #ifdef ANDROID
99091e253dSPurushottam Kushwaha 		if (access("/system/bin/dhcpcd", F_OK) != -1) {
100091e253dSPurushottam Kushwaha 			snprintf(buf, sizeof(buf), "/system/bin/dhcpcd -KL %s",
101091e253dSPurushottam Kushwaha 				 group_ifname);
10246d6426cSPurushottam Kushwaha 		} else if (access("/system/bin/dhcptool", F_OK) != -1) {
10346d6426cSPurushottam Kushwaha 			snprintf(buf, sizeof(buf), "/system/bin/dhcptool %s",
10446d6426cSPurushottam Kushwaha 				 group_ifname);
10561000393SAnkita Bajaj 		} else if (access("/vendor/bin/dhcpcd", F_OK) != -1) {
10661000393SAnkita Bajaj 			snprintf(buf, sizeof(buf), "/vendor/bin/dhcpcd %s",
10761000393SAnkita Bajaj 				 group_ifname);
10861000393SAnkita Bajaj 		} else if (access("/vendor/bin/dhcptool", F_OK) != -1) {
10961000393SAnkita Bajaj 			snprintf(buf, sizeof(buf), "/vendor/bin/dhcptool %s",
11061000393SAnkita Bajaj 				 group_ifname);
111091e253dSPurushottam Kushwaha 		} else {
112091e253dSPurushottam Kushwaha 			sigma_dut_print(dut, DUT_MSG_ERROR,
113091e253dSPurushottam Kushwaha 					"DHCP client program missing");
114091e253dSPurushottam Kushwaha 			return;
115091e253dSPurushottam Kushwaha 		}
116091e253dSPurushottam Kushwaha #else /* ANDROID */
117091e253dSPurushottam Kushwaha 		snprintf(buf, sizeof(buf),
118091e253dSPurushottam Kushwaha 			 "dhclient -nw -pf /var/run/dhclient-%s.pid %s",
119091e253dSPurushottam Kushwaha 			 group_ifname, group_ifname);
120091e253dSPurushottam Kushwaha #endif /* ANDROID */
121091e253dSPurushottam Kushwaha 	}
122091e253dSPurushottam Kushwaha 
123091e253dSPurushottam Kushwaha 	run_system(dut, buf);
124091e253dSPurushottam Kushwaha #endif /* __linux__ */
125091e253dSPurushottam Kushwaha }
126091e253dSPurushottam Kushwaha 
127091e253dSPurushottam Kushwaha 
12889b37cdcSAmarnath Hullur Subramanyam void stop_dhcp(struct sigma_dut *dut, const char *group_ifname, int go)
129091e253dSPurushottam Kushwaha {
130091e253dSPurushottam Kushwaha #ifdef __linux__
131091e253dSPurushottam Kushwaha 	char path[128];
132091e253dSPurushottam Kushwaha 	char buf[200];
133091e253dSPurushottam Kushwaha 	struct stat s;
134091e253dSPurushottam Kushwaha 
135091e253dSPurushottam Kushwaha 	if (go) {
136091e253dSPurushottam Kushwaha 		snprintf(path, sizeof(path), "/data/dnsmasq.pid");
137091e253dSPurushottam Kushwaha 		sigma_dut_print(dut, DUT_MSG_DEBUG,
138091e253dSPurushottam Kushwaha 				"Kill previous DHCP server: %s", buf);
139091e253dSPurushottam Kushwaha 	} else {
140091e253dSPurushottam Kushwaha #ifdef ANDROID
141091e253dSPurushottam Kushwaha 		if (access("/system/bin/dhcpcd", F_OK) != -1) {
142091e253dSPurushottam Kushwaha 			snprintf(path, sizeof(path),
143091e253dSPurushottam Kushwaha 				 "/data/misc/dhcp/dhcpcd-%s.pid", group_ifname);
144091e253dSPurushottam Kushwaha 		} else {
14546d6426cSPurushottam Kushwaha 			/*
14646d6426cSPurushottam Kushwaha 			 * dhcptool terminates as soon as IP is
14746d6426cSPurushottam Kushwaha 			 * assigned/registered using ioctls, no need to kill it
14846d6426cSPurushottam Kushwaha 			 * explicitly.
14946d6426cSPurushottam Kushwaha 			 */
150091e253dSPurushottam Kushwaha 			sigma_dut_print(dut, DUT_MSG_ERROR,
151091e253dSPurushottam Kushwaha 					"No active DHCP client program");
152091e253dSPurushottam Kushwaha 			return;
153091e253dSPurushottam Kushwaha 		}
154091e253dSPurushottam Kushwaha 		snprintf(path, sizeof(path), "/data/misc/dhcp/dhcpcd-%s.pid",
155091e253dSPurushottam Kushwaha 			 group_ifname);
156091e253dSPurushottam Kushwaha #else /* ANDROID */
157091e253dSPurushottam Kushwaha 		snprintf(path, sizeof(path), "/var/run/dhclient-%s.pid",
158091e253dSPurushottam Kushwaha 			 group_ifname);
159091e253dSPurushottam Kushwaha #endif /* ANDROID */
160091e253dSPurushottam Kushwaha 		sigma_dut_print(dut, DUT_MSG_DEBUG,
161091e253dSPurushottam Kushwaha 				"Kill previous DHCP client: %s", buf);
162091e253dSPurushottam Kushwaha 	}
163091e253dSPurushottam Kushwaha 	if (stat(path, &s) == 0) {
164091e253dSPurushottam Kushwaha 		snprintf(buf, sizeof(buf), "kill `cat %s`", path);
165091e253dSPurushottam Kushwaha 		run_system(dut, buf);
166091e253dSPurushottam Kushwaha 		unlink(path);
167091e253dSPurushottam Kushwaha 		sleep(1);
168091e253dSPurushottam Kushwaha 	}
169091e253dSPurushottam Kushwaha 
170091e253dSPurushottam Kushwaha 	snprintf(buf, sizeof(buf), "ip address flush dev %s", group_ifname);
171091e253dSPurushottam Kushwaha 	run_system(dut, buf);
172091e253dSPurushottam Kushwaha 	snprintf(buf, sizeof(buf), "ifconfig %s %s",
173091e253dSPurushottam Kushwaha 		 group_ifname, FLUSH_IP_ADDR);
174091e253dSPurushottam Kushwaha 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Clear IP address: %s", buf);
175091e253dSPurushottam Kushwaha 	run_system(dut, buf);
176091e253dSPurushottam Kushwaha #endif /* __linux__ */
177091e253dSPurushottam Kushwaha }
178091e253dSPurushottam Kushwaha 
179091e253dSPurushottam Kushwaha 
180091e253dSPurushottam Kushwaha static int stop_event_rx = 0;
181091e253dSPurushottam Kushwaha 
182091e253dSPurushottam Kushwaha #ifdef __linux__
183091e253dSPurushottam Kushwaha void stop_event_thread()
184091e253dSPurushottam Kushwaha {
185091e253dSPurushottam Kushwaha 	stop_event_rx = 1;
186091e253dSPurushottam Kushwaha 	printf("sigma_dut dhcp terminating\n");
187091e253dSPurushottam Kushwaha }
188091e253dSPurushottam Kushwaha #endif /* __linux__ */
189091e253dSPurushottam Kushwaha 
190091e253dSPurushottam Kushwaha 
191091e253dSPurushottam Kushwaha static void * wpa_event_recv(void *ptr)
192091e253dSPurushottam Kushwaha {
193091e253dSPurushottam Kushwaha 	struct sigma_dut *dut = ptr;
194091e253dSPurushottam Kushwaha 	struct wpa_ctrl *ctrl;
195091e253dSPurushottam Kushwaha 	char buf[4096];
196091e253dSPurushottam Kushwaha 	char *pos, *gtype, *p2p_group_ifname = NULL;
197091e253dSPurushottam Kushwaha 	int fd, ret, i;
198091e253dSPurushottam Kushwaha 	int go = 0;
199091e253dSPurushottam Kushwaha 	fd_set rfd;
200091e253dSPurushottam Kushwaha 	struct timeval tv;
201091e253dSPurushottam Kushwaha 	size_t len;
202091e253dSPurushottam Kushwaha 
203091e253dSPurushottam Kushwaha 	const char *events[] = {
204091e253dSPurushottam Kushwaha 		"P2P-GROUP-STARTED",
205091e253dSPurushottam Kushwaha 		"P2P-GROUP-REMOVED",
206091e253dSPurushottam Kushwaha 		NULL
207091e253dSPurushottam Kushwaha 	};
208091e253dSPurushottam Kushwaha 
209091e253dSPurushottam Kushwaha 	ctrl = open_wpa_mon(dut->p2p_ifname);
210091e253dSPurushottam Kushwaha 	if (!ctrl) {
211091e253dSPurushottam Kushwaha 		sigma_dut_print(dut, DUT_MSG_ERROR,
212091e253dSPurushottam Kushwaha 				"Failed to open wpa_supplicant monitor connection");
213091e253dSPurushottam Kushwaha 		return NULL;
214091e253dSPurushottam Kushwaha 	}
215091e253dSPurushottam Kushwaha 
216091e253dSPurushottam Kushwaha 	for (i = 0; events[i]; i++) {
217091e253dSPurushottam Kushwaha 		sigma_dut_print(dut, DUT_MSG_DEBUG,
218091e253dSPurushottam Kushwaha 				"Waiting for wpa_cli event: %s", events[i]);
219091e253dSPurushottam Kushwaha 	}
220091e253dSPurushottam Kushwaha 
221091e253dSPurushottam Kushwaha 	fd = wpa_ctrl_get_fd(ctrl);
222091e253dSPurushottam Kushwaha 	if (fd < 0) {
223091e253dSPurushottam Kushwaha 		wpa_ctrl_detach(ctrl);
224091e253dSPurushottam Kushwaha 		wpa_ctrl_close(ctrl);
225091e253dSPurushottam Kushwaha 		return NULL;
226091e253dSPurushottam Kushwaha 	}
227091e253dSPurushottam Kushwaha 
228091e253dSPurushottam Kushwaha 	while (!stop_event_rx) {
229091e253dSPurushottam Kushwaha 		FD_ZERO(&rfd);
230091e253dSPurushottam Kushwaha 		FD_SET(fd, &rfd);
231091e253dSPurushottam Kushwaha 		tv.tv_sec = 1;
232091e253dSPurushottam Kushwaha 		tv.tv_usec = 0;
233091e253dSPurushottam Kushwaha 
234091e253dSPurushottam Kushwaha 		ret = select(fd + 1, &rfd, NULL, NULL, &tv);
235091e253dSPurushottam Kushwaha 		if (ret == 0)
236091e253dSPurushottam Kushwaha 			continue;
237091e253dSPurushottam Kushwaha 		if (ret < 0) {
238091e253dSPurushottam Kushwaha 			sigma_dut_print(dut, DUT_MSG_INFO, "select: %s",
239091e253dSPurushottam Kushwaha 					strerror(errno));
240091e253dSPurushottam Kushwaha 			usleep(100000);
241091e253dSPurushottam Kushwaha 			continue;
242091e253dSPurushottam Kushwaha 		}
243091e253dSPurushottam Kushwaha 
244091e253dSPurushottam Kushwaha 		len = sizeof(buf);
245091e253dSPurushottam Kushwaha 		if (wpa_ctrl_recv(ctrl, buf, &len) < 0) {
246091e253dSPurushottam Kushwaha 			sigma_dut_print(dut, DUT_MSG_ERROR,
247091e253dSPurushottam Kushwaha 					"Failure while waiting for events");
248091e253dSPurushottam Kushwaha 			continue;
249091e253dSPurushottam Kushwaha 		}
250091e253dSPurushottam Kushwaha 
251091e253dSPurushottam Kushwaha 		ret = 0;
252091e253dSPurushottam Kushwaha 		pos = strchr(buf, '>');
253091e253dSPurushottam Kushwaha 		if (pos) {
254091e253dSPurushottam Kushwaha 			for (i = 0; events[i]; i++) {
255091e253dSPurushottam Kushwaha 				if (strncmp(pos + 1, events[i],
256091e253dSPurushottam Kushwaha 					    strlen(events[i])) == 0) {
257091e253dSPurushottam Kushwaha 					ret = 1;
258091e253dSPurushottam Kushwaha 					break; /* Event found */
259091e253dSPurushottam Kushwaha 				}
260091e253dSPurushottam Kushwaha 			}
261091e253dSPurushottam Kushwaha 		}
262091e253dSPurushottam Kushwaha 		if (!ret)
263091e253dSPurushottam Kushwaha 			continue;
264091e253dSPurushottam Kushwaha 
265091e253dSPurushottam Kushwaha 		if (strstr(buf, "P2P-GROUP-")) {
266091e253dSPurushottam Kushwaha 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Group event '%s'",
267091e253dSPurushottam Kushwaha 					buf);
268091e253dSPurushottam Kushwaha 			p2p_group_ifname = strchr(buf, ' ');
269091e253dSPurushottam Kushwaha 			if (!p2p_group_ifname)
270091e253dSPurushottam Kushwaha 				continue;
271091e253dSPurushottam Kushwaha 			p2p_group_ifname++;
272091e253dSPurushottam Kushwaha 			pos = strchr(p2p_group_ifname, ' ');
273091e253dSPurushottam Kushwaha 			if (!pos)
274091e253dSPurushottam Kushwaha 				continue;
275091e253dSPurushottam Kushwaha 			*pos++ = '\0';
276091e253dSPurushottam Kushwaha 			gtype = pos;
277091e253dSPurushottam Kushwaha 			pos = strchr(gtype, ' ');
278091e253dSPurushottam Kushwaha 			if (!pos)
279091e253dSPurushottam Kushwaha 				continue;
280091e253dSPurushottam Kushwaha 			*pos++ = '\0';
281091e253dSPurushottam Kushwaha 
282091e253dSPurushottam Kushwaha 			go = strcmp(gtype, "GO") == 0;
283091e253dSPurushottam Kushwaha 		}
284091e253dSPurushottam Kushwaha 
285091e253dSPurushottam Kushwaha 		if (strstr(buf, "P2P-GROUP-STARTED")) {
286091e253dSPurushottam Kushwaha 			start_dhcp(dut, p2p_group_ifname, go);
287091e253dSPurushottam Kushwaha 		} else if (strstr(buf, "P2P-GROUP-REMOVED")) {
288091e253dSPurushottam Kushwaha 			stop_dhcp(dut, p2p_group_ifname, go);
289091e253dSPurushottam Kushwaha 			go = 0;
290091e253dSPurushottam Kushwaha 		}
291091e253dSPurushottam Kushwaha 	}
292091e253dSPurushottam Kushwaha 
293091e253dSPurushottam Kushwaha 	/* terminate DHCP server, if runnin! */
294091e253dSPurushottam Kushwaha 	if (go)
295091e253dSPurushottam Kushwaha 		stop_dhcp(dut, p2p_group_ifname, go);
296091e253dSPurushottam Kushwaha 
297091e253dSPurushottam Kushwaha 	wpa_ctrl_detach(ctrl);
298091e253dSPurushottam Kushwaha 	wpa_ctrl_close(ctrl);
299091e253dSPurushottam Kushwaha 
300091e253dSPurushottam Kushwaha 	pthread_exit(0);
301091e253dSPurushottam Kushwaha 	return NULL;
302091e253dSPurushottam Kushwaha }
303091e253dSPurushottam Kushwaha 
304091e253dSPurushottam Kushwaha 
305091e253dSPurushottam Kushwaha void p2p_create_event_thread(struct sigma_dut *dut)
306091e253dSPurushottam Kushwaha {
307091e253dSPurushottam Kushwaha 	static pthread_t event_thread;
308091e253dSPurushottam Kushwaha 
309091e253dSPurushottam Kushwaha 	/* create event thread */
310091e253dSPurushottam Kushwaha 	pthread_create(&event_thread, NULL, &wpa_event_recv, (void *) dut);
311091e253dSPurushottam Kushwaha }
312091e253dSPurushottam Kushwaha 
313091e253dSPurushottam Kushwaha 
314cd4e3c3eSJouni Malinen static int p2p_group_add(struct sigma_dut *dut, const char *ifname,
315cd4e3c3eSJouni Malinen 			 int go, const char *grpid, const char *ssid)
316cd4e3c3eSJouni Malinen {
317cd4e3c3eSJouni Malinen 	struct wfa_cs_p2p_group *grp;
318cd4e3c3eSJouni Malinen 
319cd4e3c3eSJouni Malinen 	if (go)
320cd4e3c3eSJouni Malinen 		dut->go = 1;
321cd4e3c3eSJouni Malinen 	else
322cd4e3c3eSJouni Malinen 		dut->p2p_client = 1;
323cd4e3c3eSJouni Malinen 	grp = malloc(sizeof(*grp));
324cd4e3c3eSJouni Malinen 	if (grp == NULL)
325cd4e3c3eSJouni Malinen 		return -1;
326cd4e3c3eSJouni Malinen 	memset(grp, 0, sizeof(*grp));
327b8fc5cc8SPeng Xu 	strlcpy(grp->ifname, ifname, IFNAMSIZ);
328cd4e3c3eSJouni Malinen 	grp->go = go;
329b8fc5cc8SPeng Xu 	strlcpy(grp->grpid, grpid, P2P_GRP_ID_LEN);
330b8fc5cc8SPeng Xu 	strlcpy(grp->ssid, ssid, sizeof(grp->ssid));
331cd4e3c3eSJouni Malinen 
332cd4e3c3eSJouni Malinen 	grp->next = dut->groups;
333cd4e3c3eSJouni Malinen 	dut->groups = grp;
334cd4e3c3eSJouni Malinen 
335cd4e3c3eSJouni Malinen 	return 0;
336cd4e3c3eSJouni Malinen }
337cd4e3c3eSJouni Malinen 
338cd4e3c3eSJouni Malinen 
339cd4e3c3eSJouni Malinen static int p2p_group_remove(struct sigma_dut *dut, const char *grpid)
340cd4e3c3eSJouni Malinen {
341cd4e3c3eSJouni Malinen 	struct wfa_cs_p2p_group *grp, *prev;
342cd4e3c3eSJouni Malinen 
343cd4e3c3eSJouni Malinen 	prev = NULL;
344cd4e3c3eSJouni Malinen 	grp = dut->groups;
345cd4e3c3eSJouni Malinen 	while (grp) {
346cd4e3c3eSJouni Malinen 		if (strcmp(grpid, grp->grpid) == 0) {
347cd4e3c3eSJouni Malinen 			if (prev)
348cd4e3c3eSJouni Malinen 				prev->next = grp->next;
349cd4e3c3eSJouni Malinen 			else
350cd4e3c3eSJouni Malinen 				dut->groups = grp->next;
351cd4e3c3eSJouni Malinen 			free(grp);
352cd4e3c3eSJouni Malinen 			return 0;
353cd4e3c3eSJouni Malinen 		}
354cd4e3c3eSJouni Malinen 		prev = grp;
355cd4e3c3eSJouni Malinen 		grp = grp->next;
356cd4e3c3eSJouni Malinen 	}
357cd4e3c3eSJouni Malinen 	return -1;
358cd4e3c3eSJouni Malinen }
359cd4e3c3eSJouni Malinen 
360cd4e3c3eSJouni Malinen 
361cd4e3c3eSJouni Malinen static struct wfa_cs_p2p_group * p2p_group_get(struct sigma_dut *dut,
362cd4e3c3eSJouni Malinen 					       const char *grpid)
363cd4e3c3eSJouni Malinen {
364cd4e3c3eSJouni Malinen 	struct wfa_cs_p2p_group *grp;
365cd4e3c3eSJouni Malinen 	char buf[1000], buf2[4096], *ifname, *pos;
366cd4e3c3eSJouni Malinen 	char go_dev_addr[50];
367cd4e3c3eSJouni Malinen 	char ssid[33];
368cd4e3c3eSJouni Malinen 
369cd4e3c3eSJouni Malinen 	for (grp = dut->groups; grp; grp = grp->next) {
370cd4e3c3eSJouni Malinen 		if (strcmp(grpid, grp->grpid) == 0)
371cd4e3c3eSJouni Malinen 			return grp;
372cd4e3c3eSJouni Malinen 	}
373cd4e3c3eSJouni Malinen 
374cd4e3c3eSJouni Malinen 	/*
375cd4e3c3eSJouni Malinen 	 * No group found based on group id. As a workaround for GO Negotiation
376cd4e3c3eSJouni Malinen 	 * responder case where we do not store group id, try to find an active
377cd4e3c3eSJouni Malinen 	 * group that matches with the requested group id.
378cd4e3c3eSJouni Malinen 	 */
379cd4e3c3eSJouni Malinen 
380cd4e3c3eSJouni Malinen 	pos = strchr(grpid, ' ');
381cd4e3c3eSJouni Malinen 	if (pos == NULL)
382cd4e3c3eSJouni Malinen 		return NULL;
38340cbba39SPeng Xu 	if (pos - grpid >= (int) sizeof(go_dev_addr))
384cd4e3c3eSJouni Malinen 		return NULL;
385cd4e3c3eSJouni Malinen 	memcpy(go_dev_addr, grpid, pos - grpid);
386cd4e3c3eSJouni Malinen 	go_dev_addr[pos - grpid] = '\0';
387b8fc5cc8SPeng Xu 	strlcpy(ssid, pos + 1, sizeof(ssid));
388cd4e3c3eSJouni Malinen 	ssid[sizeof(ssid) - 1] = '\0';
389cd4e3c3eSJouni Malinen 	printf("Trying to find suitable interface for group: go_dev_addr='%s' "
390cd4e3c3eSJouni Malinen 	       "grpid='%s'\n", go_dev_addr, grpid);
391cd4e3c3eSJouni Malinen 
392cd4e3c3eSJouni Malinen 	if (wpa_command_resp(get_main_ifname(), "INTERFACES", buf, sizeof(buf))
393cd4e3c3eSJouni Malinen 	    < 0)
394cd4e3c3eSJouni Malinen 		return NULL;
395cd4e3c3eSJouni Malinen 	ifname = buf;
396cd4e3c3eSJouni Malinen 	while (ifname && *ifname) {
397cd4e3c3eSJouni Malinen 		int add = 0;
398cd4e3c3eSJouni Malinen 		int go = 0;
399cd4e3c3eSJouni Malinen 		pos = strchr(ifname, '\n');
400cd4e3c3eSJouni Malinen 		if (pos)
401cd4e3c3eSJouni Malinen 			*pos++ = '\0';
402cd4e3c3eSJouni Malinen 		printf("Considering interface '%s' for group\n", ifname);
403cd4e3c3eSJouni Malinen 
404cd4e3c3eSJouni Malinen 		if (wpa_command_resp(ifname, "STATUS", buf2, sizeof(buf2)) ==
405cd4e3c3eSJouni Malinen 		    0) {
406cd4e3c3eSJouni Malinen 			if (strstr(buf2, ssid)) {
407cd4e3c3eSJouni Malinen 				printf("Selected interface '%s' based on "
408cd4e3c3eSJouni Malinen 				       "STATUS\n", ifname);
409cd4e3c3eSJouni Malinen 				add = 1;
410cd4e3c3eSJouni Malinen 			}
411cd4e3c3eSJouni Malinen 			if (strstr(buf2, "P2P GO"))
412cd4e3c3eSJouni Malinen 				go = 1;
413cd4e3c3eSJouni Malinen 		}
414cd4e3c3eSJouni Malinen 
415cd4e3c3eSJouni Malinen 		if (wpa_command_resp(ifname, "LIST_NETWORKS", buf2,
416cd4e3c3eSJouni Malinen 				     sizeof(buf2)) == 0) {
417cd4e3c3eSJouni Malinen 			char *line, *end;
418cd4e3c3eSJouni Malinen 			line = buf2;
419cd4e3c3eSJouni Malinen 			while (line && *line) {
420cd4e3c3eSJouni Malinen 				end = strchr(line, ' ');
421cd4e3c3eSJouni Malinen 				if (end)
422cd4e3c3eSJouni Malinen 					*end++ = '\0';
423cd4e3c3eSJouni Malinen 				if (strstr(line, ssid) &&
424cd4e3c3eSJouni Malinen 				    strstr(line, "[CURRENT]")) {
425cd4e3c3eSJouni Malinen 					printf("Selected interface '%s' "
426cd4e3c3eSJouni Malinen 					       "based on LIST_NETWORKS\n",
427cd4e3c3eSJouni Malinen 					       ifname);
428cd4e3c3eSJouni Malinen 					add = 1;
429cd4e3c3eSJouni Malinen 					break;
430cd4e3c3eSJouni Malinen 				}
431cd4e3c3eSJouni Malinen 				line = end;
432cd4e3c3eSJouni Malinen 			}
433cd4e3c3eSJouni Malinen 		}
434cd4e3c3eSJouni Malinen 
435cd4e3c3eSJouni Malinen 		if (add) {
436cd4e3c3eSJouni Malinen 			p2p_group_add(dut, ifname, go, grpid, ssid);
437cd4e3c3eSJouni Malinen 			return dut->groups;
438cd4e3c3eSJouni Malinen 		}
439cd4e3c3eSJouni Malinen 
440cd4e3c3eSJouni Malinen 		ifname = pos;
441cd4e3c3eSJouni Malinen 	}
442cd4e3c3eSJouni Malinen 
443cd4e3c3eSJouni Malinen 	return NULL;
444cd4e3c3eSJouni Malinen }
445cd4e3c3eSJouni Malinen 
446cd4e3c3eSJouni Malinen 
447cd4e3c3eSJouni Malinen static const char * get_group_ifname(struct sigma_dut *dut, const char *ifname)
448cd4e3c3eSJouni Malinen {
449326123a3SJouni Malinen 	static char buf[1000];
450326123a3SJouni Malinen 	char *iface, *pos;
451cd4e3c3eSJouni Malinen 	char state[100];
452cd4e3c3eSJouni Malinen 
453cd4e3c3eSJouni Malinen 	if (dut->groups) {
454cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "%s: Use group interface "
455cd4e3c3eSJouni Malinen 				"%s instead of main interface %s",
456cd4e3c3eSJouni Malinen 				__func__, dut->groups->ifname, ifname);
457cd4e3c3eSJouni Malinen 		return dut->groups->ifname;
458cd4e3c3eSJouni Malinen 	}
459cd4e3c3eSJouni Malinen 
460cd4e3c3eSJouni Malinen 	/* Try to find a suitable group interface */
461cd4e3c3eSJouni Malinen 	if (wpa_command_resp(get_main_ifname(), "INTERFACES",
462cd4e3c3eSJouni Malinen 			     buf, sizeof(buf)) < 0)
463cd4e3c3eSJouni Malinen 		return ifname;
464cd4e3c3eSJouni Malinen 
465cd4e3c3eSJouni Malinen 	iface = buf;
466cd4e3c3eSJouni Malinen 	while (iface && *iface) {
467cd4e3c3eSJouni Malinen 		pos = strchr(iface, '\n');
468cd4e3c3eSJouni Malinen 		if (pos)
469cd4e3c3eSJouni Malinen 			*pos++ = '\0';
470cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Considering interface "
471cd4e3c3eSJouni Malinen 				"'%s' for IP address", iface);
472cd4e3c3eSJouni Malinen 		if (get_wpa_status(iface, "wpa_state", state, sizeof(state)) ==
473cd4e3c3eSJouni Malinen 		    0 && strcmp(state, "COMPLETED") == 0)
474cd4e3c3eSJouni Malinen 			return iface;
475cd4e3c3eSJouni Malinen 		iface = pos;
476cd4e3c3eSJouni Malinen 	}
477cd4e3c3eSJouni Malinen 
478cd4e3c3eSJouni Malinen 	return ifname;
479cd4e3c3eSJouni Malinen }
480cd4e3c3eSJouni Malinen 
481cd4e3c3eSJouni Malinen 
482cd4e3c3eSJouni Malinen static int p2p_peer_known(const char *ifname, const char *peer, int full)
483cd4e3c3eSJouni Malinen {
484cd4e3c3eSJouni Malinen 	char buf[4096];
485cd4e3c3eSJouni Malinen 
486cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "P2P_PEER %s", peer);
487cd4e3c3eSJouni Malinen 	if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0)
488cd4e3c3eSJouni Malinen 		return 0;
489cd4e3c3eSJouni Malinen 	if (strncasecmp(buf, peer, strlen(peer)) != 0)
490cd4e3c3eSJouni Malinen 		return 0;
491cd4e3c3eSJouni Malinen 	if (!full)
492cd4e3c3eSJouni Malinen 		return 1;
493cd4e3c3eSJouni Malinen 	return strstr(buf, "[PROBE_REQ_ONLY]") == NULL ? 1 : 0;
494cd4e3c3eSJouni Malinen }
495cd4e3c3eSJouni Malinen 
496cd4e3c3eSJouni Malinen 
49789b37cdcSAmarnath Hullur Subramanyam int p2p_discover_peer(struct sigma_dut *dut, const char *ifname,
498cd4e3c3eSJouni Malinen 		      const char *peer, int full)
499cd4e3c3eSJouni Malinen {
500cd4e3c3eSJouni Malinen 	unsigned int count;
501cd4e3c3eSJouni Malinen 
502cd4e3c3eSJouni Malinen 	if (p2p_peer_known(ifname, peer, full))
503cd4e3c3eSJouni Malinen 		return 0;
504cd4e3c3eSJouni Malinen 	printf("Peer not yet discovered - start discovery\n");
505a46a453aSPurushottam Kushwaha 	if (wpa_command(ifname, "P2P_FIND type=progressive") < 0) {
506cd4e3c3eSJouni Malinen 		printf("Failed to start discovery\n");
507cd4e3c3eSJouni Malinen 		return -1;
508cd4e3c3eSJouni Malinen 	}
509cd4e3c3eSJouni Malinen 
510cd4e3c3eSJouni Malinen 	count = 0;
511cd4e3c3eSJouni Malinen 	while (count < dut->default_timeout) {
512cd4e3c3eSJouni Malinen 		count++;
513cd4e3c3eSJouni Malinen 		sleep(1);
514cd4e3c3eSJouni Malinen 		if (p2p_peer_known(ifname, peer, full)) {
515cd4e3c3eSJouni Malinen 			printf("Peer discovered - return to previous state\n");
516cd4e3c3eSJouni Malinen 			switch (dut->p2p_mode) {
517cd4e3c3eSJouni Malinen 			case P2P_IDLE:
518cd4e3c3eSJouni Malinen 				wpa_command(ifname, "P2P_STOP_FIND");
519cd4e3c3eSJouni Malinen 				break;
520cd4e3c3eSJouni Malinen 			case P2P_DISCOVER:
521cd4e3c3eSJouni Malinen 				/* Already running discovery */
522cd4e3c3eSJouni Malinen 				break;
523cd4e3c3eSJouni Malinen 			case P2P_LISTEN:
524cd4e3c3eSJouni Malinen 				wpa_command(ifname, "P2P_LISTEN");
525cd4e3c3eSJouni Malinen 				break;
526cd4e3c3eSJouni Malinen 			case P2P_DISABLE:
527cd4e3c3eSJouni Malinen 				printf("Invalid state - P2P was disabled?!\n");
528cd4e3c3eSJouni Malinen 				break;
529cd4e3c3eSJouni Malinen 			}
530cd4e3c3eSJouni Malinen 			return 0;
531cd4e3c3eSJouni Malinen 		}
532cd4e3c3eSJouni Malinen 	}
533cd4e3c3eSJouni Malinen 
534cd4e3c3eSJouni Malinen 	printf("Peer discovery timed out - peer not discovered\n");
535cd4e3c3eSJouni Malinen 	wpa_command(ifname, "P2P_STOP_FIND");
536cd4e3c3eSJouni Malinen 
537cd4e3c3eSJouni Malinen 	return -1;
538cd4e3c3eSJouni Malinen }
539cd4e3c3eSJouni Malinen 
540cd4e3c3eSJouni Malinen 
541cd4e3c3eSJouni Malinen static void add_dummy_services(const char *intf)
542cd4e3c3eSJouni Malinen {
543cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD bonjour 0b5f6166706f766572746370c00c000c01 074578616d706c65c027");
544cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD bonjour 076578616d706c650b5f6166706f766572746370c00c001001 00");
545cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD bonjour 045f697070c00c000c01 094d795072696e746572c027");
546cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD bonjour 096d797072696e746572045f697070c00c001001 09747874766572733d311a70646c3d6170706c69636174696f6e2f706f7374736372797074");
547cd4e3c3eSJouni Malinen 
548cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::upnp:rootdevice");
549cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:5566d33e-9774-09ab-4822-333456785632::upnp:rootdevice");
550cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2");
551cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:5566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2");
552cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1");
553cd4e3c3eSJouni Malinen 
554cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1859dede-8574-59ab-9332-123456789012::upnp:rootdevice");
555cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1566d33e-9774-09ab-4822-333456785632::upnp:rootdevice");
556cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2");
557cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2");
558cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1");
559cd4e3c3eSJouni Malinen 
560cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2859dede-8574-59ab-9332-123456789012::upnp:rootdevice");
561cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2566d33e-9774-09ab-4822-333456785632::upnp:rootdevice");
562cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2");
563cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2");
564cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1");
565cd4e3c3eSJouni Malinen 
566cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3859dede-8574-59ab-9332-123456789012::upnp:rootdevice");
567cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3566d33e-9774-09ab-4822-333456785632::upnp:rootdevice");
568cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:4122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2");
569cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2");
570cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1");
571cd4e3c3eSJouni Malinen }
572cd4e3c3eSJouni Malinen 
573cd4e3c3eSJouni Malinen 
574cd4e3c3eSJouni Malinen void disconnect_station(struct sigma_dut *dut)
575cd4e3c3eSJouni Malinen {
576cd4e3c3eSJouni Malinen 	wpa_command(get_station_ifname(), "DISCONNECT");
577cd4e3c3eSJouni Malinen 	remove_wpa_networks(get_station_ifname());
578cd4e3c3eSJouni Malinen 	dut->infra_ssid[0] = '\0';
579cd4e3c3eSJouni Malinen #ifdef __linux__
580cd4e3c3eSJouni Malinen 	{
581cd4e3c3eSJouni Malinen 		char path[128];
582cd4e3c3eSJouni Malinen 		char buf[200];
583cd4e3c3eSJouni Malinen 		struct stat s;
584cd4e3c3eSJouni Malinen 		snprintf(path, sizeof(path), "/var/run/dhclient-%s.pid",
585cd4e3c3eSJouni Malinen 			 get_station_ifname());
586cd4e3c3eSJouni Malinen 		if (stat(path, &s) == 0) {
587cd4e3c3eSJouni Malinen 			snprintf(buf, sizeof(buf),
588cd4e3c3eSJouni Malinen 				 "kill `cat %s`", path);
589cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG,
590cd4e3c3eSJouni Malinen 					"Kill previous DHCP client: %s", buf);
591cd4e3c3eSJouni Malinen 			run_system(dut, buf);
592cd4e3c3eSJouni Malinen 			unlink(path);
593cd4e3c3eSJouni Malinen 		}
594cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf),
595cd4e3c3eSJouni Malinen 			 "ifconfig %s 0.0.0.0", get_station_ifname());
596cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG,
597cd4e3c3eSJouni Malinen 				"Clear infrastructure station IP address: %s",
598cd4e3c3eSJouni Malinen 				buf);
599cd4e3c3eSJouni Malinen 		run_system(dut, buf);
600cd4e3c3eSJouni Malinen    }
601cd4e3c3eSJouni Malinen #endif /* __linux__ */
602cd4e3c3eSJouni Malinen }
603cd4e3c3eSJouni Malinen 
604cd4e3c3eSJouni Malinen 
605cd4e3c3eSJouni Malinen static int cmd_sta_get_p2p_dev_address(struct sigma_dut *dut,
606cd4e3c3eSJouni Malinen 				       struct sigma_conn *conn,
607cd4e3c3eSJouni Malinen 				       struct sigma_cmd *cmd)
608cd4e3c3eSJouni Malinen {
609cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "interface");
610cd4e3c3eSJouni Malinen 	char buf[100], resp[200];
611cd4e3c3eSJouni Malinen 
612cd4e3c3eSJouni Malinen 	start_sta_mode(dut);
613cd4e3c3eSJouni Malinen 	if (get_wpa_status(intf, "p2p_device_address", buf, sizeof(buf)) < 0) {
614cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, NULL);
615cd4e3c3eSJouni Malinen 		return 0;
616cd4e3c3eSJouni Malinen 	}
617cd4e3c3eSJouni Malinen 
618cd4e3c3eSJouni Malinen 	snprintf(resp, sizeof(resp), "DevID,%s", buf);
619cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
620cd4e3c3eSJouni Malinen 	return 0;
621cd4e3c3eSJouni Malinen }
622cd4e3c3eSJouni Malinen 
623cd4e3c3eSJouni Malinen 
624cd4e3c3eSJouni Malinen static int cmd_sta_set_p2p(struct sigma_dut *dut, struct sigma_conn *conn,
625cd4e3c3eSJouni Malinen 			   struct sigma_cmd *cmd)
626cd4e3c3eSJouni Malinen {
627f2af39bfSDanny Segal 	const char *intf = get_p2p_ifname(get_param(cmd, "Interface"));
628cd4e3c3eSJouni Malinen 	char buf[256];
629cd4e3c3eSJouni Malinen 	const char *val;
630cd4e3c3eSJouni Malinen 	const char *noa_dur, *noa_int, *noa_count;
631cd4e3c3eSJouni Malinen 	const char *ext_listen_int, *ext_listen_period;
632cd4e3c3eSJouni Malinen 
633cd4e3c3eSJouni Malinen 	val = get_param(cmd, "LISTEN_CHN");
634cd4e3c3eSJouni Malinen 	if (val) {
635cd4e3c3eSJouni Malinen 		dut->listen_chn = atoi(val);
636842a4e05SDanny Segal 		if (dut->listen_chn == 2) {
637842a4e05SDanny Segal 			/* social channel 2 on 60 GHz band */
638842a4e05SDanny Segal 			snprintf(buf, sizeof(buf),
639842a4e05SDanny Segal 				 "P2P_SET listen_channel 2 180");
640842a4e05SDanny Segal 		} else {
641842a4e05SDanny Segal 			/* social channels 1/6/11 on 2.4 GHz band */
642cd4e3c3eSJouni Malinen 			snprintf(buf, sizeof(buf), "P2P_SET listen_channel %d",
643cd4e3c3eSJouni Malinen 				 dut->listen_chn);
644842a4e05SDanny Segal 		}
645cd4e3c3eSJouni Malinen 		if (wpa_command(intf, buf) < 0)
646cd4e3c3eSJouni Malinen 			return -2;
647cd4e3c3eSJouni Malinen 	}
648cd4e3c3eSJouni Malinen 
649cd4e3c3eSJouni Malinen 	ext_listen_int = get_param(cmd, "Ext_Listen_Time_Interval");
650cd4e3c3eSJouni Malinen 	ext_listen_period = get_param(cmd, "Ext_Listen_Time_Period");
651cd4e3c3eSJouni Malinen 
652cd4e3c3eSJouni Malinen 	if (ext_listen_int || ext_listen_period) {
653cd4e3c3eSJouni Malinen 		if (!ext_listen_int || !ext_listen_period) {
654cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO, "Only one "
655cd4e3c3eSJouni Malinen 					"ext_listen_time parameter included; "
656cd4e3c3eSJouni Malinen 					"both are needed");
657cd4e3c3eSJouni Malinen 			return -1;
658cd4e3c3eSJouni Malinen 		}
659cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_EXT_LISTEN %d %d",
660cd4e3c3eSJouni Malinen 			 atoi(ext_listen_period),
661cd4e3c3eSJouni Malinen 			 atoi(ext_listen_int));
662cd4e3c3eSJouni Malinen 		if (wpa_command(intf, buf) < 0)
663cd4e3c3eSJouni Malinen 			return -2;
664cd4e3c3eSJouni Malinen 	}
665cd4e3c3eSJouni Malinen 
666cd4e3c3eSJouni Malinen 	val = get_param(cmd, "P2P_MODE");
667cd4e3c3eSJouni Malinen 	if (val) {
668cd4e3c3eSJouni Malinen 		if (strcasecmp(val, "Listen") == 0) {
669cd4e3c3eSJouni Malinen 			wpa_command(intf, "P2P_SET disabled 0");
670cd4e3c3eSJouni Malinen 			if (wpa_command(intf, "P2P_LISTEN") < 0)
671cd4e3c3eSJouni Malinen 				return -2;
672cd4e3c3eSJouni Malinen 			dut->p2p_mode = P2P_LISTEN;
673cd4e3c3eSJouni Malinen 		} else if (strcasecmp(val, "Discover") == 0) {
674cd4e3c3eSJouni Malinen 			wpa_command(intf, "P2P_SET disabled 0");
675cd4e3c3eSJouni Malinen 			if (wpa_command(intf, "P2P_FIND") < 0)
676cd4e3c3eSJouni Malinen 				return -2;
677cd4e3c3eSJouni Malinen 			dut->p2p_mode = P2P_DISCOVER;
678cd4e3c3eSJouni Malinen 		} else if (strcasecmp(val, "Idle") == 0) {
679cd4e3c3eSJouni Malinen 			wpa_command(intf, "P2P_SET disabled 0");
680cd4e3c3eSJouni Malinen 			if (wpa_command(intf, "P2P_STOP_FIND") < 0)
681cd4e3c3eSJouni Malinen 				return -2;
682cd4e3c3eSJouni Malinen 			dut->p2p_mode = P2P_IDLE;
683cd4e3c3eSJouni Malinen 		} else if (strcasecmp(val, "Disable") == 0) {
684cd4e3c3eSJouni Malinen 			if (wpa_command(intf, "P2P_SET disabled 1") < 0)
685cd4e3c3eSJouni Malinen 				return -2;
686cd4e3c3eSJouni Malinen 			dut->p2p_mode = P2P_DISABLE;
687cd4e3c3eSJouni Malinen 		} else
688cd4e3c3eSJouni Malinen 			return -1;
689cd4e3c3eSJouni Malinen 	}
690cd4e3c3eSJouni Malinen 
691cd4e3c3eSJouni Malinen 	val = get_param(cmd, "PERSISTENT");
692cd4e3c3eSJouni Malinen 	if (val) {
693cd4e3c3eSJouni Malinen 		dut->persistent = atoi(val);
694cd4e3c3eSJouni Malinen 	}
695cd4e3c3eSJouni Malinen 
696cd4e3c3eSJouni Malinen 	val = get_param(cmd, "INTRA_BSS");
697cd4e3c3eSJouni Malinen 	if (val) {
698cd4e3c3eSJouni Malinen 		int intra_bss = atoi(val);
699cd4e3c3eSJouni Malinen 		/* TODO: add support for this */
700cd4e3c3eSJouni Malinen 		if (!intra_bss) {
701cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO, "Disabling of "
702cd4e3c3eSJouni Malinen 					"intra-BSS bridging not supported");
703cd4e3c3eSJouni Malinen 			return -1;
704cd4e3c3eSJouni Malinen 		}
705cd4e3c3eSJouni Malinen 		dut->intra_bss = intra_bss;
706cd4e3c3eSJouni Malinen 	}
707cd4e3c3eSJouni Malinen 
70845c3c474SDanny Segal 	/* NoA is not applicable for 60 GHz */
70945c3c474SDanny Segal 	if (dut->program != PROGRAM_60GHZ) {
710cd4e3c3eSJouni Malinen 		noa_dur = get_param(cmd, "NoA_duration");
711cd4e3c3eSJouni Malinen 		noa_int = get_param(cmd, "NoA_Interval");
712cd4e3c3eSJouni Malinen 		noa_count = get_param(cmd, "NoA_Count");
713cd4e3c3eSJouni Malinen 		if (noa_dur)
714cd4e3c3eSJouni Malinen 			dut->noa_duration = atoi(noa_dur);
715cd4e3c3eSJouni Malinen 
716cd4e3c3eSJouni Malinen 		if (noa_int)
717cd4e3c3eSJouni Malinen 			dut->noa_interval = atoi(noa_int);
718cd4e3c3eSJouni Malinen 
719cd4e3c3eSJouni Malinen 		if (noa_count)
720cd4e3c3eSJouni Malinen 			dut->noa_count = atoi(noa_count);
721cd4e3c3eSJouni Malinen 
722cd4e3c3eSJouni Malinen 		if (noa_dur || noa_int || noa_count) {
723cd4e3c3eSJouni Malinen 			int start;
724cd4e3c3eSJouni Malinen 			const char *ifname;
725cd4e3c3eSJouni Malinen 			if (dut->noa_count == 0 && dut->noa_duration == 0)
726cd4e3c3eSJouni Malinen 				start = 0;
72745c3c474SDanny Segal 			else if (dut->noa_duration > 102) /* likely non-periodic
72845c3c474SDanny Segal 							   * NoA */
729cd4e3c3eSJouni Malinen 				start = 50;
730cd4e3c3eSJouni Malinen 			else
731cd4e3c3eSJouni Malinen 				start = 102 - dut->noa_duration;
732cd4e3c3eSJouni Malinen 			snprintf(buf, sizeof(buf), "P2P_SET noa %d,%d,%d",
733cd4e3c3eSJouni Malinen 				dut->noa_count, start,
734cd4e3c3eSJouni Malinen 				dut->noa_duration);
735cd4e3c3eSJouni Malinen 			ifname = get_group_ifname(dut, intf);
736cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO,
737cd4e3c3eSJouni Malinen 					"Set GO NoA for interface %s", ifname);
738cd4e3c3eSJouni Malinen 			if (wpa_command(ifname, buf) < 0) {
739cd4e3c3eSJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
740cd4e3c3eSJouni Malinen 					  "errorCode,Use of NoA as GO not supported");
741cd4e3c3eSJouni Malinen 				return 0;
742cd4e3c3eSJouni Malinen 			}
743cd4e3c3eSJouni Malinen 		}
74445c3c474SDanny Segal 	}
745cd4e3c3eSJouni Malinen 
746cd4e3c3eSJouni Malinen 	val = get_param(cmd, "Concurrency");
747cd4e3c3eSJouni Malinen 	if (val) {
748cd4e3c3eSJouni Malinen 		/* TODO */
749cd4e3c3eSJouni Malinen 	}
750cd4e3c3eSJouni Malinen 
751cd4e3c3eSJouni Malinen 	val = get_param(cmd, "P2PInvitation");
752cd4e3c3eSJouni Malinen 	if (val) {
753cd4e3c3eSJouni Malinen 		/* TODO */
754cd4e3c3eSJouni Malinen 	}
755cd4e3c3eSJouni Malinen 
756cd4e3c3eSJouni Malinen 	val = get_param(cmd, "BCN_INT");
757cd4e3c3eSJouni Malinen 	if (val) {
758cd4e3c3eSJouni Malinen 		/* TODO */
759cd4e3c3eSJouni Malinen 	}
760cd4e3c3eSJouni Malinen 
761cd4e3c3eSJouni Malinen 	val = get_param(cmd, "Discoverability");
762cd4e3c3eSJouni Malinen 	if (val) {
763cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_SET discoverability %d",
764cd4e3c3eSJouni Malinen 			 atoi(val));
765cd4e3c3eSJouni Malinen 		if (wpa_command(intf, buf) < 0)
766cd4e3c3eSJouni Malinen 			return -2;
767cd4e3c3eSJouni Malinen 	}
768cd4e3c3eSJouni Malinen 
769cd4e3c3eSJouni Malinen 	val = get_param(cmd, "Service_Discovery");
770cd4e3c3eSJouni Malinen 	if (val) {
771cd4e3c3eSJouni Malinen 		int sd = atoi(val);
772cd4e3c3eSJouni Malinen 		if (sd) {
773cd4e3c3eSJouni Malinen 			wpa_command(intf, "P2P_SERVICE_FLUSH");
774cd4e3c3eSJouni Malinen 
775cd4e3c3eSJouni Malinen 			if (sd == 2)
776cd4e3c3eSJouni Malinen 				wpa_command(intf, "P2P_SET force_long_sd 1");
777cd4e3c3eSJouni Malinen 
778cd4e3c3eSJouni Malinen 			/*
779cd4e3c3eSJouni Malinen 			 * Set up some dummy service to create a large SD
780cd4e3c3eSJouni Malinen 			 * response that requires fragmentation.
781cd4e3c3eSJouni Malinen 			 */
782cd4e3c3eSJouni Malinen 			add_dummy_services(intf);
783cd4e3c3eSJouni Malinen 		} else {
784cd4e3c3eSJouni Malinen 			wpa_command(intf, "P2P_SERVICE_FLUSH");
785cd4e3c3eSJouni Malinen 		}
786cd4e3c3eSJouni Malinen 	}
787cd4e3c3eSJouni Malinen 
788cd4e3c3eSJouni Malinen 	val = get_param(cmd, "CrossConnection");
789cd4e3c3eSJouni Malinen 	if (val) {
790cd4e3c3eSJouni Malinen 		if (atoi(val)) {
791cd4e3c3eSJouni Malinen 			if (wpa_command(intf, "P2P_SET cross_connect 1") < 0)
792cd4e3c3eSJouni Malinen 				return -2;
793cd4e3c3eSJouni Malinen 		} else {
794cd4e3c3eSJouni Malinen 			if (wpa_command(intf, "P2P_SET cross_connect 0") < 0)
795cd4e3c3eSJouni Malinen 				return -2;
796cd4e3c3eSJouni Malinen 		}
797cd4e3c3eSJouni Malinen 	}
798cd4e3c3eSJouni Malinen 
799cd4e3c3eSJouni Malinen 	val = get_param(cmd, "P2PManaged");
800cd4e3c3eSJouni Malinen 	if (val) {
801cd4e3c3eSJouni Malinen 		if (atoi(val)) {
802cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_INVALID, "ErrorCode,"
803cd4e3c3eSJouni Malinen 				  "P2P Managed functionality not supported");
804cd4e3c3eSJouni Malinen 			return 0;
805cd4e3c3eSJouni Malinen 		}
806cd4e3c3eSJouni Malinen 	}
807cd4e3c3eSJouni Malinen 
808cd4e3c3eSJouni Malinen 	val = get_param(cmd, "GO_APSD");
809cd4e3c3eSJouni Malinen 	if (val) {
810cd4e3c3eSJouni Malinen 		if (atoi(val)) {
811cd4e3c3eSJouni Malinen 			if (wpa_command(intf, "P2P_SET go_apsd 1") < 0)
812cd4e3c3eSJouni Malinen 				return -2;
813cd4e3c3eSJouni Malinen 		} else {
814cd4e3c3eSJouni Malinen 			if (wpa_command(intf, "P2P_SET go_apsd 0") < 0)
815cd4e3c3eSJouni Malinen 				return -2;
816cd4e3c3eSJouni Malinen 		}
817cd4e3c3eSJouni Malinen 	}
818cd4e3c3eSJouni Malinen 
819cd4e3c3eSJouni Malinen 	return 1;
820cd4e3c3eSJouni Malinen }
821cd4e3c3eSJouni Malinen 
822cd4e3c3eSJouni Malinen 
823cd4e3c3eSJouni Malinen static int cmd_sta_start_autonomous_go(struct sigma_dut *dut,
824cd4e3c3eSJouni Malinen 				       struct sigma_conn *conn,
825cd4e3c3eSJouni Malinen 				       struct sigma_cmd *cmd)
826cd4e3c3eSJouni Malinen {
8270591d455SAlexei Avshalom Lazar 	const char *intf = get_p2p_ifname(get_param(cmd, "Interface"));
828cd4e3c3eSJouni Malinen 	const char *oper_chn = get_param(cmd, "OPER_CHN");
829cd4e3c3eSJouni Malinen 	const char *ssid_param = get_param(cmd, "SSID");
8309c381f59SAmarnath Hullur Subramanyam #ifdef MIRACAST
8319c381f59SAmarnath Hullur Subramanyam 	const char *rtsp = get_param(cmd, "RTSP");
8329c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
833cd4e3c3eSJouni Malinen 	int freq, chan, res;
834cd4e3c3eSJouni Malinen 	char buf[256], grpid[100], resp[200];
835cd4e3c3eSJouni Malinen 	struct wpa_ctrl *ctrl;
836cd4e3c3eSJouni Malinen 	char *ifname, *gtype, *pos, *ssid, bssid[20];
837cd4e3c3eSJouni Malinen 	char *go_dev_addr;
838cd4e3c3eSJouni Malinen 
839cd4e3c3eSJouni Malinen 	if (oper_chn == NULL)
840cd4e3c3eSJouni Malinen 		return -1;
841cd4e3c3eSJouni Malinen 
842cd4e3c3eSJouni Malinen 	chan = atoi(oper_chn);
8439e390a52SDanny Segal 	if (dut->program == PROGRAM_60GHZ) {
8449e390a52SDanny Segal 		freq = get_60g_freq(chan);
8459e390a52SDanny Segal 		if (freq == 0) {
8469e390a52SDanny Segal 			sigma_dut_print(dut, DUT_MSG_ERROR,
8479e390a52SDanny Segal 					"Invalid channel: %d", chan);
8489e390a52SDanny Segal 			return -1;
8499e390a52SDanny Segal 		}
8509e390a52SDanny Segal 	} else if (chan >= 1 && chan <= 13)
851cd4e3c3eSJouni Malinen 		freq = 2407 + chan * 5;
852cd4e3c3eSJouni Malinen 	else if (chan == 14)
853cd4e3c3eSJouni Malinen 		freq = 2484;
8548086d188SPradeep Reddy POTTETI 	else if (chan >= 36 && chan <= 165)
855cd4e3c3eSJouni Malinen 		freq = 5000 + chan * 5;
8568086d188SPradeep Reddy POTTETI 	else {
8578086d188SPradeep Reddy POTTETI 		sigma_dut_print(dut, DUT_MSG_ERROR,
8588086d188SPradeep Reddy POTTETI 				"Invalid channel: %d", chan);
8598086d188SPradeep Reddy POTTETI 		return -1;
8608086d188SPradeep Reddy POTTETI 	}
861cd4e3c3eSJouni Malinen 
862cd4e3c3eSJouni Malinen 	if (ssid_param)
863cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix %s",
864cd4e3c3eSJouni Malinen 			 ssid_param);
865cd4e3c3eSJouni Malinen 	else
866cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix ");
867cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0)
868cd4e3c3eSJouni Malinen 		return -2;
869cd4e3c3eSJouni Malinen 
870cd4e3c3eSJouni Malinen 	/* Stop Listen/Discovery state to avoid issues with GO operations */
871cd4e3c3eSJouni Malinen 	if (wpa_command(intf, "P2P_STOP_FIND") < 0)
872cd4e3c3eSJouni Malinen 		return -2;
873cd4e3c3eSJouni Malinen 
874cd4e3c3eSJouni Malinen 	ctrl = open_wpa_mon(intf);
875cd4e3c3eSJouni Malinen 	if (ctrl == NULL) {
876cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
877cd4e3c3eSJouni Malinen 				"wpa_supplicant monitor connection");
878cd4e3c3eSJouni Malinen 		return -2;
879cd4e3c3eSJouni Malinen 	}
880cd4e3c3eSJouni Malinen 
881cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "P2P_GROUP_ADD %sfreq=%d",
882cd4e3c3eSJouni Malinen 		 dut->persistent ? "persistent " : "", freq);
883cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0) {
884cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
885cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
886cd4e3c3eSJouni Malinen 		return -2;
887cd4e3c3eSJouni Malinen 	}
888cd4e3c3eSJouni Malinen 
889cd4e3c3eSJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "P2P-GROUP-STARTED",
890cd4e3c3eSJouni Malinen 				buf, sizeof(buf));
891cd4e3c3eSJouni Malinen 
892cd4e3c3eSJouni Malinen 	wpa_ctrl_detach(ctrl);
893cd4e3c3eSJouni Malinen 	wpa_ctrl_close(ctrl);
894cd4e3c3eSJouni Malinen 
895cd4e3c3eSJouni Malinen 	if (res < 0) {
896cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,GO starting "
897cd4e3c3eSJouni Malinen 			  "did not complete");
898cd4e3c3eSJouni Malinen 		return 0;
899cd4e3c3eSJouni Malinen 	}
900cd4e3c3eSJouni Malinen 
901cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group started event '%s'", buf);
902cd4e3c3eSJouni Malinen 	ifname = strchr(buf, ' ');
903cd4e3c3eSJouni Malinen 	if (ifname == NULL)
904cd4e3c3eSJouni Malinen 		return -2;
905cd4e3c3eSJouni Malinen 	ifname++;
906cd4e3c3eSJouni Malinen 	pos = strchr(ifname, ' ');
907cd4e3c3eSJouni Malinen 	if (pos == NULL)
908cd4e3c3eSJouni Malinen 		return -2;
909cd4e3c3eSJouni Malinen 	*pos++ = '\0';
910cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group interface %s", ifname);
911cd4e3c3eSJouni Malinen 
912cd4e3c3eSJouni Malinen 	gtype = pos;
913cd4e3c3eSJouni Malinen 	pos = strchr(gtype, ' ');
914cd4e3c3eSJouni Malinen 	if (pos == NULL)
915cd4e3c3eSJouni Malinen 		return -2;
916cd4e3c3eSJouni Malinen 	*pos++ = '\0';
917cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group type %s", gtype);
918cd4e3c3eSJouni Malinen 
919cd4e3c3eSJouni Malinen 	ssid = strstr(pos, "ssid=\"");
920cd4e3c3eSJouni Malinen 	if (ssid == NULL)
921cd4e3c3eSJouni Malinen 		return -2;
922cd4e3c3eSJouni Malinen 	ssid += 6;
923cd4e3c3eSJouni Malinen 	pos = strchr(ssid, '"');
924cd4e3c3eSJouni Malinen 	if (pos == NULL)
925cd4e3c3eSJouni Malinen 		return -2;
926cd4e3c3eSJouni Malinen 	*pos++ = '\0';
927cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group SSID %s", ssid);
928cd4e3c3eSJouni Malinen 
929cd4e3c3eSJouni Malinen 	go_dev_addr = strstr(pos, "go_dev_addr=");
930cd4e3c3eSJouni Malinen 	if (go_dev_addr == NULL) {
931cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "No GO P2P Device Address "
932cd4e3c3eSJouni Malinen 				"found");
933cd4e3c3eSJouni Malinen 		return -2;
934cd4e3c3eSJouni Malinen 	}
935cd4e3c3eSJouni Malinen 	go_dev_addr += 12;
936cd4e3c3eSJouni Malinen 	if (strlen(go_dev_addr) < 17) {
937cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Too short GO P2P Device "
938cd4e3c3eSJouni Malinen 				"Address '%s'", go_dev_addr);
939cd4e3c3eSJouni Malinen 		return -2;
940cd4e3c3eSJouni Malinen 	}
941cd4e3c3eSJouni Malinen 	go_dev_addr[17] = '\0';
942cd4e3c3eSJouni Malinen 	*pos = '\0';
943cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "GO P2P Device Address %s",
944cd4e3c3eSJouni Malinen 			go_dev_addr);
945cd4e3c3eSJouni Malinen 
946cd4e3c3eSJouni Malinen 	if (get_wpa_status(ifname, "bssid", bssid, sizeof(bssid)) < 0)
947cd4e3c3eSJouni Malinen 		return -2;
948cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group BSSID %s", bssid);
949cd4e3c3eSJouni Malinen 
950cd4e3c3eSJouni Malinen 	snprintf(grpid, sizeof(grpid), "%s %s", go_dev_addr, ssid);
951cd4e3c3eSJouni Malinen 	p2p_group_add(dut, ifname, strcmp(gtype, "GO") == 0, grpid, ssid);
952cd4e3c3eSJouni Malinen 
953cd4e3c3eSJouni Malinen 	snprintf(resp, sizeof(resp), "GroupID,%s", grpid);
9549c381f59SAmarnath Hullur Subramanyam 
9559c381f59SAmarnath Hullur Subramanyam #ifdef MIRACAST
9569c381f59SAmarnath Hullur Subramanyam 	if (rtsp && atoi(rtsp) == 1) {
9579c381f59SAmarnath Hullur Subramanyam 		/* Start RTSP Thread for incoming connections */
9589c381f59SAmarnath Hullur Subramanyam 		miracast_start_autonomous_go(dut, conn, cmd, ifname);
9599c381f59SAmarnath Hullur Subramanyam 	}
9609c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
9619c381f59SAmarnath Hullur Subramanyam 
962cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
963cd4e3c3eSJouni Malinen 	return 0;
964cd4e3c3eSJouni Malinen }
965cd4e3c3eSJouni Malinen 
966cd4e3c3eSJouni Malinen 
967cd4e3c3eSJouni Malinen static int cmd_sta_p2p_connect(struct sigma_dut *dut, struct sigma_conn *conn,
968cd4e3c3eSJouni Malinen 			       struct sigma_cmd *cmd)
969cd4e3c3eSJouni Malinen {
970f2af39bfSDanny Segal 	const char *intf = get_p2p_ifname(get_param(cmd, "Interface"));
971cd4e3c3eSJouni Malinen 	const char *devid = get_param(cmd, "P2PDevID");
972cd4e3c3eSJouni Malinen 	/* const char *grpid_param = get_param(cmd, "GroupID"); */
973cd4e3c3eSJouni Malinen 	int res;
974cd4e3c3eSJouni Malinen 	char buf[256];
975cd4e3c3eSJouni Malinen 	struct wpa_ctrl *ctrl;
976cd4e3c3eSJouni Malinen 	char *ifname, *gtype, *pos, *ssid, bssid[20];
977cd4e3c3eSJouni Malinen 	char grpid[100];
978cd4e3c3eSJouni Malinen 
979cd4e3c3eSJouni Malinen 	/* TODO: handle the new grpid argument */
980cd4e3c3eSJouni Malinen 
981cd4e3c3eSJouni Malinen 	if (devid == NULL)
982cd4e3c3eSJouni Malinen 		return -1;
983cd4e3c3eSJouni Malinen 
984cd4e3c3eSJouni Malinen 	if (dut->wps_method == WFA_CS_WPS_NOT_READY) {
985cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS parameters "
986cd4e3c3eSJouni Malinen 			  "not yet set");
987cd4e3c3eSJouni Malinen 		return 0;
988cd4e3c3eSJouni Malinen 	}
989cd4e3c3eSJouni Malinen 
990cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover GO %s", devid);
991cd4e3c3eSJouni Malinen 	if (p2p_discover_peer(dut, intf, devid, 1) < 0) {
992cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
993cd4e3c3eSJouni Malinen 			  "discover the requested peer");
994cd4e3c3eSJouni Malinen 		return 0;
995cd4e3c3eSJouni Malinen 	}
996cd4e3c3eSJouni Malinen 
997cd4e3c3eSJouni Malinen 	ctrl = open_wpa_mon(intf);
998cd4e3c3eSJouni Malinen 	if (ctrl == NULL) {
999cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
1000cd4e3c3eSJouni Malinen 				"wpa_supplicant monitor connection");
1001cd4e3c3eSJouni Malinen 		return -2;
1002cd4e3c3eSJouni Malinen 	}
1003cd4e3c3eSJouni Malinen 
1004cd4e3c3eSJouni Malinen 	switch (dut->wps_method) {
1005cd4e3c3eSJouni Malinen 	case WFA_CS_WPS_PBC:
1006cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_CONNECT %s pbc join",
1007cd4e3c3eSJouni Malinen 			 devid);
1008cd4e3c3eSJouni Malinen 		break;
1009cd4e3c3eSJouni Malinen 	case WFA_CS_WPS_PIN_DISPLAY:
1010cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s display join",
1011cd4e3c3eSJouni Malinen 			 devid, dut->wps_pin);
1012cd4e3c3eSJouni Malinen 		break;
1013cd4e3c3eSJouni Malinen 	case WFA_CS_WPS_PIN_KEYPAD:
1014cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s keypad join",
1015cd4e3c3eSJouni Malinen 			 devid, dut->wps_pin);
1016cd4e3c3eSJouni Malinen 		break;
1017cd4e3c3eSJouni Malinen 	default:
1018cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unknown WPS "
1019cd4e3c3eSJouni Malinen 			  "method for sta_p2p_connect");
1020cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
1021cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
1022cd4e3c3eSJouni Malinen 		return 0;
1023cd4e3c3eSJouni Malinen 	}
1024cd4e3c3eSJouni Malinen 
1025cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0) {
1026cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to join "
1027cd4e3c3eSJouni Malinen 			  "the group");
1028cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
1029cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
1030cd4e3c3eSJouni Malinen 		return 0;
1031cd4e3c3eSJouni Malinen 	}
1032cd4e3c3eSJouni Malinen 
1033cd4e3c3eSJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "P2P-GROUP-STARTED",
1034cd4e3c3eSJouni Malinen 				buf, sizeof(buf));
1035cd4e3c3eSJouni Malinen 
1036cd4e3c3eSJouni Malinen 	wpa_ctrl_detach(ctrl);
1037cd4e3c3eSJouni Malinen 	wpa_ctrl_close(ctrl);
1038cd4e3c3eSJouni Malinen 
1039cd4e3c3eSJouni Malinen 	if (res < 0) {
1040cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Group joining "
1041cd4e3c3eSJouni Malinen 			  "did not complete");
1042cd4e3c3eSJouni Malinen 		return 0;
1043cd4e3c3eSJouni Malinen 	}
1044cd4e3c3eSJouni Malinen 
1045cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group started event '%s'", buf);
1046cd4e3c3eSJouni Malinen 	ifname = strchr(buf, ' ');
1047cd4e3c3eSJouni Malinen 	if (ifname == NULL)
1048cd4e3c3eSJouni Malinen 		return -2;
1049cd4e3c3eSJouni Malinen 	ifname++;
1050cd4e3c3eSJouni Malinen 	pos = strchr(ifname, ' ');
1051cd4e3c3eSJouni Malinen 	if (pos == NULL)
1052cd4e3c3eSJouni Malinen 		return -2;
1053cd4e3c3eSJouni Malinen 	*pos++ = '\0';
1054cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group interface %s", ifname);
1055cd4e3c3eSJouni Malinen 
1056cd4e3c3eSJouni Malinen 	gtype = pos;
1057cd4e3c3eSJouni Malinen 	pos = strchr(gtype, ' ');
1058cd4e3c3eSJouni Malinen 	if (pos == NULL)
1059cd4e3c3eSJouni Malinen 		return -2;
1060cd4e3c3eSJouni Malinen 	*pos++ = '\0';
1061cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group type %s", gtype);
1062cd4e3c3eSJouni Malinen 
1063cd4e3c3eSJouni Malinen 	ssid = strstr(pos, "ssid=\"");
1064cd4e3c3eSJouni Malinen 	if (ssid == NULL)
1065cd4e3c3eSJouni Malinen 		return -2;
1066cd4e3c3eSJouni Malinen 	ssid += 6;
1067cd4e3c3eSJouni Malinen 	pos = strchr(ssid, '"');
1068cd4e3c3eSJouni Malinen 	if (pos == NULL)
1069cd4e3c3eSJouni Malinen 		return -2;
1070cd4e3c3eSJouni Malinen 	*pos = '\0';
1071cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group SSID %s", ssid);
1072cd4e3c3eSJouni Malinen 
1073cd4e3c3eSJouni Malinen 	if (get_wpa_status(ifname, "bssid", bssid, sizeof(bssid)) < 0)
1074cd4e3c3eSJouni Malinen 		return -2;
1075cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group BSSID %s", bssid);
1076cd4e3c3eSJouni Malinen 
1077cd4e3c3eSJouni Malinen 	snprintf(grpid, sizeof(grpid), "%s %s", bssid, ssid);
1078cd4e3c3eSJouni Malinen 	p2p_group_add(dut, ifname, strcmp(gtype, "GO") == 0, grpid, ssid);
1079cd4e3c3eSJouni Malinen 
1080cd4e3c3eSJouni Malinen 	return 1;
1081cd4e3c3eSJouni Malinen }
1082cd4e3c3eSJouni Malinen 
1083cd4e3c3eSJouni Malinen 
1084cd4e3c3eSJouni Malinen static int p2p_group_formation_event(struct sigma_dut *dut,
1085cd4e3c3eSJouni Malinen 				     struct sigma_conn *conn,
1086cd4e3c3eSJouni Malinen 				     struct wpa_ctrl *ctrl,
1087cd4e3c3eSJouni Malinen 				     const char *intf, const char *peer_role,
1088cd4e3c3eSJouni Malinen 				     int nfc);
1089cd4e3c3eSJouni Malinen 
1090cd4e3c3eSJouni Malinen static int cmd_sta_p2p_start_group_formation(struct sigma_dut *dut,
1091cd4e3c3eSJouni Malinen 					     struct sigma_conn *conn,
1092cd4e3c3eSJouni Malinen 					     struct sigma_cmd *cmd)
1093cd4e3c3eSJouni Malinen {
1094f2af39bfSDanny Segal 	const char *intf = get_p2p_ifname(get_param(cmd, "Interface"));
1095cd4e3c3eSJouni Malinen 	const char *devid = get_param(cmd, "P2PDevID");
1096cd4e3c3eSJouni Malinen 	const char *intent_val = get_param(cmd, "INTENT_VAL");
1097cd4e3c3eSJouni Malinen 	const char *init_go_neg = get_param(cmd, "INIT_GO_NEG");
1098cd4e3c3eSJouni Malinen 	const char *oper_chn = get_param(cmd, "OPER_CHN");
1099cd4e3c3eSJouni Malinen 	const char *ssid_param = get_param(cmd, "SSID");
11009e390a52SDanny Segal 	int freq = 0, chan = 0, init;
1101cd4e3c3eSJouni Malinen 	char buf[256];
1102cd4e3c3eSJouni Malinen 	struct wpa_ctrl *ctrl;
11039c381f59SAmarnath Hullur Subramanyam 	int intent;
1104cd4e3c3eSJouni Malinen 
1105cd4e3c3eSJouni Malinen 	if (devid == NULL || intent_val == NULL)
1106cd4e3c3eSJouni Malinen 		return -1;
1107cd4e3c3eSJouni Malinen 
11089c381f59SAmarnath Hullur Subramanyam 	intent = atoi(intent_val);
11099c381f59SAmarnath Hullur Subramanyam 	if (intent > 15)
11109c381f59SAmarnath Hullur Subramanyam 		intent = 1;
1111cd4e3c3eSJouni Malinen 	if (init_go_neg)
1112cd4e3c3eSJouni Malinen 		init = atoi(init_go_neg);
1113cd4e3c3eSJouni Malinen 	else
1114cd4e3c3eSJouni Malinen 		init = 0;
1115cd4e3c3eSJouni Malinen 
11169e390a52SDanny Segal 	if (dut->program == PROGRAM_60GHZ) {
11179e390a52SDanny Segal 		if (!oper_chn)
11189e390a52SDanny Segal 			return -1;
11199e390a52SDanny Segal 		chan = atoi(oper_chn);
11209e390a52SDanny Segal 		freq = get_60g_freq(chan);
11219e390a52SDanny Segal 		if (freq == 0) {
11229e390a52SDanny Segal 			sigma_dut_print(dut, DUT_MSG_ERROR,
11239e390a52SDanny Segal 					"Invalid channel: %d", chan);
11249e390a52SDanny Segal 			return -1;
11259e390a52SDanny Segal 		}
11269e390a52SDanny Segal 	} else if (oper_chn) {
1127cd4e3c3eSJouni Malinen 		chan = atoi(oper_chn);
1128cd4e3c3eSJouni Malinen 		if (chan >= 1 && chan <= 13)
1129cd4e3c3eSJouni Malinen 			freq = 2407 + chan * 5;
1130cd4e3c3eSJouni Malinen 		else if (chan == 14)
1131cd4e3c3eSJouni Malinen 			freq = 2484;
11328086d188SPradeep Reddy POTTETI 		else if (chan >= 36 && chan <= 165)
1133cd4e3c3eSJouni Malinen 			freq = 5000 + chan * 5;
11348086d188SPradeep Reddy POTTETI 		else {
11358086d188SPradeep Reddy POTTETI 			sigma_dut_print(dut, DUT_MSG_ERROR,
11368086d188SPradeep Reddy POTTETI 					"Invalid channel: %d", chan);
11378086d188SPradeep Reddy POTTETI 			return -1;
11388086d188SPradeep Reddy POTTETI 		}
1139cd4e3c3eSJouni Malinen 	}
1140cd4e3c3eSJouni Malinen 
1141cd4e3c3eSJouni Malinen 	if (dut->wps_method == WFA_CS_WPS_NOT_READY) {
1142cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS parameters "
1143cd4e3c3eSJouni Malinen 			  "not yet set");
1144cd4e3c3eSJouni Malinen 		return 0;
1145cd4e3c3eSJouni Malinen 	}
1146cd4e3c3eSJouni Malinen 
11479e390a52SDanny Segal 	sigma_dut_print(dut, DUT_MSG_DEBUG,
11489e390a52SDanny Segal 			"Trying to discover peer %s for group formation chan %d (freq %d)",
11499e390a52SDanny Segal 			devid, chan, freq);
1150cd4e3c3eSJouni Malinen 	if (p2p_discover_peer(dut, intf, devid, init) < 0) {
1151cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
1152cd4e3c3eSJouni Malinen 			  "discover the requested peer");
1153cd4e3c3eSJouni Malinen 		return 0;
1154cd4e3c3eSJouni Malinen 	}
1155cd4e3c3eSJouni Malinen 
1156cd4e3c3eSJouni Malinen 	if (ssid_param)
1157cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix %s",
1158cd4e3c3eSJouni Malinen 			 ssid_param);
1159cd4e3c3eSJouni Malinen 	else
1160cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix ");
1161cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0)
1162cd4e3c3eSJouni Malinen 		return -2;
1163cd4e3c3eSJouni Malinen 
1164cd4e3c3eSJouni Malinen 	if (init) {
1165cd4e3c3eSJouni Malinen 		ctrl = open_wpa_mon(intf);
1166cd4e3c3eSJouni Malinen 		if (ctrl == NULL) {
1167cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
1168cd4e3c3eSJouni Malinen 					"wpa_supplicant monitor connection");
1169cd4e3c3eSJouni Malinen 			return -2;
1170cd4e3c3eSJouni Malinen 		}
1171cd4e3c3eSJouni Malinen 	} else
1172cd4e3c3eSJouni Malinen 		ctrl = NULL;
1173cd4e3c3eSJouni Malinen 
1174cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s%s%s%s go_intent=%d",
1175cd4e3c3eSJouni Malinen 		 devid,
1176cd4e3c3eSJouni Malinen 		 dut->wps_method == WFA_CS_WPS_PBC ?
1177cd4e3c3eSJouni Malinen 		 "pbc" : dut->wps_pin,
1178cd4e3c3eSJouni Malinen 		 dut->wps_method == WFA_CS_WPS_PBC ? "" :
1179cd4e3c3eSJouni Malinen 		 (dut->wps_method == WFA_CS_WPS_PIN_DISPLAY ? " display" :
1180cd4e3c3eSJouni Malinen 		  (dut->wps_method == WFA_CS_WPS_PIN_LABEL ? " label" :
1181cd4e3c3eSJouni Malinen 		   " keypad" )),
1182cd4e3c3eSJouni Malinen 		 dut->persistent ? " persistent" : "",
1183cd4e3c3eSJouni Malinen 		 init ? "" : " auth",
11849c381f59SAmarnath Hullur Subramanyam 		 intent);
1185cd4e3c3eSJouni Malinen 	if (freq > 0) {
1186cd4e3c3eSJouni Malinen 		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1187cd4e3c3eSJouni Malinen 			 " freq=%d", freq);
1188cd4e3c3eSJouni Malinen 	}
1189cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0) {
1190cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to start "
1191cd4e3c3eSJouni Malinen 			  "group formation");
1192cd4e3c3eSJouni Malinen 		if (ctrl) {
1193cd4e3c3eSJouni Malinen 			wpa_ctrl_detach(ctrl);
1194cd4e3c3eSJouni Malinen 			wpa_ctrl_close(ctrl);
1195cd4e3c3eSJouni Malinen 		}
1196cd4e3c3eSJouni Malinen 		return 0;
1197cd4e3c3eSJouni Malinen 	}
1198cd4e3c3eSJouni Malinen 
1199cd4e3c3eSJouni Malinen 	if (!init)
1200cd4e3c3eSJouni Malinen 		return 1;
1201cd4e3c3eSJouni Malinen 
1202cd4e3c3eSJouni Malinen 	return p2p_group_formation_event(dut, conn, ctrl, intf, NULL, 0);
1203cd4e3c3eSJouni Malinen }
1204cd4e3c3eSJouni Malinen 
1205cd4e3c3eSJouni Malinen 
1206cd4e3c3eSJouni Malinen static int p2p_group_formation_event(struct sigma_dut *dut,
1207cd4e3c3eSJouni Malinen 				     struct sigma_conn *conn,
1208cd4e3c3eSJouni Malinen 				     struct wpa_ctrl *ctrl,
1209cd4e3c3eSJouni Malinen 				     const char *intf, const char *peer_role,
1210cd4e3c3eSJouni Malinen 				     int nfc)
1211cd4e3c3eSJouni Malinen {
1212cd4e3c3eSJouni Malinen 	int res;
1213cd4e3c3eSJouni Malinen 	char buf[256], grpid[50], resp[256];
1214cd4e3c3eSJouni Malinen 	char *ifname, *gtype, *pos, *ssid, bssid[20];
1215cd4e3c3eSJouni Malinen 	char *go_dev_addr;
1216cd4e3c3eSJouni Malinen 	char role[30];
1217cd4e3c3eSJouni Malinen 	const char *events[] = {
1218cd4e3c3eSJouni Malinen 		"P2P-GROUP-STARTED",
1219cd4e3c3eSJouni Malinen 		"P2P-GO-NEG-FAILURE",
1220cd4e3c3eSJouni Malinen 		"P2P-NFC-PEER-CLIENT",
1221cd4e3c3eSJouni Malinen 		"P2P-GROUP-FORMATION-FAILURE",
1222cd4e3c3eSJouni Malinen 		NULL
1223cd4e3c3eSJouni Malinen 	};
1224cd4e3c3eSJouni Malinen 
1225cd4e3c3eSJouni Malinen 	role[0] = '\0';
1226cd4e3c3eSJouni Malinen 	if (peer_role)
1227cd4e3c3eSJouni Malinen 		snprintf(role, sizeof(role), ",PeerRole,%s", peer_role);
1228cd4e3c3eSJouni Malinen 
1229cd4e3c3eSJouni Malinen 	res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
1230cd4e3c3eSJouni Malinen 
1231cd4e3c3eSJouni Malinen 	wpa_ctrl_detach(ctrl);
1232cd4e3c3eSJouni Malinen 	wpa_ctrl_close(ctrl);
1233cd4e3c3eSJouni Malinen 
1234cd4e3c3eSJouni Malinen 	if (res < 0) {
1235cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Group formation "
1236cd4e3c3eSJouni Malinen 			  "did not complete");
1237cd4e3c3eSJouni Malinen 		return 0;
1238cd4e3c3eSJouni Malinen 	}
1239cd4e3c3eSJouni Malinen 
1240cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group started event '%s'", buf);
1241cd4e3c3eSJouni Malinen 
1242cd4e3c3eSJouni Malinen 	if (strstr(buf, "P2P-NFC-PEER-CLIENT")) {
1243cd4e3c3eSJouni Malinen 		snprintf(resp, sizeof(resp),
1244cd4e3c3eSJouni Malinen 			 "Result,,GroupID,,PeerRole,1,PauseFlag,0");
1245cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, resp);
1246cd4e3c3eSJouni Malinen 		return 0;
1247cd4e3c3eSJouni Malinen 	}
1248cd4e3c3eSJouni Malinen 
1249cd4e3c3eSJouni Malinen 	if (strstr(buf, "P2P-GROUP-FORMATION-FAILURE")) {
1250cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "ErrorCode,Group formation failed");
1251cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, buf);
1252cd4e3c3eSJouni Malinen 		return 0;
1253cd4e3c3eSJouni Malinen 	}
1254cd4e3c3eSJouni Malinen 
1255cd4e3c3eSJouni Malinen 	if (strstr(buf, "P2P-GO-NEG-FAILURE")) {
1256cd4e3c3eSJouni Malinen 		int status = -1;
1257cd4e3c3eSJouni Malinen 		pos = strstr(buf, " status=");
1258cd4e3c3eSJouni Malinen 		if (pos)
1259cd4e3c3eSJouni Malinen 			status = atoi(pos + 8);
1260cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "GO Negotiation failed "
1261cd4e3c3eSJouni Malinen 				"(status=%d)", status);
1262cd4e3c3eSJouni Malinen 		if (status == 9) {
1263cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO, "Both devices "
1264cd4e3c3eSJouni Malinen 					"tried to use GO Intent 15");
1265cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_COMPLETE, "result,FAIL");
1266cd4e3c3eSJouni Malinen 			return 0;
1267cd4e3c3eSJouni Malinen 		}
1268cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "ErrorCode,GO Negotiation failed "
1269cd4e3c3eSJouni Malinen 			 "(status=%d)", status);
1270cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, buf);
1271cd4e3c3eSJouni Malinen 		return 0;
1272cd4e3c3eSJouni Malinen 	}
1273cd4e3c3eSJouni Malinen 
1274cd4e3c3eSJouni Malinen 	ifname = strchr(buf, ' ');
1275cd4e3c3eSJouni Malinen 	if (ifname == NULL)
1276cd4e3c3eSJouni Malinen 		return -2;
1277cd4e3c3eSJouni Malinen 	ifname++;
1278cd4e3c3eSJouni Malinen 	pos = strchr(ifname, ' ');
1279cd4e3c3eSJouni Malinen 	if (pos == NULL)
1280cd4e3c3eSJouni Malinen 		return -2;
1281cd4e3c3eSJouni Malinen 	*pos++ = '\0';
1282cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group interface %s", ifname);
1283cd4e3c3eSJouni Malinen 
1284cd4e3c3eSJouni Malinen 	gtype = pos;
1285cd4e3c3eSJouni Malinen 	pos = strchr(gtype, ' ');
1286cd4e3c3eSJouni Malinen 	if (pos == NULL)
1287cd4e3c3eSJouni Malinen 		return -2;
1288cd4e3c3eSJouni Malinen 	*pos++ = '\0';
1289cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group type %s", gtype);
1290cd4e3c3eSJouni Malinen 
1291cd4e3c3eSJouni Malinen 	ssid = strstr(pos, "ssid=\"");
1292cd4e3c3eSJouni Malinen 	if (ssid == NULL)
1293cd4e3c3eSJouni Malinen 		return -2;
1294cd4e3c3eSJouni Malinen 	ssid += 6;
1295cd4e3c3eSJouni Malinen 	pos = strchr(ssid, '"');
1296cd4e3c3eSJouni Malinen 	if (pos == NULL)
1297cd4e3c3eSJouni Malinen 		return -2;
1298cd4e3c3eSJouni Malinen 	*pos++ = '\0';
1299cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group SSID %s", ssid);
1300cd4e3c3eSJouni Malinen 
1301cd4e3c3eSJouni Malinen 	go_dev_addr = strstr(pos, "go_dev_addr=");
1302cd4e3c3eSJouni Malinen 	if (go_dev_addr == NULL) {
1303cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "No GO P2P Device Address "
1304cd4e3c3eSJouni Malinen 				"found\n");
1305cd4e3c3eSJouni Malinen 		return -2;
1306cd4e3c3eSJouni Malinen 	}
1307cd4e3c3eSJouni Malinen 	go_dev_addr += 12;
1308cd4e3c3eSJouni Malinen 	if (strlen(go_dev_addr) < 17) {
1309cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Too short GO P2P Device "
1310cd4e3c3eSJouni Malinen 				"Address '%s'", go_dev_addr);
1311cd4e3c3eSJouni Malinen 		return -2;
1312cd4e3c3eSJouni Malinen 	}
1313cd4e3c3eSJouni Malinen 	go_dev_addr[17] = '\0';
1314cd4e3c3eSJouni Malinen 	*pos = '\0';
1315cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_ERROR, "GO P2P Device Address %s",
1316cd4e3c3eSJouni Malinen 			go_dev_addr);
1317cd4e3c3eSJouni Malinen 
1318cd4e3c3eSJouni Malinen 	if (get_wpa_status(ifname, "bssid", bssid, sizeof(bssid)) < 0)
1319cd4e3c3eSJouni Malinen 		return -2;
1320cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group BSSID %s", bssid);
1321cd4e3c3eSJouni Malinen 
1322cd4e3c3eSJouni Malinen 	snprintf(grpid, sizeof(grpid), "%s %s", go_dev_addr, ssid);
1323cd4e3c3eSJouni Malinen 	p2p_group_add(dut, ifname, strcmp(gtype, "GO") == 0, grpid, ssid);
1324cd4e3c3eSJouni Malinen 	snprintf(resp, sizeof(resp), "Result,%s,GroupID,%s%s%s",
1325cd4e3c3eSJouni Malinen 		 strcmp(gtype, "GO") == 0 ? "GO" : "CLIENT", grpid, role,
1326cd4e3c3eSJouni Malinen 		 nfc ? ",PauseFlag,0" : "");
1327cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1328cd4e3c3eSJouni Malinen 
1329cd4e3c3eSJouni Malinen #ifdef __QNXNTO__
1330cd4e3c3eSJouni Malinen 	/* Start DHCP server if we became the GO */
1331cd4e3c3eSJouni Malinen 	if (strcmp(gtype, "GO") == 0 &&
1332cd4e3c3eSJouni Malinen 	    system("dhcpd -cf /etc/dhcpd.conf -pf /var/run/dhcpd qca1 &") == 0)
1333cd4e3c3eSJouni Malinen 	     sigma_dut_print(dut, DUT_MSG_ERROR,
1334cd4e3c3eSJouni Malinen 			     "Failed to start DHCPD server");
1335cd4e3c3eSJouni Malinen #endif /* __QNXNTO__ */
1336cd4e3c3eSJouni Malinen 
1337cd4e3c3eSJouni Malinen 	return 0;
1338cd4e3c3eSJouni Malinen }
1339cd4e3c3eSJouni Malinen 
1340cd4e3c3eSJouni Malinen 
1341cd4e3c3eSJouni Malinen int wps_connection_event(struct sigma_dut *dut, struct sigma_conn *conn,
1342cd4e3c3eSJouni Malinen 			 struct wpa_ctrl *ctrl, const char *intf, int p2p_resp)
1343cd4e3c3eSJouni Malinen {
1344cd4e3c3eSJouni Malinen 	int res;
1345cd4e3c3eSJouni Malinen 	char buf[256];
1346cd4e3c3eSJouni Malinen 	const char *events[] = {
1347cd4e3c3eSJouni Malinen 		"CTRL-EVENT-CONNECTED",
1348cd4e3c3eSJouni Malinen 		"WPS-FAIL",
1349cd4e3c3eSJouni Malinen 		"WPS-TIMEOUT",
1350cd4e3c3eSJouni Malinen 		NULL
1351cd4e3c3eSJouni Malinen 	};
1352cd4e3c3eSJouni Malinen 
1353cd4e3c3eSJouni Malinen 	res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
1354cd4e3c3eSJouni Malinen 
1355cd4e3c3eSJouni Malinen 	wpa_ctrl_detach(ctrl);
1356cd4e3c3eSJouni Malinen 	wpa_ctrl_close(ctrl);
1357cd4e3c3eSJouni Malinen 
1358cd4e3c3eSJouni Malinen 	if (res < 0) {
1359cd4e3c3eSJouni Malinen #ifdef USE_ERROR_RETURNS
1360cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS connection "
1361cd4e3c3eSJouni Malinen 			  "did not complete");
1362cd4e3c3eSJouni Malinen #else
1363cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, "ErrorCode,WPS connection "
1364cd4e3c3eSJouni Malinen 			  "did not complete");
1365cd4e3c3eSJouni Malinen #endif
1366cd4e3c3eSJouni Malinen 		return 0;
1367cd4e3c3eSJouni Malinen 	}
1368cd4e3c3eSJouni Malinen 
1369cd4e3c3eSJouni Malinen 	if (strstr(buf, "WPS-FAIL") || strstr(buf, "WPS-TIMEOUT")) {
1370cd4e3c3eSJouni Malinen #ifdef USE_ERROR_RETURNS
1371cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS operation "
1372cd4e3c3eSJouni Malinen 			  "failed");
1373cd4e3c3eSJouni Malinen #else
1374cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, "ErrorCode,WPS operation "
1375cd4e3c3eSJouni Malinen 			  "failed");
1376cd4e3c3eSJouni Malinen #endif
1377cd4e3c3eSJouni Malinen 		return 0;
1378cd4e3c3eSJouni Malinen 	}
1379cd4e3c3eSJouni Malinen 
1380cd4e3c3eSJouni Malinen 	if (!p2p_resp)
1381cd4e3c3eSJouni Malinen 		return 1;
1382cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, "Result,,GroupID,,PeerRole,");
1383cd4e3c3eSJouni Malinen 	return 0;
1384cd4e3c3eSJouni Malinen }
1385cd4e3c3eSJouni Malinen 
1386cd4e3c3eSJouni Malinen 
1387cd4e3c3eSJouni Malinen static int cmd_sta_p2p_dissolve(struct sigma_dut *dut, struct sigma_conn *conn,
1388cd4e3c3eSJouni Malinen 				struct sigma_cmd *cmd)
1389cd4e3c3eSJouni Malinen {
1390cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "interface");
1391cd4e3c3eSJouni Malinen 	const char *grpid = get_param(cmd, "GroupID");
1392cd4e3c3eSJouni Malinen 	struct wfa_cs_p2p_group *grp;
1393cd4e3c3eSJouni Malinen 	char buf[128];
1394cd4e3c3eSJouni Malinen 
1395cd4e3c3eSJouni Malinen 	if (grpid == NULL)
1396cd4e3c3eSJouni Malinen 		return -1;
1397cd4e3c3eSJouni Malinen 
1398cd4e3c3eSJouni Malinen 	grp = p2p_group_get(dut, grpid);
1399cd4e3c3eSJouni Malinen 	if (grp == NULL) {
1400cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Requested group "
1401cd4e3c3eSJouni Malinen 			  "not found");
1402cd4e3c3eSJouni Malinen 		return 0;
1403cd4e3c3eSJouni Malinen 	}
1404cd4e3c3eSJouni Malinen 
1405cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "P2P_GROUP_REMOVE %s", grp->ifname);
1406cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0) {
1407cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to remove the "
1408cd4e3c3eSJouni Malinen 				"specified group from wpa_supplicant - assume "
1409cd4e3c3eSJouni Malinen 				"group has already been removed");
1410cd4e3c3eSJouni Malinen 	}
1411cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Removed group %s", grpid);
1412cd4e3c3eSJouni Malinen 	if (grp->go)
1413cd4e3c3eSJouni Malinen 		dut->go = 0;
1414cd4e3c3eSJouni Malinen 	else
1415cd4e3c3eSJouni Malinen 		dut->p2p_client = 0;
1416cd4e3c3eSJouni Malinen 	p2p_group_remove(dut, grpid);
1417cd4e3c3eSJouni Malinen 	return 1;
1418cd4e3c3eSJouni Malinen }
1419cd4e3c3eSJouni Malinen 
1420cd4e3c3eSJouni Malinen 
1421cd4e3c3eSJouni Malinen static int cmd_sta_send_p2p_invitation_req(struct sigma_dut *dut,
1422cd4e3c3eSJouni Malinen 					   struct sigma_conn *conn,
1423cd4e3c3eSJouni Malinen 					   struct sigma_cmd *cmd)
1424cd4e3c3eSJouni Malinen {
1425cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "interface");
1426cd4e3c3eSJouni Malinen 	const char *devid = get_param(cmd, "P2PDevID");
1427cd4e3c3eSJouni Malinen 	const char *grpid = get_param(cmd, "GroupID");
1428cd4e3c3eSJouni Malinen 	const char *reinvoke = get_param(cmd, "Reinvoke");
1429cd4e3c3eSJouni Malinen 	char c[256];
1430cd4e3c3eSJouni Malinen 	char buf[4096];
1431cd4e3c3eSJouni Malinen 	struct wpa_ctrl *ctrl;
1432cd4e3c3eSJouni Malinen 	int res;
1433cd4e3c3eSJouni Malinen 
1434cd4e3c3eSJouni Malinen 	if (devid == NULL || grpid == NULL)
1435cd4e3c3eSJouni Malinen 		return -1;
1436cd4e3c3eSJouni Malinen 
1437cd4e3c3eSJouni Malinen 	if (reinvoke && atoi(reinvoke)) {
1438cd4e3c3eSJouni Malinen 		int id = -1;
1439cd4e3c3eSJouni Malinen 		char *ssid, *pos;
1440cd4e3c3eSJouni Malinen 
1441cd4e3c3eSJouni Malinen 		ssid = strchr(grpid, ' ');
1442cd4e3c3eSJouni Malinen 		if (ssid == NULL) {
1443cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO, "Invalid grpid");
1444cd4e3c3eSJouni Malinen 			return -1;
1445cd4e3c3eSJouni Malinen 		}
1446cd4e3c3eSJouni Malinen 		ssid++;
1447cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Search for persistent "
1448cd4e3c3eSJouni Malinen 				"group credentials based on SSID: '%s'", ssid);
1449cd4e3c3eSJouni Malinen 		if (wpa_command_resp(intf, "LIST_NETWORKS",
1450cd4e3c3eSJouni Malinen 				     buf, sizeof(buf)) < 0)
1451cd4e3c3eSJouni Malinen 			return -2;
1452cd4e3c3eSJouni Malinen 		pos = strstr(buf, ssid);
1453cd4e3c3eSJouni Malinen 		if (pos == NULL || pos == buf || pos[-1] != '\t' ||
1454cd4e3c3eSJouni Malinen 		    pos[strlen(ssid)] != '\t') {
1455cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
1456cd4e3c3eSJouni Malinen 				  "Persistent group credentials not found");
1457cd4e3c3eSJouni Malinen 			return 0;
1458cd4e3c3eSJouni Malinen 		}
1459cd4e3c3eSJouni Malinen 		while (pos > buf && pos[-1] != '\n')
1460cd4e3c3eSJouni Malinen 			pos--;
1461cd4e3c3eSJouni Malinen 		id = atoi(pos);
1462cd4e3c3eSJouni Malinen 		snprintf(c, sizeof(c), "P2P_INVITE persistent=%d peer=%s",
1463cd4e3c3eSJouni Malinen 			 id, devid);
1464cd4e3c3eSJouni Malinen 	} else {
1465cd4e3c3eSJouni Malinen 		struct wfa_cs_p2p_group *grp;
1466cd4e3c3eSJouni Malinen 		grp = p2p_group_get(dut, grpid);
1467cd4e3c3eSJouni Malinen 		if (grp == NULL) {
1468cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
1469cd4e3c3eSJouni Malinen 				  "No active P2P group found for invitation");
1470cd4e3c3eSJouni Malinen 			return 0;
1471cd4e3c3eSJouni Malinen 		}
1472cd4e3c3eSJouni Malinen 		snprintf(c, sizeof(c), "P2P_INVITE group=%s peer=%s",
1473cd4e3c3eSJouni Malinen 			 grp->ifname, devid);
1474cd4e3c3eSJouni Malinen 	}
1475cd4e3c3eSJouni Malinen 
1476cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover peer %s for "
1477cd4e3c3eSJouni Malinen 			"invitation", devid);
1478cd4e3c3eSJouni Malinen 	if (p2p_discover_peer(dut, intf, devid, 0) < 0) {
1479cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
1480cd4e3c3eSJouni Malinen 			  "discover the requested peer");
1481cd4e3c3eSJouni Malinen 		return 0;
1482cd4e3c3eSJouni Malinen 	}
1483cd4e3c3eSJouni Malinen 
1484cd4e3c3eSJouni Malinen 	ctrl = open_wpa_mon(intf);
1485cd4e3c3eSJouni Malinen 	if (ctrl == NULL) {
1486cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
1487cd4e3c3eSJouni Malinen 				"wpa_supplicant monitor connection");
1488cd4e3c3eSJouni Malinen 		return -2;
1489cd4e3c3eSJouni Malinen 	}
1490cd4e3c3eSJouni Malinen 
1491cd4e3c3eSJouni Malinen 	if (wpa_command(intf, c) < 0) {
1492cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to send invitation "
1493cd4e3c3eSJouni Malinen 				"request");
1494cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
1495cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
1496cd4e3c3eSJouni Malinen 		return -2;
1497cd4e3c3eSJouni Malinen 	}
1498cd4e3c3eSJouni Malinen 
1499cd4e3c3eSJouni Malinen 	res = get_wpa_cli_event(dut, ctrl, "P2P-INVITATION-RESULT",
1500cd4e3c3eSJouni Malinen 				buf, sizeof(buf));
1501cd4e3c3eSJouni Malinen 
1502cd4e3c3eSJouni Malinen 	wpa_ctrl_detach(ctrl);
1503cd4e3c3eSJouni Malinen 	wpa_ctrl_close(ctrl);
1504cd4e3c3eSJouni Malinen 
1505cd4e3c3eSJouni Malinen 	if (res < 0)
1506cd4e3c3eSJouni Malinen 		return -2;
1507cd4e3c3eSJouni Malinen 
1508cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Invitation event: '%s'", buf);
1509cd4e3c3eSJouni Malinen 	return 1;
1510cd4e3c3eSJouni Malinen }
1511cd4e3c3eSJouni Malinen 
1512cd4e3c3eSJouni Malinen 
1513cd4e3c3eSJouni Malinen static int cmd_sta_accept_p2p_invitation_req(struct sigma_dut *dut,
1514cd4e3c3eSJouni Malinen 					     struct sigma_conn *conn,
1515cd4e3c3eSJouni Malinen 					     struct sigma_cmd *cmd)
1516cd4e3c3eSJouni Malinen {
1517cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "Interface");
1518cd4e3c3eSJouni Malinen 	const char *devid = get_param(cmd, "P2PDevID");
1519cd4e3c3eSJouni Malinen 	const char *grpid = get_param(cmd, "GroupID");
1520cd4e3c3eSJouni Malinen 	const char *reinvoke = get_param(cmd, "Reinvoke");
1521cd4e3c3eSJouni Malinen 	char buf[100];
1522cd4e3c3eSJouni Malinen 
1523cd4e3c3eSJouni Malinen 	if (devid == NULL || grpid == NULL)
1524cd4e3c3eSJouni Malinen 		return -1;
1525cd4e3c3eSJouni Malinen 
1526cd4e3c3eSJouni Malinen 	if (reinvoke && atoi(reinvoke)) {
1527cd4e3c3eSJouni Malinen 		/*
1528cd4e3c3eSJouni Malinen 		 * Assume persistent reconnect is enabled and there is no need
1529cd4e3c3eSJouni Malinen 		 * to do anything here.
1530cd4e3c3eSJouni Malinen 		 */
1531cd4e3c3eSJouni Malinen 		return 1;
1532cd4e3c3eSJouni Malinen 	}
1533cd4e3c3eSJouni Malinen 
1534cd4e3c3eSJouni Malinen 	/*
1535cd4e3c3eSJouni Malinen 	 * In a client-joining-a-running-group case, we need to separately
1536cd4e3c3eSJouni Malinen 	 * authorize the invitation.
1537cd4e3c3eSJouni Malinen 	 */
1538cd4e3c3eSJouni Malinen 
1539cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover GO %s", devid);
1540cd4e3c3eSJouni Malinen 	if (p2p_discover_peer(dut, intf, devid, 1) < 0) {
1541cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
1542cd4e3c3eSJouni Malinen 			  "discover the requested peer");
1543cd4e3c3eSJouni Malinen 		return 0;
1544cd4e3c3eSJouni Malinen 	}
1545cd4e3c3eSJouni Malinen 
1546cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s join auth",
1547cd4e3c3eSJouni Malinen 		 devid,
1548cd4e3c3eSJouni Malinen 		 dut->wps_method == WFA_CS_WPS_PBC ?
1549cd4e3c3eSJouni Malinen 		 "pbc" : dut->wps_pin);
1550cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0)
1551cd4e3c3eSJouni Malinen 		return -2;
1552cd4e3c3eSJouni Malinen 
1553cd4e3c3eSJouni Malinen 	return 1;
1554cd4e3c3eSJouni Malinen }
1555cd4e3c3eSJouni Malinen 
1556cd4e3c3eSJouni Malinen 
1557cd4e3c3eSJouni Malinen static int cmd_sta_send_p2p_provision_dis_req(struct sigma_dut *dut,
1558cd4e3c3eSJouni Malinen 					      struct sigma_conn *conn,
1559cd4e3c3eSJouni Malinen 					      struct sigma_cmd *cmd)
1560cd4e3c3eSJouni Malinen {
1561cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "interface");
1562cd4e3c3eSJouni Malinen 	const char *conf_method = get_param(cmd, "ConfigMethod");
1563cd4e3c3eSJouni Malinen 	const char *devid = get_param(cmd, "P2PDevID");
1564cd4e3c3eSJouni Malinen 	char buf[256];
1565cd4e3c3eSJouni Malinen 	char *method;
1566cd4e3c3eSJouni Malinen 
1567cd4e3c3eSJouni Malinen 	if (conf_method == NULL || devid == NULL)
1568cd4e3c3eSJouni Malinen 		return -1;
1569cd4e3c3eSJouni Malinen 
1570cd4e3c3eSJouni Malinen 	if (strcasecmp(conf_method, "Display") == 0)
1571cd4e3c3eSJouni Malinen 		method = "display";
1572cd4e3c3eSJouni Malinen 	else if (strcasecmp(conf_method, "Keyboard") == 0 ||
1573cd4e3c3eSJouni Malinen 		 strcasecmp(conf_method, "keypad") == 0)
1574cd4e3c3eSJouni Malinen 		method = "keypad";
1575cd4e3c3eSJouni Malinen 	else if (strcasecmp(conf_method, "Label") == 0)
1576cd4e3c3eSJouni Malinen 		method = "label";
1577cd4e3c3eSJouni Malinen 	else if (strcasecmp(conf_method, "pbc") == 0 ||
1578cd4e3c3eSJouni Malinen 		 strcasecmp(conf_method, "pushbutton") == 0)
1579cd4e3c3eSJouni Malinen 		method = "pbc";
1580cd4e3c3eSJouni Malinen 	else
1581cd4e3c3eSJouni Malinen 		return -1;
1582cd4e3c3eSJouni Malinen 
1583cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover peer %s for "
1584cd4e3c3eSJouni Malinen 			"provision discovery", devid);
1585cd4e3c3eSJouni Malinen 	if (p2p_discover_peer(dut, intf, devid, 0) < 0) {
1586cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
1587cd4e3c3eSJouni Malinen 			  "discover the requested peer");
1588cd4e3c3eSJouni Malinen 		return 0;
1589cd4e3c3eSJouni Malinen 	}
1590cd4e3c3eSJouni Malinen 
1591cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "P2P_PROV_DISC %s %s", devid, method);
1592cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0) {
1593cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to send provision "
1594cd4e3c3eSJouni Malinen 				"discovery request");
1595cd4e3c3eSJouni Malinen 		return -2;
1596cd4e3c3eSJouni Malinen 	}
1597cd4e3c3eSJouni Malinen 
1598cd4e3c3eSJouni Malinen 	return 1;
1599cd4e3c3eSJouni Malinen }
1600cd4e3c3eSJouni Malinen 
1601cd4e3c3eSJouni Malinen 
1602cd4e3c3eSJouni Malinen static int cmd_sta_set_wps_pbc(struct sigma_dut *dut, struct sigma_conn *conn,
1603cd4e3c3eSJouni Malinen 			       struct sigma_cmd *cmd)
1604cd4e3c3eSJouni Malinen {
1605cd4e3c3eSJouni Malinen 	/* const char *intf = get_param(cmd, "Interface"); */
1606cd4e3c3eSJouni Malinen 	const char *grpid = get_param(cmd, "GroupID");
1607cd4e3c3eSJouni Malinen 
1608cd4e3c3eSJouni Malinen 	if (grpid) {
1609cd4e3c3eSJouni Malinen 		struct wfa_cs_p2p_group *grp;
1610cd4e3c3eSJouni Malinen 		grp = p2p_group_get(dut, grpid);
1611cd4e3c3eSJouni Malinen 		if (grp && grp->go) {
1612cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a "
1613cd4e3c3eSJouni Malinen 					"client to join with WPS");
1614cd4e3c3eSJouni Malinen 			wpa_command(grp->ifname, "WPS_PBC");
1615cd4e3c3eSJouni Malinen 			return 1;
1616cd4e3c3eSJouni Malinen 		}
1617cd4e3c3eSJouni Malinen 	}
1618cd4e3c3eSJouni Malinen 
1619cd4e3c3eSJouni Malinen 	dut->wps_method = WFA_CS_WPS_PBC;
1620cd4e3c3eSJouni Malinen 	return 1;
1621cd4e3c3eSJouni Malinen }
1622cd4e3c3eSJouni Malinen 
1623cd4e3c3eSJouni Malinen 
1624cd4e3c3eSJouni Malinen static int cmd_sta_wps_read_pin(struct sigma_dut *dut, struct sigma_conn *conn,
1625cd4e3c3eSJouni Malinen 				struct sigma_cmd *cmd)
1626cd4e3c3eSJouni Malinen {
1627*0dae51c5SAlexei Avshalom Lazar 	const char *intf = get_param(cmd, "Interface");
1628cd4e3c3eSJouni Malinen 	const char *grpid = get_param(cmd, "GroupID");
1629*0dae51c5SAlexei Avshalom Lazar 	char pin[9], addr[20];
1630cd4e3c3eSJouni Malinen 	char resp[100];
1631cd4e3c3eSJouni Malinen 
1632*0dae51c5SAlexei Avshalom Lazar 	if (get_wpa_status(intf, "address", addr, sizeof(addr)) < 0 ||
1633*0dae51c5SAlexei Avshalom Lazar 	    get_wps_pin_from_mac(dut, addr, pin, sizeof(pin)) < 0) {
1634*0dae51c5SAlexei Avshalom Lazar 		sigma_dut_print(dut, DUT_MSG_DEBUG,
1635*0dae51c5SAlexei Avshalom Lazar 				"Failed to calculate PIN from MAC, use default");
1636*0dae51c5SAlexei Avshalom Lazar 		strlcpy(pin, "12345670", sizeof(pin));
1637*0dae51c5SAlexei Avshalom Lazar 	}
1638*0dae51c5SAlexei Avshalom Lazar 
1639cd4e3c3eSJouni Malinen 	if (grpid) {
1640cd4e3c3eSJouni Malinen 		char buf[100];
1641cd4e3c3eSJouni Malinen 		struct wfa_cs_p2p_group *grp;
1642cd4e3c3eSJouni Malinen 		grp = p2p_group_get(dut, grpid);
1643cd4e3c3eSJouni Malinen 		if (grp && grp->go) {
1644cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a "
1645cd4e3c3eSJouni Malinen 					"client to join with WPS");
1646cd4e3c3eSJouni Malinen 			snprintf(buf, sizeof(buf), "WPS_PIN any %s", pin);
1647cd4e3c3eSJouni Malinen 			if (wpa_command(grp->ifname, buf) < 0)
1648cd4e3c3eSJouni Malinen 				return -1;
1649cd4e3c3eSJouni Malinen 			goto done;
1650cd4e3c3eSJouni Malinen 		}
1651cd4e3c3eSJouni Malinen 	}
1652cd4e3c3eSJouni Malinen 
1653b8fc5cc8SPeng Xu 	strlcpy(dut->wps_pin, pin, sizeof(dut->wps_pin));
1654cd4e3c3eSJouni Malinen 	dut->wps_method = WFA_CS_WPS_PIN_DISPLAY;
1655cd4e3c3eSJouni Malinen done:
1656cd4e3c3eSJouni Malinen 	snprintf(resp, sizeof(resp), "PIN,%s", pin);
1657cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1658cd4e3c3eSJouni Malinen 
1659cd4e3c3eSJouni Malinen 	return 0;
1660cd4e3c3eSJouni Malinen }
1661cd4e3c3eSJouni Malinen 
1662cd4e3c3eSJouni Malinen 
1663cd4e3c3eSJouni Malinen static int cmd_sta_wps_read_label(struct sigma_dut *dut,
1664cd4e3c3eSJouni Malinen 				  struct sigma_conn *conn,
1665cd4e3c3eSJouni Malinen 				  struct sigma_cmd *cmd)
1666cd4e3c3eSJouni Malinen {
1667cd4e3c3eSJouni Malinen 	/* const char *intf = get_param(cmd, "Interface"); */
1668cd4e3c3eSJouni Malinen 	const char *grpid = get_param(cmd, "GroupID");
1669cd4e3c3eSJouni Malinen 	char *pin = "12345670";
1670cd4e3c3eSJouni Malinen 	char resp[100];
1671cd4e3c3eSJouni Malinen 
1672cd4e3c3eSJouni Malinen 	if (grpid) {
1673cd4e3c3eSJouni Malinen 		char buf[100];
1674cd4e3c3eSJouni Malinen 		struct wfa_cs_p2p_group *grp;
1675cd4e3c3eSJouni Malinen 		grp = p2p_group_get(dut, grpid);
1676cd4e3c3eSJouni Malinen 		if (grp && grp->go) {
1677cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a "
1678cd4e3c3eSJouni Malinen 					"client to join with WPS");
1679cd4e3c3eSJouni Malinen 			snprintf(buf, sizeof(buf), "WPS_PIN any %s", pin);
1680cd4e3c3eSJouni Malinen 			wpa_command(grp->ifname, buf);
1681cd4e3c3eSJouni Malinen 			return 1;
1682cd4e3c3eSJouni Malinen 		}
1683cd4e3c3eSJouni Malinen 	}
1684cd4e3c3eSJouni Malinen 
1685b8fc5cc8SPeng Xu 	strlcpy(dut->wps_pin, pin, sizeof(dut->wps_pin));
1686cd4e3c3eSJouni Malinen 	dut->wps_method = WFA_CS_WPS_PIN_LABEL;
1687cd4e3c3eSJouni Malinen 	snprintf(resp, sizeof(resp), "LABEL,%s", pin);
1688cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1689cd4e3c3eSJouni Malinen 
1690cd4e3c3eSJouni Malinen 	return 0;
1691cd4e3c3eSJouni Malinen }
1692cd4e3c3eSJouni Malinen 
1693cd4e3c3eSJouni Malinen 
1694cd4e3c3eSJouni Malinen static int cmd_sta_wps_enter_pin(struct sigma_dut *dut,
1695cd4e3c3eSJouni Malinen 				 struct sigma_conn *conn,
1696cd4e3c3eSJouni Malinen 				 struct sigma_cmd *cmd)
1697cd4e3c3eSJouni Malinen {
1698cd4e3c3eSJouni Malinen 	/* const char *intf = get_param(cmd, "Interface"); */
1699cd4e3c3eSJouni Malinen 	const char *grpid = get_param(cmd, "GroupID");
1700cd4e3c3eSJouni Malinen 	const char *pin = get_param(cmd, "PIN");
1701cd4e3c3eSJouni Malinen 
1702cd4e3c3eSJouni Malinen 	if (pin == NULL)
1703cd4e3c3eSJouni Malinen 		return -1;
1704cd4e3c3eSJouni Malinen 
1705cd4e3c3eSJouni Malinen 	if (grpid) {
1706cd4e3c3eSJouni Malinen 		char buf[100];
1707cd4e3c3eSJouni Malinen 		struct wfa_cs_p2p_group *grp;
1708cd4e3c3eSJouni Malinen 		grp = p2p_group_get(dut, grpid);
1709cd4e3c3eSJouni Malinen 		if (grp && grp->go) {
1710cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a "
1711cd4e3c3eSJouni Malinen 					"client to join with WPS");
1712cd4e3c3eSJouni Malinen 			snprintf(buf, sizeof(buf), "WPS_PIN any %s", pin);
1713cd4e3c3eSJouni Malinen 			wpa_command(grp->ifname, buf);
1714cd4e3c3eSJouni Malinen 			return 1;
1715cd4e3c3eSJouni Malinen 		}
1716cd4e3c3eSJouni Malinen 	}
1717cd4e3c3eSJouni Malinen 
1718b8fc5cc8SPeng Xu 	strlcpy(dut->wps_pin, pin, sizeof(dut->wps_pin));
1719cd4e3c3eSJouni Malinen 	dut->wps_pin[sizeof(dut->wps_pin) - 1] = '\0';
1720cd4e3c3eSJouni Malinen 	dut->wps_method = WFA_CS_WPS_PIN_KEYPAD;
1721cd4e3c3eSJouni Malinen 
1722cd4e3c3eSJouni Malinen 	return 1;
1723cd4e3c3eSJouni Malinen }
1724cd4e3c3eSJouni Malinen 
1725cd4e3c3eSJouni Malinen 
1726cd4e3c3eSJouni Malinen static int cmd_sta_get_psk(struct sigma_dut *dut, struct sigma_conn *conn,
1727cd4e3c3eSJouni Malinen 			   struct sigma_cmd *cmd)
1728cd4e3c3eSJouni Malinen {
1729cd4e3c3eSJouni Malinen 	/* const char *intf = get_param(cmd, "interface"); */
1730cd4e3c3eSJouni Malinen 	const char *grpid = get_param(cmd, "GroupID");
1731cd4e3c3eSJouni Malinen 	struct wfa_cs_p2p_group *grp;
1732cd4e3c3eSJouni Malinen 	char passphrase[64], resp[200];
1733cd4e3c3eSJouni Malinen 
1734cd4e3c3eSJouni Malinen 	if (grpid == NULL)
1735cd4e3c3eSJouni Malinen 		return -1;
1736cd4e3c3eSJouni Malinen 
1737cd4e3c3eSJouni Malinen 	grp = p2p_group_get(dut, grpid);
1738cd4e3c3eSJouni Malinen 	if (grp == NULL) {
1739cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
1740cd4e3c3eSJouni Malinen 			  "errorCode,Requested group not found");
1741cd4e3c3eSJouni Malinen 		return 0;
1742cd4e3c3eSJouni Malinen 	}
1743cd4e3c3eSJouni Malinen 	if (!grp->go) {
1744cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
1745cd4e3c3eSJouni Malinen 			  "errorCode,Local role is not GO in the specified "
1746cd4e3c3eSJouni Malinen 			  "group");
1747cd4e3c3eSJouni Malinen 		return 0;
1748cd4e3c3eSJouni Malinen 	}
1749cd4e3c3eSJouni Malinen 
1750cd4e3c3eSJouni Malinen 	if (wpa_command_resp(grp->ifname, "P2P_GET_PASSPHRASE",
1751cd4e3c3eSJouni Malinen 			     passphrase, sizeof(passphrase)) < 0)
1752cd4e3c3eSJouni Malinen 		return -2;
1753cd4e3c3eSJouni Malinen 
1754cd4e3c3eSJouni Malinen 	snprintf(resp, sizeof(resp), "passPhrase,%s,ssid,%s",
1755cd4e3c3eSJouni Malinen 		 passphrase, grp->ssid);
1756cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1757cd4e3c3eSJouni Malinen 
1758cd4e3c3eSJouni Malinen 	return 0;
1759cd4e3c3eSJouni Malinen }
1760cd4e3c3eSJouni Malinen 
1761cd4e3c3eSJouni Malinen 
1762cd4e3c3eSJouni Malinen int cmd_sta_p2p_reset(struct sigma_dut *dut, struct sigma_conn *conn,
1763cd4e3c3eSJouni Malinen 		      struct sigma_cmd *cmd)
1764cd4e3c3eSJouni Malinen {
1765cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "interface");
1766cd4e3c3eSJouni Malinen 	struct wfa_cs_p2p_group *grp, *prev;
1767cd4e3c3eSJouni Malinen 	char buf[256];
1768cd4e3c3eSJouni Malinen 
17699c381f59SAmarnath Hullur Subramanyam #ifdef MIRACAST
17709c381f59SAmarnath Hullur Subramanyam 	if (dut->program == PROGRAM_WFD ||
17719c381f59SAmarnath Hullur Subramanyam 	    dut->program == PROGRAM_DISPLAYR2)
17729c381f59SAmarnath Hullur Subramanyam 		miracast_sta_reset_default(dut, conn, cmd);
17739c381f59SAmarnath Hullur Subramanyam #endif /* MIRACAST */
17749c381f59SAmarnath Hullur Subramanyam 
1775cd4e3c3eSJouni Malinen 	dut->go = 0;
1776cd4e3c3eSJouni Malinen 	dut->p2p_client = 0;
1777cd4e3c3eSJouni Malinen 	dut->wps_method = WFA_CS_WPS_NOT_READY;
1778cd4e3c3eSJouni Malinen 
1779cd4e3c3eSJouni Malinen 	grp = dut->groups;
1780cd4e3c3eSJouni Malinen 	while (grp) {
1781cd4e3c3eSJouni Malinen 		prev = grp;
1782cd4e3c3eSJouni Malinen 		grp = grp->next;
1783cd4e3c3eSJouni Malinen 
1784cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_GROUP_REMOVE %s",
1785cd4e3c3eSJouni Malinen 			 prev->ifname);
1786cd4e3c3eSJouni Malinen 		wpa_command(intf, buf);
1787cd4e3c3eSJouni Malinen 		p2p_group_remove(dut, prev->grpid);
1788cd4e3c3eSJouni Malinen 	}
1789cd4e3c3eSJouni Malinen 
1790cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_GROUP_REMOVE *");
1791cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_STOP_FIND");
1792cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_FLUSH");
1793cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SERVICE_FLUSH");
1794cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SET disabled 0");
1795cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SET ssid_postfix ");
1796842a4e05SDanny Segal 
1797842a4e05SDanny Segal 	if (dut->program == PROGRAM_60GHZ) {
1798842a4e05SDanny Segal 		wpa_command(intf, "SET p2p_oper_reg_class 180");
1799842a4e05SDanny Segal 		wpa_command(intf, "P2P_SET listen_channel 2 180");
1800842a4e05SDanny Segal 		dut->listen_chn = 2;
1801842a4e05SDanny Segal 	} else {
1802cd4e3c3eSJouni Malinen 		wpa_command(intf, "P2P_SET listen_channel 6");
1803cd4e3c3eSJouni Malinen 		dut->listen_chn = 6;
1804842a4e05SDanny Segal 	}
1805842a4e05SDanny Segal 
1806cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_EXT_LISTEN");
1807cd4e3c3eSJouni Malinen 	wpa_command(intf, "SET p2p_go_intent 7");
1808cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SET client_apsd disable");
1809cd4e3c3eSJouni Malinen 	wpa_command(intf, "P2P_SET go_apsd disable");
1810cd4e3c3eSJouni Malinen 	wpa_command(get_station_ifname(), "P2P_SET ps 98");
1811cd4e3c3eSJouni Malinen 	wpa_command(get_station_ifname(), "P2P_SET ps 96");
1812cd4e3c3eSJouni Malinen 	wpa_command(get_station_ifname(), "P2P_SET ps 0");
18134476a209SSunil Dutt 	wpa_command(intf, "P2P_SET ps 0");
1814cd4e3c3eSJouni Malinen 	wpa_command(intf, "SET persistent_reconnect 1");
1815cd4e3c3eSJouni Malinen 	wpa_command(intf, "SET ampdu 1");
1816cd4e3c3eSJouni Malinen 	run_system(dut, "iptables -F INPUT");
1817cd4e3c3eSJouni Malinen 	if (dut->arp_ipaddr[0]) {
1818cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "ip nei del %s dev %s",
1819cd4e3c3eSJouni Malinen 			 dut->arp_ipaddr, dut->arp_ifname);
1820cd4e3c3eSJouni Malinen 		run_system(dut, buf);
1821cd4e3c3eSJouni Malinen 		dut->arp_ipaddr[0] = '\0';
1822cd4e3c3eSJouni Malinen 	}
1823cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "ip nei flush dev %s",
1824cd4e3c3eSJouni Malinen 		 get_station_ifname());
1825cd4e3c3eSJouni Malinen 	run_system(dut, buf);
1826cd4e3c3eSJouni Malinen 	dut->p2p_mode = P2P_IDLE;
1827cd4e3c3eSJouni Malinen 	dut->client_uapsd = 0;
1828cd4e3c3eSJouni Malinen 	ath6kl_client_uapsd(dut, intf, 0);
1829cd4e3c3eSJouni Malinen 
1830cd4e3c3eSJouni Malinen 	remove_wpa_networks(intf);
1831cd4e3c3eSJouni Malinen 
1832cd4e3c3eSJouni Malinen 	disconnect_station(dut);
1833cd4e3c3eSJouni Malinen 
1834cd4e3c3eSJouni Malinen 	if (dut->iface_down_on_reset)
1835cd4e3c3eSJouni Malinen 		dut_ifc_reset(dut);
1836cd4e3c3eSJouni Malinen 
1837cd4e3c3eSJouni Malinen 	return 1;
1838cd4e3c3eSJouni Malinen }
1839cd4e3c3eSJouni Malinen 
1840cd4e3c3eSJouni Malinen 
1841cd4e3c3eSJouni Malinen static int cmd_sta_get_p2p_ip_config(struct sigma_dut *dut,
1842cd4e3c3eSJouni Malinen 				     struct sigma_conn *conn,
1843cd4e3c3eSJouni Malinen 				     struct sigma_cmd *cmd)
1844cd4e3c3eSJouni Malinen {
1845cd4e3c3eSJouni Malinen 	/* const char *intf = get_param(cmd, "Interface"); */
1846cd4e3c3eSJouni Malinen 	const char *grpid = get_param(cmd, "GroupID");
1847cd4e3c3eSJouni Malinen 	struct wfa_cs_p2p_group *grp = NULL;
1848cd4e3c3eSJouni Malinen 	int count;
1849cd4e3c3eSJouni Malinen 	char macaddr[20];
1850cd4e3c3eSJouni Malinen 	char resp[200], info[150];
1851cd4e3c3eSJouni Malinen 
1852cd4e3c3eSJouni Malinen 	if (grpid == NULL)
1853cd4e3c3eSJouni Malinen 		return -1;
1854cd4e3c3eSJouni Malinen 
1855cd4e3c3eSJouni Malinen 	if (strcmp(grpid, "$P2P_GROUP_ID") == 0)
1856cd4e3c3eSJouni Malinen 		return -1;
1857cd4e3c3eSJouni Malinen 
1858cd4e3c3eSJouni Malinen 	/*
1859cd4e3c3eSJouni Malinen 	 * If we did not initiate the operation that created the group, we may
1860cd4e3c3eSJouni Malinen 	 * not have the group information available in the DUT code yet and it
1861cd4e3c3eSJouni Malinen 	 * may take some time to get this from wpa_supplicant in case we are
1862cd4e3c3eSJouni Malinen 	 * the P2P client. As such, we better try this multiple times to allow
1863cd4e3c3eSJouni Malinen 	 * some time to complete the operation.
1864cd4e3c3eSJouni Malinen 	 */
1865cd4e3c3eSJouni Malinen 
1866cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting to find the requested "
1867cd4e3c3eSJouni Malinen 			"group");
1868cd4e3c3eSJouni Malinen 	count = dut->default_timeout;
1869cd4e3c3eSJouni Malinen 	while (count > 0) {
1870cd4e3c3eSJouni Malinen 		grp = p2p_group_get(dut, grpid);
1871cd4e3c3eSJouni Malinen 		if (grp == NULL) {
1872cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Requested group "
1873cd4e3c3eSJouni Malinen 					"not yet found (count=%d)", count);
1874cd4e3c3eSJouni Malinen 			sleep(1);
1875cd4e3c3eSJouni Malinen 		} else
1876cd4e3c3eSJouni Malinen 			break;
1877cd4e3c3eSJouni Malinen 		count--;
1878cd4e3c3eSJouni Malinen 	}
1879cd4e3c3eSJouni Malinen 	if (grp == NULL) {
1880cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
1881cd4e3c3eSJouni Malinen 			  "errorCode,Requested group not found");
1882cd4e3c3eSJouni Malinen 		return 0;
1883cd4e3c3eSJouni Malinen 	}
1884cd4e3c3eSJouni Malinen 
1885cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting for IP address on group "
1886cd4e3c3eSJouni Malinen 			"interface %s", grp->ifname);
1887cd4e3c3eSJouni Malinen 	if (wait_ip_addr(dut, grp->ifname, dut->default_timeout) < 0) {
1888cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
1889cd4e3c3eSJouni Malinen 			  "errorCode,No IP address received");
1890cd4e3c3eSJouni Malinen 		return 0;
1891cd4e3c3eSJouni Malinen 	}
1892cd4e3c3eSJouni Malinen 
1893cd4e3c3eSJouni Malinen 	if (get_ip_config(dut, grp->ifname, info, sizeof(info)) < 0) {
1894cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get IP address "
1895cd4e3c3eSJouni Malinen 				"for group interface %s",
1896cd4e3c3eSJouni Malinen 				grp->ifname);
1897cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
1898cd4e3c3eSJouni Malinen 			  "errorCode,Failed to get IP address");
1899cd4e3c3eSJouni Malinen 		return 0;
1900cd4e3c3eSJouni Malinen 	}
1901cd4e3c3eSJouni Malinen 
1902cd4e3c3eSJouni Malinen 	if (get_wpa_status(grp->ifname, "address",
1903cd4e3c3eSJouni Malinen 			   macaddr, sizeof(macaddr)) < 0) {
1904cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to get interface "
1905cd4e3c3eSJouni Malinen 				"address for group interface %s",
1906cd4e3c3eSJouni Malinen 				grp->ifname);
1907cd4e3c3eSJouni Malinen 		return -2;
1908cd4e3c3eSJouni Malinen 	}
1909cd4e3c3eSJouni Malinen 
1910cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_DEBUG, "IP address for group interface "
1911cd4e3c3eSJouni Malinen 			"%s found", grp->ifname);
1912cd4e3c3eSJouni Malinen 
1913cd4e3c3eSJouni Malinen 	snprintf(resp, sizeof(resp), "%s,P2PInterfaceAddress,%s",
1914cd4e3c3eSJouni Malinen 		 info, macaddr);
1915cd4e3c3eSJouni Malinen 
1916cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1917cd4e3c3eSJouni Malinen 	return 0;
1918cd4e3c3eSJouni Malinen }
1919cd4e3c3eSJouni Malinen 
1920cd4e3c3eSJouni Malinen 
1921cd4e3c3eSJouni Malinen static int cmd_sta_send_p2p_presence_req(struct sigma_dut *dut,
1922cd4e3c3eSJouni Malinen 					 struct sigma_conn *conn,
1923cd4e3c3eSJouni Malinen 					 struct sigma_cmd *cmd)
1924cd4e3c3eSJouni Malinen {
1925cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "Interface");
1926cd4e3c3eSJouni Malinen 	const char *dur = get_param(cmd, "Duration");
1927cd4e3c3eSJouni Malinen 	const char *interv = get_param(cmd, "Interval");
1928cd4e3c3eSJouni Malinen 	/* const char *grpid = get_param(cmd, "GroupID"); */
1929cd4e3c3eSJouni Malinen 	const char *ifname;
1930cd4e3c3eSJouni Malinen 	char buf[100];
1931cd4e3c3eSJouni Malinen 
1932cd4e3c3eSJouni Malinen 	if (dur == NULL || interv == NULL)
1933cd4e3c3eSJouni Malinen 		return -1;
1934cd4e3c3eSJouni Malinen 
1935cd4e3c3eSJouni Malinen 	/* TODO: need to add groupid into parameters in CAPI spec; for now,
1936cd4e3c3eSJouni Malinen 	 * pick the first active group */
1937cd4e3c3eSJouni Malinen 	ifname = get_group_ifname(dut, intf);
1938cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "P2P_PRESENCE_REQ %s %s", dur, interv);
1939cd4e3c3eSJouni Malinen 	if (wpa_command(ifname, buf) < 0)
1940cd4e3c3eSJouni Malinen 		return -2;
1941cd4e3c3eSJouni Malinen 
1942cd4e3c3eSJouni Malinen 	return 1;
1943cd4e3c3eSJouni Malinen }
1944cd4e3c3eSJouni Malinen 
1945cd4e3c3eSJouni Malinen 
1946cd4e3c3eSJouni Malinen static int cmd_sta_set_sleep(struct sigma_dut *dut, struct sigma_conn *conn,
1947cd4e3c3eSJouni Malinen 			     struct sigma_cmd *cmd)
1948cd4e3c3eSJouni Malinen {
1949cd4e3c3eSJouni Malinen 	/* const char *intf = get_param(cmd, "Interface"); */
1950cd4e3c3eSJouni Malinen 	struct wfa_cs_p2p_group *grp;
1951cd4e3c3eSJouni Malinen 	char *ifname;
1952cd4e3c3eSJouni Malinen 	const char *grpid = get_param(cmd, "GroupID");
1953cd4e3c3eSJouni Malinen 
19540c0b2614SDanny Segal 	if (dut->program == PROGRAM_60GHZ) {
19550c0b2614SDanny Segal 		send_resp(dut, conn, SIGMA_ERROR,
19560c0b2614SDanny Segal 			  "errorCode,UAPSD Sleep is not applicable for 60 GHz");
19570c0b2614SDanny Segal 		return 0;
19580c0b2614SDanny Segal 	}
19590c0b2614SDanny Segal 
1960cd4e3c3eSJouni Malinen 	if (grpid == NULL)
1961cd4e3c3eSJouni Malinen 		ifname = get_station_ifname();
1962cd4e3c3eSJouni Malinen 	else {
1963cd4e3c3eSJouni Malinen 		grp = p2p_group_get(dut, grpid);
1964cd4e3c3eSJouni Malinen 		if (grp == NULL) {
1965cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
1966cd4e3c3eSJouni Malinen 				  "errorCode,Requested group not found");
1967cd4e3c3eSJouni Malinen 			return 0;
1968cd4e3c3eSJouni Malinen 		}
1969cd4e3c3eSJouni Malinen 		ifname = grp->ifname;
1970cd4e3c3eSJouni Malinen 	}
1971cd4e3c3eSJouni Malinen 
1972cd4e3c3eSJouni Malinen 	if (dut->client_uapsd) {
1973cd4e3c3eSJouni Malinen #ifdef __linux__
1974cd4e3c3eSJouni Malinen 		/* no special handling for nl80211 yet */
1975cd4e3c3eSJouni Malinen 		char path[128];
1976cd4e3c3eSJouni Malinen 		struct stat s;
1977cd4e3c3eSJouni Malinen 		snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211",
1978cd4e3c3eSJouni Malinen 			 ifname);
1979cd4e3c3eSJouni Malinen 		if (stat(path, &s) == 0) {
1980cd4e3c3eSJouni Malinen 			if (wpa_command(ifname, "P2P_SET ps 1") < 0) {
1981cd4e3c3eSJouni Malinen 				send_resp(dut, conn, SIGMA_ERROR,
1982cd4e3c3eSJouni Malinen 					  "errorCode,Going to sleep not supported");
1983cd4e3c3eSJouni Malinen 				return 0;
1984cd4e3c3eSJouni Malinen 			}
1985cd4e3c3eSJouni Malinen 			return 1;
1986cd4e3c3eSJouni Malinen 		}
1987cd4e3c3eSJouni Malinen #endif /* __linux__ */
1988cd4e3c3eSJouni Malinen 		if (wpa_command(ifname, "P2P_SET ps 99") < 0)
1989cd4e3c3eSJouni Malinen 			return -2;
1990cd4e3c3eSJouni Malinen 	} else {
1991cd4e3c3eSJouni Malinen 		if (wpa_command(ifname, "P2P_SET ps 1") < 0) {
1992cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
1993cd4e3c3eSJouni Malinen 				  "errorCode,Going to sleep not supported");
1994cd4e3c3eSJouni Malinen 			return 0;
1995cd4e3c3eSJouni Malinen 		}
1996cd4e3c3eSJouni Malinen 	}
1997cd4e3c3eSJouni Malinen 
1998cd4e3c3eSJouni Malinen 	return 1;
1999cd4e3c3eSJouni Malinen }
2000cd4e3c3eSJouni Malinen 
2001cd4e3c3eSJouni Malinen 
2002cd4e3c3eSJouni Malinen static int cmd_sta_set_opportunistic_ps(struct sigma_dut *dut,
2003cd4e3c3eSJouni Malinen 					struct sigma_conn *conn,
2004cd4e3c3eSJouni Malinen 					struct sigma_cmd *cmd)
2005cd4e3c3eSJouni Malinen {
2006cd4e3c3eSJouni Malinen 	/* const char *intf = get_param(cmd, "Interface"); */
2007cd4e3c3eSJouni Malinen 	struct wfa_cs_p2p_group *grp;
2008cd4e3c3eSJouni Malinen 	char buf[100];
2009cd4e3c3eSJouni Malinen 	const char *grpid = get_param(cmd, "GroupID");
2010cd4e3c3eSJouni Malinen 	const char *ctwindow = get_param(cmd, "CTWindow");
2011cd4e3c3eSJouni Malinen 
2012cd4e3c3eSJouni Malinen 	if (grpid == NULL || ctwindow == NULL)
2013cd4e3c3eSJouni Malinen 		return -1;
2014cd4e3c3eSJouni Malinen 
2015cd4e3c3eSJouni Malinen 	grp = p2p_group_get(dut, grpid);
2016cd4e3c3eSJouni Malinen 	if (grp == NULL) {
2017cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2018cd4e3c3eSJouni Malinen 			  "errorCode,Requested group not found");
2019cd4e3c3eSJouni Malinen 		return 0;
2020cd4e3c3eSJouni Malinen 	}
2021cd4e3c3eSJouni Malinen 
2022cd4e3c3eSJouni Malinen 	if (wpa_command(grp->ifname, "P2P_SET oppps 1") < 0) {
2023cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2024cd4e3c3eSJouni Malinen 			  "errorCode,Use of OppPS as GO not supported");
2025cd4e3c3eSJouni Malinen 		return 0;
2026cd4e3c3eSJouni Malinen 	}
2027cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "P2P_SET ctwindow %d", atoi(ctwindow));
2028cd4e3c3eSJouni Malinen 	if (wpa_command(grp->ifname, buf) < 0) {
2029cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2030cd4e3c3eSJouni Malinen 			  "errorCode,Use of CTWindow as GO not supported");
2031cd4e3c3eSJouni Malinen 		return 0;
2032cd4e3c3eSJouni Malinen 	}
2033cd4e3c3eSJouni Malinen 
2034cd4e3c3eSJouni Malinen 	return 1;
2035cd4e3c3eSJouni Malinen }
2036cd4e3c3eSJouni Malinen 
2037cd4e3c3eSJouni Malinen 
2038cd4e3c3eSJouni Malinen static int cmd_sta_send_service_discovery_req(struct sigma_dut *dut,
2039cd4e3c3eSJouni Malinen 					      struct sigma_conn *conn,
2040cd4e3c3eSJouni Malinen 					      struct sigma_cmd *cmd)
2041cd4e3c3eSJouni Malinen {
2042cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "Interface");
2043cd4e3c3eSJouni Malinen 	const char *devid = get_param(cmd, "P2PDevID");
2044cd4e3c3eSJouni Malinen 	char buf[128];
2045cd4e3c3eSJouni Malinen 
2046cd4e3c3eSJouni Malinen 	if (devid == NULL)
2047cd4e3c3eSJouni Malinen 		return -1;
2048cd4e3c3eSJouni Malinen 
2049cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "P2P_SERV_DISC_REQ %s 02000001",
2050cd4e3c3eSJouni Malinen 		 devid);
2051cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0) {
2052cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR, NULL);
2053cd4e3c3eSJouni Malinen 		return 0;
2054cd4e3c3eSJouni Malinen 	}
2055cd4e3c3eSJouni Malinen 
2056cd4e3c3eSJouni Malinen 	return 1;
2057cd4e3c3eSJouni Malinen }
2058cd4e3c3eSJouni Malinen 
2059cd4e3c3eSJouni Malinen 
2060cd4e3c3eSJouni Malinen static int cmd_sta_add_arp_table_entry(struct sigma_dut *dut,
2061cd4e3c3eSJouni Malinen 				       struct sigma_conn *conn,
2062cd4e3c3eSJouni Malinen 				       struct sigma_cmd *cmd)
2063cd4e3c3eSJouni Malinen {
2064cd4e3c3eSJouni Malinen 	char buf[256];
2065cd4e3c3eSJouni Malinen 	char *ifname;
2066cd4e3c3eSJouni Malinen 	const char *grpid, *ipaddr, *macaddr;
2067cd4e3c3eSJouni Malinen 
2068cd4e3c3eSJouni Malinen 	grpid = get_param(cmd, "GroupID");
2069cd4e3c3eSJouni Malinen 	ipaddr = get_param(cmd, "IPAddress");
2070cd4e3c3eSJouni Malinen 	macaddr = get_param(cmd, "MACAddress");
2071cd4e3c3eSJouni Malinen 	if (ipaddr == NULL || macaddr == NULL)
2072cd4e3c3eSJouni Malinen 		return -1;
2073cd4e3c3eSJouni Malinen 
2074cd4e3c3eSJouni Malinen 	if (grpid == NULL)
2075cd4e3c3eSJouni Malinen 		ifname = get_station_ifname();
2076cd4e3c3eSJouni Malinen 	else {
2077cd4e3c3eSJouni Malinen 		struct wfa_cs_p2p_group *grp;
2078cd4e3c3eSJouni Malinen 		grp = p2p_group_get(dut, grpid);
2079cd4e3c3eSJouni Malinen 		if (grp == NULL) {
2080cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
2081cd4e3c3eSJouni Malinen 				  "errorCode,Requested group not found");
2082cd4e3c3eSJouni Malinen 			return 0;
2083cd4e3c3eSJouni Malinen 		}
2084cd4e3c3eSJouni Malinen 		ifname = grp->ifname;
2085cd4e3c3eSJouni Malinen 	}
2086cd4e3c3eSJouni Malinen 
2087cd4e3c3eSJouni Malinen 	snprintf(dut->arp_ipaddr, sizeof(dut->arp_ipaddr), "%s",
2088cd4e3c3eSJouni Malinen 		 ipaddr);
2089cd4e3c3eSJouni Malinen 	snprintf(dut->arp_ifname, sizeof(dut->arp_ifname), "%s",
2090cd4e3c3eSJouni Malinen 		 ifname);
2091cd4e3c3eSJouni Malinen 
2092cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "ip nei add %s lladdr %s dev %s",
2093cd4e3c3eSJouni Malinen 		 ipaddr, macaddr, ifname);
2094cd4e3c3eSJouni Malinen 	run_system(dut, buf);
2095cd4e3c3eSJouni Malinen 
2096cd4e3c3eSJouni Malinen 	return 1;
2097cd4e3c3eSJouni Malinen }
2098cd4e3c3eSJouni Malinen 
2099cd4e3c3eSJouni Malinen 
2100cd4e3c3eSJouni Malinen static int cmd_sta_block_icmp_response(struct sigma_dut *dut,
2101cd4e3c3eSJouni Malinen 				       struct sigma_conn *conn,
2102cd4e3c3eSJouni Malinen 				       struct sigma_cmd *cmd)
2103cd4e3c3eSJouni Malinen {
2104cd4e3c3eSJouni Malinen 	char buf[256];
2105cd4e3c3eSJouni Malinen 	struct wfa_cs_p2p_group *grp;
2106cd4e3c3eSJouni Malinen 	char *ifname;
2107cd4e3c3eSJouni Malinen 	const char *grpid, *ipaddr;
2108cd4e3c3eSJouni Malinen 
2109cd4e3c3eSJouni Malinen 	grpid = get_param(cmd, "GroupID");
2110cd4e3c3eSJouni Malinen 	ipaddr = get_param(cmd, "IPAddress");
2111cd4e3c3eSJouni Malinen 	if (ipaddr == NULL)
2112cd4e3c3eSJouni Malinen 		return -1;
2113cd4e3c3eSJouni Malinen 
2114cd4e3c3eSJouni Malinen 	if (grpid == NULL)
2115cd4e3c3eSJouni Malinen 		ifname = get_station_ifname();
2116cd4e3c3eSJouni Malinen 	else {
2117cd4e3c3eSJouni Malinen 		grp = p2p_group_get(dut, grpid);
2118cd4e3c3eSJouni Malinen 		if (grp == NULL) {
2119cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
2120cd4e3c3eSJouni Malinen 				  "errorCode,Requested group not found");
2121cd4e3c3eSJouni Malinen 			return 0;
2122cd4e3c3eSJouni Malinen 		}
2123cd4e3c3eSJouni Malinen 		ifname = grp->ifname;
2124cd4e3c3eSJouni Malinen 	}
2125cd4e3c3eSJouni Malinen 
2126cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf),
2127cd4e3c3eSJouni Malinen 		 "iptables -I INPUT -s %s -p icmp -i %s -j DROP",
2128cd4e3c3eSJouni Malinen 		 ipaddr, ifname);
2129cd4e3c3eSJouni Malinen 	run_system(dut, buf);
2130cd4e3c3eSJouni Malinen 
2131cd4e3c3eSJouni Malinen 	return 1;
2132cd4e3c3eSJouni Malinen }
2133cd4e3c3eSJouni Malinen 
2134cd4e3c3eSJouni Malinen 
2135cd4e3c3eSJouni Malinen static int run_nfc_command(struct sigma_dut *dut, const char *cmd,
2136cd4e3c3eSJouni Malinen 			   const char *info)
2137cd4e3c3eSJouni Malinen {
2138cd4e3c3eSJouni Malinen 	int res;
2139cd4e3c3eSJouni Malinen 
2140cd4e3c3eSJouni Malinen 	sigma_dut_summary(dut, "NFC operation: %s", info);
2141cd4e3c3eSJouni Malinen 	printf("\n\n\n=====[ NFC operation ]=========================\n\n");
2142cd4e3c3eSJouni Malinen 	printf("%s\n\n", info);
2143cd4e3c3eSJouni Malinen 
2144cd4e3c3eSJouni Malinen 	nfc_status(dut, "START", info);
2145cd4e3c3eSJouni Malinen 	res = run_system(dut, cmd);
2146cd4e3c3eSJouni Malinen 	nfc_status(dut, res ? "FAIL" : "SUCCESS", info);
2147cd4e3c3eSJouni Malinen 	if (res) {
2148cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to run '%s': %d",
2149cd4e3c3eSJouni Malinen 				cmd, res);
2150cd4e3c3eSJouni Malinen 		return res;
2151cd4e3c3eSJouni Malinen 	}
2152cd4e3c3eSJouni Malinen 
2153cd4e3c3eSJouni Malinen 	return 0;
2154cd4e3c3eSJouni Malinen }
2155cd4e3c3eSJouni Malinen 
2156cd4e3c3eSJouni Malinen 
2157cd4e3c3eSJouni Malinen static int nfc_write_p2p_select(struct sigma_dut *dut, struct sigma_conn *conn,
2158cd4e3c3eSJouni Malinen 				struct sigma_cmd *cmd)
2159cd4e3c3eSJouni Malinen {
2160cd4e3c3eSJouni Malinen 	int res;
2161cd4e3c3eSJouni Malinen 	const char *ifname = get_param(cmd, "Interface");
2162cd4e3c3eSJouni Malinen 	char buf[300];
2163cd4e3c3eSJouni Malinen 
2164cd4e3c3eSJouni Malinen 	run_system(dut, "killall wps-nfc.py");
2165cd4e3c3eSJouni Malinen 	run_system(dut, "killall p2p-nfc.py");
2166cd4e3c3eSJouni Malinen 
2167cd4e3c3eSJouni Malinen 	if (wpa_command(ifname, "WPS_NFC_TOKEN NDEF") < 0) {
2168cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2169cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to generate NFC password token");
2170cd4e3c3eSJouni Malinen 		return 0;
2171cd4e3c3eSJouni Malinen 	}
2172cd4e3c3eSJouni Malinen 
2173cd4e3c3eSJouni Malinen 	unlink("nfc-success");
2174cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf),
2175cd4e3c3eSJouni Malinen 		 "./p2p-nfc.py -1 --no-wait %s%s --success nfc-success write-p2p-sel",
2176cd4e3c3eSJouni Malinen 		 dut->summary_log ? "--summary " : "",
2177cd4e3c3eSJouni Malinen 		 dut->summary_log ? dut->summary_log : "");
2178cd4e3c3eSJouni Malinen 	res = run_nfc_command(dut, buf,
2179cd4e3c3eSJouni Malinen 			      "Touch NFC Tag to write P2P connection handover select");
2180cd4e3c3eSJouni Malinen 	if (res || !file_exists("nfc-success")) {
2181cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2182cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to write tag");
2183cd4e3c3eSJouni Malinen 		return 0;
2184cd4e3c3eSJouni Malinen 	}
2185cd4e3c3eSJouni Malinen 
2186cd4e3c3eSJouni Malinen 	if (wpa_command(ifname, "P2P_SET nfc_tag 1") < 0) {
2187cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2188cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to enable NFC password token");
2189cd4e3c3eSJouni Malinen 		return 0;
2190cd4e3c3eSJouni Malinen 	}
2191cd4e3c3eSJouni Malinen 
2192cd4e3c3eSJouni Malinen 	if (!dut->go && wpa_command(ifname, "P2P_LISTEN") < 0) {
2193cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2194cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to start listen mode");
2195cd4e3c3eSJouni Malinen 		return 0;
2196cd4e3c3eSJouni Malinen 	}
2197cd4e3c3eSJouni Malinen 
2198cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE,
2199cd4e3c3eSJouni Malinen 		  "Result,,GroupID,,PeerRole,,PauseFlag,0");
2200cd4e3c3eSJouni Malinen 	return 0;
2201cd4e3c3eSJouni Malinen }
2202cd4e3c3eSJouni Malinen 
2203cd4e3c3eSJouni Malinen 
2204cd4e3c3eSJouni Malinen static int nfc_write_config_token(struct sigma_dut *dut,
2205cd4e3c3eSJouni Malinen 				  struct sigma_conn *conn,
2206cd4e3c3eSJouni Malinen 				  struct sigma_cmd *cmd)
2207cd4e3c3eSJouni Malinen {
2208cd4e3c3eSJouni Malinen 	int res;
2209cd4e3c3eSJouni Malinen 	const char *bssid = get_param(cmd, "Bssid");
2210cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "Interface");
2211cd4e3c3eSJouni Malinen 	char buf[200];
2212cd4e3c3eSJouni Malinen 
2213cd4e3c3eSJouni Malinen 	run_system(dut, "killall wps-nfc.py");
2214cd4e3c3eSJouni Malinen 	run_system(dut, "killall p2p-nfc.py");
2215cd4e3c3eSJouni Malinen 	unlink("nfc-success");
2216cd4e3c3eSJouni Malinen 	if (dut->er_oper_performed && bssid) {
2217cd4e3c3eSJouni Malinen 		char current_bssid[30], id[10];
2218cd4e3c3eSJouni Malinen 		if (get_wpa_status(intf, "id", id, sizeof(id)) < 0 ||
2219cd4e3c3eSJouni Malinen 		    get_wpa_status(intf, "bssid", current_bssid,
2220cd4e3c3eSJouni Malinen 				   sizeof(current_bssid)) < 0 ||
2221cd4e3c3eSJouni Malinen 		    strncasecmp(bssid, current_bssid, strlen(current_bssid)) !=
2222cd4e3c3eSJouni Malinen 		    0) {
2223cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
2224cd4e3c3eSJouni Malinen 				  "ErrorCode,No configuration known for BSSID");
2225cd4e3c3eSJouni Malinen 			return 0;
2226cd4e3c3eSJouni Malinen 		}
2227cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf),
2228cd4e3c3eSJouni Malinen 			 "./wps-nfc.py --id %s --no-wait %s%s --success nfc-success write-config",
2229cd4e3c3eSJouni Malinen 			 id,
2230cd4e3c3eSJouni Malinen 			 dut->summary_log ? "--summary " : "",
2231cd4e3c3eSJouni Malinen 			 dut->summary_log ? dut->summary_log : "");
2232cd4e3c3eSJouni Malinen 		res = run_nfc_command(dut, buf,
2233cd4e3c3eSJouni Malinen 				      "Touch NFC Tag to write WPS configuration token");
2234cd4e3c3eSJouni Malinen 	} else {
2235cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf),
2236cd4e3c3eSJouni Malinen 			 "./wps-nfc.py --no-wait %s%s --success nfc-success write-config",
2237cd4e3c3eSJouni Malinen 			 dut->summary_log ? "--summary " : "",
2238cd4e3c3eSJouni Malinen 			 dut->summary_log ? dut->summary_log : "");
2239cd4e3c3eSJouni Malinen 		res = run_nfc_command(dut, buf,
2240cd4e3c3eSJouni Malinen 				      "Touch NFC Tag to write WPS configuration token");
2241cd4e3c3eSJouni Malinen 	}
2242cd4e3c3eSJouni Malinen 	if (res || !file_exists("nfc-success")) {
2243cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2244cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to write tag");
2245cd4e3c3eSJouni Malinen 		return 0;
2246cd4e3c3eSJouni Malinen 	}
2247cd4e3c3eSJouni Malinen 
2248cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE,
2249cd4e3c3eSJouni Malinen 		  "Result,,GroupID,,PeerRole,,PauseFlag,0");
2250cd4e3c3eSJouni Malinen 	return 0;
2251cd4e3c3eSJouni Malinen }
2252cd4e3c3eSJouni Malinen 
2253cd4e3c3eSJouni Malinen 
2254cd4e3c3eSJouni Malinen static int nfc_write_password_token(struct sigma_dut *dut,
2255cd4e3c3eSJouni Malinen 				    struct sigma_conn *conn,
2256cd4e3c3eSJouni Malinen 				    struct sigma_cmd *cmd)
2257cd4e3c3eSJouni Malinen {
2258cd4e3c3eSJouni Malinen 	int res;
2259cd4e3c3eSJouni Malinen 	char buf[300];
2260cd4e3c3eSJouni Malinen 
2261cd4e3c3eSJouni Malinen 	run_system(dut, "killall wps-nfc.py");
2262cd4e3c3eSJouni Malinen 	run_system(dut, "killall p2p-nfc.py");
2263cd4e3c3eSJouni Malinen 	unlink("nfc-success");
2264cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf),
2265cd4e3c3eSJouni Malinen 		 "./wps-nfc.py --no-wait %s%s --success nfc-success write-password",
2266cd4e3c3eSJouni Malinen 		 dut->summary_log ? "--summary " : "",
2267cd4e3c3eSJouni Malinen 		 dut->summary_log ? dut->summary_log : "");
2268cd4e3c3eSJouni Malinen 	res = run_nfc_command(dut, buf,
2269cd4e3c3eSJouni Malinen 			      "Touch NFC Tag to write WPS password token");
2270cd4e3c3eSJouni Malinen 	if (res || !file_exists("nfc-success")) {
2271cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2272cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to write tag");
2273cd4e3c3eSJouni Malinen 		return 0;
2274cd4e3c3eSJouni Malinen 	}
2275cd4e3c3eSJouni Malinen 
2276cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE,
2277cd4e3c3eSJouni Malinen 		  "Result,,GroupID,,PeerRole,,PauseFlag,0");
2278cd4e3c3eSJouni Malinen 	return 0;
2279cd4e3c3eSJouni Malinen }
2280cd4e3c3eSJouni Malinen 
2281cd4e3c3eSJouni Malinen 
2282cd4e3c3eSJouni Malinen static int nfc_read_tag(struct sigma_dut *dut,
2283cd4e3c3eSJouni Malinen 			struct sigma_conn *conn,
2284cd4e3c3eSJouni Malinen 			struct sigma_cmd *cmd)
2285cd4e3c3eSJouni Malinen {
2286cd4e3c3eSJouni Malinen 	int res;
2287cd4e3c3eSJouni Malinen 	struct wpa_ctrl *ctrl;
2288cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "Interface");
2289cd4e3c3eSJouni Malinen 	const char *oper_chn = get_param(cmd, "OPER_CHN");
2290cd4e3c3eSJouni Malinen 	char buf[1000], freq_str[20];
2291cd4e3c3eSJouni Malinen 
2292cd4e3c3eSJouni Malinen 	run_system(dut, "killall wps-nfc.py");
2293cd4e3c3eSJouni Malinen 	run_system(dut, "killall p2p-nfc.py");
2294cd4e3c3eSJouni Malinen 
2295cd4e3c3eSJouni Malinen 	ctrl = open_wpa_mon(intf);
2296cd4e3c3eSJouni Malinen 	if (ctrl == NULL) {
2297cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
2298cd4e3c3eSJouni Malinen 				"wpa_supplicant monitor connection");
2299cd4e3c3eSJouni Malinen 		return -2;
2300cd4e3c3eSJouni Malinen 	}
2301cd4e3c3eSJouni Malinen 
2302cd4e3c3eSJouni Malinen 	freq_str[0] = '\0';
2303cd4e3c3eSJouni Malinen 	if (oper_chn) {
2304cd4e3c3eSJouni Malinen 		int chan = atoi(oper_chn);
2305cd4e3c3eSJouni Malinen 		if (chan >= 1 && chan <= 11)
2306cd4e3c3eSJouni Malinen 			snprintf(freq_str, sizeof(freq_str), " --freq %d",
2307cd4e3c3eSJouni Malinen 				 2407 + chan * 5);
2308cd4e3c3eSJouni Malinen 	}
2309cd4e3c3eSJouni Malinen 
2310cd4e3c3eSJouni Malinen 	unlink("nfc-success");
2311cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf),
2312cd4e3c3eSJouni Malinen 		 "./p2p-nfc.py -1 -t %s%s --success nfc-success --no-wait%s",
2313cd4e3c3eSJouni Malinen 		 dut->summary_log ? "--summary " : "",
2314cd4e3c3eSJouni Malinen 		 dut->summary_log ? dut->summary_log : "",
2315cd4e3c3eSJouni Malinen 		 freq_str);
2316cd4e3c3eSJouni Malinen 	res = run_nfc_command(dut, buf,
2317cd4e3c3eSJouni Malinen 			      "Touch NFC Tag to read it");
2318cd4e3c3eSJouni Malinen 	if (res || !file_exists("nfc-success")) {
2319cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2320cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to read tag");
2321cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2322cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2323cd4e3c3eSJouni Malinen 		return 0;
2324cd4e3c3eSJouni Malinen 	}
2325cd4e3c3eSJouni Malinen 
2326cd4e3c3eSJouni Malinen 	if (dut->p2p_mode == P2P_DISABLE)
2327cd4e3c3eSJouni Malinen 		return wps_connection_event(dut, conn, ctrl, intf, 1);
2328cd4e3c3eSJouni Malinen 
2329cd4e3c3eSJouni Malinen 	if (dut->go || dut->p2p_client) {
2330cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2331cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2332cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
2333cd4e3c3eSJouni Malinen 			  "Result,,GroupID,,PeerRole,,PauseFlag,0");
2334cd4e3c3eSJouni Malinen 		return 0;
2335cd4e3c3eSJouni Malinen 	}
2336cd4e3c3eSJouni Malinen 
2337cd4e3c3eSJouni Malinen 	/* FIX: PeerRole */
2338cd4e3c3eSJouni Malinen 	return p2p_group_formation_event(dut, conn, ctrl, intf, "0", 1);
2339cd4e3c3eSJouni Malinen }
2340cd4e3c3eSJouni Malinen 
2341cd4e3c3eSJouni Malinen 
2342cd4e3c3eSJouni Malinen static int nfc_wps_read_tag(struct sigma_dut *dut,
2343cd4e3c3eSJouni Malinen 			    struct sigma_conn *conn,
2344cd4e3c3eSJouni Malinen 			    struct sigma_cmd *cmd)
2345cd4e3c3eSJouni Malinen {
2346cd4e3c3eSJouni Malinen 	int res;
2347cd4e3c3eSJouni Malinen 	struct wpa_ctrl *ctrl;
2348cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "Interface");
2349cd4e3c3eSJouni Malinen 	char buf[300];
2350cd4e3c3eSJouni Malinen 
2351cd4e3c3eSJouni Malinen 	run_system(dut, "killall wps-nfc.py");
2352cd4e3c3eSJouni Malinen 	run_system(dut, "killall p2p-nfc.py");
2353cd4e3c3eSJouni Malinen 
2354cd4e3c3eSJouni Malinen 	ctrl = open_wpa_mon(intf);
2355cd4e3c3eSJouni Malinen 	if (ctrl == NULL) {
2356cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
2357cd4e3c3eSJouni Malinen 				"wpa_supplicant monitor connection");
2358cd4e3c3eSJouni Malinen 		return -2;
2359cd4e3c3eSJouni Malinen 	}
2360cd4e3c3eSJouni Malinen 
2361cd4e3c3eSJouni Malinen 	unlink("nfc-success");
2362cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf),
2363cd4e3c3eSJouni Malinen 		 "./wps-nfc.py -1 --no-wait %s%s --success nfc-success",
2364cd4e3c3eSJouni Malinen 		 dut->summary_log ? "--summary " : "",
2365cd4e3c3eSJouni Malinen 		 dut->summary_log ? dut->summary_log : "");
2366cd4e3c3eSJouni Malinen 	res = run_nfc_command(dut, buf, "Touch NFC Tag to read it");
2367cd4e3c3eSJouni Malinen 	if (res || !file_exists("nfc-success")) {
2368cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2369cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to read tag");
2370cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2371cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2372cd4e3c3eSJouni Malinen 		return 0;
2373cd4e3c3eSJouni Malinen 	}
2374cd4e3c3eSJouni Malinen 
2375cd4e3c3eSJouni Malinen 	return wps_connection_event(dut, conn, ctrl, intf, 1);
2376cd4e3c3eSJouni Malinen }
2377cd4e3c3eSJouni Malinen 
2378cd4e3c3eSJouni Malinen 
2379cd4e3c3eSJouni Malinen static int er_ap_add_match(const char *event, const char *bssid,
2380cd4e3c3eSJouni Malinen 			   const char *req_uuid,
2381cd4e3c3eSJouni Malinen 			   char *ret_uuid, size_t max_uuid_len)
2382cd4e3c3eSJouni Malinen {
2383cd4e3c3eSJouni Malinen 	const char *pos, *uuid;
2384cd4e3c3eSJouni Malinen 
2385cd4e3c3eSJouni Malinen 	pos = strchr(event, ' ');
2386cd4e3c3eSJouni Malinen 	if (pos == NULL)
2387cd4e3c3eSJouni Malinen 		return 0;
2388cd4e3c3eSJouni Malinen 	pos++;
2389cd4e3c3eSJouni Malinen 	uuid = pos;
2390cd4e3c3eSJouni Malinen 
2391cd4e3c3eSJouni Malinen 	pos = strchr(pos, ' ');
2392cd4e3c3eSJouni Malinen 	if (pos == NULL)
2393cd4e3c3eSJouni Malinen 		return 0;
2394cd4e3c3eSJouni Malinen 	if (ret_uuid) {
2395cd4e3c3eSJouni Malinen 		if ((size_t) (pos - uuid + 1) < max_uuid_len) {
2396cd4e3c3eSJouni Malinen 			memcpy(ret_uuid, uuid, pos - uuid);
2397cd4e3c3eSJouni Malinen 			ret_uuid[pos - uuid] = '\0';
2398cd4e3c3eSJouni Malinen 		} else
2399cd4e3c3eSJouni Malinen 			ret_uuid[0] = '\0';
2400cd4e3c3eSJouni Malinen 	}
2401cd4e3c3eSJouni Malinen 
2402cd4e3c3eSJouni Malinen 	if (req_uuid && strncasecmp(req_uuid, uuid, pos - uuid) == 0)
2403cd4e3c3eSJouni Malinen 		return 1;
2404cd4e3c3eSJouni Malinen 
2405cd4e3c3eSJouni Malinen 	pos++;
2406cd4e3c3eSJouni Malinen 	/* at BSSID */
2407cd4e3c3eSJouni Malinen 
2408cd4e3c3eSJouni Malinen 	return strncasecmp(pos, bssid, strlen(bssid)) == 0;
2409cd4e3c3eSJouni Malinen }
2410cd4e3c3eSJouni Malinen 
2411cd4e3c3eSJouni Malinen 
2412cd4e3c3eSJouni Malinen static int er_start(struct sigma_dut *dut, struct sigma_conn *conn,
2413cd4e3c3eSJouni Malinen 		    struct wpa_ctrl *ctrl, const char *intf, const char *bssid,
2414cd4e3c3eSJouni Malinen 		    const char *uuid, char *ret_uuid, size_t max_uuid_len)
2415cd4e3c3eSJouni Malinen {
2416cd4e3c3eSJouni Malinen 	char id[10];
2417cd4e3c3eSJouni Malinen 	int res;
2418cd4e3c3eSJouni Malinen 	char buf[1000];
2419cd4e3c3eSJouni Malinen 
2420cd4e3c3eSJouni Malinen 	sigma_dut_print(dut, DUT_MSG_INFO, "Trying to find WPS AP %s over UPnP",
2421cd4e3c3eSJouni Malinen 			bssid);
2422cd4e3c3eSJouni Malinen 
2423cd4e3c3eSJouni Malinen 	if (wpa_command(intf, "WPS_ER_START") < 0) {
2424cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2425cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to start ER");
2426cd4e3c3eSJouni Malinen 		return 0;
2427cd4e3c3eSJouni Malinen 	}
2428cd4e3c3eSJouni Malinen 
2429cd4e3c3eSJouni Malinen 	for (;;) {
2430cd4e3c3eSJouni Malinen 		res = get_wpa_cli_event(dut, ctrl, "WPS-ER-AP-ADD",
2431cd4e3c3eSJouni Malinen 					buf, sizeof(buf));
2432cd4e3c3eSJouni Malinen 		if (res < 0) {
2433cd4e3c3eSJouni Malinen #ifdef USE_ERROR_RETURNS
2434cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
2435cd4e3c3eSJouni Malinen 				  "ErrorCode,Could not find the AP over UPnP");
2436cd4e3c3eSJouni Malinen #else
2437cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_COMPLETE,
2438cd4e3c3eSJouni Malinen 				  "ErrorCode,Could not find the AP over UPnP");
2439cd4e3c3eSJouni Malinen #endif
2440cd4e3c3eSJouni Malinen 			return 0;
2441cd4e3c3eSJouni Malinen 		}
2442cd4e3c3eSJouni Malinen 
2443cd4e3c3eSJouni Malinen 		if (er_ap_add_match(buf, bssid, uuid, ret_uuid, max_uuid_len)) {
2444cd4e3c3eSJouni Malinen 			sigma_dut_print(dut, DUT_MSG_INFO,
2445cd4e3c3eSJouni Malinen 					"Found WPS AP over UPnP: %s", buf);
2446cd4e3c3eSJouni Malinen 			break;
2447cd4e3c3eSJouni Malinen 		}
2448cd4e3c3eSJouni Malinen 	}
2449cd4e3c3eSJouni Malinen 
2450cd4e3c3eSJouni Malinen 	if (get_wpa_status(intf, "id", id, sizeof(id)) < 0) {
2451cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2452cd4e3c3eSJouni Malinen 			  "ErrorCode,Could not find AP configuration");
2453cd4e3c3eSJouni Malinen 		return 0;
2454cd4e3c3eSJouni Malinen 	}
2455cd4e3c3eSJouni Malinen 
2456cd4e3c3eSJouni Malinen 	if (ret_uuid) {
2457cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "WPS_ER_SET_CONFIG %s %s",
2458cd4e3c3eSJouni Malinen 			 ret_uuid, id);
2459cd4e3c3eSJouni Malinen 	} else if (uuid) {
2460cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "WPS_ER_SET_CONFIG %s %s",
2461cd4e3c3eSJouni Malinen 			 uuid, id);
2462cd4e3c3eSJouni Malinen 	} else {
2463cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "WPS_ER_SET_CONFIG %s %s",
2464cd4e3c3eSJouni Malinen 			 bssid, id);
2465cd4e3c3eSJouni Malinen 	}
2466cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0) {
2467cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2468cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to select network configuration for ER");
2469cd4e3c3eSJouni Malinen 		return 0;
2470cd4e3c3eSJouni Malinen 	}
2471cd4e3c3eSJouni Malinen 
2472cd4e3c3eSJouni Malinen 	return 1;
2473cd4e3c3eSJouni Malinen }
2474cd4e3c3eSJouni Malinen 
2475cd4e3c3eSJouni Malinen 
2476cd4e3c3eSJouni Malinen static int nfc_wps_read_passwd(struct sigma_dut *dut,
2477cd4e3c3eSJouni Malinen 			       struct sigma_conn *conn,
2478cd4e3c3eSJouni Malinen 			       struct sigma_cmd *cmd)
2479cd4e3c3eSJouni Malinen {
2480cd4e3c3eSJouni Malinen 	int res;
2481cd4e3c3eSJouni Malinen 	struct wpa_ctrl *ctrl;
2482cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "Interface");
2483cd4e3c3eSJouni Malinen 	const char *bssid = get_param(cmd, "Bssid");
2484cd4e3c3eSJouni Malinen 	const char *ssid = get_param(cmd, "SSID");
2485cd4e3c3eSJouni Malinen 	const char *security = get_param(cmd, "Security");
2486cd4e3c3eSJouni Malinen 	const char *passphrase = get_param(cmd, "Passphrase");
2487cd4e3c3eSJouni Malinen 	char ssid_hex[200], passphrase_hex[200];
2488cd4e3c3eSJouni Malinen 	const char *val;
2489cd4e3c3eSJouni Malinen 	int sta_action;
2490cd4e3c3eSJouni Malinen 	char buf[1000];
2491cd4e3c3eSJouni Malinen 	const char *keymgmt, *cipher;
2492cd4e3c3eSJouni Malinen 
2493cd4e3c3eSJouni Malinen 	run_system(dut, "killall wps-nfc.py");
2494cd4e3c3eSJouni Malinen 	run_system(dut, "killall p2p-nfc.py");
2495cd4e3c3eSJouni Malinen 
24968c9c1563Svamsi krishna 	if ((ssid && 2 * strlen(ssid) >= sizeof(ssid_hex)) ||
24978c9c1563Svamsi krishna 	    (passphrase && 2 * strlen(passphrase) >= sizeof(passphrase_hex))) {
2498cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2499cd4e3c3eSJouni Malinen 			  "ErrorCode,Too long SSID/passphrase");
2500cd4e3c3eSJouni Malinen 		return 0;
2501cd4e3c3eSJouni Malinen 	}
2502cd4e3c3eSJouni Malinen 
2503cd4e3c3eSJouni Malinen 	val = get_param(cmd, "WpsStaAction");
2504cd4e3c3eSJouni Malinen 	if (!val) {
2505cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2506cd4e3c3eSJouni Malinen 			  "ErrorCode,Missing WpsStaAction argument");
2507cd4e3c3eSJouni Malinen 		return 0;
2508cd4e3c3eSJouni Malinen 	}
2509cd4e3c3eSJouni Malinen 
2510cd4e3c3eSJouni Malinen 	sta_action = atoi(val);
2511cd4e3c3eSJouni Malinen 	if (sta_action != 1 && sta_action != 2) {
2512cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2513cd4e3c3eSJouni Malinen 			  "ErrorCode,Unsupported WpsStaAction value");
2514cd4e3c3eSJouni Malinen 		return 0;
2515cd4e3c3eSJouni Malinen 	}
2516cd4e3c3eSJouni Malinen 
2517cd4e3c3eSJouni Malinen 	if (!bssid) {
2518cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2519cd4e3c3eSJouni Malinen 			  "ErrorCode,Missing Bssid argument");
2520cd4e3c3eSJouni Malinen 		return 0;
2521cd4e3c3eSJouni Malinen 	}
2522cd4e3c3eSJouni Malinen 
2523cd4e3c3eSJouni Malinen 	if (sta_action == 2) {
2524cd4e3c3eSJouni Malinen 		if (!ssid) {
2525cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
2526cd4e3c3eSJouni Malinen 				  "ErrorCode,Missing SSID argument");
2527cd4e3c3eSJouni Malinen 			return 0;
2528cd4e3c3eSJouni Malinen 		}
2529cd4e3c3eSJouni Malinen 
2530cd4e3c3eSJouni Malinen 		if (!security) {
2531cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
2532cd4e3c3eSJouni Malinen 				  "ErrorCode,Missing Security argument");
2533cd4e3c3eSJouni Malinen 			return 0;
2534cd4e3c3eSJouni Malinen 		}
2535cd4e3c3eSJouni Malinen 
2536cd4e3c3eSJouni Malinen 		if (!passphrase) {
2537cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
2538cd4e3c3eSJouni Malinen 				  "ErrorCode,Missing Passphrase argument");
2539cd4e3c3eSJouni Malinen 			return 0;
2540cd4e3c3eSJouni Malinen 		}
2541cd4e3c3eSJouni Malinen 	}
2542cd4e3c3eSJouni Malinen 
2543cd4e3c3eSJouni Malinen 	ctrl = open_wpa_mon(intf);
2544cd4e3c3eSJouni Malinen 	if (ctrl == NULL) {
2545cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
2546cd4e3c3eSJouni Malinen 				"wpa_supplicant monitor connection");
2547cd4e3c3eSJouni Malinen 		return -2;
2548cd4e3c3eSJouni Malinen 	}
2549cd4e3c3eSJouni Malinen 
2550cd4e3c3eSJouni Malinen 	if (sta_action == 1) {
2551cd4e3c3eSJouni Malinen 		const char *uuid = get_param(cmd, "UUID");
2552cd4e3c3eSJouni Malinen 		res = er_start(dut, conn, ctrl, intf, bssid, uuid, NULL, 0);
2553cd4e3c3eSJouni Malinen 		if (res != 1) {
2554cd4e3c3eSJouni Malinen 			wpa_ctrl_detach(ctrl);
2555cd4e3c3eSJouni Malinen 			wpa_ctrl_close(ctrl);
2556cd4e3c3eSJouni Malinen 			return res;
2557cd4e3c3eSJouni Malinen 		}
2558cd4e3c3eSJouni Malinen 	}
2559cd4e3c3eSJouni Malinen 
2560cd4e3c3eSJouni Malinen 	unlink("nfc-success");
2561cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf),
2562cd4e3c3eSJouni Malinen 		 "./wps-nfc.py -1 --no-wait %s%s --success nfc-success",
2563cd4e3c3eSJouni Malinen 		 dut->summary_log ? "--summary " : "",
2564cd4e3c3eSJouni Malinen 		 dut->summary_log ? dut->summary_log : "");
2565cd4e3c3eSJouni Malinen 	res = run_nfc_command(dut, buf, "Touch NFC Tag to read it");
2566cd4e3c3eSJouni Malinen 	if (res || !file_exists("nfc-success")) {
2567cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2568cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2569cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2570cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to read tag");
2571cd4e3c3eSJouni Malinen 		return 0;
2572cd4e3c3eSJouni Malinen 	}
2573cd4e3c3eSJouni Malinen 
2574cd4e3c3eSJouni Malinen 	if (sta_action == 1) {
2575cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Prepared device password for ER to enroll a new station");
2576cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2577cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2578cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
2579cd4e3c3eSJouni Malinen 			  "Result,,GroupID,,PeerRole,");
2580cd4e3c3eSJouni Malinen 		return 0;
2581cd4e3c3eSJouni Malinen 	}
2582cd4e3c3eSJouni Malinen 	if (strcasecmp(security, "wpa2-psk") == 0) {
2583cd4e3c3eSJouni Malinen 		keymgmt = "WPA2PSK";
2584cd4e3c3eSJouni Malinen 		cipher = "CCMP";
2585cd4e3c3eSJouni Malinen 	} else {
2586cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2587cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2588cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2589cd4e3c3eSJouni Malinen 			  "ErrorCode,Unsupported Security value");
2590cd4e3c3eSJouni Malinen 		return 0;
2591cd4e3c3eSJouni Malinen 	}
2592cd4e3c3eSJouni Malinen 
2593cd4e3c3eSJouni Malinen 	ascii2hexstr(ssid, ssid_hex);
2594cd4e3c3eSJouni Malinen 	ascii2hexstr(passphrase, passphrase_hex);
2595cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf), "WPS_REG %s nfc-pw %s %s %s %s",
2596cd4e3c3eSJouni Malinen 		 bssid, ssid_hex, keymgmt, cipher, passphrase_hex);
2597cd4e3c3eSJouni Malinen 
2598cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0) {
2599cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2600cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2601cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2602cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to start registrar");
2603cd4e3c3eSJouni Malinen 		return 0;
2604cd4e3c3eSJouni Malinen 	}
2605cd4e3c3eSJouni Malinen 
2606cd4e3c3eSJouni Malinen 	return wps_connection_event(dut, conn, ctrl, intf, 1);
2607cd4e3c3eSJouni Malinen }
2608cd4e3c3eSJouni Malinen 
2609cd4e3c3eSJouni Malinen 
2610cd4e3c3eSJouni Malinen static int nfc_wps_read_config(struct sigma_dut *dut,
2611cd4e3c3eSJouni Malinen 			       struct sigma_conn *conn,
2612cd4e3c3eSJouni Malinen 			       struct sigma_cmd *cmd)
2613cd4e3c3eSJouni Malinen {
2614cd4e3c3eSJouni Malinen 	int res;
2615cd4e3c3eSJouni Malinen 	struct wpa_ctrl *ctrl;
2616cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "Interface");
2617cd4e3c3eSJouni Malinen 	char buf[300];
2618cd4e3c3eSJouni Malinen 
2619cd4e3c3eSJouni Malinen 	run_system(dut, "killall wps-nfc.py");
2620cd4e3c3eSJouni Malinen 	run_system(dut, "killall p2p-nfc.py");
2621cd4e3c3eSJouni Malinen 
2622cd4e3c3eSJouni Malinen 	ctrl = open_wpa_mon(intf);
2623cd4e3c3eSJouni Malinen 	if (ctrl == NULL) {
2624cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
2625cd4e3c3eSJouni Malinen 				"wpa_supplicant monitor connection");
2626cd4e3c3eSJouni Malinen 		return -2;
2627cd4e3c3eSJouni Malinen 	}
2628cd4e3c3eSJouni Malinen 
2629cd4e3c3eSJouni Malinen 	unlink("nfc-success");
2630cd4e3c3eSJouni Malinen 	snprintf(buf, sizeof(buf),
2631cd4e3c3eSJouni Malinen 		 "./wps-nfc.py -1 --no-wait %s%s --success nfc-success",
2632cd4e3c3eSJouni Malinen 		 dut->summary_log ? "--summary " : "",
2633cd4e3c3eSJouni Malinen 		 dut->summary_log ? dut->summary_log : "");
2634cd4e3c3eSJouni Malinen 	res = run_nfc_command(dut, buf, "Touch NFC Tag to read it");
2635cd4e3c3eSJouni Malinen 	if (res || !file_exists("nfc-success")) {
2636cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2637cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to read tag");
2638cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2639cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2640cd4e3c3eSJouni Malinen 		return 0;
2641cd4e3c3eSJouni Malinen 	}
2642cd4e3c3eSJouni Malinen 
2643cd4e3c3eSJouni Malinen 	return wps_connection_event(dut, conn, ctrl, intf, 1);
2644cd4e3c3eSJouni Malinen }
2645cd4e3c3eSJouni Malinen 
2646cd4e3c3eSJouni Malinen 
2647cd4e3c3eSJouni Malinen static int nfc_wps_connection_handover(struct sigma_dut *dut,
2648cd4e3c3eSJouni Malinen 				       struct sigma_conn *conn,
2649cd4e3c3eSJouni Malinen 				       struct sigma_cmd *cmd)
2650cd4e3c3eSJouni Malinen {
2651cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "Interface");
2652cd4e3c3eSJouni Malinen 	int res;
2653cd4e3c3eSJouni Malinen 	const char *init = get_param(cmd, "Init");
2654cd4e3c3eSJouni Malinen 	struct wpa_ctrl *ctrl = NULL;
2655cd4e3c3eSJouni Malinen 	char buf[300];
2656cd4e3c3eSJouni Malinen 
2657cd4e3c3eSJouni Malinen 	run_system(dut, "killall wps-nfc.py");
2658cd4e3c3eSJouni Malinen 	run_system(dut, "killall p2p-nfc.py");
2659cd4e3c3eSJouni Malinen 
2660cd4e3c3eSJouni Malinen 	ctrl = open_wpa_mon(intf);
2661cd4e3c3eSJouni Malinen 	if (ctrl == NULL) {
2662cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
2663cd4e3c3eSJouni Malinen 				"wpa_supplicant monitor connection");
2664cd4e3c3eSJouni Malinen 		return -2;
2665cd4e3c3eSJouni Malinen 	}
2666cd4e3c3eSJouni Malinen 
2667cd4e3c3eSJouni Malinen 	unlink("nfc-success");
2668cd4e3c3eSJouni Malinen 	if ((!init || atoi(init) == 0) && dut->er_oper_performed) {
2669cd4e3c3eSJouni Malinen 		const char *bssid = get_param(cmd, "Bssid");
2670cd4e3c3eSJouni Malinen 		const char *req_uuid = get_param(cmd, "UUID");
2671cd4e3c3eSJouni Malinen 		char uuid[100];
2672cd4e3c3eSJouni Malinen 
2673cd4e3c3eSJouni Malinen 		if (bssid == NULL)
2674cd4e3c3eSJouni Malinen 			bssid = dut->er_oper_bssid;
2675cd4e3c3eSJouni Malinen 
2676cd4e3c3eSJouni Malinen 		res = er_start(dut, conn, ctrl, intf, bssid, req_uuid, uuid,
2677cd4e3c3eSJouni Malinen 			       sizeof(uuid));
2678cd4e3c3eSJouni Malinen 		if (res != 1) {
2679cd4e3c3eSJouni Malinen 			wpa_ctrl_detach(ctrl);
2680cd4e3c3eSJouni Malinen 			wpa_ctrl_close(ctrl);
2681cd4e3c3eSJouni Malinen 			return res;
2682cd4e3c3eSJouni Malinen 		}
2683cd4e3c3eSJouni Malinen 
2684cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf),
2685cd4e3c3eSJouni Malinen 			 "./wps-nfc.py -1 --uuid %s %s%s --success nfc-success",
2686cd4e3c3eSJouni Malinen 			 uuid,
2687cd4e3c3eSJouni Malinen 			 dut->summary_log ? "--summary " : "",
2688cd4e3c3eSJouni Malinen 			 dut->summary_log ? dut->summary_log : "");
2689cd4e3c3eSJouni Malinen 		res = run_nfc_command(dut, buf,
2690cd4e3c3eSJouni Malinen 				      "Touch NFC Device to respond to WPS connection handover");
2691cd4e3c3eSJouni Malinen 	} else if (!init || atoi(init)) {
2692cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf),
2693cd4e3c3eSJouni Malinen 			 "./wps-nfc.py -1 --no-wait %s%s --success nfc-success",
2694cd4e3c3eSJouni Malinen 			 dut->summary_log ? "--summary " : "",
2695cd4e3c3eSJouni Malinen 			 dut->summary_log ? dut->summary_log : "");
2696cd4e3c3eSJouni Malinen 		res = run_nfc_command(dut, buf,
2697cd4e3c3eSJouni Malinen 				      "Touch NFC Device to initiate WPS connection handover");
2698cd4e3c3eSJouni Malinen 	} else {
2699cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf),
2700cd4e3c3eSJouni Malinen 			 "./p2p-nfc.py -1 --no-wait --no-input %s%s --success nfc-success --handover-only",
2701cd4e3c3eSJouni Malinen 			 dut->summary_log ? "--summary " : "",
2702cd4e3c3eSJouni Malinen 			 dut->summary_log ? dut->summary_log : "");
2703cd4e3c3eSJouni Malinen 		res = run_nfc_command(dut, buf,
2704cd4e3c3eSJouni Malinen 				      "Touch NFC Device to respond to WPS connection handover");
2705cd4e3c3eSJouni Malinen 	}
2706cd4e3c3eSJouni Malinen 	if (res) {
2707cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2708cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2709cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2710cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to enable NFC for connection "
2711cd4e3c3eSJouni Malinen 			  "handover");
2712cd4e3c3eSJouni Malinen 		return 0;
2713cd4e3c3eSJouni Malinen 	}
2714cd4e3c3eSJouni Malinen 	if (!file_exists("nfc-success")) {
2715cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2716cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2717cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2718cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to complete NFC connection handover");
2719cd4e3c3eSJouni Malinen 		return 0;
2720cd4e3c3eSJouni Malinen 	}
2721cd4e3c3eSJouni Malinen 
2722cd4e3c3eSJouni Malinen 	if (init && atoi(init))
2723cd4e3c3eSJouni Malinen 		return wps_connection_event(dut, conn, ctrl, intf, 1);
2724cd4e3c3eSJouni Malinen 
2725cd4e3c3eSJouni Malinen 	wpa_ctrl_detach(ctrl);
2726cd4e3c3eSJouni Malinen 	wpa_ctrl_close(ctrl);
2727cd4e3c3eSJouni Malinen 
2728cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_COMPLETE,
2729cd4e3c3eSJouni Malinen 		  "Result,,GroupID,,PeerRole,,PauseFlag,0");
2730cd4e3c3eSJouni Malinen 	return 0;
2731cd4e3c3eSJouni Malinen }
2732cd4e3c3eSJouni Malinen 
2733cd4e3c3eSJouni Malinen 
2734cd4e3c3eSJouni Malinen static int nfc_p2p_connection_handover(struct sigma_dut *dut,
2735cd4e3c3eSJouni Malinen 				       struct sigma_conn *conn,
2736cd4e3c3eSJouni Malinen 				       struct sigma_cmd *cmd)
2737cd4e3c3eSJouni Malinen {
2738cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "Interface");
2739cd4e3c3eSJouni Malinen 	int res;
2740cd4e3c3eSJouni Malinen 	const char *init = get_param(cmd, "Init");
2741cd4e3c3eSJouni Malinen 	const char *oper_chn = get_param(cmd, "OPER_CHN");
2742cd4e3c3eSJouni Malinen 	struct wpa_ctrl *ctrl;
2743cd4e3c3eSJouni Malinen 	char buf[1000], freq_str[20];
2744cd4e3c3eSJouni Malinen 
2745cd4e3c3eSJouni Malinen 	run_system(dut, "killall wps-nfc.py");
2746cd4e3c3eSJouni Malinen 	run_system(dut, "killall p2p-nfc.py");
2747cd4e3c3eSJouni Malinen 
2748cd4e3c3eSJouni Malinen 	ctrl = open_wpa_mon(intf);
2749cd4e3c3eSJouni Malinen 	if (ctrl == NULL) {
2750cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
2751cd4e3c3eSJouni Malinen 				"wpa_supplicant monitor connection");
2752cd4e3c3eSJouni Malinen 		return -2;
2753cd4e3c3eSJouni Malinen 	}
2754cd4e3c3eSJouni Malinen 
2755cd4e3c3eSJouni Malinen 	freq_str[0] = '\0';
2756cd4e3c3eSJouni Malinen 	if (oper_chn) {
2757cd4e3c3eSJouni Malinen 		int chan = atoi(oper_chn);
2758cd4e3c3eSJouni Malinen 		if (chan >= 1 && chan <= 11)
2759cd4e3c3eSJouni Malinen 			snprintf(freq_str, sizeof(freq_str), " --freq %d",
2760cd4e3c3eSJouni Malinen 				 2407 + chan * 5);
2761cd4e3c3eSJouni Malinen 	}
2762cd4e3c3eSJouni Malinen 
2763cd4e3c3eSJouni Malinen 	unlink("nfc-success");
2764cd4e3c3eSJouni Malinen 	if (init && atoi(init)) {
2765cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf),
2766cd4e3c3eSJouni Malinen 			 "./p2p-nfc.py -1 -I -N --no-wait %s%s --success nfc-success --no-input%s --handover-only",
2767cd4e3c3eSJouni Malinen 			 dut->summary_log ? "--summary " : "",
2768cd4e3c3eSJouni Malinen 			 dut->summary_log ? dut->summary_log : "",
2769cd4e3c3eSJouni Malinen 			 freq_str);
2770cd4e3c3eSJouni Malinen 		res = run_nfc_command(dut, buf,
2771cd4e3c3eSJouni Malinen 				      "Touch NFC Device to initiate P2P connection handover");
2772cd4e3c3eSJouni Malinen 	} else {
2773cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf),
2774cd4e3c3eSJouni Malinen 			 "./p2p-nfc.py -1 --no-wait %s%s --success nfc-success --no-input%s --handover-only",
2775cd4e3c3eSJouni Malinen 			 dut->summary_log ? "--summary " : "",
2776cd4e3c3eSJouni Malinen 			 dut->summary_log ? dut->summary_log : "",
2777cd4e3c3eSJouni Malinen 			 freq_str);
2778cd4e3c3eSJouni Malinen 		res = run_nfc_command(dut, buf,
2779cd4e3c3eSJouni Malinen 				      "Touch NFC Device to respond to P2P connection handover");
2780cd4e3c3eSJouni Malinen 	}
2781cd4e3c3eSJouni Malinen 	if (res) {
2782cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2783cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2784cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2785cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to enable NFC for connection "
2786cd4e3c3eSJouni Malinen 			  "handover");
2787cd4e3c3eSJouni Malinen 		return 0;
2788cd4e3c3eSJouni Malinen 	}
2789cd4e3c3eSJouni Malinen 	if (!file_exists("nfc-success")) {
2790cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2791cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2792cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_ERROR,
2793cd4e3c3eSJouni Malinen 			  "ErrorCode,Failed to complete NFC connection handover");
2794cd4e3c3eSJouni Malinen 		return 0;
2795cd4e3c3eSJouni Malinen 	}
2796cd4e3c3eSJouni Malinen 
2797cd4e3c3eSJouni Malinen 	if (dut->go || dut->p2p_client) {
2798cd4e3c3eSJouni Malinen 		wpa_ctrl_detach(ctrl);
2799cd4e3c3eSJouni Malinen 		wpa_ctrl_close(ctrl);
2800cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE,
2801cd4e3c3eSJouni Malinen 			  "Result,,GroupID,,PeerRole,,PauseFlag,0");
2802cd4e3c3eSJouni Malinen 		return 0;
2803cd4e3c3eSJouni Malinen 	}
2804cd4e3c3eSJouni Malinen 
2805cd4e3c3eSJouni Malinen 	/* FIX: peer role from handover message */
2806cd4e3c3eSJouni Malinen 	return p2p_group_formation_event(dut, conn, ctrl, intf, "0", 1);
2807cd4e3c3eSJouni Malinen }
2808cd4e3c3eSJouni Malinen 
2809cd4e3c3eSJouni Malinen 
2810cd4e3c3eSJouni Malinen static int cmd_sta_nfc_action(struct sigma_dut *dut, struct sigma_conn *conn,
2811cd4e3c3eSJouni Malinen 			      struct sigma_cmd *cmd)
2812cd4e3c3eSJouni Malinen {
2813cd4e3c3eSJouni Malinen 	const char *intf = get_param(cmd, "Interface");
2814cd4e3c3eSJouni Malinen 	const char *oper = get_param(cmd, "Operation");
2815cd4e3c3eSJouni Malinen 	const char *ssid_param = get_param(cmd, "SSID");
2816cd4e3c3eSJouni Malinen 	const char *intent_val = get_param(cmd, "INTENT_VAL");
2817cd4e3c3eSJouni Malinen 	const char *oper_chn = get_param(cmd, "OPER_CHN");
2818cd4e3c3eSJouni Malinen 	char buf[256];
2819cd4e3c3eSJouni Malinen 
2820cd4e3c3eSJouni Malinen 	if (oper == NULL)
2821cd4e3c3eSJouni Malinen 		return -1;
2822cd4e3c3eSJouni Malinen 
2823cd4e3c3eSJouni Malinen 	if (ssid_param)
2824cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix %s",
2825cd4e3c3eSJouni Malinen 			 ssid_param);
2826cd4e3c3eSJouni Malinen 	else
2827cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix ");
2828cd4e3c3eSJouni Malinen 	if (wpa_command(intf, buf) < 0)
2829cd4e3c3eSJouni Malinen 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed P2P ssid_postfix - ignore and assume this is for non-P2P case");
2830cd4e3c3eSJouni Malinen 
2831cd4e3c3eSJouni Malinen 	if (intent_val) {
2832cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "SET p2p_go_intent %s", intent_val);
2833cd4e3c3eSJouni Malinen 		if (wpa_command(intf, buf) < 0)
2834cd4e3c3eSJouni Malinen 			return -2;
2835cd4e3c3eSJouni Malinen 	}
2836cd4e3c3eSJouni Malinen 
2837cd4e3c3eSJouni Malinen 	if (oper_chn) {
2838cd4e3c3eSJouni Malinen 		int chan = atoi(oper_chn);
2839cd4e3c3eSJouni Malinen 		if (chan < 1 || chan > 11) {
2840cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
2841cd4e3c3eSJouni Malinen 				  "ErrorCode,Unsupported operating channel");
2842cd4e3c3eSJouni Malinen 			return 0;
2843cd4e3c3eSJouni Malinen 		}
2844cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "SET p2p_oper_channel %d", chan);
2845cd4e3c3eSJouni Malinen 		if (wpa_command(intf, "SET p2p_oper_reg_class 81") < 0 ||
2846cd4e3c3eSJouni Malinen 		    wpa_command(intf, buf) < 0) {
2847cd4e3c3eSJouni Malinen 			send_resp(dut, conn, SIGMA_ERROR,
2848cd4e3c3eSJouni Malinen 				  "ErrorCode,Failed to set operating channel");
2849cd4e3c3eSJouni Malinen 			return 0;
2850cd4e3c3eSJouni Malinen 		}
2851cd4e3c3eSJouni Malinen 	}
2852cd4e3c3eSJouni Malinen 
2853cd4e3c3eSJouni Malinen 	if (strcasecmp(oper, "WRITE_SELECT") == 0)
2854cd4e3c3eSJouni Malinen 		return nfc_write_p2p_select(dut, conn, cmd);
2855cd4e3c3eSJouni Malinen 	if (strcasecmp(oper, "WRITE_CONFIG") == 0)
2856cd4e3c3eSJouni Malinen 		return nfc_write_config_token(dut, conn, cmd);
2857cd4e3c3eSJouni Malinen 	if (strcasecmp(oper, "WRITE_PASSWD") == 0)
2858cd4e3c3eSJouni Malinen 		return nfc_write_password_token(dut, conn, cmd);
2859cd4e3c3eSJouni Malinen 	if (strcasecmp(oper, "READ_TAG") == 0)
2860cd4e3c3eSJouni Malinen 		return nfc_read_tag(dut, conn, cmd);
2861cd4e3c3eSJouni Malinen 	if (strcasecmp(oper, "WPS_READ_TAG") == 0)
2862cd4e3c3eSJouni Malinen 		return nfc_wps_read_tag(dut, conn, cmd);
2863cd4e3c3eSJouni Malinen 	if (strcasecmp(oper, "WPS_READ_PASSWD") == 0)
2864cd4e3c3eSJouni Malinen 		return nfc_wps_read_passwd(dut, conn, cmd);
2865cd4e3c3eSJouni Malinen 	if (strcasecmp(oper, "WPS_READ_CONFIG") == 0)
2866cd4e3c3eSJouni Malinen 		return nfc_wps_read_config(dut, conn, cmd);
2867cd4e3c3eSJouni Malinen 	if (strcasecmp(oper, "CONN_HNDOVR") == 0)
2868cd4e3c3eSJouni Malinen 		return nfc_p2p_connection_handover(dut, conn, cmd);
2869cd4e3c3eSJouni Malinen 	if (strcasecmp(oper, "WPS_CONN_HNDOVR") == 0)
2870cd4e3c3eSJouni Malinen 		return nfc_wps_connection_handover(dut, conn, cmd);
2871cd4e3c3eSJouni Malinen 
2872cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported operation");
2873cd4e3c3eSJouni Malinen 	return 0;
2874cd4e3c3eSJouni Malinen }
2875cd4e3c3eSJouni Malinen 
2876cd4e3c3eSJouni Malinen 
2877cd4e3c3eSJouni Malinen int p2p_cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
2878cd4e3c3eSJouni Malinen 			      struct sigma_cmd *cmd)
2879cd4e3c3eSJouni Malinen {
2880cd4e3c3eSJouni Malinen 	const char *parameter = get_param(cmd, "Parameter");
2881cd4e3c3eSJouni Malinen 	char buf[100];
2882cd4e3c3eSJouni Malinen 
2883cd4e3c3eSJouni Malinen 	if (parameter == NULL)
2884cd4e3c3eSJouni Malinen 		return -1;
2885cd4e3c3eSJouni Malinen 	if (strcasecmp(parameter, "ListenChannel") == 0) {
2886cd4e3c3eSJouni Malinen 		snprintf(buf, sizeof(buf), "ListenChnl,%u", dut->listen_chn);
2887cd4e3c3eSJouni Malinen 		send_resp(dut, conn, SIGMA_COMPLETE, buf);
2888cd4e3c3eSJouni Malinen 		return 0;
2889cd4e3c3eSJouni Malinen 	}
2890cd4e3c3eSJouni Malinen 
2891cd4e3c3eSJouni Malinen 	send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
2892cd4e3c3eSJouni Malinen 	return 0;
2893cd4e3c3eSJouni Malinen }
2894cd4e3c3eSJouni Malinen 
2895cd4e3c3eSJouni Malinen 
2896cd4e3c3eSJouni Malinen static int req_intf(struct sigma_cmd *cmd)
2897cd4e3c3eSJouni Malinen {
2898cd4e3c3eSJouni Malinen 	return get_param(cmd, "interface") == NULL ? -1 : 0;
2899cd4e3c3eSJouni Malinen }
2900cd4e3c3eSJouni Malinen 
2901cd4e3c3eSJouni Malinen 
2902cd4e3c3eSJouni Malinen void p2p_register_cmds(void)
2903cd4e3c3eSJouni Malinen {
2904cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_get_p2p_dev_address", req_intf,
2905cd4e3c3eSJouni Malinen 			  cmd_sta_get_p2p_dev_address);
2906cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_set_p2p", req_intf, cmd_sta_set_p2p);
2907cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_start_autonomous_go", req_intf,
2908cd4e3c3eSJouni Malinen 			  cmd_sta_start_autonomous_go);
2909cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_p2p_connect", req_intf, cmd_sta_p2p_connect);
2910cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_p2p_start_group_formation", req_intf,
2911cd4e3c3eSJouni Malinen 			  cmd_sta_p2p_start_group_formation);
2912cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_p2p_dissolve", req_intf, cmd_sta_p2p_dissolve);
2913cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_send_p2p_invitation_req", req_intf,
2914cd4e3c3eSJouni Malinen 			  cmd_sta_send_p2p_invitation_req);
2915cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_accept_p2p_invitation_req", req_intf,
2916cd4e3c3eSJouni Malinen 			  cmd_sta_accept_p2p_invitation_req);
2917cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_send_p2p_provision_dis_req", req_intf,
2918cd4e3c3eSJouni Malinen 			  cmd_sta_send_p2p_provision_dis_req);
2919cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_set_wps_pbc", req_intf, cmd_sta_set_wps_pbc);
2920cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_wps_read_pin", req_intf, cmd_sta_wps_read_pin);
2921cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_wps_read_label", req_intf,
2922cd4e3c3eSJouni Malinen 			  cmd_sta_wps_read_label);
2923cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_wps_enter_pin", req_intf,
2924cd4e3c3eSJouni Malinen 			  cmd_sta_wps_enter_pin);
2925cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_get_psk", req_intf, cmd_sta_get_psk);
2926cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_p2p_reset", req_intf, cmd_sta_p2p_reset);
2927cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_get_p2p_ip_config", req_intf,
2928cd4e3c3eSJouni Malinen 			  cmd_sta_get_p2p_ip_config);
2929cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_send_p2p_presence_req", req_intf,
2930cd4e3c3eSJouni Malinen 			  cmd_sta_send_p2p_presence_req);
2931cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_set_sleep", req_intf, cmd_sta_set_sleep);
2932cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_set_opportunistic_ps", req_intf,
2933cd4e3c3eSJouni Malinen 			  cmd_sta_set_opportunistic_ps);
2934cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_send_service_discovery_req", req_intf,
2935cd4e3c3eSJouni Malinen 			  cmd_sta_send_service_discovery_req);
2936cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_add_arp_table_entry", req_intf,
2937cd4e3c3eSJouni Malinen 			  cmd_sta_add_arp_table_entry);
2938cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_block_icmp_response", req_intf,
2939cd4e3c3eSJouni Malinen 			  cmd_sta_block_icmp_response);
2940cd4e3c3eSJouni Malinen 	sigma_dut_reg_cmd("sta_nfc_action", req_intf, cmd_sta_nfc_action);
2941cd4e3c3eSJouni Malinen }
2942