1 /* 2 * WPA Supplicant / Control interface (shared code for all backends) 3 * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "utils/includes.h" 16 17 #include "utils/common.h" 18 #include "utils/eloop.h" 19 #include "common/ieee802_11_defs.h" 20 #include "common/wpa_ctrl.h" 21 #include "eap_peer/eap.h" 22 #include "eapol_supp/eapol_supp_sm.h" 23 #include "rsn_supp/wpa.h" 24 #include "rsn_supp/preauth.h" 25 #include "rsn_supp/pmksa_cache.h" 26 #include "l2_packet/l2_packet.h" 27 #include "wps/wps.h" 28 #include "config.h" 29 #include "wpa_supplicant_i.h" 30 #include "driver_i.h" 31 #include "wps_supplicant.h" 32 #include "ibss_rsn.h" 33 #include "ap.h" 34 #include "notify.h" 35 #include "bss.h" 36 #include "scan.h" 37 #include "ctrl_iface.h" 38 39 extern struct wpa_driver_ops *wpa_drivers[]; 40 41 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 42 char *buf, int len); 43 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 44 char *buf, int len); 45 46 47 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 48 char *cmd) 49 { 50 char *value; 51 int ret = 0; 52 53 value = os_strchr(cmd, ' '); 54 if (value == NULL) 55 return -1; 56 *value++ = '\0'; 57 58 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 59 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 60 eapol_sm_configure(wpa_s->eapol, 61 atoi(value), -1, -1, -1); 62 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 63 eapol_sm_configure(wpa_s->eapol, 64 -1, atoi(value), -1, -1); 65 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 66 eapol_sm_configure(wpa_s->eapol, 67 -1, -1, atoi(value), -1); 68 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 69 eapol_sm_configure(wpa_s->eapol, 70 -1, -1, -1, atoi(value)); 71 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 72 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 73 atoi(value))) 74 ret = -1; 75 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 76 0) { 77 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 78 atoi(value))) 79 ret = -1; 80 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 81 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) 82 ret = -1; 83 } else 84 ret = -1; 85 86 return ret; 87 } 88 89 90 #ifdef IEEE8021X_EAPOL 91 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 92 char *addr) 93 { 94 u8 bssid[ETH_ALEN]; 95 struct wpa_ssid *ssid = wpa_s->current_ssid; 96 97 if (hwaddr_aton(addr, bssid)) { 98 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 99 "'%s'", addr); 100 return -1; 101 } 102 103 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 104 rsn_preauth_deinit(wpa_s->wpa); 105 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL)) 106 return -1; 107 108 return 0; 109 } 110 #endif /* IEEE8021X_EAPOL */ 111 112 113 #ifdef CONFIG_PEERKEY 114 /* MLME-STKSTART.request(peer) */ 115 static int wpa_supplicant_ctrl_iface_stkstart( 116 struct wpa_supplicant *wpa_s, char *addr) 117 { 118 u8 peer[ETH_ALEN]; 119 120 if (hwaddr_aton(addr, peer)) { 121 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid " 122 "address '%s'", addr); 123 return -1; 124 } 125 126 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR, 127 MAC2STR(peer)); 128 129 return wpa_sm_stkstart(wpa_s->wpa, peer); 130 } 131 #endif /* CONFIG_PEERKEY */ 132 133 134 #ifdef CONFIG_IEEE80211R 135 static int wpa_supplicant_ctrl_iface_ft_ds( 136 struct wpa_supplicant *wpa_s, char *addr) 137 { 138 u8 target_ap[ETH_ALEN]; 139 struct wpa_bss *bss; 140 const u8 *mdie; 141 142 if (hwaddr_aton(addr, target_ap)) { 143 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 144 "address '%s'", addr); 145 return -1; 146 } 147 148 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); 149 150 bss = wpa_bss_get_bssid(wpa_s, target_ap); 151 if (bss) 152 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 153 else 154 mdie = NULL; 155 156 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie); 157 } 158 #endif /* CONFIG_IEEE80211R */ 159 160 161 #ifdef CONFIG_WPS 162 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, 163 char *cmd) 164 { 165 u8 bssid[ETH_ALEN], *_bssid = bssid; 166 167 if (cmd == NULL || os_strcmp(cmd, "any") == 0) 168 _bssid = NULL; 169 else if (hwaddr_aton(cmd, bssid)) { 170 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", 171 cmd); 172 return -1; 173 } 174 175 #ifdef CONFIG_AP 176 if (wpa_s->ap_iface) 177 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid); 178 #endif /* CONFIG_AP */ 179 180 return wpas_wps_start_pbc(wpa_s, _bssid); 181 } 182 183 184 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, 185 char *cmd, char *buf, 186 size_t buflen) 187 { 188 u8 bssid[ETH_ALEN], *_bssid = bssid; 189 char *pin; 190 int ret; 191 192 pin = os_strchr(cmd, ' '); 193 if (pin) 194 *pin++ = '\0'; 195 196 if (os_strcmp(cmd, "any") == 0) 197 _bssid = NULL; 198 else if (hwaddr_aton(cmd, bssid)) { 199 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'", 200 cmd); 201 return -1; 202 } 203 204 #ifdef CONFIG_AP 205 if (wpa_s->ap_iface) 206 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin, 207 buf, buflen); 208 #endif /* CONFIG_AP */ 209 210 if (pin) { 211 ret = wpas_wps_start_pin(wpa_s, _bssid, pin); 212 if (ret < 0) 213 return -1; 214 ret = os_snprintf(buf, buflen, "%s", pin); 215 if (ret < 0 || (size_t) ret >= buflen) 216 return -1; 217 return ret; 218 } 219 220 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL); 221 if (ret < 0) 222 return -1; 223 224 /* Return the generated PIN */ 225 ret = os_snprintf(buf, buflen, "%08d", ret); 226 if (ret < 0 || (size_t) ret >= buflen) 227 return -1; 228 return ret; 229 } 230 231 232 #ifdef CONFIG_WPS_OOB 233 static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s, 234 char *cmd) 235 { 236 char *path, *method, *name; 237 238 path = os_strchr(cmd, ' '); 239 if (path == NULL) 240 return -1; 241 *path++ = '\0'; 242 243 method = os_strchr(path, ' '); 244 if (method == NULL) 245 return -1; 246 *method++ = '\0'; 247 248 name = os_strchr(method, ' '); 249 if (name != NULL) 250 *name++ = '\0'; 251 252 return wpas_wps_start_oob(wpa_s, cmd, path, method, name); 253 } 254 #endif /* CONFIG_WPS_OOB */ 255 256 257 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s, 258 char *cmd) 259 { 260 u8 bssid[ETH_ALEN], *_bssid = bssid; 261 char *pin; 262 char *new_ssid; 263 char *new_auth; 264 char *new_encr; 265 char *new_key; 266 struct wps_new_ap_settings ap; 267 268 pin = os_strchr(cmd, ' '); 269 if (pin == NULL) 270 return -1; 271 *pin++ = '\0'; 272 273 if (os_strcmp(cmd, "any") == 0) 274 _bssid = NULL; 275 else if (hwaddr_aton(cmd, bssid)) { 276 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'", 277 cmd); 278 return -1; 279 } 280 281 new_ssid = os_strchr(pin, ' '); 282 if (new_ssid == NULL) 283 return wpas_wps_start_reg(wpa_s, _bssid, pin, NULL); 284 *new_ssid++ = '\0'; 285 286 new_auth = os_strchr(new_ssid, ' '); 287 if (new_auth == NULL) 288 return -1; 289 *new_auth++ = '\0'; 290 291 new_encr = os_strchr(new_auth, ' '); 292 if (new_encr == NULL) 293 return -1; 294 *new_encr++ = '\0'; 295 296 new_key = os_strchr(new_encr, ' '); 297 if (new_key == NULL) 298 return -1; 299 *new_key++ = '\0'; 300 301 os_memset(&ap, 0, sizeof(ap)); 302 ap.ssid_hex = new_ssid; 303 ap.auth = new_auth; 304 ap.encr = new_encr; 305 ap.key_hex = new_key; 306 return wpas_wps_start_reg(wpa_s, _bssid, pin, &ap); 307 } 308 309 310 #ifdef CONFIG_WPS_ER 311 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s, 312 char *cmd) 313 { 314 char *uuid = cmd, *pin; 315 pin = os_strchr(uuid, ' '); 316 if (pin == NULL) 317 return -1; 318 *pin++ = '\0'; 319 return wpas_wps_er_add_pin(wpa_s, uuid, pin); 320 } 321 322 323 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s, 324 char *cmd) 325 { 326 char *uuid = cmd, *pin; 327 pin = os_strchr(uuid, ' '); 328 if (pin == NULL) 329 return -1; 330 *pin++ = '\0'; 331 return wpas_wps_er_learn(wpa_s, uuid, pin); 332 } 333 #endif /* CONFIG_WPS_ER */ 334 335 #endif /* CONFIG_WPS */ 336 337 338 #ifdef CONFIG_IBSS_RSN 339 static int wpa_supplicant_ctrl_iface_ibss_rsn( 340 struct wpa_supplicant *wpa_s, char *addr) 341 { 342 u8 peer[ETH_ALEN]; 343 344 if (hwaddr_aton(addr, peer)) { 345 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid " 346 "address '%s'", addr); 347 return -1; 348 } 349 350 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR, 351 MAC2STR(peer)); 352 353 return ibss_rsn_start(wpa_s->ibss_rsn, peer); 354 } 355 #endif /* CONFIG_IBSS_RSN */ 356 357 358 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 359 char *rsp) 360 { 361 #ifdef IEEE8021X_EAPOL 362 char *pos, *id_pos; 363 int id; 364 struct wpa_ssid *ssid; 365 struct eap_peer_config *eap; 366 367 pos = os_strchr(rsp, '-'); 368 if (pos == NULL) 369 return -1; 370 *pos++ = '\0'; 371 id_pos = pos; 372 pos = os_strchr(pos, ':'); 373 if (pos == NULL) 374 return -1; 375 *pos++ = '\0'; 376 id = atoi(id_pos); 377 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 378 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 379 (u8 *) pos, os_strlen(pos)); 380 381 ssid = wpa_config_get_network(wpa_s->conf, id); 382 if (ssid == NULL) { 383 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 384 "to update", id); 385 return -1; 386 } 387 eap = &ssid->eap; 388 389 if (os_strcmp(rsp, "IDENTITY") == 0) { 390 os_free(eap->identity); 391 eap->identity = (u8 *) os_strdup(pos); 392 eap->identity_len = os_strlen(pos); 393 eap->pending_req_identity = 0; 394 if (ssid == wpa_s->current_ssid) 395 wpa_s->reassociate = 1; 396 } else if (os_strcmp(rsp, "PASSWORD") == 0) { 397 os_free(eap->password); 398 eap->password = (u8 *) os_strdup(pos); 399 eap->password_len = os_strlen(pos); 400 eap->pending_req_password = 0; 401 if (ssid == wpa_s->current_ssid) 402 wpa_s->reassociate = 1; 403 } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) { 404 os_free(eap->new_password); 405 eap->new_password = (u8 *) os_strdup(pos); 406 eap->new_password_len = os_strlen(pos); 407 eap->pending_req_new_password = 0; 408 if (ssid == wpa_s->current_ssid) 409 wpa_s->reassociate = 1; 410 } else if (os_strcmp(rsp, "PIN") == 0) { 411 os_free(eap->pin); 412 eap->pin = os_strdup(pos); 413 eap->pending_req_pin = 0; 414 if (ssid == wpa_s->current_ssid) 415 wpa_s->reassociate = 1; 416 } else if (os_strcmp(rsp, "OTP") == 0) { 417 os_free(eap->otp); 418 eap->otp = (u8 *) os_strdup(pos); 419 eap->otp_len = os_strlen(pos); 420 os_free(eap->pending_req_otp); 421 eap->pending_req_otp = NULL; 422 eap->pending_req_otp_len = 0; 423 } else if (os_strcmp(rsp, "PASSPHRASE") == 0) { 424 os_free(eap->private_key_passwd); 425 eap->private_key_passwd = (u8 *) os_strdup(pos); 426 eap->pending_req_passphrase = 0; 427 if (ssid == wpa_s->current_ssid) 428 wpa_s->reassociate = 1; 429 } else { 430 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp); 431 return -1; 432 } 433 434 return 0; 435 #else /* IEEE8021X_EAPOL */ 436 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 437 return -1; 438 #endif /* IEEE8021X_EAPOL */ 439 } 440 441 442 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 443 const char *params, 444 char *buf, size_t buflen) 445 { 446 char *pos, *end, tmp[30]; 447 int res, verbose, ret; 448 449 verbose = os_strcmp(params, "-VERBOSE") == 0; 450 pos = buf; 451 end = buf + buflen; 452 if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 453 struct wpa_ssid *ssid = wpa_s->current_ssid; 454 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 455 MAC2STR(wpa_s->bssid)); 456 if (ret < 0 || ret >= end - pos) 457 return pos - buf; 458 pos += ret; 459 if (ssid) { 460 u8 *_ssid = ssid->ssid; 461 size_t ssid_len = ssid->ssid_len; 462 u8 ssid_buf[MAX_SSID_LEN]; 463 if (ssid_len == 0) { 464 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 465 if (_res < 0) 466 ssid_len = 0; 467 else 468 ssid_len = _res; 469 _ssid = ssid_buf; 470 } 471 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 472 wpa_ssid_txt(_ssid, ssid_len), 473 ssid->id); 474 if (ret < 0 || ret >= end - pos) 475 return pos - buf; 476 pos += ret; 477 478 if (ssid->id_str) { 479 ret = os_snprintf(pos, end - pos, 480 "id_str=%s\n", 481 ssid->id_str); 482 if (ret < 0 || ret >= end - pos) 483 return pos - buf; 484 pos += ret; 485 } 486 487 switch (ssid->mode) { 488 case WPAS_MODE_INFRA: 489 ret = os_snprintf(pos, end - pos, 490 "mode=station\n"); 491 break; 492 case WPAS_MODE_IBSS: 493 ret = os_snprintf(pos, end - pos, 494 "mode=IBSS\n"); 495 break; 496 case WPAS_MODE_AP: 497 ret = os_snprintf(pos, end - pos, 498 "mode=AP\n"); 499 break; 500 default: 501 ret = 0; 502 break; 503 } 504 if (ret < 0 || ret >= end - pos) 505 return pos - buf; 506 pos += ret; 507 } 508 509 #ifdef CONFIG_AP 510 if (wpa_s->ap_iface) { 511 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, 512 end - pos, 513 verbose); 514 } else 515 #endif /* CONFIG_AP */ 516 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 517 } 518 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 519 wpa_supplicant_state_txt(wpa_s->wpa_state)); 520 if (ret < 0 || ret >= end - pos) 521 return pos - buf; 522 pos += ret; 523 524 if (wpa_s->l2 && 525 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 526 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 527 if (ret < 0 || ret >= end - pos) 528 return pos - buf; 529 pos += ret; 530 } 531 532 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 533 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 534 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 535 verbose); 536 if (res >= 0) 537 pos += res; 538 } 539 540 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 541 if (res >= 0) 542 pos += res; 543 544 return pos - buf; 545 } 546 547 548 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 549 char *cmd) 550 { 551 char *pos; 552 int id; 553 struct wpa_ssid *ssid; 554 u8 bssid[ETH_ALEN]; 555 556 /* cmd: "<network id> <BSSID>" */ 557 pos = os_strchr(cmd, ' '); 558 if (pos == NULL) 559 return -1; 560 *pos++ = '\0'; 561 id = atoi(cmd); 562 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 563 if (hwaddr_aton(pos, bssid)) { 564 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 565 return -1; 566 } 567 568 ssid = wpa_config_get_network(wpa_s->conf, id); 569 if (ssid == NULL) { 570 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 571 "to update", id); 572 return -1; 573 } 574 575 os_memcpy(ssid->bssid, bssid, ETH_ALEN); 576 ssid->bssid_set = !is_zero_ether_addr(bssid); 577 578 return 0; 579 } 580 581 582 static int wpa_supplicant_ctrl_iface_list_networks( 583 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 584 { 585 char *pos, *end; 586 struct wpa_ssid *ssid; 587 int ret; 588 589 pos = buf; 590 end = buf + buflen; 591 ret = os_snprintf(pos, end - pos, 592 "network id / ssid / bssid / flags\n"); 593 if (ret < 0 || ret >= end - pos) 594 return pos - buf; 595 pos += ret; 596 597 ssid = wpa_s->conf->ssid; 598 while (ssid) { 599 ret = os_snprintf(pos, end - pos, "%d\t%s", 600 ssid->id, 601 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 602 if (ret < 0 || ret >= end - pos) 603 return pos - buf; 604 pos += ret; 605 if (ssid->bssid_set) { 606 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 607 MAC2STR(ssid->bssid)); 608 } else { 609 ret = os_snprintf(pos, end - pos, "\tany"); 610 } 611 if (ret < 0 || ret >= end - pos) 612 return pos - buf; 613 pos += ret; 614 ret = os_snprintf(pos, end - pos, "\t%s%s", 615 ssid == wpa_s->current_ssid ? 616 "[CURRENT]" : "", 617 ssid->disabled ? "[DISABLED]" : ""); 618 if (ret < 0 || ret >= end - pos) 619 return pos - buf; 620 pos += ret; 621 ret = os_snprintf(pos, end - pos, "\n"); 622 if (ret < 0 || ret >= end - pos) 623 return pos - buf; 624 pos += ret; 625 626 ssid = ssid->next; 627 } 628 629 return pos - buf; 630 } 631 632 633 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 634 { 635 int first = 1, ret; 636 ret = os_snprintf(pos, end - pos, "-"); 637 if (ret < 0 || ret >= end - pos) 638 return pos; 639 pos += ret; 640 if (cipher & WPA_CIPHER_NONE) { 641 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+"); 642 if (ret < 0 || ret >= end - pos) 643 return pos; 644 pos += ret; 645 first = 0; 646 } 647 if (cipher & WPA_CIPHER_WEP40) { 648 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+"); 649 if (ret < 0 || ret >= end - pos) 650 return pos; 651 pos += ret; 652 first = 0; 653 } 654 if (cipher & WPA_CIPHER_WEP104) { 655 ret = os_snprintf(pos, end - pos, "%sWEP104", 656 first ? "" : "+"); 657 if (ret < 0 || ret >= end - pos) 658 return pos; 659 pos += ret; 660 first = 0; 661 } 662 if (cipher & WPA_CIPHER_TKIP) { 663 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+"); 664 if (ret < 0 || ret >= end - pos) 665 return pos; 666 pos += ret; 667 first = 0; 668 } 669 if (cipher & WPA_CIPHER_CCMP) { 670 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+"); 671 if (ret < 0 || ret >= end - pos) 672 return pos; 673 pos += ret; 674 first = 0; 675 } 676 return pos; 677 } 678 679 680 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 681 const u8 *ie, size_t ie_len) 682 { 683 struct wpa_ie_data data; 684 int first, ret; 685 686 ret = os_snprintf(pos, end - pos, "[%s-", proto); 687 if (ret < 0 || ret >= end - pos) 688 return pos; 689 pos += ret; 690 691 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 692 ret = os_snprintf(pos, end - pos, "?]"); 693 if (ret < 0 || ret >= end - pos) 694 return pos; 695 pos += ret; 696 return pos; 697 } 698 699 first = 1; 700 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 701 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+"); 702 if (ret < 0 || ret >= end - pos) 703 return pos; 704 pos += ret; 705 first = 0; 706 } 707 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 708 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+"); 709 if (ret < 0 || ret >= end - pos) 710 return pos; 711 pos += ret; 712 first = 0; 713 } 714 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 715 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+"); 716 if (ret < 0 || ret >= end - pos) 717 return pos; 718 pos += ret; 719 first = 0; 720 } 721 #ifdef CONFIG_IEEE80211R 722 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 723 ret = os_snprintf(pos, end - pos, "%sFT/EAP", 724 first ? "" : "+"); 725 if (ret < 0 || ret >= end - pos) 726 return pos; 727 pos += ret; 728 first = 0; 729 } 730 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) { 731 ret = os_snprintf(pos, end - pos, "%sFT/PSK", 732 first ? "" : "+"); 733 if (ret < 0 || ret >= end - pos) 734 return pos; 735 pos += ret; 736 first = 0; 737 } 738 #endif /* CONFIG_IEEE80211R */ 739 #ifdef CONFIG_IEEE80211W 740 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 741 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", 742 first ? "" : "+"); 743 if (ret < 0 || ret >= end - pos) 744 return pos; 745 pos += ret; 746 first = 0; 747 } 748 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 749 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", 750 first ? "" : "+"); 751 if (ret < 0 || ret >= end - pos) 752 return pos; 753 pos += ret; 754 first = 0; 755 } 756 #endif /* CONFIG_IEEE80211W */ 757 758 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 759 760 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 761 ret = os_snprintf(pos, end - pos, "-preauth"); 762 if (ret < 0 || ret >= end - pos) 763 return pos; 764 pos += ret; 765 } 766 767 ret = os_snprintf(pos, end - pos, "]"); 768 if (ret < 0 || ret >= end - pos) 769 return pos; 770 pos += ret; 771 772 return pos; 773 } 774 775 776 #ifdef CONFIG_WPS 777 static char * wpa_supplicant_wps_ie_txt_buf(char *pos, char *end, 778 struct wpabuf *wps_ie) 779 { 780 int ret; 781 const char *txt; 782 783 if (wps_ie == NULL) 784 return pos; 785 if (wps_is_selected_pbc_registrar(wps_ie)) 786 txt = "[WPS-PBC]"; 787 else if (wps_is_selected_pin_registrar(wps_ie)) 788 txt = "[WPS-PIN]"; 789 else 790 txt = "[WPS]"; 791 792 ret = os_snprintf(pos, end - pos, "%s", txt); 793 if (ret >= 0 && ret < end - pos) 794 pos += ret; 795 wpabuf_free(wps_ie); 796 return pos; 797 } 798 #endif /* CONFIG_WPS */ 799 800 801 static char * wpa_supplicant_wps_ie_txt(char *pos, char *end, 802 const struct wpa_bss *bss) 803 { 804 #ifdef CONFIG_WPS 805 struct wpabuf *wps_ie; 806 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 807 return wpa_supplicant_wps_ie_txt_buf(pos, end, wps_ie); 808 #else /* CONFIG_WPS */ 809 return pos; 810 #endif /* CONFIG_WPS */ 811 } 812 813 814 /* Format one result on one text line into a buffer. */ 815 static int wpa_supplicant_ctrl_iface_scan_result( 816 const struct wpa_bss *bss, char *buf, size_t buflen) 817 { 818 char *pos, *end; 819 int ret; 820 const u8 *ie, *ie2; 821 822 pos = buf; 823 end = buf + buflen; 824 825 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 826 MAC2STR(bss->bssid), bss->freq, bss->level); 827 if (ret < 0 || ret >= end - pos) 828 return pos - buf; 829 pos += ret; 830 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 831 if (ie) 832 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 833 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 834 if (ie2) 835 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 836 pos = wpa_supplicant_wps_ie_txt(pos, end, bss); 837 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 838 ret = os_snprintf(pos, end - pos, "[WEP]"); 839 if (ret < 0 || ret >= end - pos) 840 return pos - buf; 841 pos += ret; 842 } 843 if (bss->caps & IEEE80211_CAP_IBSS) { 844 ret = os_snprintf(pos, end - pos, "[IBSS]"); 845 if (ret < 0 || ret >= end - pos) 846 return pos - buf; 847 pos += ret; 848 } 849 if (bss->caps & IEEE80211_CAP_ESS) { 850 ret = os_snprintf(pos, end - pos, "[ESS]"); 851 if (ret < 0 || ret >= end - pos) 852 return pos - buf; 853 pos += ret; 854 } 855 856 ret = os_snprintf(pos, end - pos, "\t%s", 857 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 858 if (ret < 0 || ret >= end - pos) 859 return pos - buf; 860 pos += ret; 861 862 ret = os_snprintf(pos, end - pos, "\n"); 863 if (ret < 0 || ret >= end - pos) 864 return pos - buf; 865 pos += ret; 866 867 return pos - buf; 868 } 869 870 871 static int wpa_supplicant_ctrl_iface_scan_results( 872 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 873 { 874 char *pos, *end; 875 struct wpa_bss *bss; 876 int ret; 877 878 pos = buf; 879 end = buf + buflen; 880 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 881 "flags / ssid\n"); 882 if (ret < 0 || ret >= end - pos) 883 return pos - buf; 884 pos += ret; 885 886 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 887 ret = wpa_supplicant_ctrl_iface_scan_result(bss, pos, 888 end - pos); 889 if (ret < 0 || ret >= end - pos) 890 return pos - buf; 891 pos += ret; 892 } 893 894 return pos - buf; 895 } 896 897 898 static int wpa_supplicant_ctrl_iface_select_network( 899 struct wpa_supplicant *wpa_s, char *cmd) 900 { 901 int id; 902 struct wpa_ssid *ssid; 903 904 /* cmd: "<network id>" or "any" */ 905 if (os_strcmp(cmd, "any") == 0) { 906 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 907 ssid = NULL; 908 } else { 909 id = atoi(cmd); 910 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 911 912 ssid = wpa_config_get_network(wpa_s->conf, id); 913 if (ssid == NULL) { 914 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 915 "network id=%d", id); 916 return -1; 917 } 918 } 919 920 wpa_supplicant_select_network(wpa_s, ssid); 921 922 return 0; 923 } 924 925 926 static int wpa_supplicant_ctrl_iface_enable_network( 927 struct wpa_supplicant *wpa_s, char *cmd) 928 { 929 int id; 930 struct wpa_ssid *ssid; 931 932 /* cmd: "<network id>" or "all" */ 933 if (os_strcmp(cmd, "all") == 0) { 934 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 935 ssid = NULL; 936 } else { 937 id = atoi(cmd); 938 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 939 940 ssid = wpa_config_get_network(wpa_s->conf, id); 941 if (ssid == NULL) { 942 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 943 "network id=%d", id); 944 return -1; 945 } 946 } 947 wpa_supplicant_enable_network(wpa_s, ssid); 948 949 return 0; 950 } 951 952 953 static int wpa_supplicant_ctrl_iface_disable_network( 954 struct wpa_supplicant *wpa_s, char *cmd) 955 { 956 int id; 957 struct wpa_ssid *ssid; 958 959 /* cmd: "<network id>" or "all" */ 960 if (os_strcmp(cmd, "all") == 0) { 961 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 962 ssid = NULL; 963 } else { 964 id = atoi(cmd); 965 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 966 967 ssid = wpa_config_get_network(wpa_s->conf, id); 968 if (ssid == NULL) { 969 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 970 "network id=%d", id); 971 return -1; 972 } 973 } 974 wpa_supplicant_disable_network(wpa_s, ssid); 975 976 return 0; 977 } 978 979 980 static int wpa_supplicant_ctrl_iface_add_network( 981 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 982 { 983 struct wpa_ssid *ssid; 984 int ret; 985 986 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 987 988 ssid = wpa_config_add_network(wpa_s->conf); 989 if (ssid == NULL) 990 return -1; 991 992 wpas_notify_network_added(wpa_s, ssid); 993 994 ssid->disabled = 1; 995 wpa_config_set_network_defaults(ssid); 996 997 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 998 if (ret < 0 || (size_t) ret >= buflen) 999 return -1; 1000 return ret; 1001 } 1002 1003 1004 static int wpa_supplicant_ctrl_iface_remove_network( 1005 struct wpa_supplicant *wpa_s, char *cmd) 1006 { 1007 int id; 1008 struct wpa_ssid *ssid; 1009 1010 /* cmd: "<network id>" or "all" */ 1011 if (os_strcmp(cmd, "all") == 0) { 1012 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 1013 ssid = wpa_s->conf->ssid; 1014 while (ssid) { 1015 struct wpa_ssid *remove_ssid = ssid; 1016 id = ssid->id; 1017 ssid = ssid->next; 1018 wpas_notify_network_removed(wpa_s, remove_ssid); 1019 wpa_config_remove_network(wpa_s->conf, id); 1020 } 1021 if (wpa_s->current_ssid) { 1022 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1023 wpa_supplicant_disassociate(wpa_s, 1024 WLAN_REASON_DEAUTH_LEAVING); 1025 } 1026 return 0; 1027 } 1028 1029 id = atoi(cmd); 1030 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 1031 1032 ssid = wpa_config_get_network(wpa_s->conf, id); 1033 if (ssid == NULL || 1034 wpa_config_remove_network(wpa_s->conf, id) < 0) { 1035 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1036 "id=%d", id); 1037 return -1; 1038 } 1039 1040 if (ssid == wpa_s->current_ssid) { 1041 /* 1042 * Invalidate the EAP session cache if the current network is 1043 * removed. 1044 */ 1045 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1046 1047 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 1048 } 1049 1050 return 0; 1051 } 1052 1053 1054 static int wpa_supplicant_ctrl_iface_set_network( 1055 struct wpa_supplicant *wpa_s, char *cmd) 1056 { 1057 int id; 1058 struct wpa_ssid *ssid; 1059 char *name, *value; 1060 1061 /* cmd: "<network id> <variable name> <value>" */ 1062 name = os_strchr(cmd, ' '); 1063 if (name == NULL) 1064 return -1; 1065 *name++ = '\0'; 1066 1067 value = os_strchr(name, ' '); 1068 if (value == NULL) 1069 return -1; 1070 *value++ = '\0'; 1071 1072 id = atoi(cmd); 1073 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 1074 id, name); 1075 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 1076 (u8 *) value, os_strlen(value)); 1077 1078 ssid = wpa_config_get_network(wpa_s->conf, id); 1079 if (ssid == NULL) { 1080 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1081 "id=%d", id); 1082 return -1; 1083 } 1084 1085 if (wpa_config_set(ssid, name, value, 0) < 0) { 1086 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 1087 "variable '%s'", name); 1088 return -1; 1089 } 1090 1091 if (wpa_s->current_ssid == ssid) { 1092 /* 1093 * Invalidate the EAP session cache if anything in the current 1094 * configuration changes. 1095 */ 1096 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1097 } 1098 1099 if ((os_strcmp(name, "psk") == 0 && 1100 value[0] == '"' && ssid->ssid_len) || 1101 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 1102 wpa_config_update_psk(ssid); 1103 else if (os_strcmp(name, "priority") == 0) 1104 wpa_config_update_prio_list(wpa_s->conf); 1105 1106 return 0; 1107 } 1108 1109 1110 static int wpa_supplicant_ctrl_iface_get_network( 1111 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 1112 { 1113 int id; 1114 size_t res; 1115 struct wpa_ssid *ssid; 1116 char *name, *value; 1117 1118 /* cmd: "<network id> <variable name>" */ 1119 name = os_strchr(cmd, ' '); 1120 if (name == NULL || buflen == 0) 1121 return -1; 1122 *name++ = '\0'; 1123 1124 id = atoi(cmd); 1125 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 1126 id, name); 1127 1128 ssid = wpa_config_get_network(wpa_s->conf, id); 1129 if (ssid == NULL) { 1130 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1131 "id=%d", id); 1132 return -1; 1133 } 1134 1135 value = wpa_config_get_no_key(ssid, name); 1136 if (value == NULL) { 1137 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 1138 "variable '%s'", name); 1139 return -1; 1140 } 1141 1142 res = os_strlcpy(buf, value, buflen); 1143 if (res >= buflen) { 1144 os_free(value); 1145 return -1; 1146 } 1147 1148 os_free(value); 1149 1150 return res; 1151 } 1152 1153 1154 #ifndef CONFIG_NO_CONFIG_WRITE 1155 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 1156 { 1157 int ret; 1158 1159 if (!wpa_s->conf->update_config) { 1160 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 1161 "to update configuration (update_config=0)"); 1162 return -1; 1163 } 1164 1165 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 1166 if (ret) { 1167 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 1168 "update configuration"); 1169 } else { 1170 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 1171 " updated"); 1172 } 1173 1174 return ret; 1175 } 1176 #endif /* CONFIG_NO_CONFIG_WRITE */ 1177 1178 1179 static int ctrl_iface_get_capability_pairwise(int res, char *strict, 1180 struct wpa_driver_capa *capa, 1181 char *buf, size_t buflen) 1182 { 1183 int ret, first = 1; 1184 char *pos, *end; 1185 size_t len; 1186 1187 pos = buf; 1188 end = pos + buflen; 1189 1190 if (res < 0) { 1191 if (strict) 1192 return 0; 1193 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 1194 if (len >= buflen) 1195 return -1; 1196 return len; 1197 } 1198 1199 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 1200 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 1201 if (ret < 0 || ret >= end - pos) 1202 return pos - buf; 1203 pos += ret; 1204 first = 0; 1205 } 1206 1207 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 1208 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 1209 if (ret < 0 || ret >= end - pos) 1210 return pos - buf; 1211 pos += ret; 1212 first = 0; 1213 } 1214 1215 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 1216 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " "); 1217 if (ret < 0 || ret >= end - pos) 1218 return pos - buf; 1219 pos += ret; 1220 first = 0; 1221 } 1222 1223 return pos - buf; 1224 } 1225 1226 1227 static int ctrl_iface_get_capability_group(int res, char *strict, 1228 struct wpa_driver_capa *capa, 1229 char *buf, size_t buflen) 1230 { 1231 int ret, first = 1; 1232 char *pos, *end; 1233 size_t len; 1234 1235 pos = buf; 1236 end = pos + buflen; 1237 1238 if (res < 0) { 1239 if (strict) 1240 return 0; 1241 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 1242 if (len >= buflen) 1243 return -1; 1244 return len; 1245 } 1246 1247 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 1248 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 1249 if (ret < 0 || ret >= end - pos) 1250 return pos - buf; 1251 pos += ret; 1252 first = 0; 1253 } 1254 1255 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 1256 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 1257 if (ret < 0 || ret >= end - pos) 1258 return pos - buf; 1259 pos += ret; 1260 first = 0; 1261 } 1262 1263 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) { 1264 ret = os_snprintf(pos, end - pos, "%sWEP104", 1265 first ? "" : " "); 1266 if (ret < 0 || ret >= end - pos) 1267 return pos - buf; 1268 pos += ret; 1269 first = 0; 1270 } 1271 1272 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) { 1273 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " "); 1274 if (ret < 0 || ret >= end - pos) 1275 return pos - buf; 1276 pos += ret; 1277 first = 0; 1278 } 1279 1280 return pos - buf; 1281 } 1282 1283 1284 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, 1285 struct wpa_driver_capa *capa, 1286 char *buf, size_t buflen) 1287 { 1288 int ret; 1289 char *pos, *end; 1290 size_t len; 1291 1292 pos = buf; 1293 end = pos + buflen; 1294 1295 if (res < 0) { 1296 if (strict) 1297 return 0; 1298 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 1299 "NONE", buflen); 1300 if (len >= buflen) 1301 return -1; 1302 return len; 1303 } 1304 1305 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 1306 if (ret < 0 || ret >= end - pos) 1307 return pos - buf; 1308 pos += ret; 1309 1310 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1311 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 1312 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 1313 if (ret < 0 || ret >= end - pos) 1314 return pos - buf; 1315 pos += ret; 1316 } 1317 1318 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 1319 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 1320 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 1321 if (ret < 0 || ret >= end - pos) 1322 return pos - buf; 1323 pos += ret; 1324 } 1325 1326 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 1327 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 1328 if (ret < 0 || ret >= end - pos) 1329 return pos - buf; 1330 pos += ret; 1331 } 1332 1333 return pos - buf; 1334 } 1335 1336 1337 static int ctrl_iface_get_capability_proto(int res, char *strict, 1338 struct wpa_driver_capa *capa, 1339 char *buf, size_t buflen) 1340 { 1341 int ret, first = 1; 1342 char *pos, *end; 1343 size_t len; 1344 1345 pos = buf; 1346 end = pos + buflen; 1347 1348 if (res < 0) { 1349 if (strict) 1350 return 0; 1351 len = os_strlcpy(buf, "RSN WPA", buflen); 1352 if (len >= buflen) 1353 return -1; 1354 return len; 1355 } 1356 1357 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 1358 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 1359 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); 1360 if (ret < 0 || ret >= end - pos) 1361 return pos - buf; 1362 pos += ret; 1363 first = 0; 1364 } 1365 1366 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1367 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 1368 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); 1369 if (ret < 0 || ret >= end - pos) 1370 return pos - buf; 1371 pos += ret; 1372 first = 0; 1373 } 1374 1375 return pos - buf; 1376 } 1377 1378 1379 static int ctrl_iface_get_capability_auth_alg(int res, char *strict, 1380 struct wpa_driver_capa *capa, 1381 char *buf, size_t buflen) 1382 { 1383 int ret, first = 1; 1384 char *pos, *end; 1385 size_t len; 1386 1387 pos = buf; 1388 end = pos + buflen; 1389 1390 if (res < 0) { 1391 if (strict) 1392 return 0; 1393 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 1394 if (len >= buflen) 1395 return -1; 1396 return len; 1397 } 1398 1399 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 1400 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " "); 1401 if (ret < 0 || ret >= end - pos) 1402 return pos - buf; 1403 pos += ret; 1404 first = 0; 1405 } 1406 1407 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 1408 ret = os_snprintf(pos, end - pos, "%sSHARED", 1409 first ? "" : " "); 1410 if (ret < 0 || ret >= end - pos) 1411 return pos - buf; 1412 pos += ret; 1413 first = 0; 1414 } 1415 1416 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 1417 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " "); 1418 if (ret < 0 || ret >= end - pos) 1419 return pos - buf; 1420 pos += ret; 1421 first = 0; 1422 } 1423 1424 return pos - buf; 1425 } 1426 1427 1428 static int wpa_supplicant_ctrl_iface_get_capability( 1429 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 1430 size_t buflen) 1431 { 1432 struct wpa_driver_capa capa; 1433 int res; 1434 char *strict; 1435 char field[30]; 1436 size_t len; 1437 1438 /* Determine whether or not strict checking was requested */ 1439 len = os_strlcpy(field, _field, sizeof(field)); 1440 if (len >= sizeof(field)) 1441 return -1; 1442 strict = os_strchr(field, ' '); 1443 if (strict != NULL) { 1444 *strict++ = '\0'; 1445 if (os_strcmp(strict, "strict") != 0) 1446 return -1; 1447 } 1448 1449 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", 1450 field, strict ? strict : ""); 1451 1452 if (os_strcmp(field, "eap") == 0) { 1453 return eap_get_names(buf, buflen); 1454 } 1455 1456 res = wpa_drv_get_capa(wpa_s, &capa); 1457 1458 if (os_strcmp(field, "pairwise") == 0) 1459 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 1460 buf, buflen); 1461 1462 if (os_strcmp(field, "group") == 0) 1463 return ctrl_iface_get_capability_group(res, strict, &capa, 1464 buf, buflen); 1465 1466 if (os_strcmp(field, "key_mgmt") == 0) 1467 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 1468 buf, buflen); 1469 1470 if (os_strcmp(field, "proto") == 0) 1471 return ctrl_iface_get_capability_proto(res, strict, &capa, 1472 buf, buflen); 1473 1474 if (os_strcmp(field, "auth_alg") == 0) 1475 return ctrl_iface_get_capability_auth_alg(res, strict, &capa, 1476 buf, buflen); 1477 1478 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 1479 field); 1480 1481 return -1; 1482 } 1483 1484 1485 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 1486 const char *cmd, char *buf, 1487 size_t buflen) 1488 { 1489 u8 bssid[ETH_ALEN]; 1490 size_t i; 1491 struct wpa_bss *bss; 1492 int ret; 1493 char *pos, *end; 1494 const u8 *ie, *ie2; 1495 1496 if (os_strcmp(cmd, "FIRST") == 0) 1497 bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list); 1498 else if (os_strncmp(cmd, "ID-", 3) == 0) { 1499 i = atoi(cmd + 3); 1500 bss = wpa_bss_get_id(wpa_s, i); 1501 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 1502 i = atoi(cmd + 5); 1503 bss = wpa_bss_get_id(wpa_s, i); 1504 if (bss) { 1505 struct dl_list *next = bss->list_id.next; 1506 if (next == &wpa_s->bss_id) 1507 bss = NULL; 1508 else 1509 bss = dl_list_entry(next, struct wpa_bss, 1510 list_id); 1511 } 1512 } else if (hwaddr_aton(cmd, bssid) == 0) 1513 bss = wpa_bss_get_bssid(wpa_s, bssid); 1514 else { 1515 struct wpa_bss *tmp; 1516 i = atoi(cmd); 1517 bss = NULL; 1518 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) 1519 { 1520 if (i-- == 0) { 1521 bss = tmp; 1522 break; 1523 } 1524 } 1525 } 1526 1527 if (bss == NULL) 1528 return 0; 1529 1530 pos = buf; 1531 end = buf + buflen; 1532 ret = os_snprintf(pos, end - pos, 1533 "id=%u\n" 1534 "bssid=" MACSTR "\n" 1535 "freq=%d\n" 1536 "beacon_int=%d\n" 1537 "capabilities=0x%04x\n" 1538 "qual=%d\n" 1539 "noise=%d\n" 1540 "level=%d\n" 1541 "tsf=%016llu\n" 1542 "ie=", 1543 bss->id, 1544 MAC2STR(bss->bssid), bss->freq, bss->beacon_int, 1545 bss->caps, bss->qual, bss->noise, bss->level, 1546 (unsigned long long) bss->tsf); 1547 if (ret < 0 || ret >= end - pos) 1548 return pos - buf; 1549 pos += ret; 1550 1551 ie = (const u8 *) (bss + 1); 1552 for (i = 0; i < bss->ie_len; i++) { 1553 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 1554 if (ret < 0 || ret >= end - pos) 1555 return pos - buf; 1556 pos += ret; 1557 } 1558 1559 ret = os_snprintf(pos, end - pos, "\n"); 1560 if (ret < 0 || ret >= end - pos) 1561 return pos - buf; 1562 pos += ret; 1563 1564 ret = os_snprintf(pos, end - pos, "flags="); 1565 if (ret < 0 || ret >= end - pos) 1566 return pos - buf; 1567 pos += ret; 1568 1569 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 1570 if (ie) 1571 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 1572 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 1573 if (ie2) 1574 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 1575 pos = wpa_supplicant_wps_ie_txt(pos, end, bss); 1576 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 1577 ret = os_snprintf(pos, end - pos, "[WEP]"); 1578 if (ret < 0 || ret >= end - pos) 1579 return pos - buf; 1580 pos += ret; 1581 } 1582 if (bss->caps & IEEE80211_CAP_IBSS) { 1583 ret = os_snprintf(pos, end - pos, "[IBSS]"); 1584 if (ret < 0 || ret >= end - pos) 1585 return pos - buf; 1586 pos += ret; 1587 } 1588 if (bss->caps & IEEE80211_CAP_ESS) { 1589 ret = os_snprintf(pos, end - pos, "[ESS]"); 1590 if (ret < 0 || ret >= end - pos) 1591 return pos - buf; 1592 pos += ret; 1593 } 1594 1595 ret = os_snprintf(pos, end - pos, "\n"); 1596 if (ret < 0 || ret >= end - pos) 1597 return pos - buf; 1598 pos += ret; 1599 1600 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 1601 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 1602 if (ret < 0 || ret >= end - pos) 1603 return pos - buf; 1604 pos += ret; 1605 1606 #ifdef CONFIG_WPS 1607 ie = (const u8 *) (bss + 1); 1608 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); 1609 if (ret < 0 || ret >= end - pos) 1610 return pos - buf; 1611 pos += ret; 1612 #endif /* CONFIG_WPS */ 1613 1614 return pos - buf; 1615 } 1616 1617 1618 static int wpa_supplicant_ctrl_iface_ap_scan( 1619 struct wpa_supplicant *wpa_s, char *cmd) 1620 { 1621 int ap_scan = atoi(cmd); 1622 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan); 1623 } 1624 1625 1626 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) 1627 { 1628 u8 *bcast = (u8 *) "\xff\xff\xff\xff\xff\xff"; 1629 1630 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication"); 1631 /* MLME-DELETEKEYS.request */ 1632 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 0, 0, NULL, 0, NULL, 0); 1633 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 1, 0, NULL, 0, NULL, 0); 1634 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 2, 0, NULL, 0, NULL, 0); 1635 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 3, 0, NULL, 0, NULL, 0); 1636 #ifdef CONFIG_IEEE80211W 1637 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 4, 0, NULL, 0, NULL, 0); 1638 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 5, 0, NULL, 0, NULL, 0); 1639 #endif /* CONFIG_IEEE80211W */ 1640 1641 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 1642 0); 1643 /* MLME-SETPROTECTION.request(None) */ 1644 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, 1645 MLME_SETPROTECTION_PROTECT_TYPE_NONE, 1646 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 1647 wpa_sm_drop_sa(wpa_s->wpa); 1648 } 1649 1650 1651 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, 1652 char *addr) 1653 { 1654 u8 bssid[ETH_ALEN]; 1655 struct wpa_bss *bss; 1656 struct wpa_ssid *ssid = wpa_s->current_ssid; 1657 1658 if (hwaddr_aton(addr, bssid)) { 1659 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " 1660 "address '%s'", addr); 1661 return -1; 1662 } 1663 1664 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); 1665 1666 bss = wpa_bss_get_bssid(wpa_s, bssid); 1667 if (!bss) { 1668 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " 1669 "from BSS table"); 1670 return -1; 1671 } 1672 1673 /* 1674 * TODO: Find best network configuration block from configuration to 1675 * allow roaming to other networks 1676 */ 1677 1678 if (!ssid) { 1679 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " 1680 "configuration known for the target AP"); 1681 return -1; 1682 } 1683 1684 wpa_s->reassociate = 1; 1685 wpa_supplicant_connect(wpa_s, bss, ssid); 1686 1687 return 0; 1688 } 1689 1690 1691 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 1692 char *buf, size_t *resp_len) 1693 { 1694 char *reply; 1695 const int reply_size = 2048; 1696 int ctrl_rsp = 0; 1697 int reply_len; 1698 1699 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 1700 os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 1701 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 1702 (const u8 *) buf, os_strlen(buf)); 1703 } else { 1704 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", 1705 (const u8 *) buf, os_strlen(buf)); 1706 } 1707 1708 reply = os_malloc(reply_size); 1709 if (reply == NULL) { 1710 *resp_len = 1; 1711 return NULL; 1712 } 1713 1714 os_memcpy(reply, "OK\n", 3); 1715 reply_len = 3; 1716 1717 if (os_strcmp(buf, "PING") == 0) { 1718 os_memcpy(reply, "PONG\n", 5); 1719 reply_len = 5; 1720 } else if (os_strcmp(buf, "MIB") == 0) { 1721 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 1722 if (reply_len >= 0) { 1723 int res; 1724 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, 1725 reply_size - reply_len); 1726 if (res < 0) 1727 reply_len = -1; 1728 else 1729 reply_len += res; 1730 } 1731 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 1732 reply_len = wpa_supplicant_ctrl_iface_status( 1733 wpa_s, buf + 6, reply, reply_size); 1734 } else if (os_strcmp(buf, "PMKSA") == 0) { 1735 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply, 1736 reply_size); 1737 } else if (os_strncmp(buf, "SET ", 4) == 0) { 1738 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 1739 reply_len = -1; 1740 } else if (os_strcmp(buf, "LOGON") == 0) { 1741 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 1742 } else if (os_strcmp(buf, "LOGOFF") == 0) { 1743 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 1744 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 1745 wpa_s->disconnected = 0; 1746 wpa_s->reassociate = 1; 1747 wpa_supplicant_req_scan(wpa_s, 0, 0); 1748 } else if (os_strcmp(buf, "RECONNECT") == 0) { 1749 if (wpa_s->disconnected) { 1750 wpa_s->disconnected = 0; 1751 wpa_s->reassociate = 1; 1752 wpa_supplicant_req_scan(wpa_s, 0, 0); 1753 } 1754 #ifdef IEEE8021X_EAPOL 1755 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 1756 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 1757 reply_len = -1; 1758 #endif /* IEEE8021X_EAPOL */ 1759 #ifdef CONFIG_PEERKEY 1760 } else if (os_strncmp(buf, "STKSTART ", 9) == 0) { 1761 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9)) 1762 reply_len = -1; 1763 #endif /* CONFIG_PEERKEY */ 1764 #ifdef CONFIG_IEEE80211R 1765 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 1766 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 1767 reply_len = -1; 1768 #endif /* CONFIG_IEEE80211R */ 1769 #ifdef CONFIG_WPS 1770 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 1771 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL)) 1772 reply_len = -1; 1773 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 1774 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8)) 1775 reply_len = -1; 1776 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 1777 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 1778 reply, 1779 reply_size); 1780 #ifdef CONFIG_WPS_OOB 1781 } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) { 1782 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8)) 1783 reply_len = -1; 1784 #endif /* CONFIG_WPS_OOB */ 1785 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 1786 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 1787 reply_len = -1; 1788 #ifdef CONFIG_WPS_ER 1789 } else if (os_strcmp(buf, "WPS_ER_START") == 0) { 1790 if (wpas_wps_er_start(wpa_s)) 1791 reply_len = -1; 1792 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) { 1793 if (wpas_wps_er_stop(wpa_s)) 1794 reply_len = -1; 1795 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) { 1796 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11)) 1797 reply_len = -1; 1798 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) { 1799 if (wpas_wps_er_pbc(wpa_s, buf + 11)) 1800 reply_len = -1; 1801 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { 1802 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) 1803 reply_len = -1; 1804 #endif /* CONFIG_WPS_ER */ 1805 #endif /* CONFIG_WPS */ 1806 #ifdef CONFIG_IBSS_RSN 1807 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) { 1808 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9)) 1809 reply_len = -1; 1810 #endif /* CONFIG_IBSS_RSN */ 1811 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 1812 { 1813 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 1814 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 1815 reply_len = -1; 1816 else 1817 ctrl_rsp = 1; 1818 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 1819 if (wpa_supplicant_reload_configuration(wpa_s)) 1820 reply_len = -1; 1821 } else if (os_strcmp(buf, "TERMINATE") == 0) { 1822 wpa_supplicant_terminate_proc(wpa_s->global); 1823 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 1824 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 1825 reply_len = -1; 1826 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 1827 reply_len = wpa_supplicant_ctrl_iface_list_networks( 1828 wpa_s, reply, reply_size); 1829 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 1830 wpa_s->reassociate = 0; 1831 wpa_s->disconnected = 1; 1832 wpa_supplicant_deauthenticate(wpa_s, 1833 WLAN_REASON_DEAUTH_LEAVING); 1834 } else if (os_strcmp(buf, "SCAN") == 0) { 1835 wpa_s->scan_req = 2; 1836 wpa_supplicant_req_scan(wpa_s, 0, 0); 1837 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 1838 reply_len = wpa_supplicant_ctrl_iface_scan_results( 1839 wpa_s, reply, reply_size); 1840 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 1841 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 1842 reply_len = -1; 1843 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 1844 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 1845 reply_len = -1; 1846 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 1847 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 1848 reply_len = -1; 1849 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 1850 reply_len = wpa_supplicant_ctrl_iface_add_network( 1851 wpa_s, reply, reply_size); 1852 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 1853 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 1854 reply_len = -1; 1855 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 1856 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 1857 reply_len = -1; 1858 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 1859 reply_len = wpa_supplicant_ctrl_iface_get_network( 1860 wpa_s, buf + 12, reply, reply_size); 1861 #ifndef CONFIG_NO_CONFIG_WRITE 1862 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 1863 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 1864 reply_len = -1; 1865 #endif /* CONFIG_NO_CONFIG_WRITE */ 1866 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 1867 reply_len = wpa_supplicant_ctrl_iface_get_capability( 1868 wpa_s, buf + 15, reply, reply_size); 1869 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 1870 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 1871 reply_len = -1; 1872 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 1873 reply_len = wpa_supplicant_global_iface_list( 1874 wpa_s->global, reply, reply_size); 1875 } else if (os_strcmp(buf, "INTERFACES") == 0) { 1876 reply_len = wpa_supplicant_global_iface_interfaces( 1877 wpa_s->global, reply, reply_size); 1878 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 1879 reply_len = wpa_supplicant_ctrl_iface_bss( 1880 wpa_s, buf + 4, reply, reply_size); 1881 #ifdef CONFIG_AP 1882 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 1883 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); 1884 } else if (os_strncmp(buf, "STA ", 4) == 0) { 1885 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply, 1886 reply_size); 1887 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 1888 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, 1889 reply_size); 1890 #endif /* CONFIG_AP */ 1891 } else if (os_strcmp(buf, "SUSPEND") == 0) { 1892 wpas_notify_suspend(wpa_s->global); 1893 } else if (os_strcmp(buf, "RESUME") == 0) { 1894 wpas_notify_resume(wpa_s->global); 1895 } else if (os_strcmp(buf, "DROP_SA") == 0) { 1896 wpa_supplicant_ctrl_iface_drop_sa(wpa_s); 1897 } else if (os_strncmp(buf, "ROAM ", 5) == 0) { 1898 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) 1899 reply_len = -1; 1900 } else { 1901 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 1902 reply_len = 16; 1903 } 1904 1905 if (reply_len < 0) { 1906 os_memcpy(reply, "FAIL\n", 5); 1907 reply_len = 5; 1908 } 1909 1910 if (ctrl_rsp) 1911 eapol_sm_notify_ctrl_response(wpa_s->eapol); 1912 1913 *resp_len = reply_len; 1914 return reply; 1915 } 1916 1917 1918 static int wpa_supplicant_global_iface_add(struct wpa_global *global, 1919 char *cmd) 1920 { 1921 struct wpa_interface iface; 1922 char *pos; 1923 1924 /* 1925 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 1926 * TAB<bridge_ifname> 1927 */ 1928 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 1929 1930 os_memset(&iface, 0, sizeof(iface)); 1931 1932 do { 1933 iface.ifname = pos = cmd; 1934 pos = os_strchr(pos, '\t'); 1935 if (pos) 1936 *pos++ = '\0'; 1937 if (iface.ifname[0] == '\0') 1938 return -1; 1939 if (pos == NULL) 1940 break; 1941 1942 iface.confname = pos; 1943 pos = os_strchr(pos, '\t'); 1944 if (pos) 1945 *pos++ = '\0'; 1946 if (iface.confname[0] == '\0') 1947 iface.confname = NULL; 1948 if (pos == NULL) 1949 break; 1950 1951 iface.driver = pos; 1952 pos = os_strchr(pos, '\t'); 1953 if (pos) 1954 *pos++ = '\0'; 1955 if (iface.driver[0] == '\0') 1956 iface.driver = NULL; 1957 if (pos == NULL) 1958 break; 1959 1960 iface.ctrl_interface = pos; 1961 pos = os_strchr(pos, '\t'); 1962 if (pos) 1963 *pos++ = '\0'; 1964 if (iface.ctrl_interface[0] == '\0') 1965 iface.ctrl_interface = NULL; 1966 if (pos == NULL) 1967 break; 1968 1969 iface.driver_param = pos; 1970 pos = os_strchr(pos, '\t'); 1971 if (pos) 1972 *pos++ = '\0'; 1973 if (iface.driver_param[0] == '\0') 1974 iface.driver_param = NULL; 1975 if (pos == NULL) 1976 break; 1977 1978 iface.bridge_ifname = pos; 1979 pos = os_strchr(pos, '\t'); 1980 if (pos) 1981 *pos++ = '\0'; 1982 if (iface.bridge_ifname[0] == '\0') 1983 iface.bridge_ifname = NULL; 1984 if (pos == NULL) 1985 break; 1986 } while (0); 1987 1988 if (wpa_supplicant_get_iface(global, iface.ifname)) 1989 return -1; 1990 1991 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1; 1992 } 1993 1994 1995 static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 1996 char *cmd) 1997 { 1998 struct wpa_supplicant *wpa_s; 1999 2000 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 2001 2002 wpa_s = wpa_supplicant_get_iface(global, cmd); 2003 if (wpa_s == NULL) 2004 return -1; 2005 return wpa_supplicant_remove_iface(global, wpa_s); 2006 } 2007 2008 2009 static void wpa_free_iface_info(struct wpa_interface_info *iface) 2010 { 2011 struct wpa_interface_info *prev; 2012 2013 while (iface) { 2014 prev = iface; 2015 iface = iface->next; 2016 2017 os_free(prev->ifname); 2018 os_free(prev->desc); 2019 os_free(prev); 2020 } 2021 } 2022 2023 2024 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 2025 char *buf, int len) 2026 { 2027 int i, res; 2028 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 2029 char *pos, *end; 2030 2031 for (i = 0; wpa_drivers[i]; i++) { 2032 struct wpa_driver_ops *drv = wpa_drivers[i]; 2033 if (drv->get_interfaces == NULL) 2034 continue; 2035 tmp = drv->get_interfaces(global->drv_priv[i]); 2036 if (tmp == NULL) 2037 continue; 2038 2039 if (last == NULL) 2040 iface = last = tmp; 2041 else 2042 last->next = tmp; 2043 while (last->next) 2044 last = last->next; 2045 } 2046 2047 pos = buf; 2048 end = buf + len; 2049 for (tmp = iface; tmp; tmp = tmp->next) { 2050 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 2051 tmp->drv_name, tmp->ifname, 2052 tmp->desc ? tmp->desc : ""); 2053 if (res < 0 || res >= end - pos) { 2054 *pos = '\0'; 2055 break; 2056 } 2057 pos += res; 2058 } 2059 2060 wpa_free_iface_info(iface); 2061 2062 return pos - buf; 2063 } 2064 2065 2066 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 2067 char *buf, int len) 2068 { 2069 int res; 2070 char *pos, *end; 2071 struct wpa_supplicant *wpa_s; 2072 2073 wpa_s = global->ifaces; 2074 pos = buf; 2075 end = buf + len; 2076 2077 while (wpa_s) { 2078 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname); 2079 if (res < 0 || res >= end - pos) { 2080 *pos = '\0'; 2081 break; 2082 } 2083 pos += res; 2084 wpa_s = wpa_s->next; 2085 } 2086 return pos - buf; 2087 } 2088 2089 2090 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 2091 char *buf, size_t *resp_len) 2092 { 2093 char *reply; 2094 const int reply_size = 2048; 2095 int reply_len; 2096 2097 wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", 2098 (const u8 *) buf, os_strlen(buf)); 2099 2100 reply = os_malloc(reply_size); 2101 if (reply == NULL) { 2102 *resp_len = 1; 2103 return NULL; 2104 } 2105 2106 os_memcpy(reply, "OK\n", 3); 2107 reply_len = 3; 2108 2109 if (os_strcmp(buf, "PING") == 0) { 2110 os_memcpy(reply, "PONG\n", 5); 2111 reply_len = 5; 2112 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 2113 if (wpa_supplicant_global_iface_add(global, buf + 14)) 2114 reply_len = -1; 2115 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 2116 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 2117 reply_len = -1; 2118 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 2119 reply_len = wpa_supplicant_global_iface_list( 2120 global, reply, reply_size); 2121 } else if (os_strcmp(buf, "INTERFACES") == 0) { 2122 reply_len = wpa_supplicant_global_iface_interfaces( 2123 global, reply, reply_size); 2124 } else if (os_strcmp(buf, "TERMINATE") == 0) { 2125 wpa_supplicant_terminate_proc(global); 2126 } else if (os_strcmp(buf, "SUSPEND") == 0) { 2127 wpas_notify_suspend(global); 2128 } else if (os_strcmp(buf, "RESUME") == 0) { 2129 wpas_notify_resume(global); 2130 } else { 2131 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 2132 reply_len = 16; 2133 } 2134 2135 if (reply_len < 0) { 2136 os_memcpy(reply, "FAIL\n", 5); 2137 reply_len = 5; 2138 } 2139 2140 *resp_len = reply_len; 2141 return reply; 2142 } 2143