1 /*
2 * hostapd / UNIX domain socket -based control interface
3 * Copyright (c) 2004-2018, 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 #ifdef __NetBSD__
15 #include <net/if_ether.h>
16 #else
17 #include <net/ethernet.h>
18 #endif
19 #include <netinet/ip.h>
20 #endif /* CONFIG_TESTING_OPTIONS */
21
22 #ifndef __ZEPHYR__
23 #include <sys/un.h>
24 #endif /* __ZEPHYR__ */
25 #include <sys/stat.h>
26 #include <stddef.h>
27
28 #ifdef CONFIG_CTRL_IFACE_UDP
29 #include <netdb.h>
30 #endif /* CONFIG_CTRL_IFACE_UDP */
31
32 #include "utils/common.h"
33 #include "utils/eloop.h"
34 #include "utils/module_tests.h"
35 #include "common/version.h"
36 #include "common/ieee802_11_defs.h"
37 #include "common/ctrl_iface_common.h"
38 #ifdef CONFIG_DPP
39 #include "common/dpp.h"
40 #endif /* CONFIG_DPP */
41 #include "common/wpa_ctrl.h"
42 #include "common/ptksa_cache.h"
43 #include "common/hw_features_common.h"
44 #include "common/nan_de.h"
45 #include "crypto/tls.h"
46 #include "drivers/driver.h"
47 #include "eapol_auth/eapol_auth_sm.h"
48 #include "radius/radius_client.h"
49 #include "radius/radius_server.h"
50 #include "l2_packet/l2_packet.h"
51 #include "ap/hostapd.h"
52 #include "ap/ap_config.h"
53 #include "ap/ieee802_1x.h"
54 #include "ap/wpa_auth.h"
55 #include "ap/pmksa_cache_auth.h"
56 #include "ap/ieee802_11.h"
57 #include "ap/sta_info.h"
58 #include "ap/wps_hostapd.h"
59 #include "ap/ctrl_iface_ap.h"
60 #include "ap/ap_drv_ops.h"
61 #include "ap/hs20.h"
62 #include "ap/wnm_ap.h"
63 #include "ap/wpa_auth.h"
64 #include "ap/beacon.h"
65 #include "ap/neighbor_db.h"
66 #include "ap/rrm.h"
67 #include "ap/dpp_hostapd.h"
68 #include "ap/dfs.h"
69 #include "ap/nan_usd_ap.h"
70 #include "wps/wps_defs.h"
71 #include "wps/wps.h"
72 #include "fst/fst_ctrl_iface.h"
73 #include "config_file.h"
74 #include "ctrl_iface.h"
75
76
77 #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
78
79 #ifdef CONFIG_CTRL_IFACE_UDP
80 #define HOSTAPD_CTRL_IFACE_PORT 8877
81 #define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50
82 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878
83 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT 50
84 #endif /* CONFIG_CTRL_IFACE_UDP */
85
86 #ifndef __ZEPHYR__
87 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
88 enum wpa_msg_type type,
89 const char *buf, size_t len);
90
91
hostapd_ctrl_iface_attach(struct hostapd_data * hapd,struct sockaddr_storage * from,socklen_t fromlen,const char * input)92 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
93 struct sockaddr_storage *from,
94 socklen_t fromlen, const char *input)
95 {
96 return ctrl_iface_attach(&hapd->ctrl_dst, from, fromlen, input);
97 }
98
99
hostapd_ctrl_iface_detach(struct hostapd_data * hapd,struct sockaddr_storage * from,socklen_t fromlen)100 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
101 struct sockaddr_storage *from,
102 socklen_t fromlen)
103 {
104 return ctrl_iface_detach(&hapd->ctrl_dst, from, fromlen);
105 }
106
107
hostapd_ctrl_iface_level(struct hostapd_data * hapd,struct sockaddr_storage * from,socklen_t fromlen,char * level)108 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
109 struct sockaddr_storage *from,
110 socklen_t fromlen,
111 char *level)
112 {
113 return ctrl_iface_level(&hapd->ctrl_dst, from, fromlen, level);
114 }
115 #endif /* __ZEPHYR__ */
116
hostapd_ctrl_iface_new_sta(struct hostapd_data * hapd,const char * txtaddr)117 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
118 const char *txtaddr)
119 {
120 u8 addr[ETH_ALEN];
121 struct sta_info *sta;
122
123 wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
124
125 if (hwaddr_aton(txtaddr, addr))
126 return -1;
127
128 sta = ap_get_sta(hapd, addr);
129 if (sta)
130 return 0;
131
132 wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
133 "notification", MAC2STR(addr));
134 sta = ap_sta_add(hapd, addr);
135 if (sta == NULL)
136 return -1;
137
138 hostapd_new_assoc_sta(hapd, sta, 0);
139 return 0;
140 }
141
142
143 #ifdef NEED_AP_MLME
hostapd_ctrl_iface_sa_query(struct hostapd_data * hapd,const char * txtaddr)144 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
145 const char *txtaddr)
146 {
147 u8 addr[ETH_ALEN];
148 u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
149
150 wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
151
152 if (hwaddr_aton(txtaddr, addr) ||
153 os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
154 return -1;
155
156 ieee802_11_send_sa_query_req(hapd, addr, trans_id);
157
158 return 0;
159 }
160 #endif /* NEED_AP_MLME */
161
162
163 #ifdef CONFIG_WPS
hostapd_ctrl_iface_wps_pin(struct hostapd_data * hapd,char * txt)164 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
165 {
166 char *pin = os_strchr(txt, ' ');
167 char *timeout_txt;
168 int timeout;
169 u8 addr_buf[ETH_ALEN], *addr = NULL;
170 char *pos;
171
172 if (pin == NULL)
173 return -1;
174 *pin++ = '\0';
175
176 timeout_txt = os_strchr(pin, ' ');
177 if (timeout_txt) {
178 *timeout_txt++ = '\0';
179 timeout = atoi(timeout_txt);
180 pos = os_strchr(timeout_txt, ' ');
181 if (pos) {
182 *pos++ = '\0';
183 if (hwaddr_aton(pos, addr_buf) == 0)
184 addr = addr_buf;
185 }
186 } else
187 timeout = 0;
188
189 return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
190 }
191
192
hostapd_ctrl_iface_wps_check_pin(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)193 static int hostapd_ctrl_iface_wps_check_pin(
194 struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
195 {
196 char pin[9];
197 size_t len;
198 char *pos;
199 int ret;
200
201 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
202 (u8 *) cmd, os_strlen(cmd));
203 for (pos = cmd, len = 0; *pos != '\0'; pos++) {
204 if (*pos < '0' || *pos > '9')
205 continue;
206 pin[len++] = *pos;
207 if (len == 9) {
208 wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
209 return -1;
210 }
211 }
212 if (len != 4 && len != 8) {
213 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
214 return -1;
215 }
216 pin[len] = '\0';
217
218 if (len == 8) {
219 unsigned int pin_val;
220 pin_val = atoi(pin);
221 if (!wps_pin_valid(pin_val)) {
222 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
223 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
224 if (os_snprintf_error(buflen, ret))
225 return -1;
226 return ret;
227 }
228 }
229
230 ret = os_snprintf(buf, buflen, "%s", pin);
231 if (os_snprintf_error(buflen, ret))
232 return -1;
233
234 return ret;
235 }
236
237
238 #ifdef CONFIG_WPS_NFC
hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data * hapd,char * pos)239 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
240 char *pos)
241 {
242 size_t len;
243 struct wpabuf *buf;
244 int ret;
245
246 len = os_strlen(pos);
247 if (len & 0x01)
248 return -1;
249 len /= 2;
250
251 buf = wpabuf_alloc(len);
252 if (buf == NULL)
253 return -1;
254 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
255 wpabuf_free(buf);
256 return -1;
257 }
258
259 ret = hostapd_wps_nfc_tag_read(hapd, buf);
260 wpabuf_free(buf);
261
262 return ret;
263 }
264
265
hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data * hapd,char * cmd,char * reply,size_t max_len)266 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
267 char *cmd, char *reply,
268 size_t max_len)
269 {
270 int ndef;
271 struct wpabuf *buf;
272 int res;
273
274 if (os_strcmp(cmd, "WPS") == 0)
275 ndef = 0;
276 else if (os_strcmp(cmd, "NDEF") == 0)
277 ndef = 1;
278 else
279 return -1;
280
281 buf = hostapd_wps_nfc_config_token(hapd, ndef);
282 if (buf == NULL)
283 return -1;
284
285 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
286 wpabuf_len(buf));
287 reply[res++] = '\n';
288 reply[res] = '\0';
289
290 wpabuf_free(buf);
291
292 return res;
293 }
294
295
hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data * hapd,char * reply,size_t max_len,int ndef)296 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
297 char *reply, size_t max_len,
298 int ndef)
299 {
300 struct wpabuf *buf;
301 int res;
302
303 buf = hostapd_wps_nfc_token_gen(hapd, ndef);
304 if (buf == NULL)
305 return -1;
306
307 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
308 wpabuf_len(buf));
309 reply[res++] = '\n';
310 reply[res] = '\0';
311
312 wpabuf_free(buf);
313
314 return res;
315 }
316
317
hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data * hapd,char * cmd,char * reply,size_t max_len)318 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
319 char *cmd, char *reply,
320 size_t max_len)
321 {
322 if (os_strcmp(cmd, "WPS") == 0)
323 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
324 max_len, 0);
325
326 if (os_strcmp(cmd, "NDEF") == 0)
327 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
328 max_len, 1);
329
330 if (os_strcmp(cmd, "enable") == 0)
331 return hostapd_wps_nfc_token_enable(hapd);
332
333 if (os_strcmp(cmd, "disable") == 0) {
334 hostapd_wps_nfc_token_disable(hapd);
335 return 0;
336 }
337
338 return -1;
339 }
340
341
hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data * hapd,char * cmd,char * reply,size_t max_len)342 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
343 char *cmd, char *reply,
344 size_t max_len)
345 {
346 struct wpabuf *buf;
347 int res;
348 char *pos;
349 int ndef;
350
351 pos = os_strchr(cmd, ' ');
352 if (pos == NULL)
353 return -1;
354 *pos++ = '\0';
355
356 if (os_strcmp(cmd, "WPS") == 0)
357 ndef = 0;
358 else if (os_strcmp(cmd, "NDEF") == 0)
359 ndef = 1;
360 else
361 return -1;
362
363 if (os_strcmp(pos, "WPS-CR") == 0)
364 buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
365 else
366 buf = NULL;
367 if (buf == NULL)
368 return -1;
369
370 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
371 wpabuf_len(buf));
372 reply[res++] = '\n';
373 reply[res] = '\0';
374
375 wpabuf_free(buf);
376
377 return res;
378 }
379
380
hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data * hapd,char * cmd)381 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
382 char *cmd)
383 {
384 size_t len;
385 struct wpabuf *req, *sel;
386 int ret;
387 char *pos, *role, *type, *pos2;
388
389 role = cmd;
390 pos = os_strchr(role, ' ');
391 if (pos == NULL)
392 return -1;
393 *pos++ = '\0';
394
395 type = pos;
396 pos = os_strchr(type, ' ');
397 if (pos == NULL)
398 return -1;
399 *pos++ = '\0';
400
401 pos2 = os_strchr(pos, ' ');
402 if (pos2 == NULL)
403 return -1;
404 *pos2++ = '\0';
405
406 len = os_strlen(pos);
407 if (len & 0x01)
408 return -1;
409 len /= 2;
410
411 req = wpabuf_alloc(len);
412 if (req == NULL)
413 return -1;
414 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
415 wpabuf_free(req);
416 return -1;
417 }
418
419 len = os_strlen(pos2);
420 if (len & 0x01) {
421 wpabuf_free(req);
422 return -1;
423 }
424 len /= 2;
425
426 sel = wpabuf_alloc(len);
427 if (sel == NULL) {
428 wpabuf_free(req);
429 return -1;
430 }
431 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
432 wpabuf_free(req);
433 wpabuf_free(sel);
434 return -1;
435 }
436
437 if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
438 ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
439 } else {
440 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
441 "reported: role=%s type=%s", role, type);
442 ret = -1;
443 }
444 wpabuf_free(req);
445 wpabuf_free(sel);
446
447 return ret;
448 }
449
450 #endif /* CONFIG_WPS_NFC */
451
452
hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data * hapd,char * txt,char * buf,size_t buflen)453 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
454 char *buf, size_t buflen)
455 {
456 int timeout = 300;
457 char *pos;
458 const char *pin_txt;
459
460 pos = os_strchr(txt, ' ');
461 if (pos)
462 *pos++ = '\0';
463
464 if (os_strcmp(txt, "disable") == 0) {
465 hostapd_wps_ap_pin_disable(hapd);
466 return os_snprintf(buf, buflen, "OK\n");
467 }
468
469 if (os_strcmp(txt, "random") == 0) {
470 if (pos)
471 timeout = atoi(pos);
472 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
473 if (pin_txt == NULL)
474 return -1;
475 return os_snprintf(buf, buflen, "%s", pin_txt);
476 }
477
478 if (os_strcmp(txt, "get") == 0) {
479 pin_txt = hostapd_wps_ap_pin_get(hapd);
480 if (pin_txt == NULL)
481 return -1;
482 return os_snprintf(buf, buflen, "%s", pin_txt);
483 }
484
485 if (os_strcmp(txt, "set") == 0) {
486 char *pin;
487 if (pos == NULL)
488 return -1;
489 pin = pos;
490 pos = os_strchr(pos, ' ');
491 if (pos) {
492 *pos++ = '\0';
493 timeout = atoi(pos);
494 }
495 if (os_strlen(pin) > buflen)
496 return -1;
497 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
498 return -1;
499 return os_snprintf(buf, buflen, "%s", pin);
500 }
501
502 return -1;
503 }
504
505
hostapd_ctrl_iface_wps_config(struct hostapd_data * hapd,char * txt)506 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
507 {
508 char *pos;
509 char *ssid, *auth, *encr = NULL, *key = NULL;
510
511 ssid = txt;
512 pos = os_strchr(txt, ' ');
513 if (!pos)
514 return -1;
515 *pos++ = '\0';
516
517 auth = pos;
518 pos = os_strchr(pos, ' ');
519 if (pos) {
520 *pos++ = '\0';
521 encr = pos;
522 pos = os_strchr(pos, ' ');
523 if (pos) {
524 *pos++ = '\0';
525 key = pos;
526 }
527 }
528
529 return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
530 }
531
532
pbc_status_str(enum pbc_status status)533 static const char * pbc_status_str(enum pbc_status status)
534 {
535 switch (status) {
536 case WPS_PBC_STATUS_DISABLE:
537 return "Disabled";
538 case WPS_PBC_STATUS_ACTIVE:
539 return "Active";
540 case WPS_PBC_STATUS_TIMEOUT:
541 return "Timed-out";
542 case WPS_PBC_STATUS_OVERLAP:
543 return "Overlap";
544 default:
545 return "Unknown";
546 }
547 }
548
549
hostapd_ctrl_iface_wps_get_status(struct hostapd_data * hapd,char * buf,size_t buflen)550 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
551 char *buf, size_t buflen)
552 {
553 int ret;
554 char *pos, *end;
555
556 pos = buf;
557 end = buf + buflen;
558
559 ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
560 pbc_status_str(hapd->wps_stats.pbc_status));
561
562 if (os_snprintf_error(end - pos, ret))
563 return pos - buf;
564 pos += ret;
565
566 ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
567 (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
568 "Success":
569 (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
570 "Failed" : "None")));
571
572 if (os_snprintf_error(end - pos, ret))
573 return pos - buf;
574 pos += ret;
575
576 /* If status == Failure - Add possible Reasons */
577 if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
578 hapd->wps_stats.failure_reason > 0) {
579 ret = os_snprintf(pos, end - pos,
580 "Failure Reason: %s\n",
581 wps_ei_str(hapd->wps_stats.failure_reason));
582
583 if (os_snprintf_error(end - pos, ret))
584 return pos - buf;
585 pos += ret;
586 }
587
588 if (hapd->wps_stats.status) {
589 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
590 MAC2STR(hapd->wps_stats.peer_addr));
591
592 if (os_snprintf_error(end - pos, ret))
593 return pos - buf;
594 pos += ret;
595 }
596
597 return pos - buf;
598 }
599
600 #endif /* CONFIG_WPS */
601
602 #ifdef CONFIG_HS20
603
hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data * hapd,const char * cmd)604 static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
605 const char *cmd)
606 {
607 u8 addr[ETH_ALEN];
608 const char *url;
609
610 if (hwaddr_aton(cmd, addr))
611 return -1;
612 url = cmd + 17;
613 if (*url == '\0') {
614 url = NULL;
615 } else {
616 if (*url != ' ')
617 return -1;
618 url++;
619 if (*url == '\0')
620 url = NULL;
621 }
622
623 return hs20_send_wnm_notification(hapd, addr, 1, url);
624 }
625
626
hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data * hapd,const char * cmd)627 static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
628 const char *cmd)
629 {
630 u8 addr[ETH_ALEN];
631 int code, reauth_delay, ret;
632 const char *pos;
633 size_t url_len;
634 struct wpabuf *req;
635
636 /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
637 if (hwaddr_aton(cmd, addr))
638 return -1;
639
640 pos = os_strchr(cmd, ' ');
641 if (pos == NULL)
642 return -1;
643 pos++;
644 code = atoi(pos);
645
646 pos = os_strchr(pos, ' ');
647 if (pos == NULL)
648 return -1;
649 pos++;
650 reauth_delay = atoi(pos);
651
652 url_len = 0;
653 pos = os_strchr(pos, ' ');
654 if (pos) {
655 pos++;
656 url_len = os_strlen(pos);
657 }
658
659 req = wpabuf_alloc(4 + url_len);
660 if (req == NULL)
661 return -1;
662 wpabuf_put_u8(req, code);
663 wpabuf_put_le16(req, reauth_delay);
664 wpabuf_put_u8(req, url_len);
665 if (pos)
666 wpabuf_put_data(req, pos, url_len);
667
668 wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
669 " to indicate imminent deauthentication (code=%d "
670 "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
671 ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
672 wpabuf_free(req);
673 return ret;
674 }
675
676 #endif /* CONFIG_HS20 */
677
678
679 #ifdef CONFIG_INTERWORKING
680
hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data * hapd,const char * cmd)681 static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
682 const char *cmd)
683 {
684 u8 qos_map_set[16 + 2 * 21], count = 0;
685 const char *pos = cmd;
686 int val, ret;
687
688 for (;;) {
689 if (count == sizeof(qos_map_set)) {
690 wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
691 return -1;
692 }
693
694 val = atoi(pos);
695 if (val < 0 || val > 255) {
696 wpa_printf(MSG_INFO, "Invalid QoS Map Set");
697 return -1;
698 }
699
700 qos_map_set[count++] = val;
701 pos = os_strchr(pos, ',');
702 if (!pos)
703 break;
704 pos++;
705 }
706
707 if (count < 16 || count & 1) {
708 wpa_printf(MSG_INFO, "Invalid QoS Map Set");
709 return -1;
710 }
711
712 ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
713 if (ret) {
714 wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
715 return -1;
716 }
717
718 os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
719 hapd->conf->qos_map_set_len = count;
720
721 return 0;
722 }
723
724
hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data * hapd,const char * cmd)725 static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
726 const char *cmd)
727 {
728 u8 addr[ETH_ALEN];
729 struct sta_info *sta;
730 struct wpabuf *buf;
731 u8 *qos_map_set = hapd->conf->qos_map_set;
732 u8 qos_map_set_len = hapd->conf->qos_map_set_len;
733 int ret;
734
735 if (!qos_map_set_len) {
736 wpa_printf(MSG_INFO, "QoS Map Set is not set");
737 return -1;
738 }
739
740 if (hwaddr_aton(cmd, addr))
741 return -1;
742
743 sta = ap_get_sta(hapd, addr);
744 if (sta == NULL) {
745 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
746 "for QoS Map Configuration message",
747 MAC2STR(addr));
748 return -1;
749 }
750
751 if (!sta->qos_map_enabled) {
752 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
753 "support for QoS Map", MAC2STR(addr));
754 return -1;
755 }
756
757 buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
758 if (buf == NULL)
759 return -1;
760
761 wpabuf_put_u8(buf, WLAN_ACTION_QOS);
762 wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
763
764 /* QoS Map Set Element */
765 wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
766 wpabuf_put_u8(buf, qos_map_set_len);
767 wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
768
769 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
770 wpabuf_head(buf), wpabuf_len(buf));
771 wpabuf_free(buf);
772
773 return ret;
774 }
775
776 #endif /* CONFIG_INTERWORKING */
777
778
779 #ifdef CONFIG_WNM_AP
780
hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data * hapd,const char * cmd)781 static int hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data *hapd,
782 const char *cmd)
783 {
784 u8 addr[ETH_ALEN];
785 struct sta_info *sta;
786 const char *pos;
787 unsigned int auto_report, timeout;
788
789 if (hwaddr_aton(cmd, addr)) {
790 wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
791 return -1;
792 }
793
794 sta = ap_get_sta(hapd, addr);
795 if (!sta) {
796 wpa_printf(MSG_DEBUG, "Station " MACSTR
797 " not found for Collocated Interference Request",
798 MAC2STR(addr));
799 return -1;
800 }
801
802 pos = cmd + 17;
803 if (*pos != ' ')
804 return -1;
805 pos++;
806 auto_report = atoi(pos);
807 pos = os_strchr(pos, ' ');
808 if (!pos)
809 return -1;
810 pos++;
811 timeout = atoi(pos);
812
813 return wnm_send_coloc_intf_req(hapd, sta, auto_report, timeout);
814 }
815
816 #endif /* CONFIG_WNM_AP */
817
818
hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data * hapd,char * buf,size_t buflen)819 static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd,
820 char *buf, size_t buflen)
821 {
822 int ret = 0;
823 char *pos, *end;
824
825 pos = buf;
826 end = buf + buflen;
827
828 WPA_ASSERT(hapd->conf->wpa_key_mgmt);
829
830 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
831 ret = os_snprintf(pos, end - pos, "WPA-PSK ");
832 if (os_snprintf_error(end - pos, ret))
833 return pos - buf;
834 pos += ret;
835 }
836 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
837 ret = os_snprintf(pos, end - pos, "WPA-EAP ");
838 if (os_snprintf_error(end - pos, ret))
839 return pos - buf;
840 pos += ret;
841 }
842 #ifdef CONFIG_IEEE80211R_AP
843 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
844 ret = os_snprintf(pos, end - pos, "FT-PSK ");
845 if (os_snprintf_error(end - pos, ret))
846 return pos - buf;
847 pos += ret;
848 }
849 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
850 ret = os_snprintf(pos, end - pos, "FT-EAP ");
851 if (os_snprintf_error(end - pos, ret))
852 return pos - buf;
853 pos += ret;
854 }
855 #ifdef CONFIG_SHA384
856 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
857 ret = os_snprintf(pos, end - pos, "FT-EAP-SHA384 ");
858 if (os_snprintf_error(end - pos, ret))
859 return pos - buf;
860 pos += ret;
861 }
862 #endif /* CONFIG_SHA384 */
863 #ifdef CONFIG_SAE
864 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
865 ret = os_snprintf(pos, end - pos, "FT-SAE ");
866 if (os_snprintf_error(end - pos, ret))
867 return pos - buf;
868 pos += ret;
869 }
870 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
871 ret = os_snprintf(pos, end - pos, "FT-SAE-EXT-KEY ");
872 if (os_snprintf_error(end - pos, ret))
873 return pos - buf;
874 pos += ret;
875 }
876 #endif /* CONFIG_SAE */
877 #ifdef CONFIG_FILS
878 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
879 ret = os_snprintf(pos, end - pos, "FT-FILS-SHA256 ");
880 if (os_snprintf_error(end - pos, ret))
881 return pos - buf;
882 pos += ret;
883 }
884 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
885 ret = os_snprintf(pos, end - pos, "FT-FILS-SHA384 ");
886 if (os_snprintf_error(end - pos, ret))
887 return pos - buf;
888 pos += ret;
889 }
890 #endif /* CONFIG_FILS */
891 #endif /* CONFIG_IEEE80211R_AP */
892 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
893 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
894 if (os_snprintf_error(end - pos, ret))
895 return pos - buf;
896 pos += ret;
897 }
898 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
899 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
900 if (os_snprintf_error(end - pos, ret))
901 return pos - buf;
902 pos += ret;
903 }
904 #ifdef CONFIG_SAE
905 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
906 ret = os_snprintf(pos, end - pos, "SAE ");
907 if (os_snprintf_error(end - pos, ret))
908 return pos - buf;
909 pos += ret;
910 }
911 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
912 ret = os_snprintf(pos, end - pos, "SAE-EXT-KEY ");
913 if (os_snprintf_error(end - pos, ret))
914 return pos - buf;
915 pos += ret;
916 }
917 #endif /* CONFIG_SAE */
918 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
919 ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
920 if (os_snprintf_error(end - pos, ret))
921 return pos - buf;
922 pos += ret;
923 }
924 if (hapd->conf->wpa_key_mgmt &
925 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
926 ret = os_snprintf(pos, end - pos,
927 "WPA-EAP-SUITE-B-192 ");
928 if (os_snprintf_error(end - pos, ret))
929 return pos - buf;
930 pos += ret;
931 }
932 #ifdef CONFIG_FILS
933 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
934 ret = os_snprintf(pos, end - pos, "FILS-SHA256 ");
935 if (os_snprintf_error(end - pos, ret))
936 return pos - buf;
937 pos += ret;
938 }
939 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
940 ret = os_snprintf(pos, end - pos, "FILS-SHA384 ");
941 if (os_snprintf_error(end - pos, ret))
942 return pos - buf;
943 pos += ret;
944 }
945 #endif /* CONFIG_FILS */
946
947 #ifdef CONFIG_OWE
948 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) {
949 ret = os_snprintf(pos, end - pos, "OWE ");
950 if (os_snprintf_error(end - pos, ret))
951 return pos - buf;
952 pos += ret;
953 }
954 #endif /* CONFIG_OWE */
955
956 #ifdef CONFIG_DPP
957 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) {
958 ret = os_snprintf(pos, end - pos, "DPP ");
959 if (os_snprintf_error(end - pos, ret))
960 return pos - buf;
961 pos += ret;
962 }
963 #endif /* CONFIG_DPP */
964 #ifdef CONFIG_SHA384
965 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
966 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA384 ");
967 if (os_snprintf_error(end - pos, ret))
968 return pos - buf;
969 pos += ret;
970 }
971 #endif /* CONFIG_SHA384 */
972
973 if (pos > buf && *(pos - 1) == ' ') {
974 *(pos - 1) = '\0';
975 pos--;
976 }
977
978 return pos - buf;
979 }
980
981
hostapd_ctrl_iface_get_config(struct hostapd_data * hapd,char * buf,size_t buflen)982 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
983 char *buf, size_t buflen)
984 {
985 int ret;
986 char *pos, *end;
987
988 pos = buf;
989 end = buf + buflen;
990
991 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
992 "ssid=%s\n",
993 MAC2STR(hapd->own_addr),
994 wpa_ssid_txt(hapd->conf->ssid.ssid,
995 hapd->conf->ssid.ssid_len));
996 if (os_snprintf_error(end - pos, ret))
997 return pos - buf;
998 pos += ret;
999
1000 if ((hapd->conf->config_id)) {
1001 ret = os_snprintf(pos, end - pos, "config_id=%s\n",
1002 hapd->conf->config_id);
1003 if (os_snprintf_error(end - pos, ret))
1004 return pos - buf;
1005 pos += ret;
1006 }
1007
1008 #ifdef CONFIG_WPS
1009 ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
1010 hapd->conf->wps_state == 0 ? "disabled" :
1011 (hapd->conf->wps_state == 1 ? "not configured" :
1012 "configured"));
1013 if (os_snprintf_error(end - pos, ret))
1014 return pos - buf;
1015 pos += ret;
1016
1017 if (hapd->conf->wps_state && hapd->conf->wpa &&
1018 hapd->conf->ssid.wpa_passphrase) {
1019 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
1020 hapd->conf->ssid.wpa_passphrase);
1021 if (os_snprintf_error(end - pos, ret))
1022 return pos - buf;
1023 pos += ret;
1024 }
1025
1026 if (hapd->conf->wps_state && hapd->conf->wpa &&
1027 hapd->conf->ssid.wpa_psk &&
1028 hapd->conf->ssid.wpa_psk->group) {
1029 char hex[PMK_LEN * 2 + 1];
1030 wpa_snprintf_hex(hex, sizeof(hex),
1031 hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
1032 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
1033 if (os_snprintf_error(end - pos, ret))
1034 return pos - buf;
1035 pos += ret;
1036 }
1037
1038 if (hapd->conf->multi_ap) {
1039 struct hostapd_ssid *ssid = &hapd->conf->multi_ap_backhaul_ssid;
1040
1041 ret = os_snprintf(pos, end - pos, "multi_ap=%d\n",
1042 hapd->conf->multi_ap);
1043 if (os_snprintf_error(end - pos, ret))
1044 return pos - buf;
1045 pos += ret;
1046
1047 if (ssid->ssid_len) {
1048 ret = os_snprintf(pos, end - pos,
1049 "multi_ap_backhaul_ssid=%s\n",
1050 wpa_ssid_txt(ssid->ssid,
1051 ssid->ssid_len));
1052 if (os_snprintf_error(end - pos, ret))
1053 return pos - buf;
1054 pos += ret;
1055 }
1056
1057 if (hapd->conf->wps_state && hapd->conf->wpa &&
1058 ssid->wpa_passphrase) {
1059 ret = os_snprintf(pos, end - pos,
1060 "multi_ap_backhaul_wpa_passphrase=%s\n",
1061 ssid->wpa_passphrase);
1062 if (os_snprintf_error(end - pos, ret))
1063 return pos - buf;
1064 pos += ret;
1065 }
1066
1067 if (hapd->conf->wps_state && hapd->conf->wpa &&
1068 ssid->wpa_psk &&
1069 ssid->wpa_psk->group) {
1070 char hex[PMK_LEN * 2 + 1];
1071
1072 wpa_snprintf_hex(hex, sizeof(hex), ssid->wpa_psk->psk,
1073 PMK_LEN);
1074 ret = os_snprintf(pos, end - pos,
1075 "multi_ap_backhaul_wpa_psk=%s\n",
1076 hex);
1077 forced_memzero(hex, sizeof(hex));
1078 if (os_snprintf_error(end - pos, ret))
1079 return pos - buf;
1080 pos += ret;
1081 }
1082 }
1083 #endif /* CONFIG_WPS */
1084
1085 if (hapd->conf->wpa) {
1086 ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa);
1087 if (os_snprintf_error(end - pos, ret))
1088 return pos - buf;
1089 pos += ret;
1090 }
1091
1092 if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
1093 ret = os_snprintf(pos, end - pos, "key_mgmt=");
1094 if (os_snprintf_error(end - pos, ret))
1095 return pos - buf;
1096 pos += ret;
1097
1098 pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos);
1099
1100 ret = os_snprintf(pos, end - pos, "\n");
1101 if (os_snprintf_error(end - pos, ret))
1102 return pos - buf;
1103 pos += ret;
1104 }
1105
1106 if (hapd->conf->wpa) {
1107 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
1108 wpa_cipher_txt(hapd->conf->wpa_group));
1109 if (os_snprintf_error(end - pos, ret))
1110 return pos - buf;
1111 pos += ret;
1112 }
1113
1114 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
1115 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
1116 if (os_snprintf_error(end - pos, ret))
1117 return pos - buf;
1118 pos += ret;
1119
1120 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
1121 " ");
1122 if (ret < 0)
1123 return pos - buf;
1124 pos += ret;
1125
1126 ret = os_snprintf(pos, end - pos, "\n");
1127 if (os_snprintf_error(end - pos, ret))
1128 return pos - buf;
1129 pos += ret;
1130 }
1131
1132 if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
1133 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
1134 if (os_snprintf_error(end - pos, ret))
1135 return pos - buf;
1136 pos += ret;
1137
1138 ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
1139 " ");
1140 if (ret < 0)
1141 return pos - buf;
1142 pos += ret;
1143
1144 ret = os_snprintf(pos, end - pos, "\n");
1145 if (os_snprintf_error(end - pos, ret))
1146 return pos - buf;
1147 pos += ret;
1148 }
1149
1150 if (hapd->conf->wpa && hapd->conf->wpa_deny_ptk0_rekey) {
1151 ret = os_snprintf(pos, end - pos, "wpa_deny_ptk0_rekey=%d\n",
1152 hapd->conf->wpa_deny_ptk0_rekey);
1153 if (os_snprintf_error(end - pos, ret))
1154 return pos - buf;
1155 pos += ret;
1156 }
1157
1158 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->extended_key_id) {
1159 ret = os_snprintf(pos, end - pos, "extended_key_id=%d\n",
1160 hapd->conf->extended_key_id);
1161 if (os_snprintf_error(end - pos, ret))
1162 return pos - buf;
1163 pos += ret;
1164 }
1165
1166 return pos - buf;
1167 }
1168
1169
hostapd_ctrl_iface_set_band(struct hostapd_data * hapd,const char * bands)1170 static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd,
1171 const char *bands)
1172 {
1173 union wpa_event_data event;
1174 u32 setband_mask = WPA_SETBAND_AUTO;
1175
1176 /*
1177 * For example:
1178 * SET setband 2G,6G
1179 * SET setband 5G
1180 * SET setband AUTO
1181 */
1182 if (!os_strstr(bands, "AUTO")) {
1183 if (os_strstr(bands, "5G"))
1184 setband_mask |= WPA_SETBAND_5G;
1185 if (os_strstr(bands, "6G"))
1186 setband_mask |= WPA_SETBAND_6G;
1187 if (os_strstr(bands, "2G"))
1188 setband_mask |= WPA_SETBAND_2G;
1189 if (setband_mask == WPA_SETBAND_AUTO)
1190 return -1;
1191 }
1192
1193 if (hostapd_drv_set_band(hapd, setband_mask) == 0) {
1194 os_memset(&event, 0, sizeof(event));
1195 event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
1196 event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
1197 wpa_supplicant_event(hapd, EVENT_CHANNEL_LIST_CHANGED, &event);
1198 }
1199
1200 return 0;
1201 }
1202
1203
hostapd_ctrl_iface_set(struct hostapd_data * hapd,char * cmd)1204 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
1205 {
1206 char *value;
1207 int ret = 0;
1208
1209 value = os_strchr(cmd, ' ');
1210 if (value == NULL)
1211 return -1;
1212 *value++ = '\0';
1213
1214 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
1215 if (0) {
1216 #ifdef CONFIG_WPS_TESTING
1217 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
1218 long int val;
1219 val = strtol(value, NULL, 0);
1220 if (val < 0 || val > 0xff) {
1221 ret = -1;
1222 wpa_printf(MSG_DEBUG, "WPS: Invalid "
1223 "wps_version_number %ld", val);
1224 } else {
1225 wps_version_number = val;
1226 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
1227 "version %u.%u",
1228 (wps_version_number & 0xf0) >> 4,
1229 wps_version_number & 0x0f);
1230 hostapd_wps_update_ie(hapd);
1231 }
1232 } else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) {
1233 wps_testing_stub_cred = atoi(value);
1234 wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d",
1235 wps_testing_stub_cred);
1236 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
1237 wps_corrupt_pkhash = atoi(value);
1238 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
1239 wps_corrupt_pkhash);
1240 #endif /* CONFIG_WPS_TESTING */
1241 #ifdef CONFIG_TESTING_OPTIONS
1242 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
1243 hapd->ext_mgmt_frame_handling = atoi(value);
1244 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
1245 hapd->ext_eapol_frame_io = atoi(value);
1246 } else if (os_strcasecmp(cmd, "force_backlog_bytes") == 0) {
1247 hapd->force_backlog_bytes = atoi(value);
1248 #ifdef CONFIG_DPP
1249 } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
1250 os_free(hapd->dpp_config_obj_override);
1251 hapd->dpp_config_obj_override = os_strdup(value);
1252 } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) {
1253 os_free(hapd->dpp_discovery_override);
1254 hapd->dpp_discovery_override = os_strdup(value);
1255 } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) {
1256 os_free(hapd->dpp_groups_override);
1257 hapd->dpp_groups_override = os_strdup(value);
1258 } else if (os_strcasecmp(cmd,
1259 "dpp_ignore_netaccesskey_mismatch") == 0) {
1260 hapd->dpp_ignore_netaccesskey_mismatch = atoi(value);
1261 } else if (os_strcasecmp(cmd, "dpp_test") == 0) {
1262 dpp_test = atoi(value);
1263 } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) {
1264 dpp_version_override = atoi(value);
1265 #endif /* CONFIG_DPP */
1266 #endif /* CONFIG_TESTING_OPTIONS */
1267 #ifdef CONFIG_MBO
1268 } else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) {
1269 int val;
1270
1271 if (!hapd->conf->mbo_enabled)
1272 return -1;
1273
1274 val = atoi(value);
1275 if (val < 0 || val > MBO_ASSOC_DISALLOW_REASON_LOW_RSSI)
1276 return -1;
1277
1278 hapd->mbo_assoc_disallow = val;
1279 ieee802_11_update_beacons(hapd->iface);
1280
1281 /*
1282 * TODO: Need to configure drivers that do AP MLME offload with
1283 * disallowing station logic.
1284 */
1285 #endif /* CONFIG_MBO */
1286 #ifdef CONFIG_DPP
1287 } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
1288 os_free(hapd->dpp_configurator_params);
1289 hapd->dpp_configurator_params = os_strdup(value);
1290 #ifdef CONFIG_DPP2
1291 dpp_controller_set_params(hapd->iface->interfaces->dpp, value);
1292 #endif /* CONFIG_DPP2 */
1293 } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
1294 hapd->dpp_init_max_tries = atoi(value);
1295 } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
1296 hapd->dpp_init_retry_time = atoi(value);
1297 } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
1298 hapd->dpp_resp_wait_time = atoi(value);
1299 } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
1300 hapd->dpp_resp_max_tries = atoi(value);
1301 } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
1302 hapd->dpp_resp_retry_time = atoi(value);
1303 #endif /* CONFIG_DPP */
1304 } else if (os_strcasecmp(cmd, "setband") == 0) {
1305 ret = hostapd_ctrl_iface_set_band(hapd, value);
1306 } else {
1307 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
1308 if (ret)
1309 return ret;
1310
1311 if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
1312 hostapd_disassoc_deny_mac(hapd);
1313 } else if (os_strcasecmp(cmd, "accept_mac_file") == 0) {
1314 hostapd_disassoc_accept_mac(hapd);
1315 } else if (os_strcasecmp(cmd, "ssid") == 0) {
1316 hostapd_neighbor_sync_own_report(hapd);
1317 #ifndef CONFIG_NO_WMM_AC
1318 } else if (os_strncmp(cmd, "wme_ac_", 7) == 0 ||
1319 os_strncmp(cmd, "wmm_ac_", 7) == 0) {
1320 hapd->parameter_set_count++;
1321 if (ieee802_11_update_beacons(hapd->iface))
1322 wpa_printf(MSG_DEBUG,
1323 "Failed to update beacons with WMM parameters");
1324 #endif /* CONFIG_WMM_AC */
1325 } else if (os_strcmp(cmd, "wpa_passphrase") == 0 ||
1326 os_strcmp(cmd, "sae_password") == 0 ||
1327 os_strcmp(cmd, "sae_pwe") == 0) {
1328 if (hapd->started)
1329 hostapd_setup_sae_pt(hapd->conf);
1330 } else if (os_strcasecmp(cmd, "transition_disable") == 0) {
1331 wpa_auth_set_transition_disable(hapd->wpa_auth,
1332 hapd->conf->transition_disable);
1333 }
1334
1335 #ifdef CONFIG_TESTING_OPTIONS
1336 if (os_strcmp(cmd, "ft_rsnxe_used") == 0)
1337 wpa_auth_set_ft_rsnxe_used(hapd->wpa_auth,
1338 hapd->conf->ft_rsnxe_used);
1339 else if (os_strcmp(cmd, "oci_freq_override_eapol_m3") == 0)
1340 wpa_auth_set_ocv_override_freq(
1341 hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_M3,
1342 atoi(value));
1343 else if (os_strcmp(cmd, "oci_freq_override_eapol_g1") == 0)
1344 wpa_auth_set_ocv_override_freq(
1345 hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_G1,
1346 atoi(value));
1347 else if (os_strcmp(cmd, "oci_freq_override_ft_assoc") == 0)
1348 wpa_auth_set_ocv_override_freq(
1349 hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_FT_ASSOC,
1350 atoi(value));
1351 else if (os_strcmp(cmd, "oci_freq_override_fils_assoc") == 0)
1352 wpa_auth_set_ocv_override_freq(
1353 hapd->wpa_auth,
1354 WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, atoi(value));
1355 #endif /* CONFIG_TESTING_OPTIONS */
1356 }
1357
1358 return ret;
1359 }
1360
1361
hostapd_ctrl_iface_get(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)1362 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
1363 char *buf, size_t buflen)
1364 {
1365 int res;
1366
1367 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
1368
1369 if (os_strcmp(cmd, "version") == 0) {
1370 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
1371 if (os_snprintf_error(buflen, res))
1372 return -1;
1373 return res;
1374 } else if (os_strcmp(cmd, "tls_library") == 0) {
1375 res = tls_get_library_version(buf, buflen);
1376 if (os_snprintf_error(buflen, res))
1377 return -1;
1378 return res;
1379 }
1380
1381 return -1;
1382 }
1383
1384
hostapd_ctrl_iface_enable(struct hostapd_iface * iface)1385 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
1386 {
1387 if (hostapd_enable_iface(iface) < 0) {
1388 wpa_printf(MSG_ERROR, "Enabling of interface failed");
1389 return -1;
1390 }
1391 return 0;
1392 }
1393
1394
hostapd_ctrl_iface_reload(struct hostapd_iface * iface)1395 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
1396 {
1397 if (hostapd_reload_iface(iface) < 0) {
1398 wpa_printf(MSG_ERROR, "Reloading of interface failed");
1399 return -1;
1400 }
1401 return 0;
1402 }
1403
1404
hostapd_ctrl_iface_reload_bss(struct hostapd_data * bss)1405 static int hostapd_ctrl_iface_reload_bss(struct hostapd_data *bss)
1406 {
1407 if (hostapd_reload_bss_only(bss) < 0) {
1408 wpa_printf(MSG_ERROR, "Reloading of BSS failed");
1409 return -1;
1410 }
1411 return 0;
1412 }
1413
1414
hostapd_ctrl_iface_disable(struct hostapd_iface * iface)1415 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
1416 {
1417 if (hostapd_disable_iface(iface) < 0) {
1418 wpa_printf(MSG_ERROR, "Disabling of interface failed");
1419 return -1;
1420 }
1421 return 0;
1422 }
1423
1424
1425 static int
hostapd_ctrl_iface_kick_mismatch_psk_sta_iter(struct hostapd_data * hapd,struct sta_info * sta,void * ctx)1426 hostapd_ctrl_iface_kick_mismatch_psk_sta_iter(struct hostapd_data *hapd,
1427 struct sta_info *sta, void *ctx)
1428 {
1429 struct hostapd_wpa_psk *psk;
1430 const u8 *pmk;
1431 int pmk_len;
1432 int pmk_match;
1433 int sta_match;
1434 int bss_match;
1435 int reason;
1436
1437 pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len);
1438
1439 for (psk = hapd->conf->ssid.wpa_psk; pmk && psk; psk = psk->next) {
1440 pmk_match = PMK_LEN == pmk_len &&
1441 os_memcmp(psk->psk, pmk, pmk_len) == 0;
1442 sta_match = psk->group == 0 &&
1443 ether_addr_equal(sta->addr, psk->addr);
1444 bss_match = psk->group == 1;
1445
1446 if (pmk_match && (sta_match || bss_match))
1447 return 0;
1448 }
1449
1450 wpa_printf(MSG_INFO, "STA " MACSTR
1451 " PSK/passphrase no longer valid - disconnect",
1452 MAC2STR(sta->addr));
1453 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
1454 hostapd_drv_sta_deauth(hapd, sta->addr, reason);
1455 ap_sta_deauthenticate(hapd, sta, reason);
1456
1457 return 0;
1458 }
1459
1460
hostapd_ctrl_iface_reload_wpa_psk(struct hostapd_data * hapd)1461 static int hostapd_ctrl_iface_reload_wpa_psk(struct hostapd_data *hapd)
1462 {
1463 struct hostapd_bss_config *conf = hapd->conf;
1464 int err;
1465
1466 hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk);
1467
1468 err = hostapd_setup_wpa_psk(conf);
1469 if (err < 0) {
1470 wpa_printf(MSG_ERROR, "Reloading WPA-PSK passwords failed: %d",
1471 err);
1472 return -1;
1473 }
1474
1475 ap_for_each_sta(hapd, hostapd_ctrl_iface_kick_mismatch_psk_sta_iter,
1476 NULL);
1477
1478 return 0;
1479 }
1480
1481
1482 #ifdef CONFIG_IEEE80211R_AP
1483
hostapd_ctrl_iface_get_rxkhs(struct hostapd_data * hapd,char * buf,size_t buflen)1484 static int hostapd_ctrl_iface_get_rxkhs(struct hostapd_data *hapd,
1485 char *buf, size_t buflen)
1486 {
1487 int ret, start_pos;
1488 char *pos, *end;
1489 struct ft_remote_r0kh *r0kh;
1490 struct ft_remote_r1kh *r1kh;
1491 struct hostapd_bss_config *conf = hapd->conf;
1492
1493 pos = buf;
1494 end = buf + buflen;
1495
1496 for (r0kh = conf->r0kh_list; r0kh; r0kh=r0kh->next) {
1497 start_pos = pos - buf;
1498 ret = os_snprintf(pos, end - pos, "r0kh=" MACSTR " ",
1499 MAC2STR(r0kh->addr));
1500 if (os_snprintf_error(end - pos, ret))
1501 return start_pos;
1502 pos += ret;
1503 if (r0kh->id_len + 1 >= (size_t) (end - pos))
1504 return start_pos;
1505 os_memcpy(pos, r0kh->id, r0kh->id_len);
1506 pos += r0kh->id_len;
1507 *pos++ = ' ';
1508 pos += wpa_snprintf_hex(pos, end - pos, r0kh->key,
1509 sizeof(r0kh->key));
1510 ret = os_snprintf(pos, end - pos, "\n");
1511 if (os_snprintf_error(end - pos, ret))
1512 return start_pos;
1513 pos += ret;
1514 }
1515
1516 for (r1kh = conf->r1kh_list; r1kh; r1kh=r1kh->next) {
1517 start_pos = pos - buf;
1518 ret = os_snprintf(pos, end - pos, "r1kh=" MACSTR " " MACSTR " ",
1519 MAC2STR(r1kh->addr), MAC2STR(r1kh->id));
1520 if (os_snprintf_error(end - pos, ret))
1521 return start_pos;
1522 pos += ret;
1523 pos += wpa_snprintf_hex(pos, end - pos, r1kh->key,
1524 sizeof(r1kh->key));
1525 ret = os_snprintf(pos, end - pos, "\n");
1526 if (os_snprintf_error(end - pos, ret))
1527 return start_pos;
1528 pos += ret;
1529 }
1530
1531 return pos - buf;
1532 }
1533
1534
hostapd_ctrl_iface_reload_rxkhs(struct hostapd_data * hapd)1535 static int hostapd_ctrl_iface_reload_rxkhs(struct hostapd_data *hapd)
1536 {
1537 struct hostapd_bss_config *conf = hapd->conf;
1538 int err;
1539
1540 hostapd_config_clear_rxkhs(conf);
1541
1542 err = hostapd_config_read_rxkh_file(conf, conf->rxkh_file);
1543 if (err < 0) {
1544 wpa_printf(MSG_ERROR, "Reloading RxKHs failed: %d",
1545 err);
1546 return -1;
1547 }
1548
1549 return 0;
1550 }
1551
1552 #endif /* CONFIG_IEEE80211R_AP */
1553
1554
1555 #ifdef CONFIG_TESTING_OPTIONS
1556
hostapd_ctrl_iface_radar(struct hostapd_data * hapd,char * cmd)1557 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
1558 {
1559 union wpa_event_data data;
1560 char *pos, *param;
1561 enum wpa_event_type event;
1562
1563 wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1564
1565 os_memset(&data, 0, sizeof(data));
1566
1567 param = os_strchr(cmd, ' ');
1568 if (param == NULL)
1569 return -1;
1570 *param++ = '\0';
1571
1572 if (os_strcmp(cmd, "DETECTED") == 0)
1573 event = EVENT_DFS_RADAR_DETECTED;
1574 else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1575 event = EVENT_DFS_CAC_FINISHED;
1576 else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1577 event = EVENT_DFS_CAC_ABORTED;
1578 else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1579 event = EVENT_DFS_NOP_FINISHED;
1580 else {
1581 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1582 cmd);
1583 return -1;
1584 }
1585
1586 pos = os_strstr(param, "freq=");
1587 if (pos)
1588 data.dfs_event.freq = atoi(pos + 5);
1589
1590 pos = os_strstr(param, "ht_enabled=1");
1591 if (pos)
1592 data.dfs_event.ht_enabled = 1;
1593
1594 pos = os_strstr(param, "chan_offset=");
1595 if (pos)
1596 data.dfs_event.chan_offset = atoi(pos + 12);
1597
1598 pos = os_strstr(param, "chan_width=");
1599 if (pos)
1600 data.dfs_event.chan_width = atoi(pos + 11);
1601
1602 pos = os_strstr(param, "cf1=");
1603 if (pos)
1604 data.dfs_event.cf1 = atoi(pos + 4);
1605
1606 pos = os_strstr(param, "cf2=");
1607 if (pos)
1608 data.dfs_event.cf2 = atoi(pos + 4);
1609
1610 wpa_supplicant_event(hapd, event, &data);
1611
1612 return 0;
1613 }
1614
1615
hostapd_ctrl_iface_mgmt_tx(struct hostapd_data * hapd,char * cmd)1616 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
1617 {
1618 size_t len;
1619 u8 *buf;
1620 int res;
1621
1622 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
1623
1624 len = os_strlen(cmd);
1625 if (len & 1)
1626 return -1;
1627 len /= 2;
1628
1629 buf = os_malloc(len);
1630 if (buf == NULL)
1631 return -1;
1632
1633 if (hexstr2bin(cmd, buf, len) < 0) {
1634 os_free(buf);
1635 return -1;
1636 }
1637
1638 res = hostapd_drv_send_mlme(hapd, buf, len, 0, NULL, 0, 0);
1639 os_free(buf);
1640 return res;
1641 }
1642
1643
hostapd_ctrl_iface_mgmt_tx_status_process(struct hostapd_data * hapd,char * cmd)1644 static int hostapd_ctrl_iface_mgmt_tx_status_process(struct hostapd_data *hapd,
1645 char *cmd)
1646 {
1647 char *pos, *param;
1648 size_t len;
1649 u8 *buf;
1650 int stype = 0, ok = 0;
1651 union wpa_event_data event;
1652
1653 if (!hapd->ext_mgmt_frame_handling)
1654 return -1;
1655
1656 /* stype=<val> ok=<0/1> buf=<frame hexdump> */
1657
1658 wpa_printf(MSG_DEBUG, "External MGMT TX status process: %s", cmd);
1659
1660 pos = cmd;
1661 param = os_strstr(pos, "stype=");
1662 if (param) {
1663 param += 6;
1664 stype = atoi(param);
1665 }
1666
1667 param = os_strstr(pos, " ok=");
1668 if (param) {
1669 param += 4;
1670 ok = atoi(param);
1671 }
1672
1673 param = os_strstr(pos, " buf=");
1674 if (!param)
1675 return -1;
1676 param += 5;
1677
1678 len = os_strlen(param);
1679 if (len & 1)
1680 return -1;
1681 len /= 2;
1682
1683 buf = os_malloc(len);
1684 if (!buf || hexstr2bin(param, buf, len) < 0) {
1685 os_free(buf);
1686 return -1;
1687 }
1688
1689 os_memset(&event, 0, sizeof(event));
1690 event.tx_status.type = WLAN_FC_TYPE_MGMT;
1691 event.tx_status.data = buf;
1692 event.tx_status.data_len = len;
1693 event.tx_status.stype = stype;
1694 event.tx_status.ack = ok;
1695 hapd->ext_mgmt_frame_handling = 0;
1696 wpa_supplicant_event(hapd, EVENT_TX_STATUS, &event);
1697 hapd->ext_mgmt_frame_handling = 1;
1698
1699 os_free(buf);
1700
1701 return 0;
1702 }
1703
1704
hostapd_ctrl_iface_mgmt_rx_process(struct hostapd_data * hapd,char * cmd)1705 static int hostapd_ctrl_iface_mgmt_rx_process(struct hostapd_data *hapd,
1706 char *cmd)
1707 {
1708 char *pos, *param;
1709 size_t len;
1710 u8 *buf;
1711 int freq = 0, datarate = 0, ssi_signal = 0;
1712 union wpa_event_data event;
1713
1714 if (!hapd->ext_mgmt_frame_handling)
1715 return -1;
1716
1717 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
1718
1719 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
1720
1721 pos = cmd;
1722 param = os_strstr(pos, "freq=");
1723 if (param) {
1724 param += 5;
1725 freq = atoi(param);
1726 }
1727
1728 param = os_strstr(pos, " datarate=");
1729 if (param) {
1730 param += 10;
1731 datarate = atoi(param);
1732 }
1733
1734 param = os_strstr(pos, " ssi_signal=");
1735 if (param) {
1736 param += 12;
1737 ssi_signal = atoi(param);
1738 }
1739
1740 param = os_strstr(pos, " frame=");
1741 if (param == NULL)
1742 return -1;
1743 param += 7;
1744
1745 len = os_strlen(param);
1746 if (len & 1)
1747 return -1;
1748 len /= 2;
1749
1750 buf = os_malloc(len);
1751 if (buf == NULL)
1752 return -1;
1753
1754 if (hexstr2bin(param, buf, len) < 0) {
1755 os_free(buf);
1756 return -1;
1757 }
1758
1759 os_memset(&event, 0, sizeof(event));
1760 event.rx_mgmt.freq = freq;
1761 event.rx_mgmt.frame = buf;
1762 event.rx_mgmt.frame_len = len;
1763 event.rx_mgmt.ssi_signal = ssi_signal;
1764 event.rx_mgmt.datarate = datarate;
1765 hapd->ext_mgmt_frame_handling = 0;
1766 wpa_supplicant_event(hapd, EVENT_RX_MGMT, &event);
1767 hapd->ext_mgmt_frame_handling = 1;
1768
1769 os_free(buf);
1770
1771 return 0;
1772 }
1773
1774
hostapd_ctrl_iface_eapol_rx(struct hostapd_data * hapd,char * cmd)1775 static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
1776 {
1777 char *pos;
1778 u8 src[ETH_ALEN], *buf;
1779 int used;
1780 size_t len;
1781
1782 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
1783
1784 pos = cmd;
1785 used = hwaddr_aton2(pos, src);
1786 if (used < 0)
1787 return -1;
1788 pos += used;
1789 while (*pos == ' ')
1790 pos++;
1791
1792 len = os_strlen(pos);
1793 if (len & 1)
1794 return -1;
1795 len /= 2;
1796
1797 buf = os_malloc(len);
1798 if (buf == NULL)
1799 return -1;
1800
1801 if (hexstr2bin(pos, buf, len) < 0) {
1802 os_free(buf);
1803 return -1;
1804 }
1805
1806 ieee802_1x_receive(hapd, src, buf, len, FRAME_ENCRYPTION_UNKNOWN);
1807 os_free(buf);
1808
1809 return 0;
1810 }
1811
1812
hostapd_ctrl_iface_eapol_tx(struct hostapd_data * hapd,char * cmd)1813 static int hostapd_ctrl_iface_eapol_tx(struct hostapd_data *hapd, char *cmd)
1814 {
1815 char *pos, *pos2;
1816 u8 dst[ETH_ALEN], *buf;
1817 int used, ret;
1818 size_t len;
1819 unsigned int prev;
1820 int encrypt = 0;
1821
1822 wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
1823
1824 pos = cmd;
1825 used = hwaddr_aton2(pos, dst);
1826 if (used < 0)
1827 return -1;
1828 pos += used;
1829 while (*pos == ' ')
1830 pos++;
1831
1832 pos2 = os_strchr(pos, ' ');
1833 if (pos2) {
1834 len = pos2 - pos;
1835 encrypt = os_strstr(pos2, "encrypt=1") != NULL;
1836 } else {
1837 len = os_strlen(pos);
1838 }
1839 if (len & 1)
1840 return -1;
1841 len /= 2;
1842
1843 buf = os_malloc(len);
1844 if (!buf || hexstr2bin(pos, buf, len) < 0) {
1845 os_free(buf);
1846 return -1;
1847 }
1848
1849 prev = hapd->ext_eapol_frame_io;
1850 hapd->ext_eapol_frame_io = 0;
1851 ret = hostapd_wpa_auth_send_eapol(hapd, dst, buf, len, encrypt);
1852 hapd->ext_eapol_frame_io = prev;
1853 os_free(buf);
1854
1855 return ret;
1856 }
1857
1858
ipv4_hdr_checksum(const void * buf,size_t len)1859 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
1860 {
1861 size_t i;
1862 u32 sum = 0;
1863 const u16 *pos = buf;
1864
1865 for (i = 0; i < len / 2; i++)
1866 sum += *pos++;
1867
1868 while (sum >> 16)
1869 sum = (sum & 0xffff) + (sum >> 16);
1870
1871 return sum ^ 0xffff;
1872 }
1873
1874
1875 #define HWSIM_PACKETLEN 1500
1876 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
1877
hostapd_data_test_rx(void * ctx,const u8 * src_addr,const u8 * buf,size_t len)1878 static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
1879 size_t len)
1880 {
1881 struct hostapd_data *hapd = ctx;
1882 const struct ether_header *eth;
1883 struct ip ip;
1884 const u8 *pos;
1885 unsigned int i;
1886 char extra[30];
1887
1888 if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) {
1889 wpa_printf(MSG_DEBUG,
1890 "test data: RX - ignore unexpected length %d",
1891 (int) len);
1892 return;
1893 }
1894
1895 eth = (const struct ether_header *) buf;
1896 os_memcpy(&ip, eth + 1, sizeof(ip));
1897 pos = &buf[sizeof(*eth) + sizeof(ip)];
1898
1899 if (ip.ip_hl != 5 || ip.ip_v != 4 ||
1900 ntohs(ip.ip_len) > HWSIM_IP_LEN) {
1901 wpa_printf(MSG_DEBUG,
1902 "test data: RX - ignore unexpected IP header");
1903 return;
1904 }
1905
1906 for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
1907 if (*pos != (u8) i) {
1908 wpa_printf(MSG_DEBUG,
1909 "test data: RX - ignore mismatching payload");
1910 return;
1911 }
1912 pos++;
1913 }
1914
1915 extra[0] = '\0';
1916 if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
1917 os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
1918 wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
1919 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
1920 }
1921
1922
hostapd_ctrl_iface_data_test_config(struct hostapd_data * hapd,char * cmd)1923 static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
1924 char *cmd)
1925 {
1926 int enabled = atoi(cmd);
1927 char *pos;
1928 const char *ifname;
1929 const u8 *addr = hapd->own_addr;
1930
1931 if (!enabled) {
1932 if (hapd->l2_test) {
1933 l2_packet_deinit(hapd->l2_test);
1934 hapd->l2_test = NULL;
1935 wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
1936 "test data: Disabled");
1937 }
1938 return 0;
1939 }
1940
1941 if (hapd->l2_test)
1942 return 0;
1943
1944 pos = os_strstr(cmd, " ifname=");
1945 if (pos)
1946 ifname = pos + 8;
1947 else
1948 ifname = hapd->conf->iface;
1949
1950 #ifdef CONFIG_IEEE80211BE
1951 if (hapd->conf->mld_ap)
1952 addr = hapd->mld->mld_addr;
1953 #endif /* CONFIG_IEEE80211BE */
1954 hapd->l2_test = l2_packet_init(ifname, addr,
1955 ETHERTYPE_IP, hostapd_data_test_rx,
1956 hapd, 1);
1957 if (hapd->l2_test == NULL)
1958 return -1;
1959
1960 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
1961
1962 return 0;
1963 }
1964
1965
hostapd_ctrl_iface_data_test_tx(struct hostapd_data * hapd,char * cmd)1966 static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
1967 {
1968 u8 dst[ETH_ALEN], src[ETH_ALEN];
1969 char *pos, *pos2;
1970 int used;
1971 long int val;
1972 u8 tos;
1973 u8 buf[2 + HWSIM_PACKETLEN];
1974 struct ether_header *eth;
1975 struct ip *ip;
1976 u8 *dpos;
1977 unsigned int i;
1978 size_t send_len = HWSIM_IP_LEN;
1979
1980 if (hapd->l2_test == NULL)
1981 return -1;
1982
1983 /* format: <dst> <src> <tos> [len=<length>] */
1984
1985 pos = cmd;
1986 used = hwaddr_aton2(pos, dst);
1987 if (used < 0)
1988 return -1;
1989 pos += used;
1990 while (*pos == ' ')
1991 pos++;
1992 used = hwaddr_aton2(pos, src);
1993 if (used < 0)
1994 return -1;
1995 pos += used;
1996
1997 val = strtol(pos, &pos2, 0);
1998 if (val < 0 || val > 0xff)
1999 return -1;
2000 tos = val;
2001
2002 pos = os_strstr(pos2, " len=");
2003 if (pos) {
2004 i = atoi(pos + 5);
2005 if (i < sizeof(*ip) || i > HWSIM_IP_LEN)
2006 return -1;
2007 send_len = i;
2008 }
2009
2010 eth = (struct ether_header *) &buf[2];
2011 os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
2012 os_memcpy(eth->ether_shost, src, ETH_ALEN);
2013 eth->ether_type = htons(ETHERTYPE_IP);
2014 ip = (struct ip *) (eth + 1);
2015 os_memset(ip, 0, sizeof(*ip));
2016 ip->ip_hl = 5;
2017 ip->ip_v = 4;
2018 ip->ip_ttl = 64;
2019 ip->ip_tos = tos;
2020 ip->ip_len = htons(send_len);
2021 ip->ip_p = 1;
2022 ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
2023 ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
2024 ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
2025 dpos = (u8 *) (ip + 1);
2026 for (i = 0; i < send_len - sizeof(*ip); i++)
2027 *dpos++ = i;
2028
2029 if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
2030 sizeof(struct ether_header) + send_len) < 0)
2031 return -1;
2032
2033 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
2034 " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
2035
2036 return 0;
2037 }
2038
2039
hostapd_ctrl_iface_data_test_frame(struct hostapd_data * hapd,char * cmd)2040 static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
2041 char *cmd)
2042 {
2043 u8 *buf;
2044 struct ether_header *eth;
2045 struct l2_packet_data *l2 = NULL;
2046 size_t len;
2047 u16 ethertype;
2048 int res = -1;
2049 const char *ifname = hapd->conf->iface;
2050
2051 if (os_strncmp(cmd, "ifname=", 7) == 0) {
2052 cmd += 7;
2053 ifname = cmd;
2054 cmd = os_strchr(cmd, ' ');
2055 if (cmd == NULL)
2056 return -1;
2057 *cmd++ = '\0';
2058 }
2059
2060 len = os_strlen(cmd);
2061 if (len & 1 || len < ETH_HLEN * 2)
2062 return -1;
2063 len /= 2;
2064
2065 buf = os_malloc(len);
2066 if (buf == NULL)
2067 return -1;
2068
2069 if (hexstr2bin(cmd, buf, len) < 0)
2070 goto done;
2071
2072 eth = (struct ether_header *) buf;
2073 ethertype = ntohs(eth->ether_type);
2074
2075 l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
2076 hostapd_data_test_rx, hapd, 1);
2077 if (l2 == NULL)
2078 goto done;
2079
2080 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
2081 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
2082 done:
2083 if (l2)
2084 l2_packet_deinit(l2);
2085 os_free(buf);
2086
2087 return res < 0 ? -1 : 0;
2088 }
2089
2090
hostapd_ctrl_reset_pn(struct hostapd_data * hapd,const char * cmd)2091 static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
2092 {
2093 struct sta_info *sta;
2094 u8 addr[ETH_ALEN];
2095 u8 zero[WPA_TK_MAX_LEN];
2096
2097 os_memset(zero, 0, sizeof(zero));
2098
2099 if (hwaddr_aton(cmd, addr))
2100 return -1;
2101
2102 if (is_broadcast_ether_addr(addr) && os_strstr(cmd, " BIGTK")) {
2103 if (hapd->last_bigtk_alg == WPA_ALG_NONE)
2104 return -1;
2105
2106 wpa_printf(MSG_INFO, "TESTING: Reset BIPN for BIGTK");
2107
2108 /* First, use a zero key to avoid any possible duplicate key
2109 * avoidance in the driver. */
2110 if (hostapd_drv_set_key(hapd->conf->iface, hapd,
2111 hapd->last_bigtk_alg,
2112 broadcast_ether_addr,
2113 hapd->last_bigtk_key_idx, 0, 1, NULL, 0,
2114 zero, hapd->last_bigtk_len,
2115 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
2116 return -1;
2117
2118 /* Set the previously configured key to reset its TSC */
2119 return hostapd_drv_set_key(hapd->conf->iface, hapd,
2120 hapd->last_bigtk_alg,
2121 broadcast_ether_addr,
2122 hapd->last_bigtk_key_idx, 0, 1, NULL,
2123 0, hapd->last_bigtk,
2124 hapd->last_bigtk_len,
2125 KEY_FLAG_GROUP_TX_DEFAULT);
2126 }
2127
2128 if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) {
2129 if (hapd->last_igtk_alg == WPA_ALG_NONE)
2130 return -1;
2131
2132 wpa_printf(MSG_INFO, "TESTING: Reset IPN for IGTK");
2133
2134 /* First, use a zero key to avoid any possible duplicate key
2135 * avoidance in the driver. */
2136 if (hostapd_drv_set_key(hapd->conf->iface, hapd,
2137 hapd->last_igtk_alg,
2138 broadcast_ether_addr,
2139 hapd->last_igtk_key_idx, 0, 1, NULL, 0,
2140 zero, hapd->last_igtk_len,
2141 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
2142 return -1;
2143
2144 /* Set the previously configured key to reset its TSC */
2145 return hostapd_drv_set_key(hapd->conf->iface, hapd,
2146 hapd->last_igtk_alg,
2147 broadcast_ether_addr,
2148 hapd->last_igtk_key_idx, 0, 1, NULL,
2149 0, hapd->last_igtk,
2150 hapd->last_igtk_len,
2151 KEY_FLAG_GROUP_TX_DEFAULT);
2152 }
2153
2154 if (is_broadcast_ether_addr(addr)) {
2155 if (hapd->last_gtk_alg == WPA_ALG_NONE)
2156 return -1;
2157
2158 wpa_printf(MSG_INFO, "TESTING: Reset PN for GTK");
2159
2160 /* First, use a zero key to avoid any possible duplicate key
2161 * avoidance in the driver. */
2162 if (hostapd_drv_set_key(hapd->conf->iface, hapd,
2163 hapd->last_gtk_alg,
2164 broadcast_ether_addr,
2165 hapd->last_gtk_key_idx, 0, 1, NULL, 0,
2166 zero, hapd->last_gtk_len,
2167 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
2168 return -1;
2169
2170 /* Set the previously configured key to reset its TSC */
2171 return hostapd_drv_set_key(hapd->conf->iface, hapd,
2172 hapd->last_gtk_alg,
2173 broadcast_ether_addr,
2174 hapd->last_gtk_key_idx, 0, 1, NULL,
2175 0, hapd->last_gtk,
2176 hapd->last_gtk_len,
2177 KEY_FLAG_GROUP_TX_DEFAULT);
2178 }
2179
2180 sta = ap_get_sta(hapd, addr);
2181 if (!sta)
2182 return -1;
2183
2184 if (sta->last_tk_alg == WPA_ALG_NONE)
2185 return -1;
2186
2187 wpa_printf(MSG_INFO, "TESTING: Reset PN for " MACSTR,
2188 MAC2STR(sta->addr));
2189
2190 /* First, use a zero key to avoid any possible duplicate key avoidance
2191 * in the driver. */
2192 if (hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
2193 sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 0,
2194 zero, sta->last_tk_len,
2195 KEY_FLAG_PAIRWISE_RX_TX) < 0)
2196 return -1;
2197
2198 /* Set the previously configured key to reset its TSC/RSC */
2199 return hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
2200 sta->addr, sta->last_tk_key_idx, 0, 1, NULL,
2201 0, sta->last_tk, sta->last_tk_len,
2202 KEY_FLAG_PAIRWISE_RX_TX);
2203 }
2204
2205
hostapd_ctrl_set_key(struct hostapd_data * hapd,const char * cmd)2206 static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
2207 {
2208 u8 addr[ETH_ALEN];
2209 const char *pos = cmd;
2210 enum wpa_alg alg;
2211 enum key_flag key_flag;
2212 int idx, set_tx;
2213 u8 seq[6], key[WPA_TK_MAX_LEN];
2214 size_t key_len;
2215
2216 /* parameters: alg addr idx set_tx seq key key_flag */
2217
2218 alg = atoi(pos);
2219 pos = os_strchr(pos, ' ');
2220 if (!pos)
2221 return -1;
2222 pos++;
2223 if (hwaddr_aton(pos, addr))
2224 return -1;
2225 pos += 17;
2226 if (*pos != ' ')
2227 return -1;
2228 pos++;
2229 idx = atoi(pos);
2230 pos = os_strchr(pos, ' ');
2231 if (!pos)
2232 return -1;
2233 pos++;
2234 set_tx = atoi(pos);
2235 pos = os_strchr(pos, ' ');
2236 if (!pos)
2237 return -1;
2238 pos++;
2239 if (hexstr2bin(pos, seq, sizeof(seq)) < 0)
2240 return -1;
2241 pos += 2 * 6;
2242 if (*pos != ' ')
2243 return -1;
2244 pos++;
2245 if (!os_strchr(pos, ' '))
2246 return -1;
2247 key_len = (os_strchr(pos, ' ') - pos) / 2;
2248 if (hexstr2bin(pos, key, key_len) < 0)
2249 return -1;
2250 pos += 2 * key_len;
2251 if (*pos != ' ')
2252 return -1;
2253
2254 pos++;
2255 key_flag = atoi(pos);
2256 pos = os_strchr(pos, ' ');
2257 if (pos)
2258 return -1;
2259
2260 wpa_printf(MSG_INFO, "TESTING: Set key");
2261 return hostapd_drv_set_key(hapd->conf->iface, hapd, alg, addr, idx, 0,
2262 set_tx, seq, 6, key, key_len, key_flag);
2263 }
2264
2265
restore_tk(void * ctx1,void * ctx2)2266 static void restore_tk(void *ctx1, void *ctx2)
2267 {
2268 struct hostapd_data *hapd = ctx1;
2269 struct sta_info *sta = ctx2;
2270
2271 wpa_printf(MSG_INFO, "TESTING: Restore TK for " MACSTR,
2272 MAC2STR(sta->addr));
2273 /* This does not really restore the TSC properly, so this will result
2274 * in replay protection issues for now since there is no clean way of
2275 * preventing encryption of a single EAPOL frame. */
2276 hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
2277 sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 0,
2278 sta->last_tk, sta->last_tk_len,
2279 KEY_FLAG_PAIRWISE_RX_TX);
2280 }
2281
2282
hostapd_ctrl_resend_m1(struct hostapd_data * hapd,const char * cmd)2283 static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd)
2284 {
2285 struct sta_info *sta;
2286 u8 addr[ETH_ALEN];
2287 int plain = os_strstr(cmd, "plaintext") != NULL;
2288
2289 if (hwaddr_aton(cmd, addr))
2290 return -1;
2291
2292 sta = ap_get_sta(hapd, addr);
2293 if (!sta || !sta->wpa_sm)
2294 return -1;
2295
2296 if (plain && sta->last_tk_alg == WPA_ALG_NONE)
2297 plain = 0; /* no need for special processing */
2298 if (plain) {
2299 wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
2300 MAC2STR(sta->addr));
2301 hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
2302 sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
2303 0, NULL, 0, KEY_FLAG_PAIRWISE);
2304 }
2305
2306 wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr));
2307 return wpa_auth_resend_m1(sta->wpa_sm,
2308 os_strstr(cmd, "change-anonce") != NULL,
2309 plain ? restore_tk : NULL, hapd, sta);
2310 }
2311
2312
hostapd_ctrl_resend_m3(struct hostapd_data * hapd,const char * cmd)2313 static int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd)
2314 {
2315 struct sta_info *sta;
2316 u8 addr[ETH_ALEN];
2317 int plain = os_strstr(cmd, "plaintext") != NULL;
2318
2319 if (hwaddr_aton(cmd, addr))
2320 return -1;
2321
2322 sta = ap_get_sta(hapd, addr);
2323 if (!sta || !sta->wpa_sm)
2324 return -1;
2325
2326 if (plain && sta->last_tk_alg == WPA_ALG_NONE)
2327 plain = 0; /* no need for special processing */
2328 if (plain) {
2329 wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
2330 MAC2STR(sta->addr));
2331 hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
2332 sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
2333 0, NULL, 0, KEY_FLAG_PAIRWISE);
2334 }
2335
2336 wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr));
2337 return wpa_auth_resend_m3(sta->wpa_sm,
2338 plain ? restore_tk : NULL, hapd, sta);
2339 }
2340
2341
hostapd_ctrl_resend_group_m1(struct hostapd_data * hapd,const char * cmd)2342 static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
2343 const char *cmd)
2344 {
2345 struct sta_info *sta;
2346 u8 addr[ETH_ALEN];
2347 int plain = os_strstr(cmd, "plaintext") != NULL;
2348
2349 if (hwaddr_aton(cmd, addr))
2350 return -1;
2351
2352 sta = ap_get_sta(hapd, addr);
2353 if (!sta || !sta->wpa_sm)
2354 return -1;
2355
2356 if (plain && sta->last_tk_alg == WPA_ALG_NONE)
2357 plain = 0; /* no need for special processing */
2358 if (plain) {
2359 wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
2360 MAC2STR(sta->addr));
2361 hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
2362 sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
2363 0, NULL, 0, KEY_FLAG_PAIRWISE);
2364 }
2365
2366 wpa_printf(MSG_INFO,
2367 "TESTING: Send group M1 for the same GTK and zero RSC to "
2368 MACSTR, MAC2STR(sta->addr));
2369 return wpa_auth_resend_group_m1(sta->wpa_sm,
2370 plain ? restore_tk : NULL, hapd, sta);
2371 }
2372
2373
hostapd_ctrl_rekey_ptk(struct hostapd_data * hapd,const char * cmd)2374 static int hostapd_ctrl_rekey_ptk(struct hostapd_data *hapd, const char *cmd)
2375 {
2376 struct sta_info *sta;
2377 u8 addr[ETH_ALEN];
2378
2379 if (hwaddr_aton(cmd, addr))
2380 return -1;
2381
2382 sta = ap_get_sta(hapd, addr);
2383 if (!sta || !sta->wpa_sm)
2384 return -1;
2385
2386 return wpa_auth_rekey_ptk(hapd->wpa_auth, sta->wpa_sm);
2387 }
2388
2389
hostapd_ctrl_get_pmksa_pmk(struct hostapd_data * hapd,const u8 * addr,char * buf,size_t buflen)2390 static int hostapd_ctrl_get_pmksa_pmk(struct hostapd_data *hapd, const u8 *addr,
2391 char *buf, size_t buflen)
2392 {
2393 struct rsn_pmksa_cache_entry *pmksa;
2394
2395 pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, addr, NULL);
2396 if (!pmksa)
2397 return -1;
2398
2399 return wpa_snprintf_hex(buf, buflen, pmksa->pmk, pmksa->pmk_len);
2400 }
2401
2402
hostapd_ctrl_get_pmk(struct hostapd_data * hapd,const char * cmd,char * buf,size_t buflen)2403 static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd,
2404 char *buf, size_t buflen)
2405 {
2406 struct sta_info *sta;
2407 u8 addr[ETH_ALEN];
2408 const u8 *pmk;
2409 int pmk_len;
2410
2411 if (hwaddr_aton(cmd, addr))
2412 return -1;
2413
2414 sta = ap_get_sta(hapd, addr);
2415 if (!sta || !sta->wpa_sm) {
2416 wpa_printf(MSG_DEBUG, "No STA WPA state machine for " MACSTR,
2417 MAC2STR(addr));
2418 return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen);
2419 }
2420 pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len);
2421 if (!pmk || !pmk_len) {
2422 wpa_printf(MSG_DEBUG, "No PMK stored for " MACSTR,
2423 MAC2STR(addr));
2424 return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen);
2425 }
2426
2427 return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
2428 }
2429
2430
hostapd_ctrl_register_frame(struct hostapd_data * hapd,const char * cmd)2431 static int hostapd_ctrl_register_frame(struct hostapd_data *hapd,
2432 const char *cmd)
2433 {
2434 u16 type;
2435 char *pos, *end;
2436 u8 match[10];
2437 size_t match_len;
2438 bool multicast = false;
2439
2440 type = strtol(cmd, &pos, 16);
2441 if (*pos != ' ')
2442 return -1;
2443 pos++;
2444 end = os_strchr(pos, ' ');
2445 if (end) {
2446 match_len = end - pos;
2447 multicast = os_strstr(end, "multicast") != NULL;
2448 } else {
2449 match_len = os_strlen(pos) / 2;
2450 }
2451 if (hexstr2bin(pos, match, match_len))
2452 return -1;
2453
2454 return hostapd_drv_register_frame(hapd, type, match, match_len,
2455 multicast);
2456 }
2457
2458 #endif /* CONFIG_TESTING_OPTIONS */
2459
2460
2461 #ifdef NEED_AP_MLME
hostapd_ctrl_check_freq_params(struct hostapd_freq_params * params,u16 punct_bitmap)2462 static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
2463 u16 punct_bitmap)
2464 {
2465 u32 start_freq;
2466
2467 if (is_6ghz_freq(params->freq)) {
2468 const int bw_idx[] = { 20, 40, 80, 160, 320 };
2469 int idx, bw;
2470
2471 /* The 6 GHz band requires HE to be enabled. */
2472 params->he_enabled = 1;
2473
2474 if (params->center_freq1) {
2475 if (params->freq == 5935)
2476 idx = (params->center_freq1 - 5925) / 5;
2477 else
2478 idx = (params->center_freq1 - 5950) / 5;
2479
2480 bw = center_idx_to_bw_6ghz(idx);
2481 if (bw < 0 || bw > (int) ARRAY_SIZE(bw_idx) ||
2482 bw_idx[bw] != params->bandwidth)
2483 return -1;
2484 }
2485 } else { /* Non-6 GHz channel */
2486 /* An EHT STA is also an HE STA as defined in
2487 * IEEE P802.11be/D5.0, 4.3.16a. */
2488 if (params->he_enabled || params->eht_enabled) {
2489 params->he_enabled = 1;
2490 /* An HE STA is also a VHT STA if operating in the 5 GHz
2491 * band and an HE STA is also an HT STA in the 2.4 GHz
2492 * band as defined in IEEE Std 802.11ax-2021, 4.3.15a.
2493 * A VHT STA is an HT STA as defined in IEEE
2494 * Std 802.11, 4.3.15. */
2495 if (IS_5GHZ(params->freq))
2496 params->vht_enabled = 1;
2497
2498 params->ht_enabled = 1;
2499 }
2500 }
2501
2502 switch (params->bandwidth) {
2503 case 0:
2504 /* bandwidth not specified: use 20 MHz by default */
2505 /* fall-through */
2506 case 20:
2507 if (params->center_freq1 &&
2508 params->center_freq1 != params->freq)
2509 return -1;
2510
2511 if (params->center_freq2 || params->sec_channel_offset)
2512 return -1;
2513
2514 if (punct_bitmap)
2515 return -1;
2516 break;
2517 case 40:
2518 if (params->center_freq2 || !params->sec_channel_offset)
2519 return -1;
2520
2521 if (punct_bitmap)
2522 return -1;
2523
2524 if (!params->center_freq1)
2525 break;
2526 switch (params->sec_channel_offset) {
2527 case 1:
2528 if (params->freq + 10 != params->center_freq1)
2529 return -1;
2530 break;
2531 case -1:
2532 if (params->freq - 10 != params->center_freq1)
2533 return -1;
2534 break;
2535 default:
2536 return -1;
2537 }
2538 break;
2539 case 80:
2540 if (!params->center_freq1 || !params->sec_channel_offset)
2541 return 1;
2542
2543 switch (params->sec_channel_offset) {
2544 case 1:
2545 if (params->freq - 10 != params->center_freq1 &&
2546 params->freq + 30 != params->center_freq1)
2547 return 1;
2548 break;
2549 case -1:
2550 if (params->freq + 10 != params->center_freq1 &&
2551 params->freq - 30 != params->center_freq1)
2552 return -1;
2553 break;
2554 default:
2555 return -1;
2556 }
2557
2558 if (params->center_freq2 && punct_bitmap)
2559 return -1;
2560
2561 /* Adjacent and overlapped are not allowed for 80+80 */
2562 if (params->center_freq2 &&
2563 params->center_freq1 - params->center_freq2 <= 80 &&
2564 params->center_freq2 - params->center_freq1 <= 80)
2565 return 1;
2566 break;
2567 case 160:
2568 if (!params->center_freq1 || params->center_freq2 ||
2569 !params->sec_channel_offset)
2570 return -1;
2571
2572 switch (params->sec_channel_offset) {
2573 case 1:
2574 if (params->freq + 70 != params->center_freq1 &&
2575 params->freq + 30 != params->center_freq1 &&
2576 params->freq - 10 != params->center_freq1 &&
2577 params->freq - 50 != params->center_freq1)
2578 return -1;
2579 break;
2580 case -1:
2581 if (params->freq + 50 != params->center_freq1 &&
2582 params->freq + 10 != params->center_freq1 &&
2583 params->freq - 30 != params->center_freq1 &&
2584 params->freq - 70 != params->center_freq1)
2585 return -1;
2586 break;
2587 default:
2588 return -1;
2589 }
2590 break;
2591 case 320:
2592 if (!params->center_freq1 || params->center_freq2 ||
2593 !params->sec_channel_offset)
2594 return -1;
2595
2596 switch (params->sec_channel_offset) {
2597 case 1:
2598 if (params->freq + 150 != params->center_freq1 &&
2599 params->freq + 110 != params->center_freq1 &&
2600 params->freq + 70 != params->center_freq1 &&
2601 params->freq + 30 != params->center_freq1 &&
2602 params->freq - 10 != params->center_freq1 &&
2603 params->freq - 50 != params->center_freq1 &&
2604 params->freq - 90 != params->center_freq1 &&
2605 params->freq - 130 != params->center_freq1)
2606 return -1;
2607 break;
2608 case -1:
2609 if (params->freq + 130 != params->center_freq1 &&
2610 params->freq + 90 != params->center_freq1 &&
2611 params->freq + 50 != params->center_freq1 &&
2612 params->freq + 10 != params->center_freq1 &&
2613 params->freq - 30 != params->center_freq1 &&
2614 params->freq - 70 != params->center_freq1 &&
2615 params->freq - 110 != params->center_freq1 &&
2616 params->freq - 150 != params->center_freq1)
2617 return -1;
2618 break;
2619 }
2620 break;
2621 default:
2622 return -1;
2623 }
2624
2625 if (!punct_bitmap)
2626 return 0;
2627
2628 if (!params->eht_enabled) {
2629 wpa_printf(MSG_ERROR,
2630 "Preamble puncturing supported only in EHT");
2631 return -1;
2632 }
2633
2634 if (params->freq >= 2412 && params->freq <= 2484) {
2635 wpa_printf(MSG_ERROR,
2636 "Preamble puncturing is not supported in 2.4 GHz");
2637 return -1;
2638 }
2639
2640 start_freq = params->center_freq1 - (params->bandwidth / 2);
2641 if (!is_punct_bitmap_valid(params->bandwidth,
2642 (params->freq - start_freq) / 20,
2643 punct_bitmap)) {
2644 wpa_printf(MSG_ERROR, "Invalid preamble puncturing bitmap");
2645 return -1;
2646 }
2647
2648 return 0;
2649 }
2650 #endif /* NEED_AP_MLME */
2651
2652
hostapd_ctrl_iface_chan_switch(struct hostapd_iface * iface,char * pos)2653 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
2654 char *pos)
2655 {
2656 #ifdef NEED_AP_MLME
2657 struct csa_settings settings;
2658 int ret;
2659 int dfs_range = 0;
2660 unsigned int i;
2661 int bandwidth;
2662 u8 chan;
2663 unsigned int num_err = 0;
2664 int err = 0;
2665
2666 ret = hostapd_parse_csa_settings(pos, &settings);
2667 if (ret)
2668 return ret;
2669
2670 settings.link_id = -1;
2671 #ifdef CONFIG_IEEE80211BE
2672 if (iface->num_bss && iface->bss[0]->conf->mld_ap)
2673 settings.link_id = iface->bss[0]->mld_link_id;
2674 #endif /* CONFIG_IEEE80211BE */
2675
2676 ret = hostapd_ctrl_check_freq_params(&settings.freq_params,
2677 settings.punct_bitmap);
2678 if (ret) {
2679 wpa_printf(MSG_INFO,
2680 "chanswitch: invalid frequency settings provided");
2681 return ret;
2682 }
2683
2684 switch (settings.freq_params.bandwidth) {
2685 case 40:
2686 bandwidth = CHAN_WIDTH_40;
2687 break;
2688 case 80:
2689 if (settings.freq_params.center_freq2)
2690 bandwidth = CHAN_WIDTH_80P80;
2691 else
2692 bandwidth = CHAN_WIDTH_80;
2693 break;
2694 case 160:
2695 bandwidth = CHAN_WIDTH_160;
2696 break;
2697 case 320:
2698 bandwidth = CHAN_WIDTH_320;
2699 break;
2700 default:
2701 bandwidth = CHAN_WIDTH_20;
2702 break;
2703 }
2704
2705 if (settings.freq_params.center_freq1)
2706 dfs_range += hostapd_is_dfs_overlap(
2707 iface, bandwidth, settings.freq_params.center_freq1);
2708 else
2709 dfs_range += hostapd_is_dfs_overlap(
2710 iface, bandwidth, settings.freq_params.freq);
2711
2712 if (settings.freq_params.center_freq2)
2713 dfs_range += hostapd_is_dfs_overlap(
2714 iface, bandwidth, settings.freq_params.center_freq2);
2715
2716 if (dfs_range) {
2717 ret = ieee80211_freq_to_chan(settings.freq_params.freq, &chan);
2718 if (ret == NUM_HOSTAPD_MODES) {
2719 wpa_printf(MSG_ERROR,
2720 "Failed to get channel for (freq=%d, sec_channel_offset=%d, bw=%d)",
2721 settings.freq_params.freq,
2722 settings.freq_params.sec_channel_offset,
2723 settings.freq_params.bandwidth);
2724 return -1;
2725 }
2726
2727 settings.freq_params.channel = chan;
2728
2729 wpa_printf(MSG_DEBUG,
2730 "DFS/CAC to (channel=%u, freq=%d, sec_channel_offset=%d, bw=%d, center_freq1=%d)",
2731 settings.freq_params.channel,
2732 settings.freq_params.freq,
2733 settings.freq_params.sec_channel_offset,
2734 settings.freq_params.bandwidth,
2735 settings.freq_params.center_freq1);
2736
2737 /* Perform CAC and switch channel */
2738 iface->is_ch_switch_dfs = true;
2739 hostapd_switch_channel_fallback(iface, &settings.freq_params);
2740 return 0;
2741 }
2742
2743 for (i = 0; i < iface->num_bss; i++) {
2744
2745 /* Save CHAN_SWITCH VHT, HE, and EHT config */
2746 hostapd_chan_switch_config(iface->bss[i],
2747 &settings.freq_params);
2748
2749 err = hostapd_switch_channel(iface->bss[i], &settings);
2750 if (err) {
2751 ret = err;
2752 num_err++;
2753 }
2754 }
2755
2756 return (iface->num_bss == num_err) ? ret : 0;
2757 #else /* NEED_AP_MLME */
2758 return -1;
2759 #endif /* NEED_AP_MLME */
2760 }
2761
2762
2763 #ifdef CONFIG_IEEE80211AX
hostapd_ctrl_iface_color_change(struct hostapd_iface * iface,const char * pos)2764 static int hostapd_ctrl_iface_color_change(struct hostapd_iface *iface,
2765 const char *pos)
2766 {
2767 #ifdef NEED_AP_MLME
2768 struct cca_settings settings;
2769 struct hostapd_data *hapd = iface->bss[0];
2770 int ret, color;
2771 unsigned int i;
2772 char *end;
2773
2774 os_memset(&settings, 0, sizeof(settings));
2775
2776 color = strtol(pos, &end, 10);
2777 if (pos == end || color < 0 || color > 63) {
2778 wpa_printf(MSG_ERROR, "color_change: Invalid color provided");
2779 return -1;
2780 }
2781
2782 /* Color value is expected to be [1-63]. If 0 comes, assumption is this
2783 * is to disable the color. In this case no need to do CCA, just
2784 * changing Beacon frames is sufficient. */
2785 if (color == 0) {
2786 if (iface->conf->he_op.he_bss_color_disabled) {
2787 wpa_printf(MSG_ERROR,
2788 "color_change: Color is already disabled");
2789 return -1;
2790 }
2791
2792 iface->conf->he_op.he_bss_color_disabled = 1;
2793
2794 for (i = 0; i < iface->num_bss; i++)
2795 ieee802_11_set_beacon(iface->bss[i]);
2796
2797 return 0;
2798 }
2799
2800 if (color == iface->conf->he_op.he_bss_color) {
2801 if (!iface->conf->he_op.he_bss_color_disabled) {
2802 wpa_printf(MSG_ERROR,
2803 "color_change: Provided color is already set");
2804 return -1;
2805 }
2806
2807 iface->conf->he_op.he_bss_color_disabled = 0;
2808
2809 for (i = 0; i < iface->num_bss; i++)
2810 ieee802_11_set_beacon(iface->bss[i]);
2811
2812 return 0;
2813 }
2814
2815 if (hapd->cca_in_progress) {
2816 wpa_printf(MSG_ERROR,
2817 "color_change: CCA is already in progress");
2818 return -1;
2819 }
2820
2821 iface->conf->he_op.he_bss_color_disabled = 0;
2822
2823 for (i = 0; i < iface->num_bss; i++) {
2824 struct hostapd_data *bss = iface->bss[i];
2825
2826 hostapd_cleanup_cca_params(bss);
2827
2828 bss->cca_color = color;
2829 bss->cca_count = 10;
2830
2831 if (hostapd_fill_cca_settings(bss, &settings)) {
2832 wpa_printf(MSG_DEBUG,
2833 "color_change: Filling CCA settings failed for color: %d\n",
2834 color);
2835 hostapd_cleanup_cca_params(bss);
2836 continue;
2837 }
2838
2839 wpa_printf(MSG_DEBUG, "Setting user selected color: %d", color);
2840 ret = hostapd_drv_switch_color(bss, &settings);
2841 if (ret)
2842 hostapd_cleanup_cca_params(bss);
2843
2844 free_beacon_data(&settings.beacon_cca);
2845 free_beacon_data(&settings.beacon_after);
2846 }
2847
2848 return 0;
2849 #else /* NEED_AP_MLME */
2850 return -1;
2851 #endif /* NEED_AP_MLME */
2852 }
2853 #endif /* CONFIG_IEEE80211AX */
2854
2855
hostapd_maxnss(struct hostapd_data * hapd,struct sta_info * sta)2856 static u8 hostapd_maxnss(struct hostapd_data *hapd, struct sta_info *sta)
2857 {
2858 u8 *mcs_set = NULL;
2859 u16 mcs_map;
2860 u8 ht_rx_nss = 0;
2861 u8 vht_rx_nss = 1;
2862 u8 mcs;
2863 bool ht_supported = false;
2864 bool vht_supported = false;
2865 int i;
2866
2867 if (sta->ht_capabilities && (sta->flags & WLAN_STA_HT)) {
2868 mcs_set = sta->ht_capabilities->supported_mcs_set;
2869 ht_supported = true;
2870 }
2871
2872 if (sta->vht_capabilities && (sta->flags & WLAN_STA_VHT)) {
2873 mcs_map = le_to_host16(
2874 sta->vht_capabilities->vht_supported_mcs_set.rx_map);
2875 vht_supported = true;
2876 }
2877
2878 if (ht_supported && mcs_set) {
2879 if (mcs_set[0])
2880 ht_rx_nss++;
2881 if (mcs_set[1])
2882 ht_rx_nss++;
2883 if (mcs_set[2])
2884 ht_rx_nss++;
2885 if (mcs_set[3])
2886 ht_rx_nss++;
2887 }
2888 if (vht_supported) {
2889 for (i = 7; i >= 0; i--) {
2890 mcs = (mcs_map >> (2 * i)) & 0x03;
2891 if (mcs != 0x03) {
2892 vht_rx_nss = i + 1;
2893 break;
2894 }
2895 }
2896 }
2897
2898 return ht_rx_nss > vht_rx_nss ? ht_rx_nss : vht_rx_nss;
2899 }
2900
2901
hostapd_ctrl_iface_notify_cw_htaction(struct hostapd_data * hapd,const u8 * addr,u8 width)2902 static char hostapd_ctrl_iface_notify_cw_htaction(struct hostapd_data *hapd,
2903 const u8 *addr, u8 width)
2904 {
2905 u8 buf[3];
2906 char ret;
2907
2908 width = width >= 1 ? 1 : 0;
2909
2910 buf[0] = WLAN_ACTION_HT;
2911 buf[1] = WLAN_HT_ACTION_NOTIFY_CHANWIDTH;
2912 buf[2] = width;
2913
2914 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
2915 buf, sizeof(buf));
2916 if (ret)
2917 wpa_printf(MSG_DEBUG,
2918 "Failed to send Notify Channel Width frame to "
2919 MACSTR, MAC2STR(addr));
2920
2921 return ret;
2922 }
2923
2924
hostapd_ctrl_iface_notify_cw_vhtaction(struct hostapd_data * hapd,const u8 * addr,u8 width)2925 static char hostapd_ctrl_iface_notify_cw_vhtaction(struct hostapd_data *hapd,
2926 const u8 *addr, u8 width)
2927 {
2928 u8 buf[3];
2929 char ret;
2930
2931 buf[0] = WLAN_ACTION_VHT;
2932 buf[1] = WLAN_VHT_ACTION_OPMODE_NOTIF;
2933 buf[2] = width;
2934
2935 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
2936 buf, sizeof(buf));
2937 if (ret)
2938 wpa_printf(MSG_DEBUG,
2939 "Failed to send Opeating Mode Notification frame to "
2940 MACSTR, MAC2STR(addr));
2941
2942 return ret;
2943 }
2944
2945
hostapd_ctrl_iface_notify_cw_change(struct hostapd_data * hapd,const char * cmd)2946 static char hostapd_ctrl_iface_notify_cw_change(struct hostapd_data *hapd,
2947 const char *cmd)
2948 {
2949 u8 cw, operating_mode = 0, nss;
2950 struct sta_info *sta;
2951 enum hostapd_hw_mode hw_mode;
2952
2953 if (is_6ghz_freq(hapd->iface->freq)) {
2954 wpa_printf(MSG_ERROR, "20/40 BSS coex not supported in 6 GHz");
2955 return -1;
2956 }
2957
2958 cw = atoi(cmd);
2959 hw_mode = hapd->iface->current_mode->mode;
2960 if ((hw_mode == HOSTAPD_MODE_IEEE80211G ||
2961 hw_mode == HOSTAPD_MODE_IEEE80211B) &&
2962 !(cw == 0 || cw == 1)) {
2963 wpa_printf(MSG_ERROR,
2964 "Channel width should be either 20 MHz or 40 MHz for 2.4 GHz band");
2965 return -1;
2966 }
2967
2968 switch (cw) {
2969 case 0:
2970 operating_mode = 0;
2971 break;
2972 case 1:
2973 operating_mode = VHT_OPMODE_CHANNEL_40MHZ;
2974 break;
2975 case 2:
2976 operating_mode = VHT_OPMODE_CHANNEL_80MHZ;
2977 break;
2978 case 3:
2979 operating_mode = VHT_OPMODE_CHANNEL_160MHZ;
2980 break;
2981 default:
2982 wpa_printf(MSG_ERROR, "Channel width should be between 0 to 3");
2983 return -1;
2984 }
2985
2986 for (sta = hapd->sta_list; sta; sta = sta->next) {
2987 if ((sta->flags & WLAN_STA_VHT) && sta->vht_capabilities) {
2988 nss = hostapd_maxnss(hapd, sta) - 1;
2989 hostapd_ctrl_iface_notify_cw_vhtaction(hapd, sta->addr,
2990 operating_mode |
2991 (u8) (nss << 4));
2992 continue;
2993 }
2994
2995 if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) ==
2996 WLAN_STA_HT && sta->ht_capabilities)
2997 hostapd_ctrl_iface_notify_cw_htaction(hapd, sta->addr,
2998 cw);
2999 }
3000
3001 return 0;
3002 }
3003
3004
hostapd_ctrl_iface_mib(struct hostapd_data * hapd,char * reply,int reply_size,const char * param)3005 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
3006 int reply_size, const char *param)
3007 {
3008 #ifdef RADIUS_SERVER
3009 if (os_strcmp(param, "radius_server") == 0) {
3010 return radius_server_get_mib(hapd->radius_srv, reply,
3011 reply_size);
3012 }
3013 #endif /* RADIUS_SERVER */
3014 return -1;
3015 }
3016
3017
hostapd_ctrl_iface_vendor(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3018 static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
3019 char *buf, size_t buflen)
3020 {
3021 int ret;
3022 char *pos, *temp = NULL;
3023 u8 *data = NULL;
3024 unsigned int vendor_id, subcmd;
3025 enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED;
3026 struct wpabuf *reply;
3027 size_t data_len = 0;
3028
3029 /**
3030 * cmd: <vendor id> <subcommand id> [<hex formatted data>]
3031 * [nested=<0|1>]
3032 */
3033 vendor_id = strtoul(cmd, &pos, 16);
3034 if (!isblank((unsigned char) *pos))
3035 return -EINVAL;
3036
3037 subcmd = strtoul(pos, &pos, 10);
3038
3039 if (*pos != '\0') {
3040 if (!isblank((unsigned char) *pos++))
3041 return -EINVAL;
3042
3043 temp = os_strchr(pos, ' ');
3044 data_len = temp ? (size_t) (temp - pos) : os_strlen(pos);
3045 }
3046
3047 if (data_len) {
3048 data_len /= 2;
3049 data = os_malloc(data_len);
3050 if (!data)
3051 return -ENOBUFS;
3052
3053 if (hexstr2bin(pos, data, data_len)) {
3054 wpa_printf(MSG_DEBUG,
3055 "Vendor command: wrong parameter format");
3056 os_free(data);
3057 return -EINVAL;
3058 }
3059 }
3060
3061 pos = os_strstr(cmd, "nested=");
3062 if (pos)
3063 nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED :
3064 NESTED_ATTR_NOT_USED;
3065
3066 reply = wpabuf_alloc((buflen - 1) / 2);
3067 if (!reply) {
3068 os_free(data);
3069 return -ENOBUFS;
3070 }
3071
3072 ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
3073 nested_attr_flag, reply);
3074
3075 if (ret == 0)
3076 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
3077 wpabuf_len(reply));
3078
3079 wpabuf_free(reply);
3080 os_free(data);
3081
3082 return ret;
3083 }
3084
3085
hostapd_ctrl_iface_eapol_reauth(struct hostapd_data * hapd,const char * cmd)3086 static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
3087 const char *cmd)
3088 {
3089 u8 addr[ETH_ALEN];
3090 struct sta_info *sta;
3091
3092 if (hwaddr_aton(cmd, addr))
3093 return -1;
3094
3095 sta = ap_get_sta(hapd, addr);
3096 if (!sta || !sta->eapol_sm)
3097 return -1;
3098
3099 eapol_auth_reauthenticate(sta->eapol_sm);
3100 return 0;
3101 }
3102
3103
hostapd_ctrl_iface_eapol_set(struct hostapd_data * hapd,char * cmd)3104 static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
3105 {
3106 u8 addr[ETH_ALEN];
3107 struct sta_info *sta;
3108 char *pos = cmd, *param;
3109
3110 if (hwaddr_aton(pos, addr) || pos[17] != ' ')
3111 return -1;
3112 pos += 18;
3113 param = pos;
3114 pos = os_strchr(pos, ' ');
3115 if (!pos)
3116 return -1;
3117 *pos++ = '\0';
3118
3119 sta = ap_get_sta(hapd, addr);
3120 if (!sta || !sta->eapol_sm)
3121 return -1;
3122
3123 return eapol_auth_set_conf(sta->eapol_sm, param, pos);
3124 }
3125
3126
hostapd_ctrl_iface_log_level(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3127 static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd,
3128 char *buf, size_t buflen)
3129 {
3130 char *pos, *end, *stamp;
3131 int ret;
3132
3133 /* cmd: "LOG_LEVEL [<level>]" */
3134 if (*cmd == '\0') {
3135 pos = buf;
3136 end = buf + buflen;
3137 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
3138 "Timestamp: %d\n",
3139 debug_level_str(wpa_debug_level),
3140 wpa_debug_timestamp);
3141 if (os_snprintf_error(end - pos, ret))
3142 ret = 0;
3143
3144 return ret;
3145 }
3146
3147 while (*cmd == ' ')
3148 cmd++;
3149
3150 stamp = os_strchr(cmd, ' ');
3151 if (stamp) {
3152 *stamp++ = '\0';
3153 while (*stamp == ' ') {
3154 stamp++;
3155 }
3156 }
3157
3158 if (os_strlen(cmd)) {
3159 int level = str_to_debug_level(cmd);
3160 if (level < 0)
3161 return -1;
3162 wpa_debug_level = level;
3163 }
3164
3165 if (stamp && os_strlen(stamp))
3166 wpa_debug_timestamp = atoi(stamp);
3167
3168 os_memcpy(buf, "OK\n", 3);
3169 return 3;
3170 }
3171
3172
3173 #ifdef NEED_AP_MLME
hostapd_ctrl_iface_track_sta_list(struct hostapd_data * hapd,char * buf,size_t buflen)3174 static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
3175 char *buf, size_t buflen)
3176 {
3177 struct hostapd_iface *iface = hapd->iface;
3178 char *pos, *end;
3179 struct hostapd_sta_info *info;
3180 struct os_reltime now;
3181
3182 if (!iface->num_sta_seen)
3183 return 0;
3184
3185 sta_track_expire(iface, 0);
3186
3187 pos = buf;
3188 end = buf + buflen;
3189
3190 os_get_reltime(&now);
3191 dl_list_for_each_reverse(info, &iface->sta_seen,
3192 struct hostapd_sta_info, list) {
3193 struct os_reltime age;
3194 int ret;
3195
3196 os_reltime_sub(&now, &info->last_seen, &age);
3197 ret = os_snprintf(pos, end - pos, MACSTR " %u %d\n",
3198 MAC2STR(info->addr), (unsigned int) age.sec,
3199 info->ssi_signal);
3200 if (os_snprintf_error(end - pos, ret))
3201 break;
3202 pos += ret;
3203 }
3204
3205 return pos - buf;
3206 }
3207 #endif /* NEED_AP_MLME */
3208
3209
hostapd_ctrl_iface_req_lci(struct hostapd_data * hapd,const char * cmd)3210 static int hostapd_ctrl_iface_req_lci(struct hostapd_data *hapd,
3211 const char *cmd)
3212 {
3213 u8 addr[ETH_ALEN];
3214
3215 if (hwaddr_aton(cmd, addr)) {
3216 wpa_printf(MSG_INFO, "CTRL: REQ_LCI: Invalid MAC address");
3217 return -1;
3218 }
3219
3220 return hostapd_send_lci_req(hapd, addr);
3221 }
3222
3223
hostapd_ctrl_iface_req_range(struct hostapd_data * hapd,char * cmd)3224 static int hostapd_ctrl_iface_req_range(struct hostapd_data *hapd, char *cmd)
3225 {
3226 u8 addr[ETH_ALEN];
3227 char *token, *context = NULL;
3228 int random_interval, min_ap;
3229 u8 responders[ETH_ALEN * RRM_RANGE_REQ_MAX_RESPONDERS];
3230 unsigned int n_responders;
3231
3232 token = str_token(cmd, " ", &context);
3233 if (!token || hwaddr_aton(token, addr)) {
3234 wpa_printf(MSG_INFO,
3235 "CTRL: REQ_RANGE - Bad destination address");
3236 return -1;
3237 }
3238
3239 token = str_token(cmd, " ", &context);
3240 if (!token)
3241 return -1;
3242
3243 random_interval = atoi(token);
3244 if (random_interval < 0 || random_interval > 0xffff)
3245 return -1;
3246
3247 token = str_token(cmd, " ", &context);
3248 if (!token)
3249 return -1;
3250
3251 min_ap = atoi(token);
3252 if (min_ap <= 0 || min_ap > WLAN_RRM_RANGE_REQ_MAX_MIN_AP)
3253 return -1;
3254
3255 n_responders = 0;
3256 while ((token = str_token(cmd, " ", &context))) {
3257 if (n_responders == RRM_RANGE_REQ_MAX_RESPONDERS) {
3258 wpa_printf(MSG_INFO,
3259 "CTRL: REQ_RANGE: Too many responders");
3260 return -1;
3261 }
3262
3263 if (hwaddr_aton(token, responders + n_responders * ETH_ALEN)) {
3264 wpa_printf(MSG_INFO,
3265 "CTRL: REQ_RANGE: Bad responder address");
3266 return -1;
3267 }
3268
3269 n_responders++;
3270 }
3271
3272 if (!n_responders) {
3273 wpa_printf(MSG_INFO,
3274 "CTRL: REQ_RANGE - No FTM responder address");
3275 return -1;
3276 }
3277
3278 return hostapd_send_range_req(hapd, addr, random_interval, min_ap,
3279 responders, n_responders);
3280 }
3281
3282
hostapd_ctrl_iface_req_beacon(struct hostapd_data * hapd,const char * cmd,char * reply,size_t reply_size)3283 static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd,
3284 const char *cmd, char *reply,
3285 size_t reply_size)
3286 {
3287 u8 addr[ETH_ALEN];
3288 const char *pos;
3289 struct wpabuf *req;
3290 int ret;
3291 u8 req_mode = 0;
3292
3293 if (hwaddr_aton(cmd, addr))
3294 return -1;
3295 pos = os_strchr(cmd, ' ');
3296 if (!pos)
3297 return -1;
3298 pos++;
3299 if (os_strncmp(pos, "req_mode=", 9) == 0) {
3300 int val = hex2byte(pos + 9);
3301
3302 if (val < 0)
3303 return -1;
3304 req_mode = val;
3305 pos += 11;
3306 pos = os_strchr(pos, ' ');
3307 if (!pos)
3308 return -1;
3309 pos++;
3310 }
3311 req = wpabuf_parse_bin(pos);
3312 if (!req)
3313 return -1;
3314
3315 ret = hostapd_send_beacon_req(hapd, addr, req_mode, req);
3316 wpabuf_free(req);
3317 if (ret >= 0)
3318 ret = os_snprintf(reply, reply_size, "%d", ret);
3319 return ret;
3320 }
3321
3322
hostapd_ctrl_iface_req_link_measurement(struct hostapd_data * hapd,const char * cmd,char * reply,size_t reply_size)3323 static int hostapd_ctrl_iface_req_link_measurement(struct hostapd_data *hapd,
3324 const char *cmd, char *reply,
3325 size_t reply_size)
3326 {
3327 u8 addr[ETH_ALEN];
3328 int ret;
3329
3330 if (hwaddr_aton(cmd, addr)) {
3331 wpa_printf(MSG_ERROR,
3332 "CTRL: REQ_LINK_MEASUREMENT: Invalid MAC address");
3333 return -1;
3334 }
3335
3336 ret = hostapd_send_link_measurement_req(hapd, addr);
3337 if (ret >= 0)
3338 ret = os_snprintf(reply, reply_size, "%d", ret);
3339 return ret;
3340 }
3341
3342
hostapd_ctrl_iface_show_neighbor(struct hostapd_data * hapd,char * buf,size_t buflen)3343 static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd,
3344 char *buf, size_t buflen)
3345 {
3346 if (!(hapd->conf->radio_measurements[0] &
3347 WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
3348 wpa_printf(MSG_ERROR,
3349 "CTRL: SHOW_NEIGHBOR: Neighbor report is not enabled");
3350 return -1;
3351 }
3352
3353 return hostapd_neighbor_show(hapd, buf, buflen);
3354 }
3355
3356
hostapd_ctrl_iface_set_neighbor(struct hostapd_data * hapd,char * buf)3357 static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf)
3358 {
3359 struct wpa_ssid_value ssid;
3360 u8 bssid[ETH_ALEN];
3361 struct wpabuf *nr, *lci = NULL, *civic = NULL;
3362 int stationary = 0;
3363 int bss_parameters = 0;
3364 char *tmp;
3365 int ret = -1;
3366
3367 if (!(hapd->conf->radio_measurements[0] &
3368 WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
3369 wpa_printf(MSG_ERROR,
3370 "CTRL: SET_NEIGHBOR: Neighbor report is not enabled");
3371 return -1;
3372 }
3373
3374 if (hwaddr_aton(buf, bssid)) {
3375 wpa_printf(MSG_ERROR, "CTRL: SET_NEIGHBOR: Bad BSSID");
3376 return -1;
3377 }
3378
3379 tmp = os_strstr(buf, "ssid=");
3380 if (!tmp || ssid_parse(tmp + 5, &ssid)) {
3381 wpa_printf(MSG_ERROR,
3382 "CTRL: SET_NEIGHBOR: Bad or missing SSID");
3383 return -1;
3384 }
3385 buf = os_strchr(tmp + 6, tmp[5] == '"' ? '"' : ' ');
3386 if (!buf)
3387 return -1;
3388
3389 tmp = os_strstr(buf, "nr=");
3390 if (!tmp) {
3391 wpa_printf(MSG_ERROR,
3392 "CTRL: SET_NEIGHBOR: Missing Neighbor Report element");
3393 return -1;
3394 }
3395
3396 buf = os_strchr(tmp, ' ');
3397 if (buf)
3398 *buf++ = '\0';
3399
3400 nr = wpabuf_parse_bin(tmp + 3);
3401 if (!nr) {
3402 wpa_printf(MSG_ERROR,
3403 "CTRL: SET_NEIGHBOR: Bad Neighbor Report element");
3404 return -1;
3405 }
3406
3407 if (!buf)
3408 goto set;
3409
3410 tmp = os_strstr(buf, "lci=");
3411 if (tmp) {
3412 buf = os_strchr(tmp, ' ');
3413 if (buf)
3414 *buf++ = '\0';
3415 lci = wpabuf_parse_bin(tmp + 4);
3416 if (!lci) {
3417 wpa_printf(MSG_ERROR,
3418 "CTRL: SET_NEIGHBOR: Bad LCI subelement");
3419 goto fail;
3420 }
3421 }
3422
3423 if (!buf)
3424 goto set;
3425
3426 tmp = os_strstr(buf, "civic=");
3427 if (tmp) {
3428 buf = os_strchr(tmp, ' ');
3429 if (buf)
3430 *buf++ = '\0';
3431 civic = wpabuf_parse_bin(tmp + 6);
3432 if (!civic) {
3433 wpa_printf(MSG_ERROR,
3434 "CTRL: SET_NEIGHBOR: Bad civic subelement");
3435 goto fail;
3436 }
3437 }
3438
3439 if (!buf)
3440 goto set;
3441
3442 if (os_strstr(buf, "stat"))
3443 stationary = 1;
3444
3445 tmp = os_strstr(buf, "bss_parameter=");
3446 if (tmp) {
3447 bss_parameters = atoi(tmp + 14);
3448 if (bss_parameters < 0 || bss_parameters > 0xff) {
3449 wpa_printf(MSG_ERROR,
3450 "CTRL: SET_NEIGHBOR: Bad bss_parameters subelement");
3451 goto fail;
3452 }
3453 }
3454
3455 set:
3456 ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic,
3457 stationary, bss_parameters);
3458
3459 fail:
3460 wpabuf_free(nr);
3461 wpabuf_free(lci);
3462 wpabuf_free(civic);
3463
3464 return ret;
3465 }
3466
3467
hostapd_ctrl_iface_remove_neighbor(struct hostapd_data * hapd,char * buf)3468 static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd,
3469 char *buf)
3470 {
3471 struct wpa_ssid_value ssid;
3472 struct wpa_ssid_value *ssidp = NULL;
3473 u8 bssid[ETH_ALEN];
3474 char *tmp;
3475
3476 if (hwaddr_aton(buf, bssid)) {
3477 wpa_printf(MSG_ERROR, "CTRL: REMOVE_NEIGHBOR: Bad BSSID");
3478 return -1;
3479 }
3480
3481 tmp = os_strstr(buf, "ssid=");
3482 if (tmp) {
3483 ssidp = &ssid;
3484 if (ssid_parse(tmp + 5, &ssid)) {
3485 wpa_printf(MSG_ERROR,
3486 "CTRL: REMOVE_NEIGHBOR: Bad SSID");
3487 return -1;
3488 }
3489 }
3490
3491 return hostapd_neighbor_remove(hapd, bssid, ssidp);
3492 }
3493
3494
hostapd_ctrl_driver_flags(struct hostapd_iface * iface,char * buf,size_t buflen)3495 static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
3496 size_t buflen)
3497 {
3498 int ret, i;
3499 char *pos, *end;
3500
3501 ret = os_snprintf(buf, buflen, "%016llX:\n",
3502 (long long unsigned) iface->drv_flags);
3503 if (os_snprintf_error(buflen, ret))
3504 return -1;
3505
3506 pos = buf + ret;
3507 end = buf + buflen;
3508
3509 for (i = 0; i < 64; i++) {
3510 if (iface->drv_flags & (1LLU << i)) {
3511 ret = os_snprintf(pos, end - pos, "%s\n",
3512 driver_flag_to_string(1LLU << i));
3513 if (os_snprintf_error(end - pos, ret))
3514 return -1;
3515 pos += ret;
3516 }
3517 }
3518
3519 return pos - buf;
3520 }
3521
3522
hostapd_ctrl_driver_flags2(struct hostapd_iface * iface,char * buf,size_t buflen)3523 static int hostapd_ctrl_driver_flags2(struct hostapd_iface *iface, char *buf,
3524 size_t buflen)
3525 {
3526 int ret, i;
3527 char *pos, *end;
3528
3529 ret = os_snprintf(buf, buflen, "%016llX:\n",
3530 (long long unsigned) iface->drv_flags2);
3531 if (os_snprintf_error(buflen, ret))
3532 return -1;
3533
3534 pos = buf + ret;
3535 end = buf + buflen;
3536
3537 for (i = 0; i < 64; i++) {
3538 if (iface->drv_flags2 & (1LLU << i)) {
3539 ret = os_snprintf(pos, end - pos, "%s\n",
3540 driver_flag2_to_string(1LLU << i));
3541 if (os_snprintf_error(end - pos, ret))
3542 return -1;
3543 pos += ret;
3544 }
3545 }
3546
3547 return pos - buf;
3548 }
3549
3550
hostapd_ctrl_iface_get_capability(struct hostapd_data * hapd,const char * field,char * buf,size_t buflen)3551 static int hostapd_ctrl_iface_get_capability(struct hostapd_data *hapd,
3552 const char *field, char *buf,
3553 size_t buflen)
3554 {
3555 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'", field);
3556
3557 #ifdef CONFIG_DPP
3558 if (os_strcmp(field, "dpp") == 0) {
3559 int res;
3560
3561 #ifdef CONFIG_DPP3
3562 res = os_snprintf(buf, buflen, "DPP=3");
3563 #elif defined(CONFIG_DPP2)
3564 res = os_snprintf(buf, buflen, "DPP=2");
3565 #else /* CONFIG_DPP2 */
3566 res = os_snprintf(buf, buflen, "DPP=1");
3567 #endif /* CONFIG_DPP2 */
3568 if (os_snprintf_error(buflen, res))
3569 return -1;
3570 return res;
3571 }
3572 #endif /* CONFIG_DPP */
3573
3574 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
3575 field);
3576
3577 return -1;
3578 }
3579
3580
3581 #ifdef ANDROID
hostapd_ctrl_iface_driver_cmd(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3582 static int hostapd_ctrl_iface_driver_cmd(struct hostapd_data *hapd, char *cmd,
3583 char *buf, size_t buflen)
3584 {
3585 int ret;
3586
3587 ret = hostapd_drv_driver_cmd(hapd, cmd, buf, buflen);
3588 if (ret == 0) {
3589 ret = os_snprintf(buf, buflen, "%s\n", "OK");
3590 if (os_snprintf_error(buflen, ret))
3591 ret = -1;
3592 }
3593 return ret;
3594 }
3595 #endif /* ANDROID */
3596
3597
3598 #ifdef CONFIG_IEEE80211BE
3599
hostapd_ctrl_iface_enable_mld(struct hostapd_iface * iface)3600 static int hostapd_ctrl_iface_enable_mld(struct hostapd_iface *iface)
3601 {
3602 unsigned int i;
3603
3604 if (!iface || !iface->bss[0]->conf->mld_ap) {
3605 wpa_printf(MSG_ERROR,
3606 "Trying to enable AP MLD on an interface that is not affiliated with an AP MLD");
3607 return -1;
3608 }
3609
3610 for (i = 0; i < iface->interfaces->count; ++i) {
3611 struct hostapd_iface *h_iface = iface->interfaces->iface[i];
3612 struct hostapd_data *h_hapd = h_iface->bss[0];
3613
3614 if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
3615 continue;
3616
3617 if (hostapd_enable_iface(h_iface)) {
3618 wpa_printf(MSG_ERROR, "Enabling of AP MLD failed");
3619 return -1;
3620 }
3621 }
3622 return 0;
3623 }
3624
3625
hostapd_disable_iface_bss(struct hostapd_iface * iface)3626 static void hostapd_disable_iface_bss(struct hostapd_iface *iface)
3627 {
3628 unsigned int i;
3629
3630 for (i = 0; i < iface->num_bss; i++)
3631 hostapd_bss_deinit_no_free(iface->bss[i]);
3632 }
3633
3634
hostapd_ctrl_iface_disable_mld(struct hostapd_iface * iface)3635 static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface)
3636 {
3637 unsigned int i;
3638
3639 if (!iface || !iface->bss[0]->conf->mld_ap) {
3640 wpa_printf(MSG_ERROR,
3641 "Trying to disable AP MLD on an interface that is not affiliated with an AP MLD.");
3642 return -1;
3643 }
3644
3645 /* First, disable BSSs before stopping beaconing and doing driver
3646 * deinit so that the broadcast Deauthentication frames go out. */
3647
3648 for (i = 0; i < iface->interfaces->count; ++i) {
3649 struct hostapd_iface *h_iface = iface->interfaces->iface[i];
3650 struct hostapd_data *h_hapd = h_iface->bss[0];
3651
3652 if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
3653 continue;
3654
3655 hostapd_disable_iface_bss(iface);
3656 }
3657
3658 /* Then, fully disable interfaces */
3659 for (i = 0; i < iface->interfaces->count; ++i) {
3660 struct hostapd_iface *h_iface = iface->interfaces->iface[i];
3661 struct hostapd_data *h_hapd = h_iface->bss[0];
3662
3663 if (!hostapd_is_ml_partner(h_hapd, iface->bss[0]))
3664 continue;
3665
3666 if (hostapd_disable_iface(h_iface)) {
3667 wpa_printf(MSG_ERROR, "Disabling AP MLD failed");
3668 return -1;
3669 }
3670 }
3671
3672 return 0;
3673 }
3674
3675
3676 #ifdef CONFIG_TESTING_OPTIONS
hostapd_ctrl_iface_link_remove(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3677 static int hostapd_ctrl_iface_link_remove(struct hostapd_data *hapd, char *cmd,
3678 char *buf, size_t buflen)
3679 {
3680 int ret;
3681 u32 count = atoi(cmd);
3682
3683 if (!count)
3684 count = 1;
3685
3686 ret = hostapd_link_remove(hapd, count);
3687 if (ret == 0) {
3688 ret = os_snprintf(buf, buflen, "%s\n", "OK");
3689 if (os_snprintf_error(buflen, ret))
3690 ret = -1;
3691 else
3692 ret = 0;
3693 }
3694
3695 return ret;
3696 }
3697 #endif /* CONFIG_TESTING_OPTIONS */
3698 #endif /* CONFIG_IEEE80211BE */
3699
3700
3701 #ifdef CONFIG_NAN_USD
3702
hostapd_ctrl_nan_publish(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3703 static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
3704 char *buf, size_t buflen)
3705 {
3706 char *token, *context = NULL;
3707 int publish_id;
3708 struct nan_publish_params params;
3709 const char *service_name = NULL;
3710 struct wpabuf *ssi = NULL;
3711 int ret = -1;
3712 enum nan_service_protocol_type srv_proto_type = 0;
3713
3714 os_memset(¶ms, 0, sizeof(params));
3715 /* USD shall use both solicited and unsolicited transmissions */
3716 params.unsolicited = true;
3717 params.solicited = true;
3718 /* USD shall require FSD without GAS */
3719 params.fsd = true;
3720
3721 while ((token = str_token(cmd, " ", &context))) {
3722 if (os_strncmp(token, "service_name=", 13) == 0) {
3723 service_name = token + 13;
3724 continue;
3725 }
3726
3727 if (os_strncmp(token, "ttl=", 4) == 0) {
3728 params.ttl = atoi(token + 4);
3729 continue;
3730 }
3731
3732 if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
3733 srv_proto_type = atoi(token + 15);
3734 continue;
3735 }
3736
3737 if (os_strncmp(token, "ssi=", 4) == 0) {
3738 if (ssi)
3739 goto fail;
3740 ssi = wpabuf_parse_bin(token + 4);
3741 if (!ssi)
3742 goto fail;
3743 continue;
3744 }
3745
3746 if (os_strcmp(token, "solicited=0") == 0) {
3747 params.solicited = false;
3748 continue;
3749 }
3750
3751 if (os_strcmp(token, "unsolicited=0") == 0) {
3752 params.unsolicited = false;
3753 continue;
3754 }
3755
3756 if (os_strcmp(token, "fsd=0") == 0) {
3757 params.fsd = false;
3758 continue;
3759 }
3760
3761 wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s",
3762 token);
3763 goto fail;
3764 }
3765
3766 publish_id = hostapd_nan_usd_publish(hapd, service_name, srv_proto_type,
3767 ssi, ¶ms);
3768 if (publish_id > 0)
3769 ret = os_snprintf(buf, buflen, "%d", publish_id);
3770 fail:
3771 wpabuf_free(ssi);
3772 return ret;
3773 }
3774
3775
hostapd_ctrl_nan_cancel_publish(struct hostapd_data * hapd,char * cmd)3776 static int hostapd_ctrl_nan_cancel_publish(struct hostapd_data *hapd,
3777 char *cmd)
3778 {
3779 char *token, *context = NULL;
3780 int publish_id = 0;
3781
3782 while ((token = str_token(cmd, " ", &context))) {
3783 if (sscanf(token, "publish_id=%i", &publish_id) == 1)
3784 continue;
3785 wpa_printf(MSG_INFO,
3786 "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s",
3787 token);
3788 return -1;
3789 }
3790
3791 if (publish_id <= 0) {
3792 wpa_printf(MSG_INFO,
3793 "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id");
3794 return -1;
3795 }
3796
3797 hostapd_nan_usd_cancel_publish(hapd, publish_id);
3798 return 0;
3799 }
3800
3801
hostapd_ctrl_nan_update_publish(struct hostapd_data * hapd,char * cmd)3802 static int hostapd_ctrl_nan_update_publish(struct hostapd_data *hapd,
3803 char *cmd)
3804 {
3805 char *token, *context = NULL;
3806 int publish_id = 0;
3807 struct wpabuf *ssi = NULL;
3808 int ret = -1;
3809
3810 while ((token = str_token(cmd, " ", &context))) {
3811 if (sscanf(token, "publish_id=%i", &publish_id) == 1)
3812 continue;
3813 if (os_strncmp(token, "ssi=", 4) == 0) {
3814 if (ssi)
3815 goto fail;
3816 ssi = wpabuf_parse_bin(token + 4);
3817 if (!ssi)
3818 goto fail;
3819 continue;
3820 }
3821 wpa_printf(MSG_INFO,
3822 "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s",
3823 token);
3824 goto fail;
3825 }
3826
3827 if (publish_id <= 0) {
3828 wpa_printf(MSG_INFO,
3829 "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id");
3830 goto fail;
3831 }
3832
3833 ret = hostapd_nan_usd_update_publish(hapd, publish_id, ssi);
3834 fail:
3835 wpabuf_free(ssi);
3836 return ret;
3837 }
3838
3839
hostapd_ctrl_nan_subscribe(struct hostapd_data * hapd,char * cmd,char * buf,size_t buflen)3840 static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
3841 char *buf, size_t buflen)
3842 {
3843 char *token, *context = NULL;
3844 int subscribe_id;
3845 struct nan_subscribe_params params;
3846 const char *service_name = NULL;
3847 struct wpabuf *ssi = NULL;
3848 int ret = -1;
3849 enum nan_service_protocol_type srv_proto_type = 0;
3850
3851 os_memset(¶ms, 0, sizeof(params));
3852
3853 while ((token = str_token(cmd, " ", &context))) {
3854 if (os_strncmp(token, "service_name=", 13) == 0) {
3855 service_name = token + 13;
3856 continue;
3857 }
3858
3859 if (os_strcmp(token, "active=1") == 0) {
3860 params.active = true;
3861 continue;
3862 }
3863
3864 if (os_strncmp(token, "ttl=", 4) == 0) {
3865 params.ttl = atoi(token + 4);
3866 continue;
3867 }
3868
3869 if (os_strncmp(token, "srv_proto_type=", 15) == 0) {
3870 srv_proto_type = atoi(token + 15);
3871 continue;
3872 }
3873
3874 if (os_strncmp(token, "ssi=", 4) == 0) {
3875 if (ssi)
3876 goto fail;
3877 ssi = wpabuf_parse_bin(token + 4);
3878 if (!ssi)
3879 goto fail;
3880 continue;
3881 }
3882
3883 wpa_printf(MSG_INFO,
3884 "CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
3885 token);
3886 goto fail;
3887 }
3888
3889 subscribe_id = hostapd_nan_usd_subscribe(hapd, service_name,
3890 srv_proto_type, ssi,
3891 ¶ms);
3892 if (subscribe_id > 0)
3893 ret = os_snprintf(buf, buflen, "%d", subscribe_id);
3894 fail:
3895 wpabuf_free(ssi);
3896 return ret;
3897 }
3898
3899
hostapd_ctrl_nan_cancel_subscribe(struct hostapd_data * hapd,char * cmd)3900 static int hostapd_ctrl_nan_cancel_subscribe(struct hostapd_data *hapd,
3901 char *cmd)
3902 {
3903 char *token, *context = NULL;
3904 int subscribe_id = 0;
3905
3906 while ((token = str_token(cmd, " ", &context))) {
3907 if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1)
3908 continue;
3909 wpa_printf(MSG_INFO,
3910 "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s",
3911 token);
3912 return -1;
3913 }
3914
3915 if (subscribe_id <= 0) {
3916 wpa_printf(MSG_INFO,
3917 "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id");
3918 return -1;
3919 }
3920
3921 hostapd_nan_usd_cancel_subscribe(hapd, subscribe_id);
3922 return 0;
3923 }
3924
3925
hostapd_ctrl_nan_transmit(struct hostapd_data * hapd,char * cmd)3926 static int hostapd_ctrl_nan_transmit(struct hostapd_data *hapd, char *cmd)
3927 {
3928 char *token, *context = NULL;
3929 int handle = 0;
3930 int req_instance_id = 0;
3931 struct wpabuf *ssi = NULL;
3932 u8 peer_addr[ETH_ALEN];
3933 int ret = -1;
3934
3935 os_memset(peer_addr, 0, ETH_ALEN);
3936
3937 while ((token = str_token(cmd, " ", &context))) {
3938 if (sscanf(token, "handle=%i", &handle) == 1)
3939 continue;
3940
3941 if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1)
3942 continue;
3943
3944 if (os_strncmp(token, "address=", 8) == 0) {
3945 if (hwaddr_aton(token + 8, peer_addr) < 0)
3946 return -1;
3947 continue;
3948 }
3949
3950 if (os_strncmp(token, "ssi=", 4) == 0) {
3951 if (ssi)
3952 goto fail;
3953 ssi = wpabuf_parse_bin(token + 4);
3954 if (!ssi)
3955 goto fail;
3956 continue;
3957 }
3958
3959 wpa_printf(MSG_INFO,
3960 "CTRL: Invalid NAN_TRANSMIT parameter: %s",
3961 token);
3962 goto fail;
3963 }
3964
3965 if (handle <= 0) {
3966 wpa_printf(MSG_INFO,
3967 "CTRL: Invalid or missing NAN_TRANSMIT handle");
3968 goto fail;
3969 }
3970
3971 if (is_zero_ether_addr(peer_addr)) {
3972 wpa_printf(MSG_INFO,
3973 "CTRL: Invalid or missing NAN_TRANSMIT address");
3974 goto fail;
3975 }
3976
3977 ret = hostapd_nan_usd_transmit(hapd, handle, ssi, NULL, peer_addr,
3978 req_instance_id);
3979 fail:
3980 wpabuf_free(ssi);
3981 return ret;
3982 }
3983
3984 #endif /* CONFIG_NAN_USD */
3985
3986 #ifdef __ZEPHYR__
hostapd_ctrl_iface_receive_process(struct hostapd_data * hapd,char * buf,char * reply,int reply_size,struct sockaddr_storage * from,socklen_t fromlen)3987 int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
3988 char *buf, char *reply,
3989 int reply_size,
3990 struct sockaddr_storage *from,
3991 socklen_t fromlen)
3992 #else
3993 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
3994 char *buf, char *reply,
3995 int reply_size,
3996 struct sockaddr_storage *from,
3997 socklen_t fromlen)
3998 #endif /* __ZEPHYR__ */
3999 {
4000 int reply_len, res;
4001
4002 os_memcpy(reply, "OK\n", 3);
4003 reply_len = 3;
4004
4005 if (os_strcmp(buf, "PING") == 0) {
4006 os_memcpy(reply, "PONG\n", 5);
4007 reply_len = 5;
4008 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
4009 if (wpa_debug_reopen_file() < 0)
4010 reply_len = -1;
4011 } else if (os_strcmp(buf, "CLOSE_LOG") == 0) {
4012 wpa_debug_stop_log();
4013 } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
4014 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
4015 } else if (os_strcmp(buf, "STATUS") == 0) {
4016 reply_len = hostapd_ctrl_iface_status(hapd, reply,
4017 reply_size);
4018 } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
4019 reply_len = hostapd_drv_status(hapd, reply, reply_size);
4020 } else if (os_strcmp(buf, "MIB") == 0) {
4021 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
4022 if (reply_len >= 0) {
4023 res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
4024 reply_size - reply_len);
4025 if (res < 0)
4026 reply_len = -1;
4027 else
4028 reply_len += res;
4029 }
4030 if (reply_len >= 0) {
4031 res = ieee802_1x_get_mib(hapd, reply + reply_len,
4032 reply_size - reply_len);
4033 if (res < 0)
4034 reply_len = -1;
4035 else
4036 reply_len += res;
4037 }
4038 #ifndef CONFIG_NO_RADIUS
4039 if (reply_len >= 0) {
4040 res = radius_client_get_mib(hapd->radius,
4041 reply + reply_len,
4042 reply_size - reply_len);
4043 if (res < 0)
4044 reply_len = -1;
4045 else
4046 reply_len += res;
4047 }
4048 #endif /* CONFIG_NO_RADIUS */
4049 } else if (os_strncmp(buf, "MIB ", 4) == 0) {
4050 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
4051 buf + 4);
4052 } else if (os_strcmp(buf, "STA-FIRST") == 0) {
4053 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
4054 reply_size);
4055 } else if (os_strncmp(buf, "STA ", 4) == 0) {
4056 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
4057 reply_size);
4058 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
4059 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
4060 reply_size);
4061 /* TODO: support iface attach/detach operations */
4062 #ifndef __ZEPHYR__
4063 } else if (os_strcmp(buf, "ATTACH") == 0) {
4064 if (hostapd_ctrl_iface_attach(hapd, from, fromlen, NULL))
4065 reply_len = -1;
4066 } else if (os_strncmp(buf, "ATTACH ", 7) == 0) {
4067 if (hostapd_ctrl_iface_attach(hapd, from, fromlen, buf + 7))
4068 reply_len = -1;
4069 } else if (os_strcmp(buf, "DETACH") == 0) {
4070 if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
4071 reply_len = -1;
4072 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
4073 if (hostapd_ctrl_iface_level(hapd, from, fromlen,
4074 buf + 6))
4075 reply_len = -1;
4076 #endif /* __ZEPHYR__ */
4077 } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
4078 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
4079 reply_len = -1;
4080 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
4081 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
4082 reply_len = -1;
4083 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
4084 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
4085 reply_len = -1;
4086 #ifdef CONFIG_TAXONOMY
4087 } else if (os_strncmp(buf, "SIGNATURE ", 10) == 0) {
4088 reply_len = hostapd_ctrl_iface_signature(hapd, buf + 10,
4089 reply, reply_size);
4090 #endif /* CONFIG_TAXONOMY */
4091 } else if (os_strncmp(buf, "POLL_STA ", 9) == 0) {
4092 if (hostapd_ctrl_iface_poll_sta(hapd, buf + 9))
4093 reply_len = -1;
4094 } else if (os_strcmp(buf, "STOP_AP") == 0) {
4095 if (hostapd_ctrl_iface_stop_ap(hapd))
4096 reply_len = -1;
4097 #ifdef NEED_AP_MLME
4098 } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
4099 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
4100 reply_len = -1;
4101 #endif /* NEED_AP_MLME */
4102 #ifdef CONFIG_WPS
4103 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
4104 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
4105 reply_len = -1;
4106 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
4107 reply_len = hostapd_ctrl_iface_wps_check_pin(
4108 hapd, buf + 14, reply, reply_size);
4109 } else if (os_strcmp(buf, "WPS_PBC") == 0) {
4110 if (hostapd_wps_button_pushed(hapd, NULL))
4111 reply_len = -1;
4112 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
4113 if (hostapd_wps_cancel(hapd))
4114 reply_len = -1;
4115 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
4116 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
4117 reply, reply_size);
4118 } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
4119 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
4120 reply_len = -1;
4121 } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
4122 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
4123 reply_size);
4124 #ifdef CONFIG_WPS_NFC
4125 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
4126 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
4127 reply_len = -1;
4128 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
4129 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
4130 hapd, buf + 21, reply, reply_size);
4131 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
4132 reply_len = hostapd_ctrl_iface_wps_nfc_token(
4133 hapd, buf + 14, reply, reply_size);
4134 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
4135 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
4136 hapd, buf + 21, reply, reply_size);
4137 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
4138 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
4139 reply_len = -1;
4140 #endif /* CONFIG_WPS_NFC */
4141 #endif /* CONFIG_WPS */
4142 #ifdef CONFIG_INTERWORKING
4143 } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
4144 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
4145 reply_len = -1;
4146 } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
4147 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
4148 reply_len = -1;
4149 #endif /* CONFIG_INTERWORKING */
4150 #ifdef CONFIG_HS20
4151 } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
4152 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
4153 reply_len = -1;
4154 } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
4155 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
4156 reply_len = -1;
4157 #endif /* CONFIG_HS20 */
4158 #ifdef CONFIG_WNM_AP
4159 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
4160 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
4161 reply_len = -1;
4162 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
4163 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
4164 reply_len = -1;
4165 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
4166 if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
4167 reply_len = -1;
4168 } else if (os_strncmp(buf, "COLOC_INTF_REQ ", 15) == 0) {
4169 if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15))
4170 reply_len = -1;
4171 #endif /* CONFIG_WNM_AP */
4172 } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
4173 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
4174 reply_size);
4175 } else if (os_strncmp(buf, "SET ", 4) == 0) {
4176 if (hostapd_ctrl_iface_set(hapd, buf + 4))
4177 reply_len = -1;
4178 } else if (os_strncmp(buf, "GET ", 4) == 0) {
4179 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
4180 reply_size);
4181 } else if (os_strcmp(buf, "ENABLE") == 0) {
4182 if (hostapd_ctrl_iface_enable(hapd->iface))
4183 reply_len = -1;
4184 } else if (os_strcmp(buf, "RELOAD_WPA_PSK") == 0) {
4185 if (hostapd_ctrl_iface_reload_wpa_psk(hapd))
4186 reply_len = -1;
4187 #ifdef CONFIG_IEEE80211R_AP
4188 } else if (os_strcmp(buf, "GET_RXKHS") == 0) {
4189 reply_len = hostapd_ctrl_iface_get_rxkhs(hapd, reply,
4190 reply_size);
4191 } else if (os_strcmp(buf, "RELOAD_RXKHS") == 0) {
4192 if (hostapd_ctrl_iface_reload_rxkhs(hapd))
4193 reply_len = -1;
4194 #endif /* CONFIG_IEEE80211R_AP */
4195 } else if (os_strcmp(buf, "RELOAD_BSS") == 0) {
4196 if (hostapd_ctrl_iface_reload_bss(hapd))
4197 reply_len = -1;
4198 } else if (os_strcmp(buf, "RELOAD_CONFIG") == 0) {
4199 if (hostapd_reload_config(hapd->iface))
4200 reply_len = -1;
4201 } else if (os_strcmp(buf, "RELOAD") == 0) {
4202 if (hostapd_ctrl_iface_reload(hapd->iface))
4203 reply_len = -1;
4204 } else if (os_strcmp(buf, "DISABLE") == 0) {
4205 if (hostapd_ctrl_iface_disable(hapd->iface))
4206 reply_len = -1;
4207 } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
4208 if (ieee802_11_set_beacon(hapd))
4209 reply_len = -1;
4210 #ifdef CONFIG_TESTING_OPTIONS
4211 } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
4212 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
4213 reply_len = -1;
4214 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
4215 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
4216 reply_len = -1;
4217 } else if (os_strncmp(buf, "MGMT_TX_STATUS_PROCESS ", 23) == 0) {
4218 if (hostapd_ctrl_iface_mgmt_tx_status_process(hapd,
4219 buf + 23) < 0)
4220 reply_len = -1;
4221 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
4222 if (hostapd_ctrl_iface_mgmt_rx_process(hapd, buf + 16) < 0)
4223 reply_len = -1;
4224 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
4225 if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
4226 reply_len = -1;
4227 } else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
4228 if (hostapd_ctrl_iface_eapol_tx(hapd, buf + 9) < 0)
4229 reply_len = -1;
4230 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
4231 if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
4232 reply_len = -1;
4233 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
4234 if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
4235 reply_len = -1;
4236 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
4237 if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
4238 reply_len = -1;
4239 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
4240 if (testing_set_fail_pattern(true, buf + 16) < 0)
4241 reply_len = -1;
4242 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
4243 reply_len = testing_get_fail_pattern(true, reply, reply_size);
4244 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
4245 if (testing_set_fail_pattern(false, buf + 10) < 0)
4246 reply_len = -1;
4247 } else if (os_strcmp(buf, "GET_FAIL") == 0) {
4248 reply_len = testing_get_fail_pattern(false, reply, reply_size);
4249 } else if (os_strncmp(buf, "RESET_PN ", 9) == 0) {
4250 if (hostapd_ctrl_reset_pn(hapd, buf + 9) < 0)
4251 reply_len = -1;
4252 } else if (os_strncmp(buf, "SET_KEY ", 8) == 0) {
4253 if (hostapd_ctrl_set_key(hapd, buf + 8) < 0)
4254 reply_len = -1;
4255 } else if (os_strncmp(buf, "RESEND_M1 ", 10) == 0) {
4256 if (hostapd_ctrl_resend_m1(hapd, buf + 10) < 0)
4257 reply_len = -1;
4258 } else if (os_strncmp(buf, "RESEND_M3 ", 10) == 0) {
4259 if (hostapd_ctrl_resend_m3(hapd, buf + 10) < 0)
4260 reply_len = -1;
4261 } else if (os_strncmp(buf, "RESEND_GROUP_M1 ", 16) == 0) {
4262 if (hostapd_ctrl_resend_group_m1(hapd, buf + 16) < 0)
4263 reply_len = -1;
4264 } else if (os_strncmp(buf, "REKEY_PTK ", 10) == 0) {
4265 if (hostapd_ctrl_rekey_ptk(hapd, buf + 10) < 0)
4266 reply_len = -1;
4267 } else if (os_strcmp(buf, "REKEY_GTK") == 0) {
4268 if (wpa_auth_rekey_gtk(hapd->wpa_auth) < 0)
4269 reply_len = -1;
4270 } else if (os_strncmp(buf, "GET_PMK ", 8) == 0) {
4271 reply_len = hostapd_ctrl_get_pmk(hapd, buf + 8, reply,
4272 reply_size);
4273 } else if (os_strncmp(buf, "REGISTER_FRAME ", 15) == 0) {
4274 if (hostapd_ctrl_register_frame(hapd, buf + 16) < 0)
4275 reply_len = -1;
4276 #endif /* CONFIG_TESTING_OPTIONS */
4277 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
4278 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
4279 reply_len = -1;
4280 #ifdef CONFIG_IEEE80211AX
4281 } else if (os_strncmp(buf, "COLOR_CHANGE ", 13) == 0) {
4282 if (hostapd_ctrl_iface_color_change(hapd->iface, buf + 13))
4283 reply_len = -1;
4284 #endif /* CONFIG_IEEE80211AX */
4285 } else if (os_strncmp(buf, "NOTIFY_CW_CHANGE ", 17) == 0) {
4286 if (hostapd_ctrl_iface_notify_cw_change(hapd, buf + 17))
4287 reply_len = -1;
4288 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
4289 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
4290 reply_size);
4291 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
4292 ieee802_1x_erp_flush(hapd);
4293 #ifdef RADIUS_SERVER
4294 radius_server_erp_flush(hapd->radius_srv);
4295 #endif /* RADIUS_SERVER */
4296 } else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
4297 if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
4298 reply_len = -1;
4299 } else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
4300 if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
4301 reply_len = -1;
4302 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
4303 reply_len = hostapd_ctrl_iface_log_level(
4304 hapd, buf + 9, reply, reply_size);
4305 #ifdef NEED_AP_MLME
4306 } else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
4307 reply_len = hostapd_ctrl_iface_track_sta_list(
4308 hapd, reply, reply_size);
4309 #endif /* NEED_AP_MLME */
4310 } else if (os_strcmp(buf, "PMKSA") == 0) {
4311 reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply,
4312 reply_size);
4313 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
4314 hostapd_ctrl_iface_pmksa_flush(hapd);
4315 } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) {
4316 if (hostapd_ctrl_iface_pmksa_add(hapd, buf + 10) < 0)
4317 reply_len = -1;
4318 } else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) {
4319 if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13))
4320 reply_len = -1;
4321 } else if (os_strcmp(buf, "SHOW_NEIGHBOR") == 0) {
4322 reply_len = hostapd_ctrl_iface_show_neighbor(hapd, reply,
4323 reply_size);
4324 } else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) {
4325 if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16))
4326 reply_len = -1;
4327 } else if (os_strncmp(buf, "REQ_LCI ", 8) == 0) {
4328 if (hostapd_ctrl_iface_req_lci(hapd, buf + 8))
4329 reply_len = -1;
4330 } else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) {
4331 if (hostapd_ctrl_iface_req_range(hapd, buf + 10))
4332 reply_len = -1;
4333 } else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) {
4334 reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11,
4335 reply, reply_size);
4336 } else if (os_strncmp(buf, "REQ_LINK_MEASUREMENT ", 21) == 0) {
4337 reply_len = hostapd_ctrl_iface_req_link_measurement(
4338 hapd, buf + 21, reply, reply_size);
4339 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
4340 reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
4341 reply_size);
4342 } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) {
4343 reply_len = hostapd_ctrl_driver_flags2(hapd->iface, reply,
4344 reply_size);
4345 } else if (os_strcmp(buf, "TERMINATE") == 0) {
4346 eloop_terminate();
4347 } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
4348 if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) {
4349 if (hostapd_ctrl_iface_acl_add_mac(
4350 &hapd->conf->accept_mac,
4351 &hapd->conf->num_accept_mac, buf + 19) ||
4352 hostapd_set_acl(hapd))
4353 reply_len = -1;
4354 } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) {
4355 if (hostapd_ctrl_iface_acl_del_mac(
4356 &hapd->conf->accept_mac,
4357 &hapd->conf->num_accept_mac, buf + 19) ||
4358 hostapd_set_acl(hapd) ||
4359 hostapd_disassoc_accept_mac(hapd))
4360 reply_len = -1;
4361 } else if (os_strcmp(buf + 11, "SHOW") == 0) {
4362 reply_len = hostapd_ctrl_iface_acl_show_mac(
4363 hapd->conf->accept_mac,
4364 hapd->conf->num_accept_mac, reply, reply_size);
4365 } else if (os_strcmp(buf + 11, "CLEAR") == 0) {
4366 hostapd_ctrl_iface_acl_clear_list(
4367 &hapd->conf->accept_mac,
4368 &hapd->conf->num_accept_mac);
4369 if (hostapd_set_acl(hapd) ||
4370 hostapd_disassoc_accept_mac(hapd))
4371 reply_len = -1;
4372 } else {
4373 reply_len = -1;
4374 }
4375 } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) {
4376 if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) {
4377 if (hostapd_ctrl_iface_acl_add_mac(
4378 &hapd->conf->deny_mac,
4379 &hapd->conf->num_deny_mac, buf + 17) ||
4380 hostapd_set_acl(hapd) ||
4381 hostapd_disassoc_deny_mac(hapd))
4382 reply_len = -1;
4383 } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) {
4384 if (hostapd_ctrl_iface_acl_del_mac(
4385 &hapd->conf->deny_mac,
4386 &hapd->conf->num_deny_mac, buf + 17) ||
4387 hostapd_set_acl(hapd))
4388 reply_len = -1;
4389 } else if (os_strcmp(buf + 9, "SHOW") == 0) {
4390 reply_len = hostapd_ctrl_iface_acl_show_mac(
4391 hapd->conf->deny_mac,
4392 hapd->conf->num_deny_mac, reply, reply_size);
4393 } else if (os_strcmp(buf + 9, "CLEAR") == 0) {
4394 hostapd_ctrl_iface_acl_clear_list(
4395 &hapd->conf->deny_mac,
4396 &hapd->conf->num_deny_mac);
4397 if (hostapd_set_acl(hapd))
4398 reply_len = -1;
4399 } else {
4400 reply_len = -1;
4401 }
4402 #ifdef CONFIG_DPP
4403 } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
4404 res = hostapd_dpp_qr_code(hapd, buf + 12);
4405 if (res < 0) {
4406 reply_len = -1;
4407 } else {
4408 reply_len = os_snprintf(reply, reply_size, "%d", res);
4409 if (os_snprintf_error(reply_size, reply_len))
4410 reply_len = -1;
4411 }
4412 } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
4413 res = hostapd_dpp_nfc_uri(hapd, buf + 12);
4414 if (res < 0) {
4415 reply_len = -1;
4416 } else {
4417 reply_len = os_snprintf(reply, reply_size, "%d", res);
4418 if (os_snprintf_error(reply_size, reply_len))
4419 reply_len = -1;
4420 }
4421 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) {
4422 res = hostapd_dpp_nfc_handover_req(hapd, buf + 20);
4423 if (res < 0) {
4424 reply_len = -1;
4425 } else {
4426 reply_len = os_snprintf(reply, reply_size, "%d", res);
4427 if (os_snprintf_error(reply_size, reply_len))
4428 reply_len = -1;
4429 }
4430 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) {
4431 res = hostapd_dpp_nfc_handover_sel(hapd, buf + 20);
4432 if (res < 0) {
4433 reply_len = -1;
4434 } else {
4435 reply_len = os_snprintf(reply, reply_size, "%d", res);
4436 if (os_snprintf_error(reply_size, reply_len))
4437 reply_len = -1;
4438 }
4439 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
4440 res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18);
4441 if (res < 0) {
4442 reply_len = -1;
4443 } else {
4444 reply_len = os_snprintf(reply, reply_size, "%d", res);
4445 if (os_snprintf_error(reply_size, reply_len))
4446 reply_len = -1;
4447 }
4448 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) {
4449 if (dpp_bootstrap_remove(hapd->iface->interfaces->dpp,
4450 buf + 21) < 0)
4451 reply_len = -1;
4452 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) {
4453 const char *uri;
4454
4455 uri = dpp_bootstrap_get_uri(hapd->iface->interfaces->dpp,
4456 atoi(buf + 22));
4457 if (!uri) {
4458 reply_len = -1;
4459 } else {
4460 reply_len = os_snprintf(reply, reply_size, "%s", uri);
4461 if (os_snprintf_error(reply_size, reply_len))
4462 reply_len = -1;
4463 }
4464 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) {
4465 reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp,
4466 atoi(buf + 19),
4467 reply, reply_size);
4468 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
4469 if (dpp_bootstrap_set(hapd->iface->interfaces->dpp,
4470 atoi(buf + 18),
4471 os_strchr(buf + 18, ' ')) < 0)
4472 reply_len = -1;
4473 } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
4474 if (hostapd_dpp_auth_init(hapd, buf + 13) < 0)
4475 reply_len = -1;
4476 } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) {
4477 if (hostapd_dpp_listen(hapd, buf + 11) < 0)
4478 reply_len = -1;
4479 } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) {
4480 hostapd_dpp_stop(hapd);
4481 hostapd_dpp_listen_stop(hapd);
4482 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) {
4483 res = dpp_configurator_add(hapd->iface->interfaces->dpp,
4484 buf + 20);
4485 if (res < 0) {
4486 reply_len = -1;
4487 } else {
4488 reply_len = os_snprintf(reply, reply_size, "%d", res);
4489 if (os_snprintf_error(reply_size, reply_len))
4490 reply_len = -1;
4491 }
4492 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) {
4493 if (dpp_configurator_set(hapd->iface->interfaces->dpp,
4494 buf + 20) < 0)
4495 reply_len = -1;
4496 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) {
4497 if (dpp_configurator_remove(hapd->iface->interfaces->dpp,
4498 buf + 24) < 0)
4499 reply_len = -1;
4500 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) {
4501 if (hostapd_dpp_configurator_sign(hapd, buf + 21) < 0)
4502 reply_len = -1;
4503 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) {
4504 reply_len = dpp_configurator_get_key_id(
4505 hapd->iface->interfaces->dpp,
4506 atoi(buf + 25),
4507 reply, reply_size);
4508 } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) {
4509 res = hostapd_dpp_pkex_add(hapd, buf + 12);
4510 if (res < 0) {
4511 reply_len = -1;
4512 } else {
4513 reply_len = os_snprintf(reply, reply_size, "%d", res);
4514 if (os_snprintf_error(reply_size, reply_len))
4515 reply_len = -1;
4516 }
4517 } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
4518 if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0)
4519 reply_len = -1;
4520 #ifdef CONFIG_DPP2
4521 } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
4522 if (hostapd_dpp_controller_start(hapd, buf + 20) < 0)
4523 reply_len = -1;
4524 } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
4525 if (hostapd_dpp_controller_start(hapd, NULL) < 0)
4526 reply_len = -1;
4527 } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
4528 dpp_controller_stop(hapd->iface->interfaces->dpp);
4529 } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
4530 if (hostapd_dpp_chirp(hapd, buf + 9) < 0)
4531 reply_len = -1;
4532 } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
4533 hostapd_dpp_chirp_stop(hapd);
4534 } else if (os_strncmp(buf, "DPP_RELAY_ADD_CONTROLLER ", 25) == 0) {
4535 if (hostapd_dpp_add_controller(hapd, buf + 25) < 0)
4536 reply_len = -1;
4537 } else if (os_strncmp(buf, "DPP_RELAY_REMOVE_CONTROLLER ", 28) == 0) {
4538 hostapd_dpp_remove_controller(hapd, buf + 28);
4539 #endif /* CONFIG_DPP2 */
4540 #ifdef CONFIG_DPP3
4541 } else if (os_strcmp(buf, "DPP_PUSH_BUTTON") == 0) {
4542 if (hostapd_dpp_push_button(hapd, NULL) < 0)
4543 reply_len = -1;
4544 } else if (os_strncmp(buf, "DPP_PUSH_BUTTON ", 16) == 0) {
4545 if (hostapd_dpp_push_button(hapd, buf + 15) < 0)
4546 reply_len = -1;
4547 #endif /* CONFIG_DPP3 */
4548 #endif /* CONFIG_DPP */
4549 #ifdef CONFIG_NAN_USD
4550 } else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) {
4551 reply_len = hostapd_ctrl_nan_publish(hapd, buf + 12, reply,
4552 reply_size);
4553 } else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) {
4554 if (hostapd_ctrl_nan_cancel_publish(hapd, buf + 19) < 0)
4555 reply_len = -1;
4556 } else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) {
4557 if (hostapd_ctrl_nan_update_publish(hapd, buf + 19) < 0)
4558 reply_len = -1;
4559 } else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) {
4560 reply_len = hostapd_ctrl_nan_subscribe(hapd, buf + 14, reply,
4561 reply_size);
4562 } else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) {
4563 if (hostapd_ctrl_nan_cancel_subscribe(hapd, buf + 21) < 0)
4564 reply_len = -1;
4565 } else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) {
4566 if (hostapd_ctrl_nan_transmit(hapd, buf + 13) < 0)
4567 reply_len = -1;
4568 #endif /* CONFIG_NAN_USD */
4569 #ifdef RADIUS_SERVER
4570 } else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) {
4571 if (radius_server_dac_request(hapd->radius_srv, buf + 12) < 0)
4572 reply_len = -1;
4573 #endif /* RADIUS_SERVER */
4574 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
4575 reply_len = hostapd_ctrl_iface_get_capability(
4576 hapd, buf + 15, reply, reply_size);
4577 #ifdef CONFIG_PASN
4578 } else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
4579 reply_len = ptksa_cache_list(hapd->ptksa, reply, reply_size);
4580 #endif /* CONFIG_PASN */
4581 #ifdef ANDROID
4582 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
4583 reply_len = hostapd_ctrl_iface_driver_cmd(hapd, buf + 7, reply,
4584 reply_size);
4585 #endif /* ANDROID */
4586 #ifdef CONFIG_IEEE80211BE
4587 } else if (os_strcmp(buf, "ENABLE_MLD") == 0) {
4588 if (hostapd_ctrl_iface_enable_mld(hapd->iface))
4589 reply_len = -1;
4590 } else if (os_strcmp(buf, "DISABLE_MLD") == 0) {
4591 if (hostapd_ctrl_iface_disable_mld(hapd->iface))
4592 reply_len = -1;
4593 #ifdef CONFIG_TESTING_OPTIONS
4594 } else if (os_strncmp(buf, "LINK_REMOVE ", 12) == 0) {
4595 if (hostapd_ctrl_iface_link_remove(hapd, buf + 12,
4596 reply, reply_size))
4597 reply_len = -1;
4598 #endif /* CONFIG_TESTING_OPTIONS */
4599 #endif /* CONFIG_IEEE80211BE */
4600 } else {
4601 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
4602 reply_len = 16;
4603 }
4604
4605 if (reply_len < 0) {
4606 os_memcpy(reply, "FAIL\n", 5);
4607 reply_len = 5;
4608 }
4609
4610 return reply_len;
4611 }
4612
4613
4614 #ifndef __ZEPHYR__
hostapd_ctrl_iface_receive(int sock,void * eloop_ctx,void * sock_ctx)4615 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
4616 void *sock_ctx)
4617 {
4618 struct hostapd_data *hapd = eloop_ctx;
4619 char buf[4096];
4620 int res;
4621 struct sockaddr_storage from;
4622 socklen_t fromlen = sizeof(from);
4623 char *reply, *pos = buf;
4624 const int reply_size = 4096;
4625 int reply_len;
4626 int level = MSG_DEBUG;
4627 #ifdef CONFIG_CTRL_IFACE_UDP
4628 unsigned char lcookie[CTRL_IFACE_COOKIE_LEN];
4629 #endif /* CONFIG_CTRL_IFACE_UDP */
4630
4631 res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
4632 (struct sockaddr *) &from, &fromlen);
4633 if (res < 0) {
4634 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
4635 strerror(errno));
4636 return;
4637 }
4638 buf[res] = '\0';
4639
4640 reply = os_malloc(reply_size);
4641 if (reply == NULL) {
4642 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
4643 fromlen) < 0) {
4644 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
4645 strerror(errno));
4646 }
4647 return;
4648 }
4649
4650 #ifdef CONFIG_CTRL_IFACE_UDP
4651 if (os_strcmp(buf, "GET_COOKIE") == 0) {
4652 os_memcpy(reply, "COOKIE=", 7);
4653 wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1,
4654 hapd->ctrl_iface_cookie,
4655 CTRL_IFACE_COOKIE_LEN);
4656 reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN;
4657 goto done;
4658 }
4659
4660 if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
4661 hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) {
4662 wpa_printf(MSG_DEBUG,
4663 "CTRL: No cookie in the request - drop request");
4664 os_free(reply);
4665 return;
4666 }
4667
4668 if (os_memcmp(hapd->ctrl_iface_cookie, lcookie,
4669 CTRL_IFACE_COOKIE_LEN) != 0) {
4670 wpa_printf(MSG_DEBUG,
4671 "CTRL: Invalid cookie in the request - drop request");
4672 os_free(reply);
4673 return;
4674 }
4675
4676 pos = buf + 7 + 2 * CTRL_IFACE_COOKIE_LEN;
4677 while (*pos == ' ')
4678 pos++;
4679 #endif /* CONFIG_CTRL_IFACE_UDP */
4680
4681 if (os_strcmp(pos, "PING") == 0)
4682 level = MSG_EXCESSIVE;
4683 wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res);
4684
4685 reply_len = hostapd_ctrl_iface_receive_process(hapd, pos,
4686 reply, reply_size,
4687 &from, fromlen);
4688
4689 #ifdef CONFIG_CTRL_IFACE_UDP
4690 done:
4691 #endif /* CONFIG_CTRL_IFACE_UDP */
4692 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
4693 fromlen) < 0) {
4694 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
4695 strerror(errno));
4696 }
4697 os_free(reply);
4698 }
4699
4700
4701 #ifndef CONFIG_CTRL_IFACE_UDP
hostapd_ctrl_iface_path(struct hostapd_data * hapd)4702 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
4703 {
4704 char *buf;
4705 size_t len;
4706
4707 if (hapd->conf->ctrl_interface == NULL)
4708 return NULL;
4709
4710 len = os_strlen(hapd->conf->ctrl_interface) +
4711 os_strlen(hapd->conf->iface) + 2;
4712 buf = os_malloc(len);
4713 if (buf == NULL)
4714 return NULL;
4715
4716 os_snprintf(buf, len, "%s/%s",
4717 hapd->conf->ctrl_interface, hapd->conf->iface);
4718 buf[len - 1] = '\0';
4719 return buf;
4720 }
4721 #endif /* CONFIG_CTRL_IFACE_UDP */
4722
4723
hostapd_ctrl_iface_msg_cb(void * ctx,int level,enum wpa_msg_type type,const char * txt,size_t len)4724 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
4725 enum wpa_msg_type type,
4726 const char *txt, size_t len)
4727 {
4728 struct hostapd_data *hapd = ctx;
4729 if (hapd == NULL)
4730 return;
4731 hostapd_ctrl_iface_send(hapd, level, type, txt, len);
4732 }
4733 #endif /* __ZEPHYR__ */
4734
4735
hostapd_ctrl_iface_init(struct hostapd_data * hapd)4736 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
4737 {
4738 #ifndef __ZEPHYR__
4739 #ifdef CONFIG_CTRL_IFACE_UDP
4740 int port = HOSTAPD_CTRL_IFACE_PORT;
4741 char p[32] = { 0 };
4742 char port_str[40], *tmp;
4743 char *pos;
4744 struct addrinfo hints = { 0 }, *res, *saveres;
4745 int n;
4746
4747 if (hapd->ctrl_sock > -1) {
4748 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
4749 return 0;
4750 }
4751
4752 if (hapd->conf->ctrl_interface == NULL)
4753 return 0;
4754
4755 pos = os_strstr(hapd->conf->ctrl_interface, "udp:");
4756 if (pos) {
4757 pos += 4;
4758 port = atoi(pos);
4759 if (port <= 0) {
4760 wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port");
4761 goto fail;
4762 }
4763 }
4764
4765 dl_list_init(&hapd->ctrl_dst);
4766 hapd->ctrl_sock = -1;
4767 os_get_random(hapd->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN);
4768
4769 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
4770 hints.ai_flags = AI_PASSIVE;
4771 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
4772
4773 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
4774 hints.ai_family = AF_INET6;
4775 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
4776 hints.ai_family = AF_INET;
4777 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
4778 hints.ai_socktype = SOCK_DGRAM;
4779
4780 try_again:
4781 os_snprintf(p, sizeof(p), "%d", port);
4782 n = getaddrinfo(NULL, p, &hints, &res);
4783 if (n) {
4784 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
4785 goto fail;
4786 }
4787
4788 saveres = res;
4789 hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype,
4790 res->ai_protocol);
4791 if (hapd->ctrl_sock < 0) {
4792 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
4793 goto fail;
4794 }
4795
4796 if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) {
4797 port--;
4798 if ((HOSTAPD_CTRL_IFACE_PORT - port) <
4799 HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos)
4800 goto try_again;
4801 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
4802 goto fail;
4803 }
4804
4805 freeaddrinfo(saveres);
4806
4807 os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
4808 tmp = os_strdup(port_str);
4809 if (tmp) {
4810 os_free(hapd->conf->ctrl_interface);
4811 hapd->conf->ctrl_interface = tmp;
4812 }
4813 wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
4814
4815 if (eloop_register_read_sock(hapd->ctrl_sock,
4816 hostapd_ctrl_iface_receive, hapd, NULL) <
4817 0) {
4818 hostapd_ctrl_iface_deinit(hapd);
4819 return -1;
4820 }
4821
4822 hapd->msg_ctx = hapd;
4823 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
4824
4825 return 0;
4826
4827 fail:
4828 if (hapd->ctrl_sock >= 0)
4829 close(hapd->ctrl_sock);
4830 return -1;
4831 #else /* CONFIG_CTRL_IFACE_UDP */
4832 struct sockaddr_un addr;
4833 int s = -1;
4834 char *fname = NULL;
4835
4836 if (hapd->ctrl_sock > -1) {
4837 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
4838 return 0;
4839 }
4840
4841 dl_list_init(&hapd->ctrl_dst);
4842
4843 if (hapd->conf->ctrl_interface == NULL)
4844 return 0;
4845
4846 if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
4847 if (errno == EEXIST) {
4848 wpa_printf(MSG_DEBUG, "Using existing control "
4849 "interface directory.");
4850 } else {
4851 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
4852 strerror(errno));
4853 goto fail;
4854 }
4855 }
4856
4857 if (hapd->conf->ctrl_interface_gid_set &&
4858 lchown(hapd->conf->ctrl_interface, -1,
4859 hapd->conf->ctrl_interface_gid) < 0) {
4860 wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
4861 strerror(errno));
4862 return -1;
4863 }
4864
4865 if (!hapd->conf->ctrl_interface_gid_set &&
4866 hapd->iface->interfaces->ctrl_iface_group &&
4867 lchown(hapd->conf->ctrl_interface, -1,
4868 hapd->iface->interfaces->ctrl_iface_group) < 0) {
4869 wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
4870 strerror(errno));
4871 return -1;
4872 }
4873
4874 #ifdef ANDROID
4875 /*
4876 * Android is using umask 0077 which would leave the control interface
4877 * directory without group access. This breaks things since Wi-Fi
4878 * framework assumes that this directory can be accessed by other
4879 * applications in the wifi group. Fix this by adding group access even
4880 * if umask value would prevent this.
4881 */
4882 if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
4883 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
4884 strerror(errno));
4885 /* Try to continue anyway */
4886 }
4887 #endif /* ANDROID */
4888
4889 if (os_strlen(hapd->conf->ctrl_interface) + 1 +
4890 os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
4891 goto fail;
4892
4893 s = socket(PF_UNIX, SOCK_DGRAM, 0);
4894 if (s < 0) {
4895 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
4896 goto fail;
4897 }
4898
4899 os_memset(&addr, 0, sizeof(addr));
4900 #ifdef __FreeBSD__
4901 addr.sun_len = sizeof(addr);
4902 #endif /* __FreeBSD__ */
4903 addr.sun_family = AF_UNIX;
4904 fname = hostapd_ctrl_iface_path(hapd);
4905 if (fname == NULL)
4906 goto fail;
4907 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
4908 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
4909 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
4910 strerror(errno));
4911 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
4912 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
4913 " allow connections - assuming it was left"
4914 "over from forced program termination");
4915 if (unlink(fname) < 0) {
4916 wpa_printf(MSG_ERROR,
4917 "Could not unlink existing ctrl_iface socket '%s': %s",
4918 fname, strerror(errno));
4919 goto fail;
4920 }
4921 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
4922 0) {
4923 wpa_printf(MSG_ERROR,
4924 "hostapd-ctrl-iface: bind(PF_UNIX): %s",
4925 strerror(errno));
4926 goto fail;
4927 }
4928 wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
4929 "ctrl_iface socket '%s'", fname);
4930 } else {
4931 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
4932 "be in use - cannot override it");
4933 wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
4934 "not used anymore", fname);
4935 os_free(fname);
4936 fname = NULL;
4937 goto fail;
4938 }
4939 }
4940
4941 if (hapd->conf->ctrl_interface_gid_set &&
4942 lchown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
4943 wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s",
4944 strerror(errno));
4945 goto fail;
4946 }
4947
4948 if (!hapd->conf->ctrl_interface_gid_set &&
4949 hapd->iface->interfaces->ctrl_iface_group &&
4950 lchown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
4951 wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s",
4952 strerror(errno));
4953 goto fail;
4954 }
4955
4956 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
4957 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
4958 strerror(errno));
4959 goto fail;
4960 }
4961 os_free(fname);
4962
4963 hapd->ctrl_sock = s;
4964 if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
4965 NULL) < 0) {
4966 hostapd_ctrl_iface_deinit(hapd);
4967 return -1;
4968 }
4969 hapd->msg_ctx = hapd;
4970 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
4971
4972 return 0;
4973
4974 fail:
4975 if (s >= 0)
4976 close(s);
4977 if (fname) {
4978 unlink(fname);
4979 os_free(fname);
4980 }
4981 return -1;
4982 #endif /* CONFIG_CTRL_IFACE_UDP */
4983 #else
4984 return 0;
4985 #endif /* __ZEPHYR__ */
4986 }
4987
4988
hostapd_ctrl_iface_deinit(struct hostapd_data * hapd)4989 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
4990 {
4991 #ifndef __ZEPHYR__
4992 struct wpa_ctrl_dst *dst, *prev;
4993
4994 if (hapd->ctrl_sock > -1) {
4995 #ifndef CONFIG_CTRL_IFACE_UDP
4996 char *fname;
4997 #endif /* !CONFIG_CTRL_IFACE_UDP */
4998
4999 eloop_unregister_read_sock(hapd->ctrl_sock);
5000 close(hapd->ctrl_sock);
5001 hapd->ctrl_sock = -1;
5002 #ifndef CONFIG_CTRL_IFACE_UDP
5003 fname = hostapd_ctrl_iface_path(hapd);
5004 if (fname)
5005 unlink(fname);
5006 os_free(fname);
5007
5008 if (hapd->conf->ctrl_interface &&
5009 rmdir(hapd->conf->ctrl_interface) < 0) {
5010 if (errno == ENOTEMPTY) {
5011 wpa_printf(MSG_DEBUG, "Control interface "
5012 "directory not empty - leaving it "
5013 "behind");
5014 } else {
5015 wpa_printf(MSG_ERROR,
5016 "rmdir[ctrl_interface=%s]: %s",
5017 hapd->conf->ctrl_interface,
5018 strerror(errno));
5019 }
5020 }
5021 #endif /* !CONFIG_CTRL_IFACE_UDP */
5022 }
5023
5024 dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst,
5025 list)
5026 os_free(dst);
5027
5028 #ifdef CONFIG_TESTING_OPTIONS
5029 l2_packet_deinit(hapd->l2_test);
5030 hapd->l2_test = NULL;
5031 #endif /* CONFIG_TESTING_OPTIONS */
5032 #endif /* __ZEPHYR__ */
5033 }
5034
5035
5036 #ifndef __ZEPHYR__
hostapd_ctrl_iface_add(struct hapd_interfaces * interfaces,char * buf)5037 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
5038 char *buf)
5039 {
5040 if (hostapd_add_iface(interfaces, buf) < 0) {
5041 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
5042 return -1;
5043 }
5044 return 0;
5045 }
5046
5047
hostapd_ctrl_iface_remove(struct hapd_interfaces * interfaces,char * buf)5048 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
5049 char *buf)
5050 {
5051 if (hostapd_remove_iface(interfaces, buf) < 0) {
5052 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
5053 return -1;
5054 }
5055 return 0;
5056 }
5057
5058
hostapd_global_ctrl_iface_attach(struct hapd_interfaces * interfaces,struct sockaddr_storage * from,socklen_t fromlen,char * input)5059 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
5060 struct sockaddr_storage *from,
5061 socklen_t fromlen, char *input)
5062 {
5063 return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen,
5064 input);
5065 }
5066
5067
hostapd_global_ctrl_iface_detach(struct hapd_interfaces * interfaces,struct sockaddr_storage * from,socklen_t fromlen)5068 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
5069 struct sockaddr_storage *from,
5070 socklen_t fromlen)
5071 {
5072 return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen);
5073 }
5074
5075
hostapd_ctrl_iface_flush(struct hapd_interfaces * interfaces)5076 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
5077 {
5078 #ifdef CONFIG_WPS_TESTING
5079 wps_version_number = 0x20;
5080 wps_testing_stub_cred = 0;
5081 wps_corrupt_pkhash = 0;
5082 #endif /* CONFIG_WPS_TESTING */
5083
5084 #ifdef CONFIG_TESTING_OPTIONS
5085 #ifdef CONFIG_DPP
5086 dpp_test = DPP_TEST_DISABLED;
5087 #ifdef CONFIG_DPP3
5088 dpp_version_override = 3;
5089 #elif defined(CONFIG_DPP2)
5090 dpp_version_override = 2;
5091 #else /* CONFIG_DPP2 */
5092 dpp_version_override = 1;
5093 #endif /* CONFIG_DPP2 */
5094 #endif /* CONFIG_DPP */
5095 #endif /* CONFIG_TESTING_OPTIONS */
5096
5097 #ifdef CONFIG_DPP
5098 dpp_global_clear(interfaces->dpp);
5099 #ifdef CONFIG_DPP3
5100 interfaces->dpp_pb_bi = NULL;
5101 {
5102 int i;
5103
5104 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
5105 struct dpp_pb_info *info;
5106
5107 info = &interfaces->dpp_pb[i];
5108 info->rx_time.sec = 0;
5109 info->rx_time.usec = 0;
5110 }
5111 }
5112 #endif /* CONFIG_DPP3 */
5113 #endif /* CONFIG_DPP */
5114 }
5115 #endif /* __ZEPHYR__ */
5116
5117
5118 #ifdef CONFIG_FST
5119
5120 static int
hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces * interfaces,const char * cmd)5121 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
5122 const char *cmd)
5123 {
5124 char ifname[IFNAMSIZ + 1];
5125 struct fst_iface_cfg cfg;
5126 struct hostapd_data *hapd;
5127 struct fst_wpa_obj iface_obj;
5128
5129 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
5130 hapd = hostapd_get_iface(interfaces, ifname);
5131 if (hapd) {
5132 if (hapd->iface->fst) {
5133 wpa_printf(MSG_INFO, "FST: Already attached");
5134 return -1;
5135 }
5136 fst_hostapd_fill_iface_obj(hapd, &iface_obj);
5137 hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
5138 &iface_obj, &cfg);
5139 if (hapd->iface->fst)
5140 return 0;
5141 }
5142 }
5143
5144 return -EINVAL;
5145 }
5146
5147
5148 static int
hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces * interfaces,const char * cmd)5149 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
5150 const char *cmd)
5151 {
5152 char ifname[IFNAMSIZ + 1];
5153 struct hostapd_data * hapd;
5154
5155 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
5156 hapd = hostapd_get_iface(interfaces, ifname);
5157 if (hapd) {
5158 if (!fst_iface_detach(ifname)) {
5159 hapd->iface->fst = NULL;
5160 hapd->iface->fst_ies = NULL;
5161 return 0;
5162 }
5163 }
5164 }
5165
5166 return -EINVAL;
5167 }
5168
5169 #endif /* CONFIG_FST */
5170
5171
5172 #ifndef __ZEPHYR__
5173 static struct hostapd_data *
hostapd_interfaces_get_hapd(struct hapd_interfaces * interfaces,const char * ifname)5174 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
5175 const char *ifname)
5176 {
5177 size_t i, j;
5178
5179 for (i = 0; i < interfaces->count; i++) {
5180 struct hostapd_iface *iface = interfaces->iface[i];
5181
5182 for (j = 0; j < iface->num_bss; j++) {
5183 struct hostapd_data *hapd;
5184
5185 hapd = iface->bss[j];
5186 if (os_strcmp(ifname, hapd->conf->iface) == 0)
5187 return hapd;
5188 }
5189 }
5190
5191 return NULL;
5192 }
5193
5194
hostapd_ctrl_iface_dup_param(struct hostapd_data * src_hapd,struct hostapd_data * dst_hapd,const char * param)5195 static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
5196 struct hostapd_data *dst_hapd,
5197 const char *param)
5198 {
5199 int res;
5200 char *value;
5201
5202 value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
5203 if (!value) {
5204 wpa_printf(MSG_ERROR,
5205 "DUP: cannot allocate buffer to stringify %s",
5206 param);
5207 goto error_return;
5208 }
5209
5210 if (os_strcmp(param, "wpa") == 0) {
5211 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
5212 src_hapd->conf->wpa);
5213 } else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
5214 src_hapd->conf->wpa_key_mgmt) {
5215 res = hostapd_ctrl_iface_get_key_mgmt(
5216 src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
5217 if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
5218 goto error_stringify;
5219 } else if (os_strcmp(param, "wpa_pairwise") == 0 &&
5220 src_hapd->conf->wpa_pairwise) {
5221 res = wpa_write_ciphers(value,
5222 value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
5223 src_hapd->conf->wpa_pairwise, " ");
5224 if (res < 0)
5225 goto error_stringify;
5226 } else if (os_strcmp(param, "rsn_pairwise") == 0 &&
5227 src_hapd->conf->rsn_pairwise) {
5228 res = wpa_write_ciphers(value,
5229 value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
5230 src_hapd->conf->rsn_pairwise, " ");
5231 if (res < 0)
5232 goto error_stringify;
5233 } else if (os_strcmp(param, "wpa_passphrase") == 0 &&
5234 src_hapd->conf->ssid.wpa_passphrase) {
5235 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
5236 src_hapd->conf->ssid.wpa_passphrase);
5237 } else if (os_strcmp(param, "wpa_psk") == 0 &&
5238 src_hapd->conf->ssid.wpa_psk_set) {
5239 wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
5240 src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
5241 } else {
5242 wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
5243 goto error_return;
5244 }
5245
5246 res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
5247 os_free(value);
5248 return res;
5249
5250 error_stringify:
5251 wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
5252 error_return:
5253 os_free(value);
5254 return -1;
5255 }
5256
5257
5258 static int
hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces * interfaces,const char * input,char * reply,int reply_size)5259 hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces,
5260 const char *input,
5261 char *reply, int reply_size)
5262 {
5263 size_t i, j;
5264 int res;
5265 char *pos, *end;
5266 struct hostapd_iface *iface;
5267 int show_ctrl = 0;
5268
5269 if (input)
5270 show_ctrl = !!os_strstr(input, "ctrl");
5271
5272 pos = reply;
5273 end = reply + reply_size;
5274
5275 for (i = 0; i < interfaces->count; i++) {
5276 iface = interfaces->iface[i];
5277
5278 for (j = 0; j < iface->num_bss; j++) {
5279 struct hostapd_bss_config *conf;
5280
5281 conf = iface->conf->bss[j];
5282 if (show_ctrl)
5283 res = os_snprintf(pos, end - pos,
5284 "%s ctrl_iface=%s\n",
5285 conf->iface,
5286 conf->ctrl_interface ?
5287 conf->ctrl_interface : "N/A");
5288 else
5289 res = os_snprintf(pos, end - pos, "%s\n",
5290 conf->iface);
5291 if (os_snprintf_error(end - pos, res)) {
5292 *pos = '\0';
5293 return pos - reply;
5294 }
5295 pos += res;
5296 }
5297 }
5298
5299 return pos - reply;
5300 }
5301
5302
5303 static int
hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces * interfaces,char * cmd)5304 hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
5305 char *cmd)
5306 {
5307 char *p_start = cmd, *p_end;
5308 struct hostapd_data *src_hapd, *dst_hapd;
5309
5310 /* cmd: "<src ifname> <dst ifname> <variable name> */
5311
5312 p_end = os_strchr(p_start, ' ');
5313 if (!p_end) {
5314 wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
5315 cmd);
5316 return -1;
5317 }
5318
5319 *p_end = '\0';
5320 src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
5321 if (!src_hapd) {
5322 wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
5323 p_start);
5324 return -1;
5325 }
5326
5327 p_start = p_end + 1;
5328 p_end = os_strchr(p_start, ' ');
5329 if (!p_end) {
5330 wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
5331 cmd);
5332 return -1;
5333 }
5334
5335 *p_end = '\0';
5336 dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
5337 if (!dst_hapd) {
5338 wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
5339 p_start);
5340 return -1;
5341 }
5342
5343 p_start = p_end + 1;
5344 return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
5345 }
5346
5347
hostapd_global_ctrl_iface_ifname(struct hapd_interfaces * interfaces,const char * ifname,char * buf,char * reply,int reply_size,struct sockaddr_storage * from,socklen_t fromlen)5348 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
5349 const char *ifname,
5350 char *buf, char *reply,
5351 int reply_size,
5352 struct sockaddr_storage *from,
5353 socklen_t fromlen)
5354 {
5355 struct hostapd_data *hapd;
5356
5357 hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
5358 if (hapd == NULL) {
5359 int res;
5360
5361 res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
5362 if (os_snprintf_error(reply_size, res))
5363 return -1;
5364 return res;
5365 }
5366
5367 return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
5368 from, fromlen);
5369 }
5370
5371
hostapd_global_ctrl_iface_receive(int sock,void * eloop_ctx,void * sock_ctx)5372 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
5373 void *sock_ctx)
5374 {
5375 struct hapd_interfaces *interfaces = eloop_ctx;
5376 char buffer[256], *buf = buffer;
5377 int res;
5378 struct sockaddr_storage from;
5379 socklen_t fromlen = sizeof(from);
5380 char *reply;
5381 int reply_len;
5382 const int reply_size = 4096;
5383 #ifdef CONFIG_CTRL_IFACE_UDP
5384 unsigned char lcookie[CTRL_IFACE_COOKIE_LEN];
5385 #endif /* CONFIG_CTRL_IFACE_UDP */
5386
5387 res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
5388 (struct sockaddr *) &from, &fromlen);
5389 if (res < 0) {
5390 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
5391 strerror(errno));
5392 return;
5393 }
5394 buf[res] = '\0';
5395 wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
5396
5397 reply = os_malloc(reply_size);
5398 if (reply == NULL) {
5399 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
5400 fromlen) < 0) {
5401 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
5402 strerror(errno));
5403 }
5404 return;
5405 }
5406
5407 os_memcpy(reply, "OK\n", 3);
5408 reply_len = 3;
5409
5410 #ifdef CONFIG_CTRL_IFACE_UDP
5411 if (os_strcmp(buf, "GET_COOKIE") == 0) {
5412 os_memcpy(reply, "COOKIE=", 7);
5413 wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1,
5414 interfaces->ctrl_iface_cookie,
5415 CTRL_IFACE_COOKIE_LEN);
5416 reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN;
5417 goto send_reply;
5418 }
5419
5420 if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
5421 hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) {
5422 wpa_printf(MSG_DEBUG,
5423 "CTRL: No cookie in the request - drop request");
5424 os_free(reply);
5425 return;
5426 }
5427
5428 if (os_memcmp(interfaces->ctrl_iface_cookie, lcookie,
5429 CTRL_IFACE_COOKIE_LEN) != 0) {
5430 wpa_printf(MSG_DEBUG,
5431 "CTRL: Invalid cookie in the request - drop request");
5432 os_free(reply);
5433 return;
5434 }
5435
5436 buf += 7 + 2 * CTRL_IFACE_COOKIE_LEN;
5437 while (*buf == ' ')
5438 buf++;
5439 #endif /* CONFIG_CTRL_IFACE_UDP */
5440
5441 if (os_strncmp(buf, "IFNAME=", 7) == 0) {
5442 char *pos = os_strchr(buf + 7, ' ');
5443
5444 if (pos) {
5445 *pos++ = '\0';
5446 reply_len = hostapd_global_ctrl_iface_ifname(
5447 interfaces, buf + 7, pos, reply, reply_size,
5448 &from, fromlen);
5449 goto send_reply;
5450 }
5451 }
5452
5453 if (os_strcmp(buf, "PING") == 0) {
5454 os_memcpy(reply, "PONG\n", 5);
5455 reply_len = 5;
5456 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
5457 if (wpa_debug_reopen_file() < 0)
5458 reply_len = -1;
5459 } else if (os_strcmp(buf, "FLUSH") == 0) {
5460 hostapd_ctrl_iface_flush(interfaces);
5461 } else if (os_strncmp(buf, "ADD ", 4) == 0) {
5462 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
5463 reply_len = -1;
5464 } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
5465 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
5466 reply_len = -1;
5467 } else if (os_strcmp(buf, "ATTACH") == 0) {
5468 if (hostapd_global_ctrl_iface_attach(interfaces, &from,
5469 fromlen, NULL))
5470 reply_len = -1;
5471 } else if (os_strncmp(buf, "ATTACH ", 7) == 0) {
5472 if (hostapd_global_ctrl_iface_attach(interfaces, &from,
5473 fromlen, buf + 7))
5474 reply_len = -1;
5475 } else if (os_strcmp(buf, "DETACH") == 0) {
5476 if (hostapd_global_ctrl_iface_detach(interfaces, &from,
5477 fromlen))
5478 reply_len = -1;
5479 #ifdef CONFIG_MODULE_TESTS
5480 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
5481 if (hapd_module_tests() < 0)
5482 reply_len = -1;
5483 #endif /* CONFIG_MODULE_TESTS */
5484 #ifdef CONFIG_FST
5485 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
5486 if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
5487 reply_len = os_snprintf(reply, reply_size, "OK\n");
5488 else
5489 reply_len = -1;
5490 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
5491 if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
5492 reply_len = os_snprintf(reply, reply_size, "OK\n");
5493 else
5494 reply_len = -1;
5495 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
5496 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
5497 #endif /* CONFIG_FST */
5498 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
5499 if (!hostapd_global_ctrl_iface_dup_network(interfaces,
5500 buf + 12))
5501 reply_len = os_snprintf(reply, reply_size, "OK\n");
5502 else
5503 reply_len = -1;
5504 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
5505 reply_len = hostapd_global_ctrl_iface_interfaces(
5506 interfaces, buf + 10, reply, reply_size);
5507 } else if (os_strcmp(buf, "TERMINATE") == 0) {
5508 eloop_terminate();
5509 } else {
5510 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
5511 "ignored");
5512 reply_len = -1;
5513 }
5514
5515 send_reply:
5516 if (reply_len < 0) {
5517 os_memcpy(reply, "FAIL\n", 5);
5518 reply_len = 5;
5519 }
5520
5521 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
5522 fromlen) < 0) {
5523 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
5524 strerror(errno));
5525 }
5526 os_free(reply);
5527 }
5528
5529
5530 #ifndef CONFIG_CTRL_IFACE_UDP
hostapd_global_ctrl_iface_path(struct hapd_interfaces * interface)5531 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
5532 {
5533 char *buf;
5534 size_t len;
5535
5536 if (interface->global_iface_path == NULL)
5537 return NULL;
5538
5539 len = os_strlen(interface->global_iface_path) +
5540 os_strlen(interface->global_iface_name) + 2;
5541 buf = os_malloc(len);
5542 if (buf == NULL)
5543 return NULL;
5544
5545 os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
5546 interface->global_iface_name);
5547 buf[len - 1] = '\0';
5548 return buf;
5549 }
5550 #endif /* CONFIG_CTRL_IFACE_UDP */
5551
5552
hostapd_global_ctrl_iface_init(struct hapd_interfaces * interface)5553 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
5554 {
5555 #ifdef CONFIG_CTRL_IFACE_UDP
5556 int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT;
5557 char p[32] = { 0 };
5558 char *pos;
5559 struct addrinfo hints = { 0 }, *res, *saveres;
5560 int n;
5561
5562 if (interface->global_ctrl_sock > -1) {
5563 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
5564 return 0;
5565 }
5566
5567 if (interface->global_iface_path == NULL)
5568 return 0;
5569
5570 pos = os_strstr(interface->global_iface_path, "udp:");
5571 if (pos) {
5572 pos += 4;
5573 port = atoi(pos);
5574 if (port <= 0) {
5575 wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port");
5576 goto fail;
5577 }
5578 }
5579
5580 os_get_random(interface->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN);
5581
5582 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
5583 hints.ai_flags = AI_PASSIVE;
5584 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
5585
5586 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
5587 hints.ai_family = AF_INET6;
5588 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
5589 hints.ai_family = AF_INET;
5590 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
5591 hints.ai_socktype = SOCK_DGRAM;
5592
5593 try_again:
5594 os_snprintf(p, sizeof(p), "%d", port);
5595 n = getaddrinfo(NULL, p, &hints, &res);
5596 if (n) {
5597 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
5598 goto fail;
5599 }
5600
5601 saveres = res;
5602 interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype,
5603 res->ai_protocol);
5604 if (interface->global_ctrl_sock < 0) {
5605 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
5606 goto fail;
5607 }
5608
5609 if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) <
5610 0) {
5611 port++;
5612 if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) <
5613 HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
5614 goto try_again;
5615 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
5616 goto fail;
5617 }
5618
5619 freeaddrinfo(saveres);
5620
5621 wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port);
5622
5623 if (eloop_register_read_sock(interface->global_ctrl_sock,
5624 hostapd_global_ctrl_iface_receive,
5625 interface, NULL) < 0) {
5626 hostapd_global_ctrl_iface_deinit(interface);
5627 return -1;
5628 }
5629
5630 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
5631
5632 return 0;
5633
5634 fail:
5635 if (interface->global_ctrl_sock >= 0)
5636 close(interface->global_ctrl_sock);
5637 return -1;
5638 #else /* CONFIG_CTRL_IFACE_UDP */
5639 struct sockaddr_un addr;
5640 int s = -1;
5641 char *fname = NULL;
5642
5643 if (interface->global_iface_path == NULL) {
5644 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
5645 return 0;
5646 }
5647
5648 if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
5649 if (errno == EEXIST) {
5650 wpa_printf(MSG_DEBUG, "Using existing control "
5651 "interface directory.");
5652 } else {
5653 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
5654 strerror(errno));
5655 goto fail;
5656 }
5657 } else if (interface->ctrl_iface_group &&
5658 lchown(interface->global_iface_path, -1,
5659 interface->ctrl_iface_group) < 0) {
5660 wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
5661 strerror(errno));
5662 goto fail;
5663 }
5664
5665 if (os_strlen(interface->global_iface_path) + 1 +
5666 os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
5667 goto fail;
5668
5669 s = socket(PF_UNIX, SOCK_DGRAM, 0);
5670 if (s < 0) {
5671 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
5672 goto fail;
5673 }
5674
5675 os_memset(&addr, 0, sizeof(addr));
5676 #ifdef __FreeBSD__
5677 addr.sun_len = sizeof(addr);
5678 #endif /* __FreeBSD__ */
5679 addr.sun_family = AF_UNIX;
5680 fname = hostapd_global_ctrl_iface_path(interface);
5681 if (fname == NULL)
5682 goto fail;
5683 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
5684 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
5685 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
5686 strerror(errno));
5687 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
5688 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
5689 " allow connections - assuming it was left"
5690 "over from forced program termination");
5691 if (unlink(fname) < 0) {
5692 wpa_printf(MSG_ERROR,
5693 "Could not unlink existing ctrl_iface socket '%s': %s",
5694 fname, strerror(errno));
5695 goto fail;
5696 }
5697 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
5698 0) {
5699 wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
5700 strerror(errno));
5701 goto fail;
5702 }
5703 wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
5704 "ctrl_iface socket '%s'", fname);
5705 } else {
5706 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
5707 "be in use - cannot override it");
5708 wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
5709 "not used anymore", fname);
5710 os_free(fname);
5711 fname = NULL;
5712 goto fail;
5713 }
5714 }
5715
5716 if (interface->ctrl_iface_group &&
5717 lchown(fname, -1, interface->ctrl_iface_group) < 0) {
5718 wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s",
5719 strerror(errno));
5720 goto fail;
5721 }
5722
5723 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
5724 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
5725 strerror(errno));
5726 goto fail;
5727 }
5728 os_free(fname);
5729
5730 interface->global_ctrl_sock = s;
5731 eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
5732 interface, NULL);
5733
5734 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
5735
5736 return 0;
5737
5738 fail:
5739 if (s >= 0)
5740 close(s);
5741 if (fname) {
5742 unlink(fname);
5743 os_free(fname);
5744 }
5745 return -1;
5746 #endif /* CONFIG_CTRL_IFACE_UDP */
5747 }
5748
5749
hostapd_global_ctrl_iface_deinit(struct hapd_interfaces * interfaces)5750 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
5751 {
5752 #ifndef CONFIG_CTRL_IFACE_UDP
5753 char *fname = NULL;
5754 #endif /* CONFIG_CTRL_IFACE_UDP */
5755 struct wpa_ctrl_dst *dst, *prev;
5756
5757 if (interfaces->global_ctrl_sock > -1) {
5758 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
5759 close(interfaces->global_ctrl_sock);
5760 interfaces->global_ctrl_sock = -1;
5761 #ifndef CONFIG_CTRL_IFACE_UDP
5762 fname = hostapd_global_ctrl_iface_path(interfaces);
5763 if (fname) {
5764 unlink(fname);
5765 os_free(fname);
5766 }
5767
5768 if (interfaces->global_iface_path &&
5769 rmdir(interfaces->global_iface_path) < 0) {
5770 if (errno == ENOTEMPTY) {
5771 wpa_printf(MSG_DEBUG, "Control interface "
5772 "directory not empty - leaving it "
5773 "behind");
5774 } else {
5775 wpa_printf(MSG_ERROR,
5776 "rmdir[ctrl_interface=%s]: %s",
5777 interfaces->global_iface_path,
5778 strerror(errno));
5779 }
5780 }
5781 #endif /* CONFIG_CTRL_IFACE_UDP */
5782 }
5783
5784 os_free(interfaces->global_iface_path);
5785 interfaces->global_iface_path = NULL;
5786
5787 dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst,
5788 struct wpa_ctrl_dst, list)
5789 os_free(dst);
5790 }
5791
5792
hostapd_ctrl_check_event_enabled(struct wpa_ctrl_dst * dst,const char * buf)5793 static int hostapd_ctrl_check_event_enabled(struct wpa_ctrl_dst *dst,
5794 const char *buf)
5795 {
5796 /* Enable Probe Request events based on explicit request.
5797 * Other events are enabled by default.
5798 */
5799 if (str_starts(buf, RX_PROBE_REQUEST))
5800 return !!(dst->events & WPA_EVENT_RX_PROBE_REQUEST);
5801 return 1;
5802 }
5803
5804
hostapd_ctrl_iface_send_internal(int sock,struct dl_list * ctrl_dst,const char * ifname,int level,const char * buf,size_t len)5805 static void hostapd_ctrl_iface_send_internal(int sock, struct dl_list *ctrl_dst,
5806 const char *ifname, int level,
5807 const char *buf, size_t len)
5808 {
5809 struct wpa_ctrl_dst *dst, *next;
5810 struct msghdr msg;
5811 int idx, res;
5812 struct iovec io[5];
5813 char levelstr[10];
5814
5815 if (sock < 0 || dl_list_empty(ctrl_dst))
5816 return;
5817
5818 res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
5819 if (os_snprintf_error(sizeof(levelstr), res))
5820 return;
5821 idx = 0;
5822 if (ifname) {
5823 io[idx].iov_base = "IFNAME=";
5824 io[idx].iov_len = 7;
5825 idx++;
5826 io[idx].iov_base = (char *) ifname;
5827 io[idx].iov_len = os_strlen(ifname);
5828 idx++;
5829 io[idx].iov_base = " ";
5830 io[idx].iov_len = 1;
5831 idx++;
5832 }
5833 io[idx].iov_base = levelstr;
5834 io[idx].iov_len = os_strlen(levelstr);
5835 idx++;
5836 io[idx].iov_base = (char *) buf;
5837 io[idx].iov_len = len;
5838 idx++;
5839 os_memset(&msg, 0, sizeof(msg));
5840 msg.msg_iov = io;
5841 msg.msg_iovlen = idx;
5842
5843 idx = 0;
5844 dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
5845 if ((level >= dst->debug_level) &&
5846 hostapd_ctrl_check_event_enabled(dst, buf)) {
5847 sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send",
5848 &dst->addr, dst->addrlen);
5849 msg.msg_name = &dst->addr;
5850 msg.msg_namelen = dst->addrlen;
5851 if (sendmsg(sock, &msg, 0) < 0) {
5852 int _errno = errno;
5853 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
5854 "%d - %s",
5855 idx, errno, strerror(errno));
5856 dst->errors++;
5857 if (dst->errors > 10 || _errno == ENOENT) {
5858 ctrl_iface_detach(ctrl_dst,
5859 &dst->addr,
5860 dst->addrlen);
5861 }
5862 } else
5863 dst->errors = 0;
5864 }
5865 idx++;
5866 }
5867 }
5868
5869
hostapd_ctrl_iface_send(struct hostapd_data * hapd,int level,enum wpa_msg_type type,const char * buf,size_t len)5870 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
5871 enum wpa_msg_type type,
5872 const char *buf, size_t len)
5873 {
5874 if (type != WPA_MSG_NO_GLOBAL) {
5875 hostapd_ctrl_iface_send_internal(
5876 hapd->iface->interfaces->global_ctrl_sock,
5877 &hapd->iface->interfaces->global_ctrl_dst,
5878 type != WPA_MSG_PER_INTERFACE ?
5879 NULL : hapd->conf->iface,
5880 level, buf, len);
5881 }
5882
5883 if (type != WPA_MSG_ONLY_GLOBAL) {
5884 hostapd_ctrl_iface_send_internal(
5885 hapd->ctrl_sock, &hapd->ctrl_dst,
5886 NULL, level, buf, len);
5887 }
5888 }
5889 #endif /* __ZEPHYR__ */
5890 #endif /* CONFIG_NATIVE_WINDOWS */
5891