OSDN Git Service

am be5cce4a: Check if interface is valid in wpa_ctrl_close()
[android-x86/external-wpa_supplicant.git] / ctrl_iface.c
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eloop.h"
19 #include "wpa.h"
20 #include "wpa_supplicant.h"
21 #include "config.h"
22 #include "eapol_sm.h"
23 #include "wpa_supplicant_i.h"
24 #include "ctrl_iface.h"
25 #include "l2_packet.h"
26 #include "preauth.h"
27 #include "pmksa_cache.h"
28 #include "wpa_ctrl.h"
29 #include "eap.h"
30
31
32 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
33                                                   char *buf, int len);
34
35
36 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
37                                          char *cmd)
38 {
39         char *value;
40         int ret = 0;
41
42         value = os_strchr(cmd, ' ');
43         if (value == NULL)
44                 return -1;
45         *value++ = '\0';
46
47         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
48         if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
49                 eapol_sm_configure(wpa_s->eapol,
50                                    atoi(value), -1, -1, -1);
51         } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
52                 eapol_sm_configure(wpa_s->eapol,
53                                    -1, atoi(value), -1, -1);
54         } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
55                 eapol_sm_configure(wpa_s->eapol,
56                                    -1, -1, atoi(value), -1);
57         } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
58                 eapol_sm_configure(wpa_s->eapol,
59                                    -1, -1, -1, atoi(value));
60         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
61                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
62                                      atoi(value)))
63                         ret = -1;
64         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
65                    0) {
66                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
67                                      atoi(value)))
68                         ret = -1;
69         } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
70                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
71                         ret = -1;
72         } else
73                 ret = -1;
74
75         return ret;
76 }
77
78
79 #ifdef IEEE8021X_EAPOL
80 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
81                                              char *addr)
82 {
83         u8 bssid[ETH_ALEN];
84
85         if (hwaddr_aton(addr, bssid)) {
86                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
87                            "'%s'", addr);
88                 return -1;
89         }
90
91         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
92         rsn_preauth_deinit(wpa_s->wpa);
93         if (rsn_preauth_init(wpa_s->wpa, bssid, wpa_s->current_ssid))
94                 return -1;
95
96         return 0;
97 }
98 #endif /* IEEE8021X_EAPOL */
99
100
101 #ifdef CONFIG_PEERKEY
102 /* MLME-STKSTART.request(peer) */
103 static int wpa_supplicant_ctrl_iface_stkstart(
104         struct wpa_supplicant *wpa_s, char *addr)
105 {
106         u8 peer[ETH_ALEN];
107
108         if (hwaddr_aton(addr, peer)) {
109                 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
110                            "address '%s'", peer);
111                 return -1;
112         }
113
114         wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
115                    MAC2STR(peer));
116
117         return wpa_sm_stkstart(wpa_s->wpa, peer);
118 }
119 #endif /* CONFIG_PEERKEY */
120
121
122 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
123                                               char *rsp)
124 {
125 #ifdef IEEE8021X_EAPOL
126         char *pos, *id_pos;
127         int id;
128         struct wpa_ssid *ssid;
129
130         pos = os_strchr(rsp, '-');
131         if (pos == NULL)
132                 return -1;
133         *pos++ = '\0';
134         id_pos = pos;
135         pos = os_strchr(pos, ':');
136         if (pos == NULL)
137                 return -1;
138         *pos++ = '\0';
139         id = atoi(id_pos);
140         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
141         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
142                               (u8 *) pos, os_strlen(pos));
143
144         ssid = wpa_config_get_network(wpa_s->conf, id);
145         if (ssid == NULL) {
146                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
147                            "to update", id);
148                 return -1;
149         }
150
151         if (os_strcmp(rsp, "IDENTITY") == 0) {
152                 os_free(ssid->identity);
153                 ssid->identity = (u8 *) os_strdup(pos);
154                 ssid->identity_len = os_strlen(pos);
155                 ssid->pending_req_identity = 0;
156                 if (ssid == wpa_s->current_ssid)
157                         wpa_s->reassociate = 1;
158         } else if (os_strcmp(rsp, "PASSWORD") == 0) {
159                 os_free(ssid->password);
160                 ssid->password = (u8 *) os_strdup(pos);
161                 ssid->password_len = os_strlen(pos);
162                 ssid->pending_req_password = 0;
163                 if (ssid == wpa_s->current_ssid)
164                         wpa_s->reassociate = 1;
165         } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
166                 os_free(ssid->new_password);
167                 ssid->new_password = (u8 *) os_strdup(pos);
168                 ssid->new_password_len = os_strlen(pos);
169                 ssid->pending_req_new_password = 0;
170                 if (ssid == wpa_s->current_ssid)
171                         wpa_s->reassociate = 1;
172         } else if (os_strcmp(rsp, "PIN") == 0) {
173                 os_free(ssid->pin);
174                 ssid->pin = os_strdup(pos);
175                 ssid->pending_req_pin = 0;
176                 if (ssid == wpa_s->current_ssid)
177                         wpa_s->reassociate = 1;
178         } else if (os_strcmp(rsp, "OTP") == 0) {
179                 os_free(ssid->otp);
180                 ssid->otp = (u8 *) os_strdup(pos);
181                 ssid->otp_len = os_strlen(pos);
182                 os_free(ssid->pending_req_otp);
183                 ssid->pending_req_otp = NULL;
184                 ssid->pending_req_otp_len = 0;
185         } else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
186                 os_free(ssid->private_key_passwd);
187                 ssid->private_key_passwd = (u8 *) os_strdup(pos);
188                 ssid->pending_req_passphrase = 0;
189                 if (ssid == wpa_s->current_ssid)
190                         wpa_s->reassociate = 1;
191         } else {
192                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
193                 return -1;
194         }
195
196         return 0;
197 #else /* IEEE8021X_EAPOL */
198         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
199         return -1;
200 #endif /* IEEE8021X_EAPOL */
201 }
202
203
204 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
205                                             const char *params,
206                                             char *buf, size_t buflen)
207 {
208         char *pos, *end, tmp[30];
209         int res, verbose, ret;
210
211         verbose = os_strcmp(params, "-VERBOSE") == 0;
212         pos = buf;
213         end = buf + buflen;
214         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
215                 struct wpa_ssid *ssid = wpa_s->current_ssid;
216                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
217                                   MAC2STR(wpa_s->bssid));
218                 if (ret < 0 || ret >= end - pos)
219                         return pos - buf;
220                 pos += ret;
221                 if (ssid) {
222                         u8 *_ssid = ssid->ssid;
223                         size_t ssid_len = ssid->ssid_len;
224                         u8 ssid_buf[MAX_SSID_LEN];
225                         if (ssid_len == 0) {
226                                 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
227                                 if (_res < 0)
228                                         ssid_len = 0;
229                                 else
230                                         ssid_len = _res;
231                                 _ssid = ssid_buf;
232                         }
233                         ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
234                                           wpa_ssid_txt(_ssid, ssid_len),
235                                           ssid->id);
236                         if (ret < 0 || ret >= end - pos)
237                                 return pos - buf;
238                         pos += ret;
239
240                         if (ssid->id_str) {
241                                 ret = os_snprintf(pos, end - pos,
242                                                   "id_str=%s\n",
243                                                   ssid->id_str);
244                                 if (ret < 0 || ret >= end - pos)
245                                         return pos - buf;
246                                 pos += ret;
247                         }
248                 }
249
250                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
251         }
252         ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
253                           wpa_supplicant_state_txt(wpa_s->wpa_state));
254         if (ret < 0 || ret >= end - pos)
255                 return pos - buf;
256         pos += ret;
257
258         if (wpa_s->l2 &&
259             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
260                 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
261                 if (ret < 0 || ret >= end - pos)
262                         return pos - buf;
263                 pos += ret;
264         }
265
266         if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
267             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
268                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
269                                           verbose);
270                 if (res >= 0)
271                         pos += res;
272         }
273
274         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
275         if (res >= 0)
276                 pos += res;
277
278         return pos - buf;
279 }
280
281
282 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
283                                            char *cmd)
284 {
285         char *pos;
286         int id;
287         struct wpa_ssid *ssid;
288         u8 bssid[ETH_ALEN];
289
290         /* cmd: "<network id> <BSSID>" */
291         pos = os_strchr(cmd, ' ');
292         if (pos == NULL)
293                 return -1;
294         *pos++ = '\0';
295         id = atoi(cmd);
296         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
297         if (hwaddr_aton(pos, bssid)) {
298                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
299                 return -1;
300         }
301
302         ssid = wpa_config_get_network(wpa_s->conf, id);
303         if (ssid == NULL) {
304                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
305                            "to update", id);
306                 return -1;
307         }
308
309         os_memcpy(ssid->bssid, bssid, ETH_ALEN);
310         ssid->bssid_set =
311                 os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0;
312                 
313
314         return 0;
315 }
316
317 #ifdef ANDROID
318 static int wpa_supplicant_ctrl_iface_blacklist(
319                 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
320 {
321         struct wpa_ssid *ssid;
322         u8 bssid[ETH_ALEN];
323         struct wpa_blacklist *e;
324         char *pos, *end;
325         int ret;
326
327         /* cmd: "BLACKLIST [<BSSID>]" */
328         if (*cmd == '\0') {
329                 pos = buf;
330                 end = buf + buflen;
331
332                 e = wpa_s->blacklist;
333                 while (e) {
334                         ret = os_snprintf(pos, end-pos,
335                                           "%02x:%02x:%02x:%02x:%02x:%02x\n",
336                                           e->bssid[0],
337                                           e->bssid[1],
338                                           e->bssid[2],
339                                           e->bssid[3],
340                                           e->bssid[4],
341                                           e->bssid[5]);
342                         if (ret < 0 || ret >= end - pos)
343                                 return pos - buf;
344                         pos += ret;
345                         e = e->next;
346                 }
347                 return pos - buf;
348         }
349         wpa_printf(MSG_DEBUG, "CTRL_IFACE: bssid='%s'", cmd);
350
351         ++cmd;
352         if (os_strncmp(cmd, "clear", 5) == 0) {
353                 wpa_blacklist_clear(wpa_s);
354                 return 0;
355         }
356
357         if (hwaddr_aton(cmd, bssid)) {
358                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", cmd);
359                 return -1;
360         }
361
362         /*
363          * Add the BSSID twice, so its count will be 2, causing it to be
364          * skipped when processing scan results.
365          */
366         ret = wpa_blacklist_add(wpa_s, bssid);
367         if (ret != 0)
368                 return ret;
369         return wpa_blacklist_add(wpa_s, bssid);
370 }
371 #endif
372
373 static int wpa_supplicant_ctrl_iface_list_networks(
374         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
375 {
376         char *pos, *end;
377         struct wpa_ssid *ssid;
378         int ret;
379
380         pos = buf;
381         end = buf + buflen;
382         ret = os_snprintf(pos, end - pos,
383                           "network id / ssid / bssid / flags\n");
384         if (ret < 0 || ret >= end - pos)
385                 return pos - buf;
386         pos += ret;
387
388         ssid = wpa_s->conf->ssid;
389         while (ssid) {
390                 ret = os_snprintf(pos, end - pos, "%d\t%s",
391                                   ssid->id,
392                                   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
393                 if (ret < 0 || ret >= end - pos)
394                         return pos - buf;
395                 pos += ret;
396                 if (ssid->bssid_set) {
397                         ret = os_snprintf(pos, end - pos, "\t" MACSTR,
398                                           MAC2STR(ssid->bssid));
399                 } else {
400                         ret = os_snprintf(pos, end - pos, "\tany");
401                 }
402                 if (ret < 0 || ret >= end - pos)
403                         return pos - buf;
404                 pos += ret;
405                 ret = os_snprintf(pos, end - pos, "\t%s%s",
406                                   ssid == wpa_s->current_ssid ?
407                                   "[CURRENT]" : "",
408                                   ssid->disabled ? "[DISABLED]" : "");
409                 if (ret < 0 || ret >= end - pos)
410                         return pos - buf;
411                 pos += ret;
412                 ret = os_snprintf(pos, end - pos, "\n");
413                 if (ret < 0 || ret >= end - pos)
414                         return pos - buf;
415                 pos += ret;
416
417                 ssid = ssid->next;
418         }
419
420         return pos - buf;
421 }
422
423
424 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
425 {
426         int first = 1, ret;
427         ret = os_snprintf(pos, end - pos, "-");
428         if (ret < 0 || ret >= end - pos)
429                 return pos;
430         pos += ret;
431         if (cipher & WPA_CIPHER_NONE) {
432                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
433                 if (ret < 0 || ret >= end - pos)
434                         return pos;
435                 pos += ret;
436                 first = 0;
437         }
438         if (cipher & WPA_CIPHER_WEP40) {
439                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
440                 if (ret < 0 || ret >= end - pos)
441                         return pos;
442                 pos += ret;
443                 first = 0;
444         }
445         if (cipher & WPA_CIPHER_WEP104) {
446                 ret = os_snprintf(pos, end - pos, "%sWEP104",
447                                   first ? "" : "+");
448                 if (ret < 0 || ret >= end - pos)
449                         return pos;
450                 pos += ret;
451                 first = 0;
452         }
453         if (cipher & WPA_CIPHER_TKIP) {
454                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
455                 if (ret < 0 || ret >= end - pos)
456                         return pos;
457                 pos += ret;
458                 first = 0;
459         }
460         if (cipher & WPA_CIPHER_CCMP) {
461                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
462                 if (ret < 0 || ret >= end - pos)
463                         return pos;
464                 pos += ret;
465                 first = 0;
466         }
467         return pos;
468 }
469
470
471 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
472                                     const u8 *ie, size_t ie_len)
473 {
474         struct wpa_ie_data data;
475         int first, ret;
476
477         ret = os_snprintf(pos, end - pos, "[%s-", proto);
478         if (ret < 0 || ret >= end - pos)
479                 return pos;
480         pos += ret;
481
482         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
483                 ret = os_snprintf(pos, end - pos, "?]");
484                 if (ret < 0 || ret >= end - pos)
485                         return pos;
486                 pos += ret;
487                 return pos;
488         }
489
490         first = 1;
491         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
492                 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
493                 if (ret < 0 || ret >= end - pos)
494                         return pos;
495                 pos += ret;
496                 first = 0;
497         }
498         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
499                 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
500                 if (ret < 0 || ret >= end - pos)
501                         return pos;
502                 pos += ret;
503                 first = 0;
504         }
505         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
506                 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
507                 if (ret < 0 || ret >= end - pos)
508                         return pos;
509                 pos += ret;
510                 first = 0;
511         }
512
513         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
514
515         if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
516                 ret = os_snprintf(pos, end - pos, "-preauth");
517                 if (ret < 0 || ret >= end - pos)
518                         return pos;
519                 pos += ret;
520         }
521
522         ret = os_snprintf(pos, end - pos, "]");
523         if (ret < 0 || ret >= end - pos)
524                 return pos;
525         pos += ret;
526
527         return pos;
528 }
529
530
531 static int wpa_supplicant_ctrl_iface_scan_results(
532         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
533 {
534         char *pos, *end, *retpos;
535         struct wpa_scan_result *res;
536         int i, ret;
537
538         if (wpa_s->scan_results == NULL &&
539             wpa_supplicant_get_scan_results(wpa_s) < 0)
540                 return 0;
541         if (wpa_s->scan_results == NULL)
542                 return 0;
543
544         pos = buf;
545         end = buf + buflen;
546         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
547                           "flags / ssid\n");
548         if (ret < 0 || ret >= end - pos)
549                 return pos - buf;
550         pos += ret;
551
552         for (i = 0; i < wpa_s->num_scan_results; i++) {
553                 retpos = pos;
554                 res = &wpa_s->scan_results[i];
555                 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
556                                   MAC2STR(res->bssid), res->freq, res->level);
557                 if (ret < 0 || ret >= end - pos)
558                         return retpos - buf;
559                 pos += ret;
560                 if (res->wpa_ie_len) {
561                         pos = wpa_supplicant_ie_txt(pos, end, "WPA",
562                                                     res->wpa_ie,
563                                                     res->wpa_ie_len);
564                 }
565                 if (res->rsn_ie_len) {
566                         pos = wpa_supplicant_ie_txt(pos, end, "WPA2",
567                                                     res->rsn_ie,
568                                                     res->rsn_ie_len);
569                 }
570                 if (!res->wpa_ie_len && !res->rsn_ie_len &&
571                     res->caps & IEEE80211_CAP_PRIVACY) {
572                         ret = os_snprintf(pos, end - pos, "[WEP]");
573                         if (ret < 0 || ret >= end - pos)
574                                 return retpos - buf;
575                         pos += ret;
576                 }
577                 if (res->caps & IEEE80211_CAP_IBSS) {
578                         ret = os_snprintf(pos, end - pos, "[IBSS]");
579                         if (ret < 0 || ret >= end - pos)
580                                 return retpos - buf;
581                         pos += ret;
582                 }
583                 if (!res->wpa_ie_len && !res->rsn_ie_len) {
584                         ret = os_snprintf(pos, end - pos, "\t");
585                         if (ret < 0 || ret >= end - pos)
586                                 return retpos - buf;
587                         pos += ret;
588                 }
589
590                 ret = os_snprintf(pos, end - pos, "\t%s",
591                                   wpa_ssid_txt(res->ssid, res->ssid_len));
592                 if (ret < 0 || ret >= end - pos)
593                         return retpos - buf;
594                 pos += ret;
595
596                 ret = os_snprintf(pos, end - pos, "\n");
597                 if (ret < 0 || ret >= end - pos)
598                         return retpos - buf;
599                 pos += ret;
600         }
601
602         return pos - buf;
603 }
604
605
606 static int wpa_supplicant_ctrl_iface_select_network(
607         struct wpa_supplicant *wpa_s, char *cmd)
608 {
609         int id;
610         struct wpa_ssid *ssid;
611
612         /* cmd: "<network id>" or "any" */
613         if (os_strcmp(cmd, "any") == 0) {
614                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
615                 ssid = wpa_s->conf->ssid;
616                 while (ssid) {
617                         ssid->disabled = 0;
618                         ssid = ssid->next;
619                 }
620                 wpa_s->reassociate = 1;
621                 wpa_supplicant_req_scan(wpa_s, 0, 0);
622                 return 0;
623         }
624
625         id = atoi(cmd);
626         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
627
628         ssid = wpa_config_get_network(wpa_s->conf, id);
629         if (ssid == NULL) {
630                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
631                            "id=%d", id);
632                 return -1;
633         }
634
635         if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
636                 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
637
638         /* Mark all other networks disabled and trigger reassociation */
639         ssid = wpa_s->conf->ssid;
640         while (ssid) {
641                 ssid->disabled = id != ssid->id;
642                 ssid = ssid->next;
643         }
644         wpa_s->reassociate = 1;
645         wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
646         wpa_supplicant_req_scan(wpa_s, 0, 0);
647
648         return 0;
649 }
650
651
652 static int wpa_supplicant_ctrl_iface_enable_network(
653         struct wpa_supplicant *wpa_s, char *cmd)
654 {
655         int id;
656         struct wpa_ssid *ssid;
657
658         /* cmd: "<network id>" */
659         id = atoi(cmd);
660         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
661
662         ssid = wpa_config_get_network(wpa_s->conf, id);
663         if (ssid == NULL) {
664                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
665                            "id=%d", id);
666                 return -1;
667         }
668
669         if (wpa_s->current_ssid == NULL && ssid->disabled) {
670                 /*
671                  * Try to reassociate since there is no current configuration
672                  * and a new network was made available. */
673                 wpa_s->reassociate = 1;
674 #ifdef ANDROID
675                 wpa_supplicant_req_scan(wpa_s, 2, 0);
676 #else
677                 wpa_supplicant_req_scan(wpa_s, 0, 0);
678 #endif
679         }
680         ssid->disabled = 0;
681
682         return 0;
683 }
684
685
686 static int wpa_supplicant_ctrl_iface_disable_network(
687         struct wpa_supplicant *wpa_s, char *cmd)
688 {
689         int id;
690         struct wpa_ssid *ssid;
691
692         /* cmd: "<network id>" */
693         id = atoi(cmd);
694         wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
695
696         ssid = wpa_config_get_network(wpa_s->conf, id);
697         if (ssid == NULL) {
698                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
699                            "id=%d", id);
700                 return -1;
701         }
702
703         if (ssid == wpa_s->current_ssid)
704                 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
705         ssid->disabled = 1;
706
707         return 0;
708 }
709
710
711 static int wpa_supplicant_ctrl_iface_add_network(
712         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
713 {
714         struct wpa_ssid *ssid;
715         int ret;
716
717         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
718
719         ssid = wpa_config_add_network(wpa_s->conf);
720         if (ssid == NULL)
721                 return -1;
722         ssid->disabled = 1;
723         wpa_config_set_network_defaults(ssid);
724
725         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
726         if (ret < 0 || (size_t) ret >= buflen)
727                 return -1;
728         return ret;
729 }
730
731
732 static int wpa_supplicant_ctrl_iface_remove_network(
733         struct wpa_supplicant *wpa_s, char *cmd)
734 {
735         int id;
736         struct wpa_ssid *ssid;
737
738         /* cmd: "<network id>" */
739         id = atoi(cmd);
740         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
741
742         ssid = wpa_config_get_network(wpa_s->conf, id);
743         if (ssid == NULL ||
744             wpa_config_remove_network(wpa_s->conf, id) < 0) {
745                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
746                            "id=%d", id);
747                 return -1;
748         }
749
750         if (ssid == wpa_s->current_ssid) {
751                 /*
752                  * Invalidate the EAP session cache if the current network is
753                  * removed.
754                  */
755                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
756
757                 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
758         }
759
760         return 0;
761 }
762
763
764 static int wpa_supplicant_ctrl_iface_set_network(
765         struct wpa_supplicant *wpa_s, char *cmd)
766 {
767         int id;
768         struct wpa_ssid *ssid;
769         char *name, *value;
770
771         /* cmd: "<network id> <variable name> <value>" */
772         name = os_strchr(cmd, ' ');
773         if (name == NULL)
774                 return -1;
775         *name++ = '\0';
776
777         value = os_strchr(name, ' ');
778         if (value == NULL)
779                 return -1;
780         *value++ = '\0';
781
782         id = atoi(cmd);
783         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
784                    id, name);
785         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
786                               (u8 *) value, os_strlen(value));
787
788         ssid = wpa_config_get_network(wpa_s->conf, id);
789         if (ssid == NULL) {
790                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
791                            "id=%d", id);
792                 return -1;
793         }
794
795         if (wpa_config_set(ssid, name, value, 0) < 0) {
796                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
797                            "variable '%s'", name);
798                 return -1;
799         }
800
801         if (wpa_s->current_ssid == ssid) {
802                 /*
803                  * Invalidate the EAP session cache if anything in the current
804                  * configuration changes.
805                  */
806                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
807         }
808
809         if ((os_strcmp(name, "psk") == 0 &&
810              value[0] == '"' && ssid->ssid_len) ||
811             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
812                 wpa_config_update_psk(ssid);
813
814         return 0;
815 }
816
817
818 static int wpa_supplicant_ctrl_iface_get_network(
819         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
820 {
821         int id;
822         struct wpa_ssid *ssid;
823         char *name, *value;
824
825         /* cmd: "<network id> <variable name>" */
826         name = os_strchr(cmd, ' ');
827         if (name == NULL || buflen == 0)
828                 return -1;
829         *name++ = '\0';
830
831         id = atoi(cmd);
832         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
833                    id, name);
834
835         ssid = wpa_config_get_network(wpa_s->conf, id);
836         if (ssid == NULL) {
837                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
838                            "id=%d", id);
839                 return -1;
840         }
841
842         value = wpa_config_get_no_key(ssid, name);
843         if (value == NULL) {
844                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
845                            "variable '%s'", name);
846                 return -1;
847         }
848
849         os_snprintf(buf, buflen, "%s", value);
850         buf[buflen - 1] = '\0';
851
852         os_free(value);
853
854         return os_strlen(buf);
855 }
856
857
858 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
859 {
860         int ret;
861
862         if (!wpa_s->conf->update_config) {
863                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
864                            "to update configuration (update_config=0)");
865                 return -1;
866         }
867
868         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
869         if (ret) {
870                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
871                            "update configuration");
872         } else {
873                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
874                            " updated");
875         }
876
877         return ret;
878 }
879
880
881 static int wpa_supplicant_ctrl_iface_get_capability(
882         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
883         size_t buflen)
884 {
885         struct wpa_driver_capa capa;
886         int res, first = 1, ret;
887         char *pos, *end, *strict;
888         char field[30];
889
890         /* Determine whether or not strict checking was requested */
891         os_snprintf(field, sizeof(field), "%s", _field);
892         field[sizeof(field) - 1] = '\0';
893         strict = os_strchr(field, ' ');
894         if (strict != NULL) {
895                 *strict++ = '\0';
896                 if (os_strcmp(strict, "strict") != 0)
897                         return -1;
898         }
899
900         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
901                 field, strict ? strict : "");
902
903         if (os_strcmp(field, "eap") == 0) {
904                 return eap_get_names(buf, buflen);
905         }
906
907         res = wpa_drv_get_capa(wpa_s, &capa);
908
909         pos = buf;
910         end = pos + buflen;
911
912         if (os_strcmp(field, "pairwise") == 0) {
913                 if (res < 0) {
914                         if (strict)
915                                 return 0;
916                         ret = os_snprintf(buf, buflen, "CCMP TKIP NONE");
917                         if (ret < 0 || (size_t) ret >= buflen)
918                                 return -1;
919                         return ret;
920                 }
921
922                 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
923                         ret = os_snprintf(pos, end - pos, "%sCCMP",
924                                           first ? "" : " ");
925                         if (ret < 0 || ret >= end - pos)
926                                 return pos - buf;
927                         pos += ret;
928                         first = 0;
929                 }
930
931                 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
932                         ret = os_snprintf(pos, end - pos, "%sTKIP",
933                                           first ? "" : " ");
934                         if (ret < 0 || ret >= end - pos)
935                                 return pos - buf;
936                         pos += ret;
937                         first = 0;
938                 }
939
940                 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
941                         ret = os_snprintf(pos, end - pos, "%sNONE",
942                                           first ? "" : " ");
943                         if (ret < 0 || ret >= end - pos)
944                                 return pos - buf;
945                         pos += ret;
946                         first = 0;
947                 }
948
949                 return pos - buf;
950         }
951
952         if (os_strcmp(field, "group") == 0) {
953                 if (res < 0) {
954                         if (strict)
955                                 return 0;
956                         ret = os_snprintf(buf, buflen,
957                                           "CCMP TKIP WEP104 WEP40");
958                         if (ret < 0 || (size_t) ret >= buflen)
959                                 return -1;
960                         return ret;
961                 }
962
963                 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
964                         ret = os_snprintf(pos, end - pos, "%sCCMP",
965                                           first ? "" : " ");
966                         if (ret < 0 || ret >= end - pos)
967                                 return pos - buf;
968                         pos += ret;
969                         first = 0;
970                 }
971
972                 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
973                         ret = os_snprintf(pos, end - pos, "%sTKIP",
974                                           first ? "" : " ");
975                         if (ret < 0 || ret >= end - pos)
976                                 return pos - buf;
977                         pos += ret;
978                         first = 0;
979                 }
980
981                 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
982                         ret = os_snprintf(pos, end - pos, "%sWEP104",
983                                           first ? "" : " ");
984                         if (ret < 0 || ret >= end - pos)
985                                 return pos - buf;
986                         pos += ret;
987                         first = 0;
988                 }
989
990                 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
991                         ret = os_snprintf(pos, end - pos, "%sWEP40",
992                                           first ? "" : " ");
993                         if (ret < 0 || ret >= end - pos)
994                                 return pos - buf;
995                         pos += ret;
996                         first = 0;
997                 }
998
999                 return pos - buf;
1000         }
1001
1002         if (os_strcmp(field, "key_mgmt") == 0) {
1003                 if (res < 0) {
1004                         if (strict)
1005                                 return 0;
1006                         ret = os_snprintf(buf, buflen, "WPA-PSK WPA-EAP "
1007                                           "IEEE8021X WPA-NONE NONE");
1008                         if (ret < 0 || (size_t) ret >= buflen)
1009                                 return -1;
1010                         return ret;
1011                 }
1012
1013                 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
1014                 if (ret < 0 || ret >= end - pos)
1015                         return pos - buf;
1016                 pos += ret;
1017
1018                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1019                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1020                         ret = os_snprintf(pos, end - pos, " WPA-EAP");
1021                         if (ret < 0 || ret >= end - pos)
1022                                 return pos - buf;
1023                         pos += ret;
1024                 }
1025
1026                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1027                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1028                         ret = os_snprintf(pos, end - pos, " WPA-PSK");
1029                         if (ret < 0 || ret >= end - pos)
1030                                 return pos - buf;
1031                         pos += ret;
1032                 }
1033
1034                 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1035                         ret = os_snprintf(pos, end - pos, " WPA-NONE");
1036                         if (ret < 0 || ret >= end - pos)
1037                                 return pos - buf;
1038                         pos += ret;
1039                 }
1040
1041                 return pos - buf;
1042         }
1043
1044         if (os_strcmp(field, "proto") == 0) {
1045                 if (res < 0) {
1046                         if (strict)
1047                                 return 0;
1048                         ret = os_snprintf(buf, buflen, "RSN WPA");
1049                         if (ret < 0 || (size_t) ret >= buflen)
1050                                 return -1;
1051                         return ret;
1052                 }
1053
1054                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1055                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1056                         ret = os_snprintf(pos, end - pos, "%sRSN",
1057                                           first ? "" : " ");
1058                         if (ret < 0 || ret >= end - pos)
1059                                 return pos - buf;
1060                         pos += ret;
1061                         first = 0;
1062                 }
1063
1064                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1065                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1066                         ret = os_snprintf(pos, end - pos, "%sWPA",
1067                                           first ? "" : " ");
1068                         if (ret < 0 || ret >= end - pos)
1069                                 return pos - buf;
1070                         pos += ret;
1071                         first = 0;
1072                 }
1073
1074                 return pos - buf;
1075         }
1076
1077         if (os_strcmp(field, "auth_alg") == 0) {
1078                 if (res < 0) {
1079                         if (strict)
1080                                 return 0;
1081                         ret = os_snprintf(buf, buflen, "OPEN SHARED LEAP");
1082                         if (ret < 0 || (size_t) ret >= buflen)
1083                                 return -1;
1084                         return ret;
1085                 }
1086
1087                 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
1088                         ret = os_snprintf(pos, end - pos, "%sOPEN",
1089                                           first ? "" : " ");
1090                         if (ret < 0 || ret >= end - pos)
1091                                 return pos - buf;
1092                         pos += ret;
1093                         first = 0;
1094                 }
1095
1096                 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
1097                         ret = os_snprintf(pos, end - pos, "%sSHARED",
1098                                           first ? "" : " ");
1099                         if (ret < 0 || ret >= end - pos)
1100                                 return pos - buf;
1101                         pos += ret;
1102                         first = 0;
1103                 }
1104
1105                 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
1106                         ret = os_snprintf(pos, end - pos, "%sLEAP",
1107                                           first ? "" : " ");
1108                         if (ret < 0 || ret >= end - pos)
1109                                 return pos - buf;
1110                         pos += ret;
1111                         first = 0;
1112                 }
1113
1114                 return pos - buf;
1115         }
1116
1117         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
1118                    field);
1119
1120         return -1;
1121 }
1122
1123
1124 static int wpa_supplicant_ctrl_iface_ap_scan(
1125         struct wpa_supplicant *wpa_s, char *cmd)
1126 {
1127         int ap_scan = atoi(cmd);
1128
1129         if (ap_scan < 0 || ap_scan > 2)
1130                 return -1;
1131         wpa_s->conf->ap_scan = ap_scan;
1132         return 0;
1133 }
1134
1135 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, 
1136                                      char *cmd, char *buf, size_t buflen)
1137 {
1138     int ret;
1139
1140     ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
1141     if( ret == 0 ) {
1142         ret = sprintf(buf, "%s\n", "OK");
1143     }
1144     return( ret );
1145 }
1146
1147 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
1148                                          char *buf, size_t *resp_len)
1149 {
1150         char *reply;
1151         const int reply_size = 4096;
1152         int ctrl_rsp = 0;
1153         int reply_len;
1154
1155         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
1156             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
1157                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
1158                                       (const u8 *) buf, os_strlen(buf));
1159         } else {
1160         if (os_strcmp(buf, "PING") != 0)
1161             wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
1162                               (const u8 *) buf, os_strlen(buf));
1163         }
1164
1165         reply = os_malloc(reply_size);
1166         if (reply == NULL) {
1167                 *resp_len = 1;
1168                 return NULL;
1169         }
1170
1171         os_memcpy(reply, "OK\n", 3);
1172         reply_len = 3;
1173
1174         if (os_strcmp(buf, "PING") == 0) {
1175                 os_memcpy(reply, "PONG\n", 5);
1176                 reply_len = 5;
1177         } else if (os_strcmp(buf, "MIB") == 0) {
1178                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
1179                 if (reply_len >= 0) {
1180                         int res;
1181                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
1182                                                reply_size - reply_len);
1183                         if (res < 0)
1184                                 reply_len = -1;
1185                         else
1186                                 reply_len += res;
1187                 }
1188         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
1189                 reply_len = wpa_supplicant_ctrl_iface_status(
1190                         wpa_s, buf + 6, reply, reply_size);
1191         } else if (os_strcmp(buf, "PMKSA") == 0) {
1192                 reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);
1193         } else if (os_strncmp(buf, "SET ", 4) == 0) {
1194                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
1195                         reply_len = -1;
1196         } else if (os_strcmp(buf, "LOGON") == 0) {
1197                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
1198         } else if (os_strcmp(buf, "LOGOFF") == 0) {
1199                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
1200         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
1201                 wpa_s->disconnected = 0;
1202                 wpa_s->reassociate = 1;
1203                 wpa_supplicant_req_scan(wpa_s, 0, 0);
1204         } else if (os_strcmp(buf, "RECONNECT") == 0) {
1205                 if (wpa_s->disconnected) {
1206                         wpa_s->disconnected = 0;
1207                         wpa_s->reassociate = 1;
1208                         wpa_supplicant_req_scan(wpa_s, 0, 0);
1209                 }
1210 #ifdef IEEE8021X_EAPOL
1211         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
1212                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
1213                         reply_len = -1;
1214 #endif /* IEEE8021X_EAPOL */
1215 #ifdef CONFIG_PEERKEY
1216         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
1217                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
1218                         reply_len = -1;
1219 #endif /* CONFIG_PEERKEY */
1220         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
1221         {
1222                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
1223                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
1224                         reply_len = -1;
1225                 else
1226                         ctrl_rsp = 1;
1227         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
1228                 if (wpa_supplicant_reload_configuration(wpa_s))
1229                         reply_len = -1;
1230         } else if (os_strcmp(buf, "TERMINATE") == 0) {
1231                 eloop_terminate();
1232         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
1233                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
1234                         reply_len = -1;
1235 #ifdef ANDROID
1236         } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
1237                 reply_len = wpa_supplicant_ctrl_iface_blacklist(
1238                                 wpa_s, buf + 9, reply, reply_size);
1239                 if (os_strlen(buf) > 10 && reply_len == 0) {
1240                         struct wpa_blacklist *bl = wpa_s->blacklist;
1241                         if (os_strncmp(buf+10, "clear", 5) == 0 ||
1242                             (bl != NULL && os_memcmp(bl->bssid, wpa_s->bssid, ETH_ALEN) == 0)) {
1243                                 wpa_s->disconnected = 0;
1244                                 wpa_s->reassociate = 1;
1245                                 wpa_supplicant_req_scan(wpa_s, 0, 0);
1246                         }
1247                 }
1248 #endif
1249         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
1250                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
1251                         wpa_s, reply, reply_size);
1252         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
1253                 wpa_s->reassociate = 0;
1254                 wpa_s->disconnected = 1;
1255                 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
1256         } else if (os_strcmp(buf, "SCAN") == 0) {
1257                 if (!wpa_s->scan_ongoing) {
1258                         wpa_s->scan_req = 2;
1259                         wpa_supplicant_req_scan(wpa_s, 0, 0);
1260                 }
1261                 else
1262                         wpa_printf(MSG_DEBUG, "Ongoing Scan action...");
1263         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
1264                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
1265                         wpa_s, reply, reply_size);
1266         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
1267                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
1268                         reply_len = -1;
1269         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
1270                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
1271                         reply_len = -1;
1272         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
1273                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
1274                         reply_len = -1;
1275         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
1276                 reply_len = wpa_supplicant_ctrl_iface_add_network(
1277                         wpa_s, reply, reply_size);
1278         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
1279                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
1280                         reply_len = -1;
1281         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
1282                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
1283                         reply_len = -1;
1284         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
1285                 reply_len = wpa_supplicant_ctrl_iface_get_network(
1286                         wpa_s, buf + 12, reply, reply_size);
1287         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
1288                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
1289                         reply_len = -1;
1290         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
1291                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
1292                         wpa_s, buf + 15, reply, reply_size);
1293         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
1294                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
1295                         reply_len = -1;
1296         } else if (os_strcmp(buf, "INTERFACES") == 0) {
1297                 reply_len = wpa_supplicant_global_iface_interfaces(
1298                         wpa_s->global, reply, reply_size);
1299     } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
1300         reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, reply_size);
1301         } else {
1302                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1303                 reply_len = 16;
1304         }
1305
1306         if (reply_len < 0) {
1307                 os_memcpy(reply, "FAIL\n", 5);
1308                 reply_len = 5;
1309         }
1310
1311         if (ctrl_rsp)
1312                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1313
1314         *resp_len = reply_len;
1315         return reply;
1316 }
1317
1318
1319 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
1320                                            char *cmd)
1321 {
1322         struct wpa_interface iface;
1323         char *pos;
1324
1325         /*
1326          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
1327          * TAB<bridge_ifname>
1328          */
1329         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
1330
1331         os_memset(&iface, 0, sizeof(iface));
1332
1333         do {
1334                 iface.ifname = pos = cmd;
1335                 pos = os_strchr(pos, '\t');
1336                 if (pos)
1337                         *pos++ = '\0';
1338                 if (iface.ifname[0] == '\0')
1339                         return -1;
1340                 if (pos == NULL)
1341                         break;
1342
1343                 iface.confname = pos;
1344                 pos = os_strchr(pos, '\t');
1345                 if (pos)
1346                         *pos++ = '\0';
1347                 if (iface.confname[0] == '\0')
1348                         iface.confname = NULL;
1349                 if (pos == NULL)
1350                         break;
1351
1352                 iface.driver = pos;
1353                 pos = os_strchr(pos, '\t');
1354                 if (pos)
1355                         *pos++ = '\0';
1356                 if (iface.driver[0] == '\0')
1357                         iface.driver = NULL;
1358                 if (pos == NULL)
1359                         break;
1360
1361                 iface.ctrl_interface = pos;
1362                 pos = os_strchr(pos, '\t');
1363                 if (pos)
1364                         *pos++ = '\0';
1365                 if (iface.ctrl_interface[0] == '\0')
1366                         iface.ctrl_interface = NULL;
1367                 if (pos == NULL)
1368                         break;
1369
1370                 iface.driver_param = pos;
1371                 pos = os_strchr(pos, '\t');
1372                 if (pos)
1373                         *pos++ = '\0';
1374                 if (iface.driver_param[0] == '\0')
1375                         iface.driver_param = NULL;
1376                 if (pos == NULL)
1377                         break;
1378
1379                 iface.bridge_ifname = pos;
1380                 pos = os_strchr(pos, '\t');
1381                 if (pos)
1382                         *pos++ = '\0';
1383                 if (iface.bridge_ifname[0] == '\0')
1384                         iface.bridge_ifname = NULL;
1385                 if (pos == NULL)
1386                         break;
1387         } while (0);
1388
1389         if (wpa_supplicant_get_iface(global, iface.ifname))
1390                 return -1;
1391
1392         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
1393 }
1394
1395
1396 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
1397                                               char *cmd)
1398 {
1399         struct wpa_supplicant *wpa_s;
1400
1401         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
1402
1403         wpa_s = wpa_supplicant_get_iface(global, cmd);
1404         if (wpa_s == NULL)
1405                 return -1;
1406         return wpa_supplicant_remove_iface(global, wpa_s);
1407 }
1408
1409
1410 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
1411                                                   char *buf, int len)
1412 {
1413         int res;
1414         char *pos, *end;
1415         struct wpa_supplicant *wpa_s;
1416
1417         wpa_s = global->ifaces;
1418         pos = buf;
1419         end = buf + len;
1420
1421         while (wpa_s) {
1422                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
1423                 if (res < 0 || res >= end - pos) {
1424                         *pos = '\0';
1425                         break;
1426                 }
1427                 pos += res;
1428                 wpa_s = wpa_s->next;
1429         }
1430         return pos - buf;
1431 }
1432
1433
1434 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
1435                                                 char *buf, size_t *resp_len)
1436 {
1437         char *reply;
1438         const int reply_size = 4096;
1439         int reply_len;
1440
1441     if (os_strcmp(buf, "PING") != 0)
1442         wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
1443                           (const u8 *) buf, os_strlen(buf));
1444
1445         reply = os_malloc(reply_size);
1446         if (reply == NULL) {
1447                 *resp_len = 1;
1448                 return NULL;
1449         }
1450
1451         os_memcpy(reply, "OK\n", 3);
1452         reply_len = 3;
1453
1454         if (os_strcmp(buf, "PING") == 0) {
1455                 os_memcpy(reply, "PONG\n", 5);
1456                 reply_len = 5;
1457         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
1458                 if (wpa_supplicant_global_iface_add(global, buf + 14))
1459                         reply_len = -1;
1460         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
1461                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
1462                         reply_len = -1;
1463         } else if (os_strcmp(buf, "INTERFACES") == 0) {
1464                 reply_len = wpa_supplicant_global_iface_interfaces(
1465                         global, reply, reply_size);
1466         } else if (os_strcmp(buf, "TERMINATE") == 0) {
1467                 eloop_terminate();
1468         } else {
1469                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1470                 reply_len = 16;
1471         }
1472
1473         if (reply_len < 0) {
1474                 os_memcpy(reply, "FAIL\n", 5);
1475                 reply_len = 5;
1476         }
1477
1478         *resp_len = reply_len;
1479         return reply;
1480 }