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