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