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