Merge branch 'vendor/OPENBSD_LIBM'
[dragonfly.git] / contrib / hostapd / 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         size_t len;
403         struct wpabuf *req, *sel;
404         int ret;
405         char *pos, *role, *type, *pos2;
406
407         role = cmd;
408         pos = os_strchr(role, ' ');
409         if (pos == NULL)
410                 return -1;
411         *pos++ = '\0';
412
413         type = pos;
414         pos = os_strchr(type, ' ');
415         if (pos == NULL)
416                 return -1;
417         *pos++ = '\0';
418
419         pos2 = os_strchr(pos, ' ');
420         if (pos2 == NULL)
421                 return -1;
422         *pos2++ = '\0';
423
424         len = os_strlen(pos);
425         if (len & 0x01)
426                 return -1;
427         len /= 2;
428
429         req = wpabuf_alloc(len);
430         if (req == NULL)
431                 return -1;
432         if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
433                 wpabuf_free(req);
434                 return -1;
435         }
436
437         len = os_strlen(pos2);
438         if (len & 0x01) {
439                 wpabuf_free(req);
440                 return -1;
441         }
442         len /= 2;
443
444         sel = wpabuf_alloc(len);
445         if (sel == NULL) {
446                 wpabuf_free(req);
447                 return -1;
448         }
449         if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
450                 wpabuf_free(req);
451                 wpabuf_free(sel);
452                 return -1;
453         }
454
455         if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
456                 ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
457         } else {
458                 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
459                            "reported: role=%s type=%s", role, type);
460                 ret = -1;
461         }
462         wpabuf_free(req);
463         wpabuf_free(sel);
464
465         return ret;
466 }
467
468 #endif /* CONFIG_WPS_NFC */
469
470
471 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
472                                          char *buf, size_t buflen)
473 {
474         int timeout = 300;
475         char *pos;
476         const char *pin_txt;
477
478         pos = os_strchr(txt, ' ');
479         if (pos)
480                 *pos++ = '\0';
481
482         if (os_strcmp(txt, "disable") == 0) {
483                 hostapd_wps_ap_pin_disable(hapd);
484                 return os_snprintf(buf, buflen, "OK\n");
485         }
486
487         if (os_strcmp(txt, "random") == 0) {
488                 if (pos)
489                         timeout = atoi(pos);
490                 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
491                 if (pin_txt == NULL)
492                         return -1;
493                 return os_snprintf(buf, buflen, "%s", pin_txt);
494         }
495
496         if (os_strcmp(txt, "get") == 0) {
497                 pin_txt = hostapd_wps_ap_pin_get(hapd);
498                 if (pin_txt == NULL)
499                         return -1;
500                 return os_snprintf(buf, buflen, "%s", pin_txt);
501         }
502
503         if (os_strcmp(txt, "set") == 0) {
504                 char *pin;
505                 if (pos == NULL)
506                         return -1;
507                 pin = pos;
508                 pos = os_strchr(pos, ' ');
509                 if (pos) {
510                         *pos++ = '\0';
511                         timeout = atoi(pos);
512                 }
513                 if (os_strlen(pin) > buflen)
514                         return -1;
515                 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
516                         return -1;
517                 return os_snprintf(buf, buflen, "%s", pin);
518         }
519
520         return -1;
521 }
522
523
524 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
525 {
526         char *pos;
527         char *ssid, *auth, *encr = NULL, *key = NULL;
528
529         ssid = txt;
530         pos = os_strchr(txt, ' ');
531         if (!pos)
532                 return -1;
533         *pos++ = '\0';
534
535         auth = pos;
536         pos = os_strchr(pos, ' ');
537         if (pos) {
538                 *pos++ = '\0';
539                 encr = pos;
540                 pos = os_strchr(pos, ' ');
541                 if (pos) {
542                         *pos++ = '\0';
543                         key = pos;
544                 }
545         }
546
547         return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
548 }
549
550
551 static const char * pbc_status_str(enum pbc_status status)
552 {
553         switch (status) {
554         case WPS_PBC_STATUS_DISABLE:
555                 return "Disabled";
556         case WPS_PBC_STATUS_ACTIVE:
557                 return "Active";
558         case WPS_PBC_STATUS_TIMEOUT:
559                 return "Timed-out";
560         case WPS_PBC_STATUS_OVERLAP:
561                 return "Overlap";
562         default:
563                 return "Unknown";
564         }
565 }
566
567
568 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
569                                              char *buf, size_t buflen)
570 {
571         int ret;
572         char *pos, *end;
573
574         pos = buf;
575         end = buf + buflen;
576
577         ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
578                           pbc_status_str(hapd->wps_stats.pbc_status));
579
580         if (ret < 0 || ret >= end - pos)
581                 return pos - buf;
582         pos += ret;
583
584         ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
585                           (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
586                            "Success":
587                            (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
588                             "Failed" : "None")));
589
590         if (ret < 0 || ret >= end - pos)
591                 return pos - buf;
592         pos += ret;
593
594         /* If status == Failure - Add possible Reasons */
595         if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
596            hapd->wps_stats.failure_reason > 0) {
597                 ret = os_snprintf(pos, end - pos,
598                                   "Failure Reason: %s\n",
599                                   wps_ei_str(hapd->wps_stats.failure_reason));
600
601                 if (ret < 0 || ret >= end - pos)
602                         return pos - buf;
603                 pos += ret;
604         }
605
606         if (hapd->wps_stats.status) {
607                 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
608                                   MAC2STR(hapd->wps_stats.peer_addr));
609
610                 if (ret < 0 || ret >= end - pos)
611                         return pos - buf;
612                 pos += ret;
613         }
614
615         return pos - buf;
616 }
617
618 #endif /* CONFIG_WPS */
619
620
621 #ifdef CONFIG_INTERWORKING
622
623 static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
624                                               const char *cmd)
625 {
626         u8 qos_map_set[16 + 2 * 21], count = 0;
627         const char *pos = cmd;
628         int val, ret;
629
630         for (;;) {
631                 if (count == sizeof(qos_map_set)) {
632                         wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
633                         return -1;
634                 }
635
636                 val = atoi(pos);
637                 if (val < 0 || val > 255) {
638                         wpa_printf(MSG_INFO, "Invalid QoS Map Set");
639                         return -1;
640                 }
641
642                 qos_map_set[count++] = val;
643                 pos = os_strchr(pos, ',');
644                 if (!pos)
645                         break;
646                 pos++;
647         }
648
649         if (count < 16 || count & 1) {
650                 wpa_printf(MSG_INFO, "Invalid QoS Map Set");
651                 return -1;
652         }
653
654         ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
655         if (ret) {
656                 wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
657                 return -1;
658         }
659
660         os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
661         hapd->conf->qos_map_set_len = count;
662
663         return 0;
664 }
665
666
667 static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
668                                                 const char *cmd)
669 {
670         u8 addr[ETH_ALEN];
671         struct sta_info *sta;
672         struct wpabuf *buf;
673         u8 *qos_map_set = hapd->conf->qos_map_set;
674         u8 qos_map_set_len = hapd->conf->qos_map_set_len;
675         int ret;
676
677         if (!qos_map_set_len) {
678                 wpa_printf(MSG_INFO, "QoS Map Set is not set");
679                 return -1;
680         }
681
682         if (hwaddr_aton(cmd, addr))
683                 return -1;
684
685         sta = ap_get_sta(hapd, addr);
686         if (sta == NULL) {
687                 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
688                            "for QoS Map Configuration message",
689                            MAC2STR(addr));
690                 return -1;
691         }
692
693         if (!sta->qos_map_enabled) {
694                 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
695                            "support for QoS Map", MAC2STR(addr));
696                 return -1;
697         }
698
699         buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
700         if (buf == NULL)
701                 return -1;
702
703         wpabuf_put_u8(buf, WLAN_ACTION_QOS);
704         wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
705
706         /* QoS Map Set Element */
707         wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
708         wpabuf_put_u8(buf, qos_map_set_len);
709         wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
710
711         ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
712                                       wpabuf_head(buf), wpabuf_len(buf));
713         wpabuf_free(buf);
714
715         return ret;
716 }
717
718 #endif /* CONFIG_INTERWORKING */
719
720
721 #ifdef CONFIG_WNM
722
723 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
724                                                 const char *cmd)
725 {
726         u8 addr[ETH_ALEN];
727         int disassoc_timer;
728         struct sta_info *sta;
729
730         if (hwaddr_aton(cmd, addr))
731                 return -1;
732         if (cmd[17] != ' ')
733                 return -1;
734         disassoc_timer = atoi(cmd + 17);
735
736         sta = ap_get_sta(hapd, addr);
737         if (sta == NULL) {
738                 wpa_printf(MSG_DEBUG, "Station " MACSTR
739                            " not found for disassociation imminent message",
740                            MAC2STR(addr));
741                 return -1;
742         }
743
744         return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
745 }
746
747
748 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
749                                            const char *cmd)
750 {
751         u8 addr[ETH_ALEN];
752         const char *url, *timerstr;
753         int disassoc_timer;
754         struct sta_info *sta;
755
756         if (hwaddr_aton(cmd, addr))
757                 return -1;
758
759         sta = ap_get_sta(hapd, addr);
760         if (sta == NULL) {
761                 wpa_printf(MSG_DEBUG, "Station " MACSTR
762                            " not found for ESS disassociation imminent message",
763                            MAC2STR(addr));
764                 return -1;
765         }
766
767         timerstr = cmd + 17;
768         if (*timerstr != ' ')
769                 return -1;
770         timerstr++;
771         disassoc_timer = atoi(timerstr);
772         if (disassoc_timer < 0 || disassoc_timer > 65535)
773                 return -1;
774
775         url = os_strchr(timerstr, ' ');
776         if (url == NULL)
777                 return -1;
778         url++;
779
780         return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
781 }
782
783 #endif /* CONFIG_WNM */
784
785
786 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
787                                          char *buf, size_t buflen)
788 {
789         int ret;
790         char *pos, *end;
791
792         pos = buf;
793         end = buf + buflen;
794
795         ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
796                           "ssid=%s\n",
797                           MAC2STR(hapd->own_addr),
798                           wpa_ssid_txt(hapd->conf->ssid.ssid,
799                                        hapd->conf->ssid.ssid_len));
800         if (ret < 0 || ret >= end - pos)
801                 return pos - buf;
802         pos += ret;
803
804 #ifdef CONFIG_WPS
805         ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
806                           hapd->conf->wps_state == 0 ? "disabled" :
807                           (hapd->conf->wps_state == 1 ? "not configured" :
808                            "configured"));
809         if (ret < 0 || ret >= end - pos)
810                 return pos - buf;
811         pos += ret;
812
813         if (hapd->conf->wps_state && hapd->conf->wpa &&
814             hapd->conf->ssid.wpa_passphrase) {
815                 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
816                                   hapd->conf->ssid.wpa_passphrase);
817                 if (ret < 0 || ret >= end - pos)
818                         return pos - buf;
819                 pos += ret;
820         }
821
822         if (hapd->conf->wps_state && hapd->conf->wpa &&
823             hapd->conf->ssid.wpa_psk &&
824             hapd->conf->ssid.wpa_psk->group) {
825                 char hex[PMK_LEN * 2 + 1];
826                 wpa_snprintf_hex(hex, sizeof(hex),
827                                  hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
828                 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
829                 if (ret < 0 || ret >= end - pos)
830                         return pos - buf;
831                 pos += ret;
832         }
833 #endif /* CONFIG_WPS */
834
835         if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
836                 ret = os_snprintf(pos, end - pos, "key_mgmt=");
837                 if (ret < 0 || ret >= end - pos)
838                         return pos - buf;
839                 pos += ret;
840
841                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
842                         ret = os_snprintf(pos, end - pos, "WPA-PSK ");
843                         if (ret < 0 || ret >= end - pos)
844                                 return pos - buf;
845                         pos += ret;
846                 }
847                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
848                         ret = os_snprintf(pos, end - pos, "WPA-EAP ");
849                         if (ret < 0 || ret >= end - pos)
850                                 return pos - buf;
851                         pos += ret;
852                 }
853 #ifdef CONFIG_IEEE80211R
854                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
855                         ret = os_snprintf(pos, end - pos, "FT-PSK ");
856                         if (ret < 0 || ret >= end - pos)
857                                 return pos - buf;
858                         pos += ret;
859                 }
860                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
861                         ret = os_snprintf(pos, end - pos, "FT-EAP ");
862                         if (ret < 0 || ret >= end - pos)
863                                 return pos - buf;
864                         pos += ret;
865                 }
866 #endif /* CONFIG_IEEE80211R */
867 #ifdef CONFIG_IEEE80211W
868                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
869                         ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
870                         if (ret < 0 || ret >= end - pos)
871                                 return pos - buf;
872                         pos += ret;
873                 }
874                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
875                         ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
876                         if (ret < 0 || ret >= end - pos)
877                                 return pos - buf;
878                         pos += ret;
879                 }
880 #endif /* CONFIG_IEEE80211W */
881
882                 ret = os_snprintf(pos, end - pos, "\n");
883                 if (ret < 0 || ret >= end - pos)
884                         return pos - buf;
885                 pos += ret;
886         }
887
888         if (hapd->conf->wpa) {
889                 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
890                                   wpa_cipher_txt(hapd->conf->wpa_group));
891                 if (ret < 0 || ret >= end - pos)
892                         return pos - buf;
893                 pos += ret;
894         }
895
896         if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
897                 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
898                 if (ret < 0 || ret >= end - pos)
899                         return pos - buf;
900                 pos += ret;
901
902                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
903                                         " ");
904                 if (ret < 0)
905                         return pos - buf;
906                 pos += ret;
907
908                 ret = os_snprintf(pos, end - pos, "\n");
909                 if (ret < 0 || ret >= end - pos)
910                         return pos - buf;
911                 pos += ret;
912         }
913
914         if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
915                 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
916                 if (ret < 0 || ret >= end - pos)
917                         return pos - buf;
918                 pos += ret;
919
920                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
921                                         " ");
922                 if (ret < 0)
923                         return pos - buf;
924                 pos += ret;
925
926                 ret = os_snprintf(pos, end - pos, "\n");
927                 if (ret < 0 || ret >= end - pos)
928                         return pos - buf;
929                 pos += ret;
930         }
931
932         return pos - buf;
933 }
934
935
936 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
937 {
938         char *value;
939         int ret = 0;
940
941         value = os_strchr(cmd, ' ');
942         if (value == NULL)
943                 return -1;
944         *value++ = '\0';
945
946         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
947         if (0) {
948 #ifdef CONFIG_WPS_TESTING
949         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
950                 long int val;
951                 val = strtol(value, NULL, 0);
952                 if (val < 0 || val > 0xff) {
953                         ret = -1;
954                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
955                                    "wps_version_number %ld", val);
956                 } else {
957                         wps_version_number = val;
958                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
959                                    "version %u.%u",
960                                    (wps_version_number & 0xf0) >> 4,
961                                    wps_version_number & 0x0f);
962                         hostapd_wps_update_ie(hapd);
963                 }
964         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
965                 wps_testing_dummy_cred = atoi(value);
966                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
967                            wps_testing_dummy_cred);
968         } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
969                 wps_corrupt_pkhash = atoi(value);
970                 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
971                            wps_corrupt_pkhash);
972 #endif /* CONFIG_WPS_TESTING */
973 #ifdef CONFIG_INTERWORKING
974         } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
975                 int val = atoi(value);
976                 if (val <= 0)
977                         ret = -1;
978                 else
979                         hapd->gas_frag_limit = val;
980 #endif /* CONFIG_INTERWORKING */
981 #ifdef CONFIG_TESTING_OPTIONS
982         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
983                 hapd->ext_mgmt_frame_handling = atoi(value);
984 #endif /* CONFIG_TESTING_OPTIONS */
985         } else {
986                 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
987         }
988
989         return ret;
990 }
991
992
993 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
994                                   char *buf, size_t buflen)
995 {
996         int res;
997
998         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
999
1000         if (os_strcmp(cmd, "version") == 0) {
1001                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
1002                 if (res < 0 || (unsigned int) res >= buflen)
1003                         return -1;
1004                 return res;
1005         }
1006
1007         return -1;
1008 }
1009
1010
1011 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
1012 {
1013         if (hostapd_enable_iface(iface) < 0) {
1014                 wpa_printf(MSG_ERROR, "Enabling of interface failed");
1015                 return -1;
1016         }
1017         return 0;
1018 }
1019
1020
1021 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
1022 {
1023         if (hostapd_reload_iface(iface) < 0) {
1024                 wpa_printf(MSG_ERROR, "Reloading of interface failed");
1025                 return -1;
1026         }
1027         return 0;
1028 }
1029
1030
1031 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
1032 {
1033         if (hostapd_disable_iface(iface) < 0) {
1034                 wpa_printf(MSG_ERROR, "Disabling of interface failed");
1035                 return -1;
1036         }
1037         return 0;
1038 }
1039
1040
1041 #ifdef CONFIG_TESTING_OPTIONS
1042
1043 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
1044 {
1045         union wpa_event_data data;
1046         char *pos, *param;
1047         enum wpa_event_type event;
1048
1049         wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1050
1051         os_memset(&data, 0, sizeof(data));
1052
1053         param = os_strchr(cmd, ' ');
1054         if (param == NULL)
1055                 return -1;
1056         *param++ = '\0';
1057
1058         if (os_strcmp(cmd, "DETECTED") == 0)
1059                 event = EVENT_DFS_RADAR_DETECTED;
1060         else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1061                 event = EVENT_DFS_CAC_FINISHED;
1062         else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1063                 event = EVENT_DFS_CAC_ABORTED;
1064         else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1065                 event = EVENT_DFS_NOP_FINISHED;
1066         else {
1067                 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1068                            cmd);
1069                 return -1;
1070         }
1071
1072         pos = os_strstr(param, "freq=");
1073         if (pos)
1074                 data.dfs_event.freq = atoi(pos + 5);
1075
1076         pos = os_strstr(param, "ht_enabled=1");
1077         if (pos)
1078                 data.dfs_event.ht_enabled = 1;
1079
1080         pos = os_strstr(param, "chan_offset=");
1081         if (pos)
1082                 data.dfs_event.chan_offset = atoi(pos + 12);
1083
1084         pos = os_strstr(param, "chan_width=");
1085         if (pos)
1086                 data.dfs_event.chan_width = atoi(pos + 11);
1087
1088         pos = os_strstr(param, "cf1=");
1089         if (pos)
1090                 data.dfs_event.cf1 = atoi(pos + 4);
1091
1092         pos = os_strstr(param, "cf2=");
1093         if (pos)
1094                 data.dfs_event.cf2 = atoi(pos + 4);
1095
1096         wpa_supplicant_event(hapd, event, &data);
1097
1098         return 0;
1099 }
1100
1101
1102 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
1103 {
1104         size_t len;
1105         u8 *buf;
1106         int res;
1107
1108         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
1109
1110         len = os_strlen(cmd);
1111         if (len & 1)
1112                 return -1;
1113         len /= 2;
1114
1115         buf = os_malloc(len);
1116         if (buf == NULL)
1117                 return -1;
1118
1119         if (hexstr2bin(cmd, buf, len) < 0) {
1120                 os_free(buf);
1121                 return -1;
1122         }
1123
1124         res = hostapd_drv_send_mlme(hapd, buf, len, 0);
1125         os_free(buf);
1126         return res;
1127 }
1128
1129 #endif /* CONFIG_TESTING_OPTIONS */
1130
1131
1132 static int hostapd_ctrl_iface_chan_switch(struct hostapd_data *hapd, char *pos)
1133 {
1134 #ifdef NEED_AP_MLME
1135         struct csa_settings settings;
1136         int ret = hostapd_parse_csa_settings(pos, &settings);
1137
1138         if (ret)
1139                 return ret;
1140
1141         return hostapd_switch_channel(hapd, &settings);
1142 #else /* NEED_AP_MLME */
1143         return -1;
1144 #endif /* NEED_AP_MLME */
1145 }
1146
1147
1148 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
1149                                   int reply_size, const char *param)
1150 {
1151 #ifdef RADIUS_SERVER
1152         if (os_strcmp(param, "radius_server") == 0) {
1153                 return radius_server_get_mib(hapd->radius_srv, reply,
1154                                              reply_size);
1155         }
1156 #endif /* RADIUS_SERVER */
1157         return -1;
1158 }
1159
1160
1161 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
1162                                        void *sock_ctx)
1163 {
1164         struct hostapd_data *hapd = eloop_ctx;
1165         char buf[4096];
1166         int res;
1167         struct sockaddr_un from;
1168         socklen_t fromlen = sizeof(from);
1169         char *reply;
1170         const int reply_size = 4096;
1171         int reply_len;
1172         int level = MSG_DEBUG;
1173
1174         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1175                        (struct sockaddr *) &from, &fromlen);
1176         if (res < 0) {
1177                 perror("recvfrom(ctrl_iface)");
1178                 return;
1179         }
1180         buf[res] = '\0';
1181         if (os_strcmp(buf, "PING") == 0)
1182                 level = MSG_EXCESSIVE;
1183         wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
1184
1185         reply = os_malloc(reply_size);
1186         if (reply == NULL) {
1187                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
1188                        fromlen);
1189                 return;
1190         }
1191
1192         os_memcpy(reply, "OK\n", 3);
1193         reply_len = 3;
1194
1195         if (os_strcmp(buf, "PING") == 0) {
1196                 os_memcpy(reply, "PONG\n", 5);
1197                 reply_len = 5;
1198         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
1199                 if (wpa_debug_reopen_file() < 0)
1200                         reply_len = -1;
1201         } else if (os_strcmp(buf, "STATUS") == 0) {
1202                 reply_len = hostapd_ctrl_iface_status(hapd, reply,
1203                                                       reply_size);
1204         } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
1205                 reply_len = hostapd_drv_status(hapd, reply, reply_size);
1206         } else if (os_strcmp(buf, "MIB") == 0) {
1207                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
1208                 if (reply_len >= 0) {
1209                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
1210                                           reply_size - reply_len);
1211                         if (res < 0)
1212                                 reply_len = -1;
1213                         else
1214                                 reply_len += res;
1215                 }
1216                 if (reply_len >= 0) {
1217                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
1218                                                  reply_size - reply_len);
1219                         if (res < 0)
1220                                 reply_len = -1;
1221                         else
1222                                 reply_len += res;
1223                 }
1224 #ifndef CONFIG_NO_RADIUS
1225                 if (reply_len >= 0) {
1226                         res = radius_client_get_mib(hapd->radius,
1227                                                     reply + reply_len,
1228                                                     reply_size - reply_len);
1229                         if (res < 0)
1230                                 reply_len = -1;
1231                         else
1232                                 reply_len += res;
1233                 }
1234 #endif /* CONFIG_NO_RADIUS */
1235         } else if (os_strncmp(buf, "MIB ", 4) == 0) {
1236                 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
1237                                                    buf + 4);
1238         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
1239                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
1240                                                          reply_size);
1241         } else if (os_strncmp(buf, "STA ", 4) == 0) {
1242                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
1243                                                    reply_size);
1244         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
1245                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
1246                                                         reply_size);
1247         } else if (os_strcmp(buf, "ATTACH") == 0) {
1248                 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
1249                         reply_len = -1;
1250         } else if (os_strcmp(buf, "DETACH") == 0) {
1251                 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
1252                         reply_len = -1;
1253         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
1254                 if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
1255                                                     buf + 6))
1256                         reply_len = -1;
1257         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
1258                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
1259                         reply_len = -1;
1260         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
1261                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
1262                         reply_len = -1;
1263         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
1264                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
1265                         reply_len = -1;
1266 #ifdef CONFIG_IEEE80211W
1267 #ifdef NEED_AP_MLME
1268         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
1269                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
1270                         reply_len = -1;
1271 #endif /* NEED_AP_MLME */
1272 #endif /* CONFIG_IEEE80211W */
1273 #ifdef CONFIG_WPS
1274         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
1275                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
1276                         reply_len = -1;
1277         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
1278                 reply_len = hostapd_ctrl_iface_wps_check_pin(
1279                         hapd, buf + 14, reply, reply_size);
1280         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
1281                 if (hostapd_wps_button_pushed(hapd, NULL))
1282                         reply_len = -1;
1283         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
1284                 if (hostapd_wps_cancel(hapd))
1285                         reply_len = -1;
1286         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
1287                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
1288                                                           reply, reply_size);
1289         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
1290                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
1291                         reply_len = -1;
1292         } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
1293                 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
1294                                                               reply_size);
1295 #ifdef CONFIG_WPS_NFC
1296         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
1297                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
1298                         reply_len = -1;
1299         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
1300                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
1301                         hapd, buf + 21, reply, reply_size);
1302         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
1303                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
1304                         hapd, buf + 14, reply, reply_size);
1305         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
1306                 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
1307                         hapd, buf + 21, reply, reply_size);
1308         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
1309                 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
1310                         reply_len = -1;
1311 #endif /* CONFIG_WPS_NFC */
1312 #endif /* CONFIG_WPS */
1313 #ifdef CONFIG_INTERWORKING
1314         } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
1315                 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
1316                         reply_len = -1;
1317         } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
1318                 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
1319                         reply_len = -1;
1320 #endif /* CONFIG_INTERWORKING */
1321 #ifdef CONFIG_WNM
1322         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
1323                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
1324                         reply_len = -1;
1325         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
1326                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
1327                         reply_len = -1;
1328 #endif /* CONFIG_WNM */
1329         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
1330                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
1331                                                           reply_size);
1332         } else if (os_strncmp(buf, "SET ", 4) == 0) {
1333                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
1334                         reply_len = -1;
1335         } else if (os_strncmp(buf, "GET ", 4) == 0) {
1336                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
1337                                                    reply_size);
1338         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
1339                 if (hostapd_ctrl_iface_enable(hapd->iface))
1340                         reply_len = -1;
1341         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
1342                 if (hostapd_ctrl_iface_reload(hapd->iface))
1343                         reply_len = -1;
1344         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
1345                 if (hostapd_ctrl_iface_disable(hapd->iface))
1346                         reply_len = -1;
1347 #ifdef CONFIG_TESTING_OPTIONS
1348         } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
1349                 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
1350                         reply_len = -1;
1351         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
1352                 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
1353                         reply_len = -1;
1354 #endif /* CONFIG_TESTING_OPTIONS */
1355         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
1356                 if (hostapd_ctrl_iface_chan_switch(hapd, buf + 12))
1357                         reply_len = -1;
1358         } else {
1359                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1360                 reply_len = 16;
1361         }
1362
1363         if (reply_len < 0) {
1364                 os_memcpy(reply, "FAIL\n", 5);
1365                 reply_len = 5;
1366         }
1367         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1368         os_free(reply);
1369 }
1370
1371
1372 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
1373 {
1374         char *buf;
1375         size_t len;
1376
1377         if (hapd->conf->ctrl_interface == NULL)
1378                 return NULL;
1379
1380         len = os_strlen(hapd->conf->ctrl_interface) +
1381                 os_strlen(hapd->conf->iface) + 2;
1382         buf = os_malloc(len);
1383         if (buf == NULL)
1384                 return NULL;
1385
1386         os_snprintf(buf, len, "%s/%s",
1387                     hapd->conf->ctrl_interface, hapd->conf->iface);
1388         buf[len - 1] = '\0';
1389         return buf;
1390 }
1391
1392
1393 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
1394                                       const char *txt, size_t len)
1395 {
1396         struct hostapd_data *hapd = ctx;
1397         if (hapd == NULL)
1398                 return;
1399         hostapd_ctrl_iface_send(hapd, level, txt, len);
1400 }
1401
1402
1403 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
1404 {
1405         struct sockaddr_un addr;
1406         int s = -1;
1407         char *fname = NULL;
1408
1409         if (hapd->ctrl_sock > -1) {
1410                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
1411                 return 0;
1412         }
1413
1414         if (hapd->conf->ctrl_interface == NULL)
1415                 return 0;
1416
1417         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1418                 if (errno == EEXIST) {
1419                         wpa_printf(MSG_DEBUG, "Using existing control "
1420                                    "interface directory.");
1421                 } else {
1422                         perror("mkdir[ctrl_interface]");
1423                         goto fail;
1424                 }
1425         }
1426
1427         if (hapd->conf->ctrl_interface_gid_set &&
1428             chown(hapd->conf->ctrl_interface, -1,
1429                   hapd->conf->ctrl_interface_gid) < 0) {
1430                 perror("chown[ctrl_interface]");
1431                 return -1;
1432         }
1433
1434         if (!hapd->conf->ctrl_interface_gid_set &&
1435             hapd->iface->interfaces->ctrl_iface_group &&
1436             chown(hapd->conf->ctrl_interface, -1,
1437                   hapd->iface->interfaces->ctrl_iface_group) < 0) {
1438                 perror("chown[ctrl_interface]");
1439                 return -1;
1440         }
1441
1442 #ifdef ANDROID
1443         /*
1444          * Android is using umask 0077 which would leave the control interface
1445          * directory without group access. This breaks things since Wi-Fi
1446          * framework assumes that this directory can be accessed by other
1447          * applications in the wifi group. Fix this by adding group access even
1448          * if umask value would prevent this.
1449          */
1450         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1451                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
1452                            strerror(errno));
1453                 /* Try to continue anyway */
1454         }
1455 #endif /* ANDROID */
1456
1457         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
1458             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
1459                 goto fail;
1460
1461         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1462         if (s < 0) {
1463                 perror("socket(PF_UNIX)");
1464                 goto fail;
1465         }
1466
1467         os_memset(&addr, 0, sizeof(addr));
1468 #ifdef __FreeBSD__
1469         addr.sun_len = sizeof(addr);
1470 #endif /* __FreeBSD__ */
1471         addr.sun_family = AF_UNIX;
1472         fname = hostapd_ctrl_iface_path(hapd);
1473         if (fname == NULL)
1474                 goto fail;
1475         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1476         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1477                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1478                            strerror(errno));
1479                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1480                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1481                                    " allow connections - assuming it was left"
1482                                    "over from forced program termination");
1483                         if (unlink(fname) < 0) {
1484                                 perror("unlink[ctrl_iface]");
1485                                 wpa_printf(MSG_ERROR, "Could not unlink "
1486                                            "existing ctrl_iface socket '%s'",
1487                                            fname);
1488                                 goto fail;
1489                         }
1490                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1491                             0) {
1492                                 perror("hostapd-ctrl-iface: bind(PF_UNIX)");
1493                                 goto fail;
1494                         }
1495                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1496                                    "ctrl_iface socket '%s'", fname);
1497                 } else {
1498                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1499                                    "be in use - cannot override it");
1500                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1501                                    "not used anymore", fname);
1502                         os_free(fname);
1503                         fname = NULL;
1504                         goto fail;
1505                 }
1506         }
1507
1508         if (hapd->conf->ctrl_interface_gid_set &&
1509             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
1510                 perror("chown[ctrl_interface/ifname]");
1511                 goto fail;
1512         }
1513
1514         if (!hapd->conf->ctrl_interface_gid_set &&
1515             hapd->iface->interfaces->ctrl_iface_group &&
1516             chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
1517                 perror("chown[ctrl_interface/ifname]");
1518                 goto fail;
1519         }
1520
1521         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1522                 perror("chmod[ctrl_interface/ifname]");
1523                 goto fail;
1524         }
1525         os_free(fname);
1526
1527         hapd->ctrl_sock = s;
1528         eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
1529                                  NULL);
1530         hapd->msg_ctx = hapd;
1531         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
1532
1533         return 0;
1534
1535 fail:
1536         if (s >= 0)
1537                 close(s);
1538         if (fname) {
1539                 unlink(fname);
1540                 os_free(fname);
1541         }
1542         return -1;
1543 }
1544
1545
1546 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
1547 {
1548         struct wpa_ctrl_dst *dst, *prev;
1549
1550         if (hapd->ctrl_sock > -1) {
1551                 char *fname;
1552                 eloop_unregister_read_sock(hapd->ctrl_sock);
1553                 close(hapd->ctrl_sock);
1554                 hapd->ctrl_sock = -1;
1555                 fname = hostapd_ctrl_iface_path(hapd);
1556                 if (fname)
1557                         unlink(fname);
1558                 os_free(fname);
1559
1560                 if (hapd->conf->ctrl_interface &&
1561                     rmdir(hapd->conf->ctrl_interface) < 0) {
1562                         if (errno == ENOTEMPTY) {
1563                                 wpa_printf(MSG_DEBUG, "Control interface "
1564                                            "directory not empty - leaving it "
1565                                            "behind");
1566                         } else {
1567                                 wpa_printf(MSG_ERROR,
1568                                            "rmdir[ctrl_interface=%s]: %s",
1569                                            hapd->conf->ctrl_interface,
1570                                            strerror(errno));
1571                         }
1572                 }
1573         }
1574
1575         dst = hapd->ctrl_dst;
1576         while (dst) {
1577                 prev = dst;
1578                 dst = dst->next;
1579                 os_free(prev);
1580         }
1581 }
1582
1583
1584 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
1585                                   char *buf)
1586 {
1587         if (hostapd_add_iface(interfaces, buf) < 0) {
1588                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
1589                 return -1;
1590         }
1591         return 0;
1592 }
1593
1594
1595 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
1596                                      char *buf)
1597 {
1598         if (hostapd_remove_iface(interfaces, buf) < 0) {
1599                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
1600                 return -1;
1601         }
1602         return 0;
1603 }
1604
1605
1606 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
1607 {
1608 #ifdef CONFIG_WPS_TESTING
1609         wps_version_number = 0x20;
1610         wps_testing_dummy_cred = 0;
1611         wps_corrupt_pkhash = 0;
1612 #endif /* CONFIG_WPS_TESTING */
1613 }
1614
1615
1616 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
1617                                               void *sock_ctx)
1618 {
1619         void *interfaces = eloop_ctx;
1620         char buf[256];
1621         int res;
1622         struct sockaddr_un from;
1623         socklen_t fromlen = sizeof(from);
1624         char reply[24];
1625         int reply_len;
1626
1627         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1628                        (struct sockaddr *) &from, &fromlen);
1629         if (res < 0) {
1630                 perror("recvfrom(ctrl_iface)");
1631                 return;
1632         }
1633         buf[res] = '\0';
1634         wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
1635
1636         os_memcpy(reply, "OK\n", 3);
1637         reply_len = 3;
1638
1639         if (os_strcmp(buf, "PING") == 0) {
1640                 os_memcpy(reply, "PONG\n", 5);
1641                 reply_len = 5;
1642         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
1643                 if (wpa_debug_reopen_file() < 0)
1644                         reply_len = -1;
1645         } else if (os_strcmp(buf, "FLUSH") == 0) {
1646                 hostapd_ctrl_iface_flush(interfaces);
1647         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
1648                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
1649                         reply_len = -1;
1650         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
1651                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
1652                         reply_len = -1;
1653         } else {
1654                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
1655                            "ignored");
1656                 reply_len = -1;
1657         }
1658
1659         if (reply_len < 0) {
1660                 os_memcpy(reply, "FAIL\n", 5);
1661                 reply_len = 5;
1662         }
1663
1664         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1665 }
1666
1667
1668 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
1669 {
1670         char *buf;
1671         size_t len;
1672
1673         if (interface->global_iface_path == NULL)
1674                 return NULL;
1675
1676         len = os_strlen(interface->global_iface_path) +
1677                 os_strlen(interface->global_iface_name) + 2;
1678         buf = os_malloc(len);
1679         if (buf == NULL)
1680                 return NULL;
1681
1682         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
1683                     interface->global_iface_name);
1684         buf[len - 1] = '\0';
1685         return buf;
1686 }
1687
1688
1689 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
1690 {
1691         struct sockaddr_un addr;
1692         int s = -1;
1693         char *fname = NULL;
1694
1695         if (interface->global_iface_path == NULL) {
1696                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
1697                 return 0;
1698         }
1699
1700         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
1701                 if (errno == EEXIST) {
1702                         wpa_printf(MSG_DEBUG, "Using existing control "
1703                                    "interface directory.");
1704                 } else {
1705                         perror("mkdir[ctrl_interface]");
1706                         goto fail;
1707                 }
1708         } else if (interface->ctrl_iface_group &&
1709                    chown(interface->global_iface_path, -1,
1710                          interface->ctrl_iface_group) < 0) {
1711                 perror("chown[ctrl_interface]");
1712                 goto fail;
1713         }
1714
1715         if (os_strlen(interface->global_iface_path) + 1 +
1716             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
1717                 goto fail;
1718
1719         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1720         if (s < 0) {
1721                 perror("socket(PF_UNIX)");
1722                 goto fail;
1723         }
1724
1725         os_memset(&addr, 0, sizeof(addr));
1726 #ifdef __FreeBSD__
1727         addr.sun_len = sizeof(addr);
1728 #endif /* __FreeBSD__ */
1729         addr.sun_family = AF_UNIX;
1730         fname = hostapd_global_ctrl_iface_path(interface);
1731         if (fname == NULL)
1732                 goto fail;
1733         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
1734         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1735                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
1736                            strerror(errno));
1737                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1738                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1739                                    " allow connections - assuming it was left"
1740                                    "over from forced program termination");
1741                         if (unlink(fname) < 0) {
1742                                 perror("unlink[ctrl_iface]");
1743                                 wpa_printf(MSG_ERROR, "Could not unlink "
1744                                            "existing ctrl_iface socket '%s'",
1745                                            fname);
1746                                 goto fail;
1747                         }
1748                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1749                             0) {
1750                                 perror("bind(PF_UNIX)");
1751                                 goto fail;
1752                         }
1753                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1754                                    "ctrl_iface socket '%s'", fname);
1755                 } else {
1756                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1757                                    "be in use - cannot override it");
1758                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1759                                    "not used anymore", fname);
1760                         os_free(fname);
1761                         fname = NULL;
1762                         goto fail;
1763                 }
1764         }
1765
1766         if (interface->ctrl_iface_group &&
1767             chown(fname, -1, interface->ctrl_iface_group) < 0) {
1768                 perror("chown[ctrl_interface]");
1769                 goto fail;
1770         }
1771
1772         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1773                 perror("chmod[ctrl_interface/ifname]");
1774                 goto fail;
1775         }
1776         os_free(fname);
1777
1778         interface->global_ctrl_sock = s;
1779         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
1780                                  interface, NULL);
1781
1782         return 0;
1783
1784 fail:
1785         if (s >= 0)
1786                 close(s);
1787         if (fname) {
1788                 unlink(fname);
1789                 os_free(fname);
1790         }
1791         return -1;
1792 }
1793
1794
1795 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
1796 {
1797         char *fname = NULL;
1798
1799         if (interfaces->global_ctrl_sock > -1) {
1800                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
1801                 close(interfaces->global_ctrl_sock);
1802                 interfaces->global_ctrl_sock = -1;
1803                 fname = hostapd_global_ctrl_iface_path(interfaces);
1804                 if (fname) {
1805                         unlink(fname);
1806                         os_free(fname);
1807                 }
1808
1809                 if (interfaces->global_iface_path &&
1810                     rmdir(interfaces->global_iface_path) < 0) {
1811                         if (errno == ENOTEMPTY) {
1812                                 wpa_printf(MSG_DEBUG, "Control interface "
1813                                            "directory not empty - leaving it "
1814                                            "behind");
1815                         } else {
1816                                 wpa_printf(MSG_ERROR,
1817                                            "rmdir[ctrl_interface=%s]: %s",
1818                                            interfaces->global_iface_path,
1819                                            strerror(errno));
1820                         }
1821                 }
1822                 os_free(interfaces->global_iface_path);
1823                 interfaces->global_iface_path = NULL;
1824         }
1825 }
1826
1827
1828 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
1829                                     const char *buf, size_t len)
1830 {
1831         struct wpa_ctrl_dst *dst, *next;
1832         struct msghdr msg;
1833         int idx;
1834         struct iovec io[2];
1835         char levelstr[10];
1836
1837         dst = hapd->ctrl_dst;
1838         if (hapd->ctrl_sock < 0 || dst == NULL)
1839                 return;
1840
1841         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
1842         io[0].iov_base = levelstr;
1843         io[0].iov_len = os_strlen(levelstr);
1844         io[1].iov_base = (char *) buf;
1845         io[1].iov_len = len;
1846         os_memset(&msg, 0, sizeof(msg));
1847         msg.msg_iov = io;
1848         msg.msg_iovlen = 2;
1849
1850         idx = 0;
1851         while (dst) {
1852                 next = dst->next;
1853                 if (level >= dst->debug_level) {
1854                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
1855                                     (u8 *) dst->addr.sun_path, dst->addrlen -
1856                                     offsetof(struct sockaddr_un, sun_path));
1857                         msg.msg_name = &dst->addr;
1858                         msg.msg_namelen = dst->addrlen;
1859                         if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
1860                                 int _errno = errno;
1861                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
1862                                            "%d - %s",
1863                                            idx, errno, strerror(errno));
1864                                 dst->errors++;
1865                                 if (dst->errors > 10 || _errno == ENOENT) {
1866                                         hostapd_ctrl_iface_detach(
1867                                                 hapd, &dst->addr,
1868                                                 dst->addrlen);
1869                                 }
1870                         } else
1871                                 dst->errors = 0;
1872                 }
1873                 idx++;
1874                 dst = next;
1875         }
1876 }
1877
1878 #endif /* CONFIG_NATIVE_WINDOWS */