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