c0008fdfefd9465e876fe47cabde2ab772a436fa
[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         u8 mbo[10];
888         size_t mbo_len = 0;
889
890         if (hwaddr_aton(cmd, addr)) {
891                 wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
892                 return -1;
893         }
894
895         sta = ap_get_sta(hapd, addr);
896         if (sta == NULL) {
897                 wpa_printf(MSG_DEBUG, "Station " MACSTR
898                            " not found for BSS TM Request message",
899                            MAC2STR(addr));
900                 return -1;
901         }
902
903         pos = os_strstr(cmd, " disassoc_timer=");
904         if (pos) {
905                 pos += 16;
906                 disassoc_timer = atoi(pos);
907                 if (disassoc_timer < 0 || disassoc_timer > 65535) {
908                         wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
909                         return -1;
910                 }
911         }
912
913         pos = os_strstr(cmd, " valid_int=");
914         if (pos) {
915                 pos += 11;
916                 valid_int = atoi(pos);
917         }
918
919         pos = os_strstr(cmd, " bss_term=");
920         if (pos) {
921                 pos += 10;
922                 req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
923                 /* TODO: TSF configurable/learnable */
924                 bss_term_dur[0] = 4; /* Subelement ID */
925                 bss_term_dur[1] = 10; /* Length */
926                 os_memset(bss_term_dur, 2, 8);
927                 end = os_strchr(pos, ',');
928                 if (end == NULL) {
929                         wpa_printf(MSG_DEBUG, "Invalid bss_term data");
930                         return -1;
931                 }
932                 end++;
933                 WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
934         }
935
936
937         /*
938          * BSS Transition Candidate List Entries - Neighbor Report elements
939          * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
940          * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
941          */
942         pos = cmd;
943         while (pos) {
944                 u8 *nei_start;
945                 long int val;
946                 char *endptr, *tmp;
947
948                 pos = os_strstr(pos, " neighbor=");
949                 if (!pos)
950                         break;
951                 if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) {
952                         wpa_printf(MSG_DEBUG,
953                                    "Not enough room for additional neighbor");
954                         return -1;
955                 }
956                 pos += 10;
957
958                 nei_start = nei_pos;
959                 *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
960                 nei_pos++; /* length to be filled in */
961
962                 if (hwaddr_aton(pos, nei_pos)) {
963                         wpa_printf(MSG_DEBUG, "Invalid BSSID");
964                         return -1;
965                 }
966                 nei_pos += ETH_ALEN;
967                 pos += 17;
968                 if (*pos != ',') {
969                         wpa_printf(MSG_DEBUG, "Missing BSSID Information");
970                         return -1;
971                 }
972                 pos++;
973
974                 val = strtol(pos, &endptr, 0);
975                 WPA_PUT_LE32(nei_pos, val);
976                 nei_pos += 4;
977                 if (*endptr != ',') {
978                         wpa_printf(MSG_DEBUG, "Missing Operating Class");
979                         return -1;
980                 }
981                 pos = endptr + 1;
982
983                 *nei_pos++ = atoi(pos); /* Operating Class */
984                 pos = os_strchr(pos, ',');
985                 if (pos == NULL) {
986                         wpa_printf(MSG_DEBUG, "Missing Channel Number");
987                         return -1;
988                 }
989                 pos++;
990
991                 *nei_pos++ = atoi(pos); /* Channel Number */
992                 pos = os_strchr(pos, ',');
993                 if (pos == NULL) {
994                         wpa_printf(MSG_DEBUG, "Missing PHY Type");
995                         return -1;
996                 }
997                 pos++;
998
999                 *nei_pos++ = atoi(pos); /* PHY Type */
1000                 end = os_strchr(pos, ' ');
1001                 tmp = os_strchr(pos, ',');
1002                 if (tmp && (!end || tmp < end)) {
1003                         /* Optional Subelements (hexdump) */
1004                         size_t len;
1005
1006                         pos = tmp + 1;
1007                         end = os_strchr(pos, ' ');
1008                         if (end)
1009                                 len = end - pos;
1010                         else
1011                                 len = os_strlen(pos);
1012                         if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) {
1013                                 wpa_printf(MSG_DEBUG,
1014                                            "Not enough room for neighbor subelements");
1015                                 return -1;
1016                         }
1017                         if (len & 0x01 ||
1018                             hexstr2bin(pos, nei_pos, len / 2) < 0) {
1019                                 wpa_printf(MSG_DEBUG,
1020                                            "Invalid neighbor subelement info");
1021                                 return -1;
1022                         }
1023                         nei_pos += len / 2;
1024                         pos = end;
1025                 }
1026
1027                 nei_start[1] = nei_pos - nei_start - 2;
1028         }
1029
1030         pos = os_strstr(cmd, " url=");
1031         if (pos) {
1032                 size_t len;
1033                 pos += 5;
1034                 end = os_strchr(pos, ' ');
1035                 if (end)
1036                         len = end - pos;
1037                 else
1038                         len = os_strlen(pos);
1039                 url = os_malloc(len + 1);
1040                 if (url == NULL)
1041                         return -1;
1042                 os_memcpy(url, pos, len);
1043                 url[len] = '\0';
1044                 req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
1045         }
1046
1047         if (os_strstr(cmd, " pref=1"))
1048                 req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
1049         if (os_strstr(cmd, " abridged=1"))
1050                 req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
1051         if (os_strstr(cmd, " disassoc_imminent=1"))
1052                 req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
1053
1054 #ifdef CONFIG_MBO
1055         pos = os_strstr(cmd, "mbo=");
1056         if (pos) {
1057                 unsigned int mbo_reason, cell_pref, reassoc_delay;
1058                 u8 *mbo_pos = mbo;
1059
1060                 ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
1061                              &reassoc_delay, &cell_pref);
1062                 if (ret != 3) {
1063                         wpa_printf(MSG_DEBUG,
1064                                    "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
1065                         return -1;
1066                 }
1067
1068                 if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
1069                         wpa_printf(MSG_DEBUG,
1070                                    "Invalid MBO transition reason code %u",
1071                                    mbo_reason);
1072                         return -1;
1073                 }
1074
1075                 /* Valid values for Cellular preference are: 0, 1, 255 */
1076                 if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) {
1077                         wpa_printf(MSG_DEBUG,
1078                                    "Invalid MBO cellular capability %u",
1079                                    cell_pref);
1080                         return -1;
1081                 }
1082
1083                 if (reassoc_delay > 65535 ||
1084                     (reassoc_delay &&
1085                      !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) {
1086                         wpa_printf(MSG_DEBUG,
1087                                    "MBO: Assoc retry delay is only valid in disassoc imminent mode");
1088                         return -1;
1089                 }
1090
1091                 *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
1092                 *mbo_pos++ = 1;
1093                 *mbo_pos++ = mbo_reason;
1094                 *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
1095                 *mbo_pos++ = 1;
1096                 *mbo_pos++ = cell_pref;
1097
1098                 if (reassoc_delay) {
1099                         *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
1100                         *mbo_pos++ = 2;
1101                         WPA_PUT_LE16(mbo_pos, reassoc_delay);
1102                         mbo_pos += 2;
1103                 }
1104
1105                 mbo_len = mbo_pos - mbo;
1106         }
1107 #endif /* CONFIG_MBO */
1108
1109         ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
1110                                   valid_int, bss_term_dur, url,
1111                                   nei_pos > nei_rep ? nei_rep : NULL,
1112                                   nei_pos - nei_rep, mbo_len ? mbo : NULL,
1113                                   mbo_len);
1114         os_free(url);
1115         return ret;
1116 }
1117
1118 #endif /* CONFIG_WNM */
1119
1120
1121 static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd,
1122                                            char *buf, size_t buflen)
1123 {
1124         int ret = 0;
1125         char *pos, *end;
1126
1127         pos = buf;
1128         end = buf + buflen;
1129
1130         WPA_ASSERT(hapd->conf->wpa_key_mgmt);
1131
1132         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
1133                 ret = os_snprintf(pos, end - pos, "WPA-PSK ");
1134                 if (os_snprintf_error(end - pos, ret))
1135                         return pos - buf;
1136                 pos += ret;
1137         }
1138         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1139                 ret = os_snprintf(pos, end - pos, "WPA-EAP ");
1140                 if (os_snprintf_error(end - pos, ret))
1141                         return pos - buf;
1142                 pos += ret;
1143         }
1144 #ifdef CONFIG_IEEE80211R
1145         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1146                 ret = os_snprintf(pos, end - pos, "FT-PSK ");
1147                 if (os_snprintf_error(end - pos, ret))
1148                         return pos - buf;
1149                 pos += ret;
1150         }
1151         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1152                 ret = os_snprintf(pos, end - pos, "FT-EAP ");
1153                 if (os_snprintf_error(end - pos, ret))
1154                         return pos - buf;
1155                 pos += ret;
1156         }
1157 #ifdef CONFIG_SAE
1158         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
1159                 ret = os_snprintf(pos, end - pos, "FT-SAE ");
1160                 if (os_snprintf_error(end - pos, ret))
1161                         return pos - buf;
1162                 pos += ret;
1163         }
1164 #endif /* CONFIG_SAE */
1165 #endif /* CONFIG_IEEE80211R */
1166 #ifdef CONFIG_IEEE80211W
1167         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1168                 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
1169                 if (os_snprintf_error(end - pos, ret))
1170                         return pos - buf;
1171                 pos += ret;
1172         }
1173         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1174                 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
1175                 if (os_snprintf_error(end - pos, ret))
1176                         return pos - buf;
1177                 pos += ret;
1178         }
1179 #endif /* CONFIG_IEEE80211W */
1180 #ifdef CONFIG_SAE
1181         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
1182                 ret = os_snprintf(pos, end - pos, "SAE ");
1183                 if (os_snprintf_error(end - pos, ret))
1184                         return pos - buf;
1185                 pos += ret;
1186         }
1187 #endif /* CONFIG_SAE */
1188         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1189                 ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
1190                 if (os_snprintf_error(end - pos, ret))
1191                         return pos - buf;
1192                 pos += ret;
1193         }
1194         if (hapd->conf->wpa_key_mgmt &
1195             WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1196                 ret = os_snprintf(pos, end - pos,
1197                                   "WPA-EAP-SUITE-B-192 ");
1198                 if (os_snprintf_error(end - pos, ret))
1199                         return pos - buf;
1200                 pos += ret;
1201         }
1202
1203         if (pos > buf && *(pos - 1) == ' ') {
1204                 *(pos - 1) = '\0';
1205                 pos--;
1206         }
1207
1208         return pos - buf;
1209 }
1210
1211
1212 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
1213                                          char *buf, size_t buflen)
1214 {
1215         int ret;
1216         char *pos, *end;
1217
1218         pos = buf;
1219         end = buf + buflen;
1220
1221         ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
1222                           "ssid=%s\n",
1223                           MAC2STR(hapd->own_addr),
1224                           wpa_ssid_txt(hapd->conf->ssid.ssid,
1225                                        hapd->conf->ssid.ssid_len));
1226         if (os_snprintf_error(end - pos, ret))
1227                 return pos - buf;
1228         pos += ret;
1229
1230 #ifdef CONFIG_WPS
1231         ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
1232                           hapd->conf->wps_state == 0 ? "disabled" :
1233                           (hapd->conf->wps_state == 1 ? "not configured" :
1234                            "configured"));
1235         if (os_snprintf_error(end - pos, ret))
1236                 return pos - buf;
1237         pos += ret;
1238
1239         if (hapd->conf->wps_state && hapd->conf->wpa &&
1240             hapd->conf->ssid.wpa_passphrase) {
1241                 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
1242                                   hapd->conf->ssid.wpa_passphrase);
1243                 if (os_snprintf_error(end - pos, ret))
1244                         return pos - buf;
1245                 pos += ret;
1246         }
1247
1248         if (hapd->conf->wps_state && hapd->conf->wpa &&
1249             hapd->conf->ssid.wpa_psk &&
1250             hapd->conf->ssid.wpa_psk->group) {
1251                 char hex[PMK_LEN * 2 + 1];
1252                 wpa_snprintf_hex(hex, sizeof(hex),
1253                                  hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
1254                 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
1255                 if (os_snprintf_error(end - pos, ret))
1256                         return pos - buf;
1257                 pos += ret;
1258         }
1259 #endif /* CONFIG_WPS */
1260
1261         if (hapd->conf->wpa) {
1262                 ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa);
1263                 if (os_snprintf_error(end - pos, ret))
1264                         return pos - buf;
1265                 pos += ret;
1266         }
1267
1268         if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
1269                 ret = os_snprintf(pos, end - pos, "key_mgmt=");
1270                 if (os_snprintf_error(end - pos, ret))
1271                         return pos - buf;
1272                 pos += ret;
1273
1274                 pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos);
1275
1276                 ret = os_snprintf(pos, end - pos, "\n");
1277                 if (os_snprintf_error(end - pos, ret))
1278                         return pos - buf;
1279                 pos += ret;
1280         }
1281
1282         if (hapd->conf->wpa) {
1283                 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
1284                                   wpa_cipher_txt(hapd->conf->wpa_group));
1285                 if (os_snprintf_error(end - pos, ret))
1286                         return pos - buf;
1287                 pos += ret;
1288         }
1289
1290         if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
1291                 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
1292                 if (os_snprintf_error(end - pos, ret))
1293                         return pos - buf;
1294                 pos += ret;
1295
1296                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
1297                                         " ");
1298                 if (ret < 0)
1299                         return pos - buf;
1300                 pos += ret;
1301
1302                 ret = os_snprintf(pos, end - pos, "\n");
1303                 if (os_snprintf_error(end - pos, ret))
1304                         return pos - buf;
1305                 pos += ret;
1306         }
1307
1308         if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
1309                 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
1310                 if (os_snprintf_error(end - pos, ret))
1311                         return pos - buf;
1312                 pos += ret;
1313
1314                 ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
1315                                         " ");
1316                 if (ret < 0)
1317                         return pos - buf;
1318                 pos += ret;
1319
1320                 ret = os_snprintf(pos, end - pos, "\n");
1321                 if (os_snprintf_error(end - pos, ret))
1322                         return pos - buf;
1323                 pos += ret;
1324         }
1325
1326         return pos - buf;
1327 }
1328
1329
1330 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
1331 {
1332         char *value;
1333         int ret = 0;
1334
1335         value = os_strchr(cmd, ' ');
1336         if (value == NULL)
1337                 return -1;
1338         *value++ = '\0';
1339
1340         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
1341         if (0) {
1342 #ifdef CONFIG_WPS_TESTING
1343         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
1344                 long int val;
1345                 val = strtol(value, NULL, 0);
1346                 if (val < 0 || val > 0xff) {
1347                         ret = -1;
1348                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
1349                                    "wps_version_number %ld", val);
1350                 } else {
1351                         wps_version_number = val;
1352                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
1353                                    "version %u.%u",
1354                                    (wps_version_number & 0xf0) >> 4,
1355                                    wps_version_number & 0x0f);
1356                         hostapd_wps_update_ie(hapd);
1357                 }
1358         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
1359                 wps_testing_dummy_cred = atoi(value);
1360                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
1361                            wps_testing_dummy_cred);
1362         } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
1363                 wps_corrupt_pkhash = atoi(value);
1364                 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
1365                            wps_corrupt_pkhash);
1366 #endif /* CONFIG_WPS_TESTING */
1367 #ifdef CONFIG_INTERWORKING
1368         } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
1369                 int val = atoi(value);
1370                 if (val <= 0)
1371                         ret = -1;
1372                 else
1373                         hapd->gas_frag_limit = val;
1374 #endif /* CONFIG_INTERWORKING */
1375 #ifdef CONFIG_TESTING_OPTIONS
1376         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
1377                 hapd->ext_mgmt_frame_handling = atoi(value);
1378         } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
1379                 hapd->ext_eapol_frame_io = atoi(value);
1380 #endif /* CONFIG_TESTING_OPTIONS */
1381 #ifdef CONFIG_MBO
1382         } else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) {
1383                 int val;
1384
1385                 if (!hapd->conf->mbo_enabled)
1386                         return -1;
1387
1388                 val = atoi(value);
1389                 if (val < 0 || val > 1)
1390                         return -1;
1391
1392                 hapd->mbo_assoc_disallow = val;
1393                 ieee802_11_update_beacons(hapd->iface);
1394
1395                 /*
1396                  * TODO: Need to configure drivers that do AP MLME offload with
1397                  * disallowing station logic.
1398                  */
1399 #endif /* CONFIG_MBO */
1400         } else {
1401                 struct sta_info *sta;
1402                 struct vlan_description vlan_id;
1403
1404                 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
1405                 if (ret)
1406                         return ret;
1407
1408                 if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
1409                         for (sta = hapd->sta_list; sta; sta = sta->next) {
1410                                 if (hostapd_maclist_found(
1411                                             hapd->conf->deny_mac,
1412                                             hapd->conf->num_deny_mac, sta->addr,
1413                                             &vlan_id) &&
1414                                     (!vlan_id.notempty ||
1415                                      !vlan_compare(&vlan_id, sta->vlan_desc)))
1416                                         ap_sta_disconnect(
1417                                                 hapd, sta, sta->addr,
1418                                                 WLAN_REASON_UNSPECIFIED);
1419                         }
1420                 } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
1421                            os_strcasecmp(cmd, "accept_mac_file") == 0) {
1422                         for (sta = hapd->sta_list; sta; sta = sta->next) {
1423                                 if (!hostapd_maclist_found(
1424                                             hapd->conf->accept_mac,
1425                                             hapd->conf->num_accept_mac,
1426                                             sta->addr, &vlan_id) ||
1427                                     (vlan_id.notempty &&
1428                                      vlan_compare(&vlan_id, sta->vlan_desc)))
1429                                         ap_sta_disconnect(
1430                                                 hapd, sta, sta->addr,
1431                                                 WLAN_REASON_UNSPECIFIED);
1432                         }
1433                 }
1434         }
1435
1436         return ret;
1437 }
1438
1439
1440 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
1441                                   char *buf, size_t buflen)
1442 {
1443         int res;
1444
1445         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
1446
1447         if (os_strcmp(cmd, "version") == 0) {
1448                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
1449                 if (os_snprintf_error(buflen, res))
1450                         return -1;
1451                 return res;
1452         } else if (os_strcmp(cmd, "tls_library") == 0) {
1453                 res = tls_get_library_version(buf, buflen);
1454                 if (os_snprintf_error(buflen, res))
1455                         return -1;
1456                 return res;
1457         }
1458
1459         return -1;
1460 }
1461
1462
1463 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
1464 {
1465         if (hostapd_enable_iface(iface) < 0) {
1466                 wpa_printf(MSG_ERROR, "Enabling of interface failed");
1467                 return -1;
1468         }
1469         return 0;
1470 }
1471
1472
1473 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
1474 {
1475         if (hostapd_reload_iface(iface) < 0) {
1476                 wpa_printf(MSG_ERROR, "Reloading of interface failed");
1477                 return -1;
1478         }
1479         return 0;
1480 }
1481
1482
1483 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
1484 {
1485         if (hostapd_disable_iface(iface) < 0) {
1486                 wpa_printf(MSG_ERROR, "Disabling of interface failed");
1487                 return -1;
1488         }
1489         return 0;
1490 }
1491
1492
1493 #ifdef CONFIG_TESTING_OPTIONS
1494
1495 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
1496 {
1497         union wpa_event_data data;
1498         char *pos, *param;
1499         enum wpa_event_type event;
1500
1501         wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1502
1503         os_memset(&data, 0, sizeof(data));
1504
1505         param = os_strchr(cmd, ' ');
1506         if (param == NULL)
1507                 return -1;
1508         *param++ = '\0';
1509
1510         if (os_strcmp(cmd, "DETECTED") == 0)
1511                 event = EVENT_DFS_RADAR_DETECTED;
1512         else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1513                 event = EVENT_DFS_CAC_FINISHED;
1514         else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1515                 event = EVENT_DFS_CAC_ABORTED;
1516         else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1517                 event = EVENT_DFS_NOP_FINISHED;
1518         else {
1519                 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1520                            cmd);
1521                 return -1;
1522         }
1523
1524         pos = os_strstr(param, "freq=");
1525         if (pos)
1526                 data.dfs_event.freq = atoi(pos + 5);
1527
1528         pos = os_strstr(param, "ht_enabled=1");
1529         if (pos)
1530                 data.dfs_event.ht_enabled = 1;
1531
1532         pos = os_strstr(param, "chan_offset=");
1533         if (pos)
1534                 data.dfs_event.chan_offset = atoi(pos + 12);
1535
1536         pos = os_strstr(param, "chan_width=");
1537         if (pos)
1538                 data.dfs_event.chan_width = atoi(pos + 11);
1539
1540         pos = os_strstr(param, "cf1=");
1541         if (pos)
1542                 data.dfs_event.cf1 = atoi(pos + 4);
1543
1544         pos = os_strstr(param, "cf2=");
1545         if (pos)
1546                 data.dfs_event.cf2 = atoi(pos + 4);
1547
1548         wpa_supplicant_event(hapd, event, &data);
1549
1550         return 0;
1551 }
1552
1553
1554 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
1555 {
1556         size_t len;
1557         u8 *buf;
1558         int res;
1559
1560         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
1561
1562         len = os_strlen(cmd);
1563         if (len & 1)
1564                 return -1;
1565         len /= 2;
1566
1567         buf = os_malloc(len);
1568         if (buf == NULL)
1569                 return -1;
1570
1571         if (hexstr2bin(cmd, buf, len) < 0) {
1572                 os_free(buf);
1573                 return -1;
1574         }
1575
1576         res = hostapd_drv_send_mlme(hapd, buf, len, 0);
1577         os_free(buf);
1578         return res;
1579 }
1580
1581
1582 static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
1583 {
1584         char *pos;
1585         u8 src[ETH_ALEN], *buf;
1586         int used;
1587         size_t len;
1588
1589         wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
1590
1591         pos = cmd;
1592         used = hwaddr_aton2(pos, src);
1593         if (used < 0)
1594                 return -1;
1595         pos += used;
1596         while (*pos == ' ')
1597                 pos++;
1598
1599         len = os_strlen(pos);
1600         if (len & 1)
1601                 return -1;
1602         len /= 2;
1603
1604         buf = os_malloc(len);
1605         if (buf == NULL)
1606                 return -1;
1607
1608         if (hexstr2bin(pos, buf, len) < 0) {
1609                 os_free(buf);
1610                 return -1;
1611         }
1612
1613         ieee802_1x_receive(hapd, src, buf, len);
1614         os_free(buf);
1615
1616         return 0;
1617 }
1618
1619
1620 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
1621 {
1622         size_t i;
1623         u32 sum = 0;
1624         const u16 *pos = buf;
1625
1626         for (i = 0; i < len / 2; i++)
1627                 sum += *pos++;
1628
1629         while (sum >> 16)
1630                 sum = (sum & 0xffff) + (sum >> 16);
1631
1632         return sum ^ 0xffff;
1633 }
1634
1635
1636 #define HWSIM_PACKETLEN 1500
1637 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
1638
1639 void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
1640                           size_t len)
1641 {
1642         struct hostapd_data *hapd = ctx;
1643         const struct ether_header *eth;
1644         struct iphdr ip;
1645         const u8 *pos;
1646         unsigned int i;
1647
1648         if (len != HWSIM_PACKETLEN)
1649                 return;
1650
1651         eth = (const struct ether_header *) buf;
1652         os_memcpy(&ip, eth + 1, sizeof(ip));
1653         pos = &buf[sizeof(*eth) + sizeof(ip)];
1654
1655         if (ip.ihl != 5 || ip.version != 4 ||
1656             ntohs(ip.tot_len) != HWSIM_IP_LEN)
1657                 return;
1658
1659         for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
1660                 if (*pos != (u8) i)
1661                         return;
1662                 pos++;
1663         }
1664
1665         wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
1666                 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
1667 }
1668
1669
1670 static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
1671                                                char *cmd)
1672 {
1673         int enabled = atoi(cmd);
1674         char *pos;
1675         const char *ifname;
1676
1677         if (!enabled) {
1678                 if (hapd->l2_test) {
1679                         l2_packet_deinit(hapd->l2_test);
1680                         hapd->l2_test = NULL;
1681                         wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
1682                                 "test data: Disabled");
1683                 }
1684                 return 0;
1685         }
1686
1687         if (hapd->l2_test)
1688                 return 0;
1689
1690         pos = os_strstr(cmd, " ifname=");
1691         if (pos)
1692                 ifname = pos + 8;
1693         else
1694                 ifname = hapd->conf->iface;
1695
1696         hapd->l2_test = l2_packet_init(ifname, hapd->own_addr,
1697                                         ETHERTYPE_IP, hostapd_data_test_rx,
1698                                         hapd, 1);
1699         if (hapd->l2_test == NULL)
1700                 return -1;
1701
1702         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
1703
1704         return 0;
1705 }
1706
1707
1708 static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
1709 {
1710         u8 dst[ETH_ALEN], src[ETH_ALEN];
1711         char *pos;
1712         int used;
1713         long int val;
1714         u8 tos;
1715         u8 buf[2 + HWSIM_PACKETLEN];
1716         struct ether_header *eth;
1717         struct iphdr *ip;
1718         u8 *dpos;
1719         unsigned int i;
1720
1721         if (hapd->l2_test == NULL)
1722                 return -1;
1723
1724         /* format: <dst> <src> <tos> */
1725
1726         pos = cmd;
1727         used = hwaddr_aton2(pos, dst);
1728         if (used < 0)
1729                 return -1;
1730         pos += used;
1731         while (*pos == ' ')
1732                 pos++;
1733         used = hwaddr_aton2(pos, src);
1734         if (used < 0)
1735                 return -1;
1736         pos += used;
1737
1738         val = strtol(pos, NULL, 0);
1739         if (val < 0 || val > 0xff)
1740                 return -1;
1741         tos = val;
1742
1743         eth = (struct ether_header *) &buf[2];
1744         os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
1745         os_memcpy(eth->ether_shost, src, ETH_ALEN);
1746         eth->ether_type = htons(ETHERTYPE_IP);
1747         ip = (struct iphdr *) (eth + 1);
1748         os_memset(ip, 0, sizeof(*ip));
1749         ip->ihl = 5;
1750         ip->version = 4;
1751         ip->ttl = 64;
1752         ip->tos = tos;
1753         ip->tot_len = htons(HWSIM_IP_LEN);
1754         ip->protocol = 1;
1755         ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
1756         ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
1757         ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
1758         dpos = (u8 *) (ip + 1);
1759         for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
1760                 *dpos++ = i;
1761
1762         if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
1763                            HWSIM_PACKETLEN) < 0)
1764                 return -1;
1765
1766         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
1767                 " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
1768
1769         return 0;
1770 }
1771
1772
1773 static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
1774                                               char *cmd)
1775 {
1776         u8 *buf;
1777         struct ether_header *eth;
1778         struct l2_packet_data *l2 = NULL;
1779         size_t len;
1780         u16 ethertype;
1781         int res = -1;
1782         const char *ifname = hapd->conf->iface;
1783
1784         if (os_strncmp(cmd, "ifname=", 7) == 0) {
1785                 cmd += 7;
1786                 ifname = cmd;
1787                 cmd = os_strchr(cmd, ' ');
1788                 if (cmd == NULL)
1789                         return -1;
1790                 *cmd++ = '\0';
1791         }
1792
1793         len = os_strlen(cmd);
1794         if (len & 1 || len < ETH_HLEN * 2)
1795                 return -1;
1796         len /= 2;
1797
1798         buf = os_malloc(len);
1799         if (buf == NULL)
1800                 return -1;
1801
1802         if (hexstr2bin(cmd, buf, len) < 0)
1803                 goto done;
1804
1805         eth = (struct ether_header *) buf;
1806         ethertype = ntohs(eth->ether_type);
1807
1808         l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
1809                             hostapd_data_test_rx, hapd, 1);
1810         if (l2 == NULL)
1811                 goto done;
1812
1813         res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
1814         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
1815 done:
1816         if (l2)
1817                 l2_packet_deinit(l2);
1818         os_free(buf);
1819
1820         return res < 0 ? -1 : 0;
1821 }
1822
1823
1824 static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
1825 {
1826 #ifdef WPA_TRACE_BFD
1827         extern char wpa_trace_fail_func[256];
1828         extern unsigned int wpa_trace_fail_after;
1829         char *pos;
1830
1831         wpa_trace_fail_after = atoi(cmd);
1832         pos = os_strchr(cmd, ':');
1833         if (pos) {
1834                 pos++;
1835                 os_strlcpy(wpa_trace_fail_func, pos,
1836                            sizeof(wpa_trace_fail_func));
1837         } else {
1838                 wpa_trace_fail_after = 0;
1839         }
1840
1841         return 0;
1842 #else /* WPA_TRACE_BFD */
1843         return -1;
1844 #endif /* WPA_TRACE_BFD */
1845 }
1846
1847
1848 static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
1849                                        char *buf, size_t buflen)
1850 {
1851 #ifdef WPA_TRACE_BFD
1852         extern char wpa_trace_fail_func[256];
1853         extern unsigned int wpa_trace_fail_after;
1854
1855         return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
1856                            wpa_trace_fail_func);
1857 #else /* WPA_TRACE_BFD */
1858         return -1;
1859 #endif /* WPA_TRACE_BFD */
1860 }
1861
1862
1863 static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
1864 {
1865 #ifdef WPA_TRACE_BFD
1866         extern char wpa_trace_test_fail_func[256];
1867         extern unsigned int wpa_trace_test_fail_after;
1868         char *pos;
1869
1870         wpa_trace_test_fail_after = atoi(cmd);
1871         pos = os_strchr(cmd, ':');
1872         if (pos) {
1873                 pos++;
1874                 os_strlcpy(wpa_trace_test_fail_func, pos,
1875                            sizeof(wpa_trace_test_fail_func));
1876         } else {
1877                 wpa_trace_test_fail_after = 0;
1878         }
1879
1880         return 0;
1881 #else /* WPA_TRACE_BFD */
1882         return -1;
1883 #endif /* WPA_TRACE_BFD */
1884 }
1885
1886
1887 static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
1888                                  char *buf, size_t buflen)
1889 {
1890 #ifdef WPA_TRACE_BFD
1891         extern char wpa_trace_test_fail_func[256];
1892         extern unsigned int wpa_trace_test_fail_after;
1893
1894         return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
1895                            wpa_trace_test_fail_func);
1896 #else /* WPA_TRACE_BFD */
1897         return -1;
1898 #endif /* WPA_TRACE_BFD */
1899 }
1900
1901 #endif /* CONFIG_TESTING_OPTIONS */
1902
1903
1904 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
1905                                           char *pos)
1906 {
1907 #ifdef NEED_AP_MLME
1908         struct csa_settings settings;
1909         int ret;
1910         unsigned int i;
1911
1912         ret = hostapd_parse_csa_settings(pos, &settings);
1913         if (ret)
1914                 return ret;
1915
1916         for (i = 0; i < iface->num_bss; i++) {
1917                 ret = hostapd_switch_channel(iface->bss[i], &settings);
1918                 if (ret) {
1919                         /* FIX: What do we do if CSA fails in the middle of
1920                          * submitting multi-BSS CSA requests? */
1921                         return ret;
1922                 }
1923         }
1924
1925         return 0;
1926 #else /* NEED_AP_MLME */
1927         return -1;
1928 #endif /* NEED_AP_MLME */
1929 }
1930
1931
1932 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
1933                                   int reply_size, const char *param)
1934 {
1935 #ifdef RADIUS_SERVER
1936         if (os_strcmp(param, "radius_server") == 0) {
1937                 return radius_server_get_mib(hapd->radius_srv, reply,
1938                                              reply_size);
1939         }
1940 #endif /* RADIUS_SERVER */
1941         return -1;
1942 }
1943
1944
1945 static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
1946                                      char *buf, size_t buflen)
1947 {
1948         int ret;
1949         char *pos;
1950         u8 *data = NULL;
1951         unsigned int vendor_id, subcmd;
1952         struct wpabuf *reply;
1953         size_t data_len = 0;
1954
1955         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
1956         vendor_id = strtoul(cmd, &pos, 16);
1957         if (!isblank((unsigned char) *pos))
1958                 return -EINVAL;
1959
1960         subcmd = strtoul(pos, &pos, 10);
1961
1962         if (*pos != '\0') {
1963                 if (!isblank((unsigned char) *pos++))
1964                         return -EINVAL;
1965                 data_len = os_strlen(pos);
1966         }
1967
1968         if (data_len) {
1969                 data_len /= 2;
1970                 data = os_malloc(data_len);
1971                 if (!data)
1972                         return -ENOBUFS;
1973
1974                 if (hexstr2bin(pos, data, data_len)) {
1975                         wpa_printf(MSG_DEBUG,
1976                                    "Vendor command: wrong parameter format");
1977                         os_free(data);
1978                         return -EINVAL;
1979                 }
1980         }
1981
1982         reply = wpabuf_alloc((buflen - 1) / 2);
1983         if (!reply) {
1984                 os_free(data);
1985                 return -ENOBUFS;
1986         }
1987
1988         ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
1989                                      reply);
1990
1991         if (ret == 0)
1992                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
1993                                        wpabuf_len(reply));
1994
1995         wpabuf_free(reply);
1996         os_free(data);
1997
1998         return ret;
1999 }
2000
2001
2002 static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
2003                                            const char *cmd)
2004 {
2005         u8 addr[ETH_ALEN];
2006         struct sta_info *sta;
2007
2008         if (hwaddr_aton(cmd, addr))
2009                 return -1;
2010
2011         sta = ap_get_sta(hapd, addr);
2012         if (!sta || !sta->eapol_sm)
2013                 return -1;
2014
2015         eapol_auth_reauthenticate(sta->eapol_sm);
2016         return 0;
2017 }
2018
2019
2020 static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
2021 {
2022         u8 addr[ETH_ALEN];
2023         struct sta_info *sta;
2024         char *pos = cmd, *param;
2025
2026         if (hwaddr_aton(pos, addr) || pos[17] != ' ')
2027                 return -1;
2028         pos += 18;
2029         param = pos;
2030         pos = os_strchr(pos, ' ');
2031         if (!pos)
2032                 return -1;
2033         *pos++ = '\0';
2034
2035         sta = ap_get_sta(hapd, addr);
2036         if (!sta || !sta->eapol_sm)
2037                 return -1;
2038
2039         return eapol_auth_set_conf(sta->eapol_sm, param, pos);
2040 }
2041
2042
2043 static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd,
2044                                         char *buf, size_t buflen)
2045 {
2046         char *pos, *end, *stamp;
2047         int ret;
2048
2049         /* cmd: "LOG_LEVEL [<level>]" */
2050         if (*cmd == '\0') {
2051                 pos = buf;
2052                 end = buf + buflen;
2053                 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2054                                   "Timestamp: %d\n",
2055                                   debug_level_str(wpa_debug_level),
2056                                   wpa_debug_timestamp);
2057                 if (os_snprintf_error(end - pos, ret))
2058                         ret = 0;
2059
2060                 return ret;
2061         }
2062
2063         while (*cmd == ' ')
2064                 cmd++;
2065
2066         stamp = os_strchr(cmd, ' ');
2067         if (stamp) {
2068                 *stamp++ = '\0';
2069                 while (*stamp == ' ') {
2070                         stamp++;
2071                 }
2072         }
2073
2074         if (os_strlen(cmd)) {
2075                 int level = str_to_debug_level(cmd);
2076                 if (level < 0)
2077                         return -1;
2078                 wpa_debug_level = level;
2079         }
2080
2081         if (stamp && os_strlen(stamp))
2082                 wpa_debug_timestamp = atoi(stamp);
2083
2084         os_memcpy(buf, "OK\n", 3);
2085         return 3;
2086 }
2087
2088
2089 #ifdef NEED_AP_MLME
2090 static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
2091                                              char *buf, size_t buflen)
2092 {
2093         struct hostapd_iface *iface = hapd->iface;
2094         char *pos, *end;
2095         struct hostapd_sta_info *info;
2096         struct os_reltime now;
2097
2098         sta_track_expire(iface, 0);
2099
2100         pos = buf;
2101         end = buf + buflen;
2102
2103         os_get_reltime(&now);
2104         dl_list_for_each_reverse(info, &iface->sta_seen,
2105                                  struct hostapd_sta_info, list) {
2106                 struct os_reltime age;
2107                 int ret;
2108
2109                 os_reltime_sub(&now, &info->last_seen, &age);
2110                 ret = os_snprintf(pos, end - pos, MACSTR " %u\n",
2111                                   MAC2STR(info->addr), (unsigned int) age.sec);
2112                 if (os_snprintf_error(end - pos, ret))
2113                         break;
2114                 pos += ret;
2115         }
2116
2117         return pos - buf;
2118 }
2119 #endif /* NEED_AP_MLME */
2120
2121
2122 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
2123                                               char *buf, char *reply,
2124                                               int reply_size,
2125                                               struct sockaddr_un *from,
2126                                               socklen_t fromlen)
2127 {
2128         int reply_len, res;
2129
2130         os_memcpy(reply, "OK\n", 3);
2131         reply_len = 3;
2132
2133         if (os_strcmp(buf, "PING") == 0) {
2134                 os_memcpy(reply, "PONG\n", 5);
2135                 reply_len = 5;
2136         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
2137                 if (wpa_debug_reopen_file() < 0)
2138                         reply_len = -1;
2139         } else if (os_strcmp(buf, "STATUS") == 0) {
2140                 reply_len = hostapd_ctrl_iface_status(hapd, reply,
2141                                                       reply_size);
2142         } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
2143                 reply_len = hostapd_drv_status(hapd, reply, reply_size);
2144         } else if (os_strcmp(buf, "MIB") == 0) {
2145                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
2146                 if (reply_len >= 0) {
2147                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
2148                                           reply_size - reply_len);
2149                         if (res < 0)
2150                                 reply_len = -1;
2151                         else
2152                                 reply_len += res;
2153                 }
2154                 if (reply_len >= 0) {
2155                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
2156                                                  reply_size - reply_len);
2157                         if (res < 0)
2158                                 reply_len = -1;
2159                         else
2160                                 reply_len += res;
2161                 }
2162 #ifndef CONFIG_NO_RADIUS
2163                 if (reply_len >= 0) {
2164                         res = radius_client_get_mib(hapd->radius,
2165                                                     reply + reply_len,
2166                                                     reply_size - reply_len);
2167                         if (res < 0)
2168                                 reply_len = -1;
2169                         else
2170                                 reply_len += res;
2171                 }
2172 #endif /* CONFIG_NO_RADIUS */
2173         } else if (os_strncmp(buf, "MIB ", 4) == 0) {
2174                 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
2175                                                    buf + 4);
2176         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
2177                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
2178                                                          reply_size);
2179         } else if (os_strncmp(buf, "STA ", 4) == 0) {
2180                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
2181                                                    reply_size);
2182         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
2183                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
2184                                                         reply_size);
2185         } else if (os_strcmp(buf, "ATTACH") == 0) {
2186                 if (hostapd_ctrl_iface_attach(hapd, from, fromlen))
2187                         reply_len = -1;
2188         } else if (os_strcmp(buf, "DETACH") == 0) {
2189                 if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
2190                         reply_len = -1;
2191         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
2192                 if (hostapd_ctrl_iface_level(hapd, from, fromlen,
2193                                                     buf + 6))
2194                         reply_len = -1;
2195         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
2196                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
2197                         reply_len = -1;
2198         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
2199                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
2200                         reply_len = -1;
2201         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
2202                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
2203                         reply_len = -1;
2204         } else if (os_strcmp(buf, "STOP_AP") == 0) {
2205                 if (hostapd_ctrl_iface_stop_ap(hapd))
2206                         reply_len = -1;
2207 #ifdef CONFIG_IEEE80211W
2208 #ifdef NEED_AP_MLME
2209         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
2210                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
2211                         reply_len = -1;
2212 #endif /* NEED_AP_MLME */
2213 #endif /* CONFIG_IEEE80211W */
2214 #ifdef CONFIG_WPS
2215         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
2216                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
2217                         reply_len = -1;
2218         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
2219                 reply_len = hostapd_ctrl_iface_wps_check_pin(
2220                         hapd, buf + 14, reply, reply_size);
2221         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
2222                 if (hostapd_wps_button_pushed(hapd, NULL))
2223                         reply_len = -1;
2224         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
2225                 if (hostapd_wps_cancel(hapd))
2226                         reply_len = -1;
2227         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
2228                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
2229                                                           reply, reply_size);
2230         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
2231                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
2232                         reply_len = -1;
2233         } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
2234                 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
2235                                                               reply_size);
2236 #ifdef CONFIG_WPS_NFC
2237         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
2238                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
2239                         reply_len = -1;
2240         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
2241                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
2242                         hapd, buf + 21, reply, reply_size);
2243         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
2244                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
2245                         hapd, buf + 14, reply, reply_size);
2246         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
2247                 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
2248                         hapd, buf + 21, reply, reply_size);
2249         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
2250                 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
2251                         reply_len = -1;
2252 #endif /* CONFIG_WPS_NFC */
2253 #endif /* CONFIG_WPS */
2254 #ifdef CONFIG_INTERWORKING
2255         } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
2256                 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
2257                         reply_len = -1;
2258         } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
2259                 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
2260                         reply_len = -1;
2261 #endif /* CONFIG_INTERWORKING */
2262 #ifdef CONFIG_HS20
2263         } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
2264                 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
2265                         reply_len = -1;
2266         } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
2267                 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
2268                         reply_len = -1;
2269 #endif /* CONFIG_HS20 */
2270 #ifdef CONFIG_WNM
2271         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
2272                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
2273                         reply_len = -1;
2274         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
2275                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
2276                         reply_len = -1;
2277         } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
2278                 if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
2279                         reply_len = -1;
2280 #endif /* CONFIG_WNM */
2281         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
2282                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
2283                                                           reply_size);
2284         } else if (os_strncmp(buf, "SET ", 4) == 0) {
2285                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
2286                         reply_len = -1;
2287         } else if (os_strncmp(buf, "GET ", 4) == 0) {
2288                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
2289                                                    reply_size);
2290         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
2291                 if (hostapd_ctrl_iface_enable(hapd->iface))
2292                         reply_len = -1;
2293         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
2294                 if (hostapd_ctrl_iface_reload(hapd->iface))
2295                         reply_len = -1;
2296         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
2297                 if (hostapd_ctrl_iface_disable(hapd->iface))
2298                         reply_len = -1;
2299         } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
2300                 if (ieee802_11_set_beacon(hapd))
2301                         reply_len = -1;
2302 #ifdef CONFIG_TESTING_OPTIONS
2303         } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
2304                 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
2305                         reply_len = -1;
2306         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
2307                 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
2308                         reply_len = -1;
2309         } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
2310                 if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
2311                         reply_len = -1;
2312         } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
2313                 if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
2314                         reply_len = -1;
2315         } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
2316                 if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
2317                         reply_len = -1;
2318         } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
2319                 if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
2320                         reply_len = -1;
2321         } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
2322                 if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
2323                         reply_len = -1;
2324         } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
2325                 reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
2326                                                         reply_size);
2327         } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
2328                 if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
2329                         reply_len = -1;
2330         } else if (os_strcmp(buf, "GET_FAIL") == 0) {
2331                 reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
2332 #endif /* CONFIG_TESTING_OPTIONS */
2333         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
2334                 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
2335                         reply_len = -1;
2336         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
2337                 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
2338                                                       reply_size);
2339         } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
2340                 ieee802_1x_erp_flush(hapd);
2341 #ifdef RADIUS_SERVER
2342                 radius_server_erp_flush(hapd->radius_srv);
2343 #endif /* RADIUS_SERVER */
2344         } else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
2345                 if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
2346                         reply_len = -1;
2347         } else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
2348                 if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
2349                         reply_len = -1;
2350         } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
2351                 reply_len = hostapd_ctrl_iface_log_level(
2352                         hapd, buf + 9, reply, reply_size);
2353 #ifdef NEED_AP_MLME
2354         } else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
2355                 reply_len = hostapd_ctrl_iface_track_sta_list(
2356                         hapd, reply, reply_size);
2357 #endif /* NEED_AP_MLME */
2358         } else {
2359                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
2360                 reply_len = 16;
2361         }
2362
2363         if (reply_len < 0) {
2364                 os_memcpy(reply, "FAIL\n", 5);
2365                 reply_len = 5;
2366         }
2367
2368         return reply_len;
2369 }
2370
2371
2372 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
2373                                        void *sock_ctx)
2374 {
2375         struct hostapd_data *hapd = eloop_ctx;
2376         char buf[4096];
2377         int res;
2378         struct sockaddr_un from;
2379         socklen_t fromlen = sizeof(from);
2380         char *reply;
2381         const int reply_size = 4096;
2382         int reply_len;
2383         int level = MSG_DEBUG;
2384
2385         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
2386                        (struct sockaddr *) &from, &fromlen);
2387         if (res < 0) {
2388                 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
2389                            strerror(errno));
2390                 return;
2391         }
2392         buf[res] = '\0';
2393         if (os_strcmp(buf, "PING") == 0)
2394                 level = MSG_EXCESSIVE;
2395         wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
2396
2397         reply = os_malloc(reply_size);
2398         if (reply == NULL) {
2399                 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
2400                            fromlen) < 0) {
2401                         wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2402                                    strerror(errno));
2403                 }
2404                 return;
2405         }
2406
2407         reply_len = hostapd_ctrl_iface_receive_process(hapd, buf,
2408                                                        reply, reply_size,
2409                                                        &from, fromlen);
2410
2411         if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
2412                    fromlen) < 0) {
2413                 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2414                            strerror(errno));
2415         }
2416         os_free(reply);
2417 }
2418
2419
2420 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
2421 {
2422         char *buf;
2423         size_t len;
2424
2425         if (hapd->conf->ctrl_interface == NULL)
2426                 return NULL;
2427
2428         len = os_strlen(hapd->conf->ctrl_interface) +
2429                 os_strlen(hapd->conf->iface) + 2;
2430         buf = os_malloc(len);
2431         if (buf == NULL)
2432                 return NULL;
2433
2434         os_snprintf(buf, len, "%s/%s",
2435                     hapd->conf->ctrl_interface, hapd->conf->iface);
2436         buf[len - 1] = '\0';
2437         return buf;
2438 }
2439
2440
2441 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
2442                                       enum wpa_msg_type type,
2443                                       const char *txt, size_t len)
2444 {
2445         struct hostapd_data *hapd = ctx;
2446         if (hapd == NULL)
2447                 return;
2448         hostapd_ctrl_iface_send(hapd, level, type, txt, len);
2449 }
2450
2451
2452 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
2453 {
2454         struct sockaddr_un addr;
2455         int s = -1;
2456         char *fname = NULL;
2457
2458         if (hapd->ctrl_sock > -1) {
2459                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
2460                 return 0;
2461         }
2462
2463         if (hapd->conf->ctrl_interface == NULL)
2464                 return 0;
2465
2466         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2467                 if (errno == EEXIST) {
2468                         wpa_printf(MSG_DEBUG, "Using existing control "
2469                                    "interface directory.");
2470                 } else {
2471                         wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
2472                                    strerror(errno));
2473                         goto fail;
2474                 }
2475         }
2476
2477         if (hapd->conf->ctrl_interface_gid_set &&
2478             chown(hapd->conf->ctrl_interface, -1,
2479                   hapd->conf->ctrl_interface_gid) < 0) {
2480                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2481                            strerror(errno));
2482                 return -1;
2483         }
2484
2485         if (!hapd->conf->ctrl_interface_gid_set &&
2486             hapd->iface->interfaces->ctrl_iface_group &&
2487             chown(hapd->conf->ctrl_interface, -1,
2488                   hapd->iface->interfaces->ctrl_iface_group) < 0) {
2489                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2490                            strerror(errno));
2491                 return -1;
2492         }
2493
2494 #ifdef ANDROID
2495         /*
2496          * Android is using umask 0077 which would leave the control interface
2497          * directory without group access. This breaks things since Wi-Fi
2498          * framework assumes that this directory can be accessed by other
2499          * applications in the wifi group. Fix this by adding group access even
2500          * if umask value would prevent this.
2501          */
2502         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2503                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
2504                            strerror(errno));
2505                 /* Try to continue anyway */
2506         }
2507 #endif /* ANDROID */
2508
2509         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
2510             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
2511                 goto fail;
2512
2513         s = socket(PF_UNIX, SOCK_DGRAM, 0);
2514         if (s < 0) {
2515                 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
2516                 goto fail;
2517         }
2518
2519         os_memset(&addr, 0, sizeof(addr));
2520 #ifdef __FreeBSD__
2521         addr.sun_len = sizeof(addr);
2522 #endif /* __FreeBSD__ */
2523         addr.sun_family = AF_UNIX;
2524         fname = hostapd_ctrl_iface_path(hapd);
2525         if (fname == NULL)
2526                 goto fail;
2527         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
2528         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2529                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
2530                            strerror(errno));
2531                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2532                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
2533                                    " allow connections - assuming it was left"
2534                                    "over from forced program termination");
2535                         if (unlink(fname) < 0) {
2536                                 wpa_printf(MSG_ERROR,
2537                                            "Could not unlink existing ctrl_iface socket '%s': %s",
2538                                            fname, strerror(errno));
2539                                 goto fail;
2540                         }
2541                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
2542                             0) {
2543                                 wpa_printf(MSG_ERROR,
2544                                            "hostapd-ctrl-iface: bind(PF_UNIX): %s",
2545                                            strerror(errno));
2546                                 goto fail;
2547                         }
2548                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
2549                                    "ctrl_iface socket '%s'", fname);
2550                 } else {
2551                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
2552                                    "be in use - cannot override it");
2553                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
2554                                    "not used anymore", fname);
2555                         os_free(fname);
2556                         fname = NULL;
2557                         goto fail;
2558                 }
2559         }
2560
2561         if (hapd->conf->ctrl_interface_gid_set &&
2562             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
2563                 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
2564                            strerror(errno));
2565                 goto fail;
2566         }
2567
2568         if (!hapd->conf->ctrl_interface_gid_set &&
2569             hapd->iface->interfaces->ctrl_iface_group &&
2570             chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
2571                 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
2572                            strerror(errno));
2573                 goto fail;
2574         }
2575
2576         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
2577                 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
2578                            strerror(errno));
2579                 goto fail;
2580         }
2581         os_free(fname);
2582
2583         hapd->ctrl_sock = s;
2584         if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
2585                                      NULL) < 0) {
2586                 hostapd_ctrl_iface_deinit(hapd);
2587                 return -1;
2588         }
2589         hapd->msg_ctx = hapd;
2590         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
2591
2592         return 0;
2593
2594 fail:
2595         if (s >= 0)
2596                 close(s);
2597         if (fname) {
2598                 unlink(fname);
2599                 os_free(fname);
2600         }
2601         return -1;
2602 }
2603
2604
2605 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
2606 {
2607         struct wpa_ctrl_dst *dst, *prev;
2608
2609         if (hapd->ctrl_sock > -1) {
2610                 char *fname;
2611                 eloop_unregister_read_sock(hapd->ctrl_sock);
2612                 close(hapd->ctrl_sock);
2613                 hapd->ctrl_sock = -1;
2614                 fname = hostapd_ctrl_iface_path(hapd);
2615                 if (fname)
2616                         unlink(fname);
2617                 os_free(fname);
2618
2619                 if (hapd->conf->ctrl_interface &&
2620                     rmdir(hapd->conf->ctrl_interface) < 0) {
2621                         if (errno == ENOTEMPTY) {
2622                                 wpa_printf(MSG_DEBUG, "Control interface "
2623                                            "directory not empty - leaving it "
2624                                            "behind");
2625                         } else {
2626                                 wpa_printf(MSG_ERROR,
2627                                            "rmdir[ctrl_interface=%s]: %s",
2628                                            hapd->conf->ctrl_interface,
2629                                            strerror(errno));
2630                         }
2631                 }
2632         }
2633
2634         dst = hapd->ctrl_dst;
2635         hapd->ctrl_dst = NULL;
2636         while (dst) {
2637                 prev = dst;
2638                 dst = dst->next;
2639                 os_free(prev);
2640         }
2641
2642 #ifdef CONFIG_TESTING_OPTIONS
2643         l2_packet_deinit(hapd->l2_test);
2644         hapd->l2_test = NULL;
2645 #endif /* CONFIG_TESTING_OPTIONS */
2646 }
2647
2648
2649 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
2650                                   char *buf)
2651 {
2652         if (hostapd_add_iface(interfaces, buf) < 0) {
2653                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
2654                 return -1;
2655         }
2656         return 0;
2657 }
2658
2659
2660 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
2661                                      char *buf)
2662 {
2663         if (hostapd_remove_iface(interfaces, buf) < 0) {
2664                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
2665                 return -1;
2666         }
2667         return 0;
2668 }
2669
2670
2671 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
2672                                             struct sockaddr_un *from,
2673                                             socklen_t fromlen)
2674 {
2675         struct wpa_ctrl_dst *dst;
2676
2677         dst = os_zalloc(sizeof(*dst));
2678         if (dst == NULL)
2679                 return -1;
2680         os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
2681         dst->addrlen = fromlen;
2682         dst->debug_level = MSG_INFO;
2683         dst->next = interfaces->global_ctrl_dst;
2684         interfaces->global_ctrl_dst = dst;
2685         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached (global)",
2686                     from->sun_path,
2687                     fromlen - offsetof(struct sockaddr_un, sun_path));
2688         return 0;
2689 }
2690
2691
2692 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
2693                                             struct sockaddr_un *from,
2694                                             socklen_t fromlen)
2695 {
2696         struct wpa_ctrl_dst *dst, *prev = NULL;
2697
2698         dst = interfaces->global_ctrl_dst;
2699         while (dst) {
2700                 if (fromlen == dst->addrlen &&
2701                     os_memcmp(from->sun_path, dst->addr.sun_path,
2702                               fromlen - offsetof(struct sockaddr_un, sun_path))
2703                     == 0) {
2704                         wpa_hexdump(MSG_DEBUG,
2705                                     "CTRL_IFACE monitor detached (global)",
2706                                     from->sun_path,
2707                                     fromlen -
2708                                     offsetof(struct sockaddr_un, sun_path));
2709                         if (prev == NULL)
2710                                 interfaces->global_ctrl_dst = dst->next;
2711                         else
2712                                 prev->next = dst->next;
2713                         os_free(dst);
2714                         return 0;
2715                 }
2716                 prev = dst;
2717                 dst = dst->next;
2718         }
2719         return -1;
2720 }
2721
2722
2723 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
2724 {
2725 #ifdef CONFIG_WPS_TESTING
2726         wps_version_number = 0x20;
2727         wps_testing_dummy_cred = 0;
2728         wps_corrupt_pkhash = 0;
2729 #endif /* CONFIG_WPS_TESTING */
2730 }
2731
2732
2733 #ifdef CONFIG_FST
2734
2735 static int
2736 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
2737                                      const char *cmd)
2738 {
2739         char ifname[IFNAMSIZ + 1];
2740         struct fst_iface_cfg cfg;
2741         struct hostapd_data *hapd;
2742         struct fst_wpa_obj iface_obj;
2743
2744         if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
2745                 hapd = hostapd_get_iface(interfaces, ifname);
2746                 if (hapd) {
2747                         if (hapd->iface->fst) {
2748                                 wpa_printf(MSG_INFO, "FST: Already attached");
2749                                 return -1;
2750                         }
2751                         fst_hostapd_fill_iface_obj(hapd, &iface_obj);
2752                         hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
2753                                                       &iface_obj, &cfg);
2754                         if (hapd->iface->fst)
2755                                 return 0;
2756                 }
2757         }
2758
2759         return -EINVAL;
2760 }
2761
2762
2763 static int
2764 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
2765                                      const char *cmd)
2766 {
2767         char ifname[IFNAMSIZ + 1];
2768         struct hostapd_data * hapd;
2769
2770         if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
2771                 hapd = hostapd_get_iface(interfaces, ifname);
2772                 if (hapd) {
2773                         if (!fst_iface_detach(ifname)) {
2774                                 hapd->iface->fst = NULL;
2775                                 hapd->iface->fst_ies = NULL;
2776                                 return 0;
2777                         }
2778                 }
2779         }
2780
2781         return -EINVAL;
2782 }
2783
2784 #endif /* CONFIG_FST */
2785
2786
2787 static struct hostapd_data *
2788 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
2789                             const char *ifname)
2790 {
2791         size_t i, j;
2792
2793         for (i = 0; i < interfaces->count; i++) {
2794                 struct hostapd_iface *iface = interfaces->iface[i];
2795
2796                 for (j = 0; j < iface->num_bss; j++) {
2797                         struct hostapd_data *hapd;
2798
2799                         hapd = iface->bss[j];
2800                         if (os_strcmp(ifname, hapd->conf->iface) == 0)
2801                                 return hapd;
2802                 }
2803         }
2804
2805         return NULL;
2806 }
2807
2808
2809 static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
2810                                         struct hostapd_data *dst_hapd,
2811                                         const char *param)
2812 {
2813         int res;
2814         char *value;
2815
2816         value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
2817         if (!value) {
2818                 wpa_printf(MSG_ERROR,
2819                            "DUP: cannot allocate buffer to stringify %s",
2820                            param);
2821                 goto error_return;
2822         }
2823
2824         if (os_strcmp(param, "wpa") == 0) {
2825                 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
2826                             src_hapd->conf->wpa);
2827         } else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
2828                    src_hapd->conf->wpa_key_mgmt) {
2829                 res = hostapd_ctrl_iface_get_key_mgmt(
2830                         src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
2831                 if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
2832                         goto error_stringify;
2833         } else if (os_strcmp(param, "wpa_pairwise") == 0 &&
2834                    src_hapd->conf->wpa_pairwise) {
2835                 res = wpa_write_ciphers(value,
2836                                         value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2837                                         src_hapd->conf->wpa_pairwise, " ");
2838                 if (res < 0)
2839                         goto error_stringify;
2840         } else if (os_strcmp(param, "rsn_pairwise") == 0 &&
2841                    src_hapd->conf->rsn_pairwise) {
2842                 res = wpa_write_ciphers(value,
2843                                         value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2844                                         src_hapd->conf->rsn_pairwise, " ");
2845                 if (res < 0)
2846                         goto error_stringify;
2847         } else if (os_strcmp(param, "wpa_passphrase") == 0 &&
2848                    src_hapd->conf->ssid.wpa_passphrase) {
2849                 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
2850                             src_hapd->conf->ssid.wpa_passphrase);
2851         } else if (os_strcmp(param, "wpa_psk") == 0 &&
2852                    src_hapd->conf->ssid.wpa_psk_set) {
2853                 wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2854                         src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
2855         } else {
2856                 wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
2857                 goto error_return;
2858         }
2859
2860         res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
2861         os_free(value);
2862         return res;
2863
2864 error_stringify:
2865         wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
2866 error_return:
2867         os_free(value);
2868         return -1;
2869 }
2870
2871
2872 static int
2873 hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
2874                                       char *cmd)
2875 {
2876         char *p_start = cmd, *p_end;
2877         struct hostapd_data *src_hapd, *dst_hapd;
2878
2879         /* cmd: "<src ifname> <dst ifname> <variable name> */
2880
2881         p_end = os_strchr(p_start, ' ');
2882         if (!p_end) {
2883                 wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
2884                            cmd);
2885                 return -1;
2886         }
2887
2888         *p_end = '\0';
2889         src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
2890         if (!src_hapd) {
2891                 wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
2892                            p_start);
2893                 return -1;
2894         }
2895
2896         p_start = p_end + 1;
2897         p_end = os_strchr(p_start, ' ');
2898         if (!p_end) {
2899                 wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
2900                            cmd);
2901                 return -1;
2902         }
2903
2904         *p_end = '\0';
2905         dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
2906         if (!dst_hapd) {
2907                 wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
2908                            p_start);
2909                 return -1;
2910         }
2911
2912         p_start = p_end + 1;
2913         return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
2914 }
2915
2916
2917 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
2918                                             const char *ifname,
2919                                             char *buf, char *reply,
2920                                             int reply_size,
2921                                             struct sockaddr_un *from,
2922                                             socklen_t fromlen)
2923 {
2924         struct hostapd_data *hapd;
2925
2926         hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
2927         if (hapd == NULL) {
2928                 int res;
2929
2930                 res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
2931                 if (os_snprintf_error(reply_size, res))
2932                         return -1;
2933                 return res;
2934         }
2935
2936         return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
2937                                                   from, fromlen);
2938 }
2939
2940
2941 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
2942                                               void *sock_ctx)
2943 {
2944         void *interfaces = eloop_ctx;
2945         char buf[256];
2946         int res;
2947         struct sockaddr_un from;
2948         socklen_t fromlen = sizeof(from);
2949         char *reply;
2950         int reply_len;
2951         const int reply_size = 4096;
2952
2953         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
2954                        (struct sockaddr *) &from, &fromlen);
2955         if (res < 0) {
2956                 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
2957                            strerror(errno));
2958                 return;
2959         }
2960         buf[res] = '\0';
2961         wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
2962
2963         reply = os_malloc(reply_size);
2964         if (reply == NULL) {
2965                 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
2966                            fromlen) < 0) {
2967                         wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2968                                    strerror(errno));
2969                 }
2970                 return;
2971         }
2972
2973         os_memcpy(reply, "OK\n", 3);
2974         reply_len = 3;
2975
2976         if (os_strncmp(buf, "IFNAME=", 7) == 0) {
2977                 char *pos = os_strchr(buf + 7, ' ');
2978
2979                 if (pos) {
2980                         *pos++ = '\0';
2981                         reply_len = hostapd_global_ctrl_iface_ifname(
2982                                 interfaces, buf + 7, pos, reply, reply_size,
2983                                 &from, fromlen);
2984                         goto send_reply;
2985                 }
2986         }
2987
2988         if (os_strcmp(buf, "PING") == 0) {
2989                 os_memcpy(reply, "PONG\n", 5);
2990                 reply_len = 5;
2991         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
2992                 if (wpa_debug_reopen_file() < 0)
2993                         reply_len = -1;
2994         } else if (os_strcmp(buf, "FLUSH") == 0) {
2995                 hostapd_ctrl_iface_flush(interfaces);
2996         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
2997                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
2998                         reply_len = -1;
2999         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
3000                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
3001                         reply_len = -1;
3002         } else if (os_strcmp(buf, "ATTACH") == 0) {
3003                 if (hostapd_global_ctrl_iface_attach(interfaces, &from,
3004                                                      fromlen))
3005                         reply_len = -1;
3006         } else if (os_strcmp(buf, "DETACH") == 0) {
3007                 if (hostapd_global_ctrl_iface_detach(interfaces, &from,
3008                         fromlen))
3009                         reply_len = -1;
3010 #ifdef CONFIG_MODULE_TESTS
3011         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
3012                 int hapd_module_tests(void);
3013                 if (hapd_module_tests() < 0)
3014                         reply_len = -1;
3015 #endif /* CONFIG_MODULE_TESTS */
3016 #ifdef CONFIG_FST
3017         } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
3018                 if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
3019                         reply_len = os_snprintf(reply, reply_size, "OK\n");
3020                 else
3021                         reply_len = -1;
3022         } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
3023                 if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
3024                         reply_len = os_snprintf(reply, reply_size, "OK\n");
3025                 else
3026                         reply_len = -1;
3027         } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
3028                 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
3029 #endif /* CONFIG_FST */
3030         } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
3031                 if (!hostapd_global_ctrl_iface_dup_network(interfaces,
3032                                                            buf + 12))
3033                         reply_len = os_snprintf(reply, reply_size, "OK\n");
3034                 else
3035                         reply_len = -1;
3036         } else {
3037                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
3038                            "ignored");
3039                 reply_len = -1;
3040         }
3041
3042 send_reply:
3043         if (reply_len < 0) {
3044                 os_memcpy(reply, "FAIL\n", 5);
3045                 reply_len = 5;
3046         }
3047
3048         if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
3049                    fromlen) < 0) {
3050                 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
3051                            strerror(errno));
3052         }
3053         os_free(reply);
3054 }
3055
3056
3057 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
3058 {
3059         char *buf;
3060         size_t len;
3061
3062         if (interface->global_iface_path == NULL)
3063                 return NULL;
3064
3065         len = os_strlen(interface->global_iface_path) +
3066                 os_strlen(interface->global_iface_name) + 2;
3067         buf = os_malloc(len);
3068         if (buf == NULL)
3069                 return NULL;
3070
3071         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
3072                     interface->global_iface_name);
3073         buf[len - 1] = '\0';
3074         return buf;
3075 }
3076
3077
3078 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
3079 {
3080         struct sockaddr_un addr;
3081         int s = -1;
3082         char *fname = NULL;
3083
3084         if (interface->global_iface_path == NULL) {
3085                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
3086                 return 0;
3087         }
3088
3089         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
3090                 if (errno == EEXIST) {
3091                         wpa_printf(MSG_DEBUG, "Using existing control "
3092                                    "interface directory.");
3093                 } else {
3094                         wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
3095                                    strerror(errno));
3096                         goto fail;
3097                 }
3098         } else if (interface->ctrl_iface_group &&
3099                    chown(interface->global_iface_path, -1,
3100                          interface->ctrl_iface_group) < 0) {
3101                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
3102                            strerror(errno));
3103                 goto fail;
3104         }
3105
3106         if (os_strlen(interface->global_iface_path) + 1 +
3107             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
3108                 goto fail;
3109
3110         s = socket(PF_UNIX, SOCK_DGRAM, 0);
3111         if (s < 0) {
3112                 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
3113                 goto fail;
3114         }
3115
3116         os_memset(&addr, 0, sizeof(addr));
3117 #ifdef __FreeBSD__
3118         addr.sun_len = sizeof(addr);
3119 #endif /* __FreeBSD__ */
3120         addr.sun_family = AF_UNIX;
3121         fname = hostapd_global_ctrl_iface_path(interface);
3122         if (fname == NULL)
3123                 goto fail;
3124         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
3125         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3126                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
3127                            strerror(errno));
3128                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3129                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
3130                                    " allow connections - assuming it was left"
3131                                    "over from forced program termination");
3132                         if (unlink(fname) < 0) {
3133                                 wpa_printf(MSG_ERROR,
3134                                            "Could not unlink existing ctrl_iface socket '%s': %s",
3135                                            fname, strerror(errno));
3136                                 goto fail;
3137                         }
3138                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
3139                             0) {
3140                                 wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
3141                                            strerror(errno));
3142                                 goto fail;
3143                         }
3144                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
3145                                    "ctrl_iface socket '%s'", fname);
3146                 } else {
3147                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
3148                                    "be in use - cannot override it");
3149                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
3150                                    "not used anymore", fname);
3151                         os_free(fname);
3152                         fname = NULL;
3153                         goto fail;
3154                 }
3155         }
3156
3157         if (interface->ctrl_iface_group &&
3158             chown(fname, -1, interface->ctrl_iface_group) < 0) {
3159                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
3160                            strerror(errno));
3161                 goto fail;
3162         }
3163
3164         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
3165                 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
3166                            strerror(errno));
3167                 goto fail;
3168         }
3169         os_free(fname);
3170
3171         interface->global_ctrl_sock = s;
3172         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
3173                                  interface, NULL);
3174
3175         return 0;
3176
3177 fail:
3178         if (s >= 0)
3179                 close(s);
3180         if (fname) {
3181                 unlink(fname);
3182                 os_free(fname);
3183         }
3184         return -1;
3185 }
3186
3187
3188 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
3189 {
3190         char *fname = NULL;
3191         struct wpa_ctrl_dst *dst, *prev;
3192
3193         if (interfaces->global_ctrl_sock > -1) {
3194                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
3195                 close(interfaces->global_ctrl_sock);
3196                 interfaces->global_ctrl_sock = -1;
3197                 fname = hostapd_global_ctrl_iface_path(interfaces);
3198                 if (fname) {
3199                         unlink(fname);
3200                         os_free(fname);
3201                 }
3202
3203                 if (interfaces->global_iface_path &&
3204                     rmdir(interfaces->global_iface_path) < 0) {
3205                         if (errno == ENOTEMPTY) {
3206                                 wpa_printf(MSG_DEBUG, "Control interface "
3207                                            "directory not empty - leaving it "
3208                                            "behind");
3209                         } else {
3210                                 wpa_printf(MSG_ERROR,
3211                                            "rmdir[ctrl_interface=%s]: %s",
3212                                            interfaces->global_iface_path,
3213                                            strerror(errno));
3214                         }
3215                 }
3216         }
3217
3218         os_free(interfaces->global_iface_path);
3219         interfaces->global_iface_path = NULL;
3220
3221         dst = interfaces->global_ctrl_dst;
3222         interfaces->global_ctrl_dst = NULL;
3223         while (dst) {
3224                 prev = dst;
3225                 dst = dst->next;
3226                 os_free(prev);
3227         }
3228 }
3229
3230
3231 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
3232                                     enum wpa_msg_type type,
3233                                     const char *buf, size_t len)
3234 {
3235         struct wpa_ctrl_dst *dst, *next;
3236         struct msghdr msg;
3237         int idx;
3238         struct iovec io[2];
3239         char levelstr[10];
3240         int s;
3241
3242         if (type != WPA_MSG_ONLY_GLOBAL) {
3243                 s = hapd->ctrl_sock;
3244                 dst = hapd->ctrl_dst;
3245         } else {
3246                 s = hapd->iface->interfaces->global_ctrl_sock;
3247                 dst = hapd->iface->interfaces->global_ctrl_dst;
3248         }
3249
3250         if (s < 0 || dst == NULL)
3251                 return;
3252
3253         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
3254         io[0].iov_base = levelstr;
3255         io[0].iov_len = os_strlen(levelstr);
3256         io[1].iov_base = (char *) buf;
3257         io[1].iov_len = len;
3258         os_memset(&msg, 0, sizeof(msg));
3259         msg.msg_iov = io;
3260         msg.msg_iovlen = 2;
3261
3262         idx = 0;
3263         while (dst) {
3264                 next = dst->next;
3265                 if (level >= dst->debug_level) {
3266                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
3267                                     (u8 *) dst->addr.sun_path, dst->addrlen -
3268                                     offsetof(struct sockaddr_un, sun_path));
3269                         msg.msg_name = &dst->addr;
3270                         msg.msg_namelen = dst->addrlen;
3271                         if (sendmsg(s, &msg, 0) < 0) {
3272                                 int _errno = errno;
3273                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
3274                                            "%d - %s",
3275                                            idx, errno, strerror(errno));
3276                                 dst->errors++;
3277                                 if (dst->errors > 10 || _errno == ENOENT) {
3278                                         if (type != WPA_MSG_ONLY_GLOBAL)
3279                                                 hostapd_ctrl_iface_detach(
3280                                                         hapd, &dst->addr,
3281                                                         dst->addrlen);
3282                                         else
3283                                                 hostapd_global_ctrl_iface_detach(
3284                                                         hapd->iface->interfaces,
3285                                                         &dst->addr,
3286                                                         dst->addrlen);
3287                                 }
3288                         } else
3289                                 dst->errors = 0;
3290                 }
3291                 idx++;
3292                 dst = next;
3293         }
3294 }
3295
3296 #endif /* CONFIG_NATIVE_WINDOWS */