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