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