00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00113
00114
00115 #ifdef CONFIG_PEERKEY
00116
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
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
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
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
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
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
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
00336
00337 #endif
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
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
00438 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
00439 return -1;
00440 #endif
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
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
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
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
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
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
00811 return pos;
00812 #endif
00813 }
00814
00815
00816
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
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
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
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
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
01045
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
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
01096
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
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
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
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
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
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
01644
01645 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
01646 0);
01647
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
01679
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
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
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
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
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
01809 #endif
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
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
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
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
01930
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 }