ctrl_iface.c revision da134e99c37d7b8d29aab91ba68c54c1d536c598
1/* 2 * WPA Supplicant / Control interface (shared code for all backends) 3 * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9#include "utils/includes.h" 10 11#include "utils/common.h" 12#include "utils/eloop.h" 13#include "utils/uuid.h" 14#include "common/version.h" 15#include "common/ieee802_11_defs.h" 16#include "common/ieee802_11_common.h" 17#include "common/wpa_ctrl.h" 18#include "eap_peer/eap.h" 19#include "eapol_supp/eapol_supp_sm.h" 20#include "rsn_supp/wpa.h" 21#include "rsn_supp/preauth.h" 22#include "rsn_supp/pmksa_cache.h" 23#include "l2_packet/l2_packet.h" 24#include "wps/wps.h" 25#include "config.h" 26#include "wpa_supplicant_i.h" 27#include "driver_i.h" 28#include "wps_supplicant.h" 29#include "ibss_rsn.h" 30#include "ap.h" 31#include "p2p_supplicant.h" 32#include "p2p/p2p.h" 33#include "hs20_supplicant.h" 34#include "wifi_display.h" 35#include "notify.h" 36#include "bss.h" 37#include "scan.h" 38#include "ctrl_iface.h" 39#include "interworking.h" 40#include "blacklist.h" 41#include "autoscan.h" 42#include "wnm_sta.h" 43#include "offchannel.h" 44#include "drivers/driver.h" 45 46static int wpa_supplicant_global_iface_list(struct wpa_global *global, 47 char *buf, int len); 48static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 49 char *buf, int len); 50static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, 51 char *val); 52 53static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val) 54{ 55 char *pos; 56 u8 addr[ETH_ALEN], *filter = NULL, *n; 57 size_t count = 0; 58 59 pos = val; 60 while (pos) { 61 if (*pos == '\0') 62 break; 63 if (hwaddr_aton(pos, addr)) { 64 os_free(filter); 65 return -1; 66 } 67 n = os_realloc_array(filter, count + 1, ETH_ALEN); 68 if (n == NULL) { 69 os_free(filter); 70 return -1; 71 } 72 filter = n; 73 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN); 74 count++; 75 76 pos = os_strchr(pos, ' '); 77 if (pos) 78 pos++; 79 } 80 81 wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN); 82 os_free(wpa_s->bssid_filter); 83 wpa_s->bssid_filter = filter; 84 wpa_s->bssid_filter_count = count; 85 86 return 0; 87} 88 89 90static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val) 91{ 92 char *pos; 93 u8 addr[ETH_ALEN], *bssid = NULL, *n; 94 struct wpa_ssid_value *ssid = NULL, *ns; 95 size_t count = 0, ssid_count = 0; 96 struct wpa_ssid *c; 97 98 /* 99 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | "" 100 * SSID_SPEC ::= ssid <SSID_HEX> 101 * BSSID_SPEC ::= bssid <BSSID_HEX> 102 */ 103 104 pos = val; 105 while (pos) { 106 if (*pos == '\0') 107 break; 108 if (os_strncmp(pos, "bssid ", 6) == 0) { 109 int res; 110 pos += 6; 111 res = hwaddr_aton2(pos, addr); 112 if (res < 0) { 113 os_free(ssid); 114 os_free(bssid); 115 wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 116 "BSSID value '%s'", pos); 117 return -1; 118 } 119 pos += res; 120 n = os_realloc_array(bssid, count + 1, ETH_ALEN); 121 if (n == NULL) { 122 os_free(ssid); 123 os_free(bssid); 124 return -1; 125 } 126 bssid = n; 127 os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN); 128 count++; 129 } else if (os_strncmp(pos, "ssid ", 5) == 0) { 130 char *end; 131 pos += 5; 132 133 end = pos; 134 while (*end) { 135 if (*end == '\0' || *end == ' ') 136 break; 137 end++; 138 } 139 140 ns = os_realloc_array(ssid, ssid_count + 1, 141 sizeof(struct wpa_ssid_value)); 142 if (ns == NULL) { 143 os_free(ssid); 144 os_free(bssid); 145 return -1; 146 } 147 ssid = ns; 148 149 if ((end - pos) & 0x01 || end - pos > 2 * 32 || 150 hexstr2bin(pos, ssid[ssid_count].ssid, 151 (end - pos) / 2) < 0) { 152 os_free(ssid); 153 os_free(bssid); 154 wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 155 "SSID value '%s'", pos); 156 return -1; 157 } 158 ssid[ssid_count].ssid_len = (end - pos) / 2; 159 wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID", 160 ssid[ssid_count].ssid, 161 ssid[ssid_count].ssid_len); 162 ssid_count++; 163 pos = end; 164 } else { 165 wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value " 166 "'%s'", pos); 167 os_free(ssid); 168 os_free(bssid); 169 return -1; 170 } 171 172 pos = os_strchr(pos, ' '); 173 if (pos) 174 pos++; 175 } 176 177 wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN); 178 os_free(wpa_s->disallow_aps_bssid); 179 wpa_s->disallow_aps_bssid = bssid; 180 wpa_s->disallow_aps_bssid_count = count; 181 182 wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count); 183 os_free(wpa_s->disallow_aps_ssid); 184 wpa_s->disallow_aps_ssid = ssid; 185 wpa_s->disallow_aps_ssid_count = ssid_count; 186 187 if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING) 188 return 0; 189 190 c = wpa_s->current_ssid; 191 if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS) 192 return 0; 193 194 if (!disallowed_bssid(wpa_s, wpa_s->bssid) && 195 !disallowed_ssid(wpa_s, c->ssid, c->ssid_len)) 196 return 0; 197 198 wpa_printf(MSG_DEBUG, "Disconnect and try to find another network " 199 "because current AP was marked disallowed"); 200 201#ifdef CONFIG_SME 202 wpa_s->sme.prev_bssid_set = 0; 203#endif /* CONFIG_SME */ 204 wpa_s->reassociate = 1; 205 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 206 wpa_supplicant_req_scan(wpa_s, 0, 0); 207 208 return 0; 209} 210 211 212#ifndef CONFIG_NO_CONFIG_BLOBS 213static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos) 214{ 215 char *name = pos; 216 struct wpa_config_blob *blob; 217 size_t len; 218 219 pos = os_strchr(pos, ' '); 220 if (pos == NULL) 221 return -1; 222 *pos++ = '\0'; 223 len = os_strlen(pos); 224 if (len & 1) 225 return -1; 226 227 wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name); 228 blob = os_zalloc(sizeof(*blob)); 229 if (blob == NULL) 230 return -1; 231 blob->name = os_strdup(name); 232 blob->data = os_malloc(len / 2); 233 if (blob->name == NULL || blob->data == NULL) { 234 wpa_config_free_blob(blob); 235 return -1; 236 } 237 238 if (hexstr2bin(pos, blob->data, len / 2) < 0) { 239 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data"); 240 wpa_config_free_blob(blob); 241 return -1; 242 } 243 blob->len = len / 2; 244 245 wpa_config_set_blob(wpa_s->conf, blob); 246 247 return 0; 248} 249#endif /* CONFIG_NO_CONFIG_BLOBS */ 250 251 252static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd) 253{ 254 char *params; 255 char *pos; 256 int *freqs = NULL; 257 int ret; 258 259 if (atoi(cmd)) { 260 params = os_strchr(cmd, ' '); 261 os_free(wpa_s->manual_sched_scan_freqs); 262 if (params) { 263 params++; 264 pos = os_strstr(params, "freq="); 265 if (pos) 266 freqs = freq_range_to_channel_list(wpa_s, 267 pos + 5); 268 } 269 wpa_s->manual_sched_scan_freqs = freqs; 270 ret = wpas_start_pno(wpa_s); 271 } else { 272 ret = wpas_stop_pno(wpa_s); 273 } 274 return ret; 275} 276 277 278static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 279 char *cmd) 280{ 281 char *value; 282 int ret = 0; 283 284 value = os_strchr(cmd, ' '); 285 if (value == NULL) 286 return -1; 287 *value++ = '\0'; 288 289 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 290 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 291 eapol_sm_configure(wpa_s->eapol, 292 atoi(value), -1, -1, -1); 293 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 294 eapol_sm_configure(wpa_s->eapol, 295 -1, atoi(value), -1, -1); 296 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 297 eapol_sm_configure(wpa_s->eapol, 298 -1, -1, atoi(value), -1); 299 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 300 eapol_sm_configure(wpa_s->eapol, 301 -1, -1, -1, atoi(value)); 302 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 303 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 304 atoi(value))) 305 ret = -1; 306 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 307 0) { 308 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 309 atoi(value))) 310 ret = -1; 311 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 312 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) 313 ret = -1; 314 } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) { 315 wpa_s->wps_fragment_size = atoi(value); 316#ifdef CONFIG_WPS_TESTING 317 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 318 long int val; 319 val = strtol(value, NULL, 0); 320 if (val < 0 || val > 0xff) { 321 ret = -1; 322 wpa_printf(MSG_DEBUG, "WPS: Invalid " 323 "wps_version_number %ld", val); 324 } else { 325 wps_version_number = val; 326 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 327 "version %u.%u", 328 (wps_version_number & 0xf0) >> 4, 329 wps_version_number & 0x0f); 330 } 331 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 332 wps_testing_dummy_cred = atoi(value); 333 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 334 wps_testing_dummy_cred); 335 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) { 336 wps_corrupt_pkhash = atoi(value); 337 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d", 338 wps_corrupt_pkhash); 339#endif /* CONFIG_WPS_TESTING */ 340 } else if (os_strcasecmp(cmd, "ampdu") == 0) { 341 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0) 342 ret = -1; 343#ifdef CONFIG_TDLS 344#ifdef CONFIG_TDLS_TESTING 345 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) { 346 extern unsigned int tdls_testing; 347 tdls_testing = strtol(value, NULL, 0); 348 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing); 349#endif /* CONFIG_TDLS_TESTING */ 350 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) { 351 int disabled = atoi(value); 352 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled); 353 if (disabled) { 354 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0) 355 ret = -1; 356 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0) 357 ret = -1; 358 wpa_tdls_enable(wpa_s->wpa, !disabled); 359#endif /* CONFIG_TDLS */ 360 } else if (os_strcasecmp(cmd, "pno") == 0) { 361 ret = wpas_ctrl_pno(wpa_s, value); 362 } else if (os_strcasecmp(cmd, "radio_disabled") == 0) { 363 int disabled = atoi(value); 364 if (wpa_drv_radio_disable(wpa_s, disabled) < 0) 365 ret = -1; 366 else if (disabled) 367 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 368 } else if (os_strcasecmp(cmd, "uapsd") == 0) { 369 if (os_strcmp(value, "disable") == 0) 370 wpa_s->set_sta_uapsd = 0; 371 else { 372 int be, bk, vi, vo; 373 char *pos; 374 /* format: BE,BK,VI,VO;max SP Length */ 375 be = atoi(value); 376 pos = os_strchr(value, ','); 377 if (pos == NULL) 378 return -1; 379 pos++; 380 bk = atoi(pos); 381 pos = os_strchr(pos, ','); 382 if (pos == NULL) 383 return -1; 384 pos++; 385 vi = atoi(pos); 386 pos = os_strchr(pos, ','); 387 if (pos == NULL) 388 return -1; 389 pos++; 390 vo = atoi(pos); 391 /* ignore max SP Length for now */ 392 393 wpa_s->set_sta_uapsd = 1; 394 wpa_s->sta_uapsd = 0; 395 if (be) 396 wpa_s->sta_uapsd |= BIT(0); 397 if (bk) 398 wpa_s->sta_uapsd |= BIT(1); 399 if (vi) 400 wpa_s->sta_uapsd |= BIT(2); 401 if (vo) 402 wpa_s->sta_uapsd |= BIT(3); 403 } 404 } else if (os_strcasecmp(cmd, "ps") == 0) { 405 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1); 406#ifdef CONFIG_WIFI_DISPLAY 407 } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 408 int enabled = !!atoi(value); 409 if (enabled && !wpa_s->global->p2p) 410 ret = -1; 411 else 412 wifi_display_enable(wpa_s->global, enabled); 413#endif /* CONFIG_WIFI_DISPLAY */ 414 } else if (os_strcasecmp(cmd, "bssid_filter") == 0) { 415 ret = set_bssid_filter(wpa_s, value); 416 } else if (os_strcasecmp(cmd, "disallow_aps") == 0) { 417 ret = set_disallow_aps(wpa_s, value); 418 } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) { 419 wpa_s->no_keep_alive = !!atoi(value); 420#ifdef CONFIG_TESTING_OPTIONS 421 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { 422 wpa_s->ext_mgmt_frame_handling = !!atoi(value); 423#endif /* CONFIG_TESTING_OPTIONS */ 424#ifndef CONFIG_NO_CONFIG_BLOBS 425 } else if (os_strcmp(cmd, "blob") == 0) { 426 ret = wpas_ctrl_set_blob(wpa_s, value); 427#endif /* CONFIG_NO_CONFIG_BLOBS */ 428 } else { 429 value[-1] = '='; 430 ret = wpa_config_process_global(wpa_s->conf, cmd, -1); 431 if (ret == 0) 432 wpa_supplicant_update_config(wpa_s); 433 } 434 435 return ret; 436} 437 438 439static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, 440 char *cmd, char *buf, size_t buflen) 441{ 442 int res = -1; 443 444 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 445 446 if (os_strcmp(cmd, "version") == 0) { 447 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 448 } else if (os_strcasecmp(cmd, "country") == 0) { 449 if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) 450 res = os_snprintf(buf, buflen, "%c%c", 451 wpa_s->conf->country[0], 452 wpa_s->conf->country[1]); 453#ifdef CONFIG_WIFI_DISPLAY 454 } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 455 int enabled; 456 if (wpa_s->global->p2p == NULL || 457 wpa_s->global->p2p_disabled) 458 enabled = 0; 459 else 460 enabled = wpa_s->global->wifi_display; 461 res = os_snprintf(buf, buflen, "%d", enabled); 462 if (res < 0 || (unsigned int) res >= buflen) 463 return -1; 464 return res; 465#endif /* CONFIG_WIFI_DISPLAY */ 466#ifdef CONFIG_TESTING_GET_GTK 467 } else if (os_strcmp(cmd, "gtk") == 0) { 468 if (wpa_s->last_gtk_len == 0) 469 return -1; 470 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk, 471 wpa_s->last_gtk_len); 472 return res; 473#endif /* CONFIG_TESTING_GET_GTK */ 474 } 475 476 if (res < 0 || (unsigned int) res >= buflen) 477 return -1; 478 return res; 479} 480 481 482#ifdef IEEE8021X_EAPOL 483static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 484 char *addr) 485{ 486 u8 bssid[ETH_ALEN]; 487 struct wpa_ssid *ssid = wpa_s->current_ssid; 488 489 if (hwaddr_aton(addr, bssid)) { 490 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 491 "'%s'", addr); 492 return -1; 493 } 494 495 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 496 rsn_preauth_deinit(wpa_s->wpa); 497 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL)) 498 return -1; 499 500 return 0; 501} 502#endif /* IEEE8021X_EAPOL */ 503 504 505#ifdef CONFIG_PEERKEY 506/* MLME-STKSTART.request(peer) */ 507static int wpa_supplicant_ctrl_iface_stkstart( 508 struct wpa_supplicant *wpa_s, char *addr) 509{ 510 u8 peer[ETH_ALEN]; 511 512 if (hwaddr_aton(addr, peer)) { 513 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid " 514 "address '%s'", addr); 515 return -1; 516 } 517 518 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR, 519 MAC2STR(peer)); 520 521 return wpa_sm_stkstart(wpa_s->wpa, peer); 522} 523#endif /* CONFIG_PEERKEY */ 524 525 526#ifdef CONFIG_TDLS 527 528static int wpa_supplicant_ctrl_iface_tdls_discover( 529 struct wpa_supplicant *wpa_s, char *addr) 530{ 531 u8 peer[ETH_ALEN]; 532 int ret; 533 534 if (hwaddr_aton(addr, peer)) { 535 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid " 536 "address '%s'", addr); 537 return -1; 538 } 539 540 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR, 541 MAC2STR(peer)); 542 543 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 544 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer); 545 else 546 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); 547 548 return ret; 549} 550 551 552static int wpa_supplicant_ctrl_iface_tdls_setup( 553 struct wpa_supplicant *wpa_s, char *addr) 554{ 555 u8 peer[ETH_ALEN]; 556 int ret; 557 558 if (hwaddr_aton(addr, peer)) { 559 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid " 560 "address '%s'", addr); 561 return -1; 562 } 563 564 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR, 565 MAC2STR(peer)); 566 567 if ((wpa_s->conf->tdls_external_control) && 568 wpa_tdls_is_external_setup(wpa_s->wpa)) 569 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 570 571 wpa_tdls_remove(wpa_s->wpa, peer); 572 573 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 574 ret = wpa_tdls_start(wpa_s->wpa, peer); 575 else 576 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 577 578 return ret; 579} 580 581 582static int wpa_supplicant_ctrl_iface_tdls_teardown( 583 struct wpa_supplicant *wpa_s, char *addr) 584{ 585 u8 peer[ETH_ALEN]; 586 int ret; 587 588 if (os_strcmp(addr, "*") == 0) { 589 /* remove everyone */ 590 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *"); 591 wpa_tdls_teardown_peers(wpa_s->wpa); 592 return 0; 593 } 594 595 if (hwaddr_aton(addr, peer)) { 596 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid " 597 "address '%s'", addr); 598 return -1; 599 } 600 601 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR, 602 MAC2STR(peer)); 603 604 if ((wpa_s->conf->tdls_external_control) && 605 wpa_tdls_is_external_setup(wpa_s->wpa)) 606 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 607 608 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 609 ret = wpa_tdls_teardown_link( 610 wpa_s->wpa, peer, 611 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 612 else 613 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 614 615 return ret; 616} 617 618 619static int ctrl_iface_get_capability_tdls( 620 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 621{ 622 int ret; 623 624 ret = os_snprintf(buf, buflen, "%s\n", 625 wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ? 626 (wpa_s->drv_flags & 627 WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ? 628 "EXTERNAL" : "INTERNAL") : "UNSUPPORTED"); 629 if (ret < 0 || (size_t) ret > buflen) 630 return -1; 631 return ret; 632} 633 634#endif /* CONFIG_TDLS */ 635 636 637#ifdef CONFIG_IEEE80211R 638static int wpa_supplicant_ctrl_iface_ft_ds( 639 struct wpa_supplicant *wpa_s, char *addr) 640{ 641 u8 target_ap[ETH_ALEN]; 642 struct wpa_bss *bss; 643 const u8 *mdie; 644 645 if (hwaddr_aton(addr, target_ap)) { 646 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 647 "address '%s'", addr); 648 return -1; 649 } 650 651 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); 652 653 bss = wpa_bss_get_bssid(wpa_s, target_ap); 654 if (bss) 655 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 656 else 657 mdie = NULL; 658 659 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie); 660} 661#endif /* CONFIG_IEEE80211R */ 662 663 664#ifdef CONFIG_WPS 665static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, 666 char *cmd) 667{ 668 u8 bssid[ETH_ALEN], *_bssid = bssid; 669#ifdef CONFIG_P2P 670 u8 p2p_dev_addr[ETH_ALEN]; 671#endif /* CONFIG_P2P */ 672#ifdef CONFIG_AP 673 u8 *_p2p_dev_addr = NULL; 674#endif /* CONFIG_AP */ 675 676 if (cmd == NULL || os_strcmp(cmd, "any") == 0) { 677 _bssid = NULL; 678#ifdef CONFIG_P2P 679 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 680 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) { 681 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid " 682 "P2P Device Address '%s'", 683 cmd + 13); 684 return -1; 685 } 686 _p2p_dev_addr = p2p_dev_addr; 687#endif /* CONFIG_P2P */ 688 } else if (hwaddr_aton(cmd, bssid)) { 689 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", 690 cmd); 691 return -1; 692 } 693 694#ifdef CONFIG_AP 695 if (wpa_s->ap_iface) 696 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr); 697#endif /* CONFIG_AP */ 698 699 return wpas_wps_start_pbc(wpa_s, _bssid, 0); 700} 701 702 703static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, 704 char *cmd, char *buf, 705 size_t buflen) 706{ 707 u8 bssid[ETH_ALEN], *_bssid = bssid; 708 char *pin; 709 int ret; 710 711 pin = os_strchr(cmd, ' '); 712 if (pin) 713 *pin++ = '\0'; 714 715 if (os_strcmp(cmd, "any") == 0) 716 _bssid = NULL; 717 else if (os_strcmp(cmd, "get") == 0) { 718 ret = wps_generate_pin(); 719 goto done; 720 } else if (hwaddr_aton(cmd, bssid)) { 721 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'", 722 cmd); 723 return -1; 724 } 725 726#ifdef CONFIG_AP 727 if (wpa_s->ap_iface) { 728 int timeout = 0; 729 char *pos; 730 731 if (pin) { 732 pos = os_strchr(pin, ' '); 733 if (pos) { 734 *pos++ = '\0'; 735 timeout = atoi(pos); 736 } 737 } 738 739 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin, 740 buf, buflen, timeout); 741 } 742#endif /* CONFIG_AP */ 743 744 if (pin) { 745 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0, 746 DEV_PW_DEFAULT); 747 if (ret < 0) 748 return -1; 749 ret = os_snprintf(buf, buflen, "%s", pin); 750 if (ret < 0 || (size_t) ret >= buflen) 751 return -1; 752 return ret; 753 } 754 755 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT); 756 if (ret < 0) 757 return -1; 758 759done: 760 /* Return the generated PIN */ 761 ret = os_snprintf(buf, buflen, "%08d", ret); 762 if (ret < 0 || (size_t) ret >= buflen) 763 return -1; 764 return ret; 765} 766 767 768static int wpa_supplicant_ctrl_iface_wps_check_pin( 769 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 770{ 771 char pin[9]; 772 size_t len; 773 char *pos; 774 int ret; 775 776 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 777 (u8 *) cmd, os_strlen(cmd)); 778 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 779 if (*pos < '0' || *pos > '9') 780 continue; 781 pin[len++] = *pos; 782 if (len == 9) { 783 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 784 return -1; 785 } 786 } 787 if (len != 4 && len != 8) { 788 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 789 return -1; 790 } 791 pin[len] = '\0'; 792 793 if (len == 8) { 794 unsigned int pin_val; 795 pin_val = atoi(pin); 796 if (!wps_pin_valid(pin_val)) { 797 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 798 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 799 if (ret < 0 || (size_t) ret >= buflen) 800 return -1; 801 return ret; 802 } 803 } 804 805 ret = os_snprintf(buf, buflen, "%s", pin); 806 if (ret < 0 || (size_t) ret >= buflen) 807 return -1; 808 809 return ret; 810} 811 812 813#ifdef CONFIG_WPS_NFC 814 815static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s, 816 char *cmd) 817{ 818 u8 bssid[ETH_ALEN], *_bssid = bssid; 819 820 if (cmd == NULL || cmd[0] == '\0') 821 _bssid = NULL; 822 else if (hwaddr_aton(cmd, bssid)) 823 return -1; 824 825 return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL, 826 0, 0); 827} 828 829 830static int wpa_supplicant_ctrl_iface_wps_nfc_config_token( 831 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 832{ 833 int ndef; 834 struct wpabuf *buf; 835 int res; 836 char *pos; 837 838 pos = os_strchr(cmd, ' '); 839 if (pos) 840 *pos++ = '\0'; 841 if (os_strcmp(cmd, "WPS") == 0) 842 ndef = 0; 843 else if (os_strcmp(cmd, "NDEF") == 0) 844 ndef = 1; 845 else 846 return -1; 847 848 buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos); 849 if (buf == NULL) 850 return -1; 851 852 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 853 wpabuf_len(buf)); 854 reply[res++] = '\n'; 855 reply[res] = '\0'; 856 857 wpabuf_free(buf); 858 859 return res; 860} 861 862 863static int wpa_supplicant_ctrl_iface_wps_nfc_token( 864 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 865{ 866 int ndef; 867 struct wpabuf *buf; 868 int res; 869 870 if (os_strcmp(cmd, "WPS") == 0) 871 ndef = 0; 872 else if (os_strcmp(cmd, "NDEF") == 0) 873 ndef = 1; 874 else 875 return -1; 876 877 buf = wpas_wps_nfc_token(wpa_s, ndef); 878 if (buf == NULL) 879 return -1; 880 881 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 882 wpabuf_len(buf)); 883 reply[res++] = '\n'; 884 reply[res] = '\0'; 885 886 wpabuf_free(buf); 887 888 return res; 889} 890 891 892static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read( 893 struct wpa_supplicant *wpa_s, char *pos) 894{ 895 size_t len; 896 struct wpabuf *buf; 897 int ret; 898 char *freq; 899 int forced_freq = 0; 900 901 freq = strstr(pos, " freq="); 902 if (freq) { 903 *freq = '\0'; 904 freq += 6; 905 forced_freq = atoi(freq); 906 } 907 908 len = os_strlen(pos); 909 if (len & 0x01) 910 return -1; 911 len /= 2; 912 913 buf = wpabuf_alloc(len); 914 if (buf == NULL) 915 return -1; 916 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 917 wpabuf_free(buf); 918 return -1; 919 } 920 921 ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq); 922 wpabuf_free(buf); 923 924 return ret; 925} 926 927 928static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s, 929 char *reply, size_t max_len, 930 int ndef) 931{ 932 struct wpabuf *buf; 933 int res; 934 935 buf = wpas_wps_nfc_handover_req(wpa_s, ndef); 936 if (buf == NULL) 937 return -1; 938 939 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 940 wpabuf_len(buf)); 941 reply[res++] = '\n'; 942 reply[res] = '\0'; 943 944 wpabuf_free(buf); 945 946 return res; 947} 948 949 950#ifdef CONFIG_P2P 951static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s, 952 char *reply, size_t max_len, 953 int ndef) 954{ 955 struct wpabuf *buf; 956 int res; 957 958 buf = wpas_p2p_nfc_handover_req(wpa_s, ndef); 959 if (buf == NULL) { 960 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request"); 961 return -1; 962 } 963 964 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 965 wpabuf_len(buf)); 966 reply[res++] = '\n'; 967 reply[res] = '\0'; 968 969 wpabuf_free(buf); 970 971 return res; 972} 973#endif /* CONFIG_P2P */ 974 975 976static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s, 977 char *cmd, char *reply, 978 size_t max_len) 979{ 980 char *pos; 981 int ndef; 982 983 pos = os_strchr(cmd, ' '); 984 if (pos == NULL) 985 return -1; 986 *pos++ = '\0'; 987 988 if (os_strcmp(cmd, "WPS") == 0) 989 ndef = 0; 990 else if (os_strcmp(cmd, "NDEF") == 0) 991 ndef = 1; 992 else 993 return -1; 994 995 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) { 996 if (!ndef) 997 return -1; 998 return wpas_ctrl_nfc_get_handover_req_wps( 999 wpa_s, reply, max_len, ndef); 1000 } 1001 1002#ifdef CONFIG_P2P 1003 if (os_strcmp(pos, "P2P-CR") == 0) { 1004 return wpas_ctrl_nfc_get_handover_req_p2p( 1005 wpa_s, reply, max_len, ndef); 1006 } 1007#endif /* CONFIG_P2P */ 1008 1009 return -1; 1010} 1011 1012 1013static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s, 1014 char *reply, size_t max_len, 1015 int ndef, int cr, char *uuid) 1016{ 1017 struct wpabuf *buf; 1018 int res; 1019 1020 buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid); 1021 if (buf == NULL) 1022 return -1; 1023 1024 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1025 wpabuf_len(buf)); 1026 reply[res++] = '\n'; 1027 reply[res] = '\0'; 1028 1029 wpabuf_free(buf); 1030 1031 return res; 1032} 1033 1034 1035#ifdef CONFIG_P2P 1036static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s, 1037 char *reply, size_t max_len, 1038 int ndef, int tag) 1039{ 1040 struct wpabuf *buf; 1041 int res; 1042 1043 buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag); 1044 if (buf == NULL) 1045 return -1; 1046 1047 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1048 wpabuf_len(buf)); 1049 reply[res++] = '\n'; 1050 reply[res] = '\0'; 1051 1052 wpabuf_free(buf); 1053 1054 return res; 1055} 1056#endif /* CONFIG_P2P */ 1057 1058 1059static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s, 1060 char *cmd, char *reply, 1061 size_t max_len) 1062{ 1063 char *pos, *pos2; 1064 int ndef; 1065 1066 pos = os_strchr(cmd, ' '); 1067 if (pos == NULL) 1068 return -1; 1069 *pos++ = '\0'; 1070 1071 if (os_strcmp(cmd, "WPS") == 0) 1072 ndef = 0; 1073 else if (os_strcmp(cmd, "NDEF") == 0) 1074 ndef = 1; 1075 else 1076 return -1; 1077 1078 pos2 = os_strchr(pos, ' '); 1079 if (pos2) 1080 *pos2++ = '\0'; 1081 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) { 1082 if (!ndef) 1083 return -1; 1084 return wpas_ctrl_nfc_get_handover_sel_wps( 1085 wpa_s, reply, max_len, ndef, 1086 os_strcmp(pos, "WPS-CR") == 0, pos2); 1087 } 1088 1089#ifdef CONFIG_P2P 1090 if (os_strcmp(pos, "P2P-CR") == 0) { 1091 return wpas_ctrl_nfc_get_handover_sel_p2p( 1092 wpa_s, reply, max_len, ndef, 0); 1093 } 1094 1095 if (os_strcmp(pos, "P2P-CR-TAG") == 0) { 1096 return wpas_ctrl_nfc_get_handover_sel_p2p( 1097 wpa_s, reply, max_len, ndef, 1); 1098 } 1099#endif /* CONFIG_P2P */ 1100 1101 return -1; 1102} 1103 1104 1105static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s, 1106 char *cmd) 1107{ 1108 size_t len; 1109 struct wpabuf *req, *sel; 1110 int ret; 1111 char *pos, *role, *type, *pos2; 1112#ifdef CONFIG_P2P 1113 char *freq; 1114 int forced_freq = 0; 1115 1116 freq = strstr(cmd, " freq="); 1117 if (freq) { 1118 *freq = '\0'; 1119 freq += 6; 1120 forced_freq = atoi(freq); 1121 } 1122#endif /* CONFIG_P2P */ 1123 1124 role = cmd; 1125 pos = os_strchr(role, ' '); 1126 if (pos == NULL) { 1127 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report"); 1128 return -1; 1129 } 1130 *pos++ = '\0'; 1131 1132 type = pos; 1133 pos = os_strchr(type, ' '); 1134 if (pos == NULL) { 1135 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report"); 1136 return -1; 1137 } 1138 *pos++ = '\0'; 1139 1140 pos2 = os_strchr(pos, ' '); 1141 if (pos2 == NULL) { 1142 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report"); 1143 return -1; 1144 } 1145 *pos2++ = '\0'; 1146 1147 len = os_strlen(pos); 1148 if (len & 0x01) { 1149 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report"); 1150 return -1; 1151 } 1152 len /= 2; 1153 1154 req = wpabuf_alloc(len); 1155 if (req == NULL) { 1156 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message"); 1157 return -1; 1158 } 1159 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) { 1160 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report"); 1161 wpabuf_free(req); 1162 return -1; 1163 } 1164 1165 len = os_strlen(pos2); 1166 if (len & 0x01) { 1167 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report"); 1168 wpabuf_free(req); 1169 return -1; 1170 } 1171 len /= 2; 1172 1173 sel = wpabuf_alloc(len); 1174 if (sel == NULL) { 1175 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message"); 1176 wpabuf_free(req); 1177 return -1; 1178 } 1179 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) { 1180 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report"); 1181 wpabuf_free(req); 1182 wpabuf_free(sel); 1183 return -1; 1184 } 1185 1186 wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d", 1187 role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel)); 1188 1189 if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) { 1190 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel); 1191#ifdef CONFIG_AP 1192 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) 1193 { 1194 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel); 1195 if (ret < 0) 1196 ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel); 1197#endif /* CONFIG_AP */ 1198#ifdef CONFIG_P2P 1199 } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0) 1200 { 1201 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0); 1202 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0) 1203 { 1204 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel, 1205 forced_freq); 1206#endif /* CONFIG_P2P */ 1207 } else { 1208 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover " 1209 "reported: role=%s type=%s", role, type); 1210 ret = -1; 1211 } 1212 wpabuf_free(req); 1213 wpabuf_free(sel); 1214 1215 if (ret) 1216 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages"); 1217 1218 return ret; 1219} 1220 1221#endif /* CONFIG_WPS_NFC */ 1222 1223 1224static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s, 1225 char *cmd) 1226{ 1227 u8 bssid[ETH_ALEN]; 1228 char *pin; 1229 char *new_ssid; 1230 char *new_auth; 1231 char *new_encr; 1232 char *new_key; 1233 struct wps_new_ap_settings ap; 1234 1235 pin = os_strchr(cmd, ' '); 1236 if (pin == NULL) 1237 return -1; 1238 *pin++ = '\0'; 1239 1240 if (hwaddr_aton(cmd, bssid)) { 1241 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'", 1242 cmd); 1243 return -1; 1244 } 1245 1246 new_ssid = os_strchr(pin, ' '); 1247 if (new_ssid == NULL) 1248 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL); 1249 *new_ssid++ = '\0'; 1250 1251 new_auth = os_strchr(new_ssid, ' '); 1252 if (new_auth == NULL) 1253 return -1; 1254 *new_auth++ = '\0'; 1255 1256 new_encr = os_strchr(new_auth, ' '); 1257 if (new_encr == NULL) 1258 return -1; 1259 *new_encr++ = '\0'; 1260 1261 new_key = os_strchr(new_encr, ' '); 1262 if (new_key == NULL) 1263 return -1; 1264 *new_key++ = '\0'; 1265 1266 os_memset(&ap, 0, sizeof(ap)); 1267 ap.ssid_hex = new_ssid; 1268 ap.auth = new_auth; 1269 ap.encr = new_encr; 1270 ap.key_hex = new_key; 1271 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap); 1272} 1273 1274 1275#ifdef CONFIG_AP 1276static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s, 1277 char *cmd, char *buf, 1278 size_t buflen) 1279{ 1280 int timeout = 300; 1281 char *pos; 1282 const char *pin_txt; 1283 1284 if (!wpa_s->ap_iface) 1285 return -1; 1286 1287 pos = os_strchr(cmd, ' '); 1288 if (pos) 1289 *pos++ = '\0'; 1290 1291 if (os_strcmp(cmd, "disable") == 0) { 1292 wpas_wps_ap_pin_disable(wpa_s); 1293 return os_snprintf(buf, buflen, "OK\n"); 1294 } 1295 1296 if (os_strcmp(cmd, "random") == 0) { 1297 if (pos) 1298 timeout = atoi(pos); 1299 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout); 1300 if (pin_txt == NULL) 1301 return -1; 1302 return os_snprintf(buf, buflen, "%s", pin_txt); 1303 } 1304 1305 if (os_strcmp(cmd, "get") == 0) { 1306 pin_txt = wpas_wps_ap_pin_get(wpa_s); 1307 if (pin_txt == NULL) 1308 return -1; 1309 return os_snprintf(buf, buflen, "%s", pin_txt); 1310 } 1311 1312 if (os_strcmp(cmd, "set") == 0) { 1313 char *pin; 1314 if (pos == NULL) 1315 return -1; 1316 pin = pos; 1317 pos = os_strchr(pos, ' '); 1318 if (pos) { 1319 *pos++ = '\0'; 1320 timeout = atoi(pos); 1321 } 1322 if (os_strlen(pin) > buflen) 1323 return -1; 1324 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0) 1325 return -1; 1326 return os_snprintf(buf, buflen, "%s", pin); 1327 } 1328 1329 return -1; 1330} 1331#endif /* CONFIG_AP */ 1332 1333 1334#ifdef CONFIG_WPS_ER 1335static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s, 1336 char *cmd) 1337{ 1338 char *uuid = cmd, *pin, *pos; 1339 u8 addr_buf[ETH_ALEN], *addr = NULL; 1340 pin = os_strchr(uuid, ' '); 1341 if (pin == NULL) 1342 return -1; 1343 *pin++ = '\0'; 1344 pos = os_strchr(pin, ' '); 1345 if (pos) { 1346 *pos++ = '\0'; 1347 if (hwaddr_aton(pos, addr_buf) == 0) 1348 addr = addr_buf; 1349 } 1350 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin); 1351} 1352 1353 1354static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s, 1355 char *cmd) 1356{ 1357 char *uuid = cmd, *pin; 1358 pin = os_strchr(uuid, ' '); 1359 if (pin == NULL) 1360 return -1; 1361 *pin++ = '\0'; 1362 return wpas_wps_er_learn(wpa_s, uuid, pin); 1363} 1364 1365 1366static int wpa_supplicant_ctrl_iface_wps_er_set_config( 1367 struct wpa_supplicant *wpa_s, char *cmd) 1368{ 1369 char *uuid = cmd, *id; 1370 id = os_strchr(uuid, ' '); 1371 if (id == NULL) 1372 return -1; 1373 *id++ = '\0'; 1374 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id)); 1375} 1376 1377 1378static int wpa_supplicant_ctrl_iface_wps_er_config( 1379 struct wpa_supplicant *wpa_s, char *cmd) 1380{ 1381 char *pin; 1382 char *new_ssid; 1383 char *new_auth; 1384 char *new_encr; 1385 char *new_key; 1386 struct wps_new_ap_settings ap; 1387 1388 pin = os_strchr(cmd, ' '); 1389 if (pin == NULL) 1390 return -1; 1391 *pin++ = '\0'; 1392 1393 new_ssid = os_strchr(pin, ' '); 1394 if (new_ssid == NULL) 1395 return -1; 1396 *new_ssid++ = '\0'; 1397 1398 new_auth = os_strchr(new_ssid, ' '); 1399 if (new_auth == NULL) 1400 return -1; 1401 *new_auth++ = '\0'; 1402 1403 new_encr = os_strchr(new_auth, ' '); 1404 if (new_encr == NULL) 1405 return -1; 1406 *new_encr++ = '\0'; 1407 1408 new_key = os_strchr(new_encr, ' '); 1409 if (new_key == NULL) 1410 return -1; 1411 *new_key++ = '\0'; 1412 1413 os_memset(&ap, 0, sizeof(ap)); 1414 ap.ssid_hex = new_ssid; 1415 ap.auth = new_auth; 1416 ap.encr = new_encr; 1417 ap.key_hex = new_key; 1418 return wpas_wps_er_config(wpa_s, cmd, pin, &ap); 1419} 1420 1421 1422#ifdef CONFIG_WPS_NFC 1423static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 1424 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 1425{ 1426 int ndef; 1427 struct wpabuf *buf; 1428 int res; 1429 char *uuid; 1430 1431 uuid = os_strchr(cmd, ' '); 1432 if (uuid == NULL) 1433 return -1; 1434 *uuid++ = '\0'; 1435 1436 if (os_strcmp(cmd, "WPS") == 0) 1437 ndef = 0; 1438 else if (os_strcmp(cmd, "NDEF") == 0) 1439 ndef = 1; 1440 else 1441 return -1; 1442 1443 buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid); 1444 if (buf == NULL) 1445 return -1; 1446 1447 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1448 wpabuf_len(buf)); 1449 reply[res++] = '\n'; 1450 reply[res] = '\0'; 1451 1452 wpabuf_free(buf); 1453 1454 return res; 1455} 1456#endif /* CONFIG_WPS_NFC */ 1457#endif /* CONFIG_WPS_ER */ 1458 1459#endif /* CONFIG_WPS */ 1460 1461 1462#ifdef CONFIG_IBSS_RSN 1463static int wpa_supplicant_ctrl_iface_ibss_rsn( 1464 struct wpa_supplicant *wpa_s, char *addr) 1465{ 1466 u8 peer[ETH_ALEN]; 1467 1468 if (hwaddr_aton(addr, peer)) { 1469 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid " 1470 "address '%s'", addr); 1471 return -1; 1472 } 1473 1474 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR, 1475 MAC2STR(peer)); 1476 1477 return ibss_rsn_start(wpa_s->ibss_rsn, peer); 1478} 1479#endif /* CONFIG_IBSS_RSN */ 1480 1481 1482static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 1483 char *rsp) 1484{ 1485#ifdef IEEE8021X_EAPOL 1486 char *pos, *id_pos; 1487 int id; 1488 struct wpa_ssid *ssid; 1489 1490 pos = os_strchr(rsp, '-'); 1491 if (pos == NULL) 1492 return -1; 1493 *pos++ = '\0'; 1494 id_pos = pos; 1495 pos = os_strchr(pos, ':'); 1496 if (pos == NULL) 1497 return -1; 1498 *pos++ = '\0'; 1499 id = atoi(id_pos); 1500 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 1501 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 1502 (u8 *) pos, os_strlen(pos)); 1503 1504 ssid = wpa_config_get_network(wpa_s->conf, id); 1505 if (ssid == NULL) { 1506 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 1507 "to update", id); 1508 return -1; 1509 } 1510 1511 return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp, 1512 pos); 1513#else /* IEEE8021X_EAPOL */ 1514 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 1515 return -1; 1516#endif /* IEEE8021X_EAPOL */ 1517} 1518 1519 1520static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 1521 const char *params, 1522 char *buf, size_t buflen) 1523{ 1524 char *pos, *end, tmp[30]; 1525 int res, verbose, wps, ret; 1526#ifdef CONFIG_HS20 1527 const u8 *hs20; 1528#endif /* CONFIG_HS20 */ 1529 1530 if (os_strcmp(params, "-DRIVER") == 0) 1531 return wpa_drv_status(wpa_s, buf, buflen); 1532 verbose = os_strcmp(params, "-VERBOSE") == 0; 1533 wps = os_strcmp(params, "-WPS") == 0; 1534 pos = buf; 1535 end = buf + buflen; 1536 if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 1537 struct wpa_ssid *ssid = wpa_s->current_ssid; 1538 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 1539 MAC2STR(wpa_s->bssid)); 1540 if (ret < 0 || ret >= end - pos) 1541 return pos - buf; 1542 pos += ret; 1543 ret = os_snprintf(pos, end - pos, "freq=%u\n", 1544 wpa_s->assoc_freq); 1545 if (ret < 0 || ret >= end - pos) 1546 return pos - buf; 1547 pos += ret; 1548 if (ssid) { 1549 u8 *_ssid = ssid->ssid; 1550 size_t ssid_len = ssid->ssid_len; 1551 u8 ssid_buf[MAX_SSID_LEN]; 1552 if (ssid_len == 0) { 1553 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 1554 if (_res < 0) 1555 ssid_len = 0; 1556 else 1557 ssid_len = _res; 1558 _ssid = ssid_buf; 1559 } 1560 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 1561 wpa_ssid_txt(_ssid, ssid_len), 1562 ssid->id); 1563 if (ret < 0 || ret >= end - pos) 1564 return pos - buf; 1565 pos += ret; 1566 1567 if (wps && ssid->passphrase && 1568 wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && 1569 (ssid->mode == WPAS_MODE_AP || 1570 ssid->mode == WPAS_MODE_P2P_GO)) { 1571 ret = os_snprintf(pos, end - pos, 1572 "passphrase=%s\n", 1573 ssid->passphrase); 1574 if (ret < 0 || ret >= end - pos) 1575 return pos - buf; 1576 pos += ret; 1577 } 1578 if (ssid->id_str) { 1579 ret = os_snprintf(pos, end - pos, 1580 "id_str=%s\n", 1581 ssid->id_str); 1582 if (ret < 0 || ret >= end - pos) 1583 return pos - buf; 1584 pos += ret; 1585 } 1586 1587 switch (ssid->mode) { 1588 case WPAS_MODE_INFRA: 1589 ret = os_snprintf(pos, end - pos, 1590 "mode=station\n"); 1591 break; 1592 case WPAS_MODE_IBSS: 1593 ret = os_snprintf(pos, end - pos, 1594 "mode=IBSS\n"); 1595 break; 1596 case WPAS_MODE_AP: 1597 ret = os_snprintf(pos, end - pos, 1598 "mode=AP\n"); 1599 break; 1600 case WPAS_MODE_P2P_GO: 1601 ret = os_snprintf(pos, end - pos, 1602 "mode=P2P GO\n"); 1603 break; 1604 case WPAS_MODE_P2P_GROUP_FORMATION: 1605 ret = os_snprintf(pos, end - pos, 1606 "mode=P2P GO - group " 1607 "formation\n"); 1608 break; 1609 default: 1610 ret = 0; 1611 break; 1612 } 1613 if (ret < 0 || ret >= end - pos) 1614 return pos - buf; 1615 pos += ret; 1616 } 1617 1618#ifdef CONFIG_AP 1619 if (wpa_s->ap_iface) { 1620 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, 1621 end - pos, 1622 verbose); 1623 } else 1624#endif /* CONFIG_AP */ 1625 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 1626 } 1627#ifdef CONFIG_SAE 1628 if (wpa_s->wpa_state >= WPA_ASSOCIATED && 1629#ifdef CONFIG_AP 1630 !wpa_s->ap_iface && 1631#endif /* CONFIG_AP */ 1632 wpa_s->sme.sae.state == SAE_ACCEPTED) { 1633 ret = os_snprintf(pos, end - pos, "sae_group=%d\n", 1634 wpa_s->sme.sae.group); 1635 if (ret < 0 || ret >= end - pos) 1636 return pos - buf; 1637 pos += ret; 1638 } 1639#endif /* CONFIG_SAE */ 1640 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 1641 wpa_supplicant_state_txt(wpa_s->wpa_state)); 1642 if (ret < 0 || ret >= end - pos) 1643 return pos - buf; 1644 pos += ret; 1645 1646 if (wpa_s->l2 && 1647 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 1648 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 1649 if (ret < 0 || ret >= end - pos) 1650 return pos - buf; 1651 pos += ret; 1652 } 1653 1654#ifdef CONFIG_P2P 1655 if (wpa_s->global->p2p) { 1656 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 1657 "\n", MAC2STR(wpa_s->global->p2p_dev_addr)); 1658 if (ret < 0 || ret >= end - pos) 1659 return pos - buf; 1660 pos += ret; 1661 } 1662#endif /* CONFIG_P2P */ 1663 1664 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n", 1665 MAC2STR(wpa_s->own_addr)); 1666 if (ret < 0 || ret >= end - pos) 1667 return pos - buf; 1668 pos += ret; 1669 1670#ifdef CONFIG_HS20 1671 if (wpa_s->current_bss && 1672 (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss, 1673 HS20_IE_VENDOR_TYPE)) && 1674 wpa_s->wpa_proto == WPA_PROTO_RSN && 1675 wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { 1676 int release = 1; 1677 if (hs20[1] >= 5) { 1678 u8 rel_num = (hs20[6] & 0xf0) >> 4; 1679 release = rel_num + 1; 1680 } 1681 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release); 1682 if (ret < 0 || ret >= end - pos) 1683 return pos - buf; 1684 pos += ret; 1685 } 1686 1687 if (wpa_s->current_ssid) { 1688 struct wpa_cred *cred; 1689 char *type; 1690 1691 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1692 size_t i; 1693 1694 if (wpa_s->current_ssid->parent_cred != cred) 1695 continue; 1696 1697 if (cred->provisioning_sp) { 1698 ret = os_snprintf(pos, end - pos, 1699 "provisioning_sp=%s\n", 1700 cred->provisioning_sp); 1701 if (ret < 0 || ret >= end - pos) 1702 return pos - buf; 1703 pos += ret; 1704 } 1705 1706 if (!cred->domain) 1707 goto no_domain; 1708 1709 i = 0; 1710 if (wpa_s->current_bss && wpa_s->current_bss->anqp) { 1711 struct wpabuf *names = 1712 wpa_s->current_bss->anqp->domain_name; 1713 for (i = 0; names && i < cred->num_domain; i++) 1714 { 1715 if (domain_name_list_contains( 1716 names, cred->domain[i], 1)) 1717 break; 1718 } 1719 if (i == cred->num_domain) 1720 i = 0; /* show first entry by default */ 1721 } 1722 ret = os_snprintf(pos, end - pos, "home_sp=%s\n", 1723 cred->domain[i]); 1724 if (ret < 0 || ret >= end - pos) 1725 return pos - buf; 1726 pos += ret; 1727 1728 no_domain: 1729 if (wpa_s->current_bss == NULL || 1730 wpa_s->current_bss->anqp == NULL) 1731 res = -1; 1732 else 1733 res = interworking_home_sp_cred( 1734 wpa_s, cred, 1735 wpa_s->current_bss->anqp->domain_name); 1736 if (res > 0) 1737 type = "home"; 1738 else if (res == 0) 1739 type = "roaming"; 1740 else 1741 type = "unknown"; 1742 1743 ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type); 1744 if (ret < 0 || ret >= end - pos) 1745 return pos - buf; 1746 pos += ret; 1747 1748 break; 1749 } 1750 } 1751#endif /* CONFIG_HS20 */ 1752 1753 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 1754 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 1755 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 1756 verbose); 1757 if (res >= 0) 1758 pos += res; 1759 } 1760 1761 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 1762 if (res >= 0) 1763 pos += res; 1764 1765#ifdef CONFIG_WPS 1766 { 1767 char uuid_str[100]; 1768 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str)); 1769 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str); 1770 if (ret < 0 || ret >= end - pos) 1771 return pos - buf; 1772 pos += ret; 1773 } 1774#endif /* CONFIG_WPS */ 1775 1776#ifdef ANDROID 1777 /* 1778 * Allow using the STATUS command with default behavior, say for debug, 1779 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE 1780 * events with STATUS-NO_EVENTS. 1781 */ 1782 if (os_strcmp(params, "-NO_EVENTS")) { 1783 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE 1784 "id=%d state=%d BSSID=" MACSTR " SSID=%s", 1785 wpa_s->current_ssid ? wpa_s->current_ssid->id : -1, 1786 wpa_s->wpa_state, 1787 MAC2STR(wpa_s->bssid), 1788 wpa_s->current_ssid && wpa_s->current_ssid->ssid ? 1789 wpa_ssid_txt(wpa_s->current_ssid->ssid, 1790 wpa_s->current_ssid->ssid_len) : ""); 1791 if (wpa_s->wpa_state == WPA_COMPLETED) { 1792 struct wpa_ssid *ssid = wpa_s->current_ssid; 1793 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED 1794 "- connection to " MACSTR 1795 " completed %s [id=%d id_str=%s]", 1796 MAC2STR(wpa_s->bssid), "(auth)", 1797 ssid ? ssid->id : -1, 1798 ssid && ssid->id_str ? ssid->id_str : ""); 1799 } 1800 } 1801#endif /* ANDROID */ 1802 1803 return pos - buf; 1804} 1805 1806 1807static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 1808 char *cmd) 1809{ 1810 char *pos; 1811 int id; 1812 struct wpa_ssid *ssid; 1813 u8 bssid[ETH_ALEN]; 1814 1815 /* cmd: "<network id> <BSSID>" */ 1816 pos = os_strchr(cmd, ' '); 1817 if (pos == NULL) 1818 return -1; 1819 *pos++ = '\0'; 1820 id = atoi(cmd); 1821 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 1822 if (hwaddr_aton(pos, bssid)) { 1823 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 1824 return -1; 1825 } 1826 1827 ssid = wpa_config_get_network(wpa_s->conf, id); 1828 if (ssid == NULL) { 1829 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 1830 "to update", id); 1831 return -1; 1832 } 1833 1834 os_memcpy(ssid->bssid, bssid, ETH_ALEN); 1835 ssid->bssid_set = !is_zero_ether_addr(bssid); 1836 1837 return 0; 1838} 1839 1840 1841static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s, 1842 char *cmd, char *buf, 1843 size_t buflen) 1844{ 1845 u8 bssid[ETH_ALEN]; 1846 struct wpa_blacklist *e; 1847 char *pos, *end; 1848 int ret; 1849 1850 /* cmd: "BLACKLIST [<BSSID>]" */ 1851 if (*cmd == '\0') { 1852 pos = buf; 1853 end = buf + buflen; 1854 e = wpa_s->blacklist; 1855 while (e) { 1856 ret = os_snprintf(pos, end - pos, MACSTR "\n", 1857 MAC2STR(e->bssid)); 1858 if (ret < 0 || ret >= end - pos) 1859 return pos - buf; 1860 pos += ret; 1861 e = e->next; 1862 } 1863 return pos - buf; 1864 } 1865 1866 cmd++; 1867 if (os_strncmp(cmd, "clear", 5) == 0) { 1868 wpa_blacklist_clear(wpa_s); 1869 os_memcpy(buf, "OK\n", 3); 1870 return 3; 1871 } 1872 1873 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd); 1874 if (hwaddr_aton(cmd, bssid)) { 1875 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd); 1876 return -1; 1877 } 1878 1879 /* 1880 * Add the BSSID twice, so its count will be 2, causing it to be 1881 * skipped when processing scan results. 1882 */ 1883 ret = wpa_blacklist_add(wpa_s, bssid); 1884 if (ret < 0) 1885 return -1; 1886 ret = wpa_blacklist_add(wpa_s, bssid); 1887 if (ret < 0) 1888 return -1; 1889 os_memcpy(buf, "OK\n", 3); 1890 return 3; 1891} 1892 1893 1894static const char * debug_level_str(int level) 1895{ 1896 switch (level) { 1897 case MSG_EXCESSIVE: 1898 return "EXCESSIVE"; 1899 case MSG_MSGDUMP: 1900 return "MSGDUMP"; 1901 case MSG_DEBUG: 1902 return "DEBUG"; 1903 case MSG_INFO: 1904 return "INFO"; 1905 case MSG_WARNING: 1906 return "WARNING"; 1907 case MSG_ERROR: 1908 return "ERROR"; 1909 default: 1910 return "?"; 1911 } 1912} 1913 1914 1915static int str_to_debug_level(const char *s) 1916{ 1917 if (os_strcasecmp(s, "EXCESSIVE") == 0) 1918 return MSG_EXCESSIVE; 1919 if (os_strcasecmp(s, "MSGDUMP") == 0) 1920 return MSG_MSGDUMP; 1921 if (os_strcasecmp(s, "DEBUG") == 0) 1922 return MSG_DEBUG; 1923 if (os_strcasecmp(s, "INFO") == 0) 1924 return MSG_INFO; 1925 if (os_strcasecmp(s, "WARNING") == 0) 1926 return MSG_WARNING; 1927 if (os_strcasecmp(s, "ERROR") == 0) 1928 return MSG_ERROR; 1929 return -1; 1930} 1931 1932 1933static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s, 1934 char *cmd, char *buf, 1935 size_t buflen) 1936{ 1937 char *pos, *end, *stamp; 1938 int ret; 1939 1940 if (cmd == NULL) { 1941 return -1; 1942 } 1943 1944 /* cmd: "LOG_LEVEL [<level>]" */ 1945 if (*cmd == '\0') { 1946 pos = buf; 1947 end = buf + buflen; 1948 ret = os_snprintf(pos, end - pos, "Current level: %s\n" 1949 "Timestamp: %d\n", 1950 debug_level_str(wpa_debug_level), 1951 wpa_debug_timestamp); 1952 if (ret < 0 || ret >= end - pos) 1953 ret = 0; 1954 1955 return ret; 1956 } 1957 1958 while (*cmd == ' ') 1959 cmd++; 1960 1961 stamp = os_strchr(cmd, ' '); 1962 if (stamp) { 1963 *stamp++ = '\0'; 1964 while (*stamp == ' ') { 1965 stamp++; 1966 } 1967 } 1968 1969 if (cmd && os_strlen(cmd)) { 1970 int level = str_to_debug_level(cmd); 1971 if (level < 0) 1972 return -1; 1973 wpa_debug_level = level; 1974 } 1975 1976 if (stamp && os_strlen(stamp)) 1977 wpa_debug_timestamp = atoi(stamp); 1978 1979 os_memcpy(buf, "OK\n", 3); 1980 return 3; 1981} 1982 1983 1984static int wpa_supplicant_ctrl_iface_list_networks( 1985 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 1986{ 1987 char *pos, *end; 1988 struct wpa_ssid *ssid; 1989 int ret; 1990 1991 pos = buf; 1992 end = buf + buflen; 1993 ret = os_snprintf(pos, end - pos, 1994 "network id / ssid / bssid / flags\n"); 1995 if (ret < 0 || ret >= end - pos) 1996 return pos - buf; 1997 pos += ret; 1998 1999 ssid = wpa_s->conf->ssid; 2000 2001 /* skip over ssids until we find next one */ 2002 if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) { 2003 int last_id = atoi(cmd + 8); 2004 if (last_id != -1) { 2005 while (ssid != NULL && ssid->id <= last_id) { 2006 ssid = ssid->next; 2007 } 2008 } 2009 } 2010 2011 while (ssid) { 2012 ret = os_snprintf(pos, end - pos, "%d\t%s", 2013 ssid->id, 2014 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 2015 if (ret < 0 || ret >= end - pos) 2016 return pos - buf; 2017 pos += ret; 2018 if (ssid->bssid_set) { 2019 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 2020 MAC2STR(ssid->bssid)); 2021 } else { 2022 ret = os_snprintf(pos, end - pos, "\tany"); 2023 } 2024 if (ret < 0 || ret >= end - pos) 2025 return pos - buf; 2026 pos += ret; 2027 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s", 2028 ssid == wpa_s->current_ssid ? 2029 "[CURRENT]" : "", 2030 ssid->disabled ? "[DISABLED]" : "", 2031 ssid->disabled_until.sec ? 2032 "[TEMP-DISABLED]" : "", 2033 ssid->disabled == 2 ? "[P2P-PERSISTENT]" : 2034 ""); 2035 if (ret < 0 || ret >= end - pos) 2036 return pos - buf; 2037 pos += ret; 2038 ret = os_snprintf(pos, end - pos, "\n"); 2039 if (ret < 0 || ret >= end - pos) 2040 return pos - buf; 2041 pos += ret; 2042 2043 ssid = ssid->next; 2044 } 2045 2046 return pos - buf; 2047} 2048 2049 2050static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 2051{ 2052 int ret; 2053 ret = os_snprintf(pos, end - pos, "-"); 2054 if (ret < 0 || ret >= end - pos) 2055 return pos; 2056 pos += ret; 2057 ret = wpa_write_ciphers(pos, end, cipher, "+"); 2058 if (ret < 0) 2059 return pos; 2060 pos += ret; 2061 return pos; 2062} 2063 2064 2065static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 2066 const u8 *ie, size_t ie_len) 2067{ 2068 struct wpa_ie_data data; 2069 char *start; 2070 int ret; 2071 2072 ret = os_snprintf(pos, end - pos, "[%s-", proto); 2073 if (ret < 0 || ret >= end - pos) 2074 return pos; 2075 pos += ret; 2076 2077 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 2078 ret = os_snprintf(pos, end - pos, "?]"); 2079 if (ret < 0 || ret >= end - pos) 2080 return pos; 2081 pos += ret; 2082 return pos; 2083 } 2084 2085 start = pos; 2086 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 2087 ret = os_snprintf(pos, end - pos, "%sEAP", 2088 pos == start ? "" : "+"); 2089 if (ret < 0 || ret >= end - pos) 2090 return pos; 2091 pos += ret; 2092 } 2093 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 2094 ret = os_snprintf(pos, end - pos, "%sPSK", 2095 pos == start ? "" : "+"); 2096 if (ret < 0 || ret >= end - pos) 2097 return pos; 2098 pos += ret; 2099 } 2100 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 2101 ret = os_snprintf(pos, end - pos, "%sNone", 2102 pos == start ? "" : "+"); 2103 if (ret < 0 || ret >= end - pos) 2104 return pos; 2105 pos += ret; 2106 } 2107#ifdef CONFIG_IEEE80211R 2108 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 2109 ret = os_snprintf(pos, end - pos, "%sFT/EAP", 2110 pos == start ? "" : "+"); 2111 if (ret < 0 || ret >= end - pos) 2112 return pos; 2113 pos += ret; 2114 } 2115 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) { 2116 ret = os_snprintf(pos, end - pos, "%sFT/PSK", 2117 pos == start ? "" : "+"); 2118 if (ret < 0 || ret >= end - pos) 2119 return pos; 2120 pos += ret; 2121 } 2122#endif /* CONFIG_IEEE80211R */ 2123#ifdef CONFIG_IEEE80211W 2124 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 2125 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", 2126 pos == start ? "" : "+"); 2127 if (ret < 0 || ret >= end - pos) 2128 return pos; 2129 pos += ret; 2130 } 2131 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 2132 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", 2133 pos == start ? "" : "+"); 2134 if (ret < 0 || ret >= end - pos) 2135 return pos; 2136 pos += ret; 2137 } 2138#endif /* CONFIG_IEEE80211W */ 2139 2140 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 2141 2142 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 2143 ret = os_snprintf(pos, end - pos, "-preauth"); 2144 if (ret < 0 || ret >= end - pos) 2145 return pos; 2146 pos += ret; 2147 } 2148 2149 ret = os_snprintf(pos, end - pos, "]"); 2150 if (ret < 0 || ret >= end - pos) 2151 return pos; 2152 pos += ret; 2153 2154 return pos; 2155} 2156 2157 2158#ifdef CONFIG_WPS 2159static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s, 2160 char *pos, char *end, 2161 struct wpabuf *wps_ie) 2162{ 2163 int ret; 2164 const char *txt; 2165 2166 if (wps_ie == NULL) 2167 return pos; 2168 if (wps_is_selected_pbc_registrar(wps_ie)) 2169 txt = "[WPS-PBC]"; 2170 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0)) 2171 txt = "[WPS-AUTH]"; 2172 else if (wps_is_selected_pin_registrar(wps_ie)) 2173 txt = "[WPS-PIN]"; 2174 else 2175 txt = "[WPS]"; 2176 2177 ret = os_snprintf(pos, end - pos, "%s", txt); 2178 if (ret >= 0 && ret < end - pos) 2179 pos += ret; 2180 wpabuf_free(wps_ie); 2181 return pos; 2182} 2183#endif /* CONFIG_WPS */ 2184 2185 2186static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s, 2187 char *pos, char *end, 2188 const struct wpa_bss *bss) 2189{ 2190#ifdef CONFIG_WPS 2191 struct wpabuf *wps_ie; 2192 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 2193 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie); 2194#else /* CONFIG_WPS */ 2195 return pos; 2196#endif /* CONFIG_WPS */ 2197} 2198 2199 2200/* Format one result on one text line into a buffer. */ 2201static int wpa_supplicant_ctrl_iface_scan_result( 2202 struct wpa_supplicant *wpa_s, 2203 const struct wpa_bss *bss, char *buf, size_t buflen) 2204{ 2205 char *pos, *end; 2206 int ret; 2207 const u8 *ie, *ie2, *p2p; 2208 2209 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); 2210 if (!p2p) 2211 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE); 2212 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN && 2213 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 2214 0) 2215 return 0; /* Do not show P2P listen discovery results here */ 2216 2217 pos = buf; 2218 end = buf + buflen; 2219 2220 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 2221 MAC2STR(bss->bssid), bss->freq, bss->level); 2222 if (ret < 0 || ret >= end - pos) 2223 return -1; 2224 pos += ret; 2225 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 2226 if (ie) 2227 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 2228 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 2229 if (ie2) 2230 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 2231 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 2232 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 2233 ret = os_snprintf(pos, end - pos, "[WEP]"); 2234 if (ret < 0 || ret >= end - pos) 2235 return -1; 2236 pos += ret; 2237 } 2238 if (bss_is_dmg(bss)) { 2239 const char *s; 2240 ret = os_snprintf(pos, end - pos, "[DMG]"); 2241 if (ret < 0 || ret >= end - pos) 2242 return -1; 2243 pos += ret; 2244 switch (bss->caps & IEEE80211_CAP_DMG_MASK) { 2245 case IEEE80211_CAP_DMG_IBSS: 2246 s = "[IBSS]"; 2247 break; 2248 case IEEE80211_CAP_DMG_AP: 2249 s = "[ESS]"; 2250 break; 2251 case IEEE80211_CAP_DMG_PBSS: 2252 s = "[PBSS]"; 2253 break; 2254 default: 2255 s = ""; 2256 break; 2257 } 2258 ret = os_snprintf(pos, end - pos, "%s", s); 2259 if (ret < 0 || ret >= end - pos) 2260 return -1; 2261 pos += ret; 2262 } else { 2263 if (bss->caps & IEEE80211_CAP_IBSS) { 2264 ret = os_snprintf(pos, end - pos, "[IBSS]"); 2265 if (ret < 0 || ret >= end - pos) 2266 return -1; 2267 pos += ret; 2268 } 2269 if (bss->caps & IEEE80211_CAP_ESS) { 2270 ret = os_snprintf(pos, end - pos, "[ESS]"); 2271 if (ret < 0 || ret >= end - pos) 2272 return -1; 2273 pos += ret; 2274 } 2275 } 2276 if (p2p) { 2277 ret = os_snprintf(pos, end - pos, "[P2P]"); 2278 if (ret < 0 || ret >= end - pos) 2279 return -1; 2280 pos += ret; 2281 } 2282#ifdef CONFIG_HS20 2283 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) { 2284 ret = os_snprintf(pos, end - pos, "[HS20]"); 2285 if (ret < 0 || ret >= end - pos) 2286 return -1; 2287 pos += ret; 2288 } 2289#endif /* CONFIG_HS20 */ 2290 2291 ret = os_snprintf(pos, end - pos, "\t%s", 2292 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 2293 if (ret < 0 || ret >= end - pos) 2294 return -1; 2295 pos += ret; 2296 2297 ret = os_snprintf(pos, end - pos, "\n"); 2298 if (ret < 0 || ret >= end - pos) 2299 return -1; 2300 pos += ret; 2301 2302 return pos - buf; 2303} 2304 2305 2306static int wpa_supplicant_ctrl_iface_scan_results( 2307 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 2308{ 2309 char *pos, *end; 2310 struct wpa_bss *bss; 2311 int ret; 2312 2313 pos = buf; 2314 end = buf + buflen; 2315 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 2316 "flags / ssid\n"); 2317 if (ret < 0 || ret >= end - pos) 2318 return pos - buf; 2319 pos += ret; 2320 2321 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 2322 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos, 2323 end - pos); 2324 if (ret < 0 || ret >= end - pos) 2325 return pos - buf; 2326 pos += ret; 2327 } 2328 2329 return pos - buf; 2330} 2331 2332 2333static int wpa_supplicant_ctrl_iface_select_network( 2334 struct wpa_supplicant *wpa_s, char *cmd) 2335{ 2336 int id; 2337 struct wpa_ssid *ssid; 2338 char *pos; 2339 2340 /* cmd: "<network id>" or "any" */ 2341 if (os_strncmp(cmd, "any", 3) == 0) { 2342 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 2343 ssid = NULL; 2344 } else { 2345 id = atoi(cmd); 2346 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 2347 2348 ssid = wpa_config_get_network(wpa_s->conf, id); 2349 if (ssid == NULL) { 2350 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 2351 "network id=%d", id); 2352 return -1; 2353 } 2354 if (ssid->disabled == 2) { 2355 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 2356 "SELECT_NETWORK with persistent P2P group"); 2357 return -1; 2358 } 2359 } 2360 2361 pos = os_strstr(cmd, " freq="); 2362 if (pos) { 2363 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6); 2364 if (freqs) { 2365 wpa_s->scan_req = MANUAL_SCAN_REQ; 2366 os_free(wpa_s->manual_scan_freqs); 2367 wpa_s->manual_scan_freqs = freqs; 2368 } 2369 } 2370 2371 wpa_supplicant_select_network(wpa_s, ssid); 2372 2373 return 0; 2374} 2375 2376 2377static int wpa_supplicant_ctrl_iface_enable_network( 2378 struct wpa_supplicant *wpa_s, char *cmd) 2379{ 2380 int id; 2381 struct wpa_ssid *ssid; 2382 2383 /* cmd: "<network id>" or "all" */ 2384 if (os_strcmp(cmd, "all") == 0) { 2385 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 2386 ssid = NULL; 2387 } else { 2388 id = atoi(cmd); 2389 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 2390 2391 ssid = wpa_config_get_network(wpa_s->conf, id); 2392 if (ssid == NULL) { 2393 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 2394 "network id=%d", id); 2395 return -1; 2396 } 2397 if (ssid->disabled == 2) { 2398 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 2399 "ENABLE_NETWORK with persistent P2P group"); 2400 return -1; 2401 } 2402 2403 if (os_strstr(cmd, " no-connect")) { 2404 ssid->disabled = 0; 2405 return 0; 2406 } 2407 } 2408 wpa_supplicant_enable_network(wpa_s, ssid); 2409 2410 return 0; 2411} 2412 2413 2414static int wpa_supplicant_ctrl_iface_disable_network( 2415 struct wpa_supplicant *wpa_s, char *cmd) 2416{ 2417 int id; 2418 struct wpa_ssid *ssid; 2419 2420 /* cmd: "<network id>" or "all" */ 2421 if (os_strcmp(cmd, "all") == 0) { 2422 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 2423 ssid = NULL; 2424 } else { 2425 id = atoi(cmd); 2426 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 2427 2428 ssid = wpa_config_get_network(wpa_s->conf, id); 2429 if (ssid == NULL) { 2430 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 2431 "network id=%d", id); 2432 return -1; 2433 } 2434 if (ssid->disabled == 2) { 2435 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 2436 "DISABLE_NETWORK with persistent P2P " 2437 "group"); 2438 return -1; 2439 } 2440 } 2441 wpa_supplicant_disable_network(wpa_s, ssid); 2442 2443 return 0; 2444} 2445 2446 2447static int wpa_supplicant_ctrl_iface_add_network( 2448 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 2449{ 2450 struct wpa_ssid *ssid; 2451 int ret; 2452 2453 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 2454 2455 ssid = wpa_config_add_network(wpa_s->conf); 2456 if (ssid == NULL) 2457 return -1; 2458 2459 wpas_notify_network_added(wpa_s, ssid); 2460 2461 ssid->disabled = 1; 2462 wpa_config_set_network_defaults(ssid); 2463 2464 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 2465 if (ret < 0 || (size_t) ret >= buflen) 2466 return -1; 2467 return ret; 2468} 2469 2470 2471static int wpa_supplicant_ctrl_iface_remove_network( 2472 struct wpa_supplicant *wpa_s, char *cmd) 2473{ 2474 int id; 2475 struct wpa_ssid *ssid; 2476 int was_disabled; 2477 2478 /* cmd: "<network id>" or "all" */ 2479 if (os_strcmp(cmd, "all") == 0) { 2480 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 2481 if (wpa_s->sched_scanning) 2482 wpa_supplicant_cancel_sched_scan(wpa_s); 2483 2484 eapol_sm_invalidate_cached_session(wpa_s->eapol); 2485 if (wpa_s->current_ssid) { 2486#ifdef CONFIG_SME 2487 wpa_s->sme.prev_bssid_set = 0; 2488#endif /* CONFIG_SME */ 2489 wpa_sm_set_config(wpa_s->wpa, NULL); 2490 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 2491 wpa_supplicant_deauthenticate( 2492 wpa_s, WLAN_REASON_DEAUTH_LEAVING); 2493 } 2494 ssid = wpa_s->conf->ssid; 2495 while (ssid) { 2496 struct wpa_ssid *remove_ssid = ssid; 2497 id = ssid->id; 2498 ssid = ssid->next; 2499 if (wpa_s->last_ssid == remove_ssid) 2500 wpa_s->last_ssid = NULL; 2501 wpas_notify_network_removed(wpa_s, remove_ssid); 2502 wpa_config_remove_network(wpa_s->conf, id); 2503 } 2504 return 0; 2505 } 2506 2507 id = atoi(cmd); 2508 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 2509 2510 ssid = wpa_config_get_network(wpa_s->conf, id); 2511 if (ssid) 2512 wpas_notify_network_removed(wpa_s, ssid); 2513 if (ssid == NULL) { 2514 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 2515 "id=%d", id); 2516 return -1; 2517 } 2518 2519 if (wpa_s->last_ssid == ssid) 2520 wpa_s->last_ssid = NULL; 2521 2522 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) { 2523#ifdef CONFIG_SME 2524 wpa_s->sme.prev_bssid_set = 0; 2525#endif /* CONFIG_SME */ 2526 /* 2527 * Invalidate the EAP session cache if the current or 2528 * previously used network is removed. 2529 */ 2530 eapol_sm_invalidate_cached_session(wpa_s->eapol); 2531 } 2532 2533 if (ssid == wpa_s->current_ssid) { 2534 wpa_sm_set_config(wpa_s->wpa, NULL); 2535 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 2536 2537 wpa_supplicant_deauthenticate(wpa_s, 2538 WLAN_REASON_DEAUTH_LEAVING); 2539 } 2540 2541 was_disabled = ssid->disabled; 2542 2543 if (wpa_config_remove_network(wpa_s->conf, id) < 0) { 2544 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the " 2545 "network id=%d", id); 2546 return -1; 2547 } 2548 2549 if (!was_disabled && wpa_s->sched_scanning) { 2550 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove " 2551 "network from filters"); 2552 wpa_supplicant_cancel_sched_scan(wpa_s); 2553 wpa_supplicant_req_scan(wpa_s, 0, 0); 2554 } 2555 2556 return 0; 2557} 2558 2559 2560static int wpa_supplicant_ctrl_iface_update_network( 2561 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, 2562 char *name, char *value) 2563{ 2564 if (wpa_config_set(ssid, name, value, 0) < 0) { 2565 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 2566 "variable '%s'", name); 2567 return -1; 2568 } 2569 2570 if (os_strcmp(name, "bssid") != 0 && 2571 os_strcmp(name, "priority") != 0) 2572 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 2573 2574 if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) { 2575 /* 2576 * Invalidate the EAP session cache if anything in the current 2577 * or previously used configuration changes. 2578 */ 2579 eapol_sm_invalidate_cached_session(wpa_s->eapol); 2580 } 2581 2582 if ((os_strcmp(name, "psk") == 0 && 2583 value[0] == '"' && ssid->ssid_len) || 2584 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 2585 wpa_config_update_psk(ssid); 2586 else if (os_strcmp(name, "priority") == 0) 2587 wpa_config_update_prio_list(wpa_s->conf); 2588 2589 return 0; 2590} 2591 2592 2593static int wpa_supplicant_ctrl_iface_set_network( 2594 struct wpa_supplicant *wpa_s, char *cmd) 2595{ 2596 int id, ret, prev_bssid_set; 2597 struct wpa_ssid *ssid; 2598 char *name, *value; 2599 u8 prev_bssid[ETH_ALEN]; 2600 2601 /* cmd: "<network id> <variable name> <value>" */ 2602 name = os_strchr(cmd, ' '); 2603 if (name == NULL) 2604 return -1; 2605 *name++ = '\0'; 2606 2607 value = os_strchr(name, ' '); 2608 if (value == NULL) 2609 return -1; 2610 *value++ = '\0'; 2611 2612 id = atoi(cmd); 2613 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 2614 id, name); 2615 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 2616 (u8 *) value, os_strlen(value)); 2617 2618 ssid = wpa_config_get_network(wpa_s->conf, id); 2619 if (ssid == NULL) { 2620 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 2621 "id=%d", id); 2622 return -1; 2623 } 2624 2625 prev_bssid_set = ssid->bssid_set; 2626 os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN); 2627 ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name, 2628 value); 2629 if (ret == 0 && 2630 (ssid->bssid_set != prev_bssid_set || 2631 os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0)) 2632 wpas_notify_network_bssid_set_changed(wpa_s, ssid); 2633 return ret; 2634} 2635 2636 2637static int wpa_supplicant_ctrl_iface_get_network( 2638 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 2639{ 2640 int id; 2641 size_t res; 2642 struct wpa_ssid *ssid; 2643 char *name, *value; 2644 2645 /* cmd: "<network id> <variable name>" */ 2646 name = os_strchr(cmd, ' '); 2647 if (name == NULL || buflen == 0) 2648 return -1; 2649 *name++ = '\0'; 2650 2651 id = atoi(cmd); 2652 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 2653 id, name); 2654 2655 ssid = wpa_config_get_network(wpa_s->conf, id); 2656 if (ssid == NULL) { 2657 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 2658 "id=%d", id); 2659 return -1; 2660 } 2661 2662 value = wpa_config_get_no_key(ssid, name); 2663 if (value == NULL) { 2664 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 2665 "variable '%s'", name); 2666 return -1; 2667 } 2668 2669 res = os_strlcpy(buf, value, buflen); 2670 if (res >= buflen) { 2671 os_free(value); 2672 return -1; 2673 } 2674 2675 os_free(value); 2676 2677 return res; 2678} 2679 2680 2681static int wpa_supplicant_ctrl_iface_dup_network( 2682 struct wpa_supplicant *wpa_s, char *cmd) 2683{ 2684 struct wpa_ssid *ssid_s, *ssid_d; 2685 char *name, *id, *value; 2686 int id_s, id_d, ret; 2687 2688 /* cmd: "<src network id> <dst network id> <variable name>" */ 2689 id = os_strchr(cmd, ' '); 2690 if (id == NULL) 2691 return -1; 2692 *id++ = '\0'; 2693 2694 name = os_strchr(id, ' '); 2695 if (name == NULL) 2696 return -1; 2697 *name++ = '\0'; 2698 2699 id_s = atoi(cmd); 2700 id_d = atoi(id); 2701 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DUP_NETWORK id=%d -> %d name='%s'", 2702 id_s, id_d, name); 2703 2704 ssid_s = wpa_config_get_network(wpa_s->conf, id_s); 2705 if (ssid_s == NULL) { 2706 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 2707 "network id=%d", id_s); 2708 return -1; 2709 } 2710 2711 ssid_d = wpa_config_get_network(wpa_s->conf, id_d); 2712 if (ssid_d == NULL) { 2713 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 2714 "network id=%d", id_s); 2715 return -1; 2716 } 2717 2718 value = wpa_config_get(ssid_s, name); 2719 if (value == NULL) { 2720 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 2721 "variable '%s'", name); 2722 return -1; 2723 } 2724 2725 ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid_d, name, 2726 value); 2727 2728 os_free(value); 2729 2730 return ret; 2731} 2732 2733 2734static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s, 2735 char *buf, size_t buflen) 2736{ 2737 char *pos, *end; 2738 struct wpa_cred *cred; 2739 int ret; 2740 2741 pos = buf; 2742 end = buf + buflen; 2743 ret = os_snprintf(pos, end - pos, 2744 "cred id / realm / username / domain / imsi\n"); 2745 if (ret < 0 || ret >= end - pos) 2746 return pos - buf; 2747 pos += ret; 2748 2749 cred = wpa_s->conf->cred; 2750 while (cred) { 2751 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n", 2752 cred->id, cred->realm ? cred->realm : "", 2753 cred->username ? cred->username : "", 2754 cred->domain ? cred->domain[0] : "", 2755 cred->imsi ? cred->imsi : ""); 2756 if (ret < 0 || ret >= end - pos) 2757 return pos - buf; 2758 pos += ret; 2759 2760 cred = cred->next; 2761 } 2762 2763 return pos - buf; 2764} 2765 2766 2767static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s, 2768 char *buf, size_t buflen) 2769{ 2770 struct wpa_cred *cred; 2771 int ret; 2772 2773 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED"); 2774 2775 cred = wpa_config_add_cred(wpa_s->conf); 2776 if (cred == NULL) 2777 return -1; 2778 2779 wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id); 2780 2781 ret = os_snprintf(buf, buflen, "%d\n", cred->id); 2782 if (ret < 0 || (size_t) ret >= buflen) 2783 return -1; 2784 return ret; 2785} 2786 2787 2788static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s, 2789 struct wpa_cred *cred) 2790{ 2791 struct wpa_ssid *ssid; 2792 char str[20]; 2793 int id; 2794 2795 if (cred == NULL) { 2796 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred"); 2797 return -1; 2798 } 2799 2800 id = cred->id; 2801 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) { 2802 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred"); 2803 return -1; 2804 } 2805 2806 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id); 2807 2808 /* Remove any network entry created based on the removed credential */ 2809 ssid = wpa_s->conf->ssid; 2810 while (ssid) { 2811 if (ssid->parent_cred == cred) { 2812 wpa_printf(MSG_DEBUG, "Remove network id %d since it " 2813 "used the removed credential", ssid->id); 2814 os_snprintf(str, sizeof(str), "%d", ssid->id); 2815 ssid = ssid->next; 2816 wpa_supplicant_ctrl_iface_remove_network(wpa_s, str); 2817 } else 2818 ssid = ssid->next; 2819 } 2820 2821 return 0; 2822} 2823 2824 2825static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, 2826 char *cmd) 2827{ 2828 int id; 2829 struct wpa_cred *cred, *prev; 2830 2831 /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or 2832 * "provisioning_sp=<FQDN> */ 2833 if (os_strcmp(cmd, "all") == 0) { 2834 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all"); 2835 cred = wpa_s->conf->cred; 2836 while (cred) { 2837 prev = cred; 2838 cred = cred->next; 2839 wpas_ctrl_remove_cred(wpa_s, prev); 2840 } 2841 return 0; 2842 } 2843 2844 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) { 2845 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'", 2846 cmd + 8); 2847 cred = wpa_s->conf->cred; 2848 while (cred) { 2849 prev = cred; 2850 cred = cred->next; 2851 if (prev->domain) { 2852 size_t i; 2853 for (i = 0; i < prev->num_domain; i++) { 2854 if (os_strcmp(prev->domain[i], cmd + 8) 2855 != 0) 2856 continue; 2857 wpas_ctrl_remove_cred(wpa_s, prev); 2858 break; 2859 } 2860 } 2861 } 2862 return 0; 2863 } 2864 2865 if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) { 2866 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'", 2867 cmd + 16); 2868 cred = wpa_s->conf->cred; 2869 while (cred) { 2870 prev = cred; 2871 cred = cred->next; 2872 if (prev->provisioning_sp && 2873 os_strcmp(prev->provisioning_sp, cmd + 16) == 0) 2874 wpas_ctrl_remove_cred(wpa_s, prev); 2875 } 2876 return 0; 2877 } 2878 2879 id = atoi(cmd); 2880 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id); 2881 2882 cred = wpa_config_get_cred(wpa_s->conf, id); 2883 return wpas_ctrl_remove_cred(wpa_s, cred); 2884} 2885 2886 2887static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s, 2888 char *cmd) 2889{ 2890 int id; 2891 struct wpa_cred *cred; 2892 char *name, *value; 2893 2894 /* cmd: "<cred id> <variable name> <value>" */ 2895 name = os_strchr(cmd, ' '); 2896 if (name == NULL) 2897 return -1; 2898 *name++ = '\0'; 2899 2900 value = os_strchr(name, ' '); 2901 if (value == NULL) 2902 return -1; 2903 *value++ = '\0'; 2904 2905 id = atoi(cmd); 2906 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'", 2907 id, name); 2908 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 2909 (u8 *) value, os_strlen(value)); 2910 2911 cred = wpa_config_get_cred(wpa_s->conf, id); 2912 if (cred == NULL) { 2913 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 2914 id); 2915 return -1; 2916 } 2917 2918 if (wpa_config_set_cred(cred, name, value, 0) < 0) { 2919 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred " 2920 "variable '%s'", name); 2921 return -1; 2922 } 2923 2924 wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name); 2925 2926 return 0; 2927} 2928 2929 2930static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s, 2931 char *cmd, char *buf, 2932 size_t buflen) 2933{ 2934 int id; 2935 size_t res; 2936 struct wpa_cred *cred; 2937 char *name, *value; 2938 2939 /* cmd: "<cred id> <variable name>" */ 2940 name = os_strchr(cmd, ' '); 2941 if (name == NULL) 2942 return -1; 2943 *name++ = '\0'; 2944 2945 id = atoi(cmd); 2946 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'", 2947 id, name); 2948 2949 cred = wpa_config_get_cred(wpa_s->conf, id); 2950 if (cred == NULL) { 2951 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 2952 id); 2953 return -1; 2954 } 2955 2956 value = wpa_config_get_cred_no_key(cred, name); 2957 if (value == NULL) { 2958 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'", 2959 name); 2960 return -1; 2961 } 2962 2963 res = os_strlcpy(buf, value, buflen); 2964 if (res >= buflen) { 2965 os_free(value); 2966 return -1; 2967 } 2968 2969 os_free(value); 2970 2971 return res; 2972} 2973 2974 2975#ifndef CONFIG_NO_CONFIG_WRITE 2976static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 2977{ 2978 int ret; 2979 2980 if (!wpa_s->conf->update_config) { 2981 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 2982 "to update configuration (update_config=0)"); 2983 return -1; 2984 } 2985 2986 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 2987 if (ret) { 2988 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 2989 "update configuration"); 2990 } else { 2991 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 2992 " updated"); 2993 } 2994 2995 return ret; 2996} 2997#endif /* CONFIG_NO_CONFIG_WRITE */ 2998 2999 3000struct cipher_info { 3001 unsigned int capa; 3002 const char *name; 3003 int group_only; 3004}; 3005 3006static const struct cipher_info ciphers[] = { 3007 { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 }, 3008 { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 }, 3009 { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 }, 3010 { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 }, 3011 { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 }, 3012 { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 }, 3013 { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 }, 3014 { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 } 3015}; 3016 3017 3018static int ctrl_iface_get_capability_pairwise(int res, char *strict, 3019 struct wpa_driver_capa *capa, 3020 char *buf, size_t buflen) 3021{ 3022 int ret; 3023 char *pos, *end; 3024 size_t len; 3025 unsigned int i; 3026 3027 pos = buf; 3028 end = pos + buflen; 3029 3030 if (res < 0) { 3031 if (strict) 3032 return 0; 3033 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 3034 if (len >= buflen) 3035 return -1; 3036 return len; 3037 } 3038 3039 for (i = 0; i < ARRAY_SIZE(ciphers); i++) { 3040 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) { 3041 ret = os_snprintf(pos, end - pos, "%s%s", 3042 pos == buf ? "" : " ", 3043 ciphers[i].name); 3044 if (ret < 0 || ret >= end - pos) 3045 return pos - buf; 3046 pos += ret; 3047 } 3048 } 3049 3050 return pos - buf; 3051} 3052 3053 3054static int ctrl_iface_get_capability_group(int res, char *strict, 3055 struct wpa_driver_capa *capa, 3056 char *buf, size_t buflen) 3057{ 3058 int ret; 3059 char *pos, *end; 3060 size_t len; 3061 unsigned int i; 3062 3063 pos = buf; 3064 end = pos + buflen; 3065 3066 if (res < 0) { 3067 if (strict) 3068 return 0; 3069 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 3070 if (len >= buflen) 3071 return -1; 3072 return len; 3073 } 3074 3075 for (i = 0; i < ARRAY_SIZE(ciphers); i++) { 3076 if (capa->enc & ciphers[i].capa) { 3077 ret = os_snprintf(pos, end - pos, "%s%s", 3078 pos == buf ? "" : " ", 3079 ciphers[i].name); 3080 if (ret < 0 || ret >= end - pos) 3081 return pos - buf; 3082 pos += ret; 3083 } 3084 } 3085 3086 return pos - buf; 3087} 3088 3089 3090static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, 3091 struct wpa_driver_capa *capa, 3092 char *buf, size_t buflen) 3093{ 3094 int ret; 3095 char *pos, *end; 3096 size_t len; 3097 3098 pos = buf; 3099 end = pos + buflen; 3100 3101 if (res < 0) { 3102 if (strict) 3103 return 0; 3104 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 3105 "NONE", buflen); 3106 if (len >= buflen) 3107 return -1; 3108 return len; 3109 } 3110 3111 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 3112 if (ret < 0 || ret >= end - pos) 3113 return pos - buf; 3114 pos += ret; 3115 3116 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 3117 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 3118 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 3119 if (ret < 0 || ret >= end - pos) 3120 return pos - buf; 3121 pos += ret; 3122 } 3123 3124 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 3125 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 3126 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 3127 if (ret < 0 || ret >= end - pos) 3128 return pos - buf; 3129 pos += ret; 3130 } 3131 3132 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 3133 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 3134 if (ret < 0 || ret >= end - pos) 3135 return pos - buf; 3136 pos += ret; 3137 } 3138 3139 return pos - buf; 3140} 3141 3142 3143static int ctrl_iface_get_capability_proto(int res, char *strict, 3144 struct wpa_driver_capa *capa, 3145 char *buf, size_t buflen) 3146{ 3147 int ret; 3148 char *pos, *end; 3149 size_t len; 3150 3151 pos = buf; 3152 end = pos + buflen; 3153 3154 if (res < 0) { 3155 if (strict) 3156 return 0; 3157 len = os_strlcpy(buf, "RSN WPA", buflen); 3158 if (len >= buflen) 3159 return -1; 3160 return len; 3161 } 3162 3163 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 3164 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 3165 ret = os_snprintf(pos, end - pos, "%sRSN", 3166 pos == buf ? "" : " "); 3167 if (ret < 0 || ret >= end - pos) 3168 return pos - buf; 3169 pos += ret; 3170 } 3171 3172 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 3173 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 3174 ret = os_snprintf(pos, end - pos, "%sWPA", 3175 pos == buf ? "" : " "); 3176 if (ret < 0 || ret >= end - pos) 3177 return pos - buf; 3178 pos += ret; 3179 } 3180 3181 return pos - buf; 3182} 3183 3184 3185static int ctrl_iface_get_capability_auth_alg(int res, char *strict, 3186 struct wpa_driver_capa *capa, 3187 char *buf, size_t buflen) 3188{ 3189 int ret; 3190 char *pos, *end; 3191 size_t len; 3192 3193 pos = buf; 3194 end = pos + buflen; 3195 3196 if (res < 0) { 3197 if (strict) 3198 return 0; 3199 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 3200 if (len >= buflen) 3201 return -1; 3202 return len; 3203 } 3204 3205 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 3206 ret = os_snprintf(pos, end - pos, "%sOPEN", 3207 pos == buf ? "" : " "); 3208 if (ret < 0 || ret >= end - pos) 3209 return pos - buf; 3210 pos += ret; 3211 } 3212 3213 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 3214 ret = os_snprintf(pos, end - pos, "%sSHARED", 3215 pos == buf ? "" : " "); 3216 if (ret < 0 || ret >= end - pos) 3217 return pos - buf; 3218 pos += ret; 3219 } 3220 3221 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 3222 ret = os_snprintf(pos, end - pos, "%sLEAP", 3223 pos == buf ? "" : " "); 3224 if (ret < 0 || ret >= end - pos) 3225 return pos - buf; 3226 pos += ret; 3227 } 3228 3229 return pos - buf; 3230} 3231 3232 3233static int ctrl_iface_get_capability_modes(int res, char *strict, 3234 struct wpa_driver_capa *capa, 3235 char *buf, size_t buflen) 3236{ 3237 int ret; 3238 char *pos, *end; 3239 size_t len; 3240 3241 pos = buf; 3242 end = pos + buflen; 3243 3244 if (res < 0) { 3245 if (strict) 3246 return 0; 3247 len = os_strlcpy(buf, "IBSS AP", buflen); 3248 if (len >= buflen) 3249 return -1; 3250 return len; 3251 } 3252 3253 if (capa->flags & WPA_DRIVER_FLAGS_IBSS) { 3254 ret = os_snprintf(pos, end - pos, "%sIBSS", 3255 pos == buf ? "" : " "); 3256 if (ret < 0 || ret >= end - pos) 3257 return pos - buf; 3258 pos += ret; 3259 } 3260 3261 if (capa->flags & WPA_DRIVER_FLAGS_AP) { 3262 ret = os_snprintf(pos, end - pos, "%sAP", 3263 pos == buf ? "" : " "); 3264 if (ret < 0 || ret >= end - pos) 3265 return pos - buf; 3266 pos += ret; 3267 } 3268 3269 return pos - buf; 3270} 3271 3272 3273static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s, 3274 char *buf, size_t buflen) 3275{ 3276 struct hostapd_channel_data *chnl; 3277 int ret, i, j; 3278 char *pos, *end, *hmode; 3279 3280 pos = buf; 3281 end = pos + buflen; 3282 3283 for (j = 0; j < wpa_s->hw.num_modes; j++) { 3284 switch (wpa_s->hw.modes[j].mode) { 3285 case HOSTAPD_MODE_IEEE80211B: 3286 hmode = "B"; 3287 break; 3288 case HOSTAPD_MODE_IEEE80211G: 3289 hmode = "G"; 3290 break; 3291 case HOSTAPD_MODE_IEEE80211A: 3292 hmode = "A"; 3293 break; 3294 case HOSTAPD_MODE_IEEE80211AD: 3295 hmode = "AD"; 3296 break; 3297 default: 3298 continue; 3299 } 3300 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode); 3301 if (ret < 0 || ret >= end - pos) 3302 return pos - buf; 3303 pos += ret; 3304 chnl = wpa_s->hw.modes[j].channels; 3305 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 3306 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 3307 continue; 3308 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan); 3309 if (ret < 0 || ret >= end - pos) 3310 return pos - buf; 3311 pos += ret; 3312 } 3313 ret = os_snprintf(pos, end - pos, "\n"); 3314 if (ret < 0 || ret >= end - pos) 3315 return pos - buf; 3316 pos += ret; 3317 } 3318 3319 return pos - buf; 3320} 3321 3322 3323static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s, 3324 char *buf, size_t buflen) 3325{ 3326 struct hostapd_channel_data *chnl; 3327 int ret, i, j; 3328 char *pos, *end, *hmode; 3329 3330 pos = buf; 3331 end = pos + buflen; 3332 3333 for (j = 0; j < wpa_s->hw.num_modes; j++) { 3334 switch (wpa_s->hw.modes[j].mode) { 3335 case HOSTAPD_MODE_IEEE80211B: 3336 hmode = "B"; 3337 break; 3338 case HOSTAPD_MODE_IEEE80211G: 3339 hmode = "G"; 3340 break; 3341 case HOSTAPD_MODE_IEEE80211A: 3342 hmode = "A"; 3343 break; 3344 case HOSTAPD_MODE_IEEE80211AD: 3345 hmode = "AD"; 3346 break; 3347 default: 3348 continue; 3349 } 3350 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n", 3351 hmode); 3352 if (ret < 0 || ret >= end - pos) 3353 return pos - buf; 3354 pos += ret; 3355 chnl = wpa_s->hw.modes[j].channels; 3356 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 3357 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 3358 continue; 3359 ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n", 3360 chnl[i].chan, chnl[i].freq, 3361 chnl[i].flag & HOSTAPD_CHAN_NO_IBSS ? 3362 " (NO_IBSS)" : "", 3363 chnl[i].flag & HOSTAPD_CHAN_RADAR ? 3364 " (DFS)" : ""); 3365 3366 if (ret < 0 || ret >= end - pos) 3367 return pos - buf; 3368 pos += ret; 3369 } 3370 ret = os_snprintf(pos, end - pos, "\n"); 3371 if (ret < 0 || ret >= end - pos) 3372 return pos - buf; 3373 pos += ret; 3374 } 3375 3376 return pos - buf; 3377} 3378 3379 3380static int wpa_supplicant_ctrl_iface_get_capability( 3381 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 3382 size_t buflen) 3383{ 3384 struct wpa_driver_capa capa; 3385 int res; 3386 char *strict; 3387 char field[30]; 3388 size_t len; 3389 3390 /* Determine whether or not strict checking was requested */ 3391 len = os_strlcpy(field, _field, sizeof(field)); 3392 if (len >= sizeof(field)) 3393 return -1; 3394 strict = os_strchr(field, ' '); 3395 if (strict != NULL) { 3396 *strict++ = '\0'; 3397 if (os_strcmp(strict, "strict") != 0) 3398 return -1; 3399 } 3400 3401 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", 3402 field, strict ? strict : ""); 3403 3404 if (os_strcmp(field, "eap") == 0) { 3405 return eap_get_names(buf, buflen); 3406 } 3407 3408 res = wpa_drv_get_capa(wpa_s, &capa); 3409 3410 if (os_strcmp(field, "pairwise") == 0) 3411 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 3412 buf, buflen); 3413 3414 if (os_strcmp(field, "group") == 0) 3415 return ctrl_iface_get_capability_group(res, strict, &capa, 3416 buf, buflen); 3417 3418 if (os_strcmp(field, "key_mgmt") == 0) 3419 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 3420 buf, buflen); 3421 3422 if (os_strcmp(field, "proto") == 0) 3423 return ctrl_iface_get_capability_proto(res, strict, &capa, 3424 buf, buflen); 3425 3426 if (os_strcmp(field, "auth_alg") == 0) 3427 return ctrl_iface_get_capability_auth_alg(res, strict, &capa, 3428 buf, buflen); 3429 3430 if (os_strcmp(field, "modes") == 0) 3431 return ctrl_iface_get_capability_modes(res, strict, &capa, 3432 buf, buflen); 3433 3434 if (os_strcmp(field, "channels") == 0) 3435 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen); 3436 3437 if (os_strcmp(field, "freq") == 0) 3438 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen); 3439 3440#ifdef CONFIG_TDLS 3441 if (os_strcmp(field, "tdls") == 0) 3442 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen); 3443#endif /* CONFIG_TDLS */ 3444 3445 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 3446 field); 3447 3448 return -1; 3449} 3450 3451 3452#ifdef CONFIG_INTERWORKING 3453static char * anqp_add_hex(char *pos, char *end, const char *title, 3454 struct wpabuf *data) 3455{ 3456 char *start = pos; 3457 size_t i; 3458 int ret; 3459 const u8 *d; 3460 3461 if (data == NULL) 3462 return start; 3463 3464 ret = os_snprintf(pos, end - pos, "%s=", title); 3465 if (ret < 0 || ret >= end - pos) 3466 return start; 3467 pos += ret; 3468 3469 d = wpabuf_head_u8(data); 3470 for (i = 0; i < wpabuf_len(data); i++) { 3471 ret = os_snprintf(pos, end - pos, "%02x", *d++); 3472 if (ret < 0 || ret >= end - pos) 3473 return start; 3474 pos += ret; 3475 } 3476 3477 ret = os_snprintf(pos, end - pos, "\n"); 3478 if (ret < 0 || ret >= end - pos) 3479 return start; 3480 pos += ret; 3481 3482 return pos; 3483} 3484#endif /* CONFIG_INTERWORKING */ 3485 3486 3487static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 3488 unsigned long mask, char *buf, size_t buflen) 3489{ 3490 size_t i; 3491 int ret; 3492 char *pos, *end; 3493 const u8 *ie, *ie2; 3494 3495 pos = buf; 3496 end = buf + buflen; 3497 3498 if (mask & WPA_BSS_MASK_ID) { 3499 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id); 3500 if (ret < 0 || ret >= end - pos) 3501 return 0; 3502 pos += ret; 3503 } 3504 3505 if (mask & WPA_BSS_MASK_BSSID) { 3506 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 3507 MAC2STR(bss->bssid)); 3508 if (ret < 0 || ret >= end - pos) 3509 return 0; 3510 pos += ret; 3511 } 3512 3513 if (mask & WPA_BSS_MASK_FREQ) { 3514 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq); 3515 if (ret < 0 || ret >= end - pos) 3516 return 0; 3517 pos += ret; 3518 } 3519 3520 if (mask & WPA_BSS_MASK_BEACON_INT) { 3521 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n", 3522 bss->beacon_int); 3523 if (ret < 0 || ret >= end - pos) 3524 return 0; 3525 pos += ret; 3526 } 3527 3528 if (mask & WPA_BSS_MASK_CAPABILITIES) { 3529 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n", 3530 bss->caps); 3531 if (ret < 0 || ret >= end - pos) 3532 return 0; 3533 pos += ret; 3534 } 3535 3536 if (mask & WPA_BSS_MASK_QUAL) { 3537 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual); 3538 if (ret < 0 || ret >= end - pos) 3539 return 0; 3540 pos += ret; 3541 } 3542 3543 if (mask & WPA_BSS_MASK_NOISE) { 3544 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise); 3545 if (ret < 0 || ret >= end - pos) 3546 return 0; 3547 pos += ret; 3548 } 3549 3550 if (mask & WPA_BSS_MASK_LEVEL) { 3551 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level); 3552 if (ret < 0 || ret >= end - pos) 3553 return 0; 3554 pos += ret; 3555 } 3556 3557 if (mask & WPA_BSS_MASK_TSF) { 3558 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n", 3559 (unsigned long long) bss->tsf); 3560 if (ret < 0 || ret >= end - pos) 3561 return 0; 3562 pos += ret; 3563 } 3564 3565 if (mask & WPA_BSS_MASK_AGE) { 3566 struct os_reltime now; 3567 3568 os_get_reltime(&now); 3569 ret = os_snprintf(pos, end - pos, "age=%d\n", 3570 (int) (now.sec - bss->last_update.sec)); 3571 if (ret < 0 || ret >= end - pos) 3572 return 0; 3573 pos += ret; 3574 } 3575 3576 if (mask & WPA_BSS_MASK_IE) { 3577 ret = os_snprintf(pos, end - pos, "ie="); 3578 if (ret < 0 || ret >= end - pos) 3579 return 0; 3580 pos += ret; 3581 3582 ie = (const u8 *) (bss + 1); 3583 for (i = 0; i < bss->ie_len; i++) { 3584 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 3585 if (ret < 0 || ret >= end - pos) 3586 return 0; 3587 pos += ret; 3588 } 3589 3590 ret = os_snprintf(pos, end - pos, "\n"); 3591 if (ret < 0 || ret >= end - pos) 3592 return 0; 3593 pos += ret; 3594 } 3595 3596 if (mask & WPA_BSS_MASK_FLAGS) { 3597 ret = os_snprintf(pos, end - pos, "flags="); 3598 if (ret < 0 || ret >= end - pos) 3599 return 0; 3600 pos += ret; 3601 3602 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 3603 if (ie) 3604 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 3605 2 + ie[1]); 3606 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 3607 if (ie2) 3608 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 3609 2 + ie2[1]); 3610 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 3611 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 3612 ret = os_snprintf(pos, end - pos, "[WEP]"); 3613 if (ret < 0 || ret >= end - pos) 3614 return 0; 3615 pos += ret; 3616 } 3617 if (bss_is_dmg(bss)) { 3618 const char *s; 3619 ret = os_snprintf(pos, end - pos, "[DMG]"); 3620 if (ret < 0 || ret >= end - pos) 3621 return 0; 3622 pos += ret; 3623 switch (bss->caps & IEEE80211_CAP_DMG_MASK) { 3624 case IEEE80211_CAP_DMG_IBSS: 3625 s = "[IBSS]"; 3626 break; 3627 case IEEE80211_CAP_DMG_AP: 3628 s = "[ESS]"; 3629 break; 3630 case IEEE80211_CAP_DMG_PBSS: 3631 s = "[PBSS]"; 3632 break; 3633 default: 3634 s = ""; 3635 break; 3636 } 3637 ret = os_snprintf(pos, end - pos, "%s", s); 3638 if (ret < 0 || ret >= end - pos) 3639 return 0; 3640 pos += ret; 3641 } else { 3642 if (bss->caps & IEEE80211_CAP_IBSS) { 3643 ret = os_snprintf(pos, end - pos, "[IBSS]"); 3644 if (ret < 0 || ret >= end - pos) 3645 return 0; 3646 pos += ret; 3647 } 3648 if (bss->caps & IEEE80211_CAP_ESS) { 3649 ret = os_snprintf(pos, end - pos, "[ESS]"); 3650 if (ret < 0 || ret >= end - pos) 3651 return 0; 3652 pos += ret; 3653 } 3654 } 3655 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || 3656 wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { 3657 ret = os_snprintf(pos, end - pos, "[P2P]"); 3658 if (ret < 0 || ret >= end - pos) 3659 return 0; 3660 pos += ret; 3661 } 3662#ifdef CONFIG_HS20 3663 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 3664 ret = os_snprintf(pos, end - pos, "[HS20]"); 3665 if (ret < 0 || ret >= end - pos) 3666 return 0; 3667 pos += ret; 3668 } 3669#endif /* CONFIG_HS20 */ 3670 3671 ret = os_snprintf(pos, end - pos, "\n"); 3672 if (ret < 0 || ret >= end - pos) 3673 return 0; 3674 pos += ret; 3675 } 3676 3677 if (mask & WPA_BSS_MASK_SSID) { 3678 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 3679 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 3680 if (ret < 0 || ret >= end - pos) 3681 return 0; 3682 pos += ret; 3683 } 3684 3685#ifdef CONFIG_WPS 3686 if (mask & WPA_BSS_MASK_WPS_SCAN) { 3687 ie = (const u8 *) (bss + 1); 3688 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); 3689 if (ret < 0 || ret >= end - pos) 3690 return 0; 3691 pos += ret; 3692 } 3693#endif /* CONFIG_WPS */ 3694 3695#ifdef CONFIG_P2P 3696 if (mask & WPA_BSS_MASK_P2P_SCAN) { 3697 ie = (const u8 *) (bss + 1); 3698 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); 3699 if (ret < 0 || ret >= end - pos) 3700 return 0; 3701 pos += ret; 3702 } 3703#endif /* CONFIG_P2P */ 3704 3705#ifdef CONFIG_WIFI_DISPLAY 3706 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) { 3707 struct wpabuf *wfd; 3708 ie = (const u8 *) (bss + 1); 3709 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len, 3710 WFD_IE_VENDOR_TYPE); 3711 if (wfd) { 3712 ret = os_snprintf(pos, end - pos, "wfd_subelems="); 3713 if (ret < 0 || ret >= end - pos) { 3714 wpabuf_free(wfd); 3715 return 0; 3716 } 3717 pos += ret; 3718 3719 pos += wpa_snprintf_hex(pos, end - pos, 3720 wpabuf_head(wfd), 3721 wpabuf_len(wfd)); 3722 wpabuf_free(wfd); 3723 3724 ret = os_snprintf(pos, end - pos, "\n"); 3725 if (ret < 0 || ret >= end - pos) 3726 return 0; 3727 pos += ret; 3728 } 3729 } 3730#endif /* CONFIG_WIFI_DISPLAY */ 3731 3732#ifdef CONFIG_INTERWORKING 3733 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) { 3734 struct wpa_bss_anqp *anqp = bss->anqp; 3735 pos = anqp_add_hex(pos, end, "anqp_venue_name", 3736 anqp->venue_name); 3737 pos = anqp_add_hex(pos, end, "anqp_network_auth_type", 3738 anqp->network_auth_type); 3739 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium", 3740 anqp->roaming_consortium); 3741 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability", 3742 anqp->ip_addr_type_availability); 3743 pos = anqp_add_hex(pos, end, "anqp_nai_realm", 3744 anqp->nai_realm); 3745 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp); 3746 pos = anqp_add_hex(pos, end, "anqp_domain_name", 3747 anqp->domain_name); 3748#ifdef CONFIG_HS20 3749 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name", 3750 anqp->hs20_operator_friendly_name); 3751 pos = anqp_add_hex(pos, end, "hs20_wan_metrics", 3752 anqp->hs20_wan_metrics); 3753 pos = anqp_add_hex(pos, end, "hs20_connection_capability", 3754 anqp->hs20_connection_capability); 3755 pos = anqp_add_hex(pos, end, "hs20_operating_class", 3756 anqp->hs20_operating_class); 3757 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list", 3758 anqp->hs20_osu_providers_list); 3759#endif /* CONFIG_HS20 */ 3760 } 3761#endif /* CONFIG_INTERWORKING */ 3762 3763 if (mask & WPA_BSS_MASK_DELIM) { 3764 ret = os_snprintf(pos, end - pos, "====\n"); 3765 if (ret < 0 || ret >= end - pos) 3766 return 0; 3767 pos += ret; 3768 } 3769 3770 return pos - buf; 3771} 3772 3773 3774static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 3775 const char *cmd, char *buf, 3776 size_t buflen) 3777{ 3778 u8 bssid[ETH_ALEN]; 3779 size_t i; 3780 struct wpa_bss *bss; 3781 struct wpa_bss *bsslast = NULL; 3782 struct dl_list *next; 3783 int ret = 0; 3784 int len; 3785 char *ctmp; 3786 unsigned long mask = WPA_BSS_MASK_ALL; 3787 3788 if (os_strncmp(cmd, "RANGE=", 6) == 0) { 3789 if (os_strncmp(cmd + 6, "ALL", 3) == 0) { 3790 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, 3791 list_id); 3792 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss, 3793 list_id); 3794 } else { /* N1-N2 */ 3795 unsigned int id1, id2; 3796 3797 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) { 3798 wpa_printf(MSG_INFO, "Wrong BSS range " 3799 "format"); 3800 return 0; 3801 } 3802 3803 if (*(cmd + 6) == '-') 3804 id1 = 0; 3805 else 3806 id1 = atoi(cmd + 6); 3807 ctmp++; 3808 if (*ctmp >= '0' && *ctmp <= '9') 3809 id2 = atoi(ctmp); 3810 else 3811 id2 = (unsigned int) -1; 3812 bss = wpa_bss_get_id_range(wpa_s, id1, id2); 3813 if (id2 == (unsigned int) -1) 3814 bsslast = dl_list_last(&wpa_s->bss_id, 3815 struct wpa_bss, 3816 list_id); 3817 else { 3818 bsslast = wpa_bss_get_id(wpa_s, id2); 3819 if (bsslast == NULL && bss && id2 > id1) { 3820 struct wpa_bss *tmp = bss; 3821 for (;;) { 3822 next = tmp->list_id.next; 3823 if (next == &wpa_s->bss_id) 3824 break; 3825 tmp = dl_list_entry( 3826 next, struct wpa_bss, 3827 list_id); 3828 if (tmp->id > id2) 3829 break; 3830 bsslast = tmp; 3831 } 3832 } 3833 } 3834 } 3835 } else if (os_strncmp(cmd, "FIRST", 5) == 0) 3836 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id); 3837 else if (os_strncmp(cmd, "LAST", 4) == 0) 3838 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id); 3839 else if (os_strncmp(cmd, "ID-", 3) == 0) { 3840 i = atoi(cmd + 3); 3841 bss = wpa_bss_get_id(wpa_s, i); 3842 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 3843 i = atoi(cmd + 5); 3844 bss = wpa_bss_get_id(wpa_s, i); 3845 if (bss) { 3846 next = bss->list_id.next; 3847 if (next == &wpa_s->bss_id) 3848 bss = NULL; 3849 else 3850 bss = dl_list_entry(next, struct wpa_bss, 3851 list_id); 3852 } 3853#ifdef CONFIG_P2P 3854 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 3855 if (hwaddr_aton(cmd + 13, bssid) == 0) 3856 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid); 3857 else 3858 bss = NULL; 3859#endif /* CONFIG_P2P */ 3860 } else if (hwaddr_aton(cmd, bssid) == 0) 3861 bss = wpa_bss_get_bssid(wpa_s, bssid); 3862 else { 3863 struct wpa_bss *tmp; 3864 i = atoi(cmd); 3865 bss = NULL; 3866 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) 3867 { 3868 if (i-- == 0) { 3869 bss = tmp; 3870 break; 3871 } 3872 } 3873 } 3874 3875 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) { 3876 mask = strtoul(ctmp + 5, NULL, 0x10); 3877 if (mask == 0) 3878 mask = WPA_BSS_MASK_ALL; 3879 } 3880 3881 if (bss == NULL) 3882 return 0; 3883 3884 if (bsslast == NULL) 3885 bsslast = bss; 3886 do { 3887 len = print_bss_info(wpa_s, bss, mask, buf, buflen); 3888 ret += len; 3889 buf += len; 3890 buflen -= len; 3891 if (bss == bsslast) { 3892 if ((mask & WPA_BSS_MASK_DELIM) && len && 3893 (bss == dl_list_last(&wpa_s->bss_id, 3894 struct wpa_bss, list_id))) 3895 os_snprintf(buf - 5, 5, "####\n"); 3896 break; 3897 } 3898 next = bss->list_id.next; 3899 if (next == &wpa_s->bss_id) 3900 break; 3901 bss = dl_list_entry(next, struct wpa_bss, list_id); 3902 } while (bss && len); 3903 3904 return ret; 3905} 3906 3907 3908static int wpa_supplicant_ctrl_iface_ap_scan( 3909 struct wpa_supplicant *wpa_s, char *cmd) 3910{ 3911 int ap_scan = atoi(cmd); 3912 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan); 3913} 3914 3915 3916static int wpa_supplicant_ctrl_iface_scan_interval( 3917 struct wpa_supplicant *wpa_s, char *cmd) 3918{ 3919 int scan_int = atoi(cmd); 3920 return wpa_supplicant_set_scan_interval(wpa_s, scan_int); 3921} 3922 3923 3924static int wpa_supplicant_ctrl_iface_bss_expire_age( 3925 struct wpa_supplicant *wpa_s, char *cmd) 3926{ 3927 int expire_age = atoi(cmd); 3928 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age); 3929} 3930 3931 3932static int wpa_supplicant_ctrl_iface_bss_expire_count( 3933 struct wpa_supplicant *wpa_s, char *cmd) 3934{ 3935 int expire_count = atoi(cmd); 3936 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count); 3937} 3938 3939 3940static int wpa_supplicant_ctrl_iface_bss_flush( 3941 struct wpa_supplicant *wpa_s, char *cmd) 3942{ 3943 int flush_age = atoi(cmd); 3944 3945 if (flush_age == 0) 3946 wpa_bss_flush(wpa_s); 3947 else 3948 wpa_bss_flush_by_age(wpa_s, flush_age); 3949 return 0; 3950} 3951 3952 3953#ifdef CONFIG_TESTING_OPTIONS 3954static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) 3955{ 3956 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication"); 3957 /* MLME-DELETEKEYS.request */ 3958 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0); 3959 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0); 3960 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0); 3961 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0); 3962#ifdef CONFIG_IEEE80211W 3963 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0); 3964 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0); 3965#endif /* CONFIG_IEEE80211W */ 3966 3967 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 3968 0); 3969 /* MLME-SETPROTECTION.request(None) */ 3970 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, 3971 MLME_SETPROTECTION_PROTECT_TYPE_NONE, 3972 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 3973 wpa_sm_drop_sa(wpa_s->wpa); 3974} 3975#endif /* CONFIG_TESTING_OPTIONS */ 3976 3977 3978static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, 3979 char *addr) 3980{ 3981#ifdef CONFIG_NO_SCAN_PROCESSING 3982 return -1; 3983#else /* CONFIG_NO_SCAN_PROCESSING */ 3984 u8 bssid[ETH_ALEN]; 3985 struct wpa_bss *bss; 3986 struct wpa_ssid *ssid = wpa_s->current_ssid; 3987 3988 if (hwaddr_aton(addr, bssid)) { 3989 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " 3990 "address '%s'", addr); 3991 return -1; 3992 } 3993 3994 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); 3995 3996 if (!ssid) { 3997 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " 3998 "configuration known for the target AP"); 3999 return -1; 4000 } 4001 4002 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len); 4003 if (!bss) { 4004 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " 4005 "from BSS table"); 4006 return -1; 4007 } 4008 4009 /* 4010 * TODO: Find best network configuration block from configuration to 4011 * allow roaming to other networks 4012 */ 4013 4014 wpa_s->reassociate = 1; 4015 wpa_supplicant_connect(wpa_s, bss, ssid); 4016 4017 return 0; 4018#endif /* CONFIG_NO_SCAN_PROCESSING */ 4019} 4020 4021 4022#ifdef CONFIG_P2P 4023static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) 4024{ 4025 unsigned int timeout = atoi(cmd); 4026 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; 4027 u8 dev_id[ETH_ALEN], *_dev_id = NULL; 4028 u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL; 4029 char *pos; 4030 unsigned int search_delay; 4031 4032 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 4033 wpa_dbg(wpa_s, MSG_INFO, 4034 "Reject P2P_FIND since interface is disabled"); 4035 return -1; 4036 } 4037 if (os_strstr(cmd, "type=social")) 4038 type = P2P_FIND_ONLY_SOCIAL; 4039 else if (os_strstr(cmd, "type=progressive")) 4040 type = P2P_FIND_PROGRESSIVE; 4041 4042 pos = os_strstr(cmd, "dev_id="); 4043 if (pos) { 4044 pos += 7; 4045 if (hwaddr_aton(pos, dev_id)) 4046 return -1; 4047 _dev_id = dev_id; 4048 } 4049 4050 pos = os_strstr(cmd, "dev_type="); 4051 if (pos) { 4052 pos += 9; 4053 if (wps_dev_type_str2bin(pos, dev_type) < 0) 4054 return -1; 4055 _dev_type = dev_type; 4056 } 4057 4058 pos = os_strstr(cmd, "delay="); 4059 if (pos) { 4060 pos += 6; 4061 search_delay = atoi(pos); 4062 } else 4063 search_delay = wpas_p2p_search_delay(wpa_s); 4064 4065 return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type, 4066 _dev_id, search_delay); 4067} 4068 4069 4070static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, 4071 char *buf, size_t buflen) 4072{ 4073 u8 addr[ETH_ALEN]; 4074 char *pos, *pos2; 4075 char *pin = NULL; 4076 enum p2p_wps_method wps_method; 4077 int new_pin; 4078 int ret; 4079 int persistent_group, persistent_id = -1; 4080 int join; 4081 int auth; 4082 int automatic; 4083 int go_intent = -1; 4084 int freq = 0; 4085 int pd; 4086 int ht40, vht; 4087 4088 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] 4089 * [persistent|persistent=<network id>] 4090 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] 4091 * [ht40] [vht] */ 4092 4093 if (hwaddr_aton(cmd, addr)) 4094 return -1; 4095 4096 pos = cmd + 17; 4097 if (*pos != ' ') 4098 return -1; 4099 pos++; 4100 4101 persistent_group = os_strstr(pos, " persistent") != NULL; 4102 pos2 = os_strstr(pos, " persistent="); 4103 if (pos2) { 4104 struct wpa_ssid *ssid; 4105 persistent_id = atoi(pos2 + 12); 4106 ssid = wpa_config_get_network(wpa_s->conf, persistent_id); 4107 if (ssid == NULL || ssid->disabled != 2 || 4108 ssid->mode != WPAS_MODE_P2P_GO) { 4109 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 4110 "SSID id=%d for persistent P2P group (GO)", 4111 persistent_id); 4112 return -1; 4113 } 4114 } 4115 join = os_strstr(pos, " join") != NULL; 4116 auth = os_strstr(pos, " auth") != NULL; 4117 automatic = os_strstr(pos, " auto") != NULL; 4118 pd = os_strstr(pos, " provdisc") != NULL; 4119 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; 4120 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || 4121 vht; 4122 4123 pos2 = os_strstr(pos, " go_intent="); 4124 if (pos2) { 4125 pos2 += 11; 4126 go_intent = atoi(pos2); 4127 if (go_intent < 0 || go_intent > 15) 4128 return -1; 4129 } 4130 4131 pos2 = os_strstr(pos, " freq="); 4132 if (pos2) { 4133 pos2 += 6; 4134 freq = atoi(pos2); 4135 if (freq <= 0) 4136 return -1; 4137 } 4138 4139 if (os_strncmp(pos, "pin", 3) == 0) { 4140 /* Request random PIN (to be displayed) and enable the PIN */ 4141 wps_method = WPS_PIN_DISPLAY; 4142 } else if (os_strncmp(pos, "pbc", 3) == 0) { 4143 wps_method = WPS_PBC; 4144 } else { 4145 pin = pos; 4146 pos = os_strchr(pin, ' '); 4147 wps_method = WPS_PIN_KEYPAD; 4148 if (pos) { 4149 *pos++ = '\0'; 4150 if (os_strncmp(pos, "display", 7) == 0) 4151 wps_method = WPS_PIN_DISPLAY; 4152 } 4153 if (!wps_pin_str_valid(pin)) { 4154 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17); 4155 return 17; 4156 } 4157 } 4158 4159 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, 4160 persistent_group, automatic, join, 4161 auth, go_intent, freq, persistent_id, pd, 4162 ht40, vht); 4163 if (new_pin == -2) { 4164 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); 4165 return 25; 4166 } 4167 if (new_pin == -3) { 4168 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25); 4169 return 25; 4170 } 4171 if (new_pin < 0) 4172 return -1; 4173 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) { 4174 ret = os_snprintf(buf, buflen, "%08d", new_pin); 4175 if (ret < 0 || (size_t) ret >= buflen) 4176 return -1; 4177 return ret; 4178 } 4179 4180 os_memcpy(buf, "OK\n", 3); 4181 return 3; 4182} 4183 4184 4185static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd) 4186{ 4187 unsigned int timeout = atoi(cmd); 4188 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 4189 wpa_dbg(wpa_s, MSG_INFO, 4190 "Reject P2P_LISTEN since interface is disabled"); 4191 return -1; 4192 } 4193 return wpas_p2p_listen(wpa_s, timeout); 4194} 4195 4196 4197static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd) 4198{ 4199 u8 addr[ETH_ALEN]; 4200 char *pos; 4201 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG; 4202 4203 /* <addr> <config method> [join|auto] */ 4204 4205 if (hwaddr_aton(cmd, addr)) 4206 return -1; 4207 4208 pos = cmd + 17; 4209 if (*pos != ' ') 4210 return -1; 4211 pos++; 4212 4213 if (os_strstr(pos, " join") != NULL) 4214 use = WPAS_P2P_PD_FOR_JOIN; 4215 else if (os_strstr(pos, " auto") != NULL) 4216 use = WPAS_P2P_PD_AUTO; 4217 4218 return wpas_p2p_prov_disc(wpa_s, addr, pos, use); 4219} 4220 4221 4222static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf, 4223 size_t buflen) 4224{ 4225 struct wpa_ssid *ssid = wpa_s->current_ssid; 4226 4227 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || 4228 ssid->passphrase == NULL) 4229 return -1; 4230 4231 os_strlcpy(buf, ssid->passphrase, buflen); 4232 return os_strlen(buf); 4233} 4234 4235 4236static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd, 4237 char *buf, size_t buflen) 4238{ 4239 u64 ref; 4240 int res; 4241 u8 dst_buf[ETH_ALEN], *dst; 4242 struct wpabuf *tlvs; 4243 char *pos; 4244 size_t len; 4245 4246 if (hwaddr_aton(cmd, dst_buf)) 4247 return -1; 4248 dst = dst_buf; 4249 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 && 4250 dst[3] == 0 && dst[4] == 0 && dst[5] == 0) 4251 dst = NULL; 4252 pos = cmd + 17; 4253 if (*pos != ' ') 4254 return -1; 4255 pos++; 4256 4257 if (os_strncmp(pos, "upnp ", 5) == 0) { 4258 u8 version; 4259 pos += 5; 4260 if (hexstr2bin(pos, &version, 1) < 0) 4261 return -1; 4262 pos += 2; 4263 if (*pos != ' ') 4264 return -1; 4265 pos++; 4266 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos); 4267#ifdef CONFIG_WIFI_DISPLAY 4268 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) { 4269 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13); 4270#endif /* CONFIG_WIFI_DISPLAY */ 4271 } else { 4272 len = os_strlen(pos); 4273 if (len & 1) 4274 return -1; 4275 len /= 2; 4276 tlvs = wpabuf_alloc(len); 4277 if (tlvs == NULL) 4278 return -1; 4279 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) { 4280 wpabuf_free(tlvs); 4281 return -1; 4282 } 4283 4284 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs); 4285 wpabuf_free(tlvs); 4286 } 4287 if (ref == 0) 4288 return -1; 4289 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref); 4290 if (res < 0 || (unsigned) res >= buflen) 4291 return -1; 4292 return res; 4293} 4294 4295 4296static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s, 4297 char *cmd) 4298{ 4299 long long unsigned val; 4300 u64 req; 4301 if (sscanf(cmd, "%llx", &val) != 1) 4302 return -1; 4303 req = val; 4304 return wpas_p2p_sd_cancel_request(wpa_s, req); 4305} 4306 4307 4308static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd) 4309{ 4310 int freq; 4311 u8 dst[ETH_ALEN]; 4312 u8 dialog_token; 4313 struct wpabuf *resp_tlvs; 4314 char *pos, *pos2; 4315 size_t len; 4316 4317 pos = os_strchr(cmd, ' '); 4318 if (pos == NULL) 4319 return -1; 4320 *pos++ = '\0'; 4321 freq = atoi(cmd); 4322 if (freq == 0) 4323 return -1; 4324 4325 if (hwaddr_aton(pos, dst)) 4326 return -1; 4327 pos += 17; 4328 if (*pos != ' ') 4329 return -1; 4330 pos++; 4331 4332 pos2 = os_strchr(pos, ' '); 4333 if (pos2 == NULL) 4334 return -1; 4335 *pos2++ = '\0'; 4336 dialog_token = atoi(pos); 4337 4338 len = os_strlen(pos2); 4339 if (len & 1) 4340 return -1; 4341 len /= 2; 4342 resp_tlvs = wpabuf_alloc(len); 4343 if (resp_tlvs == NULL) 4344 return -1; 4345 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) { 4346 wpabuf_free(resp_tlvs); 4347 return -1; 4348 } 4349 4350 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs); 4351 wpabuf_free(resp_tlvs); 4352 return 0; 4353} 4354 4355 4356static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s, 4357 char *cmd) 4358{ 4359 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1")) 4360 return -1; 4361 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd); 4362 return 0; 4363} 4364 4365 4366static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s, 4367 char *cmd) 4368{ 4369 char *pos; 4370 size_t len; 4371 struct wpabuf *query, *resp; 4372 4373 pos = os_strchr(cmd, ' '); 4374 if (pos == NULL) 4375 return -1; 4376 *pos++ = '\0'; 4377 4378 len = os_strlen(cmd); 4379 if (len & 1) 4380 return -1; 4381 len /= 2; 4382 query = wpabuf_alloc(len); 4383 if (query == NULL) 4384 return -1; 4385 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 4386 wpabuf_free(query); 4387 return -1; 4388 } 4389 4390 len = os_strlen(pos); 4391 if (len & 1) { 4392 wpabuf_free(query); 4393 return -1; 4394 } 4395 len /= 2; 4396 resp = wpabuf_alloc(len); 4397 if (resp == NULL) { 4398 wpabuf_free(query); 4399 return -1; 4400 } 4401 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) { 4402 wpabuf_free(query); 4403 wpabuf_free(resp); 4404 return -1; 4405 } 4406 4407 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) { 4408 wpabuf_free(query); 4409 wpabuf_free(resp); 4410 return -1; 4411 } 4412 return 0; 4413} 4414 4415 4416static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd) 4417{ 4418 char *pos; 4419 u8 version; 4420 4421 pos = os_strchr(cmd, ' '); 4422 if (pos == NULL) 4423 return -1; 4424 *pos++ = '\0'; 4425 4426 if (hexstr2bin(cmd, &version, 1) < 0) 4427 return -1; 4428 4429 return wpas_p2p_service_add_upnp(wpa_s, version, pos); 4430} 4431 4432 4433static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd) 4434{ 4435 char *pos; 4436 4437 pos = os_strchr(cmd, ' '); 4438 if (pos == NULL) 4439 return -1; 4440 *pos++ = '\0'; 4441 4442 if (os_strcmp(cmd, "bonjour") == 0) 4443 return p2p_ctrl_service_add_bonjour(wpa_s, pos); 4444 if (os_strcmp(cmd, "upnp") == 0) 4445 return p2p_ctrl_service_add_upnp(wpa_s, pos); 4446 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 4447 return -1; 4448} 4449 4450 4451static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s, 4452 char *cmd) 4453{ 4454 size_t len; 4455 struct wpabuf *query; 4456 int ret; 4457 4458 len = os_strlen(cmd); 4459 if (len & 1) 4460 return -1; 4461 len /= 2; 4462 query = wpabuf_alloc(len); 4463 if (query == NULL) 4464 return -1; 4465 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 4466 wpabuf_free(query); 4467 return -1; 4468 } 4469 4470 ret = wpas_p2p_service_del_bonjour(wpa_s, query); 4471 wpabuf_free(query); 4472 return ret; 4473} 4474 4475 4476static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd) 4477{ 4478 char *pos; 4479 u8 version; 4480 4481 pos = os_strchr(cmd, ' '); 4482 if (pos == NULL) 4483 return -1; 4484 *pos++ = '\0'; 4485 4486 if (hexstr2bin(cmd, &version, 1) < 0) 4487 return -1; 4488 4489 return wpas_p2p_service_del_upnp(wpa_s, version, pos); 4490} 4491 4492 4493static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd) 4494{ 4495 char *pos; 4496 4497 pos = os_strchr(cmd, ' '); 4498 if (pos == NULL) 4499 return -1; 4500 *pos++ = '\0'; 4501 4502 if (os_strcmp(cmd, "bonjour") == 0) 4503 return p2p_ctrl_service_del_bonjour(wpa_s, pos); 4504 if (os_strcmp(cmd, "upnp") == 0) 4505 return p2p_ctrl_service_del_upnp(wpa_s, pos); 4506 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 4507 return -1; 4508} 4509 4510 4511static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd) 4512{ 4513 u8 addr[ETH_ALEN]; 4514 4515 /* <addr> */ 4516 4517 if (hwaddr_aton(cmd, addr)) 4518 return -1; 4519 4520 return wpas_p2p_reject(wpa_s, addr); 4521} 4522 4523 4524static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) 4525{ 4526 char *pos; 4527 int id; 4528 struct wpa_ssid *ssid; 4529 u8 *_peer = NULL, peer[ETH_ALEN]; 4530 int freq = 0, pref_freq = 0; 4531 int ht40, vht; 4532 4533 id = atoi(cmd); 4534 pos = os_strstr(cmd, " peer="); 4535 if (pos) { 4536 pos += 6; 4537 if (hwaddr_aton(pos, peer)) 4538 return -1; 4539 _peer = peer; 4540 } 4541 ssid = wpa_config_get_network(wpa_s->conf, id); 4542 if (ssid == NULL || ssid->disabled != 2) { 4543 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 4544 "for persistent P2P group", 4545 id); 4546 return -1; 4547 } 4548 4549 pos = os_strstr(cmd, " freq="); 4550 if (pos) { 4551 pos += 6; 4552 freq = atoi(pos); 4553 if (freq <= 0) 4554 return -1; 4555 } 4556 4557 pos = os_strstr(cmd, " pref="); 4558 if (pos) { 4559 pos += 6; 4560 pref_freq = atoi(pos); 4561 if (pref_freq <= 0) 4562 return -1; 4563 } 4564 4565 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; 4566 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || 4567 vht; 4568 4569 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht, 4570 pref_freq); 4571} 4572 4573 4574static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd) 4575{ 4576 char *pos; 4577 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL; 4578 4579 pos = os_strstr(cmd, " peer="); 4580 if (!pos) 4581 return -1; 4582 4583 *pos = '\0'; 4584 pos += 6; 4585 if (hwaddr_aton(pos, peer)) { 4586 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos); 4587 return -1; 4588 } 4589 4590 pos = os_strstr(pos, " go_dev_addr="); 4591 if (pos) { 4592 pos += 13; 4593 if (hwaddr_aton(pos, go_dev_addr)) { 4594 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", 4595 pos); 4596 return -1; 4597 } 4598 go_dev = go_dev_addr; 4599 } 4600 4601 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev); 4602} 4603 4604 4605static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd) 4606{ 4607 if (os_strncmp(cmd, "persistent=", 11) == 0) 4608 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11); 4609 if (os_strncmp(cmd, "group=", 6) == 0) 4610 return p2p_ctrl_invite_group(wpa_s, cmd + 6); 4611 4612 return -1; 4613} 4614 4615 4616static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, 4617 char *cmd, int freq, int ht40, 4618 int vht) 4619{ 4620 int id; 4621 struct wpa_ssid *ssid; 4622 4623 id = atoi(cmd); 4624 ssid = wpa_config_get_network(wpa_s->conf, id); 4625 if (ssid == NULL || ssid->disabled != 2) { 4626 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 4627 "for persistent P2P group", 4628 id); 4629 return -1; 4630 } 4631 4632 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht, 4633 NULL, 0); 4634} 4635 4636 4637static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) 4638{ 4639 int freq = 0, ht40, vht; 4640 char *pos; 4641 4642 pos = os_strstr(cmd, "freq="); 4643 if (pos) 4644 freq = atoi(pos + 5); 4645 4646 vht = (os_strstr(cmd, "vht") != NULL) || wpa_s->conf->p2p_go_vht; 4647 ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || 4648 vht; 4649 4650 if (os_strncmp(cmd, "persistent=", 11) == 0) 4651 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq, 4652 ht40, vht); 4653 if (os_strcmp(cmd, "persistent") == 0 || 4654 os_strncmp(cmd, "persistent ", 11) == 0) 4655 return wpas_p2p_group_add(wpa_s, 1, freq, ht40, vht); 4656 if (os_strncmp(cmd, "freq=", 5) == 0) 4657 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht); 4658 if (ht40) 4659 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht); 4660 4661 wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'", 4662 cmd); 4663 return -1; 4664} 4665 4666 4667static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, 4668 char *buf, size_t buflen) 4669{ 4670 u8 addr[ETH_ALEN], *addr_ptr; 4671 int next, res; 4672 const struct p2p_peer_info *info; 4673 char *pos, *end; 4674 char devtype[WPS_DEV_TYPE_BUFSIZE]; 4675 struct wpa_ssid *ssid; 4676 size_t i; 4677 4678 if (!wpa_s->global->p2p) 4679 return -1; 4680 4681 if (os_strcmp(cmd, "FIRST") == 0) { 4682 addr_ptr = NULL; 4683 next = 0; 4684 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 4685 if (hwaddr_aton(cmd + 5, addr) < 0) 4686 return -1; 4687 addr_ptr = addr; 4688 next = 1; 4689 } else { 4690 if (hwaddr_aton(cmd, addr) < 0) 4691 return -1; 4692 addr_ptr = addr; 4693 next = 0; 4694 } 4695 4696 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next); 4697 if (info == NULL) 4698 return -1; 4699 4700 pos = buf; 4701 end = buf + buflen; 4702 4703 res = os_snprintf(pos, end - pos, MACSTR "\n" 4704 "pri_dev_type=%s\n" 4705 "device_name=%s\n" 4706 "manufacturer=%s\n" 4707 "model_name=%s\n" 4708 "model_number=%s\n" 4709 "serial_number=%s\n" 4710 "config_methods=0x%x\n" 4711 "dev_capab=0x%x\n" 4712 "group_capab=0x%x\n" 4713 "level=%d\n", 4714 MAC2STR(info->p2p_device_addr), 4715 wps_dev_type_bin2str(info->pri_dev_type, 4716 devtype, sizeof(devtype)), 4717 info->device_name, 4718 info->manufacturer, 4719 info->model_name, 4720 info->model_number, 4721 info->serial_number, 4722 info->config_methods, 4723 info->dev_capab, 4724 info->group_capab, 4725 info->level); 4726 if (res < 0 || res >= end - pos) 4727 return pos - buf; 4728 pos += res; 4729 4730 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++) 4731 { 4732 const u8 *t; 4733 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN]; 4734 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n", 4735 wps_dev_type_bin2str(t, devtype, 4736 sizeof(devtype))); 4737 if (res < 0 || res >= end - pos) 4738 return pos - buf; 4739 pos += res; 4740 } 4741 4742 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0); 4743 if (ssid) { 4744 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id); 4745 if (res < 0 || res >= end - pos) 4746 return pos - buf; 4747 pos += res; 4748 } 4749 4750 res = p2p_get_peer_info_txt(info, pos, end - pos); 4751 if (res < 0) 4752 return pos - buf; 4753 pos += res; 4754 4755 if (info->vendor_elems) { 4756 res = os_snprintf(pos, end - pos, "vendor_elems="); 4757 if (res < 0 || res >= end - pos) 4758 return pos - buf; 4759 pos += res; 4760 4761 pos += wpa_snprintf_hex(pos, end - pos, 4762 wpabuf_head(info->vendor_elems), 4763 wpabuf_len(info->vendor_elems)); 4764 4765 res = os_snprintf(pos, end - pos, "\n"); 4766 if (res < 0 || res >= end - pos) 4767 return pos - buf; 4768 pos += res; 4769 } 4770 4771 return pos - buf; 4772} 4773 4774 4775static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s, 4776 const char *param) 4777{ 4778 unsigned int i; 4779 4780 if (wpa_s->global->p2p == NULL) 4781 return -1; 4782 4783 if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0) 4784 return -1; 4785 4786 for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) { 4787 struct wpa_freq_range *freq; 4788 freq = &wpa_s->global->p2p_disallow_freq.range[i]; 4789 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u", 4790 freq->min, freq->max); 4791 } 4792 4793 wpas_p2p_update_channel_list(wpa_s); 4794 return 0; 4795} 4796 4797 4798static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) 4799{ 4800 char *param; 4801 4802 if (wpa_s->global->p2p == NULL) 4803 return -1; 4804 4805 param = os_strchr(cmd, ' '); 4806 if (param == NULL) 4807 return -1; 4808 *param++ = '\0'; 4809 4810 if (os_strcmp(cmd, "discoverability") == 0) { 4811 p2p_set_client_discoverability(wpa_s->global->p2p, 4812 atoi(param)); 4813 return 0; 4814 } 4815 4816 if (os_strcmp(cmd, "managed") == 0) { 4817 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param)); 4818 return 0; 4819 } 4820 4821 if (os_strcmp(cmd, "listen_channel") == 0) { 4822 return p2p_set_listen_channel(wpa_s->global->p2p, 81, 4823 atoi(param), 1); 4824 } 4825 4826 if (os_strcmp(cmd, "ssid_postfix") == 0) { 4827 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param, 4828 os_strlen(param)); 4829 } 4830 4831 if (os_strcmp(cmd, "noa") == 0) { 4832 char *pos; 4833 int count, start, duration; 4834 /* GO NoA parameters: count,start_offset(ms),duration(ms) */ 4835 count = atoi(param); 4836 pos = os_strchr(param, ','); 4837 if (pos == NULL) 4838 return -1; 4839 pos++; 4840 start = atoi(pos); 4841 pos = os_strchr(pos, ','); 4842 if (pos == NULL) 4843 return -1; 4844 pos++; 4845 duration = atoi(pos); 4846 if (count < 0 || count > 255 || start < 0 || duration < 0) 4847 return -1; 4848 if (count == 0 && duration > 0) 4849 return -1; 4850 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d " 4851 "start=%d duration=%d", count, start, duration); 4852 return wpas_p2p_set_noa(wpa_s, count, start, duration); 4853 } 4854 4855 if (os_strcmp(cmd, "ps") == 0) 4856 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1); 4857 4858 if (os_strcmp(cmd, "oppps") == 0) 4859 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1); 4860 4861 if (os_strcmp(cmd, "ctwindow") == 0) 4862 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param)); 4863 4864 if (os_strcmp(cmd, "disabled") == 0) { 4865 wpa_s->global->p2p_disabled = atoi(param); 4866 wpa_printf(MSG_DEBUG, "P2P functionality %s", 4867 wpa_s->global->p2p_disabled ? 4868 "disabled" : "enabled"); 4869 if (wpa_s->global->p2p_disabled) { 4870 wpas_p2p_stop_find(wpa_s); 4871 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 4872 p2p_flush(wpa_s->global->p2p); 4873 } 4874 return 0; 4875 } 4876 4877 if (os_strcmp(cmd, "conc_pref") == 0) { 4878 if (os_strcmp(param, "sta") == 0) 4879 wpa_s->global->conc_pref = WPA_CONC_PREF_STA; 4880 else if (os_strcmp(param, "p2p") == 0) 4881 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P; 4882 else { 4883 wpa_printf(MSG_INFO, "Invalid conc_pref value"); 4884 return -1; 4885 } 4886 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: " 4887 "%s", param); 4888 return 0; 4889 } 4890 4891 if (os_strcmp(cmd, "force_long_sd") == 0) { 4892 wpa_s->force_long_sd = atoi(param); 4893 return 0; 4894 } 4895 4896 if (os_strcmp(cmd, "peer_filter") == 0) { 4897 u8 addr[ETH_ALEN]; 4898 if (hwaddr_aton(param, addr)) 4899 return -1; 4900 p2p_set_peer_filter(wpa_s->global->p2p, addr); 4901 return 0; 4902 } 4903 4904 if (os_strcmp(cmd, "cross_connect") == 0) 4905 return wpas_p2p_set_cross_connect(wpa_s, atoi(param)); 4906 4907 if (os_strcmp(cmd, "go_apsd") == 0) { 4908 if (os_strcmp(param, "disable") == 0) 4909 wpa_s->set_ap_uapsd = 0; 4910 else { 4911 wpa_s->set_ap_uapsd = 1; 4912 wpa_s->ap_uapsd = atoi(param); 4913 } 4914 return 0; 4915 } 4916 4917 if (os_strcmp(cmd, "client_apsd") == 0) { 4918 if (os_strcmp(param, "disable") == 0) 4919 wpa_s->set_sta_uapsd = 0; 4920 else { 4921 int be, bk, vi, vo; 4922 char *pos; 4923 /* format: BE,BK,VI,VO;max SP Length */ 4924 be = atoi(param); 4925 pos = os_strchr(param, ','); 4926 if (pos == NULL) 4927 return -1; 4928 pos++; 4929 bk = atoi(pos); 4930 pos = os_strchr(pos, ','); 4931 if (pos == NULL) 4932 return -1; 4933 pos++; 4934 vi = atoi(pos); 4935 pos = os_strchr(pos, ','); 4936 if (pos == NULL) 4937 return -1; 4938 pos++; 4939 vo = atoi(pos); 4940 /* ignore max SP Length for now */ 4941 4942 wpa_s->set_sta_uapsd = 1; 4943 wpa_s->sta_uapsd = 0; 4944 if (be) 4945 wpa_s->sta_uapsd |= BIT(0); 4946 if (bk) 4947 wpa_s->sta_uapsd |= BIT(1); 4948 if (vi) 4949 wpa_s->sta_uapsd |= BIT(2); 4950 if (vo) 4951 wpa_s->sta_uapsd |= BIT(3); 4952 } 4953 return 0; 4954 } 4955 4956 if (os_strcmp(cmd, "disallow_freq") == 0) 4957 return p2p_ctrl_disallow_freq(wpa_s, param); 4958 4959 if (os_strcmp(cmd, "disc_int") == 0) { 4960 int min_disc_int, max_disc_int, max_disc_tu; 4961 char *pos; 4962 4963 pos = param; 4964 4965 min_disc_int = atoi(pos); 4966 pos = os_strchr(pos, ' '); 4967 if (pos == NULL) 4968 return -1; 4969 *pos++ = '\0'; 4970 4971 max_disc_int = atoi(pos); 4972 pos = os_strchr(pos, ' '); 4973 if (pos == NULL) 4974 return -1; 4975 *pos++ = '\0'; 4976 4977 max_disc_tu = atoi(pos); 4978 4979 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int, 4980 max_disc_int, max_disc_tu); 4981 } 4982 4983 if (os_strcmp(cmd, "per_sta_psk") == 0) { 4984 wpa_s->global->p2p_per_sta_psk = !!atoi(param); 4985 return 0; 4986 } 4987 4988#ifdef CONFIG_WPS_NFC 4989 if (os_strcmp(cmd, "nfc_tag") == 0) 4990 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param)); 4991#endif /* CONFIG_WPS_NFC */ 4992 4993 if (os_strcmp(cmd, "disable_ip_addr_req") == 0) { 4994 wpa_s->p2p_disable_ip_addr_req = !!atoi(param); 4995 return 0; 4996 } 4997 4998 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", 4999 cmd); 5000 5001 return -1; 5002} 5003 5004 5005static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s) 5006{ 5007 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 5008 wpa_s->force_long_sd = 0; 5009 if (wpa_s->global->p2p) 5010 p2p_flush(wpa_s->global->p2p); 5011} 5012 5013 5014static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd) 5015{ 5016 char *pos, *pos2; 5017 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0; 5018 5019 if (cmd[0]) { 5020 pos = os_strchr(cmd, ' '); 5021 if (pos == NULL) 5022 return -1; 5023 *pos++ = '\0'; 5024 dur1 = atoi(cmd); 5025 5026 pos2 = os_strchr(pos, ' '); 5027 if (pos2) 5028 *pos2++ = '\0'; 5029 int1 = atoi(pos); 5030 } else 5031 pos2 = NULL; 5032 5033 if (pos2) { 5034 pos = os_strchr(pos2, ' '); 5035 if (pos == NULL) 5036 return -1; 5037 *pos++ = '\0'; 5038 dur2 = atoi(pos2); 5039 int2 = atoi(pos); 5040 } 5041 5042 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2); 5043} 5044 5045 5046static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd) 5047{ 5048 char *pos; 5049 unsigned int period = 0, interval = 0; 5050 5051 if (cmd[0]) { 5052 pos = os_strchr(cmd, ' '); 5053 if (pos == NULL) 5054 return -1; 5055 *pos++ = '\0'; 5056 period = atoi(cmd); 5057 interval = atoi(pos); 5058 } 5059 5060 return wpas_p2p_ext_listen(wpa_s, period, interval); 5061} 5062 5063 5064static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd) 5065{ 5066 const char *pos; 5067 u8 peer[ETH_ALEN]; 5068 int iface_addr = 0; 5069 5070 pos = cmd; 5071 if (os_strncmp(pos, "iface=", 6) == 0) { 5072 iface_addr = 1; 5073 pos += 6; 5074 } 5075 if (hwaddr_aton(pos, peer)) 5076 return -1; 5077 5078 wpas_p2p_remove_client(wpa_s, peer, iface_addr); 5079 return 0; 5080} 5081 5082#endif /* CONFIG_P2P */ 5083 5084 5085static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val) 5086{ 5087 struct wpa_freq_range_list ranges; 5088 int *freqs = NULL; 5089 struct hostapd_hw_modes *mode; 5090 u16 i; 5091 5092 if (wpa_s->hw.modes == NULL) 5093 return NULL; 5094 5095 os_memset(&ranges, 0, sizeof(ranges)); 5096 if (freq_range_list_parse(&ranges, val) < 0) 5097 return NULL; 5098 5099 for (i = 0; i < wpa_s->hw.num_modes; i++) { 5100 int j; 5101 5102 mode = &wpa_s->hw.modes[i]; 5103 for (j = 0; j < mode->num_channels; j++) { 5104 unsigned int freq; 5105 5106 if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED) 5107 continue; 5108 5109 freq = mode->channels[j].freq; 5110 if (!freq_range_list_includes(&ranges, freq)) 5111 continue; 5112 5113 int_array_add_unique(&freqs, freq); 5114 } 5115 } 5116 5117 os_free(ranges.range); 5118 return freqs; 5119} 5120 5121 5122#ifdef CONFIG_INTERWORKING 5123 5124static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param) 5125{ 5126 int auto_sel = 0; 5127 int *freqs = NULL; 5128 5129 if (param) { 5130 char *pos; 5131 5132 auto_sel = os_strstr(param, "auto") != NULL; 5133 5134 pos = os_strstr(param, "freq="); 5135 if (pos) { 5136 freqs = freq_range_to_channel_list(wpa_s, pos + 5); 5137 if (freqs == NULL) 5138 return -1; 5139 } 5140 5141 } 5142 5143 return interworking_select(wpa_s, auto_sel, freqs); 5144} 5145 5146 5147static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst) 5148{ 5149 u8 bssid[ETH_ALEN]; 5150 struct wpa_bss *bss; 5151 5152 if (hwaddr_aton(dst, bssid)) { 5153 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst); 5154 return -1; 5155 } 5156 5157 bss = wpa_bss_get_bssid(wpa_s, bssid); 5158 if (bss == NULL) { 5159 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR, 5160 MAC2STR(bssid)); 5161 return -1; 5162 } 5163 5164 return interworking_connect(wpa_s, bss); 5165} 5166 5167 5168static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) 5169{ 5170 u8 dst_addr[ETH_ALEN]; 5171 int used; 5172 char *pos; 5173#define MAX_ANQP_INFO_ID 100 5174 u16 id[MAX_ANQP_INFO_ID]; 5175 size_t num_id = 0; 5176 u32 subtypes = 0; 5177 5178 used = hwaddr_aton2(dst, dst_addr); 5179 if (used < 0) 5180 return -1; 5181 pos = dst + used; 5182 while (num_id < MAX_ANQP_INFO_ID) { 5183 if (os_strncmp(pos, "hs20:", 5) == 0) { 5184#ifdef CONFIG_HS20 5185 int num = atoi(pos + 5); 5186 if (num <= 0 || num > 31) 5187 return -1; 5188 subtypes |= BIT(num); 5189#else /* CONFIG_HS20 */ 5190 return -1; 5191#endif /* CONFIG_HS20 */ 5192 } else { 5193 id[num_id] = atoi(pos); 5194 if (id[num_id]) 5195 num_id++; 5196 } 5197 pos = os_strchr(pos + 1, ','); 5198 if (pos == NULL) 5199 break; 5200 pos++; 5201 } 5202 5203 if (num_id == 0) 5204 return -1; 5205 5206 return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes); 5207} 5208 5209 5210static int gas_request(struct wpa_supplicant *wpa_s, char *cmd) 5211{ 5212 u8 dst_addr[ETH_ALEN]; 5213 struct wpabuf *advproto, *query = NULL; 5214 int used, ret = -1; 5215 char *pos, *end; 5216 size_t len; 5217 5218 used = hwaddr_aton2(cmd, dst_addr); 5219 if (used < 0) 5220 return -1; 5221 5222 pos = cmd + used; 5223 while (*pos == ' ') 5224 pos++; 5225 5226 /* Advertisement Protocol ID */ 5227 end = os_strchr(pos, ' '); 5228 if (end) 5229 len = end - pos; 5230 else 5231 len = os_strlen(pos); 5232 if (len & 0x01) 5233 return -1; 5234 len /= 2; 5235 if (len == 0) 5236 return -1; 5237 advproto = wpabuf_alloc(len); 5238 if (advproto == NULL) 5239 return -1; 5240 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0) 5241 goto fail; 5242 5243 if (end) { 5244 /* Optional Query Request */ 5245 pos = end + 1; 5246 while (*pos == ' ') 5247 pos++; 5248 5249 len = os_strlen(pos); 5250 if (len) { 5251 if (len & 0x01) 5252 goto fail; 5253 len /= 2; 5254 if (len == 0) 5255 goto fail; 5256 query = wpabuf_alloc(len); 5257 if (query == NULL) 5258 goto fail; 5259 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0) 5260 goto fail; 5261 } 5262 } 5263 5264 ret = gas_send_request(wpa_s, dst_addr, advproto, query); 5265 5266fail: 5267 wpabuf_free(advproto); 5268 wpabuf_free(query); 5269 5270 return ret; 5271} 5272 5273 5274static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf, 5275 size_t buflen) 5276{ 5277 u8 addr[ETH_ALEN]; 5278 int dialog_token; 5279 int used; 5280 char *pos; 5281 size_t resp_len, start, requested_len; 5282 struct wpabuf *resp; 5283 int ret; 5284 5285 used = hwaddr_aton2(cmd, addr); 5286 if (used < 0) 5287 return -1; 5288 5289 pos = cmd + used; 5290 while (*pos == ' ') 5291 pos++; 5292 dialog_token = atoi(pos); 5293 5294 if (wpa_s->last_gas_resp && 5295 os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 && 5296 dialog_token == wpa_s->last_gas_dialog_token) 5297 resp = wpa_s->last_gas_resp; 5298 else if (wpa_s->prev_gas_resp && 5299 os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 && 5300 dialog_token == wpa_s->prev_gas_dialog_token) 5301 resp = wpa_s->prev_gas_resp; 5302 else 5303 return -1; 5304 5305 resp_len = wpabuf_len(resp); 5306 start = 0; 5307 requested_len = resp_len; 5308 5309 pos = os_strchr(pos, ' '); 5310 if (pos) { 5311 start = atoi(pos); 5312 if (start > resp_len) 5313 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 5314 pos = os_strchr(pos, ','); 5315 if (pos == NULL) 5316 return -1; 5317 pos++; 5318 requested_len = atoi(pos); 5319 if (start + requested_len > resp_len) 5320 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 5321 } 5322 5323 if (requested_len * 2 + 1 > buflen) 5324 return os_snprintf(buf, buflen, "FAIL-Too long response"); 5325 5326 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start, 5327 requested_len); 5328 5329 if (start + requested_len == resp_len) { 5330 /* 5331 * Free memory by dropping the response after it has been 5332 * fetched. 5333 */ 5334 if (resp == wpa_s->prev_gas_resp) { 5335 wpabuf_free(wpa_s->prev_gas_resp); 5336 wpa_s->prev_gas_resp = NULL; 5337 } else { 5338 wpabuf_free(wpa_s->last_gas_resp); 5339 wpa_s->last_gas_resp = NULL; 5340 } 5341 } 5342 5343 return ret; 5344} 5345#endif /* CONFIG_INTERWORKING */ 5346 5347 5348#ifdef CONFIG_HS20 5349 5350static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst) 5351{ 5352 u8 dst_addr[ETH_ALEN]; 5353 int used; 5354 char *pos; 5355 u32 subtypes = 0; 5356 5357 used = hwaddr_aton2(dst, dst_addr); 5358 if (used < 0) 5359 return -1; 5360 pos = dst + used; 5361 for (;;) { 5362 int num = atoi(pos); 5363 if (num <= 0 || num > 31) 5364 return -1; 5365 subtypes |= BIT(num); 5366 pos = os_strchr(pos + 1, ','); 5367 if (pos == NULL) 5368 break; 5369 pos++; 5370 } 5371 5372 if (subtypes == 0) 5373 return -1; 5374 5375 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0); 5376} 5377 5378 5379static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s, 5380 const u8 *addr, const char *realm) 5381{ 5382 u8 *buf; 5383 size_t rlen, len; 5384 int ret; 5385 5386 rlen = os_strlen(realm); 5387 len = 3 + rlen; 5388 buf = os_malloc(len); 5389 if (buf == NULL) 5390 return -1; 5391 buf[0] = 1; /* NAI Home Realm Count */ 5392 buf[1] = 0; /* Formatted in accordance with RFC 4282 */ 5393 buf[2] = rlen; 5394 os_memcpy(buf + 3, realm, rlen); 5395 5396 ret = hs20_anqp_send_req(wpa_s, addr, 5397 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 5398 buf, len); 5399 5400 os_free(buf); 5401 5402 return ret; 5403} 5404 5405 5406static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s, 5407 char *dst) 5408{ 5409 struct wpa_cred *cred = wpa_s->conf->cred; 5410 u8 dst_addr[ETH_ALEN]; 5411 int used; 5412 u8 *buf; 5413 size_t len; 5414 int ret; 5415 5416 used = hwaddr_aton2(dst, dst_addr); 5417 if (used < 0) 5418 return -1; 5419 5420 while (dst[used] == ' ') 5421 used++; 5422 if (os_strncmp(dst + used, "realm=", 6) == 0) 5423 return hs20_nai_home_realm_list(wpa_s, dst_addr, 5424 dst + used + 6); 5425 5426 len = os_strlen(dst + used); 5427 5428 if (len == 0 && cred && cred->realm) 5429 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm); 5430 5431 if (len & 1) 5432 return -1; 5433 len /= 2; 5434 buf = os_malloc(len); 5435 if (buf == NULL) 5436 return -1; 5437 if (hexstr2bin(dst + used, buf, len) < 0) { 5438 os_free(buf); 5439 return -1; 5440 } 5441 5442 ret = hs20_anqp_send_req(wpa_s, dst_addr, 5443 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 5444 buf, len); 5445 os_free(buf); 5446 5447 return ret; 5448} 5449 5450 5451static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd) 5452{ 5453 u8 dst_addr[ETH_ALEN]; 5454 int used; 5455 char *icon; 5456 5457 used = hwaddr_aton2(cmd, dst_addr); 5458 if (used < 0) 5459 return -1; 5460 5461 while (cmd[used] == ' ') 5462 used++; 5463 icon = &cmd[used]; 5464 5465 wpa_s->fetch_osu_icon_in_progress = 0; 5466 return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST), 5467 (u8 *) icon, os_strlen(icon)); 5468} 5469 5470#endif /* CONFIG_HS20 */ 5471 5472 5473static int wpa_supplicant_ctrl_iface_sta_autoconnect( 5474 struct wpa_supplicant *wpa_s, char *cmd) 5475{ 5476 wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0; 5477 return 0; 5478} 5479 5480 5481#ifdef CONFIG_AUTOSCAN 5482 5483static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s, 5484 char *cmd) 5485{ 5486 enum wpa_states state = wpa_s->wpa_state; 5487 char *new_params = NULL; 5488 5489 if (os_strlen(cmd) > 0) { 5490 new_params = os_strdup(cmd); 5491 if (new_params == NULL) 5492 return -1; 5493 } 5494 5495 os_free(wpa_s->conf->autoscan); 5496 wpa_s->conf->autoscan = new_params; 5497 5498 if (wpa_s->conf->autoscan == NULL) 5499 autoscan_deinit(wpa_s); 5500 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) 5501 autoscan_init(wpa_s, 1); 5502 else if (state == WPA_SCANNING) 5503 wpa_supplicant_reinit_autoscan(wpa_s); 5504 5505 return 0; 5506} 5507 5508#endif /* CONFIG_AUTOSCAN */ 5509 5510 5511#ifdef CONFIG_WNM 5512 5513static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd) 5514{ 5515 int enter; 5516 int intval = 0; 5517 char *pos; 5518 int ret; 5519 struct wpabuf *tfs_req = NULL; 5520 5521 if (os_strncmp(cmd, "enter", 5) == 0) 5522 enter = 1; 5523 else if (os_strncmp(cmd, "exit", 4) == 0) 5524 enter = 0; 5525 else 5526 return -1; 5527 5528 pos = os_strstr(cmd, " interval="); 5529 if (pos) 5530 intval = atoi(pos + 10); 5531 5532 pos = os_strstr(cmd, " tfs_req="); 5533 if (pos) { 5534 char *end; 5535 size_t len; 5536 pos += 9; 5537 end = os_strchr(pos, ' '); 5538 if (end) 5539 len = end - pos; 5540 else 5541 len = os_strlen(pos); 5542 if (len & 1) 5543 return -1; 5544 len /= 2; 5545 tfs_req = wpabuf_alloc(len); 5546 if (tfs_req == NULL) 5547 return -1; 5548 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) { 5549 wpabuf_free(tfs_req); 5550 return -1; 5551 } 5552 } 5553 5554 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER : 5555 WNM_SLEEP_MODE_EXIT, intval, 5556 tfs_req); 5557 wpabuf_free(tfs_req); 5558 5559 return ret; 5560} 5561 5562 5563static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd) 5564{ 5565 int query_reason; 5566 5567 query_reason = atoi(cmd); 5568 5569 wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d", 5570 query_reason); 5571 5572 return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason); 5573} 5574 5575#endif /* CONFIG_WNM */ 5576 5577 5578static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf, 5579 size_t buflen) 5580{ 5581 struct wpa_signal_info si; 5582 int ret; 5583 char *pos, *end; 5584 5585 ret = wpa_drv_signal_poll(wpa_s, &si); 5586 if (ret) 5587 return -1; 5588 5589 pos = buf; 5590 end = buf + buflen; 5591 5592 ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n" 5593 "NOISE=%d\nFREQUENCY=%u\n", 5594 si.current_signal, si.current_txrate / 1000, 5595 si.current_noise, si.frequency); 5596 if (ret < 0 || ret > end - pos) 5597 return -1; 5598 pos += ret; 5599 5600 if (si.chanwidth != CHAN_WIDTH_UNKNOWN) { 5601 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n", 5602 channel_width_to_string(si.chanwidth)); 5603 if (ret < 0 || ret > end - pos) 5604 return -1; 5605 pos += ret; 5606 } 5607 5608 if (si.center_frq1 > 0 && si.center_frq2 > 0) { 5609 ret = os_snprintf(pos, end - pos, 5610 "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n", 5611 si.center_frq1, si.center_frq2); 5612 if (ret < 0 || ret > end - pos) 5613 return -1; 5614 pos += ret; 5615 } 5616 5617 if (si.avg_signal) { 5618 ret = os_snprintf(pos, end - pos, 5619 "AVG_RSSI=%d\n", si.avg_signal); 5620 if (ret < 0 || ret >= end - pos) 5621 return -1; 5622 pos += ret; 5623 } 5624 5625 return pos - buf; 5626} 5627 5628 5629static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, 5630 size_t buflen) 5631{ 5632 struct hostap_sta_driver_data sta; 5633 int ret; 5634 5635 ret = wpa_drv_pktcnt_poll(wpa_s, &sta); 5636 if (ret) 5637 return -1; 5638 5639 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n", 5640 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets); 5641 if (ret < 0 || (size_t) ret > buflen) 5642 return -1; 5643 return ret; 5644} 5645 5646 5647#ifdef ANDROID 5648static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd, 5649 char *buf, size_t buflen) 5650{ 5651 int ret; 5652 5653 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen); 5654 if (ret == 0) { 5655 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) { 5656 struct p2p_data *p2p = wpa_s->global->p2p; 5657 if (p2p) { 5658 char country[3]; 5659 country[0] = cmd[8]; 5660 country[1] = cmd[9]; 5661 country[2] = 0x04; 5662 p2p_set_country(p2p, country); 5663 } 5664 } 5665 ret = os_snprintf(buf, buflen, "%s\n", "OK"); 5666 } 5667 return ret; 5668} 5669#endif /* ANDROID */ 5670 5671 5672static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, 5673 char *buf, size_t buflen) 5674{ 5675 int ret; 5676 char *pos; 5677 u8 *data = NULL; 5678 unsigned int vendor_id, subcmd; 5679 struct wpabuf *reply; 5680 size_t data_len = 0; 5681 5682 /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */ 5683 vendor_id = strtoul(cmd, &pos, 16); 5684 if (!isblank(*pos)) 5685 return -EINVAL; 5686 5687 subcmd = strtoul(pos, &pos, 10); 5688 5689 if (*pos != '\0') { 5690 if (!isblank(*pos++)) 5691 return -EINVAL; 5692 data_len = os_strlen(pos); 5693 } 5694 5695 if (data_len) { 5696 data_len /= 2; 5697 data = os_malloc(data_len); 5698 if (!data) 5699 return -1; 5700 5701 if (hexstr2bin(pos, data, data_len)) { 5702 wpa_printf(MSG_DEBUG, 5703 "Vendor command: wrong parameter format"); 5704 os_free(data); 5705 return -EINVAL; 5706 } 5707 } 5708 5709 reply = wpabuf_alloc((buflen - 1) / 2); 5710 if (!reply) { 5711 os_free(data); 5712 return -1; 5713 } 5714 5715 ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len, 5716 reply); 5717 5718 if (ret == 0) 5719 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), 5720 wpabuf_len(reply)); 5721 5722 wpabuf_free(reply); 5723 os_free(data); 5724 5725 return ret; 5726} 5727 5728 5729static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) 5730{ 5731 wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state"); 5732 5733#ifdef CONFIG_P2P 5734 wpas_p2p_cancel(wpa_s); 5735 wpas_p2p_stop_find(wpa_s); 5736 p2p_ctrl_flush(wpa_s); 5737 wpas_p2p_group_remove(wpa_s, "*"); 5738 wpas_p2p_service_flush(wpa_s); 5739 wpa_s->global->p2p_disabled = 0; 5740 wpa_s->global->p2p_per_sta_psk = 0; 5741 wpa_s->conf->num_sec_device_types = 0; 5742 wpa_s->p2p_disable_ip_addr_req = 0; 5743 os_free(wpa_s->global->p2p_go_avoid_freq.range); 5744 wpa_s->global->p2p_go_avoid_freq.range = NULL; 5745#endif /* CONFIG_P2P */ 5746 5747#ifdef CONFIG_WPS_TESTING 5748 wps_version_number = 0x20; 5749 wps_testing_dummy_cred = 0; 5750 wps_corrupt_pkhash = 0; 5751#endif /* CONFIG_WPS_TESTING */ 5752#ifdef CONFIG_WPS 5753 wpa_s->wps_fragment_size = 0; 5754 wpas_wps_cancel(wpa_s); 5755#endif /* CONFIG_WPS */ 5756 wpa_s->after_wps = 0; 5757 wpa_s->known_wps_freq = 0; 5758 5759#ifdef CONFIG_TDLS 5760#ifdef CONFIG_TDLS_TESTING 5761 extern unsigned int tdls_testing; 5762 tdls_testing = 0; 5763#endif /* CONFIG_TDLS_TESTING */ 5764 wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL); 5765 wpa_tdls_enable(wpa_s->wpa, 1); 5766#endif /* CONFIG_TDLS */ 5767 5768 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL); 5769 wpa_supplicant_stop_countermeasures(wpa_s, NULL); 5770 5771 wpa_s->no_keep_alive = 0; 5772 5773 os_free(wpa_s->disallow_aps_bssid); 5774 wpa_s->disallow_aps_bssid = NULL; 5775 wpa_s->disallow_aps_bssid_count = 0; 5776 os_free(wpa_s->disallow_aps_ssid); 5777 wpa_s->disallow_aps_ssid = NULL; 5778 wpa_s->disallow_aps_ssid_count = 0; 5779 5780 wpa_s->set_sta_uapsd = 0; 5781 wpa_s->sta_uapsd = 0; 5782 5783 wpa_drv_radio_disable(wpa_s, 0); 5784 5785 wpa_bss_flush(wpa_s); 5786 wpa_blacklist_clear(wpa_s); 5787 wpa_s->extra_blacklist_count = 0; 5788 wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all"); 5789 wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all"); 5790 wpa_config_flush_blobs(wpa_s->conf); 5791 wpa_s->conf->auto_interworking = 0; 5792 wpa_s->conf->okc = 0; 5793 5794 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200); 5795 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70); 5796 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60); 5797 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 5798 5799 radio_remove_works(wpa_s, NULL, 1); 5800 5801 wpa_s->next_ssid = NULL; 5802 5803#ifdef CONFIG_INTERWORKING 5804 hs20_cancel_fetch_osu(wpa_s); 5805#endif /* CONFIG_INTERWORKING */ 5806 5807 wpa_s->ext_mgmt_frame_handling = 0; 5808} 5809 5810 5811static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s, 5812 char *buf, size_t buflen) 5813{ 5814 struct wpa_radio_work *work; 5815 char *pos, *end; 5816 struct os_reltime now, diff; 5817 5818 pos = buf; 5819 end = buf + buflen; 5820 5821 os_get_reltime(&now); 5822 5823 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list) 5824 { 5825 int ret; 5826 5827 os_reltime_sub(&now, &work->time, &diff); 5828 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n", 5829 work->type, work->wpa_s->ifname, work->freq, 5830 work->started, diff.sec, diff.usec); 5831 if (ret < 0 || ret >= end - pos) 5832 break; 5833 pos += ret; 5834 } 5835 5836 return pos - buf; 5837} 5838 5839 5840static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx) 5841{ 5842 struct wpa_radio_work *work = eloop_ctx; 5843 struct wpa_external_work *ework = work->ctx; 5844 5845 wpa_dbg(work->wpa_s, MSG_DEBUG, 5846 "Timing out external radio work %u (%s)", 5847 ework->id, work->type); 5848 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id); 5849 radio_work_done(work); 5850 os_free(ework); 5851} 5852 5853 5854static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit) 5855{ 5856 struct wpa_external_work *ework = work->ctx; 5857 5858 if (deinit) { 5859 if (work->started) 5860 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, 5861 work, NULL); 5862 5863 os_free(ework); 5864 return; 5865 } 5866 5867 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)", 5868 ework->id, ework->type); 5869 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id); 5870 if (!ework->timeout) 5871 ework->timeout = 10; 5872 eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout, 5873 work, NULL); 5874} 5875 5876 5877static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd, 5878 char *buf, size_t buflen) 5879{ 5880 struct wpa_external_work *ework; 5881 char *pos, *pos2; 5882 size_t type_len; 5883 int ret; 5884 unsigned int freq = 0; 5885 5886 /* format: <name> [freq=<MHz>] [timeout=<seconds>] */ 5887 5888 ework = os_zalloc(sizeof(*ework)); 5889 if (ework == NULL) 5890 return -1; 5891 5892 pos = os_strchr(cmd, ' '); 5893 if (pos) { 5894 type_len = pos - cmd; 5895 pos++; 5896 5897 pos2 = os_strstr(pos, "freq="); 5898 if (pos2) 5899 freq = atoi(pos2 + 5); 5900 5901 pos2 = os_strstr(pos, "timeout="); 5902 if (pos2) 5903 ework->timeout = atoi(pos2 + 8); 5904 } else { 5905 type_len = os_strlen(cmd); 5906 } 5907 if (4 + type_len >= sizeof(ework->type)) 5908 type_len = sizeof(ework->type) - 4 - 1; 5909 os_strlcpy(ework->type, "ext:", sizeof(ework->type)); 5910 os_memcpy(ework->type + 4, cmd, type_len); 5911 ework->type[4 + type_len] = '\0'; 5912 5913 wpa_s->ext_work_id++; 5914 if (wpa_s->ext_work_id == 0) 5915 wpa_s->ext_work_id++; 5916 ework->id = wpa_s->ext_work_id; 5917 5918 if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb, 5919 ework) < 0) { 5920 os_free(ework); 5921 return -1; 5922 } 5923 5924 ret = os_snprintf(buf, buflen, "%u", ework->id); 5925 if (ret < 0 || (size_t) ret >= buflen) 5926 return -1; 5927 return ret; 5928} 5929 5930 5931static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd) 5932{ 5933 struct wpa_radio_work *work; 5934 unsigned int id = atoi(cmd); 5935 5936 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list) 5937 { 5938 struct wpa_external_work *ework; 5939 5940 if (os_strncmp(work->type, "ext:", 4) != 0) 5941 continue; 5942 ework = work->ctx; 5943 if (id && ework->id != id) 5944 continue; 5945 wpa_dbg(wpa_s, MSG_DEBUG, 5946 "Completed external radio work %u (%s)", 5947 ework->id, ework->type); 5948 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL); 5949 radio_work_done(work); 5950 os_free(ework); 5951 return 3; /* "OK\n" */ 5952 } 5953 5954 return -1; 5955} 5956 5957 5958static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd, 5959 char *buf, size_t buflen) 5960{ 5961 if (os_strcmp(cmd, "show") == 0) 5962 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen); 5963 if (os_strncmp(cmd, "add ", 4) == 0) 5964 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen); 5965 if (os_strncmp(cmd, "done ", 5) == 0) 5966 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4); 5967 return -1; 5968} 5969 5970 5971void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s) 5972{ 5973 struct wpa_radio_work *work, *tmp; 5974 5975 if (!wpa_s || !wpa_s->radio) 5976 return; 5977 5978 dl_list_for_each_safe(work, tmp, &wpa_s->radio->work, 5979 struct wpa_radio_work, list) { 5980 struct wpa_external_work *ework; 5981 5982 if (os_strncmp(work->type, "ext:", 4) != 0) 5983 continue; 5984 ework = work->ctx; 5985 wpa_dbg(wpa_s, MSG_DEBUG, 5986 "Flushing%s external radio work %u (%s)", 5987 work->started ? " started" : "", ework->id, 5988 ework->type); 5989 if (work->started) 5990 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, 5991 work, NULL); 5992 radio_work_done(work); 5993 os_free(ework); 5994 } 5995} 5996 5997 5998static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx) 5999{ 6000 struct wpa_supplicant *wpa_s = eloop_ctx; 6001 eapol_sm_notify_ctrl_response(wpa_s->eapol); 6002} 6003 6004 6005static int set_scan_freqs(struct wpa_supplicant *wpa_s, char *val) 6006{ 6007 int *freqs = NULL; 6008 6009 freqs = freq_range_to_channel_list(wpa_s, val); 6010 if (freqs == NULL) 6011 return -1; 6012 6013 os_free(wpa_s->manual_scan_freqs); 6014 wpa_s->manual_scan_freqs = freqs; 6015 6016 return 0; 6017} 6018 6019 6020static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value) 6021{ 6022 const char *pos = value; 6023 6024 while (pos) { 6025 if (*pos == ' ' || *pos == '\0') 6026 break; 6027 if (wpa_s->scan_id_count == MAX_SCAN_ID) 6028 return -1; 6029 wpa_s->scan_id[wpa_s->scan_id_count++] = atoi(pos); 6030 pos = os_strchr(pos, ','); 6031 if (pos) 6032 pos++; 6033 } 6034 6035 return 0; 6036} 6037 6038 6039static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, 6040 char *reply, int reply_size, int *reply_len) 6041{ 6042 char *pos; 6043 6044 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 6045 *reply_len = -1; 6046 return; 6047 } 6048 6049 wpa_s->manual_scan_passive = 0; 6050 wpa_s->manual_scan_use_id = 0; 6051 wpa_s->manual_scan_only_new = 0; 6052 wpa_s->scan_id_count = 0; 6053 6054 if (params) { 6055 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0) 6056 wpa_s->scan_res_handler = scan_only_handler; 6057 6058 pos = os_strstr(params, "freq="); 6059 if (pos && set_scan_freqs(wpa_s, pos + 5) < 0) { 6060 *reply_len = -1; 6061 return; 6062 } 6063 6064 pos = os_strstr(params, "passive="); 6065 if (pos) 6066 wpa_s->manual_scan_passive = !!atoi(pos + 8); 6067 6068 pos = os_strstr(params, "use_id="); 6069 if (pos) 6070 wpa_s->manual_scan_use_id = atoi(pos + 7); 6071 6072 pos = os_strstr(params, "only_new=1"); 6073 if (pos) 6074 wpa_s->manual_scan_only_new = 1; 6075 6076 pos = os_strstr(params, "scan_id="); 6077 if (pos && scan_id_list_parse(wpa_s, pos + 8) < 0) { 6078 *reply_len = -1; 6079 return; 6080 } 6081 } else { 6082 os_free(wpa_s->manual_scan_freqs); 6083 wpa_s->manual_scan_freqs = NULL; 6084 if (wpa_s->scan_res_handler == scan_only_handler) 6085 wpa_s->scan_res_handler = NULL; 6086 } 6087 6088 if (!wpa_s->sched_scanning && !wpa_s->scanning && 6089 ((wpa_s->wpa_state <= WPA_SCANNING) || 6090 (wpa_s->wpa_state == WPA_COMPLETED))) { 6091 wpa_s->normal_scans = 0; 6092 wpa_s->scan_req = MANUAL_SCAN_REQ; 6093 wpa_s->after_wps = 0; 6094 wpa_s->known_wps_freq = 0; 6095 wpa_supplicant_req_scan(wpa_s, 0, 0); 6096 if (wpa_s->manual_scan_use_id) { 6097 wpa_s->manual_scan_id++; 6098 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", 6099 wpa_s->manual_scan_id); 6100 *reply_len = os_snprintf(reply, reply_size, "%u\n", 6101 wpa_s->manual_scan_id); 6102 } 6103 } else if (wpa_s->sched_scanning) { 6104 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed"); 6105 wpa_supplicant_cancel_sched_scan(wpa_s); 6106 wpa_s->scan_req = MANUAL_SCAN_REQ; 6107 wpa_supplicant_req_scan(wpa_s, 0, 0); 6108 if (wpa_s->manual_scan_use_id) { 6109 wpa_s->manual_scan_id++; 6110 *reply_len = os_snprintf(reply, reply_size, "%u\n", 6111 wpa_s->manual_scan_id); 6112 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", 6113 wpa_s->manual_scan_id); 6114 } 6115 } else { 6116 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request"); 6117 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 6118 } 6119} 6120 6121 6122#ifdef CONFIG_TESTING_OPTIONS 6123 6124static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s, 6125 unsigned int freq, const u8 *dst, 6126 const u8 *src, const u8 *bssid, 6127 const u8 *data, size_t data_len, 6128 enum offchannel_send_action_result 6129 result) 6130{ 6131 wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR 6132 " src=" MACSTR " bssid=" MACSTR " result=%s", 6133 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), 6134 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? 6135 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? 6136 "NO_ACK" : "FAILED")); 6137} 6138 6139 6140static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd) 6141{ 6142 char *pos, *param; 6143 size_t len; 6144 u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN]; 6145 int res, used; 6146 int freq = 0, no_cck = 0, wait_time = 0; 6147 6148 /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1] 6149 * <action=Action frame payload> */ 6150 6151 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd); 6152 6153 pos = cmd; 6154 used = hwaddr_aton2(pos, da); 6155 if (used < 0) 6156 return -1; 6157 pos += used; 6158 while (*pos == ' ') 6159 pos++; 6160 used = hwaddr_aton2(pos, bssid); 6161 if (used < 0) 6162 return -1; 6163 pos += used; 6164 6165 param = os_strstr(pos, " freq="); 6166 if (param) { 6167 param += 6; 6168 freq = atoi(param); 6169 } 6170 6171 param = os_strstr(pos, " no_cck="); 6172 if (param) { 6173 param += 8; 6174 no_cck = atoi(param); 6175 } 6176 6177 param = os_strstr(pos, " wait_time="); 6178 if (param) { 6179 param += 11; 6180 wait_time = atoi(param); 6181 } 6182 6183 param = os_strstr(pos, " action="); 6184 if (param == NULL) 6185 return -1; 6186 param += 8; 6187 6188 len = os_strlen(param); 6189 if (len & 1) 6190 return -1; 6191 len /= 2; 6192 6193 buf = os_malloc(len); 6194 if (buf == NULL) 6195 return -1; 6196 6197 if (hexstr2bin(param, buf, len) < 0) { 6198 os_free(buf); 6199 return -1; 6200 } 6201 6202 res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid, 6203 buf, len, wait_time, 6204 wpas_ctrl_iface_mgmt_tx_cb, no_cck); 6205 os_free(buf); 6206 return res; 6207} 6208 6209 6210static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s) 6211{ 6212 wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting"); 6213 offchannel_send_action_done(wpa_s); 6214} 6215 6216 6217static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd) 6218{ 6219 char *pos, *param; 6220 union wpa_event_data event; 6221 enum wpa_event_type ev; 6222 6223 /* <event name> [parameters..] */ 6224 6225 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd); 6226 6227 pos = cmd; 6228 param = os_strchr(pos, ' '); 6229 if (param) 6230 *param++ = '\0'; 6231 6232 os_memset(&event, 0, sizeof(event)); 6233 6234 if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) { 6235 ev = EVENT_INTERFACE_ENABLED; 6236 } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) { 6237 ev = EVENT_INTERFACE_DISABLED; 6238 } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) { 6239 ev = EVENT_AVOID_FREQUENCIES; 6240 if (param == NULL) 6241 param = ""; 6242 if (freq_range_list_parse(&event.freq_range, param) < 0) 6243 return -1; 6244 wpa_supplicant_event(wpa_s, ev, &event); 6245 os_free(event.freq_range.range); 6246 return 0; 6247 } else { 6248 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s", 6249 cmd); 6250 return -1; 6251 } 6252 6253 wpa_supplicant_event(wpa_s, ev, &event); 6254 6255 return 0; 6256} 6257 6258#endif /* CONFIG_TESTING_OPTIONS */ 6259 6260 6261static void wpas_ctrl_vendor_elem_update(struct wpa_supplicant *wpa_s) 6262{ 6263 unsigned int i; 6264 char buf[30]; 6265 6266 wpa_printf(MSG_DEBUG, "Update vendor elements"); 6267 6268 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) { 6269 if (wpa_s->vendor_elem[i]) { 6270 os_snprintf(buf, sizeof(buf), "frame[%u]", i); 6271 wpa_hexdump_buf(MSG_DEBUG, buf, wpa_s->vendor_elem[i]); 6272 } 6273 } 6274 6275#ifdef CONFIG_P2P 6276 if (wpa_s->parent == wpa_s && 6277 wpa_s->global->p2p && 6278 !wpa_s->global->p2p_disabled) 6279 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem); 6280#endif /* CONFIG_P2P */ 6281} 6282 6283 6284static struct wpa_supplicant * 6285wpas_ctrl_vendor_elem_iface(struct wpa_supplicant *wpa_s, 6286 enum wpa_vendor_elem_frame frame) 6287{ 6288 switch (frame) { 6289#ifdef CONFIG_P2P 6290 case VENDOR_ELEM_PROBE_REQ_P2P: 6291 case VENDOR_ELEM_PROBE_RESP_P2P: 6292 case VENDOR_ELEM_PROBE_RESP_P2P_GO: 6293 case VENDOR_ELEM_BEACON_P2P_GO: 6294 case VENDOR_ELEM_P2P_PD_REQ: 6295 case VENDOR_ELEM_P2P_PD_RESP: 6296 case VENDOR_ELEM_P2P_GO_NEG_REQ: 6297 case VENDOR_ELEM_P2P_GO_NEG_RESP: 6298 case VENDOR_ELEM_P2P_GO_NEG_CONF: 6299 case VENDOR_ELEM_P2P_INV_REQ: 6300 case VENDOR_ELEM_P2P_INV_RESP: 6301 case VENDOR_ELEM_P2P_ASSOC_REQ: 6302 return wpa_s->parent; 6303#endif /* CONFIG_P2P */ 6304 default: 6305 return wpa_s; 6306 } 6307} 6308 6309 6310static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd) 6311{ 6312 char *pos = cmd; 6313 int frame; 6314 size_t len; 6315 struct wpabuf *buf; 6316 struct ieee802_11_elems elems; 6317 6318 frame = atoi(pos); 6319 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 6320 return -1; 6321 wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame); 6322 6323 pos = os_strchr(pos, ' '); 6324 if (pos == NULL) 6325 return -1; 6326 pos++; 6327 6328 len = os_strlen(pos); 6329 if (len == 0) 6330 return 0; 6331 if (len & 1) 6332 return -1; 6333 len /= 2; 6334 6335 buf = wpabuf_alloc(len); 6336 if (buf == NULL) 6337 return -1; 6338 6339 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 6340 wpabuf_free(buf); 6341 return -1; 6342 } 6343 6344 if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) == 6345 ParseFailed) { 6346 wpabuf_free(buf); 6347 return -1; 6348 } 6349 6350 if (wpa_s->vendor_elem[frame] == NULL) { 6351 wpa_s->vendor_elem[frame] = buf; 6352 wpas_ctrl_vendor_elem_update(wpa_s); 6353 return 0; 6354 } 6355 6356 if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) { 6357 wpabuf_free(buf); 6358 return -1; 6359 } 6360 6361 wpabuf_put_buf(wpa_s->vendor_elem[frame], buf); 6362 wpabuf_free(buf); 6363 wpas_ctrl_vendor_elem_update(wpa_s); 6364 6365 return 0; 6366} 6367 6368 6369static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd, 6370 char *buf, size_t buflen) 6371{ 6372 int frame = atoi(cmd); 6373 6374 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 6375 return -1; 6376 wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame); 6377 6378 if (wpa_s->vendor_elem[frame] == NULL) 6379 return 0; 6380 6381 return wpa_snprintf_hex(buf, buflen, 6382 wpabuf_head_u8(wpa_s->vendor_elem[frame]), 6383 wpabuf_len(wpa_s->vendor_elem[frame])); 6384} 6385 6386 6387static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd) 6388{ 6389 char *pos = cmd; 6390 int frame; 6391 size_t len; 6392 u8 *buf; 6393 struct ieee802_11_elems elems; 6394 u8 *ie, *end; 6395 6396 frame = atoi(pos); 6397 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 6398 return -1; 6399 wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame); 6400 6401 pos = os_strchr(pos, ' '); 6402 if (pos == NULL) 6403 return -1; 6404 pos++; 6405 6406 if (*pos == '*') { 6407 wpabuf_free(wpa_s->vendor_elem[frame]); 6408 wpa_s->vendor_elem[frame] = NULL; 6409 wpas_ctrl_vendor_elem_update(wpa_s); 6410 return 0; 6411 } 6412 6413 if (wpa_s->vendor_elem[frame] == NULL) 6414 return -1; 6415 6416 len = os_strlen(pos); 6417 if (len == 0) 6418 return 0; 6419 if (len & 1) 6420 return -1; 6421 len /= 2; 6422 6423 buf = os_malloc(len); 6424 if (buf == NULL) 6425 return -1; 6426 6427 if (hexstr2bin(pos, buf, len) < 0) { 6428 os_free(buf); 6429 return -1; 6430 } 6431 6432 if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) { 6433 os_free(buf); 6434 return -1; 6435 } 6436 6437 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]); 6438 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]); 6439 6440 for (; ie + 1 < end; ie += 2 + ie[1]) { 6441 if (ie + len > end) 6442 break; 6443 if (os_memcmp(ie, buf, len) != 0) 6444 continue; 6445 6446 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) { 6447 wpabuf_free(wpa_s->vendor_elem[frame]); 6448 wpa_s->vendor_elem[frame] = NULL; 6449 } else { 6450 os_memmove(ie, ie + len, 6451 end - (ie + len)); 6452 wpa_s->vendor_elem[frame]->used -= len; 6453 } 6454 os_free(buf); 6455 wpas_ctrl_vendor_elem_update(wpa_s); 6456 return 0; 6457 } 6458 6459 os_free(buf); 6460 6461 return -1; 6462} 6463 6464 6465char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 6466 char *buf, size_t *resp_len) 6467{ 6468 char *reply; 6469 const int reply_size = 4096; 6470 int reply_len; 6471 6472 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 6473 os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 6474 if (wpa_debug_show_keys) 6475 wpa_dbg(wpa_s, MSG_DEBUG, 6476 "Control interface command '%s'", buf); 6477 else 6478 wpa_dbg(wpa_s, MSG_DEBUG, 6479 "Control interface command '%s [REMOVED]'", 6480 os_strncmp(buf, WPA_CTRL_RSP, 6481 os_strlen(WPA_CTRL_RSP)) == 0 ? 6482 WPA_CTRL_RSP : "SET_NETWORK"); 6483 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 || 6484 os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) { 6485 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 6486 (const u8 *) buf, os_strlen(buf)); 6487 } else { 6488 int level = MSG_DEBUG; 6489 if (os_strcmp(buf, "PING") == 0) 6490 level = MSG_EXCESSIVE; 6491 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf); 6492 } 6493 6494 reply = os_malloc(reply_size); 6495 if (reply == NULL) { 6496 *resp_len = 1; 6497 return NULL; 6498 } 6499 6500 os_memcpy(reply, "OK\n", 3); 6501 reply_len = 3; 6502 6503 if (os_strcmp(buf, "PING") == 0) { 6504 os_memcpy(reply, "PONG\n", 5); 6505 reply_len = 5; 6506 } else if (os_strcmp(buf, "IFNAME") == 0) { 6507 reply_len = os_strlen(wpa_s->ifname); 6508 os_memcpy(reply, wpa_s->ifname, reply_len); 6509 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 6510 if (wpa_debug_reopen_file() < 0) 6511 reply_len = -1; 6512 } else if (os_strncmp(buf, "NOTE ", 5) == 0) { 6513 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); 6514 } else if (os_strcmp(buf, "MIB") == 0) { 6515 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 6516 if (reply_len >= 0) { 6517 int res; 6518 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, 6519 reply_size - reply_len); 6520 if (res < 0) 6521 reply_len = -1; 6522 else 6523 reply_len += res; 6524 } 6525 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 6526 reply_len = wpa_supplicant_ctrl_iface_status( 6527 wpa_s, buf + 6, reply, reply_size); 6528 } else if (os_strcmp(buf, "PMKSA") == 0) { 6529 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply, 6530 reply_size); 6531 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) { 6532 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); 6533 } else if (os_strncmp(buf, "SET ", 4) == 0) { 6534 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 6535 reply_len = -1; 6536 } else if (os_strncmp(buf, "GET ", 4) == 0) { 6537 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4, 6538 reply, reply_size); 6539 } else if (os_strcmp(buf, "LOGON") == 0) { 6540 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 6541 } else if (os_strcmp(buf, "LOGOFF") == 0) { 6542 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 6543 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 6544 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 6545 reply_len = -1; 6546 else 6547 wpas_request_connection(wpa_s); 6548 } else if (os_strcmp(buf, "REATTACH") == 0) { 6549 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED || 6550 !wpa_s->current_ssid) 6551 reply_len = -1; 6552 else { 6553 wpa_s->reattach = 1; 6554 wpas_request_connection(wpa_s); 6555 } 6556 } else if (os_strcmp(buf, "RECONNECT") == 0) { 6557 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 6558 reply_len = -1; 6559 else if (wpa_s->disconnected) 6560 wpas_request_connection(wpa_s); 6561#ifdef IEEE8021X_EAPOL 6562 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 6563 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 6564 reply_len = -1; 6565#endif /* IEEE8021X_EAPOL */ 6566#ifdef CONFIG_PEERKEY 6567 } else if (os_strncmp(buf, "STKSTART ", 9) == 0) { 6568 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9)) 6569 reply_len = -1; 6570#endif /* CONFIG_PEERKEY */ 6571#ifdef CONFIG_IEEE80211R 6572 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 6573 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 6574 reply_len = -1; 6575#endif /* CONFIG_IEEE80211R */ 6576#ifdef CONFIG_WPS 6577 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 6578 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL); 6579 if (res == -2) { 6580 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 6581 reply_len = 17; 6582 } else if (res) 6583 reply_len = -1; 6584 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 6585 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8); 6586 if (res == -2) { 6587 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 6588 reply_len = 17; 6589 } else if (res) 6590 reply_len = -1; 6591 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 6592 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 6593 reply, 6594 reply_size); 6595 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 6596 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin( 6597 wpa_s, buf + 14, reply, reply_size); 6598 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 6599 if (wpas_wps_cancel(wpa_s)) 6600 reply_len = -1; 6601#ifdef CONFIG_WPS_NFC 6602 } else if (os_strcmp(buf, "WPS_NFC") == 0) { 6603 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL)) 6604 reply_len = -1; 6605 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) { 6606 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8)) 6607 reply_len = -1; 6608 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 6609 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token( 6610 wpa_s, buf + 21, reply, reply_size); 6611 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 6612 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token( 6613 wpa_s, buf + 14, reply, reply_size); 6614 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 6615 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s, 6616 buf + 17)) 6617 reply_len = -1; 6618 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) { 6619 reply_len = wpas_ctrl_nfc_get_handover_req( 6620 wpa_s, buf + 21, reply, reply_size); 6621 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 6622 reply_len = wpas_ctrl_nfc_get_handover_sel( 6623 wpa_s, buf + 21, reply, reply_size); 6624 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 6625 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20)) 6626 reply_len = -1; 6627#endif /* CONFIG_WPS_NFC */ 6628 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 6629 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 6630 reply_len = -1; 6631#ifdef CONFIG_AP 6632 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 6633 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin( 6634 wpa_s, buf + 11, reply, reply_size); 6635#endif /* CONFIG_AP */ 6636#ifdef CONFIG_WPS_ER 6637 } else if (os_strcmp(buf, "WPS_ER_START") == 0) { 6638 if (wpas_wps_er_start(wpa_s, NULL)) 6639 reply_len = -1; 6640 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) { 6641 if (wpas_wps_er_start(wpa_s, buf + 13)) 6642 reply_len = -1; 6643 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) { 6644 if (wpas_wps_er_stop(wpa_s)) 6645 reply_len = -1; 6646 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) { 6647 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11)) 6648 reply_len = -1; 6649 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) { 6650 int ret = wpas_wps_er_pbc(wpa_s, buf + 11); 6651 if (ret == -2) { 6652 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 6653 reply_len = 17; 6654 } else if (ret == -3) { 6655 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18); 6656 reply_len = 18; 6657 } else if (ret == -4) { 6658 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20); 6659 reply_len = 20; 6660 } else if (ret) 6661 reply_len = -1; 6662 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { 6663 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) 6664 reply_len = -1; 6665 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) { 6666 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s, 6667 buf + 18)) 6668 reply_len = -1; 6669 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) { 6670 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14)) 6671 reply_len = -1; 6672#ifdef CONFIG_WPS_NFC 6673 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) { 6674 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 6675 wpa_s, buf + 24, reply, reply_size); 6676#endif /* CONFIG_WPS_NFC */ 6677#endif /* CONFIG_WPS_ER */ 6678#endif /* CONFIG_WPS */ 6679#ifdef CONFIG_IBSS_RSN 6680 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) { 6681 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9)) 6682 reply_len = -1; 6683#endif /* CONFIG_IBSS_RSN */ 6684#ifdef CONFIG_P2P 6685 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) { 6686 if (p2p_ctrl_find(wpa_s, buf + 9)) 6687 reply_len = -1; 6688 } else if (os_strcmp(buf, "P2P_FIND") == 0) { 6689 if (p2p_ctrl_find(wpa_s, "")) 6690 reply_len = -1; 6691 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) { 6692 wpas_p2p_stop_find(wpa_s); 6693 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) { 6694 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply, 6695 reply_size); 6696 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) { 6697 if (p2p_ctrl_listen(wpa_s, buf + 11)) 6698 reply_len = -1; 6699 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) { 6700 if (p2p_ctrl_listen(wpa_s, "")) 6701 reply_len = -1; 6702 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) { 6703 if (wpas_p2p_group_remove(wpa_s, buf + 17)) 6704 reply_len = -1; 6705 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) { 6706 if (wpas_p2p_group_add(wpa_s, 0, 0, 0, 0)) 6707 reply_len = -1; 6708 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) { 6709 if (p2p_ctrl_group_add(wpa_s, buf + 14)) 6710 reply_len = -1; 6711 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) { 6712 if (p2p_ctrl_prov_disc(wpa_s, buf + 14)) 6713 reply_len = -1; 6714 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) { 6715 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size); 6716 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) { 6717 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply, 6718 reply_size); 6719 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) { 6720 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0) 6721 reply_len = -1; 6722 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) { 6723 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0) 6724 reply_len = -1; 6725 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) { 6726 wpas_p2p_sd_service_update(wpa_s); 6727 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) { 6728 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0) 6729 reply_len = -1; 6730 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) { 6731 wpas_p2p_service_flush(wpa_s); 6732 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) { 6733 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0) 6734 reply_len = -1; 6735 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) { 6736 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0) 6737 reply_len = -1; 6738 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) { 6739 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0) 6740 reply_len = -1; 6741 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) { 6742 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0) 6743 reply_len = -1; 6744 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) { 6745 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply, 6746 reply_size); 6747 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) { 6748 if (p2p_ctrl_set(wpa_s, buf + 8) < 0) 6749 reply_len = -1; 6750 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) { 6751 p2p_ctrl_flush(wpa_s); 6752 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) { 6753 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0) 6754 reply_len = -1; 6755 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) { 6756 if (wpas_p2p_cancel(wpa_s)) 6757 reply_len = -1; 6758 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) { 6759 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0) 6760 reply_len = -1; 6761 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) { 6762 if (p2p_ctrl_presence_req(wpa_s, "") < 0) 6763 reply_len = -1; 6764 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) { 6765 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0) 6766 reply_len = -1; 6767 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) { 6768 if (p2p_ctrl_ext_listen(wpa_s, "") < 0) 6769 reply_len = -1; 6770 } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) { 6771 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0) 6772 reply_len = -1; 6773#endif /* CONFIG_P2P */ 6774#ifdef CONFIG_WIFI_DISPLAY 6775 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) { 6776 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0) 6777 reply_len = -1; 6778 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) { 6779 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16, 6780 reply, reply_size); 6781#endif /* CONFIG_WIFI_DISPLAY */ 6782#ifdef CONFIG_INTERWORKING 6783 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) { 6784 if (interworking_fetch_anqp(wpa_s) < 0) 6785 reply_len = -1; 6786 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) { 6787 interworking_stop_fetch_anqp(wpa_s); 6788 } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) { 6789 if (ctrl_interworking_select(wpa_s, NULL) < 0) 6790 reply_len = -1; 6791 } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) { 6792 if (ctrl_interworking_select(wpa_s, buf + 20) < 0) 6793 reply_len = -1; 6794 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) { 6795 if (ctrl_interworking_connect(wpa_s, buf + 21) < 0) 6796 reply_len = -1; 6797 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) { 6798 if (get_anqp(wpa_s, buf + 9) < 0) 6799 reply_len = -1; 6800 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) { 6801 if (gas_request(wpa_s, buf + 12) < 0) 6802 reply_len = -1; 6803 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) { 6804 reply_len = gas_response_get(wpa_s, buf + 17, reply, 6805 reply_size); 6806#endif /* CONFIG_INTERWORKING */ 6807#ifdef CONFIG_HS20 6808 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) { 6809 if (get_hs20_anqp(wpa_s, buf + 14) < 0) 6810 reply_len = -1; 6811 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) { 6812 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0) 6813 reply_len = -1; 6814 } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) { 6815 if (hs20_icon_request(wpa_s, buf + 18) < 0) 6816 reply_len = -1; 6817 } else if (os_strcmp(buf, "FETCH_OSU") == 0) { 6818 if (hs20_fetch_osu(wpa_s) < 0) 6819 reply_len = -1; 6820 } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) { 6821 hs20_cancel_fetch_osu(wpa_s); 6822#endif /* CONFIG_HS20 */ 6823 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 6824 { 6825 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 6826 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 6827 reply_len = -1; 6828 else { 6829 /* 6830 * Notify response from timeout to allow the control 6831 * interface response to be sent first. 6832 */ 6833 eloop_register_timeout(0, 0, wpas_ctrl_eapol_response, 6834 wpa_s, NULL); 6835 } 6836 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 6837 if (wpa_supplicant_reload_configuration(wpa_s)) 6838 reply_len = -1; 6839 } else if (os_strcmp(buf, "TERMINATE") == 0) { 6840 wpa_supplicant_terminate_proc(wpa_s->global); 6841 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 6842 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 6843 reply_len = -1; 6844 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { 6845 reply_len = wpa_supplicant_ctrl_iface_blacklist( 6846 wpa_s, buf + 9, reply, reply_size); 6847 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 6848 reply_len = wpa_supplicant_ctrl_iface_log_level( 6849 wpa_s, buf + 9, reply, reply_size); 6850 } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) { 6851 reply_len = wpa_supplicant_ctrl_iface_list_networks( 6852 wpa_s, buf + 14, reply, reply_size); 6853 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 6854 reply_len = wpa_supplicant_ctrl_iface_list_networks( 6855 wpa_s, NULL, reply, reply_size); 6856 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 6857#ifdef CONFIG_SME 6858 wpa_s->sme.prev_bssid_set = 0; 6859#endif /* CONFIG_SME */ 6860 wpa_s->reassociate = 0; 6861 wpa_s->disconnected = 1; 6862 wpa_supplicant_cancel_sched_scan(wpa_s); 6863 wpa_supplicant_cancel_scan(wpa_s); 6864 wpa_supplicant_deauthenticate(wpa_s, 6865 WLAN_REASON_DEAUTH_LEAVING); 6866 } else if (os_strcmp(buf, "SCAN") == 0) { 6867 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len); 6868 } else if (os_strncmp(buf, "SCAN ", 5) == 0) { 6869 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len); 6870 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 6871 reply_len = wpa_supplicant_ctrl_iface_scan_results( 6872 wpa_s, reply, reply_size); 6873 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 6874 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 6875 reply_len = -1; 6876 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 6877 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 6878 reply_len = -1; 6879 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 6880 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 6881 reply_len = -1; 6882 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 6883 reply_len = wpa_supplicant_ctrl_iface_add_network( 6884 wpa_s, reply, reply_size); 6885 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 6886 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 6887 reply_len = -1; 6888 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 6889 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 6890 reply_len = -1; 6891 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 6892 reply_len = wpa_supplicant_ctrl_iface_get_network( 6893 wpa_s, buf + 12, reply, reply_size); 6894 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 6895 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12)) 6896 reply_len = -1; 6897 } else if (os_strcmp(buf, "LIST_CREDS") == 0) { 6898 reply_len = wpa_supplicant_ctrl_iface_list_creds( 6899 wpa_s, reply, reply_size); 6900 } else if (os_strcmp(buf, "ADD_CRED") == 0) { 6901 reply_len = wpa_supplicant_ctrl_iface_add_cred( 6902 wpa_s, reply, reply_size); 6903 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) { 6904 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12)) 6905 reply_len = -1; 6906 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) { 6907 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9)) 6908 reply_len = -1; 6909 } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) { 6910 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9, 6911 reply, 6912 reply_size); 6913#ifndef CONFIG_NO_CONFIG_WRITE 6914 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 6915 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 6916 reply_len = -1; 6917#endif /* CONFIG_NO_CONFIG_WRITE */ 6918 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 6919 reply_len = wpa_supplicant_ctrl_iface_get_capability( 6920 wpa_s, buf + 15, reply, reply_size); 6921 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 6922 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 6923 reply_len = -1; 6924 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) { 6925 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14)) 6926 reply_len = -1; 6927 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 6928 reply_len = wpa_supplicant_global_iface_list( 6929 wpa_s->global, reply, reply_size); 6930 } else if (os_strcmp(buf, "INTERFACES") == 0) { 6931 reply_len = wpa_supplicant_global_iface_interfaces( 6932 wpa_s->global, reply, reply_size); 6933 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 6934 reply_len = wpa_supplicant_ctrl_iface_bss( 6935 wpa_s, buf + 4, reply, reply_size); 6936#ifdef CONFIG_AP 6937 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 6938 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); 6939 } else if (os_strncmp(buf, "STA ", 4) == 0) { 6940 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply, 6941 reply_size); 6942 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 6943 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, 6944 reply_size); 6945 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 6946 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15)) 6947 reply_len = -1; 6948 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 6949 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13)) 6950 reply_len = -1; 6951 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { 6952 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12)) 6953 reply_len = -1; 6954#endif /* CONFIG_AP */ 6955 } else if (os_strcmp(buf, "SUSPEND") == 0) { 6956 wpas_notify_suspend(wpa_s->global); 6957 } else if (os_strcmp(buf, "RESUME") == 0) { 6958 wpas_notify_resume(wpa_s->global); 6959#ifdef CONFIG_TESTING_OPTIONS 6960 } else if (os_strcmp(buf, "DROP_SA") == 0) { 6961 wpa_supplicant_ctrl_iface_drop_sa(wpa_s); 6962#endif /* CONFIG_TESTING_OPTIONS */ 6963 } else if (os_strncmp(buf, "ROAM ", 5) == 0) { 6964 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) 6965 reply_len = -1; 6966 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) { 6967 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16)) 6968 reply_len = -1; 6969 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) { 6970 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15)) 6971 reply_len = -1; 6972 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) { 6973 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s, 6974 buf + 17)) 6975 reply_len = -1; 6976 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) { 6977 if (wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10)) 6978 reply_len = -1; 6979#ifdef CONFIG_TDLS 6980 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) { 6981 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14)) 6982 reply_len = -1; 6983 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) { 6984 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11)) 6985 reply_len = -1; 6986 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) { 6987 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14)) 6988 reply_len = -1; 6989#endif /* CONFIG_TDLS */ 6990 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) { 6991 reply_len = wpa_supplicant_signal_poll(wpa_s, reply, 6992 reply_size); 6993 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) { 6994 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply, 6995 reply_size); 6996#ifdef CONFIG_AUTOSCAN 6997 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) { 6998 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9)) 6999 reply_len = -1; 7000#endif /* CONFIG_AUTOSCAN */ 7001#ifdef ANDROID 7002 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { 7003 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, 7004 reply_size); 7005#endif /* ANDROID */ 7006 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { 7007 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply, 7008 reply_size); 7009 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) { 7010 pmksa_cache_clear_current(wpa_s->wpa); 7011 eapol_sm_request_reauth(wpa_s->eapol); 7012#ifdef CONFIG_WNM 7013 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) { 7014 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10)) 7015 reply_len = -1; 7016 } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 10) == 0) { 7017 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 10)) 7018 reply_len = -1; 7019#endif /* CONFIG_WNM */ 7020 } else if (os_strcmp(buf, "FLUSH") == 0) { 7021 wpa_supplicant_ctrl_iface_flush(wpa_s); 7022 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) { 7023 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply, 7024 reply_size); 7025#ifdef CONFIG_TESTING_OPTIONS 7026 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) { 7027 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0) 7028 reply_len = -1; 7029 } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) { 7030 wpas_ctrl_iface_mgmt_tx_done(wpa_s); 7031 } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) { 7032 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0) 7033 reply_len = -1; 7034#endif /* CONFIG_TESTING_OPTIONS */ 7035 } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) { 7036 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0) 7037 reply_len = -1; 7038 } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) { 7039 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply, 7040 reply_size); 7041 } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) { 7042 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0) 7043 reply_len = -1; 7044 } else { 7045 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 7046 reply_len = 16; 7047 } 7048 7049 if (reply_len < 0) { 7050 os_memcpy(reply, "FAIL\n", 5); 7051 reply_len = 5; 7052 } 7053 7054 *resp_len = reply_len; 7055 return reply; 7056} 7057 7058 7059static int wpa_supplicant_global_iface_add(struct wpa_global *global, 7060 char *cmd) 7061{ 7062 struct wpa_interface iface; 7063 char *pos; 7064 7065 /* 7066 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 7067 * TAB<bridge_ifname> 7068 */ 7069 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 7070 7071 os_memset(&iface, 0, sizeof(iface)); 7072 7073 do { 7074 iface.ifname = pos = cmd; 7075 pos = os_strchr(pos, '\t'); 7076 if (pos) 7077 *pos++ = '\0'; 7078 if (iface.ifname[0] == '\0') 7079 return -1; 7080 if (pos == NULL) 7081 break; 7082 7083 iface.confname = pos; 7084 pos = os_strchr(pos, '\t'); 7085 if (pos) 7086 *pos++ = '\0'; 7087 if (iface.confname[0] == '\0') 7088 iface.confname = NULL; 7089 if (pos == NULL) 7090 break; 7091 7092 iface.driver = pos; 7093 pos = os_strchr(pos, '\t'); 7094 if (pos) 7095 *pos++ = '\0'; 7096 if (iface.driver[0] == '\0') 7097 iface.driver = NULL; 7098 if (pos == NULL) 7099 break; 7100 7101 iface.ctrl_interface = pos; 7102 pos = os_strchr(pos, '\t'); 7103 if (pos) 7104 *pos++ = '\0'; 7105 if (iface.ctrl_interface[0] == '\0') 7106 iface.ctrl_interface = NULL; 7107 if (pos == NULL) 7108 break; 7109 7110 iface.driver_param = pos; 7111 pos = os_strchr(pos, '\t'); 7112 if (pos) 7113 *pos++ = '\0'; 7114 if (iface.driver_param[0] == '\0') 7115 iface.driver_param = NULL; 7116 if (pos == NULL) 7117 break; 7118 7119 iface.bridge_ifname = pos; 7120 pos = os_strchr(pos, '\t'); 7121 if (pos) 7122 *pos++ = '\0'; 7123 if (iface.bridge_ifname[0] == '\0') 7124 iface.bridge_ifname = NULL; 7125 if (pos == NULL) 7126 break; 7127 } while (0); 7128 7129 if (wpa_supplicant_get_iface(global, iface.ifname)) 7130 return -1; 7131 7132 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1; 7133} 7134 7135 7136static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 7137 char *cmd) 7138{ 7139 struct wpa_supplicant *wpa_s; 7140 7141 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 7142 7143 wpa_s = wpa_supplicant_get_iface(global, cmd); 7144 if (wpa_s == NULL) 7145 return -1; 7146 return wpa_supplicant_remove_iface(global, wpa_s, 0); 7147} 7148 7149 7150static void wpa_free_iface_info(struct wpa_interface_info *iface) 7151{ 7152 struct wpa_interface_info *prev; 7153 7154 while (iface) { 7155 prev = iface; 7156 iface = iface->next; 7157 7158 os_free(prev->ifname); 7159 os_free(prev->desc); 7160 os_free(prev); 7161 } 7162} 7163 7164 7165static int wpa_supplicant_global_iface_list(struct wpa_global *global, 7166 char *buf, int len) 7167{ 7168 int i, res; 7169 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 7170 char *pos, *end; 7171 7172 for (i = 0; wpa_drivers[i]; i++) { 7173 struct wpa_driver_ops *drv = wpa_drivers[i]; 7174 if (drv->get_interfaces == NULL) 7175 continue; 7176 tmp = drv->get_interfaces(global->drv_priv[i]); 7177 if (tmp == NULL) 7178 continue; 7179 7180 if (last == NULL) 7181 iface = last = tmp; 7182 else 7183 last->next = tmp; 7184 while (last->next) 7185 last = last->next; 7186 } 7187 7188 pos = buf; 7189 end = buf + len; 7190 for (tmp = iface; tmp; tmp = tmp->next) { 7191 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 7192 tmp->drv_name, tmp->ifname, 7193 tmp->desc ? tmp->desc : ""); 7194 if (res < 0 || res >= end - pos) { 7195 *pos = '\0'; 7196 break; 7197 } 7198 pos += res; 7199 } 7200 7201 wpa_free_iface_info(iface); 7202 7203 return pos - buf; 7204} 7205 7206 7207static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 7208 char *buf, int len) 7209{ 7210 int res; 7211 char *pos, *end; 7212 struct wpa_supplicant *wpa_s; 7213 7214 wpa_s = global->ifaces; 7215 pos = buf; 7216 end = buf + len; 7217 7218 while (wpa_s) { 7219 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname); 7220 if (res < 0 || res >= end - pos) { 7221 *pos = '\0'; 7222 break; 7223 } 7224 pos += res; 7225 wpa_s = wpa_s->next; 7226 } 7227 return pos - buf; 7228} 7229 7230 7231static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global, 7232 const char *ifname, 7233 char *cmd, size_t *resp_len) 7234{ 7235 struct wpa_supplicant *wpa_s; 7236 7237 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 7238 if (os_strcmp(ifname, wpa_s->ifname) == 0) 7239 break; 7240 } 7241 7242 if (wpa_s == NULL) { 7243 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n"); 7244 if (resp) 7245 *resp_len = os_strlen(resp); 7246 else 7247 *resp_len = 1; 7248 return resp; 7249 } 7250 7251 return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len); 7252} 7253 7254 7255static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global, 7256 char *buf, size_t *resp_len) 7257{ 7258#ifdef CONFIG_P2P 7259 static const char * cmd[] = { 7260 "LIST_NETWORKS", 7261 "P2P_FIND", 7262 "P2P_STOP_FIND", 7263 "P2P_LISTEN", 7264 "P2P_GROUP_ADD", 7265 "P2P_GET_PASSPHRASE", 7266 "P2P_SERVICE_UPDATE", 7267 "P2P_SERVICE_FLUSH", 7268 "P2P_FLUSH", 7269 "P2P_CANCEL", 7270 "P2P_PRESENCE_REQ", 7271 "P2P_EXT_LISTEN", 7272 NULL 7273 }; 7274 static const char * prefix[] = { 7275#ifdef ANDROID 7276 "DRIVER ", 7277#endif /* ANDROID */ 7278 "GET_NETWORK ", 7279 "REMOVE_NETWORK ", 7280 "P2P_FIND ", 7281 "P2P_CONNECT ", 7282 "P2P_LISTEN ", 7283 "P2P_GROUP_REMOVE ", 7284 "P2P_GROUP_ADD ", 7285 "P2P_PROV_DISC ", 7286 "P2P_SERV_DISC_REQ ", 7287 "P2P_SERV_DISC_CANCEL_REQ ", 7288 "P2P_SERV_DISC_RESP ", 7289 "P2P_SERV_DISC_EXTERNAL ", 7290 "P2P_SERVICE_ADD ", 7291 "P2P_SERVICE_DEL ", 7292 "P2P_REJECT ", 7293 "P2P_INVITE ", 7294 "P2P_PEER ", 7295 "P2P_SET ", 7296 "P2P_UNAUTHORIZE ", 7297 "P2P_PRESENCE_REQ ", 7298 "P2P_EXT_LISTEN ", 7299 "P2P_REMOVE_CLIENT ", 7300 "NFC_GET_HANDOVER_SEL ", 7301 "NFC_GET_HANDOVER_REQ ", 7302 "NFC_REPORT_HANDOVER ", 7303 NULL 7304 }; 7305 int found = 0; 7306 int i; 7307 7308 if (global->p2p_init_wpa_s == NULL) 7309 return NULL; 7310 7311 for (i = 0; !found && cmd[i]; i++) { 7312 if (os_strcmp(buf, cmd[i]) == 0) 7313 found = 1; 7314 } 7315 7316 for (i = 0; !found && prefix[i]; i++) { 7317 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0) 7318 found = 1; 7319 } 7320 7321 if (found) 7322 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s, 7323 buf, resp_len); 7324#endif /* CONFIG_P2P */ 7325 return NULL; 7326} 7327 7328 7329static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global, 7330 char *buf, size_t *resp_len) 7331{ 7332#ifdef CONFIG_WIFI_DISPLAY 7333 if (global->p2p_init_wpa_s == NULL) 7334 return NULL; 7335 if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 || 7336 os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) 7337 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s, 7338 buf, resp_len); 7339#endif /* CONFIG_WIFI_DISPLAY */ 7340 return NULL; 7341} 7342 7343 7344static char * wpas_global_ctrl_iface_redir(struct wpa_global *global, 7345 char *buf, size_t *resp_len) 7346{ 7347 char *ret; 7348 7349 ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len); 7350 if (ret) 7351 return ret; 7352 7353 ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len); 7354 if (ret) 7355 return ret; 7356 7357 return NULL; 7358} 7359 7360 7361static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd) 7362{ 7363 char *value; 7364 7365 value = os_strchr(cmd, ' '); 7366 if (value == NULL) 7367 return -1; 7368 *value++ = '\0'; 7369 7370 wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value); 7371 7372#ifdef CONFIG_WIFI_DISPLAY 7373 if (os_strcasecmp(cmd, "wifi_display") == 0) { 7374 wifi_display_enable(global, !!atoi(value)); 7375 return 0; 7376 } 7377#endif /* CONFIG_WIFI_DISPLAY */ 7378 7379 /* Restore cmd to its original value to allow redirection */ 7380 value[-1] = ' '; 7381 7382 return -1; 7383} 7384 7385 7386#ifndef CONFIG_NO_CONFIG_WRITE 7387static int wpas_global_ctrl_iface_save_config(struct wpa_global *global) 7388{ 7389 int ret = 0, saved = 0; 7390 struct wpa_supplicant *wpa_s; 7391 7392 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 7393 if (!wpa_s->conf->update_config) { 7394 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)"); 7395 continue; 7396 } 7397 7398 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) { 7399 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration"); 7400 ret = 1; 7401 } else { 7402 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated"); 7403 saved++; 7404 } 7405 } 7406 7407 if (!saved && !ret) { 7408 wpa_dbg(wpa_s, MSG_DEBUG, 7409 "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated"); 7410 ret = 1; 7411 } 7412 7413 return ret; 7414} 7415#endif /* CONFIG_NO_CONFIG_WRITE */ 7416 7417 7418static int wpas_global_ctrl_iface_status(struct wpa_global *global, 7419 char *buf, size_t buflen) 7420{ 7421 char *pos, *end; 7422 int ret; 7423 struct wpa_supplicant *wpa_s; 7424 7425 pos = buf; 7426 end = buf + buflen; 7427 7428#ifdef CONFIG_P2P 7429 if (global->p2p && !global->p2p_disabled) { 7430 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 7431 "\n" 7432 "p2p_state=%s\n", 7433 MAC2STR(global->p2p_dev_addr), 7434 p2p_get_state_txt(global->p2p)); 7435 if (ret < 0 || ret >= end - pos) 7436 return pos - buf; 7437 pos += ret; 7438 } else if (global->p2p) { 7439 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n"); 7440 if (ret < 0 || ret >= end - pos) 7441 return pos - buf; 7442 pos += ret; 7443 } 7444#endif /* CONFIG_P2P */ 7445 7446#ifdef CONFIG_WIFI_DISPLAY 7447 ret = os_snprintf(pos, end - pos, "wifi_display=%d\n", 7448 !!global->wifi_display); 7449 if (ret < 0 || ret >= end - pos) 7450 return pos - buf; 7451 pos += ret; 7452#endif /* CONFIG_WIFI_DISPLAY */ 7453 7454 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 7455 ret = os_snprintf(pos, end - pos, "ifname=%s\n" 7456 "address=" MACSTR "\n", 7457 wpa_s->ifname, MAC2STR(wpa_s->own_addr)); 7458 if (ret < 0 || ret >= end - pos) 7459 return pos - buf; 7460 pos += ret; 7461 } 7462 7463 return pos - buf; 7464} 7465 7466 7467char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 7468 char *buf, size_t *resp_len) 7469{ 7470 char *reply; 7471 const int reply_size = 2048; 7472 int reply_len; 7473 int level = MSG_DEBUG; 7474 7475 if (os_strncmp(buf, "IFNAME=", 7) == 0) { 7476 char *pos = os_strchr(buf + 7, ' '); 7477 if (pos) { 7478 *pos++ = '\0'; 7479 return wpas_global_ctrl_iface_ifname(global, 7480 buf + 7, pos, 7481 resp_len); 7482 } 7483 } 7484 7485 reply = wpas_global_ctrl_iface_redir(global, buf, resp_len); 7486 if (reply) 7487 return reply; 7488 7489 if (os_strcmp(buf, "PING") == 0) 7490 level = MSG_EXCESSIVE; 7491 wpa_hexdump_ascii(level, "RX global ctrl_iface", 7492 (const u8 *) buf, os_strlen(buf)); 7493 7494 reply = os_malloc(reply_size); 7495 if (reply == NULL) { 7496 *resp_len = 1; 7497 return NULL; 7498 } 7499 7500 os_memcpy(reply, "OK\n", 3); 7501 reply_len = 3; 7502 7503 if (os_strcmp(buf, "PING") == 0) { 7504 os_memcpy(reply, "PONG\n", 5); 7505 reply_len = 5; 7506 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 7507 if (wpa_supplicant_global_iface_add(global, buf + 14)) 7508 reply_len = -1; 7509 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 7510 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 7511 reply_len = -1; 7512 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 7513 reply_len = wpa_supplicant_global_iface_list( 7514 global, reply, reply_size); 7515 } else if (os_strcmp(buf, "INTERFACES") == 0) { 7516 reply_len = wpa_supplicant_global_iface_interfaces( 7517 global, reply, reply_size); 7518 } else if (os_strcmp(buf, "TERMINATE") == 0) { 7519 wpa_supplicant_terminate_proc(global); 7520 } else if (os_strcmp(buf, "SUSPEND") == 0) { 7521 wpas_notify_suspend(global); 7522 } else if (os_strcmp(buf, "RESUME") == 0) { 7523 wpas_notify_resume(global); 7524 } else if (os_strncmp(buf, "SET ", 4) == 0) { 7525 if (wpas_global_ctrl_iface_set(global, buf + 4)) { 7526#ifdef CONFIG_P2P 7527 if (global->p2p_init_wpa_s) { 7528 os_free(reply); 7529 /* Check if P2P redirection would work for this 7530 * command. */ 7531 return wpa_supplicant_ctrl_iface_process( 7532 global->p2p_init_wpa_s, 7533 buf, resp_len); 7534 } 7535#endif /* CONFIG_P2P */ 7536 reply_len = -1; 7537 } 7538#ifndef CONFIG_NO_CONFIG_WRITE 7539 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 7540 if (wpas_global_ctrl_iface_save_config(global)) 7541 reply_len = -1; 7542#endif /* CONFIG_NO_CONFIG_WRITE */ 7543 } else if (os_strcmp(buf, "STATUS") == 0) { 7544 reply_len = wpas_global_ctrl_iface_status(global, reply, 7545 reply_size); 7546#ifdef CONFIG_MODULE_TESTS 7547 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) { 7548 int wpas_module_tests(void); 7549 if (wpas_module_tests() < 0) 7550 reply_len = -1; 7551#endif /* CONFIG_MODULE_TESTS */ 7552 } else { 7553 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 7554 reply_len = 16; 7555 } 7556 7557 if (reply_len < 0) { 7558 os_memcpy(reply, "FAIL\n", 5); 7559 reply_len = 5; 7560 } 7561 7562 *resp_len = reply_len; 7563 return reply; 7564} 7565