/* * Sigma Control API DUT (station/AP) * Copyright (c) 2010-2011, Atheros Communications, Inc. * Copyright (c) 2011-2014, Qualcomm Atheros, Inc. * All Rights Reserved. * Licensed under the Clear BSD license. See README for more details. */ #include "sigma_dut.h" #include #include "wpa_ctrl.h" #include "wpa_helpers.h" int run_system(struct sigma_dut *dut, const char *cmd) { int res; sigma_dut_print(dut, DUT_MSG_DEBUG, "Running '%s'", cmd); res = system(cmd); if (res < 0) { sigma_dut_print(dut, DUT_MSG_DEBUG, "Failed to execute " "command '%s'", cmd); } return res; } static int get_60g_freq(int chan) { int freq = 0; switch(chan) { case 1: freq = 58320; break; case 2: freq = 60480; break; case 3: freq = 62640; break; case 4: /* freq = 64800; Not supported in Sparrow 2.0 */ break; default: break; } return freq; } static int p2p_group_add(struct sigma_dut *dut, const char *ifname, int go, const char *grpid, const char *ssid) { struct wfa_cs_p2p_group *grp; if (go) dut->go = 1; else dut->p2p_client = 1; grp = malloc(sizeof(*grp)); if (grp == NULL) return -1; memset(grp, 0, sizeof(*grp)); strncpy(grp->ifname, ifname, IFNAMSIZ); grp->go = go; strncpy(grp->grpid, grpid, P2P_GRP_ID_LEN); strncpy(grp->ssid, ssid, sizeof(grp->ssid)); grp->next = dut->groups; dut->groups = grp; return 0; } static int p2p_group_remove(struct sigma_dut *dut, const char *grpid) { struct wfa_cs_p2p_group *grp, *prev; prev = NULL; grp = dut->groups; while (grp) { if (strcmp(grpid, grp->grpid) == 0) { if (prev) prev->next = grp->next; else dut->groups = grp->next; free(grp); return 0; } prev = grp; grp = grp->next; } return -1; } static struct wfa_cs_p2p_group * p2p_group_get(struct sigma_dut *dut, const char *grpid) { struct wfa_cs_p2p_group *grp; char buf[1000], buf2[4096], *ifname, *pos; char go_dev_addr[50]; char ssid[33]; for (grp = dut->groups; grp; grp = grp->next) { if (strcmp(grpid, grp->grpid) == 0) return grp; } /* * No group found based on group id. As a workaround for GO Negotiation * responder case where we do not store group id, try to find an active * group that matches with the requested group id. */ pos = strchr(grpid, ' '); if (pos == NULL) return NULL; if (pos - grpid > (int) sizeof(go_dev_addr)) return NULL; memcpy(go_dev_addr, grpid, pos - grpid); go_dev_addr[pos - grpid] = '\0'; strncpy(ssid, pos + 1, sizeof(ssid)); ssid[sizeof(ssid) - 1] = '\0'; printf("Trying to find suitable interface for group: go_dev_addr='%s' " "grpid='%s'\n", go_dev_addr, grpid); if (wpa_command_resp(get_main_ifname(), "INTERFACES", buf, sizeof(buf)) < 0) return NULL; ifname = buf; while (ifname && *ifname) { int add = 0; int go = 0; pos = strchr(ifname, '\n'); if (pos) *pos++ = '\0'; printf("Considering interface '%s' for group\n", ifname); if (wpa_command_resp(ifname, "STATUS", buf2, sizeof(buf2)) == 0) { if (strstr(buf2, ssid)) { printf("Selected interface '%s' based on " "STATUS\n", ifname); add = 1; } if (strstr(buf2, "P2P GO")) go = 1; } if (wpa_command_resp(ifname, "LIST_NETWORKS", buf2, sizeof(buf2)) == 0) { char *line, *end; line = buf2; while (line && *line) { end = strchr(line, ' '); if (end) *end++ = '\0'; if (strstr(line, ssid) && strstr(line, "[CURRENT]")) { printf("Selected interface '%s' " "based on LIST_NETWORKS\n", ifname); add = 1; break; } line = end; } } if (add) { p2p_group_add(dut, ifname, go, grpid, ssid); return dut->groups; } ifname = pos; } return NULL; } static const char * get_group_ifname(struct sigma_dut *dut, const char *ifname) { char buf[1000], *iface, *pos; char state[100]; if (dut->groups) { sigma_dut_print(dut, DUT_MSG_DEBUG, "%s: Use group interface " "%s instead of main interface %s", __func__, dut->groups->ifname, ifname); return dut->groups->ifname; } /* Try to find a suitable group interface */ if (wpa_command_resp(get_main_ifname(), "INTERFACES", buf, sizeof(buf)) < 0) return ifname; iface = buf; while (iface && *iface) { pos = strchr(iface, '\n'); if (pos) *pos++ = '\0'; sigma_dut_print(dut, DUT_MSG_DEBUG, "Considering interface " "'%s' for IP address", iface); if (get_wpa_status(iface, "wpa_state", state, sizeof(state)) == 0 && strcmp(state, "COMPLETED") == 0) return iface; iface = pos; } return ifname; } static int p2p_peer_known(const char *ifname, const char *peer, int full) { char buf[4096]; snprintf(buf, sizeof(buf), "P2P_PEER %s", peer); if (wpa_command_resp(ifname, buf, buf, sizeof(buf)) < 0) return 0; if (strncasecmp(buf, peer, strlen(peer)) != 0) return 0; if (!full) return 1; return strstr(buf, "[PROBE_REQ_ONLY]") == NULL ? 1 : 0; } static int p2p_discover_peer(struct sigma_dut *dut, const char *ifname, const char *peer, int full) { unsigned int count; if (p2p_peer_known(ifname, peer, full)) return 0; printf("Peer not yet discovered - start discovery\n"); if (wpa_command(ifname, "P2P_FIND") < 0) { printf("Failed to start discovery\n"); return -1; } count = 0; while (count < dut->default_timeout) { count++; sleep(1); if (p2p_peer_known(ifname, peer, full)) { printf("Peer discovered - return to previous state\n"); switch (dut->p2p_mode) { case P2P_IDLE: wpa_command(ifname, "P2P_STOP_FIND"); break; case P2P_DISCOVER: /* Already running discovery */ break; case P2P_LISTEN: wpa_command(ifname, "P2P_LISTEN"); break; case P2P_DISABLE: printf("Invalid state - P2P was disabled?!\n"); break; } return 0; } } printf("Peer discovery timed out - peer not discovered\n"); wpa_command(ifname, "P2P_STOP_FIND"); return -1; } static void add_dummy_services(const char *intf) { wpa_command(intf, "P2P_SERVICE_ADD bonjour 0b5f6166706f766572746370c00c000c01 074578616d706c65c027"); wpa_command(intf, "P2P_SERVICE_ADD bonjour 076578616d706c650b5f6166706f766572746370c00c001001 00"); wpa_command(intf, "P2P_SERVICE_ADD bonjour 045f697070c00c000c01 094d795072696e746572c027"); wpa_command(intf, "P2P_SERVICE_ADD bonjour 096d797072696e746572045f697070c00c001001 09747874766572733d311a70646c3d6170706c69636174696f6e2f706f7374736372797074"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::upnp:rootdevice"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:5566d33e-9774-09ab-4822-333456785632::upnp:rootdevice"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:5566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1859dede-8574-59ab-9332-123456789012::upnp:rootdevice"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1566d33e-9774-09ab-4822-333456785632::upnp:rootdevice"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:1859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2859dede-8574-59ab-9332-123456789012::upnp:rootdevice"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2566d33e-9774-09ab-4822-333456785632::upnp:rootdevice"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:2859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3859dede-8574-59ab-9332-123456789012::upnp:rootdevice"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3566d33e-9774-09ab-4822-333456785632::upnp:rootdevice"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:4122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2"); wpa_command(intf, "P2P_SERVICE_ADD upnp 10 uuid:3859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1"); } void disconnect_station(struct sigma_dut *dut) { wpa_command(get_station_ifname(), "DISCONNECT"); remove_wpa_networks(get_station_ifname()); dut->infra_ssid[0] = '\0'; #ifdef __linux__ { char path[128]; char buf[200]; struct stat s; snprintf(path, sizeof(path), "/var/run/dhclient-%s.pid", get_station_ifname()); if (stat(path, &s) == 0) { snprintf(buf, sizeof(buf), "kill `cat %s`", path); sigma_dut_print(dut, DUT_MSG_DEBUG, "Kill previous DHCP client: %s", buf); run_system(dut, buf); unlink(path); } snprintf(buf, sizeof(buf), "ifconfig %s 0.0.0.0", get_station_ifname()); sigma_dut_print(dut, DUT_MSG_DEBUG, "Clear infrastructure station IP address: %s", buf); run_system(dut, buf); } #endif /* __linux__ */ } static int cmd_sta_get_p2p_dev_address(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "interface"); char buf[100], resp[200]; start_sta_mode(dut); if (get_wpa_status(intf, "p2p_device_address", buf, sizeof(buf)) < 0) { send_resp(dut, conn, SIGMA_ERROR, NULL); return 0; } snprintf(resp, sizeof(resp), "DevID,%s", buf); send_resp(dut, conn, SIGMA_COMPLETE, resp); return 0; } static int cmd_sta_set_p2p(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_p2p_ifname(get_param(cmd, "Interface")); char buf[256]; const char *val; const char *noa_dur, *noa_int, *noa_count; const char *ext_listen_int, *ext_listen_period; val = get_param(cmd, "LISTEN_CHN"); if (val) { dut->listen_chn = atoi(val); if (dut->listen_chn == 2) { /* social channel 2 on 60 GHz band */ snprintf(buf, sizeof(buf), "P2P_SET listen_channel 2 180"); } else { /* social channels 1/6/11 on 2.4 GHz band */ snprintf(buf, sizeof(buf), "P2P_SET listen_channel %d", dut->listen_chn); } if (wpa_command(intf, buf) < 0) return -2; } ext_listen_int = get_param(cmd, "Ext_Listen_Time_Interval"); ext_listen_period = get_param(cmd, "Ext_Listen_Time_Period"); if (ext_listen_int || ext_listen_period) { if (!ext_listen_int || !ext_listen_period) { sigma_dut_print(dut, DUT_MSG_INFO, "Only one " "ext_listen_time parameter included; " "both are needed"); return -1; } snprintf(buf, sizeof(buf), "P2P_EXT_LISTEN %d %d", atoi(ext_listen_period), atoi(ext_listen_int)); if (wpa_command(intf, buf) < 0) return -2; } val = get_param(cmd, "P2P_MODE"); if (val) { if (strcasecmp(val, "Listen") == 0) { wpa_command(intf, "P2P_SET disabled 0"); if (wpa_command(intf, "P2P_LISTEN") < 0) return -2; dut->p2p_mode = P2P_LISTEN; } else if (strcasecmp(val, "Discover") == 0) { wpa_command(intf, "P2P_SET disabled 0"); if (wpa_command(intf, "P2P_FIND") < 0) return -2; dut->p2p_mode = P2P_DISCOVER; } else if (strcasecmp(val, "Idle") == 0) { wpa_command(intf, "P2P_SET disabled 0"); if (wpa_command(intf, "P2P_STOP_FIND") < 0) return -2; dut->p2p_mode = P2P_IDLE; } else if (strcasecmp(val, "Disable") == 0) { if (wpa_command(intf, "P2P_SET disabled 1") < 0) return -2; dut->p2p_mode = P2P_DISABLE; } else return -1; } val = get_param(cmd, "PERSISTENT"); if (val) { dut->persistent = atoi(val); } val = get_param(cmd, "INTRA_BSS"); if (val) { int intra_bss = atoi(val); /* TODO: add support for this */ if (!intra_bss) { sigma_dut_print(dut, DUT_MSG_INFO, "Disabling of " "intra-BSS bridging not supported"); return -1; } dut->intra_bss = intra_bss; } /* NoA is not applicable for 60 GHz */ if (dut->program != PROGRAM_60GHZ) { noa_dur = get_param(cmd, "NoA_duration"); noa_int = get_param(cmd, "NoA_Interval"); noa_count = get_param(cmd, "NoA_Count"); if (noa_dur) dut->noa_duration = atoi(noa_dur); if (noa_int) dut->noa_interval = atoi(noa_int); if (noa_count) dut->noa_count = atoi(noa_count); if (noa_dur || noa_int || noa_count) { int start; const char *ifname; if (dut->noa_count == 0 && dut->noa_duration == 0) start = 0; else if (dut->noa_duration > 102) /* likely non-periodic * NoA */ start = 50; else start = 102 - dut->noa_duration; snprintf(buf, sizeof(buf), "P2P_SET noa %d,%d,%d", dut->noa_count, start, dut->noa_duration); ifname = get_group_ifname(dut, intf); sigma_dut_print(dut, DUT_MSG_INFO, "Set GO NoA for interface %s", ifname); if (wpa_command(ifname, buf) < 0) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Use of NoA as GO not supported"); return 0; } } } val = get_param(cmd, "Concurrency"); if (val) { /* TODO */ } val = get_param(cmd, "P2PInvitation"); if (val) { /* TODO */ } val = get_param(cmd, "BCN_INT"); if (val) { /* TODO */ } val = get_param(cmd, "Discoverability"); if (val) { snprintf(buf, sizeof(buf), "P2P_SET discoverability %d", atoi(val)); if (wpa_command(intf, buf) < 0) return -2; } val = get_param(cmd, "Service_Discovery"); if (val) { int sd = atoi(val); if (sd) { wpa_command(intf, "P2P_SERVICE_FLUSH"); if (sd == 2) wpa_command(intf, "P2P_SET force_long_sd 1"); /* * Set up some dummy service to create a large SD * response that requires fragmentation. */ add_dummy_services(intf); } else { wpa_command(intf, "P2P_SERVICE_FLUSH"); } } val = get_param(cmd, "CrossConnection"); if (val) { if (atoi(val)) { if (wpa_command(intf, "P2P_SET cross_connect 1") < 0) return -2; } else { if (wpa_command(intf, "P2P_SET cross_connect 0") < 0) return -2; } } val = get_param(cmd, "P2PManaged"); if (val) { if (atoi(val)) { send_resp(dut, conn, SIGMA_INVALID, "ErrorCode," "P2P Managed functionality not supported"); return 0; } } val = get_param(cmd, "GO_APSD"); if (val) { if (atoi(val)) { if (wpa_command(intf, "P2P_SET go_apsd 1") < 0) return -2; } else { if (wpa_command(intf, "P2P_SET go_apsd 0") < 0) return -2; } } return 1; } static int cmd_sta_start_autonomous_go(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "Interface"); const char *oper_chn = get_param(cmd, "OPER_CHN"); const char *ssid_param = get_param(cmd, "SSID"); int freq, chan, res; char buf[256], grpid[100], resp[200]; struct wpa_ctrl *ctrl; char *ifname, *gtype, *pos, *ssid, bssid[20]; char *go_dev_addr; if (oper_chn == NULL) return -1; chan = atoi(oper_chn); if (dut->program == PROGRAM_60GHZ) { freq = get_60g_freq(chan); if (freq == 0) { sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid channel: %d", chan); return -1; } } else if (chan >= 1 && chan <= 13) freq = 2407 + chan * 5; else if (chan == 14) freq = 2484; else freq = 5000 + chan * 5; if (ssid_param) snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix %s", ssid_param); else snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix "); if (wpa_command(intf, buf) < 0) return -2; /* Stop Listen/Discovery state to avoid issues with GO operations */ if (wpa_command(intf, "P2P_STOP_FIND") < 0) return -2; ctrl = open_wpa_mon(intf); if (ctrl == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open " "wpa_supplicant monitor connection"); return -2; } snprintf(buf, sizeof(buf), "P2P_GROUP_ADD %sfreq=%d", dut->persistent ? "persistent " : "", freq); if (wpa_command(intf, buf) < 0) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); return -2; } res = get_wpa_cli_event(dut, ctrl, "P2P-GROUP-STARTED", buf, sizeof(buf)); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); if (res < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,GO starting " "did not complete"); return 0; } sigma_dut_print(dut, DUT_MSG_DEBUG, "Group started event '%s'", buf); ifname = strchr(buf, ' '); if (ifname == NULL) return -2; ifname++; pos = strchr(ifname, ' '); if (pos == NULL) return -2; *pos++ = '\0'; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group interface %s", ifname); gtype = pos; pos = strchr(gtype, ' '); if (pos == NULL) return -2; *pos++ = '\0'; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group type %s", gtype); ssid = strstr(pos, "ssid=\""); if (ssid == NULL) return -2; ssid += 6; pos = strchr(ssid, '"'); if (pos == NULL) return -2; *pos++ = '\0'; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group SSID %s", ssid); go_dev_addr = strstr(pos, "go_dev_addr="); if (go_dev_addr == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "No GO P2P Device Address " "found"); return -2; } go_dev_addr += 12; if (strlen(go_dev_addr) < 17) { sigma_dut_print(dut, DUT_MSG_ERROR, "Too short GO P2P Device " "Address '%s'", go_dev_addr); return -2; } go_dev_addr[17] = '\0'; *pos = '\0'; sigma_dut_print(dut, DUT_MSG_DEBUG, "GO P2P Device Address %s", go_dev_addr); if (get_wpa_status(ifname, "bssid", bssid, sizeof(bssid)) < 0) return -2; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group BSSID %s", bssid); snprintf(grpid, sizeof(grpid), "%s %s", go_dev_addr, ssid); p2p_group_add(dut, ifname, strcmp(gtype, "GO") == 0, grpid, ssid); snprintf(resp, sizeof(resp), "GroupID,%s", grpid); send_resp(dut, conn, SIGMA_COMPLETE, resp); return 0; } static int cmd_sta_p2p_connect(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_p2p_ifname(get_param(cmd, "Interface")); const char *devid = get_param(cmd, "P2PDevID"); /* const char *grpid_param = get_param(cmd, "GroupID"); */ int res; char buf[256]; struct wpa_ctrl *ctrl; char *ifname, *gtype, *pos, *ssid, bssid[20]; char grpid[100]; /* TODO: handle the new grpid argument */ if (devid == NULL) return -1; if (dut->wps_method == WFA_CS_WPS_NOT_READY) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS parameters " "not yet set"); return 0; } sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover GO %s", devid); if (p2p_discover_peer(dut, intf, devid, 1) < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not " "discover the requested peer"); return 0; } ctrl = open_wpa_mon(intf); if (ctrl == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open " "wpa_supplicant monitor connection"); return -2; } switch (dut->wps_method) { case WFA_CS_WPS_PBC: snprintf(buf, sizeof(buf), "P2P_CONNECT %s pbc join", devid); break; case WFA_CS_WPS_PIN_DISPLAY: snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s display join", devid, dut->wps_pin); break; case WFA_CS_WPS_PIN_KEYPAD: snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s keypad join", devid, dut->wps_pin); break; default: send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unknown WPS " "method for sta_p2p_connect"); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); return 0; } if (wpa_command(intf, buf) < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to join " "the group"); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); return 0; } res = get_wpa_cli_event(dut, ctrl, "P2P-GROUP-STARTED", buf, sizeof(buf)); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); if (res < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Group joining " "did not complete"); return 0; } sigma_dut_print(dut, DUT_MSG_DEBUG, "Group started event '%s'", buf); ifname = strchr(buf, ' '); if (ifname == NULL) return -2; ifname++; pos = strchr(ifname, ' '); if (pos == NULL) return -2; *pos++ = '\0'; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group interface %s", ifname); gtype = pos; pos = strchr(gtype, ' '); if (pos == NULL) return -2; *pos++ = '\0'; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group type %s", gtype); ssid = strstr(pos, "ssid=\""); if (ssid == NULL) return -2; ssid += 6; pos = strchr(ssid, '"'); if (pos == NULL) return -2; *pos = '\0'; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group SSID %s", ssid); if (get_wpa_status(ifname, "bssid", bssid, sizeof(bssid)) < 0) return -2; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group BSSID %s", bssid); snprintf(grpid, sizeof(grpid), "%s %s", bssid, ssid); p2p_group_add(dut, ifname, strcmp(gtype, "GO") == 0, grpid, ssid); return 1; } static int p2p_group_formation_event(struct sigma_dut *dut, struct sigma_conn *conn, struct wpa_ctrl *ctrl, const char *intf, const char *peer_role, int nfc); static int cmd_sta_p2p_start_group_formation(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_p2p_ifname(get_param(cmd, "Interface")); const char *devid = get_param(cmd, "P2PDevID"); const char *intent_val = get_param(cmd, "INTENT_VAL"); const char *init_go_neg = get_param(cmd, "INIT_GO_NEG"); const char *oper_chn = get_param(cmd, "OPER_CHN"); const char *ssid_param = get_param(cmd, "SSID"); int freq = 0, chan = 0, init; char buf[256]; struct wpa_ctrl *ctrl; if (devid == NULL || intent_val == NULL) return -1; if (init_go_neg) init = atoi(init_go_neg); else init = 0; if (dut->program == PROGRAM_60GHZ) { if (!oper_chn) return -1; chan = atoi(oper_chn); freq = get_60g_freq(chan); if (freq == 0) { sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid channel: %d", chan); return -1; } } else if (oper_chn) { chan = atoi(oper_chn); if (chan >= 1 && chan <= 13) freq = 2407 + chan * 5; else if (chan == 14) freq = 2484; else freq = 5000 + chan * 5; } if (dut->wps_method == WFA_CS_WPS_NOT_READY) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS parameters " "not yet set"); return 0; } sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover peer %s for group formation chan %d (freq %d)", devid, chan, freq); if (p2p_discover_peer(dut, intf, devid, init) < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not " "discover the requested peer"); return 0; } if (ssid_param) snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix %s", ssid_param); else snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix "); if (wpa_command(intf, buf) < 0) return -2; if (init) { ctrl = open_wpa_mon(intf); if (ctrl == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open " "wpa_supplicant monitor connection"); return -2; } } else ctrl = NULL; snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s%s%s%s go_intent=%d", devid, dut->wps_method == WFA_CS_WPS_PBC ? "pbc" : dut->wps_pin, dut->wps_method == WFA_CS_WPS_PBC ? "" : (dut->wps_method == WFA_CS_WPS_PIN_DISPLAY ? " display" : (dut->wps_method == WFA_CS_WPS_PIN_LABEL ? " label" : " keypad" )), dut->persistent ? " persistent" : "", init ? "" : " auth", atoi(intent_val)); if (freq > 0) { snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " freq=%d", freq); } if (wpa_command(intf, buf) < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to start " "group formation"); if (ctrl) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); } return 0; } if (!init) return 1; return p2p_group_formation_event(dut, conn, ctrl, intf, NULL, 0); } static int p2p_group_formation_event(struct sigma_dut *dut, struct sigma_conn *conn, struct wpa_ctrl *ctrl, const char *intf, const char *peer_role, int nfc) { int res; char buf[256], grpid[50], resp[256]; char *ifname, *gtype, *pos, *ssid, bssid[20]; char *go_dev_addr; char role[30]; const char *events[] = { "P2P-GROUP-STARTED", "P2P-GO-NEG-FAILURE", "P2P-NFC-PEER-CLIENT", "P2P-GROUP-FORMATION-FAILURE", NULL }; role[0] = '\0'; if (peer_role) snprintf(role, sizeof(role), ",PeerRole,%s", peer_role); res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf)); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); if (res < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Group formation " "did not complete"); return 0; } sigma_dut_print(dut, DUT_MSG_DEBUG, "Group started event '%s'", buf); if (strstr(buf, "P2P-NFC-PEER-CLIENT")) { snprintf(resp, sizeof(resp), "Result,,GroupID,,PeerRole,1,PauseFlag,0"); send_resp(dut, conn, SIGMA_COMPLETE, resp); return 0; } if (strstr(buf, "P2P-GROUP-FORMATION-FAILURE")) { snprintf(buf, sizeof(buf), "ErrorCode,Group formation failed"); send_resp(dut, conn, SIGMA_ERROR, buf); return 0; } if (strstr(buf, "P2P-GO-NEG-FAILURE")) { int status = -1; pos = strstr(buf, " status="); if (pos) status = atoi(pos + 8); sigma_dut_print(dut, DUT_MSG_INFO, "GO Negotiation failed " "(status=%d)", status); if (status == 9) { sigma_dut_print(dut, DUT_MSG_INFO, "Both devices " "tried to use GO Intent 15"); send_resp(dut, conn, SIGMA_COMPLETE, "result,FAIL"); return 0; } snprintf(buf, sizeof(buf), "ErrorCode,GO Negotiation failed " "(status=%d)", status); send_resp(dut, conn, SIGMA_ERROR, buf); return 0; } ifname = strchr(buf, ' '); if (ifname == NULL) return -2; ifname++; pos = strchr(ifname, ' '); if (pos == NULL) return -2; *pos++ = '\0'; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group interface %s", ifname); gtype = pos; pos = strchr(gtype, ' '); if (pos == NULL) return -2; *pos++ = '\0'; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group type %s", gtype); ssid = strstr(pos, "ssid=\""); if (ssid == NULL) return -2; ssid += 6; pos = strchr(ssid, '"'); if (pos == NULL) return -2; *pos++ = '\0'; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group SSID %s", ssid); go_dev_addr = strstr(pos, "go_dev_addr="); if (go_dev_addr == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "No GO P2P Device Address " "found\n"); return -2; } go_dev_addr += 12; if (strlen(go_dev_addr) < 17) { sigma_dut_print(dut, DUT_MSG_ERROR, "Too short GO P2P Device " "Address '%s'", go_dev_addr); return -2; } go_dev_addr[17] = '\0'; *pos = '\0'; sigma_dut_print(dut, DUT_MSG_ERROR, "GO P2P Device Address %s", go_dev_addr); if (get_wpa_status(ifname, "bssid", bssid, sizeof(bssid)) < 0) return -2; sigma_dut_print(dut, DUT_MSG_DEBUG, "Group BSSID %s", bssid); snprintf(grpid, sizeof(grpid), "%s %s", go_dev_addr, ssid); p2p_group_add(dut, ifname, strcmp(gtype, "GO") == 0, grpid, ssid); snprintf(resp, sizeof(resp), "Result,%s,GroupID,%s%s%s", strcmp(gtype, "GO") == 0 ? "GO" : "CLIENT", grpid, role, nfc ? ",PauseFlag,0" : ""); send_resp(dut, conn, SIGMA_COMPLETE, resp); #ifdef __QNXNTO__ /* Start DHCP server if we became the GO */ if (strcmp(gtype, "GO") == 0 && system("dhcpd -cf /etc/dhcpd.conf -pf /var/run/dhcpd qca1 &") == 0) sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to start DHCPD server"); #endif /* __QNXNTO__ */ return 0; } int wps_connection_event(struct sigma_dut *dut, struct sigma_conn *conn, struct wpa_ctrl *ctrl, const char *intf, int p2p_resp) { int res; char buf[256]; const char *events[] = { "CTRL-EVENT-CONNECTED", "WPS-FAIL", "WPS-TIMEOUT", NULL }; res = get_wpa_cli_events(dut, ctrl, events, buf, sizeof(buf)); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); if (res < 0) { #ifdef USE_ERROR_RETURNS send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS connection " "did not complete"); #else send_resp(dut, conn, SIGMA_COMPLETE, "ErrorCode,WPS connection " "did not complete"); #endif return 0; } if (strstr(buf, "WPS-FAIL") || strstr(buf, "WPS-TIMEOUT")) { #ifdef USE_ERROR_RETURNS send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,WPS operation " "failed"); #else send_resp(dut, conn, SIGMA_COMPLETE, "ErrorCode,WPS operation " "failed"); #endif return 0; } if (!p2p_resp) return 1; send_resp(dut, conn, SIGMA_COMPLETE, "Result,,GroupID,,PeerRole,"); return 0; } static int cmd_sta_p2p_dissolve(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "interface"); const char *grpid = get_param(cmd, "GroupID"); struct wfa_cs_p2p_group *grp; char buf[128]; if (grpid == NULL) return -1; grp = p2p_group_get(dut, grpid); if (grp == NULL) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Requested group " "not found"); return 0; } snprintf(buf, sizeof(buf), "P2P_GROUP_REMOVE %s", grp->ifname); if (wpa_command(intf, buf) < 0) { sigma_dut_print(dut, DUT_MSG_INFO, "Failed to remove the " "specified group from wpa_supplicant - assume " "group has already been removed"); } sigma_dut_print(dut, DUT_MSG_DEBUG, "Removed group %s", grpid); if (grp->go) dut->go = 0; else dut->p2p_client = 0; p2p_group_remove(dut, grpid); return 1; } static int cmd_sta_send_p2p_invitation_req(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "interface"); const char *devid = get_param(cmd, "P2PDevID"); const char *grpid = get_param(cmd, "GroupID"); const char *reinvoke = get_param(cmd, "Reinvoke"); char c[256]; char buf[4096]; struct wpa_ctrl *ctrl; int res; if (devid == NULL || grpid == NULL) return -1; if (reinvoke && atoi(reinvoke)) { int id = -1; char *ssid, *pos; ssid = strchr(grpid, ' '); if (ssid == NULL) { sigma_dut_print(dut, DUT_MSG_INFO, "Invalid grpid"); return -1; } ssid++; sigma_dut_print(dut, DUT_MSG_DEBUG, "Search for persistent " "group credentials based on SSID: '%s'", ssid); if (wpa_command_resp(intf, "LIST_NETWORKS", buf, sizeof(buf)) < 0) return -2; pos = strstr(buf, ssid); if (pos == NULL || pos == buf || pos[-1] != '\t' || pos[strlen(ssid)] != '\t') { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode," "Persistent group credentials not found"); return 0; } while (pos > buf && pos[-1] != '\n') pos--; id = atoi(pos); snprintf(c, sizeof(c), "P2P_INVITE persistent=%d peer=%s", id, devid); } else { struct wfa_cs_p2p_group *grp; grp = p2p_group_get(dut, grpid); if (grp == NULL) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode," "No active P2P group found for invitation"); return 0; } snprintf(c, sizeof(c), "P2P_INVITE group=%s peer=%s", grp->ifname, devid); } sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover peer %s for " "invitation", devid); if (p2p_discover_peer(dut, intf, devid, 0) < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not " "discover the requested peer"); return 0; } ctrl = open_wpa_mon(intf); if (ctrl == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open " "wpa_supplicant monitor connection"); return -2; } if (wpa_command(intf, c) < 0) { sigma_dut_print(dut, DUT_MSG_INFO, "Failed to send invitation " "request"); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); return -2; } res = get_wpa_cli_event(dut, ctrl, "P2P-INVITATION-RESULT", buf, sizeof(buf)); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); if (res < 0) return -2; sigma_dut_print(dut, DUT_MSG_DEBUG, "Invitation event: '%s'", buf); return 1; } static int cmd_sta_accept_p2p_invitation_req(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "Interface"); const char *devid = get_param(cmd, "P2PDevID"); const char *grpid = get_param(cmd, "GroupID"); const char *reinvoke = get_param(cmd, "Reinvoke"); char buf[100]; if (devid == NULL || grpid == NULL) return -1; if (reinvoke && atoi(reinvoke)) { /* * Assume persistent reconnect is enabled and there is no need * to do anything here. */ return 1; } /* * In a client-joining-a-running-group case, we need to separately * authorize the invitation. */ sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover GO %s", devid); if (p2p_discover_peer(dut, intf, devid, 1) < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not " "discover the requested peer"); return 0; } snprintf(buf, sizeof(buf), "P2P_CONNECT %s %s join auth", devid, dut->wps_method == WFA_CS_WPS_PBC ? "pbc" : dut->wps_pin); if (wpa_command(intf, buf) < 0) return -2; return 1; } static int cmd_sta_send_p2p_provision_dis_req(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "interface"); const char *conf_method = get_param(cmd, "ConfigMethod"); const char *devid = get_param(cmd, "P2PDevID"); char buf[256]; char *method; if (conf_method == NULL || devid == NULL) return -1; if (strcasecmp(conf_method, "Display") == 0) method = "display"; else if (strcasecmp(conf_method, "Keyboard") == 0 || strcasecmp(conf_method, "keypad") == 0) method = "keypad"; else if (strcasecmp(conf_method, "Label") == 0) method = "label"; else if (strcasecmp(conf_method, "pbc") == 0 || strcasecmp(conf_method, "pushbutton") == 0) method = "pbc"; else return -1; sigma_dut_print(dut, DUT_MSG_DEBUG, "Trying to discover peer %s for " "provision discovery", devid); if (p2p_discover_peer(dut, intf, devid, 0) < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not " "discover the requested peer"); return 0; } snprintf(buf, sizeof(buf), "P2P_PROV_DISC %s %s", devid, method); if (wpa_command(intf, buf) < 0) { sigma_dut_print(dut, DUT_MSG_INFO, "Failed to send provision " "discovery request"); return -2; } return 1; } static int cmd_sta_set_wps_pbc(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { /* const char *intf = get_param(cmd, "Interface"); */ const char *grpid = get_param(cmd, "GroupID"); if (grpid) { struct wfa_cs_p2p_group *grp; grp = p2p_group_get(dut, grpid); if (grp && grp->go) { sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a " "client to join with WPS"); wpa_command(grp->ifname, "WPS_PBC"); return 1; } } dut->wps_method = WFA_CS_WPS_PBC; return 1; } static int cmd_sta_wps_read_pin(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { /* const char *intf = get_param(cmd, "Interface"); */ const char *grpid = get_param(cmd, "GroupID"); char *pin = "12345670"; /* TODO: use random PIN */ char resp[100]; if (grpid) { char buf[100]; struct wfa_cs_p2p_group *grp; grp = p2p_group_get(dut, grpid); if (grp && grp->go) { sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a " "client to join with WPS"); snprintf(buf, sizeof(buf), "WPS_PIN any %s", pin); if (wpa_command(grp->ifname, buf) < 0) return -1; goto done; } } strncpy(dut->wps_pin, pin, sizeof(dut->wps_pin)); dut->wps_method = WFA_CS_WPS_PIN_DISPLAY; done: snprintf(resp, sizeof(resp), "PIN,%s", pin); send_resp(dut, conn, SIGMA_COMPLETE, resp); return 0; } static int cmd_sta_wps_read_label(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { /* const char *intf = get_param(cmd, "Interface"); */ const char *grpid = get_param(cmd, "GroupID"); char *pin = "12345670"; char resp[100]; if (grpid) { char buf[100]; struct wfa_cs_p2p_group *grp; grp = p2p_group_get(dut, grpid); if (grp && grp->go) { sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a " "client to join with WPS"); snprintf(buf, sizeof(buf), "WPS_PIN any %s", pin); wpa_command(grp->ifname, buf); return 1; } } strncpy(dut->wps_pin, pin, sizeof(dut->wps_pin)); dut->wps_method = WFA_CS_WPS_PIN_LABEL; snprintf(resp, sizeof(resp), "LABEL,%s", pin); send_resp(dut, conn, SIGMA_COMPLETE, resp); return 0; } static int cmd_sta_wps_enter_pin(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { /* const char *intf = get_param(cmd, "Interface"); */ const char *grpid = get_param(cmd, "GroupID"); const char *pin = get_param(cmd, "PIN"); if (pin == NULL) return -1; if (grpid) { char buf[100]; struct wfa_cs_p2p_group *grp; grp = p2p_group_get(dut, grpid); if (grp && grp->go) { sigma_dut_print(dut, DUT_MSG_DEBUG, "Authorize a " "client to join with WPS"); snprintf(buf, sizeof(buf), "WPS_PIN any %s", pin); wpa_command(grp->ifname, buf); return 1; } } strncpy(dut->wps_pin, pin, sizeof(dut->wps_pin)); dut->wps_pin[sizeof(dut->wps_pin) - 1] = '\0'; dut->wps_method = WFA_CS_WPS_PIN_KEYPAD; return 1; } static int cmd_sta_get_psk(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { /* const char *intf = get_param(cmd, "interface"); */ const char *grpid = get_param(cmd, "GroupID"); struct wfa_cs_p2p_group *grp; char passphrase[64], resp[200]; if (grpid == NULL) return -1; grp = p2p_group_get(dut, grpid); if (grp == NULL) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested group not found"); return 0; } if (!grp->go) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Local role is not GO in the specified " "group"); return 0; } if (wpa_command_resp(grp->ifname, "P2P_GET_PASSPHRASE", passphrase, sizeof(passphrase)) < 0) return -2; snprintf(resp, sizeof(resp), "passPhrase,%s,ssid,%s", passphrase, grp->ssid); send_resp(dut, conn, SIGMA_COMPLETE, resp); return 0; } int cmd_sta_p2p_reset(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "interface"); struct wfa_cs_p2p_group *grp, *prev; char buf[256]; dut->go = 0; dut->p2p_client = 0; dut->wps_method = WFA_CS_WPS_NOT_READY; grp = dut->groups; while (grp) { prev = grp; grp = grp->next; snprintf(buf, sizeof(buf), "P2P_GROUP_REMOVE %s", prev->ifname); wpa_command(intf, buf); p2p_group_remove(dut, prev->grpid); } wpa_command(intf, "P2P_GROUP_REMOVE *"); wpa_command(intf, "P2P_STOP_FIND"); wpa_command(intf, "P2P_FLUSH"); wpa_command(intf, "P2P_SERVICE_FLUSH"); wpa_command(intf, "P2P_SET disabled 0"); wpa_command(intf, "P2P_SET ssid_postfix "); if (dut->program == PROGRAM_60GHZ) { wpa_command(intf, "SET p2p_oper_reg_class 180"); wpa_command(intf, "P2P_SET listen_channel 2 180"); dut->listen_chn = 2; } else { wpa_command(intf, "P2P_SET listen_channel 6"); dut->listen_chn = 6; } wpa_command(intf, "P2P_EXT_LISTEN"); wpa_command(intf, "SET p2p_go_intent 7"); wpa_command(intf, "P2P_SET client_apsd disable"); wpa_command(intf, "P2P_SET go_apsd disable"); wpa_command(get_station_ifname(), "P2P_SET ps 98"); wpa_command(get_station_ifname(), "P2P_SET ps 96"); wpa_command(get_station_ifname(), "P2P_SET ps 0"); wpa_command(intf, "SET persistent_reconnect 1"); wpa_command(intf, "SET ampdu 1"); run_system(dut, "iptables -F INPUT"); if (dut->arp_ipaddr[0]) { snprintf(buf, sizeof(buf), "ip nei del %s dev %s", dut->arp_ipaddr, dut->arp_ifname); run_system(dut, buf); dut->arp_ipaddr[0] = '\0'; } snprintf(buf, sizeof(buf), "ip nei flush dev %s", get_station_ifname()); run_system(dut, buf); dut->p2p_mode = P2P_IDLE; dut->client_uapsd = 0; ath6kl_client_uapsd(dut, intf, 0); remove_wpa_networks(intf); disconnect_station(dut); if (dut->iface_down_on_reset) dut_ifc_reset(dut); return 1; } static int cmd_sta_get_p2p_ip_config(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { /* const char *intf = get_param(cmd, "Interface"); */ const char *grpid = get_param(cmd, "GroupID"); struct wfa_cs_p2p_group *grp = NULL; int count; char macaddr[20]; char resp[200], info[150]; if (grpid == NULL) return -1; if (strcmp(grpid, "$P2P_GROUP_ID") == 0) return -1; /* * If we did not initiate the operation that created the group, we may * not have the group information available in the DUT code yet and it * may take some time to get this from wpa_supplicant in case we are * the P2P client. As such, we better try this multiple times to allow * some time to complete the operation. */ sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting to find the requested " "group"); count = dut->default_timeout; while (count > 0) { grp = p2p_group_get(dut, grpid); if (grp == NULL) { sigma_dut_print(dut, DUT_MSG_DEBUG, "Requested group " "not yet found (count=%d)", count); sleep(1); } else break; count--; } if (grp == NULL) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested group not found"); return 0; } sigma_dut_print(dut, DUT_MSG_DEBUG, "Waiting for IP address on group " "interface %s", grp->ifname); if (wait_ip_addr(dut, grp->ifname, dut->default_timeout) < 0) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,No IP address received"); return 0; } if (get_ip_config(dut, grp->ifname, info, sizeof(info)) < 0) { sigma_dut_print(dut, DUT_MSG_INFO, "Failed to get IP address " "for group interface %s", grp->ifname); send_resp(dut, conn, SIGMA_ERROR, "errorCode,Failed to get IP address"); return 0; } if (get_wpa_status(grp->ifname, "address", macaddr, sizeof(macaddr)) < 0) { sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to get interface " "address for group interface %s", grp->ifname); return -2; } sigma_dut_print(dut, DUT_MSG_DEBUG, "IP address for group interface " "%s found", grp->ifname); snprintf(resp, sizeof(resp), "%s,P2PInterfaceAddress,%s", info, macaddr); send_resp(dut, conn, SIGMA_COMPLETE, resp); return 0; } static int cmd_sta_send_p2p_presence_req(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "Interface"); const char *dur = get_param(cmd, "Duration"); const char *interv = get_param(cmd, "Interval"); /* const char *grpid = get_param(cmd, "GroupID"); */ const char *ifname; char buf[100]; if (dur == NULL || interv == NULL) return -1; /* TODO: need to add groupid into parameters in CAPI spec; for now, * pick the first active group */ ifname = get_group_ifname(dut, intf); snprintf(buf, sizeof(buf), "P2P_PRESENCE_REQ %s %s", dur, interv); if (wpa_command(ifname, buf) < 0) return -2; return 1; } static int cmd_sta_set_sleep(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { /* const char *intf = get_param(cmd, "Interface"); */ struct wfa_cs_p2p_group *grp; char *ifname; const char *grpid = get_param(cmd, "GroupID"); if (dut->program == PROGRAM_60GHZ) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,UAPSD Sleep is not applicable for 60 GHz"); return 0; } if (grpid == NULL) ifname = get_station_ifname(); else { grp = p2p_group_get(dut, grpid); if (grp == NULL) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested group not found"); return 0; } ifname = grp->ifname; } if (dut->client_uapsd) { #ifdef __linux__ /* no special handling for nl80211 yet */ char path[128]; struct stat s; snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname); if (stat(path, &s) == 0) { if (wpa_command(ifname, "P2P_SET ps 1") < 0) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Going to sleep not supported"); return 0; } return 1; } #endif /* __linux__ */ if (wpa_command(ifname, "P2P_SET ps 99") < 0) return -2; } else { if (wpa_command(ifname, "P2P_SET ps 1") < 0) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Going to sleep not supported"); return 0; } } return 1; } static int cmd_sta_set_opportunistic_ps(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { /* const char *intf = get_param(cmd, "Interface"); */ struct wfa_cs_p2p_group *grp; char buf[100]; const char *grpid = get_param(cmd, "GroupID"); const char *ctwindow = get_param(cmd, "CTWindow"); if (grpid == NULL || ctwindow == NULL) return -1; grp = p2p_group_get(dut, grpid); if (grp == NULL) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested group not found"); return 0; } if (wpa_command(grp->ifname, "P2P_SET oppps 1") < 0) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Use of OppPS as GO not supported"); return 0; } snprintf(buf, sizeof(buf), "P2P_SET ctwindow %d", atoi(ctwindow)); if (wpa_command(grp->ifname, buf) < 0) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Use of CTWindow as GO not supported"); return 0; } return 1; } static int cmd_sta_send_service_discovery_req(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "Interface"); const char *devid = get_param(cmd, "P2PDevID"); char buf[128]; if (devid == NULL) return -1; snprintf(buf, sizeof(buf), "P2P_SERV_DISC_REQ %s 02000001", devid); if (wpa_command(intf, buf) < 0) { send_resp(dut, conn, SIGMA_ERROR, NULL); return 0; } return 1; } static int cmd_sta_add_arp_table_entry(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { char buf[256]; char *ifname; const char *grpid, *ipaddr, *macaddr; grpid = get_param(cmd, "GroupID"); ipaddr = get_param(cmd, "IPAddress"); macaddr = get_param(cmd, "MACAddress"); if (ipaddr == NULL || macaddr == NULL) return -1; if (grpid == NULL) ifname = get_station_ifname(); else { struct wfa_cs_p2p_group *grp; grp = p2p_group_get(dut, grpid); if (grp == NULL) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested group not found"); return 0; } ifname = grp->ifname; } snprintf(dut->arp_ipaddr, sizeof(dut->arp_ipaddr), "%s", ipaddr); snprintf(dut->arp_ifname, sizeof(dut->arp_ifname), "%s", ifname); snprintf(buf, sizeof(buf), "ip nei add %s lladdr %s dev %s", ipaddr, macaddr, ifname); run_system(dut, buf); return 1; } static int cmd_sta_block_icmp_response(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { char buf[256]; struct wfa_cs_p2p_group *grp; char *ifname; const char *grpid, *ipaddr; grpid = get_param(cmd, "GroupID"); ipaddr = get_param(cmd, "IPAddress"); if (ipaddr == NULL) return -1; if (grpid == NULL) ifname = get_station_ifname(); else { grp = p2p_group_get(dut, grpid); if (grp == NULL) { send_resp(dut, conn, SIGMA_ERROR, "errorCode,Requested group not found"); return 0; } ifname = grp->ifname; } snprintf(buf, sizeof(buf), "iptables -I INPUT -s %s -p icmp -i %s -j DROP", ipaddr, ifname); run_system(dut, buf); return 1; } static int run_nfc_command(struct sigma_dut *dut, const char *cmd, const char *info) { int res; sigma_dut_summary(dut, "NFC operation: %s", info); printf("\n\n\n=====[ NFC operation ]=========================\n\n"); printf("%s\n\n", info); nfc_status(dut, "START", info); res = run_system(dut, cmd); nfc_status(dut, res ? "FAIL" : "SUCCESS", info); if (res) { sigma_dut_print(dut, DUT_MSG_INFO, "Failed to run '%s': %d", cmd, res); return res; } return 0; } static int nfc_write_p2p_select(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { int res; const char *ifname = get_param(cmd, "Interface"); char buf[300]; run_system(dut, "killall wps-nfc.py"); run_system(dut, "killall p2p-nfc.py"); if (wpa_command(ifname, "WPS_NFC_TOKEN NDEF") < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to generate NFC password token"); return 0; } unlink("nfc-success"); snprintf(buf, sizeof(buf), "./p2p-nfc.py -1 --no-wait %s%s --success nfc-success write-p2p-sel", dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : ""); res = run_nfc_command(dut, buf, "Touch NFC Tag to write P2P connection handover select"); if (res || !file_exists("nfc-success")) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to write tag"); return 0; } if (wpa_command(ifname, "P2P_SET nfc_tag 1") < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to enable NFC password token"); return 0; } if (!dut->go && wpa_command(ifname, "P2P_LISTEN") < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to start listen mode"); return 0; } send_resp(dut, conn, SIGMA_COMPLETE, "Result,,GroupID,,PeerRole,,PauseFlag,0"); return 0; } static int nfc_write_config_token(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { int res; const char *bssid = get_param(cmd, "Bssid"); const char *intf = get_param(cmd, "Interface"); char buf[200]; run_system(dut, "killall wps-nfc.py"); run_system(dut, "killall p2p-nfc.py"); unlink("nfc-success"); if (dut->er_oper_performed && bssid) { char current_bssid[30], id[10]; if (get_wpa_status(intf, "id", id, sizeof(id)) < 0 || get_wpa_status(intf, "bssid", current_bssid, sizeof(current_bssid)) < 0 || strncasecmp(bssid, current_bssid, strlen(current_bssid)) != 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,No configuration known for BSSID"); return 0; } snprintf(buf, sizeof(buf), "./wps-nfc.py --id %s --no-wait %s%s --success nfc-success write-config", id, dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : ""); res = run_nfc_command(dut, buf, "Touch NFC Tag to write WPS configuration token"); } else { snprintf(buf, sizeof(buf), "./wps-nfc.py --no-wait %s%s --success nfc-success write-config", dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : ""); res = run_nfc_command(dut, buf, "Touch NFC Tag to write WPS configuration token"); } if (res || !file_exists("nfc-success")) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to write tag"); return 0; } send_resp(dut, conn, SIGMA_COMPLETE, "Result,,GroupID,,PeerRole,,PauseFlag,0"); return 0; } static int nfc_write_password_token(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { int res; char buf[300]; run_system(dut, "killall wps-nfc.py"); run_system(dut, "killall p2p-nfc.py"); unlink("nfc-success"); snprintf(buf, sizeof(buf), "./wps-nfc.py --no-wait %s%s --success nfc-success write-password", dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : ""); res = run_nfc_command(dut, buf, "Touch NFC Tag to write WPS password token"); if (res || !file_exists("nfc-success")) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to write tag"); return 0; } send_resp(dut, conn, SIGMA_COMPLETE, "Result,,GroupID,,PeerRole,,PauseFlag,0"); return 0; } static int nfc_read_tag(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { int res; struct wpa_ctrl *ctrl; const char *intf = get_param(cmd, "Interface"); const char *oper_chn = get_param(cmd, "OPER_CHN"); char buf[1000], freq_str[20]; run_system(dut, "killall wps-nfc.py"); run_system(dut, "killall p2p-nfc.py"); ctrl = open_wpa_mon(intf); if (ctrl == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open " "wpa_supplicant monitor connection"); return -2; } freq_str[0] = '\0'; if (oper_chn) { int chan = atoi(oper_chn); if (chan >= 1 && chan <= 11) snprintf(freq_str, sizeof(freq_str), " --freq %d", 2407 + chan * 5); } unlink("nfc-success"); snprintf(buf, sizeof(buf), "./p2p-nfc.py -1 -t %s%s --success nfc-success --no-wait%s", dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : "", freq_str); res = run_nfc_command(dut, buf, "Touch NFC Tag to read it"); if (res || !file_exists("nfc-success")) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to read tag"); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); return 0; } if (dut->p2p_mode == P2P_DISABLE) return wps_connection_event(dut, conn, ctrl, intf, 1); if (dut->go || dut->p2p_client) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); send_resp(dut, conn, SIGMA_COMPLETE, "Result,,GroupID,,PeerRole,,PauseFlag,0"); return 0; } /* FIX: PeerRole */ return p2p_group_formation_event(dut, conn, ctrl, intf, "0", 1); } static int nfc_wps_read_tag(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { int res; struct wpa_ctrl *ctrl; const char *intf = get_param(cmd, "Interface"); char buf[300]; run_system(dut, "killall wps-nfc.py"); run_system(dut, "killall p2p-nfc.py"); ctrl = open_wpa_mon(intf); if (ctrl == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open " "wpa_supplicant monitor connection"); return -2; } unlink("nfc-success"); snprintf(buf, sizeof(buf), "./wps-nfc.py -1 --no-wait %s%s --success nfc-success", dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : ""); res = run_nfc_command(dut, buf, "Touch NFC Tag to read it"); if (res || !file_exists("nfc-success")) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to read tag"); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); return 0; } return wps_connection_event(dut, conn, ctrl, intf, 1); } static int er_ap_add_match(const char *event, const char *bssid, const char *req_uuid, char *ret_uuid, size_t max_uuid_len) { const char *pos, *uuid; pos = strchr(event, ' '); if (pos == NULL) return 0; pos++; uuid = pos; pos = strchr(pos, ' '); if (pos == NULL) return 0; if (ret_uuid) { if ((size_t) (pos - uuid + 1) < max_uuid_len) { memcpy(ret_uuid, uuid, pos - uuid); ret_uuid[pos - uuid] = '\0'; } else ret_uuid[0] = '\0'; } if (req_uuid && strncasecmp(req_uuid, uuid, pos - uuid) == 0) return 1; pos++; /* at BSSID */ return strncasecmp(pos, bssid, strlen(bssid)) == 0; } static int er_start(struct sigma_dut *dut, struct sigma_conn *conn, struct wpa_ctrl *ctrl, const char *intf, const char *bssid, const char *uuid, char *ret_uuid, size_t max_uuid_len) { char id[10]; int res; char buf[1000]; sigma_dut_print(dut, DUT_MSG_INFO, "Trying to find WPS AP %s over UPnP", bssid); if (wpa_command(intf, "WPS_ER_START") < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to start ER"); return 0; } for (;;) { res = get_wpa_cli_event(dut, ctrl, "WPS-ER-AP-ADD", buf, sizeof(buf)); if (res < 0) { #ifdef USE_ERROR_RETURNS send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not find the AP over UPnP"); #else send_resp(dut, conn, SIGMA_COMPLETE, "ErrorCode,Could not find the AP over UPnP"); #endif return 0; } if (er_ap_add_match(buf, bssid, uuid, ret_uuid, max_uuid_len)) { sigma_dut_print(dut, DUT_MSG_INFO, "Found WPS AP over UPnP: %s", buf); break; } } if (get_wpa_status(intf, "id", id, sizeof(id)) < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Could not find AP configuration"); return 0; } if (ret_uuid) { snprintf(buf, sizeof(buf), "WPS_ER_SET_CONFIG %s %s", ret_uuid, id); } else if (uuid) { snprintf(buf, sizeof(buf), "WPS_ER_SET_CONFIG %s %s", uuid, id); } else { snprintf(buf, sizeof(buf), "WPS_ER_SET_CONFIG %s %s", bssid, id); } if (wpa_command(intf, buf) < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to select network configuration for ER"); return 0; } return 1; } static int nfc_wps_read_passwd(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { int res; struct wpa_ctrl *ctrl; const char *intf = get_param(cmd, "Interface"); const char *bssid = get_param(cmd, "Bssid"); const char *ssid = get_param(cmd, "SSID"); const char *security = get_param(cmd, "Security"); const char *passphrase = get_param(cmd, "Passphrase"); char ssid_hex[200], passphrase_hex[200]; const char *val; int sta_action; char buf[1000]; const char *keymgmt, *cipher; run_system(dut, "killall wps-nfc.py"); run_system(dut, "killall p2p-nfc.py"); if ((ssid && strlen(ssid) >= 2 * sizeof(ssid_hex)) || (passphrase && strlen(passphrase) >= 2 * sizeof(passphrase_hex))) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Too long SSID/passphrase"); return 0; } val = get_param(cmd, "WpsStaAction"); if (!val) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Missing WpsStaAction argument"); return 0; } sta_action = atoi(val); if (sta_action != 1 && sta_action != 2) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported WpsStaAction value"); return 0; } if (!bssid) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Missing Bssid argument"); return 0; } if (sta_action == 2) { if (!ssid) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Missing SSID argument"); return 0; } if (!security) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Missing Security argument"); return 0; } if (!passphrase) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Missing Passphrase argument"); return 0; } } ctrl = open_wpa_mon(intf); if (ctrl == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open " "wpa_supplicant monitor connection"); return -2; } if (sta_action == 1) { const char *uuid = get_param(cmd, "UUID"); res = er_start(dut, conn, ctrl, intf, bssid, uuid, NULL, 0); if (res != 1) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); return res; } } unlink("nfc-success"); snprintf(buf, sizeof(buf), "./wps-nfc.py -1 --no-wait %s%s --success nfc-success", dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : ""); res = run_nfc_command(dut, buf, "Touch NFC Tag to read it"); if (res || !file_exists("nfc-success")) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to read tag"); return 0; } if (sta_action == 1) { sigma_dut_print(dut, DUT_MSG_INFO, "Prepared device password for ER to enroll a new station"); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); send_resp(dut, conn, SIGMA_COMPLETE, "Result,,GroupID,,PeerRole,"); return 0; } if (strcasecmp(security, "wpa2-psk") == 0) { keymgmt = "WPA2PSK"; cipher = "CCMP"; } else { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported Security value"); return 0; } ascii2hexstr(ssid, ssid_hex); ascii2hexstr(passphrase, passphrase_hex); snprintf(buf, sizeof(buf), "WPS_REG %s nfc-pw %s %s %s %s", bssid, ssid_hex, keymgmt, cipher, passphrase_hex); if (wpa_command(intf, buf) < 0) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to start registrar"); return 0; } return wps_connection_event(dut, conn, ctrl, intf, 1); } static int nfc_wps_read_config(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { int res; struct wpa_ctrl *ctrl; const char *intf = get_param(cmd, "Interface"); char buf[300]; run_system(dut, "killall wps-nfc.py"); run_system(dut, "killall p2p-nfc.py"); ctrl = open_wpa_mon(intf); if (ctrl == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open " "wpa_supplicant monitor connection"); return -2; } unlink("nfc-success"); snprintf(buf, sizeof(buf), "./wps-nfc.py -1 --no-wait %s%s --success nfc-success", dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : ""); res = run_nfc_command(dut, buf, "Touch NFC Tag to read it"); if (res || !file_exists("nfc-success")) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to read tag"); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); return 0; } return wps_connection_event(dut, conn, ctrl, intf, 1); } static int nfc_wps_connection_handover(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "Interface"); int res; const char *init = get_param(cmd, "Init"); struct wpa_ctrl *ctrl = NULL; char buf[300]; run_system(dut, "killall wps-nfc.py"); run_system(dut, "killall p2p-nfc.py"); ctrl = open_wpa_mon(intf); if (ctrl == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open " "wpa_supplicant monitor connection"); return -2; } unlink("nfc-success"); if ((!init || atoi(init) == 0) && dut->er_oper_performed) { const char *bssid = get_param(cmd, "Bssid"); const char *req_uuid = get_param(cmd, "UUID"); char uuid[100]; if (bssid == NULL) bssid = dut->er_oper_bssid; res = er_start(dut, conn, ctrl, intf, bssid, req_uuid, uuid, sizeof(uuid)); if (res != 1) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); return res; } snprintf(buf, sizeof(buf), "./wps-nfc.py -1 --uuid %s %s%s --success nfc-success", uuid, dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : ""); res = run_nfc_command(dut, buf, "Touch NFC Device to respond to WPS connection handover"); } else if (!init || atoi(init)) { snprintf(buf, sizeof(buf), "./wps-nfc.py -1 --no-wait %s%s --success nfc-success", dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : ""); res = run_nfc_command(dut, buf, "Touch NFC Device to initiate WPS connection handover"); } else { snprintf(buf, sizeof(buf), "./p2p-nfc.py -1 --no-wait --no-input %s%s --success nfc-success --handover-only", dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : ""); res = run_nfc_command(dut, buf, "Touch NFC Device to respond to WPS connection handover"); } if (res) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to enable NFC for connection " "handover"); return 0; } if (!file_exists("nfc-success")) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to complete NFC connection handover"); return 0; } if (init && atoi(init)) return wps_connection_event(dut, conn, ctrl, intf, 1); wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); send_resp(dut, conn, SIGMA_COMPLETE, "Result,,GroupID,,PeerRole,,PauseFlag,0"); return 0; } static int nfc_p2p_connection_handover(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "Interface"); int res; const char *init = get_param(cmd, "Init"); const char *oper_chn = get_param(cmd, "OPER_CHN"); struct wpa_ctrl *ctrl; char buf[1000], freq_str[20]; run_system(dut, "killall wps-nfc.py"); run_system(dut, "killall p2p-nfc.py"); ctrl = open_wpa_mon(intf); if (ctrl == NULL) { sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to open " "wpa_supplicant monitor connection"); return -2; } freq_str[0] = '\0'; if (oper_chn) { int chan = atoi(oper_chn); if (chan >= 1 && chan <= 11) snprintf(freq_str, sizeof(freq_str), " --freq %d", 2407 + chan * 5); } unlink("nfc-success"); if (init && atoi(init)) { snprintf(buf, sizeof(buf), "./p2p-nfc.py -1 -I -N --no-wait %s%s --success nfc-success --no-input%s --handover-only", dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : "", freq_str); res = run_nfc_command(dut, buf, "Touch NFC Device to initiate P2P connection handover"); } else { snprintf(buf, sizeof(buf), "./p2p-nfc.py -1 --no-wait %s%s --success nfc-success --no-input%s --handover-only", dut->summary_log ? "--summary " : "", dut->summary_log ? dut->summary_log : "", freq_str); res = run_nfc_command(dut, buf, "Touch NFC Device to respond to P2P connection handover"); } if (res) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to enable NFC for connection " "handover"); return 0; } if (!file_exists("nfc-success")) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to complete NFC connection handover"); return 0; } if (dut->go || dut->p2p_client) { wpa_ctrl_detach(ctrl); wpa_ctrl_close(ctrl); send_resp(dut, conn, SIGMA_COMPLETE, "Result,,GroupID,,PeerRole,,PauseFlag,0"); return 0; } /* FIX: peer role from handover message */ return p2p_group_formation_event(dut, conn, ctrl, intf, "0", 1); } static int cmd_sta_nfc_action(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *intf = get_param(cmd, "Interface"); const char *oper = get_param(cmd, "Operation"); const char *ssid_param = get_param(cmd, "SSID"); const char *intent_val = get_param(cmd, "INTENT_VAL"); const char *oper_chn = get_param(cmd, "OPER_CHN"); char buf[256]; if (oper == NULL) return -1; if (ssid_param) snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix %s", ssid_param); else snprintf(buf, sizeof(buf), "P2P_SET ssid_postfix "); if (wpa_command(intf, buf) < 0) sigma_dut_print(dut, DUT_MSG_INFO, "Failed P2P ssid_postfix - ignore and assume this is for non-P2P case"); if (intent_val) { snprintf(buf, sizeof(buf), "SET p2p_go_intent %s", intent_val); if (wpa_command(intf, buf) < 0) return -2; } if (oper_chn) { int chan = atoi(oper_chn); if (chan < 1 || chan > 11) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported operating channel"); return 0; } snprintf(buf, sizeof(buf), "SET p2p_oper_channel %d", chan); if (wpa_command(intf, "SET p2p_oper_reg_class 81") < 0 || wpa_command(intf, buf) < 0) { send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Failed to set operating channel"); return 0; } } if (strcasecmp(oper, "WRITE_SELECT") == 0) return nfc_write_p2p_select(dut, conn, cmd); if (strcasecmp(oper, "WRITE_CONFIG") == 0) return nfc_write_config_token(dut, conn, cmd); if (strcasecmp(oper, "WRITE_PASSWD") == 0) return nfc_write_password_token(dut, conn, cmd); if (strcasecmp(oper, "READ_TAG") == 0) return nfc_read_tag(dut, conn, cmd); if (strcasecmp(oper, "WPS_READ_TAG") == 0) return nfc_wps_read_tag(dut, conn, cmd); if (strcasecmp(oper, "WPS_READ_PASSWD") == 0) return nfc_wps_read_passwd(dut, conn, cmd); if (strcasecmp(oper, "WPS_READ_CONFIG") == 0) return nfc_wps_read_config(dut, conn, cmd); if (strcasecmp(oper, "CONN_HNDOVR") == 0) return nfc_p2p_connection_handover(dut, conn, cmd); if (strcasecmp(oper, "WPS_CONN_HNDOVR") == 0) return nfc_wps_connection_handover(dut, conn, cmd); send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported operation"); return 0; } int p2p_cmd_sta_get_parameter(struct sigma_dut *dut, struct sigma_conn *conn, struct sigma_cmd *cmd) { const char *parameter = get_param(cmd, "Parameter"); char buf[100]; if (parameter == NULL) return -1; if (strcasecmp(parameter, "ListenChannel") == 0) { snprintf(buf, sizeof(buf), "ListenChnl,%u", dut->listen_chn); send_resp(dut, conn, SIGMA_COMPLETE, buf); return 0; } send_resp(dut, conn, SIGMA_ERROR, "ErrorCode,Unsupported parameter"); return 0; } static int req_intf(struct sigma_cmd *cmd) { return get_param(cmd, "interface") == NULL ? -1 : 0; } void p2p_register_cmds(void) { sigma_dut_reg_cmd("sta_get_p2p_dev_address", req_intf, cmd_sta_get_p2p_dev_address); sigma_dut_reg_cmd("sta_set_p2p", req_intf, cmd_sta_set_p2p); sigma_dut_reg_cmd("sta_start_autonomous_go", req_intf, cmd_sta_start_autonomous_go); sigma_dut_reg_cmd("sta_p2p_connect", req_intf, cmd_sta_p2p_connect); sigma_dut_reg_cmd("sta_p2p_start_group_formation", req_intf, cmd_sta_p2p_start_group_formation); sigma_dut_reg_cmd("sta_p2p_dissolve", req_intf, cmd_sta_p2p_dissolve); sigma_dut_reg_cmd("sta_send_p2p_invitation_req", req_intf, cmd_sta_send_p2p_invitation_req); sigma_dut_reg_cmd("sta_accept_p2p_invitation_req", req_intf, cmd_sta_accept_p2p_invitation_req); sigma_dut_reg_cmd("sta_send_p2p_provision_dis_req", req_intf, cmd_sta_send_p2p_provision_dis_req); sigma_dut_reg_cmd("sta_set_wps_pbc", req_intf, cmd_sta_set_wps_pbc); sigma_dut_reg_cmd("sta_wps_read_pin", req_intf, cmd_sta_wps_read_pin); sigma_dut_reg_cmd("sta_wps_read_label", req_intf, cmd_sta_wps_read_label); sigma_dut_reg_cmd("sta_wps_enter_pin", req_intf, cmd_sta_wps_enter_pin); sigma_dut_reg_cmd("sta_get_psk", req_intf, cmd_sta_get_psk); sigma_dut_reg_cmd("sta_p2p_reset", req_intf, cmd_sta_p2p_reset); sigma_dut_reg_cmd("sta_get_p2p_ip_config", req_intf, cmd_sta_get_p2p_ip_config); sigma_dut_reg_cmd("sta_send_p2p_presence_req", req_intf, cmd_sta_send_p2p_presence_req); sigma_dut_reg_cmd("sta_set_sleep", req_intf, cmd_sta_set_sleep); sigma_dut_reg_cmd("sta_set_opportunistic_ps", req_intf, cmd_sta_set_opportunistic_ps); sigma_dut_reg_cmd("sta_send_service_discovery_req", req_intf, cmd_sta_send_service_discovery_req); sigma_dut_reg_cmd("sta_add_arp_table_entry", req_intf, cmd_sta_add_arp_table_entry); sigma_dut_reg_cmd("sta_block_icmp_response", req_intf, cmd_sta_block_icmp_response); sigma_dut_reg_cmd("sta_nfc_action", req_intf, cmd_sta_nfc_action); }