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


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:34