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