hostapd: Fix DETACH command debug prints to avoid use of freed memory
[mech_eap.git] / hostapd / ctrl_iface.c
1 /*
2  * hostapd / UNIX domain socket -based control interface
3  * Copyright (c) 2004-2013, 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 #include <sys/un.h>
14 #include <sys/stat.h>
15 #include <stddef.h>
16
17 #include "utils/common.h"
18 #include "utils/eloop.h"
19 #include "common/version.h"
20 #include "common/ieee802_11_defs.h"
21 #include "drivers/driver.h"
22 #include "radius/radius_client.h"
23 #include "ap/hostapd.h"
24 #include "ap/ap_config.h"
25 #include "ap/ieee802_1x.h"
26 #include "ap/wpa_auth.h"
27 #include "ap/ieee802_11.h"
28 #include "ap/sta_info.h"
29 #include "ap/wps_hostapd.h"
30 #include "ap/ctrl_iface_ap.h"
31 #include "ap/ap_drv_ops.h"
32 #include "ap/wpa_auth.h"
33 #include "wps/wps_defs.h"
34 #include "wps/wps.h"
35 #include "config_file.h"
36 #include "ctrl_iface.h"
37
38
39 struct wpa_ctrl_dst {
40         struct wpa_ctrl_dst *next;
41         struct sockaddr_un addr;
42         socklen_t addrlen;
43         int debug_level;
44         int errors;
45 };
46
47
48 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
49                                     const char *buf, size_t len);
50
51
52 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
53                                      struct sockaddr_un *from,
54                                      socklen_t fromlen)
55 {
56         struct wpa_ctrl_dst *dst;
57
58         dst = os_zalloc(sizeof(*dst));
59         if (dst == NULL)
60                 return -1;
61         os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
62         dst->addrlen = fromlen;
63         dst->debug_level = MSG_INFO;
64         dst->next = hapd->ctrl_dst;
65         hapd->ctrl_dst = dst;
66         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
67                     (u8 *) from->sun_path,
68                     fromlen - offsetof(struct sockaddr_un, sun_path));
69         return 0;
70 }
71
72
73 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
74                                      struct sockaddr_un *from,
75                                      socklen_t fromlen)
76 {
77         struct wpa_ctrl_dst *dst, *prev = NULL;
78
79         dst = hapd->ctrl_dst;
80         while (dst) {
81                 if (fromlen == dst->addrlen &&
82                     os_memcmp(from->sun_path, dst->addr.sun_path,
83                               fromlen - offsetof(struct sockaddr_un, sun_path))
84                     == 0) {
85                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
86                                     (u8 *) from->sun_path,
87                                     fromlen -
88                                     offsetof(struct sockaddr_un, sun_path));
89                         if (prev == NULL)
90                                 hapd->ctrl_dst = dst->next;
91                         else
92                                 prev->next = dst->next;
93                         os_free(dst);
94                         return 0;
95                 }
96                 prev = dst;
97                 dst = dst->next;
98         }
99         return -1;
100 }
101
102
103 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
104                                     struct sockaddr_un *from,
105                                     socklen_t fromlen,
106                                     char *level)
107 {
108         struct wpa_ctrl_dst *dst;
109
110         wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
111
112         dst = hapd->ctrl_dst;
113         while (dst) {
114                 if (fromlen == dst->addrlen &&
115                     os_memcmp(from->sun_path, dst->addr.sun_path,
116                               fromlen - offsetof(struct sockaddr_un, sun_path))
117                     == 0) {
118                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
119                                     "level", (u8 *) from->sun_path, fromlen -
120                                     offsetof(struct sockaddr_un, sun_path));
121                         dst->debug_level = atoi(level);
122                         return 0;
123                 }
124                 dst = dst->next;
125         }
126
127         return -1;
128 }
129
130
131 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
132                                       const char *txtaddr)
133 {
134         u8 addr[ETH_ALEN];
135         struct sta_info *sta;
136
137         wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
138
139         if (hwaddr_aton(txtaddr, addr))
140                 return -1;
141
142         sta = ap_get_sta(hapd, addr);
143         if (sta)
144                 return 0;
145
146         wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
147                    "notification", MAC2STR(addr));
148         sta = ap_sta_add(hapd, addr);
149         if (sta == NULL)
150                 return -1;
151
152         hostapd_new_assoc_sta(hapd, sta, 0);
153         return 0;
154 }
155
156
157 #ifdef CONFIG_IEEE80211W
158 #ifdef NEED_AP_MLME
159 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
160                                        const char *txtaddr)
161 {
162         u8 addr[ETH_ALEN];
163         u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
164
165         wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
166
167         if (hwaddr_aton(txtaddr, addr) ||
168             os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
169                 return -1;
170
171         ieee802_11_send_sa_query_req(hapd, addr, trans_id);
172
173         return 0;
174 }
175 #endif /* NEED_AP_MLME */
176 #endif /* CONFIG_IEEE80211W */
177
178
179 #ifdef CONFIG_WPS
180 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
181 {
182         char *pin = os_strchr(txt, ' ');
183         char *timeout_txt;
184         int timeout;
185         u8 addr_buf[ETH_ALEN], *addr = NULL;
186         char *pos;
187
188         if (pin == NULL)
189                 return -1;
190         *pin++ = '\0';
191
192         timeout_txt = os_strchr(pin, ' ');
193         if (timeout_txt) {
194                 *timeout_txt++ = '\0';
195                 timeout = atoi(timeout_txt);
196                 pos = os_strchr(timeout_txt, ' ');
197                 if (pos) {
198                         *pos++ = '\0';
199                         if (hwaddr_aton(pos, addr_buf) == 0)
200                                 addr = addr_buf;
201                 }
202         } else
203                 timeout = 0;
204
205         return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
206 }
207
208
209 static int hostapd_ctrl_iface_wps_check_pin(
210         struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
211 {
212         char pin[9];
213         size_t len;
214         char *pos;
215         int ret;
216
217         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
218                               (u8 *) cmd, os_strlen(cmd));
219         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
220                 if (*pos < '0' || *pos > '9')
221                         continue;
222                 pin[len++] = *pos;
223                 if (len == 9) {
224                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
225                         return -1;
226                 }
227         }
228         if (len != 4 && len != 8) {
229                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
230                 return -1;
231         }
232         pin[len] = '\0';
233
234         if (len == 8) {
235                 unsigned int pin_val;
236                 pin_val = atoi(pin);
237                 if (!wps_pin_valid(pin_val)) {
238                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
239                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
240                         if (ret < 0 || (size_t) ret >= buflen)
241                                 return -1;
242                         return ret;
243                 }
244         }
245
246         ret = os_snprintf(buf, buflen, "%s", pin);
247         if (ret < 0 || (size_t) ret >= buflen)
248                 return -1;
249
250         return ret;
251 }
252
253
254 #ifdef CONFIG_WPS_NFC
255 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
256                                                char *pos)
257 {
258         size_t len;
259         struct wpabuf *buf;
260         int ret;
261
262         len = os_strlen(pos);
263         if (len & 0x01)
264                 return -1;
265         len /= 2;
266
267         buf = wpabuf_alloc(len);
268         if (buf == NULL)
269                 return -1;
270         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
271                 wpabuf_free(buf);
272                 return -1;
273         }
274
275         ret = hostapd_wps_nfc_tag_read(hapd, buf);
276         wpabuf_free(buf);
277
278         return ret;
279 }
280
281
282 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
283                                                    char *cmd, char *reply,
284                                                    size_t max_len)
285 {
286         int ndef;
287         struct wpabuf *buf;
288         int res;
289
290         if (os_strcmp(cmd, "WPS") == 0)
291                 ndef = 0;
292         else if (os_strcmp(cmd, "NDEF") == 0)
293                 ndef = 1;
294         else
295                 return -1;
296
297         buf = hostapd_wps_nfc_config_token(hapd, ndef);
298         if (buf == NULL)
299                 return -1;
300
301         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
302                                          wpabuf_len(buf));
303         reply[res++] = '\n';
304         reply[res] = '\0';
305
306         wpabuf_free(buf);
307
308         return res;
309 }
310
311
312 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
313                                                 char *reply, size_t max_len,
314                                                 int ndef)
315 {
316         struct wpabuf *buf;
317         int res;
318
319         buf = hostapd_wps_nfc_token_gen(hapd, ndef);
320         if (buf == NULL)
321                 return -1;
322
323         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
324                                          wpabuf_len(buf));
325         reply[res++] = '\n';
326         reply[res] = '\0';
327
328         wpabuf_free(buf);
329
330         return res;
331 }
332
333
334 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
335                                             char *cmd, char *reply,
336                                             size_t max_len)
337 {
338         if (os_strcmp(cmd, "WPS") == 0)
339                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
340                                                             max_len, 0);
341
342         if (os_strcmp(cmd, "NDEF") == 0)
343                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
344                                                             max_len, 1);
345
346         if (os_strcmp(cmd, "enable") == 0)
347                 return hostapd_wps_nfc_token_enable(hapd);
348
349         if (os_strcmp(cmd, "disable") == 0) {
350                 hostapd_wps_nfc_token_disable(hapd);
351                 return 0;
352         }
353
354         return -1;
355 }
356
357
358 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
359                                                    char *cmd, char *reply,
360                                                    size_t max_len)
361 {
362         struct wpabuf *buf;
363         int res;
364         char *pos;
365         int ndef;
366
367         pos = os_strchr(cmd, ' ');
368         if (pos == NULL)
369                 return -1;
370         *pos++ = '\0';
371
372         if (os_strcmp(cmd, "WPS") == 0)
373                 ndef = 0;
374         else if (os_strcmp(cmd, "NDEF") == 0)
375                 ndef = 1;
376         else
377                 return -1;
378
379         if (os_strcmp(pos, "WPS-CR") == 0)
380                 buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
381         else
382                 buf = NULL;
383         if (buf == NULL)
384                 return -1;
385
386         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
387                                          wpabuf_len(buf));
388         reply[res++] = '\n';
389         reply[res] = '\0';
390
391         wpabuf_free(buf);
392
393         return res;
394 }
395
396
397 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
398                                                   char *cmd)
399 {
400         /*
401          * Since NFC connection handover provided full WPS Credential, there is
402          * no need for additional operations within hostapd. Just report this in
403          * debug log.
404          */
405         wpa_printf(MSG_DEBUG, "NFC: Connection handover reported: %s", cmd);
406         return 0;
407 }
408
409 #endif /* CONFIG_WPS_NFC */
410
411
412 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
413                                          char *buf, size_t buflen)
414 {
415         int timeout = 300;
416         char *pos;
417         const char *pin_txt;
418
419         pos = os_strchr(txt, ' ');
420         if (pos)
421                 *pos++ = '\0';
422
423         if (os_strcmp(txt, "disable") == 0) {
424                 hostapd_wps_ap_pin_disable(hapd);
425                 return os_snprintf(buf, buflen, "OK\n");
426         }
427
428         if (os_strcmp(txt, "random") == 0) {
429                 if (pos)
430                         timeout = atoi(pos);
431                 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
432                 if (pin_txt == NULL)
433                         return -1;
434                 return os_snprintf(buf, buflen, "%s", pin_txt);
435         }
436
437         if (os_strcmp(txt, "get") == 0) {
438                 pin_txt = hostapd_wps_ap_pin_get(hapd);
439                 if (pin_txt == NULL)
440                         return -1;
441                 return os_snprintf(buf, buflen, "%s", pin_txt);
442         }
443
444         if (os_strcmp(txt, "set") == 0) {
445                 char *pin;
446                 if (pos == NULL)
447                         return -1;
448                 pin = pos;
449                 pos = os_strchr(pos, ' ');
450                 if (pos) {
451                         *pos++ = '\0';
452                         timeout = atoi(pos);
453                 }
454                 if (os_strlen(pin) > buflen)
455                         return -1;
456                 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
457                         return -1;
458                 return os_snprintf(buf, buflen, "%s", pin);
459         }
460
461         return -1;
462 }
463
464
465 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
466 {
467         char *pos;
468         char *ssid, *auth, *encr = NULL, *key = NULL;
469
470         ssid = txt;
471         pos = os_strchr(txt, ' ');
472         if (!pos)
473                 return -1;
474         *pos++ = '\0';
475
476         auth = pos;
477         pos = os_strchr(pos, ' ');
478         if (pos) {
479                 *pos++ = '\0';
480                 encr = pos;
481                 pos = os_strchr(pos, ' ');
482                 if (pos) {
483                         *pos++ = '\0';
484                         key = pos;
485                 }
486         }
487
488         return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
489 }
490
491
492 static const char * pbc_status_str(enum pbc_status status)
493 {
494         switch (status) {
495         case WPS_PBC_STATUS_DISABLE:
496                 return "Disabled";
497         case WPS_PBC_STATUS_ACTIVE:
498                 return "Active";
499         case WPS_PBC_STATUS_TIMEOUT:
500                 return "Timed-out";
501         case WPS_PBC_STATUS_OVERLAP:
502                 return "Overlap";
503         default:
504                 return "Unknown";
505         }
506 }
507
508
509 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
510                                              char *buf, size_t buflen)
511 {
512         int ret;
513         char *pos, *end;
514
515         pos = buf;
516         end = buf + buflen;
517
518         ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
519                           pbc_status_str(hapd->wps_stats.pbc_status));
520
521         if (ret < 0 || ret >= end - pos)
522                 return pos - buf;
523         pos += ret;
524
525         ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
526                           (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
527                            "Success":
528                            (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
529                             "Failed" : "None")));
530
531         if (ret < 0 || ret >= end - pos)
532                 return pos - buf;
533         pos += ret;
534
535         /* If status == Failure - Add possible Reasons */
536         if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
537            hapd->wps_stats.failure_reason > 0) {
538                 ret = os_snprintf(pos, end - pos,
539                                   "Failure Reason: %s\n",
540                                   wps_ei_str(hapd->wps_stats.failure_reason));
541
542                 if (ret < 0 || ret >= end - pos)
543                         return pos - buf;
544                 pos += ret;
545         }
546
547         if (hapd->wps_stats.status) {
548                 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
549                                   MAC2STR(hapd->wps_stats.peer_addr));
550
551                 if (ret < 0 || ret >= end - pos)
552                         return pos - buf;
553                 pos += ret;
554         }
555
556         return pos - buf;
557 }
558
559 #endif /* CONFIG_WPS */
560
561
562 #ifdef CONFIG_INTERWORKING
563
564 static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
565                                               const char *cmd)
566 {
567         u8 qos_map_set[16 + 2 * 21], count = 0;
568         const char *pos = cmd;
569         int val, ret;
570
571         for (;;) {
572                 if (count == sizeof(qos_map_set)) {
573                         wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
574                         return -1;
575                 }
576
577                 val = atoi(pos);
578                 if (val < 0 || val > 255) {
579                         wpa_printf(MSG_INFO, "Invalid QoS Map Set");
580                         return -1;
581                 }
582
583                 qos_map_set[count++] = val;
584                 pos = os_strchr(pos, ',');
585                 if (!pos)
586                         break;
587                 pos++;
588         }
589
590         if (count < 16 || count & 1) {
591                 wpa_printf(MSG_INFO, "Invalid QoS Map Set");
592                 return -1;
593         }
594
595         ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
596         if (ret) {
597                 wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
598                 return -1;
599         }
600
601         os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
602         hapd->conf->qos_map_set_len = count;
603
604         return 0;
605 }
606
607
608 static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
609                                                 const char *cmd)
610 {
611         u8 addr[ETH_ALEN];
612         struct sta_info *sta;
613         struct wpabuf *buf;
614         u8 *qos_map_set = hapd->conf->qos_map_set;
615         u8 qos_map_set_len = hapd->conf->qos_map_set_len;
616         int ret;
617
618         if (!qos_map_set_len) {
619                 wpa_printf(MSG_INFO, "QoS Map Set is not set");
620                 return -1;
621         }
622
623         if (hwaddr_aton(cmd, addr))
624                 return -1;
625
626         sta = ap_get_sta(hapd, addr);
627         if (sta == NULL) {
628                 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
629                            "for QoS Map Configuration message",
630                            MAC2STR(addr));
631                 return -1;
632         }
633
634         if (!sta->qos_map_enabled) {
635                 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
636                            "support for QoS Map", MAC2STR(addr));
637                 return -1;
638         }
639
640         buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
641         if (buf == NULL)
642                 return -1;
643
644         wpabuf_put_u8(buf, WLAN_ACTION_QOS);
645         wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
646
647         /* QoS Map Set Element */
648         wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
649         wpabuf_put_u8(buf, qos_map_set_len);
650         wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
651
652         ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
653                                       wpabuf_head(buf), wpabuf_len(buf));
654         wpabuf_free(buf);
655
656         return ret;
657 }
658
659 #endif /* CONFIG_INTERWORKING */
660
661
662 #ifdef CONFIG_WNM
663
664 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
665                                                 const char *cmd)
666 {
667         u8 addr[ETH_ALEN];
668         u8 buf[1000], *pos;
669         struct ieee80211_mgmt *mgmt;
670         int disassoc_timer;
671
672         if (hwaddr_aton(cmd, addr))
673                 return -1;
674         if (cmd[17] != ' ')
675                 return -1;
676         disassoc_timer = atoi(cmd + 17);
677
678         os_memset(buf, 0, sizeof(buf));
679         mgmt = (struct ieee80211_mgmt *) buf;
680         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
681                                            WLAN_FC_STYPE_ACTION);
682         os_memcpy(mgmt->da, addr, ETH_ALEN);
683         os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
684         os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
685         mgmt->u.action.category = WLAN_ACTION_WNM;
686         mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
687         mgmt->u.action.u.bss_tm_req.dialog_token = 1;
688         mgmt->u.action.u.bss_tm_req.req_mode =
689                 WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
690         mgmt->u.action.u.bss_tm_req.disassoc_timer =
691                 host_to_le16(disassoc_timer);
692         mgmt->u.action.u.bss_tm_req.validity_interval = 0;
693
694         pos = mgmt->u.action.u.bss_tm_req.variable;
695
696         if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
697                 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
698                            "Management Request frame");
699                 return -1;
700         }
701
702         return 0;
703 }
704
705
706 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
707                                            const char *cmd)
708 {
709         u8 addr[ETH_ALEN];
710         const char *url, *timerstr;
711         u8 buf[1000], *pos;
712         struct ieee80211_mgmt *mgmt;
713         size_t url_len;
714         int disassoc_timer;
715
716         if (hwaddr_aton(cmd, addr))
717                 return -1;
718
719         timerstr = cmd + 17;
720         if (*timerstr != ' ')
721                 return -1;
722         timerstr++;
723         disassoc_timer = atoi(timerstr);
724         if (disassoc_timer < 0 || disassoc_timer > 65535)
725                 return -1;
726
727         url = os_strchr(timerstr, ' ');
728         if (url == NULL)
729                 return -1;
730         url++;
731         url_len = os_strlen(url);
732         if (url_len > 255)
733                 return -1;
734
735         os_memset(buf, 0, sizeof(buf));
736         mgmt = (struct ieee80211_mgmt *) buf;
737         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
738                                            WLAN_FC_STYPE_ACTION);
739         os_memcpy(mgmt->da, addr, ETH_ALEN);
740         os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
741         os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
742         mgmt->u.action.category = WLAN_ACTION_WNM;
743         mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
744         mgmt->u.action.u.bss_tm_req.dialog_token = 1;
745         mgmt->u.action.u.bss_tm_req.req_mode =
746                 WNM_BSS_TM_REQ_DISASSOC_IMMINENT |
747                 WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
748         mgmt->u.action.u.bss_tm_req.disassoc_timer =
749                 host_to_le16(disassoc_timer);
750         mgmt->u.action.u.bss_tm_req.validity_interval = 0x01;
751
752         pos = mgmt->u.action.u.bss_tm_req.variable;
753
754         /* Session Information URL */
755         *pos++ = url_len;
756         os_memcpy(pos, url, url_len);
757         pos += url_len;
758
759         if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
760                 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
761                            "Management Request frame");
762                 return -1;
763         }
764
765         /* send disassociation frame after time-out */
766         if (disassoc_timer) {
767                 struct sta_info *sta;
768                 int timeout, beacon_int;
769
770                 /*
771                  * Prevent STA from reconnecting using cached PMKSA to force
772                  * full authentication with the authentication server (which may
773                  * decide to reject the connection),
774                  */
775                 wpa_auth_pmksa_remove(hapd->wpa_auth, addr);
776
777                 sta = ap_get_sta(hapd, addr);
778                 if (sta == NULL) {
779                         wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
780                                    "for ESS disassociation imminent message",
781                                    MAC2STR(addr));
782                         return -1;
783                 }
784
785                 beacon_int = hapd->iconf->beacon_int;
786                 if (beacon_int < 1)
787                         beacon_int = 100; /* best guess */
788                 /* Calculate timeout in ms based on beacon_int in TU */
789                 timeout = disassoc_timer * beacon_int * 128 / 125;
790                 wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR
791                            " set to %d ms", MAC2STR(addr), timeout);
792
793                 sta->timeout_next = STA_DISASSOC_FROM_CLI;
794                 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
795                 eloop_register_timeout(timeout / 1000,
796                                        timeout % 1000 * 1000,
797                                        ap_handle_timer, hapd, sta);
798         }
799
800         return 0;
801 }
802
803 #endif /* CONFIG_WNM */
804
805
806 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
807                                          char *buf, size_t buflen)
808 {
809         int ret;
810         char *pos, *end;
811
812         pos = buf;
813         end = buf + buflen;
814
815         ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
816                           "ssid=%s\n",
817                           MAC2STR(hapd->own_addr),
818                           wpa_ssid_txt(hapd->conf->ssid.ssid,
819                                        hapd->conf->ssid.ssid_len));
820         if (ret < 0 || ret >= end - pos)
821                 return pos - buf;
822         pos += ret;
823
824 #ifdef CONFIG_WPS
825         ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
826                           hapd->conf->wps_state == 0 ? "disabled" :
827                           (hapd->conf->wps_state == 1 ? "not configured" :
828                            "configured"));
829         if (ret < 0 || ret >= end - pos)
830                 return pos - buf;
831         pos += ret;
832
833         if (hapd->conf->wps_state && hapd->conf->wpa &&
834             hapd->conf->ssid.wpa_passphrase) {
835                 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
836                                   hapd->conf->ssid.wpa_passphrase);
837                 if (ret < 0 || ret >= end - pos)
838                         return pos - buf;
839                 pos += ret;
840         }
841
842         if (hapd->conf->wps_state && hapd->conf->wpa &&
843             hapd->conf->ssid.wpa_psk &&
844             hapd->conf->ssid.wpa_psk->group) {
845                 char hex[PMK_LEN * 2 + 1];
846                 wpa_snprintf_hex(hex, sizeof(hex),
847                                  hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
848                 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
849                 if (ret < 0 || ret >= end - pos)
850                         return pos - buf;
851                 pos += ret;
852         }
853 #endif /* CONFIG_WPS */
854
855         if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
856                 ret = os_snprintf(pos, end - pos, "key_mgmt=");
857                 if (ret < 0 || ret >= end - pos)
858                         return pos - buf;
859                 pos += ret;
860
861                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
862                         ret = os_snprintf(pos, end - pos, "WPA-PSK ");
863                         if (ret < 0 || ret >= end - pos)
864                                 return pos - buf;
865                         pos += ret;
866                 }
867                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
868                         ret = os_snprintf(pos, end - pos, "WPA-EAP ");
869                         if (ret < 0 || ret >= end - pos)
870                                 return pos - buf;
871                         pos += ret;
872                 }
873 #ifdef CONFIG_IEEE80211R
874                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
875                         ret = os_snprintf(pos, end - pos, "FT-PSK ");
876                         if (ret < 0 || ret >= end - pos)
877                                 return pos - buf;
878                         pos += ret;
879                 }
880                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
881                         ret = os_snprintf(pos, end - pos, "FT-EAP ");
882                         if (ret < 0 || ret >= end - pos)
883                                 return pos - buf;
884                         pos += ret;
885                 }
886 #endif /* CONFIG_IEEE80211R */
887 #ifdef CONFIG_IEEE80211W
888                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
889                         ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
890                         if (ret < 0 || ret >= end - pos)
891                                 return pos - buf;
892                         pos += ret;
893                 }
894                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
895                         ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
896                         if (ret < 0 || ret >= end - pos)
897                                 return pos - buf;
898                         pos += ret;
899                 }
900 #endif /* CONFIG_IEEE80211W */
901
902                 ret = os_snprintf(pos, end - pos, "\n");
903                 if (ret < 0 || ret >= end - pos)
904                         return pos - buf;
905                 pos += ret;
906         }
907
908         if (hapd->conf->wpa) {
909                 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
910                                   wpa_cipher_txt(hapd->conf->wpa_group));
911                 if (ret < 0 || ret >= end - pos)
912                         return pos - buf;
913                 pos += ret;
914         }
915
916         if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
917                 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
918                 if (ret < 0 || ret >= end - pos)
919                         return pos - buf;
920                 pos += ret;
921
922                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
923                                         " ");
924                 if (ret < 0)
925                         return pos - buf;
926                 pos += ret;
927
928                 ret = os_snprintf(pos, end - pos, "\n");
929                 if (ret < 0 || ret >= end - pos)
930                         return pos - buf;
931                 pos += ret;
932         }
933
934         if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
935                 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
936                 if (ret < 0 || ret >= end - pos)
937                         return pos - buf;
938                 pos += ret;
939
940                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
941                                         " ");
942                 if (ret < 0)
943                         return pos - buf;
944                 pos += ret;
945
946                 ret = os_snprintf(pos, end - pos, "\n");
947                 if (ret < 0 || ret >= end - pos)
948                         return pos - buf;
949                 pos += ret;
950         }
951
952         return pos - buf;
953 }
954
955
956 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
957 {
958         char *value;
959         int ret = 0;
960
961         value = os_strchr(cmd, ' ');
962         if (value == NULL)
963                 return -1;
964         *value++ = '\0';
965
966         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
967         if (0) {
968 #ifdef CONFIG_WPS_TESTING
969         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
970                 long int val;
971                 val = strtol(value, NULL, 0);
972                 if (val < 0 || val > 0xff) {
973                         ret = -1;
974                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
975                                    "wps_version_number %ld", val);
976                 } else {
977                         wps_version_number = val;
978                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
979                                    "version %u.%u",
980                                    (wps_version_number & 0xf0) >> 4,
981                                    wps_version_number & 0x0f);
982                         hostapd_wps_update_ie(hapd);
983                 }
984         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
985                 wps_testing_dummy_cred = atoi(value);
986                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
987                            wps_testing_dummy_cred);
988 #endif /* CONFIG_WPS_TESTING */
989 #ifdef CONFIG_INTERWORKING
990         } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
991                 int val = atoi(value);
992                 if (val <= 0)
993                         ret = -1;
994                 else
995                         hapd->gas_frag_limit = val;
996 #endif /* CONFIG_INTERWORKING */
997         } else {
998                 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
999         }
1000
1001         return ret;
1002 }
1003
1004
1005 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
1006                                   char *buf, size_t buflen)
1007 {
1008         int res;
1009
1010         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
1011
1012         if (os_strcmp(cmd, "version") == 0) {
1013                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
1014                 if (res < 0 || (unsigned int) res >= buflen)
1015                         return -1;
1016                 return res;
1017         }
1018
1019         return -1;
1020 }
1021
1022
1023 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
1024 {
1025         if (hostapd_enable_iface(iface) < 0) {
1026                 wpa_printf(MSG_ERROR, "Enabling of interface failed");
1027                 return -1;
1028         }
1029         return 0;
1030 }
1031
1032
1033 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
1034 {
1035         if (hostapd_reload_iface(iface) < 0) {
1036                 wpa_printf(MSG_ERROR, "Reloading of interface failed");
1037                 return -1;
1038         }
1039         return 0;
1040 }
1041
1042
1043 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
1044 {
1045         if (hostapd_disable_iface(iface) < 0) {
1046                 wpa_printf(MSG_ERROR, "Disabling of interface failed");
1047                 return -1;
1048         }
1049         return 0;
1050 }
1051
1052
1053 #ifdef CONFIG_TESTING_OPTIONS
1054 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
1055 {
1056         union wpa_event_data data;
1057         char *pos, *param;
1058         enum wpa_event_type event;
1059
1060         wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1061
1062         os_memset(&data, 0, sizeof(data));
1063
1064         param = os_strchr(cmd, ' ');
1065         if (param == NULL)
1066                 return -1;
1067         *param++ = '\0';
1068
1069         if (os_strcmp(cmd, "DETECTED") == 0)
1070                 event = EVENT_DFS_RADAR_DETECTED;
1071         else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1072                 event = EVENT_DFS_CAC_FINISHED;
1073         else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1074                 event = EVENT_DFS_CAC_ABORTED;
1075         else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1076                 event = EVENT_DFS_NOP_FINISHED;
1077         else {
1078                 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1079                            cmd);
1080                 return -1;
1081         }
1082
1083         pos = os_strstr(param, "freq=");
1084         if (pos)
1085                 data.dfs_event.freq = atoi(pos + 5);
1086
1087         pos = os_strstr(param, "ht_enabled=1");
1088         if (pos)
1089                 data.dfs_event.ht_enabled = 1;
1090
1091         pos = os_strstr(param, "chan_offset=");
1092         if (pos)
1093                 data.dfs_event.chan_offset = atoi(pos + 12);
1094
1095         pos = os_strstr(param, "chan_width=");
1096         if (pos)
1097                 data.dfs_event.chan_width = atoi(pos + 11);
1098
1099         pos = os_strstr(param, "cf1=");
1100         if (pos)
1101                 data.dfs_event.cf1 = atoi(pos + 4);
1102
1103         pos = os_strstr(param, "cf2=");
1104         if (pos)
1105                 data.dfs_event.cf2 = atoi(pos + 4);
1106
1107         wpa_supplicant_event(hapd, event, &data);
1108
1109         return 0;
1110 }
1111 #endif /* CONFIG_TESTING_OPTIONS */
1112
1113
1114 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
1115                                        void *sock_ctx)
1116 {
1117         struct hostapd_data *hapd = eloop_ctx;
1118         char buf[256];
1119         int res;
1120         struct sockaddr_un from;
1121         socklen_t fromlen = sizeof(from);
1122         char *reply;
1123         const int reply_size = 4096;
1124         int reply_len;
1125         int level = MSG_DEBUG;
1126
1127         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1128                        (struct sockaddr *) &from, &fromlen);
1129         if (res < 0) {
1130                 perror("recvfrom(ctrl_iface)");
1131                 return;
1132         }
1133         buf[res] = '\0';
1134         if (os_strcmp(buf, "PING") == 0)
1135                 level = MSG_EXCESSIVE;
1136         wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
1137
1138         reply = os_malloc(reply_size);
1139         if (reply == NULL) {
1140                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
1141                        fromlen);
1142                 return;
1143         }
1144
1145         os_memcpy(reply, "OK\n", 3);
1146         reply_len = 3;
1147
1148         if (os_strcmp(buf, "PING") == 0) {
1149                 os_memcpy(reply, "PONG\n", 5);
1150                 reply_len = 5;
1151         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
1152                 if (wpa_debug_reopen_file() < 0)
1153                         reply_len = -1;
1154         } else if (os_strcmp(buf, "STATUS") == 0) {
1155                 reply_len = hostapd_ctrl_iface_status(hapd, reply,
1156                                                       reply_size);
1157         } else if (os_strcmp(buf, "MIB") == 0) {
1158                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
1159                 if (reply_len >= 0) {
1160                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
1161                                           reply_size - reply_len);
1162                         if (res < 0)
1163                                 reply_len = -1;
1164                         else
1165                                 reply_len += res;
1166                 }
1167                 if (reply_len >= 0) {
1168                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
1169                                                  reply_size - reply_len);
1170                         if (res < 0)
1171                                 reply_len = -1;
1172                         else
1173                                 reply_len += res;
1174                 }
1175 #ifndef CONFIG_NO_RADIUS
1176                 if (reply_len >= 0) {
1177                         res = radius_client_get_mib(hapd->radius,
1178                                                     reply + reply_len,
1179                                                     reply_size - reply_len);
1180                         if (res < 0)
1181                                 reply_len = -1;
1182                         else
1183                                 reply_len += res;
1184                 }
1185 #endif /* CONFIG_NO_RADIUS */
1186         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
1187                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
1188                                                          reply_size);
1189         } else if (os_strncmp(buf, "STA ", 4) == 0) {
1190                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
1191                                                    reply_size);
1192         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
1193                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
1194                                                         reply_size);
1195         } else if (os_strcmp(buf, "ATTACH") == 0) {
1196                 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
1197                         reply_len = -1;
1198         } else if (os_strcmp(buf, "DETACH") == 0) {
1199                 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
1200                         reply_len = -1;
1201         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
1202                 if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
1203                                                     buf + 6))
1204                         reply_len = -1;
1205         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
1206                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
1207                         reply_len = -1;
1208         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
1209                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
1210                         reply_len = -1;
1211         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
1212                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
1213                         reply_len = -1;
1214 #ifdef CONFIG_IEEE80211W
1215 #ifdef NEED_AP_MLME
1216         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
1217                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
1218                         reply_len = -1;
1219 #endif /* NEED_AP_MLME */
1220 #endif /* CONFIG_IEEE80211W */
1221 #ifdef CONFIG_WPS
1222         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
1223                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
1224                         reply_len = -1;
1225         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
1226                 reply_len = hostapd_ctrl_iface_wps_check_pin(
1227                         hapd, buf + 14, reply, reply_size);
1228         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
1229                 if (hostapd_wps_button_pushed(hapd, NULL))
1230                         reply_len = -1;
1231         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
1232                 if (hostapd_wps_cancel(hapd))
1233                         reply_len = -1;
1234         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
1235                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
1236                                                           reply, reply_size);
1237         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
1238                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
1239                         reply_len = -1;
1240         } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
1241                 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
1242                                                               reply_size);
1243 #ifdef CONFIG_WPS_NFC
1244         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
1245                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
1246                         reply_len = -1;
1247         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
1248                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
1249                         hapd, buf + 21, reply, reply_size);
1250         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
1251                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
1252                         hapd, buf + 14, reply, reply_size);
1253         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
1254                 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
1255                         hapd, buf + 21, reply, reply_size);
1256         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
1257                 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
1258                         reply_len = -1;
1259 #endif /* CONFIG_WPS_NFC */
1260 #endif /* CONFIG_WPS */
1261 #ifdef CONFIG_INTERWORKING
1262         } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
1263                 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
1264                         reply_len = -1;
1265         } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
1266                 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
1267                         reply_len = -1;
1268 #endif /* CONFIG_INTERWORKING */
1269 #ifdef CONFIG_WNM
1270         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
1271                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
1272                         reply_len = -1;
1273         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
1274                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
1275                         reply_len = -1;
1276 #endif /* CONFIG_WNM */
1277         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
1278                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
1279                                                           reply_size);
1280         } else if (os_strncmp(buf, "SET ", 4) == 0) {
1281                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
1282                         reply_len = -1;
1283         } else if (os_strncmp(buf, "GET ", 4) == 0) {
1284                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
1285                                                    reply_size);
1286         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
1287                 if (hostapd_ctrl_iface_enable(hapd->iface))
1288                         reply_len = -1;
1289         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
1290                 if (hostapd_ctrl_iface_reload(hapd->iface))
1291                         reply_len = -1;
1292         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
1293                 if (hostapd_ctrl_iface_disable(hapd->iface))
1294                         reply_len = -1;
1295 #ifdef CONFIG_TESTING_OPTIONS
1296         } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
1297                 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
1298                         reply_len = -1;
1299 #endif /* CONFIG_TESTING_OPTIONS */
1300         } else {
1301                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1302                 reply_len = 16;
1303         }
1304
1305         if (reply_len < 0) {
1306                 os_memcpy(reply, "FAIL\n", 5);
1307                 reply_len = 5;
1308         }
1309         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1310         os_free(reply);
1311 }
1312
1313
1314 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
1315 {
1316         char *buf;
1317         size_t len;
1318
1319         if (hapd->conf->ctrl_interface == NULL)
1320                 return NULL;
1321
1322         len = os_strlen(hapd->conf->ctrl_interface) +
1323                 os_strlen(hapd->conf->iface) + 2;
1324         buf = os_malloc(len);
1325         if (buf == NULL)
1326                 return NULL;
1327
1328         os_snprintf(buf, len, "%s/%s",
1329                     hapd->conf->ctrl_interface, hapd->conf->iface);
1330         buf[len - 1] = '\0';
1331         return buf;
1332 }
1333
1334
1335 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
1336                                       const char *txt, size_t len)
1337 {
1338         struct hostapd_data *hapd = ctx;
1339         if (hapd == NULL)
1340                 return;
1341         hostapd_ctrl_iface_send(hapd, level, txt, len);
1342 }
1343
1344
1345 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
1346 {
1347         struct sockaddr_un addr;
1348         int s = -1;
1349         char *fname = NULL;
1350
1351         if (hapd->ctrl_sock > -1) {
1352                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
1353                 return 0;
1354         }
1355
1356         if (hapd->conf->ctrl_interface == NULL)
1357                 return 0;
1358
1359         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1360                 if (errno == EEXIST) {
1361                         wpa_printf(MSG_DEBUG, "Using existing control "
1362                                    "interface directory.");
1363                 } else {
1364                         perror("mkdir[ctrl_interface]");
1365                         goto fail;
1366                 }
1367         }
1368
1369         if (hapd->conf->ctrl_interface_gid_set &&
1370             chown(hapd->conf->ctrl_interface, -1,
1371                   hapd->conf->ctrl_interface_gid) < 0) {
1372                 perror("chown[ctrl_interface]");
1373                 return -1;
1374         }
1375
1376         if (!hapd->conf->ctrl_interface_gid_set &&
1377             hapd->iface->interfaces->ctrl_iface_group &&
1378             chown(hapd->conf->ctrl_interface, -1,
1379                   hapd->iface->interfaces->ctrl_iface_group) < 0) {
1380                 perror("chown[ctrl_interface]");
1381                 return -1;
1382         }
1383
1384 #ifdef ANDROID
1385         /*
1386          * Android is using umask 0077 which would leave the control interface
1387          * directory without group access. This breaks things since Wi-Fi
1388          * framework assumes that this directory can be accessed by other
1389          * applications in the wifi group. Fix this by adding group access even
1390          * if umask value would prevent this.
1391          */
1392         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1393                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
1394                            strerror(errno));
1395                 /* Try to continue anyway */
1396         }
1397 #endif /* ANDROID */
1398
1399         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
1400             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
1401                 goto fail;
1402
1403         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1404         if (s < 0) {
1405                 perror("socket(PF_UNIX)");
1406                 goto fail;
1407         }
1408
1409         os_memset(&addr, 0, sizeof(addr));
1410 #ifdef __FreeBSD__
1411         addr.sun_len = sizeof(addr);
1412 #endif /* __FreeBSD__ */
1413         addr.sun_family = AF_UNIX;
1414         fname = hostapd_ctrl_iface_path(hapd);
1415         if (fname == NULL)
1416                 goto fail;
1417         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1418         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1419                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1420                            strerror(errno));
1421                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1422                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1423                                    " allow connections - assuming it was left"
1424                                    "over from forced program termination");
1425                         if (unlink(fname) < 0) {
1426                                 perror("unlink[ctrl_iface]");
1427                                 wpa_printf(MSG_ERROR, "Could not unlink "
1428                                            "existing ctrl_iface socket '%s'",
1429                                            fname);
1430                                 goto fail;
1431                         }
1432                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1433                             0) {
1434                                 perror("hostapd-ctrl-iface: bind(PF_UNIX)");
1435                                 goto fail;
1436                         }
1437                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1438                                    "ctrl_iface socket '%s'", fname);
1439                 } else {
1440                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1441                                    "be in use - cannot override it");
1442                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1443                                    "not used anymore", fname);
1444                         os_free(fname);
1445                         fname = NULL;
1446                         goto fail;
1447                 }
1448         }
1449
1450         if (hapd->conf->ctrl_interface_gid_set &&
1451             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
1452                 perror("chown[ctrl_interface/ifname]");
1453                 goto fail;
1454         }
1455
1456         if (!hapd->conf->ctrl_interface_gid_set &&
1457             hapd->iface->interfaces->ctrl_iface_group &&
1458             chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
1459                 perror("chown[ctrl_interface/ifname]");
1460                 goto fail;
1461         }
1462
1463         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1464                 perror("chmod[ctrl_interface/ifname]");
1465                 goto fail;
1466         }
1467         os_free(fname);
1468
1469         hapd->ctrl_sock = s;
1470         eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
1471                                  NULL);
1472         hapd->msg_ctx = hapd;
1473         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
1474
1475         return 0;
1476
1477 fail:
1478         if (s >= 0)
1479                 close(s);
1480         if (fname) {
1481                 unlink(fname);
1482                 os_free(fname);
1483         }
1484         return -1;
1485 }
1486
1487
1488 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
1489 {
1490         struct wpa_ctrl_dst *dst, *prev;
1491
1492         if (hapd->ctrl_sock > -1) {
1493                 char *fname;
1494                 eloop_unregister_read_sock(hapd->ctrl_sock);
1495                 close(hapd->ctrl_sock);
1496                 hapd->ctrl_sock = -1;
1497                 fname = hostapd_ctrl_iface_path(hapd);
1498                 if (fname)
1499                         unlink(fname);
1500                 os_free(fname);
1501
1502                 if (hapd->conf->ctrl_interface &&
1503                     rmdir(hapd->conf->ctrl_interface) < 0) {
1504                         if (errno == ENOTEMPTY) {
1505                                 wpa_printf(MSG_DEBUG, "Control interface "
1506                                            "directory not empty - leaving it "
1507                                            "behind");
1508                         } else {
1509                                 wpa_printf(MSG_ERROR,
1510                                            "rmdir[ctrl_interface=%s]: %s",
1511                                            hapd->conf->ctrl_interface,
1512                                            strerror(errno));
1513                         }
1514                 }
1515         }
1516
1517         dst = hapd->ctrl_dst;
1518         while (dst) {
1519                 prev = dst;
1520                 dst = dst->next;
1521                 os_free(prev);
1522         }
1523 }
1524
1525
1526 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
1527                                   char *buf)
1528 {
1529         if (hostapd_add_iface(interfaces, buf) < 0) {
1530                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
1531                 return -1;
1532         }
1533         return 0;
1534 }
1535
1536
1537 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
1538                                      char *buf)
1539 {
1540         if (hostapd_remove_iface(interfaces, buf) < 0) {
1541                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
1542                 return -1;
1543         }
1544         return 0;
1545 }
1546
1547
1548 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
1549                                               void *sock_ctx)
1550 {
1551         void *interfaces = eloop_ctx;
1552         char buf[256];
1553         int res;
1554         struct sockaddr_un from;
1555         socklen_t fromlen = sizeof(from);
1556         char reply[24];
1557         int reply_len;
1558
1559         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1560                        (struct sockaddr *) &from, &fromlen);
1561         if (res < 0) {
1562                 perror("recvfrom(ctrl_iface)");
1563                 return;
1564         }
1565         buf[res] = '\0';
1566         wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
1567
1568         os_memcpy(reply, "OK\n", 3);
1569         reply_len = 3;
1570
1571         if (os_strcmp(buf, "PING") == 0) {
1572                 os_memcpy(reply, "PONG\n", 5);
1573                 reply_len = 5;
1574         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
1575                 if (wpa_debug_reopen_file() < 0)
1576                         reply_len = -1;
1577         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
1578                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
1579                         reply_len = -1;
1580         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
1581                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
1582                         reply_len = -1;
1583         } else {
1584                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
1585                            "ignored");
1586                 reply_len = -1;
1587         }
1588
1589         if (reply_len < 0) {
1590                 os_memcpy(reply, "FAIL\n", 5);
1591                 reply_len = 5;
1592         }
1593
1594         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1595 }
1596
1597
1598 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
1599 {
1600         char *buf;
1601         size_t len;
1602
1603         if (interface->global_iface_path == NULL)
1604                 return NULL;
1605
1606         len = os_strlen(interface->global_iface_path) +
1607                 os_strlen(interface->global_iface_name) + 2;
1608         buf = os_malloc(len);
1609         if (buf == NULL)
1610                 return NULL;
1611
1612         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
1613                     interface->global_iface_name);
1614         buf[len - 1] = '\0';
1615         return buf;
1616 }
1617
1618
1619 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
1620 {
1621         struct sockaddr_un addr;
1622         int s = -1;
1623         char *fname = NULL;
1624
1625         if (interface->global_iface_path == NULL) {
1626                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
1627                 return 0;
1628         }
1629
1630         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
1631                 if (errno == EEXIST) {
1632                         wpa_printf(MSG_DEBUG, "Using existing control "
1633                                    "interface directory.");
1634                 } else {
1635                         perror("mkdir[ctrl_interface]");
1636                         goto fail;
1637                 }
1638         } else if (interface->ctrl_iface_group &&
1639                    chown(interface->global_iface_path, -1,
1640                          interface->ctrl_iface_group) < 0) {
1641                 perror("chown[ctrl_interface]");
1642                 goto fail;
1643         }
1644
1645         if (os_strlen(interface->global_iface_path) + 1 +
1646             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
1647                 goto fail;
1648
1649         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1650         if (s < 0) {
1651                 perror("socket(PF_UNIX)");
1652                 goto fail;
1653         }
1654
1655         os_memset(&addr, 0, sizeof(addr));
1656 #ifdef __FreeBSD__
1657         addr.sun_len = sizeof(addr);
1658 #endif /* __FreeBSD__ */
1659         addr.sun_family = AF_UNIX;
1660         fname = hostapd_global_ctrl_iface_path(interface);
1661         if (fname == NULL)
1662                 goto fail;
1663         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1664         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1665                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1666                            strerror(errno));
1667                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1668                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1669                                    " allow connections - assuming it was left"
1670                                    "over from forced program termination");
1671                         if (unlink(fname) < 0) {
1672                                 perror("unlink[ctrl_iface]");
1673                                 wpa_printf(MSG_ERROR, "Could not unlink "
1674                                            "existing ctrl_iface socket '%s'",
1675                                            fname);
1676                                 goto fail;
1677                         }
1678                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1679                             0) {
1680                                 perror("bind(PF_UNIX)");
1681                                 goto fail;
1682                         }
1683                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1684                                    "ctrl_iface socket '%s'", fname);
1685                 } else {
1686                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1687                                    "be in use - cannot override it");
1688                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1689                                    "not used anymore", fname);
1690                         os_free(fname);
1691                         fname = NULL;
1692                         goto fail;
1693                 }
1694         }
1695
1696         if (interface->ctrl_iface_group &&
1697             chown(fname, -1, interface->ctrl_iface_group) < 0) {
1698                 perror("chown[ctrl_interface]");
1699                 goto fail;
1700         }
1701
1702         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1703                 perror("chmod[ctrl_interface/ifname]");
1704                 goto fail;
1705         }
1706         os_free(fname);
1707
1708         interface->global_ctrl_sock = s;
1709         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
1710                                  interface, NULL);
1711
1712         return 0;
1713
1714 fail:
1715         if (s >= 0)
1716                 close(s);
1717         if (fname) {
1718                 unlink(fname);
1719                 os_free(fname);
1720         }
1721         return -1;
1722 }
1723
1724
1725 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
1726 {
1727         char *fname = NULL;
1728
1729         if (interfaces->global_ctrl_sock > -1) {
1730                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
1731                 close(interfaces->global_ctrl_sock);
1732                 interfaces->global_ctrl_sock = -1;
1733                 fname = hostapd_global_ctrl_iface_path(interfaces);
1734                 if (fname) {
1735                         unlink(fname);
1736                         os_free(fname);
1737                 }
1738
1739                 if (interfaces->global_iface_path &&
1740                     rmdir(interfaces->global_iface_path) < 0) {
1741                         if (errno == ENOTEMPTY) {
1742                                 wpa_printf(MSG_DEBUG, "Control interface "
1743                                            "directory not empty - leaving it "
1744                                            "behind");
1745                         } else {
1746                                 wpa_printf(MSG_ERROR,
1747                                            "rmdir[ctrl_interface=%s]: %s",
1748                                            interfaces->global_iface_path,
1749                                            strerror(errno));
1750                         }
1751                 }
1752                 os_free(interfaces->global_iface_path);
1753                 interfaces->global_iface_path = NULL;
1754         }
1755 }
1756
1757
1758 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
1759                                     const char *buf, size_t len)
1760 {
1761         struct wpa_ctrl_dst *dst, *next;
1762         struct msghdr msg;
1763         int idx;
1764         struct iovec io[2];
1765         char levelstr[10];
1766
1767         dst = hapd->ctrl_dst;
1768         if (hapd->ctrl_sock < 0 || dst == NULL)
1769                 return;
1770
1771         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
1772         io[0].iov_base = levelstr;
1773         io[0].iov_len = os_strlen(levelstr);
1774         io[1].iov_base = (char *) buf;
1775         io[1].iov_len = len;
1776         os_memset(&msg, 0, sizeof(msg));
1777         msg.msg_iov = io;
1778         msg.msg_iovlen = 2;
1779
1780         idx = 0;
1781         while (dst) {
1782                 next = dst->next;
1783                 if (level >= dst->debug_level) {
1784                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
1785                                     (u8 *) dst->addr.sun_path, dst->addrlen -
1786                                     offsetof(struct sockaddr_un, sun_path));
1787                         msg.msg_name = &dst->addr;
1788                         msg.msg_namelen = dst->addrlen;
1789                         if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
1790                                 int _errno = errno;
1791                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
1792                                            "%d - %s",
1793                                            idx, errno, strerror(errno));
1794                                 dst->errors++;
1795                                 if (dst->errors > 10 || _errno == ENOENT) {
1796                                         hostapd_ctrl_iface_detach(
1797                                                 hapd, &dst->addr,
1798                                                 dst->addrlen);
1799                                 }
1800                         } else
1801                                 dst->errors = 0;
1802                 }
1803                 idx++;
1804                 dst = next;
1805         }
1806 }
1807
1808 #endif /* CONFIG_NATIVE_WINDOWS */