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