1151497Sru/* 2151497Sru * WPA Supplicant / Control interface (shared code for all backends) 3151497Sru * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> 4151497Sru * 5151497Sru * This software may be distributed under the terms of the BSD license. 6151497Sru * See README for more details. 7151497Sru */ 8151497Sru 9151497Sru#include "utils/includes.h" 10151497Sru 11151497Sru#include "utils/common.h" 12151497Sru#include "utils/eloop.h" 13151497Sru#include "common/version.h" 14151497Sru#include "common/ieee802_11_defs.h" 15151497Sru#include "common/ieee802_11_common.h" 16151497Sru#include "common/wpa_ctrl.h" 17151497Sru#include "eap_peer/eap.h" 18151497Sru#include "eapol_supp/eapol_supp_sm.h" 19151497Sru#include "rsn_supp/wpa.h" 20151497Sru#include "rsn_supp/preauth.h" 21151497Sru#include "rsn_supp/pmksa_cache.h" 22151497Sru#include "l2_packet/l2_packet.h" 23151497Sru#include "wps/wps.h" 24151497Sru#include "config.h" 25151497Sru#include "wpa_supplicant_i.h" 26151497Sru#include "driver_i.h" 27151497Sru#include "wps_supplicant.h" 28151497Sru#include "ibss_rsn.h" 29151497Sru#include "ap.h" 30151497Sru#include "p2p_supplicant.h" 31151497Sru#include "p2p/p2p.h" 32151497Sru#include "hs20_supplicant.h" 33151497Sru#include "wifi_display.h" 34151497Sru#include "notify.h" 35151497Sru#include "bss.h" 36151497Sru#include "scan.h" 37151497Sru#include "ctrl_iface.h" 38151497Sru#include "interworking.h" 39151497Sru#include "blacklist.h" 40151497Sru#include "autoscan.h" 41151497Sru#include "wnm_sta.h" 42151497Sru 43151497Sruextern struct wpa_driver_ops *wpa_drivers[]; 44151497Sru 45151497Srustatic int wpa_supplicant_global_iface_list(struct wpa_global *global, 46151497Sru char *buf, int len); 47151497Srustatic int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 48151497Sru char *buf, int len); 49151497Sru 50151497Sru 51151497Srustatic int pno_start(struct wpa_supplicant *wpa_s) 52151497Sru{ 53151497Sru int ret; 54151497Sru size_t i, num_ssid; 55151497Sru struct wpa_ssid *ssid; 56151497Sru struct wpa_driver_scan_params params; 57151497Sru 58151497Sru if (wpa_s->pno) 59151497Sru return 0; 60151497Sru 61151497Sru if (wpa_s->wpa_state == WPA_SCANNING) { 62151497Sru wpa_supplicant_cancel_sched_scan(wpa_s); 63151497Sru wpa_supplicant_cancel_scan(wpa_s); 64151497Sru } 65151497Sru 66151497Sru os_memset(¶ms, 0, sizeof(params)); 67151497Sru 68151497Sru num_ssid = 0; 69151497Sru ssid = wpa_s->conf->ssid; 70151497Sru while (ssid) { 71151497Sru if (!wpas_network_disabled(wpa_s, ssid)) 72151497Sru num_ssid++; 73151497Sru ssid = ssid->next; 74151497Sru } 75151497Sru if (num_ssid > WPAS_MAX_SCAN_SSIDS) { 76151497Sru wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from " 77151497Sru "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid); 78151497Sru num_ssid = WPAS_MAX_SCAN_SSIDS; 79151497Sru } 80151497Sru 81151497Sru if (num_ssid == 0) { 82151497Sru wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs"); 83151497Sru return -1; 84151497Sru } 85151497Sru 86151497Sru params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) * 87151497Sru num_ssid); 88151497Sru if (params.filter_ssids == NULL) 89151497Sru return -1; 90151497Sru i = 0; 91151497Sru ssid = wpa_s->conf->ssid; 92151497Sru while (ssid) { 93151497Sru if (!wpas_network_disabled(wpa_s, ssid)) { 94151497Sru params.ssids[i].ssid = ssid->ssid; 95151497Sru params.ssids[i].ssid_len = ssid->ssid_len; 96151497Sru params.num_ssids++; 97151497Sru os_memcpy(params.filter_ssids[i].ssid, ssid->ssid, 98151497Sru ssid->ssid_len); 99151497Sru params.filter_ssids[i].ssid_len = ssid->ssid_len; 100151497Sru params.num_filter_ssids++; 101151497Sru i++; 102151497Sru if (i == num_ssid) 103151497Sru break; 104151497Sru } 105151497Sru ssid = ssid->next; 106151497Sru } 107151497Sru 108151497Sru if (wpa_s->conf->filter_rssi) 109151497Sru params.filter_rssi = wpa_s->conf->filter_rssi; 110151497Sru 111151497Sru ret = wpa_drv_sched_scan(wpa_s, ¶ms, 10 * 1000); 112151497Sru os_free(params.filter_ssids); 113151497Sru if (ret == 0) 114151497Sru wpa_s->pno = 1; 115151497Sru return ret; 116151497Sru} 117151497Sru 118151497Sru 119151497Srustatic int pno_stop(struct wpa_supplicant *wpa_s) 120151497Sru{ 121151497Sru int ret = 0; 122151497Sru 123151497Sru if (wpa_s->pno) { 124151497Sru wpa_s->pno = 0; 125151497Sru ret = wpa_drv_stop_sched_scan(wpa_s); 126151497Sru } 127151497Sru 128151497Sru if (wpa_s->wpa_state == WPA_SCANNING) 129151497Sru wpa_supplicant_req_scan(wpa_s, 0, 0); 130151497Sru 131151497Sru return ret; 132151497Sru} 133151497Sru 134151497Sru 135151497Srustatic int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val) 136151497Sru{ 137151497Sru char *pos; 138151497Sru u8 addr[ETH_ALEN], *filter = NULL, *n; 139151497Sru size_t count = 0; 140151497Sru 141151497Sru pos = val; 142151497Sru while (pos) { 143151497Sru if (*pos == '\0') 144151497Sru break; 145151497Sru if (hwaddr_aton(pos, addr)) { 146151497Sru os_free(filter); 147151497Sru return -1; 148151497Sru } 149151497Sru n = os_realloc_array(filter, count + 1, ETH_ALEN); 150151497Sru if (n == NULL) { 151151497Sru os_free(filter); 152151497Sru return -1; 153151497Sru } 154151497Sru filter = n; 155151497Sru os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN); 156151497Sru count++; 157151497Sru 158151497Sru pos = os_strchr(pos, ' '); 159151497Sru if (pos) 160151497Sru pos++; 161151497Sru } 162151497Sru 163151497Sru wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN); 164151497Sru os_free(wpa_s->bssid_filter); 165151497Sru wpa_s->bssid_filter = filter; 166151497Sru wpa_s->bssid_filter_count = count; 167151497Sru 168151497Sru return 0; 169151497Sru} 170151497Sru 171151497Sru 172151497Srustatic int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val) 173151497Sru{ 174151497Sru char *pos; 175151497Sru u8 addr[ETH_ALEN], *bssid = NULL, *n; 176151497Sru struct wpa_ssid_value *ssid = NULL, *ns; 177151497Sru size_t count = 0, ssid_count = 0; 178151497Sru struct wpa_ssid *c; 179151497Sru 180151497Sru /* 181151497Sru * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ������ 182151497Sru * SSID_SPEC ::= ssid <SSID_HEX> 183151497Sru * BSSID_SPEC ::= bssid <BSSID_HEX> 184151497Sru */ 185151497Sru 186151497Sru pos = val; 187151497Sru while (pos) { 188151497Sru if (*pos == '\0') 189151497Sru break; 190151497Sru if (os_strncmp(pos, "bssid ", 6) == 0) { 191151497Sru int res; 192151497Sru pos += 6; 193151497Sru res = hwaddr_aton2(pos, addr); 194151497Sru if (res < 0) { 195151497Sru os_free(ssid); 196151497Sru os_free(bssid); 197151497Sru wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 198151497Sru "BSSID value '%s'", pos); 199151497Sru return -1; 200151497Sru } 201151497Sru pos += res; 202151497Sru n = os_realloc_array(bssid, count + 1, ETH_ALEN); 203151497Sru if (n == NULL) { 204151497Sru os_free(ssid); 205151497Sru os_free(bssid); 206151497Sru return -1; 207151497Sru } 208151497Sru bssid = n; 209151497Sru os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN); 210151497Sru count++; 211151497Sru } else if (os_strncmp(pos, "ssid ", 5) == 0) { 212151497Sru char *end; 213151497Sru pos += 5; 214151497Sru 215151497Sru end = pos; 216151497Sru while (*end) { 217151497Sru if (*end == '\0' || *end == ' ') 218151497Sru break; 219151497Sru end++; 220151497Sru } 221151497Sru 222151497Sru ns = os_realloc_array(ssid, ssid_count + 1, 223151497Sru sizeof(struct wpa_ssid_value)); 224151497Sru if (ns == NULL) { 225151497Sru os_free(ssid); 226151497Sru os_free(bssid); 227151497Sru return -1; 228151497Sru } 229151497Sru ssid = ns; 230151497Sru 231151497Sru if ((end - pos) & 0x01 || end - pos > 2 * 32 || 232151497Sru hexstr2bin(pos, ssid[ssid_count].ssid, 233151497Sru (end - pos) / 2) < 0) { 234151497Sru os_free(ssid); 235151497Sru os_free(bssid); 236151497Sru wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 237151497Sru "SSID value '%s'", pos); 238151497Sru return -1; 239151497Sru } 240151497Sru ssid[ssid_count].ssid_len = (end - pos) / 2; 241151497Sru wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID", 242151497Sru ssid[ssid_count].ssid, 243151497Sru ssid[ssid_count].ssid_len); 244151497Sru ssid_count++; 245151497Sru pos = end; 246151497Sru } else { 247151497Sru wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value " 248151497Sru "'%s'", pos); 249151497Sru os_free(ssid); 250151497Sru os_free(bssid); 251151497Sru return -1; 252151497Sru } 253151497Sru 254151497Sru pos = os_strchr(pos, ' '); 255151497Sru if (pos) 256151497Sru pos++; 257151497Sru } 258151497Sru 259151497Sru wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN); 260151497Sru os_free(wpa_s->disallow_aps_bssid); 261151497Sru wpa_s->disallow_aps_bssid = bssid; 262151497Sru wpa_s->disallow_aps_bssid_count = count; 263151497Sru 264151497Sru wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count); 265151497Sru os_free(wpa_s->disallow_aps_ssid); 266151497Sru wpa_s->disallow_aps_ssid = ssid; 267151497Sru wpa_s->disallow_aps_ssid_count = ssid_count; 268151497Sru 269151497Sru if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING) 270151497Sru return 0; 271151497Sru 272151497Sru c = wpa_s->current_ssid; 273151497Sru if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS) 274151497Sru return 0; 275151497Sru 276151497Sru if (!disallowed_bssid(wpa_s, wpa_s->bssid) && 277151497Sru !disallowed_ssid(wpa_s, c->ssid, c->ssid_len)) 278151497Sru return 0; 279151497Sru 280151497Sru wpa_printf(MSG_DEBUG, "Disconnect and try to find another network " 281151497Sru "because current AP was marked disallowed"); 282151497Sru 283151497Sru#ifdef CONFIG_SME 284151497Sru wpa_s->sme.prev_bssid_set = 0; 285151497Sru#endif /* CONFIG_SME */ 286151497Sru wpa_s->reassociate = 1; 287151497Sru wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 288151497Sru wpa_supplicant_req_scan(wpa_s, 0, 0); 289151497Sru 290151497Sru return 0; 291151497Sru} 292151497Sru 293151497Sru 294151497Srustatic int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 295151497Sru char *cmd) 296151497Sru{ 297151497Sru char *value; 298151497Sru int ret = 0; 299151497Sru 300151497Sru value = os_strchr(cmd, ' '); 301151497Sru if (value == NULL) 302151497Sru return -1; 303151497Sru *value++ = '\0'; 304151497Sru 305151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 306151497Sru if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 307151497Sru eapol_sm_configure(wpa_s->eapol, 308151497Sru atoi(value), -1, -1, -1); 309151497Sru } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 310151497Sru eapol_sm_configure(wpa_s->eapol, 311151497Sru -1, atoi(value), -1, -1); 312151497Sru } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 313151497Sru eapol_sm_configure(wpa_s->eapol, 314151497Sru -1, -1, atoi(value), -1); 315151497Sru } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 316151497Sru eapol_sm_configure(wpa_s->eapol, 317151497Sru -1, -1, -1, atoi(value)); 318151497Sru } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 319151497Sru if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 320151497Sru atoi(value))) 321151497Sru ret = -1; 322151497Sru } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 323151497Sru 0) { 324151497Sru if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 325151497Sru atoi(value))) 326151497Sru ret = -1; 327151497Sru } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 328151497Sru if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) 329151497Sru ret = -1; 330151497Sru } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) { 331151497Sru wpa_s->wps_fragment_size = atoi(value); 332151497Sru#ifdef CONFIG_WPS_TESTING 333151497Sru } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 334151497Sru long int val; 335151497Sru val = strtol(value, NULL, 0); 336151497Sru if (val < 0 || val > 0xff) { 337151497Sru ret = -1; 338151497Sru wpa_printf(MSG_DEBUG, "WPS: Invalid " 339151497Sru "wps_version_number %ld", val); 340151497Sru } else { 341151497Sru wps_version_number = val; 342151497Sru wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 343151497Sru "version %u.%u", 344151497Sru (wps_version_number & 0xf0) >> 4, 345151497Sru wps_version_number & 0x0f); 346151497Sru } 347151497Sru } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 348151497Sru wps_testing_dummy_cred = atoi(value); 349151497Sru wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 350151497Sru wps_testing_dummy_cred); 351151497Sru#endif /* CONFIG_WPS_TESTING */ 352151497Sru } else if (os_strcasecmp(cmd, "ampdu") == 0) { 353151497Sru if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0) 354151497Sru ret = -1; 355151497Sru#ifdef CONFIG_TDLS_TESTING 356151497Sru } else if (os_strcasecmp(cmd, "tdls_testing") == 0) { 357151497Sru extern unsigned int tdls_testing; 358151497Sru tdls_testing = strtol(value, NULL, 0); 359151497Sru wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing); 360151497Sru#endif /* CONFIG_TDLS_TESTING */ 361151497Sru#ifdef CONFIG_TDLS 362151497Sru } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) { 363151497Sru int disabled = atoi(value); 364151497Sru wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled); 365151497Sru if (disabled) { 366151497Sru if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0) 367151497Sru ret = -1; 368151497Sru } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0) 369151497Sru ret = -1; 370151497Sru wpa_tdls_enable(wpa_s->wpa, !disabled); 371151497Sru#endif /* CONFIG_TDLS */ 372151497Sru } else if (os_strcasecmp(cmd, "pno") == 0) { 373151497Sru if (atoi(value)) 374151497Sru ret = pno_start(wpa_s); 375151497Sru else 376151497Sru ret = pno_stop(wpa_s); 377151497Sru } else if (os_strcasecmp(cmd, "radio_disabled") == 0) { 378151497Sru int disabled = atoi(value); 379151497Sru if (wpa_drv_radio_disable(wpa_s, disabled) < 0) 380151497Sru ret = -1; 381151497Sru else if (disabled) 382151497Sru wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 383151497Sru } else if (os_strcasecmp(cmd, "uapsd") == 0) { 384151497Sru if (os_strcmp(value, "disable") == 0) 385151497Sru wpa_s->set_sta_uapsd = 0; 386151497Sru else { 387151497Sru int be, bk, vi, vo; 388151497Sru char *pos; 389151497Sru /* format: BE,BK,VI,VO;max SP Length */ 390151497Sru be = atoi(value); 391151497Sru pos = os_strchr(value, ','); 392151497Sru if (pos == NULL) 393151497Sru return -1; 394151497Sru pos++; 395151497Sru bk = atoi(pos); 396151497Sru pos = os_strchr(pos, ','); 397151497Sru if (pos == NULL) 398151497Sru return -1; 399151497Sru pos++; 400151497Sru vi = atoi(pos); 401151497Sru pos = os_strchr(pos, ','); 402151497Sru if (pos == NULL) 403151497Sru return -1; 404151497Sru pos++; 405151497Sru vo = atoi(pos); 406151497Sru /* ignore max SP Length for now */ 407151497Sru 408151497Sru wpa_s->set_sta_uapsd = 1; 409151497Sru wpa_s->sta_uapsd = 0; 410151497Sru if (be) 411151497Sru wpa_s->sta_uapsd |= BIT(0); 412151497Sru if (bk) 413151497Sru wpa_s->sta_uapsd |= BIT(1); 414151497Sru if (vi) 415151497Sru wpa_s->sta_uapsd |= BIT(2); 416151497Sru if (vo) 417151497Sru wpa_s->sta_uapsd |= BIT(3); 418151497Sru } 419151497Sru } else if (os_strcasecmp(cmd, "ps") == 0) { 420151497Sru ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1); 421151497Sru#ifdef CONFIG_WIFI_DISPLAY 422151497Sru } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 423151497Sru wifi_display_enable(wpa_s->global, !!atoi(value)); 424151497Sru#endif /* CONFIG_WIFI_DISPLAY */ 425151497Sru } else if (os_strcasecmp(cmd, "bssid_filter") == 0) { 426151497Sru ret = set_bssid_filter(wpa_s, value); 427151497Sru } else if (os_strcasecmp(cmd, "disallow_aps") == 0) { 428151497Sru ret = set_disallow_aps(wpa_s, value); 429151497Sru } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) { 430151497Sru wpa_s->no_keep_alive = !!atoi(value); 431151497Sru } else { 432151497Sru value[-1] = '='; 433151497Sru ret = wpa_config_process_global(wpa_s->conf, cmd, -1); 434151497Sru if (ret == 0) 435151497Sru wpa_supplicant_update_config(wpa_s); 436151497Sru } 437151497Sru 438151497Sru return ret; 439151497Sru} 440151497Sru 441151497Sru 442151497Srustatic int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, 443151497Sru char *cmd, char *buf, size_t buflen) 444151497Sru{ 445151497Sru int res = -1; 446151497Sru 447151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 448151497Sru 449151497Sru if (os_strcmp(cmd, "version") == 0) { 450151497Sru res = os_snprintf(buf, buflen, "%s", VERSION_STR); 451151497Sru } else if (os_strcasecmp(cmd, "country") == 0) { 452151497Sru if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) 453151497Sru res = os_snprintf(buf, buflen, "%c%c", 454151497Sru wpa_s->conf->country[0], 455151497Sru wpa_s->conf->country[1]); 456151497Sru#ifdef CONFIG_WIFI_DISPLAY 457151497Sru } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 458151497Sru res = os_snprintf(buf, buflen, "%d", 459151497Sru wpa_s->global->wifi_display); 460151497Sru if (res < 0 || (unsigned int) res >= buflen) 461151497Sru return -1; 462151497Sru return res; 463151497Sru#endif /* CONFIG_WIFI_DISPLAY */ 464151497Sru } 465151497Sru 466151497Sru if (res < 0 || (unsigned int) res >= buflen) 467151497Sru return -1; 468151497Sru return res; 469151497Sru} 470151497Sru 471151497Sru 472151497Sru#ifdef IEEE8021X_EAPOL 473151497Srustatic int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 474151497Sru char *addr) 475151497Sru{ 476151497Sru u8 bssid[ETH_ALEN]; 477151497Sru struct wpa_ssid *ssid = wpa_s->current_ssid; 478151497Sru 479151497Sru if (hwaddr_aton(addr, bssid)) { 480151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 481151497Sru "'%s'", addr); 482151497Sru return -1; 483151497Sru } 484151497Sru 485151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 486151497Sru rsn_preauth_deinit(wpa_s->wpa); 487151497Sru if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL)) 488151497Sru return -1; 489151497Sru 490151497Sru return 0; 491151497Sru} 492151497Sru#endif /* IEEE8021X_EAPOL */ 493151497Sru 494151497Sru 495151497Sru#ifdef CONFIG_PEERKEY 496151497Sru/* MLME-STKSTART.request(peer) */ 497151497Srustatic int wpa_supplicant_ctrl_iface_stkstart( 498151497Sru struct wpa_supplicant *wpa_s, char *addr) 499151497Sru{ 500151497Sru u8 peer[ETH_ALEN]; 501151497Sru 502151497Sru if (hwaddr_aton(addr, peer)) { 503151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid " 504151497Sru "address '%s'", addr); 505151497Sru return -1; 506151497Sru } 507151497Sru 508151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR, 509151497Sru MAC2STR(peer)); 510151497Sru 511151497Sru return wpa_sm_stkstart(wpa_s->wpa, peer); 512151497Sru} 513151497Sru#endif /* CONFIG_PEERKEY */ 514151497Sru 515151497Sru 516151497Sru#ifdef CONFIG_TDLS 517151497Sru 518151497Srustatic int wpa_supplicant_ctrl_iface_tdls_discover( 519151497Sru struct wpa_supplicant *wpa_s, char *addr) 520151497Sru{ 521151497Sru u8 peer[ETH_ALEN]; 522151497Sru int ret; 523151497Sru 524151497Sru if (hwaddr_aton(addr, peer)) { 525151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid " 526151497Sru "address '%s'", addr); 527151497Sru return -1; 528151497Sru } 529151497Sru 530151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR, 531151497Sru MAC2STR(peer)); 532151497Sru 533151497Sru if (wpa_tdls_is_external_setup(wpa_s->wpa)) 534151497Sru ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer); 535151497Sru else 536151497Sru ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); 537151497Sru 538151497Sru return ret; 539151497Sru} 540151497Sru 541151497Sru 542151497Srustatic int wpa_supplicant_ctrl_iface_tdls_setup( 543151497Sru struct wpa_supplicant *wpa_s, char *addr) 544151497Sru{ 545151497Sru u8 peer[ETH_ALEN]; 546151497Sru int ret; 547151497Sru 548151497Sru if (hwaddr_aton(addr, peer)) { 549151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid " 550151497Sru "address '%s'", addr); 551151497Sru return -1; 552151497Sru } 553151497Sru 554151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR, 555151497Sru MAC2STR(peer)); 556151497Sru 557151497Sru ret = wpa_tdls_reneg(wpa_s->wpa, peer); 558151497Sru if (ret) { 559151497Sru if (wpa_tdls_is_external_setup(wpa_s->wpa)) 560151497Sru ret = wpa_tdls_start(wpa_s->wpa, peer); 561151497Sru else 562151497Sru ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 563151497Sru } 564151497Sru 565151497Sru return ret; 566151497Sru} 567151497Sru 568151497Sru 569151497Srustatic int wpa_supplicant_ctrl_iface_tdls_teardown( 570151497Sru struct wpa_supplicant *wpa_s, char *addr) 571151497Sru{ 572151497Sru u8 peer[ETH_ALEN]; 573151497Sru 574151497Sru if (hwaddr_aton(addr, peer)) { 575151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid " 576151497Sru "address '%s'", addr); 577151497Sru return -1; 578151497Sru } 579151497Sru 580151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR, 581151497Sru MAC2STR(peer)); 582151497Sru 583151497Sru return wpa_tdls_teardown_link(wpa_s->wpa, peer, 584151497Sru WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 585151497Sru} 586151497Sru 587151497Sru#endif /* CONFIG_TDLS */ 588151497Sru 589151497Sru 590151497Sru#ifdef CONFIG_IEEE80211R 591151497Srustatic int wpa_supplicant_ctrl_iface_ft_ds( 592151497Sru struct wpa_supplicant *wpa_s, char *addr) 593151497Sru{ 594151497Sru u8 target_ap[ETH_ALEN]; 595151497Sru struct wpa_bss *bss; 596151497Sru const u8 *mdie; 597151497Sru 598151497Sru if (hwaddr_aton(addr, target_ap)) { 599151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 600151497Sru "address '%s'", addr); 601151497Sru return -1; 602151497Sru } 603151497Sru 604151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); 605151497Sru 606151497Sru bss = wpa_bss_get_bssid(wpa_s, target_ap); 607151497Sru if (bss) 608151497Sru mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 609151497Sru else 610151497Sru mdie = NULL; 611151497Sru 612151497Sru return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie); 613151497Sru} 614151497Sru#endif /* CONFIG_IEEE80211R */ 615151497Sru 616151497Sru 617151497Sru#ifdef CONFIG_WPS 618151497Srustatic int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, 619151497Sru char *cmd) 620151497Sru{ 621151497Sru u8 bssid[ETH_ALEN], *_bssid = bssid; 622151497Sru#ifdef CONFIG_P2P 623151497Sru u8 p2p_dev_addr[ETH_ALEN]; 624151497Sru#endif /* CONFIG_P2P */ 625151497Sru#ifdef CONFIG_AP 626151497Sru u8 *_p2p_dev_addr = NULL; 627151497Sru#endif /* CONFIG_AP */ 628151497Sru 629151497Sru if (cmd == NULL || os_strcmp(cmd, "any") == 0) { 630151497Sru _bssid = NULL; 631151497Sru#ifdef CONFIG_P2P 632151497Sru } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 633151497Sru if (hwaddr_aton(cmd + 13, p2p_dev_addr)) { 634151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid " 635151497Sru "P2P Device Address '%s'", 636151497Sru cmd + 13); 637151497Sru return -1; 638151497Sru } 639151497Sru _p2p_dev_addr = p2p_dev_addr; 640151497Sru#endif /* CONFIG_P2P */ 641151497Sru } else if (hwaddr_aton(cmd, bssid)) { 642151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", 643151497Sru cmd); 644151497Sru return -1; 645151497Sru } 646151497Sru 647151497Sru#ifdef CONFIG_AP 648151497Sru if (wpa_s->ap_iface) 649151497Sru return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr); 650151497Sru#endif /* CONFIG_AP */ 651151497Sru 652151497Sru return wpas_wps_start_pbc(wpa_s, _bssid, 0); 653151497Sru} 654151497Sru 655151497Sru 656151497Srustatic int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, 657151497Sru char *cmd, char *buf, 658151497Sru size_t buflen) 659151497Sru{ 660151497Sru u8 bssid[ETH_ALEN], *_bssid = bssid; 661151497Sru char *pin; 662151497Sru int ret; 663151497Sru 664151497Sru pin = os_strchr(cmd, ' '); 665151497Sru if (pin) 666151497Sru *pin++ = '\0'; 667151497Sru 668151497Sru if (os_strcmp(cmd, "any") == 0) 669151497Sru _bssid = NULL; 670151497Sru else if (os_strcmp(cmd, "get") == 0) { 671151497Sru ret = wps_generate_pin(); 672151497Sru goto done; 673151497Sru } else if (hwaddr_aton(cmd, bssid)) { 674151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'", 675151497Sru cmd); 676151497Sru return -1; 677151497Sru } 678151497Sru 679151497Sru#ifdef CONFIG_AP 680151497Sru if (wpa_s->ap_iface) { 681151497Sru int timeout = 0; 682151497Sru char *pos; 683151497Sru 684151497Sru if (pin) { 685151497Sru pos = os_strchr(pin, ' '); 686151497Sru if (pos) { 687151497Sru *pos++ = '\0'; 688151497Sru timeout = atoi(pos); 689151497Sru } 690151497Sru } 691151497Sru 692151497Sru return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin, 693151497Sru buf, buflen, timeout); 694151497Sru } 695151497Sru#endif /* CONFIG_AP */ 696151497Sru 697151497Sru if (pin) { 698151497Sru ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0, 699151497Sru DEV_PW_DEFAULT); 700151497Sru if (ret < 0) 701151497Sru return -1; 702151497Sru ret = os_snprintf(buf, buflen, "%s", pin); 703151497Sru if (ret < 0 || (size_t) ret >= buflen) 704151497Sru return -1; 705151497Sru return ret; 706151497Sru } 707151497Sru 708151497Sru ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT); 709151497Sru if (ret < 0) 710151497Sru return -1; 711151497Sru 712151497Srudone: 713151497Sru /* Return the generated PIN */ 714151497Sru ret = os_snprintf(buf, buflen, "%08d", ret); 715151497Sru if (ret < 0 || (size_t) ret >= buflen) 716151497Sru return -1; 717151497Sru return ret; 718151497Sru} 719151497Sru 720151497Sru 721151497Srustatic int wpa_supplicant_ctrl_iface_wps_check_pin( 722151497Sru struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 723151497Sru{ 724151497Sru char pin[9]; 725151497Sru size_t len; 726151497Sru char *pos; 727151497Sru int ret; 728151497Sru 729151497Sru wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 730151497Sru (u8 *) cmd, os_strlen(cmd)); 731151497Sru for (pos = cmd, len = 0; *pos != '\0'; pos++) { 732151497Sru if (*pos < '0' || *pos > '9') 733151497Sru continue; 734151497Sru pin[len++] = *pos; 735151497Sru if (len == 9) { 736151497Sru wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 737151497Sru return -1; 738151497Sru } 739151497Sru } 740151497Sru if (len != 4 && len != 8) { 741151497Sru wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 742151497Sru return -1; 743151497Sru } 744151497Sru pin[len] = '\0'; 745151497Sru 746151497Sru if (len == 8) { 747151497Sru unsigned int pin_val; 748151497Sru pin_val = atoi(pin); 749151497Sru if (!wps_pin_valid(pin_val)) { 750151497Sru wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 751151497Sru ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 752151497Sru if (ret < 0 || (size_t) ret >= buflen) 753151497Sru return -1; 754151497Sru return ret; 755151497Sru } 756151497Sru } 757151497Sru 758151497Sru ret = os_snprintf(buf, buflen, "%s", pin); 759151497Sru if (ret < 0 || (size_t) ret >= buflen) 760151497Sru return -1; 761151497Sru 762151497Sru return ret; 763151497Sru} 764151497Sru 765151497Sru 766151497Sru#ifdef CONFIG_WPS_NFC 767151497Sru 768151497Srustatic int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s, 769151497Sru char *cmd) 770151497Sru{ 771151497Sru u8 bssid[ETH_ALEN], *_bssid = bssid; 772151497Sru 773151497Sru if (cmd == NULL || cmd[0] == '\0') 774151497Sru _bssid = NULL; 775151497Sru else if (hwaddr_aton(cmd, bssid)) 776151497Sru return -1; 777151497Sru 778151497Sru return wpas_wps_start_nfc(wpa_s, _bssid); 779151497Sru} 780151497Sru 781151497Sru 782151497Srustatic int wpa_supplicant_ctrl_iface_wps_nfc_token( 783151497Sru struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 784151497Sru{ 785151497Sru int ndef; 786151497Sru struct wpabuf *buf; 787151497Sru int res; 788151497Sru 789151497Sru if (os_strcmp(cmd, "WPS") == 0) 790151497Sru ndef = 0; 791151497Sru else if (os_strcmp(cmd, "NDEF") == 0) 792151497Sru ndef = 1; 793151497Sru else 794151497Sru return -1; 795151497Sru 796151497Sru buf = wpas_wps_nfc_token(wpa_s, ndef); 797151497Sru if (buf == NULL) 798151497Sru return -1; 799151497Sru 800151497Sru res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 801151497Sru wpabuf_len(buf)); 802151497Sru reply[res++] = '\n'; 803151497Sru reply[res] = '\0'; 804151497Sru 805151497Sru wpabuf_free(buf); 806151497Sru 807151497Sru return res; 808151497Sru} 809151497Sru 810151497Sru 811151497Srustatic int wpa_supplicant_ctrl_iface_wps_nfc_tag_read( 812151497Sru struct wpa_supplicant *wpa_s, char *pos) 813151497Sru{ 814151497Sru size_t len; 815151497Sru struct wpabuf *buf; 816151497Sru int ret; 817151497Sru 818151497Sru len = os_strlen(pos); 819151497Sru if (len & 0x01) 820151497Sru return -1; 821151497Sru len /= 2; 822151497Sru 823151497Sru buf = wpabuf_alloc(len); 824151497Sru if (buf == NULL) 825151497Sru return -1; 826151497Sru if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 827151497Sru wpabuf_free(buf); 828151497Sru return -1; 829151497Sru } 830151497Sru 831151497Sru ret = wpas_wps_nfc_tag_read(wpa_s, buf); 832151497Sru wpabuf_free(buf); 833151497Sru 834151497Sru return ret; 835151497Sru} 836151497Sru 837151497Sru 838151497Srustatic int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s, 839151497Sru char *reply, size_t max_len) 840151497Sru{ 841151497Sru struct wpabuf *buf; 842151497Sru int res; 843151497Sru 844151497Sru buf = wpas_wps_nfc_handover_req(wpa_s); 845151497Sru if (buf == NULL) 846151497Sru return -1; 847151497Sru 848151497Sru res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 849151497Sru wpabuf_len(buf)); 850151497Sru reply[res++] = '\n'; 851151497Sru reply[res] = '\0'; 852151497Sru 853151497Sru wpabuf_free(buf); 854151497Sru 855151497Sru return res; 856151497Sru} 857151497Sru 858151497Sru 859151497Srustatic int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s, 860151497Sru char *cmd, char *reply, 861151497Sru size_t max_len) 862151497Sru{ 863151497Sru char *pos; 864151497Sru 865151497Sru pos = os_strchr(cmd, ' '); 866151497Sru if (pos == NULL) 867151497Sru return -1; 868151497Sru *pos++ = '\0'; 869151497Sru 870151497Sru if (os_strcmp(cmd, "NDEF") != 0) 871151497Sru return -1; 872151497Sru 873151497Sru if (os_strcmp(pos, "WPS") == 0) { 874151497Sru return wpas_ctrl_nfc_get_handover_req_wps(wpa_s, reply, 875151497Sru max_len); 876151497Sru } 877151497Sru 878151497Sru return -1; 879151497Sru} 880151497Sru 881151497Sru 882151497Srustatic int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s, 883151497Sru char *reply, size_t max_len) 884151497Sru{ 885151497Sru struct wpabuf *buf; 886151497Sru int res; 887151497Sru 888151497Sru buf = wpas_wps_nfc_handover_sel(wpa_s); 889151497Sru if (buf == NULL) 890151497Sru return -1; 891151497Sru 892151497Sru res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 893151497Sru wpabuf_len(buf)); 894151497Sru reply[res++] = '\n'; 895151497Sru reply[res] = '\0'; 896151497Sru 897151497Sru wpabuf_free(buf); 898151497Sru 899151497Sru return res; 900151497Sru} 901151497Sru 902151497Sru 903151497Srustatic int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s, 904151497Sru char *cmd, char *reply, 905151497Sru size_t max_len) 906151497Sru{ 907151497Sru char *pos; 908151497Sru 909151497Sru pos = os_strchr(cmd, ' '); 910151497Sru if (pos == NULL) 911151497Sru return -1; 912151497Sru *pos++ = '\0'; 913151497Sru 914151497Sru if (os_strcmp(cmd, "NDEF") != 0) 915151497Sru return -1; 916151497Sru 917151497Sru if (os_strcmp(pos, "WPS") == 0) { 918151497Sru return wpas_ctrl_nfc_get_handover_sel_wps(wpa_s, reply, 919151497Sru max_len); 920151497Sru } 921151497Sru 922151497Sru return -1; 923151497Sru} 924151497Sru 925151497Sru 926151497Srustatic int wpas_ctrl_nfc_rx_handover_req(struct wpa_supplicant *wpa_s, 927151497Sru char *cmd, char *reply, 928151497Sru size_t max_len) 929151497Sru{ 930151497Sru size_t len; 931151497Sru struct wpabuf *buf; 932151497Sru int ret; 933151497Sru 934151497Sru len = os_strlen(cmd); 935151497Sru if (len & 0x01) 936151497Sru return -1; 937151497Sru len /= 2; 938151497Sru 939151497Sru buf = wpabuf_alloc(len); 940151497Sru if (buf == NULL) 941151497Sru return -1; 942151497Sru if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) { 943151497Sru wpabuf_free(buf); 944151497Sru return -1; 945151497Sru } 946151497Sru 947151497Sru ret = wpas_wps_nfc_rx_handover_req(wpa_s, buf); 948151497Sru wpabuf_free(buf); 949151497Sru 950151497Sru return ret; 951151497Sru} 952151497Sru 953151497Sru 954151497Srustatic int wpas_ctrl_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s, 955151497Sru char *cmd) 956151497Sru{ 957151497Sru size_t len; 958151497Sru struct wpabuf *buf; 959151497Sru int ret; 960151497Sru 961151497Sru len = os_strlen(cmd); 962151497Sru if (len & 0x01) 963151497Sru return -1; 964151497Sru len /= 2; 965151497Sru 966151497Sru buf = wpabuf_alloc(len); 967151497Sru if (buf == NULL) 968151497Sru return -1; 969151497Sru if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) { 970151497Sru wpabuf_free(buf); 971151497Sru return -1; 972151497Sru } 973151497Sru 974151497Sru ret = wpas_wps_nfc_rx_handover_sel(wpa_s, buf); 975151497Sru wpabuf_free(buf); 976151497Sru 977151497Sru return ret; 978151497Sru} 979151497Sru 980151497Sru#endif /* CONFIG_WPS_NFC */ 981151497Sru 982151497Sru 983151497Srustatic int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s, 984151497Sru char *cmd) 985151497Sru{ 986151497Sru u8 bssid[ETH_ALEN]; 987151497Sru char *pin; 988151497Sru char *new_ssid; 989151497Sru char *new_auth; 990151497Sru char *new_encr; 991151497Sru char *new_key; 992151497Sru struct wps_new_ap_settings ap; 993151497Sru 994151497Sru pin = os_strchr(cmd, ' '); 995151497Sru if (pin == NULL) 996151497Sru return -1; 997151497Sru *pin++ = '\0'; 998151497Sru 999151497Sru if (hwaddr_aton(cmd, bssid)) { 1000151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'", 1001151497Sru cmd); 1002151497Sru return -1; 1003151497Sru } 1004151497Sru 1005151497Sru new_ssid = os_strchr(pin, ' '); 1006151497Sru if (new_ssid == NULL) 1007151497Sru return wpas_wps_start_reg(wpa_s, bssid, pin, NULL); 1008151497Sru *new_ssid++ = '\0'; 1009151497Sru 1010151497Sru new_auth = os_strchr(new_ssid, ' '); 1011151497Sru if (new_auth == NULL) 1012151497Sru return -1; 1013151497Sru *new_auth++ = '\0'; 1014151497Sru 1015151497Sru new_encr = os_strchr(new_auth, ' '); 1016151497Sru if (new_encr == NULL) 1017151497Sru return -1; 1018151497Sru *new_encr++ = '\0'; 1019151497Sru 1020151497Sru new_key = os_strchr(new_encr, ' '); 1021151497Sru if (new_key == NULL) 1022151497Sru return -1; 1023151497Sru *new_key++ = '\0'; 1024151497Sru 1025151497Sru os_memset(&ap, 0, sizeof(ap)); 1026151497Sru ap.ssid_hex = new_ssid; 1027151497Sru ap.auth = new_auth; 1028151497Sru ap.encr = new_encr; 1029151497Sru ap.key_hex = new_key; 1030151497Sru return wpas_wps_start_reg(wpa_s, bssid, pin, &ap); 1031151497Sru} 1032151497Sru 1033151497Sru 1034151497Sru#ifdef CONFIG_AP 1035151497Srustatic int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s, 1036151497Sru char *cmd, char *buf, 1037151497Sru size_t buflen) 1038151497Sru{ 1039151497Sru int timeout = 300; 1040151497Sru char *pos; 1041151497Sru const char *pin_txt; 1042151497Sru 1043151497Sru if (!wpa_s->ap_iface) 1044151497Sru return -1; 1045151497Sru 1046151497Sru pos = os_strchr(cmd, ' '); 1047151497Sru if (pos) 1048151497Sru *pos++ = '\0'; 1049151497Sru 1050151497Sru if (os_strcmp(cmd, "disable") == 0) { 1051151497Sru wpas_wps_ap_pin_disable(wpa_s); 1052151497Sru return os_snprintf(buf, buflen, "OK\n"); 1053151497Sru } 1054151497Sru 1055151497Sru if (os_strcmp(cmd, "random") == 0) { 1056151497Sru if (pos) 1057151497Sru timeout = atoi(pos); 1058151497Sru pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout); 1059151497Sru if (pin_txt == NULL) 1060151497Sru return -1; 1061151497Sru return os_snprintf(buf, buflen, "%s", pin_txt); 1062151497Sru } 1063151497Sru 1064151497Sru if (os_strcmp(cmd, "get") == 0) { 1065151497Sru pin_txt = wpas_wps_ap_pin_get(wpa_s); 1066151497Sru if (pin_txt == NULL) 1067151497Sru return -1; 1068151497Sru return os_snprintf(buf, buflen, "%s", pin_txt); 1069151497Sru } 1070151497Sru 1071151497Sru if (os_strcmp(cmd, "set") == 0) { 1072151497Sru char *pin; 1073151497Sru if (pos == NULL) 1074151497Sru return -1; 1075151497Sru pin = pos; 1076151497Sru pos = os_strchr(pos, ' '); 1077151497Sru if (pos) { 1078151497Sru *pos++ = '\0'; 1079151497Sru timeout = atoi(pos); 1080151497Sru } 1081151497Sru if (os_strlen(pin) > buflen) 1082151497Sru return -1; 1083151497Sru if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0) 1084151497Sru return -1; 1085151497Sru return os_snprintf(buf, buflen, "%s", pin); 1086151497Sru } 1087151497Sru 1088151497Sru return -1; 1089151497Sru} 1090151497Sru#endif /* CONFIG_AP */ 1091151497Sru 1092151497Sru 1093151497Sru#ifdef CONFIG_WPS_ER 1094151497Srustatic int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s, 1095151497Sru char *cmd) 1096151497Sru{ 1097151497Sru char *uuid = cmd, *pin, *pos; 1098151497Sru u8 addr_buf[ETH_ALEN], *addr = NULL; 1099151497Sru pin = os_strchr(uuid, ' '); 1100151497Sru if (pin == NULL) 1101151497Sru return -1; 1102151497Sru *pin++ = '\0'; 1103151497Sru pos = os_strchr(pin, ' '); 1104151497Sru if (pos) { 1105151497Sru *pos++ = '\0'; 1106151497Sru if (hwaddr_aton(pos, addr_buf) == 0) 1107151497Sru addr = addr_buf; 1108151497Sru } 1109151497Sru return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin); 1110151497Sru} 1111151497Sru 1112151497Sru 1113151497Srustatic int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s, 1114151497Sru char *cmd) 1115151497Sru{ 1116151497Sru char *uuid = cmd, *pin; 1117151497Sru pin = os_strchr(uuid, ' '); 1118151497Sru if (pin == NULL) 1119151497Sru return -1; 1120151497Sru *pin++ = '\0'; 1121151497Sru return wpas_wps_er_learn(wpa_s, uuid, pin); 1122151497Sru} 1123151497Sru 1124151497Sru 1125151497Srustatic int wpa_supplicant_ctrl_iface_wps_er_set_config( 1126151497Sru struct wpa_supplicant *wpa_s, char *cmd) 1127151497Sru{ 1128151497Sru char *uuid = cmd, *id; 1129151497Sru id = os_strchr(uuid, ' '); 1130151497Sru if (id == NULL) 1131151497Sru return -1; 1132151497Sru *id++ = '\0'; 1133151497Sru return wpas_wps_er_set_config(wpa_s, uuid, atoi(id)); 1134151497Sru} 1135151497Sru 1136151497Sru 1137151497Srustatic int wpa_supplicant_ctrl_iface_wps_er_config( 1138151497Sru struct wpa_supplicant *wpa_s, char *cmd) 1139151497Sru{ 1140151497Sru char *pin; 1141151497Sru char *new_ssid; 1142151497Sru char *new_auth; 1143151497Sru char *new_encr; 1144151497Sru char *new_key; 1145151497Sru struct wps_new_ap_settings ap; 1146151497Sru 1147151497Sru pin = os_strchr(cmd, ' '); 1148151497Sru if (pin == NULL) 1149151497Sru return -1; 1150151497Sru *pin++ = '\0'; 1151151497Sru 1152151497Sru new_ssid = os_strchr(pin, ' '); 1153151497Sru if (new_ssid == NULL) 1154151497Sru return -1; 1155151497Sru *new_ssid++ = '\0'; 1156151497Sru 1157151497Sru new_auth = os_strchr(new_ssid, ' '); 1158151497Sru if (new_auth == NULL) 1159151497Sru return -1; 1160151497Sru *new_auth++ = '\0'; 1161151497Sru 1162151497Sru new_encr = os_strchr(new_auth, ' '); 1163151497Sru if (new_encr == NULL) 1164151497Sru return -1; 1165151497Sru *new_encr++ = '\0'; 1166151497Sru 1167151497Sru new_key = os_strchr(new_encr, ' '); 1168151497Sru if (new_key == NULL) 1169151497Sru return -1; 1170151497Sru *new_key++ = '\0'; 1171151497Sru 1172151497Sru os_memset(&ap, 0, sizeof(ap)); 1173151497Sru ap.ssid_hex = new_ssid; 1174151497Sru ap.auth = new_auth; 1175151497Sru ap.encr = new_encr; 1176151497Sru ap.key_hex = new_key; 1177151497Sru return wpas_wps_er_config(wpa_s, cmd, pin, &ap); 1178151497Sru} 1179151497Sru 1180151497Sru 1181151497Sru#ifdef CONFIG_WPS_NFC 1182151497Srustatic int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 1183151497Sru struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 1184151497Sru{ 1185151497Sru int ndef; 1186151497Sru struct wpabuf *buf; 1187151497Sru int res; 1188151497Sru char *uuid; 1189151497Sru 1190151497Sru uuid = os_strchr(cmd, ' '); 1191151497Sru if (uuid == NULL) 1192151497Sru return -1; 1193151497Sru *uuid++ = '\0'; 1194151497Sru 1195151497Sru if (os_strcmp(cmd, "WPS") == 0) 1196151497Sru ndef = 0; 1197151497Sru else if (os_strcmp(cmd, "NDEF") == 0) 1198151497Sru ndef = 1; 1199151497Sru else 1200151497Sru return -1; 1201151497Sru 1202151497Sru buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid); 1203151497Sru if (buf == NULL) 1204151497Sru return -1; 1205151497Sru 1206151497Sru res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1207151497Sru wpabuf_len(buf)); 1208151497Sru reply[res++] = '\n'; 1209151497Sru reply[res] = '\0'; 1210151497Sru 1211151497Sru wpabuf_free(buf); 1212151497Sru 1213151497Sru return res; 1214151497Sru} 1215151497Sru#endif /* CONFIG_WPS_NFC */ 1216151497Sru#endif /* CONFIG_WPS_ER */ 1217151497Sru 1218151497Sru#endif /* CONFIG_WPS */ 1219151497Sru 1220151497Sru 1221151497Sru#ifdef CONFIG_IBSS_RSN 1222151497Srustatic int wpa_supplicant_ctrl_iface_ibss_rsn( 1223151497Sru struct wpa_supplicant *wpa_s, char *addr) 1224151497Sru{ 1225151497Sru u8 peer[ETH_ALEN]; 1226151497Sru 1227151497Sru if (hwaddr_aton(addr, peer)) { 1228151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid " 1229151497Sru "address '%s'", addr); 1230151497Sru return -1; 1231151497Sru } 1232151497Sru 1233151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR, 1234151497Sru MAC2STR(peer)); 1235151497Sru 1236151497Sru return ibss_rsn_start(wpa_s->ibss_rsn, peer); 1237151497Sru} 1238151497Sru#endif /* CONFIG_IBSS_RSN */ 1239151497Sru 1240151497Sru 1241151497Srustatic int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 1242151497Sru char *rsp) 1243151497Sru{ 1244151497Sru#ifdef IEEE8021X_EAPOL 1245151497Sru char *pos, *id_pos; 1246151497Sru int id; 1247151497Sru struct wpa_ssid *ssid; 1248151497Sru 1249151497Sru pos = os_strchr(rsp, '-'); 1250151497Sru if (pos == NULL) 1251151497Sru return -1; 1252151497Sru *pos++ = '\0'; 1253151497Sru id_pos = pos; 1254151497Sru pos = os_strchr(pos, ':'); 1255151497Sru if (pos == NULL) 1256151497Sru return -1; 1257151497Sru *pos++ = '\0'; 1258151497Sru id = atoi(id_pos); 1259151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 1260151497Sru wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 1261151497Sru (u8 *) pos, os_strlen(pos)); 1262151497Sru 1263151497Sru ssid = wpa_config_get_network(wpa_s->conf, id); 1264151497Sru if (ssid == NULL) { 1265151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 1266151497Sru "to update", id); 1267151497Sru return -1; 1268151497Sru } 1269151497Sru 1270151497Sru return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp, 1271151497Sru pos); 1272151497Sru#else /* IEEE8021X_EAPOL */ 1273151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 1274151497Sru return -1; 1275151497Sru#endif /* IEEE8021X_EAPOL */ 1276151497Sru} 1277151497Sru 1278151497Sru 1279151497Srustatic int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 1280151497Sru const char *params, 1281151497Sru char *buf, size_t buflen) 1282151497Sru{ 1283151497Sru char *pos, *end, tmp[30]; 1284151497Sru int res, verbose, wps, ret; 1285151497Sru 1286151497Sru verbose = os_strcmp(params, "-VERBOSE") == 0; 1287151497Sru wps = os_strcmp(params, "-WPS") == 0; 1288151497Sru pos = buf; 1289151497Sru end = buf + buflen; 1290151497Sru if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 1291151497Sru struct wpa_ssid *ssid = wpa_s->current_ssid; 1292151497Sru ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 1293151497Sru MAC2STR(wpa_s->bssid)); 1294151497Sru if (ret < 0 || ret >= end - pos) 1295151497Sru return pos - buf; 1296151497Sru pos += ret; 1297151497Sru if (ssid) { 1298151497Sru u8 *_ssid = ssid->ssid; 1299151497Sru size_t ssid_len = ssid->ssid_len; 1300151497Sru u8 ssid_buf[MAX_SSID_LEN]; 1301151497Sru if (ssid_len == 0) { 1302151497Sru int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 1303151497Sru if (_res < 0) 1304151497Sru ssid_len = 0; 1305151497Sru else 1306151497Sru ssid_len = _res; 1307151497Sru _ssid = ssid_buf; 1308151497Sru } 1309151497Sru ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 1310151497Sru wpa_ssid_txt(_ssid, ssid_len), 1311151497Sru ssid->id); 1312151497Sru if (ret < 0 || ret >= end - pos) 1313151497Sru return pos - buf; 1314151497Sru pos += ret; 1315151497Sru 1316151497Sru if (wps && ssid->passphrase && 1317151497Sru wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && 1318151497Sru (ssid->mode == WPAS_MODE_AP || 1319151497Sru ssid->mode == WPAS_MODE_P2P_GO)) { 1320151497Sru ret = os_snprintf(pos, end - pos, 1321151497Sru "passphrase=%s\n", 1322151497Sru ssid->passphrase); 1323151497Sru if (ret < 0 || ret >= end - pos) 1324151497Sru return pos - buf; 1325151497Sru pos += ret; 1326151497Sru } 1327151497Sru if (ssid->id_str) { 1328151497Sru ret = os_snprintf(pos, end - pos, 1329151497Sru "id_str=%s\n", 1330151497Sru ssid->id_str); 1331151497Sru if (ret < 0 || ret >= end - pos) 1332151497Sru return pos - buf; 1333151497Sru pos += ret; 1334151497Sru } 1335151497Sru 1336151497Sru switch (ssid->mode) { 1337151497Sru case WPAS_MODE_INFRA: 1338151497Sru ret = os_snprintf(pos, end - pos, 1339151497Sru "mode=station\n"); 1340151497Sru break; 1341151497Sru case WPAS_MODE_IBSS: 1342151497Sru ret = os_snprintf(pos, end - pos, 1343151497Sru "mode=IBSS\n"); 1344151497Sru break; 1345151497Sru case WPAS_MODE_AP: 1346151497Sru ret = os_snprintf(pos, end - pos, 1347151497Sru "mode=AP\n"); 1348151497Sru break; 1349151497Sru case WPAS_MODE_P2P_GO: 1350151497Sru ret = os_snprintf(pos, end - pos, 1351151497Sru "mode=P2P GO\n"); 1352151497Sru break; 1353151497Sru case WPAS_MODE_P2P_GROUP_FORMATION: 1354151497Sru ret = os_snprintf(pos, end - pos, 1355151497Sru "mode=P2P GO - group " 1356151497Sru "formation\n"); 1357151497Sru break; 1358151497Sru default: 1359151497Sru ret = 0; 1360151497Sru break; 1361151497Sru } 1362151497Sru if (ret < 0 || ret >= end - pos) 1363151497Sru return pos - buf; 1364151497Sru pos += ret; 1365151497Sru } 1366151497Sru 1367151497Sru#ifdef CONFIG_AP 1368151497Sru if (wpa_s->ap_iface) { 1369151497Sru pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, 1370151497Sru end - pos, 1371151497Sru verbose); 1372151497Sru } else 1373151497Sru#endif /* CONFIG_AP */ 1374151497Sru pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 1375151497Sru } 1376151497Sru ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 1377151497Sru wpa_supplicant_state_txt(wpa_s->wpa_state)); 1378151497Sru if (ret < 0 || ret >= end - pos) 1379151497Sru return pos - buf; 1380151497Sru pos += ret; 1381151497Sru 1382151497Sru if (wpa_s->l2 && 1383151497Sru l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 1384151497Sru ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 1385151497Sru if (ret < 0 || ret >= end - pos) 1386151497Sru return pos - buf; 1387151497Sru pos += ret; 1388151497Sru } 1389151497Sru 1390151497Sru#ifdef CONFIG_P2P 1391151497Sru if (wpa_s->global->p2p) { 1392151497Sru ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 1393151497Sru "\n", MAC2STR(wpa_s->global->p2p_dev_addr)); 1394151497Sru if (ret < 0 || ret >= end - pos) 1395151497Sru return pos - buf; 1396151497Sru pos += ret; 1397151497Sru } 1398151497Sru#endif /* CONFIG_P2P */ 1399151497Sru 1400151497Sru ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n", 1401151497Sru MAC2STR(wpa_s->own_addr)); 1402151497Sru if (ret < 0 || ret >= end - pos) 1403151497Sru return pos - buf; 1404151497Sru pos += ret; 1405151497Sru 1406151497Sru#ifdef CONFIG_HS20 1407151497Sru if (wpa_s->current_bss && 1408151497Sru wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE) && 1409151497Sru wpa_s->wpa_proto == WPA_PROTO_RSN && 1410151497Sru wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { 1411151497Sru ret = os_snprintf(pos, end - pos, "hs20=1\n"); 1412151497Sru if (ret < 0 || ret >= end - pos) 1413151497Sru return pos - buf; 1414151497Sru pos += ret; 1415151497Sru } 1416151497Sru 1417151497Sru if (wpa_s->current_ssid) { 1418151497Sru struct wpa_cred *cred; 1419151497Sru char *type; 1420151497Sru 1421151497Sru for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1422151497Sru if (wpa_s->current_ssid->parent_cred != cred) 1423151497Sru continue; 1424151497Sru if (!cred->domain) 1425151497Sru continue; 1426151497Sru 1427151497Sru ret = os_snprintf(pos, end - pos, "home_sp=%s\n", 1428151497Sru cred->domain); 1429151497Sru if (ret < 0 || ret >= end - pos) 1430151497Sru return pos - buf; 1431151497Sru pos += ret; 1432151497Sru 1433151497Sru if (wpa_s->current_bss == NULL || 1434151497Sru wpa_s->current_bss->anqp == NULL) 1435151497Sru res = -1; 1436151497Sru else 1437151497Sru res = interworking_home_sp_cred( 1438151497Sru wpa_s, cred, 1439151497Sru wpa_s->current_bss->anqp->domain_name); 1440151497Sru if (res > 0) 1441151497Sru type = "home"; 1442151497Sru else if (res == 0) 1443151497Sru type = "roaming"; 1444151497Sru else 1445151497Sru type = "unknown"; 1446151497Sru 1447151497Sru ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type); 1448151497Sru if (ret < 0 || ret >= end - pos) 1449151497Sru return pos - buf; 1450151497Sru pos += ret; 1451151497Sru 1452151497Sru break; 1453151497Sru } 1454151497Sru } 1455151497Sru#endif /* CONFIG_HS20 */ 1456151497Sru 1457151497Sru if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 1458151497Sru wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 1459151497Sru res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 1460151497Sru verbose); 1461151497Sru if (res >= 0) 1462151497Sru pos += res; 1463151497Sru } 1464151497Sru 1465151497Sru res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 1466151497Sru if (res >= 0) 1467151497Sru pos += res; 1468151497Sru 1469151497Sru return pos - buf; 1470151497Sru} 1471151497Sru 1472151497Sru 1473151497Srustatic int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 1474151497Sru char *cmd) 1475151497Sru{ 1476151497Sru char *pos; 1477151497Sru int id; 1478151497Sru struct wpa_ssid *ssid; 1479151497Sru u8 bssid[ETH_ALEN]; 1480151497Sru 1481151497Sru /* cmd: "<network id> <BSSID>" */ 1482151497Sru pos = os_strchr(cmd, ' '); 1483151497Sru if (pos == NULL) 1484151497Sru return -1; 1485151497Sru *pos++ = '\0'; 1486151497Sru id = atoi(cmd); 1487151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 1488151497Sru if (hwaddr_aton(pos, bssid)) { 1489151497Sru wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 1490151497Sru return -1; 1491151497Sru } 1492151497Sru 1493151497Sru ssid = wpa_config_get_network(wpa_s->conf, id); 1494151497Sru if (ssid == NULL) { 1495151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 1496151497Sru "to update", id); 1497151497Sru return -1; 1498151497Sru } 1499151497Sru 1500151497Sru os_memcpy(ssid->bssid, bssid, ETH_ALEN); 1501151497Sru ssid->bssid_set = !is_zero_ether_addr(bssid); 1502151497Sru 1503151497Sru return 0; 1504151497Sru} 1505151497Sru 1506151497Sru 1507151497Srustatic int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s, 1508151497Sru char *cmd, char *buf, 1509151497Sru size_t buflen) 1510151497Sru{ 1511151497Sru u8 bssid[ETH_ALEN]; 1512151497Sru struct wpa_blacklist *e; 1513151497Sru char *pos, *end; 1514151497Sru int ret; 1515151497Sru 1516151497Sru /* cmd: "BLACKLIST [<BSSID>]" */ 1517151497Sru if (*cmd == '\0') { 1518151497Sru pos = buf; 1519151497Sru end = buf + buflen; 1520151497Sru e = wpa_s->blacklist; 1521151497Sru while (e) { 1522151497Sru ret = os_snprintf(pos, end - pos, MACSTR "\n", 1523151497Sru MAC2STR(e->bssid)); 1524151497Sru if (ret < 0 || ret >= end - pos) 1525151497Sru return pos - buf; 1526151497Sru pos += ret; 1527151497Sru e = e->next; 1528151497Sru } 1529151497Sru return pos - buf; 1530151497Sru } 1531151497Sru 1532151497Sru cmd++; 1533151497Sru if (os_strncmp(cmd, "clear", 5) == 0) { 1534151497Sru wpa_blacklist_clear(wpa_s); 1535151497Sru os_memcpy(buf, "OK\n", 3); 1536151497Sru return 3; 1537151497Sru } 1538151497Sru 1539151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd); 1540151497Sru if (hwaddr_aton(cmd, bssid)) { 1541151497Sru wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd); 1542151497Sru return -1; 1543151497Sru } 1544151497Sru 1545151497Sru /* 1546151497Sru * Add the BSSID twice, so its count will be 2, causing it to be 1547151497Sru * skipped when processing scan results. 1548151497Sru */ 1549151497Sru ret = wpa_blacklist_add(wpa_s, bssid); 1550151497Sru if (ret != 0) 1551151497Sru return -1; 1552151497Sru ret = wpa_blacklist_add(wpa_s, bssid); 1553151497Sru if (ret != 0) 1554151497Sru return -1; 1555151497Sru os_memcpy(buf, "OK\n", 3); 1556151497Sru return 3; 1557151497Sru} 1558151497Sru 1559151497Sru 1560151497Sruextern int wpa_debug_level; 1561151497Sruextern int wpa_debug_timestamp; 1562151497Sru 1563static const char * debug_level_str(int level) 1564{ 1565 switch (level) { 1566 case MSG_EXCESSIVE: 1567 return "EXCESSIVE"; 1568 case MSG_MSGDUMP: 1569 return "MSGDUMP"; 1570 case MSG_DEBUG: 1571 return "DEBUG"; 1572 case MSG_INFO: 1573 return "INFO"; 1574 case MSG_WARNING: 1575 return "WARNING"; 1576 case MSG_ERROR: 1577 return "ERROR"; 1578 default: 1579 return "?"; 1580 } 1581} 1582 1583 1584static int str_to_debug_level(const char *s) 1585{ 1586 if (os_strcasecmp(s, "EXCESSIVE") == 0) 1587 return MSG_EXCESSIVE; 1588 if (os_strcasecmp(s, "MSGDUMP") == 0) 1589 return MSG_MSGDUMP; 1590 if (os_strcasecmp(s, "DEBUG") == 0) 1591 return MSG_DEBUG; 1592 if (os_strcasecmp(s, "INFO") == 0) 1593 return MSG_INFO; 1594 if (os_strcasecmp(s, "WARNING") == 0) 1595 return MSG_WARNING; 1596 if (os_strcasecmp(s, "ERROR") == 0) 1597 return MSG_ERROR; 1598 return -1; 1599} 1600 1601 1602static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s, 1603 char *cmd, char *buf, 1604 size_t buflen) 1605{ 1606 char *pos, *end, *stamp; 1607 int ret; 1608 1609 if (cmd == NULL) { 1610 return -1; 1611 } 1612 1613 /* cmd: "LOG_LEVEL [<level>]" */ 1614 if (*cmd == '\0') { 1615 pos = buf; 1616 end = buf + buflen; 1617 ret = os_snprintf(pos, end - pos, "Current level: %s\n" 1618 "Timestamp: %d\n", 1619 debug_level_str(wpa_debug_level), 1620 wpa_debug_timestamp); 1621 if (ret < 0 || ret >= end - pos) 1622 ret = 0; 1623 1624 return ret; 1625 } 1626 1627 while (*cmd == ' ') 1628 cmd++; 1629 1630 stamp = os_strchr(cmd, ' '); 1631 if (stamp) { 1632 *stamp++ = '\0'; 1633 while (*stamp == ' ') { 1634 stamp++; 1635 } 1636 } 1637 1638 if (cmd && os_strlen(cmd)) { 1639 int level = str_to_debug_level(cmd); 1640 if (level < 0) 1641 return -1; 1642 wpa_debug_level = level; 1643 } 1644 1645 if (stamp && os_strlen(stamp)) 1646 wpa_debug_timestamp = atoi(stamp); 1647 1648 os_memcpy(buf, "OK\n", 3); 1649 return 3; 1650} 1651 1652 1653static int wpa_supplicant_ctrl_iface_list_networks( 1654 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1655{ 1656 char *pos, *end; 1657 struct wpa_ssid *ssid; 1658 int ret; 1659 1660 pos = buf; 1661 end = buf + buflen; 1662 ret = os_snprintf(pos, end - pos, 1663 "network id / ssid / bssid / flags\n"); 1664 if (ret < 0 || ret >= end - pos) 1665 return pos - buf; 1666 pos += ret; 1667 1668 ssid = wpa_s->conf->ssid; 1669 while (ssid) { 1670 ret = os_snprintf(pos, end - pos, "%d\t%s", 1671 ssid->id, 1672 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 1673 if (ret < 0 || ret >= end - pos) 1674 return pos - buf; 1675 pos += ret; 1676 if (ssid->bssid_set) { 1677 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 1678 MAC2STR(ssid->bssid)); 1679 } else { 1680 ret = os_snprintf(pos, end - pos, "\tany"); 1681 } 1682 if (ret < 0 || ret >= end - pos) 1683 return pos - buf; 1684 pos += ret; 1685 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s", 1686 ssid == wpa_s->current_ssid ? 1687 "[CURRENT]" : "", 1688 ssid->disabled ? "[DISABLED]" : "", 1689 ssid->disabled_until.sec ? 1690 "[TEMP-DISABLED]" : "", 1691 ssid->disabled == 2 ? "[P2P-PERSISTENT]" : 1692 ""); 1693 if (ret < 0 || ret >= end - pos) 1694 return pos - buf; 1695 pos += ret; 1696 ret = os_snprintf(pos, end - pos, "\n"); 1697 if (ret < 0 || ret >= end - pos) 1698 return pos - buf; 1699 pos += ret; 1700 1701 ssid = ssid->next; 1702 } 1703 1704 return pos - buf; 1705} 1706 1707 1708static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 1709{ 1710 int first = 1, ret; 1711 ret = os_snprintf(pos, end - pos, "-"); 1712 if (ret < 0 || ret >= end - pos) 1713 return pos; 1714 pos += ret; 1715 if (cipher & WPA_CIPHER_NONE) { 1716 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+"); 1717 if (ret < 0 || ret >= end - pos) 1718 return pos; 1719 pos += ret; 1720 first = 0; 1721 } 1722 if (cipher & WPA_CIPHER_WEP40) { 1723 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+"); 1724 if (ret < 0 || ret >= end - pos) 1725 return pos; 1726 pos += ret; 1727 first = 0; 1728 } 1729 if (cipher & WPA_CIPHER_WEP104) { 1730 ret = os_snprintf(pos, end - pos, "%sWEP104", 1731 first ? "" : "+"); 1732 if (ret < 0 || ret >= end - pos) 1733 return pos; 1734 pos += ret; 1735 first = 0; 1736 } 1737 if (cipher & WPA_CIPHER_TKIP) { 1738 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+"); 1739 if (ret < 0 || ret >= end - pos) 1740 return pos; 1741 pos += ret; 1742 first = 0; 1743 } 1744 if (cipher & WPA_CIPHER_CCMP) { 1745 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+"); 1746 if (ret < 0 || ret >= end - pos) 1747 return pos; 1748 pos += ret; 1749 first = 0; 1750 } 1751 if (cipher & WPA_CIPHER_GCMP) { 1752 ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : "+"); 1753 if (ret < 0 || ret >= end - pos) 1754 return pos; 1755 pos += ret; 1756 first = 0; 1757 } 1758 return pos; 1759} 1760 1761 1762static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 1763 const u8 *ie, size_t ie_len) 1764{ 1765 struct wpa_ie_data data; 1766 int first, ret; 1767 1768 ret = os_snprintf(pos, end - pos, "[%s-", proto); 1769 if (ret < 0 || ret >= end - pos) 1770 return pos; 1771 pos += ret; 1772 1773 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 1774 ret = os_snprintf(pos, end - pos, "?]"); 1775 if (ret < 0 || ret >= end - pos) 1776 return pos; 1777 pos += ret; 1778 return pos; 1779 } 1780 1781 first = 1; 1782 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 1783 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+"); 1784 if (ret < 0 || ret >= end - pos) 1785 return pos; 1786 pos += ret; 1787 first = 0; 1788 } 1789 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 1790 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+"); 1791 if (ret < 0 || ret >= end - pos) 1792 return pos; 1793 pos += ret; 1794 first = 0; 1795 } 1796 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 1797 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+"); 1798 if (ret < 0 || ret >= end - pos) 1799 return pos; 1800 pos += ret; 1801 first = 0; 1802 } 1803#ifdef CONFIG_IEEE80211R 1804 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 1805 ret = os_snprintf(pos, end - pos, "%sFT/EAP", 1806 first ? "" : "+"); 1807 if (ret < 0 || ret >= end - pos) 1808 return pos; 1809 pos += ret; 1810 first = 0; 1811 } 1812 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) { 1813 ret = os_snprintf(pos, end - pos, "%sFT/PSK", 1814 first ? "" : "+"); 1815 if (ret < 0 || ret >= end - pos) 1816 return pos; 1817 pos += ret; 1818 first = 0; 1819 } 1820#endif /* CONFIG_IEEE80211R */ 1821#ifdef CONFIG_IEEE80211W 1822 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 1823 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", 1824 first ? "" : "+"); 1825 if (ret < 0 || ret >= end - pos) 1826 return pos; 1827 pos += ret; 1828 first = 0; 1829 } 1830 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 1831 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", 1832 first ? "" : "+"); 1833 if (ret < 0 || ret >= end - pos) 1834 return pos; 1835 pos += ret; 1836 first = 0; 1837 } 1838#endif /* CONFIG_IEEE80211W */ 1839 1840 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 1841 1842 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 1843 ret = os_snprintf(pos, end - pos, "-preauth"); 1844 if (ret < 0 || ret >= end - pos) 1845 return pos; 1846 pos += ret; 1847 } 1848 1849 ret = os_snprintf(pos, end - pos, "]"); 1850 if (ret < 0 || ret >= end - pos) 1851 return pos; 1852 pos += ret; 1853 1854 return pos; 1855} 1856 1857 1858#ifdef CONFIG_WPS 1859static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s, 1860 char *pos, char *end, 1861 struct wpabuf *wps_ie) 1862{ 1863 int ret; 1864 const char *txt; 1865 1866 if (wps_ie == NULL) 1867 return pos; 1868 if (wps_is_selected_pbc_registrar(wps_ie)) 1869 txt = "[WPS-PBC]"; 1870#ifdef CONFIG_WPS2 1871 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0)) 1872 txt = "[WPS-AUTH]"; 1873#endif /* CONFIG_WPS2 */ 1874 else if (wps_is_selected_pin_registrar(wps_ie)) 1875 txt = "[WPS-PIN]"; 1876 else 1877 txt = "[WPS]"; 1878 1879 ret = os_snprintf(pos, end - pos, "%s", txt); 1880 if (ret >= 0 && ret < end - pos) 1881 pos += ret; 1882 wpabuf_free(wps_ie); 1883 return pos; 1884} 1885#endif /* CONFIG_WPS */ 1886 1887 1888static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s, 1889 char *pos, char *end, 1890 const struct wpa_bss *bss) 1891{ 1892#ifdef CONFIG_WPS 1893 struct wpabuf *wps_ie; 1894 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 1895 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie); 1896#else /* CONFIG_WPS */ 1897 return pos; 1898#endif /* CONFIG_WPS */ 1899} 1900 1901 1902/* Format one result on one text line into a buffer. */ 1903static int wpa_supplicant_ctrl_iface_scan_result( 1904 struct wpa_supplicant *wpa_s, 1905 const struct wpa_bss *bss, char *buf, size_t buflen) 1906{ 1907 char *pos, *end; 1908 int ret; 1909 const u8 *ie, *ie2, *p2p; 1910 1911 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); 1912 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN && 1913 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 1914 0) 1915 return 0; /* Do not show P2P listen discovery results here */ 1916 1917 pos = buf; 1918 end = buf + buflen; 1919 1920 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 1921 MAC2STR(bss->bssid), bss->freq, bss->level); 1922 if (ret < 0 || ret >= end - pos) 1923 return -1; 1924 pos += ret; 1925 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 1926 if (ie) 1927 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 1928 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 1929 if (ie2) 1930 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 1931 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 1932 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 1933 ret = os_snprintf(pos, end - pos, "[WEP]"); 1934 if (ret < 0 || ret >= end - pos) 1935 return -1; 1936 pos += ret; 1937 } 1938 if (bss->caps & IEEE80211_CAP_IBSS) { 1939 ret = os_snprintf(pos, end - pos, "[IBSS]"); 1940 if (ret < 0 || ret >= end - pos) 1941 return -1; 1942 pos += ret; 1943 } 1944 if (bss->caps & IEEE80211_CAP_ESS) { 1945 ret = os_snprintf(pos, end - pos, "[ESS]"); 1946 if (ret < 0 || ret >= end - pos) 1947 return -1; 1948 pos += ret; 1949 } 1950 if (p2p) { 1951 ret = os_snprintf(pos, end - pos, "[P2P]"); 1952 if (ret < 0 || ret >= end - pos) 1953 return -1; 1954 pos += ret; 1955 } 1956#ifdef CONFIG_HS20 1957 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) { 1958 ret = os_snprintf(pos, end - pos, "[HS20]"); 1959 if (ret < 0 || ret >= end - pos) 1960 return -1; 1961 pos += ret; 1962 } 1963#endif /* CONFIG_HS20 */ 1964 1965 ret = os_snprintf(pos, end - pos, "\t%s", 1966 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 1967 if (ret < 0 || ret >= end - pos) 1968 return -1; 1969 pos += ret; 1970 1971 ret = os_snprintf(pos, end - pos, "\n"); 1972 if (ret < 0 || ret >= end - pos) 1973 return -1; 1974 pos += ret; 1975 1976 return pos - buf; 1977} 1978 1979 1980static int wpa_supplicant_ctrl_iface_scan_results( 1981 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1982{ 1983 char *pos, *end; 1984 struct wpa_bss *bss; 1985 int ret; 1986 1987 pos = buf; 1988 end = buf + buflen; 1989 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 1990 "flags / ssid\n"); 1991 if (ret < 0 || ret >= end - pos) 1992 return pos - buf; 1993 pos += ret; 1994 1995 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 1996 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos, 1997 end - pos); 1998 if (ret < 0 || ret >= end - pos) 1999 return pos - buf; 2000 pos += ret; 2001 } 2002 2003 return pos - buf; 2004} 2005 2006 2007static int wpa_supplicant_ctrl_iface_select_network( 2008 struct wpa_supplicant *wpa_s, char *cmd) 2009{ 2010 int id; 2011 struct wpa_ssid *ssid; 2012 2013 /* cmd: "<network id>" or "any" */ 2014 if (os_strcmp(cmd, "any") == 0) { 2015 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 2016 ssid = NULL; 2017 } else { 2018 id = atoi(cmd); 2019 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 2020 2021 ssid = wpa_config_get_network(wpa_s->conf, id); 2022 if (ssid == NULL) { 2023 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 2024 "network id=%d", id); 2025 return -1; 2026 } 2027 if (ssid->disabled == 2) { 2028 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 2029 "SELECT_NETWORK with persistent P2P group"); 2030 return -1; 2031 } 2032 } 2033 2034 wpa_supplicant_select_network(wpa_s, ssid); 2035 2036 return 0; 2037} 2038 2039 2040static int wpa_supplicant_ctrl_iface_enable_network( 2041 struct wpa_supplicant *wpa_s, char *cmd) 2042{ 2043 int id; 2044 struct wpa_ssid *ssid; 2045 2046 /* cmd: "<network id>" or "all" */ 2047 if (os_strcmp(cmd, "all") == 0) { 2048 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 2049 ssid = NULL; 2050 } else { 2051 id = atoi(cmd); 2052 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 2053 2054 ssid = wpa_config_get_network(wpa_s->conf, id); 2055 if (ssid == NULL) { 2056 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 2057 "network id=%d", id); 2058 return -1; 2059 } 2060 if (ssid->disabled == 2) { 2061 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 2062 "ENABLE_NETWORK with persistent P2P group"); 2063 return -1; 2064 } 2065 2066 if (os_strstr(cmd, " no-connect")) { 2067 ssid->disabled = 0; 2068 return 0; 2069 } 2070 } 2071 wpa_supplicant_enable_network(wpa_s, ssid); 2072 2073 return 0; 2074} 2075 2076 2077static int wpa_supplicant_ctrl_iface_disable_network( 2078 struct wpa_supplicant *wpa_s, char *cmd) 2079{ 2080 int id; 2081 struct wpa_ssid *ssid; 2082 2083 /* cmd: "<network id>" or "all" */ 2084 if (os_strcmp(cmd, "all") == 0) { 2085 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 2086 ssid = NULL; 2087 } else { 2088 id = atoi(cmd); 2089 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 2090 2091 ssid = wpa_config_get_network(wpa_s->conf, id); 2092 if (ssid == NULL) { 2093 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 2094 "network id=%d", id); 2095 return -1; 2096 } 2097 if (ssid->disabled == 2) { 2098 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 2099 "DISABLE_NETWORK with persistent P2P " 2100 "group"); 2101 return -1; 2102 } 2103 } 2104 wpa_supplicant_disable_network(wpa_s, ssid); 2105 2106 return 0; 2107} 2108 2109 2110static int wpa_supplicant_ctrl_iface_add_network( 2111 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 2112{ 2113 struct wpa_ssid *ssid; 2114 int ret; 2115 2116 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 2117 2118 ssid = wpa_config_add_network(wpa_s->conf); 2119 if (ssid == NULL) 2120 return -1; 2121 2122 wpas_notify_network_added(wpa_s, ssid); 2123 2124 ssid->disabled = 1; 2125 wpa_config_set_network_defaults(ssid); 2126 2127 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 2128 if (ret < 0 || (size_t) ret >= buflen) 2129 return -1; 2130 return ret; 2131} 2132 2133 2134static int wpa_supplicant_ctrl_iface_remove_network( 2135 struct wpa_supplicant *wpa_s, char *cmd) 2136{ 2137 int id; 2138 struct wpa_ssid *ssid; 2139 2140 /* cmd: "<network id>" or "all" */ 2141 if (os_strcmp(cmd, "all") == 0) { 2142 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 2143 ssid = wpa_s->conf->ssid; 2144 while (ssid) { 2145 struct wpa_ssid *remove_ssid = ssid; 2146 id = ssid->id; 2147 ssid = ssid->next; 2148 wpas_notify_network_removed(wpa_s, remove_ssid); 2149 wpa_config_remove_network(wpa_s->conf, id); 2150 } 2151 eapol_sm_invalidate_cached_session(wpa_s->eapol); 2152 if (wpa_s->current_ssid) { 2153#ifdef CONFIG_SME 2154 wpa_s->sme.prev_bssid_set = 0; 2155#endif /* CONFIG_SME */ 2156 wpa_sm_set_config(wpa_s->wpa, NULL); 2157 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 2158 wpa_supplicant_deauthenticate( 2159 wpa_s, WLAN_REASON_DEAUTH_LEAVING); 2160 } 2161 return 0; 2162 } 2163 2164 id = atoi(cmd); 2165 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 2166 2167 ssid = wpa_config_get_network(wpa_s->conf, id); 2168 if (ssid) 2169 wpas_notify_network_removed(wpa_s, ssid); 2170 if (ssid == NULL) { 2171 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 2172 "id=%d", id); 2173 return -1; 2174 } 2175 2176 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) { 2177#ifdef CONFIG_SME 2178 wpa_s->sme.prev_bssid_set = 0; 2179#endif /* CONFIG_SME */ 2180 /* 2181 * Invalidate the EAP session cache if the current or 2182 * previously used network is removed. 2183 */ 2184 eapol_sm_invalidate_cached_session(wpa_s->eapol); 2185 } 2186 2187 if (ssid == wpa_s->current_ssid) { 2188 wpa_sm_set_config(wpa_s->wpa, NULL); 2189 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 2190 2191 wpa_supplicant_deauthenticate(wpa_s, 2192 WLAN_REASON_DEAUTH_LEAVING); 2193 } 2194 2195 if (wpa_config_remove_network(wpa_s->conf, id) < 0) { 2196 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the " 2197 "network id=%d", id); 2198 return -1; 2199 } 2200 2201 return 0; 2202} 2203 2204 2205static int wpa_supplicant_ctrl_iface_set_network( 2206 struct wpa_supplicant *wpa_s, char *cmd) 2207{ 2208 int id; 2209 struct wpa_ssid *ssid; 2210 char *name, *value; 2211 2212 /* cmd: "<network id> <variable name> <value>" */ 2213 name = os_strchr(cmd, ' '); 2214 if (name == NULL) 2215 return -1; 2216 *name++ = '\0'; 2217 2218 value = os_strchr(name, ' '); 2219 if (value == NULL) 2220 return -1; 2221 *value++ = '\0'; 2222 2223 id = atoi(cmd); 2224 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 2225 id, name); 2226 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 2227 (u8 *) value, os_strlen(value)); 2228 2229 ssid = wpa_config_get_network(wpa_s->conf, id); 2230 if (ssid == NULL) { 2231 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 2232 "id=%d", id); 2233 return -1; 2234 } 2235 2236 if (wpa_config_set(ssid, name, value, 0) < 0) { 2237 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 2238 "variable '%s'", name); 2239 return -1; 2240 } 2241 2242 if (os_strcmp(name, "bssid") != 0 && 2243 os_strcmp(name, "priority") != 0) 2244 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 2245 2246 if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) { 2247 /* 2248 * Invalidate the EAP session cache if anything in the current 2249 * or previously used configuration changes. 2250 */ 2251 eapol_sm_invalidate_cached_session(wpa_s->eapol); 2252 } 2253 2254 if ((os_strcmp(name, "psk") == 0 && 2255 value[0] == '"' && ssid->ssid_len) || 2256 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 2257 wpa_config_update_psk(ssid); 2258 else if (os_strcmp(name, "priority") == 0) 2259 wpa_config_update_prio_list(wpa_s->conf); 2260 2261 return 0; 2262} 2263 2264 2265static int wpa_supplicant_ctrl_iface_get_network( 2266 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 2267{ 2268 int id; 2269 size_t res; 2270 struct wpa_ssid *ssid; 2271 char *name, *value; 2272 2273 /* cmd: "<network id> <variable name>" */ 2274 name = os_strchr(cmd, ' '); 2275 if (name == NULL || buflen == 0) 2276 return -1; 2277 *name++ = '\0'; 2278 2279 id = atoi(cmd); 2280 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 2281 id, name); 2282 2283 ssid = wpa_config_get_network(wpa_s->conf, id); 2284 if (ssid == NULL) { 2285 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 2286 "id=%d", id); 2287 return -1; 2288 } 2289 2290 value = wpa_config_get_no_key(ssid, name); 2291 if (value == NULL) { 2292 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 2293 "variable '%s'", name); 2294 return -1; 2295 } 2296 2297 res = os_strlcpy(buf, value, buflen); 2298 if (res >= buflen) { 2299 os_free(value); 2300 return -1; 2301 } 2302 2303 os_free(value); 2304 2305 return res; 2306} 2307 2308 2309static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s, 2310 char *buf, size_t buflen) 2311{ 2312 char *pos, *end; 2313 struct wpa_cred *cred; 2314 int ret; 2315 2316 pos = buf; 2317 end = buf + buflen; 2318 ret = os_snprintf(pos, end - pos, 2319 "cred id / realm / username / domain / imsi\n"); 2320 if (ret < 0 || ret >= end - pos) 2321 return pos - buf; 2322 pos += ret; 2323 2324 cred = wpa_s->conf->cred; 2325 while (cred) { 2326 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n", 2327 cred->id, cred->realm ? cred->realm : "", 2328 cred->username ? cred->username : "", 2329 cred->domain ? cred->domain : "", 2330 cred->imsi ? cred->imsi : ""); 2331 if (ret < 0 || ret >= end - pos) 2332 return pos - buf; 2333 pos += ret; 2334 2335 cred = cred->next; 2336 } 2337 2338 return pos - buf; 2339} 2340 2341 2342static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s, 2343 char *buf, size_t buflen) 2344{ 2345 struct wpa_cred *cred; 2346 int ret; 2347 2348 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED"); 2349 2350 cred = wpa_config_add_cred(wpa_s->conf); 2351 if (cred == NULL) 2352 return -1; 2353 2354 ret = os_snprintf(buf, buflen, "%d\n", cred->id); 2355 if (ret < 0 || (size_t) ret >= buflen) 2356 return -1; 2357 return ret; 2358} 2359 2360 2361static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s, 2362 struct wpa_cred *cred) 2363{ 2364 struct wpa_ssid *ssid; 2365 char str[20]; 2366 2367 if (cred == NULL || wpa_config_remove_cred(wpa_s->conf, cred->id) < 0) { 2368 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred"); 2369 return -1; 2370 } 2371 2372 /* Remove any network entry created based on the removed credential */ 2373 ssid = wpa_s->conf->ssid; 2374 while (ssid) { 2375 if (ssid->parent_cred == cred) { 2376 wpa_printf(MSG_DEBUG, "Remove network id %d since it " 2377 "used the removed credential", ssid->id); 2378 os_snprintf(str, sizeof(str), "%d", ssid->id); 2379 ssid = ssid->next; 2380 wpa_supplicant_ctrl_iface_remove_network(wpa_s, str); 2381 } else 2382 ssid = ssid->next; 2383 } 2384 2385 return 0; 2386} 2387 2388 2389static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, 2390 char *cmd) 2391{ 2392 int id; 2393 struct wpa_cred *cred, *prev; 2394 2395 /* cmd: "<cred id>", "all", or "sp_fqdn=<FQDN>" */ 2396 if (os_strcmp(cmd, "all") == 0) { 2397 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all"); 2398 cred = wpa_s->conf->cred; 2399 while (cred) { 2400 prev = cred; 2401 cred = cred->next; 2402 wpas_ctrl_remove_cred(wpa_s, prev); 2403 } 2404 return 0; 2405 } 2406 2407 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) { 2408 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'", 2409 cmd + 8); 2410 cred = wpa_s->conf->cred; 2411 while (cred) { 2412 prev = cred; 2413 cred = cred->next; 2414 if (prev->domain && 2415 os_strcmp(prev->domain, cmd + 8) == 0) 2416 wpas_ctrl_remove_cred(wpa_s, prev); 2417 } 2418 return 0; 2419 } 2420 2421 id = atoi(cmd); 2422 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id); 2423 2424 cred = wpa_config_get_cred(wpa_s->conf, id); 2425 return wpas_ctrl_remove_cred(wpa_s, cred); 2426} 2427 2428 2429static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s, 2430 char *cmd) 2431{ 2432 int id; 2433 struct wpa_cred *cred; 2434 char *name, *value; 2435 2436 /* cmd: "<cred id> <variable name> <value>" */ 2437 name = os_strchr(cmd, ' '); 2438 if (name == NULL) 2439 return -1; 2440 *name++ = '\0'; 2441 2442 value = os_strchr(name, ' '); 2443 if (value == NULL) 2444 return -1; 2445 *value++ = '\0'; 2446 2447 id = atoi(cmd); 2448 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'", 2449 id, name); 2450 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 2451 (u8 *) value, os_strlen(value)); 2452 2453 cred = wpa_config_get_cred(wpa_s->conf, id); 2454 if (cred == NULL) { 2455 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 2456 id); 2457 return -1; 2458 } 2459 2460 if (wpa_config_set_cred(cred, name, value, 0) < 0) { 2461 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred " 2462 "variable '%s'", name); 2463 return -1; 2464 } 2465 2466 return 0; 2467} 2468 2469 2470#ifndef CONFIG_NO_CONFIG_WRITE 2471static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 2472{ 2473 int ret; 2474 2475 if (!wpa_s->conf->update_config) { 2476 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 2477 "to update configuration (update_config=0)"); 2478 return -1; 2479 } 2480 2481 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 2482 if (ret) { 2483 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 2484 "update configuration"); 2485 } else { 2486 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 2487 " updated"); 2488 } 2489 2490 return ret; 2491} 2492#endif /* CONFIG_NO_CONFIG_WRITE */ 2493 2494 2495static int ctrl_iface_get_capability_pairwise(int res, char *strict, 2496 struct wpa_driver_capa *capa, 2497 char *buf, size_t buflen) 2498{ 2499 int ret, first = 1; 2500 char *pos, *end; 2501 size_t len; 2502 2503 pos = buf; 2504 end = pos + buflen; 2505 2506 if (res < 0) { 2507 if (strict) 2508 return 0; 2509 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 2510 if (len >= buflen) 2511 return -1; 2512 return len; 2513 } 2514 2515 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 2516 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 2517 if (ret < 0 || ret >= end - pos) 2518 return pos - buf; 2519 pos += ret; 2520 first = 0; 2521 } 2522 2523 if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) { 2524 ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " "); 2525 if (ret < 0 || ret >= end - pos) 2526 return pos - buf; 2527 pos += ret; 2528 first = 0; 2529 } 2530 2531 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 2532 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 2533 if (ret < 0 || ret >= end - pos) 2534 return pos - buf; 2535 pos += ret; 2536 first = 0; 2537 } 2538 2539 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 2540 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " "); 2541 if (ret < 0 || ret >= end - pos) 2542 return pos - buf; 2543 pos += ret; 2544 first = 0; 2545 } 2546 2547 return pos - buf; 2548} 2549 2550 2551static int ctrl_iface_get_capability_group(int res, char *strict, 2552 struct wpa_driver_capa *capa, 2553 char *buf, size_t buflen) 2554{ 2555 int ret, first = 1; 2556 char *pos, *end; 2557 size_t len; 2558 2559 pos = buf; 2560 end = pos + buflen; 2561 2562 if (res < 0) { 2563 if (strict) 2564 return 0; 2565 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 2566 if (len >= buflen) 2567 return -1; 2568 return len; 2569 } 2570 2571 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 2572 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 2573 if (ret < 0 || ret >= end - pos) 2574 return pos - buf; 2575 pos += ret; 2576 first = 0; 2577 } 2578 2579 if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) { 2580 ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " "); 2581 if (ret < 0 || ret >= end - pos) 2582 return pos - buf; 2583 pos += ret; 2584 first = 0; 2585 } 2586 2587 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 2588 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 2589 if (ret < 0 || ret >= end - pos) 2590 return pos - buf; 2591 pos += ret; 2592 first = 0; 2593 } 2594 2595 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) { 2596 ret = os_snprintf(pos, end - pos, "%sWEP104", 2597 first ? "" : " "); 2598 if (ret < 0 || ret >= end - pos) 2599 return pos - buf; 2600 pos += ret; 2601 first = 0; 2602 } 2603 2604 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) { 2605 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " "); 2606 if (ret < 0 || ret >= end - pos) 2607 return pos - buf; 2608 pos += ret; 2609 first = 0; 2610 } 2611 2612 return pos - buf; 2613} 2614 2615 2616static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, 2617 struct wpa_driver_capa *capa, 2618 char *buf, size_t buflen) 2619{ 2620 int ret; 2621 char *pos, *end; 2622 size_t len; 2623 2624 pos = buf; 2625 end = pos + buflen; 2626 2627 if (res < 0) { 2628 if (strict) 2629 return 0; 2630 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 2631 "NONE", buflen); 2632 if (len >= buflen) 2633 return -1; 2634 return len; 2635 } 2636 2637 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 2638 if (ret < 0 || ret >= end - pos) 2639 return pos - buf; 2640 pos += ret; 2641 2642 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2643 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 2644 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 2645 if (ret < 0 || ret >= end - pos) 2646 return pos - buf; 2647 pos += ret; 2648 } 2649 2650 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 2651 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 2652 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 2653 if (ret < 0 || ret >= end - pos) 2654 return pos - buf; 2655 pos += ret; 2656 } 2657 2658 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 2659 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 2660 if (ret < 0 || ret >= end - pos) 2661 return pos - buf; 2662 pos += ret; 2663 } 2664 2665 return pos - buf; 2666} 2667 2668 2669static int ctrl_iface_get_capability_proto(int res, char *strict, 2670 struct wpa_driver_capa *capa, 2671 char *buf, size_t buflen) 2672{ 2673 int ret, first = 1; 2674 char *pos, *end; 2675 size_t len; 2676 2677 pos = buf; 2678 end = pos + buflen; 2679 2680 if (res < 0) { 2681 if (strict) 2682 return 0; 2683 len = os_strlcpy(buf, "RSN WPA", buflen); 2684 if (len >= buflen) 2685 return -1; 2686 return len; 2687 } 2688 2689 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 2690 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 2691 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); 2692 if (ret < 0 || ret >= end - pos) 2693 return pos - buf; 2694 pos += ret; 2695 first = 0; 2696 } 2697 2698 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2699 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 2700 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); 2701 if (ret < 0 || ret >= end - pos) 2702 return pos - buf; 2703 pos += ret; 2704 first = 0; 2705 } 2706 2707 return pos - buf; 2708} 2709 2710 2711static int ctrl_iface_get_capability_auth_alg(int res, char *strict, 2712 struct wpa_driver_capa *capa, 2713 char *buf, size_t buflen) 2714{ 2715 int ret, first = 1; 2716 char *pos, *end; 2717 size_t len; 2718 2719 pos = buf; 2720 end = pos + buflen; 2721 2722 if (res < 0) { 2723 if (strict) 2724 return 0; 2725 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 2726 if (len >= buflen) 2727 return -1; 2728 return len; 2729 } 2730 2731 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 2732 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " "); 2733 if (ret < 0 || ret >= end - pos) 2734 return pos - buf; 2735 pos += ret; 2736 first = 0; 2737 } 2738 2739 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 2740 ret = os_snprintf(pos, end - pos, "%sSHARED", 2741 first ? "" : " "); 2742 if (ret < 0 || ret >= end - pos) 2743 return pos - buf; 2744 pos += ret; 2745 first = 0; 2746 } 2747 2748 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 2749 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " "); 2750 if (ret < 0 || ret >= end - pos) 2751 return pos - buf; 2752 pos += ret; 2753 first = 0; 2754 } 2755 2756 return pos - buf; 2757} 2758 2759 2760static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s, 2761 char *buf, size_t buflen) 2762{ 2763 struct hostapd_channel_data *chnl; 2764 int ret, i, j; 2765 char *pos, *end, *hmode; 2766 2767 pos = buf; 2768 end = pos + buflen; 2769 2770 for (j = 0; j < wpa_s->hw.num_modes; j++) { 2771 switch (wpa_s->hw.modes[j].mode) { 2772 case HOSTAPD_MODE_IEEE80211B: 2773 hmode = "B"; 2774 break; 2775 case HOSTAPD_MODE_IEEE80211G: 2776 hmode = "G"; 2777 break; 2778 case HOSTAPD_MODE_IEEE80211A: 2779 hmode = "A"; 2780 break; 2781 case HOSTAPD_MODE_IEEE80211AD: 2782 hmode = "AD"; 2783 break; 2784 default: 2785 continue; 2786 } 2787 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode); 2788 if (ret < 0 || ret >= end - pos) 2789 return pos - buf; 2790 pos += ret; 2791 chnl = wpa_s->hw.modes[j].channels; 2792 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 2793 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 2794 continue; 2795 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan); 2796 if (ret < 0 || ret >= end - pos) 2797 return pos - buf; 2798 pos += ret; 2799 } 2800 ret = os_snprintf(pos, end - pos, "\n"); 2801 if (ret < 0 || ret >= end - pos) 2802 return pos - buf; 2803 pos += ret; 2804 } 2805 2806 return pos - buf; 2807} 2808 2809 2810static int wpa_supplicant_ctrl_iface_get_capability( 2811 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 2812 size_t buflen) 2813{ 2814 struct wpa_driver_capa capa; 2815 int res; 2816 char *strict; 2817 char field[30]; 2818 size_t len; 2819 2820 /* Determine whether or not strict checking was requested */ 2821 len = os_strlcpy(field, _field, sizeof(field)); 2822 if (len >= sizeof(field)) 2823 return -1; 2824 strict = os_strchr(field, ' '); 2825 if (strict != NULL) { 2826 *strict++ = '\0'; 2827 if (os_strcmp(strict, "strict") != 0) 2828 return -1; 2829 } 2830 2831 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", 2832 field, strict ? strict : ""); 2833 2834 if (os_strcmp(field, "eap") == 0) { 2835 return eap_get_names(buf, buflen); 2836 } 2837 2838 res = wpa_drv_get_capa(wpa_s, &capa); 2839 2840 if (os_strcmp(field, "pairwise") == 0) 2841 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 2842 buf, buflen); 2843 2844 if (os_strcmp(field, "group") == 0) 2845 return ctrl_iface_get_capability_group(res, strict, &capa, 2846 buf, buflen); 2847 2848 if (os_strcmp(field, "key_mgmt") == 0) 2849 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 2850 buf, buflen); 2851 2852 if (os_strcmp(field, "proto") == 0) 2853 return ctrl_iface_get_capability_proto(res, strict, &capa, 2854 buf, buflen); 2855 2856 if (os_strcmp(field, "auth_alg") == 0) 2857 return ctrl_iface_get_capability_auth_alg(res, strict, &capa, 2858 buf, buflen); 2859 2860 if (os_strcmp(field, "channels") == 0) 2861 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen); 2862 2863 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 2864 field); 2865 2866 return -1; 2867} 2868 2869 2870#ifdef CONFIG_INTERWORKING 2871static char * anqp_add_hex(char *pos, char *end, const char *title, 2872 struct wpabuf *data) 2873{ 2874 char *start = pos; 2875 size_t i; 2876 int ret; 2877 const u8 *d; 2878 2879 if (data == NULL) 2880 return start; 2881 2882 ret = os_snprintf(pos, end - pos, "%s=", title); 2883 if (ret < 0 || ret >= end - pos) 2884 return start; 2885 pos += ret; 2886 2887 d = wpabuf_head_u8(data); 2888 for (i = 0; i < wpabuf_len(data); i++) { 2889 ret = os_snprintf(pos, end - pos, "%02x", *d++); 2890 if (ret < 0 || ret >= end - pos) 2891 return start; 2892 pos += ret; 2893 } 2894 2895 ret = os_snprintf(pos, end - pos, "\n"); 2896 if (ret < 0 || ret >= end - pos) 2897 return start; 2898 pos += ret; 2899 2900 return pos; 2901} 2902#endif /* CONFIG_INTERWORKING */ 2903 2904 2905static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 2906 unsigned long mask, char *buf, size_t buflen) 2907{ 2908 size_t i; 2909 int ret; 2910 char *pos, *end; 2911 const u8 *ie, *ie2; 2912 2913 pos = buf; 2914 end = buf + buflen; 2915 2916 if (mask & WPA_BSS_MASK_ID) { 2917 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id); 2918 if (ret < 0 || ret >= end - pos) 2919 return 0; 2920 pos += ret; 2921 } 2922 2923 if (mask & WPA_BSS_MASK_BSSID) { 2924 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 2925 MAC2STR(bss->bssid)); 2926 if (ret < 0 || ret >= end - pos) 2927 return 0; 2928 pos += ret; 2929 } 2930 2931 if (mask & WPA_BSS_MASK_FREQ) { 2932 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq); 2933 if (ret < 0 || ret >= end - pos) 2934 return 0; 2935 pos += ret; 2936 } 2937 2938 if (mask & WPA_BSS_MASK_BEACON_INT) { 2939 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n", 2940 bss->beacon_int); 2941 if (ret < 0 || ret >= end - pos) 2942 return 0; 2943 pos += ret; 2944 } 2945 2946 if (mask & WPA_BSS_MASK_CAPABILITIES) { 2947 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n", 2948 bss->caps); 2949 if (ret < 0 || ret >= end - pos) 2950 return 0; 2951 pos += ret; 2952 } 2953 2954 if (mask & WPA_BSS_MASK_QUAL) { 2955 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual); 2956 if (ret < 0 || ret >= end - pos) 2957 return 0; 2958 pos += ret; 2959 } 2960 2961 if (mask & WPA_BSS_MASK_NOISE) { 2962 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise); 2963 if (ret < 0 || ret >= end - pos) 2964 return 0; 2965 pos += ret; 2966 } 2967 2968 if (mask & WPA_BSS_MASK_LEVEL) { 2969 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level); 2970 if (ret < 0 || ret >= end - pos) 2971 return 0; 2972 pos += ret; 2973 } 2974 2975 if (mask & WPA_BSS_MASK_TSF) { 2976 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n", 2977 (unsigned long long) bss->tsf); 2978 if (ret < 0 || ret >= end - pos) 2979 return 0; 2980 pos += ret; 2981 } 2982 2983 if (mask & WPA_BSS_MASK_AGE) { 2984 struct os_time now; 2985 2986 os_get_time(&now); 2987 ret = os_snprintf(pos, end - pos, "age=%d\n", 2988 (int) (now.sec - bss->last_update.sec)); 2989 if (ret < 0 || ret >= end - pos) 2990 return 0; 2991 pos += ret; 2992 } 2993 2994 if (mask & WPA_BSS_MASK_IE) { 2995 ret = os_snprintf(pos, end - pos, "ie="); 2996 if (ret < 0 || ret >= end - pos) 2997 return 0; 2998 pos += ret; 2999 3000 ie = (const u8 *) (bss + 1); 3001 for (i = 0; i < bss->ie_len; i++) { 3002 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 3003 if (ret < 0 || ret >= end - pos) 3004 return 0; 3005 pos += ret; 3006 } 3007 3008 ret = os_snprintf(pos, end - pos, "\n"); 3009 if (ret < 0 || ret >= end - pos) 3010 return 0; 3011 pos += ret; 3012 } 3013 3014 if (mask & WPA_BSS_MASK_FLAGS) { 3015 ret = os_snprintf(pos, end - pos, "flags="); 3016 if (ret < 0 || ret >= end - pos) 3017 return 0; 3018 pos += ret; 3019 3020 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 3021 if (ie) 3022 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 3023 2 + ie[1]); 3024 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 3025 if (ie2) 3026 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 3027 2 + ie2[1]); 3028 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 3029 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 3030 ret = os_snprintf(pos, end - pos, "[WEP]"); 3031 if (ret < 0 || ret >= end - pos) 3032 return 0; 3033 pos += ret; 3034 } 3035 if (bss->caps & IEEE80211_CAP_IBSS) { 3036 ret = os_snprintf(pos, end - pos, "[IBSS]"); 3037 if (ret < 0 || ret >= end - pos) 3038 return 0; 3039 pos += ret; 3040 } 3041 if (bss->caps & IEEE80211_CAP_ESS) { 3042 ret = os_snprintf(pos, end - pos, "[ESS]"); 3043 if (ret < 0 || ret >= end - pos) 3044 return 0; 3045 pos += ret; 3046 } 3047 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) { 3048 ret = os_snprintf(pos, end - pos, "[P2P]"); 3049 if (ret < 0 || ret >= end - pos) 3050 return 0; 3051 pos += ret; 3052 } 3053#ifdef CONFIG_HS20 3054 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 3055 ret = os_snprintf(pos, end - pos, "[HS20]"); 3056 if (ret < 0 || ret >= end - pos) 3057 return -1; 3058 pos += ret; 3059 } 3060#endif /* CONFIG_HS20 */ 3061 3062 ret = os_snprintf(pos, end - pos, "\n"); 3063 if (ret < 0 || ret >= end - pos) 3064 return 0; 3065 pos += ret; 3066 } 3067 3068 if (mask & WPA_BSS_MASK_SSID) { 3069 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 3070 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 3071 if (ret < 0 || ret >= end - pos) 3072 return 0; 3073 pos += ret; 3074 } 3075 3076#ifdef CONFIG_WPS 3077 if (mask & WPA_BSS_MASK_WPS_SCAN) { 3078 ie = (const u8 *) (bss + 1); 3079 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); 3080 if (ret < 0 || ret >= end - pos) 3081 return 0; 3082 pos += ret; 3083 } 3084#endif /* CONFIG_WPS */ 3085 3086#ifdef CONFIG_P2P 3087 if (mask & WPA_BSS_MASK_P2P_SCAN) { 3088 ie = (const u8 *) (bss + 1); 3089 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); 3090 if (ret < 0 || ret >= end - pos) 3091 return 0; 3092 pos += ret; 3093 } 3094#endif /* CONFIG_P2P */ 3095 3096#ifdef CONFIG_WIFI_DISPLAY 3097 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) { 3098 struct wpabuf *wfd; 3099 ie = (const u8 *) (bss + 1); 3100 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len, 3101 WFD_IE_VENDOR_TYPE); 3102 if (wfd) { 3103 ret = os_snprintf(pos, end - pos, "wfd_subelems="); 3104 if (ret < 0 || ret >= end - pos) 3105 return pos - buf; 3106 pos += ret; 3107 3108 pos += wpa_snprintf_hex(pos, end - pos, 3109 wpabuf_head(wfd), 3110 wpabuf_len(wfd)); 3111 wpabuf_free(wfd); 3112 3113 ret = os_snprintf(pos, end - pos, "\n"); 3114 if (ret < 0 || ret >= end - pos) 3115 return pos - buf; 3116 pos += ret; 3117 } 3118 } 3119#endif /* CONFIG_WIFI_DISPLAY */ 3120 3121#ifdef CONFIG_INTERWORKING 3122 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) { 3123 struct wpa_bss_anqp *anqp = bss->anqp; 3124 pos = anqp_add_hex(pos, end, "anqp_venue_name", 3125 anqp->venue_name); 3126 pos = anqp_add_hex(pos, end, "anqp_network_auth_type", 3127 anqp->network_auth_type); 3128 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium", 3129 anqp->roaming_consortium); 3130 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability", 3131 anqp->ip_addr_type_availability); 3132 pos = anqp_add_hex(pos, end, "anqp_nai_realm", 3133 anqp->nai_realm); 3134 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp); 3135 pos = anqp_add_hex(pos, end, "anqp_domain_name", 3136 anqp->domain_name); 3137#ifdef CONFIG_HS20 3138 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name", 3139 anqp->hs20_operator_friendly_name); 3140 pos = anqp_add_hex(pos, end, "hs20_wan_metrics", 3141 anqp->hs20_wan_metrics); 3142 pos = anqp_add_hex(pos, end, "hs20_connection_capability", 3143 anqp->hs20_connection_capability); 3144#endif /* CONFIG_HS20 */ 3145 } 3146#endif /* CONFIG_INTERWORKING */ 3147 3148 return pos - buf; 3149} 3150 3151 3152static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 3153 const char *cmd, char *buf, 3154 size_t buflen) 3155{ 3156 u8 bssid[ETH_ALEN]; 3157 size_t i; 3158 struct wpa_bss *bss; 3159 struct wpa_bss *bsslast = NULL; 3160 struct dl_list *next; 3161 int ret = 0; 3162 int len; 3163 char *ctmp; 3164 unsigned long mask = WPA_BSS_MASK_ALL; 3165 3166 if (os_strncmp(cmd, "RANGE=", 6) == 0) { 3167 if (os_strncmp(cmd + 6, "ALL", 3) == 0) { 3168 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, 3169 list_id); 3170 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss, 3171 list_id); 3172 } else { /* N1-N2 */ 3173 unsigned int id1, id2; 3174 3175 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) { 3176 wpa_printf(MSG_INFO, "Wrong BSS range " 3177 "format"); 3178 return 0; 3179 } 3180 3181 id1 = atoi(cmd + 6); 3182 bss = wpa_bss_get_id(wpa_s, id1); 3183 id2 = atoi(ctmp + 1); 3184 if (id2 == 0) 3185 bsslast = dl_list_last(&wpa_s->bss_id, 3186 struct wpa_bss, 3187 list_id); 3188 else { 3189 bsslast = wpa_bss_get_id(wpa_s, id2); 3190 if (bsslast == NULL && bss && id2 > id1) { 3191 struct wpa_bss *tmp = bss; 3192 for (;;) { 3193 next = tmp->list_id.next; 3194 if (next == &wpa_s->bss_id) 3195 break; 3196 tmp = dl_list_entry( 3197 next, struct wpa_bss, 3198 list_id); 3199 if (tmp->id > id2) 3200 break; 3201 bsslast = tmp; 3202 } 3203 } 3204 } 3205 } 3206 } else if (os_strcmp(cmd, "FIRST") == 0) 3207 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id); 3208 else if (os_strncmp(cmd, "ID-", 3) == 0) { 3209 i = atoi(cmd + 3); 3210 bss = wpa_bss_get_id(wpa_s, i); 3211 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 3212 i = atoi(cmd + 5); 3213 bss = wpa_bss_get_id(wpa_s, i); 3214 if (bss) { 3215 next = bss->list_id.next; 3216 if (next == &wpa_s->bss_id) 3217 bss = NULL; 3218 else 3219 bss = dl_list_entry(next, struct wpa_bss, 3220 list_id); 3221 } 3222#ifdef CONFIG_P2P 3223 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 3224 if (hwaddr_aton(cmd + 13, bssid) == 0) 3225 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid); 3226 else 3227 bss = NULL; 3228#endif /* CONFIG_P2P */ 3229 } else if (hwaddr_aton(cmd, bssid) == 0) 3230 bss = wpa_bss_get_bssid(wpa_s, bssid); 3231 else { 3232 struct wpa_bss *tmp; 3233 i = atoi(cmd); 3234 bss = NULL; 3235 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) 3236 { 3237 if (i-- == 0) { 3238 bss = tmp; 3239 break; 3240 } 3241 } 3242 } 3243 3244 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) { 3245 mask = strtoul(ctmp + 5, NULL, 0x10); 3246 if (mask == 0) 3247 mask = WPA_BSS_MASK_ALL; 3248 } 3249 3250 if (bss == NULL) 3251 return 0; 3252 3253 if (bsslast == NULL) 3254 bsslast = bss; 3255 do { 3256 len = print_bss_info(wpa_s, bss, mask, buf, buflen); 3257 ret += len; 3258 buf += len; 3259 buflen -= len; 3260 if (bss == bsslast) 3261 break; 3262 next = bss->list_id.next; 3263 if (next == &wpa_s->bss_id) 3264 break; 3265 bss = dl_list_entry(next, struct wpa_bss, list_id); 3266 } while (bss && len); 3267 3268 return ret; 3269} 3270 3271 3272static int wpa_supplicant_ctrl_iface_ap_scan( 3273 struct wpa_supplicant *wpa_s, char *cmd) 3274{ 3275 int ap_scan = atoi(cmd); 3276 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan); 3277} 3278 3279 3280static int wpa_supplicant_ctrl_iface_scan_interval( 3281 struct wpa_supplicant *wpa_s, char *cmd) 3282{ 3283 int scan_int = atoi(cmd); 3284 return wpa_supplicant_set_scan_interval(wpa_s, scan_int); 3285} 3286 3287 3288static int wpa_supplicant_ctrl_iface_bss_expire_age( 3289 struct wpa_supplicant *wpa_s, char *cmd) 3290{ 3291 int expire_age = atoi(cmd); 3292 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age); 3293} 3294 3295 3296static int wpa_supplicant_ctrl_iface_bss_expire_count( 3297 struct wpa_supplicant *wpa_s, char *cmd) 3298{ 3299 int expire_count = atoi(cmd); 3300 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count); 3301} 3302 3303 3304static int wpa_supplicant_ctrl_iface_bss_flush( 3305 struct wpa_supplicant *wpa_s, char *cmd) 3306{ 3307 int flush_age = atoi(cmd); 3308 3309 if (flush_age == 0) 3310 wpa_bss_flush(wpa_s); 3311 else 3312 wpa_bss_flush_by_age(wpa_s, flush_age); 3313 return 0; 3314} 3315 3316 3317static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) 3318{ 3319 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication"); 3320 /* MLME-DELETEKEYS.request */ 3321 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0); 3322 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0); 3323 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0); 3324 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0); 3325#ifdef CONFIG_IEEE80211W 3326 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0); 3327 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0); 3328#endif /* CONFIG_IEEE80211W */ 3329 3330 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 3331 0); 3332 /* MLME-SETPROTECTION.request(None) */ 3333 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, 3334 MLME_SETPROTECTION_PROTECT_TYPE_NONE, 3335 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 3336 wpa_sm_drop_sa(wpa_s->wpa); 3337} 3338 3339 3340static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, 3341 char *addr) 3342{ 3343#ifdef CONFIG_NO_SCAN_PROCESSING 3344 return -1; 3345#else /* CONFIG_NO_SCAN_PROCESSING */ 3346 u8 bssid[ETH_ALEN]; 3347 struct wpa_bss *bss; 3348 struct wpa_ssid *ssid = wpa_s->current_ssid; 3349 3350 if (hwaddr_aton(addr, bssid)) { 3351 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " 3352 "address '%s'", addr); 3353 return -1; 3354 } 3355 3356 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); 3357 3358 bss = wpa_bss_get_bssid(wpa_s, bssid); 3359 if (!bss) { 3360 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " 3361 "from BSS table"); 3362 return -1; 3363 } 3364 3365 /* 3366 * TODO: Find best network configuration block from configuration to 3367 * allow roaming to other networks 3368 */ 3369 3370 if (!ssid) { 3371 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " 3372 "configuration known for the target AP"); 3373 return -1; 3374 } 3375 3376 wpa_s->reassociate = 1; 3377 wpa_supplicant_connect(wpa_s, bss, ssid); 3378 3379 return 0; 3380#endif /* CONFIG_NO_SCAN_PROCESSING */ 3381} 3382 3383 3384#ifdef CONFIG_P2P 3385static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) 3386{ 3387 unsigned int timeout = atoi(cmd); 3388 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; 3389 u8 dev_id[ETH_ALEN], *_dev_id = NULL; 3390 char *pos; 3391 unsigned int search_delay; 3392 3393 if (os_strstr(cmd, "type=social")) 3394 type = P2P_FIND_ONLY_SOCIAL; 3395 else if (os_strstr(cmd, "type=progressive")) 3396 type = P2P_FIND_PROGRESSIVE; 3397 3398 pos = os_strstr(cmd, "dev_id="); 3399 if (pos) { 3400 pos += 7; 3401 if (hwaddr_aton(pos, dev_id)) 3402 return -1; 3403 _dev_id = dev_id; 3404 } 3405 3406 pos = os_strstr(cmd, "delay="); 3407 if (pos) { 3408 pos += 6; 3409 search_delay = atoi(pos); 3410 } else 3411 search_delay = wpas_p2p_search_delay(wpa_s); 3412 3413 return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id, 3414 search_delay); 3415} 3416 3417 3418static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, 3419 char *buf, size_t buflen) 3420{ 3421 u8 addr[ETH_ALEN]; 3422 char *pos, *pos2; 3423 char *pin = NULL; 3424 enum p2p_wps_method wps_method; 3425 int new_pin; 3426 int ret; 3427 int persistent_group, persistent_id = -1; 3428 int join; 3429 int auth; 3430 int automatic; 3431 int go_intent = -1; 3432 int freq = 0; 3433 int pd; 3434 int ht40; 3435 3436 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] 3437 * [persistent|persistent=<network id>] 3438 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] 3439 * [ht40] */ 3440 3441 if (hwaddr_aton(cmd, addr)) 3442 return -1; 3443 3444 pos = cmd + 17; 3445 if (*pos != ' ') 3446 return -1; 3447 pos++; 3448 3449 persistent_group = os_strstr(pos, " persistent") != NULL; 3450 pos2 = os_strstr(pos, " persistent="); 3451 if (pos2) { 3452 struct wpa_ssid *ssid; 3453 persistent_id = atoi(pos2 + 12); 3454 ssid = wpa_config_get_network(wpa_s->conf, persistent_id); 3455 if (ssid == NULL || ssid->disabled != 2 || 3456 ssid->mode != WPAS_MODE_P2P_GO) { 3457 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3458 "SSID id=%d for persistent P2P group (GO)", 3459 persistent_id); 3460 return -1; 3461 } 3462 } 3463 join = os_strstr(pos, " join") != NULL; 3464 auth = os_strstr(pos, " auth") != NULL; 3465 automatic = os_strstr(pos, " auto") != NULL; 3466 pd = os_strstr(pos, " provdisc") != NULL; 3467 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40; 3468 3469 pos2 = os_strstr(pos, " go_intent="); 3470 if (pos2) { 3471 pos2 += 11; 3472 go_intent = atoi(pos2); 3473 if (go_intent < 0 || go_intent > 15) 3474 return -1; 3475 } 3476 3477 pos2 = os_strstr(pos, " freq="); 3478 if (pos2) { 3479 pos2 += 6; 3480 freq = atoi(pos2); 3481 if (freq <= 0) 3482 return -1; 3483 } 3484 3485 if (os_strncmp(pos, "pin", 3) == 0) { 3486 /* Request random PIN (to be displayed) and enable the PIN */ 3487 wps_method = WPS_PIN_DISPLAY; 3488 } else if (os_strncmp(pos, "pbc", 3) == 0) { 3489 wps_method = WPS_PBC; 3490 } else { 3491 pin = pos; 3492 pos = os_strchr(pin, ' '); 3493 wps_method = WPS_PIN_KEYPAD; 3494 if (pos) { 3495 *pos++ = '\0'; 3496 if (os_strncmp(pos, "display", 7) == 0) 3497 wps_method = WPS_PIN_DISPLAY; 3498 } 3499 if (!wps_pin_str_valid(pin)) { 3500 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17); 3501 return 17; 3502 } 3503 } 3504 3505 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, 3506 persistent_group, automatic, join, 3507 auth, go_intent, freq, persistent_id, pd, 3508 ht40); 3509 if (new_pin == -2) { 3510 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); 3511 return 25; 3512 } 3513 if (new_pin == -3) { 3514 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25); 3515 return 25; 3516 } 3517 if (new_pin < 0) 3518 return -1; 3519 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) { 3520 ret = os_snprintf(buf, buflen, "%08d", new_pin); 3521 if (ret < 0 || (size_t) ret >= buflen) 3522 return -1; 3523 return ret; 3524 } 3525 3526 os_memcpy(buf, "OK\n", 3); 3527 return 3; 3528} 3529 3530 3531static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd) 3532{ 3533 unsigned int timeout = atoi(cmd); 3534 return wpas_p2p_listen(wpa_s, timeout); 3535} 3536 3537 3538static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd) 3539{ 3540 u8 addr[ETH_ALEN]; 3541 char *pos; 3542 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG; 3543 3544 /* <addr> <config method> [join|auto] */ 3545 3546 if (hwaddr_aton(cmd, addr)) 3547 return -1; 3548 3549 pos = cmd + 17; 3550 if (*pos != ' ') 3551 return -1; 3552 pos++; 3553 3554 if (os_strstr(pos, " join") != NULL) 3555 use = WPAS_P2P_PD_FOR_JOIN; 3556 else if (os_strstr(pos, " auto") != NULL) 3557 use = WPAS_P2P_PD_AUTO; 3558 3559 return wpas_p2p_prov_disc(wpa_s, addr, pos, use); 3560} 3561 3562 3563static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf, 3564 size_t buflen) 3565{ 3566 struct wpa_ssid *ssid = wpa_s->current_ssid; 3567 3568 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || 3569 ssid->passphrase == NULL) 3570 return -1; 3571 3572 os_strlcpy(buf, ssid->passphrase, buflen); 3573 return os_strlen(buf); 3574} 3575 3576 3577static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd, 3578 char *buf, size_t buflen) 3579{ 3580 u64 ref; 3581 int res; 3582 u8 dst_buf[ETH_ALEN], *dst; 3583 struct wpabuf *tlvs; 3584 char *pos; 3585 size_t len; 3586 3587 if (hwaddr_aton(cmd, dst_buf)) 3588 return -1; 3589 dst = dst_buf; 3590 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 && 3591 dst[3] == 0 && dst[4] == 0 && dst[5] == 0) 3592 dst = NULL; 3593 pos = cmd + 17; 3594 if (*pos != ' ') 3595 return -1; 3596 pos++; 3597 3598 if (os_strncmp(pos, "upnp ", 5) == 0) { 3599 u8 version; 3600 pos += 5; 3601 if (hexstr2bin(pos, &version, 1) < 0) 3602 return -1; 3603 pos += 2; 3604 if (*pos != ' ') 3605 return -1; 3606 pos++; 3607 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos); 3608#ifdef CONFIG_WIFI_DISPLAY 3609 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) { 3610 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13); 3611#endif /* CONFIG_WIFI_DISPLAY */ 3612 } else { 3613 len = os_strlen(pos); 3614 if (len & 1) 3615 return -1; 3616 len /= 2; 3617 tlvs = wpabuf_alloc(len); 3618 if (tlvs == NULL) 3619 return -1; 3620 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) { 3621 wpabuf_free(tlvs); 3622 return -1; 3623 } 3624 3625 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs); 3626 wpabuf_free(tlvs); 3627 } 3628 if (ref == 0) 3629 return -1; 3630 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref); 3631 if (res < 0 || (unsigned) res >= buflen) 3632 return -1; 3633 return res; 3634} 3635 3636 3637static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s, 3638 char *cmd) 3639{ 3640 long long unsigned val; 3641 u64 req; 3642 if (sscanf(cmd, "%llx", &val) != 1) 3643 return -1; 3644 req = val; 3645 return wpas_p2p_sd_cancel_request(wpa_s, req); 3646} 3647 3648 3649static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd) 3650{ 3651 int freq; 3652 u8 dst[ETH_ALEN]; 3653 u8 dialog_token; 3654 struct wpabuf *resp_tlvs; 3655 char *pos, *pos2; 3656 size_t len; 3657 3658 pos = os_strchr(cmd, ' '); 3659 if (pos == NULL) 3660 return -1; 3661 *pos++ = '\0'; 3662 freq = atoi(cmd); 3663 if (freq == 0) 3664 return -1; 3665 3666 if (hwaddr_aton(pos, dst)) 3667 return -1; 3668 pos += 17; 3669 if (*pos != ' ') 3670 return -1; 3671 pos++; 3672 3673 pos2 = os_strchr(pos, ' '); 3674 if (pos2 == NULL) 3675 return -1; 3676 *pos2++ = '\0'; 3677 dialog_token = atoi(pos); 3678 3679 len = os_strlen(pos2); 3680 if (len & 1) 3681 return -1; 3682 len /= 2; 3683 resp_tlvs = wpabuf_alloc(len); 3684 if (resp_tlvs == NULL) 3685 return -1; 3686 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) { 3687 wpabuf_free(resp_tlvs); 3688 return -1; 3689 } 3690 3691 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs); 3692 wpabuf_free(resp_tlvs); 3693 return 0; 3694} 3695 3696 3697static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s, 3698 char *cmd) 3699{ 3700 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1")) 3701 return -1; 3702 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd); 3703 return 0; 3704} 3705 3706 3707static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s, 3708 char *cmd) 3709{ 3710 char *pos; 3711 size_t len; 3712 struct wpabuf *query, *resp; 3713 3714 pos = os_strchr(cmd, ' '); 3715 if (pos == NULL) 3716 return -1; 3717 *pos++ = '\0'; 3718 3719 len = os_strlen(cmd); 3720 if (len & 1) 3721 return -1; 3722 len /= 2; 3723 query = wpabuf_alloc(len); 3724 if (query == NULL) 3725 return -1; 3726 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 3727 wpabuf_free(query); 3728 return -1; 3729 } 3730 3731 len = os_strlen(pos); 3732 if (len & 1) { 3733 wpabuf_free(query); 3734 return -1; 3735 } 3736 len /= 2; 3737 resp = wpabuf_alloc(len); 3738 if (resp == NULL) { 3739 wpabuf_free(query); 3740 return -1; 3741 } 3742 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) { 3743 wpabuf_free(query); 3744 wpabuf_free(resp); 3745 return -1; 3746 } 3747 3748 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) { 3749 wpabuf_free(query); 3750 wpabuf_free(resp); 3751 return -1; 3752 } 3753 return 0; 3754} 3755 3756 3757static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd) 3758{ 3759 char *pos; 3760 u8 version; 3761 3762 pos = os_strchr(cmd, ' '); 3763 if (pos == NULL) 3764 return -1; 3765 *pos++ = '\0'; 3766 3767 if (hexstr2bin(cmd, &version, 1) < 0) 3768 return -1; 3769 3770 return wpas_p2p_service_add_upnp(wpa_s, version, pos); 3771} 3772 3773 3774static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd) 3775{ 3776 char *pos; 3777 3778 pos = os_strchr(cmd, ' '); 3779 if (pos == NULL) 3780 return -1; 3781 *pos++ = '\0'; 3782 3783 if (os_strcmp(cmd, "bonjour") == 0) 3784 return p2p_ctrl_service_add_bonjour(wpa_s, pos); 3785 if (os_strcmp(cmd, "upnp") == 0) 3786 return p2p_ctrl_service_add_upnp(wpa_s, pos); 3787 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 3788 return -1; 3789} 3790 3791 3792static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s, 3793 char *cmd) 3794{ 3795 size_t len; 3796 struct wpabuf *query; 3797 int ret; 3798 3799 len = os_strlen(cmd); 3800 if (len & 1) 3801 return -1; 3802 len /= 2; 3803 query = wpabuf_alloc(len); 3804 if (query == NULL) 3805 return -1; 3806 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 3807 wpabuf_free(query); 3808 return -1; 3809 } 3810 3811 ret = wpas_p2p_service_del_bonjour(wpa_s, query); 3812 wpabuf_free(query); 3813 return ret; 3814} 3815 3816 3817static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd) 3818{ 3819 char *pos; 3820 u8 version; 3821 3822 pos = os_strchr(cmd, ' '); 3823 if (pos == NULL) 3824 return -1; 3825 *pos++ = '\0'; 3826 3827 if (hexstr2bin(cmd, &version, 1) < 0) 3828 return -1; 3829 3830 return wpas_p2p_service_del_upnp(wpa_s, version, pos); 3831} 3832 3833 3834static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd) 3835{ 3836 char *pos; 3837 3838 pos = os_strchr(cmd, ' '); 3839 if (pos == NULL) 3840 return -1; 3841 *pos++ = '\0'; 3842 3843 if (os_strcmp(cmd, "bonjour") == 0) 3844 return p2p_ctrl_service_del_bonjour(wpa_s, pos); 3845 if (os_strcmp(cmd, "upnp") == 0) 3846 return p2p_ctrl_service_del_upnp(wpa_s, pos); 3847 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 3848 return -1; 3849} 3850 3851 3852static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd) 3853{ 3854 u8 addr[ETH_ALEN]; 3855 3856 /* <addr> */ 3857 3858 if (hwaddr_aton(cmd, addr)) 3859 return -1; 3860 3861 return wpas_p2p_reject(wpa_s, addr); 3862} 3863 3864 3865static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) 3866{ 3867 char *pos; 3868 int id; 3869 struct wpa_ssid *ssid; 3870 u8 *_peer = NULL, peer[ETH_ALEN]; 3871 int freq = 0; 3872 int ht40; 3873 3874 id = atoi(cmd); 3875 pos = os_strstr(cmd, " peer="); 3876 if (pos) { 3877 pos += 6; 3878 if (hwaddr_aton(pos, peer)) 3879 return -1; 3880 _peer = peer; 3881 } 3882 ssid = wpa_config_get_network(wpa_s->conf, id); 3883 if (ssid == NULL || ssid->disabled != 2) { 3884 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 3885 "for persistent P2P group", 3886 id); 3887 return -1; 3888 } 3889 3890 pos = os_strstr(cmd, " freq="); 3891 if (pos) { 3892 pos += 6; 3893 freq = atoi(pos); 3894 if (freq <= 0) 3895 return -1; 3896 } 3897 3898 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40; 3899 3900 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40); 3901} 3902 3903 3904static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd) 3905{ 3906 char *pos; 3907 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL; 3908 3909 pos = os_strstr(cmd, " peer="); 3910 if (!pos) 3911 return -1; 3912 3913 *pos = '\0'; 3914 pos += 6; 3915 if (hwaddr_aton(pos, peer)) { 3916 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos); 3917 return -1; 3918 } 3919 3920 pos = os_strstr(pos, " go_dev_addr="); 3921 if (pos) { 3922 pos += 13; 3923 if (hwaddr_aton(pos, go_dev_addr)) { 3924 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", 3925 pos); 3926 return -1; 3927 } 3928 go_dev = go_dev_addr; 3929 } 3930 3931 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev); 3932} 3933 3934 3935static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd) 3936{ 3937 if (os_strncmp(cmd, "persistent=", 11) == 0) 3938 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11); 3939 if (os_strncmp(cmd, "group=", 6) == 0) 3940 return p2p_ctrl_invite_group(wpa_s, cmd + 6); 3941 3942 return -1; 3943} 3944 3945 3946static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, 3947 char *cmd, int freq, int ht40) 3948{ 3949 int id; 3950 struct wpa_ssid *ssid; 3951 3952 id = atoi(cmd); 3953 ssid = wpa_config_get_network(wpa_s->conf, id); 3954 if (ssid == NULL || ssid->disabled != 2) { 3955 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 3956 "for persistent P2P group", 3957 id); 3958 return -1; 3959 } 3960 3961 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, ht40); 3962} 3963 3964 3965static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) 3966{ 3967 int freq = 0, ht40; 3968 char *pos; 3969 3970 pos = os_strstr(cmd, "freq="); 3971 if (pos) 3972 freq = atoi(pos + 5); 3973 3974 ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40; 3975 3976 if (os_strncmp(cmd, "persistent=", 11) == 0) 3977 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq, 3978 ht40); 3979 if (os_strcmp(cmd, "persistent") == 0 || 3980 os_strncmp(cmd, "persistent ", 11) == 0) 3981 return wpas_p2p_group_add(wpa_s, 1, freq, ht40); 3982 if (os_strncmp(cmd, "freq=", 5) == 0) 3983 return wpas_p2p_group_add(wpa_s, 0, freq, ht40); 3984 if (ht40) 3985 return wpas_p2p_group_add(wpa_s, 0, freq, ht40); 3986 3987 wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'", 3988 cmd); 3989 return -1; 3990} 3991 3992 3993static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, 3994 char *buf, size_t buflen) 3995{ 3996 u8 addr[ETH_ALEN], *addr_ptr; 3997 int next, res; 3998 const struct p2p_peer_info *info; 3999 char *pos, *end; 4000 char devtype[WPS_DEV_TYPE_BUFSIZE]; 4001 struct wpa_ssid *ssid; 4002 size_t i; 4003 4004 if (!wpa_s->global->p2p) 4005 return -1; 4006 4007 if (os_strcmp(cmd, "FIRST") == 0) { 4008 addr_ptr = NULL; 4009 next = 0; 4010 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 4011 if (hwaddr_aton(cmd + 5, addr) < 0) 4012 return -1; 4013 addr_ptr = addr; 4014 next = 1; 4015 } else { 4016 if (hwaddr_aton(cmd, addr) < 0) 4017 return -1; 4018 addr_ptr = addr; 4019 next = 0; 4020 } 4021 4022 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next); 4023 if (info == NULL) 4024 return -1; 4025 4026 pos = buf; 4027 end = buf + buflen; 4028 4029 res = os_snprintf(pos, end - pos, MACSTR "\n" 4030 "pri_dev_type=%s\n" 4031 "device_name=%s\n" 4032 "manufacturer=%s\n" 4033 "model_name=%s\n" 4034 "model_number=%s\n" 4035 "serial_number=%s\n" 4036 "config_methods=0x%x\n" 4037 "dev_capab=0x%x\n" 4038 "group_capab=0x%x\n" 4039 "level=%d\n", 4040 MAC2STR(info->p2p_device_addr), 4041 wps_dev_type_bin2str(info->pri_dev_type, 4042 devtype, sizeof(devtype)), 4043 info->device_name, 4044 info->manufacturer, 4045 info->model_name, 4046 info->model_number, 4047 info->serial_number, 4048 info->config_methods, 4049 info->dev_capab, 4050 info->group_capab, 4051 info->level); 4052 if (res < 0 || res >= end - pos) 4053 return pos - buf; 4054 pos += res; 4055 4056 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++) 4057 { 4058 const u8 *t; 4059 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN]; 4060 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n", 4061 wps_dev_type_bin2str(t, devtype, 4062 sizeof(devtype))); 4063 if (res < 0 || res >= end - pos) 4064 return pos - buf; 4065 pos += res; 4066 } 4067 4068 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0); 4069 if (ssid) { 4070 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id); 4071 if (res < 0 || res >= end - pos) 4072 return pos - buf; 4073 pos += res; 4074 } 4075 4076 res = p2p_get_peer_info_txt(info, pos, end - pos); 4077 if (res < 0) 4078 return pos - buf; 4079 pos += res; 4080 4081 return pos - buf; 4082} 4083 4084 4085static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s, 4086 const char *param) 4087{ 4088 struct wpa_freq_range *freq = NULL, *n; 4089 unsigned int count = 0, i; 4090 const char *pos, *pos2, *pos3; 4091 4092 if (wpa_s->global->p2p == NULL) 4093 return -1; 4094 4095 /* 4096 * param includes comma separated frequency range. 4097 * For example: 2412-2432,2462,5000-6000 4098 */ 4099 pos = param; 4100 while (pos && pos[0]) { 4101 n = os_realloc_array(freq, count + 1, 4102 sizeof(struct wpa_freq_range)); 4103 if (n == NULL) { 4104 os_free(freq); 4105 return -1; 4106 } 4107 freq = n; 4108 freq[count].min = atoi(pos); 4109 pos2 = os_strchr(pos, '-'); 4110 pos3 = os_strchr(pos, ','); 4111 if (pos2 && (!pos3 || pos2 < pos3)) { 4112 pos2++; 4113 freq[count].max = atoi(pos2); 4114 } else 4115 freq[count].max = freq[count].min; 4116 pos = pos3; 4117 if (pos) 4118 pos++; 4119 count++; 4120 } 4121 4122 for (i = 0; i < count; i++) { 4123 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u", 4124 freq[i].min, freq[i].max); 4125 } 4126 4127 os_free(wpa_s->global->p2p_disallow_freq); 4128 wpa_s->global->p2p_disallow_freq = freq; 4129 wpa_s->global->num_p2p_disallow_freq = count; 4130 wpas_p2p_update_channel_list(wpa_s); 4131 return 0; 4132} 4133 4134 4135static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) 4136{ 4137 char *param; 4138 4139 if (wpa_s->global->p2p == NULL) 4140 return -1; 4141 4142 param = os_strchr(cmd, ' '); 4143 if (param == NULL) 4144 return -1; 4145 *param++ = '\0'; 4146 4147 if (os_strcmp(cmd, "discoverability") == 0) { 4148 p2p_set_client_discoverability(wpa_s->global->p2p, 4149 atoi(param)); 4150 return 0; 4151 } 4152 4153 if (os_strcmp(cmd, "managed") == 0) { 4154 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param)); 4155 return 0; 4156 } 4157 4158 if (os_strcmp(cmd, "listen_channel") == 0) { 4159 return p2p_set_listen_channel(wpa_s->global->p2p, 81, 4160 atoi(param)); 4161 } 4162 4163 if (os_strcmp(cmd, "ssid_postfix") == 0) { 4164 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param, 4165 os_strlen(param)); 4166 } 4167 4168 if (os_strcmp(cmd, "noa") == 0) { 4169 char *pos; 4170 int count, start, duration; 4171 /* GO NoA parameters: count,start_offset(ms),duration(ms) */ 4172 count = atoi(param); 4173 pos = os_strchr(param, ','); 4174 if (pos == NULL) 4175 return -1; 4176 pos++; 4177 start = atoi(pos); 4178 pos = os_strchr(pos, ','); 4179 if (pos == NULL) 4180 return -1; 4181 pos++; 4182 duration = atoi(pos); 4183 if (count < 0 || count > 255 || start < 0 || duration < 0) 4184 return -1; 4185 if (count == 0 && duration > 0) 4186 return -1; 4187 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d " 4188 "start=%d duration=%d", count, start, duration); 4189 return wpas_p2p_set_noa(wpa_s, count, start, duration); 4190 } 4191 4192 if (os_strcmp(cmd, "ps") == 0) 4193 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1); 4194 4195 if (os_strcmp(cmd, "oppps") == 0) 4196 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1); 4197 4198 if (os_strcmp(cmd, "ctwindow") == 0) 4199 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param)); 4200 4201 if (os_strcmp(cmd, "disabled") == 0) { 4202 wpa_s->global->p2p_disabled = atoi(param); 4203 wpa_printf(MSG_DEBUG, "P2P functionality %s", 4204 wpa_s->global->p2p_disabled ? 4205 "disabled" : "enabled"); 4206 if (wpa_s->global->p2p_disabled) { 4207 wpas_p2p_stop_find(wpa_s); 4208 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 4209 p2p_flush(wpa_s->global->p2p); 4210 } 4211 return 0; 4212 } 4213 4214 if (os_strcmp(cmd, "conc_pref") == 0) { 4215 if (os_strcmp(param, "sta") == 0) 4216 wpa_s->global->conc_pref = WPA_CONC_PREF_STA; 4217 else if (os_strcmp(param, "p2p") == 0) 4218 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P; 4219 else { 4220 wpa_printf(MSG_INFO, "Invalid conc_pref value"); 4221 return -1; 4222 } 4223 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: " 4224 "%s", param); 4225 return 0; 4226 } 4227 4228 if (os_strcmp(cmd, "force_long_sd") == 0) { 4229 wpa_s->force_long_sd = atoi(param); 4230 return 0; 4231 } 4232 4233 if (os_strcmp(cmd, "peer_filter") == 0) { 4234 u8 addr[ETH_ALEN]; 4235 if (hwaddr_aton(param, addr)) 4236 return -1; 4237 p2p_set_peer_filter(wpa_s->global->p2p, addr); 4238 return 0; 4239 } 4240 4241 if (os_strcmp(cmd, "cross_connect") == 0) 4242 return wpas_p2p_set_cross_connect(wpa_s, atoi(param)); 4243 4244 if (os_strcmp(cmd, "go_apsd") == 0) { 4245 if (os_strcmp(param, "disable") == 0) 4246 wpa_s->set_ap_uapsd = 0; 4247 else { 4248 wpa_s->set_ap_uapsd = 1; 4249 wpa_s->ap_uapsd = atoi(param); 4250 } 4251 return 0; 4252 } 4253 4254 if (os_strcmp(cmd, "client_apsd") == 0) { 4255 if (os_strcmp(param, "disable") == 0) 4256 wpa_s->set_sta_uapsd = 0; 4257 else { 4258 int be, bk, vi, vo; 4259 char *pos; 4260 /* format: BE,BK,VI,VO;max SP Length */ 4261 be = atoi(param); 4262 pos = os_strchr(param, ','); 4263 if (pos == NULL) 4264 return -1; 4265 pos++; 4266 bk = atoi(pos); 4267 pos = os_strchr(pos, ','); 4268 if (pos == NULL) 4269 return -1; 4270 pos++; 4271 vi = atoi(pos); 4272 pos = os_strchr(pos, ','); 4273 if (pos == NULL) 4274 return -1; 4275 pos++; 4276 vo = atoi(pos); 4277 /* ignore max SP Length for now */ 4278 4279 wpa_s->set_sta_uapsd = 1; 4280 wpa_s->sta_uapsd = 0; 4281 if (be) 4282 wpa_s->sta_uapsd |= BIT(0); 4283 if (bk) 4284 wpa_s->sta_uapsd |= BIT(1); 4285 if (vi) 4286 wpa_s->sta_uapsd |= BIT(2); 4287 if (vo) 4288 wpa_s->sta_uapsd |= BIT(3); 4289 } 4290 return 0; 4291 } 4292 4293 if (os_strcmp(cmd, "disallow_freq") == 0) 4294 return p2p_ctrl_disallow_freq(wpa_s, param); 4295 4296 if (os_strcmp(cmd, "disc_int") == 0) { 4297 int min_disc_int, max_disc_int, max_disc_tu; 4298 char *pos; 4299 4300 pos = param; 4301 4302 min_disc_int = atoi(pos); 4303 pos = os_strchr(pos, ' '); 4304 if (pos == NULL) 4305 return -1; 4306 *pos++ = '\0'; 4307 4308 max_disc_int = atoi(pos); 4309 pos = os_strchr(pos, ' '); 4310 if (pos == NULL) 4311 return -1; 4312 *pos++ = '\0'; 4313 4314 max_disc_tu = atoi(pos); 4315 4316 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int, 4317 max_disc_int, max_disc_tu); 4318 } 4319 4320 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", 4321 cmd); 4322 4323 return -1; 4324} 4325 4326 4327static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd) 4328{ 4329 char *pos, *pos2; 4330 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0; 4331 4332 if (cmd[0]) { 4333 pos = os_strchr(cmd, ' '); 4334 if (pos == NULL) 4335 return -1; 4336 *pos++ = '\0'; 4337 dur1 = atoi(cmd); 4338 4339 pos2 = os_strchr(pos, ' '); 4340 if (pos2) 4341 *pos2++ = '\0'; 4342 int1 = atoi(pos); 4343 } else 4344 pos2 = NULL; 4345 4346 if (pos2) { 4347 pos = os_strchr(pos2, ' '); 4348 if (pos == NULL) 4349 return -1; 4350 *pos++ = '\0'; 4351 dur2 = atoi(pos2); 4352 int2 = atoi(pos); 4353 } 4354 4355 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2); 4356} 4357 4358 4359static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd) 4360{ 4361 char *pos; 4362 unsigned int period = 0, interval = 0; 4363 4364 if (cmd[0]) { 4365 pos = os_strchr(cmd, ' '); 4366 if (pos == NULL) 4367 return -1; 4368 *pos++ = '\0'; 4369 period = atoi(cmd); 4370 interval = atoi(pos); 4371 } 4372 4373 return wpas_p2p_ext_listen(wpa_s, period, interval); 4374} 4375 4376#endif /* CONFIG_P2P */ 4377 4378 4379#ifdef CONFIG_INTERWORKING 4380static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst) 4381{ 4382 u8 bssid[ETH_ALEN]; 4383 struct wpa_bss *bss; 4384 4385 if (hwaddr_aton(dst, bssid)) { 4386 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst); 4387 return -1; 4388 } 4389 4390 bss = wpa_bss_get_bssid(wpa_s, bssid); 4391 if (bss == NULL) { 4392 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR, 4393 MAC2STR(bssid)); 4394 return -1; 4395 } 4396 4397 return interworking_connect(wpa_s, bss); 4398} 4399 4400 4401static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) 4402{ 4403 u8 dst_addr[ETH_ALEN]; 4404 int used; 4405 char *pos; 4406#define MAX_ANQP_INFO_ID 100 4407 u16 id[MAX_ANQP_INFO_ID]; 4408 size_t num_id = 0; 4409 4410 used = hwaddr_aton2(dst, dst_addr); 4411 if (used < 0) 4412 return -1; 4413 pos = dst + used; 4414 while (num_id < MAX_ANQP_INFO_ID) { 4415 id[num_id] = atoi(pos); 4416 if (id[num_id]) 4417 num_id++; 4418 pos = os_strchr(pos + 1, ','); 4419 if (pos == NULL) 4420 break; 4421 pos++; 4422 } 4423 4424 if (num_id == 0) 4425 return -1; 4426 4427 return anqp_send_req(wpa_s, dst_addr, id, num_id); 4428} 4429 4430 4431static int gas_request(struct wpa_supplicant *wpa_s, char *cmd) 4432{ 4433 u8 dst_addr[ETH_ALEN]; 4434 struct wpabuf *advproto, *query = NULL; 4435 int used, ret = -1; 4436 char *pos, *end; 4437 size_t len; 4438 4439 used = hwaddr_aton2(cmd, dst_addr); 4440 if (used < 0) 4441 return -1; 4442 4443 pos = cmd + used; 4444 while (*pos == ' ') 4445 pos++; 4446 4447 /* Advertisement Protocol ID */ 4448 end = os_strchr(pos, ' '); 4449 if (end) 4450 len = end - pos; 4451 else 4452 len = os_strlen(pos); 4453 if (len & 0x01) 4454 return -1; 4455 len /= 2; 4456 if (len == 0) 4457 return -1; 4458 advproto = wpabuf_alloc(len); 4459 if (advproto == NULL) 4460 return -1; 4461 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0) 4462 goto fail; 4463 4464 if (end) { 4465 /* Optional Query Request */ 4466 pos = end + 1; 4467 while (*pos == ' ') 4468 pos++; 4469 4470 len = os_strlen(pos); 4471 if (len) { 4472 if (len & 0x01) 4473 goto fail; 4474 len /= 2; 4475 if (len == 0) 4476 goto fail; 4477 query = wpabuf_alloc(len); 4478 if (query == NULL) 4479 goto fail; 4480 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0) 4481 goto fail; 4482 } 4483 } 4484 4485 ret = gas_send_request(wpa_s, dst_addr, advproto, query); 4486 4487fail: 4488 wpabuf_free(advproto); 4489 wpabuf_free(query); 4490 4491 return ret; 4492} 4493 4494 4495static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf, 4496 size_t buflen) 4497{ 4498 u8 addr[ETH_ALEN]; 4499 int dialog_token; 4500 int used; 4501 char *pos; 4502 size_t resp_len, start, requested_len; 4503 4504 if (!wpa_s->last_gas_resp) 4505 return -1; 4506 4507 used = hwaddr_aton2(cmd, addr); 4508 if (used < 0) 4509 return -1; 4510 4511 pos = cmd + used; 4512 while (*pos == ' ') 4513 pos++; 4514 dialog_token = atoi(pos); 4515 4516 if (os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) != 0 || 4517 dialog_token != wpa_s->last_gas_dialog_token) 4518 return -1; 4519 4520 resp_len = wpabuf_len(wpa_s->last_gas_resp); 4521 start = 0; 4522 requested_len = resp_len; 4523 4524 pos = os_strchr(pos, ' '); 4525 if (pos) { 4526 start = atoi(pos); 4527 if (start > resp_len) 4528 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 4529 pos = os_strchr(pos, ','); 4530 if (pos == NULL) 4531 return -1; 4532 pos++; 4533 requested_len = atoi(pos); 4534 if (start + requested_len > resp_len) 4535 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 4536 } 4537 4538 if (requested_len * 2 + 1 > buflen) 4539 return os_snprintf(buf, buflen, "FAIL-Too long response"); 4540 4541 return wpa_snprintf_hex(buf, buflen, 4542 wpabuf_head_u8(wpa_s->last_gas_resp) + start, 4543 requested_len); 4544} 4545#endif /* CONFIG_INTERWORKING */ 4546 4547 4548#ifdef CONFIG_HS20 4549 4550static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst) 4551{ 4552 u8 dst_addr[ETH_ALEN]; 4553 int used; 4554 char *pos; 4555 u32 subtypes = 0; 4556 4557 used = hwaddr_aton2(dst, dst_addr); 4558 if (used < 0) 4559 return -1; 4560 pos = dst + used; 4561 for (;;) { 4562 int num = atoi(pos); 4563 if (num <= 0 || num > 31) 4564 return -1; 4565 subtypes |= BIT(num); 4566 pos = os_strchr(pos + 1, ','); 4567 if (pos == NULL) 4568 break; 4569 pos++; 4570 } 4571 4572 if (subtypes == 0) 4573 return -1; 4574 4575 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0); 4576} 4577 4578 4579static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s, 4580 const u8 *addr, const char *realm) 4581{ 4582 u8 *buf; 4583 size_t rlen, len; 4584 int ret; 4585 4586 rlen = os_strlen(realm); 4587 len = 3 + rlen; 4588 buf = os_malloc(len); 4589 if (buf == NULL) 4590 return -1; 4591 buf[0] = 1; /* NAI Home Realm Count */ 4592 buf[1] = 0; /* Formatted in accordance with RFC 4282 */ 4593 buf[2] = rlen; 4594 os_memcpy(buf + 3, realm, rlen); 4595 4596 ret = hs20_anqp_send_req(wpa_s, addr, 4597 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 4598 buf, len); 4599 4600 os_free(buf); 4601 4602 return ret; 4603} 4604 4605 4606static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s, 4607 char *dst) 4608{ 4609 struct wpa_cred *cred = wpa_s->conf->cred; 4610 u8 dst_addr[ETH_ALEN]; 4611 int used; 4612 u8 *buf; 4613 size_t len; 4614 int ret; 4615 4616 used = hwaddr_aton2(dst, dst_addr); 4617 if (used < 0) 4618 return -1; 4619 4620 while (dst[used] == ' ') 4621 used++; 4622 if (os_strncmp(dst + used, "realm=", 6) == 0) 4623 return hs20_nai_home_realm_list(wpa_s, dst_addr, 4624 dst + used + 6); 4625 4626 len = os_strlen(dst + used); 4627 4628 if (len == 0 && cred && cred->realm) 4629 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm); 4630 4631 if (len % 1) 4632 return -1; 4633 len /= 2; 4634 buf = os_malloc(len); 4635 if (buf == NULL) 4636 return -1; 4637 if (hexstr2bin(dst + used, buf, len) < 0) { 4638 os_free(buf); 4639 return -1; 4640 } 4641 4642 ret = hs20_anqp_send_req(wpa_s, dst_addr, 4643 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 4644 buf, len); 4645 os_free(buf); 4646 4647 return ret; 4648} 4649 4650#endif /* CONFIG_HS20 */ 4651 4652 4653static int wpa_supplicant_ctrl_iface_sta_autoconnect( 4654 struct wpa_supplicant *wpa_s, char *cmd) 4655{ 4656 wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0; 4657 return 0; 4658} 4659 4660 4661#ifdef CONFIG_AUTOSCAN 4662 4663static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s, 4664 char *cmd) 4665{ 4666 enum wpa_states state = wpa_s->wpa_state; 4667 char *new_params = NULL; 4668 4669 if (os_strlen(cmd) > 0) { 4670 new_params = os_strdup(cmd); 4671 if (new_params == NULL) 4672 return -1; 4673 } 4674 4675 os_free(wpa_s->conf->autoscan); 4676 wpa_s->conf->autoscan = new_params; 4677 4678 if (wpa_s->conf->autoscan == NULL) 4679 autoscan_deinit(wpa_s); 4680 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) 4681 autoscan_init(wpa_s, 1); 4682 else if (state == WPA_SCANNING) 4683 wpa_supplicant_reinit_autoscan(wpa_s); 4684 4685 return 0; 4686} 4687 4688#endif /* CONFIG_AUTOSCAN */ 4689 4690 4691#ifdef CONFIG_WNM 4692 4693static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd) 4694{ 4695 int enter; 4696 int intval = 0; 4697 char *pos; 4698 int ret; 4699 struct wpabuf *tfs_req = NULL; 4700 4701 if (os_strncmp(cmd, "enter", 5) == 0) 4702 enter = 1; 4703 else if (os_strncmp(cmd, "exit", 4) == 0) 4704 enter = 0; 4705 else 4706 return -1; 4707 4708 pos = os_strstr(cmd, " interval="); 4709 if (pos) 4710 intval = atoi(pos + 10); 4711 4712 pos = os_strstr(cmd, " tfs_req="); 4713 if (pos) { 4714 char *end; 4715 size_t len; 4716 pos += 9; 4717 end = os_strchr(pos, ' '); 4718 if (end) 4719 len = end - pos; 4720 else 4721 len = os_strlen(pos); 4722 if (len & 1) 4723 return -1; 4724 len /= 2; 4725 tfs_req = wpabuf_alloc(len); 4726 if (tfs_req == NULL) 4727 return -1; 4728 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) { 4729 wpabuf_free(tfs_req); 4730 return -1; 4731 } 4732 } 4733 4734 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER : 4735 WNM_SLEEP_MODE_EXIT, intval, 4736 tfs_req); 4737 wpabuf_free(tfs_req); 4738 4739 return ret; 4740} 4741 4742#endif /* CONFIG_WNM */ 4743 4744 4745static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf, 4746 size_t buflen) 4747{ 4748 struct wpa_signal_info si; 4749 int ret; 4750 4751 ret = wpa_drv_signal_poll(wpa_s, &si); 4752 if (ret) 4753 return -1; 4754 4755 ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n" 4756 "NOISE=%d\nFREQUENCY=%u\n", 4757 si.current_signal, si.current_txrate / 1000, 4758 si.current_noise, si.frequency); 4759 if (ret < 0 || (unsigned int) ret > buflen) 4760 return -1; 4761 return ret; 4762} 4763 4764 4765static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, 4766 size_t buflen) 4767{ 4768 struct hostap_sta_driver_data sta; 4769 int ret; 4770 4771 ret = wpa_drv_pktcnt_poll(wpa_s, &sta); 4772 if (ret) 4773 return -1; 4774 4775 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n", 4776 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets); 4777 if (ret < 0 || (size_t) ret > buflen) 4778 return -1; 4779 return ret; 4780} 4781 4782 4783char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 4784 char *buf, size_t *resp_len) 4785{ 4786 char *reply; 4787 const int reply_size = 4096; 4788 int ctrl_rsp = 0; 4789 int reply_len; 4790 4791 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 4792 os_strncmp(buf, "SET_NETWORK ", 12) == 0 || 4793 os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 || 4794 os_strncmp(buf, "NFC_RX_HANDOVER_SEL", 19) == 0) { 4795 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 4796 (const u8 *) buf, os_strlen(buf)); 4797 } else { 4798 int level = MSG_DEBUG; 4799 if (os_strcmp(buf, "PING") == 0) 4800 level = MSG_EXCESSIVE; 4801 wpa_hexdump_ascii(level, "RX ctrl_iface", 4802 (const u8 *) buf, os_strlen(buf)); 4803 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf); 4804 } 4805 4806 reply = os_malloc(reply_size); 4807 if (reply == NULL) { 4808 *resp_len = 1; 4809 return NULL; 4810 } 4811 4812 os_memcpy(reply, "OK\n", 3); 4813 reply_len = 3; 4814 4815 if (os_strcmp(buf, "PING") == 0) { 4816 os_memcpy(reply, "PONG\n", 5); 4817 reply_len = 5; 4818 } else if (os_strcmp(buf, "IFNAME") == 0) { 4819 reply_len = os_strlen(wpa_s->ifname); 4820 os_memcpy(reply, wpa_s->ifname, reply_len); 4821 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 4822 if (wpa_debug_reopen_file() < 0) 4823 reply_len = -1; 4824 } else if (os_strncmp(buf, "NOTE ", 5) == 0) { 4825 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); 4826 } else if (os_strcmp(buf, "MIB") == 0) { 4827 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 4828 if (reply_len >= 0) { 4829 int res; 4830 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, 4831 reply_size - reply_len); 4832 if (res < 0) 4833 reply_len = -1; 4834 else 4835 reply_len += res; 4836 } 4837 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 4838 reply_len = wpa_supplicant_ctrl_iface_status( 4839 wpa_s, buf + 6, reply, reply_size); 4840 } else if (os_strcmp(buf, "PMKSA") == 0) { 4841 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply, 4842 reply_size); 4843 } else if (os_strncmp(buf, "SET ", 4) == 0) { 4844 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 4845 reply_len = -1; 4846 } else if (os_strncmp(buf, "GET ", 4) == 0) { 4847 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4, 4848 reply, reply_size); 4849 } else if (os_strcmp(buf, "LOGON") == 0) { 4850 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 4851 } else if (os_strcmp(buf, "LOGOFF") == 0) { 4852 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 4853 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 4854 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 4855 reply_len = -1; 4856 else 4857 wpas_request_connection(wpa_s); 4858 } else if (os_strcmp(buf, "RECONNECT") == 0) { 4859 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 4860 reply_len = -1; 4861 else if (wpa_s->disconnected) 4862 wpas_request_connection(wpa_s); 4863#ifdef IEEE8021X_EAPOL 4864 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 4865 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 4866 reply_len = -1; 4867#endif /* IEEE8021X_EAPOL */ 4868#ifdef CONFIG_PEERKEY 4869 } else if (os_strncmp(buf, "STKSTART ", 9) == 0) { 4870 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9)) 4871 reply_len = -1; 4872#endif /* CONFIG_PEERKEY */ 4873#ifdef CONFIG_IEEE80211R 4874 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 4875 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 4876 reply_len = -1; 4877#endif /* CONFIG_IEEE80211R */ 4878#ifdef CONFIG_WPS 4879 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 4880 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL); 4881 if (res == -2) { 4882 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 4883 reply_len = 17; 4884 } else if (res) 4885 reply_len = -1; 4886 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 4887 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8); 4888 if (res == -2) { 4889 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 4890 reply_len = 17; 4891 } else if (res) 4892 reply_len = -1; 4893 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 4894 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 4895 reply, 4896 reply_size); 4897 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 4898 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin( 4899 wpa_s, buf + 14, reply, reply_size); 4900 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 4901 if (wpas_wps_cancel(wpa_s)) 4902 reply_len = -1; 4903#ifdef CONFIG_WPS_NFC 4904 } else if (os_strcmp(buf, "WPS_NFC") == 0) { 4905 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL)) 4906 reply_len = -1; 4907 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) { 4908 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8)) 4909 reply_len = -1; 4910 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 4911 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token( 4912 wpa_s, buf + 14, reply, reply_size); 4913 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 4914 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s, 4915 buf + 17)) 4916 reply_len = -1; 4917 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) { 4918 reply_len = wpas_ctrl_nfc_get_handover_req( 4919 wpa_s, buf + 21, reply, reply_size); 4920 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 4921 reply_len = wpas_ctrl_nfc_get_handover_sel( 4922 wpa_s, buf + 21, reply, reply_size); 4923 } else if (os_strncmp(buf, "NFC_RX_HANDOVER_REQ ", 20) == 0) { 4924 reply_len = wpas_ctrl_nfc_rx_handover_req( 4925 wpa_s, buf + 20, reply, reply_size); 4926 } else if (os_strncmp(buf, "NFC_RX_HANDOVER_SEL ", 20) == 0) { 4927 if (wpas_ctrl_nfc_rx_handover_sel(wpa_s, buf + 20)) 4928 reply_len = -1; 4929#endif /* CONFIG_WPS_NFC */ 4930 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 4931 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 4932 reply_len = -1; 4933#ifdef CONFIG_AP 4934 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 4935 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin( 4936 wpa_s, buf + 11, reply, reply_size); 4937#endif /* CONFIG_AP */ 4938#ifdef CONFIG_WPS_ER 4939 } else if (os_strcmp(buf, "WPS_ER_START") == 0) { 4940 if (wpas_wps_er_start(wpa_s, NULL)) 4941 reply_len = -1; 4942 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) { 4943 if (wpas_wps_er_start(wpa_s, buf + 13)) 4944 reply_len = -1; 4945 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) { 4946 if (wpas_wps_er_stop(wpa_s)) 4947 reply_len = -1; 4948 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) { 4949 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11)) 4950 reply_len = -1; 4951 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) { 4952 int ret = wpas_wps_er_pbc(wpa_s, buf + 11); 4953 if (ret == -2) { 4954 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 4955 reply_len = 17; 4956 } else if (ret == -3) { 4957 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18); 4958 reply_len = 18; 4959 } else if (ret == -4) { 4960 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20); 4961 reply_len = 20; 4962 } else if (ret) 4963 reply_len = -1; 4964 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { 4965 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) 4966 reply_len = -1; 4967 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) { 4968 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s, 4969 buf + 18)) 4970 reply_len = -1; 4971 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) { 4972 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14)) 4973 reply_len = -1; 4974#ifdef CONFIG_WPS_NFC 4975 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) { 4976 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 4977 wpa_s, buf + 24, reply, reply_size); 4978#endif /* CONFIG_WPS_NFC */ 4979#endif /* CONFIG_WPS_ER */ 4980#endif /* CONFIG_WPS */ 4981#ifdef CONFIG_IBSS_RSN 4982 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) { 4983 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9)) 4984 reply_len = -1; 4985#endif /* CONFIG_IBSS_RSN */ 4986#ifdef CONFIG_P2P 4987 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) { 4988 if (p2p_ctrl_find(wpa_s, buf + 9)) 4989 reply_len = -1; 4990 } else if (os_strcmp(buf, "P2P_FIND") == 0) { 4991 if (p2p_ctrl_find(wpa_s, "")) 4992 reply_len = -1; 4993 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) { 4994 wpas_p2p_stop_find(wpa_s); 4995 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) { 4996 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply, 4997 reply_size); 4998 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) { 4999 if (p2p_ctrl_listen(wpa_s, buf + 11)) 5000 reply_len = -1; 5001 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) { 5002 if (p2p_ctrl_listen(wpa_s, "")) 5003 reply_len = -1; 5004 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) { 5005 if (wpas_p2p_group_remove(wpa_s, buf + 17)) 5006 reply_len = -1; 5007 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) { 5008 if (wpas_p2p_group_add(wpa_s, 0, 0, 0)) 5009 reply_len = -1; 5010 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) { 5011 if (p2p_ctrl_group_add(wpa_s, buf + 14)) 5012 reply_len = -1; 5013 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) { 5014 if (p2p_ctrl_prov_disc(wpa_s, buf + 14)) 5015 reply_len = -1; 5016 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) { 5017 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size); 5018 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) { 5019 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply, 5020 reply_size); 5021 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) { 5022 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0) 5023 reply_len = -1; 5024 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) { 5025 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0) 5026 reply_len = -1; 5027 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) { 5028 wpas_p2p_sd_service_update(wpa_s); 5029 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) { 5030 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0) 5031 reply_len = -1; 5032 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) { 5033 wpas_p2p_service_flush(wpa_s); 5034 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) { 5035 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0) 5036 reply_len = -1; 5037 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) { 5038 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0) 5039 reply_len = -1; 5040 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) { 5041 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0) 5042 reply_len = -1; 5043 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) { 5044 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0) 5045 reply_len = -1; 5046 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) { 5047 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply, 5048 reply_size); 5049 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) { 5050 if (p2p_ctrl_set(wpa_s, buf + 8) < 0) 5051 reply_len = -1; 5052 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) { 5053 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 5054 wpa_s->force_long_sd = 0; 5055 if (wpa_s->global->p2p) 5056 p2p_flush(wpa_s->global->p2p); 5057 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) { 5058 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0) 5059 reply_len = -1; 5060 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) { 5061 if (wpas_p2p_cancel(wpa_s)) 5062 reply_len = -1; 5063 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) { 5064 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0) 5065 reply_len = -1; 5066 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) { 5067 if (p2p_ctrl_presence_req(wpa_s, "") < 0) 5068 reply_len = -1; 5069 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) { 5070 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0) 5071 reply_len = -1; 5072 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) { 5073 if (p2p_ctrl_ext_listen(wpa_s, "") < 0) 5074 reply_len = -1; 5075#endif /* CONFIG_P2P */ 5076#ifdef CONFIG_WIFI_DISPLAY 5077 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) { 5078 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0) 5079 reply_len = -1; 5080 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) { 5081 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16, 5082 reply, reply_size); 5083#endif /* CONFIG_WIFI_DISPLAY */ 5084#ifdef CONFIG_INTERWORKING 5085 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) { 5086 if (interworking_fetch_anqp(wpa_s) < 0) 5087 reply_len = -1; 5088 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) { 5089 interworking_stop_fetch_anqp(wpa_s); 5090 } else if (os_strncmp(buf, "INTERWORKING_SELECT", 19) == 0) { 5091 if (interworking_select(wpa_s, os_strstr(buf + 19, "auto") != 5092 NULL) < 0) 5093 reply_len = -1; 5094 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) { 5095 if (ctrl_interworking_connect(wpa_s, buf + 21) < 0) 5096 reply_len = -1; 5097 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) { 5098 if (get_anqp(wpa_s, buf + 9) < 0) 5099 reply_len = -1; 5100 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) { 5101 if (gas_request(wpa_s, buf + 12) < 0) 5102 reply_len = -1; 5103 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) { 5104 reply_len = gas_response_get(wpa_s, buf + 17, reply, 5105 reply_size); 5106#endif /* CONFIG_INTERWORKING */ 5107#ifdef CONFIG_HS20 5108 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) { 5109 if (get_hs20_anqp(wpa_s, buf + 14) < 0) 5110 reply_len = -1; 5111 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) { 5112 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0) 5113 reply_len = -1; 5114#endif /* CONFIG_HS20 */ 5115 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 5116 { 5117 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 5118 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 5119 reply_len = -1; 5120 else 5121 ctrl_rsp = 1; 5122 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 5123 if (wpa_supplicant_reload_configuration(wpa_s)) 5124 reply_len = -1; 5125 } else if (os_strcmp(buf, "TERMINATE") == 0) { 5126 wpa_supplicant_terminate_proc(wpa_s->global); 5127 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 5128 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 5129 reply_len = -1; 5130 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { 5131 reply_len = wpa_supplicant_ctrl_iface_blacklist( 5132 wpa_s, buf + 9, reply, reply_size); 5133 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 5134 reply_len = wpa_supplicant_ctrl_iface_log_level( 5135 wpa_s, buf + 9, reply, reply_size); 5136 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 5137 reply_len = wpa_supplicant_ctrl_iface_list_networks( 5138 wpa_s, reply, reply_size); 5139 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 5140#ifdef CONFIG_SME 5141 wpa_s->sme.prev_bssid_set = 0; 5142#endif /* CONFIG_SME */ 5143 wpa_s->reassociate = 0; 5144 wpa_s->disconnected = 1; 5145 wpa_supplicant_cancel_sched_scan(wpa_s); 5146 wpa_supplicant_cancel_scan(wpa_s); 5147 wpa_supplicant_deauthenticate(wpa_s, 5148 WLAN_REASON_DEAUTH_LEAVING); 5149 } else if (os_strcmp(buf, "SCAN") == 0) { 5150 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 5151 reply_len = -1; 5152 else { 5153 if (!wpa_s->sched_scanning && !wpa_s->scanning && 5154 ((wpa_s->wpa_state <= WPA_SCANNING) || 5155 (wpa_s->wpa_state == WPA_COMPLETED))) { 5156 wpa_s->normal_scans = 0; 5157 wpa_s->scan_req = MANUAL_SCAN_REQ; 5158 wpa_supplicant_req_scan(wpa_s, 0, 0); 5159 } else if (wpa_s->sched_scanning) { 5160 wpa_printf(MSG_DEBUG, "Stop ongoing " 5161 "sched_scan to allow requested " 5162 "full scan to proceed"); 5163 wpa_supplicant_cancel_sched_scan(wpa_s); 5164 wpa_s->scan_req = MANUAL_SCAN_REQ; 5165 wpa_supplicant_req_scan(wpa_s, 0, 0); 5166 } else { 5167 wpa_printf(MSG_DEBUG, "Ongoing scan action - " 5168 "reject new request"); 5169 reply_len = os_snprintf(reply, reply_size, 5170 "FAIL-BUSY\n"); 5171 } 5172 } 5173 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 5174 reply_len = wpa_supplicant_ctrl_iface_scan_results( 5175 wpa_s, reply, reply_size); 5176 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 5177 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 5178 reply_len = -1; 5179 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 5180 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 5181 reply_len = -1; 5182 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 5183 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 5184 reply_len = -1; 5185 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 5186 reply_len = wpa_supplicant_ctrl_iface_add_network( 5187 wpa_s, reply, reply_size); 5188 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 5189 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 5190 reply_len = -1; 5191 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 5192 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 5193 reply_len = -1; 5194 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 5195 reply_len = wpa_supplicant_ctrl_iface_get_network( 5196 wpa_s, buf + 12, reply, reply_size); 5197 } else if (os_strcmp(buf, "LIST_CREDS") == 0) { 5198 reply_len = wpa_supplicant_ctrl_iface_list_creds( 5199 wpa_s, reply, reply_size); 5200 } else if (os_strcmp(buf, "ADD_CRED") == 0) { 5201 reply_len = wpa_supplicant_ctrl_iface_add_cred( 5202 wpa_s, reply, reply_size); 5203 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) { 5204 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12)) 5205 reply_len = -1; 5206 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) { 5207 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9)) 5208 reply_len = -1; 5209#ifndef CONFIG_NO_CONFIG_WRITE 5210 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 5211 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 5212 reply_len = -1; 5213#endif /* CONFIG_NO_CONFIG_WRITE */ 5214 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 5215 reply_len = wpa_supplicant_ctrl_iface_get_capability( 5216 wpa_s, buf + 15, reply, reply_size); 5217 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 5218 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 5219 reply_len = -1; 5220 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) { 5221 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14)) 5222 reply_len = -1; 5223 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 5224 reply_len = wpa_supplicant_global_iface_list( 5225 wpa_s->global, reply, reply_size); 5226 } else if (os_strcmp(buf, "INTERFACES") == 0) { 5227 reply_len = wpa_supplicant_global_iface_interfaces( 5228 wpa_s->global, reply, reply_size); 5229 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 5230 reply_len = wpa_supplicant_ctrl_iface_bss( 5231 wpa_s, buf + 4, reply, reply_size); 5232#ifdef CONFIG_AP 5233 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 5234 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); 5235 } else if (os_strncmp(buf, "STA ", 4) == 0) { 5236 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply, 5237 reply_size); 5238 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 5239 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, 5240 reply_size); 5241 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 5242 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15)) 5243 reply_len = -1; 5244 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 5245 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13)) 5246 reply_len = -1; 5247#endif /* CONFIG_AP */ 5248 } else if (os_strcmp(buf, "SUSPEND") == 0) { 5249 wpas_notify_suspend(wpa_s->global); 5250 } else if (os_strcmp(buf, "RESUME") == 0) { 5251 wpas_notify_resume(wpa_s->global); 5252 } else if (os_strcmp(buf, "DROP_SA") == 0) { 5253 wpa_supplicant_ctrl_iface_drop_sa(wpa_s); 5254 } else if (os_strncmp(buf, "ROAM ", 5) == 0) { 5255 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) 5256 reply_len = -1; 5257 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) { 5258 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16)) 5259 reply_len = -1; 5260 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) { 5261 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15)) 5262 reply_len = -1; 5263 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) { 5264 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s, 5265 buf + 17)) 5266 reply_len = -1; 5267 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) { 5268 if (wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10)) 5269 reply_len = -1; 5270#ifdef CONFIG_TDLS 5271 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) { 5272 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14)) 5273 reply_len = -1; 5274 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) { 5275 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11)) 5276 reply_len = -1; 5277 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) { 5278 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14)) 5279 reply_len = -1; 5280#endif /* CONFIG_TDLS */ 5281 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) { 5282 reply_len = wpa_supplicant_signal_poll(wpa_s, reply, 5283 reply_size); 5284 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) { 5285 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply, 5286 reply_size); 5287#ifdef CONFIG_AUTOSCAN 5288 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) { 5289 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9)) 5290 reply_len = -1; 5291#endif /* CONFIG_AUTOSCAN */ 5292 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) { 5293 pmksa_cache_clear_current(wpa_s->wpa); 5294 eapol_sm_request_reauth(wpa_s->eapol); 5295#ifdef CONFIG_WNM 5296 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) { 5297 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10)) 5298 reply_len = -1; 5299#endif /* CONFIG_WNM */ 5300 } else { 5301 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 5302 reply_len = 16; 5303 } 5304 5305 if (reply_len < 0) { 5306 os_memcpy(reply, "FAIL\n", 5); 5307 reply_len = 5; 5308 } 5309 5310 if (ctrl_rsp) 5311 eapol_sm_notify_ctrl_response(wpa_s->eapol); 5312 5313 *resp_len = reply_len; 5314 return reply; 5315} 5316 5317 5318static int wpa_supplicant_global_iface_add(struct wpa_global *global, 5319 char *cmd) 5320{ 5321 struct wpa_interface iface; 5322 char *pos; 5323 5324 /* 5325 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 5326 * TAB<bridge_ifname> 5327 */ 5328 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 5329 5330 os_memset(&iface, 0, sizeof(iface)); 5331 5332 do { 5333 iface.ifname = pos = cmd; 5334 pos = os_strchr(pos, '\t'); 5335 if (pos) 5336 *pos++ = '\0'; 5337 if (iface.ifname[0] == '\0') 5338 return -1; 5339 if (pos == NULL) 5340 break; 5341 5342 iface.confname = pos; 5343 pos = os_strchr(pos, '\t'); 5344 if (pos) 5345 *pos++ = '\0'; 5346 if (iface.confname[0] == '\0') 5347 iface.confname = NULL; 5348 if (pos == NULL) 5349 break; 5350 5351 iface.driver = pos; 5352 pos = os_strchr(pos, '\t'); 5353 if (pos) 5354 *pos++ = '\0'; 5355 if (iface.driver[0] == '\0') 5356 iface.driver = NULL; 5357 if (pos == NULL) 5358 break; 5359 5360 iface.ctrl_interface = pos; 5361 pos = os_strchr(pos, '\t'); 5362 if (pos) 5363 *pos++ = '\0'; 5364 if (iface.ctrl_interface[0] == '\0') 5365 iface.ctrl_interface = NULL; 5366 if (pos == NULL) 5367 break; 5368 5369 iface.driver_param = pos; 5370 pos = os_strchr(pos, '\t'); 5371 if (pos) 5372 *pos++ = '\0'; 5373 if (iface.driver_param[0] == '\0') 5374 iface.driver_param = NULL; 5375 if (pos == NULL) 5376 break; 5377 5378 iface.bridge_ifname = pos; 5379 pos = os_strchr(pos, '\t'); 5380 if (pos) 5381 *pos++ = '\0'; 5382 if (iface.bridge_ifname[0] == '\0') 5383 iface.bridge_ifname = NULL; 5384 if (pos == NULL) 5385 break; 5386 } while (0); 5387 5388 if (wpa_supplicant_get_iface(global, iface.ifname)) 5389 return -1; 5390 5391 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1; 5392} 5393 5394 5395static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 5396 char *cmd) 5397{ 5398 struct wpa_supplicant *wpa_s; 5399 5400 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 5401 5402 wpa_s = wpa_supplicant_get_iface(global, cmd); 5403 if (wpa_s == NULL) 5404 return -1; 5405 return wpa_supplicant_remove_iface(global, wpa_s, 0); 5406} 5407 5408 5409static void wpa_free_iface_info(struct wpa_interface_info *iface) 5410{ 5411 struct wpa_interface_info *prev; 5412 5413 while (iface) { 5414 prev = iface; 5415 iface = iface->next; 5416 5417 os_free(prev->ifname); 5418 os_free(prev->desc); 5419 os_free(prev); 5420 } 5421} 5422 5423 5424static int wpa_supplicant_global_iface_list(struct wpa_global *global, 5425 char *buf, int len) 5426{ 5427 int i, res; 5428 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 5429 char *pos, *end; 5430 5431 for (i = 0; wpa_drivers[i]; i++) { 5432 struct wpa_driver_ops *drv = wpa_drivers[i]; 5433 if (drv->get_interfaces == NULL) 5434 continue; 5435 tmp = drv->get_interfaces(global->drv_priv[i]); 5436 if (tmp == NULL) 5437 continue; 5438 5439 if (last == NULL) 5440 iface = last = tmp; 5441 else 5442 last->next = tmp; 5443 while (last->next) 5444 last = last->next; 5445 } 5446 5447 pos = buf; 5448 end = buf + len; 5449 for (tmp = iface; tmp; tmp = tmp->next) { 5450 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 5451 tmp->drv_name, tmp->ifname, 5452 tmp->desc ? tmp->desc : ""); 5453 if (res < 0 || res >= end - pos) { 5454 *pos = '\0'; 5455 break; 5456 } 5457 pos += res; 5458 } 5459 5460 wpa_free_iface_info(iface); 5461 5462 return pos - buf; 5463} 5464 5465 5466static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 5467 char *buf, int len) 5468{ 5469 int res; 5470 char *pos, *end; 5471 struct wpa_supplicant *wpa_s; 5472 5473 wpa_s = global->ifaces; 5474 pos = buf; 5475 end = buf + len; 5476 5477 while (wpa_s) { 5478 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname); 5479 if (res < 0 || res >= end - pos) { 5480 *pos = '\0'; 5481 break; 5482 } 5483 pos += res; 5484 wpa_s = wpa_s->next; 5485 } 5486 return pos - buf; 5487} 5488 5489 5490char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 5491 char *buf, size_t *resp_len) 5492{ 5493 char *reply; 5494 const int reply_size = 2048; 5495 int reply_len; 5496 int level = MSG_DEBUG; 5497 5498 if (os_strcmp(buf, "PING") == 0) 5499 level = MSG_EXCESSIVE; 5500 wpa_hexdump_ascii(level, "RX global ctrl_iface", 5501 (const u8 *) buf, os_strlen(buf)); 5502 5503 reply = os_malloc(reply_size); 5504 if (reply == NULL) { 5505 *resp_len = 1; 5506 return NULL; 5507 } 5508 5509 os_memcpy(reply, "OK\n", 3); 5510 reply_len = 3; 5511 5512 if (os_strcmp(buf, "PING") == 0) { 5513 os_memcpy(reply, "PONG\n", 5); 5514 reply_len = 5; 5515 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 5516 if (wpa_supplicant_global_iface_add(global, buf + 14)) 5517 reply_len = -1; 5518 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 5519 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 5520 reply_len = -1; 5521 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 5522 reply_len = wpa_supplicant_global_iface_list( 5523 global, reply, reply_size); 5524 } else if (os_strcmp(buf, "INTERFACES") == 0) { 5525 reply_len = wpa_supplicant_global_iface_interfaces( 5526 global, reply, reply_size); 5527 } else if (os_strcmp(buf, "TERMINATE") == 0) { 5528 wpa_supplicant_terminate_proc(global); 5529 } else if (os_strcmp(buf, "SUSPEND") == 0) { 5530 wpas_notify_suspend(global); 5531 } else if (os_strcmp(buf, "RESUME") == 0) { 5532 wpas_notify_resume(global); 5533 } else { 5534 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 5535 reply_len = 16; 5536 } 5537 5538 if (reply_len < 0) { 5539 os_memcpy(reply, "FAIL\n", 5); 5540 reply_len = 5; 5541 } 5542 5543 *resp_len = reply_len; 5544 return reply; 5545} 5546