WNM: Move ESS Disassoc Imminent sending to a helper function
[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 "ap/hostapd.h"
24 #include "ap/ap_config.h"
25 #include "ap/ieee802_1x.h"
26 #include "ap/wpa_auth.h"
27 #include "ap/ieee802_11.h"
28 #include "ap/sta_info.h"
29 #include "ap/wps_hostapd.h"
30 #include "ap/ctrl_iface_ap.h"
31 #include "ap/ap_drv_ops.h"
32 #include "ap/wnm_ap.h"
33 #include "ap/wpa_auth.h"
34 #include "wps/wps_defs.h"
35 #include "wps/wps.h"
36 #include "config_file.h"
37 #include "ctrl_iface.h"
38
39
40 struct wpa_ctrl_dst {
41         struct wpa_ctrl_dst *next;
42         struct sockaddr_un addr;
43         socklen_t addrlen;
44         int debug_level;
45         int errors;
46 };
47
48
49 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
50                                     const char *buf, size_t len);
51
52
53 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
54                                      struct sockaddr_un *from,
55                                      socklen_t fromlen)
56 {
57         struct wpa_ctrl_dst *dst;
58
59         dst = os_zalloc(sizeof(*dst));
60         if (dst == NULL)
61                 return -1;
62         os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
63         dst->addrlen = fromlen;
64         dst->debug_level = MSG_INFO;
65         dst->next = hapd->ctrl_dst;
66         hapd->ctrl_dst = dst;
67         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
68                     (u8 *) from->sun_path,
69                     fromlen - offsetof(struct sockaddr_un, sun_path));
70         return 0;
71 }
72
73
74 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
75                                      struct sockaddr_un *from,
76                                      socklen_t fromlen)
77 {
78         struct wpa_ctrl_dst *dst, *prev = NULL;
79
80         dst = hapd->ctrl_dst;
81         while (dst) {
82                 if (fromlen == dst->addrlen &&
83                     os_memcmp(from->sun_path, dst->addr.sun_path,
84                               fromlen - offsetof(struct sockaddr_un, sun_path))
85                     == 0) {
86                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
87                                     (u8 *) from->sun_path,
88                                     fromlen -
89                                     offsetof(struct sockaddr_un, sun_path));
90                         if (prev == NULL)
91                                 hapd->ctrl_dst = dst->next;
92                         else
93                                 prev->next = dst->next;
94                         os_free(dst);
95                         return 0;
96                 }
97                 prev = dst;
98                 dst = dst->next;
99         }
100         return -1;
101 }
102
103
104 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
105                                     struct sockaddr_un *from,
106                                     socklen_t fromlen,
107                                     char *level)
108 {
109         struct wpa_ctrl_dst *dst;
110
111         wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
112
113         dst = hapd->ctrl_dst;
114         while (dst) {
115                 if (fromlen == dst->addrlen &&
116                     os_memcmp(from->sun_path, dst->addr.sun_path,
117                               fromlen - offsetof(struct sockaddr_un, sun_path))
118                     == 0) {
119                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
120                                     "level", (u8 *) from->sun_path, fromlen -
121                                     offsetof(struct sockaddr_un, sun_path));
122                         dst->debug_level = atoi(level);
123                         return 0;
124                 }
125                 dst = dst->next;
126         }
127
128         return -1;
129 }
130
131
132 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
133                                       const char *txtaddr)
134 {
135         u8 addr[ETH_ALEN];
136         struct sta_info *sta;
137
138         wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
139
140         if (hwaddr_aton(txtaddr, addr))
141                 return -1;
142
143         sta = ap_get_sta(hapd, addr);
144         if (sta)
145                 return 0;
146
147         wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
148                    "notification", MAC2STR(addr));
149         sta = ap_sta_add(hapd, addr);
150         if (sta == NULL)
151                 return -1;
152
153         hostapd_new_assoc_sta(hapd, sta, 0);
154         return 0;
155 }
156
157
158 #ifdef CONFIG_IEEE80211W
159 #ifdef NEED_AP_MLME
160 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
161                                        const char *txtaddr)
162 {
163         u8 addr[ETH_ALEN];
164         u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
165
166         wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
167
168         if (hwaddr_aton(txtaddr, addr) ||
169             os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
170                 return -1;
171
172         ieee802_11_send_sa_query_req(hapd, addr, trans_id);
173
174         return 0;
175 }
176 #endif /* NEED_AP_MLME */
177 #endif /* CONFIG_IEEE80211W */
178
179
180 #ifdef CONFIG_WPS
181 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
182 {
183         char *pin = os_strchr(txt, ' ');
184         char *timeout_txt;
185         int timeout;
186         u8 addr_buf[ETH_ALEN], *addr = NULL;
187         char *pos;
188
189         if (pin == NULL)
190                 return -1;
191         *pin++ = '\0';
192
193         timeout_txt = os_strchr(pin, ' ');
194         if (timeout_txt) {
195                 *timeout_txt++ = '\0';
196                 timeout = atoi(timeout_txt);
197                 pos = os_strchr(timeout_txt, ' ');
198                 if (pos) {
199                         *pos++ = '\0';
200                         if (hwaddr_aton(pos, addr_buf) == 0)
201                                 addr = addr_buf;
202                 }
203         } else
204                 timeout = 0;
205
206         return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
207 }
208
209
210 static int hostapd_ctrl_iface_wps_check_pin(
211         struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
212 {
213         char pin[9];
214         size_t len;
215         char *pos;
216         int ret;
217
218         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
219                               (u8 *) cmd, os_strlen(cmd));
220         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
221                 if (*pos < '0' || *pos > '9')
222                         continue;
223                 pin[len++] = *pos;
224                 if (len == 9) {
225                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
226                         return -1;
227                 }
228         }
229         if (len != 4 && len != 8) {
230                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
231                 return -1;
232         }
233         pin[len] = '\0';
234
235         if (len == 8) {
236                 unsigned int pin_val;
237                 pin_val = atoi(pin);
238                 if (!wps_pin_valid(pin_val)) {
239                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
240                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
241                         if (ret < 0 || (size_t) ret >= buflen)
242                                 return -1;
243                         return ret;
244                 }
245         }
246
247         ret = os_snprintf(buf, buflen, "%s", pin);
248         if (ret < 0 || (size_t) ret >= buflen)
249                 return -1;
250
251         return ret;
252 }
253
254
255 #ifdef CONFIG_WPS_NFC
256 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
257                                                char *pos)
258 {
259         size_t len;
260         struct wpabuf *buf;
261         int ret;
262
263         len = os_strlen(pos);
264         if (len & 0x01)
265                 return -1;
266         len /= 2;
267
268         buf = wpabuf_alloc(len);
269         if (buf == NULL)
270                 return -1;
271         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
272                 wpabuf_free(buf);
273                 return -1;
274         }
275
276         ret = hostapd_wps_nfc_tag_read(hapd, buf);
277         wpabuf_free(buf);
278
279         return ret;
280 }
281
282
283 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
284                                                    char *cmd, char *reply,
285                                                    size_t max_len)
286 {
287         int ndef;
288         struct wpabuf *buf;
289         int res;
290
291         if (os_strcmp(cmd, "WPS") == 0)
292                 ndef = 0;
293         else if (os_strcmp(cmd, "NDEF") == 0)
294                 ndef = 1;
295         else
296                 return -1;
297
298         buf = hostapd_wps_nfc_config_token(hapd, ndef);
299         if (buf == NULL)
300                 return -1;
301
302         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
303                                          wpabuf_len(buf));
304         reply[res++] = '\n';
305         reply[res] = '\0';
306
307         wpabuf_free(buf);
308
309         return res;
310 }
311
312
313 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
314                                                 char *reply, size_t max_len,
315                                                 int ndef)
316 {
317         struct wpabuf *buf;
318         int res;
319
320         buf = hostapd_wps_nfc_token_gen(hapd, ndef);
321         if (buf == NULL)
322                 return -1;
323
324         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
325                                          wpabuf_len(buf));
326         reply[res++] = '\n';
327         reply[res] = '\0';
328
329         wpabuf_free(buf);
330
331         return res;
332 }
333
334
335 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
336                                             char *cmd, char *reply,
337                                             size_t max_len)
338 {
339         if (os_strcmp(cmd, "WPS") == 0)
340                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
341                                                             max_len, 0);
342
343         if (os_strcmp(cmd, "NDEF") == 0)
344                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
345                                                             max_len, 1);
346
347         if (os_strcmp(cmd, "enable") == 0)
348                 return hostapd_wps_nfc_token_enable(hapd);
349
350         if (os_strcmp(cmd, "disable") == 0) {
351                 hostapd_wps_nfc_token_disable(hapd);
352                 return 0;
353         }
354
355         return -1;
356 }
357
358
359 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
360                                                    char *cmd, char *reply,
361                                                    size_t max_len)
362 {
363         struct wpabuf *buf;
364         int res;
365         char *pos;
366         int ndef;
367
368         pos = os_strchr(cmd, ' ');
369         if (pos == NULL)
370                 return -1;
371         *pos++ = '\0';
372
373         if (os_strcmp(cmd, "WPS") == 0)
374                 ndef = 0;
375         else if (os_strcmp(cmd, "NDEF") == 0)
376                 ndef = 1;
377         else
378                 return -1;
379
380         if (os_strcmp(pos, "WPS-CR") == 0)
381                 buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
382         else
383                 buf = NULL;
384         if (buf == NULL)
385                 return -1;
386
387         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
388                                          wpabuf_len(buf));
389         reply[res++] = '\n';
390         reply[res] = '\0';
391
392         wpabuf_free(buf);
393
394         return res;
395 }
396
397
398 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
399                                                   char *cmd)
400 {
401         /*
402          * Since NFC connection handover provided full WPS Credential, there is
403          * no need for additional operations within hostapd. Just report this in
404          * debug log.
405          */
406         wpa_printf(MSG_DEBUG, "NFC: Connection handover reported: %s", cmd);
407         return 0;
408 }
409
410 #endif /* CONFIG_WPS_NFC */
411
412
413 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
414                                          char *buf, size_t buflen)
415 {
416         int timeout = 300;
417         char *pos;
418         const char *pin_txt;
419
420         pos = os_strchr(txt, ' ');
421         if (pos)
422                 *pos++ = '\0';
423
424         if (os_strcmp(txt, "disable") == 0) {
425                 hostapd_wps_ap_pin_disable(hapd);
426                 return os_snprintf(buf, buflen, "OK\n");
427         }
428
429         if (os_strcmp(txt, "random") == 0) {
430                 if (pos)
431                         timeout = atoi(pos);
432                 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
433                 if (pin_txt == NULL)
434                         return -1;
435                 return os_snprintf(buf, buflen, "%s", pin_txt);
436         }
437
438         if (os_strcmp(txt, "get") == 0) {
439                 pin_txt = hostapd_wps_ap_pin_get(hapd);
440                 if (pin_txt == NULL)
441                         return -1;
442                 return os_snprintf(buf, buflen, "%s", pin_txt);
443         }
444
445         if (os_strcmp(txt, "set") == 0) {
446                 char *pin;
447                 if (pos == NULL)
448                         return -1;
449                 pin = pos;
450                 pos = os_strchr(pos, ' ');
451                 if (pos) {
452                         *pos++ = '\0';
453                         timeout = atoi(pos);
454                 }
455                 if (os_strlen(pin) > buflen)
456                         return -1;
457                 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
458                         return -1;
459                 return os_snprintf(buf, buflen, "%s", pin);
460         }
461
462         return -1;
463 }
464
465
466 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
467 {
468         char *pos;
469         char *ssid, *auth, *encr = NULL, *key = NULL;
470
471         ssid = txt;
472         pos = os_strchr(txt, ' ');
473         if (!pos)
474                 return -1;
475         *pos++ = '\0';
476
477         auth = pos;
478         pos = os_strchr(pos, ' ');
479         if (pos) {
480                 *pos++ = '\0';
481                 encr = pos;
482                 pos = os_strchr(pos, ' ');
483                 if (pos) {
484                         *pos++ = '\0';
485                         key = pos;
486                 }
487         }
488
489         return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
490 }
491
492
493 static const char * pbc_status_str(enum pbc_status status)
494 {
495         switch (status) {
496         case WPS_PBC_STATUS_DISABLE:
497                 return "Disabled";
498         case WPS_PBC_STATUS_ACTIVE:
499                 return "Active";
500         case WPS_PBC_STATUS_TIMEOUT:
501                 return "Timed-out";
502         case WPS_PBC_STATUS_OVERLAP:
503                 return "Overlap";
504         default:
505                 return "Unknown";
506         }
507 }
508
509
510 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
511                                              char *buf, size_t buflen)
512 {
513         int ret;
514         char *pos, *end;
515
516         pos = buf;
517         end = buf + buflen;
518
519         ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
520                           pbc_status_str(hapd->wps_stats.pbc_status));
521
522         if (ret < 0 || ret >= end - pos)
523                 return pos - buf;
524         pos += ret;
525
526         ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
527                           (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
528                            "Success":
529                            (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
530                             "Failed" : "None")));
531
532         if (ret < 0 || ret >= end - pos)
533                 return pos - buf;
534         pos += ret;
535
536         /* If status == Failure - Add possible Reasons */
537         if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
538            hapd->wps_stats.failure_reason > 0) {
539                 ret = os_snprintf(pos, end - pos,
540                                   "Failure Reason: %s\n",
541                                   wps_ei_str(hapd->wps_stats.failure_reason));
542
543                 if (ret < 0 || ret >= end - pos)
544                         return pos - buf;
545                 pos += ret;
546         }
547
548         if (hapd->wps_stats.status) {
549                 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
550                                   MAC2STR(hapd->wps_stats.peer_addr));
551
552                 if (ret < 0 || ret >= end - pos)
553                         return pos - buf;
554                 pos += ret;
555         }
556
557         return pos - buf;
558 }
559
560 #endif /* CONFIG_WPS */
561
562
563 #ifdef CONFIG_INTERWORKING
564
565 static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
566                                               const char *cmd)
567 {
568         u8 qos_map_set[16 + 2 * 21], count = 0;
569         const char *pos = cmd;
570         int val, ret;
571
572         for (;;) {
573                 if (count == sizeof(qos_map_set)) {
574                         wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
575                         return -1;
576                 }
577
578                 val = atoi(pos);
579                 if (val < 0 || val > 255) {
580                         wpa_printf(MSG_INFO, "Invalid QoS Map Set");
581                         return -1;
582                 }
583
584                 qos_map_set[count++] = val;
585                 pos = os_strchr(pos, ',');
586                 if (!pos)
587                         break;
588                 pos++;
589         }
590
591         if (count < 16 || count & 1) {
592                 wpa_printf(MSG_INFO, "Invalid QoS Map Set");
593                 return -1;
594         }
595
596         ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
597         if (ret) {
598                 wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
599                 return -1;
600         }
601
602         os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
603         hapd->conf->qos_map_set_len = count;
604
605         return 0;
606 }
607
608
609 static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
610                                                 const char *cmd)
611 {
612         u8 addr[ETH_ALEN];
613         struct sta_info *sta;
614         struct wpabuf *buf;
615         u8 *qos_map_set = hapd->conf->qos_map_set;
616         u8 qos_map_set_len = hapd->conf->qos_map_set_len;
617         int ret;
618
619         if (!qos_map_set_len) {
620                 wpa_printf(MSG_INFO, "QoS Map Set is not set");
621                 return -1;
622         }
623
624         if (hwaddr_aton(cmd, addr))
625                 return -1;
626
627         sta = ap_get_sta(hapd, addr);
628         if (sta == NULL) {
629                 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
630                            "for QoS Map Configuration message",
631                            MAC2STR(addr));
632                 return -1;
633         }
634
635         if (!sta->qos_map_enabled) {
636                 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
637                            "support for QoS Map", MAC2STR(addr));
638                 return -1;
639         }
640
641         buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
642         if (buf == NULL)
643                 return -1;
644
645         wpabuf_put_u8(buf, WLAN_ACTION_QOS);
646         wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
647
648         /* QoS Map Set Element */
649         wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
650         wpabuf_put_u8(buf, qos_map_set_len);
651         wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
652
653         ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
654                                       wpabuf_head(buf), wpabuf_len(buf));
655         wpabuf_free(buf);
656
657         return ret;
658 }
659
660 #endif /* CONFIG_INTERWORKING */
661
662
663 #ifdef CONFIG_WNM
664
665 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
666                                                 const char *cmd)
667 {
668         u8 addr[ETH_ALEN];
669         u8 buf[1000], *pos;
670         struct ieee80211_mgmt *mgmt;
671         int disassoc_timer;
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         os_memset(buf, 0, sizeof(buf));
680         mgmt = (struct ieee80211_mgmt *) buf;
681         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
682                                            WLAN_FC_STYPE_ACTION);
683         os_memcpy(mgmt->da, addr, ETH_ALEN);
684         os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
685         os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
686         mgmt->u.action.category = WLAN_ACTION_WNM;
687         mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
688         mgmt->u.action.u.bss_tm_req.dialog_token = 1;
689         mgmt->u.action.u.bss_tm_req.req_mode =
690                 WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
691         mgmt->u.action.u.bss_tm_req.disassoc_timer =
692                 host_to_le16(disassoc_timer);
693         mgmt->u.action.u.bss_tm_req.validity_interval = 0;
694
695         pos = mgmt->u.action.u.bss_tm_req.variable;
696
697         if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
698                 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
699                            "Management Request frame");
700                 return -1;
701         }
702
703         return 0;
704 }
705
706
707 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
708                                            const char *cmd)
709 {
710         u8 addr[ETH_ALEN];
711         const char *url, *timerstr;
712         int disassoc_timer;
713         struct sta_info *sta;
714
715         if (hwaddr_aton(cmd, addr))
716                 return -1;
717
718         sta = ap_get_sta(hapd, addr);
719         if (sta == NULL) {
720                 wpa_printf(MSG_DEBUG, "Station " MACSTR
721                            " not found for ESS disassociation imminent message",
722                            MAC2STR(addr));
723                 return -1;
724         }
725
726         timerstr = cmd + 17;
727         if (*timerstr != ' ')
728                 return -1;
729         timerstr++;
730         disassoc_timer = atoi(timerstr);
731         if (disassoc_timer < 0 || disassoc_timer > 65535)
732                 return -1;
733
734         url = os_strchr(timerstr, ' ');
735         if (url == NULL)
736                 return -1;
737         url++;
738
739         return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
740 }
741
742 #endif /* CONFIG_WNM */
743
744
745 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
746                                          char *buf, size_t buflen)
747 {
748         int ret;
749         char *pos, *end;
750
751         pos = buf;
752         end = buf + buflen;
753
754         ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
755                           "ssid=%s\n",
756                           MAC2STR(hapd->own_addr),
757                           wpa_ssid_txt(hapd->conf->ssid.ssid,
758                                        hapd->conf->ssid.ssid_len));
759         if (ret < 0 || ret >= end - pos)
760                 return pos - buf;
761         pos += ret;
762
763 #ifdef CONFIG_WPS
764         ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
765                           hapd->conf->wps_state == 0 ? "disabled" :
766                           (hapd->conf->wps_state == 1 ? "not configured" :
767                            "configured"));
768         if (ret < 0 || ret >= end - pos)
769                 return pos - buf;
770         pos += ret;
771
772         if (hapd->conf->wps_state && hapd->conf->wpa &&
773             hapd->conf->ssid.wpa_passphrase) {
774                 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
775                                   hapd->conf->ssid.wpa_passphrase);
776                 if (ret < 0 || ret >= end - pos)
777                         return pos - buf;
778                 pos += ret;
779         }
780
781         if (hapd->conf->wps_state && hapd->conf->wpa &&
782             hapd->conf->ssid.wpa_psk &&
783             hapd->conf->ssid.wpa_psk->group) {
784                 char hex[PMK_LEN * 2 + 1];
785                 wpa_snprintf_hex(hex, sizeof(hex),
786                                  hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
787                 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
788                 if (ret < 0 || ret >= end - pos)
789                         return pos - buf;
790                 pos += ret;
791         }
792 #endif /* CONFIG_WPS */
793
794         if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
795                 ret = os_snprintf(pos, end - pos, "key_mgmt=");
796                 if (ret < 0 || ret >= end - pos)
797                         return pos - buf;
798                 pos += ret;
799
800                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
801                         ret = os_snprintf(pos, end - pos, "WPA-PSK ");
802                         if (ret < 0 || ret >= end - pos)
803                                 return pos - buf;
804                         pos += ret;
805                 }
806                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
807                         ret = os_snprintf(pos, end - pos, "WPA-EAP ");
808                         if (ret < 0 || ret >= end - pos)
809                                 return pos - buf;
810                         pos += ret;
811                 }
812 #ifdef CONFIG_IEEE80211R
813                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
814                         ret = os_snprintf(pos, end - pos, "FT-PSK ");
815                         if (ret < 0 || ret >= end - pos)
816                                 return pos - buf;
817                         pos += ret;
818                 }
819                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
820                         ret = os_snprintf(pos, end - pos, "FT-EAP ");
821                         if (ret < 0 || ret >= end - pos)
822                                 return pos - buf;
823                         pos += ret;
824                 }
825 #endif /* CONFIG_IEEE80211R */
826 #ifdef CONFIG_IEEE80211W
827                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
828                         ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
829                         if (ret < 0 || ret >= end - pos)
830                                 return pos - buf;
831                         pos += ret;
832                 }
833                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
834                         ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
835                         if (ret < 0 || ret >= end - pos)
836                                 return pos - buf;
837                         pos += ret;
838                 }
839 #endif /* CONFIG_IEEE80211W */
840
841                 ret = os_snprintf(pos, end - pos, "\n");
842                 if (ret < 0 || ret >= end - pos)
843                         return pos - buf;
844                 pos += ret;
845         }
846
847         if (hapd->conf->wpa) {
848                 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
849                                   wpa_cipher_txt(hapd->conf->wpa_group));
850                 if (ret < 0 || ret >= end - pos)
851                         return pos - buf;
852                 pos += ret;
853         }
854
855         if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
856                 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
857                 if (ret < 0 || ret >= end - pos)
858                         return pos - buf;
859                 pos += ret;
860
861                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
862                                         " ");
863                 if (ret < 0)
864                         return pos - buf;
865                 pos += ret;
866
867                 ret = os_snprintf(pos, end - pos, "\n");
868                 if (ret < 0 || ret >= end - pos)
869                         return pos - buf;
870                 pos += ret;
871         }
872
873         if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
874                 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
875                 if (ret < 0 || ret >= end - pos)
876                         return pos - buf;
877                 pos += ret;
878
879                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
880                                         " ");
881                 if (ret < 0)
882                         return pos - buf;
883                 pos += ret;
884
885                 ret = os_snprintf(pos, end - pos, "\n");
886                 if (ret < 0 || ret >= end - pos)
887                         return pos - buf;
888                 pos += ret;
889         }
890
891         return pos - buf;
892 }
893
894
895 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
896 {
897         char *value;
898         int ret = 0;
899
900         value = os_strchr(cmd, ' ');
901         if (value == NULL)
902                 return -1;
903         *value++ = '\0';
904
905         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
906         if (0) {
907 #ifdef CONFIG_WPS_TESTING
908         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
909                 long int val;
910                 val = strtol(value, NULL, 0);
911                 if (val < 0 || val > 0xff) {
912                         ret = -1;
913                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
914                                    "wps_version_number %ld", val);
915                 } else {
916                         wps_version_number = val;
917                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
918                                    "version %u.%u",
919                                    (wps_version_number & 0xf0) >> 4,
920                                    wps_version_number & 0x0f);
921                         hostapd_wps_update_ie(hapd);
922                 }
923         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
924                 wps_testing_dummy_cred = atoi(value);
925                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
926                            wps_testing_dummy_cred);
927 #endif /* CONFIG_WPS_TESTING */
928 #ifdef CONFIG_INTERWORKING
929         } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
930                 int val = atoi(value);
931                 if (val <= 0)
932                         ret = -1;
933                 else
934                         hapd->gas_frag_limit = val;
935 #endif /* CONFIG_INTERWORKING */
936 #ifdef CONFIG_TESTING_OPTIONS
937         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
938                 hapd->ext_mgmt_frame_handling = atoi(value);
939 #endif /* CONFIG_TESTING_OPTIONS */
940         } else {
941                 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
942         }
943
944         return ret;
945 }
946
947
948 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
949                                   char *buf, size_t buflen)
950 {
951         int res;
952
953         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
954
955         if (os_strcmp(cmd, "version") == 0) {
956                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
957                 if (res < 0 || (unsigned int) res >= buflen)
958                         return -1;
959                 return res;
960         }
961
962         return -1;
963 }
964
965
966 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
967 {
968         if (hostapd_enable_iface(iface) < 0) {
969                 wpa_printf(MSG_ERROR, "Enabling of interface failed");
970                 return -1;
971         }
972         return 0;
973 }
974
975
976 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
977 {
978         if (hostapd_reload_iface(iface) < 0) {
979                 wpa_printf(MSG_ERROR, "Reloading of interface failed");
980                 return -1;
981         }
982         return 0;
983 }
984
985
986 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
987 {
988         if (hostapd_disable_iface(iface) < 0) {
989                 wpa_printf(MSG_ERROR, "Disabling of interface failed");
990                 return -1;
991         }
992         return 0;
993 }
994
995
996 #ifdef CONFIG_TESTING_OPTIONS
997
998 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
999 {
1000         union wpa_event_data data;
1001         char *pos, *param;
1002         enum wpa_event_type event;
1003
1004         wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1005
1006         os_memset(&data, 0, sizeof(data));
1007
1008         param = os_strchr(cmd, ' ');
1009         if (param == NULL)
1010                 return -1;
1011         *param++ = '\0';
1012
1013         if (os_strcmp(cmd, "DETECTED") == 0)
1014                 event = EVENT_DFS_RADAR_DETECTED;
1015         else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1016                 event = EVENT_DFS_CAC_FINISHED;
1017         else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1018                 event = EVENT_DFS_CAC_ABORTED;
1019         else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1020                 event = EVENT_DFS_NOP_FINISHED;
1021         else {
1022                 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1023                            cmd);
1024                 return -1;
1025         }
1026
1027         pos = os_strstr(param, "freq=");
1028         if (pos)
1029                 data.dfs_event.freq = atoi(pos + 5);
1030
1031         pos = os_strstr(param, "ht_enabled=1");
1032         if (pos)
1033                 data.dfs_event.ht_enabled = 1;
1034
1035         pos = os_strstr(param, "chan_offset=");
1036         if (pos)
1037                 data.dfs_event.chan_offset = atoi(pos + 12);
1038
1039         pos = os_strstr(param, "chan_width=");
1040         if (pos)
1041                 data.dfs_event.chan_width = atoi(pos + 11);
1042
1043         pos = os_strstr(param, "cf1=");
1044         if (pos)
1045                 data.dfs_event.cf1 = atoi(pos + 4);
1046
1047         pos = os_strstr(param, "cf2=");
1048         if (pos)
1049                 data.dfs_event.cf2 = atoi(pos + 4);
1050
1051         wpa_supplicant_event(hapd, event, &data);
1052
1053         return 0;
1054 }
1055
1056
1057 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
1058 {
1059         size_t len;
1060         u8 *buf;
1061         int res;
1062
1063         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
1064
1065         len = os_strlen(cmd);
1066         if (len & 1)
1067                 return -1;
1068         len /= 2;
1069
1070         buf = os_malloc(len);
1071         if (buf == NULL)
1072                 return -1;
1073
1074         if (hexstr2bin(cmd, buf, len) < 0) {
1075                 os_free(buf);
1076                 return -1;
1077         }
1078
1079         res = hostapd_drv_send_mlme(hapd, buf, len, 0);
1080         os_free(buf);
1081         return res;
1082 }
1083
1084 #endif /* CONFIG_TESTING_OPTIONS */
1085
1086
1087 static int hostapd_ctrl_iface_chan_switch(struct hostapd_data *hapd, char *pos)
1088 {
1089 #ifdef NEED_AP_MLME
1090         struct csa_settings settings;
1091         int ret = hostapd_parse_csa_settings(pos, &settings);
1092
1093         if (ret)
1094                 return ret;
1095
1096         return hostapd_switch_channel(hapd, &settings);
1097 #else /* NEED_AP_MLME */
1098         return -1;
1099 #endif /* NEED_AP_MLME */
1100 }
1101
1102
1103 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
1104                                        void *sock_ctx)
1105 {
1106         struct hostapd_data *hapd = eloop_ctx;
1107         char buf[256];
1108         int res;
1109         struct sockaddr_un from;
1110         socklen_t fromlen = sizeof(from);
1111         char *reply;
1112         const int reply_size = 4096;
1113         int reply_len;
1114         int level = MSG_DEBUG;
1115
1116         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1117                        (struct sockaddr *) &from, &fromlen);
1118         if (res < 0) {
1119                 perror("recvfrom(ctrl_iface)");
1120                 return;
1121         }
1122         buf[res] = '\0';
1123         if (os_strcmp(buf, "PING") == 0)
1124                 level = MSG_EXCESSIVE;
1125         wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
1126
1127         reply = os_malloc(reply_size);
1128         if (reply == NULL) {
1129                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
1130                        fromlen);
1131                 return;
1132         }
1133
1134         os_memcpy(reply, "OK\n", 3);
1135         reply_len = 3;
1136
1137         if (os_strcmp(buf, "PING") == 0) {
1138                 os_memcpy(reply, "PONG\n", 5);
1139                 reply_len = 5;
1140         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
1141                 if (wpa_debug_reopen_file() < 0)
1142                         reply_len = -1;
1143         } else if (os_strcmp(buf, "STATUS") == 0) {
1144                 reply_len = hostapd_ctrl_iface_status(hapd, reply,
1145                                                       reply_size);
1146         } else if (os_strcmp(buf, "MIB") == 0) {
1147                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
1148                 if (reply_len >= 0) {
1149                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
1150                                           reply_size - reply_len);
1151                         if (res < 0)
1152                                 reply_len = -1;
1153                         else
1154                                 reply_len += res;
1155                 }
1156                 if (reply_len >= 0) {
1157                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
1158                                                  reply_size - reply_len);
1159                         if (res < 0)
1160                                 reply_len = -1;
1161                         else
1162                                 reply_len += res;
1163                 }
1164 #ifndef CONFIG_NO_RADIUS
1165                 if (reply_len >= 0) {
1166                         res = radius_client_get_mib(hapd->radius,
1167                                                     reply + reply_len,
1168                                                     reply_size - reply_len);
1169                         if (res < 0)
1170                                 reply_len = -1;
1171                         else
1172                                 reply_len += res;
1173                 }
1174 #endif /* CONFIG_NO_RADIUS */
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 */