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