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