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