]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/wpa/hostapd/ctrl_iface.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / wpa / 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 "wps/wps_defs.h"
33 #include "wps/wps.h"
34 #include "config_file.h"
35 #include "ctrl_iface.h"
36
37
38 struct wpa_ctrl_dst {
39         struct wpa_ctrl_dst *next;
40         struct sockaddr_un addr;
41         socklen_t addrlen;
42         int debug_level;
43         int errors;
44 };
45
46
47 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
48                                     const char *buf, size_t len);
49
50
51 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
52                                      struct sockaddr_un *from,
53                                      socklen_t fromlen)
54 {
55         struct wpa_ctrl_dst *dst;
56
57         dst = os_zalloc(sizeof(*dst));
58         if (dst == NULL)
59                 return -1;
60         os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
61         dst->addrlen = fromlen;
62         dst->debug_level = MSG_INFO;
63         dst->next = hapd->ctrl_dst;
64         hapd->ctrl_dst = dst;
65         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
66                     (u8 *) from->sun_path,
67                     fromlen - offsetof(struct sockaddr_un, sun_path));
68         return 0;
69 }
70
71
72 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
73                                      struct sockaddr_un *from,
74                                      socklen_t fromlen)
75 {
76         struct wpa_ctrl_dst *dst, *prev = NULL;
77
78         dst = hapd->ctrl_dst;
79         while (dst) {
80                 if (fromlen == dst->addrlen &&
81                     os_memcmp(from->sun_path, dst->addr.sun_path,
82                               fromlen - offsetof(struct sockaddr_un, sun_path))
83                     == 0) {
84                         if (prev == NULL)
85                                 hapd->ctrl_dst = dst->next;
86                         else
87                                 prev->next = dst->next;
88                         os_free(dst);
89                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
90                                     (u8 *) from->sun_path,
91                                     fromlen -
92                                     offsetof(struct sockaddr_un, sun_path));
93                         return 0;
94                 }
95                 prev = dst;
96                 dst = dst->next;
97         }
98         return -1;
99 }
100
101
102 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
103                                     struct sockaddr_un *from,
104                                     socklen_t fromlen,
105                                     char *level)
106 {
107         struct wpa_ctrl_dst *dst;
108
109         wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
110
111         dst = hapd->ctrl_dst;
112         while (dst) {
113                 if (fromlen == dst->addrlen &&
114                     os_memcmp(from->sun_path, dst->addr.sun_path,
115                               fromlen - offsetof(struct sockaddr_un, sun_path))
116                     == 0) {
117                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
118                                     "level", (u8 *) from->sun_path, fromlen -
119                                     offsetof(struct sockaddr_un, sun_path));
120                         dst->debug_level = atoi(level);
121                         return 0;
122                 }
123                 dst = dst->next;
124         }
125
126         return -1;
127 }
128
129
130 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
131                                       const char *txtaddr)
132 {
133         u8 addr[ETH_ALEN];
134         struct sta_info *sta;
135
136         wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
137
138         if (hwaddr_aton(txtaddr, addr))
139                 return -1;
140
141         sta = ap_get_sta(hapd, addr);
142         if (sta)
143                 return 0;
144
145         wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
146                    "notification", MAC2STR(addr));
147         sta = ap_sta_add(hapd, addr);
148         if (sta == NULL)
149                 return -1;
150
151         hostapd_new_assoc_sta(hapd, sta, 0);
152         return 0;
153 }
154
155
156 #ifdef CONFIG_IEEE80211W
157 #ifdef NEED_AP_MLME
158 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
159                                        const char *txtaddr)
160 {
161         u8 addr[ETH_ALEN];
162         u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
163
164         wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
165
166         if (hwaddr_aton(txtaddr, addr) ||
167             os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
168                 return -1;
169
170         ieee802_11_send_sa_query_req(hapd, addr, trans_id);
171
172         return 0;
173 }
174 #endif /* NEED_AP_MLME */
175 #endif /* CONFIG_IEEE80211W */
176
177
178 #ifdef CONFIG_WPS
179 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
180 {
181         char *pin = os_strchr(txt, ' ');
182         char *timeout_txt;
183         int timeout;
184         u8 addr_buf[ETH_ALEN], *addr = NULL;
185         char *pos;
186
187         if (pin == NULL)
188                 return -1;
189         *pin++ = '\0';
190
191         timeout_txt = os_strchr(pin, ' ');
192         if (timeout_txt) {
193                 *timeout_txt++ = '\0';
194                 timeout = atoi(timeout_txt);
195                 pos = os_strchr(timeout_txt, ' ');
196                 if (pos) {
197                         *pos++ = '\0';
198                         if (hwaddr_aton(pos, addr_buf) == 0)
199                                 addr = addr_buf;
200                 }
201         } else
202                 timeout = 0;
203
204         return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
205 }
206
207
208 static int hostapd_ctrl_iface_wps_check_pin(
209         struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
210 {
211         char pin[9];
212         size_t len;
213         char *pos;
214         int ret;
215
216         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
217                               (u8 *) cmd, os_strlen(cmd));
218         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
219                 if (*pos < '0' || *pos > '9')
220                         continue;
221                 pin[len++] = *pos;
222                 if (len == 9) {
223                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
224                         return -1;
225                 }
226         }
227         if (len != 4 && len != 8) {
228                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
229                 return -1;
230         }
231         pin[len] = '\0';
232
233         if (len == 8) {
234                 unsigned int pin_val;
235                 pin_val = atoi(pin);
236                 if (!wps_pin_valid(pin_val)) {
237                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
238                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
239                         if (ret < 0 || (size_t) ret >= buflen)
240                                 return -1;
241                         return ret;
242                 }
243         }
244
245         ret = os_snprintf(buf, buflen, "%s", pin);
246         if (ret < 0 || (size_t) ret >= buflen)
247                 return -1;
248
249         return ret;
250 }
251
252
253 #ifdef CONFIG_WPS_NFC
254 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
255                                                char *pos)
256 {
257         size_t len;
258         struct wpabuf *buf;
259         int ret;
260
261         len = os_strlen(pos);
262         if (len & 0x01)
263                 return -1;
264         len /= 2;
265
266         buf = wpabuf_alloc(len);
267         if (buf == NULL)
268                 return -1;
269         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
270                 wpabuf_free(buf);
271                 return -1;
272         }
273
274         ret = hostapd_wps_nfc_tag_read(hapd, buf);
275         wpabuf_free(buf);
276
277         return ret;
278 }
279
280
281 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
282                                                    char *cmd, char *reply,
283                                                    size_t max_len)
284 {
285         int ndef;
286         struct wpabuf *buf;
287         int res;
288
289         if (os_strcmp(cmd, "WPS") == 0)
290                 ndef = 0;
291         else if (os_strcmp(cmd, "NDEF") == 0)
292                 ndef = 1;
293         else
294                 return -1;
295
296         buf = hostapd_wps_nfc_config_token(hapd, ndef);
297         if (buf == NULL)
298                 return -1;
299
300         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
301                                          wpabuf_len(buf));
302         reply[res++] = '\n';
303         reply[res] = '\0';
304
305         wpabuf_free(buf);
306
307         return res;
308 }
309
310
311 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
312                                                 char *reply, size_t max_len,
313                                                 int ndef)
314 {
315         struct wpabuf *buf;
316         int res;
317
318         buf = hostapd_wps_nfc_token_gen(hapd, ndef);
319         if (buf == NULL)
320                 return -1;
321
322         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
323                                          wpabuf_len(buf));
324         reply[res++] = '\n';
325         reply[res] = '\0';
326
327         wpabuf_free(buf);
328
329         return res;
330 }
331
332
333 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
334                                             char *cmd, char *reply,
335                                             size_t max_len)
336 {
337         if (os_strcmp(cmd, "WPS") == 0)
338                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
339                                                             max_len, 0);
340
341         if (os_strcmp(cmd, "NDEF") == 0)
342                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
343                                                             max_len, 1);
344
345         if (os_strcmp(cmd, "enable") == 0)
346                 return hostapd_wps_nfc_token_enable(hapd);
347
348         if (os_strcmp(cmd, "disable") == 0) {
349                 hostapd_wps_nfc_token_disable(hapd);
350                 return 0;
351         }
352
353         return -1;
354 }
355 #endif /* CONFIG_WPS_NFC */
356
357
358 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
359                                          char *buf, size_t buflen)
360 {
361         int timeout = 300;
362         char *pos;
363         const char *pin_txt;
364
365         pos = os_strchr(txt, ' ');
366         if (pos)
367                 *pos++ = '\0';
368
369         if (os_strcmp(txt, "disable") == 0) {
370                 hostapd_wps_ap_pin_disable(hapd);
371                 return os_snprintf(buf, buflen, "OK\n");
372         }
373
374         if (os_strcmp(txt, "random") == 0) {
375                 if (pos)
376                         timeout = atoi(pos);
377                 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
378                 if (pin_txt == NULL)
379                         return -1;
380                 return os_snprintf(buf, buflen, "%s", pin_txt);
381         }
382
383         if (os_strcmp(txt, "get") == 0) {
384                 pin_txt = hostapd_wps_ap_pin_get(hapd);
385                 if (pin_txt == NULL)
386                         return -1;
387                 return os_snprintf(buf, buflen, "%s", pin_txt);
388         }
389
390         if (os_strcmp(txt, "set") == 0) {
391                 char *pin;
392                 if (pos == NULL)
393                         return -1;
394                 pin = pos;
395                 pos = os_strchr(pos, ' ');
396                 if (pos) {
397                         *pos++ = '\0';
398                         timeout = atoi(pos);
399                 }
400                 if (os_strlen(pin) > buflen)
401                         return -1;
402                 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
403                         return -1;
404                 return os_snprintf(buf, buflen, "%s", pin);
405         }
406
407         return -1;
408 }
409
410
411 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
412 {
413         char *pos;
414         char *ssid, *auth, *encr = NULL, *key = NULL;
415
416         ssid = txt;
417         pos = os_strchr(txt, ' ');
418         if (!pos)
419                 return -1;
420         *pos++ = '\0';
421
422         auth = pos;
423         pos = os_strchr(pos, ' ');
424         if (pos) {
425                 *pos++ = '\0';
426                 encr = pos;
427                 pos = os_strchr(pos, ' ');
428                 if (pos) {
429                         *pos++ = '\0';
430                         key = pos;
431                 }
432         }
433
434         return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
435 }
436 #endif /* CONFIG_WPS */
437
438
439 #ifdef CONFIG_WNM
440
441 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
442                                                 const char *cmd)
443 {
444         u8 addr[ETH_ALEN];
445         u8 buf[1000], *pos;
446         struct ieee80211_mgmt *mgmt;
447         int disassoc_timer;
448
449         if (hwaddr_aton(cmd, addr))
450                 return -1;
451         if (cmd[17] != ' ')
452                 return -1;
453         disassoc_timer = atoi(cmd + 17);
454
455         os_memset(buf, 0, sizeof(buf));
456         mgmt = (struct ieee80211_mgmt *) buf;
457         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
458                                            WLAN_FC_STYPE_ACTION);
459         os_memcpy(mgmt->da, addr, ETH_ALEN);
460         os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
461         os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
462         mgmt->u.action.category = WLAN_ACTION_WNM;
463         mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
464         mgmt->u.action.u.bss_tm_req.dialog_token = 1;
465         mgmt->u.action.u.bss_tm_req.req_mode =
466                 WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
467         mgmt->u.action.u.bss_tm_req.disassoc_timer =
468                 host_to_le16(disassoc_timer);
469         mgmt->u.action.u.bss_tm_req.validity_interval = 0;
470
471         pos = mgmt->u.action.u.bss_tm_req.variable;
472
473         if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
474                 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
475                            "Management Request frame");
476                 return -1;
477         }
478
479         return 0;
480 }
481
482
483 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
484                                            const char *cmd)
485 {
486         u8 addr[ETH_ALEN];
487         const char *url;
488         u8 buf[1000], *pos;
489         struct ieee80211_mgmt *mgmt;
490         size_t url_len;
491
492         if (hwaddr_aton(cmd, addr))
493                 return -1;
494         url = cmd + 17;
495         if (*url != ' ')
496                 return -1;
497         url++;
498         url_len = os_strlen(url);
499         if (url_len > 255)
500                 return -1;
501
502         os_memset(buf, 0, sizeof(buf));
503         mgmt = (struct ieee80211_mgmt *) buf;
504         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
505                                            WLAN_FC_STYPE_ACTION);
506         os_memcpy(mgmt->da, addr, ETH_ALEN);
507         os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
508         os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
509         mgmt->u.action.category = WLAN_ACTION_WNM;
510         mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
511         mgmt->u.action.u.bss_tm_req.dialog_token = 1;
512         mgmt->u.action.u.bss_tm_req.req_mode =
513                 WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
514         mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0);
515         mgmt->u.action.u.bss_tm_req.validity_interval = 0;
516
517         pos = mgmt->u.action.u.bss_tm_req.variable;
518
519         /* Session Information URL */
520         *pos++ = url_len;
521         os_memcpy(pos, url, url_len);
522         pos += url_len;
523
524         if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
525                 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
526                            "Management Request frame");
527                 return -1;
528         }
529
530         return 0;
531 }
532
533 #endif /* CONFIG_WNM */
534
535
536 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
537                                          char *buf, size_t buflen)
538 {
539         int ret;
540         char *pos, *end;
541
542         pos = buf;
543         end = buf + buflen;
544
545         ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
546                           "ssid=%s\n",
547                           MAC2STR(hapd->own_addr),
548                           wpa_ssid_txt(hapd->conf->ssid.ssid,
549                                        hapd->conf->ssid.ssid_len));
550         if (ret < 0 || ret >= end - pos)
551                 return pos - buf;
552         pos += ret;
553
554 #ifdef CONFIG_WPS
555         ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
556                           hapd->conf->wps_state == 0 ? "disabled" :
557                           (hapd->conf->wps_state == 1 ? "not configured" :
558                            "configured"));
559         if (ret < 0 || ret >= end - pos)
560                 return pos - buf;
561         pos += ret;
562
563         if (hapd->conf->wps_state && hapd->conf->wpa &&
564             hapd->conf->ssid.wpa_passphrase) {
565                 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
566                                   hapd->conf->ssid.wpa_passphrase);
567                 if (ret < 0 || ret >= end - pos)
568                         return pos - buf;
569                 pos += ret;
570         }
571
572         if (hapd->conf->wps_state && hapd->conf->wpa &&
573             hapd->conf->ssid.wpa_psk &&
574             hapd->conf->ssid.wpa_psk->group) {
575                 char hex[PMK_LEN * 2 + 1];
576                 wpa_snprintf_hex(hex, sizeof(hex),
577                                  hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
578                 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
579                 if (ret < 0 || ret >= end - pos)
580                         return pos - buf;
581                 pos += ret;
582         }
583 #endif /* CONFIG_WPS */
584
585         if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
586                 ret = os_snprintf(pos, end - pos, "key_mgmt=");
587                 if (ret < 0 || ret >= end - pos)
588                         return pos - buf;
589                 pos += ret;
590
591                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
592                         ret = os_snprintf(pos, end - pos, "WPA-PSK ");
593                         if (ret < 0 || ret >= end - pos)
594                                 return pos - buf;
595                         pos += ret;
596                 }
597                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
598                         ret = os_snprintf(pos, end - pos, "WPA-EAP ");
599                         if (ret < 0 || ret >= end - pos)
600                                 return pos - buf;
601                         pos += ret;
602                 }
603 #ifdef CONFIG_IEEE80211R
604                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
605                         ret = os_snprintf(pos, end - pos, "FT-PSK ");
606                         if (ret < 0 || ret >= end - pos)
607                                 return pos - buf;
608                         pos += ret;
609                 }
610                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
611                         ret = os_snprintf(pos, end - pos, "FT-EAP ");
612                         if (ret < 0 || ret >= end - pos)
613                                 return pos - buf;
614                         pos += ret;
615                 }
616 #endif /* CONFIG_IEEE80211R */
617 #ifdef CONFIG_IEEE80211W
618                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
619                         ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
620                         if (ret < 0 || ret >= end - pos)
621                                 return pos - buf;
622                         pos += ret;
623                 }
624                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
625                         ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
626                         if (ret < 0 || ret >= end - pos)
627                                 return pos - buf;
628                         pos += ret;
629                 }
630 #endif /* CONFIG_IEEE80211W */
631
632                 ret = os_snprintf(pos, end - pos, "\n");
633                 if (ret < 0 || ret >= end - pos)
634                         return pos - buf;
635                 pos += ret;
636         }
637
638         if (hapd->conf->wpa && hapd->conf->wpa_group == WPA_CIPHER_CCMP) {
639                 ret = os_snprintf(pos, end - pos, "group_cipher=CCMP\n");
640                 if (ret < 0 || ret >= end - pos)
641                         return pos - buf;
642                 pos += ret;
643         } else if (hapd->conf->wpa &&
644                    hapd->conf->wpa_group == WPA_CIPHER_GCMP) {
645                 ret = os_snprintf(pos, end - pos, "group_cipher=GCMP\n");
646                 if (ret < 0 || ret >= end - pos)
647                         return pos - buf;
648                 pos += ret;
649         } else if (hapd->conf->wpa &&
650                    hapd->conf->wpa_group == WPA_CIPHER_TKIP) {
651                 ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n");
652                 if (ret < 0 || ret >= end - pos)
653                         return pos - buf;
654                 pos += ret;
655         }
656
657         if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
658                 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
659                 if (ret < 0 || ret >= end - pos)
660                         return pos - buf;
661                 pos += ret;
662
663                 if (hapd->conf->rsn_pairwise & WPA_CIPHER_CCMP) {
664                         ret = os_snprintf(pos, end - pos, "CCMP ");
665                         if (ret < 0 || ret >= end - pos)
666                                 return pos - buf;
667                         pos += ret;
668                 }
669                 if (hapd->conf->rsn_pairwise & WPA_CIPHER_GCMP) {
670                         ret = os_snprintf(pos, end - pos, "GCMP ");
671                         if (ret < 0 || ret >= end - pos)
672                                 return pos - buf;
673                         pos += ret;
674                 }
675                 if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) {
676                         ret = os_snprintf(pos, end - pos, "TKIP ");
677                         if (ret < 0 || ret >= end - pos)
678                                 return pos - buf;
679                         pos += ret;
680                 }
681
682                 ret = os_snprintf(pos, end - pos, "\n");
683                 if (ret < 0 || ret >= end - pos)
684                         return pos - buf;
685                 pos += ret;
686         }
687
688         if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
689                 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
690                 if (ret < 0 || ret >= end - pos)
691                         return pos - buf;
692                 pos += ret;
693
694                 if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) {
695                         ret = os_snprintf(pos, end - pos, "CCMP ");
696                         if (ret < 0 || ret >= end - pos)
697                                 return pos - buf;
698                         pos += ret;
699                 }
700                 if (hapd->conf->wpa_pairwise & WPA_CIPHER_GCMP) {
701                         ret = os_snprintf(pos, end - pos, "GCMP ");
702                         if (ret < 0 || ret >= end - pos)
703                                 return pos - buf;
704                         pos += ret;
705                 }
706                 if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {
707                         ret = os_snprintf(pos, end - pos, "TKIP ");
708                         if (ret < 0 || ret >= end - pos)
709                                 return pos - buf;
710                         pos += ret;
711                 }
712
713                 ret = os_snprintf(pos, end - pos, "\n");
714                 if (ret < 0 || ret >= end - pos)
715                         return pos - buf;
716                 pos += ret;
717         }
718
719         return pos - buf;
720 }
721
722
723 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
724 {
725         char *value;
726         int ret = 0;
727
728         value = os_strchr(cmd, ' ');
729         if (value == NULL)
730                 return -1;
731         *value++ = '\0';
732
733         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
734         if (0) {
735 #ifdef CONFIG_WPS_TESTING
736         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
737                 long int val;
738                 val = strtol(value, NULL, 0);
739                 if (val < 0 || val > 0xff) {
740                         ret = -1;
741                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
742                                    "wps_version_number %ld", val);
743                 } else {
744                         wps_version_number = val;
745                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
746                                    "version %u.%u",
747                                    (wps_version_number & 0xf0) >> 4,
748                                    wps_version_number & 0x0f);
749                         hostapd_wps_update_ie(hapd);
750                 }
751         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
752                 wps_testing_dummy_cred = atoi(value);
753                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
754                            wps_testing_dummy_cred);
755 #endif /* CONFIG_WPS_TESTING */
756 #ifdef CONFIG_INTERWORKING
757         } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
758                 int val = atoi(value);
759                 if (val <= 0)
760                         ret = -1;
761                 else
762                         hapd->gas_frag_limit = val;
763 #endif /* CONFIG_INTERWORKING */
764         } else {
765                 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
766         }
767
768         return ret;
769 }
770
771
772 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
773                                   char *buf, size_t buflen)
774 {
775         int res;
776
777         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
778
779         if (os_strcmp(cmd, "version") == 0) {
780                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
781                 if (res < 0 || (unsigned int) res >= buflen)
782                         return -1;
783                 return res;
784         }
785
786         return -1;
787 }
788
789
790 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
791 {
792         if (hostapd_enable_iface(iface) < 0) {
793                 wpa_printf(MSG_ERROR, "Enabling of interface failed");
794                 return -1;
795         }
796         return 0;
797 }
798
799
800 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
801 {
802         if (hostapd_reload_iface(iface) < 0) {
803                 wpa_printf(MSG_ERROR, "Reloading of interface failed");
804                 return -1;
805         }
806         return 0;
807 }
808
809
810 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
811 {
812         if (hostapd_disable_iface(iface) < 0) {
813                 wpa_printf(MSG_ERROR, "Disabling of interface failed");
814                 return -1;
815         }
816         return 0;
817 }
818
819
820 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
821                                        void *sock_ctx)
822 {
823         struct hostapd_data *hapd = eloop_ctx;
824         char buf[256];
825         int res;
826         struct sockaddr_un from;
827         socklen_t fromlen = sizeof(from);
828         char *reply;
829         const int reply_size = 4096;
830         int reply_len;
831         int level = MSG_DEBUG;
832
833         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
834                        (struct sockaddr *) &from, &fromlen);
835         if (res < 0) {
836                 perror("recvfrom(ctrl_iface)");
837                 return;
838         }
839         buf[res] = '\0';
840         if (os_strcmp(buf, "PING") == 0)
841                 level = MSG_EXCESSIVE;
842         wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
843
844         reply = os_malloc(reply_size);
845         if (reply == NULL) {
846                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
847                        fromlen);
848                 return;
849         }
850
851         os_memcpy(reply, "OK\n", 3);
852         reply_len = 3;
853
854         if (os_strcmp(buf, "PING") == 0) {
855                 os_memcpy(reply, "PONG\n", 5);
856                 reply_len = 5;
857         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
858                 if (wpa_debug_reopen_file() < 0)
859                         reply_len = -1;
860         } else if (os_strcmp(buf, "MIB") == 0) {
861                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
862                 if (reply_len >= 0) {
863                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
864                                           reply_size - reply_len);
865                         if (res < 0)
866                                 reply_len = -1;
867                         else
868                                 reply_len += res;
869                 }
870                 if (reply_len >= 0) {
871                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
872                                                  reply_size - reply_len);
873                         if (res < 0)
874                                 reply_len = -1;
875                         else
876                                 reply_len += res;
877                 }
878 #ifndef CONFIG_NO_RADIUS
879                 if (reply_len >= 0) {
880                         res = radius_client_get_mib(hapd->radius,
881                                                     reply + reply_len,
882                                                     reply_size - reply_len);
883                         if (res < 0)
884                                 reply_len = -1;
885                         else
886                                 reply_len += res;
887                 }
888 #endif /* CONFIG_NO_RADIUS */
889         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
890                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
891                                                          reply_size);
892         } else if (os_strncmp(buf, "STA ", 4) == 0) {
893                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
894                                                    reply_size);
895         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
896                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
897                                                         reply_size);
898         } else if (os_strcmp(buf, "ATTACH") == 0) {
899                 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
900                         reply_len = -1;
901         } else if (os_strcmp(buf, "DETACH") == 0) {
902                 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
903                         reply_len = -1;
904         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
905                 if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
906                                                     buf + 6))
907                         reply_len = -1;
908         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
909                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
910                         reply_len = -1;
911         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
912                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
913                         reply_len = -1;
914         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
915                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
916                         reply_len = -1;
917 #ifdef CONFIG_IEEE80211W
918 #ifdef NEED_AP_MLME
919         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
920                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
921                         reply_len = -1;
922 #endif /* NEED_AP_MLME */
923 #endif /* CONFIG_IEEE80211W */
924 #ifdef CONFIG_WPS
925         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
926                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
927                         reply_len = -1;
928         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
929                 reply_len = hostapd_ctrl_iface_wps_check_pin(
930                         hapd, buf + 14, reply, reply_size);
931         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
932                 if (hostapd_wps_button_pushed(hapd, NULL))
933                         reply_len = -1;
934         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
935                 if (hostapd_wps_cancel(hapd))
936                         reply_len = -1;
937         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
938                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
939                                                           reply, reply_size);
940         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
941                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
942                         reply_len = -1;
943 #ifdef CONFIG_WPS_NFC
944         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
945                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
946                         reply_len = -1;
947         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
948                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
949                         hapd, buf + 21, reply, reply_size);
950         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
951                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
952                         hapd, buf + 14, reply, reply_size);
953 #endif /* CONFIG_WPS_NFC */
954 #endif /* CONFIG_WPS */
955 #ifdef CONFIG_WNM
956         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
957                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
958                         reply_len = -1;
959         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
960                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
961                         reply_len = -1;
962 #endif /* CONFIG_WNM */
963         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
964                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
965                                                           reply_size);
966         } else if (os_strncmp(buf, "SET ", 4) == 0) {
967                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
968                         reply_len = -1;
969         } else if (os_strncmp(buf, "GET ", 4) == 0) {
970                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
971                                                    reply_size);
972         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
973                 if (hostapd_ctrl_iface_enable(hapd->iface))
974                         reply_len = -1;
975         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
976                 if (hostapd_ctrl_iface_reload(hapd->iface))
977                         reply_len = -1;
978         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
979                 if (hostapd_ctrl_iface_disable(hapd->iface))
980                         reply_len = -1;
981         } else {
982                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
983                 reply_len = 16;
984         }
985
986         if (reply_len < 0) {
987                 os_memcpy(reply, "FAIL\n", 5);
988                 reply_len = 5;
989         }
990         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
991         os_free(reply);
992 }
993
994
995 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
996 {
997         char *buf;
998         size_t len;
999
1000         if (hapd->conf->ctrl_interface == NULL)
1001                 return NULL;
1002
1003         len = os_strlen(hapd->conf->ctrl_interface) +
1004                 os_strlen(hapd->conf->iface) + 2;
1005         buf = os_malloc(len);
1006         if (buf == NULL)
1007                 return NULL;
1008
1009         os_snprintf(buf, len, "%s/%s",
1010                     hapd->conf->ctrl_interface, hapd->conf->iface);
1011         buf[len - 1] = '\0';
1012         return buf;
1013 }
1014
1015
1016 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
1017                                       const char *txt, size_t len)
1018 {
1019         struct hostapd_data *hapd = ctx;
1020         if (hapd == NULL)
1021                 return;
1022         hostapd_ctrl_iface_send(hapd, level, txt, len);
1023 }
1024
1025
1026 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
1027 {
1028         struct sockaddr_un addr;
1029         int s = -1;
1030         char *fname = NULL;
1031
1032         if (hapd->ctrl_sock > -1) {
1033                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
1034                 return 0;
1035         }
1036
1037         if (hapd->conf->ctrl_interface == NULL)
1038                 return 0;
1039
1040         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1041                 if (errno == EEXIST) {
1042                         wpa_printf(MSG_DEBUG, "Using existing control "
1043                                    "interface directory.");
1044                 } else {
1045                         perror("mkdir[ctrl_interface]");
1046                         goto fail;
1047                 }
1048         }
1049
1050         if (hapd->conf->ctrl_interface_gid_set &&
1051             chown(hapd->conf->ctrl_interface, -1,
1052                   hapd->conf->ctrl_interface_gid) < 0) {
1053                 perror("chown[ctrl_interface]");
1054                 return -1;
1055         }
1056
1057 #ifdef ANDROID
1058         /*
1059          * Android is using umask 0077 which would leave the control interface
1060          * directory without group access. This breaks things since Wi-Fi
1061          * framework assumes that this directory can be accessed by other
1062          * applications in the wifi group. Fix this by adding group access even
1063          * if umask value would prevent this.
1064          */
1065         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1066                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
1067                            strerror(errno));
1068                 /* Try to continue anyway */
1069         }
1070 #endif /* ANDROID */
1071
1072         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
1073             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
1074                 goto fail;
1075
1076         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1077         if (s < 0) {
1078                 perror("socket(PF_UNIX)");
1079                 goto fail;
1080         }
1081
1082         os_memset(&addr, 0, sizeof(addr));
1083 #ifdef __FreeBSD__
1084         addr.sun_len = sizeof(addr);
1085 #endif /* __FreeBSD__ */
1086         addr.sun_family = AF_UNIX;
1087         fname = hostapd_ctrl_iface_path(hapd);
1088         if (fname == NULL)
1089                 goto fail;
1090         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1091         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1092                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1093                            strerror(errno));
1094                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1095                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1096                                    " allow connections - assuming it was left"
1097                                    "over from forced program termination");
1098                         if (unlink(fname) < 0) {
1099                                 perror("unlink[ctrl_iface]");
1100                                 wpa_printf(MSG_ERROR, "Could not unlink "
1101                                            "existing ctrl_iface socket '%s'",
1102                                            fname);
1103                                 goto fail;
1104                         }
1105                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1106                             0) {
1107                                 perror("hostapd-ctrl-iface: bind(PF_UNIX)");
1108                                 goto fail;
1109                         }
1110                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1111                                    "ctrl_iface socket '%s'", fname);
1112                 } else {
1113                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1114                                    "be in use - cannot override it");
1115                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1116                                    "not used anymore", fname);
1117                         os_free(fname);
1118                         fname = NULL;
1119                         goto fail;
1120                 }
1121         }
1122
1123         if (hapd->conf->ctrl_interface_gid_set &&
1124             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
1125                 perror("chown[ctrl_interface/ifname]");
1126                 goto fail;
1127         }
1128
1129         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1130                 perror("chmod[ctrl_interface/ifname]");
1131                 goto fail;
1132         }
1133         os_free(fname);
1134
1135         hapd->ctrl_sock = s;
1136         eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
1137                                  NULL);
1138         hapd->msg_ctx = hapd;
1139         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
1140
1141         return 0;
1142
1143 fail:
1144         if (s >= 0)
1145                 close(s);
1146         if (fname) {
1147                 unlink(fname);
1148                 os_free(fname);
1149         }
1150         return -1;
1151 }
1152
1153
1154 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
1155 {
1156         struct wpa_ctrl_dst *dst, *prev;
1157
1158         if (hapd->ctrl_sock > -1) {
1159                 char *fname;
1160                 eloop_unregister_read_sock(hapd->ctrl_sock);
1161                 close(hapd->ctrl_sock);
1162                 hapd->ctrl_sock = -1;
1163                 fname = hostapd_ctrl_iface_path(hapd);
1164                 if (fname)
1165                         unlink(fname);
1166                 os_free(fname);
1167
1168                 if (hapd->conf->ctrl_interface &&
1169                     rmdir(hapd->conf->ctrl_interface) < 0) {
1170                         if (errno == ENOTEMPTY) {
1171                                 wpa_printf(MSG_DEBUG, "Control interface "
1172                                            "directory not empty - leaving it "
1173                                            "behind");
1174                         } else {
1175                                 perror("rmdir[ctrl_interface]");
1176                         }
1177                 }
1178         }
1179
1180         dst = hapd->ctrl_dst;
1181         while (dst) {
1182                 prev = dst;
1183                 dst = dst->next;
1184                 os_free(prev);
1185         }
1186 }
1187
1188
1189 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
1190                                   char *buf)
1191 {
1192         if (hostapd_add_iface(interfaces, buf) < 0) {
1193                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
1194                 return -1;
1195         }
1196         return 0;
1197 }
1198
1199
1200 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
1201                                      char *buf)
1202 {
1203         if (hostapd_remove_iface(interfaces, buf) < 0) {
1204                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
1205                 return -1;
1206         }
1207         return 0;
1208 }
1209
1210
1211 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
1212                                               void *sock_ctx)
1213 {
1214         void *interfaces = eloop_ctx;
1215         char buf[256];
1216         int res;
1217         struct sockaddr_un from;
1218         socklen_t fromlen = sizeof(from);
1219         char reply[24];
1220         int reply_len;
1221
1222         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1223                        (struct sockaddr *) &from, &fromlen);
1224         if (res < 0) {
1225                 perror("recvfrom(ctrl_iface)");
1226                 return;
1227         }
1228         buf[res] = '\0';
1229
1230         os_memcpy(reply, "OK\n", 3);
1231         reply_len = 3;
1232
1233         if (os_strcmp(buf, "PING") == 0) {
1234                 os_memcpy(reply, "PONG\n", 5);
1235                 reply_len = 5;
1236         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
1237                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
1238                         reply_len = -1;
1239         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
1240                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
1241                         reply_len = -1;
1242         } else {
1243                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
1244                            "ignored");
1245                 reply_len = -1;
1246         }
1247
1248         if (reply_len < 0) {
1249                 os_memcpy(reply, "FAIL\n", 5);
1250                 reply_len = 5;
1251         }
1252
1253         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1254 }
1255
1256
1257 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
1258 {
1259         char *buf;
1260         size_t len;
1261
1262         if (interface->global_iface_path == NULL)
1263                 return NULL;
1264
1265         len = os_strlen(interface->global_iface_path) +
1266                 os_strlen(interface->global_iface_name) + 2;
1267         buf = os_malloc(len);
1268         if (buf == NULL)
1269                 return NULL;
1270
1271         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
1272                     interface->global_iface_name);
1273         buf[len - 1] = '\0';
1274         return buf;
1275 }
1276
1277
1278 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
1279 {
1280         struct sockaddr_un addr;
1281         int s = -1;
1282         char *fname = NULL;
1283
1284         if (interface->global_iface_path == NULL) {
1285                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
1286                 return 0;
1287         }
1288
1289         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
1290                 if (errno == EEXIST) {
1291                         wpa_printf(MSG_DEBUG, "Using existing control "
1292                                    "interface directory.");
1293                 } else {
1294                         perror("mkdir[ctrl_interface]");
1295                         goto fail;
1296                 }
1297         }
1298
1299         if (os_strlen(interface->global_iface_path) + 1 +
1300             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
1301                 goto fail;
1302
1303         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1304         if (s < 0) {
1305                 perror("socket(PF_UNIX)");
1306                 goto fail;
1307         }
1308
1309         os_memset(&addr, 0, sizeof(addr));
1310 #ifdef __FreeBSD__
1311         addr.sun_len = sizeof(addr);
1312 #endif /* __FreeBSD__ */
1313         addr.sun_family = AF_UNIX;
1314         fname = hostapd_global_ctrl_iface_path(interface);
1315         if (fname == NULL)
1316                 goto fail;
1317         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1318         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1319                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1320                            strerror(errno));
1321                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1322                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1323                                    " allow connections - assuming it was left"
1324                                    "over from forced program termination");
1325                         if (unlink(fname) < 0) {
1326                                 perror("unlink[ctrl_iface]");
1327                                 wpa_printf(MSG_ERROR, "Could not unlink "
1328                                            "existing ctrl_iface socket '%s'",
1329                                            fname);
1330                                 goto fail;
1331                         }
1332                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1333                             0) {
1334                                 perror("bind(PF_UNIX)");
1335                                 goto fail;
1336                         }
1337                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1338                                    "ctrl_iface socket '%s'", fname);
1339                 } else {
1340                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1341                                    "be in use - cannot override it");
1342                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1343                                    "not used anymore", fname);
1344                         os_free(fname);
1345                         fname = NULL;
1346                         goto fail;
1347                 }
1348         }
1349
1350         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1351                 perror("chmod[ctrl_interface/ifname]");
1352                 goto fail;
1353         }
1354         os_free(fname);
1355
1356         interface->global_ctrl_sock = s;
1357         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
1358                                  interface, NULL);
1359
1360         return 0;
1361
1362 fail:
1363         if (s >= 0)
1364                 close(s);
1365         if (fname) {
1366                 unlink(fname);
1367                 os_free(fname);
1368         }
1369         return -1;
1370 }
1371
1372
1373 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
1374 {
1375         char *fname = NULL;
1376
1377         if (interfaces->global_ctrl_sock > -1) {
1378                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
1379                 close(interfaces->global_ctrl_sock);
1380                 interfaces->global_ctrl_sock = -1;
1381                 fname = hostapd_global_ctrl_iface_path(interfaces);
1382                 if (fname) {
1383                         unlink(fname);
1384                         os_free(fname);
1385                 }
1386
1387                 if (interfaces->global_iface_path &&
1388                     rmdir(interfaces->global_iface_path) < 0) {
1389                         if (errno == ENOTEMPTY) {
1390                                 wpa_printf(MSG_DEBUG, "Control interface "
1391                                            "directory not empty - leaving it "
1392                                            "behind");
1393                         } else {
1394                                 perror("rmdir[ctrl_interface]");
1395                         }
1396                 }
1397                 os_free(interfaces->global_iface_path);
1398                 interfaces->global_iface_path = NULL;
1399         }
1400 }
1401
1402
1403 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
1404                                     const char *buf, size_t len)
1405 {
1406         struct wpa_ctrl_dst *dst, *next;
1407         struct msghdr msg;
1408         int idx;
1409         struct iovec io[2];
1410         char levelstr[10];
1411
1412         dst = hapd->ctrl_dst;
1413         if (hapd->ctrl_sock < 0 || dst == NULL)
1414                 return;
1415
1416         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
1417         io[0].iov_base = levelstr;
1418         io[0].iov_len = os_strlen(levelstr);
1419         io[1].iov_base = (char *) buf;
1420         io[1].iov_len = len;
1421         os_memset(&msg, 0, sizeof(msg));
1422         msg.msg_iov = io;
1423         msg.msg_iovlen = 2;
1424
1425         idx = 0;
1426         while (dst) {
1427                 next = dst->next;
1428                 if (level >= dst->debug_level) {
1429                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
1430                                     (u8 *) dst->addr.sun_path, dst->addrlen -
1431                                     offsetof(struct sockaddr_un, sun_path));
1432                         msg.msg_name = &dst->addr;
1433                         msg.msg_namelen = dst->addrlen;
1434                         if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
1435                                 int _errno = errno;
1436                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
1437                                            "%d - %s",
1438                                            idx, errno, strerror(errno));
1439                                 dst->errors++;
1440                                 if (dst->errors > 10 || _errno == ENOENT) {
1441                                         hostapd_ctrl_iface_detach(
1442                                                 hapd, &dst->addr,
1443                                                 dst->addrlen);
1444                                 }
1445                         } else
1446                                 dst->errors = 0;
1447                 }
1448                 idx++;
1449                 dst = next;
1450         }
1451 }
1452
1453 #endif /* CONFIG_NATIVE_WINDOWS */