xref: /wlan-dirver/utils/sigma-dut/p2p.c (revision 45c3c474c24b87d1a03e6bc4a9425f97edc126e3)
1 /*
2  * Sigma Control API DUT (station/AP)
3  * Copyright (c) 2010-2011, Atheros Communications, Inc.
4  * Copyright (c) 2011-2014, Qualcomm Atheros, Inc.
5  * All Rights Reserved.
6  * Licensed under the Clear BSD license. See README for more details.
7  */
8 
9 #include "sigma_dut.h"
10 #include <sys/stat.h>
11 #include "wpa_ctrl.h"
12 #include "wpa_helpers.h"
13 
14 
15 int run_system(struct sigma_dut *dut, const char *cmd)
16 {
17 	int res;
18 
19 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Running '%s'", cmd);
20 	res = system(cmd);
21 	if (res < 0) {
22 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Failed to execute "
23 				"command '%s'", cmd);
24 	}
25 	return res;
26 }
27 
28 
29 static int get_60g_freq(int chan)
30 {
31 	int freq = 0;
32 
33 	switch(chan) {
34 	case 1:
35 		freq = 58320;
36 		break;
37 	case 2:
38 		freq = 60480;
39 		break;
40 	case 3:
41 		freq = 62640;
42 		break;
43 	case 4:
44 		/* freq = 64800; Not supported in Sparrow 2.0 */
45 		break;
46 	default:
47 		break;
48 	}
49 
50 	return freq;
51 }
52 
53 
54 static int p2p_group_add(struct sigma_dut *dut, const char *ifname,
55 			 int go, const char *grpid, const char *ssid)
56 {
57 	struct wfa_cs_p2p_group *grp;
58 
59 	if (go)
60 		dut->go = 1;
61 	else
62 		dut->p2p_client = 1;
63 	grp = malloc(sizeof(*grp));
64 	if (grp == NULL)
65 		return -1;
66 	memset(grp, 0, sizeof(*grp));
67 	strncpy(grp->ifname, ifname, IFNAMSIZ);
68 	grp->go = go;
69 	strncpy(grp->grpid, grpid, P2P_GRP_ID_LEN);
70 	strncpy(grp->ssid, ssid, sizeof(grp->ssid));
71 
72 	grp->next = dut->groups;
73 	dut->groups = grp;
74 
75 	return 0;
76 }
77 
78 
79 static int p2p_group_remove(struct sigma_dut *dut, const char *grpid)
80 {
81 	struct wfa_cs_p2p_group *grp, *prev;
82 
83 	prev = NULL;
84 	grp = dut->groups;
85 	while (grp) {
86 		if (strcmp(grpid, grp->grpid) == 0) {
87 			if (prev)
88 				prev->next = grp->next;
89 			else
90 				dut->groups = grp->next;
91 			free(grp);
92 			return 0;
93 		}
94 		prev = grp;
95 		grp = grp->next;
96 	}
97 	return -1;
98 }
99 
100 
101 static struct wfa_cs_p2p_group * p2p_group_get(struct sigma_dut *dut,
102 					       const char *grpid)
103 {
104 	struct wfa_cs_p2p_group *grp;
105 	char buf[1000], buf2[4096], *ifname, *pos;
106 	char go_dev_addr[50];
107 	char ssid[33];
108 
109 	for (grp = dut->groups; grp; grp = grp->next) {
110 		if (strcmp(grpid, grp->grpid) == 0)
111 			return grp;
112 	}
113 
114 	/*
115 	 * No group found based on group id. As a workaround for GO Negotiation
116 	 * responder case where we do not store group id, try to find an active
117 	 * group that matches with the requested group id.
118 	 */
119 
120 	pos = strchr(grpid, ' ');
121 	if (pos == NULL)
122 		return NULL;
123 	if (pos - grpid > (int) sizeof(go_dev_addr))
124 		return NULL;
125 	memcpy(go_dev_addr, grpid, pos - grpid);
126 	go_dev_addr[pos - grpid] = '\0';
127 	strncpy(ssid, pos + 1, sizeof(ssid));
128 	ssid[sizeof(ssid) - 1] = '\0';
129 	printf("Trying to find suitable interface for group: go_dev_addr='%s' "
130 	       "grpid='%s'\n", go_dev_addr, grpid);
131 
132 	if (wpa_command_resp(get_main_ifname(), "INTERFACES", buf, sizeof(buf))
133 	    < 0)
134 		return NULL;
135 	ifname = buf;
136 	while (ifname && *ifname) {
137 		int add = 0;
138 		int go = 0;
139 		pos = strchr(ifname, '\n');
140 		if (pos)
141 			*pos++ = '\0';
142 		printf("Considering interface '%s' for group\n", ifname);
143 
144 		if (wpa_command_resp(ifname, "STATUS", buf2, sizeof(buf2)) ==
145 		    0) {
146 			if (strstr(buf2, ssid)) {
147 				printf("Selected interface '%s' based on "
148 				       "STATUS\n", ifname);
149 				add = 1;
150 			}
151 			if (strstr(buf2, "P2P GO"))
152 				go = 1;
153 		}
154 
155 		if (wpa_command_resp(ifname, "LIST_NETWORKS", buf2,
156 				     sizeof(buf2)) == 0) {
157 			char *line, *end;
158 			line = buf2;
159 			while (line && *line) {
160 				end = strchr(line, ' ');
161 				if (end)
162 					*end++ = '\0';
163 				if (strstr(line, ssid) &&
164 				    strstr(line, "[CURRENT]")) {
165 					printf("Selected interface '%s' "
166 					       "based on LIST_NETWORKS\n",
167 					       ifname);
168 					add = 1;
169 					break;
170 				}
171 				line = end;
172 			}
173 		}
174 
175 		if (add) {
176 			p2p_group_add(dut, ifname, go, grpid, ssid);
177 			return dut->groups;
178 		}
179 
180 		ifname = pos;
181 	}
182 
183 	return NULL;
184 }
185 
186 
187 static const char * get_group_ifname(struct sigma_dut *dut, const char *ifname)
188 {
189 	char buf[1000], *iface, *pos;
190 	char state[100];
191 
192 	if (dut->groups) {
193 		sigma_dut_print(dut, DUT_MSG_DEBUG, "%s: Use group interface "
194 				"%s instead of main interface %s",
195 				__func__, dut->groups->ifname, ifname);
196 		return dut->groups->ifname;
197 	}
198 
199 	/* Try to find a suitable group interface */
200 	if (wpa_command_resp(get_main_ifname(), "INTERFACES",
201 			     buf, sizeof(buf)) < 0)
202 		return ifname;
203 
204 	iface = buf;
205 	while (iface && *iface) {
206 		pos = strchr(iface, '\n');
207 		if (pos)
208 			*pos++ = '\0';
209 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Considering interface "
210 				"'%s' for IP address", iface);
211 		if (get_wpa_status(iface, "wpa_state", state, sizeof(state)) ==
212 		    0 && strcmp(state, "COMPLETED") == 0)
213 			return iface;
214 		iface = pos;
215 	}
216 
217 	return ifname;
218 }
219 
220 
221 static int p2p_peer_known(const char *ifname, const char *peer, int full)
222 {
223 	char buf[4096];
224 
225 	snprintf(buf, sizeof(buf), "P2P_PEER %s", peer);
226 	if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0)
227 		return 0;
228 	if (strncasecmp(buf, peer, strlen(peer)) != 0)
229 		return 0;
230 	if (!full)
231 		return 1;
232 	return strstr(buf, "[PROBE_REQ_ONLY]") == NULL ? 1 : 0;
233 }
234 
235 
236 static int p2p_discover_peer(struct sigma_dut *dut, const char *ifname,
237 			     const char *peer, int full)
238 {
239 	unsigned int count;
240 
241 	if (p2p_peer_known(ifname, peer, full))
242 		return 0;
243 	printf("Peer not yet discovered - start discovery\n");
244 	if (wpa_command(ifname, "P2P_FIND") < 0) {
245 		printf("Failed to start discovery\n");
246 		return -1;
247 	}
248 
249 	count = 0;
250 	while (count < dut->default_timeout) {
251 		count++;
252 		sleep(1);
253 		if (p2p_peer_known(ifname, peer, full)) {
254 			printf("Peer discovered - return to previous state\n");
255 			switch (dut->p2p_mode) {
256 			case P2P_IDLE:
257 				wpa_command(ifname, "P2P_STOP_FIND");
258 				break;
259 			case P2P_DISCOVER:
260 				/* Already running discovery */
261 				break;
262 			case P2P_LISTEN:
263 				wpa_command(ifname, "P2P_LISTEN");
264 				break;
265 			case P2P_DISABLE:
266 				printf("Invalid state - P2P was disabled?!\n");
267 				break;
268 			}
269 			return 0;
270 		}
271 	}
272 
273 	printf("Peer discovery timed out - peer not discovered\n");
274 	wpa_command(ifname, "P2P_STOP_FIND");
275 
276 	return -1;
277 }
278 
279 
280 static void add_dummy_services(const char *intf)
281 {
282 	wpa_command(intf, "P2P_SERVICE_ADD bonjour 0b5f6166706f766572746370c00c000c01 074578616d706c65c027");
283 	wpa_command(intf, "P2P_SERVICE_ADD bonjour 076578616d706c650b5f6166706f766572746370c00c001001 00");
284 	wpa_command(intf, "P2P_SERVICE_ADD bonjour 045f697070c00c000c01 094d795072696e746572c027");
285 	wpa_command(intf, "P2P_SERVICE_ADD bonjour 096d797072696e746572045f697070c00c001001 09747874766572733d311a70646c3d6170706c69636174696f6e2f706f7374736372797074");
286 
287 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::upnp:rootdevice");
288 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:5566d33e-9774-09ab-4822-333456785632::upnp:rootdevice");
289 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2");
290 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:5566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2");
291 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1");
292 
293 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1859dede-8574-59ab-9332-123456789012::upnp:rootdevice");
294 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1566d33e-9774-09ab-4822-333456785632::upnp:rootdevice");
295 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2");
296 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2");
297 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1");
298 
299 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2859dede-8574-59ab-9332-123456789012::upnp:rootdevice");
300 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2566d33e-9774-09ab-4822-333456785632::upnp:rootdevice");
301 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2");
302 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2");
303 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1");
304 
305 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3859dede-8574-59ab-9332-123456789012::upnp:rootdevice");
306 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3566d33e-9774-09ab-4822-333456785632::upnp:rootdevice");
307 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:4122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2");
308 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2");
309 	wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1");
310 }
311 
312 
313 void disconnect_station(struct sigma_dut *dut)
314 {
315 	wpa_command(get_station_ifname(), "DISCONNECT");
316 	remove_wpa_networks(get_station_ifname());
317 	dut->infra_ssid[0] = '\0';
318 #ifdef __linux__
319 	{
320 		char path[128];
321 		char buf[200];
322 		struct stat s;
323 		snprintf(path, sizeof(path), "/var/run/dhclient-%s.pid",
324 			 get_station_ifname());
325 		if (stat(path, &s) == 0) {
326 			snprintf(buf, sizeof(buf),
327 				 "kill `cat %s`", path);
328 			sigma_dut_print(dut, DUT_MSG_DEBUG,
329 					"Kill previous DHCP client: %s", buf);
330 			run_system(dut, buf);
331 			unlink(path);
332 		}
333 		snprintf(buf, sizeof(buf),
334 			 "ifconfig %s 0.0.0.0", get_station_ifname());
335 		sigma_dut_print(dut, DUT_MSG_DEBUG,
336 				"Clear infrastructure station IP address: %s",
337 				buf);
338 		run_system(dut, buf);
339    }
340 #endif /* __linux__ */
341 }
342 
343 
344 static int cmd_sta_get_p2p_dev_address(struct sigma_dut *dut,
345 				       struct sigma_conn *conn,
346 				       struct sigma_cmd *cmd)
347 {
348 	const char *intf = get_param(cmd, "interface");
349 	char buf[100], resp[200];
350 
351 	start_sta_mode(dut);
352 	if (get_wpa_status(intf, "p2p_device_address", buf, sizeof(buf)) < 0) {
353 		send_resp(dut, conn, SIGMA_ERROR, NULL);
354 		return 0;
355 	}
356 
357 	snprintf(resp, sizeof(resp), "DevID,%s", buf);
358 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
359 	return 0;
360 }
361 
362 
363 static int cmd_sta_set_p2p(struct sigma_dut *dut, struct sigma_conn *conn,
364 			   struct sigma_cmd *cmd)
365 {
366 	const char *intf = get_p2p_ifname(get_param(cmd, "Interface"));
367 	char buf[256];
368 	const char *val;
369 	const char *noa_dur, *noa_int, *noa_count;
370 	const char *ext_listen_int, *ext_listen_period;
371 
372 	val = get_param(cmd, "LISTEN_CHN");
373 	if (val) {
374 		dut->listen_chn = atoi(val);
375 		if (dut->listen_chn == 2) {
376 			/* social channel 2 on 60 GHz band */
377 			snprintf(buf, sizeof(buf),
378 				 "P2P_SET listen_channel 2 180");
379 		} else {
380 			/* social channels 1/6/11 on 2.4 GHz band */
381 			snprintf(buf, sizeof(buf), "P2P_SET listen_channel %d",
382 				 dut->listen_chn);
383 		}
384 		if (wpa_command(intf, buf) < 0)
385 			return -2;
386 	}
387 
388 	ext_listen_int = get_param(cmd, "Ext_Listen_Time_Interval");
389 	ext_listen_period = get_param(cmd, "Ext_Listen_Time_Period");
390 
391 	if (ext_listen_int || ext_listen_period) {
392 		if (!ext_listen_int || !ext_listen_period) {
393 			sigma_dut_print(dut, DUT_MSG_INFO, "Only one "
394 					"ext_listen_time parameter included; "
395 					"both are needed");
396 			return -1;
397 		}
398 		snprintf(buf, sizeof(buf), "P2P_EXT_LISTEN %d %d",
399 			 atoi(ext_listen_period),
400 			 atoi(ext_listen_int));
401 		if (wpa_command(intf, buf) < 0)
402 			return -2;
403 	}
404 
405 	val = get_param(cmd, "P2P_MODE");
406 	if (val) {
407 		if (strcasecmp(val, "Listen") == 0) {
408 			wpa_command(intf, "P2P_SET disabled 0");
409 			if (wpa_command(intf, "P2P_LISTEN") < 0)
410 				return -2;
411 			dut->p2p_mode = P2P_LISTEN;
412 		} else if (strcasecmp(val, "Discover") == 0) {
413 			wpa_command(intf, "P2P_SET disabled 0");
414 			if (wpa_command(intf, "P2P_FIND") < 0)
415 				return -2;
416 			dut->p2p_mode = P2P_DISCOVER;
417 		} else if (strcasecmp(val, "Idle") == 0) {
418 			wpa_command(intf, "P2P_SET disabled 0");
419 			if (wpa_command(intf, "P2P_STOP_FIND") < 0)
420 				return -2;
421 			dut->p2p_mode = P2P_IDLE;
422 		} else if (strcasecmp(val, "Disable") == 0) {
423 			if (wpa_command(intf, "P2P_SET disabled 1") < 0)
424 				return -2;
425 			dut->p2p_mode = P2P_DISABLE;
426 		} else
427 			return -1;
428 	}
429 
430 	val = get_param(cmd, "PERSISTENT");
431 	if (val) {
432 		dut->persistent = atoi(val);
433 	}
434 
435 	val = get_param(cmd, "INTRA_BSS");
436 	if (val) {
437 		int intra_bss = atoi(val);
438 		/* TODO: add support for this */
439 		if (!intra_bss) {
440 			sigma_dut_print(dut, DUT_MSG_INFO, "Disabling of "
441 					"intra-BSS bridging not supported");
442 			return -1;
443 		}
444 		dut->intra_bss = intra_bss;
445 	}
446 
447 	/* NoA is not applicable for 60 GHz */
448 	if (dut->program != PROGRAM_60GHZ) {
449 		noa_dur = get_param(cmd, "NoA_duration");
450 		noa_int = get_param(cmd, "NoA_Interval");
451 		noa_count = get_param(cmd, "NoA_Count");
452 		if (noa_dur)
453 			dut->noa_duration = atoi(noa_dur);
454 
455 		if (noa_int)
456 			dut->noa_interval = atoi(noa_int);
457 
458 		if (noa_count)
459 			dut->noa_count = atoi(noa_count);
460 
461 		if (noa_dur || noa_int || noa_count) {
462 			int start;
463 			const char *ifname;
464 			if (dut->noa_count == 0 && dut->noa_duration == 0)
465 				start = 0;
466 			else if (dut->noa_duration > 102) /* likely non-periodic
467 							   * NoA */
468 				start = 50;
469 			else
470 				start = 102 - dut->noa_duration;
471 			snprintf(buf, sizeof(buf), "P2P_SET noa %d,%d,%d",
472 				dut->noa_count, start,
473 				dut->noa_duration);
474 			ifname = get_group_ifname(dut, intf);
475 			sigma_dut_print(dut, DUT_MSG_INFO,
476 					"Set GO NoA for interface %s", ifname);
477 			if (wpa_command(ifname, buf) < 0) {
478 				send_resp(dut, conn, SIGMA_ERROR,
479 					  "errorCode,Use of NoA as GO not supported");
480 				return 0;
481 			}
482 		}
483 	}
484 
485 	val = get_param(cmd, "Concurrency");
486 	if (val) {
487 		/* TODO */
488 	}
489 
490 	val = get_param(cmd, "P2PInvitation");
491 	if (val) {
492 		/* TODO */
493 	}
494 
495 	val = get_param(cmd, "BCN_INT");
496 	if (val) {
497 		/* TODO */
498 	}
499 
500 	val = get_param(cmd, "Discoverability");
501 	if (val) {
502 		snprintf(buf, sizeof(buf), "P2P_SET discoverability %d",
503 			 atoi(val));
504 		if (wpa_command(intf, buf) < 0)
505 			return -2;
506 	}
507 
508 	val = get_param(cmd, "Service_Discovery");
509 	if (val) {
510 		int sd = atoi(val);
511 		if (sd) {
512 			wpa_command(intf, "P2P_SERVICE_FLUSH");
513 
514 			if (sd == 2)
515 				wpa_command(intf, "P2P_SET force_long_sd 1");
516 
517 			/*
518 			 * Set up some dummy service to create a large SD
519 			 * response that requires fragmentation.
520 			 */
521 			add_dummy_services(intf);
522 		} else {
523 			wpa_command(intf, "P2P_SERVICE_FLUSH");
524 		}
525 	}
526 
527 	val = get_param(cmd, "CrossConnection");
528 	if (val) {
529 		if (atoi(val)) {
530 			if (wpa_command(intf, "P2P_SET cross_connect 1") < 0)
531 				return -2;
532 		} else {
533 			if (wpa_command(intf, "P2P_SET cross_connect 0") < 0)
534 				return -2;
535 		}
536 	}
537 
538 	val = get_param(cmd, "P2PManaged");
539 	if (val) {
540 		if (atoi(val)) {
541 			send_resp(dut, conn, SIGMA_INVALID, "ErrorCode,"
542 				  "P2P Managed functionality not supported");
543 			return 0;
544 		}
545 	}
546 
547 	val = get_param(cmd, "GO_APSD");
548 	if (val) {
549 		if (atoi(val)) {
550 			if (wpa_command(intf, "P2P_SET go_apsd 1") < 0)
551 				return -2;
552 		} else {
553 			if (wpa_command(intf, "P2P_SET go_apsd 0") < 0)
554 				return -2;
555 		}
556 	}
557 
558 	return 1;
559 }
560 
561 
562 static int cmd_sta_start_autonomous_go(struct sigma_dut *dut,
563 				       struct sigma_conn *conn,
564 				       struct sigma_cmd *cmd)
565 {
566 	const char *intf = get_param(cmd, "Interface");
567 	const char *oper_chn = get_param(cmd, "OPER_CHN");
568 	const char *ssid_param = get_param(cmd, "SSID");
569 	int freq, chan, res;
570 	char buf[256], grpid[100], resp[200];
571 	struct wpa_ctrl *ctrl;
572 	char *ifname, *gtype, *pos, *ssid, bssid[20];
573 	char *go_dev_addr;
574 
575 	if (oper_chn == NULL)
576 		return -1;
577 
578 	chan = atoi(oper_chn);
579 	if (dut->program == PROGRAM_60GHZ) {
580 		freq = get_60g_freq(chan);
581 		if (freq == 0) {
582 			sigma_dut_print(dut, DUT_MSG_ERROR,
583 					"Invalid channel: %d", chan);
584 			return -1;
585 		}
586 	} else if (chan >= 1 && chan <= 13)
587 		freq = 2407 + chan * 5;
588 	else if (chan == 14)
589 		freq = 2484;
590 	else
591 		freq = 5000 + chan * 5;
592 
593 	if (ssid_param)
594 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix %s",
595 			 ssid_param);
596 	else
597 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix ");
598 	if (wpa_command(intf, buf) < 0)
599 		return -2;
600 
601 	/* Stop Listen/Discovery state to avoid issues with GO operations */
602 	if (wpa_command(intf, "P2P_STOP_FIND") < 0)
603 		return -2;
604 
605 	ctrl = open_wpa_mon(intf);
606 	if (ctrl == NULL) {
607 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
608 				"wpa_supplicant monitor connection");
609 		return -2;
610 	}
611 
612 	snprintf(buf, sizeof(buf), "P2P_GROUP_ADD %sfreq=%d",
613 		 dut->persistent ? "persistent " : "", freq);
614 	if (wpa_command(intf, buf) < 0) {
615 		wpa_ctrl_detach(ctrl);
616 		wpa_ctrl_close(ctrl);
617 		return -2;
618 	}
619 
620 	res = get_wpa_cli_event(dut, ctrl, "P2P-GROUP-STARTED",
621 				buf, sizeof(buf));
622 
623 	wpa_ctrl_detach(ctrl);
624 	wpa_ctrl_close(ctrl);
625 
626 	if (res < 0) {
627 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,GO starting "
628 			  "did not complete");
629 		return 0;
630 	}
631 
632 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group started event '%s'", buf);
633 	ifname = strchr(buf, ' ');
634 	if (ifname == NULL)
635 		return -2;
636 	ifname++;
637 	pos = strchr(ifname, ' ');
638 	if (pos == NULL)
639 		return -2;
640 	*pos++ = '\0';
641 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group interface %s", ifname);
642 
643 	gtype = pos;
644 	pos = strchr(gtype, ' ');
645 	if (pos == NULL)
646 		return -2;
647 	*pos++ = '\0';
648 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group type %s", gtype);
649 
650 	ssid = strstr(pos, "ssid=\"");
651 	if (ssid == NULL)
652 		return -2;
653 	ssid += 6;
654 	pos = strchr(ssid, '"');
655 	if (pos == NULL)
656 		return -2;
657 	*pos++ = '\0';
658 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group SSID %s", ssid);
659 
660 	go_dev_addr = strstr(pos, "go_dev_addr=");
661 	if (go_dev_addr == NULL) {
662 		sigma_dut_print(dut, DUT_MSG_ERROR, "No GO P2P Device Address "
663 				"found");
664 		return -2;
665 	}
666 	go_dev_addr += 12;
667 	if (strlen(go_dev_addr) < 17) {
668 		sigma_dut_print(dut, DUT_MSG_ERROR, "Too short GO P2P Device "
669 				"Address '%s'", go_dev_addr);
670 		return -2;
671 	}
672 	go_dev_addr[17] = '\0';
673 	*pos = '\0';
674 	sigma_dut_print(dut, DUT_MSG_DEBUG, "GO P2P Device Address %s",
675 			go_dev_addr);
676 
677 	if (get_wpa_status(ifname, "bssid", bssid, sizeof(bssid)) < 0)
678 		return -2;
679 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group BSSID %s", bssid);
680 
681 	snprintf(grpid, sizeof(grpid), "%s %s", go_dev_addr, ssid);
682 	p2p_group_add(dut, ifname, strcmp(gtype, "GO") == 0, grpid, ssid);
683 
684 	snprintf(resp, sizeof(resp), "GroupID,%s", grpid);
685 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
686 	return 0;
687 }
688 
689 
690 static int cmd_sta_p2p_connect(struct sigma_dut *dut, struct sigma_conn *conn,
691 			       struct sigma_cmd *cmd)
692 {
693 	const char *intf = get_p2p_ifname(get_param(cmd, "Interface"));
694 	const char *devid = get_param(cmd, "P2PDevID");
695 	/* const char *grpid_param = get_param(cmd, "GroupID"); */
696 	int res;
697 	char buf[256];
698 	struct wpa_ctrl *ctrl;
699 	char *ifname, *gtype, *pos, *ssid, bssid[20];
700 	char grpid[100];
701 
702 	/* TODO: handle the new grpid argument */
703 
704 	if (devid == NULL)
705 		return -1;
706 
707 	if (dut->wps_method == WFA_CS_WPS_NOT_READY) {
708 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS parameters "
709 			  "not yet set");
710 		return 0;
711 	}
712 
713 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover GO %s", devid);
714 	if (p2p_discover_peer(dut, intf, devid, 1) < 0) {
715 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
716 			  "discover the requested peer");
717 		return 0;
718 	}
719 
720 	ctrl = open_wpa_mon(intf);
721 	if (ctrl == NULL) {
722 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
723 				"wpa_supplicant monitor connection");
724 		return -2;
725 	}
726 
727 	switch (dut->wps_method) {
728 	case WFA_CS_WPS_PBC:
729 		snprintf(buf, sizeof(buf), "P2P_CONNECT %s pbc join",
730 			 devid);
731 		break;
732 	case WFA_CS_WPS_PIN_DISPLAY:
733 		snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s display join",
734 			 devid, dut->wps_pin);
735 		break;
736 	case WFA_CS_WPS_PIN_KEYPAD:
737 		snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s keypad join",
738 			 devid, dut->wps_pin);
739 		break;
740 	default:
741 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unknown WPS "
742 			  "method for sta_p2p_connect");
743 		wpa_ctrl_detach(ctrl);
744 		wpa_ctrl_close(ctrl);
745 		return 0;
746 	}
747 
748 	if (wpa_command(intf, buf) < 0) {
749 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to join "
750 			  "the group");
751 		wpa_ctrl_detach(ctrl);
752 		wpa_ctrl_close(ctrl);
753 		return 0;
754 	}
755 
756 	res = get_wpa_cli_event(dut, ctrl, "P2P-GROUP-STARTED",
757 				buf, sizeof(buf));
758 
759 	wpa_ctrl_detach(ctrl);
760 	wpa_ctrl_close(ctrl);
761 
762 	if (res < 0) {
763 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Group joining "
764 			  "did not complete");
765 		return 0;
766 	}
767 
768 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group started event '%s'", buf);
769 	ifname = strchr(buf, ' ');
770 	if (ifname == NULL)
771 		return -2;
772 	ifname++;
773 	pos = strchr(ifname, ' ');
774 	if (pos == NULL)
775 		return -2;
776 	*pos++ = '\0';
777 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group interface %s", ifname);
778 
779 	gtype = pos;
780 	pos = strchr(gtype, ' ');
781 	if (pos == NULL)
782 		return -2;
783 	*pos++ = '\0';
784 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group type %s", gtype);
785 
786 	ssid = strstr(pos, "ssid=\"");
787 	if (ssid == NULL)
788 		return -2;
789 	ssid += 6;
790 	pos = strchr(ssid, '"');
791 	if (pos == NULL)
792 		return -2;
793 	*pos = '\0';
794 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group SSID %s", ssid);
795 
796 	if (get_wpa_status(ifname, "bssid", bssid, sizeof(bssid)) < 0)
797 		return -2;
798 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group BSSID %s", bssid);
799 
800 	snprintf(grpid, sizeof(grpid), "%s %s", bssid, ssid);
801 	p2p_group_add(dut, ifname, strcmp(gtype, "GO") == 0, grpid, ssid);
802 
803 	return 1;
804 }
805 
806 
807 static int p2p_group_formation_event(struct sigma_dut *dut,
808 				     struct sigma_conn *conn,
809 				     struct wpa_ctrl *ctrl,
810 				     const char *intf, const char *peer_role,
811 				     int nfc);
812 
813 static int cmd_sta_p2p_start_group_formation(struct sigma_dut *dut,
814 					     struct sigma_conn *conn,
815 					     struct sigma_cmd *cmd)
816 {
817 	const char *intf = get_p2p_ifname(get_param(cmd, "Interface"));
818 	const char *devid = get_param(cmd, "P2PDevID");
819 	const char *intent_val = get_param(cmd, "INTENT_VAL");
820 	const char *init_go_neg = get_param(cmd, "INIT_GO_NEG");
821 	const char *oper_chn = get_param(cmd, "OPER_CHN");
822 	const char *ssid_param = get_param(cmd, "SSID");
823 	int freq = 0, chan = 0, init;
824 	char buf[256];
825 	struct wpa_ctrl *ctrl;
826 
827 	if (devid == NULL || intent_val == NULL)
828 		return -1;
829 
830 	if (init_go_neg)
831 		init = atoi(init_go_neg);
832 	else
833 		init = 0;
834 
835 	if (dut->program == PROGRAM_60GHZ) {
836 		if (!oper_chn)
837 			return -1;
838 		chan = atoi(oper_chn);
839 		freq = get_60g_freq(chan);
840 		if (freq == 0) {
841 			sigma_dut_print(dut, DUT_MSG_ERROR,
842 					"Invalid channel: %d", chan);
843 			return -1;
844 		}
845 	} else if (oper_chn) {
846 		chan = atoi(oper_chn);
847 		if (chan >= 1 && chan <= 13)
848 			freq = 2407 + chan * 5;
849 		else if (chan == 14)
850 			freq = 2484;
851 		else
852 			freq = 5000 + chan * 5;
853 	}
854 
855 	if (dut->wps_method == WFA_CS_WPS_NOT_READY) {
856 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS parameters "
857 			  "not yet set");
858 		return 0;
859 	}
860 
861 	sigma_dut_print(dut, DUT_MSG_DEBUG,
862 			"Trying to discover peer %s for group formation chan %d (freq %d)",
863 			devid, chan, freq);
864 	if (p2p_discover_peer(dut, intf, devid, init) < 0) {
865 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
866 			  "discover the requested peer");
867 		return 0;
868 	}
869 
870 	if (ssid_param)
871 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix %s",
872 			 ssid_param);
873 	else
874 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix ");
875 	if (wpa_command(intf, buf) < 0)
876 		return -2;
877 
878 	if (init) {
879 		ctrl = open_wpa_mon(intf);
880 		if (ctrl == NULL) {
881 			sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
882 					"wpa_supplicant monitor connection");
883 			return -2;
884 		}
885 	} else
886 		ctrl = NULL;
887 
888 	snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s%s%s%s go_intent=%d",
889 		 devid,
890 		 dut->wps_method == WFA_CS_WPS_PBC ?
891 		 "pbc" : dut->wps_pin,
892 		 dut->wps_method == WFA_CS_WPS_PBC ? "" :
893 		 (dut->wps_method == WFA_CS_WPS_PIN_DISPLAY ? " display" :
894 		  (dut->wps_method == WFA_CS_WPS_PIN_LABEL ? " label" :
895 		   " keypad" )),
896 		 dut->persistent ? " persistent" : "",
897 		 init ? "" : " auth",
898 		 atoi(intent_val));
899 	if (freq > 0) {
900 		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
901 			 " freq=%d", freq);
902 	}
903 	if (wpa_command(intf, buf) < 0) {
904 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to start "
905 			  "group formation");
906 		if (ctrl) {
907 			wpa_ctrl_detach(ctrl);
908 			wpa_ctrl_close(ctrl);
909 		}
910 		return 0;
911 	}
912 
913 	if (!init)
914 		return 1;
915 
916 	return p2p_group_formation_event(dut, conn, ctrl, intf, NULL, 0);
917 }
918 
919 
920 static int p2p_group_formation_event(struct sigma_dut *dut,
921 				     struct sigma_conn *conn,
922 				     struct wpa_ctrl *ctrl,
923 				     const char *intf, const char *peer_role,
924 				     int nfc)
925 {
926 	int res;
927 	char buf[256], grpid[50], resp[256];
928 	char *ifname, *gtype, *pos, *ssid, bssid[20];
929 	char *go_dev_addr;
930 	char role[30];
931 	const char *events[] = {
932 		"P2P-GROUP-STARTED",
933 		"P2P-GO-NEG-FAILURE",
934 		"P2P-NFC-PEER-CLIENT",
935 		"P2P-GROUP-FORMATION-FAILURE",
936 		NULL
937 	};
938 
939 	role[0] = '\0';
940 	if (peer_role)
941 		snprintf(role, sizeof(role), ",PeerRole,%s", peer_role);
942 
943 	res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
944 
945 	wpa_ctrl_detach(ctrl);
946 	wpa_ctrl_close(ctrl);
947 
948 	if (res < 0) {
949 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Group formation "
950 			  "did not complete");
951 		return 0;
952 	}
953 
954 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group started event '%s'", buf);
955 
956 	if (strstr(buf, "P2P-NFC-PEER-CLIENT")) {
957 		snprintf(resp, sizeof(resp),
958 			 "Result,,GroupID,,PeerRole,1,PauseFlag,0");
959 		send_resp(dut, conn, SIGMA_COMPLETE, resp);
960 		return 0;
961 	}
962 
963 	if (strstr(buf, "P2P-GROUP-FORMATION-FAILURE")) {
964 		snprintf(buf, sizeof(buf), "ErrorCode,Group formation failed");
965 		send_resp(dut, conn, SIGMA_ERROR, buf);
966 		return 0;
967 	}
968 
969 	if (strstr(buf, "P2P-GO-NEG-FAILURE")) {
970 		int status = -1;
971 		pos = strstr(buf, " status=");
972 		if (pos)
973 			status = atoi(pos + 8);
974 		sigma_dut_print(dut, DUT_MSG_INFO, "GO Negotiation failed "
975 				"(status=%d)", status);
976 		if (status == 9) {
977 			sigma_dut_print(dut, DUT_MSG_INFO, "Both devices "
978 					"tried to use GO Intent 15");
979 			send_resp(dut, conn, SIGMA_COMPLETE, "result,FAIL");
980 			return 0;
981 		}
982 		snprintf(buf, sizeof(buf), "ErrorCode,GO Negotiation failed "
983 			 "(status=%d)", status);
984 		send_resp(dut, conn, SIGMA_ERROR, buf);
985 		return 0;
986 	}
987 
988 	ifname = strchr(buf, ' ');
989 	if (ifname == NULL)
990 		return -2;
991 	ifname++;
992 	pos = strchr(ifname, ' ');
993 	if (pos == NULL)
994 		return -2;
995 	*pos++ = '\0';
996 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group interface %s", ifname);
997 
998 	gtype = pos;
999 	pos = strchr(gtype, ' ');
1000 	if (pos == NULL)
1001 		return -2;
1002 	*pos++ = '\0';
1003 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group type %s", gtype);
1004 
1005 	ssid = strstr(pos, "ssid=\"");
1006 	if (ssid == NULL)
1007 		return -2;
1008 	ssid += 6;
1009 	pos = strchr(ssid, '"');
1010 	if (pos == NULL)
1011 		return -2;
1012 	*pos++ = '\0';
1013 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group SSID %s", ssid);
1014 
1015 	go_dev_addr = strstr(pos, "go_dev_addr=");
1016 	if (go_dev_addr == NULL) {
1017 		sigma_dut_print(dut, DUT_MSG_ERROR, "No GO P2P Device Address "
1018 				"found\n");
1019 		return -2;
1020 	}
1021 	go_dev_addr += 12;
1022 	if (strlen(go_dev_addr) < 17) {
1023 		sigma_dut_print(dut, DUT_MSG_ERROR, "Too short GO P2P Device "
1024 				"Address '%s'", go_dev_addr);
1025 		return -2;
1026 	}
1027 	go_dev_addr[17] = '\0';
1028 	*pos = '\0';
1029 	sigma_dut_print(dut, DUT_MSG_ERROR, "GO P2P Device Address %s",
1030 			go_dev_addr);
1031 
1032 	if (get_wpa_status(ifname, "bssid", bssid, sizeof(bssid)) < 0)
1033 		return -2;
1034 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Group BSSID %s", bssid);
1035 
1036 	snprintf(grpid, sizeof(grpid), "%s %s", go_dev_addr, ssid);
1037 	p2p_group_add(dut, ifname, strcmp(gtype, "GO") == 0, grpid, ssid);
1038 	snprintf(resp, sizeof(resp), "Result,%s,GroupID,%s%s%s",
1039 		 strcmp(gtype, "GO") == 0 ? "GO" : "CLIENT", grpid, role,
1040 		 nfc ? ",PauseFlag,0" : "");
1041 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1042 
1043 #ifdef __QNXNTO__
1044 	/* Start DHCP server if we became the GO */
1045 	if (strcmp(gtype, "GO") == 0 &&
1046 	    system("dhcpd -cf /etc/dhcpd.conf -pf /var/run/dhcpd qca1 &") == 0)
1047 	     sigma_dut_print(dut, DUT_MSG_ERROR,
1048 			     "Failed to start DHCPD server");
1049 #endif /* __QNXNTO__ */
1050 
1051 	return 0;
1052 }
1053 
1054 
1055 int wps_connection_event(struct sigma_dut *dut, struct sigma_conn *conn,
1056 			 struct wpa_ctrl *ctrl, const char *intf, int p2p_resp)
1057 {
1058 	int res;
1059 	char buf[256];
1060 	const char *events[] = {
1061 		"CTRL-EVENT-CONNECTED",
1062 		"WPS-FAIL",
1063 		"WPS-TIMEOUT",
1064 		NULL
1065 	};
1066 
1067 	res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf));
1068 
1069 	wpa_ctrl_detach(ctrl);
1070 	wpa_ctrl_close(ctrl);
1071 
1072 	if (res < 0) {
1073 #ifdef USE_ERROR_RETURNS
1074 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS connection "
1075 			  "did not complete");
1076 #else
1077 		send_resp(dut, conn, SIGMA_COMPLETE, "ErrorCode,WPS connection "
1078 			  "did not complete");
1079 #endif
1080 		return 0;
1081 	}
1082 
1083 	if (strstr(buf, "WPS-FAIL") || strstr(buf, "WPS-TIMEOUT")) {
1084 #ifdef USE_ERROR_RETURNS
1085 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS operation "
1086 			  "failed");
1087 #else
1088 		send_resp(dut, conn, SIGMA_COMPLETE, "ErrorCode,WPS operation "
1089 			  "failed");
1090 #endif
1091 		return 0;
1092 	}
1093 
1094 	if (!p2p_resp)
1095 		return 1;
1096 	send_resp(dut, conn, SIGMA_COMPLETE, "Result,,GroupID,,PeerRole,");
1097 	return 0;
1098 }
1099 
1100 
1101 static int cmd_sta_p2p_dissolve(struct sigma_dut *dut, struct sigma_conn *conn,
1102 				struct sigma_cmd *cmd)
1103 {
1104 	const char *intf = get_param(cmd, "interface");
1105 	const char *grpid = get_param(cmd, "GroupID");
1106 	struct wfa_cs_p2p_group *grp;
1107 	char buf[128];
1108 
1109 	if (grpid == NULL)
1110 		return -1;
1111 
1112 	grp = p2p_group_get(dut, grpid);
1113 	if (grp == NULL) {
1114 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Requested group "
1115 			  "not found");
1116 		return 0;
1117 	}
1118 
1119 	snprintf(buf, sizeof(buf), "P2P_GROUP_REMOVE %s", grp->ifname);
1120 	if (wpa_command(intf, buf) < 0) {
1121 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to remove the "
1122 				"specified group from wpa_supplicant - assume "
1123 				"group has already been removed");
1124 	}
1125 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Removed group %s", grpid);
1126 	if (grp->go)
1127 		dut->go = 0;
1128 	else
1129 		dut->p2p_client = 0;
1130 	p2p_group_remove(dut, grpid);
1131 	return 1;
1132 }
1133 
1134 
1135 static int cmd_sta_send_p2p_invitation_req(struct sigma_dut *dut,
1136 					   struct sigma_conn *conn,
1137 					   struct sigma_cmd *cmd)
1138 {
1139 	const char *intf = get_param(cmd, "interface");
1140 	const char *devid = get_param(cmd, "P2PDevID");
1141 	const char *grpid = get_param(cmd, "GroupID");
1142 	const char *reinvoke = get_param(cmd, "Reinvoke");
1143 	char c[256];
1144 	char buf[4096];
1145 	struct wpa_ctrl *ctrl;
1146 	int res;
1147 
1148 	if (devid == NULL || grpid == NULL)
1149 		return -1;
1150 
1151 	if (reinvoke && atoi(reinvoke)) {
1152 		int id = -1;
1153 		char *ssid, *pos;
1154 
1155 		ssid = strchr(grpid, ' ');
1156 		if (ssid == NULL) {
1157 			sigma_dut_print(dut, DUT_MSG_INFO, "Invalid grpid");
1158 			return -1;
1159 		}
1160 		ssid++;
1161 		sigma_dut_print(dut, DUT_MSG_DEBUG, "Search for persistent "
1162 				"group credentials based on SSID: '%s'", ssid);
1163 		if (wpa_command_resp(intf, "LIST_NETWORKS",
1164 				     buf, sizeof(buf)) < 0)
1165 			return -2;
1166 		pos = strstr(buf, ssid);
1167 		if (pos == NULL || pos == buf || pos[-1] != '\t' ||
1168 		    pos[strlen(ssid)] != '\t') {
1169 			send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
1170 				  "Persistent group credentials not found");
1171 			return 0;
1172 		}
1173 		while (pos > buf && pos[-1] != '\n')
1174 			pos--;
1175 		id = atoi(pos);
1176 		snprintf(c, sizeof(c), "P2P_INVITE persistent=%d peer=%s",
1177 			 id, devid);
1178 	} else {
1179 		struct wfa_cs_p2p_group *grp;
1180 		grp = p2p_group_get(dut, grpid);
1181 		if (grp == NULL) {
1182 			send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,"
1183 				  "No active P2P group found for invitation");
1184 			return 0;
1185 		}
1186 		snprintf(c, sizeof(c), "P2P_INVITE group=%s peer=%s",
1187 			 grp->ifname, devid);
1188 	}
1189 
1190 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover peer %s for "
1191 			"invitation", devid);
1192 	if (p2p_discover_peer(dut, intf, devid, 0) < 0) {
1193 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
1194 			  "discover the requested peer");
1195 		return 0;
1196 	}
1197 
1198 	ctrl = open_wpa_mon(intf);
1199 	if (ctrl == NULL) {
1200 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
1201 				"wpa_supplicant monitor connection");
1202 		return -2;
1203 	}
1204 
1205 	if (wpa_command(intf, c) < 0) {
1206 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to send invitation "
1207 				"request");
1208 		wpa_ctrl_detach(ctrl);
1209 		wpa_ctrl_close(ctrl);
1210 		return -2;
1211 	}
1212 
1213 	res = get_wpa_cli_event(dut, ctrl, "P2P-INVITATION-RESULT",
1214 				buf, sizeof(buf));
1215 
1216 	wpa_ctrl_detach(ctrl);
1217 	wpa_ctrl_close(ctrl);
1218 
1219 	if (res < 0)
1220 		return -2;
1221 
1222 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Invitation event: '%s'", buf);
1223 	return 1;
1224 }
1225 
1226 
1227 static int cmd_sta_accept_p2p_invitation_req(struct sigma_dut *dut,
1228 					     struct sigma_conn *conn,
1229 					     struct sigma_cmd *cmd)
1230 {
1231 	const char *intf = get_param(cmd, "Interface");
1232 	const char *devid = get_param(cmd, "P2PDevID");
1233 	const char *grpid = get_param(cmd, "GroupID");
1234 	const char *reinvoke = get_param(cmd, "Reinvoke");
1235 	char buf[100];
1236 
1237 	if (devid == NULL || grpid == NULL)
1238 		return -1;
1239 
1240 	if (reinvoke && atoi(reinvoke)) {
1241 		/*
1242 		 * Assume persistent reconnect is enabled and there is no need
1243 		 * to do anything here.
1244 		 */
1245 		return 1;
1246 	}
1247 
1248 	/*
1249 	 * In a client-joining-a-running-group case, we need to separately
1250 	 * authorize the invitation.
1251 	 */
1252 
1253 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover GO %s", devid);
1254 	if (p2p_discover_peer(dut, intf, devid, 1) < 0) {
1255 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
1256 			  "discover the requested peer");
1257 		return 0;
1258 	}
1259 
1260 	snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s join auth",
1261 		 devid,
1262 		 dut->wps_method == WFA_CS_WPS_PBC ?
1263 		 "pbc" : dut->wps_pin);
1264 	if (wpa_command(intf, buf) < 0)
1265 		return -2;
1266 
1267 	return 1;
1268 }
1269 
1270 
1271 static int cmd_sta_send_p2p_provision_dis_req(struct sigma_dut *dut,
1272 					      struct sigma_conn *conn,
1273 					      struct sigma_cmd *cmd)
1274 {
1275 	const char *intf = get_param(cmd, "interface");
1276 	const char *conf_method = get_param(cmd, "ConfigMethod");
1277 	const char *devid = get_param(cmd, "P2PDevID");
1278 	char buf[256];
1279 	char *method;
1280 
1281 	if (conf_method == NULL || devid == NULL)
1282 		return -1;
1283 
1284 	if (strcasecmp(conf_method, "Display") == 0)
1285 		method = "display";
1286 	else if (strcasecmp(conf_method, "Keyboard") == 0 ||
1287 		 strcasecmp(conf_method, "keypad") == 0)
1288 		method = "keypad";
1289 	else if (strcasecmp(conf_method, "Label") == 0)
1290 		method = "label";
1291 	else if (strcasecmp(conf_method, "pbc") == 0 ||
1292 		 strcasecmp(conf_method, "pushbutton") == 0)
1293 		method = "pbc";
1294 	else
1295 		return -1;
1296 
1297 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover peer %s for "
1298 			"provision discovery", devid);
1299 	if (p2p_discover_peer(dut, intf, devid, 0) < 0) {
1300 		send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not "
1301 			  "discover the requested peer");
1302 		return 0;
1303 	}
1304 
1305 	snprintf(buf, sizeof(buf), "P2P_PROV_DISC %s %s", devid, method);
1306 	if (wpa_command(intf, buf) < 0) {
1307 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to send provision "
1308 				"discovery request");
1309 		return -2;
1310 	}
1311 
1312 	return 1;
1313 }
1314 
1315 
1316 static int cmd_sta_set_wps_pbc(struct sigma_dut *dut, struct sigma_conn *conn,
1317 			       struct sigma_cmd *cmd)
1318 {
1319 	/* const char *intf = get_param(cmd, "Interface"); */
1320 	const char *grpid = get_param(cmd, "GroupID");
1321 
1322 	if (grpid) {
1323 		struct wfa_cs_p2p_group *grp;
1324 		grp = p2p_group_get(dut, grpid);
1325 		if (grp && grp->go) {
1326 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a "
1327 					"client to join with WPS");
1328 			wpa_command(grp->ifname, "WPS_PBC");
1329 			return 1;
1330 		}
1331 	}
1332 
1333 	dut->wps_method = WFA_CS_WPS_PBC;
1334 	return 1;
1335 }
1336 
1337 
1338 static int cmd_sta_wps_read_pin(struct sigma_dut *dut, struct sigma_conn *conn,
1339 				struct sigma_cmd *cmd)
1340 {
1341 	/* const char *intf = get_param(cmd, "Interface"); */
1342 	const char *grpid = get_param(cmd, "GroupID");
1343 	char *pin = "12345670"; /* TODO: use random PIN */
1344 	char resp[100];
1345 
1346 	if (grpid) {
1347 		char buf[100];
1348 		struct wfa_cs_p2p_group *grp;
1349 		grp = p2p_group_get(dut, grpid);
1350 		if (grp && grp->go) {
1351 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a "
1352 					"client to join with WPS");
1353 			snprintf(buf, sizeof(buf), "WPS_PIN any %s", pin);
1354 			if (wpa_command(grp->ifname, buf) < 0)
1355 				return -1;
1356 			goto done;
1357 		}
1358 	}
1359 
1360 	strncpy(dut->wps_pin, pin, sizeof(dut->wps_pin));
1361 	dut->wps_method = WFA_CS_WPS_PIN_DISPLAY;
1362 done:
1363 	snprintf(resp, sizeof(resp), "PIN,%s", pin);
1364 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1365 
1366 	return 0;
1367 }
1368 
1369 
1370 static int cmd_sta_wps_read_label(struct sigma_dut *dut,
1371 				  struct sigma_conn *conn,
1372 				  struct sigma_cmd *cmd)
1373 {
1374 	/* const char *intf = get_param(cmd, "Interface"); */
1375 	const char *grpid = get_param(cmd, "GroupID");
1376 	char *pin = "12345670";
1377 	char resp[100];
1378 
1379 	if (grpid) {
1380 		char buf[100];
1381 		struct wfa_cs_p2p_group *grp;
1382 		grp = p2p_group_get(dut, grpid);
1383 		if (grp && grp->go) {
1384 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a "
1385 					"client to join with WPS");
1386 			snprintf(buf, sizeof(buf), "WPS_PIN any %s", pin);
1387 			wpa_command(grp->ifname, buf);
1388 			return 1;
1389 		}
1390 	}
1391 
1392 	strncpy(dut->wps_pin, pin, sizeof(dut->wps_pin));
1393 	dut->wps_method = WFA_CS_WPS_PIN_LABEL;
1394 	snprintf(resp, sizeof(resp), "LABEL,%s", pin);
1395 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1396 
1397 	return 0;
1398 }
1399 
1400 
1401 static int cmd_sta_wps_enter_pin(struct sigma_dut *dut,
1402 				 struct sigma_conn *conn,
1403 				 struct sigma_cmd *cmd)
1404 {
1405 	/* const char *intf = get_param(cmd, "Interface"); */
1406 	const char *grpid = get_param(cmd, "GroupID");
1407 	const char *pin = get_param(cmd, "PIN");
1408 
1409 	if (pin == NULL)
1410 		return -1;
1411 
1412 	if (grpid) {
1413 		char buf[100];
1414 		struct wfa_cs_p2p_group *grp;
1415 		grp = p2p_group_get(dut, grpid);
1416 		if (grp && grp->go) {
1417 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a "
1418 					"client to join with WPS");
1419 			snprintf(buf, sizeof(buf), "WPS_PIN any %s", pin);
1420 			wpa_command(grp->ifname, buf);
1421 			return 1;
1422 		}
1423 	}
1424 
1425 	strncpy(dut->wps_pin, pin, sizeof(dut->wps_pin));
1426 	dut->wps_pin[sizeof(dut->wps_pin) - 1] = '\0';
1427 	dut->wps_method = WFA_CS_WPS_PIN_KEYPAD;
1428 
1429 	return 1;
1430 }
1431 
1432 
1433 static int cmd_sta_get_psk(struct sigma_dut *dut, struct sigma_conn *conn,
1434 			   struct sigma_cmd *cmd)
1435 {
1436 	/* const char *intf = get_param(cmd, "interface"); */
1437 	const char *grpid = get_param(cmd, "GroupID");
1438 	struct wfa_cs_p2p_group *grp;
1439 	char passphrase[64], resp[200];
1440 
1441 	if (grpid == NULL)
1442 		return -1;
1443 
1444 	grp = p2p_group_get(dut, grpid);
1445 	if (grp == NULL) {
1446 		send_resp(dut, conn, SIGMA_ERROR,
1447 			  "errorCode,Requested group not found");
1448 		return 0;
1449 	}
1450 	if (!grp->go) {
1451 		send_resp(dut, conn, SIGMA_ERROR,
1452 			  "errorCode,Local role is not GO in the specified "
1453 			  "group");
1454 		return 0;
1455 	}
1456 
1457 	if (wpa_command_resp(grp->ifname, "P2P_GET_PASSPHRASE",
1458 			     passphrase, sizeof(passphrase)) < 0)
1459 		return -2;
1460 
1461 	snprintf(resp, sizeof(resp), "passPhrase,%s,ssid,%s",
1462 		 passphrase, grp->ssid);
1463 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1464 
1465 	return 0;
1466 }
1467 
1468 
1469 int cmd_sta_p2p_reset(struct sigma_dut *dut, struct sigma_conn *conn,
1470 		      struct sigma_cmd *cmd)
1471 {
1472 	const char *intf = get_param(cmd, "interface");
1473 	struct wfa_cs_p2p_group *grp, *prev;
1474 	char buf[256];
1475 
1476 	dut->go = 0;
1477 	dut->p2p_client = 0;
1478 	dut->wps_method = WFA_CS_WPS_NOT_READY;
1479 
1480 	grp = dut->groups;
1481 	while (grp) {
1482 		prev = grp;
1483 		grp = grp->next;
1484 
1485 		snprintf(buf, sizeof(buf), "P2P_GROUP_REMOVE %s",
1486 			 prev->ifname);
1487 		wpa_command(intf, buf);
1488 		p2p_group_remove(dut, prev->grpid);
1489 	}
1490 
1491 	wpa_command(intf, "P2P_GROUP_REMOVE *");
1492 	wpa_command(intf, "P2P_STOP_FIND");
1493 	wpa_command(intf, "P2P_FLUSH");
1494 	wpa_command(intf, "P2P_SERVICE_FLUSH");
1495 	wpa_command(intf, "P2P_SET disabled 0");
1496 	wpa_command(intf, "P2P_SET ssid_postfix ");
1497 
1498 	if (dut->program == PROGRAM_60GHZ) {
1499 		wpa_command(intf, "SET p2p_oper_reg_class 180");
1500 		wpa_command(intf, "P2P_SET listen_channel 2 180");
1501 		dut->listen_chn = 2;
1502 	} else {
1503 		wpa_command(intf, "P2P_SET listen_channel 6");
1504 		dut->listen_chn = 6;
1505 	}
1506 
1507 	wpa_command(intf, "P2P_EXT_LISTEN");
1508 	wpa_command(intf, "SET p2p_go_intent 7");
1509 	wpa_command(intf, "P2P_SET client_apsd disable");
1510 	wpa_command(intf, "P2P_SET go_apsd disable");
1511 	wpa_command(get_station_ifname(), "P2P_SET ps 98");
1512 	wpa_command(get_station_ifname(), "P2P_SET ps 96");
1513 	wpa_command(get_station_ifname(), "P2P_SET ps 0");
1514 	wpa_command(intf, "SET persistent_reconnect 1");
1515 	wpa_command(intf, "SET ampdu 1");
1516 	run_system(dut, "iptables -F INPUT");
1517 	if (dut->arp_ipaddr[0]) {
1518 		snprintf(buf, sizeof(buf), "ip nei del %s dev %s",
1519 			 dut->arp_ipaddr, dut->arp_ifname);
1520 		run_system(dut, buf);
1521 		dut->arp_ipaddr[0] = '\0';
1522 	}
1523 	snprintf(buf, sizeof(buf), "ip nei flush dev %s",
1524 		 get_station_ifname());
1525 	run_system(dut, buf);
1526 	dut->p2p_mode = P2P_IDLE;
1527 	dut->client_uapsd = 0;
1528 	ath6kl_client_uapsd(dut, intf, 0);
1529 
1530 	remove_wpa_networks(intf);
1531 
1532 	disconnect_station(dut);
1533 
1534 	if (dut->iface_down_on_reset)
1535 		dut_ifc_reset(dut);
1536 
1537 	return 1;
1538 }
1539 
1540 
1541 static int cmd_sta_get_p2p_ip_config(struct sigma_dut *dut,
1542 				     struct sigma_conn *conn,
1543 				     struct sigma_cmd *cmd)
1544 {
1545 	/* const char *intf = get_param(cmd, "Interface"); */
1546 	const char *grpid = get_param(cmd, "GroupID");
1547 	struct wfa_cs_p2p_group *grp = NULL;
1548 	int count;
1549 	char macaddr[20];
1550 	char resp[200], info[150];
1551 
1552 	if (grpid == NULL)
1553 		return -1;
1554 
1555 	if (strcmp(grpid, "$P2P_GROUP_ID") == 0)
1556 		return -1;
1557 
1558 	/*
1559 	 * If we did not initiate the operation that created the group, we may
1560 	 * not have the group information available in the DUT code yet and it
1561 	 * may take some time to get this from wpa_supplicant in case we are
1562 	 * the P2P client. As such, we better try this multiple times to allow
1563 	 * some time to complete the operation.
1564 	 */
1565 
1566 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting to find the requested "
1567 			"group");
1568 	count = dut->default_timeout;
1569 	while (count > 0) {
1570 		grp = p2p_group_get(dut, grpid);
1571 		if (grp == NULL) {
1572 			sigma_dut_print(dut, DUT_MSG_DEBUG, "Requested group "
1573 					"not yet found (count=%d)", count);
1574 			sleep(1);
1575 		} else
1576 			break;
1577 		count--;
1578 	}
1579 	if (grp == NULL) {
1580 		send_resp(dut, conn, SIGMA_ERROR,
1581 			  "errorCode,Requested group not found");
1582 		return 0;
1583 	}
1584 
1585 	sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting for IP address on group "
1586 			"interface %s", grp->ifname);
1587 	if (wait_ip_addr(dut, grp->ifname, dut->default_timeout) < 0) {
1588 		send_resp(dut, conn, SIGMA_ERROR,
1589 			  "errorCode,No IP address received");
1590 		return 0;
1591 	}
1592 
1593 	if (get_ip_config(dut, grp->ifname, info, sizeof(info)) < 0) {
1594 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get IP address "
1595 				"for group interface %s",
1596 				grp->ifname);
1597 		send_resp(dut, conn, SIGMA_ERROR,
1598 			  "errorCode,Failed to get IP address");
1599 		return 0;
1600 	}
1601 
1602 	if (get_wpa_status(grp->ifname, "address",
1603 			   macaddr, sizeof(macaddr)) < 0) {
1604 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to get interface "
1605 				"address for group interface %s",
1606 				grp->ifname);
1607 		return -2;
1608 	}
1609 
1610 	sigma_dut_print(dut, DUT_MSG_DEBUG, "IP address for group interface "
1611 			"%s found", grp->ifname);
1612 
1613 	snprintf(resp, sizeof(resp), "%s,P2PInterfaceAddress,%s",
1614 		 info, macaddr);
1615 
1616 	send_resp(dut, conn, SIGMA_COMPLETE, resp);
1617 	return 0;
1618 }
1619 
1620 
1621 static int cmd_sta_send_p2p_presence_req(struct sigma_dut *dut,
1622 					 struct sigma_conn *conn,
1623 					 struct sigma_cmd *cmd)
1624 {
1625 	const char *intf = get_param(cmd, "Interface");
1626 	const char *dur = get_param(cmd, "Duration");
1627 	const char *interv = get_param(cmd, "Interval");
1628 	/* const char *grpid = get_param(cmd, "GroupID"); */
1629 	const char *ifname;
1630 	char buf[100];
1631 
1632 	if (dur == NULL || interv == NULL)
1633 		return -1;
1634 
1635 	/* TODO: need to add groupid into parameters in CAPI spec; for now,
1636 	 * pick the first active group */
1637 	ifname = get_group_ifname(dut, intf);
1638 	snprintf(buf, sizeof(buf), "P2P_PRESENCE_REQ %s %s", dur, interv);
1639 	if (wpa_command(ifname, buf) < 0)
1640 		return -2;
1641 
1642 	return 1;
1643 }
1644 
1645 
1646 static int cmd_sta_set_sleep(struct sigma_dut *dut, struct sigma_conn *conn,
1647 			     struct sigma_cmd *cmd)
1648 {
1649 	/* const char *intf = get_param(cmd, "Interface"); */
1650 	struct wfa_cs_p2p_group *grp;
1651 	char *ifname;
1652 	const char *grpid = get_param(cmd, "GroupID");
1653 
1654 	if (grpid == NULL)
1655 		ifname = get_station_ifname();
1656 	else {
1657 		grp = p2p_group_get(dut, grpid);
1658 		if (grp == NULL) {
1659 			send_resp(dut, conn, SIGMA_ERROR,
1660 				  "errorCode,Requested group not found");
1661 			return 0;
1662 		}
1663 		ifname = grp->ifname;
1664 	}
1665 
1666 	if (dut->client_uapsd) {
1667 #ifdef __linux__
1668 		/* no special handling for nl80211 yet */
1669 		char path[128];
1670 		struct stat s;
1671 		snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211",
1672 			 ifname);
1673 		if (stat(path, &s) == 0) {
1674 			if (wpa_command(ifname, "P2P_SET ps 1") < 0) {
1675 				send_resp(dut, conn, SIGMA_ERROR,
1676 					  "errorCode,Going to sleep not supported");
1677 				return 0;
1678 			}
1679 			return 1;
1680 		}
1681 #endif /* __linux__ */
1682 		if (wpa_command(ifname, "P2P_SET ps 99") < 0)
1683 			return -2;
1684 	} else {
1685 		if (wpa_command(ifname, "P2P_SET ps 1") < 0) {
1686 			send_resp(dut, conn, SIGMA_ERROR,
1687 				  "errorCode,Going to sleep not supported");
1688 			return 0;
1689 		}
1690 	}
1691 
1692 	return 1;
1693 }
1694 
1695 
1696 static int cmd_sta_set_opportunistic_ps(struct sigma_dut *dut,
1697 					struct sigma_conn *conn,
1698 					struct sigma_cmd *cmd)
1699 {
1700 	/* const char *intf = get_param(cmd, "Interface"); */
1701 	struct wfa_cs_p2p_group *grp;
1702 	char buf[100];
1703 	const char *grpid = get_param(cmd, "GroupID");
1704 	const char *ctwindow = get_param(cmd, "CTWindow");
1705 
1706 	if (grpid == NULL || ctwindow == NULL)
1707 		return -1;
1708 
1709 	grp = p2p_group_get(dut, grpid);
1710 	if (grp == NULL) {
1711 		send_resp(dut, conn, SIGMA_ERROR,
1712 			  "errorCode,Requested group not found");
1713 		return 0;
1714 	}
1715 
1716 	if (wpa_command(grp->ifname, "P2P_SET oppps 1") < 0) {
1717 		send_resp(dut, conn, SIGMA_ERROR,
1718 			  "errorCode,Use of OppPS as GO not supported");
1719 		return 0;
1720 	}
1721 	snprintf(buf, sizeof(buf), "P2P_SET ctwindow %d", atoi(ctwindow));
1722 	if (wpa_command(grp->ifname, buf) < 0) {
1723 		send_resp(dut, conn, SIGMA_ERROR,
1724 			  "errorCode,Use of CTWindow as GO not supported");
1725 		return 0;
1726 	}
1727 
1728 	return 1;
1729 }
1730 
1731 
1732 static int cmd_sta_send_service_discovery_req(struct sigma_dut *dut,
1733 					      struct sigma_conn *conn,
1734 					      struct sigma_cmd *cmd)
1735 {
1736 	const char *intf = get_param(cmd, "Interface");
1737 	const char *devid = get_param(cmd, "P2PDevID");
1738 	char buf[128];
1739 
1740 	if (devid == NULL)
1741 		return -1;
1742 
1743 	snprintf(buf, sizeof(buf), "P2P_SERV_DISC_REQ %s 02000001",
1744 		 devid);
1745 	if (wpa_command(intf, buf) < 0) {
1746 		send_resp(dut, conn, SIGMA_ERROR, NULL);
1747 		return 0;
1748 	}
1749 
1750 	return 1;
1751 }
1752 
1753 
1754 static int cmd_sta_add_arp_table_entry(struct sigma_dut *dut,
1755 				       struct sigma_conn *conn,
1756 				       struct sigma_cmd *cmd)
1757 {
1758 	char buf[256];
1759 	char *ifname;
1760 	const char *grpid, *ipaddr, *macaddr;
1761 
1762 	grpid = get_param(cmd, "GroupID");
1763 	ipaddr = get_param(cmd, "IPAddress");
1764 	macaddr = get_param(cmd, "MACAddress");
1765 	if (ipaddr == NULL || macaddr == NULL)
1766 		return -1;
1767 
1768 	if (grpid == NULL)
1769 		ifname = get_station_ifname();
1770 	else {
1771 		struct wfa_cs_p2p_group *grp;
1772 		grp = p2p_group_get(dut, grpid);
1773 		if (grp == NULL) {
1774 			send_resp(dut, conn, SIGMA_ERROR,
1775 				  "errorCode,Requested group not found");
1776 			return 0;
1777 		}
1778 		ifname = grp->ifname;
1779 	}
1780 
1781 	snprintf(dut->arp_ipaddr, sizeof(dut->arp_ipaddr), "%s",
1782 		 ipaddr);
1783 	snprintf(dut->arp_ifname, sizeof(dut->arp_ifname), "%s",
1784 		 ifname);
1785 
1786 	snprintf(buf, sizeof(buf), "ip nei add %s lladdr %s dev %s",
1787 		 ipaddr, macaddr, ifname);
1788 	run_system(dut, buf);
1789 
1790 	return 1;
1791 }
1792 
1793 
1794 static int cmd_sta_block_icmp_response(struct sigma_dut *dut,
1795 				       struct sigma_conn *conn,
1796 				       struct sigma_cmd *cmd)
1797 {
1798 	char buf[256];
1799 	struct wfa_cs_p2p_group *grp;
1800 	char *ifname;
1801 	const char *grpid, *ipaddr;
1802 
1803 	grpid = get_param(cmd, "GroupID");
1804 	ipaddr = get_param(cmd, "IPAddress");
1805 	if (ipaddr == NULL)
1806 		return -1;
1807 
1808 	if (grpid == NULL)
1809 		ifname = get_station_ifname();
1810 	else {
1811 		grp = p2p_group_get(dut, grpid);
1812 		if (grp == NULL) {
1813 			send_resp(dut, conn, SIGMA_ERROR,
1814 				  "errorCode,Requested group not found");
1815 			return 0;
1816 		}
1817 		ifname = grp->ifname;
1818 	}
1819 
1820 	snprintf(buf, sizeof(buf),
1821 		 "iptables -I INPUT -s %s -p icmp -i %s -j DROP",
1822 		 ipaddr, ifname);
1823 	run_system(dut, buf);
1824 
1825 	return 1;
1826 }
1827 
1828 
1829 static int run_nfc_command(struct sigma_dut *dut, const char *cmd,
1830 			   const char *info)
1831 {
1832 	int res;
1833 
1834 	sigma_dut_summary(dut, "NFC operation: %s", info);
1835 	printf("\n\n\n=====[ NFC operation ]=========================\n\n");
1836 	printf("%s\n\n", info);
1837 
1838 	nfc_status(dut, "START", info);
1839 	res = run_system(dut, cmd);
1840 	nfc_status(dut, res ? "FAIL" : "SUCCESS", info);
1841 	if (res) {
1842 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to run '%s': %d",
1843 				cmd, res);
1844 		return res;
1845 	}
1846 
1847 	return 0;
1848 }
1849 
1850 
1851 static int nfc_write_p2p_select(struct sigma_dut *dut, struct sigma_conn *conn,
1852 				struct sigma_cmd *cmd)
1853 {
1854 	int res;
1855 	const char *ifname = get_param(cmd, "Interface");
1856 	char buf[300];
1857 
1858 	run_system(dut, "killall wps-nfc.py");
1859 	run_system(dut, "killall p2p-nfc.py");
1860 
1861 	if (wpa_command(ifname, "WPS_NFC_TOKEN NDEF") < 0) {
1862 		send_resp(dut, conn, SIGMA_ERROR,
1863 			  "ErrorCode,Failed to generate NFC password token");
1864 		return 0;
1865 	}
1866 
1867 	unlink("nfc-success");
1868 	snprintf(buf, sizeof(buf),
1869 		 "./p2p-nfc.py -1 --no-wait %s%s --success nfc-success write-p2p-sel",
1870 		 dut->summary_log ? "--summary " : "",
1871 		 dut->summary_log ? dut->summary_log : "");
1872 	res = run_nfc_command(dut, buf,
1873 			      "Touch NFC Tag to write P2P connection handover select");
1874 	if (res || !file_exists("nfc-success")) {
1875 		send_resp(dut, conn, SIGMA_ERROR,
1876 			  "ErrorCode,Failed to write tag");
1877 		return 0;
1878 	}
1879 
1880 	if (wpa_command(ifname, "P2P_SET nfc_tag 1") < 0) {
1881 		send_resp(dut, conn, SIGMA_ERROR,
1882 			  "ErrorCode,Failed to enable NFC password token");
1883 		return 0;
1884 	}
1885 
1886 	if (!dut->go && wpa_command(ifname, "P2P_LISTEN") < 0) {
1887 		send_resp(dut, conn, SIGMA_ERROR,
1888 			  "ErrorCode,Failed to start listen mode");
1889 		return 0;
1890 	}
1891 
1892 	send_resp(dut, conn, SIGMA_COMPLETE,
1893 		  "Result,,GroupID,,PeerRole,,PauseFlag,0");
1894 	return 0;
1895 }
1896 
1897 
1898 static int nfc_write_config_token(struct sigma_dut *dut,
1899 				  struct sigma_conn *conn,
1900 				  struct sigma_cmd *cmd)
1901 {
1902 	int res;
1903 	const char *bssid = get_param(cmd, "Bssid");
1904 	const char *intf = get_param(cmd, "Interface");
1905 	char buf[200];
1906 
1907 	run_system(dut, "killall wps-nfc.py");
1908 	run_system(dut, "killall p2p-nfc.py");
1909 	unlink("nfc-success");
1910 	if (dut->er_oper_performed && bssid) {
1911 		char current_bssid[30], id[10];
1912 		if (get_wpa_status(intf, "id", id, sizeof(id)) < 0 ||
1913 		    get_wpa_status(intf, "bssid", current_bssid,
1914 				   sizeof(current_bssid)) < 0 ||
1915 		    strncasecmp(bssid, current_bssid, strlen(current_bssid)) !=
1916 		    0) {
1917 			send_resp(dut, conn, SIGMA_ERROR,
1918 				  "ErrorCode,No configuration known for BSSID");
1919 			return 0;
1920 		}
1921 		snprintf(buf, sizeof(buf),
1922 			 "./wps-nfc.py --id %s --no-wait %s%s --success nfc-success write-config",
1923 			 id,
1924 			 dut->summary_log ? "--summary " : "",
1925 			 dut->summary_log ? dut->summary_log : "");
1926 		res = run_nfc_command(dut, buf,
1927 				      "Touch NFC Tag to write WPS configuration token");
1928 	} else {
1929 		snprintf(buf, sizeof(buf),
1930 			 "./wps-nfc.py --no-wait %s%s --success nfc-success write-config",
1931 			 dut->summary_log ? "--summary " : "",
1932 			 dut->summary_log ? dut->summary_log : "");
1933 		res = run_nfc_command(dut, buf,
1934 				      "Touch NFC Tag to write WPS configuration token");
1935 	}
1936 	if (res || !file_exists("nfc-success")) {
1937 		send_resp(dut, conn, SIGMA_ERROR,
1938 			  "ErrorCode,Failed to write tag");
1939 		return 0;
1940 	}
1941 
1942 	send_resp(dut, conn, SIGMA_COMPLETE,
1943 		  "Result,,GroupID,,PeerRole,,PauseFlag,0");
1944 	return 0;
1945 }
1946 
1947 
1948 static int nfc_write_password_token(struct sigma_dut *dut,
1949 				    struct sigma_conn *conn,
1950 				    struct sigma_cmd *cmd)
1951 {
1952 	int res;
1953 	char buf[300];
1954 
1955 	run_system(dut, "killall wps-nfc.py");
1956 	run_system(dut, "killall p2p-nfc.py");
1957 	unlink("nfc-success");
1958 	snprintf(buf, sizeof(buf),
1959 		 "./wps-nfc.py --no-wait %s%s --success nfc-success write-password",
1960 		 dut->summary_log ? "--summary " : "",
1961 		 dut->summary_log ? dut->summary_log : "");
1962 	res = run_nfc_command(dut, buf,
1963 			      "Touch NFC Tag to write WPS password token");
1964 	if (res || !file_exists("nfc-success")) {
1965 		send_resp(dut, conn, SIGMA_ERROR,
1966 			  "ErrorCode,Failed to write tag");
1967 		return 0;
1968 	}
1969 
1970 	send_resp(dut, conn, SIGMA_COMPLETE,
1971 		  "Result,,GroupID,,PeerRole,,PauseFlag,0");
1972 	return 0;
1973 }
1974 
1975 
1976 static int nfc_read_tag(struct sigma_dut *dut,
1977 			struct sigma_conn *conn,
1978 			struct sigma_cmd *cmd)
1979 {
1980 	int res;
1981 	struct wpa_ctrl *ctrl;
1982 	const char *intf = get_param(cmd, "Interface");
1983 	const char *oper_chn = get_param(cmd, "OPER_CHN");
1984 	char buf[1000], freq_str[20];
1985 
1986 	run_system(dut, "killall wps-nfc.py");
1987 	run_system(dut, "killall p2p-nfc.py");
1988 
1989 	ctrl = open_wpa_mon(intf);
1990 	if (ctrl == NULL) {
1991 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
1992 				"wpa_supplicant monitor connection");
1993 		return -2;
1994 	}
1995 
1996 	freq_str[0] = '\0';
1997 	if (oper_chn) {
1998 		int chan = atoi(oper_chn);
1999 		if (chan >= 1 && chan <= 11)
2000 			snprintf(freq_str, sizeof(freq_str), " --freq %d",
2001 				 2407 + chan * 5);
2002 	}
2003 
2004 	unlink("nfc-success");
2005 	snprintf(buf, sizeof(buf),
2006 		 "./p2p-nfc.py -1 -t %s%s --success nfc-success --no-wait%s",
2007 		 dut->summary_log ? "--summary " : "",
2008 		 dut->summary_log ? dut->summary_log : "",
2009 		 freq_str);
2010 	res = run_nfc_command(dut, buf,
2011 			      "Touch NFC Tag to read it");
2012 	if (res || !file_exists("nfc-success")) {
2013 		send_resp(dut, conn, SIGMA_ERROR,
2014 			  "ErrorCode,Failed to read tag");
2015 		wpa_ctrl_detach(ctrl);
2016 		wpa_ctrl_close(ctrl);
2017 		return 0;
2018 	}
2019 
2020 	if (dut->p2p_mode == P2P_DISABLE)
2021 		return wps_connection_event(dut, conn, ctrl, intf, 1);
2022 
2023 	if (dut->go || dut->p2p_client) {
2024 		wpa_ctrl_detach(ctrl);
2025 		wpa_ctrl_close(ctrl);
2026 		send_resp(dut, conn, SIGMA_COMPLETE,
2027 			  "Result,,GroupID,,PeerRole,,PauseFlag,0");
2028 		return 0;
2029 	}
2030 
2031 	/* FIX: PeerRole */
2032 	return p2p_group_formation_event(dut, conn, ctrl, intf, "0", 1);
2033 }
2034 
2035 
2036 static int nfc_wps_read_tag(struct sigma_dut *dut,
2037 			    struct sigma_conn *conn,
2038 			    struct sigma_cmd *cmd)
2039 {
2040 	int res;
2041 	struct wpa_ctrl *ctrl;
2042 	const char *intf = get_param(cmd, "Interface");
2043 	char buf[300];
2044 
2045 	run_system(dut, "killall wps-nfc.py");
2046 	run_system(dut, "killall p2p-nfc.py");
2047 
2048 	ctrl = open_wpa_mon(intf);
2049 	if (ctrl == NULL) {
2050 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
2051 				"wpa_supplicant monitor connection");
2052 		return -2;
2053 	}
2054 
2055 	unlink("nfc-success");
2056 	snprintf(buf, sizeof(buf),
2057 		 "./wps-nfc.py -1 --no-wait %s%s --success nfc-success",
2058 		 dut->summary_log ? "--summary " : "",
2059 		 dut->summary_log ? dut->summary_log : "");
2060 	res = run_nfc_command(dut, buf, "Touch NFC Tag to read it");
2061 	if (res || !file_exists("nfc-success")) {
2062 		send_resp(dut, conn, SIGMA_ERROR,
2063 			  "ErrorCode,Failed to read tag");
2064 		wpa_ctrl_detach(ctrl);
2065 		wpa_ctrl_close(ctrl);
2066 		return 0;
2067 	}
2068 
2069 	return wps_connection_event(dut, conn, ctrl, intf, 1);
2070 }
2071 
2072 
2073 static int er_ap_add_match(const char *event, const char *bssid,
2074 			   const char *req_uuid,
2075 			   char *ret_uuid, size_t max_uuid_len)
2076 {
2077 	const char *pos, *uuid;
2078 
2079 	pos = strchr(event, ' ');
2080 	if (pos == NULL)
2081 		return 0;
2082 	pos++;
2083 	uuid = pos;
2084 
2085 	pos = strchr(pos, ' ');
2086 	if (pos == NULL)
2087 		return 0;
2088 	if (ret_uuid) {
2089 		if ((size_t) (pos - uuid + 1) < max_uuid_len) {
2090 			memcpy(ret_uuid, uuid, pos - uuid);
2091 			ret_uuid[pos - uuid] = '\0';
2092 		} else
2093 			ret_uuid[0] = '\0';
2094 	}
2095 
2096 	if (req_uuid && strncasecmp(req_uuid, uuid, pos - uuid) == 0)
2097 		return 1;
2098 
2099 	pos++;
2100 	/* at BSSID */
2101 
2102 	return strncasecmp(pos, bssid, strlen(bssid)) == 0;
2103 }
2104 
2105 
2106 static int er_start(struct sigma_dut *dut, struct sigma_conn *conn,
2107 		    struct wpa_ctrl *ctrl, const char *intf, const char *bssid,
2108 		    const char *uuid, char *ret_uuid, size_t max_uuid_len)
2109 {
2110 	char id[10];
2111 	int res;
2112 	char buf[1000];
2113 
2114 	sigma_dut_print(dut, DUT_MSG_INFO, "Trying to find WPS AP %s over UPnP",
2115 			bssid);
2116 
2117 	if (wpa_command(intf, "WPS_ER_START") < 0) {
2118 		send_resp(dut, conn, SIGMA_ERROR,
2119 			  "ErrorCode,Failed to start ER");
2120 		return 0;
2121 	}
2122 
2123 	for (;;) {
2124 		res = get_wpa_cli_event(dut, ctrl, "WPS-ER-AP-ADD",
2125 					buf, sizeof(buf));
2126 		if (res < 0) {
2127 #ifdef USE_ERROR_RETURNS
2128 			send_resp(dut, conn, SIGMA_ERROR,
2129 				  "ErrorCode,Could not find the AP over UPnP");
2130 #else
2131 			send_resp(dut, conn, SIGMA_COMPLETE,
2132 				  "ErrorCode,Could not find the AP over UPnP");
2133 #endif
2134 			return 0;
2135 		}
2136 
2137 		if (er_ap_add_match(buf, bssid, uuid, ret_uuid, max_uuid_len)) {
2138 			sigma_dut_print(dut, DUT_MSG_INFO,
2139 					"Found WPS AP over UPnP: %s", buf);
2140 			break;
2141 		}
2142 	}
2143 
2144 	if (get_wpa_status(intf, "id", id, sizeof(id)) < 0) {
2145 		send_resp(dut, conn, SIGMA_ERROR,
2146 			  "ErrorCode,Could not find AP configuration");
2147 		return 0;
2148 	}
2149 
2150 	if (ret_uuid) {
2151 		snprintf(buf, sizeof(buf), "WPS_ER_SET_CONFIG %s %s",
2152 			 ret_uuid, id);
2153 	} else if (uuid) {
2154 		snprintf(buf, sizeof(buf), "WPS_ER_SET_CONFIG %s %s",
2155 			 uuid, id);
2156 	} else {
2157 		snprintf(buf, sizeof(buf), "WPS_ER_SET_CONFIG %s %s",
2158 			 bssid, id);
2159 	}
2160 	if (wpa_command(intf, buf) < 0) {
2161 		send_resp(dut, conn, SIGMA_ERROR,
2162 			  "ErrorCode,Failed to select network configuration for ER");
2163 		return 0;
2164 	}
2165 
2166 	return 1;
2167 }
2168 
2169 
2170 static int nfc_wps_read_passwd(struct sigma_dut *dut,
2171 			       struct sigma_conn *conn,
2172 			       struct sigma_cmd *cmd)
2173 {
2174 	int res;
2175 	struct wpa_ctrl *ctrl;
2176 	const char *intf = get_param(cmd, "Interface");
2177 	const char *bssid = get_param(cmd, "Bssid");
2178 	const char *ssid = get_param(cmd, "SSID");
2179 	const char *security = get_param(cmd, "Security");
2180 	const char *passphrase = get_param(cmd, "Passphrase");
2181 	char ssid_hex[200], passphrase_hex[200];
2182 	const char *val;
2183 	int sta_action;
2184 	char buf[1000];
2185 	const char *keymgmt, *cipher;
2186 
2187 	run_system(dut, "killall wps-nfc.py");
2188 	run_system(dut, "killall p2p-nfc.py");
2189 
2190 	if ((ssid && strlen(ssid) >= 2 * sizeof(ssid_hex)) ||
2191 	    (passphrase && strlen(passphrase) >= 2 * sizeof(passphrase_hex))) {
2192 		send_resp(dut, conn, SIGMA_ERROR,
2193 			  "ErrorCode,Too long SSID/passphrase");
2194 		return 0;
2195 	}
2196 
2197 	val = get_param(cmd, "WpsStaAction");
2198 	if (!val) {
2199 		send_resp(dut, conn, SIGMA_ERROR,
2200 			  "ErrorCode,Missing WpsStaAction argument");
2201 		return 0;
2202 	}
2203 
2204 	sta_action = atoi(val);
2205 	if (sta_action != 1 && sta_action != 2) {
2206 		send_resp(dut, conn, SIGMA_ERROR,
2207 			  "ErrorCode,Unsupported WpsStaAction value");
2208 		return 0;
2209 	}
2210 
2211 	if (!bssid) {
2212 		send_resp(dut, conn, SIGMA_ERROR,
2213 			  "ErrorCode,Missing Bssid argument");
2214 		return 0;
2215 	}
2216 
2217 	if (sta_action == 2) {
2218 		if (!ssid) {
2219 			send_resp(dut, conn, SIGMA_ERROR,
2220 				  "ErrorCode,Missing SSID argument");
2221 			return 0;
2222 		}
2223 
2224 		if (!security) {
2225 			send_resp(dut, conn, SIGMA_ERROR,
2226 				  "ErrorCode,Missing Security argument");
2227 			return 0;
2228 		}
2229 
2230 		if (!passphrase) {
2231 			send_resp(dut, conn, SIGMA_ERROR,
2232 				  "ErrorCode,Missing Passphrase argument");
2233 			return 0;
2234 		}
2235 	}
2236 
2237 	ctrl = open_wpa_mon(intf);
2238 	if (ctrl == NULL) {
2239 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
2240 				"wpa_supplicant monitor connection");
2241 		return -2;
2242 	}
2243 
2244 	if (sta_action == 1) {
2245 		const char *uuid = get_param(cmd, "UUID");
2246 		res = er_start(dut, conn, ctrl, intf, bssid, uuid, NULL, 0);
2247 		if (res != 1) {
2248 			wpa_ctrl_detach(ctrl);
2249 			wpa_ctrl_close(ctrl);
2250 			return res;
2251 		}
2252 	}
2253 
2254 	unlink("nfc-success");
2255 	snprintf(buf, sizeof(buf),
2256 		 "./wps-nfc.py -1 --no-wait %s%s --success nfc-success",
2257 		 dut->summary_log ? "--summary " : "",
2258 		 dut->summary_log ? dut->summary_log : "");
2259 	res = run_nfc_command(dut, buf, "Touch NFC Tag to read it");
2260 	if (res || !file_exists("nfc-success")) {
2261 		wpa_ctrl_detach(ctrl);
2262 		wpa_ctrl_close(ctrl);
2263 		send_resp(dut, conn, SIGMA_ERROR,
2264 			  "ErrorCode,Failed to read tag");
2265 		return 0;
2266 	}
2267 
2268 	if (sta_action == 1) {
2269 		sigma_dut_print(dut, DUT_MSG_INFO, "Prepared device password for ER to enroll a new station");
2270 		wpa_ctrl_detach(ctrl);
2271 		wpa_ctrl_close(ctrl);
2272 		send_resp(dut, conn, SIGMA_COMPLETE,
2273 			  "Result,,GroupID,,PeerRole,");
2274 		return 0;
2275 	}
2276 	if (strcasecmp(security, "wpa2-psk") == 0) {
2277 		keymgmt = "WPA2PSK";
2278 		cipher = "CCMP";
2279 	} else {
2280 		wpa_ctrl_detach(ctrl);
2281 		wpa_ctrl_close(ctrl);
2282 		send_resp(dut, conn, SIGMA_ERROR,
2283 			  "ErrorCode,Unsupported Security value");
2284 		return 0;
2285 	}
2286 
2287 	ascii2hexstr(ssid, ssid_hex);
2288 	ascii2hexstr(passphrase, passphrase_hex);
2289 	snprintf(buf, sizeof(buf), "WPS_REG %s nfc-pw %s %s %s %s",
2290 		 bssid, ssid_hex, keymgmt, cipher, passphrase_hex);
2291 
2292 	if (wpa_command(intf, buf) < 0) {
2293 		wpa_ctrl_detach(ctrl);
2294 		wpa_ctrl_close(ctrl);
2295 		send_resp(dut, conn, SIGMA_ERROR,
2296 			  "ErrorCode,Failed to start registrar");
2297 		return 0;
2298 	}
2299 
2300 	return wps_connection_event(dut, conn, ctrl, intf, 1);
2301 }
2302 
2303 
2304 static int nfc_wps_read_config(struct sigma_dut *dut,
2305 			       struct sigma_conn *conn,
2306 			       struct sigma_cmd *cmd)
2307 {
2308 	int res;
2309 	struct wpa_ctrl *ctrl;
2310 	const char *intf = get_param(cmd, "Interface");
2311 	char buf[300];
2312 
2313 	run_system(dut, "killall wps-nfc.py");
2314 	run_system(dut, "killall p2p-nfc.py");
2315 
2316 	ctrl = open_wpa_mon(intf);
2317 	if (ctrl == NULL) {
2318 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
2319 				"wpa_supplicant monitor connection");
2320 		return -2;
2321 	}
2322 
2323 	unlink("nfc-success");
2324 	snprintf(buf, sizeof(buf),
2325 		 "./wps-nfc.py -1 --no-wait %s%s --success nfc-success",
2326 		 dut->summary_log ? "--summary " : "",
2327 		 dut->summary_log ? dut->summary_log : "");
2328 	res = run_nfc_command(dut, buf, "Touch NFC Tag to read it");
2329 	if (res || !file_exists("nfc-success")) {
2330 		send_resp(dut, conn, SIGMA_ERROR,
2331 			  "ErrorCode,Failed to read tag");
2332 		wpa_ctrl_detach(ctrl);
2333 		wpa_ctrl_close(ctrl);
2334 		return 0;
2335 	}
2336 
2337 	return wps_connection_event(dut, conn, ctrl, intf, 1);
2338 }
2339 
2340 
2341 static int nfc_wps_connection_handover(struct sigma_dut *dut,
2342 				       struct sigma_conn *conn,
2343 				       struct sigma_cmd *cmd)
2344 {
2345 	const char *intf = get_param(cmd, "Interface");
2346 	int res;
2347 	const char *init = get_param(cmd, "Init");
2348 	struct wpa_ctrl *ctrl = NULL;
2349 	char buf[300];
2350 
2351 	run_system(dut, "killall wps-nfc.py");
2352 	run_system(dut, "killall p2p-nfc.py");
2353 
2354 	ctrl = open_wpa_mon(intf);
2355 	if (ctrl == NULL) {
2356 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
2357 				"wpa_supplicant monitor connection");
2358 		return -2;
2359 	}
2360 
2361 	unlink("nfc-success");
2362 	if ((!init || atoi(init) == 0) && dut->er_oper_performed) {
2363 		const char *bssid = get_param(cmd, "Bssid");
2364 		const char *req_uuid = get_param(cmd, "UUID");
2365 		char uuid[100];
2366 
2367 		if (bssid == NULL)
2368 			bssid = dut->er_oper_bssid;
2369 
2370 		res = er_start(dut, conn, ctrl, intf, bssid, req_uuid, uuid,
2371 			       sizeof(uuid));
2372 		if (res != 1) {
2373 			wpa_ctrl_detach(ctrl);
2374 			wpa_ctrl_close(ctrl);
2375 			return res;
2376 		}
2377 
2378 		snprintf(buf, sizeof(buf),
2379 			 "./wps-nfc.py -1 --uuid %s %s%s --success nfc-success",
2380 			 uuid,
2381 			 dut->summary_log ? "--summary " : "",
2382 			 dut->summary_log ? dut->summary_log : "");
2383 		res = run_nfc_command(dut, buf,
2384 				      "Touch NFC Device to respond to WPS connection handover");
2385 	} else if (!init || atoi(init)) {
2386 		snprintf(buf, sizeof(buf),
2387 			 "./wps-nfc.py -1 --no-wait %s%s --success nfc-success",
2388 			 dut->summary_log ? "--summary " : "",
2389 			 dut->summary_log ? dut->summary_log : "");
2390 		res = run_nfc_command(dut, buf,
2391 				      "Touch NFC Device to initiate WPS connection handover");
2392 	} else {
2393 		snprintf(buf, sizeof(buf),
2394 			 "./p2p-nfc.py -1 --no-wait --no-input %s%s --success nfc-success --handover-only",
2395 			 dut->summary_log ? "--summary " : "",
2396 			 dut->summary_log ? dut->summary_log : "");
2397 		res = run_nfc_command(dut, buf,
2398 				      "Touch NFC Device to respond to WPS connection handover");
2399 	}
2400 	if (res) {
2401 		wpa_ctrl_detach(ctrl);
2402 		wpa_ctrl_close(ctrl);
2403 		send_resp(dut, conn, SIGMA_ERROR,
2404 			  "ErrorCode,Failed to enable NFC for connection "
2405 			  "handover");
2406 		return 0;
2407 	}
2408 	if (!file_exists("nfc-success")) {
2409 		wpa_ctrl_detach(ctrl);
2410 		wpa_ctrl_close(ctrl);
2411 		send_resp(dut, conn, SIGMA_ERROR,
2412 			  "ErrorCode,Failed to complete NFC connection handover");
2413 		return 0;
2414 	}
2415 
2416 	if (init && atoi(init))
2417 		return wps_connection_event(dut, conn, ctrl, intf, 1);
2418 
2419 	wpa_ctrl_detach(ctrl);
2420 	wpa_ctrl_close(ctrl);
2421 
2422 	send_resp(dut, conn, SIGMA_COMPLETE,
2423 		  "Result,,GroupID,,PeerRole,,PauseFlag,0");
2424 	return 0;
2425 }
2426 
2427 
2428 static int nfc_p2p_connection_handover(struct sigma_dut *dut,
2429 				       struct sigma_conn *conn,
2430 				       struct sigma_cmd *cmd)
2431 {
2432 	const char *intf = get_param(cmd, "Interface");
2433 	int res;
2434 	const char *init = get_param(cmd, "Init");
2435 	const char *oper_chn = get_param(cmd, "OPER_CHN");
2436 	struct wpa_ctrl *ctrl;
2437 	char buf[1000], freq_str[20];
2438 
2439 	run_system(dut, "killall wps-nfc.py");
2440 	run_system(dut, "killall p2p-nfc.py");
2441 
2442 	ctrl = open_wpa_mon(intf);
2443 	if (ctrl == NULL) {
2444 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open "
2445 				"wpa_supplicant monitor connection");
2446 		return -2;
2447 	}
2448 
2449 	freq_str[0] = '\0';
2450 	if (oper_chn) {
2451 		int chan = atoi(oper_chn);
2452 		if (chan >= 1 && chan <= 11)
2453 			snprintf(freq_str, sizeof(freq_str), " --freq %d",
2454 				 2407 + chan * 5);
2455 	}
2456 
2457 	unlink("nfc-success");
2458 	if (init && atoi(init)) {
2459 		snprintf(buf, sizeof(buf),
2460 			 "./p2p-nfc.py -1 -I -N --no-wait %s%s --success nfc-success --no-input%s --handover-only",
2461 			 dut->summary_log ? "--summary " : "",
2462 			 dut->summary_log ? dut->summary_log : "",
2463 			 freq_str);
2464 		res = run_nfc_command(dut, buf,
2465 				      "Touch NFC Device to initiate P2P connection handover");
2466 	} else {
2467 		snprintf(buf, sizeof(buf),
2468 			 "./p2p-nfc.py -1 --no-wait %s%s --success nfc-success --no-input%s --handover-only",
2469 			 dut->summary_log ? "--summary " : "",
2470 			 dut->summary_log ? dut->summary_log : "",
2471 			 freq_str);
2472 		res = run_nfc_command(dut, buf,
2473 				      "Touch NFC Device to respond to P2P connection handover");
2474 	}
2475 	if (res) {
2476 		wpa_ctrl_detach(ctrl);
2477 		wpa_ctrl_close(ctrl);
2478 		send_resp(dut, conn, SIGMA_ERROR,
2479 			  "ErrorCode,Failed to enable NFC for connection "
2480 			  "handover");
2481 		return 0;
2482 	}
2483 	if (!file_exists("nfc-success")) {
2484 		wpa_ctrl_detach(ctrl);
2485 		wpa_ctrl_close(ctrl);
2486 		send_resp(dut, conn, SIGMA_ERROR,
2487 			  "ErrorCode,Failed to complete NFC connection handover");
2488 		return 0;
2489 	}
2490 
2491 	if (dut->go || dut->p2p_client) {
2492 		wpa_ctrl_detach(ctrl);
2493 		wpa_ctrl_close(ctrl);
2494 		send_resp(dut, conn, SIGMA_COMPLETE,
2495 			  "Result,,GroupID,,PeerRole,,PauseFlag,0");
2496 		return 0;
2497 	}
2498 
2499 	/* FIX: peer role from handover message */
2500 	return p2p_group_formation_event(dut, conn, ctrl, intf, "0", 1);
2501 }
2502 
2503 
2504 static int cmd_sta_nfc_action(struct sigma_dut *dut, struct sigma_conn *conn,
2505 			      struct sigma_cmd *cmd)
2506 {
2507 	const char *intf = get_param(cmd, "Interface");
2508 	const char *oper = get_param(cmd, "Operation");
2509 	const char *ssid_param = get_param(cmd, "SSID");
2510 	const char *intent_val = get_param(cmd, "INTENT_VAL");
2511 	const char *oper_chn = get_param(cmd, "OPER_CHN");
2512 	char buf[256];
2513 
2514 	if (oper == NULL)
2515 		return -1;
2516 
2517 	if (ssid_param)
2518 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix %s",
2519 			 ssid_param);
2520 	else
2521 		snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix ");
2522 	if (wpa_command(intf, buf) < 0)
2523 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed P2P ssid_postfix - ignore and assume this is for non-P2P case");
2524 
2525 	if (intent_val) {
2526 		snprintf(buf, sizeof(buf), "SET p2p_go_intent %s", intent_val);
2527 		if (wpa_command(intf, buf) < 0)
2528 			return -2;
2529 	}
2530 
2531 	if (oper_chn) {
2532 		int chan = atoi(oper_chn);
2533 		if (chan < 1 || chan > 11) {
2534 			send_resp(dut, conn, SIGMA_ERROR,
2535 				  "ErrorCode,Unsupported operating channel");
2536 			return 0;
2537 		}
2538 		snprintf(buf, sizeof(buf), "SET p2p_oper_channel %d", chan);
2539 		if (wpa_command(intf, "SET p2p_oper_reg_class 81") < 0 ||
2540 		    wpa_command(intf, buf) < 0) {
2541 			send_resp(dut, conn, SIGMA_ERROR,
2542 				  "ErrorCode,Failed to set operating channel");
2543 			return 0;
2544 		}
2545 	}
2546 
2547 	if (strcasecmp(oper, "WRITE_SELECT") == 0)
2548 		return nfc_write_p2p_select(dut, conn, cmd);
2549 	if (strcasecmp(oper, "WRITE_CONFIG") == 0)
2550 		return nfc_write_config_token(dut, conn, cmd);
2551 	if (strcasecmp(oper, "WRITE_PASSWD") == 0)
2552 		return nfc_write_password_token(dut, conn, cmd);
2553 	if (strcasecmp(oper, "READ_TAG") == 0)
2554 		return nfc_read_tag(dut, conn, cmd);
2555 	if (strcasecmp(oper, "WPS_READ_TAG") == 0)
2556 		return nfc_wps_read_tag(dut, conn, cmd);
2557 	if (strcasecmp(oper, "WPS_READ_PASSWD") == 0)
2558 		return nfc_wps_read_passwd(dut, conn, cmd);
2559 	if (strcasecmp(oper, "WPS_READ_CONFIG") == 0)
2560 		return nfc_wps_read_config(dut, conn, cmd);
2561 	if (strcasecmp(oper, "CONN_HNDOVR") == 0)
2562 		return nfc_p2p_connection_handover(dut, conn, cmd);
2563 	if (strcasecmp(oper, "WPS_CONN_HNDOVR") == 0)
2564 		return nfc_wps_connection_handover(dut, conn, cmd);
2565 
2566 	send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported operation");
2567 	return 0;
2568 }
2569 
2570 
2571 int p2p_cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn,
2572 			      struct sigma_cmd *cmd)
2573 {
2574 	const char *parameter = get_param(cmd, "Parameter");
2575 	char buf[100];
2576 
2577 	if (parameter == NULL)
2578 		return -1;
2579 	if (strcasecmp(parameter, "ListenChannel") == 0) {
2580 		snprintf(buf, sizeof(buf), "ListenChnl,%u", dut->listen_chn);
2581 		send_resp(dut, conn, SIGMA_COMPLETE, buf);
2582 		return 0;
2583 	}
2584 
2585 	send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter");
2586 	return 0;
2587 }
2588 
2589 
2590 static int req_intf(struct sigma_cmd *cmd)
2591 {
2592 	return get_param(cmd, "interface") == NULL ? -1 : 0;
2593 }
2594 
2595 
2596 void p2p_register_cmds(void)
2597 {
2598 	sigma_dut_reg_cmd("sta_get_p2p_dev_address", req_intf,
2599 			  cmd_sta_get_p2p_dev_address);
2600 	sigma_dut_reg_cmd("sta_set_p2p", req_intf, cmd_sta_set_p2p);
2601 	sigma_dut_reg_cmd("sta_start_autonomous_go", req_intf,
2602 			  cmd_sta_start_autonomous_go);
2603 	sigma_dut_reg_cmd("sta_p2p_connect", req_intf, cmd_sta_p2p_connect);
2604 	sigma_dut_reg_cmd("sta_p2p_start_group_formation", req_intf,
2605 			  cmd_sta_p2p_start_group_formation);
2606 	sigma_dut_reg_cmd("sta_p2p_dissolve", req_intf, cmd_sta_p2p_dissolve);
2607 	sigma_dut_reg_cmd("sta_send_p2p_invitation_req", req_intf,
2608 			  cmd_sta_send_p2p_invitation_req);
2609 	sigma_dut_reg_cmd("sta_accept_p2p_invitation_req", req_intf,
2610 			  cmd_sta_accept_p2p_invitation_req);
2611 	sigma_dut_reg_cmd("sta_send_p2p_provision_dis_req", req_intf,
2612 			  cmd_sta_send_p2p_provision_dis_req);
2613 	sigma_dut_reg_cmd("sta_set_wps_pbc", req_intf, cmd_sta_set_wps_pbc);
2614 	sigma_dut_reg_cmd("sta_wps_read_pin", req_intf, cmd_sta_wps_read_pin);
2615 	sigma_dut_reg_cmd("sta_wps_read_label", req_intf,
2616 			  cmd_sta_wps_read_label);
2617 	sigma_dut_reg_cmd("sta_wps_enter_pin", req_intf,
2618 			  cmd_sta_wps_enter_pin);
2619 	sigma_dut_reg_cmd("sta_get_psk", req_intf, cmd_sta_get_psk);
2620 	sigma_dut_reg_cmd("sta_p2p_reset", req_intf, cmd_sta_p2p_reset);
2621 	sigma_dut_reg_cmd("sta_get_p2p_ip_config", req_intf,
2622 			  cmd_sta_get_p2p_ip_config);
2623 	sigma_dut_reg_cmd("sta_send_p2p_presence_req", req_intf,
2624 			  cmd_sta_send_p2p_presence_req);
2625 	sigma_dut_reg_cmd("sta_set_sleep", req_intf, cmd_sta_set_sleep);
2626 	sigma_dut_reg_cmd("sta_set_opportunistic_ps", req_intf,
2627 			  cmd_sta_set_opportunistic_ps);
2628 	sigma_dut_reg_cmd("sta_send_service_discovery_req", req_intf,
2629 			  cmd_sta_send_service_discovery_req);
2630 	sigma_dut_reg_cmd("sta_add_arp_table_entry", req_intf,
2631 			  cmd_sta_add_arp_table_entry);
2632 	sigma_dut_reg_cmd("sta_block_icmp_response", req_intf,
2633 			  cmd_sta_block_icmp_response);
2634 	sigma_dut_reg_cmd("sta_nfc_action", req_intf, cmd_sta_nfc_action);
2635 }
2636