]> git.ipfire.org Git - thirdparty/hostap.git/blob - hostapd/ctrl_iface.c
Fix memory leak in hostapd BSS_TM_REQ error path handling
[thirdparty/hostap.git] / hostapd / ctrl_iface.c
1 /*
2 * hostapd / UNIX domain socket -based control interface
3 * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "utils/includes.h"
10
11 #ifndef CONFIG_NATIVE_WINDOWS
12
13 #ifdef CONFIG_TESTING_OPTIONS
14 #include <net/ethernet.h>
15 #include <netinet/ip.h>
16 #endif /* CONFIG_TESTING_OPTIONS */
17
18 #include <sys/un.h>
19 #include <sys/stat.h>
20 #include <stddef.h>
21
22 #ifdef CONFIG_CTRL_IFACE_UDP
23 #include <netdb.h>
24 #endif /* CONFIG_CTRL_IFACE_UDP */
25
26 #include "utils/common.h"
27 #include "utils/eloop.h"
28 #include "utils/module_tests.h"
29 #include "common/version.h"
30 #include "common/ieee802_11_defs.h"
31 #include "common/ctrl_iface_common.h"
32 #include "crypto/tls.h"
33 #include "drivers/driver.h"
34 #include "eapol_auth/eapol_auth_sm.h"
35 #include "radius/radius_client.h"
36 #include "radius/radius_server.h"
37 #include "l2_packet/l2_packet.h"
38 #include "ap/hostapd.h"
39 #include "ap/ap_config.h"
40 #include "ap/ieee802_1x.h"
41 #include "ap/wpa_auth.h"
42 #include "ap/ieee802_11.h"
43 #include "ap/sta_info.h"
44 #include "ap/wps_hostapd.h"
45 #include "ap/ctrl_iface_ap.h"
46 #include "ap/ap_drv_ops.h"
47 #include "ap/hs20.h"
48 #include "ap/wnm_ap.h"
49 #include "ap/wpa_auth.h"
50 #include "ap/beacon.h"
51 #include "ap/neighbor_db.h"
52 #include "ap/rrm.h"
53 #include "wps/wps_defs.h"
54 #include "wps/wps.h"
55 #include "fst/fst_ctrl_iface.h"
56 #include "config_file.h"
57 #include "ctrl_iface.h"
58
59
60 #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
61
62 #ifdef CONFIG_CTRL_IFACE_UDP
63 #define COOKIE_LEN 8
64 static unsigned char cookie[COOKIE_LEN];
65 static unsigned char gcookie[COOKIE_LEN];
66 #define HOSTAPD_CTRL_IFACE_PORT 8877
67 #define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50
68 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878
69 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT 50
70 #endif /* CONFIG_CTRL_IFACE_UDP */
71
72 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
73 enum wpa_msg_type type,
74 const char *buf, size_t len);
75
76
77 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
78 struct sockaddr_storage *from,
79 socklen_t fromlen)
80 {
81 return ctrl_iface_attach(&hapd->ctrl_dst, from, fromlen);
82 }
83
84
85 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
86 struct sockaddr_storage *from,
87 socklen_t fromlen)
88 {
89 return ctrl_iface_detach(&hapd->ctrl_dst, from, fromlen);
90 }
91
92
93 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
94 struct sockaddr_storage *from,
95 socklen_t fromlen,
96 char *level)
97 {
98 return ctrl_iface_level(&hapd->ctrl_dst, from, fromlen, level);
99 }
100
101
102 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
103 const char *txtaddr)
104 {
105 u8 addr[ETH_ALEN];
106 struct sta_info *sta;
107
108 wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
109
110 if (hwaddr_aton(txtaddr, addr))
111 return -1;
112
113 sta = ap_get_sta(hapd, addr);
114 if (sta)
115 return 0;
116
117 wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
118 "notification", MAC2STR(addr));
119 sta = ap_sta_add(hapd, addr);
120 if (sta == NULL)
121 return -1;
122
123 hostapd_new_assoc_sta(hapd, sta, 0);
124 return 0;
125 }
126
127
128 #ifdef CONFIG_IEEE80211W
129 #ifdef NEED_AP_MLME
130 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
131 const char *txtaddr)
132 {
133 u8 addr[ETH_ALEN];
134 u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
135
136 wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
137
138 if (hwaddr_aton(txtaddr, addr) ||
139 os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
140 return -1;
141
142 ieee802_11_send_sa_query_req(hapd, addr, trans_id);
143
144 return 0;
145 }
146 #endif /* NEED_AP_MLME */
147 #endif /* CONFIG_IEEE80211W */
148
149
150 #ifdef CONFIG_WPS
151 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
152 {
153 char *pin = os_strchr(txt, ' ');
154 char *timeout_txt;
155 int timeout;
156 u8 addr_buf[ETH_ALEN], *addr = NULL;
157 char *pos;
158
159 if (pin == NULL)
160 return -1;
161 *pin++ = '\0';
162
163 timeout_txt = os_strchr(pin, ' ');
164 if (timeout_txt) {
165 *timeout_txt++ = '\0';
166 timeout = atoi(timeout_txt);
167 pos = os_strchr(timeout_txt, ' ');
168 if (pos) {
169 *pos++ = '\0';
170 if (hwaddr_aton(pos, addr_buf) == 0)
171 addr = addr_buf;
172 }
173 } else
174 timeout = 0;
175
176 return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
177 }
178
179
180 static int hostapd_ctrl_iface_wps_check_pin(
181 struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
182 {
183 char pin[9];
184 size_t len;
185 char *pos;
186 int ret;
187
188 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
189 (u8 *) cmd, os_strlen(cmd));
190 for (pos = cmd, len = 0; *pos != '\0'; pos++) {
191 if (*pos < '0' || *pos > '9')
192 continue;
193 pin[len++] = *pos;
194 if (len == 9) {
195 wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
196 return -1;
197 }
198 }
199 if (len != 4 && len != 8) {
200 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
201 return -1;
202 }
203 pin[len] = '\0';
204
205 if (len == 8) {
206 unsigned int pin_val;
207 pin_val = atoi(pin);
208 if (!wps_pin_valid(pin_val)) {
209 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
210 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
211 if (os_snprintf_error(buflen, ret))
212 return -1;
213 return ret;
214 }
215 }
216
217 ret = os_snprintf(buf, buflen, "%s", pin);
218 if (os_snprintf_error(buflen, ret))
219 return -1;
220
221 return ret;
222 }
223
224
225 #ifdef CONFIG_WPS_NFC
226 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
227 char *pos)
228 {
229 size_t len;
230 struct wpabuf *buf;
231 int ret;
232
233 len = os_strlen(pos);
234 if (len & 0x01)
235 return -1;
236 len /= 2;
237
238 buf = wpabuf_alloc(len);
239 if (buf == NULL)
240 return -1;
241 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
242 wpabuf_free(buf);
243 return -1;
244 }
245
246 ret = hostapd_wps_nfc_tag_read(hapd, buf);
247 wpabuf_free(buf);
248
249 return ret;
250 }
251
252
253 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
254 char *cmd, char *reply,
255 size_t max_len)
256 {
257 int ndef;
258 struct wpabuf *buf;
259 int res;
260
261 if (os_strcmp(cmd, "WPS") == 0)
262 ndef = 0;
263 else if (os_strcmp(cmd, "NDEF") == 0)
264 ndef = 1;
265 else
266 return -1;
267
268 buf = hostapd_wps_nfc_config_token(hapd, ndef);
269 if (buf == NULL)
270 return -1;
271
272 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
273 wpabuf_len(buf));
274 reply[res++] = '\n';
275 reply[res] = '\0';
276
277 wpabuf_free(buf);
278
279 return res;
280 }
281
282
283 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
284 char *reply, size_t max_len,
285 int ndef)
286 {
287 struct wpabuf *buf;
288 int res;
289
290 buf = hostapd_wps_nfc_token_gen(hapd, ndef);
291 if (buf == NULL)
292 return -1;
293
294 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
295 wpabuf_len(buf));
296 reply[res++] = '\n';
297 reply[res] = '\0';
298
299 wpabuf_free(buf);
300
301 return res;
302 }
303
304
305 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
306 char *cmd, char *reply,
307 size_t max_len)
308 {
309 if (os_strcmp(cmd, "WPS") == 0)
310 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
311 max_len, 0);
312
313 if (os_strcmp(cmd, "NDEF") == 0)
314 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
315 max_len, 1);
316
317 if (os_strcmp(cmd, "enable") == 0)
318 return hostapd_wps_nfc_token_enable(hapd);
319
320 if (os_strcmp(cmd, "disable") == 0) {
321 hostapd_wps_nfc_token_disable(hapd);
322 return 0;
323 }
324
325 return -1;
326 }
327
328
329 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
330 char *cmd, char *reply,
331 size_t max_len)
332 {
333 struct wpabuf *buf;
334 int res;
335 char *pos;
336 int ndef;
337
338 pos = os_strchr(cmd, ' ');
339 if (pos == NULL)
340 return -1;
341 *pos++ = '\0';
342
343 if (os_strcmp(cmd, "WPS") == 0)
344 ndef = 0;
345 else if (os_strcmp(cmd, "NDEF") == 0)
346 ndef = 1;
347 else
348 return -1;
349
350 if (os_strcmp(pos, "WPS-CR") == 0)
351 buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
352 else
353 buf = NULL;
354 if (buf == NULL)
355 return -1;
356
357 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
358 wpabuf_len(buf));
359 reply[res++] = '\n';
360 reply[res] = '\0';
361
362 wpabuf_free(buf);
363
364 return res;
365 }
366
367
368 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
369 char *cmd)
370 {
371 size_t len;
372 struct wpabuf *req, *sel;
373 int ret;
374 char *pos, *role, *type, *pos2;
375
376 role = cmd;
377 pos = os_strchr(role, ' ');
378 if (pos == NULL)
379 return -1;
380 *pos++ = '\0';
381
382 type = pos;
383 pos = os_strchr(type, ' ');
384 if (pos == NULL)
385 return -1;
386 *pos++ = '\0';
387
388 pos2 = os_strchr(pos, ' ');
389 if (pos2 == NULL)
390 return -1;
391 *pos2++ = '\0';
392
393 len = os_strlen(pos);
394 if (len & 0x01)
395 return -1;
396 len /= 2;
397
398 req = wpabuf_alloc(len);
399 if (req == NULL)
400 return -1;
401 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
402 wpabuf_free(req);
403 return -1;
404 }
405
406 len = os_strlen(pos2);
407 if (len & 0x01) {
408 wpabuf_free(req);
409 return -1;
410 }
411 len /= 2;
412
413 sel = wpabuf_alloc(len);
414 if (sel == NULL) {
415 wpabuf_free(req);
416 return -1;
417 }
418 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
419 wpabuf_free(req);
420 wpabuf_free(sel);
421 return -1;
422 }
423
424 if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
425 ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
426 } else {
427 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
428 "reported: role=%s type=%s", role, type);
429 ret = -1;
430 }
431 wpabuf_free(req);
432 wpabuf_free(sel);
433
434 return ret;
435 }
436
437 #endif /* CONFIG_WPS_NFC */
438
439
440 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
441 char *buf, size_t buflen)
442 {
443 int timeout = 300;
444 char *pos;
445 const char *pin_txt;
446
447 pos = os_strchr(txt, ' ');
448 if (pos)
449 *pos++ = '\0';
450
451 if (os_strcmp(txt, "disable") == 0) {
452 hostapd_wps_ap_pin_disable(hapd);
453 return os_snprintf(buf, buflen, "OK\n");
454 }
455
456 if (os_strcmp(txt, "random") == 0) {
457 if (pos)
458 timeout = atoi(pos);
459 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
460 if (pin_txt == NULL)
461 return -1;
462 return os_snprintf(buf, buflen, "%s", pin_txt);
463 }
464
465 if (os_strcmp(txt, "get") == 0) {
466 pin_txt = hostapd_wps_ap_pin_get(hapd);
467 if (pin_txt == NULL)
468 return -1;
469 return os_snprintf(buf, buflen, "%s", pin_txt);
470 }
471
472 if (os_strcmp(txt, "set") == 0) {
473 char *pin;
474 if (pos == NULL)
475 return -1;
476 pin = pos;
477 pos = os_strchr(pos, ' ');
478 if (pos) {
479 *pos++ = '\0';
480 timeout = atoi(pos);
481 }
482 if (os_strlen(pin) > buflen)
483 return -1;
484 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
485 return -1;
486 return os_snprintf(buf, buflen, "%s", pin);
487 }
488
489 return -1;
490 }
491
492
493 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
494 {
495 char *pos;
496 char *ssid, *auth, *encr = NULL, *key = NULL;
497
498 ssid = txt;
499 pos = os_strchr(txt, ' ');
500 if (!pos)
501 return -1;
502 *pos++ = '\0';
503
504 auth = pos;
505 pos = os_strchr(pos, ' ');
506 if (pos) {
507 *pos++ = '\0';
508 encr = pos;
509 pos = os_strchr(pos, ' ');
510 if (pos) {
511 *pos++ = '\0';
512 key = pos;
513 }
514 }
515
516 return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
517 }
518
519
520 static const char * pbc_status_str(enum pbc_status status)
521 {
522 switch (status) {
523 case WPS_PBC_STATUS_DISABLE:
524 return "Disabled";
525 case WPS_PBC_STATUS_ACTIVE:
526 return "Active";
527 case WPS_PBC_STATUS_TIMEOUT:
528 return "Timed-out";
529 case WPS_PBC_STATUS_OVERLAP:
530 return "Overlap";
531 default:
532 return "Unknown";
533 }
534 }
535
536
537 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
538 char *buf, size_t buflen)
539 {
540 int ret;
541 char *pos, *end;
542
543 pos = buf;
544 end = buf + buflen;
545
546 ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
547 pbc_status_str(hapd->wps_stats.pbc_status));
548
549 if (os_snprintf_error(end - pos, ret))
550 return pos - buf;
551 pos += ret;
552
553 ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
554 (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
555 "Success":
556 (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
557 "Failed" : "None")));
558
559 if (os_snprintf_error(end - pos, ret))
560 return pos - buf;
561 pos += ret;
562
563 /* If status == Failure - Add possible Reasons */
564 if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
565 hapd->wps_stats.failure_reason > 0) {
566 ret = os_snprintf(pos, end - pos,
567 "Failure Reason: %s\n",
568 wps_ei_str(hapd->wps_stats.failure_reason));
569
570 if (os_snprintf_error(end - pos, ret))
571 return pos - buf;
572 pos += ret;
573 }
574
575 if (hapd->wps_stats.status) {
576 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
577 MAC2STR(hapd->wps_stats.peer_addr));
578
579 if (os_snprintf_error(end - pos, ret))
580 return pos - buf;
581 pos += ret;
582 }
583
584 return pos - buf;
585 }
586
587 #endif /* CONFIG_WPS */
588
589 #ifdef CONFIG_HS20
590
591 static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
592 const char *cmd)
593 {
594 u8 addr[ETH_ALEN];
595 const char *url;
596
597 if (hwaddr_aton(cmd, addr))
598 return -1;
599 url = cmd + 17;
600 if (*url == '\0') {
601 url = NULL;
602 } else {
603 if (*url != ' ')
604 return -1;
605 url++;
606 if (*url == '\0')
607 url = NULL;
608 }
609
610 return hs20_send_wnm_notification(hapd, addr, 1, url);
611 }
612
613
614 static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
615 const char *cmd)
616 {
617 u8 addr[ETH_ALEN];
618 int code, reauth_delay, ret;
619 const char *pos;
620 size_t url_len;
621 struct wpabuf *req;
622
623 /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
624 if (hwaddr_aton(cmd, addr))
625 return -1;
626
627 pos = os_strchr(cmd, ' ');
628 if (pos == NULL)
629 return -1;
630 pos++;
631 code = atoi(pos);
632
633 pos = os_strchr(pos, ' ');
634 if (pos == NULL)
635 return -1;
636 pos++;
637 reauth_delay = atoi(pos);
638
639 url_len = 0;
640 pos = os_strchr(pos, ' ');
641 if (pos) {
642 pos++;
643 url_len = os_strlen(pos);
644 }
645
646 req = wpabuf_alloc(4 + url_len);
647 if (req == NULL)
648 return -1;
649 wpabuf_put_u8(req, code);
650 wpabuf_put_le16(req, reauth_delay);
651 wpabuf_put_u8(req, url_len);
652 if (pos)
653 wpabuf_put_data(req, pos, url_len);
654
655 wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
656 " to indicate imminent deauthentication (code=%d "
657 "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
658 ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
659 wpabuf_free(req);
660 return ret;
661 }
662
663 #endif /* CONFIG_HS20 */
664
665
666 #ifdef CONFIG_INTERWORKING
667
668 static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
669 const char *cmd)
670 {
671 u8 qos_map_set[16 + 2 * 21], count = 0;
672 const char *pos = cmd;
673 int val, ret;
674
675 for (;;) {
676 if (count == sizeof(qos_map_set)) {
677 wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
678 return -1;
679 }
680
681 val = atoi(pos);
682 if (val < 0 || val > 255) {
683 wpa_printf(MSG_INFO, "Invalid QoS Map Set");
684 return -1;
685 }
686
687 qos_map_set[count++] = val;
688 pos = os_strchr(pos, ',');
689 if (!pos)
690 break;
691 pos++;
692 }
693
694 if (count < 16 || count & 1) {
695 wpa_printf(MSG_INFO, "Invalid QoS Map Set");
696 return -1;
697 }
698
699 ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
700 if (ret) {
701 wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
702 return -1;
703 }
704
705 os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
706 hapd->conf->qos_map_set_len = count;
707
708 return 0;
709 }
710
711
712 static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
713 const char *cmd)
714 {
715 u8 addr[ETH_ALEN];
716 struct sta_info *sta;
717 struct wpabuf *buf;
718 u8 *qos_map_set = hapd->conf->qos_map_set;
719 u8 qos_map_set_len = hapd->conf->qos_map_set_len;
720 int ret;
721
722 if (!qos_map_set_len) {
723 wpa_printf(MSG_INFO, "QoS Map Set is not set");
724 return -1;
725 }
726
727 if (hwaddr_aton(cmd, addr))
728 return -1;
729
730 sta = ap_get_sta(hapd, addr);
731 if (sta == NULL) {
732 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
733 "for QoS Map Configuration message",
734 MAC2STR(addr));
735 return -1;
736 }
737
738 if (!sta->qos_map_enabled) {
739 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
740 "support for QoS Map", MAC2STR(addr));
741 return -1;
742 }
743
744 buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
745 if (buf == NULL)
746 return -1;
747
748 wpabuf_put_u8(buf, WLAN_ACTION_QOS);
749 wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
750
751 /* QoS Map Set Element */
752 wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
753 wpabuf_put_u8(buf, qos_map_set_len);
754 wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
755
756 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
757 wpabuf_head(buf), wpabuf_len(buf));
758 wpabuf_free(buf);
759
760 return ret;
761 }
762
763 #endif /* CONFIG_INTERWORKING */
764
765
766 #ifdef CONFIG_WNM
767
768 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
769 const char *cmd)
770 {
771 u8 addr[ETH_ALEN];
772 int disassoc_timer;
773 struct sta_info *sta;
774
775 if (hwaddr_aton(cmd, addr))
776 return -1;
777 if (cmd[17] != ' ')
778 return -1;
779 disassoc_timer = atoi(cmd + 17);
780
781 sta = ap_get_sta(hapd, addr);
782 if (sta == NULL) {
783 wpa_printf(MSG_DEBUG, "Station " MACSTR
784 " not found for disassociation imminent message",
785 MAC2STR(addr));
786 return -1;
787 }
788
789 return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
790 }
791
792
793 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
794 const char *cmd)
795 {
796 u8 addr[ETH_ALEN];
797 const char *url, *timerstr;
798 int disassoc_timer;
799 struct sta_info *sta;
800
801 if (hwaddr_aton(cmd, addr))
802 return -1;
803
804 sta = ap_get_sta(hapd, addr);
805 if (sta == NULL) {
806 wpa_printf(MSG_DEBUG, "Station " MACSTR
807 " not found for ESS disassociation imminent message",
808 MAC2STR(addr));
809 return -1;
810 }
811
812 timerstr = cmd + 17;
813 if (*timerstr != ' ')
814 return -1;
815 timerstr++;
816 disassoc_timer = atoi(timerstr);
817 if (disassoc_timer < 0 || disassoc_timer > 65535)
818 return -1;
819
820 url = os_strchr(timerstr, ' ');
821 if (url == NULL)
822 return -1;
823 url++;
824
825 return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
826 }
827
828
829 static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
830 const char *cmd)
831 {
832 u8 addr[ETH_ALEN];
833 const char *pos, *end;
834 int disassoc_timer = 0;
835 struct sta_info *sta;
836 u8 req_mode = 0, valid_int = 0x01;
837 u8 bss_term_dur[12];
838 char *url = NULL;
839 int ret;
840 u8 nei_rep[1000];
841 u8 *nei_pos = nei_rep;
842 u8 mbo[10];
843 size_t mbo_len = 0;
844
845 if (hwaddr_aton(cmd, addr)) {
846 wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
847 return -1;
848 }
849
850 sta = ap_get_sta(hapd, addr);
851 if (sta == NULL) {
852 wpa_printf(MSG_DEBUG, "Station " MACSTR
853 " not found for BSS TM Request message",
854 MAC2STR(addr));
855 return -1;
856 }
857
858 pos = os_strstr(cmd, " disassoc_timer=");
859 if (pos) {
860 pos += 16;
861 disassoc_timer = atoi(pos);
862 if (disassoc_timer < 0 || disassoc_timer > 65535) {
863 wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
864 return -1;
865 }
866 }
867
868 pos = os_strstr(cmd, " valid_int=");
869 if (pos) {
870 pos += 11;
871 valid_int = atoi(pos);
872 }
873
874 pos = os_strstr(cmd, " bss_term=");
875 if (pos) {
876 pos += 10;
877 req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
878 /* TODO: TSF configurable/learnable */
879 bss_term_dur[0] = 4; /* Subelement ID */
880 bss_term_dur[1] = 10; /* Length */
881 os_memset(bss_term_dur, 2, 8);
882 end = os_strchr(pos, ',');
883 if (end == NULL) {
884 wpa_printf(MSG_DEBUG, "Invalid bss_term data");
885 return -1;
886 }
887 end++;
888 WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
889 }
890
891
892 /*
893 * BSS Transition Candidate List Entries - Neighbor Report elements
894 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
895 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
896 */
897 pos = cmd;
898 while (pos) {
899 u8 *nei_start;
900 long int val;
901 char *endptr, *tmp;
902
903 pos = os_strstr(pos, " neighbor=");
904 if (!pos)
905 break;
906 if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) {
907 wpa_printf(MSG_DEBUG,
908 "Not enough room for additional neighbor");
909 return -1;
910 }
911 pos += 10;
912
913 nei_start = nei_pos;
914 *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
915 nei_pos++; /* length to be filled in */
916
917 if (hwaddr_aton(pos, nei_pos)) {
918 wpa_printf(MSG_DEBUG, "Invalid BSSID");
919 return -1;
920 }
921 nei_pos += ETH_ALEN;
922 pos += 17;
923 if (*pos != ',') {
924 wpa_printf(MSG_DEBUG, "Missing BSSID Information");
925 return -1;
926 }
927 pos++;
928
929 val = strtol(pos, &endptr, 0);
930 WPA_PUT_LE32(nei_pos, val);
931 nei_pos += 4;
932 if (*endptr != ',') {
933 wpa_printf(MSG_DEBUG, "Missing Operating Class");
934 return -1;
935 }
936 pos = endptr + 1;
937
938 *nei_pos++ = atoi(pos); /* Operating Class */
939 pos = os_strchr(pos, ',');
940 if (pos == NULL) {
941 wpa_printf(MSG_DEBUG, "Missing Channel Number");
942 return -1;
943 }
944 pos++;
945
946 *nei_pos++ = atoi(pos); /* Channel Number */
947 pos = os_strchr(pos, ',');
948 if (pos == NULL) {
949 wpa_printf(MSG_DEBUG, "Missing PHY Type");
950 return -1;
951 }
952 pos++;
953
954 *nei_pos++ = atoi(pos); /* PHY Type */
955 end = os_strchr(pos, ' ');
956 tmp = os_strchr(pos, ',');
957 if (tmp && (!end || tmp < end)) {
958 /* Optional Subelements (hexdump) */
959 size_t len;
960
961 pos = tmp + 1;
962 end = os_strchr(pos, ' ');
963 if (end)
964 len = end - pos;
965 else
966 len = os_strlen(pos);
967 if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) {
968 wpa_printf(MSG_DEBUG,
969 "Not enough room for neighbor subelements");
970 return -1;
971 }
972 if (len & 0x01 ||
973 hexstr2bin(pos, nei_pos, len / 2) < 0) {
974 wpa_printf(MSG_DEBUG,
975 "Invalid neighbor subelement info");
976 return -1;
977 }
978 nei_pos += len / 2;
979 pos = end;
980 }
981
982 nei_start[1] = nei_pos - nei_start - 2;
983 }
984
985 pos = os_strstr(cmd, " url=");
986 if (pos) {
987 size_t len;
988 pos += 5;
989 end = os_strchr(pos, ' ');
990 if (end)
991 len = end - pos;
992 else
993 len = os_strlen(pos);
994 url = os_malloc(len + 1);
995 if (url == NULL)
996 return -1;
997 os_memcpy(url, pos, len);
998 url[len] = '\0';
999 req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
1000 }
1001
1002 if (os_strstr(cmd, " pref=1"))
1003 req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
1004 if (os_strstr(cmd, " abridged=1"))
1005 req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
1006 if (os_strstr(cmd, " disassoc_imminent=1"))
1007 req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
1008
1009 #ifdef CONFIG_MBO
1010 pos = os_strstr(cmd, "mbo=");
1011 if (pos) {
1012 unsigned int mbo_reason, cell_pref, reassoc_delay;
1013 u8 *mbo_pos = mbo;
1014
1015 ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
1016 &reassoc_delay, &cell_pref);
1017 if (ret != 3) {
1018 wpa_printf(MSG_DEBUG,
1019 "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
1020 ret = -1;
1021 goto fail;
1022 }
1023
1024 if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
1025 wpa_printf(MSG_DEBUG,
1026 "Invalid MBO transition reason code %u",
1027 mbo_reason);
1028 ret = -1;
1029 goto fail;
1030 }
1031
1032 /* Valid values for Cellular preference are: 0, 1, 255 */
1033 if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) {
1034 wpa_printf(MSG_DEBUG,
1035 "Invalid MBO cellular capability %u",
1036 cell_pref);
1037 ret = -1;
1038 goto fail;
1039 }
1040
1041 if (reassoc_delay > 65535 ||
1042 (reassoc_delay &&
1043 !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) {
1044 wpa_printf(MSG_DEBUG,
1045 "MBO: Assoc retry delay is only valid in disassoc imminent mode");
1046 ret = -1;
1047 goto fail;
1048 }
1049
1050 *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
1051 *mbo_pos++ = 1;
1052 *mbo_pos++ = mbo_reason;
1053 *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
1054 *mbo_pos++ = 1;
1055 *mbo_pos++ = cell_pref;
1056
1057 if (reassoc_delay) {
1058 *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
1059 *mbo_pos++ = 2;
1060 WPA_PUT_LE16(mbo_pos, reassoc_delay);
1061 mbo_pos += 2;
1062 }
1063
1064 mbo_len = mbo_pos - mbo;
1065 }
1066 #endif /* CONFIG_MBO */
1067
1068 ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
1069 valid_int, bss_term_dur, url,
1070 nei_pos > nei_rep ? nei_rep : NULL,
1071 nei_pos - nei_rep, mbo_len ? mbo : NULL,
1072 mbo_len);
1073 fail:
1074 os_free(url);
1075 return ret;
1076 }
1077
1078 #endif /* CONFIG_WNM */
1079
1080
1081 static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd,
1082 char *buf, size_t buflen)
1083 {
1084 int ret = 0;
1085 char *pos, *end;
1086
1087 pos = buf;
1088 end = buf + buflen;
1089
1090 WPA_ASSERT(hapd->conf->wpa_key_mgmt);
1091
1092 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
1093 ret = os_snprintf(pos, end - pos, "WPA-PSK ");
1094 if (os_snprintf_error(end - pos, ret))
1095 return pos - buf;
1096 pos += ret;
1097 }
1098 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1099 ret = os_snprintf(pos, end - pos, "WPA-EAP ");
1100 if (os_snprintf_error(end - pos, ret))
1101 return pos - buf;
1102 pos += ret;
1103 }
1104 #ifdef CONFIG_IEEE80211R_AP
1105 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1106 ret = os_snprintf(pos, end - pos, "FT-PSK ");
1107 if (os_snprintf_error(end - pos, ret))
1108 return pos - buf;
1109 pos += ret;
1110 }
1111 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1112 ret = os_snprintf(pos, end - pos, "FT-EAP ");
1113 if (os_snprintf_error(end - pos, ret))
1114 return pos - buf;
1115 pos += ret;
1116 }
1117 #ifdef CONFIG_SAE
1118 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
1119 ret = os_snprintf(pos, end - pos, "FT-SAE ");
1120 if (os_snprintf_error(end - pos, ret))
1121 return pos - buf;
1122 pos += ret;
1123 }
1124 #endif /* CONFIG_SAE */
1125 #ifdef CONFIG_FILS
1126 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
1127 ret = os_snprintf(pos, end - pos, "FT-FILS-SHA256 ");
1128 if (os_snprintf_error(end - pos, ret))
1129 return pos - buf;
1130 pos += ret;
1131 }
1132 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
1133 ret = os_snprintf(pos, end - pos, "FT-FILS-SHA384 ");
1134 if (os_snprintf_error(end - pos, ret))
1135 return pos - buf;
1136 pos += ret;
1137 }
1138 #endif /* CONFIG_FILS */
1139 #endif /* CONFIG_IEEE80211R_AP */
1140 #ifdef CONFIG_IEEE80211W
1141 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1142 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
1143 if (os_snprintf_error(end - pos, ret))
1144 return pos - buf;
1145 pos += ret;
1146 }
1147 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1148 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
1149 if (os_snprintf_error(end - pos, ret))
1150 return pos - buf;
1151 pos += ret;
1152 }
1153 #endif /* CONFIG_IEEE80211W */
1154 #ifdef CONFIG_SAE
1155 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
1156 ret = os_snprintf(pos, end - pos, "SAE ");
1157 if (os_snprintf_error(end - pos, ret))
1158 return pos - buf;
1159 pos += ret;
1160 }
1161 #endif /* CONFIG_SAE */
1162 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1163 ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
1164 if (os_snprintf_error(end - pos, ret))
1165 return pos - buf;
1166 pos += ret;
1167 }
1168 if (hapd->conf->wpa_key_mgmt &
1169 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1170 ret = os_snprintf(pos, end - pos,
1171 "WPA-EAP-SUITE-B-192 ");
1172 if (os_snprintf_error(end - pos, ret))
1173 return pos - buf;
1174 pos += ret;
1175 }
1176 #ifdef CONFIG_FILS
1177 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
1178 ret = os_snprintf(pos, end - pos, "FILS-SHA256 ");
1179 if (os_snprintf_error(end - pos, ret))
1180 return pos - buf;
1181 pos += ret;
1182 }
1183 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
1184 ret = os_snprintf(pos, end - pos, "FILS-SHA384 ");
1185 if (os_snprintf_error(end - pos, ret))
1186 return pos - buf;
1187 pos += ret;
1188 }
1189 #endif /* CONFIG_FILS */
1190
1191 if (pos > buf && *(pos - 1) == ' ') {
1192 *(pos - 1) = '\0';
1193 pos--;
1194 }
1195
1196 return pos - buf;
1197 }
1198
1199
1200 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
1201 char *buf, size_t buflen)
1202 {
1203 int ret;
1204 char *pos, *end;
1205
1206 pos = buf;
1207 end = buf + buflen;
1208
1209 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
1210 "ssid=%s\n",
1211 MAC2STR(hapd->own_addr),
1212 wpa_ssid_txt(hapd->conf->ssid.ssid,
1213 hapd->conf->ssid.ssid_len));
1214 if (os_snprintf_error(end - pos, ret))
1215 return pos - buf;
1216 pos += ret;
1217
1218 #ifdef CONFIG_WPS
1219 ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
1220 hapd->conf->wps_state == 0 ? "disabled" :
1221 (hapd->conf->wps_state == 1 ? "not configured" :
1222 "configured"));
1223 if (os_snprintf_error(end - pos, ret))
1224 return pos - buf;
1225 pos += ret;
1226
1227 if (hapd->conf->wps_state && hapd->conf->wpa &&
1228 hapd->conf->ssid.wpa_passphrase) {
1229 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
1230 hapd->conf->ssid.wpa_passphrase);
1231 if (os_snprintf_error(end - pos, ret))
1232 return pos - buf;
1233 pos += ret;
1234 }
1235
1236 if (hapd->conf->wps_state && hapd->conf->wpa &&
1237 hapd->conf->ssid.wpa_psk &&
1238 hapd->conf->ssid.wpa_psk->group) {
1239 char hex[PMK_LEN * 2 + 1];
1240 wpa_snprintf_hex(hex, sizeof(hex),
1241 hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
1242 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
1243 if (os_snprintf_error(end - pos, ret))
1244 return pos - buf;
1245 pos += ret;
1246 }
1247 #endif /* CONFIG_WPS */
1248
1249 if (hapd->conf->wpa) {
1250 ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa);
1251 if (os_snprintf_error(end - pos, ret))
1252 return pos - buf;
1253 pos += ret;
1254 }
1255
1256 if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
1257 ret = os_snprintf(pos, end - pos, "key_mgmt=");
1258 if (os_snprintf_error(end - pos, ret))
1259 return pos - buf;
1260 pos += ret;
1261
1262 pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos);
1263
1264 ret = os_snprintf(pos, end - pos, "\n");
1265 if (os_snprintf_error(end - pos, ret))
1266 return pos - buf;
1267 pos += ret;
1268 }
1269
1270 if (hapd->conf->wpa) {
1271 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
1272 wpa_cipher_txt(hapd->conf->wpa_group));
1273 if (os_snprintf_error(end - pos, ret))
1274 return pos - buf;
1275 pos += ret;
1276 }
1277
1278 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
1279 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
1280 if (os_snprintf_error(end - pos, ret))
1281 return pos - buf;
1282 pos += ret;
1283
1284 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
1285 " ");
1286 if (ret < 0)
1287 return pos - buf;
1288 pos += ret;
1289
1290 ret = os_snprintf(pos, end - pos, "\n");
1291 if (os_snprintf_error(end - pos, ret))
1292 return pos - buf;
1293 pos += ret;
1294 }
1295
1296 if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
1297 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
1298 if (os_snprintf_error(end - pos, ret))
1299 return pos - buf;
1300 pos += ret;
1301
1302 ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
1303 " ");
1304 if (ret < 0)
1305 return pos - buf;
1306 pos += ret;
1307
1308 ret = os_snprintf(pos, end - pos, "\n");
1309 if (os_snprintf_error(end - pos, ret))
1310 return pos - buf;
1311 pos += ret;
1312 }
1313
1314 return pos - buf;
1315 }
1316
1317
1318 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
1319 {
1320 char *value;
1321 int ret = 0;
1322
1323 value = os_strchr(cmd, ' ');
1324 if (value == NULL)
1325 return -1;
1326 *value++ = '\0';
1327
1328 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
1329 if (0) {
1330 #ifdef CONFIG_WPS_TESTING
1331 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
1332 long int val;
1333 val = strtol(value, NULL, 0);
1334 if (val < 0 || val > 0xff) {
1335 ret = -1;
1336 wpa_printf(MSG_DEBUG, "WPS: Invalid "
1337 "wps_version_number %ld", val);
1338 } else {
1339 wps_version_number = val;
1340 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
1341 "version %u.%u",
1342 (wps_version_number & 0xf0) >> 4,
1343 wps_version_number & 0x0f);
1344 hostapd_wps_update_ie(hapd);
1345 }
1346 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
1347 wps_testing_dummy_cred = atoi(value);
1348 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
1349 wps_testing_dummy_cred);
1350 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
1351 wps_corrupt_pkhash = atoi(value);
1352 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
1353 wps_corrupt_pkhash);
1354 #endif /* CONFIG_WPS_TESTING */
1355 #ifdef CONFIG_INTERWORKING
1356 } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
1357 int val = atoi(value);
1358 if (val <= 0)
1359 ret = -1;
1360 else
1361 hapd->gas_frag_limit = val;
1362 #endif /* CONFIG_INTERWORKING */
1363 #ifdef CONFIG_TESTING_OPTIONS
1364 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
1365 hapd->ext_mgmt_frame_handling = atoi(value);
1366 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
1367 hapd->ext_eapol_frame_io = atoi(value);
1368 #endif /* CONFIG_TESTING_OPTIONS */
1369 #ifdef CONFIG_MBO
1370 } else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) {
1371 int val;
1372
1373 if (!hapd->conf->mbo_enabled)
1374 return -1;
1375
1376 val = atoi(value);
1377 if (val < 0 || val > 1)
1378 return -1;
1379
1380 hapd->mbo_assoc_disallow = val;
1381 ieee802_11_update_beacons(hapd->iface);
1382
1383 /*
1384 * TODO: Need to configure drivers that do AP MLME offload with
1385 * disallowing station logic.
1386 */
1387 #endif /* CONFIG_MBO */
1388 } else {
1389 struct sta_info *sta;
1390 struct vlan_description vlan_id;
1391
1392 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
1393 if (ret)
1394 return ret;
1395
1396 if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
1397 for (sta = hapd->sta_list; sta; sta = sta->next) {
1398 if (hostapd_maclist_found(
1399 hapd->conf->deny_mac,
1400 hapd->conf->num_deny_mac, sta->addr,
1401 &vlan_id) &&
1402 (!vlan_id.notempty ||
1403 !vlan_compare(&vlan_id, sta->vlan_desc)))
1404 ap_sta_disconnect(
1405 hapd, sta, sta->addr,
1406 WLAN_REASON_UNSPECIFIED);
1407 }
1408 } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
1409 os_strcasecmp(cmd, "accept_mac_file") == 0) {
1410 for (sta = hapd->sta_list; sta; sta = sta->next) {
1411 if (!hostapd_maclist_found(
1412 hapd->conf->accept_mac,
1413 hapd->conf->num_accept_mac,
1414 sta->addr, &vlan_id) ||
1415 (vlan_id.notempty &&
1416 vlan_compare(&vlan_id, sta->vlan_desc)))
1417 ap_sta_disconnect(
1418 hapd, sta, sta->addr,
1419 WLAN_REASON_UNSPECIFIED);
1420 }
1421 }
1422 }
1423
1424 return ret;
1425 }
1426
1427
1428 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
1429 char *buf, size_t buflen)
1430 {
1431 int res;
1432
1433 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
1434
1435 if (os_strcmp(cmd, "version") == 0) {
1436 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
1437 if (os_snprintf_error(buflen, res))
1438 return -1;
1439 return res;
1440 } else if (os_strcmp(cmd, "tls_library") == 0) {
1441 res = tls_get_library_version(buf, buflen);
1442 if (os_snprintf_error(buflen, res))
1443 return -1;
1444 return res;
1445 }
1446
1447 return -1;
1448 }
1449
1450
1451 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
1452 {
1453 if (hostapd_enable_iface(iface) < 0) {
1454 wpa_printf(MSG_ERROR, "Enabling of interface failed");
1455 return -1;
1456 }
1457 return 0;
1458 }
1459
1460
1461 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
1462 {
1463 if (hostapd_reload_iface(iface) < 0) {
1464 wpa_printf(MSG_ERROR, "Reloading of interface failed");
1465 return -1;
1466 }
1467 return 0;
1468 }
1469
1470
1471 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
1472 {
1473 if (hostapd_disable_iface(iface) < 0) {
1474 wpa_printf(MSG_ERROR, "Disabling of interface failed");
1475 return -1;
1476 }
1477 return 0;
1478 }
1479
1480
1481 #ifdef CONFIG_TESTING_OPTIONS
1482
1483 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
1484 {
1485 union wpa_event_data data;
1486 char *pos, *param;
1487 enum wpa_event_type event;
1488
1489 wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1490
1491 os_memset(&data, 0, sizeof(data));
1492
1493 param = os_strchr(cmd, ' ');
1494 if (param == NULL)
1495 return -1;
1496 *param++ = '\0';
1497
1498 if (os_strcmp(cmd, "DETECTED") == 0)
1499 event = EVENT_DFS_RADAR_DETECTED;
1500 else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1501 event = EVENT_DFS_CAC_FINISHED;
1502 else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1503 event = EVENT_DFS_CAC_ABORTED;
1504 else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1505 event = EVENT_DFS_NOP_FINISHED;
1506 else {
1507 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1508 cmd);
1509 return -1;
1510 }
1511
1512 pos = os_strstr(param, "freq=");
1513 if (pos)
1514 data.dfs_event.freq = atoi(pos + 5);
1515
1516 pos = os_strstr(param, "ht_enabled=1");
1517 if (pos)
1518 data.dfs_event.ht_enabled = 1;
1519
1520 pos = os_strstr(param, "chan_offset=");
1521 if (pos)
1522 data.dfs_event.chan_offset = atoi(pos + 12);
1523
1524 pos = os_strstr(param, "chan_width=");
1525 if (pos)
1526 data.dfs_event.chan_width = atoi(pos + 11);
1527
1528 pos = os_strstr(param, "cf1=");
1529 if (pos)
1530 data.dfs_event.cf1 = atoi(pos + 4);
1531
1532 pos = os_strstr(param, "cf2=");
1533 if (pos)
1534 data.dfs_event.cf2 = atoi(pos + 4);
1535
1536 wpa_supplicant_event(hapd, event, &data);
1537
1538 return 0;
1539 }
1540
1541
1542 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
1543 {
1544 size_t len;
1545 u8 *buf;
1546 int res;
1547
1548 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
1549
1550 len = os_strlen(cmd);
1551 if (len & 1)
1552 return -1;
1553 len /= 2;
1554
1555 buf = os_malloc(len);
1556 if (buf == NULL)
1557 return -1;
1558
1559 if (hexstr2bin(cmd, buf, len) < 0) {
1560 os_free(buf);
1561 return -1;
1562 }
1563
1564 res = hostapd_drv_send_mlme(hapd, buf, len, 0);
1565 os_free(buf);
1566 return res;
1567 }
1568
1569
1570 static int hostapd_ctrl_iface_mgmt_rx_process(struct hostapd_data *hapd,
1571 char *cmd)
1572 {
1573 char *pos, *param;
1574 size_t len;
1575 u8 *buf;
1576 int freq = 0, datarate = 0, ssi_signal = 0;
1577 union wpa_event_data event;
1578
1579 if (!hapd->ext_mgmt_frame_handling)
1580 return -1;
1581
1582 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
1583
1584 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
1585
1586 pos = cmd;
1587 param = os_strstr(pos, "freq=");
1588 if (param) {
1589 param += 5;
1590 freq = atoi(param);
1591 }
1592
1593 param = os_strstr(pos, " datarate=");
1594 if (param) {
1595 param += 10;
1596 datarate = atoi(param);
1597 }
1598
1599 param = os_strstr(pos, " ssi_signal=");
1600 if (param) {
1601 param += 12;
1602 ssi_signal = atoi(param);
1603 }
1604
1605 param = os_strstr(pos, " frame=");
1606 if (param == NULL)
1607 return -1;
1608 param += 7;
1609
1610 len = os_strlen(param);
1611 if (len & 1)
1612 return -1;
1613 len /= 2;
1614
1615 buf = os_malloc(len);
1616 if (buf == NULL)
1617 return -1;
1618
1619 if (hexstr2bin(param, buf, len) < 0) {
1620 os_free(buf);
1621 return -1;
1622 }
1623
1624 os_memset(&event, 0, sizeof(event));
1625 event.rx_mgmt.freq = freq;
1626 event.rx_mgmt.frame = buf;
1627 event.rx_mgmt.frame_len = len;
1628 event.rx_mgmt.ssi_signal = ssi_signal;
1629 event.rx_mgmt.datarate = datarate;
1630 hapd->ext_mgmt_frame_handling = 0;
1631 wpa_supplicant_event(hapd, EVENT_RX_MGMT, &event);
1632 hapd->ext_mgmt_frame_handling = 1;
1633
1634 os_free(buf);
1635
1636 return 0;
1637 }
1638
1639
1640 static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
1641 {
1642 char *pos;
1643 u8 src[ETH_ALEN], *buf;
1644 int used;
1645 size_t len;
1646
1647 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
1648
1649 pos = cmd;
1650 used = hwaddr_aton2(pos, src);
1651 if (used < 0)
1652 return -1;
1653 pos += used;
1654 while (*pos == ' ')
1655 pos++;
1656
1657 len = os_strlen(pos);
1658 if (len & 1)
1659 return -1;
1660 len /= 2;
1661
1662 buf = os_malloc(len);
1663 if (buf == NULL)
1664 return -1;
1665
1666 if (hexstr2bin(pos, buf, len) < 0) {
1667 os_free(buf);
1668 return -1;
1669 }
1670
1671 ieee802_1x_receive(hapd, src, buf, len);
1672 os_free(buf);
1673
1674 return 0;
1675 }
1676
1677
1678 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
1679 {
1680 size_t i;
1681 u32 sum = 0;
1682 const u16 *pos = buf;
1683
1684 for (i = 0; i < len / 2; i++)
1685 sum += *pos++;
1686
1687 while (sum >> 16)
1688 sum = (sum & 0xffff) + (sum >> 16);
1689
1690 return sum ^ 0xffff;
1691 }
1692
1693
1694 #define HWSIM_PACKETLEN 1500
1695 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
1696
1697 static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
1698 size_t len)
1699 {
1700 struct hostapd_data *hapd = ctx;
1701 const struct ether_header *eth;
1702 struct iphdr ip;
1703 const u8 *pos;
1704 unsigned int i;
1705
1706 if (len != HWSIM_PACKETLEN)
1707 return;
1708
1709 eth = (const struct ether_header *) buf;
1710 os_memcpy(&ip, eth + 1, sizeof(ip));
1711 pos = &buf[sizeof(*eth) + sizeof(ip)];
1712
1713 if (ip.ihl != 5 || ip.version != 4 ||
1714 ntohs(ip.tot_len) != HWSIM_IP_LEN)
1715 return;
1716
1717 for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
1718 if (*pos != (u8) i)
1719 return;
1720 pos++;
1721 }
1722
1723 wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
1724 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
1725 }
1726
1727
1728 static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
1729 char *cmd)
1730 {
1731 int enabled = atoi(cmd);
1732 char *pos;
1733 const char *ifname;
1734
1735 if (!enabled) {
1736 if (hapd->l2_test) {
1737 l2_packet_deinit(hapd->l2_test);
1738 hapd->l2_test = NULL;
1739 wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
1740 "test data: Disabled");
1741 }
1742 return 0;
1743 }
1744
1745 if (hapd->l2_test)
1746 return 0;
1747
1748 pos = os_strstr(cmd, " ifname=");
1749 if (pos)
1750 ifname = pos + 8;
1751 else
1752 ifname = hapd->conf->iface;
1753
1754 hapd->l2_test = l2_packet_init(ifname, hapd->own_addr,
1755 ETHERTYPE_IP, hostapd_data_test_rx,
1756 hapd, 1);
1757 if (hapd->l2_test == NULL)
1758 return -1;
1759
1760 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
1761
1762 return 0;
1763 }
1764
1765
1766 static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
1767 {
1768 u8 dst[ETH_ALEN], src[ETH_ALEN];
1769 char *pos;
1770 int used;
1771 long int val;
1772 u8 tos;
1773 u8 buf[2 + HWSIM_PACKETLEN];
1774 struct ether_header *eth;
1775 struct iphdr *ip;
1776 u8 *dpos;
1777 unsigned int i;
1778
1779 if (hapd->l2_test == NULL)
1780 return -1;
1781
1782 /* format: <dst> <src> <tos> */
1783
1784 pos = cmd;
1785 used = hwaddr_aton2(pos, dst);
1786 if (used < 0)
1787 return -1;
1788 pos += used;
1789 while (*pos == ' ')
1790 pos++;
1791 used = hwaddr_aton2(pos, src);
1792 if (used < 0)
1793 return -1;
1794 pos += used;
1795
1796 val = strtol(pos, NULL, 0);
1797 if (val < 0 || val > 0xff)
1798 return -1;
1799 tos = val;
1800
1801 eth = (struct ether_header *) &buf[2];
1802 os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
1803 os_memcpy(eth->ether_shost, src, ETH_ALEN);
1804 eth->ether_type = htons(ETHERTYPE_IP);
1805 ip = (struct iphdr *) (eth + 1);
1806 os_memset(ip, 0, sizeof(*ip));
1807 ip->ihl = 5;
1808 ip->version = 4;
1809 ip->ttl = 64;
1810 ip->tos = tos;
1811 ip->tot_len = htons(HWSIM_IP_LEN);
1812 ip->protocol = 1;
1813 ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
1814 ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
1815 ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
1816 dpos = (u8 *) (ip + 1);
1817 for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
1818 *dpos++ = i;
1819
1820 if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
1821 HWSIM_PACKETLEN) < 0)
1822 return -1;
1823
1824 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
1825 " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
1826
1827 return 0;
1828 }
1829
1830
1831 static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
1832 char *cmd)
1833 {
1834 u8 *buf;
1835 struct ether_header *eth;
1836 struct l2_packet_data *l2 = NULL;
1837 size_t len;
1838 u16 ethertype;
1839 int res = -1;
1840 const char *ifname = hapd->conf->iface;
1841
1842 if (os_strncmp(cmd, "ifname=", 7) == 0) {
1843 cmd += 7;
1844 ifname = cmd;
1845 cmd = os_strchr(cmd, ' ');
1846 if (cmd == NULL)
1847 return -1;
1848 *cmd++ = '\0';
1849 }
1850
1851 len = os_strlen(cmd);
1852 if (len & 1 || len < ETH_HLEN * 2)
1853 return -1;
1854 len /= 2;
1855
1856 buf = os_malloc(len);
1857 if (buf == NULL)
1858 return -1;
1859
1860 if (hexstr2bin(cmd, buf, len) < 0)
1861 goto done;
1862
1863 eth = (struct ether_header *) buf;
1864 ethertype = ntohs(eth->ether_type);
1865
1866 l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
1867 hostapd_data_test_rx, hapd, 1);
1868 if (l2 == NULL)
1869 goto done;
1870
1871 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
1872 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
1873 done:
1874 if (l2)
1875 l2_packet_deinit(l2);
1876 os_free(buf);
1877
1878 return res < 0 ? -1 : 0;
1879 }
1880
1881
1882 static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
1883 {
1884 #ifdef WPA_TRACE_BFD
1885 char *pos;
1886
1887 wpa_trace_fail_after = atoi(cmd);
1888 pos = os_strchr(cmd, ':');
1889 if (pos) {
1890 pos++;
1891 os_strlcpy(wpa_trace_fail_func, pos,
1892 sizeof(wpa_trace_fail_func));
1893 } else {
1894 wpa_trace_fail_after = 0;
1895 }
1896
1897 return 0;
1898 #else /* WPA_TRACE_BFD */
1899 return -1;
1900 #endif /* WPA_TRACE_BFD */
1901 }
1902
1903
1904 static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
1905 char *buf, size_t buflen)
1906 {
1907 #ifdef WPA_TRACE_BFD
1908 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
1909 wpa_trace_fail_func);
1910 #else /* WPA_TRACE_BFD */
1911 return -1;
1912 #endif /* WPA_TRACE_BFD */
1913 }
1914
1915
1916 static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
1917 {
1918 #ifdef WPA_TRACE_BFD
1919 char *pos;
1920
1921 wpa_trace_test_fail_after = atoi(cmd);
1922 pos = os_strchr(cmd, ':');
1923 if (pos) {
1924 pos++;
1925 os_strlcpy(wpa_trace_test_fail_func, pos,
1926 sizeof(wpa_trace_test_fail_func));
1927 } else {
1928 wpa_trace_test_fail_after = 0;
1929 }
1930
1931 return 0;
1932 #else /* WPA_TRACE_BFD */
1933 return -1;
1934 #endif /* WPA_TRACE_BFD */
1935 }
1936
1937
1938 static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
1939 char *buf, size_t buflen)
1940 {
1941 #ifdef WPA_TRACE_BFD
1942 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
1943 wpa_trace_test_fail_func);
1944 #else /* WPA_TRACE_BFD */
1945 return -1;
1946 #endif /* WPA_TRACE_BFD */
1947 }
1948
1949 #endif /* CONFIG_TESTING_OPTIONS */
1950
1951
1952 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
1953 char *pos)
1954 {
1955 #ifdef NEED_AP_MLME
1956 struct csa_settings settings;
1957 int ret;
1958 unsigned int i;
1959
1960 ret = hostapd_parse_csa_settings(pos, &settings);
1961 if (ret)
1962 return ret;
1963
1964 for (i = 0; i < iface->num_bss; i++) {
1965 ret = hostapd_switch_channel(iface->bss[i], &settings);
1966 if (ret) {
1967 /* FIX: What do we do if CSA fails in the middle of
1968 * submitting multi-BSS CSA requests? */
1969 return ret;
1970 }
1971 }
1972
1973 return 0;
1974 #else /* NEED_AP_MLME */
1975 return -1;
1976 #endif /* NEED_AP_MLME */
1977 }
1978
1979
1980 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
1981 int reply_size, const char *param)
1982 {
1983 #ifdef RADIUS_SERVER
1984 if (os_strcmp(param, "radius_server") == 0) {
1985 return radius_server_get_mib(hapd->radius_srv, reply,
1986 reply_size);
1987 }
1988 #endif /* RADIUS_SERVER */
1989 return -1;
1990 }
1991
1992
1993 static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
1994 char *buf, size_t buflen)
1995 {
1996 int ret;
1997 char *pos;
1998 u8 *data = NULL;
1999 unsigned int vendor_id, subcmd;
2000 struct wpabuf *reply;
2001 size_t data_len = 0;
2002
2003 /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
2004 vendor_id = strtoul(cmd, &pos, 16);
2005 if (!isblank((unsigned char) *pos))
2006 return -EINVAL;
2007
2008 subcmd = strtoul(pos, &pos, 10);
2009
2010 if (*pos != '\0') {
2011 if (!isblank((unsigned char) *pos++))
2012 return -EINVAL;
2013 data_len = os_strlen(pos);
2014 }
2015
2016 if (data_len) {
2017 data_len /= 2;
2018 data = os_malloc(data_len);
2019 if (!data)
2020 return -ENOBUFS;
2021
2022 if (hexstr2bin(pos, data, data_len)) {
2023 wpa_printf(MSG_DEBUG,
2024 "Vendor command: wrong parameter format");
2025 os_free(data);
2026 return -EINVAL;
2027 }
2028 }
2029
2030 reply = wpabuf_alloc((buflen - 1) / 2);
2031 if (!reply) {
2032 os_free(data);
2033 return -ENOBUFS;
2034 }
2035
2036 ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
2037 reply);
2038
2039 if (ret == 0)
2040 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
2041 wpabuf_len(reply));
2042
2043 wpabuf_free(reply);
2044 os_free(data);
2045
2046 return ret;
2047 }
2048
2049
2050 static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
2051 const char *cmd)
2052 {
2053 u8 addr[ETH_ALEN];
2054 struct sta_info *sta;
2055
2056 if (hwaddr_aton(cmd, addr))
2057 return -1;
2058
2059 sta = ap_get_sta(hapd, addr);
2060 if (!sta || !sta->eapol_sm)
2061 return -1;
2062
2063 eapol_auth_reauthenticate(sta->eapol_sm);
2064 return 0;
2065 }
2066
2067
2068 static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
2069 {
2070 u8 addr[ETH_ALEN];
2071 struct sta_info *sta;
2072 char *pos = cmd, *param;
2073
2074 if (hwaddr_aton(pos, addr) || pos[17] != ' ')
2075 return -1;
2076 pos += 18;
2077 param = pos;
2078 pos = os_strchr(pos, ' ');
2079 if (!pos)
2080 return -1;
2081 *pos++ = '\0';
2082
2083 sta = ap_get_sta(hapd, addr);
2084 if (!sta || !sta->eapol_sm)
2085 return -1;
2086
2087 return eapol_auth_set_conf(sta->eapol_sm, param, pos);
2088 }
2089
2090
2091 static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd,
2092 char *buf, size_t buflen)
2093 {
2094 char *pos, *end, *stamp;
2095 int ret;
2096
2097 /* cmd: "LOG_LEVEL [<level>]" */
2098 if (*cmd == '\0') {
2099 pos = buf;
2100 end = buf + buflen;
2101 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2102 "Timestamp: %d\n",
2103 debug_level_str(wpa_debug_level),
2104 wpa_debug_timestamp);
2105 if (os_snprintf_error(end - pos, ret))
2106 ret = 0;
2107
2108 return ret;
2109 }
2110
2111 while (*cmd == ' ')
2112 cmd++;
2113
2114 stamp = os_strchr(cmd, ' ');
2115 if (stamp) {
2116 *stamp++ = '\0';
2117 while (*stamp == ' ') {
2118 stamp++;
2119 }
2120 }
2121
2122 if (os_strlen(cmd)) {
2123 int level = str_to_debug_level(cmd);
2124 if (level < 0)
2125 return -1;
2126 wpa_debug_level = level;
2127 }
2128
2129 if (stamp && os_strlen(stamp))
2130 wpa_debug_timestamp = atoi(stamp);
2131
2132 os_memcpy(buf, "OK\n", 3);
2133 return 3;
2134 }
2135
2136
2137 #ifdef NEED_AP_MLME
2138 static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
2139 char *buf, size_t buflen)
2140 {
2141 struct hostapd_iface *iface = hapd->iface;
2142 char *pos, *end;
2143 struct hostapd_sta_info *info;
2144 struct os_reltime now;
2145
2146 if (!iface->num_sta_seen)
2147 return 0;
2148
2149 sta_track_expire(iface, 0);
2150
2151 pos = buf;
2152 end = buf + buflen;
2153
2154 os_get_reltime(&now);
2155 dl_list_for_each_reverse(info, &iface->sta_seen,
2156 struct hostapd_sta_info, list) {
2157 struct os_reltime age;
2158 int ret;
2159
2160 os_reltime_sub(&now, &info->last_seen, &age);
2161 ret = os_snprintf(pos, end - pos, MACSTR " %u %d\n",
2162 MAC2STR(info->addr), (unsigned int) age.sec,
2163 info->ssi_signal);
2164 if (os_snprintf_error(end - pos, ret))
2165 break;
2166 pos += ret;
2167 }
2168
2169 return pos - buf;
2170 }
2171 #endif /* NEED_AP_MLME */
2172
2173
2174 static int hostapd_ctrl_iface_req_lci(struct hostapd_data *hapd,
2175 const char *cmd)
2176 {
2177 u8 addr[ETH_ALEN];
2178
2179 if (hwaddr_aton(cmd, addr)) {
2180 wpa_printf(MSG_INFO, "CTRL: REQ_LCI: Invalid MAC address");
2181 return -1;
2182 }
2183
2184 return hostapd_send_lci_req(hapd, addr);
2185 }
2186
2187
2188 static int hostapd_ctrl_iface_req_range(struct hostapd_data *hapd, char *cmd)
2189 {
2190 u8 addr[ETH_ALEN];
2191 char *token, *context = NULL;
2192 int random_interval, min_ap;
2193 u8 responders[ETH_ALEN * RRM_RANGE_REQ_MAX_RESPONDERS];
2194 unsigned int n_responders;
2195
2196 token = str_token(cmd, " ", &context);
2197 if (!token || hwaddr_aton(token, addr)) {
2198 wpa_printf(MSG_INFO,
2199 "CTRL: REQ_RANGE - Bad destination address");
2200 return -1;
2201 }
2202
2203 token = str_token(cmd, " ", &context);
2204 if (!token)
2205 return -1;
2206
2207 random_interval = atoi(token);
2208 if (random_interval < 0 || random_interval > 0xffff)
2209 return -1;
2210
2211 token = str_token(cmd, " ", &context);
2212 if (!token)
2213 return -1;
2214
2215 min_ap = atoi(token);
2216 if (min_ap <= 0 || min_ap > WLAN_RRM_RANGE_REQ_MAX_MIN_AP)
2217 return -1;
2218
2219 n_responders = 0;
2220 while ((token = str_token(cmd, " ", &context))) {
2221 if (n_responders == RRM_RANGE_REQ_MAX_RESPONDERS) {
2222 wpa_printf(MSG_INFO,
2223 "CTRL: REQ_RANGE: Too many responders");
2224 return -1;
2225 }
2226
2227 if (hwaddr_aton(token, responders + n_responders * ETH_ALEN)) {
2228 wpa_printf(MSG_INFO,
2229 "CTRL: REQ_RANGE: Bad responder address");
2230 return -1;
2231 }
2232
2233 n_responders++;
2234 }
2235
2236 if (!n_responders) {
2237 wpa_printf(MSG_INFO,
2238 "CTRL: REQ_RANGE - No FTM responder address");
2239 return -1;
2240 }
2241
2242 return hostapd_send_range_req(hapd, addr, random_interval, min_ap,
2243 responders, n_responders);
2244 }
2245
2246
2247 static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf)
2248 {
2249 struct wpa_ssid_value ssid;
2250 u8 bssid[ETH_ALEN];
2251 struct wpabuf *nr, *lci = NULL, *civic = NULL;
2252 int stationary = 0;
2253 char *tmp;
2254 int ret;
2255
2256 if (!(hapd->conf->radio_measurements[0] &
2257 WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
2258 wpa_printf(MSG_ERROR,
2259 "CTRL: SET_NEIGHBOR: Neighbor report is not enabled");
2260 return -1;
2261 }
2262
2263 if (hwaddr_aton(buf, bssid)) {
2264 wpa_printf(MSG_ERROR, "CTRL: SET_NEIGHBOR: Bad BSSID");
2265 return -1;
2266 }
2267
2268 tmp = os_strstr(buf, "ssid=");
2269 if (!tmp || ssid_parse(tmp + 5, &ssid)) {
2270 wpa_printf(MSG_ERROR,
2271 "CTRL: SET_NEIGHBOR: Bad or missing SSID");
2272 return -1;
2273 }
2274 buf = os_strchr(tmp + 6, tmp[5] == '"' ? '"' : ' ');
2275 if (!buf)
2276 return -1;
2277
2278 tmp = os_strstr(buf, "nr=");
2279 if (!tmp) {
2280 wpa_printf(MSG_ERROR,
2281 "CTRL: SET_NEIGHBOR: Missing Neighbor Report element");
2282 return -1;
2283 }
2284
2285 buf = os_strchr(tmp, ' ');
2286 if (buf)
2287 *buf++ = '\0';
2288
2289 nr = wpabuf_parse_bin(tmp + 3);
2290 if (!nr) {
2291 wpa_printf(MSG_ERROR,
2292 "CTRL: SET_NEIGHBOR: Bad Neighbor Report element");
2293 return -1;
2294 }
2295
2296 if (!buf)
2297 goto set;
2298
2299 tmp = os_strstr(buf, "lci=");
2300 if (tmp) {
2301 buf = os_strchr(tmp, ' ');
2302 if (buf)
2303 *buf++ = '\0';
2304 lci = wpabuf_parse_bin(tmp + 4);
2305 if (!lci) {
2306 wpa_printf(MSG_ERROR,
2307 "CTRL: SET_NEIGHBOR: Bad LCI subelement");
2308 wpabuf_free(nr);
2309 return -1;
2310 }
2311 }
2312
2313 if (!buf)
2314 goto set;
2315
2316 tmp = os_strstr(buf, "civic=");
2317 if (tmp) {
2318 buf = os_strchr(tmp, ' ');
2319 if (buf)
2320 *buf++ = '\0';
2321 civic = wpabuf_parse_bin(tmp + 6);
2322 if (!civic) {
2323 wpa_printf(MSG_ERROR,
2324 "CTRL: SET_NEIGHBOR: Bad civic subelement");
2325 wpabuf_free(nr);
2326 wpabuf_free(lci);
2327 return -1;
2328 }
2329 }
2330
2331 if (!buf)
2332 goto set;
2333
2334 if (os_strstr(buf, "stat"))
2335 stationary = 1;
2336
2337 set:
2338 ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic,
2339 stationary);
2340
2341 wpabuf_free(nr);
2342 wpabuf_free(lci);
2343 wpabuf_free(civic);
2344
2345 return ret;
2346 }
2347
2348
2349 static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd,
2350 char *buf)
2351 {
2352 struct wpa_ssid_value ssid;
2353 u8 bssid[ETH_ALEN];
2354 char *tmp;
2355
2356 if (hwaddr_aton(buf, bssid)) {
2357 wpa_printf(MSG_ERROR, "CTRL: REMOVE_NEIGHBOR: Bad BSSID");
2358 return -1;
2359 }
2360
2361 tmp = os_strstr(buf, "ssid=");
2362 if (!tmp || ssid_parse(tmp + 5, &ssid)) {
2363 wpa_printf(MSG_ERROR,
2364 "CTRL: REMOVE_NEIGHBORr: Bad or missing SSID");
2365 return -1;
2366 }
2367
2368 return hostapd_neighbor_remove(hapd, bssid, &ssid);
2369 }
2370
2371
2372 static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
2373 size_t buflen)
2374 {
2375 int ret, i;
2376 char *pos, *end;
2377
2378 ret = os_snprintf(buf, buflen, "%016llX:\n",
2379 (long long unsigned) iface->drv_flags);
2380 if (os_snprintf_error(buflen, ret))
2381 return -1;
2382
2383 pos = buf + ret;
2384 end = buf + buflen;
2385
2386 for (i = 0; i < 64; i++) {
2387 if (iface->drv_flags & (1LLU << i)) {
2388 ret = os_snprintf(pos, end - pos, "%s\n",
2389 driver_flag_to_string(1LLU << i));
2390 if (os_snprintf_error(end - pos, ret))
2391 return -1;
2392 pos += ret;
2393 }
2394 }
2395
2396 return pos - buf;
2397 }
2398
2399
2400 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
2401 char *buf, char *reply,
2402 int reply_size,
2403 struct sockaddr_storage *from,
2404 socklen_t fromlen)
2405 {
2406 int reply_len, res;
2407
2408 os_memcpy(reply, "OK\n", 3);
2409 reply_len = 3;
2410
2411 if (os_strcmp(buf, "PING") == 0) {
2412 os_memcpy(reply, "PONG\n", 5);
2413 reply_len = 5;
2414 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
2415 if (wpa_debug_reopen_file() < 0)
2416 reply_len = -1;
2417 } else if (os_strcmp(buf, "STATUS") == 0) {
2418 reply_len = hostapd_ctrl_iface_status(hapd, reply,
2419 reply_size);
2420 } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
2421 reply_len = hostapd_drv_status(hapd, reply, reply_size);
2422 } else if (os_strcmp(buf, "MIB") == 0) {
2423 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
2424 if (reply_len >= 0) {
2425 res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
2426 reply_size - reply_len);
2427 if (res < 0)
2428 reply_len = -1;
2429 else
2430 reply_len += res;
2431 }
2432 if (reply_len >= 0) {
2433 res = ieee802_1x_get_mib(hapd, reply + reply_len,
2434 reply_size - reply_len);
2435 if (res < 0)
2436 reply_len = -1;
2437 else
2438 reply_len += res;
2439 }
2440 #ifndef CONFIG_NO_RADIUS
2441 if (reply_len >= 0) {
2442 res = radius_client_get_mib(hapd->radius,
2443 reply + reply_len,
2444 reply_size - reply_len);
2445 if (res < 0)
2446 reply_len = -1;
2447 else
2448 reply_len += res;
2449 }
2450 #endif /* CONFIG_NO_RADIUS */
2451 } else if (os_strncmp(buf, "MIB ", 4) == 0) {
2452 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
2453 buf + 4);
2454 } else if (os_strcmp(buf, "STA-FIRST") == 0) {
2455 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
2456 reply_size);
2457 } else if (os_strncmp(buf, "STA ", 4) == 0) {
2458 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
2459 reply_size);
2460 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
2461 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
2462 reply_size);
2463 } else if (os_strcmp(buf, "ATTACH") == 0) {
2464 if (hostapd_ctrl_iface_attach(hapd, from, fromlen))
2465 reply_len = -1;
2466 } else if (os_strcmp(buf, "DETACH") == 0) {
2467 if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
2468 reply_len = -1;
2469 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
2470 if (hostapd_ctrl_iface_level(hapd, from, fromlen,
2471 buf + 6))
2472 reply_len = -1;
2473 } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
2474 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
2475 reply_len = -1;
2476 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
2477 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
2478 reply_len = -1;
2479 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
2480 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
2481 reply_len = -1;
2482 #ifdef CONFIG_TAXONOMY
2483 } else if (os_strncmp(buf, "SIGNATURE ", 10) == 0) {
2484 reply_len = hostapd_ctrl_iface_signature(hapd, buf + 10,
2485 reply, reply_size);
2486 #endif /* CONFIG_TAXONOMY */
2487 } else if (os_strncmp(buf, "POLL_STA ", 9) == 0) {
2488 if (hostapd_ctrl_iface_poll_sta(hapd, buf + 9))
2489 reply_len = -1;
2490 } else if (os_strcmp(buf, "STOP_AP") == 0) {
2491 if (hostapd_ctrl_iface_stop_ap(hapd))
2492 reply_len = -1;
2493 #ifdef CONFIG_IEEE80211W
2494 #ifdef NEED_AP_MLME
2495 } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
2496 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
2497 reply_len = -1;
2498 #endif /* NEED_AP_MLME */
2499 #endif /* CONFIG_IEEE80211W */
2500 #ifdef CONFIG_WPS
2501 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
2502 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
2503 reply_len = -1;
2504 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
2505 reply_len = hostapd_ctrl_iface_wps_check_pin(
2506 hapd, buf + 14, reply, reply_size);
2507 } else if (os_strcmp(buf, "WPS_PBC") == 0) {
2508 if (hostapd_wps_button_pushed(hapd, NULL))
2509 reply_len = -1;
2510 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
2511 if (hostapd_wps_cancel(hapd))
2512 reply_len = -1;
2513 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
2514 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
2515 reply, reply_size);
2516 } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
2517 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
2518 reply_len = -1;
2519 } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
2520 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
2521 reply_size);
2522 #ifdef CONFIG_WPS_NFC
2523 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
2524 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
2525 reply_len = -1;
2526 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
2527 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
2528 hapd, buf + 21, reply, reply_size);
2529 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
2530 reply_len = hostapd_ctrl_iface_wps_nfc_token(
2531 hapd, buf + 14, reply, reply_size);
2532 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
2533 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
2534 hapd, buf + 21, reply, reply_size);
2535 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
2536 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
2537 reply_len = -1;
2538 #endif /* CONFIG_WPS_NFC */
2539 #endif /* CONFIG_WPS */
2540 #ifdef CONFIG_INTERWORKING
2541 } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
2542 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
2543 reply_len = -1;
2544 } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
2545 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
2546 reply_len = -1;
2547 #endif /* CONFIG_INTERWORKING */
2548 #ifdef CONFIG_HS20
2549 } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
2550 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
2551 reply_len = -1;
2552 } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
2553 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
2554 reply_len = -1;
2555 #endif /* CONFIG_HS20 */
2556 #ifdef CONFIG_WNM
2557 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
2558 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
2559 reply_len = -1;
2560 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
2561 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
2562 reply_len = -1;
2563 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
2564 if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
2565 reply_len = -1;
2566 #endif /* CONFIG_WNM */
2567 } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
2568 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
2569 reply_size);
2570 } else if (os_strncmp(buf, "SET ", 4) == 0) {
2571 if (hostapd_ctrl_iface_set(hapd, buf + 4))
2572 reply_len = -1;
2573 } else if (os_strncmp(buf, "GET ", 4) == 0) {
2574 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
2575 reply_size);
2576 } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
2577 if (hostapd_ctrl_iface_enable(hapd->iface))
2578 reply_len = -1;
2579 } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
2580 if (hostapd_ctrl_iface_reload(hapd->iface))
2581 reply_len = -1;
2582 } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
2583 if (hostapd_ctrl_iface_disable(hapd->iface))
2584 reply_len = -1;
2585 } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
2586 if (ieee802_11_set_beacon(hapd))
2587 reply_len = -1;
2588 #ifdef CONFIG_TESTING_OPTIONS
2589 } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
2590 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
2591 reply_len = -1;
2592 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
2593 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
2594 reply_len = -1;
2595 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
2596 if (hostapd_ctrl_iface_mgmt_rx_process(hapd, buf + 16) < 0)
2597 reply_len = -1;
2598 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
2599 if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
2600 reply_len = -1;
2601 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
2602 if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
2603 reply_len = -1;
2604 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
2605 if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
2606 reply_len = -1;
2607 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
2608 if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
2609 reply_len = -1;
2610 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
2611 if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
2612 reply_len = -1;
2613 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
2614 reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
2615 reply_size);
2616 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
2617 if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
2618 reply_len = -1;
2619 } else if (os_strcmp(buf, "GET_FAIL") == 0) {
2620 reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
2621 #endif /* CONFIG_TESTING_OPTIONS */
2622 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
2623 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
2624 reply_len = -1;
2625 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
2626 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
2627 reply_size);
2628 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
2629 ieee802_1x_erp_flush(hapd);
2630 #ifdef RADIUS_SERVER
2631 radius_server_erp_flush(hapd->radius_srv);
2632 #endif /* RADIUS_SERVER */
2633 } else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
2634 if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
2635 reply_len = -1;
2636 } else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
2637 if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
2638 reply_len = -1;
2639 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
2640 reply_len = hostapd_ctrl_iface_log_level(
2641 hapd, buf + 9, reply, reply_size);
2642 #ifdef NEED_AP_MLME
2643 } else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
2644 reply_len = hostapd_ctrl_iface_track_sta_list(
2645 hapd, reply, reply_size);
2646 #endif /* NEED_AP_MLME */
2647 } else if (os_strcmp(buf, "PMKSA") == 0) {
2648 reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply,
2649 reply_size);
2650 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
2651 hostapd_ctrl_iface_pmksa_flush(hapd);
2652 } else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) {
2653 if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13))
2654 reply_len = -1;
2655 } else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) {
2656 if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16))
2657 reply_len = -1;
2658 } else if (os_strncmp(buf, "REQ_LCI ", 8) == 0) {
2659 if (hostapd_ctrl_iface_req_lci(hapd, buf + 8))
2660 reply_len = -1;
2661 } else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) {
2662 if (hostapd_ctrl_iface_req_range(hapd, buf + 10))
2663 reply_len = -1;
2664 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
2665 reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
2666 reply_size);
2667 } else if (os_strcmp(buf, "TERMINATE") == 0) {
2668 eloop_terminate();
2669 } else {
2670 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
2671 reply_len = 16;
2672 }
2673
2674 if (reply_len < 0) {
2675 os_memcpy(reply, "FAIL\n", 5);
2676 reply_len = 5;
2677 }
2678
2679 return reply_len;
2680 }
2681
2682
2683 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
2684 void *sock_ctx)
2685 {
2686 struct hostapd_data *hapd = eloop_ctx;
2687 char buf[4096];
2688 int res;
2689 struct sockaddr_storage from;
2690 socklen_t fromlen = sizeof(from);
2691 char *reply, *pos = buf;
2692 const int reply_size = 4096;
2693 int reply_len;
2694 int level = MSG_DEBUG;
2695 #ifdef CONFIG_CTRL_IFACE_UDP
2696 unsigned char lcookie[COOKIE_LEN];
2697 #endif /* CONFIG_CTRL_IFACE_UDP */
2698
2699 res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
2700 (struct sockaddr *) &from, &fromlen);
2701 if (res < 0) {
2702 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
2703 strerror(errno));
2704 return;
2705 }
2706 buf[res] = '\0';
2707
2708 reply = os_malloc(reply_size);
2709 if (reply == NULL) {
2710 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
2711 fromlen) < 0) {
2712 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2713 strerror(errno));
2714 }
2715 return;
2716 }
2717
2718 #ifdef CONFIG_CTRL_IFACE_UDP
2719 if (os_strcmp(buf, "GET_COOKIE") == 0) {
2720 os_memcpy(reply, "COOKIE=", 7);
2721 wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
2722 cookie, COOKIE_LEN);
2723 reply_len = 7 + 2 * COOKIE_LEN;
2724 goto done;
2725 }
2726
2727 if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
2728 hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
2729 wpa_printf(MSG_DEBUG,
2730 "CTRL: No cookie in the request - drop request");
2731 os_free(reply);
2732 return;
2733 }
2734
2735 if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) {
2736 wpa_printf(MSG_DEBUG,
2737 "CTRL: Invalid cookie in the request - drop request");
2738 os_free(reply);
2739 return;
2740 }
2741
2742 pos = buf + 7 + 2 * COOKIE_LEN;
2743 while (*pos == ' ')
2744 pos++;
2745 #endif /* CONFIG_CTRL_IFACE_UDP */
2746
2747 if (os_strcmp(pos, "PING") == 0)
2748 level = MSG_EXCESSIVE;
2749 wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res);
2750
2751 reply_len = hostapd_ctrl_iface_receive_process(hapd, pos,
2752 reply, reply_size,
2753 &from, fromlen);
2754
2755 #ifdef CONFIG_CTRL_IFACE_UDP
2756 done:
2757 #endif /* CONFIG_CTRL_IFACE_UDP */
2758 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
2759 fromlen) < 0) {
2760 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2761 strerror(errno));
2762 }
2763 os_free(reply);
2764 }
2765
2766
2767 #ifndef CONFIG_CTRL_IFACE_UDP
2768 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
2769 {
2770 char *buf;
2771 size_t len;
2772
2773 if (hapd->conf->ctrl_interface == NULL)
2774 return NULL;
2775
2776 len = os_strlen(hapd->conf->ctrl_interface) +
2777 os_strlen(hapd->conf->iface) + 2;
2778 buf = os_malloc(len);
2779 if (buf == NULL)
2780 return NULL;
2781
2782 os_snprintf(buf, len, "%s/%s",
2783 hapd->conf->ctrl_interface, hapd->conf->iface);
2784 buf[len - 1] = '\0';
2785 return buf;
2786 }
2787 #endif /* CONFIG_CTRL_IFACE_UDP */
2788
2789
2790 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
2791 enum wpa_msg_type type,
2792 const char *txt, size_t len)
2793 {
2794 struct hostapd_data *hapd = ctx;
2795 if (hapd == NULL)
2796 return;
2797 hostapd_ctrl_iface_send(hapd, level, type, txt, len);
2798 }
2799
2800
2801 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
2802 {
2803 #ifdef CONFIG_CTRL_IFACE_UDP
2804 int port = HOSTAPD_CTRL_IFACE_PORT;
2805 char p[32] = { 0 };
2806 char port_str[40], *tmp;
2807 char *pos;
2808 struct addrinfo hints = { 0 }, *res, *saveres;
2809 int n;
2810
2811 if (hapd->ctrl_sock > -1) {
2812 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
2813 return 0;
2814 }
2815
2816 if (hapd->conf->ctrl_interface == NULL)
2817 return 0;
2818
2819 pos = os_strstr(hapd->conf->ctrl_interface, "udp:");
2820 if (pos) {
2821 pos += 4;
2822 port = atoi(pos);
2823 if (port <= 0) {
2824 wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port");
2825 goto fail;
2826 }
2827 }
2828
2829 dl_list_init(&hapd->ctrl_dst);
2830 hapd->ctrl_sock = -1;
2831 os_get_random(cookie, COOKIE_LEN);
2832
2833 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
2834 hints.ai_flags = AI_PASSIVE;
2835 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
2836
2837 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
2838 hints.ai_family = AF_INET6;
2839 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
2840 hints.ai_family = AF_INET;
2841 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
2842 hints.ai_socktype = SOCK_DGRAM;
2843
2844 try_again:
2845 os_snprintf(p, sizeof(p), "%d", port);
2846 n = getaddrinfo(NULL, p, &hints, &res);
2847 if (n) {
2848 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
2849 goto fail;
2850 }
2851
2852 saveres = res;
2853 hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype,
2854 res->ai_protocol);
2855 if (hapd->ctrl_sock < 0) {
2856 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
2857 goto fail;
2858 }
2859
2860 if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) {
2861 port--;
2862 if ((HOSTAPD_CTRL_IFACE_PORT - port) <
2863 HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos)
2864 goto try_again;
2865 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
2866 goto fail;
2867 }
2868
2869 freeaddrinfo(saveres);
2870
2871 os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
2872 tmp = os_strdup(port_str);
2873 if (tmp) {
2874 os_free(hapd->conf->ctrl_interface);
2875 hapd->conf->ctrl_interface = tmp;
2876 }
2877 wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
2878
2879 if (eloop_register_read_sock(hapd->ctrl_sock,
2880 hostapd_ctrl_iface_receive, hapd, NULL) <
2881 0) {
2882 hostapd_ctrl_iface_deinit(hapd);
2883 return -1;
2884 }
2885
2886 hapd->msg_ctx = hapd;
2887 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
2888
2889 return 0;
2890
2891 fail:
2892 if (hapd->ctrl_sock >= 0)
2893 close(hapd->ctrl_sock);
2894 return -1;
2895 #else /* CONFIG_CTRL_IFACE_UDP */
2896 struct sockaddr_un addr;
2897 int s = -1;
2898 char *fname = NULL;
2899
2900 if (hapd->ctrl_sock > -1) {
2901 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
2902 return 0;
2903 }
2904
2905 dl_list_init(&hapd->ctrl_dst);
2906
2907 if (hapd->conf->ctrl_interface == NULL)
2908 return 0;
2909
2910 if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2911 if (errno == EEXIST) {
2912 wpa_printf(MSG_DEBUG, "Using existing control "
2913 "interface directory.");
2914 } else {
2915 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
2916 strerror(errno));
2917 goto fail;
2918 }
2919 }
2920
2921 if (hapd->conf->ctrl_interface_gid_set &&
2922 chown(hapd->conf->ctrl_interface, -1,
2923 hapd->conf->ctrl_interface_gid) < 0) {
2924 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2925 strerror(errno));
2926 return -1;
2927 }
2928
2929 if (!hapd->conf->ctrl_interface_gid_set &&
2930 hapd->iface->interfaces->ctrl_iface_group &&
2931 chown(hapd->conf->ctrl_interface, -1,
2932 hapd->iface->interfaces->ctrl_iface_group) < 0) {
2933 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2934 strerror(errno));
2935 return -1;
2936 }
2937
2938 #ifdef ANDROID
2939 /*
2940 * Android is using umask 0077 which would leave the control interface
2941 * directory without group access. This breaks things since Wi-Fi
2942 * framework assumes that this directory can be accessed by other
2943 * applications in the wifi group. Fix this by adding group access even
2944 * if umask value would prevent this.
2945 */
2946 if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2947 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
2948 strerror(errno));
2949 /* Try to continue anyway */
2950 }
2951 #endif /* ANDROID */
2952
2953 if (os_strlen(hapd->conf->ctrl_interface) + 1 +
2954 os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
2955 goto fail;
2956
2957 s = socket(PF_UNIX, SOCK_DGRAM, 0);
2958 if (s < 0) {
2959 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
2960 goto fail;
2961 }
2962
2963 os_memset(&addr, 0, sizeof(addr));
2964 #ifdef __FreeBSD__
2965 addr.sun_len = sizeof(addr);
2966 #endif /* __FreeBSD__ */
2967 addr.sun_family = AF_UNIX;
2968 fname = hostapd_ctrl_iface_path(hapd);
2969 if (fname == NULL)
2970 goto fail;
2971 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
2972 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2973 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
2974 strerror(errno));
2975 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2976 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
2977 " allow connections - assuming it was left"
2978 "over from forced program termination");
2979 if (unlink(fname) < 0) {
2980 wpa_printf(MSG_ERROR,
2981 "Could not unlink existing ctrl_iface socket '%s': %s",
2982 fname, strerror(errno));
2983 goto fail;
2984 }
2985 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
2986 0) {
2987 wpa_printf(MSG_ERROR,
2988 "hostapd-ctrl-iface: bind(PF_UNIX): %s",
2989 strerror(errno));
2990 goto fail;
2991 }
2992 wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
2993 "ctrl_iface socket '%s'", fname);
2994 } else {
2995 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
2996 "be in use - cannot override it");
2997 wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
2998 "not used anymore", fname);
2999 os_free(fname);
3000 fname = NULL;
3001 goto fail;
3002 }
3003 }
3004
3005 if (hapd->conf->ctrl_interface_gid_set &&
3006 chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
3007 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
3008 strerror(errno));
3009 goto fail;
3010 }
3011
3012 if (!hapd->conf->ctrl_interface_gid_set &&
3013 hapd->iface->interfaces->ctrl_iface_group &&
3014 chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
3015 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
3016 strerror(errno));
3017 goto fail;
3018 }
3019
3020 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
3021 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
3022 strerror(errno));
3023 goto fail;
3024 }
3025 os_free(fname);
3026
3027 hapd->ctrl_sock = s;
3028 if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
3029 NULL) < 0) {
3030 hostapd_ctrl_iface_deinit(hapd);
3031 return -1;
3032 }
3033 hapd->msg_ctx = hapd;
3034 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
3035
3036 return 0;
3037
3038 fail:
3039 if (s >= 0)
3040 close(s);
3041 if (fname) {
3042 unlink(fname);
3043 os_free(fname);
3044 }
3045 return -1;
3046 #endif /* CONFIG_CTRL_IFACE_UDP */
3047 }
3048
3049
3050 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
3051 {
3052 struct wpa_ctrl_dst *dst, *prev;
3053
3054 if (hapd->ctrl_sock > -1) {
3055 #ifndef CONFIG_CTRL_IFACE_UDP
3056 char *fname;
3057 #endif /* !CONFIG_CTRL_IFACE_UDP */
3058
3059 eloop_unregister_read_sock(hapd->ctrl_sock);
3060 close(hapd->ctrl_sock);
3061 hapd->ctrl_sock = -1;
3062 #ifndef CONFIG_CTRL_IFACE_UDP
3063 fname = hostapd_ctrl_iface_path(hapd);
3064 if (fname)
3065 unlink(fname);
3066 os_free(fname);
3067
3068 if (hapd->conf->ctrl_interface &&
3069 rmdir(hapd->conf->ctrl_interface) < 0) {
3070 if (errno == ENOTEMPTY) {
3071 wpa_printf(MSG_DEBUG, "Control interface "
3072 "directory not empty - leaving it "
3073 "behind");
3074 } else {
3075 wpa_printf(MSG_ERROR,
3076 "rmdir[ctrl_interface=%s]: %s",
3077 hapd->conf->ctrl_interface,
3078 strerror(errno));
3079 }
3080 }
3081 #endif /* !CONFIG_CTRL_IFACE_UDP */
3082 }
3083
3084 dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst,
3085 list)
3086 os_free(dst);
3087
3088 #ifdef CONFIG_TESTING_OPTIONS
3089 l2_packet_deinit(hapd->l2_test);
3090 hapd->l2_test = NULL;
3091 #endif /* CONFIG_TESTING_OPTIONS */
3092 }
3093
3094
3095 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
3096 char *buf)
3097 {
3098 if (hostapd_add_iface(interfaces, buf) < 0) {
3099 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
3100 return -1;
3101 }
3102 return 0;
3103 }
3104
3105
3106 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
3107 char *buf)
3108 {
3109 if (hostapd_remove_iface(interfaces, buf) < 0) {
3110 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
3111 return -1;
3112 }
3113 return 0;
3114 }
3115
3116
3117 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
3118 struct sockaddr_storage *from,
3119 socklen_t fromlen)
3120 {
3121 return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen);
3122 }
3123
3124
3125 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
3126 struct sockaddr_storage *from,
3127 socklen_t fromlen)
3128 {
3129 return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen);
3130 }
3131
3132
3133 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
3134 {
3135 #ifdef CONFIG_WPS_TESTING
3136 wps_version_number = 0x20;
3137 wps_testing_dummy_cred = 0;
3138 wps_corrupt_pkhash = 0;
3139 #endif /* CONFIG_WPS_TESTING */
3140 }
3141
3142
3143 #ifdef CONFIG_FST
3144
3145 static int
3146 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
3147 const char *cmd)
3148 {
3149 char ifname[IFNAMSIZ + 1];
3150 struct fst_iface_cfg cfg;
3151 struct hostapd_data *hapd;
3152 struct fst_wpa_obj iface_obj;
3153
3154 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
3155 hapd = hostapd_get_iface(interfaces, ifname);
3156 if (hapd) {
3157 if (hapd->iface->fst) {
3158 wpa_printf(MSG_INFO, "FST: Already attached");
3159 return -1;
3160 }
3161 fst_hostapd_fill_iface_obj(hapd, &iface_obj);
3162 hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
3163 &iface_obj, &cfg);
3164 if (hapd->iface->fst)
3165 return 0;
3166 }
3167 }
3168
3169 return -EINVAL;
3170 }
3171
3172
3173 static int
3174 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
3175 const char *cmd)
3176 {
3177 char ifname[IFNAMSIZ + 1];
3178 struct hostapd_data * hapd;
3179
3180 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
3181 hapd = hostapd_get_iface(interfaces, ifname);
3182 if (hapd) {
3183 if (!fst_iface_detach(ifname)) {
3184 hapd->iface->fst = NULL;
3185 hapd->iface->fst_ies = NULL;
3186 return 0;
3187 }
3188 }
3189 }
3190
3191 return -EINVAL;
3192 }
3193
3194 #endif /* CONFIG_FST */
3195
3196
3197 static struct hostapd_data *
3198 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
3199 const char *ifname)
3200 {
3201 size_t i, j;
3202
3203 for (i = 0; i < interfaces->count; i++) {
3204 struct hostapd_iface *iface = interfaces->iface[i];
3205
3206 for (j = 0; j < iface->num_bss; j++) {
3207 struct hostapd_data *hapd;
3208
3209 hapd = iface->bss[j];
3210 if (os_strcmp(ifname, hapd->conf->iface) == 0)
3211 return hapd;
3212 }
3213 }
3214
3215 return NULL;
3216 }
3217
3218
3219 static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
3220 struct hostapd_data *dst_hapd,
3221 const char *param)
3222 {
3223 int res;
3224 char *value;
3225
3226 value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
3227 if (!value) {
3228 wpa_printf(MSG_ERROR,
3229 "DUP: cannot allocate buffer to stringify %s",
3230 param);
3231 goto error_return;
3232 }
3233
3234 if (os_strcmp(param, "wpa") == 0) {
3235 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
3236 src_hapd->conf->wpa);
3237 } else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
3238 src_hapd->conf->wpa_key_mgmt) {
3239 res = hostapd_ctrl_iface_get_key_mgmt(
3240 src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
3241 if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
3242 goto error_stringify;
3243 } else if (os_strcmp(param, "wpa_pairwise") == 0 &&
3244 src_hapd->conf->wpa_pairwise) {
3245 res = wpa_write_ciphers(value,
3246 value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
3247 src_hapd->conf->wpa_pairwise, " ");
3248 if (res < 0)
3249 goto error_stringify;
3250 } else if (os_strcmp(param, "rsn_pairwise") == 0 &&
3251 src_hapd->conf->rsn_pairwise) {
3252 res = wpa_write_ciphers(value,
3253 value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
3254 src_hapd->conf->rsn_pairwise, " ");
3255 if (res < 0)
3256 goto error_stringify;
3257 } else if (os_strcmp(param, "wpa_passphrase") == 0 &&
3258 src_hapd->conf->ssid.wpa_passphrase) {
3259 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
3260 src_hapd->conf->ssid.wpa_passphrase);
3261 } else if (os_strcmp(param, "wpa_psk") == 0 &&
3262 src_hapd->conf->ssid.wpa_psk_set) {
3263 wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
3264 src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
3265 } else {
3266 wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
3267 goto error_return;
3268 }
3269
3270 res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
3271 os_free(value);
3272 return res;
3273
3274 error_stringify:
3275 wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
3276 error_return:
3277 os_free(value);
3278 return -1;
3279 }
3280
3281
3282 static int
3283 hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces,
3284 const char *input,
3285 char *reply, int reply_size)
3286 {
3287 size_t i, j;
3288 int res;
3289 char *pos, *end;
3290 struct hostapd_iface *iface;
3291 int show_ctrl = 0;
3292
3293 if (input)
3294 show_ctrl = !!os_strstr(input, "ctrl");
3295
3296 pos = reply;
3297 end = reply + reply_size;
3298
3299 for (i = 0; i < interfaces->count; i++) {
3300 iface = interfaces->iface[i];
3301
3302 for (j = 0; j < iface->num_bss; j++) {
3303 struct hostapd_bss_config *conf;
3304
3305 conf = iface->conf->bss[j];
3306 if (show_ctrl)
3307 res = os_snprintf(pos, end - pos,
3308 "%s ctrl_iface=%s\n",
3309 conf->iface,
3310 conf->ctrl_interface ?
3311 conf->ctrl_interface : "N/A");
3312 else
3313 res = os_snprintf(pos, end - pos, "%s\n",
3314 conf->iface);
3315 if (os_snprintf_error(end - pos, res)) {
3316 *pos = '\0';
3317 return pos - reply;
3318 }
3319 pos += res;
3320 }
3321 }
3322
3323 return pos - reply;
3324 }
3325
3326
3327 static int
3328 hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
3329 char *cmd)
3330 {
3331 char *p_start = cmd, *p_end;
3332 struct hostapd_data *src_hapd, *dst_hapd;
3333
3334 /* cmd: "<src ifname> <dst ifname> <variable name> */
3335
3336 p_end = os_strchr(p_start, ' ');
3337 if (!p_end) {
3338 wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
3339 cmd);
3340 return -1;
3341 }
3342
3343 *p_end = '\0';
3344 src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
3345 if (!src_hapd) {
3346 wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
3347 p_start);
3348 return -1;
3349 }
3350
3351 p_start = p_end + 1;
3352 p_end = os_strchr(p_start, ' ');
3353 if (!p_end) {
3354 wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
3355 cmd);
3356 return -1;
3357 }
3358
3359 *p_end = '\0';
3360 dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
3361 if (!dst_hapd) {
3362 wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
3363 p_start);
3364 return -1;
3365 }
3366
3367 p_start = p_end + 1;
3368 return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
3369 }
3370
3371
3372 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
3373 const char *ifname,
3374 char *buf, char *reply,
3375 int reply_size,
3376 struct sockaddr_storage *from,
3377 socklen_t fromlen)
3378 {
3379 struct hostapd_data *hapd;
3380
3381 hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
3382 if (hapd == NULL) {
3383 int res;
3384
3385 res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
3386 if (os_snprintf_error(reply_size, res))
3387 return -1;
3388 return res;
3389 }
3390
3391 return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
3392 from, fromlen);
3393 }
3394
3395
3396 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
3397 void *sock_ctx)
3398 {
3399 void *interfaces = eloop_ctx;
3400 char buffer[256], *buf = buffer;
3401 int res;
3402 struct sockaddr_storage from;
3403 socklen_t fromlen = sizeof(from);
3404 char *reply;
3405 int reply_len;
3406 const int reply_size = 4096;
3407 #ifdef CONFIG_CTRL_IFACE_UDP
3408 unsigned char lcookie[COOKIE_LEN];
3409 #endif /* CONFIG_CTRL_IFACE_UDP */
3410
3411 res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
3412 (struct sockaddr *) &from, &fromlen);
3413 if (res < 0) {
3414 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
3415 strerror(errno));
3416 return;
3417 }
3418 buf[res] = '\0';
3419 wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
3420
3421 reply = os_malloc(reply_size);
3422 if (reply == NULL) {
3423 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
3424 fromlen) < 0) {
3425 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
3426 strerror(errno));
3427 }
3428 return;
3429 }
3430
3431 os_memcpy(reply, "OK\n", 3);
3432 reply_len = 3;
3433
3434 #ifdef CONFIG_CTRL_IFACE_UDP
3435 if (os_strcmp(buf, "GET_COOKIE") == 0) {
3436 os_memcpy(reply, "COOKIE=", 7);
3437 wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
3438 gcookie, COOKIE_LEN);
3439 reply_len = 7 + 2 * COOKIE_LEN;
3440 goto send_reply;
3441 }
3442
3443 if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
3444 hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
3445 wpa_printf(MSG_DEBUG,
3446 "CTRL: No cookie in the request - drop request");
3447 os_free(reply);
3448 return;
3449 }
3450
3451 if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) {
3452 wpa_printf(MSG_DEBUG,
3453 "CTRL: Invalid cookie in the request - drop request");
3454 os_free(reply);
3455 return;
3456 }
3457
3458 buf += 7 + 2 * COOKIE_LEN;
3459 while (*buf == ' ')
3460 buf++;
3461 #endif /* CONFIG_CTRL_IFACE_UDP */
3462
3463 if (os_strncmp(buf, "IFNAME=", 7) == 0) {
3464 char *pos = os_strchr(buf + 7, ' ');
3465
3466 if (pos) {
3467 *pos++ = '\0';
3468 reply_len = hostapd_global_ctrl_iface_ifname(
3469 interfaces, buf + 7, pos, reply, reply_size,
3470 &from, fromlen);
3471 goto send_reply;
3472 }
3473 }
3474
3475 if (os_strcmp(buf, "PING") == 0) {
3476 os_memcpy(reply, "PONG\n", 5);
3477 reply_len = 5;
3478 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
3479 if (wpa_debug_reopen_file() < 0)
3480 reply_len = -1;
3481 } else if (os_strcmp(buf, "FLUSH") == 0) {
3482 hostapd_ctrl_iface_flush(interfaces);
3483 } else if (os_strncmp(buf, "ADD ", 4) == 0) {
3484 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
3485 reply_len = -1;
3486 } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
3487 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
3488 reply_len = -1;
3489 } else if (os_strcmp(buf, "ATTACH") == 0) {
3490 if (hostapd_global_ctrl_iface_attach(interfaces, &from,
3491 fromlen))
3492 reply_len = -1;
3493 } else if (os_strcmp(buf, "DETACH") == 0) {
3494 if (hostapd_global_ctrl_iface_detach(interfaces, &from,
3495 fromlen))
3496 reply_len = -1;
3497 #ifdef CONFIG_MODULE_TESTS
3498 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
3499 if (hapd_module_tests() < 0)
3500 reply_len = -1;
3501 #endif /* CONFIG_MODULE_TESTS */
3502 #ifdef CONFIG_FST
3503 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
3504 if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
3505 reply_len = os_snprintf(reply, reply_size, "OK\n");
3506 else
3507 reply_len = -1;
3508 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
3509 if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
3510 reply_len = os_snprintf(reply, reply_size, "OK\n");
3511 else
3512 reply_len = -1;
3513 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
3514 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
3515 #endif /* CONFIG_FST */
3516 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
3517 if (!hostapd_global_ctrl_iface_dup_network(interfaces,
3518 buf + 12))
3519 reply_len = os_snprintf(reply, reply_size, "OK\n");
3520 else
3521 reply_len = -1;
3522 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
3523 reply_len = hostapd_global_ctrl_iface_interfaces(
3524 interfaces, buf + 10, reply, sizeof(buffer));
3525 } else if (os_strcmp(buf, "TERMINATE") == 0) {
3526 eloop_terminate();
3527 } else {
3528 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
3529 "ignored");
3530 reply_len = -1;
3531 }
3532
3533 send_reply:
3534 if (reply_len < 0) {
3535 os_memcpy(reply, "FAIL\n", 5);
3536 reply_len = 5;
3537 }
3538
3539 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
3540 fromlen) < 0) {
3541 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
3542 strerror(errno));
3543 }
3544 os_free(reply);
3545 }
3546
3547
3548 #ifndef CONFIG_CTRL_IFACE_UDP
3549 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
3550 {
3551 char *buf;
3552 size_t len;
3553
3554 if (interface->global_iface_path == NULL)
3555 return NULL;
3556
3557 len = os_strlen(interface->global_iface_path) +
3558 os_strlen(interface->global_iface_name) + 2;
3559 buf = os_malloc(len);
3560 if (buf == NULL)
3561 return NULL;
3562
3563 os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
3564 interface->global_iface_name);
3565 buf[len - 1] = '\0';
3566 return buf;
3567 }
3568 #endif /* CONFIG_CTRL_IFACE_UDP */
3569
3570
3571 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
3572 {
3573 #ifdef CONFIG_CTRL_IFACE_UDP
3574 int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT;
3575 char p[32] = { 0 };
3576 char *pos;
3577 struct addrinfo hints = { 0 }, *res, *saveres;
3578 int n;
3579
3580 if (interface->global_ctrl_sock > -1) {
3581 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
3582 return 0;
3583 }
3584
3585 if (interface->global_iface_path == NULL)
3586 return 0;
3587
3588 pos = os_strstr(interface->global_iface_path, "udp:");
3589 if (pos) {
3590 pos += 4;
3591 port = atoi(pos);
3592 if (port <= 0) {
3593 wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port");
3594 goto fail;
3595 }
3596 }
3597
3598 os_get_random(gcookie, COOKIE_LEN);
3599
3600 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3601 hints.ai_flags = AI_PASSIVE;
3602 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3603
3604 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
3605 hints.ai_family = AF_INET6;
3606 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
3607 hints.ai_family = AF_INET;
3608 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
3609 hints.ai_socktype = SOCK_DGRAM;
3610
3611 try_again:
3612 os_snprintf(p, sizeof(p), "%d", port);
3613 n = getaddrinfo(NULL, p, &hints, &res);
3614 if (n) {
3615 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
3616 goto fail;
3617 }
3618
3619 saveres = res;
3620 interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype,
3621 res->ai_protocol);
3622 if (interface->global_ctrl_sock < 0) {
3623 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
3624 goto fail;
3625 }
3626
3627 if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) <
3628 0) {
3629 port++;
3630 if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) <
3631 HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
3632 goto try_again;
3633 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
3634 goto fail;
3635 }
3636
3637 freeaddrinfo(saveres);
3638
3639 wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port);
3640
3641 if (eloop_register_read_sock(interface->global_ctrl_sock,
3642 hostapd_global_ctrl_iface_receive,
3643 interface, NULL) < 0) {
3644 hostapd_global_ctrl_iface_deinit(interface);
3645 return -1;
3646 }
3647
3648 return 0;
3649
3650 fail:
3651 if (interface->global_ctrl_sock >= 0)
3652 close(interface->global_ctrl_sock);
3653 return -1;
3654 #else /* CONFIG_CTRL_IFACE_UDP */
3655 struct sockaddr_un addr;
3656 int s = -1;
3657 char *fname = NULL;
3658
3659 if (interface->global_iface_path == NULL) {
3660 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
3661 return 0;
3662 }
3663
3664 if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
3665 if (errno == EEXIST) {
3666 wpa_printf(MSG_DEBUG, "Using existing control "
3667 "interface directory.");
3668 } else {
3669 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
3670 strerror(errno));
3671 goto fail;
3672 }
3673 } else if (interface->ctrl_iface_group &&
3674 chown(interface->global_iface_path, -1,
3675 interface->ctrl_iface_group) < 0) {
3676 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
3677 strerror(errno));
3678 goto fail;
3679 }
3680
3681 if (os_strlen(interface->global_iface_path) + 1 +
3682 os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
3683 goto fail;
3684
3685 s = socket(PF_UNIX, SOCK_DGRAM, 0);
3686 if (s < 0) {
3687 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
3688 goto fail;
3689 }
3690
3691 os_memset(&addr, 0, sizeof(addr));
3692 #ifdef __FreeBSD__
3693 addr.sun_len = sizeof(addr);
3694 #endif /* __FreeBSD__ */
3695 addr.sun_family = AF_UNIX;
3696 fname = hostapd_global_ctrl_iface_path(interface);
3697 if (fname == NULL)
3698 goto fail;
3699 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
3700 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3701 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
3702 strerror(errno));
3703 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3704 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
3705 " allow connections - assuming it was left"
3706 "over from forced program termination");
3707 if (unlink(fname) < 0) {
3708 wpa_printf(MSG_ERROR,
3709 "Could not unlink existing ctrl_iface socket '%s': %s",
3710 fname, strerror(errno));
3711 goto fail;
3712 }
3713 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
3714 0) {
3715 wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
3716 strerror(errno));
3717 goto fail;
3718 }
3719 wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
3720 "ctrl_iface socket '%s'", fname);
3721 } else {
3722 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
3723 "be in use - cannot override it");
3724 wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
3725 "not used anymore", fname);
3726 os_free(fname);
3727 fname = NULL;
3728 goto fail;
3729 }
3730 }
3731
3732 if (interface->ctrl_iface_group &&
3733 chown(fname, -1, interface->ctrl_iface_group) < 0) {
3734 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
3735 strerror(errno));
3736 goto fail;
3737 }
3738
3739 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
3740 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
3741 strerror(errno));
3742 goto fail;
3743 }
3744 os_free(fname);
3745
3746 interface->global_ctrl_sock = s;
3747 eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
3748 interface, NULL);
3749
3750 return 0;
3751
3752 fail:
3753 if (s >= 0)
3754 close(s);
3755 if (fname) {
3756 unlink(fname);
3757 os_free(fname);
3758 }
3759 return -1;
3760 #endif /* CONFIG_CTRL_IFACE_UDP */
3761 }
3762
3763
3764 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
3765 {
3766 #ifndef CONFIG_CTRL_IFACE_UDP
3767 char *fname = NULL;
3768 #endif /* CONFIG_CTRL_IFACE_UDP */
3769 struct wpa_ctrl_dst *dst, *prev;
3770
3771 if (interfaces->global_ctrl_sock > -1) {
3772 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
3773 close(interfaces->global_ctrl_sock);
3774 interfaces->global_ctrl_sock = -1;
3775 #ifndef CONFIG_CTRL_IFACE_UDP
3776 fname = hostapd_global_ctrl_iface_path(interfaces);
3777 if (fname) {
3778 unlink(fname);
3779 os_free(fname);
3780 }
3781
3782 if (interfaces->global_iface_path &&
3783 rmdir(interfaces->global_iface_path) < 0) {
3784 if (errno == ENOTEMPTY) {
3785 wpa_printf(MSG_DEBUG, "Control interface "
3786 "directory not empty - leaving it "
3787 "behind");
3788 } else {
3789 wpa_printf(MSG_ERROR,
3790 "rmdir[ctrl_interface=%s]: %s",
3791 interfaces->global_iface_path,
3792 strerror(errno));
3793 }
3794 }
3795 #endif /* CONFIG_CTRL_IFACE_UDP */
3796 }
3797
3798 os_free(interfaces->global_iface_path);
3799 interfaces->global_iface_path = NULL;
3800
3801 dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst,
3802 struct wpa_ctrl_dst, list)
3803 os_free(dst);
3804 }
3805
3806
3807 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
3808 enum wpa_msg_type type,
3809 const char *buf, size_t len)
3810 {
3811 struct wpa_ctrl_dst *dst, *next;
3812 struct dl_list *ctrl_dst;
3813 struct msghdr msg;
3814 int idx;
3815 struct iovec io[2];
3816 char levelstr[10];
3817 int s;
3818
3819 if (type != WPA_MSG_ONLY_GLOBAL) {
3820 s = hapd->ctrl_sock;
3821 ctrl_dst = &hapd->ctrl_dst;
3822 } else {
3823 s = hapd->iface->interfaces->global_ctrl_sock;
3824 ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst;
3825 }
3826
3827 if (s < 0 || dl_list_empty(ctrl_dst))
3828 return;
3829
3830 os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
3831 io[0].iov_base = levelstr;
3832 io[0].iov_len = os_strlen(levelstr);
3833 io[1].iov_base = (char *) buf;
3834 io[1].iov_len = len;
3835 os_memset(&msg, 0, sizeof(msg));
3836 msg.msg_iov = io;
3837 msg.msg_iovlen = 2;
3838
3839 idx = 0;
3840 dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
3841 if (level >= dst->debug_level) {
3842 sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send",
3843 &dst->addr, dst->addrlen);
3844 msg.msg_name = &dst->addr;
3845 msg.msg_namelen = dst->addrlen;
3846 if (sendmsg(s, &msg, 0) < 0) {
3847 int _errno = errno;
3848 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
3849 "%d - %s",
3850 idx, errno, strerror(errno));
3851 dst->errors++;
3852 if (dst->errors > 10 || _errno == ENOENT) {
3853 if (type != WPA_MSG_ONLY_GLOBAL)
3854 hostapd_ctrl_iface_detach(
3855 hapd, &dst->addr,
3856 dst->addrlen);
3857 else
3858 hostapd_global_ctrl_iface_detach(
3859 hapd->iface->interfaces,
3860 &dst->addr,
3861 dst->addrlen);
3862 }
3863 } else
3864 dst->errors = 0;
3865 }
3866 idx++;
3867 }
3868 }
3869
3870 #endif /* CONFIG_NATIVE_WINDOWS */