6f22f659826190cb9b0caccd7ca5aa5ea7ac0d46
[mech_eap.git] / hostapd / ctrl_iface.c
1 /*
2  * hostapd / UNIX domain socket -based control interface
3  * Copyright (c) 2004-2015, 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 #ifdef CONFIG_TESTING_OPTIONS
14 #include <net/ethernet.h>
15 #include <netinet/ip.h>
16 #endif /* CONFIG_TESTING_OPTIONS */
17
18 #include <sys/un.h>
19 #include <sys/stat.h>
20 #include <stddef.h>
21
22 #ifdef CONFIG_CTRL_IFACE_UDP
23 #include <netdb.h>
24 #endif /* CONFIG_CTRL_IFACE_UDP */
25
26 #include "utils/common.h"
27 #include "utils/eloop.h"
28 #include "common/version.h"
29 #include "common/ieee802_11_defs.h"
30 #include "common/ctrl_iface_common.h"
31 #include "crypto/tls.h"
32 #include "drivers/driver.h"
33 #include "eapol_auth/eapol_auth_sm.h"
34 #include "radius/radius_client.h"
35 #include "radius/radius_server.h"
36 #include "l2_packet/l2_packet.h"
37 #include "ap/hostapd.h"
38 #include "ap/ap_config.h"
39 #include "ap/ieee802_1x.h"
40 #include "ap/wpa_auth.h"
41 #include "ap/ieee802_11.h"
42 #include "ap/sta_info.h"
43 #include "ap/wps_hostapd.h"
44 #include "ap/ctrl_iface_ap.h"
45 #include "ap/ap_drv_ops.h"
46 #include "ap/hs20.h"
47 #include "ap/wnm_ap.h"
48 #include "ap/wpa_auth.h"
49 #include "ap/beacon.h"
50 #include "wps/wps_defs.h"
51 #include "wps/wps.h"
52 #include "fst/fst_ctrl_iface.h"
53 #include "config_file.h"
54 #include "ctrl_iface.h"
55
56
57 #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
58
59 #ifdef CONFIG_CTRL_IFACE_UDP
60 #define COOKIE_LEN 8
61 static unsigned char cookie[COOKIE_LEN];
62 static unsigned char gcookie[COOKIE_LEN];
63 #define HOSTAPD_CTRL_IFACE_PORT         8877
64 #define HOSTAPD_CTRL_IFACE_PORT_LIMIT   50
65 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT          8878
66 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT    50
67 #endif /* CONFIG_CTRL_IFACE_UDP */
68
69 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
70                                     enum wpa_msg_type type,
71                                     const char *buf, size_t len);
72
73
74 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
75                                      struct sockaddr_storage *from,
76                                      socklen_t fromlen)
77 {
78         return ctrl_iface_attach(&hapd->ctrl_dst, from, fromlen);
79 }
80
81
82 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
83                                      struct sockaddr_storage *from,
84                                      socklen_t fromlen)
85 {
86         return ctrl_iface_detach(&hapd->ctrl_dst, from, fromlen);
87 }
88
89
90 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
91                                     struct sockaddr_storage *from,
92                                     socklen_t fromlen,
93                                     char *level)
94 {
95         return ctrl_iface_level(&hapd->ctrl_dst, from, fromlen, level);
96 }
97
98
99 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
100                                       const char *txtaddr)
101 {
102         u8 addr[ETH_ALEN];
103         struct sta_info *sta;
104
105         wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
106
107         if (hwaddr_aton(txtaddr, addr))
108                 return -1;
109
110         sta = ap_get_sta(hapd, addr);
111         if (sta)
112                 return 0;
113
114         wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
115                    "notification", MAC2STR(addr));
116         sta = ap_sta_add(hapd, addr);
117         if (sta == NULL)
118                 return -1;
119
120         hostapd_new_assoc_sta(hapd, sta, 0);
121         return 0;
122 }
123
124
125 #ifdef CONFIG_IEEE80211W
126 #ifdef NEED_AP_MLME
127 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
128                                        const char *txtaddr)
129 {
130         u8 addr[ETH_ALEN];
131         u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
132
133         wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
134
135         if (hwaddr_aton(txtaddr, addr) ||
136             os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
137                 return -1;
138
139         ieee802_11_send_sa_query_req(hapd, addr, trans_id);
140
141         return 0;
142 }
143 #endif /* NEED_AP_MLME */
144 #endif /* CONFIG_IEEE80211W */
145
146
147 #ifdef CONFIG_WPS
148 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
149 {
150         char *pin = os_strchr(txt, ' ');
151         char *timeout_txt;
152         int timeout;
153         u8 addr_buf[ETH_ALEN], *addr = NULL;
154         char *pos;
155
156         if (pin == NULL)
157                 return -1;
158         *pin++ = '\0';
159
160         timeout_txt = os_strchr(pin, ' ');
161         if (timeout_txt) {
162                 *timeout_txt++ = '\0';
163                 timeout = atoi(timeout_txt);
164                 pos = os_strchr(timeout_txt, ' ');
165                 if (pos) {
166                         *pos++ = '\0';
167                         if (hwaddr_aton(pos, addr_buf) == 0)
168                                 addr = addr_buf;
169                 }
170         } else
171                 timeout = 0;
172
173         return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
174 }
175
176
177 static int hostapd_ctrl_iface_wps_check_pin(
178         struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
179 {
180         char pin[9];
181         size_t len;
182         char *pos;
183         int ret;
184
185         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
186                               (u8 *) cmd, os_strlen(cmd));
187         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
188                 if (*pos < '0' || *pos > '9')
189                         continue;
190                 pin[len++] = *pos;
191                 if (len == 9) {
192                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
193                         return -1;
194                 }
195         }
196         if (len != 4 && len != 8) {
197                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
198                 return -1;
199         }
200         pin[len] = '\0';
201
202         if (len == 8) {
203                 unsigned int pin_val;
204                 pin_val = atoi(pin);
205                 if (!wps_pin_valid(pin_val)) {
206                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
207                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
208                         if (os_snprintf_error(buflen, ret))
209                                 return -1;
210                         return ret;
211                 }
212         }
213
214         ret = os_snprintf(buf, buflen, "%s", pin);
215         if (os_snprintf_error(buflen, ret))
216                 return -1;
217
218         return ret;
219 }
220
221
222 #ifdef CONFIG_WPS_NFC
223 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
224                                                char *pos)
225 {
226         size_t len;
227         struct wpabuf *buf;
228         int ret;
229
230         len = os_strlen(pos);
231         if (len & 0x01)
232                 return -1;
233         len /= 2;
234
235         buf = wpabuf_alloc(len);
236         if (buf == NULL)
237                 return -1;
238         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
239                 wpabuf_free(buf);
240                 return -1;
241         }
242
243         ret = hostapd_wps_nfc_tag_read(hapd, buf);
244         wpabuf_free(buf);
245
246         return ret;
247 }
248
249
250 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
251                                                    char *cmd, char *reply,
252                                                    size_t max_len)
253 {
254         int ndef;
255         struct wpabuf *buf;
256         int res;
257
258         if (os_strcmp(cmd, "WPS") == 0)
259                 ndef = 0;
260         else if (os_strcmp(cmd, "NDEF") == 0)
261                 ndef = 1;
262         else
263                 return -1;
264
265         buf = hostapd_wps_nfc_config_token(hapd, ndef);
266         if (buf == NULL)
267                 return -1;
268
269         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
270                                          wpabuf_len(buf));
271         reply[res++] = '\n';
272         reply[res] = '\0';
273
274         wpabuf_free(buf);
275
276         return res;
277 }
278
279
280 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
281                                                 char *reply, size_t max_len,
282                                                 int ndef)
283 {
284         struct wpabuf *buf;
285         int res;
286
287         buf = hostapd_wps_nfc_token_gen(hapd, ndef);
288         if (buf == NULL)
289                 return -1;
290
291         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
292                                          wpabuf_len(buf));
293         reply[res++] = '\n';
294         reply[res] = '\0';
295
296         wpabuf_free(buf);
297
298         return res;
299 }
300
301
302 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
303                                             char *cmd, char *reply,
304                                             size_t max_len)
305 {
306         if (os_strcmp(cmd, "WPS") == 0)
307                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
308                                                             max_len, 0);
309
310         if (os_strcmp(cmd, "NDEF") == 0)
311                 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
312                                                             max_len, 1);
313
314         if (os_strcmp(cmd, "enable") == 0)
315                 return hostapd_wps_nfc_token_enable(hapd);
316
317         if (os_strcmp(cmd, "disable") == 0) {
318                 hostapd_wps_nfc_token_disable(hapd);
319                 return 0;
320         }
321
322         return -1;
323 }
324
325
326 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
327                                                    char *cmd, char *reply,
328                                                    size_t max_len)
329 {
330         struct wpabuf *buf;
331         int res;
332         char *pos;
333         int ndef;
334
335         pos = os_strchr(cmd, ' ');
336         if (pos == NULL)
337                 return -1;
338         *pos++ = '\0';
339
340         if (os_strcmp(cmd, "WPS") == 0)
341                 ndef = 0;
342         else if (os_strcmp(cmd, "NDEF") == 0)
343                 ndef = 1;
344         else
345                 return -1;
346
347         if (os_strcmp(pos, "WPS-CR") == 0)
348                 buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
349         else
350                 buf = NULL;
351         if (buf == NULL)
352                 return -1;
353
354         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
355                                          wpabuf_len(buf));
356         reply[res++] = '\n';
357         reply[res] = '\0';
358
359         wpabuf_free(buf);
360
361         return res;
362 }
363
364
365 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
366                                                   char *cmd)
367 {
368         size_t len;
369         struct wpabuf *req, *sel;
370         int ret;
371         char *pos, *role, *type, *pos2;
372
373         role = cmd;
374         pos = os_strchr(role, ' ');
375         if (pos == NULL)
376                 return -1;
377         *pos++ = '\0';
378
379         type = pos;
380         pos = os_strchr(type, ' ');
381         if (pos == NULL)
382                 return -1;
383         *pos++ = '\0';
384
385         pos2 = os_strchr(pos, ' ');
386         if (pos2 == NULL)
387                 return -1;
388         *pos2++ = '\0';
389
390         len = os_strlen(pos);
391         if (len & 0x01)
392                 return -1;
393         len /= 2;
394
395         req = wpabuf_alloc(len);
396         if (req == NULL)
397                 return -1;
398         if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
399                 wpabuf_free(req);
400                 return -1;
401         }
402
403         len = os_strlen(pos2);
404         if (len & 0x01) {
405                 wpabuf_free(req);
406                 return -1;
407         }
408         len /= 2;
409
410         sel = wpabuf_alloc(len);
411         if (sel == NULL) {
412                 wpabuf_free(req);
413                 return -1;
414         }
415         if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
416                 wpabuf_free(req);
417                 wpabuf_free(sel);
418                 return -1;
419         }
420
421         if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
422                 ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
423         } else {
424                 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
425                            "reported: role=%s type=%s", role, type);
426                 ret = -1;
427         }
428         wpabuf_free(req);
429         wpabuf_free(sel);
430
431         return ret;
432 }
433
434 #endif /* CONFIG_WPS_NFC */
435
436
437 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
438                                          char *buf, size_t buflen)
439 {
440         int timeout = 300;
441         char *pos;
442         const char *pin_txt;
443
444         pos = os_strchr(txt, ' ');
445         if (pos)
446                 *pos++ = '\0';
447
448         if (os_strcmp(txt, "disable") == 0) {
449                 hostapd_wps_ap_pin_disable(hapd);
450                 return os_snprintf(buf, buflen, "OK\n");
451         }
452
453         if (os_strcmp(txt, "random") == 0) {
454                 if (pos)
455                         timeout = atoi(pos);
456                 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
457                 if (pin_txt == NULL)
458                         return -1;
459                 return os_snprintf(buf, buflen, "%s", pin_txt);
460         }
461
462         if (os_strcmp(txt, "get") == 0) {
463                 pin_txt = hostapd_wps_ap_pin_get(hapd);
464                 if (pin_txt == NULL)
465                         return -1;
466                 return os_snprintf(buf, buflen, "%s", pin_txt);
467         }
468
469         if (os_strcmp(txt, "set") == 0) {
470                 char *pin;
471                 if (pos == NULL)
472                         return -1;
473                 pin = pos;
474                 pos = os_strchr(pos, ' ');
475                 if (pos) {
476                         *pos++ = '\0';
477                         timeout = atoi(pos);
478                 }
479                 if (os_strlen(pin) > buflen)
480                         return -1;
481                 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
482                         return -1;
483                 return os_snprintf(buf, buflen, "%s", pin);
484         }
485
486         return -1;
487 }
488
489
490 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
491 {
492         char *pos;
493         char *ssid, *auth, *encr = NULL, *key = NULL;
494
495         ssid = txt;
496         pos = os_strchr(txt, ' ');
497         if (!pos)
498                 return -1;
499         *pos++ = '\0';
500
501         auth = pos;
502         pos = os_strchr(pos, ' ');
503         if (pos) {
504                 *pos++ = '\0';
505                 encr = pos;
506                 pos = os_strchr(pos, ' ');
507                 if (pos) {
508                         *pos++ = '\0';
509                         key = pos;
510                 }
511         }
512
513         return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
514 }
515
516
517 static const char * pbc_status_str(enum pbc_status status)
518 {
519         switch (status) {
520         case WPS_PBC_STATUS_DISABLE:
521                 return "Disabled";
522         case WPS_PBC_STATUS_ACTIVE:
523                 return "Active";
524         case WPS_PBC_STATUS_TIMEOUT:
525                 return "Timed-out";
526         case WPS_PBC_STATUS_OVERLAP:
527                 return "Overlap";
528         default:
529                 return "Unknown";
530         }
531 }
532
533
534 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
535                                              char *buf, size_t buflen)
536 {
537         int ret;
538         char *pos, *end;
539
540         pos = buf;
541         end = buf + buflen;
542
543         ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
544                           pbc_status_str(hapd->wps_stats.pbc_status));
545
546         if (os_snprintf_error(end - pos, ret))
547                 return pos - buf;
548         pos += ret;
549
550         ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
551                           (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
552                            "Success":
553                            (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
554                             "Failed" : "None")));
555
556         if (os_snprintf_error(end - pos, ret))
557                 return pos - buf;
558         pos += ret;
559
560         /* If status == Failure - Add possible Reasons */
561         if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
562            hapd->wps_stats.failure_reason > 0) {
563                 ret = os_snprintf(pos, end - pos,
564                                   "Failure Reason: %s\n",
565                                   wps_ei_str(hapd->wps_stats.failure_reason));
566
567                 if (os_snprintf_error(end - pos, ret))
568                         return pos - buf;
569                 pos += ret;
570         }
571
572         if (hapd->wps_stats.status) {
573                 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
574                                   MAC2STR(hapd->wps_stats.peer_addr));
575
576                 if (os_snprintf_error(end - pos, ret))
577                         return pos - buf;
578                 pos += ret;
579         }
580
581         return pos - buf;
582 }
583
584 #endif /* CONFIG_WPS */
585
586 #ifdef CONFIG_HS20
587
588 static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
589                                              const char *cmd)
590 {
591         u8 addr[ETH_ALEN];
592         const char *url;
593
594         if (hwaddr_aton(cmd, addr))
595                 return -1;
596         url = cmd + 17;
597         if (*url == '\0') {
598                 url = NULL;
599         } else {
600                 if (*url != ' ')
601                         return -1;
602                 url++;
603                 if (*url == '\0')
604                         url = NULL;
605         }
606
607         return hs20_send_wnm_notification(hapd, addr, 1, url);
608 }
609
610
611 static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
612                                               const char *cmd)
613 {
614         u8 addr[ETH_ALEN];
615         int code, reauth_delay, ret;
616         const char *pos;
617         size_t url_len;
618         struct wpabuf *req;
619
620         /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
621         if (hwaddr_aton(cmd, addr))
622                 return -1;
623
624         pos = os_strchr(cmd, ' ');
625         if (pos == NULL)
626                 return -1;
627         pos++;
628         code = atoi(pos);
629
630         pos = os_strchr(pos, ' ');
631         if (pos == NULL)
632                 return -1;
633         pos++;
634         reauth_delay = atoi(pos);
635
636         url_len = 0;
637         pos = os_strchr(pos, ' ');
638         if (pos) {
639                 pos++;
640                 url_len = os_strlen(pos);
641         }
642
643         req = wpabuf_alloc(4 + url_len);
644         if (req == NULL)
645                 return -1;
646         wpabuf_put_u8(req, code);
647         wpabuf_put_le16(req, reauth_delay);
648         wpabuf_put_u8(req, url_len);
649         if (pos)
650                 wpabuf_put_data(req, pos, url_len);
651
652         wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
653                    " to indicate imminent deauthentication (code=%d "
654                    "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
655         ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
656         wpabuf_free(req);
657         return ret;
658 }
659
660 #endif /* CONFIG_HS20 */
661
662
663 #ifdef CONFIG_INTERWORKING
664
665 static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
666                                               const char *cmd)
667 {
668         u8 qos_map_set[16 + 2 * 21], count = 0;
669         const char *pos = cmd;
670         int val, ret;
671
672         for (;;) {
673                 if (count == sizeof(qos_map_set)) {
674                         wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
675                         return -1;
676                 }
677
678                 val = atoi(pos);
679                 if (val < 0 || val > 255) {
680                         wpa_printf(MSG_INFO, "Invalid QoS Map Set");
681                         return -1;
682                 }
683
684                 qos_map_set[count++] = val;
685                 pos = os_strchr(pos, ',');
686                 if (!pos)
687                         break;
688                 pos++;
689         }
690
691         if (count < 16 || count & 1) {
692                 wpa_printf(MSG_INFO, "Invalid QoS Map Set");
693                 return -1;
694         }
695
696         ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
697         if (ret) {
698                 wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
699                 return -1;
700         }
701
702         os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
703         hapd->conf->qos_map_set_len = count;
704
705         return 0;
706 }
707
708
709 static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
710                                                 const char *cmd)
711 {
712         u8 addr[ETH_ALEN];
713         struct sta_info *sta;
714         struct wpabuf *buf;
715         u8 *qos_map_set = hapd->conf->qos_map_set;
716         u8 qos_map_set_len = hapd->conf->qos_map_set_len;
717         int ret;
718
719         if (!qos_map_set_len) {
720                 wpa_printf(MSG_INFO, "QoS Map Set is not set");
721                 return -1;
722         }
723
724         if (hwaddr_aton(cmd, addr))
725                 return -1;
726
727         sta = ap_get_sta(hapd, addr);
728         if (sta == NULL) {
729                 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
730                            "for QoS Map Configuration message",
731                            MAC2STR(addr));
732                 return -1;
733         }
734
735         if (!sta->qos_map_enabled) {
736                 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
737                            "support for QoS Map", MAC2STR(addr));
738                 return -1;
739         }
740
741         buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
742         if (buf == NULL)
743                 return -1;
744
745         wpabuf_put_u8(buf, WLAN_ACTION_QOS);
746         wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
747
748         /* QoS Map Set Element */
749         wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
750         wpabuf_put_u8(buf, qos_map_set_len);
751         wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
752
753         ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
754                                       wpabuf_head(buf), wpabuf_len(buf));
755         wpabuf_free(buf);
756
757         return ret;
758 }
759
760 #endif /* CONFIG_INTERWORKING */
761
762
763 #ifdef CONFIG_WNM
764
765 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
766                                                 const char *cmd)
767 {
768         u8 addr[ETH_ALEN];
769         int disassoc_timer;
770         struct sta_info *sta;
771
772         if (hwaddr_aton(cmd, addr))
773                 return -1;
774         if (cmd[17] != ' ')
775                 return -1;
776         disassoc_timer = atoi(cmd + 17);
777
778         sta = ap_get_sta(hapd, addr);
779         if (sta == NULL) {
780                 wpa_printf(MSG_DEBUG, "Station " MACSTR
781                            " not found for disassociation imminent message",
782                            MAC2STR(addr));
783                 return -1;
784         }
785
786         return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
787 }
788
789
790 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
791                                            const char *cmd)
792 {
793         u8 addr[ETH_ALEN];
794         const char *url, *timerstr;
795         int disassoc_timer;
796         struct sta_info *sta;
797
798         if (hwaddr_aton(cmd, addr))
799                 return -1;
800
801         sta = ap_get_sta(hapd, addr);
802         if (sta == NULL) {
803                 wpa_printf(MSG_DEBUG, "Station " MACSTR
804                            " not found for ESS disassociation imminent message",
805                            MAC2STR(addr));
806                 return -1;
807         }
808
809         timerstr = cmd + 17;
810         if (*timerstr != ' ')
811                 return -1;
812         timerstr++;
813         disassoc_timer = atoi(timerstr);
814         if (disassoc_timer < 0 || disassoc_timer > 65535)
815                 return -1;
816
817         url = os_strchr(timerstr, ' ');
818         if (url == NULL)
819                 return -1;
820         url++;
821
822         return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
823 }
824
825
826 static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
827                                          const char *cmd)
828 {
829         u8 addr[ETH_ALEN];
830         const char *pos, *end;
831         int disassoc_timer = 0;
832         struct sta_info *sta;
833         u8 req_mode = 0, valid_int = 0x01;
834         u8 bss_term_dur[12];
835         char *url = NULL;
836         int ret;
837         u8 nei_rep[1000];
838         u8 *nei_pos = nei_rep;
839         u8 mbo[10];
840         size_t mbo_len = 0;
841
842         if (hwaddr_aton(cmd, addr)) {
843                 wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
844                 return -1;
845         }
846
847         sta = ap_get_sta(hapd, addr);
848         if (sta == NULL) {
849                 wpa_printf(MSG_DEBUG, "Station " MACSTR
850                            " not found for BSS TM Request message",
851                            MAC2STR(addr));
852                 return -1;
853         }
854
855         pos = os_strstr(cmd, " disassoc_timer=");
856         if (pos) {
857                 pos += 16;
858                 disassoc_timer = atoi(pos);
859                 if (disassoc_timer < 0 || disassoc_timer > 65535) {
860                         wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
861                         return -1;
862                 }
863         }
864
865         pos = os_strstr(cmd, " valid_int=");
866         if (pos) {
867                 pos += 11;
868                 valid_int = atoi(pos);
869         }
870
871         pos = os_strstr(cmd, " bss_term=");
872         if (pos) {
873                 pos += 10;
874                 req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
875                 /* TODO: TSF configurable/learnable */
876                 bss_term_dur[0] = 4; /* Subelement ID */
877                 bss_term_dur[1] = 10; /* Length */
878                 os_memset(bss_term_dur, 2, 8);
879                 end = os_strchr(pos, ',');
880                 if (end == NULL) {
881                         wpa_printf(MSG_DEBUG, "Invalid bss_term data");
882                         return -1;
883                 }
884                 end++;
885                 WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
886         }
887
888
889         /*
890          * BSS Transition Candidate List Entries - Neighbor Report elements
891          * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
892          * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
893          */
894         pos = cmd;
895         while (pos) {
896                 u8 *nei_start;
897                 long int val;
898                 char *endptr, *tmp;
899
900                 pos = os_strstr(pos, " neighbor=");
901                 if (!pos)
902                         break;
903                 if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) {
904                         wpa_printf(MSG_DEBUG,
905                                    "Not enough room for additional neighbor");
906                         return -1;
907                 }
908                 pos += 10;
909
910                 nei_start = nei_pos;
911                 *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
912                 nei_pos++; /* length to be filled in */
913
914                 if (hwaddr_aton(pos, nei_pos)) {
915                         wpa_printf(MSG_DEBUG, "Invalid BSSID");
916                         return -1;
917                 }
918                 nei_pos += ETH_ALEN;
919                 pos += 17;
920                 if (*pos != ',') {
921                         wpa_printf(MSG_DEBUG, "Missing BSSID Information");
922                         return -1;
923                 }
924                 pos++;
925
926                 val = strtol(pos, &endptr, 0);
927                 WPA_PUT_LE32(nei_pos, val);
928                 nei_pos += 4;
929                 if (*endptr != ',') {
930                         wpa_printf(MSG_DEBUG, "Missing Operating Class");
931                         return -1;
932                 }
933                 pos = endptr + 1;
934
935                 *nei_pos++ = atoi(pos); /* Operating Class */
936                 pos = os_strchr(pos, ',');
937                 if (pos == NULL) {
938                         wpa_printf(MSG_DEBUG, "Missing Channel Number");
939                         return -1;
940                 }
941                 pos++;
942
943                 *nei_pos++ = atoi(pos); /* Channel Number */
944                 pos = os_strchr(pos, ',');
945                 if (pos == NULL) {
946                         wpa_printf(MSG_DEBUG, "Missing PHY Type");
947                         return -1;
948                 }
949                 pos++;
950
951                 *nei_pos++ = atoi(pos); /* PHY Type */
952                 end = os_strchr(pos, ' ');
953                 tmp = os_strchr(pos, ',');
954                 if (tmp && (!end || tmp < end)) {
955                         /* Optional Subelements (hexdump) */
956                         size_t len;
957
958                         pos = tmp + 1;
959                         end = os_strchr(pos, ' ');
960                         if (end)
961                                 len = end - pos;
962                         else
963                                 len = os_strlen(pos);
964                         if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) {
965                                 wpa_printf(MSG_DEBUG,
966                                            "Not enough room for neighbor subelements");
967                                 return -1;
968                         }
969                         if (len & 0x01 ||
970                             hexstr2bin(pos, nei_pos, len / 2) < 0) {
971                                 wpa_printf(MSG_DEBUG,
972                                            "Invalid neighbor subelement info");
973                                 return -1;
974                         }
975                         nei_pos += len / 2;
976                         pos = end;
977                 }
978
979                 nei_start[1] = nei_pos - nei_start - 2;
980         }
981
982         pos = os_strstr(cmd, " url=");
983         if (pos) {
984                 size_t len;
985                 pos += 5;
986                 end = os_strchr(pos, ' ');
987                 if (end)
988                         len = end - pos;
989                 else
990                         len = os_strlen(pos);
991                 url = os_malloc(len + 1);
992                 if (url == NULL)
993                         return -1;
994                 os_memcpy(url, pos, len);
995                 url[len] = '\0';
996                 req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
997         }
998
999         if (os_strstr(cmd, " pref=1"))
1000                 req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
1001         if (os_strstr(cmd, " abridged=1"))
1002                 req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
1003         if (os_strstr(cmd, " disassoc_imminent=1"))
1004                 req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
1005
1006 #ifdef CONFIG_MBO
1007         pos = os_strstr(cmd, "mbo=");
1008         if (pos) {
1009                 unsigned int mbo_reason, cell_pref, reassoc_delay;
1010                 u8 *mbo_pos = mbo;
1011
1012                 ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
1013                              &reassoc_delay, &cell_pref);
1014                 if (ret != 3) {
1015                         wpa_printf(MSG_DEBUG,
1016                                    "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
1017                         return -1;
1018                 }
1019
1020                 if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
1021                         wpa_printf(MSG_DEBUG,
1022                                    "Invalid MBO transition reason code %u",
1023                                    mbo_reason);
1024                         return -1;
1025                 }
1026
1027                 /* Valid values for Cellular preference are: 0, 1, 255 */
1028                 if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) {
1029                         wpa_printf(MSG_DEBUG,
1030                                    "Invalid MBO cellular capability %u",
1031                                    cell_pref);
1032                         return -1;
1033                 }
1034
1035                 if (reassoc_delay > 65535 ||
1036                     (reassoc_delay &&
1037                      !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) {
1038                         wpa_printf(MSG_DEBUG,
1039                                    "MBO: Assoc retry delay is only valid in disassoc imminent mode");
1040                         return -1;
1041                 }
1042
1043                 *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
1044                 *mbo_pos++ = 1;
1045                 *mbo_pos++ = mbo_reason;
1046                 *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
1047                 *mbo_pos++ = 1;
1048                 *mbo_pos++ = cell_pref;
1049
1050                 if (reassoc_delay) {
1051                         *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
1052                         *mbo_pos++ = 2;
1053                         WPA_PUT_LE16(mbo_pos, reassoc_delay);
1054                         mbo_pos += 2;
1055                 }
1056
1057                 mbo_len = mbo_pos - mbo;
1058         }
1059 #endif /* CONFIG_MBO */
1060
1061         ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
1062                                   valid_int, bss_term_dur, url,
1063                                   nei_pos > nei_rep ? nei_rep : NULL,
1064                                   nei_pos - nei_rep, mbo_len ? mbo : NULL,
1065                                   mbo_len);
1066         os_free(url);
1067         return ret;
1068 }
1069
1070 #endif /* CONFIG_WNM */
1071
1072
1073 static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd,
1074                                            char *buf, size_t buflen)
1075 {
1076         int ret = 0;
1077         char *pos, *end;
1078
1079         pos = buf;
1080         end = buf + buflen;
1081
1082         WPA_ASSERT(hapd->conf->wpa_key_mgmt);
1083
1084         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
1085                 ret = os_snprintf(pos, end - pos, "WPA-PSK ");
1086                 if (os_snprintf_error(end - pos, ret))
1087                         return pos - buf;
1088                 pos += ret;
1089         }
1090         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1091                 ret = os_snprintf(pos, end - pos, "WPA-EAP ");
1092                 if (os_snprintf_error(end - pos, ret))
1093                         return pos - buf;
1094                 pos += ret;
1095         }
1096 #ifdef CONFIG_IEEE80211R
1097         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1098                 ret = os_snprintf(pos, end - pos, "FT-PSK ");
1099                 if (os_snprintf_error(end - pos, ret))
1100                         return pos - buf;
1101                 pos += ret;
1102         }
1103         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1104                 ret = os_snprintf(pos, end - pos, "FT-EAP ");
1105                 if (os_snprintf_error(end - pos, ret))
1106                         return pos - buf;
1107                 pos += ret;
1108         }
1109 #ifdef CONFIG_SAE
1110         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
1111                 ret = os_snprintf(pos, end - pos, "FT-SAE ");
1112                 if (os_snprintf_error(end - pos, ret))
1113                         return pos - buf;
1114                 pos += ret;
1115         }
1116 #endif /* CONFIG_SAE */
1117 #endif /* CONFIG_IEEE80211R */
1118 #ifdef CONFIG_IEEE80211W
1119         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1120                 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
1121                 if (os_snprintf_error(end - pos, ret))
1122                         return pos - buf;
1123                 pos += ret;
1124         }
1125         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1126                 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
1127                 if (os_snprintf_error(end - pos, ret))
1128                         return pos - buf;
1129                 pos += ret;
1130         }
1131 #endif /* CONFIG_IEEE80211W */
1132 #ifdef CONFIG_SAE
1133         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
1134                 ret = os_snprintf(pos, end - pos, "SAE ");
1135                 if (os_snprintf_error(end - pos, ret))
1136                         return pos - buf;
1137                 pos += ret;
1138         }
1139 #endif /* CONFIG_SAE */
1140         if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1141                 ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
1142                 if (os_snprintf_error(end - pos, ret))
1143                         return pos - buf;
1144                 pos += ret;
1145         }
1146         if (hapd->conf->wpa_key_mgmt &
1147             WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1148                 ret = os_snprintf(pos, end - pos,
1149                                   "WPA-EAP-SUITE-B-192 ");
1150                 if (os_snprintf_error(end - pos, ret))
1151                         return pos - buf;
1152                 pos += ret;
1153         }
1154
1155         if (pos > buf && *(pos - 1) == ' ') {
1156                 *(pos - 1) = '\0';
1157                 pos--;
1158         }
1159
1160         return pos - buf;
1161 }
1162
1163
1164 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
1165                                          char *buf, size_t buflen)
1166 {
1167         int ret;
1168         char *pos, *end;
1169
1170         pos = buf;
1171         end = buf + buflen;
1172
1173         ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
1174                           "ssid=%s\n",
1175                           MAC2STR(hapd->own_addr),
1176                           wpa_ssid_txt(hapd->conf->ssid.ssid,
1177                                        hapd->conf->ssid.ssid_len));
1178         if (os_snprintf_error(end - pos, ret))
1179                 return pos - buf;
1180         pos += ret;
1181
1182 #ifdef CONFIG_WPS
1183         ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
1184                           hapd->conf->wps_state == 0 ? "disabled" :
1185                           (hapd->conf->wps_state == 1 ? "not configured" :
1186                            "configured"));
1187         if (os_snprintf_error(end - pos, ret))
1188                 return pos - buf;
1189         pos += ret;
1190
1191         if (hapd->conf->wps_state && hapd->conf->wpa &&
1192             hapd->conf->ssid.wpa_passphrase) {
1193                 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
1194                                   hapd->conf->ssid.wpa_passphrase);
1195                 if (os_snprintf_error(end - pos, ret))
1196                         return pos - buf;
1197                 pos += ret;
1198         }
1199
1200         if (hapd->conf->wps_state && hapd->conf->wpa &&
1201             hapd->conf->ssid.wpa_psk &&
1202             hapd->conf->ssid.wpa_psk->group) {
1203                 char hex[PMK_LEN * 2 + 1];
1204                 wpa_snprintf_hex(hex, sizeof(hex),
1205                                  hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
1206                 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
1207                 if (os_snprintf_error(end - pos, ret))
1208                         return pos - buf;
1209                 pos += ret;
1210         }
1211 #endif /* CONFIG_WPS */
1212
1213         if (hapd->conf->wpa) {
1214                 ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa);
1215                 if (os_snprintf_error(end - pos, ret))
1216                         return pos - buf;
1217                 pos += ret;
1218         }
1219
1220         if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
1221                 ret = os_snprintf(pos, end - pos, "key_mgmt=");
1222                 if (os_snprintf_error(end - pos, ret))
1223                         return pos - buf;
1224                 pos += ret;
1225
1226                 pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos);
1227
1228                 ret = os_snprintf(pos, end - pos, "\n");
1229                 if (os_snprintf_error(end - pos, ret))
1230                         return pos - buf;
1231                 pos += ret;
1232         }
1233
1234         if (hapd->conf->wpa) {
1235                 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
1236                                   wpa_cipher_txt(hapd->conf->wpa_group));
1237                 if (os_snprintf_error(end - pos, ret))
1238                         return pos - buf;
1239                 pos += ret;
1240         }
1241
1242         if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
1243                 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
1244                 if (os_snprintf_error(end - pos, ret))
1245                         return pos - buf;
1246                 pos += ret;
1247
1248                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
1249                                         " ");
1250                 if (ret < 0)
1251                         return pos - buf;
1252                 pos += ret;
1253
1254                 ret = os_snprintf(pos, end - pos, "\n");
1255                 if (os_snprintf_error(end - pos, ret))
1256                         return pos - buf;
1257                 pos += ret;
1258         }
1259
1260         if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
1261                 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
1262                 if (os_snprintf_error(end - pos, ret))
1263                         return pos - buf;
1264                 pos += ret;
1265
1266                 ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
1267                                         " ");
1268                 if (ret < 0)
1269                         return pos - buf;
1270                 pos += ret;
1271
1272                 ret = os_snprintf(pos, end - pos, "\n");
1273                 if (os_snprintf_error(end - pos, ret))
1274                         return pos - buf;
1275                 pos += ret;
1276         }
1277
1278         return pos - buf;
1279 }
1280
1281
1282 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
1283 {
1284         char *value;
1285         int ret = 0;
1286
1287         value = os_strchr(cmd, ' ');
1288         if (value == NULL)
1289                 return -1;
1290         *value++ = '\0';
1291
1292         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
1293         if (0) {
1294 #ifdef CONFIG_WPS_TESTING
1295         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
1296                 long int val;
1297                 val = strtol(value, NULL, 0);
1298                 if (val < 0 || val > 0xff) {
1299                         ret = -1;
1300                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
1301                                    "wps_version_number %ld", val);
1302                 } else {
1303                         wps_version_number = val;
1304                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
1305                                    "version %u.%u",
1306                                    (wps_version_number & 0xf0) >> 4,
1307                                    wps_version_number & 0x0f);
1308                         hostapd_wps_update_ie(hapd);
1309                 }
1310         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
1311                 wps_testing_dummy_cred = atoi(value);
1312                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
1313                            wps_testing_dummy_cred);
1314         } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
1315                 wps_corrupt_pkhash = atoi(value);
1316                 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
1317                            wps_corrupt_pkhash);
1318 #endif /* CONFIG_WPS_TESTING */
1319 #ifdef CONFIG_INTERWORKING
1320         } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
1321                 int val = atoi(value);
1322                 if (val <= 0)
1323                         ret = -1;
1324                 else
1325                         hapd->gas_frag_limit = val;
1326 #endif /* CONFIG_INTERWORKING */
1327 #ifdef CONFIG_TESTING_OPTIONS
1328         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
1329                 hapd->ext_mgmt_frame_handling = atoi(value);
1330         } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
1331                 hapd->ext_eapol_frame_io = atoi(value);
1332 #endif /* CONFIG_TESTING_OPTIONS */
1333 #ifdef CONFIG_MBO
1334         } else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) {
1335                 int val;
1336
1337                 if (!hapd->conf->mbo_enabled)
1338                         return -1;
1339
1340                 val = atoi(value);
1341                 if (val < 0 || val > 1)
1342                         return -1;
1343
1344                 hapd->mbo_assoc_disallow = val;
1345                 ieee802_11_update_beacons(hapd->iface);
1346
1347                 /*
1348                  * TODO: Need to configure drivers that do AP MLME offload with
1349                  * disallowing station logic.
1350                  */
1351 #endif /* CONFIG_MBO */
1352         } else {
1353                 struct sta_info *sta;
1354                 struct vlan_description vlan_id;
1355
1356                 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
1357                 if (ret)
1358                         return ret;
1359
1360                 if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
1361                         for (sta = hapd->sta_list; sta; sta = sta->next) {
1362                                 if (hostapd_maclist_found(
1363                                             hapd->conf->deny_mac,
1364                                             hapd->conf->num_deny_mac, sta->addr,
1365                                             &vlan_id) &&
1366                                     (!vlan_id.notempty ||
1367                                      !vlan_compare(&vlan_id, sta->vlan_desc)))
1368                                         ap_sta_disconnect(
1369                                                 hapd, sta, sta->addr,
1370                                                 WLAN_REASON_UNSPECIFIED);
1371                         }
1372                 } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
1373                            os_strcasecmp(cmd, "accept_mac_file") == 0) {
1374                         for (sta = hapd->sta_list; sta; sta = sta->next) {
1375                                 if (!hostapd_maclist_found(
1376                                             hapd->conf->accept_mac,
1377                                             hapd->conf->num_accept_mac,
1378                                             sta->addr, &vlan_id) ||
1379                                     (vlan_id.notempty &&
1380                                      vlan_compare(&vlan_id, sta->vlan_desc)))
1381                                         ap_sta_disconnect(
1382                                                 hapd, sta, sta->addr,
1383                                                 WLAN_REASON_UNSPECIFIED);
1384                         }
1385                 }
1386         }
1387
1388         return ret;
1389 }
1390
1391
1392 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
1393                                   char *buf, size_t buflen)
1394 {
1395         int res;
1396
1397         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
1398
1399         if (os_strcmp(cmd, "version") == 0) {
1400                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
1401                 if (os_snprintf_error(buflen, res))
1402                         return -1;
1403                 return res;
1404         } else if (os_strcmp(cmd, "tls_library") == 0) {
1405                 res = tls_get_library_version(buf, buflen);
1406                 if (os_snprintf_error(buflen, res))
1407                         return -1;
1408                 return res;
1409         }
1410
1411         return -1;
1412 }
1413
1414
1415 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
1416 {
1417         if (hostapd_enable_iface(iface) < 0) {
1418                 wpa_printf(MSG_ERROR, "Enabling of interface failed");
1419                 return -1;
1420         }
1421         return 0;
1422 }
1423
1424
1425 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
1426 {
1427         if (hostapd_reload_iface(iface) < 0) {
1428                 wpa_printf(MSG_ERROR, "Reloading of interface failed");
1429                 return -1;
1430         }
1431         return 0;
1432 }
1433
1434
1435 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
1436 {
1437         if (hostapd_disable_iface(iface) < 0) {
1438                 wpa_printf(MSG_ERROR, "Disabling of interface failed");
1439                 return -1;
1440         }
1441         return 0;
1442 }
1443
1444
1445 #ifdef CONFIG_TESTING_OPTIONS
1446
1447 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
1448 {
1449         union wpa_event_data data;
1450         char *pos, *param;
1451         enum wpa_event_type event;
1452
1453         wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1454
1455         os_memset(&data, 0, sizeof(data));
1456
1457         param = os_strchr(cmd, ' ');
1458         if (param == NULL)
1459                 return -1;
1460         *param++ = '\0';
1461
1462         if (os_strcmp(cmd, "DETECTED") == 0)
1463                 event = EVENT_DFS_RADAR_DETECTED;
1464         else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1465                 event = EVENT_DFS_CAC_FINISHED;
1466         else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1467                 event = EVENT_DFS_CAC_ABORTED;
1468         else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1469                 event = EVENT_DFS_NOP_FINISHED;
1470         else {
1471                 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1472                            cmd);
1473                 return -1;
1474         }
1475
1476         pos = os_strstr(param, "freq=");
1477         if (pos)
1478                 data.dfs_event.freq = atoi(pos + 5);
1479
1480         pos = os_strstr(param, "ht_enabled=1");
1481         if (pos)
1482                 data.dfs_event.ht_enabled = 1;
1483
1484         pos = os_strstr(param, "chan_offset=");
1485         if (pos)
1486                 data.dfs_event.chan_offset = atoi(pos + 12);
1487
1488         pos = os_strstr(param, "chan_width=");
1489         if (pos)
1490                 data.dfs_event.chan_width = atoi(pos + 11);
1491
1492         pos = os_strstr(param, "cf1=");
1493         if (pos)
1494                 data.dfs_event.cf1 = atoi(pos + 4);
1495
1496         pos = os_strstr(param, "cf2=");
1497         if (pos)
1498                 data.dfs_event.cf2 = atoi(pos + 4);
1499
1500         wpa_supplicant_event(hapd, event, &data);
1501
1502         return 0;
1503 }
1504
1505
1506 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
1507 {
1508         size_t len;
1509         u8 *buf;
1510         int res;
1511
1512         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
1513
1514         len = os_strlen(cmd);
1515         if (len & 1)
1516                 return -1;
1517         len /= 2;
1518
1519         buf = os_malloc(len);
1520         if (buf == NULL)
1521                 return -1;
1522
1523         if (hexstr2bin(cmd, buf, len) < 0) {
1524                 os_free(buf);
1525                 return -1;
1526         }
1527
1528         res = hostapd_drv_send_mlme(hapd, buf, len, 0);
1529         os_free(buf);
1530         return res;
1531 }
1532
1533
1534 static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
1535 {
1536         char *pos;
1537         u8 src[ETH_ALEN], *buf;
1538         int used;
1539         size_t len;
1540
1541         wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
1542
1543         pos = cmd;
1544         used = hwaddr_aton2(pos, src);
1545         if (used < 0)
1546                 return -1;
1547         pos += used;
1548         while (*pos == ' ')
1549                 pos++;
1550
1551         len = os_strlen(pos);
1552         if (len & 1)
1553                 return -1;
1554         len /= 2;
1555
1556         buf = os_malloc(len);
1557         if (buf == NULL)
1558                 return -1;
1559
1560         if (hexstr2bin(pos, buf, len) < 0) {
1561                 os_free(buf);
1562                 return -1;
1563         }
1564
1565         ieee802_1x_receive(hapd, src, buf, len);
1566         os_free(buf);
1567
1568         return 0;
1569 }
1570
1571
1572 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
1573 {
1574         size_t i;
1575         u32 sum = 0;
1576         const u16 *pos = buf;
1577
1578         for (i = 0; i < len / 2; i++)
1579                 sum += *pos++;
1580
1581         while (sum >> 16)
1582                 sum = (sum & 0xffff) + (sum >> 16);
1583
1584         return sum ^ 0xffff;
1585 }
1586
1587
1588 #define HWSIM_PACKETLEN 1500
1589 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
1590
1591 void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
1592                           size_t len)
1593 {
1594         struct hostapd_data *hapd = ctx;
1595         const struct ether_header *eth;
1596         struct iphdr ip;
1597         const u8 *pos;
1598         unsigned int i;
1599
1600         if (len != HWSIM_PACKETLEN)
1601                 return;
1602
1603         eth = (const struct ether_header *) buf;
1604         os_memcpy(&ip, eth + 1, sizeof(ip));
1605         pos = &buf[sizeof(*eth) + sizeof(ip)];
1606
1607         if (ip.ihl != 5 || ip.version != 4 ||
1608             ntohs(ip.tot_len) != HWSIM_IP_LEN)
1609                 return;
1610
1611         for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
1612                 if (*pos != (u8) i)
1613                         return;
1614                 pos++;
1615         }
1616
1617         wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
1618                 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
1619 }
1620
1621
1622 static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
1623                                                char *cmd)
1624 {
1625         int enabled = atoi(cmd);
1626         char *pos;
1627         const char *ifname;
1628
1629         if (!enabled) {
1630                 if (hapd->l2_test) {
1631                         l2_packet_deinit(hapd->l2_test);
1632                         hapd->l2_test = NULL;
1633                         wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
1634                                 "test data: Disabled");
1635                 }
1636                 return 0;
1637         }
1638
1639         if (hapd->l2_test)
1640                 return 0;
1641
1642         pos = os_strstr(cmd, " ifname=");
1643         if (pos)
1644                 ifname = pos + 8;
1645         else
1646                 ifname = hapd->conf->iface;
1647
1648         hapd->l2_test = l2_packet_init(ifname, hapd->own_addr,
1649                                         ETHERTYPE_IP, hostapd_data_test_rx,
1650                                         hapd, 1);
1651         if (hapd->l2_test == NULL)
1652                 return -1;
1653
1654         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
1655
1656         return 0;
1657 }
1658
1659
1660 static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
1661 {
1662         u8 dst[ETH_ALEN], src[ETH_ALEN];
1663         char *pos;
1664         int used;
1665         long int val;
1666         u8 tos;
1667         u8 buf[2 + HWSIM_PACKETLEN];
1668         struct ether_header *eth;
1669         struct iphdr *ip;
1670         u8 *dpos;
1671         unsigned int i;
1672
1673         if (hapd->l2_test == NULL)
1674                 return -1;
1675
1676         /* format: <dst> <src> <tos> */
1677
1678         pos = cmd;
1679         used = hwaddr_aton2(pos, dst);
1680         if (used < 0)
1681                 return -1;
1682         pos += used;
1683         while (*pos == ' ')
1684                 pos++;
1685         used = hwaddr_aton2(pos, src);
1686         if (used < 0)
1687                 return -1;
1688         pos += used;
1689
1690         val = strtol(pos, NULL, 0);
1691         if (val < 0 || val > 0xff)
1692                 return -1;
1693         tos = val;
1694
1695         eth = (struct ether_header *) &buf[2];
1696         os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
1697         os_memcpy(eth->ether_shost, src, ETH_ALEN);
1698         eth->ether_type = htons(ETHERTYPE_IP);
1699         ip = (struct iphdr *) (eth + 1);
1700         os_memset(ip, 0, sizeof(*ip));
1701         ip->ihl = 5;
1702         ip->version = 4;
1703         ip->ttl = 64;
1704         ip->tos = tos;
1705         ip->tot_len = htons(HWSIM_IP_LEN);
1706         ip->protocol = 1;
1707         ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
1708         ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
1709         ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
1710         dpos = (u8 *) (ip + 1);
1711         for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
1712                 *dpos++ = i;
1713
1714         if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
1715                            HWSIM_PACKETLEN) < 0)
1716                 return -1;
1717
1718         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
1719                 " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
1720
1721         return 0;
1722 }
1723
1724
1725 static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
1726                                               char *cmd)
1727 {
1728         u8 *buf;
1729         struct ether_header *eth;
1730         struct l2_packet_data *l2 = NULL;
1731         size_t len;
1732         u16 ethertype;
1733         int res = -1;
1734         const char *ifname = hapd->conf->iface;
1735
1736         if (os_strncmp(cmd, "ifname=", 7) == 0) {
1737                 cmd += 7;
1738                 ifname = cmd;
1739                 cmd = os_strchr(cmd, ' ');
1740                 if (cmd == NULL)
1741                         return -1;
1742                 *cmd++ = '\0';
1743         }
1744
1745         len = os_strlen(cmd);
1746         if (len & 1 || len < ETH_HLEN * 2)
1747                 return -1;
1748         len /= 2;
1749
1750         buf = os_malloc(len);
1751         if (buf == NULL)
1752                 return -1;
1753
1754         if (hexstr2bin(cmd, buf, len) < 0)
1755                 goto done;
1756
1757         eth = (struct ether_header *) buf;
1758         ethertype = ntohs(eth->ether_type);
1759
1760         l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
1761                             hostapd_data_test_rx, hapd, 1);
1762         if (l2 == NULL)
1763                 goto done;
1764
1765         res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
1766         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
1767 done:
1768         if (l2)
1769                 l2_packet_deinit(l2);
1770         os_free(buf);
1771
1772         return res < 0 ? -1 : 0;
1773 }
1774
1775
1776 static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
1777 {
1778 #ifdef WPA_TRACE_BFD
1779         extern char wpa_trace_fail_func[256];
1780         extern unsigned int wpa_trace_fail_after;
1781         char *pos;
1782
1783         wpa_trace_fail_after = atoi(cmd);
1784         pos = os_strchr(cmd, ':');
1785         if (pos) {
1786                 pos++;
1787                 os_strlcpy(wpa_trace_fail_func, pos,
1788                            sizeof(wpa_trace_fail_func));
1789         } else {
1790                 wpa_trace_fail_after = 0;
1791         }
1792
1793         return 0;
1794 #else /* WPA_TRACE_BFD */
1795         return -1;
1796 #endif /* WPA_TRACE_BFD */
1797 }
1798
1799
1800 static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
1801                                        char *buf, size_t buflen)
1802 {
1803 #ifdef WPA_TRACE_BFD
1804         extern char wpa_trace_fail_func[256];
1805         extern unsigned int wpa_trace_fail_after;
1806
1807         return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
1808                            wpa_trace_fail_func);
1809 #else /* WPA_TRACE_BFD */
1810         return -1;
1811 #endif /* WPA_TRACE_BFD */
1812 }
1813
1814
1815 static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
1816 {
1817 #ifdef WPA_TRACE_BFD
1818         extern char wpa_trace_test_fail_func[256];
1819         extern unsigned int wpa_trace_test_fail_after;
1820         char *pos;
1821
1822         wpa_trace_test_fail_after = atoi(cmd);
1823         pos = os_strchr(cmd, ':');
1824         if (pos) {
1825                 pos++;
1826                 os_strlcpy(wpa_trace_test_fail_func, pos,
1827                            sizeof(wpa_trace_test_fail_func));
1828         } else {
1829                 wpa_trace_test_fail_after = 0;
1830         }
1831
1832         return 0;
1833 #else /* WPA_TRACE_BFD */
1834         return -1;
1835 #endif /* WPA_TRACE_BFD */
1836 }
1837
1838
1839 static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
1840                                  char *buf, size_t buflen)
1841 {
1842 #ifdef WPA_TRACE_BFD
1843         extern char wpa_trace_test_fail_func[256];
1844         extern unsigned int wpa_trace_test_fail_after;
1845
1846         return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
1847                            wpa_trace_test_fail_func);
1848 #else /* WPA_TRACE_BFD */
1849         return -1;
1850 #endif /* WPA_TRACE_BFD */
1851 }
1852
1853 #endif /* CONFIG_TESTING_OPTIONS */
1854
1855
1856 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
1857                                           char *pos)
1858 {
1859 #ifdef NEED_AP_MLME
1860         struct csa_settings settings;
1861         int ret;
1862         unsigned int i;
1863
1864         ret = hostapd_parse_csa_settings(pos, &settings);
1865         if (ret)
1866                 return ret;
1867
1868         for (i = 0; i < iface->num_bss; i++) {
1869                 ret = hostapd_switch_channel(iface->bss[i], &settings);
1870                 if (ret) {
1871                         /* FIX: What do we do if CSA fails in the middle of
1872                          * submitting multi-BSS CSA requests? */
1873                         return ret;
1874                 }
1875         }
1876
1877         return 0;
1878 #else /* NEED_AP_MLME */
1879         return -1;
1880 #endif /* NEED_AP_MLME */
1881 }
1882
1883
1884 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
1885                                   int reply_size, const char *param)
1886 {
1887 #ifdef RADIUS_SERVER
1888         if (os_strcmp(param, "radius_server") == 0) {
1889                 return radius_server_get_mib(hapd->radius_srv, reply,
1890                                              reply_size);
1891         }
1892 #endif /* RADIUS_SERVER */
1893         return -1;
1894 }
1895
1896
1897 static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
1898                                      char *buf, size_t buflen)
1899 {
1900         int ret;
1901         char *pos;
1902         u8 *data = NULL;
1903         unsigned int vendor_id, subcmd;
1904         struct wpabuf *reply;
1905         size_t data_len = 0;
1906
1907         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
1908         vendor_id = strtoul(cmd, &pos, 16);
1909         if (!isblank((unsigned char) *pos))
1910                 return -EINVAL;
1911
1912         subcmd = strtoul(pos, &pos, 10);
1913
1914         if (*pos != '\0') {
1915                 if (!isblank((unsigned char) *pos++))
1916                         return -EINVAL;
1917                 data_len = os_strlen(pos);
1918         }
1919
1920         if (data_len) {
1921                 data_len /= 2;
1922                 data = os_malloc(data_len);
1923                 if (!data)
1924                         return -ENOBUFS;
1925
1926                 if (hexstr2bin(pos, data, data_len)) {
1927                         wpa_printf(MSG_DEBUG,
1928                                    "Vendor command: wrong parameter format");
1929                         os_free(data);
1930                         return -EINVAL;
1931                 }
1932         }
1933
1934         reply = wpabuf_alloc((buflen - 1) / 2);
1935         if (!reply) {
1936                 os_free(data);
1937                 return -ENOBUFS;
1938         }
1939
1940         ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
1941                                      reply);
1942
1943         if (ret == 0)
1944                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
1945                                        wpabuf_len(reply));
1946
1947         wpabuf_free(reply);
1948         os_free(data);
1949
1950         return ret;
1951 }
1952
1953
1954 static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
1955                                            const char *cmd)
1956 {
1957         u8 addr[ETH_ALEN];
1958         struct sta_info *sta;
1959
1960         if (hwaddr_aton(cmd, addr))
1961                 return -1;
1962
1963         sta = ap_get_sta(hapd, addr);
1964         if (!sta || !sta->eapol_sm)
1965                 return -1;
1966
1967         eapol_auth_reauthenticate(sta->eapol_sm);
1968         return 0;
1969 }
1970
1971
1972 static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
1973 {
1974         u8 addr[ETH_ALEN];
1975         struct sta_info *sta;
1976         char *pos = cmd, *param;
1977
1978         if (hwaddr_aton(pos, addr) || pos[17] != ' ')
1979                 return -1;
1980         pos += 18;
1981         param = pos;
1982         pos = os_strchr(pos, ' ');
1983         if (!pos)
1984                 return -1;
1985         *pos++ = '\0';
1986
1987         sta = ap_get_sta(hapd, addr);
1988         if (!sta || !sta->eapol_sm)
1989                 return -1;
1990
1991         return eapol_auth_set_conf(sta->eapol_sm, param, pos);
1992 }
1993
1994
1995 static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd,
1996                                         char *buf, size_t buflen)
1997 {
1998         char *pos, *end, *stamp;
1999         int ret;
2000
2001         /* cmd: "LOG_LEVEL [<level>]" */
2002         if (*cmd == '\0') {
2003                 pos = buf;
2004                 end = buf + buflen;
2005                 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2006                                   "Timestamp: %d\n",
2007                                   debug_level_str(wpa_debug_level),
2008                                   wpa_debug_timestamp);
2009                 if (os_snprintf_error(end - pos, ret))
2010                         ret = 0;
2011
2012                 return ret;
2013         }
2014
2015         while (*cmd == ' ')
2016                 cmd++;
2017
2018         stamp = os_strchr(cmd, ' ');
2019         if (stamp) {
2020                 *stamp++ = '\0';
2021                 while (*stamp == ' ') {
2022                         stamp++;
2023                 }
2024         }
2025
2026         if (os_strlen(cmd)) {
2027                 int level = str_to_debug_level(cmd);
2028                 if (level < 0)
2029                         return -1;
2030                 wpa_debug_level = level;
2031         }
2032
2033         if (stamp && os_strlen(stamp))
2034                 wpa_debug_timestamp = atoi(stamp);
2035
2036         os_memcpy(buf, "OK\n", 3);
2037         return 3;
2038 }
2039
2040
2041 #ifdef NEED_AP_MLME
2042 static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
2043                                              char *buf, size_t buflen)
2044 {
2045         struct hostapd_iface *iface = hapd->iface;
2046         char *pos, *end;
2047         struct hostapd_sta_info *info;
2048         struct os_reltime now;
2049
2050         sta_track_expire(iface, 0);
2051
2052         pos = buf;
2053         end = buf + buflen;
2054
2055         os_get_reltime(&now);
2056         dl_list_for_each_reverse(info, &iface->sta_seen,
2057                                  struct hostapd_sta_info, list) {
2058                 struct os_reltime age;
2059                 int ret;
2060
2061                 os_reltime_sub(&now, &info->last_seen, &age);
2062                 ret = os_snprintf(pos, end - pos, MACSTR " %u\n",
2063                                   MAC2STR(info->addr), (unsigned int) age.sec);
2064                 if (os_snprintf_error(end - pos, ret))
2065                         break;
2066                 pos += ret;
2067         }
2068
2069         return pos - buf;
2070 }
2071 #endif /* NEED_AP_MLME */
2072
2073
2074 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
2075                                               char *buf, char *reply,
2076                                               int reply_size,
2077                                               struct sockaddr_storage *from,
2078                                               socklen_t fromlen)
2079 {
2080         int reply_len, res;
2081
2082         os_memcpy(reply, "OK\n", 3);
2083         reply_len = 3;
2084
2085         if (os_strcmp(buf, "PING") == 0) {
2086                 os_memcpy(reply, "PONG\n", 5);
2087                 reply_len = 5;
2088         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
2089                 if (wpa_debug_reopen_file() < 0)
2090                         reply_len = -1;
2091         } else if (os_strcmp(buf, "STATUS") == 0) {
2092                 reply_len = hostapd_ctrl_iface_status(hapd, reply,
2093                                                       reply_size);
2094         } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
2095                 reply_len = hostapd_drv_status(hapd, reply, reply_size);
2096         } else if (os_strcmp(buf, "MIB") == 0) {
2097                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
2098                 if (reply_len >= 0) {
2099                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
2100                                           reply_size - reply_len);
2101                         if (res < 0)
2102                                 reply_len = -1;
2103                         else
2104                                 reply_len += res;
2105                 }
2106                 if (reply_len >= 0) {
2107                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
2108                                                  reply_size - reply_len);
2109                         if (res < 0)
2110                                 reply_len = -1;
2111                         else
2112                                 reply_len += res;
2113                 }
2114 #ifndef CONFIG_NO_RADIUS
2115                 if (reply_len >= 0) {
2116                         res = radius_client_get_mib(hapd->radius,
2117                                                     reply + reply_len,
2118                                                     reply_size - reply_len);
2119                         if (res < 0)
2120                                 reply_len = -1;
2121                         else
2122                                 reply_len += res;
2123                 }
2124 #endif /* CONFIG_NO_RADIUS */
2125         } else if (os_strncmp(buf, "MIB ", 4) == 0) {
2126                 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
2127                                                    buf + 4);
2128         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
2129                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
2130                                                          reply_size);
2131         } else if (os_strncmp(buf, "STA ", 4) == 0) {
2132                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
2133                                                    reply_size);
2134         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
2135                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
2136                                                         reply_size);
2137         } else if (os_strcmp(buf, "ATTACH") == 0) {
2138                 if (hostapd_ctrl_iface_attach(hapd, from, fromlen))
2139                         reply_len = -1;
2140         } else if (os_strcmp(buf, "DETACH") == 0) {
2141                 if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
2142                         reply_len = -1;
2143         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
2144                 if (hostapd_ctrl_iface_level(hapd, from, fromlen,
2145                                                     buf + 6))
2146                         reply_len = -1;
2147         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
2148                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
2149                         reply_len = -1;
2150         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
2151                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
2152                         reply_len = -1;
2153         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
2154                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
2155                         reply_len = -1;
2156         } else if (os_strncmp(buf, "POLL_STA ", 9) == 0) {
2157                 if (hostapd_ctrl_iface_poll_sta(hapd, buf + 9))
2158                         reply_len = -1;
2159         } else if (os_strcmp(buf, "STOP_AP") == 0) {
2160                 if (hostapd_ctrl_iface_stop_ap(hapd))
2161                         reply_len = -1;
2162 #ifdef CONFIG_IEEE80211W
2163 #ifdef NEED_AP_MLME
2164         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
2165                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
2166                         reply_len = -1;
2167 #endif /* NEED_AP_MLME */
2168 #endif /* CONFIG_IEEE80211W */
2169 #ifdef CONFIG_WPS
2170         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
2171                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
2172                         reply_len = -1;
2173         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
2174                 reply_len = hostapd_ctrl_iface_wps_check_pin(
2175                         hapd, buf + 14, reply, reply_size);
2176         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
2177                 if (hostapd_wps_button_pushed(hapd, NULL))
2178                         reply_len = -1;
2179         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
2180                 if (hostapd_wps_cancel(hapd))
2181                         reply_len = -1;
2182         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
2183                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
2184                                                           reply, reply_size);
2185         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
2186                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
2187                         reply_len = -1;
2188         } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
2189                 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
2190                                                               reply_size);
2191 #ifdef CONFIG_WPS_NFC
2192         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
2193                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
2194                         reply_len = -1;
2195         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
2196                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
2197                         hapd, buf + 21, reply, reply_size);
2198         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
2199                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
2200                         hapd, buf + 14, reply, reply_size);
2201         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
2202                 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
2203                         hapd, buf + 21, reply, reply_size);
2204         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
2205                 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
2206                         reply_len = -1;
2207 #endif /* CONFIG_WPS_NFC */
2208 #endif /* CONFIG_WPS */
2209 #ifdef CONFIG_INTERWORKING
2210         } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
2211                 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
2212                         reply_len = -1;
2213         } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
2214                 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
2215                         reply_len = -1;
2216 #endif /* CONFIG_INTERWORKING */
2217 #ifdef CONFIG_HS20
2218         } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
2219                 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
2220                         reply_len = -1;
2221         } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
2222                 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
2223                         reply_len = -1;
2224 #endif /* CONFIG_HS20 */
2225 #ifdef CONFIG_WNM
2226         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
2227                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
2228                         reply_len = -1;
2229         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
2230                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
2231                         reply_len = -1;
2232         } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
2233                 if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
2234                         reply_len = -1;
2235 #endif /* CONFIG_WNM */
2236         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
2237                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
2238                                                           reply_size);
2239         } else if (os_strncmp(buf, "SET ", 4) == 0) {
2240                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
2241                         reply_len = -1;
2242         } else if (os_strncmp(buf, "GET ", 4) == 0) {
2243                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
2244                                                    reply_size);
2245         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
2246                 if (hostapd_ctrl_iface_enable(hapd->iface))
2247                         reply_len = -1;
2248         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
2249                 if (hostapd_ctrl_iface_reload(hapd->iface))
2250                         reply_len = -1;
2251         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
2252                 if (hostapd_ctrl_iface_disable(hapd->iface))
2253                         reply_len = -1;
2254         } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
2255                 if (ieee802_11_set_beacon(hapd))
2256                         reply_len = -1;
2257 #ifdef CONFIG_TESTING_OPTIONS
2258         } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
2259                 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
2260                         reply_len = -1;
2261         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
2262                 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
2263                         reply_len = -1;
2264         } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
2265                 if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
2266                         reply_len = -1;
2267         } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
2268                 if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
2269                         reply_len = -1;
2270         } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
2271                 if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
2272                         reply_len = -1;
2273         } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
2274                 if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
2275                         reply_len = -1;
2276         } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
2277                 if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
2278                         reply_len = -1;
2279         } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
2280                 reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
2281                                                         reply_size);
2282         } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
2283                 if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
2284                         reply_len = -1;
2285         } else if (os_strcmp(buf, "GET_FAIL") == 0) {
2286                 reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
2287 #endif /* CONFIG_TESTING_OPTIONS */
2288         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
2289                 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
2290                         reply_len = -1;
2291         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
2292                 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
2293                                                       reply_size);
2294         } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
2295                 ieee802_1x_erp_flush(hapd);
2296 #ifdef RADIUS_SERVER
2297                 radius_server_erp_flush(hapd->radius_srv);
2298 #endif /* RADIUS_SERVER */
2299         } else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
2300                 if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
2301                         reply_len = -1;
2302         } else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
2303                 if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
2304                         reply_len = -1;
2305         } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
2306                 reply_len = hostapd_ctrl_iface_log_level(
2307                         hapd, buf + 9, reply, reply_size);
2308 #ifdef NEED_AP_MLME
2309         } else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
2310                 reply_len = hostapd_ctrl_iface_track_sta_list(
2311                         hapd, reply, reply_size);
2312 #endif /* NEED_AP_MLME */
2313         } else if (os_strcmp(buf, "PMKSA") == 0) {
2314                 reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply,
2315                                                           reply_size);
2316         } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
2317                 hostapd_ctrl_iface_pmksa_flush(hapd);
2318         } else {
2319                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
2320                 reply_len = 16;
2321         }
2322
2323         if (reply_len < 0) {
2324                 os_memcpy(reply, "FAIL\n", 5);
2325                 reply_len = 5;
2326         }
2327
2328         return reply_len;
2329 }
2330
2331
2332 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
2333                                        void *sock_ctx)
2334 {
2335         struct hostapd_data *hapd = eloop_ctx;
2336         char buf[4096];
2337         int res;
2338         struct sockaddr_storage from;
2339         socklen_t fromlen = sizeof(from);
2340         char *reply, *pos = buf;
2341         const int reply_size = 4096;
2342         int reply_len;
2343         int level = MSG_DEBUG;
2344 #ifdef CONFIG_CTRL_IFACE_UDP
2345         unsigned char lcookie[COOKIE_LEN];
2346 #endif /* CONFIG_CTRL_IFACE_UDP */
2347
2348         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
2349                        (struct sockaddr *) &from, &fromlen);
2350         if (res < 0) {
2351                 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
2352                            strerror(errno));
2353                 return;
2354         }
2355         buf[res] = '\0';
2356
2357         reply = os_malloc(reply_size);
2358         if (reply == NULL) {
2359                 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
2360                            fromlen) < 0) {
2361                         wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2362                                    strerror(errno));
2363                 }
2364                 return;
2365         }
2366
2367 #ifdef CONFIG_CTRL_IFACE_UDP
2368         if (os_strcmp(buf, "GET_COOKIE") == 0) {
2369                 os_memcpy(reply, "COOKIE=", 7);
2370                 wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
2371                                  cookie, COOKIE_LEN);
2372                 reply_len = 7 + 2 * COOKIE_LEN;
2373                 goto done;
2374         }
2375
2376         if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
2377             hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
2378                 wpa_printf(MSG_DEBUG,
2379                            "CTRL: No cookie in the request - drop request");
2380                 os_free(reply);
2381                 return;
2382         }
2383
2384         if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) {
2385                 wpa_printf(MSG_DEBUG,
2386                            "CTRL: Invalid cookie in the request - drop request");
2387                 os_free(reply);
2388                 return;
2389         }
2390
2391         pos = buf + 7 + 2 * COOKIE_LEN;
2392         while (*pos == ' ')
2393                 pos++;
2394 #endif /* CONFIG_CTRL_IFACE_UDP */
2395
2396         if (os_strcmp(pos, "PING") == 0)
2397                 level = MSG_EXCESSIVE;
2398         wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res);
2399
2400         reply_len = hostapd_ctrl_iface_receive_process(hapd, pos,
2401                                                        reply, reply_size,
2402                                                        &from, fromlen);
2403
2404 #ifdef CONFIG_CTRL_IFACE_UDP
2405 done:
2406 #endif /* CONFIG_CTRL_IFACE_UDP */
2407         if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
2408                    fromlen) < 0) {
2409                 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2410                            strerror(errno));
2411         }
2412         os_free(reply);
2413 }
2414
2415
2416 #ifndef CONFIG_CTRL_IFACE_UDP
2417 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
2418 {
2419         char *buf;
2420         size_t len;
2421
2422         if (hapd->conf->ctrl_interface == NULL)
2423                 return NULL;
2424
2425         len = os_strlen(hapd->conf->ctrl_interface) +
2426                 os_strlen(hapd->conf->iface) + 2;
2427         buf = os_malloc(len);
2428         if (buf == NULL)
2429                 return NULL;
2430
2431         os_snprintf(buf, len, "%s/%s",
2432                     hapd->conf->ctrl_interface, hapd->conf->iface);
2433         buf[len - 1] = '\0';
2434         return buf;
2435 }
2436 #endif /* CONFIG_CTRL_IFACE_UDP */
2437
2438
2439 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
2440                                       enum wpa_msg_type type,
2441                                       const char *txt, size_t len)
2442 {
2443         struct hostapd_data *hapd = ctx;
2444         if (hapd == NULL)
2445                 return;
2446         hostapd_ctrl_iface_send(hapd, level, type, txt, len);
2447 }
2448
2449
2450 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
2451 {
2452 #ifdef CONFIG_CTRL_IFACE_UDP
2453         int port = HOSTAPD_CTRL_IFACE_PORT;
2454         char p[32] = { 0 };
2455         char port_str[40], *tmp;
2456         char *pos;
2457         struct addrinfo hints = { 0 }, *res, *saveres;
2458         int n;
2459
2460         if (hapd->ctrl_sock > -1) {
2461                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
2462                 return 0;
2463         }
2464
2465         if (hapd->conf->ctrl_interface == NULL)
2466                 return 0;
2467
2468         pos = os_strstr(hapd->conf->ctrl_interface, "udp:");
2469         if (pos) {
2470                 pos += 4;
2471                 port = atoi(pos);
2472                 if (port <= 0) {
2473                         wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port");
2474                         goto fail;
2475                 }
2476         }
2477
2478         dl_list_init(&hapd->ctrl_dst);
2479         hapd->ctrl_sock = -1;
2480         os_get_random(cookie, COOKIE_LEN);
2481
2482 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
2483         hints.ai_flags = AI_PASSIVE;
2484 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
2485
2486 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
2487         hints.ai_family = AF_INET6;
2488 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
2489         hints.ai_family = AF_INET;
2490 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
2491         hints.ai_socktype = SOCK_DGRAM;
2492
2493 try_again:
2494         os_snprintf(p, sizeof(p), "%d", port);
2495         n = getaddrinfo(NULL, p, &hints, &res);
2496         if (n) {
2497                 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
2498                 goto fail;
2499         }
2500
2501         saveres = res;
2502         hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype,
2503                                  res->ai_protocol);
2504         if (hapd->ctrl_sock < 0) {
2505                 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
2506                 goto fail;
2507         }
2508
2509         if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) {
2510                 port--;
2511                 if ((HOSTAPD_CTRL_IFACE_PORT - port) <
2512                     HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos)
2513                         goto try_again;
2514                 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
2515                 goto fail;
2516         }
2517
2518         freeaddrinfo(saveres);
2519
2520         os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
2521         tmp = os_strdup(port_str);
2522         if (tmp) {
2523                 os_free(hapd->conf->ctrl_interface);
2524                 hapd->conf->ctrl_interface = tmp;
2525         }
2526         wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
2527
2528         if (eloop_register_read_sock(hapd->ctrl_sock,
2529                                      hostapd_ctrl_iface_receive, hapd, NULL) <
2530             0) {
2531                 hostapd_ctrl_iface_deinit(hapd);
2532                 return -1;
2533         }
2534
2535         hapd->msg_ctx = hapd;
2536         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
2537
2538         return 0;
2539
2540 fail:
2541         if (hapd->ctrl_sock >= 0)
2542                 close(hapd->ctrl_sock);
2543         return -1;
2544 #else /* CONFIG_CTRL_IFACE_UDP */
2545         struct sockaddr_un addr;
2546         int s = -1;
2547         char *fname = NULL;
2548
2549         if (hapd->ctrl_sock > -1) {
2550                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
2551                 return 0;
2552         }
2553
2554         dl_list_init(&hapd->ctrl_dst);
2555
2556         if (hapd->conf->ctrl_interface == NULL)
2557                 return 0;
2558
2559         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2560                 if (errno == EEXIST) {
2561                         wpa_printf(MSG_DEBUG, "Using existing control "
2562                                    "interface directory.");
2563                 } else {
2564                         wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
2565                                    strerror(errno));
2566                         goto fail;
2567                 }
2568         }
2569
2570         if (hapd->conf->ctrl_interface_gid_set &&
2571             chown(hapd->conf->ctrl_interface, -1,
2572                   hapd->conf->ctrl_interface_gid) < 0) {
2573                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2574                            strerror(errno));
2575                 return -1;
2576         }
2577
2578         if (!hapd->conf->ctrl_interface_gid_set &&
2579             hapd->iface->interfaces->ctrl_iface_group &&
2580             chown(hapd->conf->ctrl_interface, -1,
2581                   hapd->iface->interfaces->ctrl_iface_group) < 0) {
2582                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2583                            strerror(errno));
2584                 return -1;
2585         }
2586
2587 #ifdef ANDROID
2588         /*
2589          * Android is using umask 0077 which would leave the control interface
2590          * directory without group access. This breaks things since Wi-Fi
2591          * framework assumes that this directory can be accessed by other
2592          * applications in the wifi group. Fix this by adding group access even
2593          * if umask value would prevent this.
2594          */
2595         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2596                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
2597                            strerror(errno));
2598                 /* Try to continue anyway */
2599         }
2600 #endif /* ANDROID */
2601
2602         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
2603             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
2604                 goto fail;
2605
2606         s = socket(PF_UNIX, SOCK_DGRAM, 0);
2607         if (s < 0) {
2608                 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
2609                 goto fail;
2610         }
2611
2612         os_memset(&addr, 0, sizeof(addr));
2613 #ifdef __FreeBSD__
2614         addr.sun_len = sizeof(addr);
2615 #endif /* __FreeBSD__ */
2616         addr.sun_family = AF_UNIX;
2617         fname = hostapd_ctrl_iface_path(hapd);
2618         if (fname == NULL)
2619                 goto fail;
2620         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
2621         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2622                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
2623                            strerror(errno));
2624                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2625                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
2626                                    " allow connections - assuming it was left"
2627                                    "over from forced program termination");
2628                         if (unlink(fname) < 0) {
2629                                 wpa_printf(MSG_ERROR,
2630                                            "Could not unlink existing ctrl_iface socket '%s': %s",
2631                                            fname, strerror(errno));
2632                                 goto fail;
2633                         }
2634                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
2635                             0) {
2636                                 wpa_printf(MSG_ERROR,
2637                                            "hostapd-ctrl-iface: bind(PF_UNIX): %s",
2638                                            strerror(errno));
2639                                 goto fail;
2640                         }
2641                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
2642                                    "ctrl_iface socket '%s'", fname);
2643                 } else {
2644                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
2645                                    "be in use - cannot override it");
2646                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
2647                                    "not used anymore", fname);
2648                         os_free(fname);
2649                         fname = NULL;
2650                         goto fail;
2651                 }
2652         }
2653
2654         if (hapd->conf->ctrl_interface_gid_set &&
2655             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
2656                 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
2657                            strerror(errno));
2658                 goto fail;
2659         }
2660
2661         if (!hapd->conf->ctrl_interface_gid_set &&
2662             hapd->iface->interfaces->ctrl_iface_group &&
2663             chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
2664                 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
2665                            strerror(errno));
2666                 goto fail;
2667         }
2668
2669         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
2670                 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
2671                            strerror(errno));
2672                 goto fail;
2673         }
2674         os_free(fname);
2675
2676         hapd->ctrl_sock = s;
2677         if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
2678                                      NULL) < 0) {
2679                 hostapd_ctrl_iface_deinit(hapd);
2680                 return -1;
2681         }
2682         hapd->msg_ctx = hapd;
2683         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
2684
2685         return 0;
2686
2687 fail:
2688         if (s >= 0)
2689                 close(s);
2690         if (fname) {
2691                 unlink(fname);
2692                 os_free(fname);
2693         }
2694         return -1;
2695 #endif /* CONFIG_CTRL_IFACE_UDP */
2696 }
2697
2698
2699 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
2700 {
2701         struct wpa_ctrl_dst *dst, *prev;
2702
2703         if (hapd->ctrl_sock > -1) {
2704 #ifndef CONFIG_CTRL_IFACE_UDP
2705                 char *fname;
2706 #endif /* !CONFIG_CTRL_IFACE_UDP */
2707
2708                 eloop_unregister_read_sock(hapd->ctrl_sock);
2709                 close(hapd->ctrl_sock);
2710                 hapd->ctrl_sock = -1;
2711 #ifndef CONFIG_CTRL_IFACE_UDP
2712                 fname = hostapd_ctrl_iface_path(hapd);
2713                 if (fname)
2714                         unlink(fname);
2715                 os_free(fname);
2716
2717                 if (hapd->conf->ctrl_interface &&
2718                     rmdir(hapd->conf->ctrl_interface) < 0) {
2719                         if (errno == ENOTEMPTY) {
2720                                 wpa_printf(MSG_DEBUG, "Control interface "
2721                                            "directory not empty - leaving it "
2722                                            "behind");
2723                         } else {
2724                                 wpa_printf(MSG_ERROR,
2725                                            "rmdir[ctrl_interface=%s]: %s",
2726                                            hapd->conf->ctrl_interface,
2727                                            strerror(errno));
2728                         }
2729                 }
2730 #endif /* !CONFIG_CTRL_IFACE_UDP */
2731         }
2732
2733         dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst,
2734                               list)
2735                 os_free(dst);
2736
2737 #ifdef CONFIG_TESTING_OPTIONS
2738         l2_packet_deinit(hapd->l2_test);
2739         hapd->l2_test = NULL;
2740 #endif /* CONFIG_TESTING_OPTIONS */
2741 }
2742
2743
2744 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
2745                                   char *buf)
2746 {
2747         if (hostapd_add_iface(interfaces, buf) < 0) {
2748                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
2749                 return -1;
2750         }
2751         return 0;
2752 }
2753
2754
2755 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
2756                                      char *buf)
2757 {
2758         if (hostapd_remove_iface(interfaces, buf) < 0) {
2759                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
2760                 return -1;
2761         }
2762         return 0;
2763 }
2764
2765
2766 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
2767                                             struct sockaddr_storage *from,
2768                                             socklen_t fromlen)
2769 {
2770         return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen);
2771 }
2772
2773
2774 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
2775                                             struct sockaddr_storage *from,
2776                                             socklen_t fromlen)
2777 {
2778         return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen);
2779 }
2780
2781
2782 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
2783 {
2784 #ifdef CONFIG_WPS_TESTING
2785         wps_version_number = 0x20;
2786         wps_testing_dummy_cred = 0;
2787         wps_corrupt_pkhash = 0;
2788 #endif /* CONFIG_WPS_TESTING */
2789 }
2790
2791
2792 #ifdef CONFIG_FST
2793
2794 static int
2795 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
2796                                      const char *cmd)
2797 {
2798         char ifname[IFNAMSIZ + 1];
2799         struct fst_iface_cfg cfg;
2800         struct hostapd_data *hapd;
2801         struct fst_wpa_obj iface_obj;
2802
2803         if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
2804                 hapd = hostapd_get_iface(interfaces, ifname);
2805                 if (hapd) {
2806                         if (hapd->iface->fst) {
2807                                 wpa_printf(MSG_INFO, "FST: Already attached");
2808                                 return -1;
2809                         }
2810                         fst_hostapd_fill_iface_obj(hapd, &iface_obj);
2811                         hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
2812                                                       &iface_obj, &cfg);
2813                         if (hapd->iface->fst)
2814                                 return 0;
2815                 }
2816         }
2817
2818         return -EINVAL;
2819 }
2820
2821
2822 static int
2823 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
2824                                      const char *cmd)
2825 {
2826         char ifname[IFNAMSIZ + 1];
2827         struct hostapd_data * hapd;
2828
2829         if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
2830                 hapd = hostapd_get_iface(interfaces, ifname);
2831                 if (hapd) {
2832                         if (!fst_iface_detach(ifname)) {
2833                                 hapd->iface->fst = NULL;
2834                                 hapd->iface->fst_ies = NULL;
2835                                 return 0;
2836                         }
2837                 }
2838         }
2839
2840         return -EINVAL;
2841 }
2842
2843 #endif /* CONFIG_FST */
2844
2845
2846 static struct hostapd_data *
2847 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
2848                             const char *ifname)
2849 {
2850         size_t i, j;
2851
2852         for (i = 0; i < interfaces->count; i++) {
2853                 struct hostapd_iface *iface = interfaces->iface[i];
2854
2855                 for (j = 0; j < iface->num_bss; j++) {
2856                         struct hostapd_data *hapd;
2857
2858                         hapd = iface->bss[j];
2859                         if (os_strcmp(ifname, hapd->conf->iface) == 0)
2860                                 return hapd;
2861                 }
2862         }
2863
2864         return NULL;
2865 }
2866
2867
2868 static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
2869                                         struct hostapd_data *dst_hapd,
2870                                         const char *param)
2871 {
2872         int res;
2873         char *value;
2874
2875         value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
2876         if (!value) {
2877                 wpa_printf(MSG_ERROR,
2878                            "DUP: cannot allocate buffer to stringify %s",
2879                            param);
2880                 goto error_return;
2881         }
2882
2883         if (os_strcmp(param, "wpa") == 0) {
2884                 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
2885                             src_hapd->conf->wpa);
2886         } else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
2887                    src_hapd->conf->wpa_key_mgmt) {
2888                 res = hostapd_ctrl_iface_get_key_mgmt(
2889                         src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
2890                 if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
2891                         goto error_stringify;
2892         } else if (os_strcmp(param, "wpa_pairwise") == 0 &&
2893                    src_hapd->conf->wpa_pairwise) {
2894                 res = wpa_write_ciphers(value,
2895                                         value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2896                                         src_hapd->conf->wpa_pairwise, " ");
2897                 if (res < 0)
2898                         goto error_stringify;
2899         } else if (os_strcmp(param, "rsn_pairwise") == 0 &&
2900                    src_hapd->conf->rsn_pairwise) {
2901                 res = wpa_write_ciphers(value,
2902                                         value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2903                                         src_hapd->conf->rsn_pairwise, " ");
2904                 if (res < 0)
2905                         goto error_stringify;
2906         } else if (os_strcmp(param, "wpa_passphrase") == 0 &&
2907                    src_hapd->conf->ssid.wpa_passphrase) {
2908                 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
2909                             src_hapd->conf->ssid.wpa_passphrase);
2910         } else if (os_strcmp(param, "wpa_psk") == 0 &&
2911                    src_hapd->conf->ssid.wpa_psk_set) {
2912                 wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2913                         src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
2914         } else {
2915                 wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
2916                 goto error_return;
2917         }
2918
2919         res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
2920         os_free(value);
2921         return res;
2922
2923 error_stringify:
2924         wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
2925 error_return:
2926         os_free(value);
2927         return -1;
2928 }
2929
2930
2931 static int
2932 hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces,
2933                                      const char *input,
2934                                      char *reply, int reply_size)
2935 {
2936         size_t i, j;
2937         int res;
2938         char *pos, *end;
2939         struct hostapd_iface *iface;
2940         int show_ctrl = 0;
2941
2942         if (input)
2943                 show_ctrl = !!os_strstr(input, "ctrl");
2944
2945         pos = reply;
2946         end = reply + reply_size;
2947
2948         for (i = 0; i < interfaces->count; i++) {
2949                 iface = interfaces->iface[i];
2950
2951                 for (j = 0; j < iface->num_bss; j++) {
2952                         struct hostapd_bss_config *conf;
2953
2954                         conf = iface->conf->bss[j];
2955                         if (show_ctrl)
2956                                 res = os_snprintf(pos, end - pos,
2957                                                   "%s ctrl_iface=%s\n",
2958                                                   conf->iface,
2959                                                   conf->ctrl_interface ?
2960                                                   conf->ctrl_interface : "N/A");
2961                         else
2962                                 res = os_snprintf(pos, end - pos, "%s\n",
2963                                                   conf->iface);
2964                         if (os_snprintf_error(end - pos, res)) {
2965                                 *pos = '\0';
2966                                 return pos - reply;
2967                         }
2968                         pos += res;
2969                 }
2970         }
2971
2972         return pos - reply;
2973 }
2974
2975
2976 static int
2977 hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
2978                                       char *cmd)
2979 {
2980         char *p_start = cmd, *p_end;
2981         struct hostapd_data *src_hapd, *dst_hapd;
2982
2983         /* cmd: "<src ifname> <dst ifname> <variable name> */
2984
2985         p_end = os_strchr(p_start, ' ');
2986         if (!p_end) {
2987                 wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
2988                            cmd);
2989                 return -1;
2990         }
2991
2992         *p_end = '\0';
2993         src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
2994         if (!src_hapd) {
2995                 wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
2996                            p_start);
2997                 return -1;
2998         }
2999
3000         p_start = p_end + 1;
3001         p_end = os_strchr(p_start, ' ');
3002         if (!p_end) {
3003                 wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
3004                            cmd);
3005                 return -1;
3006         }
3007
3008         *p_end = '\0';
3009         dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
3010         if (!dst_hapd) {
3011                 wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
3012                            p_start);
3013                 return -1;
3014         }
3015
3016         p_start = p_end + 1;
3017         return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
3018 }
3019
3020
3021 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
3022                                             const char *ifname,
3023                                             char *buf, char *reply,
3024                                             int reply_size,
3025                                             struct sockaddr_storage *from,
3026                                             socklen_t fromlen)
3027 {
3028         struct hostapd_data *hapd;
3029
3030         hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
3031         if (hapd == NULL) {
3032                 int res;
3033
3034                 res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
3035                 if (os_snprintf_error(reply_size, res))
3036                         return -1;
3037                 return res;
3038         }
3039
3040         return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
3041                                                   from, fromlen);
3042 }
3043
3044
3045 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
3046                                               void *sock_ctx)
3047 {
3048         void *interfaces = eloop_ctx;
3049         char buffer[256], *buf = buffer;
3050         int res;
3051         struct sockaddr_storage from;
3052         socklen_t fromlen = sizeof(from);
3053         char *reply;
3054         int reply_len;
3055         const int reply_size = 4096;
3056 #ifdef CONFIG_CTRL_IFACE_UDP
3057         unsigned char lcookie[COOKIE_LEN];
3058 #endif /* CONFIG_CTRL_IFACE_UDP */
3059
3060         res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
3061                        (struct sockaddr *) &from, &fromlen);
3062         if (res < 0) {
3063                 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
3064                            strerror(errno));
3065                 return;
3066         }
3067         buf[res] = '\0';
3068         wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
3069
3070         reply = os_malloc(reply_size);
3071         if (reply == NULL) {
3072                 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
3073                            fromlen) < 0) {
3074                         wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
3075                                    strerror(errno));
3076                 }
3077                 return;
3078         }
3079
3080         os_memcpy(reply, "OK\n", 3);
3081         reply_len = 3;
3082
3083 #ifdef CONFIG_CTRL_IFACE_UDP
3084         if (os_strcmp(buf, "GET_COOKIE") == 0) {
3085                 os_memcpy(reply, "COOKIE=", 7);
3086                 wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
3087                                  gcookie, COOKIE_LEN);
3088                 reply_len = 7 + 2 * COOKIE_LEN;
3089                 goto send_reply;
3090         }
3091
3092         if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
3093             hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
3094                 wpa_printf(MSG_DEBUG,
3095                            "CTRL: No cookie in the request - drop request");
3096                 os_free(reply);
3097                 return;
3098         }
3099
3100         if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) {
3101                 wpa_printf(MSG_DEBUG,
3102                            "CTRL: Invalid cookie in the request - drop request");
3103                 os_free(reply);
3104                 return;
3105         }
3106
3107         buf += 7 + 2 * COOKIE_LEN;
3108         while (*buf == ' ')
3109                 buf++;
3110 #endif /* CONFIG_CTRL_IFACE_UDP */
3111
3112         if (os_strncmp(buf, "IFNAME=", 7) == 0) {
3113                 char *pos = os_strchr(buf + 7, ' ');
3114
3115                 if (pos) {
3116                         *pos++ = '\0';
3117                         reply_len = hostapd_global_ctrl_iface_ifname(
3118                                 interfaces, buf + 7, pos, reply, reply_size,
3119                                 &from, fromlen);
3120                         goto send_reply;
3121                 }
3122         }
3123
3124         if (os_strcmp(buf, "PING") == 0) {
3125                 os_memcpy(reply, "PONG\n", 5);
3126                 reply_len = 5;
3127         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
3128                 if (wpa_debug_reopen_file() < 0)
3129                         reply_len = -1;
3130         } else if (os_strcmp(buf, "FLUSH") == 0) {
3131                 hostapd_ctrl_iface_flush(interfaces);
3132         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
3133                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
3134                         reply_len = -1;
3135         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
3136                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
3137                         reply_len = -1;
3138         } else if (os_strcmp(buf, "ATTACH") == 0) {
3139                 if (hostapd_global_ctrl_iface_attach(interfaces, &from,
3140                                                      fromlen))
3141                         reply_len = -1;
3142         } else if (os_strcmp(buf, "DETACH") == 0) {
3143                 if (hostapd_global_ctrl_iface_detach(interfaces, &from,
3144                         fromlen))
3145                         reply_len = -1;
3146 #ifdef CONFIG_MODULE_TESTS
3147         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
3148                 int hapd_module_tests(void);
3149                 if (hapd_module_tests() < 0)
3150                         reply_len = -1;
3151 #endif /* CONFIG_MODULE_TESTS */
3152 #ifdef CONFIG_FST
3153         } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
3154                 if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
3155                         reply_len = os_snprintf(reply, reply_size, "OK\n");
3156                 else
3157                         reply_len = -1;
3158         } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
3159                 if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
3160                         reply_len = os_snprintf(reply, reply_size, "OK\n");
3161                 else
3162                         reply_len = -1;
3163         } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
3164                 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
3165 #endif /* CONFIG_FST */
3166         } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
3167                 if (!hostapd_global_ctrl_iface_dup_network(interfaces,
3168                                                            buf + 12))
3169                         reply_len = os_snprintf(reply, reply_size, "OK\n");
3170                 else
3171                         reply_len = -1;
3172         } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
3173                 reply_len = hostapd_global_ctrl_iface_interfaces(
3174                         interfaces, buf + 10, reply, sizeof(buffer));
3175         } else if (os_strcmp(buf, "TERMINATE") == 0) {
3176                 eloop_terminate();
3177         } else {
3178                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
3179                            "ignored");
3180                 reply_len = -1;
3181         }
3182
3183 send_reply:
3184         if (reply_len < 0) {
3185                 os_memcpy(reply, "FAIL\n", 5);
3186                 reply_len = 5;
3187         }
3188
3189         if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
3190                    fromlen) < 0) {
3191                 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
3192                            strerror(errno));
3193         }
3194         os_free(reply);
3195 }
3196
3197
3198 #ifndef CONFIG_CTRL_IFACE_UDP
3199 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
3200 {
3201         char *buf;
3202         size_t len;
3203
3204         if (interface->global_iface_path == NULL)
3205                 return NULL;
3206
3207         len = os_strlen(interface->global_iface_path) +
3208                 os_strlen(interface->global_iface_name) + 2;
3209         buf = os_malloc(len);
3210         if (buf == NULL)
3211                 return NULL;
3212
3213         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
3214                     interface->global_iface_name);
3215         buf[len - 1] = '\0';
3216         return buf;
3217 }
3218 #endif /* CONFIG_CTRL_IFACE_UDP */
3219
3220
3221 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
3222 {
3223 #ifdef CONFIG_CTRL_IFACE_UDP
3224         int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT;
3225         char p[32] = { 0 };
3226         char *pos;
3227         struct addrinfo hints = { 0 }, *res, *saveres;
3228         int n;
3229
3230         if (interface->global_ctrl_sock > -1) {
3231                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
3232                 return 0;
3233         }
3234
3235         if (interface->global_iface_path == NULL)
3236                 return 0;
3237
3238         pos = os_strstr(interface->global_iface_path, "udp:");
3239         if (pos) {
3240                 pos += 4;
3241                 port = atoi(pos);
3242                 if (port <= 0) {
3243                         wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port");
3244                         goto fail;
3245                 }
3246         }
3247
3248         dl_list_init(&interface->global_ctrl_dst);
3249         interface->global_ctrl_sock = -1;
3250         os_get_random(gcookie, COOKIE_LEN);
3251
3252 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3253         hints.ai_flags = AI_PASSIVE;
3254 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3255
3256 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
3257         hints.ai_family = AF_INET6;
3258 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
3259         hints.ai_family = AF_INET;
3260 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
3261         hints.ai_socktype = SOCK_DGRAM;
3262
3263 try_again:
3264         os_snprintf(p, sizeof(p), "%d", port);
3265         n = getaddrinfo(NULL, p, &hints, &res);
3266         if (n) {
3267                 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
3268                 goto fail;
3269         }
3270
3271         saveres = res;
3272         interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype,
3273                                              res->ai_protocol);
3274         if (interface->global_ctrl_sock < 0) {
3275                 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
3276                 goto fail;
3277         }
3278
3279         if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) <
3280             0) {
3281                 port++;
3282                 if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) <
3283                     HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
3284                         goto try_again;
3285                 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
3286                 goto fail;
3287         }
3288
3289         freeaddrinfo(saveres);
3290
3291         wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port);
3292
3293         if (eloop_register_read_sock(interface->global_ctrl_sock,
3294                                      hostapd_global_ctrl_iface_receive,
3295                                      interface, NULL) < 0) {
3296                 hostapd_global_ctrl_iface_deinit(interface);
3297                 return -1;
3298         }
3299
3300         return 0;
3301
3302 fail:
3303         if (interface->global_ctrl_sock >= 0)
3304                 close(interface->global_ctrl_sock);
3305         return -1;
3306 #else /* CONFIG_CTRL_IFACE_UDP */
3307         struct sockaddr_un addr;
3308         int s = -1;
3309         char *fname = NULL;
3310
3311         if (interface->global_iface_path == NULL) {
3312                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
3313                 return 0;
3314         }
3315
3316         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
3317                 if (errno == EEXIST) {
3318                         wpa_printf(MSG_DEBUG, "Using existing control "
3319                                    "interface directory.");
3320                 } else {
3321                         wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
3322                                    strerror(errno));
3323                         goto fail;
3324                 }
3325         } else if (interface->ctrl_iface_group &&
3326                    chown(interface->global_iface_path, -1,
3327                          interface->ctrl_iface_group) < 0) {
3328                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
3329                            strerror(errno));
3330                 goto fail;
3331         }
3332
3333         if (os_strlen(interface->global_iface_path) + 1 +
3334             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
3335                 goto fail;
3336
3337         s = socket(PF_UNIX, SOCK_DGRAM, 0);
3338         if (s < 0) {
3339                 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
3340                 goto fail;
3341         }
3342
3343         os_memset(&addr, 0, sizeof(addr));
3344 #ifdef __FreeBSD__
3345         addr.sun_len = sizeof(addr);
3346 #endif /* __FreeBSD__ */
3347         addr.sun_family = AF_UNIX;
3348         fname = hostapd_global_ctrl_iface_path(interface);
3349         if (fname == NULL)
3350                 goto fail;
3351         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
3352         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3353                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
3354                            strerror(errno));
3355                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3356                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
3357                                    " allow connections - assuming it was left"
3358                                    "over from forced program termination");
3359                         if (unlink(fname) < 0) {
3360                                 wpa_printf(MSG_ERROR,
3361                                            "Could not unlink existing ctrl_iface socket '%s': %s",
3362                                            fname, strerror(errno));
3363                                 goto fail;
3364                         }
3365                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
3366                             0) {
3367                                 wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
3368                                            strerror(errno));
3369                                 goto fail;
3370                         }
3371                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
3372                                    "ctrl_iface socket '%s'", fname);
3373                 } else {
3374                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
3375                                    "be in use - cannot override it");
3376                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
3377                                    "not used anymore", fname);
3378                         os_free(fname);
3379                         fname = NULL;
3380                         goto fail;
3381                 }
3382         }
3383
3384         if (interface->ctrl_iface_group &&
3385             chown(fname, -1, interface->ctrl_iface_group) < 0) {
3386                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
3387                            strerror(errno));
3388                 goto fail;
3389         }
3390
3391         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
3392                 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
3393                            strerror(errno));
3394                 goto fail;
3395         }
3396         os_free(fname);
3397
3398         interface->global_ctrl_sock = s;
3399         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
3400                                  interface, NULL);
3401
3402         return 0;
3403
3404 fail:
3405         if (s >= 0)
3406                 close(s);
3407         if (fname) {
3408                 unlink(fname);
3409                 os_free(fname);
3410         }
3411         return -1;
3412 #endif /* CONFIG_CTRL_IFACE_UDP */
3413 }
3414
3415
3416 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
3417 {
3418 #ifndef CONFIG_CTRL_IFACE_UDP
3419         char *fname = NULL;
3420 #endif /* CONFIG_CTRL_IFACE_UDP */
3421         struct wpa_ctrl_dst *dst, *prev;
3422
3423         if (interfaces->global_ctrl_sock > -1) {
3424                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
3425                 close(interfaces->global_ctrl_sock);
3426                 interfaces->global_ctrl_sock = -1;
3427 #ifndef CONFIG_CTRL_IFACE_UDP
3428                 fname = hostapd_global_ctrl_iface_path(interfaces);
3429                 if (fname) {
3430                         unlink(fname);
3431                         os_free(fname);
3432                 }
3433
3434                 if (interfaces->global_iface_path &&
3435                     rmdir(interfaces->global_iface_path) < 0) {
3436                         if (errno == ENOTEMPTY) {
3437                                 wpa_printf(MSG_DEBUG, "Control interface "
3438                                            "directory not empty - leaving it "
3439                                            "behind");
3440                         } else {
3441                                 wpa_printf(MSG_ERROR,
3442                                            "rmdir[ctrl_interface=%s]: %s",
3443                                            interfaces->global_iface_path,
3444                                            strerror(errno));
3445                         }
3446                 }
3447 #endif /* CONFIG_CTRL_IFACE_UDP */
3448         }
3449
3450         os_free(interfaces->global_iface_path);
3451         interfaces->global_iface_path = NULL;
3452
3453         dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst,
3454                               struct wpa_ctrl_dst, list)
3455                 os_free(dst);
3456 }
3457
3458
3459 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
3460                                     enum wpa_msg_type type,
3461                                     const char *buf, size_t len)
3462 {
3463         struct wpa_ctrl_dst *dst, *next;
3464         struct dl_list *ctrl_dst;
3465         struct msghdr msg;
3466         int idx;
3467         struct iovec io[2];
3468         char levelstr[10];
3469         int s;
3470
3471         if (type != WPA_MSG_ONLY_GLOBAL) {
3472                 s = hapd->ctrl_sock;
3473                 ctrl_dst = &hapd->ctrl_dst;
3474         } else {
3475                 s = hapd->iface->interfaces->global_ctrl_sock;
3476                 ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst;
3477         }
3478
3479         if (s < 0 || dl_list_empty(ctrl_dst))
3480                 return;
3481
3482         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
3483         io[0].iov_base = levelstr;
3484         io[0].iov_len = os_strlen(levelstr);
3485         io[1].iov_base = (char *) buf;
3486         io[1].iov_len = len;
3487         os_memset(&msg, 0, sizeof(msg));
3488         msg.msg_iov = io;
3489         msg.msg_iovlen = 2;
3490
3491         idx = 0;
3492         dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
3493                 if (level >= dst->debug_level) {
3494                         sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send",
3495                                        &dst->addr, dst->addrlen);
3496                         msg.msg_name = &dst->addr;
3497                         msg.msg_namelen = dst->addrlen;
3498                         if (sendmsg(s, &msg, 0) < 0) {
3499                                 int _errno = errno;
3500                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
3501                                            "%d - %s",
3502                                            idx, errno, strerror(errno));
3503                                 dst->errors++;
3504                                 if (dst->errors > 10 || _errno == ENOENT) {
3505                                         if (type != WPA_MSG_ONLY_GLOBAL)
3506                                                 hostapd_ctrl_iface_detach(
3507                                                         hapd, &dst->addr,
3508                                                         dst->addrlen);
3509                                         else
3510                                                 hostapd_global_ctrl_iface_detach(
3511                                                         hapd->iface->interfaces,
3512                                                         &dst->addr,
3513                                                         dst->addrlen);
3514                                 }
3515                         } else
3516                                 dst->errors = 0;
3517                 }
3518                 idx++;
3519         }
3520 }
3521
3522 #endif /* CONFIG_NATIVE_WINDOWS */