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