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