$search
00001 /* 00002 * WPA Supplicant / Control interface (shared code for all backends) 00003 * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "utils/includes.h" 00016 00017 #include "utils/common.h" 00018 #include "utils/eloop.h" 00019 #include "common/ieee802_11_defs.h" 00020 #include "common/wpa_ctrl.h" 00021 #include "eap_peer/eap.h" 00022 #include "eapol_supp/eapol_supp_sm.h" 00023 #include "rsn_supp/wpa.h" 00024 #include "rsn_supp/preauth.h" 00025 #include "rsn_supp/pmksa_cache.h" 00026 #include "l2_packet/l2_packet.h" 00027 #include "wps/wps.h" 00028 #include "config.h" 00029 #include "wpa_supplicant_i.h" 00030 #include "driver_i.h" 00031 #include "wps_supplicant.h" 00032 #include "ibss_rsn.h" 00033 #include "ap.h" 00034 #include "notify.h" 00035 #include "bss.h" 00036 #include "scan.h" 00037 #include "ctrl_iface.h" 00038 00039 extern struct wpa_driver_ops *wpa_drivers[]; 00040 00041 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 00042 char *buf, int len); 00043 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 00044 char *buf, int len); 00045 00046 00047 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 00048 char *cmd) 00049 { 00050 char *value; 00051 int ret = 0; 00052 00053 value = os_strchr(cmd, ' '); 00054 if (value == NULL) 00055 return -1; 00056 *value++ = '\0'; 00057 00058 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 00059 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 00060 eapol_sm_configure(wpa_s->eapol, 00061 atoi(value), -1, -1, -1); 00062 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 00063 eapol_sm_configure(wpa_s->eapol, 00064 -1, atoi(value), -1, -1); 00065 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 00066 eapol_sm_configure(wpa_s->eapol, 00067 -1, -1, atoi(value), -1); 00068 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 00069 eapol_sm_configure(wpa_s->eapol, 00070 -1, -1, -1, atoi(value)); 00071 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 00072 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 00073 atoi(value))) 00074 ret = -1; 00075 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 00076 0) { 00077 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 00078 atoi(value))) 00079 ret = -1; 00080 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 00081 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) 00082 ret = -1; 00083 } else 00084 ret = -1; 00085 00086 return ret; 00087 } 00088 00089 00090 #ifdef IEEE8021X_EAPOL 00091 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 00092 char *addr) 00093 { 00094 u8 bssid[ETH_ALEN]; 00095 struct wpa_ssid *ssid = wpa_s->current_ssid; 00096 00097 if (hwaddr_aton(addr, bssid)) { 00098 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 00099 "'%s'", addr); 00100 return -1; 00101 } 00102 00103 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 00104 rsn_preauth_deinit(wpa_s->wpa); 00105 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL)) 00106 return -1; 00107 00108 return 0; 00109 } 00110 #endif /* IEEE8021X_EAPOL */ 00111 00112 00113 #ifdef CONFIG_PEERKEY 00114 /* MLME-STKSTART.request(peer) */ 00115 static int wpa_supplicant_ctrl_iface_stkstart( 00116 struct wpa_supplicant *wpa_s, char *addr) 00117 { 00118 u8 peer[ETH_ALEN]; 00119 00120 if (hwaddr_aton(addr, peer)) { 00121 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid " 00122 "address '%s'", addr); 00123 return -1; 00124 } 00125 00126 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR, 00127 MAC2STR(peer)); 00128 00129 return wpa_sm_stkstart(wpa_s->wpa, peer); 00130 } 00131 #endif /* CONFIG_PEERKEY */ 00132 00133 00134 #ifdef CONFIG_IEEE80211R 00135 static int wpa_supplicant_ctrl_iface_ft_ds( 00136 struct wpa_supplicant *wpa_s, char *addr) 00137 { 00138 u8 target_ap[ETH_ALEN]; 00139 struct wpa_bss *bss; 00140 const u8 *mdie; 00141 00142 if (hwaddr_aton(addr, target_ap)) { 00143 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 00144 "address '%s'", addr); 00145 return -1; 00146 } 00147 00148 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); 00149 00150 bss = wpa_bss_get_bssid(wpa_s, target_ap); 00151 if (bss) 00152 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 00153 else 00154 mdie = NULL; 00155 00156 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie); 00157 } 00158 #endif /* CONFIG_IEEE80211R */ 00159 00160 00161 #ifdef CONFIG_WPS 00162 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, 00163 char *cmd) 00164 { 00165 u8 bssid[ETH_ALEN], *_bssid = bssid; 00166 00167 if (cmd == NULL || os_strcmp(cmd, "any") == 0) 00168 _bssid = NULL; 00169 else if (hwaddr_aton(cmd, bssid)) { 00170 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", 00171 cmd); 00172 return -1; 00173 } 00174 00175 #ifdef CONFIG_AP 00176 if (wpa_s->ap_iface) 00177 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid); 00178 #endif /* CONFIG_AP */ 00179 00180 return wpas_wps_start_pbc(wpa_s, _bssid); 00181 } 00182 00183 00184 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, 00185 char *cmd, char *buf, 00186 size_t buflen) 00187 { 00188 u8 bssid[ETH_ALEN], *_bssid = bssid; 00189 char *pin; 00190 int ret; 00191 00192 pin = os_strchr(cmd, ' '); 00193 if (pin) 00194 *pin++ = '\0'; 00195 00196 if (os_strcmp(cmd, "any") == 0) 00197 _bssid = NULL; 00198 else if (hwaddr_aton(cmd, bssid)) { 00199 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'", 00200 cmd); 00201 return -1; 00202 } 00203 00204 #ifdef CONFIG_AP 00205 if (wpa_s->ap_iface) 00206 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin, 00207 buf, buflen); 00208 #endif /* CONFIG_AP */ 00209 00210 if (pin) { 00211 ret = wpas_wps_start_pin(wpa_s, _bssid, pin); 00212 if (ret < 0) 00213 return -1; 00214 ret = os_snprintf(buf, buflen, "%s", pin); 00215 if (ret < 0 || (size_t) ret >= buflen) 00216 return -1; 00217 return ret; 00218 } 00219 00220 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL); 00221 if (ret < 0) 00222 return -1; 00223 00224 /* Return the generated PIN */ 00225 ret = os_snprintf(buf, buflen, "%08d", ret); 00226 if (ret < 0 || (size_t) ret >= buflen) 00227 return -1; 00228 return ret; 00229 } 00230 00231 00232 #ifdef CONFIG_WPS_OOB 00233 static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s, 00234 char *cmd) 00235 { 00236 char *path, *method, *name; 00237 00238 path = os_strchr(cmd, ' '); 00239 if (path == NULL) 00240 return -1; 00241 *path++ = '\0'; 00242 00243 method = os_strchr(path, ' '); 00244 if (method == NULL) 00245 return -1; 00246 *method++ = '\0'; 00247 00248 name = os_strchr(method, ' '); 00249 if (name != NULL) 00250 *name++ = '\0'; 00251 00252 return wpas_wps_start_oob(wpa_s, cmd, path, method, name); 00253 } 00254 #endif /* CONFIG_WPS_OOB */ 00255 00256 00257 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s, 00258 char *cmd) 00259 { 00260 u8 bssid[ETH_ALEN], *_bssid = bssid; 00261 char *pin; 00262 char *new_ssid; 00263 char *new_auth; 00264 char *new_encr; 00265 char *new_key; 00266 struct wps_new_ap_settings ap; 00267 00268 pin = os_strchr(cmd, ' '); 00269 if (pin == NULL) 00270 return -1; 00271 *pin++ = '\0'; 00272 00273 if (os_strcmp(cmd, "any") == 0) 00274 _bssid = NULL; 00275 else if (hwaddr_aton(cmd, bssid)) { 00276 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'", 00277 cmd); 00278 return -1; 00279 } 00280 00281 new_ssid = os_strchr(pin, ' '); 00282 if (new_ssid == NULL) 00283 return wpas_wps_start_reg(wpa_s, _bssid, pin, NULL); 00284 *new_ssid++ = '\0'; 00285 00286 new_auth = os_strchr(new_ssid, ' '); 00287 if (new_auth == NULL) 00288 return -1; 00289 *new_auth++ = '\0'; 00290 00291 new_encr = os_strchr(new_auth, ' '); 00292 if (new_encr == NULL) 00293 return -1; 00294 *new_encr++ = '\0'; 00295 00296 new_key = os_strchr(new_encr, ' '); 00297 if (new_key == NULL) 00298 return -1; 00299 *new_key++ = '\0'; 00300 00301 os_memset(&ap, 0, sizeof(ap)); 00302 ap.ssid_hex = new_ssid; 00303 ap.auth = new_auth; 00304 ap.encr = new_encr; 00305 ap.key_hex = new_key; 00306 return wpas_wps_start_reg(wpa_s, _bssid, pin, &ap); 00307 } 00308 00309 00310 #ifdef CONFIG_WPS_ER 00311 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s, 00312 char *cmd) 00313 { 00314 char *uuid = cmd, *pin; 00315 pin = os_strchr(uuid, ' '); 00316 if (pin == NULL) 00317 return -1; 00318 *pin++ = '\0'; 00319 return wpas_wps_er_add_pin(wpa_s, uuid, pin); 00320 } 00321 00322 00323 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s, 00324 char *cmd) 00325 { 00326 char *uuid = cmd, *pin; 00327 pin = os_strchr(uuid, ' '); 00328 if (pin == NULL) 00329 return -1; 00330 *pin++ = '\0'; 00331 return wpas_wps_er_learn(wpa_s, uuid, pin); 00332 } 00333 #endif /* CONFIG_WPS_ER */ 00334 00335 #endif /* CONFIG_WPS */ 00336 00337 00338 #ifdef CONFIG_IBSS_RSN 00339 static int wpa_supplicant_ctrl_iface_ibss_rsn( 00340 struct wpa_supplicant *wpa_s, char *addr) 00341 { 00342 u8 peer[ETH_ALEN]; 00343 00344 if (hwaddr_aton(addr, peer)) { 00345 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid " 00346 "address '%s'", addr); 00347 return -1; 00348 } 00349 00350 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR, 00351 MAC2STR(peer)); 00352 00353 return ibss_rsn_start(wpa_s->ibss_rsn, peer); 00354 } 00355 #endif /* CONFIG_IBSS_RSN */ 00356 00357 00358 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 00359 char *rsp) 00360 { 00361 #ifdef IEEE8021X_EAPOL 00362 char *pos, *id_pos; 00363 int id; 00364 struct wpa_ssid *ssid; 00365 struct eap_peer_config *eap; 00366 00367 pos = os_strchr(rsp, '-'); 00368 if (pos == NULL) 00369 return -1; 00370 *pos++ = '\0'; 00371 id_pos = pos; 00372 pos = os_strchr(pos, ':'); 00373 if (pos == NULL) 00374 return -1; 00375 *pos++ = '\0'; 00376 id = atoi(id_pos); 00377 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 00378 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 00379 (u8 *) pos, os_strlen(pos)); 00380 00381 ssid = wpa_config_get_network(wpa_s->conf, id); 00382 if (ssid == NULL) { 00383 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 00384 "to update", id); 00385 return -1; 00386 } 00387 eap = &ssid->eap; 00388 00389 if (os_strcmp(rsp, "IDENTITY") == 0) { 00390 os_free(eap->identity); 00391 eap->identity = (u8 *) os_strdup(pos); 00392 eap->identity_len = os_strlen(pos); 00393 eap->pending_req_identity = 0; 00394 if (ssid == wpa_s->current_ssid) 00395 wpa_s->reassociate = 1; 00396 } else if (os_strcmp(rsp, "PASSWORD") == 0) { 00397 os_free(eap->password); 00398 eap->password = (u8 *) os_strdup(pos); 00399 eap->password_len = os_strlen(pos); 00400 eap->pending_req_password = 0; 00401 if (ssid == wpa_s->current_ssid) 00402 wpa_s->reassociate = 1; 00403 } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) { 00404 os_free(eap->new_password); 00405 eap->new_password = (u8 *) os_strdup(pos); 00406 eap->new_password_len = os_strlen(pos); 00407 eap->pending_req_new_password = 0; 00408 if (ssid == wpa_s->current_ssid) 00409 wpa_s->reassociate = 1; 00410 } else if (os_strcmp(rsp, "PIN") == 0) { 00411 os_free(eap->pin); 00412 eap->pin = os_strdup(pos); 00413 eap->pending_req_pin = 0; 00414 if (ssid == wpa_s->current_ssid) 00415 wpa_s->reassociate = 1; 00416 } else if (os_strcmp(rsp, "OTP") == 0) { 00417 os_free(eap->otp); 00418 eap->otp = (u8 *) os_strdup(pos); 00419 eap->otp_len = os_strlen(pos); 00420 os_free(eap->pending_req_otp); 00421 eap->pending_req_otp = NULL; 00422 eap->pending_req_otp_len = 0; 00423 } else if (os_strcmp(rsp, "PASSPHRASE") == 0) { 00424 os_free(eap->private_key_passwd); 00425 eap->private_key_passwd = (u8 *) os_strdup(pos); 00426 eap->pending_req_passphrase = 0; 00427 if (ssid == wpa_s->current_ssid) 00428 wpa_s->reassociate = 1; 00429 } else { 00430 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp); 00431 return -1; 00432 } 00433 00434 return 0; 00435 #else /* IEEE8021X_EAPOL */ 00436 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 00437 return -1; 00438 #endif /* IEEE8021X_EAPOL */ 00439 } 00440 00441 00442 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 00443 const char *params, 00444 char *buf, size_t buflen) 00445 { 00446 char *pos, *end, tmp[30]; 00447 int res, verbose, ret; 00448 00449 verbose = os_strcmp(params, "-VERBOSE") == 0; 00450 pos = buf; 00451 end = buf + buflen; 00452 if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 00453 struct wpa_ssid *ssid = wpa_s->current_ssid; 00454 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 00455 MAC2STR(wpa_s->bssid)); 00456 if (ret < 0 || ret >= end - pos) 00457 return pos - buf; 00458 pos += ret; 00459 if (ssid) { 00460 u8 *_ssid = ssid->ssid; 00461 size_t ssid_len = ssid->ssid_len; 00462 u8 ssid_buf[MAX_SSID_LEN]; 00463 if (ssid_len == 0) { 00464 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 00465 if (_res < 0) 00466 ssid_len = 0; 00467 else 00468 ssid_len = _res; 00469 _ssid = ssid_buf; 00470 } 00471 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 00472 wpa_ssid_txt(_ssid, ssid_len), 00473 ssid->id); 00474 if (ret < 0 || ret >= end - pos) 00475 return pos - buf; 00476 pos += ret; 00477 00478 if (ssid->id_str) { 00479 ret = os_snprintf(pos, end - pos, 00480 "id_str=%s\n", 00481 ssid->id_str); 00482 if (ret < 0 || ret >= end - pos) 00483 return pos - buf; 00484 pos += ret; 00485 } 00486 00487 switch (ssid->mode) { 00488 case WPAS_MODE_INFRA: 00489 ret = os_snprintf(pos, end - pos, 00490 "mode=station\n"); 00491 break; 00492 case WPAS_MODE_IBSS: 00493 ret = os_snprintf(pos, end - pos, 00494 "mode=IBSS\n"); 00495 break; 00496 case WPAS_MODE_AP: 00497 ret = os_snprintf(pos, end - pos, 00498 "mode=AP\n"); 00499 break; 00500 default: 00501 ret = 0; 00502 break; 00503 } 00504 if (ret < 0 || ret >= end - pos) 00505 return pos - buf; 00506 pos += ret; 00507 } 00508 00509 #ifdef CONFIG_AP 00510 if (wpa_s->ap_iface) { 00511 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, 00512 end - pos, 00513 verbose); 00514 } else 00515 #endif /* CONFIG_AP */ 00516 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 00517 } 00518 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 00519 wpa_supplicant_state_txt(wpa_s->wpa_state)); 00520 if (ret < 0 || ret >= end - pos) 00521 return pos - buf; 00522 pos += ret; 00523 00524 if (wpa_s->l2 && 00525 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 00526 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 00527 if (ret < 0 || ret >= end - pos) 00528 return pos - buf; 00529 pos += ret; 00530 } 00531 00532 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 00533 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 00534 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 00535 verbose); 00536 if (res >= 0) 00537 pos += res; 00538 } 00539 00540 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 00541 if (res >= 0) 00542 pos += res; 00543 00544 return pos - buf; 00545 } 00546 00547 00548 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 00549 char *cmd) 00550 { 00551 char *pos; 00552 int id; 00553 struct wpa_ssid *ssid; 00554 u8 bssid[ETH_ALEN]; 00555 00556 /* cmd: "<network id> <BSSID>" */ 00557 pos = os_strchr(cmd, ' '); 00558 if (pos == NULL) 00559 return -1; 00560 *pos++ = '\0'; 00561 id = atoi(cmd); 00562 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 00563 if (hwaddr_aton(pos, bssid)) { 00564 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 00565 return -1; 00566 } 00567 00568 ssid = wpa_config_get_network(wpa_s->conf, id); 00569 if (ssid == NULL) { 00570 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 00571 "to update", id); 00572 return -1; 00573 } 00574 00575 os_memcpy(ssid->bssid, bssid, ETH_ALEN); 00576 ssid->bssid_set = !is_zero_ether_addr(bssid); 00577 00578 return 0; 00579 } 00580 00581 00582 static int wpa_supplicant_ctrl_iface_list_networks( 00583 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 00584 { 00585 char *pos, *end; 00586 struct wpa_ssid *ssid; 00587 int ret; 00588 00589 pos = buf; 00590 end = buf + buflen; 00591 ret = os_snprintf(pos, end - pos, 00592 "network id / ssid / bssid / flags\n"); 00593 if (ret < 0 || ret >= end - pos) 00594 return pos - buf; 00595 pos += ret; 00596 00597 ssid = wpa_s->conf->ssid; 00598 while (ssid) { 00599 ret = os_snprintf(pos, end - pos, "%d\t%s", 00600 ssid->id, 00601 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 00602 if (ret < 0 || ret >= end - pos) 00603 return pos - buf; 00604 pos += ret; 00605 if (ssid->bssid_set) { 00606 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 00607 MAC2STR(ssid->bssid)); 00608 } else { 00609 ret = os_snprintf(pos, end - pos, "\tany"); 00610 } 00611 if (ret < 0 || ret >= end - pos) 00612 return pos - buf; 00613 pos += ret; 00614 ret = os_snprintf(pos, end - pos, "\t%s%s", 00615 ssid == wpa_s->current_ssid ? 00616 "[CURRENT]" : "", 00617 ssid->disabled ? "[DISABLED]" : ""); 00618 if (ret < 0 || ret >= end - pos) 00619 return pos - buf; 00620 pos += ret; 00621 ret = os_snprintf(pos, end - pos, "\n"); 00622 if (ret < 0 || ret >= end - pos) 00623 return pos - buf; 00624 pos += ret; 00625 00626 ssid = ssid->next; 00627 } 00628 00629 return pos - buf; 00630 } 00631 00632 00633 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 00634 { 00635 int first = 1, ret; 00636 ret = os_snprintf(pos, end - pos, "-"); 00637 if (ret < 0 || ret >= end - pos) 00638 return pos; 00639 pos += ret; 00640 if (cipher & WPA_CIPHER_NONE) { 00641 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+"); 00642 if (ret < 0 || ret >= end - pos) 00643 return pos; 00644 pos += ret; 00645 first = 0; 00646 } 00647 if (cipher & WPA_CIPHER_WEP40) { 00648 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+"); 00649 if (ret < 0 || ret >= end - pos) 00650 return pos; 00651 pos += ret; 00652 first = 0; 00653 } 00654 if (cipher & WPA_CIPHER_WEP104) { 00655 ret = os_snprintf(pos, end - pos, "%sWEP104", 00656 first ? "" : "+"); 00657 if (ret < 0 || ret >= end - pos) 00658 return pos; 00659 pos += ret; 00660 first = 0; 00661 } 00662 if (cipher & WPA_CIPHER_TKIP) { 00663 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+"); 00664 if (ret < 0 || ret >= end - pos) 00665 return pos; 00666 pos += ret; 00667 first = 0; 00668 } 00669 if (cipher & WPA_CIPHER_CCMP) { 00670 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+"); 00671 if (ret < 0 || ret >= end - pos) 00672 return pos; 00673 pos += ret; 00674 first = 0; 00675 } 00676 return pos; 00677 } 00678 00679 00680 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 00681 const u8 *ie, size_t ie_len) 00682 { 00683 struct wpa_ie_data data; 00684 int first, ret; 00685 00686 ret = os_snprintf(pos, end - pos, "[%s-", proto); 00687 if (ret < 0 || ret >= end - pos) 00688 return pos; 00689 pos += ret; 00690 00691 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 00692 ret = os_snprintf(pos, end - pos, "?]"); 00693 if (ret < 0 || ret >= end - pos) 00694 return pos; 00695 pos += ret; 00696 return pos; 00697 } 00698 00699 first = 1; 00700 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 00701 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+"); 00702 if (ret < 0 || ret >= end - pos) 00703 return pos; 00704 pos += ret; 00705 first = 0; 00706 } 00707 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 00708 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+"); 00709 if (ret < 0 || ret >= end - pos) 00710 return pos; 00711 pos += ret; 00712 first = 0; 00713 } 00714 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 00715 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+"); 00716 if (ret < 0 || ret >= end - pos) 00717 return pos; 00718 pos += ret; 00719 first = 0; 00720 } 00721 #ifdef CONFIG_IEEE80211R 00722 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 00723 ret = os_snprintf(pos, end - pos, "%sFT/EAP", 00724 first ? "" : "+"); 00725 if (ret < 0 || ret >= end - pos) 00726 return pos; 00727 pos += ret; 00728 first = 0; 00729 } 00730 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) { 00731 ret = os_snprintf(pos, end - pos, "%sFT/PSK", 00732 first ? "" : "+"); 00733 if (ret < 0 || ret >= end - pos) 00734 return pos; 00735 pos += ret; 00736 first = 0; 00737 } 00738 #endif /* CONFIG_IEEE80211R */ 00739 #ifdef CONFIG_IEEE80211W 00740 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 00741 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", 00742 first ? "" : "+"); 00743 if (ret < 0 || ret >= end - pos) 00744 return pos; 00745 pos += ret; 00746 first = 0; 00747 } 00748 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 00749 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", 00750 first ? "" : "+"); 00751 if (ret < 0 || ret >= end - pos) 00752 return pos; 00753 pos += ret; 00754 first = 0; 00755 } 00756 #endif /* CONFIG_IEEE80211W */ 00757 00758 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 00759 00760 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 00761 ret = os_snprintf(pos, end - pos, "-preauth"); 00762 if (ret < 0 || ret >= end - pos) 00763 return pos; 00764 pos += ret; 00765 } 00766 00767 ret = os_snprintf(pos, end - pos, "]"); 00768 if (ret < 0 || ret >= end - pos) 00769 return pos; 00770 pos += ret; 00771 00772 return pos; 00773 } 00774 00775 00776 #ifdef CONFIG_WPS 00777 static char * wpa_supplicant_wps_ie_txt_buf(char *pos, char *end, 00778 struct wpabuf *wps_ie) 00779 { 00780 int ret; 00781 const char *txt; 00782 00783 if (wps_ie == NULL) 00784 return pos; 00785 if (wps_is_selected_pbc_registrar(wps_ie)) 00786 txt = "[WPS-PBC]"; 00787 else if (wps_is_selected_pin_registrar(wps_ie)) 00788 txt = "[WPS-PIN]"; 00789 else 00790 txt = "[WPS]"; 00791 00792 ret = os_snprintf(pos, end - pos, "%s", txt); 00793 if (ret >= 0 && ret < end - pos) 00794 pos += ret; 00795 wpabuf_free(wps_ie); 00796 return pos; 00797 } 00798 #endif /* CONFIG_WPS */ 00799 00800 00801 static char * wpa_supplicant_wps_ie_txt(char *pos, char *end, 00802 const struct wpa_bss *bss) 00803 { 00804 #ifdef CONFIG_WPS 00805 struct wpabuf *wps_ie; 00806 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 00807 return wpa_supplicant_wps_ie_txt_buf(pos, end, wps_ie); 00808 #else /* CONFIG_WPS */ 00809 return pos; 00810 #endif /* CONFIG_WPS */ 00811 } 00812 00813 00814 /* Format one result on one text line into a buffer. */ 00815 static int wpa_supplicant_ctrl_iface_scan_result( 00816 const struct wpa_bss *bss, char *buf, size_t buflen) 00817 { 00818 char *pos, *end; 00819 int ret; 00820 const u8 *ie, *ie2; 00821 00822 pos = buf; 00823 end = buf + buflen; 00824 00825 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 00826 MAC2STR(bss->bssid), bss->freq, bss->level); 00827 if (ret < 0 || ret >= end - pos) 00828 return pos - buf; 00829 pos += ret; 00830 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 00831 if (ie) 00832 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 00833 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 00834 if (ie2) 00835 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 00836 pos = wpa_supplicant_wps_ie_txt(pos, end, bss); 00837 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 00838 ret = os_snprintf(pos, end - pos, "[WEP]"); 00839 if (ret < 0 || ret >= end - pos) 00840 return pos - buf; 00841 pos += ret; 00842 } 00843 if (bss->caps & IEEE80211_CAP_IBSS) { 00844 ret = os_snprintf(pos, end - pos, "[IBSS]"); 00845 if (ret < 0 || ret >= end - pos) 00846 return pos - buf; 00847 pos += ret; 00848 } 00849 if (bss->caps & IEEE80211_CAP_ESS) { 00850 ret = os_snprintf(pos, end - pos, "[ESS]"); 00851 if (ret < 0 || ret >= end - pos) 00852 return pos - buf; 00853 pos += ret; 00854 } 00855 00856 ret = os_snprintf(pos, end - pos, "\t%s", 00857 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 00858 if (ret < 0 || ret >= end - pos) 00859 return pos - buf; 00860 pos += ret; 00861 00862 ret = os_snprintf(pos, end - pos, "\n"); 00863 if (ret < 0 || ret >= end - pos) 00864 return pos - buf; 00865 pos += ret; 00866 00867 return pos - buf; 00868 } 00869 00870 00871 static int wpa_supplicant_ctrl_iface_scan_results( 00872 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 00873 { 00874 char *pos, *end; 00875 struct wpa_bss *bss; 00876 int ret; 00877 00878 pos = buf; 00879 end = buf + buflen; 00880 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 00881 "flags / ssid\n"); 00882 if (ret < 0 || ret >= end - pos) 00883 return pos - buf; 00884 pos += ret; 00885 00886 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 00887 ret = wpa_supplicant_ctrl_iface_scan_result(bss, pos, 00888 end - pos); 00889 if (ret < 0 || ret >= end - pos) 00890 return pos - buf; 00891 pos += ret; 00892 } 00893 00894 return pos - buf; 00895 } 00896 00897 00898 static int wpa_supplicant_ctrl_iface_select_network( 00899 struct wpa_supplicant *wpa_s, char *cmd) 00900 { 00901 int id; 00902 struct wpa_ssid *ssid; 00903 00904 /* cmd: "<network id>" or "any" */ 00905 if (os_strcmp(cmd, "any") == 0) { 00906 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 00907 ssid = NULL; 00908 } else { 00909 id = atoi(cmd); 00910 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 00911 00912 ssid = wpa_config_get_network(wpa_s->conf, id); 00913 if (ssid == NULL) { 00914 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 00915 "network id=%d", id); 00916 return -1; 00917 } 00918 } 00919 00920 wpa_supplicant_select_network(wpa_s, ssid); 00921 00922 return 0; 00923 } 00924 00925 00926 static int wpa_supplicant_ctrl_iface_enable_network( 00927 struct wpa_supplicant *wpa_s, char *cmd) 00928 { 00929 int id; 00930 struct wpa_ssid *ssid; 00931 00932 /* cmd: "<network id>" or "all" */ 00933 if (os_strcmp(cmd, "all") == 0) { 00934 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 00935 ssid = NULL; 00936 } else { 00937 id = atoi(cmd); 00938 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 00939 00940 ssid = wpa_config_get_network(wpa_s->conf, id); 00941 if (ssid == NULL) { 00942 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 00943 "network id=%d", id); 00944 return -1; 00945 } 00946 } 00947 wpa_supplicant_enable_network(wpa_s, ssid); 00948 00949 return 0; 00950 } 00951 00952 00953 static int wpa_supplicant_ctrl_iface_disable_network( 00954 struct wpa_supplicant *wpa_s, char *cmd) 00955 { 00956 int id; 00957 struct wpa_ssid *ssid; 00958 00959 /* cmd: "<network id>" or "all" */ 00960 if (os_strcmp(cmd, "all") == 0) { 00961 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 00962 ssid = NULL; 00963 } else { 00964 id = atoi(cmd); 00965 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 00966 00967 ssid = wpa_config_get_network(wpa_s->conf, id); 00968 if (ssid == NULL) { 00969 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 00970 "network id=%d", id); 00971 return -1; 00972 } 00973 } 00974 wpa_supplicant_disable_network(wpa_s, ssid); 00975 00976 return 0; 00977 } 00978 00979 00980 static int wpa_supplicant_ctrl_iface_add_network( 00981 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 00982 { 00983 struct wpa_ssid *ssid; 00984 int ret; 00985 00986 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 00987 00988 ssid = wpa_config_add_network(wpa_s->conf); 00989 if (ssid == NULL) 00990 return -1; 00991 00992 wpas_notify_network_added(wpa_s, ssid); 00993 00994 ssid->disabled = 1; 00995 wpa_config_set_network_defaults(ssid); 00996 00997 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 00998 if (ret < 0 || (size_t) ret >= buflen) 00999 return -1; 01000 return ret; 01001 } 01002 01003 01004 static int wpa_supplicant_ctrl_iface_remove_network( 01005 struct wpa_supplicant *wpa_s, char *cmd) 01006 { 01007 int id; 01008 struct wpa_ssid *ssid; 01009 01010 /* cmd: "<network id>" or "all" */ 01011 if (os_strcmp(cmd, "all") == 0) { 01012 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 01013 ssid = wpa_s->conf->ssid; 01014 while (ssid) { 01015 struct wpa_ssid *remove_ssid = ssid; 01016 id = ssid->id; 01017 ssid = ssid->next; 01018 wpas_notify_network_removed(wpa_s, remove_ssid); 01019 wpa_config_remove_network(wpa_s->conf, id); 01020 } 01021 if (wpa_s->current_ssid) { 01022 eapol_sm_invalidate_cached_session(wpa_s->eapol); 01023 wpa_supplicant_disassociate(wpa_s, 01024 WLAN_REASON_DEAUTH_LEAVING); 01025 } 01026 return 0; 01027 } 01028 01029 id = atoi(cmd); 01030 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 01031 01032 ssid = wpa_config_get_network(wpa_s->conf, id); 01033 if (ssid == NULL || 01034 wpa_config_remove_network(wpa_s->conf, id) < 0) { 01035 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 01036 "id=%d", id); 01037 return -1; 01038 } 01039 01040 if (ssid == wpa_s->current_ssid) { 01041 /* 01042 * Invalidate the EAP session cache if the current network is 01043 * removed. 01044 */ 01045 eapol_sm_invalidate_cached_session(wpa_s->eapol); 01046 01047 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 01048 } 01049 01050 return 0; 01051 } 01052 01053 01054 static int wpa_supplicant_ctrl_iface_set_network( 01055 struct wpa_supplicant *wpa_s, char *cmd) 01056 { 01057 int id; 01058 struct wpa_ssid *ssid; 01059 char *name, *value; 01060 01061 /* cmd: "<network id> <variable name> <value>" */ 01062 name = os_strchr(cmd, ' '); 01063 if (name == NULL) 01064 return -1; 01065 *name++ = '\0'; 01066 01067 value = os_strchr(name, ' '); 01068 if (value == NULL) 01069 return -1; 01070 *value++ = '\0'; 01071 01072 id = atoi(cmd); 01073 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 01074 id, name); 01075 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 01076 (u8 *) value, os_strlen(value)); 01077 01078 ssid = wpa_config_get_network(wpa_s->conf, id); 01079 if (ssid == NULL) { 01080 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 01081 "id=%d", id); 01082 return -1; 01083 } 01084 01085 if (wpa_config_set(ssid, name, value, 0) < 0) { 01086 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 01087 "variable '%s'", name); 01088 return -1; 01089 } 01090 01091 if (wpa_s->current_ssid == ssid) { 01092 /* 01093 * Invalidate the EAP session cache if anything in the current 01094 * configuration changes. 01095 */ 01096 eapol_sm_invalidate_cached_session(wpa_s->eapol); 01097 } 01098 01099 if ((os_strcmp(name, "psk") == 0 && 01100 value[0] == '"' && ssid->ssid_len) || 01101 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 01102 wpa_config_update_psk(ssid); 01103 else if (os_strcmp(name, "priority") == 0) 01104 wpa_config_update_prio_list(wpa_s->conf); 01105 01106 return 0; 01107 } 01108 01109 01110 static int wpa_supplicant_ctrl_iface_get_network( 01111 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 01112 { 01113 int id; 01114 size_t res; 01115 struct wpa_ssid *ssid; 01116 char *name, *value; 01117 01118 /* cmd: "<network id> <variable name>" */ 01119 name = os_strchr(cmd, ' '); 01120 if (name == NULL || buflen == 0) 01121 return -1; 01122 *name++ = '\0'; 01123 01124 id = atoi(cmd); 01125 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 01126 id, name); 01127 01128 ssid = wpa_config_get_network(wpa_s->conf, id); 01129 if (ssid == NULL) { 01130 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 01131 "id=%d", id); 01132 return -1; 01133 } 01134 01135 value = wpa_config_get_no_key(ssid, name); 01136 if (value == NULL) { 01137 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 01138 "variable '%s'", name); 01139 return -1; 01140 } 01141 01142 res = os_strlcpy(buf, value, buflen); 01143 if (res >= buflen) { 01144 os_free(value); 01145 return -1; 01146 } 01147 01148 os_free(value); 01149 01150 return res; 01151 } 01152 01153 01154 #ifndef CONFIG_NO_CONFIG_WRITE 01155 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 01156 { 01157 int ret; 01158 01159 if (!wpa_s->conf->update_config) { 01160 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 01161 "to update configuration (update_config=0)"); 01162 return -1; 01163 } 01164 01165 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 01166 if (ret) { 01167 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 01168 "update configuration"); 01169 } else { 01170 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 01171 " updated"); 01172 } 01173 01174 return ret; 01175 } 01176 #endif /* CONFIG_NO_CONFIG_WRITE */ 01177 01178 01179 static int ctrl_iface_get_capability_pairwise(int res, char *strict, 01180 struct wpa_driver_capa *capa, 01181 char *buf, size_t buflen) 01182 { 01183 int ret, first = 1; 01184 char *pos, *end; 01185 size_t len; 01186 01187 pos = buf; 01188 end = pos + buflen; 01189 01190 if (res < 0) { 01191 if (strict) 01192 return 0; 01193 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 01194 if (len >= buflen) 01195 return -1; 01196 return len; 01197 } 01198 01199 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 01200 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 01201 if (ret < 0 || ret >= end - pos) 01202 return pos - buf; 01203 pos += ret; 01204 first = 0; 01205 } 01206 01207 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 01208 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 01209 if (ret < 0 || ret >= end - pos) 01210 return pos - buf; 01211 pos += ret; 01212 first = 0; 01213 } 01214 01215 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 01216 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " "); 01217 if (ret < 0 || ret >= end - pos) 01218 return pos - buf; 01219 pos += ret; 01220 first = 0; 01221 } 01222 01223 return pos - buf; 01224 } 01225 01226 01227 static int ctrl_iface_get_capability_group(int res, char *strict, 01228 struct wpa_driver_capa *capa, 01229 char *buf, size_t buflen) 01230 { 01231 int ret, first = 1; 01232 char *pos, *end; 01233 size_t len; 01234 01235 pos = buf; 01236 end = pos + buflen; 01237 01238 if (res < 0) { 01239 if (strict) 01240 return 0; 01241 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 01242 if (len >= buflen) 01243 return -1; 01244 return len; 01245 } 01246 01247 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 01248 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 01249 if (ret < 0 || ret >= end - pos) 01250 return pos - buf; 01251 pos += ret; 01252 first = 0; 01253 } 01254 01255 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 01256 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 01257 if (ret < 0 || ret >= end - pos) 01258 return pos - buf; 01259 pos += ret; 01260 first = 0; 01261 } 01262 01263 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) { 01264 ret = os_snprintf(pos, end - pos, "%sWEP104", 01265 first ? "" : " "); 01266 if (ret < 0 || ret >= end - pos) 01267 return pos - buf; 01268 pos += ret; 01269 first = 0; 01270 } 01271 01272 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) { 01273 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " "); 01274 if (ret < 0 || ret >= end - pos) 01275 return pos - buf; 01276 pos += ret; 01277 first = 0; 01278 } 01279 01280 return pos - buf; 01281 } 01282 01283 01284 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, 01285 struct wpa_driver_capa *capa, 01286 char *buf, size_t buflen) 01287 { 01288 int ret; 01289 char *pos, *end; 01290 size_t len; 01291 01292 pos = buf; 01293 end = pos + buflen; 01294 01295 if (res < 0) { 01296 if (strict) 01297 return 0; 01298 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 01299 "NONE", buflen); 01300 if (len >= buflen) 01301 return -1; 01302 return len; 01303 } 01304 01305 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 01306 if (ret < 0 || ret >= end - pos) 01307 return pos - buf; 01308 pos += ret; 01309 01310 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 01311 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 01312 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 01313 if (ret < 0 || ret >= end - pos) 01314 return pos - buf; 01315 pos += ret; 01316 } 01317 01318 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 01319 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 01320 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 01321 if (ret < 0 || ret >= end - pos) 01322 return pos - buf; 01323 pos += ret; 01324 } 01325 01326 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 01327 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 01328 if (ret < 0 || ret >= end - pos) 01329 return pos - buf; 01330 pos += ret; 01331 } 01332 01333 return pos - buf; 01334 } 01335 01336 01337 static int ctrl_iface_get_capability_proto(int res, char *strict, 01338 struct wpa_driver_capa *capa, 01339 char *buf, size_t buflen) 01340 { 01341 int ret, first = 1; 01342 char *pos, *end; 01343 size_t len; 01344 01345 pos = buf; 01346 end = pos + buflen; 01347 01348 if (res < 0) { 01349 if (strict) 01350 return 0; 01351 len = os_strlcpy(buf, "RSN WPA", buflen); 01352 if (len >= buflen) 01353 return -1; 01354 return len; 01355 } 01356 01357 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 01358 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 01359 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); 01360 if (ret < 0 || ret >= end - pos) 01361 return pos - buf; 01362 pos += ret; 01363 first = 0; 01364 } 01365 01366 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 01367 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 01368 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); 01369 if (ret < 0 || ret >= end - pos) 01370 return pos - buf; 01371 pos += ret; 01372 first = 0; 01373 } 01374 01375 return pos - buf; 01376 } 01377 01378 01379 static int ctrl_iface_get_capability_auth_alg(int res, char *strict, 01380 struct wpa_driver_capa *capa, 01381 char *buf, size_t buflen) 01382 { 01383 int ret, first = 1; 01384 char *pos, *end; 01385 size_t len; 01386 01387 pos = buf; 01388 end = pos + buflen; 01389 01390 if (res < 0) { 01391 if (strict) 01392 return 0; 01393 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 01394 if (len >= buflen) 01395 return -1; 01396 return len; 01397 } 01398 01399 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 01400 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " "); 01401 if (ret < 0 || ret >= end - pos) 01402 return pos - buf; 01403 pos += ret; 01404 first = 0; 01405 } 01406 01407 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 01408 ret = os_snprintf(pos, end - pos, "%sSHARED", 01409 first ? "" : " "); 01410 if (ret < 0 || ret >= end - pos) 01411 return pos - buf; 01412 pos += ret; 01413 first = 0; 01414 } 01415 01416 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 01417 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " "); 01418 if (ret < 0 || ret >= end - pos) 01419 return pos - buf; 01420 pos += ret; 01421 first = 0; 01422 } 01423 01424 return pos - buf; 01425 } 01426 01427 01428 static int wpa_supplicant_ctrl_iface_get_capability( 01429 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 01430 size_t buflen) 01431 { 01432 struct wpa_driver_capa capa; 01433 int res; 01434 char *strict; 01435 char field[30]; 01436 size_t len; 01437 01438 /* Determine whether or not strict checking was requested */ 01439 len = os_strlcpy(field, _field, sizeof(field)); 01440 if (len >= sizeof(field)) 01441 return -1; 01442 strict = os_strchr(field, ' '); 01443 if (strict != NULL) { 01444 *strict++ = '\0'; 01445 if (os_strcmp(strict, "strict") != 0) 01446 return -1; 01447 } 01448 01449 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", 01450 field, strict ? strict : ""); 01451 01452 if (os_strcmp(field, "eap") == 0) { 01453 return eap_get_names(buf, buflen); 01454 } 01455 01456 res = wpa_drv_get_capa(wpa_s, &capa); 01457 01458 if (os_strcmp(field, "pairwise") == 0) 01459 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 01460 buf, buflen); 01461 01462 if (os_strcmp(field, "group") == 0) 01463 return ctrl_iface_get_capability_group(res, strict, &capa, 01464 buf, buflen); 01465 01466 if (os_strcmp(field, "key_mgmt") == 0) 01467 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 01468 buf, buflen); 01469 01470 if (os_strcmp(field, "proto") == 0) 01471 return ctrl_iface_get_capability_proto(res, strict, &capa, 01472 buf, buflen); 01473 01474 if (os_strcmp(field, "auth_alg") == 0) 01475 return ctrl_iface_get_capability_auth_alg(res, strict, &capa, 01476 buf, buflen); 01477 01478 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 01479 field); 01480 01481 return -1; 01482 } 01483 01484 01485 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 01486 const char *cmd, char *buf, 01487 size_t buflen) 01488 { 01489 u8 bssid[ETH_ALEN]; 01490 size_t i; 01491 struct wpa_bss *bss; 01492 int ret; 01493 char *pos, *end; 01494 const u8 *ie, *ie2; 01495 01496 if (os_strcmp(cmd, "FIRST") == 0) 01497 bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list); 01498 else if (os_strncmp(cmd, "ID-", 3) == 0) { 01499 i = atoi(cmd + 3); 01500 bss = wpa_bss_get_id(wpa_s, i); 01501 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 01502 i = atoi(cmd + 5); 01503 bss = wpa_bss_get_id(wpa_s, i); 01504 if (bss) { 01505 struct dl_list *next = bss->list_id.next; 01506 if (next == &wpa_s->bss_id) 01507 bss = NULL; 01508 else 01509 bss = dl_list_entry(next, struct wpa_bss, 01510 list_id); 01511 } 01512 } else if (hwaddr_aton(cmd, bssid) == 0) 01513 bss = wpa_bss_get_bssid(wpa_s, bssid); 01514 else { 01515 struct wpa_bss *tmp; 01516 i = atoi(cmd); 01517 bss = NULL; 01518 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) 01519 { 01520 if (i-- == 0) { 01521 bss = tmp; 01522 break; 01523 } 01524 } 01525 } 01526 01527 if (bss == NULL) 01528 return 0; 01529 01530 pos = buf; 01531 end = buf + buflen; 01532 ret = os_snprintf(pos, end - pos, 01533 "id=%u\n" 01534 "bssid=" MACSTR "\n" 01535 "freq=%d\n" 01536 "beacon_int=%d\n" 01537 "capabilities=0x%04x\n" 01538 "qual=%d\n" 01539 "noise=%d\n" 01540 "level=%d\n" 01541 "tsf=%016llu\n" 01542 "ie=", 01543 bss->id, 01544 MAC2STR(bss->bssid), bss->freq, bss->beacon_int, 01545 bss->caps, bss->qual, bss->noise, bss->level, 01546 (unsigned long long) bss->tsf); 01547 if (ret < 0 || ret >= end - pos) 01548 return pos - buf; 01549 pos += ret; 01550 01551 ie = (const u8 *) (bss + 1); 01552 for (i = 0; i < bss->ie_len; i++) { 01553 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 01554 if (ret < 0 || ret >= end - pos) 01555 return pos - buf; 01556 pos += ret; 01557 } 01558 01559 ret = os_snprintf(pos, end - pos, "\n"); 01560 if (ret < 0 || ret >= end - pos) 01561 return pos - buf; 01562 pos += ret; 01563 01564 ret = os_snprintf(pos, end - pos, "flags="); 01565 if (ret < 0 || ret >= end - pos) 01566 return pos - buf; 01567 pos += ret; 01568 01569 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 01570 if (ie) 01571 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 01572 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 01573 if (ie2) 01574 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 01575 pos = wpa_supplicant_wps_ie_txt(pos, end, bss); 01576 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 01577 ret = os_snprintf(pos, end - pos, "[WEP]"); 01578 if (ret < 0 || ret >= end - pos) 01579 return pos - buf; 01580 pos += ret; 01581 } 01582 if (bss->caps & IEEE80211_CAP_IBSS) { 01583 ret = os_snprintf(pos, end - pos, "[IBSS]"); 01584 if (ret < 0 || ret >= end - pos) 01585 return pos - buf; 01586 pos += ret; 01587 } 01588 if (bss->caps & IEEE80211_CAP_ESS) { 01589 ret = os_snprintf(pos, end - pos, "[ESS]"); 01590 if (ret < 0 || ret >= end - pos) 01591 return pos - buf; 01592 pos += ret; 01593 } 01594 01595 ret = os_snprintf(pos, end - pos, "\n"); 01596 if (ret < 0 || ret >= end - pos) 01597 return pos - buf; 01598 pos += ret; 01599 01600 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 01601 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 01602 if (ret < 0 || ret >= end - pos) 01603 return pos - buf; 01604 pos += ret; 01605 01606 #ifdef CONFIG_WPS 01607 ie = (const u8 *) (bss + 1); 01608 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); 01609 if (ret < 0 || ret >= end - pos) 01610 return pos - buf; 01611 pos += ret; 01612 #endif /* CONFIG_WPS */ 01613 01614 return pos - buf; 01615 } 01616 01617 01618 static int wpa_supplicant_ctrl_iface_ap_scan( 01619 struct wpa_supplicant *wpa_s, char *cmd) 01620 { 01621 int ap_scan = atoi(cmd); 01622 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan); 01623 } 01624 01625 01626 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) 01627 { 01628 u8 *bcast = (u8 *) "\xff\xff\xff\xff\xff\xff"; 01629 01630 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication"); 01631 /* MLME-DELETEKEYS.request */ 01632 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 0, 0, NULL, 0, NULL, 0); 01633 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 1, 0, NULL, 0, NULL, 0); 01634 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 2, 0, NULL, 0, NULL, 0); 01635 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 3, 0, NULL, 0, NULL, 0); 01636 #ifdef CONFIG_IEEE80211W 01637 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 4, 0, NULL, 0, NULL, 0); 01638 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 5, 0, NULL, 0, NULL, 0); 01639 #endif /* CONFIG_IEEE80211W */ 01640 01641 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 01642 0); 01643 /* MLME-SETPROTECTION.request(None) */ 01644 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, 01645 MLME_SETPROTECTION_PROTECT_TYPE_NONE, 01646 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 01647 wpa_sm_drop_sa(wpa_s->wpa); 01648 } 01649 01650 01651 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, 01652 char *addr) 01653 { 01654 u8 bssid[ETH_ALEN]; 01655 struct wpa_bss *bss; 01656 struct wpa_ssid *ssid = wpa_s->current_ssid; 01657 01658 if (hwaddr_aton(addr, bssid)) { 01659 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " 01660 "address '%s'", addr); 01661 return -1; 01662 } 01663 01664 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); 01665 01666 bss = wpa_bss_get_bssid(wpa_s, bssid); 01667 if (!bss) { 01668 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " 01669 "from BSS table"); 01670 return -1; 01671 } 01672 01673 /* 01674 * TODO: Find best network configuration block from configuration to 01675 * allow roaming to other networks 01676 */ 01677 01678 if (!ssid) { 01679 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " 01680 "configuration known for the target AP"); 01681 return -1; 01682 } 01683 01684 wpa_s->reassociate = 1; 01685 wpa_supplicant_connect(wpa_s, bss, ssid); 01686 01687 return 0; 01688 } 01689 01690 01691 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 01692 char *buf, size_t *resp_len) 01693 { 01694 char *reply; 01695 const int reply_size = 2048; 01696 int ctrl_rsp = 0; 01697 int reply_len; 01698 01699 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 01700 os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 01701 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 01702 (const u8 *) buf, os_strlen(buf)); 01703 } else { 01704 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", 01705 (const u8 *) buf, os_strlen(buf)); 01706 } 01707 01708 reply = os_malloc(reply_size); 01709 if (reply == NULL) { 01710 *resp_len = 1; 01711 return NULL; 01712 } 01713 01714 os_memcpy(reply, "OK\n", 3); 01715 reply_len = 3; 01716 01717 if (os_strcmp(buf, "PING") == 0) { 01718 os_memcpy(reply, "PONG\n", 5); 01719 reply_len = 5; 01720 } else if (os_strcmp(buf, "MIB") == 0) { 01721 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 01722 if (reply_len >= 0) { 01723 int res; 01724 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, 01725 reply_size - reply_len); 01726 if (res < 0) 01727 reply_len = -1; 01728 else 01729 reply_len += res; 01730 } 01731 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 01732 reply_len = wpa_supplicant_ctrl_iface_status( 01733 wpa_s, buf + 6, reply, reply_size); 01734 } else if (os_strcmp(buf, "PMKSA") == 0) { 01735 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply, 01736 reply_size); 01737 } else if (os_strncmp(buf, "SET ", 4) == 0) { 01738 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 01739 reply_len = -1; 01740 } else if (os_strcmp(buf, "LOGON") == 0) { 01741 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 01742 } else if (os_strcmp(buf, "LOGOFF") == 0) { 01743 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 01744 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 01745 wpa_s->disconnected = 0; 01746 wpa_s->reassociate = 1; 01747 wpa_supplicant_req_scan(wpa_s, 0, 0); 01748 } else if (os_strcmp(buf, "RECONNECT") == 0) { 01749 if (wpa_s->disconnected) { 01750 wpa_s->disconnected = 0; 01751 wpa_s->reassociate = 1; 01752 wpa_supplicant_req_scan(wpa_s, 0, 0); 01753 } 01754 #ifdef IEEE8021X_EAPOL 01755 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 01756 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 01757 reply_len = -1; 01758 #endif /* IEEE8021X_EAPOL */ 01759 #ifdef CONFIG_PEERKEY 01760 } else if (os_strncmp(buf, "STKSTART ", 9) == 0) { 01761 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9)) 01762 reply_len = -1; 01763 #endif /* CONFIG_PEERKEY */ 01764 #ifdef CONFIG_IEEE80211R 01765 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 01766 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 01767 reply_len = -1; 01768 #endif /* CONFIG_IEEE80211R */ 01769 #ifdef CONFIG_WPS 01770 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 01771 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL)) 01772 reply_len = -1; 01773 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 01774 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8)) 01775 reply_len = -1; 01776 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 01777 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 01778 reply, 01779 reply_size); 01780 #ifdef CONFIG_WPS_OOB 01781 } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) { 01782 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8)) 01783 reply_len = -1; 01784 #endif /* CONFIG_WPS_OOB */ 01785 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 01786 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 01787 reply_len = -1; 01788 #ifdef CONFIG_WPS_ER 01789 } else if (os_strcmp(buf, "WPS_ER_START") == 0) { 01790 if (wpas_wps_er_start(wpa_s)) 01791 reply_len = -1; 01792 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) { 01793 if (wpas_wps_er_stop(wpa_s)) 01794 reply_len = -1; 01795 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) { 01796 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11)) 01797 reply_len = -1; 01798 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) { 01799 if (wpas_wps_er_pbc(wpa_s, buf + 11)) 01800 reply_len = -1; 01801 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { 01802 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) 01803 reply_len = -1; 01804 #endif /* CONFIG_WPS_ER */ 01805 #endif /* CONFIG_WPS */ 01806 #ifdef CONFIG_IBSS_RSN 01807 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) { 01808 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9)) 01809 reply_len = -1; 01810 #endif /* CONFIG_IBSS_RSN */ 01811 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 01812 { 01813 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 01814 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 01815 reply_len = -1; 01816 else 01817 ctrl_rsp = 1; 01818 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 01819 if (wpa_supplicant_reload_configuration(wpa_s)) 01820 reply_len = -1; 01821 } else if (os_strcmp(buf, "TERMINATE") == 0) { 01822 wpa_supplicant_terminate_proc(wpa_s->global); 01823 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 01824 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 01825 reply_len = -1; 01826 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 01827 reply_len = wpa_supplicant_ctrl_iface_list_networks( 01828 wpa_s, reply, reply_size); 01829 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 01830 wpa_s->reassociate = 0; 01831 wpa_s->disconnected = 1; 01832 wpa_supplicant_deauthenticate(wpa_s, 01833 WLAN_REASON_DEAUTH_LEAVING); 01834 } else if (os_strcmp(buf, "SCAN") == 0) { 01835 wpa_s->scan_req = 2; 01836 wpa_supplicant_req_scan(wpa_s, 0, 0); 01837 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 01838 reply_len = wpa_supplicant_ctrl_iface_scan_results( 01839 wpa_s, reply, reply_size); 01840 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 01841 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 01842 reply_len = -1; 01843 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 01844 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 01845 reply_len = -1; 01846 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 01847 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 01848 reply_len = -1; 01849 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 01850 reply_len = wpa_supplicant_ctrl_iface_add_network( 01851 wpa_s, reply, reply_size); 01852 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 01853 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 01854 reply_len = -1; 01855 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 01856 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 01857 reply_len = -1; 01858 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 01859 reply_len = wpa_supplicant_ctrl_iface_get_network( 01860 wpa_s, buf + 12, reply, reply_size); 01861 #ifndef CONFIG_NO_CONFIG_WRITE 01862 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 01863 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 01864 reply_len = -1; 01865 #endif /* CONFIG_NO_CONFIG_WRITE */ 01866 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 01867 reply_len = wpa_supplicant_ctrl_iface_get_capability( 01868 wpa_s, buf + 15, reply, reply_size); 01869 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 01870 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 01871 reply_len = -1; 01872 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 01873 reply_len = wpa_supplicant_global_iface_list( 01874 wpa_s->global, reply, reply_size); 01875 } else if (os_strcmp(buf, "INTERFACES") == 0) { 01876 reply_len = wpa_supplicant_global_iface_interfaces( 01877 wpa_s->global, reply, reply_size); 01878 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 01879 reply_len = wpa_supplicant_ctrl_iface_bss( 01880 wpa_s, buf + 4, reply, reply_size); 01881 #ifdef CONFIG_AP 01882 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 01883 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); 01884 } else if (os_strncmp(buf, "STA ", 4) == 0) { 01885 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply, 01886 reply_size); 01887 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 01888 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, 01889 reply_size); 01890 #endif /* CONFIG_AP */ 01891 } else if (os_strcmp(buf, "SUSPEND") == 0) { 01892 wpas_notify_suspend(wpa_s->global); 01893 } else if (os_strcmp(buf, "RESUME") == 0) { 01894 wpas_notify_resume(wpa_s->global); 01895 } else if (os_strcmp(buf, "DROP_SA") == 0) { 01896 wpa_supplicant_ctrl_iface_drop_sa(wpa_s); 01897 } else if (os_strncmp(buf, "ROAM ", 5) == 0) { 01898 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) 01899 reply_len = -1; 01900 } else { 01901 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 01902 reply_len = 16; 01903 } 01904 01905 if (reply_len < 0) { 01906 os_memcpy(reply, "FAIL\n", 5); 01907 reply_len = 5; 01908 } 01909 01910 if (ctrl_rsp) 01911 eapol_sm_notify_ctrl_response(wpa_s->eapol); 01912 01913 *resp_len = reply_len; 01914 return reply; 01915 } 01916 01917 01918 static int wpa_supplicant_global_iface_add(struct wpa_global *global, 01919 char *cmd) 01920 { 01921 struct wpa_interface iface; 01922 char *pos; 01923 01924 /* 01925 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 01926 * TAB<bridge_ifname> 01927 */ 01928 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 01929 01930 os_memset(&iface, 0, sizeof(iface)); 01931 01932 do { 01933 iface.ifname = pos = cmd; 01934 pos = os_strchr(pos, '\t'); 01935 if (pos) 01936 *pos++ = '\0'; 01937 if (iface.ifname[0] == '\0') 01938 return -1; 01939 if (pos == NULL) 01940 break; 01941 01942 iface.confname = pos; 01943 pos = os_strchr(pos, '\t'); 01944 if (pos) 01945 *pos++ = '\0'; 01946 if (iface.confname[0] == '\0') 01947 iface.confname = NULL; 01948 if (pos == NULL) 01949 break; 01950 01951 iface.driver = pos; 01952 pos = os_strchr(pos, '\t'); 01953 if (pos) 01954 *pos++ = '\0'; 01955 if (iface.driver[0] == '\0') 01956 iface.driver = NULL; 01957 if (pos == NULL) 01958 break; 01959 01960 iface.ctrl_interface = pos; 01961 pos = os_strchr(pos, '\t'); 01962 if (pos) 01963 *pos++ = '\0'; 01964 if (iface.ctrl_interface[0] == '\0') 01965 iface.ctrl_interface = NULL; 01966 if (pos == NULL) 01967 break; 01968 01969 iface.driver_param = pos; 01970 pos = os_strchr(pos, '\t'); 01971 if (pos) 01972 *pos++ = '\0'; 01973 if (iface.driver_param[0] == '\0') 01974 iface.driver_param = NULL; 01975 if (pos == NULL) 01976 break; 01977 01978 iface.bridge_ifname = pos; 01979 pos = os_strchr(pos, '\t'); 01980 if (pos) 01981 *pos++ = '\0'; 01982 if (iface.bridge_ifname[0] == '\0') 01983 iface.bridge_ifname = NULL; 01984 if (pos == NULL) 01985 break; 01986 } while (0); 01987 01988 if (wpa_supplicant_get_iface(global, iface.ifname)) 01989 return -1; 01990 01991 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1; 01992 } 01993 01994 01995 static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 01996 char *cmd) 01997 { 01998 struct wpa_supplicant *wpa_s; 01999 02000 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 02001 02002 wpa_s = wpa_supplicant_get_iface(global, cmd); 02003 if (wpa_s == NULL) 02004 return -1; 02005 return wpa_supplicant_remove_iface(global, wpa_s); 02006 } 02007 02008 02009 static void wpa_free_iface_info(struct wpa_interface_info *iface) 02010 { 02011 struct wpa_interface_info *prev; 02012 02013 while (iface) { 02014 prev = iface; 02015 iface = iface->next; 02016 02017 os_free(prev->ifname); 02018 os_free(prev->desc); 02019 os_free(prev); 02020 } 02021 } 02022 02023 02024 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 02025 char *buf, int len) 02026 { 02027 int i, res; 02028 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 02029 char *pos, *end; 02030 02031 for (i = 0; wpa_drivers[i]; i++) { 02032 struct wpa_driver_ops *drv = wpa_drivers[i]; 02033 if (drv->get_interfaces == NULL) 02034 continue; 02035 tmp = drv->get_interfaces(global->drv_priv[i]); 02036 if (tmp == NULL) 02037 continue; 02038 02039 if (last == NULL) 02040 iface = last = tmp; 02041 else 02042 last->next = tmp; 02043 while (last->next) 02044 last = last->next; 02045 } 02046 02047 pos = buf; 02048 end = buf + len; 02049 for (tmp = iface; tmp; tmp = tmp->next) { 02050 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 02051 tmp->drv_name, tmp->ifname, 02052 tmp->desc ? tmp->desc : ""); 02053 if (res < 0 || res >= end - pos) { 02054 *pos = '\0'; 02055 break; 02056 } 02057 pos += res; 02058 } 02059 02060 wpa_free_iface_info(iface); 02061 02062 return pos - buf; 02063 } 02064 02065 02066 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 02067 char *buf, int len) 02068 { 02069 int res; 02070 char *pos, *end; 02071 struct wpa_supplicant *wpa_s; 02072 02073 wpa_s = global->ifaces; 02074 pos = buf; 02075 end = buf + len; 02076 02077 while (wpa_s) { 02078 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname); 02079 if (res < 0 || res >= end - pos) { 02080 *pos = '\0'; 02081 break; 02082 } 02083 pos += res; 02084 wpa_s = wpa_s->next; 02085 } 02086 return pos - buf; 02087 } 02088 02089 02090 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 02091 char *buf, size_t *resp_len) 02092 { 02093 char *reply; 02094 const int reply_size = 2048; 02095 int reply_len; 02096 02097 wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", 02098 (const u8 *) buf, os_strlen(buf)); 02099 02100 reply = os_malloc(reply_size); 02101 if (reply == NULL) { 02102 *resp_len = 1; 02103 return NULL; 02104 } 02105 02106 os_memcpy(reply, "OK\n", 3); 02107 reply_len = 3; 02108 02109 if (os_strcmp(buf, "PING") == 0) { 02110 os_memcpy(reply, "PONG\n", 5); 02111 reply_len = 5; 02112 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 02113 if (wpa_supplicant_global_iface_add(global, buf + 14)) 02114 reply_len = -1; 02115 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 02116 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 02117 reply_len = -1; 02118 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 02119 reply_len = wpa_supplicant_global_iface_list( 02120 global, reply, reply_size); 02121 } else if (os_strcmp(buf, "INTERFACES") == 0) { 02122 reply_len = wpa_supplicant_global_iface_interfaces( 02123 global, reply, reply_size); 02124 } else if (os_strcmp(buf, "TERMINATE") == 0) { 02125 wpa_supplicant_terminate_proc(global); 02126 } else if (os_strcmp(buf, "SUSPEND") == 0) { 02127 wpas_notify_suspend(global); 02128 } else if (os_strcmp(buf, "RESUME") == 0) { 02129 wpas_notify_resume(global); 02130 } else { 02131 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 02132 reply_len = 16; 02133 } 02134 02135 if (reply_len < 0) { 02136 os_memcpy(reply, "FAIL\n", 5); 02137 reply_len = 5; 02138 } 02139 02140 *resp_len = reply_len; 02141 return reply; 02142 }