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