c4108e7f9a6ec0bfc652f0a42fd77ff8635d645a
[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_strcmp(buf, "STOP_AP") == 0) {
2157                 if (hostapd_ctrl_iface_stop_ap(hapd))
2158                         reply_len = -1;
2159 #ifdef CONFIG_IEEE80211W
2160 #ifdef NEED_AP_MLME
2161         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
2162                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
2163                         reply_len = -1;
2164 #endif /* NEED_AP_MLME */
2165 #endif /* CONFIG_IEEE80211W */
2166 #ifdef CONFIG_WPS
2167         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
2168                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
2169                         reply_len = -1;
2170         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
2171                 reply_len = hostapd_ctrl_iface_wps_check_pin(
2172                         hapd, buf + 14, reply, reply_size);
2173         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
2174                 if (hostapd_wps_button_pushed(hapd, NULL))
2175                         reply_len = -1;
2176         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
2177                 if (hostapd_wps_cancel(hapd))
2178                         reply_len = -1;
2179         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
2180                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
2181                                                           reply, reply_size);
2182         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
2183                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
2184                         reply_len = -1;
2185         } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
2186                 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
2187                                                               reply_size);
2188 #ifdef CONFIG_WPS_NFC
2189         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
2190                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
2191                         reply_len = -1;
2192         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
2193                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
2194                         hapd, buf + 21, reply, reply_size);
2195         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
2196                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
2197                         hapd, buf + 14, reply, reply_size);
2198         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
2199                 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
2200                         hapd, buf + 21, reply, reply_size);
2201         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
2202                 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
2203                         reply_len = -1;
2204 #endif /* CONFIG_WPS_NFC */
2205 #endif /* CONFIG_WPS */
2206 #ifdef CONFIG_INTERWORKING
2207         } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
2208                 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
2209                         reply_len = -1;
2210         } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
2211                 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
2212                         reply_len = -1;
2213 #endif /* CONFIG_INTERWORKING */
2214 #ifdef CONFIG_HS20
2215         } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
2216                 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
2217                         reply_len = -1;
2218         } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
2219                 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
2220                         reply_len = -1;
2221 #endif /* CONFIG_HS20 */
2222 #ifdef CONFIG_WNM
2223         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
2224                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
2225                         reply_len = -1;
2226         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
2227                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
2228                         reply_len = -1;
2229         } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
2230                 if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
2231                         reply_len = -1;
2232 #endif /* CONFIG_WNM */
2233         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
2234                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
2235                                                           reply_size);
2236         } else if (os_strncmp(buf, "SET ", 4) == 0) {
2237                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
2238                         reply_len = -1;
2239         } else if (os_strncmp(buf, "GET ", 4) == 0) {
2240                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
2241                                                    reply_size);
2242         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
2243                 if (hostapd_ctrl_iface_enable(hapd->iface))
2244                         reply_len = -1;
2245         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
2246                 if (hostapd_ctrl_iface_reload(hapd->iface))
2247                         reply_len = -1;
2248         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
2249                 if (hostapd_ctrl_iface_disable(hapd->iface))
2250                         reply_len = -1;
2251         } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
2252                 if (ieee802_11_set_beacon(hapd))
2253                         reply_len = -1;
2254 #ifdef CONFIG_TESTING_OPTIONS
2255         } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
2256                 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
2257                         reply_len = -1;
2258         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
2259                 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
2260                         reply_len = -1;
2261         } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
2262                 if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
2263                         reply_len = -1;
2264         } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
2265                 if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
2266                         reply_len = -1;
2267         } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
2268                 if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
2269                         reply_len = -1;
2270         } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
2271                 if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
2272                         reply_len = -1;
2273         } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
2274                 if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
2275                         reply_len = -1;
2276         } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
2277                 reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
2278                                                         reply_size);
2279         } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
2280                 if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
2281                         reply_len = -1;
2282         } else if (os_strcmp(buf, "GET_FAIL") == 0) {
2283                 reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
2284 #endif /* CONFIG_TESTING_OPTIONS */
2285         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
2286                 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
2287                         reply_len = -1;
2288         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
2289                 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
2290                                                       reply_size);
2291         } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
2292                 ieee802_1x_erp_flush(hapd);
2293 #ifdef RADIUS_SERVER
2294                 radius_server_erp_flush(hapd->radius_srv);
2295 #endif /* RADIUS_SERVER */
2296         } else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
2297                 if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
2298                         reply_len = -1;
2299         } else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
2300                 if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
2301                         reply_len = -1;
2302         } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
2303                 reply_len = hostapd_ctrl_iface_log_level(
2304                         hapd, buf + 9, reply, reply_size);
2305 #ifdef NEED_AP_MLME
2306         } else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
2307                 reply_len = hostapd_ctrl_iface_track_sta_list(
2308                         hapd, reply, reply_size);
2309 #endif /* NEED_AP_MLME */
2310         } else if (os_strcmp(buf, "PMKSA") == 0) {
2311                 reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply,
2312                                                           reply_size);
2313         } else {
2314                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
2315                 reply_len = 16;
2316         }
2317
2318         if (reply_len < 0) {
2319                 os_memcpy(reply, "FAIL\n", 5);
2320                 reply_len = 5;
2321         }
2322
2323         return reply_len;
2324 }
2325
2326
2327 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
2328                                        void *sock_ctx)
2329 {
2330         struct hostapd_data *hapd = eloop_ctx;
2331         char buf[4096];
2332         int res;
2333         struct sockaddr_storage from;
2334         socklen_t fromlen = sizeof(from);
2335         char *reply, *pos = buf;
2336         const int reply_size = 4096;
2337         int reply_len;
2338         int level = MSG_DEBUG;
2339 #ifdef CONFIG_CTRL_IFACE_UDP
2340         unsigned char lcookie[COOKIE_LEN];
2341 #endif /* CONFIG_CTRL_IFACE_UDP */
2342
2343         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
2344                        (struct sockaddr *) &from, &fromlen);
2345         if (res < 0) {
2346                 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
2347                            strerror(errno));
2348                 return;
2349         }
2350         buf[res] = '\0';
2351
2352         reply = os_malloc(reply_size);
2353         if (reply == NULL) {
2354                 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
2355                            fromlen) < 0) {
2356                         wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2357                                    strerror(errno));
2358                 }
2359                 return;
2360         }
2361
2362 #ifdef CONFIG_CTRL_IFACE_UDP
2363         if (os_strcmp(buf, "GET_COOKIE") == 0) {
2364                 os_memcpy(reply, "COOKIE=", 7);
2365                 wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
2366                                  cookie, COOKIE_LEN);
2367                 reply_len = 7 + 2 * COOKIE_LEN;
2368                 goto done;
2369         }
2370
2371         if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
2372             hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
2373                 wpa_printf(MSG_DEBUG,
2374                            "CTRL: No cookie in the request - drop request");
2375                 os_free(reply);
2376                 return;
2377         }
2378
2379         if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) {
2380                 wpa_printf(MSG_DEBUG,
2381                            "CTRL: Invalid cookie in the request - drop request");
2382                 os_free(reply);
2383                 return;
2384         }
2385
2386         pos = buf + 7 + 2 * COOKIE_LEN;
2387         while (*pos == ' ')
2388                 pos++;
2389 #endif /* CONFIG_CTRL_IFACE_UDP */
2390
2391         if (os_strcmp(pos, "PING") == 0)
2392                 level = MSG_EXCESSIVE;
2393         wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res);
2394
2395         reply_len = hostapd_ctrl_iface_receive_process(hapd, pos,
2396                                                        reply, reply_size,
2397                                                        &from, fromlen);
2398
2399 #ifdef CONFIG_CTRL_IFACE_UDP
2400 done:
2401 #endif /* CONFIG_CTRL_IFACE_UDP */
2402         if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
2403                    fromlen) < 0) {
2404                 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2405                            strerror(errno));
2406         }
2407         os_free(reply);
2408 }
2409
2410
2411 #ifndef CONFIG_CTRL_IFACE_UDP
2412 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
2413 {
2414         char *buf;
2415         size_t len;
2416
2417         if (hapd->conf->ctrl_interface == NULL)
2418                 return NULL;
2419
2420         len = os_strlen(hapd->conf->ctrl_interface) +
2421                 os_strlen(hapd->conf->iface) + 2;
2422         buf = os_malloc(len);
2423         if (buf == NULL)
2424                 return NULL;
2425
2426         os_snprintf(buf, len, "%s/%s",
2427                     hapd->conf->ctrl_interface, hapd->conf->iface);
2428         buf[len - 1] = '\0';
2429         return buf;
2430 }
2431 #endif /* CONFIG_CTRL_IFACE_UDP */
2432
2433
2434 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
2435                                       enum wpa_msg_type type,
2436                                       const char *txt, size_t len)
2437 {
2438         struct hostapd_data *hapd = ctx;
2439         if (hapd == NULL)
2440                 return;
2441         hostapd_ctrl_iface_send(hapd, level, type, txt, len);
2442 }
2443
2444
2445 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
2446 {
2447 #ifdef CONFIG_CTRL_IFACE_UDP
2448         int port = HOSTAPD_CTRL_IFACE_PORT;
2449         char p[32] = { 0 };
2450         char port_str[40], *tmp;
2451         char *pos;
2452         struct addrinfo hints = { 0 }, *res, *saveres;
2453         int n;
2454
2455         if (hapd->ctrl_sock > -1) {
2456                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
2457                 return 0;
2458         }
2459
2460         if (hapd->conf->ctrl_interface == NULL)
2461                 return 0;
2462
2463         pos = os_strstr(hapd->conf->ctrl_interface, "udp:");
2464         if (pos) {
2465                 pos += 4;
2466                 port = atoi(pos);
2467                 if (port <= 0) {
2468                         wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port");
2469                         goto fail;
2470                 }
2471         }
2472
2473         dl_list_init(&hapd->ctrl_dst);
2474         hapd->ctrl_sock = -1;
2475         os_get_random(cookie, COOKIE_LEN);
2476
2477 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
2478         hints.ai_flags = AI_PASSIVE;
2479 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
2480
2481 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
2482         hints.ai_family = AF_INET6;
2483 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
2484         hints.ai_family = AF_INET;
2485 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
2486         hints.ai_socktype = SOCK_DGRAM;
2487
2488 try_again:
2489         os_snprintf(p, sizeof(p), "%d", port);
2490         n = getaddrinfo(NULL, p, &hints, &res);
2491         if (n) {
2492                 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
2493                 goto fail;
2494         }
2495
2496         saveres = res;
2497         hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype,
2498                                  res->ai_protocol);
2499         if (hapd->ctrl_sock < 0) {
2500                 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
2501                 goto fail;
2502         }
2503
2504         if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) {
2505                 port--;
2506                 if ((HOSTAPD_CTRL_IFACE_PORT - port) <
2507                     HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos)
2508                         goto try_again;
2509                 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
2510                 goto fail;
2511         }
2512
2513         freeaddrinfo(saveres);
2514
2515         os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
2516         tmp = os_strdup(port_str);
2517         if (tmp) {
2518                 os_free(hapd->conf->ctrl_interface);
2519                 hapd->conf->ctrl_interface = tmp;
2520         }
2521         wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
2522
2523         if (eloop_register_read_sock(hapd->ctrl_sock,
2524                                      hostapd_ctrl_iface_receive, hapd, NULL) <
2525             0) {
2526                 hostapd_ctrl_iface_deinit(hapd);
2527                 return -1;
2528         }
2529
2530         hapd->msg_ctx = hapd;
2531         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
2532
2533         return 0;
2534
2535 fail:
2536         if (hapd->ctrl_sock >= 0)
2537                 close(hapd->ctrl_sock);
2538         return -1;
2539 #else /* CONFIG_CTRL_IFACE_UDP */
2540         struct sockaddr_un addr;
2541         int s = -1;
2542         char *fname = NULL;
2543
2544         if (hapd->ctrl_sock > -1) {
2545                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
2546                 return 0;
2547         }
2548
2549         dl_list_init(&hapd->ctrl_dst);
2550
2551         if (hapd->conf->ctrl_interface == NULL)
2552                 return 0;
2553
2554         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2555                 if (errno == EEXIST) {
2556                         wpa_printf(MSG_DEBUG, "Using existing control "
2557                                    "interface directory.");
2558                 } else {
2559                         wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
2560                                    strerror(errno));
2561                         goto fail;
2562                 }
2563         }
2564
2565         if (hapd->conf->ctrl_interface_gid_set &&
2566             chown(hapd->conf->ctrl_interface, -1,
2567                   hapd->conf->ctrl_interface_gid) < 0) {
2568                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2569                            strerror(errno));
2570                 return -1;
2571         }
2572
2573         if (!hapd->conf->ctrl_interface_gid_set &&
2574             hapd->iface->interfaces->ctrl_iface_group &&
2575             chown(hapd->conf->ctrl_interface, -1,
2576                   hapd->iface->interfaces->ctrl_iface_group) < 0) {
2577                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2578                            strerror(errno));
2579                 return -1;
2580         }
2581
2582 #ifdef ANDROID
2583         /*
2584          * Android is using umask 0077 which would leave the control interface
2585          * directory without group access. This breaks things since Wi-Fi
2586          * framework assumes that this directory can be accessed by other
2587          * applications in the wifi group. Fix this by adding group access even
2588          * if umask value would prevent this.
2589          */
2590         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2591                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
2592                            strerror(errno));
2593                 /* Try to continue anyway */
2594         }
2595 #endif /* ANDROID */
2596
2597         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
2598             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
2599                 goto fail;
2600
2601         s = socket(PF_UNIX, SOCK_DGRAM, 0);
2602         if (s < 0) {
2603                 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
2604                 goto fail;
2605         }
2606
2607         os_memset(&addr, 0, sizeof(addr));
2608 #ifdef __FreeBSD__
2609         addr.sun_len = sizeof(addr);
2610 #endif /* __FreeBSD__ */
2611         addr.sun_family = AF_UNIX;
2612         fname = hostapd_ctrl_iface_path(hapd);
2613         if (fname == NULL)
2614                 goto fail;
2615         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
2616         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2617                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
2618                            strerror(errno));
2619                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2620                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
2621                                    " allow connections - assuming it was left"
2622                                    "over from forced program termination");
2623                         if (unlink(fname) < 0) {
2624                                 wpa_printf(MSG_ERROR,
2625                                            "Could not unlink existing ctrl_iface socket '%s': %s",
2626                                            fname, strerror(errno));
2627                                 goto fail;
2628                         }
2629                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
2630                             0) {
2631                                 wpa_printf(MSG_ERROR,
2632                                            "hostapd-ctrl-iface: bind(PF_UNIX): %s",
2633                                            strerror(errno));
2634                                 goto fail;
2635                         }
2636                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
2637                                    "ctrl_iface socket '%s'", fname);
2638                 } else {
2639                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
2640                                    "be in use - cannot override it");
2641                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
2642                                    "not used anymore", fname);
2643                         os_free(fname);
2644                         fname = NULL;
2645                         goto fail;
2646                 }
2647         }
2648
2649         if (hapd->conf->ctrl_interface_gid_set &&
2650             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
2651                 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
2652                            strerror(errno));
2653                 goto fail;
2654         }
2655
2656         if (!hapd->conf->ctrl_interface_gid_set &&
2657             hapd->iface->interfaces->ctrl_iface_group &&
2658             chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
2659                 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
2660                            strerror(errno));
2661                 goto fail;
2662         }
2663
2664         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
2665                 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
2666                            strerror(errno));
2667                 goto fail;
2668         }
2669         os_free(fname);
2670
2671         hapd->ctrl_sock = s;
2672         if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
2673                                      NULL) < 0) {
2674                 hostapd_ctrl_iface_deinit(hapd);
2675                 return -1;
2676         }
2677         hapd->msg_ctx = hapd;
2678         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
2679
2680         return 0;
2681
2682 fail:
2683         if (s >= 0)
2684                 close(s);
2685         if (fname) {
2686                 unlink(fname);
2687                 os_free(fname);
2688         }
2689         return -1;
2690 #endif /* CONFIG_CTRL_IFACE_UDP */
2691 }
2692
2693
2694 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
2695 {
2696         struct wpa_ctrl_dst *dst, *prev;
2697
2698         if (hapd->ctrl_sock > -1) {
2699 #ifndef CONFIG_CTRL_IFACE_UDP
2700                 char *fname;
2701 #endif /* !CONFIG_CTRL_IFACE_UDP */
2702
2703                 eloop_unregister_read_sock(hapd->ctrl_sock);
2704                 close(hapd->ctrl_sock);
2705                 hapd->ctrl_sock = -1;
2706 #ifndef CONFIG_CTRL_IFACE_UDP
2707                 fname = hostapd_ctrl_iface_path(hapd);
2708                 if (fname)
2709                         unlink(fname);
2710                 os_free(fname);
2711
2712                 if (hapd->conf->ctrl_interface &&
2713                     rmdir(hapd->conf->ctrl_interface) < 0) {
2714                         if (errno == ENOTEMPTY) {
2715                                 wpa_printf(MSG_DEBUG, "Control interface "
2716                                            "directory not empty - leaving it "
2717                                            "behind");
2718                         } else {
2719                                 wpa_printf(MSG_ERROR,
2720                                            "rmdir[ctrl_interface=%s]: %s",
2721                                            hapd->conf->ctrl_interface,
2722                                            strerror(errno));
2723                         }
2724                 }
2725 #endif /* !CONFIG_CTRL_IFACE_UDP */
2726         }
2727
2728         dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst,
2729                               list)
2730                 os_free(dst);
2731
2732 #ifdef CONFIG_TESTING_OPTIONS
2733         l2_packet_deinit(hapd->l2_test);
2734         hapd->l2_test = NULL;
2735 #endif /* CONFIG_TESTING_OPTIONS */
2736 }
2737
2738
2739 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
2740                                   char *buf)
2741 {
2742         if (hostapd_add_iface(interfaces, buf) < 0) {
2743                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
2744                 return -1;
2745         }
2746         return 0;
2747 }
2748
2749
2750 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
2751                                      char *buf)
2752 {
2753         if (hostapd_remove_iface(interfaces, buf) < 0) {
2754                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
2755                 return -1;
2756         }
2757         return 0;
2758 }
2759
2760
2761 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
2762                                             struct sockaddr_storage *from,
2763                                             socklen_t fromlen)
2764 {
2765         return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen);
2766 }
2767
2768
2769 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
2770                                             struct sockaddr_storage *from,
2771                                             socklen_t fromlen)
2772 {
2773         return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen);
2774 }
2775
2776
2777 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
2778 {
2779 #ifdef CONFIG_WPS_TESTING
2780         wps_version_number = 0x20;
2781         wps_testing_dummy_cred = 0;
2782         wps_corrupt_pkhash = 0;
2783 #endif /* CONFIG_WPS_TESTING */
2784 }
2785
2786
2787 #ifdef CONFIG_FST
2788
2789 static int
2790 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
2791                                      const char *cmd)
2792 {
2793         char ifname[IFNAMSIZ + 1];
2794         struct fst_iface_cfg cfg;
2795         struct hostapd_data *hapd;
2796         struct fst_wpa_obj iface_obj;
2797
2798         if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
2799                 hapd = hostapd_get_iface(interfaces, ifname);
2800                 if (hapd) {
2801                         if (hapd->iface->fst) {
2802                                 wpa_printf(MSG_INFO, "FST: Already attached");
2803                                 return -1;
2804                         }
2805                         fst_hostapd_fill_iface_obj(hapd, &iface_obj);
2806                         hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
2807                                                       &iface_obj, &cfg);
2808                         if (hapd->iface->fst)
2809                                 return 0;
2810                 }
2811         }
2812
2813         return -EINVAL;
2814 }
2815
2816
2817 static int
2818 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
2819                                      const char *cmd)
2820 {
2821         char ifname[IFNAMSIZ + 1];
2822         struct hostapd_data * hapd;
2823
2824         if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
2825                 hapd = hostapd_get_iface(interfaces, ifname);
2826                 if (hapd) {
2827                         if (!fst_iface_detach(ifname)) {
2828                                 hapd->iface->fst = NULL;
2829                                 hapd->iface->fst_ies = NULL;
2830                                 return 0;
2831                         }
2832                 }
2833         }
2834
2835         return -EINVAL;
2836 }
2837
2838 #endif /* CONFIG_FST */
2839
2840
2841 static struct hostapd_data *
2842 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
2843                             const char *ifname)
2844 {
2845         size_t i, j;
2846
2847         for (i = 0; i < interfaces->count; i++) {
2848                 struct hostapd_iface *iface = interfaces->iface[i];
2849
2850                 for (j = 0; j < iface->num_bss; j++) {
2851                         struct hostapd_data *hapd;
2852
2853                         hapd = iface->bss[j];
2854                         if (os_strcmp(ifname, hapd->conf->iface) == 0)
2855                                 return hapd;
2856                 }
2857         }
2858
2859         return NULL;
2860 }
2861
2862
2863 static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
2864                                         struct hostapd_data *dst_hapd,
2865                                         const char *param)
2866 {
2867         int res;
2868         char *value;
2869
2870         value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
2871         if (!value) {
2872                 wpa_printf(MSG_ERROR,
2873                            "DUP: cannot allocate buffer to stringify %s",
2874                            param);
2875                 goto error_return;
2876         }
2877
2878         if (os_strcmp(param, "wpa") == 0) {
2879                 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
2880                             src_hapd->conf->wpa);
2881         } else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
2882                    src_hapd->conf->wpa_key_mgmt) {
2883                 res = hostapd_ctrl_iface_get_key_mgmt(
2884                         src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
2885                 if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
2886                         goto error_stringify;
2887         } else if (os_strcmp(param, "wpa_pairwise") == 0 &&
2888                    src_hapd->conf->wpa_pairwise) {
2889                 res = wpa_write_ciphers(value,
2890                                         value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2891                                         src_hapd->conf->wpa_pairwise, " ");
2892                 if (res < 0)
2893                         goto error_stringify;
2894         } else if (os_strcmp(param, "rsn_pairwise") == 0 &&
2895                    src_hapd->conf->rsn_pairwise) {
2896                 res = wpa_write_ciphers(value,
2897                                         value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2898                                         src_hapd->conf->rsn_pairwise, " ");
2899                 if (res < 0)
2900                         goto error_stringify;
2901         } else if (os_strcmp(param, "wpa_passphrase") == 0 &&
2902                    src_hapd->conf->ssid.wpa_passphrase) {
2903                 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
2904                             src_hapd->conf->ssid.wpa_passphrase);
2905         } else if (os_strcmp(param, "wpa_psk") == 0 &&
2906                    src_hapd->conf->ssid.wpa_psk_set) {
2907                 wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
2908                         src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
2909         } else {
2910                 wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
2911                 goto error_return;
2912         }
2913
2914         res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
2915         os_free(value);
2916         return res;
2917
2918 error_stringify:
2919         wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
2920 error_return:
2921         os_free(value);
2922         return -1;
2923 }
2924
2925
2926 static int
2927 hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces,
2928                                      const char *input,
2929                                      char *reply, int reply_size)
2930 {
2931         size_t i, j;
2932         int res;
2933         char *pos, *end;
2934         struct hostapd_iface *iface;
2935         int show_ctrl = 0;
2936
2937         if (input)
2938                 show_ctrl = !!os_strstr(input, "ctrl");
2939
2940         pos = reply;
2941         end = reply + reply_size;
2942
2943         for (i = 0; i < interfaces->count; i++) {
2944                 iface = interfaces->iface[i];
2945
2946                 for (j = 0; j < iface->num_bss; j++) {
2947                         struct hostapd_bss_config *conf;
2948
2949                         conf = iface->conf->bss[j];
2950                         if (show_ctrl)
2951                                 res = os_snprintf(pos, end - pos,
2952                                                   "%s ctrl_iface=%s\n",
2953                                                   conf->iface,
2954                                                   conf->ctrl_interface ?
2955                                                   conf->ctrl_interface : "N/A");
2956                         else
2957                                 res = os_snprintf(pos, end - pos, "%s\n",
2958                                                   conf->iface);
2959                         if (os_snprintf_error(end - pos, res)) {
2960                                 *pos = '\0';
2961                                 return pos - reply;
2962                         }
2963                         pos += res;
2964                 }
2965         }
2966
2967         return pos - reply;
2968 }
2969
2970
2971 static int
2972 hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
2973                                       char *cmd)
2974 {
2975         char *p_start = cmd, *p_end;
2976         struct hostapd_data *src_hapd, *dst_hapd;
2977
2978         /* cmd: "<src ifname> <dst ifname> <variable name> */
2979
2980         p_end = os_strchr(p_start, ' ');
2981         if (!p_end) {
2982                 wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
2983                            cmd);
2984                 return -1;
2985         }
2986
2987         *p_end = '\0';
2988         src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
2989         if (!src_hapd) {
2990                 wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
2991                            p_start);
2992                 return -1;
2993         }
2994
2995         p_start = p_end + 1;
2996         p_end = os_strchr(p_start, ' ');
2997         if (!p_end) {
2998                 wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
2999                            cmd);
3000                 return -1;
3001         }
3002
3003         *p_end = '\0';
3004         dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
3005         if (!dst_hapd) {
3006                 wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
3007                            p_start);
3008                 return -1;
3009         }
3010
3011         p_start = p_end + 1;
3012         return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
3013 }
3014
3015
3016 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
3017                                             const char *ifname,
3018                                             char *buf, char *reply,
3019                                             int reply_size,
3020                                             struct sockaddr_storage *from,
3021                                             socklen_t fromlen)
3022 {
3023         struct hostapd_data *hapd;
3024
3025         hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
3026         if (hapd == NULL) {
3027                 int res;
3028
3029                 res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
3030                 if (os_snprintf_error(reply_size, res))
3031                         return -1;
3032                 return res;
3033         }
3034
3035         return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
3036                                                   from, fromlen);
3037 }
3038
3039
3040 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
3041                                               void *sock_ctx)
3042 {
3043         void *interfaces = eloop_ctx;
3044         char buffer[256], *buf = buffer;
3045         int res;
3046         struct sockaddr_storage from;
3047         socklen_t fromlen = sizeof(from);
3048         char *reply;
3049         int reply_len;
3050         const int reply_size = 4096;
3051 #ifdef CONFIG_CTRL_IFACE_UDP
3052         unsigned char lcookie[COOKIE_LEN];
3053 #endif /* CONFIG_CTRL_IFACE_UDP */
3054
3055         res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
3056                        (struct sockaddr *) &from, &fromlen);
3057         if (res < 0) {
3058                 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
3059                            strerror(errno));
3060                 return;
3061         }
3062         buf[res] = '\0';
3063         wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
3064
3065         reply = os_malloc(reply_size);
3066         if (reply == NULL) {
3067                 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
3068                            fromlen) < 0) {
3069                         wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
3070                                    strerror(errno));
3071                 }
3072                 return;
3073         }
3074
3075         os_memcpy(reply, "OK\n", 3);
3076         reply_len = 3;
3077
3078 #ifdef CONFIG_CTRL_IFACE_UDP
3079         if (os_strcmp(buf, "GET_COOKIE") == 0) {
3080                 os_memcpy(reply, "COOKIE=", 7);
3081                 wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
3082                                  gcookie, COOKIE_LEN);
3083                 reply_len = 7 + 2 * COOKIE_LEN;
3084                 goto send_reply;
3085         }
3086
3087         if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
3088             hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
3089                 wpa_printf(MSG_DEBUG,
3090                            "CTRL: No cookie in the request - drop request");
3091                 os_free(reply);
3092                 return;
3093         }
3094
3095         if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) {
3096                 wpa_printf(MSG_DEBUG,
3097                            "CTRL: Invalid cookie in the request - drop request");
3098                 os_free(reply);
3099                 return;
3100         }
3101
3102         buf += 7 + 2 * COOKIE_LEN;
3103         while (*buf == ' ')
3104                 buf++;
3105 #endif /* CONFIG_CTRL_IFACE_UDP */
3106
3107         if (os_strncmp(buf, "IFNAME=", 7) == 0) {
3108                 char *pos = os_strchr(buf + 7, ' ');
3109
3110                 if (pos) {
3111                         *pos++ = '\0';
3112                         reply_len = hostapd_global_ctrl_iface_ifname(
3113                                 interfaces, buf + 7, pos, reply, reply_size,
3114                                 &from, fromlen);
3115                         goto send_reply;
3116                 }
3117         }
3118
3119         if (os_strcmp(buf, "PING") == 0) {
3120                 os_memcpy(reply, "PONG\n", 5);
3121                 reply_len = 5;
3122         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
3123                 if (wpa_debug_reopen_file() < 0)
3124                         reply_len = -1;
3125         } else if (os_strcmp(buf, "FLUSH") == 0) {
3126                 hostapd_ctrl_iface_flush(interfaces);
3127         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
3128                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
3129                         reply_len = -1;
3130         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
3131                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
3132                         reply_len = -1;
3133         } else if (os_strcmp(buf, "ATTACH") == 0) {
3134                 if (hostapd_global_ctrl_iface_attach(interfaces, &from,
3135                                                      fromlen))
3136                         reply_len = -1;
3137         } else if (os_strcmp(buf, "DETACH") == 0) {
3138                 if (hostapd_global_ctrl_iface_detach(interfaces, &from,
3139                         fromlen))
3140                         reply_len = -1;
3141 #ifdef CONFIG_MODULE_TESTS
3142         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
3143                 int hapd_module_tests(void);
3144                 if (hapd_module_tests() < 0)
3145                         reply_len = -1;
3146 #endif /* CONFIG_MODULE_TESTS */
3147 #ifdef CONFIG_FST
3148         } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
3149                 if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
3150                         reply_len = os_snprintf(reply, reply_size, "OK\n");
3151                 else
3152                         reply_len = -1;
3153         } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
3154                 if (!hostapd_global_ctrl_iface_fst_detach(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-MANAGER ", 12) == 0) {
3159                 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
3160 #endif /* CONFIG_FST */
3161         } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
3162                 if (!hostapd_global_ctrl_iface_dup_network(interfaces,
3163                                                            buf + 12))
3164                         reply_len = os_snprintf(reply, reply_size, "OK\n");
3165                 else
3166                         reply_len = -1;
3167         } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
3168                 reply_len = hostapd_global_ctrl_iface_interfaces(
3169                         interfaces, buf + 10, reply, sizeof(buffer));
3170         } else if (os_strcmp(buf, "TERMINATE") == 0) {
3171                 eloop_terminate();
3172         } else {
3173                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
3174                            "ignored");
3175                 reply_len = -1;
3176         }
3177
3178 send_reply:
3179         if (reply_len < 0) {
3180                 os_memcpy(reply, "FAIL\n", 5);
3181                 reply_len = 5;
3182         }
3183
3184         if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
3185                    fromlen) < 0) {
3186                 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
3187                            strerror(errno));
3188         }
3189         os_free(reply);
3190 }
3191
3192
3193 #ifndef CONFIG_CTRL_IFACE_UDP
3194 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
3195 {
3196         char *buf;
3197         size_t len;
3198
3199         if (interface->global_iface_path == NULL)
3200                 return NULL;
3201
3202         len = os_strlen(interface->global_iface_path) +
3203                 os_strlen(interface->global_iface_name) + 2;
3204         buf = os_malloc(len);
3205         if (buf == NULL)
3206                 return NULL;
3207
3208         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
3209                     interface->global_iface_name);
3210         buf[len - 1] = '\0';
3211         return buf;
3212 }
3213 #endif /* CONFIG_CTRL_IFACE_UDP */
3214
3215
3216 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
3217 {
3218 #ifdef CONFIG_CTRL_IFACE_UDP
3219         int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT;
3220         char p[32] = { 0 };
3221         char *pos;
3222         struct addrinfo hints = { 0 }, *res, *saveres;
3223         int n;
3224
3225         if (interface->global_ctrl_sock > -1) {
3226                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
3227                 return 0;
3228         }
3229
3230         if (interface->global_iface_path == NULL)
3231                 return 0;
3232
3233         pos = os_strstr(interface->global_iface_path, "udp:");
3234         if (pos) {
3235                 pos += 4;
3236                 port = atoi(pos);
3237                 if (port <= 0) {
3238                         wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port");
3239                         goto fail;
3240                 }
3241         }
3242
3243         dl_list_init(&interface->global_ctrl_dst);
3244         interface->global_ctrl_sock = -1;
3245         os_get_random(gcookie, COOKIE_LEN);
3246
3247 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3248         hints.ai_flags = AI_PASSIVE;
3249 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3250
3251 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
3252         hints.ai_family = AF_INET6;
3253 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
3254         hints.ai_family = AF_INET;
3255 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
3256         hints.ai_socktype = SOCK_DGRAM;
3257
3258 try_again:
3259         os_snprintf(p, sizeof(p), "%d", port);
3260         n = getaddrinfo(NULL, p, &hints, &res);
3261         if (n) {
3262                 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
3263                 goto fail;
3264         }
3265
3266         saveres = res;
3267         interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype,
3268                                              res->ai_protocol);
3269         if (interface->global_ctrl_sock < 0) {
3270                 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
3271                 goto fail;
3272         }
3273
3274         if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) <
3275             0) {
3276                 port++;
3277                 if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) <
3278                     HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
3279                         goto try_again;
3280                 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
3281                 goto fail;
3282         }
3283
3284         freeaddrinfo(saveres);
3285
3286         wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port);
3287
3288         if (eloop_register_read_sock(interface->global_ctrl_sock,
3289                                      hostapd_global_ctrl_iface_receive,
3290                                      interface, NULL) < 0) {
3291                 hostapd_global_ctrl_iface_deinit(interface);
3292                 return -1;
3293         }
3294
3295         return 0;
3296
3297 fail:
3298         if (interface->global_ctrl_sock >= 0)
3299                 close(interface->global_ctrl_sock);
3300         return -1;
3301 #else /* CONFIG_CTRL_IFACE_UDP */
3302         struct sockaddr_un addr;
3303         int s = -1;
3304         char *fname = NULL;
3305
3306         if (interface->global_iface_path == NULL) {
3307                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
3308                 return 0;
3309         }
3310
3311         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
3312                 if (errno == EEXIST) {
3313                         wpa_printf(MSG_DEBUG, "Using existing control "
3314                                    "interface directory.");
3315                 } else {
3316                         wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
3317                                    strerror(errno));
3318                         goto fail;
3319                 }
3320         } else if (interface->ctrl_iface_group &&
3321                    chown(interface->global_iface_path, -1,
3322                          interface->ctrl_iface_group) < 0) {
3323                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
3324                            strerror(errno));
3325                 goto fail;
3326         }
3327
3328         if (os_strlen(interface->global_iface_path) + 1 +
3329             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
3330                 goto fail;
3331
3332         s = socket(PF_UNIX, SOCK_DGRAM, 0);
3333         if (s < 0) {
3334                 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
3335                 goto fail;
3336         }
3337
3338         os_memset(&addr, 0, sizeof(addr));
3339 #ifdef __FreeBSD__
3340         addr.sun_len = sizeof(addr);
3341 #endif /* __FreeBSD__ */
3342         addr.sun_family = AF_UNIX;
3343         fname = hostapd_global_ctrl_iface_path(interface);
3344         if (fname == NULL)
3345                 goto fail;
3346         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
3347         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3348                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
3349                            strerror(errno));
3350                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3351                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
3352                                    " allow connections - assuming it was left"
3353                                    "over from forced program termination");
3354                         if (unlink(fname) < 0) {
3355                                 wpa_printf(MSG_ERROR,
3356                                            "Could not unlink existing ctrl_iface socket '%s': %s",
3357                                            fname, strerror(errno));
3358                                 goto fail;
3359                         }
3360                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
3361                             0) {
3362                                 wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
3363                                            strerror(errno));
3364                                 goto fail;
3365                         }
3366                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
3367                                    "ctrl_iface socket '%s'", fname);
3368                 } else {
3369                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
3370                                    "be in use - cannot override it");
3371                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
3372                                    "not used anymore", fname);
3373                         os_free(fname);
3374                         fname = NULL;
3375                         goto fail;
3376                 }
3377         }
3378
3379         if (interface->ctrl_iface_group &&
3380             chown(fname, -1, interface->ctrl_iface_group) < 0) {
3381                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
3382                            strerror(errno));
3383                 goto fail;
3384         }
3385
3386         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
3387                 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
3388                            strerror(errno));
3389                 goto fail;
3390         }
3391         os_free(fname);
3392
3393         interface->global_ctrl_sock = s;
3394         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
3395                                  interface, NULL);
3396
3397         return 0;
3398
3399 fail:
3400         if (s >= 0)
3401                 close(s);
3402         if (fname) {
3403                 unlink(fname);
3404                 os_free(fname);
3405         }
3406         return -1;
3407 #endif /* CONFIG_CTRL_IFACE_UDP */
3408 }
3409
3410
3411 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
3412 {
3413 #ifndef CONFIG_CTRL_IFACE_UDP
3414         char *fname = NULL;
3415 #endif /* CONFIG_CTRL_IFACE_UDP */
3416         struct wpa_ctrl_dst *dst, *prev;
3417
3418         if (interfaces->global_ctrl_sock > -1) {
3419                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
3420                 close(interfaces->global_ctrl_sock);
3421                 interfaces->global_ctrl_sock = -1;
3422 #ifndef CONFIG_CTRL_IFACE_UDP
3423                 fname = hostapd_global_ctrl_iface_path(interfaces);
3424                 if (fname) {
3425                         unlink(fname);
3426                         os_free(fname);
3427                 }
3428
3429                 if (interfaces->global_iface_path &&
3430                     rmdir(interfaces->global_iface_path) < 0) {
3431                         if (errno == ENOTEMPTY) {
3432                                 wpa_printf(MSG_DEBUG, "Control interface "
3433                                            "directory not empty - leaving it "
3434                                            "behind");
3435                         } else {
3436                                 wpa_printf(MSG_ERROR,
3437                                            "rmdir[ctrl_interface=%s]: %s",
3438                                            interfaces->global_iface_path,
3439                                            strerror(errno));
3440                         }
3441                 }
3442 #endif /* CONFIG_CTRL_IFACE_UDP */
3443         }
3444
3445         os_free(interfaces->global_iface_path);
3446         interfaces->global_iface_path = NULL;
3447
3448         dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst,
3449                               struct wpa_ctrl_dst, list)
3450                 os_free(dst);
3451 }
3452
3453
3454 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
3455                                     enum wpa_msg_type type,
3456                                     const char *buf, size_t len)
3457 {
3458         struct wpa_ctrl_dst *dst, *next;
3459         struct dl_list *ctrl_dst;
3460         struct msghdr msg;
3461         int idx;
3462         struct iovec io[2];
3463         char levelstr[10];
3464         int s;
3465
3466         if (type != WPA_MSG_ONLY_GLOBAL) {
3467                 s = hapd->ctrl_sock;
3468                 ctrl_dst = &hapd->ctrl_dst;
3469         } else {
3470                 s = hapd->iface->interfaces->global_ctrl_sock;
3471                 ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst;
3472         }
3473
3474         if (s < 0 || dl_list_empty(ctrl_dst))
3475                 return;
3476
3477         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
3478         io[0].iov_base = levelstr;
3479         io[0].iov_len = os_strlen(levelstr);
3480         io[1].iov_base = (char *) buf;
3481         io[1].iov_len = len;
3482         os_memset(&msg, 0, sizeof(msg));
3483         msg.msg_iov = io;
3484         msg.msg_iovlen = 2;
3485
3486         idx = 0;
3487         dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
3488                 if (level >= dst->debug_level) {
3489                         sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send",
3490                                        &dst->addr, dst->addrlen);
3491                         msg.msg_name = &dst->addr;
3492                         msg.msg_namelen = dst->addrlen;
3493                         if (sendmsg(s, &msg, 0) < 0) {
3494                                 int _errno = errno;
3495                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
3496                                            "%d - %s",
3497                                            idx, errno, strerror(errno));
3498                                 dst->errors++;
3499                                 if (dst->errors > 10 || _errno == ENOENT) {
3500                                         if (type != WPA_MSG_ONLY_GLOBAL)
3501                                                 hostapd_ctrl_iface_detach(
3502                                                         hapd, &dst->addr,
3503                                                         dst->addrlen);
3504                                         else
3505                                                 hostapd_global_ctrl_iface_detach(
3506                                                         hapd->iface->interfaces,
3507                                                         &dst->addr,
3508                                                         dst->addrlen);
3509                                 }
3510                         } else
3511                                 dst->errors = 0;
3512                 }
3513                 idx++;
3514         }
3515 }
3516
3517 #endif /* CONFIG_NATIVE_WINDOWS */