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