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