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