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