OSDN Git Service

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