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


wpa_supplicant_node
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:25:12