Fix hostapd_cli get_config not to show key when WPA is disabled
[libeap.git] / hostapd / ctrl_iface.c
1 /*
2  * hostapd / UNIX domain socket -based control interface
3  * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "utils/includes.h"
16
17 #ifndef CONFIG_NATIVE_WINDOWS
18
19 #include <sys/un.h>
20 #include <sys/stat.h>
21 #include <stddef.h>
22
23 #include "utils/common.h"
24 #include "utils/eloop.h"
25 #include "common/ieee802_11_defs.h"
26 #include "drivers/driver.h"
27 #include "radius/radius_client.h"
28 #include "ap/hostapd.h"
29 #include "ap/ap_config.h"
30 #include "ap/ieee802_1x.h"
31 #include "ap/wpa_auth.h"
32 #include "ap/ieee802_11.h"
33 #include "ap/sta_info.h"
34 #include "ap/accounting.h"
35 #include "ap/wps_hostapd.h"
36 #include "ap/ctrl_iface_ap.h"
37 #include "wps/wps_defs.h"
38 #include "wps/wps.h"
39 #include "ctrl_iface.h"
40
41
42 struct wpa_ctrl_dst {
43         struct wpa_ctrl_dst *next;
44         struct sockaddr_un addr;
45         socklen_t addrlen;
46         int debug_level;
47         int errors;
48 };
49
50
51 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
52                                     const char *buf, size_t len);
53
54
55 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
56                                      struct sockaddr_un *from,
57                                      socklen_t fromlen)
58 {
59         struct wpa_ctrl_dst *dst;
60
61         dst = os_zalloc(sizeof(*dst));
62         if (dst == NULL)
63                 return -1;
64         os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
65         dst->addrlen = fromlen;
66         dst->debug_level = MSG_INFO;
67         dst->next = hapd->ctrl_dst;
68         hapd->ctrl_dst = dst;
69         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
70                     (u8 *) from->sun_path,
71                     fromlen - offsetof(struct sockaddr_un, sun_path));
72         return 0;
73 }
74
75
76 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
77                                      struct sockaddr_un *from,
78                                      socklen_t fromlen)
79 {
80         struct wpa_ctrl_dst *dst, *prev = NULL;
81
82         dst = hapd->ctrl_dst;
83         while (dst) {
84                 if (fromlen == dst->addrlen &&
85                     os_memcmp(from->sun_path, dst->addr.sun_path,
86                               fromlen - offsetof(struct sockaddr_un, sun_path))
87                     == 0) {
88                         if (prev == NULL)
89                                 hapd->ctrl_dst = dst->next;
90                         else
91                                 prev->next = dst->next;
92                         os_free(dst);
93                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
94                                     (u8 *) from->sun_path,
95                                     fromlen -
96                                     offsetof(struct sockaddr_un, sun_path));
97                         return 0;
98                 }
99                 prev = dst;
100                 dst = dst->next;
101         }
102         return -1;
103 }
104
105
106 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
107                                     struct sockaddr_un *from,
108                                     socklen_t fromlen,
109                                     char *level)
110 {
111         struct wpa_ctrl_dst *dst;
112
113         wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
114
115         dst = hapd->ctrl_dst;
116         while (dst) {
117                 if (fromlen == dst->addrlen &&
118                     os_memcmp(from->sun_path, dst->addr.sun_path,
119                               fromlen - offsetof(struct sockaddr_un, sun_path))
120                     == 0) {
121                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
122                                     "level", (u8 *) from->sun_path, fromlen -
123                                     offsetof(struct sockaddr_un, sun_path));
124                         dst->debug_level = atoi(level);
125                         return 0;
126                 }
127                 dst = dst->next;
128         }
129
130         return -1;
131 }
132
133
134 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
135                                       const char *txtaddr)
136 {
137         u8 addr[ETH_ALEN];
138         struct sta_info *sta;
139
140         wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
141
142         if (hwaddr_aton(txtaddr, addr))
143                 return -1;
144
145         sta = ap_get_sta(hapd, addr);
146         if (sta)
147                 return 0;
148
149         wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
150                    "notification", MAC2STR(addr));
151         sta = ap_sta_add(hapd, addr);
152         if (sta == NULL)
153                 return -1;
154
155         hostapd_new_assoc_sta(hapd, sta, 0);
156         return 0;
157 }
158
159
160 #ifdef CONFIG_P2P_MANAGER
161 static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
162                                   u8 minor_reason_code, const u8 *addr)
163 {
164         struct ieee80211_mgmt *mgmt;
165         int ret;
166         u8 *pos;
167
168         if (hapd->driver->send_frame == NULL)
169                 return -1;
170
171         mgmt = os_zalloc(sizeof(*mgmt) + 100);
172         if (mgmt == NULL)
173                 return -1;
174
175         wpa_printf(MSG_DEBUG, "P2P: Disconnect STA " MACSTR " with minor "
176                    "reason code %u (stype=%u)",
177                    MAC2STR(addr), minor_reason_code, stype);
178
179         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
180         os_memcpy(mgmt->da, addr, ETH_ALEN);
181         os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
182         os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
183         if (stype == WLAN_FC_STYPE_DEAUTH) {
184                 mgmt->u.deauth.reason_code =
185                         host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
186                 pos = (u8 *) (&mgmt->u.deauth.reason_code + 1);
187         } else {
188                 mgmt->u.disassoc.reason_code =
189                         host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
190                 pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1);
191         }
192
193         *pos++ = WLAN_EID_VENDOR_SPECIFIC;
194         *pos++ = 4 + 3 + 1;
195         WPA_PUT_BE24(pos, OUI_WFA);
196         pos += 3;
197         *pos++ = P2P_OUI_TYPE;
198
199         *pos++ = P2P_ATTR_MINOR_REASON_CODE;
200         WPA_PUT_LE16(pos, 1);
201         pos += 2;
202         *pos++ = minor_reason_code;
203
204         ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
205                                        pos - (u8 *) mgmt, 1);
206         os_free(mgmt);
207
208         return ret < 0 ? -1 : 0;
209 }
210 #endif /* CONFIG_P2P_MANAGER */
211
212
213 static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
214                                              const char *txtaddr)
215 {
216         u8 addr[ETH_ALEN];
217         struct sta_info *sta;
218         const char *pos;
219
220         wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr);
221
222         if (hwaddr_aton(txtaddr, addr))
223                 return -1;
224
225         pos = os_strstr(txtaddr, " test=");
226         if (pos) {
227                 struct ieee80211_mgmt mgmt;
228                 int encrypt;
229                 if (hapd->driver->send_frame == NULL)
230                         return -1;
231                 pos += 6;
232                 encrypt = atoi(pos);
233                 os_memset(&mgmt, 0, sizeof(mgmt));
234                 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
235                                                   WLAN_FC_STYPE_DEAUTH);
236                 os_memcpy(mgmt.da, addr, ETH_ALEN);
237                 os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
238                 os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
239                 mgmt.u.deauth.reason_code =
240                         host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
241                 if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
242                                              IEEE80211_HDRLEN +
243                                              sizeof(mgmt.u.deauth),
244                                              encrypt) < 0)
245                         return -1;
246                 return 0;
247         }
248
249 #ifdef CONFIG_P2P_MANAGER
250         pos = os_strstr(txtaddr, " p2p=");
251         if (pos) {
252                 return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
253                                               atoi(pos + 5), addr);
254         }
255 #endif /* CONFIG_P2P_MANAGER */
256
257         hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
258         sta = ap_get_sta(hapd, addr);
259         if (sta)
260                 ap_sta_deauthenticate(hapd, sta,
261                                       WLAN_REASON_PREV_AUTH_NOT_VALID);
262
263         return 0;
264 }
265
266
267 static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
268                                            const char *txtaddr)
269 {
270         u8 addr[ETH_ALEN];
271         struct sta_info *sta;
272         const char *pos;
273
274         wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr);
275
276         if (hwaddr_aton(txtaddr, addr))
277                 return -1;
278
279         pos = os_strstr(txtaddr, " test=");
280         if (pos) {
281                 struct ieee80211_mgmt mgmt;
282                 int encrypt;
283                 if (hapd->driver->send_frame == NULL)
284                         return -1;
285                 pos += 6;
286                 encrypt = atoi(pos);
287                 os_memset(&mgmt, 0, sizeof(mgmt));
288                 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
289                                                   WLAN_FC_STYPE_DISASSOC);
290                 os_memcpy(mgmt.da, addr, ETH_ALEN);
291                 os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
292                 os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
293                 mgmt.u.disassoc.reason_code =
294                         host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
295                 if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
296                                              IEEE80211_HDRLEN +
297                                              sizeof(mgmt.u.deauth),
298                                              encrypt) < 0)
299                         return -1;
300                 return 0;
301         }
302
303 #ifdef CONFIG_P2P_MANAGER
304         pos = os_strstr(txtaddr, " p2p=");
305         if (pos) {
306                 return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
307                                               atoi(pos + 5), addr);
308         }
309 #endif /* CONFIG_P2P_MANAGER */
310
311         hapd->drv.sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
312         sta = ap_get_sta(hapd, addr);
313         if (sta)
314                 ap_sta_disassociate(hapd, sta,
315                                     WLAN_REASON_PREV_AUTH_NOT_VALID);
316
317         return 0;
318 }
319
320
321 #ifdef CONFIG_IEEE80211W
322 #ifdef NEED_AP_MLME
323 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
324                                        const char *txtaddr)
325 {
326         u8 addr[ETH_ALEN];
327         u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
328
329         wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
330
331         if (hwaddr_aton(txtaddr, addr) ||
332             os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
333                 return -1;
334
335         ieee802_11_send_sa_query_req(hapd, addr, trans_id);
336
337         return 0;
338 }
339 #endif /* NEED_AP_MLME */
340 #endif /* CONFIG_IEEE80211W */
341
342
343 #ifdef CONFIG_WPS
344 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
345 {
346         char *pin = os_strchr(txt, ' ');
347         char *timeout_txt;
348         int timeout;
349         u8 addr_buf[ETH_ALEN], *addr = NULL;
350         char *pos;
351
352         if (pin == NULL)
353                 return -1;
354         *pin++ = '\0';
355
356         timeout_txt = os_strchr(pin, ' ');
357         if (timeout_txt) {
358                 *timeout_txt++ = '\0';
359                 timeout = atoi(timeout_txt);
360                 pos = os_strchr(timeout_txt, ' ');
361                 if (pos) {
362                         *pos++ = '\0';
363                         if (hwaddr_aton(pos, addr_buf) == 0)
364                                 addr = addr_buf;
365                 }
366         } else
367                 timeout = 0;
368
369         return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
370 }
371
372
373 static int hostapd_ctrl_iface_wps_check_pin(
374         struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
375 {
376         char pin[9];
377         size_t len;
378         char *pos;
379         int ret;
380
381         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
382                               (u8 *) cmd, os_strlen(cmd));
383         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
384                 if (*pos < '0' || *pos > '9')
385                         continue;
386                 pin[len++] = *pos;
387                 if (len == 9) {
388                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
389                         return -1;
390                 }
391         }
392         if (len != 4 && len != 8) {
393                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
394                 return -1;
395         }
396         pin[len] = '\0';
397
398         if (len == 8) {
399                 unsigned int pin_val;
400                 pin_val = atoi(pin);
401                 if (!wps_pin_valid(pin_val)) {
402                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
403                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
404                         if (ret < 0 || (size_t) ret >= buflen)
405                                 return -1;
406                         return ret;
407                 }
408         }
409
410         ret = os_snprintf(buf, buflen, "%s", pin);
411         if (ret < 0 || (size_t) ret >= buflen)
412                 return -1;
413
414         return ret;
415 }
416
417
418 #ifdef CONFIG_WPS_OOB
419 static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
420 {
421         char *path, *method, *name;
422
423         path = os_strchr(txt, ' ');
424         if (path == NULL)
425                 return -1;
426         *path++ = '\0';
427
428         method = os_strchr(path, ' ');
429         if (method == NULL)
430                 return -1;
431         *method++ = '\0';
432
433         name = os_strchr(method, ' ');
434         if (name != NULL)
435                 *name++ = '\0';
436
437         return hostapd_wps_start_oob(hapd, txt, path, method, name);
438 }
439 #endif /* CONFIG_WPS_OOB */
440
441
442 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
443                                          char *buf, size_t buflen)
444 {
445         int timeout = 300;
446         char *pos;
447         const char *pin_txt;
448
449         pos = os_strchr(txt, ' ');
450         if (pos)
451                 *pos++ = '\0';
452
453         if (os_strcmp(txt, "disable") == 0) {
454                 hostapd_wps_ap_pin_disable(hapd);
455                 return os_snprintf(buf, buflen, "OK\n");
456         }
457
458         if (os_strcmp(txt, "random") == 0) {
459                 if (pos)
460                         timeout = atoi(pos);
461                 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
462                 if (pin_txt == NULL)
463                         return -1;
464                 return os_snprintf(buf, buflen, "%s", pin_txt);
465         }
466
467         if (os_strcmp(txt, "get") == 0) {
468                 pin_txt = hostapd_wps_ap_pin_get(hapd);
469                 if (pin_txt == NULL)
470                         return -1;
471                 return os_snprintf(buf, buflen, "%s", pin_txt);
472         }
473
474         if (os_strcmp(txt, "set") == 0) {
475                 char *pin;
476                 if (pos == NULL)
477                         return -1;
478                 pin = pos;
479                 pos = os_strchr(pos, ' ');
480                 if (pos) {
481                         *pos++ = '\0';
482                         timeout = atoi(pos);
483                 }
484                 if (os_strlen(pin) > buflen)
485                         return -1;
486                 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
487                         return -1;
488                 return os_snprintf(buf, buflen, "%s", pin);
489         }
490
491         return -1;
492 }
493 #endif /* CONFIG_WPS */
494
495
496 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
497                                          char *buf, size_t buflen)
498 {
499         int ret;
500         char *pos, *end;
501
502         pos = buf;
503         end = buf + buflen;
504
505         ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
506                           "ssid=%s\n",
507                           MAC2STR(hapd->own_addr),
508                           hapd->conf->ssid.ssid);
509         if (ret < 0 || ret >= end - pos)
510                 return pos - buf;
511         pos += ret;
512
513 #ifdef CONFIG_WPS
514         ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
515                           hapd->conf->wps_state == 0 ? "disabled" :
516                           (hapd->conf->wps_state == 1 ? "not configured" :
517                            "configured"));
518         if (ret < 0 || ret >= end - pos)
519                 return pos - buf;
520         pos += ret;
521
522         if (hapd->conf->wps_state && hapd->conf->wpa &&
523             hapd->conf->ssid.wpa_passphrase) {
524                 ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
525                                   hapd->conf->ssid.wpa_passphrase);
526                 if (ret < 0 || ret >= end - pos)
527                         return pos - buf;
528                 pos += ret;
529         }
530
531         if (hapd->conf->wps_state && hapd->conf->wpa &&
532             hapd->conf->ssid.wpa_psk &&
533             hapd->conf->ssid.wpa_psk->group) {
534                 char hex[PMK_LEN * 2 + 1];
535                 wpa_snprintf_hex(hex, sizeof(hex),
536                                  hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
537                 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
538                 if (ret < 0 || ret >= end - pos)
539                         return pos - buf;
540                 pos += ret;
541         }
542 #endif /* CONFIG_WPS */
543
544         if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
545                 ret = os_snprintf(pos, end - pos, "key_mgmt=");
546                 if (ret < 0 || ret >= end - pos)
547                         return pos - buf;
548                 pos += ret;
549
550                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
551                         ret = os_snprintf(pos, end - pos, "WPA-PSK ");
552                         if (ret < 0 || ret >= end - pos)
553                                 return pos - buf;
554                         pos += ret;
555                 }
556                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
557                         ret = os_snprintf(pos, end - pos, "WPA-EAP ");
558                         if (ret < 0 || ret >= end - pos)
559                                 return pos - buf;
560                         pos += ret;
561                 }
562 #ifdef CONFIG_IEEE80211R
563                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
564                         ret = os_snprintf(pos, end - pos, "FT-PSK ");
565                         if (ret < 0 || ret >= end - pos)
566                                 return pos - buf;
567                         pos += ret;
568                 }
569                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
570                         ret = os_snprintf(pos, end - pos, "FT-EAP ");
571                         if (ret < 0 || ret >= end - pos)
572                                 return pos - buf;
573                         pos += ret;
574                 }
575 #endif /* CONFIG_IEEE80211R */
576 #ifdef CONFIG_IEEE80211W
577                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
578                         ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
579                         if (ret < 0 || ret >= end - pos)
580                                 return pos - buf;
581                         pos += ret;
582                 }
583                 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
584                         ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
585                         if (ret < 0 || ret >= end - pos)
586                                 return pos - buf;
587                         pos += ret;
588                 }
589 #endif /* CONFIG_IEEE80211W */
590
591                 ret = os_snprintf(pos, end - pos, "\n");
592                 if (ret < 0 || ret >= end - pos)
593                         return pos - buf;
594                 pos += ret;
595         }
596
597         if (hapd->conf->wpa && hapd->conf->wpa_group == WPA_CIPHER_CCMP) {
598                 ret = os_snprintf(pos, end - pos, "group_cipher=CCMP\n");
599                 if (ret < 0 || ret >= end - pos)
600                         return pos - buf;
601                 pos += ret;
602         } else if (hapd->conf->wpa &&
603                    hapd->conf->wpa_group == WPA_CIPHER_TKIP) {
604                 ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n");
605                 if (ret < 0 || ret >= end - pos)
606                         return pos - buf;
607                 pos += ret;
608         }
609
610         if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
611                 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
612                 if (ret < 0 || ret >= end - pos)
613                         return pos - buf;
614                 pos += ret;
615
616                 if (hapd->conf->rsn_pairwise & WPA_CIPHER_CCMP) {
617                         ret = os_snprintf(pos, end - pos, "CCMP ");
618                         if (ret < 0 || ret >= end - pos)
619                                 return pos - buf;
620                         pos += ret;
621                 }
622                 if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) {
623                         ret = os_snprintf(pos, end - pos, "TKIP ");
624                         if (ret < 0 || ret >= end - pos)
625                                 return pos - buf;
626                         pos += ret;
627                 }
628
629                 ret = os_snprintf(pos, end - pos, "\n");
630                 if (ret < 0 || ret >= end - pos)
631                         return pos - buf;
632                 pos += ret;
633         }
634
635         if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
636                 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
637                 if (ret < 0 || ret >= end - pos)
638                         return pos - buf;
639                 pos += ret;
640
641                 if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) {
642                         ret = os_snprintf(pos, end - pos, "CCMP ");
643                         if (ret < 0 || ret >= end - pos)
644                                 return pos - buf;
645                         pos += ret;
646                 }
647                 if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {
648                         ret = os_snprintf(pos, end - pos, "TKIP ");
649                         if (ret < 0 || ret >= end - pos)
650                                 return pos - buf;
651                         pos += ret;
652                 }
653
654                 ret = os_snprintf(pos, end - pos, "\n");
655                 if (ret < 0 || ret >= end - pos)
656                         return pos - buf;
657                 pos += ret;
658         }
659
660         return pos - buf;
661 }
662
663
664 static int hostapd_ctrl_iface_set(struct hostapd_data *wpa_s, char *cmd)
665 {
666         char *value;
667         int ret = 0;
668
669         value = os_strchr(cmd, ' ');
670         if (value == NULL)
671                 return -1;
672         *value++ = '\0';
673
674         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
675         if (0) {
676 #ifdef CONFIG_WPS_TESTING
677         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
678                 long int val;
679                 val = strtol(value, NULL, 0);
680                 if (val < 0 || val > 0xff) {
681                         ret = -1;
682                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
683                                    "wps_version_number %ld", val);
684                 } else {
685                         wps_version_number = val;
686                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
687                                    "version %u.%u",
688                                    (wps_version_number & 0xf0) >> 4,
689                                    wps_version_number & 0x0f);
690                 }
691         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
692                 wps_testing_dummy_cred = atoi(value);
693                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
694                            wps_testing_dummy_cred);
695 #endif /* CONFIG_WPS_TESTING */
696         } else {
697                 ret = -1;
698         }
699
700         return ret;
701 }
702
703
704 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
705                                        void *sock_ctx)
706 {
707         struct hostapd_data *hapd = eloop_ctx;
708         char buf[256];
709         int res;
710         struct sockaddr_un from;
711         socklen_t fromlen = sizeof(from);
712         char *reply;
713         const int reply_size = 4096;
714         int reply_len;
715         int level = MSG_DEBUG;
716
717         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
718                        (struct sockaddr *) &from, &fromlen);
719         if (res < 0) {
720                 perror("recvfrom(ctrl_iface)");
721                 return;
722         }
723         buf[res] = '\0';
724         if (os_strcmp(buf, "PING") == 0)
725                 level = MSG_EXCESSIVE;
726         wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
727
728         reply = os_malloc(reply_size);
729         if (reply == NULL) {
730                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
731                        fromlen);
732                 return;
733         }
734
735         os_memcpy(reply, "OK\n", 3);
736         reply_len = 3;
737
738         if (os_strcmp(buf, "PING") == 0) {
739                 os_memcpy(reply, "PONG\n", 5);
740                 reply_len = 5;
741         } else if (os_strcmp(buf, "MIB") == 0) {
742                 reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
743                 if (reply_len >= 0) {
744                         res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
745                                           reply_size - reply_len);
746                         if (res < 0)
747                                 reply_len = -1;
748                         else
749                                 reply_len += res;
750                 }
751                 if (reply_len >= 0) {
752                         res = ieee802_1x_get_mib(hapd, reply + reply_len,
753                                                  reply_size - reply_len);
754                         if (res < 0)
755                                 reply_len = -1;
756                         else
757                                 reply_len += res;
758                 }
759 #ifndef CONFIG_NO_RADIUS
760                 if (reply_len >= 0) {
761                         res = radius_client_get_mib(hapd->radius,
762                                                     reply + reply_len,
763                                                     reply_size - reply_len);
764                         if (res < 0)
765                                 reply_len = -1;
766                         else
767                                 reply_len += res;
768                 }
769 #endif /* CONFIG_NO_RADIUS */
770         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
771                 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
772                                                          reply_size);
773         } else if (os_strncmp(buf, "STA ", 4) == 0) {
774                 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
775                                                    reply_size);
776         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
777                 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
778                                                         reply_size);
779         } else if (os_strcmp(buf, "ATTACH") == 0) {
780                 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
781                         reply_len = -1;
782         } else if (os_strcmp(buf, "DETACH") == 0) {
783                 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen))
784                         reply_len = -1;
785         } else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
786                 if (hostapd_ctrl_iface_level(hapd, &from, fromlen,
787                                                     buf + 6))
788                         reply_len = -1;
789         } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
790                 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
791                         reply_len = -1;
792         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
793                 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
794                         reply_len = -1;
795         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
796                 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
797                         reply_len = -1;
798 #ifdef CONFIG_IEEE80211W
799 #ifdef NEED_AP_MLME
800         } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
801                 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
802                         reply_len = -1;
803 #endif /* NEED_AP_MLME */
804 #endif /* CONFIG_IEEE80211W */
805 #ifdef CONFIG_WPS
806         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
807                 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
808                         reply_len = -1;
809         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
810                 reply_len = hostapd_ctrl_iface_wps_check_pin(
811                         hapd, buf + 14, reply, reply_size);
812         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
813                 if (hostapd_wps_button_pushed(hapd))
814                         reply_len = -1;
815 #ifdef CONFIG_WPS_OOB
816         } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
817                 if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8))
818                         reply_len = -1;
819 #endif /* CONFIG_WPS_OOB */
820         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
821                 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
822                                                           reply, reply_size);
823 #endif /* CONFIG_WPS */
824         } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
825                 reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
826                                                           reply_size);
827         } else if (os_strncmp(buf, "SET ", 4) == 0) {
828                 if (hostapd_ctrl_iface_set(hapd, buf + 4))
829                         reply_len = -1;
830         } else {
831                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
832                 reply_len = 16;
833         }
834
835         if (reply_len < 0) {
836                 os_memcpy(reply, "FAIL\n", 5);
837                 reply_len = 5;
838         }
839         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
840         os_free(reply);
841 }
842
843
844 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
845 {
846         char *buf;
847         size_t len;
848
849         if (hapd->conf->ctrl_interface == NULL)
850                 return NULL;
851
852         len = os_strlen(hapd->conf->ctrl_interface) +
853                 os_strlen(hapd->conf->iface) + 2;
854         buf = os_malloc(len);
855         if (buf == NULL)
856                 return NULL;
857
858         os_snprintf(buf, len, "%s/%s",
859                     hapd->conf->ctrl_interface, hapd->conf->iface);
860         buf[len - 1] = '\0';
861         return buf;
862 }
863
864
865 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
866                                       const char *txt, size_t len)
867 {
868         struct hostapd_data *hapd = ctx;
869         if (hapd == NULL)
870                 return;
871         hostapd_ctrl_iface_send(hapd, level, txt, len);
872 }
873
874
875 int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
876 {
877         struct sockaddr_un addr;
878         int s = -1;
879         char *fname = NULL;
880
881         hapd->ctrl_sock = -1;
882
883         if (hapd->conf->ctrl_interface == NULL)
884                 return 0;
885
886         if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
887                 if (errno == EEXIST) {
888                         wpa_printf(MSG_DEBUG, "Using existing control "
889                                    "interface directory.");
890                 } else {
891                         perror("mkdir[ctrl_interface]");
892                         goto fail;
893                 }
894         }
895
896         if (hapd->conf->ctrl_interface_gid_set &&
897             chown(hapd->conf->ctrl_interface, 0,
898                   hapd->conf->ctrl_interface_gid) < 0) {
899                 perror("chown[ctrl_interface]");
900                 return -1;
901         }
902
903         if (os_strlen(hapd->conf->ctrl_interface) + 1 +
904             os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
905                 goto fail;
906
907         s = socket(PF_UNIX, SOCK_DGRAM, 0);
908         if (s < 0) {
909                 perror("socket(PF_UNIX)");
910                 goto fail;
911         }
912
913         os_memset(&addr, 0, sizeof(addr));
914 #ifdef __FreeBSD__
915         addr.sun_len = sizeof(addr);
916 #endif /* __FreeBSD__ */
917         addr.sun_family = AF_UNIX;
918         fname = hostapd_ctrl_iface_path(hapd);
919         if (fname == NULL)
920                 goto fail;
921         os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
922         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
923                 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
924                            strerror(errno));
925                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
926                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
927                                    " allow connections - assuming it was left"
928                                    "over from forced program termination");
929                         if (unlink(fname) < 0) {
930                                 perror("unlink[ctrl_iface]");
931                                 wpa_printf(MSG_ERROR, "Could not unlink "
932                                            "existing ctrl_iface socket '%s'",
933                                            fname);
934                                 goto fail;
935                         }
936                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
937                             0) {
938                                 perror("bind(PF_UNIX)");
939                                 goto fail;
940                         }
941                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
942                                    "ctrl_iface socket '%s'", fname);
943                 } else {
944                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
945                                    "be in use - cannot override it");
946                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
947                                    "not used anymore", fname);
948                         os_free(fname);
949                         fname = NULL;
950                         goto fail;
951                 }
952         }
953
954         if (hapd->conf->ctrl_interface_gid_set &&
955             chown(fname, 0, hapd->conf->ctrl_interface_gid) < 0) {
956                 perror("chown[ctrl_interface/ifname]");
957                 goto fail;
958         }
959
960         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
961                 perror("chmod[ctrl_interface/ifname]");
962                 goto fail;
963         }
964         os_free(fname);
965
966         hapd->ctrl_sock = s;
967         eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
968                                  NULL);
969         hapd->msg_ctx = hapd;
970         wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
971
972         return 0;
973
974 fail:
975         if (s >= 0)
976                 close(s);
977         if (fname) {
978                 unlink(fname);
979                 os_free(fname);
980         }
981         return -1;
982 }
983
984
985 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
986 {
987         struct wpa_ctrl_dst *dst, *prev;
988
989         if (hapd->ctrl_sock > -1) {
990                 char *fname;
991                 eloop_unregister_read_sock(hapd->ctrl_sock);
992                 close(hapd->ctrl_sock);
993                 hapd->ctrl_sock = -1;
994                 fname = hostapd_ctrl_iface_path(hapd);
995                 if (fname)
996                         unlink(fname);
997                 os_free(fname);
998
999                 if (hapd->conf->ctrl_interface &&
1000                     rmdir(hapd->conf->ctrl_interface) < 0) {
1001                         if (errno == ENOTEMPTY) {
1002                                 wpa_printf(MSG_DEBUG, "Control interface "
1003                                            "directory not empty - leaving it "
1004                                            "behind");
1005                         } else {
1006                                 perror("rmdir[ctrl_interface]");
1007                         }
1008                 }
1009         }
1010
1011         dst = hapd->ctrl_dst;
1012         while (dst) {
1013                 prev = dst;
1014                 dst = dst->next;
1015                 os_free(prev);
1016         }
1017 }
1018
1019
1020 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
1021                                     const char *buf, size_t len)
1022 {
1023         struct wpa_ctrl_dst *dst, *next;
1024         struct msghdr msg;
1025         int idx;
1026         struct iovec io[2];
1027         char levelstr[10];
1028
1029         dst = hapd->ctrl_dst;
1030         if (hapd->ctrl_sock < 0 || dst == NULL)
1031                 return;
1032
1033         os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
1034         io[0].iov_base = levelstr;
1035         io[0].iov_len = os_strlen(levelstr);
1036         io[1].iov_base = (char *) buf;
1037         io[1].iov_len = len;
1038         os_memset(&msg, 0, sizeof(msg));
1039         msg.msg_iov = io;
1040         msg.msg_iovlen = 2;
1041
1042         idx = 0;
1043         while (dst) {
1044                 next = dst->next;
1045                 if (level >= dst->debug_level) {
1046                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
1047                                     (u8 *) dst->addr.sun_path, dst->addrlen -
1048                                     offsetof(struct sockaddr_un, sun_path));
1049                         msg.msg_name = &dst->addr;
1050                         msg.msg_namelen = dst->addrlen;
1051                         if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) {
1052                                 int _errno = errno;
1053                                 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
1054                                            "%d - %s",
1055                                            idx, errno, strerror(errno));
1056                                 dst->errors++;
1057                                 if (dst->errors > 10 || _errno == ENOENT) {
1058                                         hostapd_ctrl_iface_detach(
1059                                                 hapd, &dst->addr,
1060                                                 dst->addrlen);
1061                                 }
1062                         } else
1063                                 dst->errors = 0;
1064                 }
1065                 idx++;
1066                 dst = next;
1067         }
1068 }
1069
1070 #endif /* CONFIG_NATIVE_WINDOWS */