hostapd: Introduce hostapd_interfaces_get_hapd()
[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) {
1111                 ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa);
1112                 if (os_snprintf_error(end - pos, ret))
1113                         return pos - buf;
1114                 pos += ret;
1115         }
1116
1117         if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
1118                 ret = os_snprintf(pos, end - pos, "key_mgmt=");
1119                 if (os_snprintf_error(end - pos, ret))
1120                         return pos - buf;
1121                 pos += ret;
1122
1123                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
1124                         ret = os_snprintf(pos, end - pos, "WPA-PSK ");
1125                         if (os_snprintf_error(end - pos, ret))
1126                                 return pos - buf;
1127                         pos += ret;
1128                 }
1129                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1130                         ret = os_snprintf(pos, end - pos, "WPA-EAP ");
1131                         if (os_snprintf_error(end - pos, ret))
1132                                 return pos - buf;
1133                         pos += ret;
1134                 }
1135 #ifdef CONFIG_IEEE80211R
1136                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1137                         ret = os_snprintf(pos, end - pos, "FT-PSK ");
1138                         if (os_snprintf_error(end - pos, ret))
1139                                 return pos - buf;
1140                         pos += ret;
1141                 }
1142                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1143                         ret = os_snprintf(pos, end - pos, "FT-EAP ");
1144                         if (os_snprintf_error(end - pos, ret))
1145                                 return pos - buf;
1146                         pos += ret;
1147                 }
1148 #ifdef CONFIG_SAE
1149                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
1150                         ret = os_snprintf(pos, end - pos, "FT-SAE ");
1151                         if (os_snprintf_error(end - pos, ret))
1152                                 return pos - buf;
1153                         pos += ret;
1154                 }
1155 #endif /* CONFIG_SAE */
1156 #endif /* CONFIG_IEEE80211R */
1157 #ifdef CONFIG_IEEE80211W
1158                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1159                         ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
1160                         if (os_snprintf_error(end - pos, ret))
1161                                 return pos - buf;
1162                         pos += ret;
1163                 }
1164                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1165                         ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
1166                         if (os_snprintf_error(end - pos, ret))
1167                                 return pos - buf;
1168                         pos += ret;
1169                 }
1170 #endif /* CONFIG_IEEE80211W */
1171 #ifdef CONFIG_SAE
1172                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
1173                         ret = os_snprintf(pos, end - pos, "SAE ");
1174                         if (os_snprintf_error(end - pos, ret))
1175                                 return pos - buf;
1176                         pos += ret;
1177                 }
1178 #endif /* CONFIG_SAE */
1179                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1180                         ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
1181                         if (os_snprintf_error(end - pos, ret))
1182                                 return pos - buf;
1183                         pos += ret;
1184                 }
1185                 if (hapd->conf->wpa_key_mgmt &
1186                     WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1187                         ret = os_snprintf(pos, end - pos,
1188                                           "WPA-EAP-SUITE-B-192 ");
1189                         if (os_snprintf_error(end - pos, ret))
1190                                 return pos - buf;
1191                         pos += ret;
1192                 }
1193
1194                 ret = os_snprintf(pos, end - pos, "\n");
1195                 if (os_snprintf_error(end - pos, ret))
1196                         return pos - buf;
1197                 pos += ret;
1198         }
1199
1200         if (hapd->conf->wpa) {
1201                 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
1202                                   wpa_cipher_txt(hapd->conf->wpa_group));
1203                 if (os_snprintf_error(end - pos, ret))
1204                         return pos - buf;
1205                 pos += ret;
1206         }
1207
1208         if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
1209                 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
1210                 if (os_snprintf_error(end - pos, ret))
1211                         return pos - buf;
1212                 pos += ret;
1213
1214                 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
1215                                         " ");
1216                 if (ret < 0)
1217                         return pos - buf;
1218                 pos += ret;
1219
1220                 ret = os_snprintf(pos, end - pos, "\n");
1221                 if (os_snprintf_error(end - pos, ret))
1222                         return pos - buf;
1223                 pos += ret;
1224         }
1225
1226         if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
1227                 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
1228                 if (os_snprintf_error(end - pos, ret))
1229                         return pos - buf;
1230                 pos += ret;
1231
1232                 ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
1233                                         " ");
1234                 if (ret < 0)
1235                         return pos - buf;
1236                 pos += ret;
1237
1238                 ret = os_snprintf(pos, end - pos, "\n");
1239                 if (os_snprintf_error(end - pos, ret))
1240                         return pos - buf;
1241                 pos += ret;
1242         }
1243
1244         return pos - buf;
1245 }
1246
1247
1248 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
1249 {
1250         char *value;
1251         int ret = 0;
1252
1253         value = os_strchr(cmd, ' ');
1254         if (value == NULL)
1255                 return -1;
1256         *value++ = '\0';
1257
1258         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
1259         if (0) {
1260 #ifdef CONFIG_WPS_TESTING
1261         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
1262                 long int val;
1263                 val = strtol(value, NULL, 0);
1264                 if (val < 0 || val > 0xff) {
1265                         ret = -1;
1266                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
1267                                    "wps_version_number %ld", val);
1268                 } else {
1269                         wps_version_number = val;
1270                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
1271                                    "version %u.%u",
1272                                    (wps_version_number & 0xf0) >> 4,
1273                                    wps_version_number & 0x0f);
1274                         hostapd_wps_update_ie(hapd);
1275                 }
1276         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
1277                 wps_testing_dummy_cred = atoi(value);
1278                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
1279                            wps_testing_dummy_cred);
1280         } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
1281                 wps_corrupt_pkhash = atoi(value);
1282                 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
1283                            wps_corrupt_pkhash);
1284 #endif /* CONFIG_WPS_TESTING */
1285 #ifdef CONFIG_INTERWORKING
1286         } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
1287                 int val = atoi(value);
1288                 if (val <= 0)
1289                         ret = -1;
1290                 else
1291                         hapd->gas_frag_limit = val;
1292 #endif /* CONFIG_INTERWORKING */
1293 #ifdef CONFIG_TESTING_OPTIONS
1294         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
1295                 hapd->ext_mgmt_frame_handling = atoi(value);
1296         } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
1297                 hapd->ext_eapol_frame_io = atoi(value);
1298 #endif /* CONFIG_TESTING_OPTIONS */
1299         } else {
1300                 struct sta_info *sta;
1301                 int vlan_id;
1302
1303                 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
1304                 if (ret)
1305                         return ret;
1306
1307                 if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
1308                         for (sta = hapd->sta_list; sta; sta = sta->next) {
1309                                 if (hostapd_maclist_found(
1310                                             hapd->conf->deny_mac,
1311                                             hapd->conf->num_deny_mac, sta->addr,
1312                                             &vlan_id) &&
1313                                     (!vlan_id || vlan_id == sta->vlan_id))
1314                                         ap_sta_disconnect(
1315                                                 hapd, sta, sta->addr,
1316                                                 WLAN_REASON_UNSPECIFIED);
1317                         }
1318                 } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
1319                            os_strcasecmp(cmd, "accept_mac_file") == 0) {
1320                         for (sta = hapd->sta_list; sta; sta = sta->next) {
1321                                 if (!hostapd_maclist_found(
1322                                             hapd->conf->accept_mac,
1323                                             hapd->conf->num_accept_mac,
1324                                             sta->addr, &vlan_id) ||
1325                                     (vlan_id && vlan_id != sta->vlan_id))
1326                                         ap_sta_disconnect(
1327                                                 hapd, sta, sta->addr,
1328                                                 WLAN_REASON_UNSPECIFIED);
1329                         }
1330                 }
1331         }
1332
1333         return ret;
1334 }
1335
1336
1337 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
1338                                   char *buf, size_t buflen)
1339 {
1340         int res;
1341
1342         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
1343
1344         if (os_strcmp(cmd, "version") == 0) {
1345                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
1346                 if (os_snprintf_error(buflen, res))
1347                         return -1;
1348                 return res;
1349         } else if (os_strcmp(cmd, "tls_library") == 0) {
1350                 res = tls_get_library_version(buf, buflen);
1351                 if (os_snprintf_error(buflen, res))
1352                         return -1;
1353                 return res;
1354         }
1355
1356         return -1;
1357 }
1358
1359
1360 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
1361 {
1362         if (hostapd_enable_iface(iface) < 0) {
1363                 wpa_printf(MSG_ERROR, "Enabling of interface failed");
1364                 return -1;
1365         }
1366         return 0;
1367 }
1368
1369
1370 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
1371 {
1372         if (hostapd_reload_iface(iface) < 0) {
1373                 wpa_printf(MSG_ERROR, "Reloading of interface failed");
1374                 return -1;
1375         }
1376         return 0;
1377 }
1378
1379
1380 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
1381 {
1382         if (hostapd_disable_iface(iface) < 0) {
1383                 wpa_printf(MSG_ERROR, "Disabling of interface failed");
1384                 return -1;
1385         }
1386         return 0;
1387 }
1388
1389
1390 #ifdef CONFIG_TESTING_OPTIONS
1391
1392 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
1393 {
1394         union wpa_event_data data;
1395         char *pos, *param;
1396         enum wpa_event_type event;
1397
1398         wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
1399
1400         os_memset(&data, 0, sizeof(data));
1401
1402         param = os_strchr(cmd, ' ');
1403         if (param == NULL)
1404                 return -1;
1405         *param++ = '\0';
1406
1407         if (os_strcmp(cmd, "DETECTED") == 0)
1408                 event = EVENT_DFS_RADAR_DETECTED;
1409         else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
1410                 event = EVENT_DFS_CAC_FINISHED;
1411         else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
1412                 event = EVENT_DFS_CAC_ABORTED;
1413         else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
1414                 event = EVENT_DFS_NOP_FINISHED;
1415         else {
1416                 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
1417                            cmd);
1418                 return -1;
1419         }
1420
1421         pos = os_strstr(param, "freq=");
1422         if (pos)
1423                 data.dfs_event.freq = atoi(pos + 5);
1424
1425         pos = os_strstr(param, "ht_enabled=1");
1426         if (pos)
1427                 data.dfs_event.ht_enabled = 1;
1428
1429         pos = os_strstr(param, "chan_offset=");
1430         if (pos)
1431                 data.dfs_event.chan_offset = atoi(pos + 12);
1432
1433         pos = os_strstr(param, "chan_width=");
1434         if (pos)
1435                 data.dfs_event.chan_width = atoi(pos + 11);
1436
1437         pos = os_strstr(param, "cf1=");
1438         if (pos)
1439                 data.dfs_event.cf1 = atoi(pos + 4);
1440
1441         pos = os_strstr(param, "cf2=");
1442         if (pos)
1443                 data.dfs_event.cf2 = atoi(pos + 4);
1444
1445         wpa_supplicant_event(hapd, event, &data);
1446
1447         return 0;
1448 }
1449
1450
1451 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
1452 {
1453         size_t len;
1454         u8 *buf;
1455         int res;
1456
1457         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
1458
1459         len = os_strlen(cmd);
1460         if (len & 1)
1461                 return -1;
1462         len /= 2;
1463
1464         buf = os_malloc(len);
1465         if (buf == NULL)
1466                 return -1;
1467
1468         if (hexstr2bin(cmd, buf, len) < 0) {
1469                 os_free(buf);
1470                 return -1;
1471         }
1472
1473         res = hostapd_drv_send_mlme(hapd, buf, len, 0);
1474         os_free(buf);
1475         return res;
1476 }
1477
1478
1479 static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
1480 {
1481         char *pos;
1482         u8 src[ETH_ALEN], *buf;
1483         int used;
1484         size_t len;
1485
1486         wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
1487
1488         pos = cmd;
1489         used = hwaddr_aton2(pos, src);
1490         if (used < 0)
1491                 return -1;
1492         pos += used;
1493         while (*pos == ' ')
1494                 pos++;
1495
1496         len = os_strlen(pos);
1497         if (len & 1)
1498                 return -1;
1499         len /= 2;
1500
1501         buf = os_malloc(len);
1502         if (buf == NULL)
1503                 return -1;
1504
1505         if (hexstr2bin(pos, buf, len) < 0) {
1506                 os_free(buf);
1507                 return -1;
1508         }
1509
1510         ieee802_1x_receive(hapd, src, buf, len);
1511         os_free(buf);
1512
1513         return 0;
1514 }
1515
1516
1517 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
1518 {
1519         size_t i;
1520         u32 sum = 0;
1521         const u16 *pos = buf;
1522
1523         for (i = 0; i < len / 2; i++)
1524                 sum += *pos++;
1525
1526         while (sum >> 16)
1527                 sum = (sum & 0xffff) + (sum >> 16);
1528
1529         return sum ^ 0xffff;
1530 }
1531
1532
1533 #define HWSIM_PACKETLEN 1500
1534 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
1535
1536 void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
1537                           size_t len)
1538 {
1539         struct hostapd_data *hapd = ctx;
1540         const struct ether_header *eth;
1541         struct iphdr ip;
1542         const u8 *pos;
1543         unsigned int i;
1544
1545         if (len != HWSIM_PACKETLEN)
1546                 return;
1547
1548         eth = (const struct ether_header *) buf;
1549         os_memcpy(&ip, eth + 1, sizeof(ip));
1550         pos = &buf[sizeof(*eth) + sizeof(ip)];
1551
1552         if (ip.ihl != 5 || ip.version != 4 ||
1553             ntohs(ip.tot_len) != HWSIM_IP_LEN)
1554                 return;
1555
1556         for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
1557                 if (*pos != (u8) i)
1558                         return;
1559                 pos++;
1560         }
1561
1562         wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
1563                 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
1564 }
1565
1566
1567 static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
1568                                                char *cmd)
1569 {
1570         int enabled = atoi(cmd);
1571         char *pos;
1572         const char *ifname;
1573
1574         if (!enabled) {
1575                 if (hapd->l2_test) {
1576                         l2_packet_deinit(hapd->l2_test);
1577                         hapd->l2_test = NULL;
1578                         wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
1579                                 "test data: Disabled");
1580                 }
1581                 return 0;
1582         }
1583
1584         if (hapd->l2_test)
1585                 return 0;
1586
1587         pos = os_strstr(cmd, " ifname=");
1588         if (pos)
1589                 ifname = pos + 8;
1590         else
1591                 ifname = hapd->conf->iface;
1592
1593         hapd->l2_test = l2_packet_init(ifname, hapd->own_addr,
1594                                         ETHERTYPE_IP, hostapd_data_test_rx,
1595                                         hapd, 1);
1596         if (hapd->l2_test == NULL)
1597                 return -1;
1598
1599         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
1600
1601         return 0;
1602 }
1603
1604
1605 static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
1606 {
1607         u8 dst[ETH_ALEN], src[ETH_ALEN];
1608         char *pos;
1609         int used;
1610         long int val;
1611         u8 tos;
1612         u8 buf[2 + HWSIM_PACKETLEN];
1613         struct ether_header *eth;
1614         struct iphdr *ip;
1615         u8 *dpos;
1616         unsigned int i;
1617
1618         if (hapd->l2_test == NULL)
1619                 return -1;
1620
1621         /* format: <dst> <src> <tos> */
1622
1623         pos = cmd;
1624         used = hwaddr_aton2(pos, dst);
1625         if (used < 0)
1626                 return -1;
1627         pos += used;
1628         while (*pos == ' ')
1629                 pos++;
1630         used = hwaddr_aton2(pos, src);
1631         if (used < 0)
1632                 return -1;
1633         pos += used;
1634
1635         val = strtol(pos, NULL, 0);
1636         if (val < 0 || val > 0xff)
1637                 return -1;
1638         tos = val;
1639
1640         eth = (struct ether_header *) &buf[2];
1641         os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
1642         os_memcpy(eth->ether_shost, src, ETH_ALEN);
1643         eth->ether_type = htons(ETHERTYPE_IP);
1644         ip = (struct iphdr *) (eth + 1);
1645         os_memset(ip, 0, sizeof(*ip));
1646         ip->ihl = 5;
1647         ip->version = 4;
1648         ip->ttl = 64;
1649         ip->tos = tos;
1650         ip->tot_len = htons(HWSIM_IP_LEN);
1651         ip->protocol = 1;
1652         ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
1653         ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
1654         ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
1655         dpos = (u8 *) (ip + 1);
1656         for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
1657                 *dpos++ = i;
1658
1659         if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
1660                            HWSIM_PACKETLEN) < 0)
1661                 return -1;
1662
1663         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
1664                 " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
1665
1666         return 0;
1667 }
1668
1669
1670 static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
1671                                               char *cmd)
1672 {
1673         u8 *buf;
1674         struct ether_header *eth;
1675         struct l2_packet_data *l2 = NULL;
1676         size_t len;
1677         u16 ethertype;
1678         int res = -1;
1679         const char *ifname = hapd->conf->iface;
1680
1681         if (os_strncmp(cmd, "ifname=", 7) == 0) {
1682                 cmd += 7;
1683                 ifname = cmd;
1684                 cmd = os_strchr(cmd, ' ');
1685                 if (cmd == NULL)
1686                         return -1;
1687                 *cmd++ = '\0';
1688         }
1689
1690         len = os_strlen(cmd);
1691         if (len & 1 || len < ETH_HLEN * 2)
1692                 return -1;
1693         len /= 2;
1694
1695         buf = os_malloc(len);
1696         if (buf == NULL)
1697                 return -1;
1698
1699         if (hexstr2bin(cmd, buf, len) < 0)
1700                 goto done;
1701
1702         eth = (struct ether_header *) buf;
1703         ethertype = ntohs(eth->ether_type);
1704
1705         l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
1706                             hostapd_data_test_rx, hapd, 1);
1707         if (l2 == NULL)
1708                 goto done;
1709
1710         res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
1711         wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
1712 done:
1713         if (l2)
1714                 l2_packet_deinit(l2);
1715         os_free(buf);
1716
1717         return res < 0 ? -1 : 0;
1718 }
1719
1720
1721 static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
1722 {
1723 #ifdef WPA_TRACE_BFD
1724         extern char wpa_trace_fail_func[256];
1725         extern unsigned int wpa_trace_fail_after;
1726         char *pos;
1727
1728         wpa_trace_fail_after = atoi(cmd);
1729         pos = os_strchr(cmd, ':');
1730         if (pos) {
1731                 pos++;
1732                 os_strlcpy(wpa_trace_fail_func, pos,
1733                            sizeof(wpa_trace_fail_func));
1734         } else {
1735                 wpa_trace_fail_after = 0;
1736         }
1737
1738         return 0;
1739 #else /* WPA_TRACE_BFD */
1740         return -1;
1741 #endif /* WPA_TRACE_BFD */
1742 }
1743
1744
1745 static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
1746                                        char *buf, size_t buflen)
1747 {
1748 #ifdef WPA_TRACE_BFD
1749         extern char wpa_trace_fail_func[256];
1750         extern unsigned int wpa_trace_fail_after;
1751
1752         return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
1753                            wpa_trace_fail_func);
1754 #else /* WPA_TRACE_BFD */
1755         return -1;
1756 #endif /* WPA_TRACE_BFD */
1757 }
1758
1759
1760 static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
1761 {
1762 #ifdef WPA_TRACE_BFD
1763         extern char wpa_trace_test_fail_func[256];
1764         extern unsigned int wpa_trace_test_fail_after;
1765         char *pos;
1766
1767         wpa_trace_test_fail_after = atoi(cmd);
1768         pos = os_strchr(cmd, ':');
1769         if (pos) {
1770                 pos++;
1771                 os_strlcpy(wpa_trace_test_fail_func, pos,
1772                            sizeof(wpa_trace_test_fail_func));
1773         } else {
1774                 wpa_trace_test_fail_after = 0;
1775         }
1776
1777         return 0;
1778 #else /* WPA_TRACE_BFD */
1779         return -1;
1780 #endif /* WPA_TRACE_BFD */
1781 }
1782
1783
1784 static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
1785                                  char *buf, size_t buflen)
1786 {
1787 #ifdef WPA_TRACE_BFD
1788         extern char wpa_trace_test_fail_func[256];
1789         extern unsigned int wpa_trace_test_fail_after;
1790
1791         return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
1792                            wpa_trace_test_fail_func);
1793 #else /* WPA_TRACE_BFD */
1794         return -1;
1795 #endif /* WPA_TRACE_BFD */
1796 }
1797
1798 #endif /* CONFIG_TESTING_OPTIONS */
1799
1800
1801 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
1802                                           char *pos)
1803 {
1804 #ifdef NEED_AP_MLME
1805         struct csa_settings settings;
1806         int ret;
1807         unsigned int i;
1808
1809         ret = hostapd_parse_csa_settings(pos, &settings);
1810         if (ret)
1811                 return ret;
1812
1813         for (i = 0; i < iface->num_bss; i++) {
1814                 ret = hostapd_switch_channel(iface->bss[i], &settings);
1815                 if (ret) {
1816                         /* FIX: What do we do if CSA fails in the middle of
1817                          * submitting multi-BSS CSA requests? */
1818                         return ret;
1819                 }
1820         }
1821
1822         return 0;
1823 #else /* NEED_AP_MLME */
1824         return -1;
1825 #endif /* NEED_AP_MLME */
1826 }
1827
1828
1829 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
1830                                   int reply_size, const char *param)
1831 {
1832 #ifdef RADIUS_SERVER
1833         if (os_strcmp(param, "radius_server") == 0) {
1834                 return radius_server_get_mib(hapd->radius_srv, reply,
1835                                              reply_size);
1836         }
1837 #endif /* RADIUS_SERVER */
1838         return -1;
1839 }
1840
1841
1842 static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
1843                                      char *buf, size_t buflen)
1844 {
1845         int ret;
1846         char *pos;
1847         u8 *data = NULL;
1848         unsigned int vendor_id, subcmd;
1849         struct wpabuf *reply;
1850         size_t data_len = 0;
1851
1852         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
1853         vendor_id = strtoul(cmd, &pos, 16);
1854         if (!isblank(*pos))
1855                 return -EINVAL;
1856
1857         subcmd = strtoul(pos, &pos, 10);
1858
1859         if (*pos != '\0') {
1860                 if (!isblank(*pos++))
1861                         return -EINVAL;
1862                 data_len = os_strlen(pos);
1863         }
1864
1865         if (data_len) {
1866                 data_len /= 2;
1867                 data = os_malloc(data_len);
1868                 if (!data)
1869                         return -ENOBUFS;
1870
1871                 if (hexstr2bin(pos, data, data_len)) {
1872                         wpa_printf(MSG_DEBUG,
1873                                    "Vendor command: wrong parameter format");
1874                         os_free(data);
1875                         return -EINVAL;
1876                 }
1877         }
1878
1879         reply = wpabuf_alloc((buflen - 1) / 2);
1880         if (!reply) {
1881                 os_free(data);
1882                 return -ENOBUFS;
1883         }
1884
1885         ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
1886                                      reply);
1887
1888         if (ret == 0)
1889                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
1890                                        wpabuf_len(reply));
1891
1892         wpabuf_free(reply);
1893         os_free(data);
1894
1895         return ret;
1896 }
1897
1898
1899 static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
1900                                            const char *cmd)
1901 {
1902         u8 addr[ETH_ALEN];
1903         struct sta_info *sta;
1904
1905         if (hwaddr_aton(cmd, addr))
1906                 return -1;
1907
1908         sta = ap_get_sta(hapd, addr);
1909         if (!sta || !sta->eapol_sm)
1910                 return -1;
1911
1912         eapol_auth_reauthenticate(sta->eapol_sm);
1913         return 0;
1914 }
1915
1916
1917 static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
1918 {
1919         u8 addr[ETH_ALEN];
1920         struct sta_info *sta;
1921         char *pos = cmd, *param;
1922
1923         if (hwaddr_aton(pos, addr) || pos[17] != ' ')
1924                 return -1;
1925         pos += 18;
1926         param = pos;
1927         pos = os_strchr(pos, ' ');
1928         if (!pos)
1929                 return -1;
1930         *pos++ = '\0';
1931
1932         sta = ap_get_sta(hapd, addr);
1933         if (!sta || !sta->eapol_sm)
1934                 return -1;
1935
1936         return eapol_auth_set_conf(sta->eapol_sm, param, pos);
1937 }
1938
1939
1940 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
1941                                               char *buf, char *reply,
1942                                               int reply_size,
1943                                               struct sockaddr_un *from,
1944                                               socklen_t fromlen)
1945 {
1946         int reply_len, res;
1947
1948         os_memcpy(reply, "OK\n", 3);
1949         reply_len = 3;
1950
1951         if (os_strcmp(buf, "PING") == 0) {
1952                 os_memcpy(reply, "PONG\n", 5);
1953                 reply_len = 5;
1954         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
1955                 if (wpa_debug_reopen_file() < 0)
1956                         reply_len = -1;
1957         } else if (os_strcmp(buf, "STATUS") == 0) {
1958                 reply_len = hostapd_ctrl_iface_status(hapd, reply,
1959                                                       reply_size);
1960         } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
1961                 reply_len = hostapd_drv_status(hapd, reply, reply_size);
1962         } else if (os_strcmp(buf, "MIB") == 0) {
1963                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
1964                 if (reply_len >= 0) {
1965                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
1966                                           reply_size - reply_len);
1967                         if (res < 0)
1968                                 reply_len = -1;
1969                         else
1970                                 reply_len += res;
1971                 }
1972                 if (reply_len >= 0) {
1973                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
1974                                                  reply_size - reply_len);
1975                         if (res < 0)
1976                                 reply_len = -1;
1977                         else
1978                                 reply_len += res;
1979                 }
1980 #ifndef CONFIG_NO_RADIUS
1981                 if (reply_len >= 0) {
1982                         res = radius_client_get_mib(hapd->radius,
1983                                                     reply + reply_len,
1984                                                     reply_size - reply_len);
1985                         if (res < 0)
1986                                 reply_len = -1;
1987                         else
1988                                 reply_len += res;
1989                 }
1990 #endif /* CONFIG_NO_RADIUS */
1991         } else if (os_strncmp(buf, "MIB ", 4) == 0) {
1992                 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
1993                                                    buf + 4);
1994         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
1995                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
1996                                                          reply_size);
1997         } else if (os_strncmp(buf, "STA ", 4) == 0) {
1998                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
1999                                                    reply_size);
2000         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
2001                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
2002                                                         reply_size);
2003         } else if (os_strcmp(buf, "ATTACH") == 0) {
2004                 if (hostapd_ctrl_iface_attach(hapd, from, fromlen))
2005                         reply_len = -1;
2006         } else if (os_strcmp(buf, "DETACH") == 0) {
2007                 if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
2008                         reply_len = -1;
2009         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
2010                 if (hostapd_ctrl_iface_level(hapd, from, fromlen,
2011                                                     buf + 6))
2012                         reply_len = -1;
2013         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
2014                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
2015                         reply_len = -1;
2016         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
2017                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
2018                         reply_len = -1;
2019         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
2020                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
2021                         reply_len = -1;
2022         } else if (os_strcmp(buf, "STOP_AP") == 0) {
2023                 if (hostapd_ctrl_iface_stop_ap(hapd))
2024                         reply_len = -1;
2025 #ifdef CONFIG_IEEE80211W
2026 #ifdef NEED_AP_MLME
2027         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
2028                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
2029                         reply_len = -1;
2030 #endif /* NEED_AP_MLME */
2031 #endif /* CONFIG_IEEE80211W */
2032 #ifdef CONFIG_WPS
2033         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
2034                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
2035                         reply_len = -1;
2036         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
2037                 reply_len = hostapd_ctrl_iface_wps_check_pin(
2038                         hapd, buf + 14, reply, reply_size);
2039         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
2040                 if (hostapd_wps_button_pushed(hapd, NULL))
2041                         reply_len = -1;
2042         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
2043                 if (hostapd_wps_cancel(hapd))
2044                         reply_len = -1;
2045         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
2046                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
2047                                                           reply, reply_size);
2048         } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
2049                 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
2050                         reply_len = -1;
2051         } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
2052                 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
2053                                                               reply_size);
2054 #ifdef CONFIG_WPS_NFC
2055         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
2056                 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
2057                         reply_len = -1;
2058         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
2059                 reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
2060                         hapd, buf + 21, reply, reply_size);
2061         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
2062                 reply_len = hostapd_ctrl_iface_wps_nfc_token(
2063                         hapd, buf + 14, reply, reply_size);
2064         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
2065                 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
2066                         hapd, buf + 21, reply, reply_size);
2067         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
2068                 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
2069                         reply_len = -1;
2070 #endif /* CONFIG_WPS_NFC */
2071 #endif /* CONFIG_WPS */
2072 #ifdef CONFIG_INTERWORKING
2073         } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
2074                 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
2075                         reply_len = -1;
2076         } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
2077                 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
2078                         reply_len = -1;
2079 #endif /* CONFIG_INTERWORKING */
2080 #ifdef CONFIG_HS20
2081         } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
2082                 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
2083                         reply_len = -1;
2084         } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
2085                 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
2086                         reply_len = -1;
2087 #endif /* CONFIG_HS20 */
2088 #ifdef CONFIG_WNM
2089         } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
2090                 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
2091                         reply_len = -1;
2092         } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
2093                 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
2094                         reply_len = -1;
2095         } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
2096                 if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
2097                         reply_len = -1;
2098 #endif /* CONFIG_WNM */
2099         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
2100                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
2101                                                           reply_size);
2102         } else if (os_strncmp(buf, "SET ", 4) == 0) {
2103                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
2104                         reply_len = -1;
2105         } else if (os_strncmp(buf, "GET ", 4) == 0) {
2106                 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
2107                                                    reply_size);
2108         } else if (os_strncmp(buf, "ENABLE", 6) == 0) {
2109                 if (hostapd_ctrl_iface_enable(hapd->iface))
2110                         reply_len = -1;
2111         } else if (os_strncmp(buf, "RELOAD", 6) == 0) {
2112                 if (hostapd_ctrl_iface_reload(hapd->iface))
2113                         reply_len = -1;
2114         } else if (os_strncmp(buf, "DISABLE", 7) == 0) {
2115                 if (hostapd_ctrl_iface_disable(hapd->iface))
2116                         reply_len = -1;
2117         } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
2118                 if (ieee802_11_set_beacon(hapd))
2119                         reply_len = -1;
2120 #ifdef CONFIG_TESTING_OPTIONS
2121         } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
2122                 if (hostapd_ctrl_iface_radar(hapd, buf + 6))
2123                         reply_len = -1;
2124         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
2125                 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
2126                         reply_len = -1;
2127         } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
2128                 if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
2129                         reply_len = -1;
2130         } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
2131                 if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
2132                         reply_len = -1;
2133         } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
2134                 if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
2135                         reply_len = -1;
2136         } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
2137                 if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
2138                         reply_len = -1;
2139         } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
2140                 if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
2141                         reply_len = -1;
2142         } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
2143                 reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
2144                                                         reply_size);
2145         } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
2146                 if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
2147                         reply_len = -1;
2148         } else if (os_strcmp(buf, "GET_FAIL") == 0) {
2149                 reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
2150 #endif /* CONFIG_TESTING_OPTIONS */
2151         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
2152                 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
2153                         reply_len = -1;
2154         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
2155                 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
2156                                                       reply_size);
2157         } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
2158                 ieee802_1x_erp_flush(hapd);
2159 #ifdef RADIUS_SERVER
2160                 radius_server_erp_flush(hapd->radius_srv);
2161 #endif /* RADIUS_SERVER */
2162         } else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
2163                 if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
2164                         reply_len = -1;
2165         } else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
2166                 if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
2167                         reply_len = -1;
2168         } else {
2169                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
2170                 reply_len = 16;
2171         }
2172
2173         if (reply_len < 0) {
2174                 os_memcpy(reply, "FAIL\n", 5);
2175                 reply_len = 5;
2176         }
2177
2178         return reply_len;
2179 }
2180
2181
2182 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
2183                                        void *sock_ctx)
2184 {
2185         struct hostapd_data *hapd = eloop_ctx;
2186         char buf[4096];
2187         int res;
2188         struct sockaddr_un from;
2189         socklen_t fromlen = sizeof(from);
2190         char *reply;
2191         const int reply_size = 4096;
2192         int reply_len;
2193         int level = MSG_DEBUG;
2194
2195         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
2196                        (struct sockaddr *) &from, &fromlen);
2197         if (res < 0) {
2198                 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
2199                            strerror(errno));
2200                 return;
2201         }
2202         buf[res] = '\0';
2203         if (os_strcmp(buf, "PING") == 0)
2204                 level = MSG_EXCESSIVE;
2205         wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
2206
2207         reply = os_malloc(reply_size);
2208         if (reply == NULL) {
2209                 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
2210                            fromlen) < 0) {
2211                         wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2212                                    strerror(errno));
2213                 }
2214                 return;
2215         }
2216
2217         reply_len = hostapd_ctrl_iface_receive_process(hapd, buf,
2218                                                        reply, reply_size,
2219                                                        &from, fromlen);
2220
2221         if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
2222                    fromlen) < 0) {
2223                 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2224                            strerror(errno));
2225         }
2226         os_free(reply);
2227 }
2228
2229
2230 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
2231 {
2232         char *buf;
2233         size_t len;
2234
2235         if (hapd->conf->ctrl_interface == NULL)
2236                 return NULL;
2237
2238         len = os_strlen(hapd->conf->ctrl_interface) +
2239                 os_strlen(hapd->conf->iface) + 2;
2240         buf = os_malloc(len);
2241         if (buf == NULL)
2242                 return NULL;
2243
2244         os_snprintf(buf, len, "%s/%s",
2245                     hapd->conf->ctrl_interface, hapd->conf->iface);
2246         buf[len - 1] = '\0';
2247         return buf;
2248 }
2249
2250
2251 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
2252                                       enum wpa_msg_type type,
2253                                       const char *txt, size_t len)
2254 {
2255         struct hostapd_data *hapd = ctx;
2256         if (hapd == NULL)
2257                 return;
2258         hostapd_ctrl_iface_send(hapd, level, type, txt, len);
2259 }
2260
2261
2262 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
2263 {
2264         struct sockaddr_un addr;
2265         int s = -1;
2266         char *fname = NULL;
2267
2268         if (hapd->ctrl_sock > -1) {
2269                 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
2270                 return 0;
2271         }
2272
2273         if (hapd->conf->ctrl_interface == NULL)
2274                 return 0;
2275
2276         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2277                 if (errno == EEXIST) {
2278                         wpa_printf(MSG_DEBUG, "Using existing control "
2279                                    "interface directory.");
2280                 } else {
2281                         wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
2282                                    strerror(errno));
2283                         goto fail;
2284                 }
2285         }
2286
2287         if (hapd->conf->ctrl_interface_gid_set &&
2288             chown(hapd->conf->ctrl_interface, -1,
2289                   hapd->conf->ctrl_interface_gid) < 0) {
2290                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2291                            strerror(errno));
2292                 return -1;
2293         }
2294
2295         if (!hapd->conf->ctrl_interface_gid_set &&
2296             hapd->iface->interfaces->ctrl_iface_group &&
2297             chown(hapd->conf->ctrl_interface, -1,
2298                   hapd->iface->interfaces->ctrl_iface_group) < 0) {
2299                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2300                            strerror(errno));
2301                 return -1;
2302         }
2303
2304 #ifdef ANDROID
2305         /*
2306          * Android is using umask 0077 which would leave the control interface
2307          * directory without group access. This breaks things since Wi-Fi
2308          * framework assumes that this directory can be accessed by other
2309          * applications in the wifi group. Fix this by adding group access even
2310          * if umask value would prevent this.
2311          */
2312         if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
2313                 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
2314                            strerror(errno));
2315                 /* Try to continue anyway */
2316         }
2317 #endif /* ANDROID */
2318
2319         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
2320             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
2321                 goto fail;
2322
2323         s = socket(PF_UNIX, SOCK_DGRAM, 0);
2324         if (s < 0) {
2325                 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
2326                 goto fail;
2327         }
2328
2329         os_memset(&addr, 0, sizeof(addr));
2330 #ifdef __FreeBSD__
2331         addr.sun_len = sizeof(addr);
2332 #endif /* __FreeBSD__ */
2333         addr.sun_family = AF_UNIX;
2334         fname = hostapd_ctrl_iface_path(hapd);
2335         if (fname == NULL)
2336                 goto fail;
2337         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
2338         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2339                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
2340                            strerror(errno));
2341                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2342                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
2343                                    " allow connections - assuming it was left"
2344                                    "over from forced program termination");
2345                         if (unlink(fname) < 0) {
2346                                 wpa_printf(MSG_ERROR,
2347                                            "Could not unlink existing ctrl_iface socket '%s': %s",
2348                                            fname, strerror(errno));
2349                                 goto fail;
2350                         }
2351                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
2352                             0) {
2353                                 wpa_printf(MSG_ERROR,
2354                                            "hostapd-ctrl-iface: bind(PF_UNIX): %s",
2355                                            strerror(errno));
2356                                 goto fail;
2357                         }
2358                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
2359                                    "ctrl_iface socket '%s'", fname);
2360                 } else {
2361                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
2362                                    "be in use - cannot override it");
2363                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
2364                                    "not used anymore", fname);
2365                         os_free(fname);
2366                         fname = NULL;
2367                         goto fail;
2368                 }
2369         }
2370
2371         if (hapd->conf->ctrl_interface_gid_set &&
2372             chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
2373                 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
2374                            strerror(errno));
2375                 goto fail;
2376         }
2377
2378         if (!hapd->conf->ctrl_interface_gid_set &&
2379             hapd->iface->interfaces->ctrl_iface_group &&
2380             chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
2381                 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
2382                            strerror(errno));
2383                 goto fail;
2384         }
2385
2386         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
2387                 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
2388                            strerror(errno));
2389                 goto fail;
2390         }
2391         os_free(fname);
2392
2393         hapd->ctrl_sock = s;
2394         if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
2395                                      NULL) < 0) {
2396                 hostapd_ctrl_iface_deinit(hapd);
2397                 return -1;
2398         }
2399         hapd->msg_ctx = hapd;
2400         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
2401
2402         return 0;
2403
2404 fail:
2405         if (s >= 0)
2406                 close(s);
2407         if (fname) {
2408                 unlink(fname);
2409                 os_free(fname);
2410         }
2411         return -1;
2412 }
2413
2414
2415 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
2416 {
2417         struct wpa_ctrl_dst *dst, *prev;
2418
2419         if (hapd->ctrl_sock > -1) {
2420                 char *fname;
2421                 eloop_unregister_read_sock(hapd->ctrl_sock);
2422                 close(hapd->ctrl_sock);
2423                 hapd->ctrl_sock = -1;
2424                 fname = hostapd_ctrl_iface_path(hapd);
2425                 if (fname)
2426                         unlink(fname);
2427                 os_free(fname);
2428
2429                 if (hapd->conf->ctrl_interface &&
2430                     rmdir(hapd->conf->ctrl_interface) < 0) {
2431                         if (errno == ENOTEMPTY) {
2432                                 wpa_printf(MSG_DEBUG, "Control interface "
2433                                            "directory not empty - leaving it "
2434                                            "behind");
2435                         } else {
2436                                 wpa_printf(MSG_ERROR,
2437                                            "rmdir[ctrl_interface=%s]: %s",
2438                                            hapd->conf->ctrl_interface,
2439                                            strerror(errno));
2440                         }
2441                 }
2442         }
2443
2444         dst = hapd->ctrl_dst;
2445         hapd->ctrl_dst = NULL;
2446         while (dst) {
2447                 prev = dst;
2448                 dst = dst->next;
2449                 os_free(prev);
2450         }
2451
2452 #ifdef CONFIG_TESTING_OPTIONS
2453         l2_packet_deinit(hapd->l2_test);
2454         hapd->l2_test = NULL;
2455 #endif /* CONFIG_TESTING_OPTIONS */
2456 }
2457
2458
2459 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
2460                                   char *buf)
2461 {
2462         if (hostapd_add_iface(interfaces, buf) < 0) {
2463                 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
2464                 return -1;
2465         }
2466         return 0;
2467 }
2468
2469
2470 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
2471                                      char *buf)
2472 {
2473         if (hostapd_remove_iface(interfaces, buf) < 0) {
2474                 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
2475                 return -1;
2476         }
2477         return 0;
2478 }
2479
2480
2481 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
2482                                             struct sockaddr_un *from,
2483                                             socklen_t fromlen)
2484 {
2485         struct wpa_ctrl_dst *dst;
2486
2487         dst = os_zalloc(sizeof(*dst));
2488         if (dst == NULL)
2489                 return -1;
2490         os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
2491         dst->addrlen = fromlen;
2492         dst->debug_level = MSG_INFO;
2493         dst->next = interfaces->global_ctrl_dst;
2494         interfaces->global_ctrl_dst = dst;
2495         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached (global)",
2496                     from->sun_path,
2497                     fromlen - offsetof(struct sockaddr_un, sun_path));
2498         return 0;
2499 }
2500
2501
2502 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
2503                                             struct sockaddr_un *from,
2504                                             socklen_t fromlen)
2505 {
2506         struct wpa_ctrl_dst *dst, *prev = NULL;
2507
2508         dst = interfaces->global_ctrl_dst;
2509         while (dst) {
2510                 if (fromlen == dst->addrlen &&
2511                     os_memcmp(from->sun_path, dst->addr.sun_path,
2512                               fromlen - offsetof(struct sockaddr_un, sun_path))
2513                     == 0) {
2514                         wpa_hexdump(MSG_DEBUG,
2515                                     "CTRL_IFACE monitor detached (global)",
2516                                     from->sun_path,
2517                                     fromlen -
2518                                     offsetof(struct sockaddr_un, sun_path));
2519                         if (prev == NULL)
2520                                 interfaces->global_ctrl_dst = dst->next;
2521                         else
2522                                 prev->next = dst->next;
2523                         os_free(dst);
2524                         return 0;
2525                 }
2526                 prev = dst;
2527                 dst = dst->next;
2528         }
2529         return -1;
2530 }
2531
2532
2533 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
2534 {
2535 #ifdef CONFIG_WPS_TESTING
2536         wps_version_number = 0x20;
2537         wps_testing_dummy_cred = 0;
2538         wps_corrupt_pkhash = 0;
2539 #endif /* CONFIG_WPS_TESTING */
2540 }
2541
2542
2543 #ifdef CONFIG_FST
2544
2545 static int
2546 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
2547                                      const char *cmd)
2548 {
2549         char ifname[IFNAMSIZ + 1];
2550         struct fst_iface_cfg cfg;
2551         struct hostapd_data *hapd;
2552         struct fst_wpa_obj iface_obj;
2553
2554         if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
2555                 hapd = hostapd_get_iface(interfaces, ifname);
2556                 if (hapd) {
2557                         fst_hostapd_fill_iface_obj(hapd, &iface_obj);
2558                         hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
2559                                                       &iface_obj, &cfg);
2560                         if (hapd->iface->fst)
2561                                 return 0;
2562                 }
2563         }
2564
2565         return EINVAL;
2566 }
2567
2568
2569 static int
2570 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
2571                                      const char *cmd)
2572 {
2573         char ifname[IFNAMSIZ + 1];
2574         struct hostapd_data * hapd;
2575
2576         if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
2577                 hapd = hostapd_get_iface(interfaces, ifname);
2578                 if (hapd) {
2579                         if (!fst_iface_detach(ifname)) {
2580                                 hapd->iface->fst = NULL;
2581                                 hapd->iface->fst_ies = NULL;
2582                                 return 0;
2583                         }
2584                 }
2585         }
2586
2587         return EINVAL;
2588 }
2589
2590 #endif /* CONFIG_FST */
2591
2592
2593 static struct hostapd_data *
2594 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
2595                             const char *ifname)
2596 {
2597         size_t i, j;
2598
2599         for (i = 0; i < interfaces->count; i++) {
2600                 struct hostapd_iface *iface = interfaces->iface[i];
2601
2602                 for (j = 0; j < iface->num_bss; j++) {
2603                         struct hostapd_data *hapd;
2604
2605                         hapd = iface->bss[j];
2606                         if (os_strcmp(ifname, hapd->conf->iface) == 0)
2607                                 return hapd;
2608                 }
2609         }
2610
2611         return NULL;
2612 }
2613
2614
2615 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
2616                                             const char *ifname,
2617                                             char *buf, char *reply,
2618                                             int reply_size,
2619                                             struct sockaddr_un *from,
2620                                             socklen_t fromlen)
2621 {
2622         struct hostapd_data *hapd;
2623
2624         hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
2625         if (hapd == NULL) {
2626                 int res;
2627
2628                 res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
2629                 if (os_snprintf_error(reply_size, res))
2630                         return -1;
2631                 return res;
2632         }
2633
2634         return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
2635                                                   from, fromlen);
2636 }
2637
2638
2639 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
2640                                               void *sock_ctx)
2641 {
2642         void *interfaces = eloop_ctx;
2643         char buf[256];
2644         int res;
2645         struct sockaddr_un from;
2646         socklen_t fromlen = sizeof(from);
2647         char *reply;
2648         int reply_len;
2649         const int reply_size = 4096;
2650
2651         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
2652                        (struct sockaddr *) &from, &fromlen);
2653         if (res < 0) {
2654                 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
2655                            strerror(errno));
2656                 return;
2657         }
2658         buf[res] = '\0';
2659         wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
2660
2661         reply = os_malloc(reply_size);
2662         if (reply == NULL) {
2663                 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
2664                            fromlen) < 0) {
2665                         wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2666                                    strerror(errno));
2667                 }
2668                 return;
2669         }
2670
2671         os_memcpy(reply, "OK\n", 3);
2672         reply_len = 3;
2673
2674         if (os_strncmp(buf, "IFNAME=", 7) == 0) {
2675                 char *pos = os_strchr(buf + 7, ' ');
2676
2677                 if (pos) {
2678                         *pos++ = '\0';
2679                         reply_len = hostapd_global_ctrl_iface_ifname(
2680                                 interfaces, buf + 7, pos, reply, reply_size,
2681                                 &from, fromlen);
2682                         goto send_reply;
2683                 }
2684         }
2685
2686         if (os_strcmp(buf, "PING") == 0) {
2687                 os_memcpy(reply, "PONG\n", 5);
2688                 reply_len = 5;
2689         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
2690                 if (wpa_debug_reopen_file() < 0)
2691                         reply_len = -1;
2692         } else if (os_strcmp(buf, "FLUSH") == 0) {
2693                 hostapd_ctrl_iface_flush(interfaces);
2694         } else if (os_strncmp(buf, "ADD ", 4) == 0) {
2695                 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
2696                         reply_len = -1;
2697         } else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
2698                 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
2699                         reply_len = -1;
2700         } else if (os_strcmp(buf, "ATTACH") == 0) {
2701                 if (hostapd_global_ctrl_iface_attach(interfaces, &from,
2702                                                      fromlen))
2703                         reply_len = -1;
2704         } else if (os_strcmp(buf, "DETACH") == 0) {
2705                 if (hostapd_global_ctrl_iface_detach(interfaces, &from,
2706                         fromlen))
2707                         reply_len = -1;
2708 #ifdef CONFIG_MODULE_TESTS
2709         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
2710                 int hapd_module_tests(void);
2711                 if (hapd_module_tests() < 0)
2712                         reply_len = -1;
2713 #endif /* CONFIG_MODULE_TESTS */
2714 #ifdef CONFIG_FST
2715         } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
2716                 if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
2717                         reply_len = os_snprintf(reply, reply_size, "OK\n");
2718                 else
2719                         reply_len = -1;
2720         } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
2721                 if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
2722                         reply_len = os_snprintf(reply, reply_size, "OK\n");
2723                 else
2724                         reply_len = -1;
2725         } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
2726                 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
2727 #endif /* CONFIG_FST */
2728         } else {
2729                 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
2730                            "ignored");
2731                 reply_len = -1;
2732         }
2733
2734 send_reply:
2735         if (reply_len < 0) {
2736                 os_memcpy(reply, "FAIL\n", 5);
2737                 reply_len = 5;
2738         }
2739
2740         if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
2741                    fromlen) < 0) {
2742                 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
2743                            strerror(errno));
2744         }
2745         os_free(reply);
2746 }
2747
2748
2749 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
2750 {
2751         char *buf;
2752         size_t len;
2753
2754         if (interface->global_iface_path == NULL)
2755                 return NULL;
2756
2757         len = os_strlen(interface->global_iface_path) +
2758                 os_strlen(interface->global_iface_name) + 2;
2759         buf = os_malloc(len);
2760         if (buf == NULL)
2761                 return NULL;
2762
2763         os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
2764                     interface->global_iface_name);
2765         buf[len - 1] = '\0';
2766         return buf;
2767 }
2768
2769
2770 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
2771 {
2772         struct sockaddr_un addr;
2773         int s = -1;
2774         char *fname = NULL;
2775
2776         if (interface->global_iface_path == NULL) {
2777                 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
2778                 return 0;
2779         }
2780
2781         if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
2782                 if (errno == EEXIST) {
2783                         wpa_printf(MSG_DEBUG, "Using existing control "
2784                                    "interface directory.");
2785                 } else {
2786                         wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
2787                                    strerror(errno));
2788                         goto fail;
2789                 }
2790         } else if (interface->ctrl_iface_group &&
2791                    chown(interface->global_iface_path, -1,
2792                          interface->ctrl_iface_group) < 0) {
2793                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2794                            strerror(errno));
2795                 goto fail;
2796         }
2797
2798         if (os_strlen(interface->global_iface_path) + 1 +
2799             os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
2800                 goto fail;
2801
2802         s = socket(PF_UNIX, SOCK_DGRAM, 0);
2803         if (s < 0) {
2804                 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
2805                 goto fail;
2806         }
2807
2808         os_memset(&addr, 0, sizeof(addr));
2809 #ifdef __FreeBSD__
2810         addr.sun_len = sizeof(addr);
2811 #endif /* __FreeBSD__ */
2812         addr.sun_family = AF_UNIX;
2813         fname = hostapd_global_ctrl_iface_path(interface);
2814         if (fname == NULL)
2815                 goto fail;
2816         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
2817         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2818                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
2819                            strerror(errno));
2820                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2821                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
2822                                    " allow connections - assuming it was left"
2823                                    "over from forced program termination");
2824                         if (unlink(fname) < 0) {
2825                                 wpa_printf(MSG_ERROR,
2826                                            "Could not unlink existing ctrl_iface socket '%s': %s",
2827                                            fname, strerror(errno));
2828                                 goto fail;
2829                         }
2830                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
2831                             0) {
2832                                 wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
2833                                            strerror(errno));
2834                                 goto fail;
2835                         }
2836                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
2837                                    "ctrl_iface socket '%s'", fname);
2838                 } else {
2839                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
2840                                    "be in use - cannot override it");
2841                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
2842                                    "not used anymore", fname);
2843                         os_free(fname);
2844                         fname = NULL;
2845                         goto fail;
2846                 }
2847         }
2848
2849         if (interface->ctrl_iface_group &&
2850             chown(fname, -1, interface->ctrl_iface_group) < 0) {
2851                 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
2852                            strerror(errno));
2853                 goto fail;
2854         }
2855
2856         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
2857                 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
2858                            strerror(errno));
2859                 goto fail;
2860         }
2861         os_free(fname);
2862
2863         interface->global_ctrl_sock = s;
2864         eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
2865                                  interface, NULL);
2866
2867         return 0;
2868
2869 fail:
2870         if (s >= 0)
2871                 close(s);
2872         if (fname) {
2873                 unlink(fname);
2874                 os_free(fname);
2875         }
2876         return -1;
2877 }
2878
2879
2880 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
2881 {
2882         char *fname = NULL;
2883         struct wpa_ctrl_dst *dst, *prev;
2884
2885         if (interfaces->global_ctrl_sock > -1) {
2886                 eloop_unregister_read_sock(interfaces->global_ctrl_sock);
2887                 close(interfaces->global_ctrl_sock);
2888                 interfaces->global_ctrl_sock = -1;
2889                 fname = hostapd_global_ctrl_iface_path(interfaces);
2890                 if (fname) {
2891                         unlink(fname);
2892                         os_free(fname);
2893                 }
2894
2895                 if (interfaces->global_iface_path &&
2896                     rmdir(interfaces->global_iface_path) < 0) {
2897                         if (errno == ENOTEMPTY) {
2898                                 wpa_printf(MSG_DEBUG, "Control interface "
2899                                            "directory not empty - leaving it "
2900                                            "behind");
2901                         } else {
2902                                 wpa_printf(MSG_ERROR,
2903                                            "rmdir[ctrl_interface=%s]: %s",
2904                                            interfaces->global_iface_path,
2905                                            strerror(errno));
2906                         }
2907                 }
2908         }
2909
2910         os_free(interfaces->global_iface_path);
2911         interfaces->global_iface_path = NULL;
2912
2913         dst = interfaces->global_ctrl_dst;
2914         interfaces->global_ctrl_dst = NULL;
2915         while (dst) {
2916                 prev = dst;
2917                 dst = dst->next;
2918                 os_free(prev);
2919         }
2920 }
2921
2922
2923 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
2924                                     enum wpa_msg_type type,
2925                                     const char *buf, size_t len)
2926 {
2927         struct wpa_ctrl_dst *dst, *next;
2928         struct msghdr msg;
2929         int idx;
2930         struct iovec io[2];
2931         char levelstr[10];
2932         int s;
2933
2934         if (type != WPA_MSG_ONLY_GLOBAL) {
2935                 s = hapd->ctrl_sock;
2936                 dst = hapd->ctrl_dst;
2937         } else {
2938                 s = hapd->iface->interfaces->global_ctrl_sock;
2939                 dst = hapd->iface->interfaces->global_ctrl_dst;
2940         }
2941
2942         if (s < 0 || dst == NULL)
2943                 return;
2944
2945         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
2946         io[0].iov_base = levelstr;
2947         io[0].iov_len = os_strlen(levelstr);
2948         io[1].iov_base = (char *) buf;
2949         io[1].iov_len = len;
2950         os_memset(&msg, 0, sizeof(msg));
2951         msg.msg_iov = io;
2952         msg.msg_iovlen = 2;
2953
2954         idx = 0;
2955         while (dst) {
2956                 next = dst->next;
2957                 if (level >= dst->debug_level) {
2958                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
2959                                     (u8 *) dst->addr.sun_path, dst->addrlen -
2960                                     offsetof(struct sockaddr_un, sun_path));
2961                         msg.msg_name = &dst->addr;
2962                         msg.msg_namelen = dst->addrlen;
2963                         if (sendmsg(s, &msg, 0) < 0) {
2964                                 int _errno = errno;
2965                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
2966                                            "%d - %s",
2967                                            idx, errno, strerror(errno));
2968                                 dst->errors++;
2969                                 if (dst->errors > 10 || _errno == ENOENT) {
2970                                         if (type != WPA_MSG_ONLY_GLOBAL)
2971                                                 hostapd_ctrl_iface_detach(
2972                                                         hapd, &dst->addr,
2973                                                         dst->addrlen);
2974                                         else
2975                                                 hostapd_global_ctrl_iface_detach(
2976                                                         hapd->iface->interfaces,
2977                                                         &dst->addr,
2978                                                         dst->addrlen);
2979                                 }
2980                         } else
2981                                 dst->errors = 0;
2982                 }
2983                 idx++;
2984                 dst = next;
2985         }
2986 }
2987
2988 #endif /* CONFIG_NATIVE_WINDOWS */