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