Make RADIUS server MIB available through control interface
[mech_eap.git] / hostapd / ctrl_iface.c
1 /*
2  * hostapd / UNIX domain socket -based control interface
3  * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "utils/includes.h"
10
11 #ifndef CONFIG_NATIVE_WINDOWS
12
13 #include <sys/un.h>
14 #include <sys/stat.h>
15 #include <stddef.h>
16
17 #include "utils/common.h"
18 #include "utils/eloop.h"
19 #include "common/version.h"
20 #include "common/ieee802_11_defs.h"
21 #include "drivers/driver.h"
22 #include "radius/radius_client.h"
23 #include "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, "MIB") == 0) {
1144                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
1145                 if (reply_len >= 0) {
1146                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
1147                                           reply_size - reply_len);
1148                         if (res < 0)
1149                                 reply_len = -1;
1150                         else
1151                                 reply_len += res;
1152                 }
1153                 if (reply_len >= 0) {
1154                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
1155                                                  reply_size - reply_len);
1156                         if (res < 0)
1157                                 reply_len = -1;
1158                         else
1159                                 reply_len += res;
1160                 }
1161 #ifndef CONFIG_NO_RADIUS
1162                 if (reply_len >= 0) {
1163                         res = radius_client_get_mib(hapd->radius,
1164                                                     reply + reply_len,
1165                                                     reply_size - reply_len);
1166                         if (res < 0)
1167                                 reply_len = -1;
1168                         else
1169                                 reply_len += res;
1170                 }
1171 #endif /* CONFIG_NO_RADIUS */
1172         } else if (os_strncmp(buf, "MIB ", 4) == 0) {
1173                 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
1174                                                    buf + 4);
1175         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
1176                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
1177                                                          reply_size);
1178         } else if (os_strncmp(buf, "STA ", 4) == 0) {
1179                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
1180                                                    reply_size);
1181         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
1182                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
1183                                                         reply_size);
1184         } else if (os_strcmp(buf, "ATTACH") == 0) {
1185                 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
1186                         reply_len = -1;
1187         } else if (os_strcmp(buf, "DETACH") == 0) {
1188                 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
1189                         reply_len = -1;
1190         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
1191                 if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
1192                                                     buf + 6))
1193                         reply_len = -1;
1194         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
1195                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
1196                         reply_len = -1;
1197         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
1198                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
1199                         reply_len = -1;
1200         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
1201                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
1202                         reply_len = -1;
1203 #ifdef CONFIG_IEEE80211W
1204 #ifdef NEED_AP_MLME
1205         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
1206                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
1207                         reply_len = -1;
1208 #endif /* NEED_AP_MLME */
1209 #endif /* CONFIG_IEEE80211W */
1210 #ifdef CONFIG_WPS
1211         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
1212                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
1213                         reply_len = -1;
1214         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
1215                 reply_len = hostapd_ctrl_iface_wps_check_pin(
1216                         hapd, buf + 14, reply, reply_size);
1217         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
1218                 if (hostapd_wps_button_pushed(hapd, NULL))
1219                         reply_len = -1;
1220         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
1221                 if (hostapd_wps_cancel(hapd))
1222                         reply_len = -1;
1223         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
1224                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
1225                                                           reply, reply_size);
1226         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
1227                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
1228                         reply_len = -1;
1229         } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
1230                 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
1231                                                               reply_size);
1232 #ifdef CONFIG_WPS_NFC
1233         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
1234                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
1235                         reply_len = -1;
1236         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
1237                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
1238                         hapd, buf + 21, reply, reply_size);
1239         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
1240                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
1241                         hapd, buf + 14, reply, reply_size);
1242         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
1243                 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
1244                         hapd, buf + 21, reply, reply_size);
1245         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
1246                 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
1247                         reply_len = -1;
1248 #endif /* CONFIG_WPS_NFC */
1249 #endif /* CONFIG_WPS */
1250 #ifdef CONFIG_INTERWORKING
1251         } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
1252                 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
1253                         reply_len = -1;
1254         } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
1255                 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
1256                         reply_len = -1;
1257 #endif /* CONFIG_INTERWORKING */
1258 #ifdef CONFIG_WNM
1259         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
1260                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
1261                         reply_len = -1;
1262         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
1263                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
1264                         reply_len = -1;
1265 #endif /* CONFIG_WNM */
1266         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
1267                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
1268                                                           reply_size);
1269         } else if (os_strncmp(buf, "SET ", 4) == 0) {
1270                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
1271                         reply_len = -1;
1272         } else if (os_strncmp(buf, "GET ", 4) == 0) {
1273                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
1274                                                    reply_size);
1275         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
1276                 if (hostapd_ctrl_iface_enable(hapd->iface))
1277                         reply_len = -1;
1278         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
1279                 if (hostapd_ctrl_iface_reload(hapd->iface))
1280                         reply_len = -1;
1281         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
1282                 if (hostapd_ctrl_iface_disable(hapd->iface))
1283                         reply_len = -1;
1284 #ifdef CONFIG_TESTING_OPTIONS
1285         } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
1286                 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
1287                         reply_len = -1;
1288         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
1289                 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
1290                         reply_len = -1;
1291 #endif /* CONFIG_TESTING_OPTIONS */
1292         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
1293                 if (hostapd_ctrl_iface_chan_switch(hapd, buf + 12))
1294                         reply_len = -1;
1295         } else {
1296                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1297                 reply_len = 16;
1298         }
1299
1300         if (reply_len < 0) {
1301                 os_memcpy(reply, "FAIL\n", 5);
1302                 reply_len = 5;
1303         }
1304         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1305         os_free(reply);
1306 }
1307
1308
1309 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
1310 {
1311         char *buf;
1312         size_t len;
1313
1314         if (hapd->conf->ctrl_interface == NULL)
1315                 return NULL;
1316
1317         len = os_strlen(hapd->conf->ctrl_interface) +
1318                 os_strlen(hapd->conf->iface) + 2;
1319         buf = os_malloc(len);
1320         if (buf == NULL)
1321                 return NULL;
1322
1323         os_snprintf(buf, len, "%s/%s",
1324                     hapd->conf->ctrl_interface, hapd->conf->iface);
1325         buf[len - 1] = '\0';
1326         return buf;
1327 }
1328
1329
1330 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
1331                                       const char *txt, size_t len)
1332 {
1333         struct hostapd_data *hapd = ctx;
1334         if (hapd == NULL)
1335                 return;
1336         hostapd_ctrl_iface_send(hapd, level, txt, len);
1337 }
1338
1339
1340 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
1341 {
1342         struct sockaddr_un addr;
1343         int s = -1;
1344         char *fname = NULL;
1345
1346         if (hapd->ctrl_sock > -1) {
1347                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
1348                 return 0;
1349         }
1350
1351         if (hapd->conf->ctrl_interface == NULL)
1352                 return 0;
1353
1354         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1355                 if (errno == EEXIST) {
1356                         wpa_printf(MSG_DEBUG, "Using existing control "
1357                                    "interface directory.");
1358                 } else {
1359                         perror("mkdir[ctrl_interface]");
1360                         goto fail;
1361                 }
1362         }
1363
1364         if (hapd->conf->ctrl_interface_gid_set &&
1365             chown(hapd->conf->ctrl_interface, -1,
1366                   hapd->conf->ctrl_interface_gid) < 0) {
1367                 perror("chown[ctrl_interface]");
1368                 return -1;
1369         }
1370
1371         if (!hapd->conf->ctrl_interface_gid_set &&
1372             hapd->iface->interfaces->ctrl_iface_group &&
1373             chown(hapd->conf->ctrl_interface, -1,
1374                   hapd->iface->interfaces->ctrl_iface_group) < 0) {
1375                 perror("chown[ctrl_interface]");
1376                 return -1;
1377         }
1378
1379 #ifdef ANDROID
1380         /*
1381          * Android is using umask 0077 which would leave the control interface
1382          * directory without group access. This breaks things since Wi-Fi
1383          * framework assumes that this directory can be accessed by other
1384          * applications in the wifi group. Fix this by adding group access even
1385          * if umask value would prevent this.
1386          */
1387         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1388                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
1389                            strerror(errno));
1390                 /* Try to continue anyway */
1391         }
1392 #endif /* ANDROID */
1393
1394         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
1395             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
1396                 goto fail;
1397
1398         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1399         if (s < 0) {
1400                 perror("socket(PF_UNIX)");
1401                 goto fail;
1402         }
1403
1404         os_memset(&addr, 0, sizeof(addr));
1405 #ifdef __FreeBSD__
1406         addr.sun_len = sizeof(addr);
1407 #endif /* __FreeBSD__ */
1408         addr.sun_family = AF_UNIX;
1409         fname = hostapd_ctrl_iface_path(hapd);
1410         if (fname == NULL)
1411                 goto fail;
1412         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1413         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1414                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1415                            strerror(errno));
1416                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1417                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1418                                    " allow connections - assuming it was left"
1419                                    "over from forced program termination");
1420                         if (unlink(fname) < 0) {
1421                                 perror("unlink[ctrl_iface]");
1422                                 wpa_printf(MSG_ERROR, "Could not unlink "
1423                                            "existing ctrl_iface socket '%s'",
1424                                            fname);
1425                                 goto fail;
1426                         }
1427                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1428                             0) {
1429                                 perror("hostapd-ctrl-iface: bind(PF_UNIX)");
1430                                 goto fail;
1431                         }
1432                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1433                                    "ctrl_iface socket '%s'", fname);
1434                 } else {
1435                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1436                                    "be in use - cannot override it");
1437                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1438                                    "not used anymore", fname);
1439                         os_free(fname);
1440                         fname = NULL;
1441                         goto fail;
1442                 }
1443         }
1444
1445         if (hapd->conf->ctrl_interface_gid_set &&
1446             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
1447                 perror("chown[ctrl_interface/ifname]");
1448                 goto fail;
1449         }
1450
1451         if (!hapd->conf->ctrl_interface_gid_set &&
1452             hapd->iface->interfaces->ctrl_iface_group &&
1453             chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
1454                 perror("chown[ctrl_interface/ifname]");
1455                 goto fail;
1456         }
1457
1458         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1459                 perror("chmod[ctrl_interface/ifname]");
1460                 goto fail;
1461         }
1462         os_free(fname);
1463
1464         hapd->ctrl_sock = s;
1465         eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
1466                                  NULL);
1467         hapd->msg_ctx = hapd;
1468         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
1469
1470         return 0;
1471
1472 fail:
1473         if (s >= 0)
1474                 close(s);
1475         if (fname) {
1476                 unlink(fname);
1477                 os_free(fname);
1478         }
1479         return -1;
1480 }
1481
1482
1483 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
1484 {
1485         struct wpa_ctrl_dst *dst, *prev;
1486
1487         if (hapd->ctrl_sock > -1) {
1488                 char *fname;
1489                 eloop_unregister_read_sock(hapd->ctrl_sock);
1490                 close(hapd->ctrl_sock);
1491                 hapd->ctrl_sock = -1;
1492                 fname = hostapd_ctrl_iface_path(hapd);
1493                 if (fname)
1494                         unlink(fname);
1495                 os_free(fname);
1496
1497                 if (hapd->conf->ctrl_interface &&
1498                     rmdir(hapd->conf->ctrl_interface) < 0) {
1499                         if (errno == ENOTEMPTY) {
1500                                 wpa_printf(MSG_DEBUG, "Control interface "
1501                                            "directory not empty - leaving it "
1502                                            "behind");
1503                         } else {
1504                                 wpa_printf(MSG_ERROR,
1505                                            "rmdir[ctrl_interface=%s]: %s",
1506                                            hapd->conf->ctrl_interface,
1507                                            strerror(errno));
1508                         }
1509                 }
1510         }
1511
1512         dst = hapd->ctrl_dst;
1513         while (dst) {
1514                 prev = dst;
1515                 dst = dst->next;
1516                 os_free(prev);
1517         }
1518 }
1519
1520
1521 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
1522                                   char *buf)
1523 {
1524         if (hostapd_add_iface(interfaces, buf) < 0) {
1525                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
1526                 return -1;
1527         }
1528         return 0;
1529 }
1530
1531
1532 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
1533                                      char *buf)
1534 {
1535         if (hostapd_remove_iface(interfaces, buf) < 0) {
1536                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
1537                 return -1;
1538         }
1539         return 0;
1540 }
1541
1542
1543 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
1544                                               void *sock_ctx)
1545 {
1546         void *interfaces = eloop_ctx;
1547         char buf[256];
1548         int res;
1549         struct sockaddr_un from;
1550         socklen_t fromlen = sizeof(from);
1551         char reply[24];
1552         int reply_len;
1553
1554         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1555                        (struct sockaddr *) &from, &fromlen);
1556         if (res < 0) {
1557                 perror("recvfrom(ctrl_iface)");
1558                 return;
1559         }
1560         buf[res] = '\0';
1561         wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
1562
1563         os_memcpy(reply, "OK\n", 3);
1564         reply_len = 3;
1565
1566         if (os_strcmp(buf, "PING") == 0) {
1567                 os_memcpy(reply, "PONG\n", 5);
1568                 reply_len = 5;
1569         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
1570                 if (wpa_debug_reopen_file() < 0)
1571                         reply_len = -1;
1572         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
1573                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
1574                         reply_len = -1;
1575         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
1576                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
1577                         reply_len = -1;
1578         } else {
1579                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
1580                            "ignored");
1581                 reply_len = -1;
1582         }
1583
1584         if (reply_len < 0) {
1585                 os_memcpy(reply, "FAIL\n", 5);
1586                 reply_len = 5;
1587         }
1588
1589         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1590 }
1591
1592
1593 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
1594 {
1595         char *buf;
1596         size_t len;
1597
1598         if (interface->global_iface_path == NULL)
1599                 return NULL;
1600
1601         len = os_strlen(interface->global_iface_path) +
1602                 os_strlen(interface->global_iface_name) + 2;
1603         buf = os_malloc(len);
1604         if (buf == NULL)
1605                 return NULL;
1606
1607         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
1608                     interface->global_iface_name);
1609         buf[len - 1] = '\0';
1610         return buf;
1611 }
1612
1613
1614 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
1615 {
1616         struct sockaddr_un addr;
1617         int s = -1;
1618         char *fname = NULL;
1619
1620         if (interface->global_iface_path == NULL) {
1621                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
1622                 return 0;
1623         }
1624
1625         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
1626                 if (errno == EEXIST) {
1627                         wpa_printf(MSG_DEBUG, "Using existing control "
1628                                    "interface directory.");
1629                 } else {
1630                         perror("mkdir[ctrl_interface]");
1631                         goto fail;
1632                 }
1633         } else if (interface->ctrl_iface_group &&
1634                    chown(interface->global_iface_path, -1,
1635                          interface->ctrl_iface_group) < 0) {
1636                 perror("chown[ctrl_interface]");
1637                 goto fail;
1638         }
1639
1640         if (os_strlen(interface->global_iface_path) + 1 +
1641             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
1642                 goto fail;
1643
1644         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1645         if (s < 0) {
1646                 perror("socket(PF_UNIX)");
1647                 goto fail;
1648         }
1649
1650         os_memset(&addr, 0, sizeof(addr));
1651 #ifdef __FreeBSD__
1652         addr.sun_len = sizeof(addr);
1653 #endif /* __FreeBSD__ */
1654         addr.sun_family = AF_UNIX;
1655         fname = hostapd_global_ctrl_iface_path(interface);
1656         if (fname == NULL)
1657                 goto fail;
1658         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1659         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1660                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1661                            strerror(errno));
1662                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1663                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1664                                    " allow connections - assuming it was left"
1665                                    "over from forced program termination");
1666                         if (unlink(fname) < 0) {
1667                                 perror("unlink[ctrl_iface]");
1668                                 wpa_printf(MSG_ERROR, "Could not unlink "
1669                                            "existing ctrl_iface socket '%s'",
1670                                            fname);
1671                                 goto fail;
1672                         }
1673                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1674                             0) {
1675                                 perror("bind(PF_UNIX)");
1676                                 goto fail;
1677                         }
1678                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1679                                    "ctrl_iface socket '%s'", fname);
1680                 } else {
1681                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1682                                    "be in use - cannot override it");
1683                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1684                                    "not used anymore", fname);
1685                         os_free(fname);
1686                         fname = NULL;
1687                         goto fail;
1688                 }
1689         }
1690
1691         if (interface->ctrl_iface_group &&
1692             chown(fname, -1, interface->ctrl_iface_group) < 0) {
1693                 perror("chown[ctrl_interface]");
1694                 goto fail;
1695         }
1696
1697         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1698                 perror("chmod[ctrl_interface/ifname]");
1699                 goto fail;
1700         }
1701         os_free(fname);
1702
1703         interface->global_ctrl_sock = s;
1704         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
1705                                  interface, NULL);
1706
1707         return 0;
1708
1709 fail:
1710         if (s >= 0)
1711                 close(s);
1712         if (fname) {
1713                 unlink(fname);
1714                 os_free(fname);
1715         }
1716         return -1;
1717 }
1718
1719
1720 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
1721 {
1722         char *fname = NULL;
1723
1724         if (interfaces->global_ctrl_sock > -1) {
1725                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
1726                 close(interfaces->global_ctrl_sock);
1727                 interfaces->global_ctrl_sock = -1;
1728                 fname = hostapd_global_ctrl_iface_path(interfaces);
1729                 if (fname) {
1730                         unlink(fname);
1731                         os_free(fname);
1732                 }
1733
1734                 if (interfaces->global_iface_path &&
1735                     rmdir(interfaces->global_iface_path) < 0) {
1736                         if (errno == ENOTEMPTY) {
1737                                 wpa_printf(MSG_DEBUG, "Control interface "
1738                                            "directory not empty - leaving it "
1739                                            "behind");
1740                         } else {
1741                                 wpa_printf(MSG_ERROR,
1742                                            "rmdir[ctrl_interface=%s]: %s",
1743                                            interfaces->global_iface_path,
1744                                            strerror(errno));
1745                         }
1746                 }
1747                 os_free(interfaces->global_iface_path);
1748                 interfaces->global_iface_path = NULL;
1749         }
1750 }
1751
1752
1753 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
1754                                     const char *buf, size_t len)
1755 {
1756         struct wpa_ctrl_dst *dst, *next;
1757         struct msghdr msg;
1758         int idx;
1759         struct iovec io[2];
1760         char levelstr[10];
1761
1762         dst = hapd->ctrl_dst;
1763         if (hapd->ctrl_sock < 0 || dst == NULL)
1764                 return;
1765
1766         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
1767         io[0].iov_base = levelstr;
1768         io[0].iov_len = os_strlen(levelstr);
1769         io[1].iov_base = (char *) buf;
1770         io[1].iov_len = len;
1771         os_memset(&msg, 0, sizeof(msg));
1772         msg.msg_iov = io;
1773         msg.msg_iovlen = 2;
1774
1775         idx = 0;
1776         while (dst) {
1777                 next = dst->next;
1778                 if (level >= dst->debug_level) {
1779                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
1780                                     (u8 *) dst->addr.sun_path, dst->addrlen -
1781                                     offsetof(struct sockaddr_un, sun_path));
1782                         msg.msg_name = &dst->addr;
1783                         msg.msg_namelen = dst->addrlen;
1784                         if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
1785                                 int _errno = errno;
1786                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
1787                                            "%d - %s",
1788                                            idx, errno, strerror(errno));
1789                                 dst->errors++;
1790                                 if (dst->errors > 10 || _errno == ENOENT) {
1791                                         hostapd_ctrl_iface_detach(
1792                                                 hapd, &dst->addr,
1793                                                 dst->addrlen);
1794                                 }
1795                         } else
1796                                 dst->errors = 0;
1797                 }
1798                 idx++;
1799                 dst = next;
1800         }
1801 }
1802
1803 #endif /* CONFIG_NATIVE_WINDOWS */