WNM: Remove PMKSA cache entry on ESS disassoc imminent notification
[mech_eap.git] / hostapd / ctrl_iface.c
1 /*
2  * hostapd / UNIX domain socket -based control interface
3  * Copyright (c) 2004-2012, 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                         if (prev == NULL)
86                                 hapd->ctrl_dst = dst->next;
87                         else
88                                 prev->next = dst->next;
89                         os_free(dst);
90                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
91                                     (u8 *) from->sun_path,
92                                     fromlen -
93                                     offsetof(struct sockaddr_un, sun_path));
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 #endif /* CONFIG_WPS */
491
492
493 #ifdef CONFIG_WNM
494
495 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
496                                                 const char *cmd)
497 {
498         u8 addr[ETH_ALEN];
499         u8 buf[1000], *pos;
500         struct ieee80211_mgmt *mgmt;
501         int disassoc_timer;
502
503         if (hwaddr_aton(cmd, addr))
504                 return -1;
505         if (cmd[17] != ' ')
506                 return -1;
507         disassoc_timer = atoi(cmd + 17);
508
509         os_memset(buf, 0, sizeof(buf));
510         mgmt = (struct ieee80211_mgmt *) buf;
511         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
512                                            WLAN_FC_STYPE_ACTION);
513         os_memcpy(mgmt->da, addr, ETH_ALEN);
514         os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
515         os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
516         mgmt->u.action.category = WLAN_ACTION_WNM;
517         mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
518         mgmt->u.action.u.bss_tm_req.dialog_token = 1;
519         mgmt->u.action.u.bss_tm_req.req_mode =
520                 WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
521         mgmt->u.action.u.bss_tm_req.disassoc_timer =
522                 host_to_le16(disassoc_timer);
523         mgmt->u.action.u.bss_tm_req.validity_interval = 0;
524
525         pos = mgmt->u.action.u.bss_tm_req.variable;
526
527         if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
528                 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
529                            "Management Request frame");
530                 return -1;
531         }
532
533         return 0;
534 }
535
536
537 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
538                                            const char *cmd)
539 {
540         u8 addr[ETH_ALEN];
541         const char *url, *timerstr;
542         u8 buf[1000], *pos;
543         struct ieee80211_mgmt *mgmt;
544         size_t url_len;
545         int disassoc_timer;
546
547         if (hwaddr_aton(cmd, addr))
548                 return -1;
549
550         timerstr = cmd + 17;
551         if (*timerstr != ' ')
552                 return -1;
553         timerstr++;
554         disassoc_timer = atoi(timerstr);
555         if (disassoc_timer < 0 || disassoc_timer > 65535)
556                 return -1;
557
558         url = os_strchr(timerstr, ' ');
559         if (*url != ' ')
560                 return -1;
561         url++;
562         url_len = os_strlen(url);
563         if (url_len > 255)
564                 return -1;
565
566         os_memset(buf, 0, sizeof(buf));
567         mgmt = (struct ieee80211_mgmt *) buf;
568         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
569                                            WLAN_FC_STYPE_ACTION);
570         os_memcpy(mgmt->da, addr, ETH_ALEN);
571         os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
572         os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
573         mgmt->u.action.category = WLAN_ACTION_WNM;
574         mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
575         mgmt->u.action.u.bss_tm_req.dialog_token = 1;
576         mgmt->u.action.u.bss_tm_req.req_mode =
577                 WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
578         mgmt->u.action.u.bss_tm_req.disassoc_timer =
579                 host_to_le16(disassoc_timer);
580         mgmt->u.action.u.bss_tm_req.validity_interval = 0x01;
581
582         pos = mgmt->u.action.u.bss_tm_req.variable;
583
584         /* Session Information URL */
585         *pos++ = url_len;
586         os_memcpy(pos, url, url_len);
587         pos += url_len;
588
589         if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
590                 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
591                            "Management Request frame");
592                 return -1;
593         }
594
595         /* send disassociation frame after time-out */
596         if (disassoc_timer) {
597                 struct sta_info *sta;
598
599                 /*
600                  * Prevent STA from reconnecting using cached PMKSA to force
601                  * full authentication with the authentication server (which may
602                  * decide to reject the connection),
603                  */
604                 wpa_auth_pmksa_remove(hapd->wpa_auth, addr);
605
606                 sta = ap_get_sta(hapd, addr);
607                 if (sta == NULL) {
608                         wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
609                                    "for ESS disassociation imminent message",
610                                    MAC2STR(addr));
611                         return -1;
612                 }
613
614                 sta->timeout_next = STA_DISASSOC_FROM_CLI;
615                 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
616                 eloop_register_timeout(disassoc_timer / 1000,
617                                        disassoc_timer % 1000 * 1000,
618                                        ap_handle_timer, hapd, sta);
619         }
620
621         return 0;
622 }
623
624 #endif /* CONFIG_WNM */
625
626
627 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
628                                          char *buf, size_t buflen)
629 {
630         int ret;
631         char *pos, *end;
632
633         pos = buf;
634         end = buf + buflen;
635
636         ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
637                           "ssid=%s\n",
638                           MAC2STR(hapd->own_addr),
639                           wpa_ssid_txt(hapd->conf->ssid.ssid,
640                                        hapd->conf->ssid.ssid_len));
641         if (ret < 0 || ret >= end - pos)
642                 return pos - buf;
643         pos += ret;
644
645 #ifdef CONFIG_WPS
646         ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
647                           hapd->conf->wps_state == 0 ? "disabled" :
648                           (hapd->conf->wps_state == 1 ? "not configured" :
649                            "configured"));
650         if (ret < 0 || ret >= end - pos)
651                 return pos - buf;
652         pos += ret;
653
654         if (hapd->conf->wps_state && hapd->conf->wpa &&
655             hapd->conf->ssid.wpa_passphrase) {
656                 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
657                                   hapd->conf->ssid.wpa_passphrase);
658                 if (ret < 0 || ret >= end - pos)
659                         return pos - buf;
660                 pos += ret;
661         }
662
663         if (hapd->conf->wps_state && hapd->conf->wpa &&
664             hapd->conf->ssid.wpa_psk &&
665             hapd->conf->ssid.wpa_psk->group) {
666                 char hex[PMK_LEN * 2 + 1];
667                 wpa_snprintf_hex(hex, sizeof(hex),
668                                  hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
669                 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
670                 if (ret < 0 || ret >= end - pos)
671                         return pos - buf;
672                 pos += ret;
673         }
674 #endif /* CONFIG_WPS */
675
676         if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
677                 ret = os_snprintf(pos, end - pos, "key_mgmt=");
678                 if (ret < 0 || ret >= end - pos)
679                         return pos - buf;
680                 pos += ret;
681
682                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
683                         ret = os_snprintf(pos, end - pos, "WPA-PSK ");
684                         if (ret < 0 || ret >= end - pos)
685                                 return pos - buf;
686                         pos += ret;
687                 }
688                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
689                         ret = os_snprintf(pos, end - pos, "WPA-EAP ");
690                         if (ret < 0 || ret >= end - pos)
691                                 return pos - buf;
692                         pos += ret;
693                 }
694 #ifdef CONFIG_IEEE80211R
695                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
696                         ret = os_snprintf(pos, end - pos, "FT-PSK ");
697                         if (ret < 0 || ret >= end - pos)
698                                 return pos - buf;
699                         pos += ret;
700                 }
701                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
702                         ret = os_snprintf(pos, end - pos, "FT-EAP ");
703                         if (ret < 0 || ret >= end - pos)
704                                 return pos - buf;
705                         pos += ret;
706                 }
707 #endif /* CONFIG_IEEE80211R */
708 #ifdef CONFIG_IEEE80211W
709                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
710                         ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
711                         if (ret < 0 || ret >= end - pos)
712                                 return pos - buf;
713                         pos += ret;
714                 }
715                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
716                         ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
717                         if (ret < 0 || ret >= end - pos)
718                                 return pos - buf;
719                         pos += ret;
720                 }
721 #endif /* CONFIG_IEEE80211W */
722
723                 ret = os_snprintf(pos, end - pos, "\n");
724                 if (ret < 0 || ret >= end - pos)
725                         return pos - buf;
726                 pos += ret;
727         }
728
729         if (hapd->conf->wpa) {
730                 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
731                                   wpa_cipher_txt(hapd->conf->wpa_group));
732                 if (ret < 0 || ret >= end - pos)
733                         return pos - buf;
734                 pos += ret;
735         }
736
737         if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
738                 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
739                 if (ret < 0 || ret >= end - pos)
740                         return pos - buf;
741                 pos += ret;
742
743                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
744                                         " ");
745                 if (ret < 0)
746                         return pos - buf;
747                 pos += ret;
748
749                 ret = os_snprintf(pos, end - pos, "\n");
750                 if (ret < 0 || ret >= end - pos)
751                         return pos - buf;
752                 pos += ret;
753         }
754
755         if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
756                 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
757                 if (ret < 0 || ret >= end - pos)
758                         return pos - buf;
759                 pos += ret;
760
761                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
762                                         " ");
763                 if (ret < 0)
764                         return pos - buf;
765                 pos += ret;
766
767                 ret = os_snprintf(pos, end - pos, "\n");
768                 if (ret < 0 || ret >= end - pos)
769                         return pos - buf;
770                 pos += ret;
771         }
772
773         return pos - buf;
774 }
775
776
777 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
778 {
779         char *value;
780         int ret = 0;
781
782         value = os_strchr(cmd, ' ');
783         if (value == NULL)
784                 return -1;
785         *value++ = '\0';
786
787         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
788         if (0) {
789 #ifdef CONFIG_WPS_TESTING
790         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
791                 long int val;
792                 val = strtol(value, NULL, 0);
793                 if (val < 0 || val > 0xff) {
794                         ret = -1;
795                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
796                                    "wps_version_number %ld", val);
797                 } else {
798                         wps_version_number = val;
799                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
800                                    "version %u.%u",
801                                    (wps_version_number & 0xf0) >> 4,
802                                    wps_version_number & 0x0f);
803                         hostapd_wps_update_ie(hapd);
804                 }
805         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
806                 wps_testing_dummy_cred = atoi(value);
807                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
808                            wps_testing_dummy_cred);
809 #endif /* CONFIG_WPS_TESTING */
810 #ifdef CONFIG_INTERWORKING
811         } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
812                 int val = atoi(value);
813                 if (val <= 0)
814                         ret = -1;
815                 else
816                         hapd->gas_frag_limit = val;
817 #endif /* CONFIG_INTERWORKING */
818         } else {
819                 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
820         }
821
822         return ret;
823 }
824
825
826 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
827                                   char *buf, size_t buflen)
828 {
829         int res;
830
831         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
832
833         if (os_strcmp(cmd, "version") == 0) {
834                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
835                 if (res < 0 || (unsigned int) res >= buflen)
836                         return -1;
837                 return res;
838         }
839
840         return -1;
841 }
842
843
844 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
845 {
846         if (hostapd_enable_iface(iface) < 0) {
847                 wpa_printf(MSG_ERROR, "Enabling of interface failed");
848                 return -1;
849         }
850         return 0;
851 }
852
853
854 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
855 {
856         if (hostapd_reload_iface(iface) < 0) {
857                 wpa_printf(MSG_ERROR, "Reloading of interface failed");
858                 return -1;
859         }
860         return 0;
861 }
862
863
864 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
865 {
866         if (hostapd_disable_iface(iface) < 0) {
867                 wpa_printf(MSG_ERROR, "Disabling of interface failed");
868                 return -1;
869         }
870         return 0;
871 }
872
873
874 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
875                                        void *sock_ctx)
876 {
877         struct hostapd_data *hapd = eloop_ctx;
878         char buf[256];
879         int res;
880         struct sockaddr_un from;
881         socklen_t fromlen = sizeof(from);
882         char *reply;
883         const int reply_size = 4096;
884         int reply_len;
885         int level = MSG_DEBUG;
886
887         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
888                        (struct sockaddr *) &from, &fromlen);
889         if (res < 0) {
890                 perror("recvfrom(ctrl_iface)");
891                 return;
892         }
893         buf[res] = '\0';
894         if (os_strcmp(buf, "PING") == 0)
895                 level = MSG_EXCESSIVE;
896         wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
897
898         reply = os_malloc(reply_size);
899         if (reply == NULL) {
900                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
901                        fromlen);
902                 return;
903         }
904
905         os_memcpy(reply, "OK\n", 3);
906         reply_len = 3;
907
908         if (os_strcmp(buf, "PING") == 0) {
909                 os_memcpy(reply, "PONG\n", 5);
910                 reply_len = 5;
911         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
912                 if (wpa_debug_reopen_file() < 0)
913                         reply_len = -1;
914         } else if (os_strcmp(buf, "MIB") == 0) {
915                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
916                 if (reply_len >= 0) {
917                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
918                                           reply_size - reply_len);
919                         if (res < 0)
920                                 reply_len = -1;
921                         else
922                                 reply_len += res;
923                 }
924                 if (reply_len >= 0) {
925                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
926                                                  reply_size - reply_len);
927                         if (res < 0)
928                                 reply_len = -1;
929                         else
930                                 reply_len += res;
931                 }
932 #ifndef CONFIG_NO_RADIUS
933                 if (reply_len >= 0) {
934                         res = radius_client_get_mib(hapd->radius,
935                                                     reply + reply_len,
936                                                     reply_size - reply_len);
937                         if (res < 0)
938                                 reply_len = -1;
939                         else
940                                 reply_len += res;
941                 }
942 #endif /* CONFIG_NO_RADIUS */
943         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
944                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
945                                                          reply_size);
946         } else if (os_strncmp(buf, "STA ", 4) == 0) {
947                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
948                                                    reply_size);
949         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
950                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
951                                                         reply_size);
952         } else if (os_strcmp(buf, "ATTACH") == 0) {
953                 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
954                         reply_len = -1;
955         } else if (os_strcmp(buf, "DETACH") == 0) {
956                 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
957                         reply_len = -1;
958         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
959                 if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
960                                                     buf + 6))
961                         reply_len = -1;
962         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
963                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
964                         reply_len = -1;
965         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
966                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
967                         reply_len = -1;
968         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
969                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
970                         reply_len = -1;
971 #ifdef CONFIG_IEEE80211W
972 #ifdef NEED_AP_MLME
973         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
974                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
975                         reply_len = -1;
976 #endif /* NEED_AP_MLME */
977 #endif /* CONFIG_IEEE80211W */
978 #ifdef CONFIG_WPS
979         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
980                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
981                         reply_len = -1;
982         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
983                 reply_len = hostapd_ctrl_iface_wps_check_pin(
984                         hapd, buf + 14, reply, reply_size);
985         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
986                 if (hostapd_wps_button_pushed(hapd, NULL))
987                         reply_len = -1;
988         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
989                 if (hostapd_wps_cancel(hapd))
990                         reply_len = -1;
991         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
992                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
993                                                           reply, reply_size);
994         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
995                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
996                         reply_len = -1;
997 #ifdef CONFIG_WPS_NFC
998         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
999                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
1000                         reply_len = -1;
1001         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
1002                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
1003                         hapd, buf + 21, reply, reply_size);
1004         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
1005                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
1006                         hapd, buf + 14, reply, reply_size);
1007         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
1008                 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
1009                         hapd, buf + 21, reply, reply_size);
1010         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
1011                 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
1012                         reply_len = -1;
1013 #endif /* CONFIG_WPS_NFC */
1014 #endif /* CONFIG_WPS */
1015 #ifdef CONFIG_WNM
1016         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
1017                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
1018                         reply_len = -1;
1019         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
1020                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
1021                         reply_len = -1;
1022 #endif /* CONFIG_WNM */
1023         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
1024                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
1025                                                           reply_size);
1026         } else if (os_strncmp(buf, "SET ", 4) == 0) {
1027                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
1028                         reply_len = -1;
1029         } else if (os_strncmp(buf, "GET ", 4) == 0) {
1030                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
1031                                                    reply_size);
1032         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
1033                 if (hostapd_ctrl_iface_enable(hapd->iface))
1034                         reply_len = -1;
1035         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
1036                 if (hostapd_ctrl_iface_reload(hapd->iface))
1037                         reply_len = -1;
1038         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
1039                 if (hostapd_ctrl_iface_disable(hapd->iface))
1040                         reply_len = -1;
1041         } else {
1042                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1043                 reply_len = 16;
1044         }
1045
1046         if (reply_len < 0) {
1047                 os_memcpy(reply, "FAIL\n", 5);
1048                 reply_len = 5;
1049         }
1050         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1051         os_free(reply);
1052 }
1053
1054
1055 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
1056 {
1057         char *buf;
1058         size_t len;
1059
1060         if (hapd->conf->ctrl_interface == NULL)
1061                 return NULL;
1062
1063         len = os_strlen(hapd->conf->ctrl_interface) +
1064                 os_strlen(hapd->conf->iface) + 2;
1065         buf = os_malloc(len);
1066         if (buf == NULL)
1067                 return NULL;
1068
1069         os_snprintf(buf, len, "%s/%s",
1070                     hapd->conf->ctrl_interface, hapd->conf->iface);
1071         buf[len - 1] = '\0';
1072         return buf;
1073 }
1074
1075
1076 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
1077                                       const char *txt, size_t len)
1078 {
1079         struct hostapd_data *hapd = ctx;
1080         if (hapd == NULL)
1081                 return;
1082         hostapd_ctrl_iface_send(hapd, level, txt, len);
1083 }
1084
1085
1086 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
1087 {
1088         struct sockaddr_un addr;
1089         int s = -1;
1090         char *fname = NULL;
1091
1092         if (hapd->ctrl_sock > -1) {
1093                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
1094                 return 0;
1095         }
1096
1097         if (hapd->conf->ctrl_interface == NULL)
1098                 return 0;
1099
1100         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1101                 if (errno == EEXIST) {
1102                         wpa_printf(MSG_DEBUG, "Using existing control "
1103                                    "interface directory.");
1104                 } else {
1105                         perror("mkdir[ctrl_interface]");
1106                         goto fail;
1107                 }
1108         }
1109
1110         if (hapd->conf->ctrl_interface_gid_set &&
1111             chown(hapd->conf->ctrl_interface, -1,
1112                   hapd->conf->ctrl_interface_gid) < 0) {
1113                 perror("chown[ctrl_interface]");
1114                 return -1;
1115         }
1116
1117         if (!hapd->conf->ctrl_interface_gid_set &&
1118             hapd->iface->interfaces->ctrl_iface_group &&
1119             chown(hapd->conf->ctrl_interface, -1,
1120                   hapd->iface->interfaces->ctrl_iface_group) < 0) {
1121                 perror("chown[ctrl_interface]");
1122                 return -1;
1123         }
1124
1125 #ifdef ANDROID
1126         /*
1127          * Android is using umask 0077 which would leave the control interface
1128          * directory without group access. This breaks things since Wi-Fi
1129          * framework assumes that this directory can be accessed by other
1130          * applications in the wifi group. Fix this by adding group access even
1131          * if umask value would prevent this.
1132          */
1133         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1134                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
1135                            strerror(errno));
1136                 /* Try to continue anyway */
1137         }
1138 #endif /* ANDROID */
1139
1140         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
1141             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
1142                 goto fail;
1143
1144         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1145         if (s < 0) {
1146                 perror("socket(PF_UNIX)");
1147                 goto fail;
1148         }
1149
1150         os_memset(&addr, 0, sizeof(addr));
1151 #ifdef __FreeBSD__
1152         addr.sun_len = sizeof(addr);
1153 #endif /* __FreeBSD__ */
1154         addr.sun_family = AF_UNIX;
1155         fname = hostapd_ctrl_iface_path(hapd);
1156         if (fname == NULL)
1157                 goto fail;
1158         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1159         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1160                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1161                            strerror(errno));
1162                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1163                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1164                                    " allow connections - assuming it was left"
1165                                    "over from forced program termination");
1166                         if (unlink(fname) < 0) {
1167                                 perror("unlink[ctrl_iface]");
1168                                 wpa_printf(MSG_ERROR, "Could not unlink "
1169                                            "existing ctrl_iface socket '%s'",
1170                                            fname);
1171                                 goto fail;
1172                         }
1173                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1174                             0) {
1175                                 perror("hostapd-ctrl-iface: bind(PF_UNIX)");
1176                                 goto fail;
1177                         }
1178                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1179                                    "ctrl_iface socket '%s'", fname);
1180                 } else {
1181                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1182                                    "be in use - cannot override it");
1183                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1184                                    "not used anymore", fname);
1185                         os_free(fname);
1186                         fname = NULL;
1187                         goto fail;
1188                 }
1189         }
1190
1191         if (hapd->conf->ctrl_interface_gid_set &&
1192             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
1193                 perror("chown[ctrl_interface/ifname]");
1194                 goto fail;
1195         }
1196
1197         if (!hapd->conf->ctrl_interface_gid_set &&
1198             hapd->iface->interfaces->ctrl_iface_group &&
1199             chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
1200                 perror("chown[ctrl_interface/ifname]");
1201                 goto fail;
1202         }
1203
1204         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1205                 perror("chmod[ctrl_interface/ifname]");
1206                 goto fail;
1207         }
1208         os_free(fname);
1209
1210         hapd->ctrl_sock = s;
1211         eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
1212                                  NULL);
1213         hapd->msg_ctx = hapd;
1214         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
1215
1216         return 0;
1217
1218 fail:
1219         if (s >= 0)
1220                 close(s);
1221         if (fname) {
1222                 unlink(fname);
1223                 os_free(fname);
1224         }
1225         return -1;
1226 }
1227
1228
1229 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
1230 {
1231         struct wpa_ctrl_dst *dst, *prev;
1232
1233         if (hapd->ctrl_sock > -1) {
1234                 char *fname;
1235                 eloop_unregister_read_sock(hapd->ctrl_sock);
1236                 close(hapd->ctrl_sock);
1237                 hapd->ctrl_sock = -1;
1238                 fname = hostapd_ctrl_iface_path(hapd);
1239                 if (fname)
1240                         unlink(fname);
1241                 os_free(fname);
1242
1243                 if (hapd->conf->ctrl_interface &&
1244                     rmdir(hapd->conf->ctrl_interface) < 0) {
1245                         if (errno == ENOTEMPTY) {
1246                                 wpa_printf(MSG_DEBUG, "Control interface "
1247                                            "directory not empty - leaving it "
1248                                            "behind");
1249                         } else {
1250                                 perror("rmdir[ctrl_interface]");
1251                         }
1252                 }
1253         }
1254
1255         dst = hapd->ctrl_dst;
1256         while (dst) {
1257                 prev = dst;
1258                 dst = dst->next;
1259                 os_free(prev);
1260         }
1261 }
1262
1263
1264 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
1265                                   char *buf)
1266 {
1267         if (hostapd_add_iface(interfaces, buf) < 0) {
1268                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
1269                 return -1;
1270         }
1271         return 0;
1272 }
1273
1274
1275 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
1276                                      char *buf)
1277 {
1278         if (hostapd_remove_iface(interfaces, buf) < 0) {
1279                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
1280                 return -1;
1281         }
1282         return 0;
1283 }
1284
1285
1286 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
1287                                               void *sock_ctx)
1288 {
1289         void *interfaces = eloop_ctx;
1290         char buf[256];
1291         int res;
1292         struct sockaddr_un from;
1293         socklen_t fromlen = sizeof(from);
1294         char reply[24];
1295         int reply_len;
1296
1297         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1298                        (struct sockaddr *) &from, &fromlen);
1299         if (res < 0) {
1300                 perror("recvfrom(ctrl_iface)");
1301                 return;
1302         }
1303         buf[res] = '\0';
1304
1305         os_memcpy(reply, "OK\n", 3);
1306         reply_len = 3;
1307
1308         if (os_strcmp(buf, "PING") == 0) {
1309                 os_memcpy(reply, "PONG\n", 5);
1310                 reply_len = 5;
1311         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
1312                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
1313                         reply_len = -1;
1314         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
1315                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
1316                         reply_len = -1;
1317         } else {
1318                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
1319                            "ignored");
1320                 reply_len = -1;
1321         }
1322
1323         if (reply_len < 0) {
1324                 os_memcpy(reply, "FAIL\n", 5);
1325                 reply_len = 5;
1326         }
1327
1328         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1329 }
1330
1331
1332 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
1333 {
1334         char *buf;
1335         size_t len;
1336
1337         if (interface->global_iface_path == NULL)
1338                 return NULL;
1339
1340         len = os_strlen(interface->global_iface_path) +
1341                 os_strlen(interface->global_iface_name) + 2;
1342         buf = os_malloc(len);
1343         if (buf == NULL)
1344                 return NULL;
1345
1346         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
1347                     interface->global_iface_name);
1348         buf[len - 1] = '\0';
1349         return buf;
1350 }
1351
1352
1353 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
1354 {
1355         struct sockaddr_un addr;
1356         int s = -1;
1357         char *fname = NULL;
1358
1359         if (interface->global_iface_path == NULL) {
1360                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
1361                 return 0;
1362         }
1363
1364         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
1365                 if (errno == EEXIST) {
1366                         wpa_printf(MSG_DEBUG, "Using existing control "
1367                                    "interface directory.");
1368                 } else {
1369                         perror("mkdir[ctrl_interface]");
1370                         goto fail;
1371                 }
1372         } else if (interface->ctrl_iface_group &&
1373                    chown(interface->global_iface_path, -1,
1374                          interface->ctrl_iface_group) < 0) {
1375                 perror("chown[ctrl_interface]");
1376                 goto fail;
1377         }
1378
1379         if (os_strlen(interface->global_iface_path) + 1 +
1380             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
1381                 goto fail;
1382
1383         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1384         if (s < 0) {
1385                 perror("socket(PF_UNIX)");
1386                 goto fail;
1387         }
1388
1389         os_memset(&addr, 0, sizeof(addr));
1390 #ifdef __FreeBSD__
1391         addr.sun_len = sizeof(addr);
1392 #endif /* __FreeBSD__ */
1393         addr.sun_family = AF_UNIX;
1394         fname = hostapd_global_ctrl_iface_path(interface);
1395         if (fname == NULL)
1396                 goto fail;
1397         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1398         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1399                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1400                            strerror(errno));
1401                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1402                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1403                                    " allow connections - assuming it was left"
1404                                    "over from forced program termination");
1405                         if (unlink(fname) < 0) {
1406                                 perror("unlink[ctrl_iface]");
1407                                 wpa_printf(MSG_ERROR, "Could not unlink "
1408                                            "existing ctrl_iface socket '%s'",
1409                                            fname);
1410                                 goto fail;
1411                         }
1412                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1413                             0) {
1414                                 perror("bind(PF_UNIX)");
1415                                 goto fail;
1416                         }
1417                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1418                                    "ctrl_iface socket '%s'", fname);
1419                 } else {
1420                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1421                                    "be in use - cannot override it");
1422                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1423                                    "not used anymore", fname);
1424                         os_free(fname);
1425                         fname = NULL;
1426                         goto fail;
1427                 }
1428         }
1429
1430         if (interface->ctrl_iface_group &&
1431             chown(fname, -1, interface->ctrl_iface_group) < 0) {
1432                 perror("chown[ctrl_interface]");
1433                 goto fail;
1434         }
1435
1436         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1437                 perror("chmod[ctrl_interface/ifname]");
1438                 goto fail;
1439         }
1440         os_free(fname);
1441
1442         interface->global_ctrl_sock = s;
1443         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
1444                                  interface, NULL);
1445
1446         return 0;
1447
1448 fail:
1449         if (s >= 0)
1450                 close(s);
1451         if (fname) {
1452                 unlink(fname);
1453                 os_free(fname);
1454         }
1455         return -1;
1456 }
1457
1458
1459 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
1460 {
1461         char *fname = NULL;
1462
1463         if (interfaces->global_ctrl_sock > -1) {
1464                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
1465                 close(interfaces->global_ctrl_sock);
1466                 interfaces->global_ctrl_sock = -1;
1467                 fname = hostapd_global_ctrl_iface_path(interfaces);
1468                 if (fname) {
1469                         unlink(fname);
1470                         os_free(fname);
1471                 }
1472
1473                 if (interfaces->global_iface_path &&
1474                     rmdir(interfaces->global_iface_path) < 0) {
1475                         if (errno == ENOTEMPTY) {
1476                                 wpa_printf(MSG_DEBUG, "Control interface "
1477                                            "directory not empty - leaving it "
1478                                            "behind");
1479                         } else {
1480                                 perror("rmdir[ctrl_interface]");
1481                         }
1482                 }
1483                 os_free(interfaces->global_iface_path);
1484                 interfaces->global_iface_path = NULL;
1485         }
1486 }
1487
1488
1489 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
1490                                     const char *buf, size_t len)
1491 {
1492         struct wpa_ctrl_dst *dst, *next;
1493         struct msghdr msg;
1494         int idx;
1495         struct iovec io[2];
1496         char levelstr[10];
1497
1498         dst = hapd->ctrl_dst;
1499         if (hapd->ctrl_sock < 0 || dst == NULL)
1500                 return;
1501
1502         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
1503         io[0].iov_base = levelstr;
1504         io[0].iov_len = os_strlen(levelstr);
1505         io[1].iov_base = (char *) buf;
1506         io[1].iov_len = len;
1507         os_memset(&msg, 0, sizeof(msg));
1508         msg.msg_iov = io;
1509         msg.msg_iovlen = 2;
1510
1511         idx = 0;
1512         while (dst) {
1513                 next = dst->next;
1514                 if (level >= dst->debug_level) {
1515                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
1516                                     (u8 *) dst->addr.sun_path, dst->addrlen -
1517                                     offsetof(struct sockaddr_un, sun_path));
1518                         msg.msg_name = &dst->addr;
1519                         msg.msg_namelen = dst->addrlen;
1520                         if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
1521                                 int _errno = errno;
1522                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
1523                                            "%d - %s",
1524                                            idx, errno, strerror(errno));
1525                                 dst->errors++;
1526                                 if (dst->errors > 10 || _errno == ENOENT) {
1527                                         hostapd_ctrl_iface_detach(
1528                                                 hapd, &dst->addr,
1529                                                 dst->addrlen);
1530                                 }
1531                         } else
1532                                 dst->errors = 0;
1533                 }
1534                 idx++;
1535                 dst = next;
1536         }
1537 }
1538
1539 #endif /* CONFIG_NATIVE_WINDOWS */