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