2 * hostapd / UNIX domain socket -based control interface
3 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
11 #ifndef CONFIG_NATIVE_WINDOWS
17 #include "utils/common.h"
18 #include "utils/eloop.h"
19 #include "common/version.h"
20 #include "common/ieee802_11_defs.h"
21 #include "drivers/driver.h"
22 #include "radius/radius_client.h"
23 #include "ap/hostapd.h"
24 #include "ap/ap_config.h"
25 #include "ap/ieee802_1x.h"
26 #include "ap/wpa_auth.h"
27 #include "ap/ieee802_11.h"
28 #include "ap/sta_info.h"
29 #include "ap/wps_hostapd.h"
30 #include "ap/ctrl_iface_ap.h"
31 #include "ap/ap_drv_ops.h"
32 #include "wps/wps_defs.h"
34 #include "config_file.h"
35 #include "ctrl_iface.h"
39 struct wpa_ctrl_dst
*next
;
40 struct sockaddr_un addr
;
47 static void hostapd_ctrl_iface_send(struct hostapd_data
*hapd
, int level
,
48 const char *buf
, size_t len
);
51 static int hostapd_ctrl_iface_attach(struct hostapd_data
*hapd
,
52 struct sockaddr_un
*from
,
55 struct wpa_ctrl_dst
*dst
;
57 dst
= os_zalloc(sizeof(*dst
));
60 os_memcpy(&dst
->addr
, from
, sizeof(struct sockaddr_un
));
61 dst
->addrlen
= fromlen
;
62 dst
->debug_level
= MSG_INFO
;
63 dst
->next
= hapd
->ctrl_dst
;
65 wpa_hexdump(MSG_DEBUG
, "CTRL_IFACE monitor attached",
66 (u8
*) from
->sun_path
,
67 fromlen
- offsetof(struct sockaddr_un
, sun_path
));
72 static int hostapd_ctrl_iface_detach(struct hostapd_data
*hapd
,
73 struct sockaddr_un
*from
,
76 struct wpa_ctrl_dst
*dst
, *prev
= NULL
;
80 if (fromlen
== dst
->addrlen
&&
81 os_memcmp(from
->sun_path
, dst
->addr
.sun_path
,
82 fromlen
- offsetof(struct sockaddr_un
, sun_path
))
85 hapd
->ctrl_dst
= dst
->next
;
87 prev
->next
= dst
->next
;
89 wpa_hexdump(MSG_DEBUG
, "CTRL_IFACE monitor detached",
90 (u8
*) from
->sun_path
,
92 offsetof(struct sockaddr_un
, sun_path
));
102 static int hostapd_ctrl_iface_level(struct hostapd_data
*hapd
,
103 struct sockaddr_un
*from
,
107 struct wpa_ctrl_dst
*dst
;
109 wpa_printf(MSG_DEBUG
, "CTRL_IFACE LEVEL %s", level
);
111 dst
= hapd
->ctrl_dst
;
113 if (fromlen
== dst
->addrlen
&&
114 os_memcmp(from
->sun_path
, dst
->addr
.sun_path
,
115 fromlen
- offsetof(struct sockaddr_un
, sun_path
))
117 wpa_hexdump(MSG_DEBUG
, "CTRL_IFACE changed monitor "
118 "level", (u8
*) from
->sun_path
, fromlen
-
119 offsetof(struct sockaddr_un
, sun_path
));
120 dst
->debug_level
= atoi(level
);
130 static int hostapd_ctrl_iface_new_sta(struct hostapd_data
*hapd
,
134 struct sta_info
*sta
;
136 wpa_printf(MSG_DEBUG
, "CTRL_IFACE NEW_STA %s", txtaddr
);
138 if (hwaddr_aton(txtaddr
, addr
))
141 sta
= ap_get_sta(hapd
, addr
);
145 wpa_printf(MSG_DEBUG
, "Add new STA " MACSTR
" based on ctrl_iface "
146 "notification", MAC2STR(addr
));
147 sta
= ap_sta_add(hapd
, addr
);
151 hostapd_new_assoc_sta(hapd
, sta
, 0);
156 #ifdef CONFIG_IEEE80211W
158 static int hostapd_ctrl_iface_sa_query(struct hostapd_data
*hapd
,
162 u8 trans_id
[WLAN_SA_QUERY_TR_ID_LEN
];
164 wpa_printf(MSG_DEBUG
, "CTRL_IFACE SA_QUERY %s", txtaddr
);
166 if (hwaddr_aton(txtaddr
, addr
) ||
167 os_get_random(trans_id
, WLAN_SA_QUERY_TR_ID_LEN
) < 0)
170 ieee802_11_send_sa_query_req(hapd
, addr
, trans_id
);
174 #endif /* NEED_AP_MLME */
175 #endif /* CONFIG_IEEE80211W */
179 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data
*hapd
, char *txt
)
181 char *pin
= os_strchr(txt
, ' ');
184 u8 addr_buf
[ETH_ALEN
], *addr
= NULL
;
191 timeout_txt
= os_strchr(pin
, ' ');
193 *timeout_txt
++ = '\0';
194 timeout
= atoi(timeout_txt
);
195 pos
= os_strchr(timeout_txt
, ' ');
198 if (hwaddr_aton(pos
, addr_buf
) == 0)
204 return hostapd_wps_add_pin(hapd
, addr
, txt
, pin
, timeout
);
208 static int hostapd_ctrl_iface_wps_check_pin(
209 struct hostapd_data
*hapd
, char *cmd
, char *buf
, size_t buflen
)
216 wpa_hexdump_ascii_key(MSG_DEBUG
, "WPS_CHECK_PIN",
217 (u8
*) cmd
, os_strlen(cmd
));
218 for (pos
= cmd
, len
= 0; *pos
!= '\0'; pos
++) {
219 if (*pos
< '0' || *pos
> '9')
223 wpa_printf(MSG_DEBUG
, "WPS: Too long PIN");
227 if (len
!= 4 && len
!= 8) {
228 wpa_printf(MSG_DEBUG
, "WPS: Invalid PIN length %d", (int) len
);
234 unsigned int pin_val
;
236 if (!wps_pin_valid(pin_val
)) {
237 wpa_printf(MSG_DEBUG
, "WPS: Invalid checksum digit");
238 ret
= os_snprintf(buf
, buflen
, "FAIL-CHECKSUM\n");
239 if (ret
< 0 || (size_t) ret
>= buflen
)
245 ret
= os_snprintf(buf
, buflen
, "%s", pin
);
246 if (ret
< 0 || (size_t) ret
>= buflen
)
253 #ifdef CONFIG_WPS_NFC
254 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data
*hapd
,
261 len
= os_strlen(pos
);
266 buf
= wpabuf_alloc(len
);
269 if (hexstr2bin(pos
, wpabuf_put(buf
, len
), len
) < 0) {
274 ret
= hostapd_wps_nfc_tag_read(hapd
, buf
);
281 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data
*hapd
,
282 char *cmd
, char *reply
,
289 if (os_strcmp(cmd
, "WPS") == 0)
291 else if (os_strcmp(cmd
, "NDEF") == 0)
296 buf
= hostapd_wps_nfc_config_token(hapd
, ndef
);
300 res
= wpa_snprintf_hex_uppercase(reply
, max_len
, wpabuf_head(buf
),
311 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data
*hapd
,
312 char *reply
, size_t max_len
,
318 buf
= hostapd_wps_nfc_token_gen(hapd
, ndef
);
322 res
= wpa_snprintf_hex_uppercase(reply
, max_len
, wpabuf_head(buf
),
333 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data
*hapd
,
334 char *cmd
, char *reply
,
337 if (os_strcmp(cmd
, "WPS") == 0)
338 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd
, reply
,
341 if (os_strcmp(cmd
, "NDEF") == 0)
342 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd
, reply
,
345 if (os_strcmp(cmd
, "enable") == 0)
346 return hostapd_wps_nfc_token_enable(hapd
);
348 if (os_strcmp(cmd
, "disable") == 0) {
349 hostapd_wps_nfc_token_disable(hapd
);
355 #endif /* CONFIG_WPS_NFC */
358 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data
*hapd
, char *txt
,
359 char *buf
, size_t buflen
)
365 pos
= os_strchr(txt
, ' ');
369 if (os_strcmp(txt
, "disable") == 0) {
370 hostapd_wps_ap_pin_disable(hapd
);
371 return os_snprintf(buf
, buflen
, "OK\n");
374 if (os_strcmp(txt
, "random") == 0) {
377 pin_txt
= hostapd_wps_ap_pin_random(hapd
, timeout
);
380 return os_snprintf(buf
, buflen
, "%s", pin_txt
);
383 if (os_strcmp(txt
, "get") == 0) {
384 pin_txt
= hostapd_wps_ap_pin_get(hapd
);
387 return os_snprintf(buf
, buflen
, "%s", pin_txt
);
390 if (os_strcmp(txt
, "set") == 0) {
395 pos
= os_strchr(pos
, ' ');
400 if (os_strlen(pin
) > buflen
)
402 if (hostapd_wps_ap_pin_set(hapd
, pin
, timeout
) < 0)
404 return os_snprintf(buf
, buflen
, "%s", pin
);
411 static int hostapd_ctrl_iface_wps_config(struct hostapd_data
*hapd
, char *txt
)
414 char *ssid
, *auth
, *encr
= NULL
, *key
= NULL
;
417 pos
= os_strchr(txt
, ' ');
423 pos
= os_strchr(pos
, ' ');
427 pos
= os_strchr(pos
, ' ');
434 return hostapd_wps_config_ap(hapd
, ssid
, auth
, encr
, key
);
436 #endif /* CONFIG_WPS */
441 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data
*hapd
,
446 struct ieee80211_mgmt
*mgmt
;
449 if (hwaddr_aton(cmd
, addr
))
453 disassoc_timer
= atoi(cmd
+ 17);
455 os_memset(buf
, 0, sizeof(buf
));
456 mgmt
= (struct ieee80211_mgmt
*) buf
;
457 mgmt
->frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
458 WLAN_FC_STYPE_ACTION
);
459 os_memcpy(mgmt
->da
, addr
, ETH_ALEN
);
460 os_memcpy(mgmt
->sa
, hapd
->own_addr
, ETH_ALEN
);
461 os_memcpy(mgmt
->bssid
, hapd
->own_addr
, ETH_ALEN
);
462 mgmt
->u
.action
.category
= WLAN_ACTION_WNM
;
463 mgmt
->u
.action
.u
.bss_tm_req
.action
= WNM_BSS_TRANS_MGMT_REQ
;
464 mgmt
->u
.action
.u
.bss_tm_req
.dialog_token
= 1;
465 mgmt
->u
.action
.u
.bss_tm_req
.req_mode
=
466 WNM_BSS_TM_REQ_DISASSOC_IMMINENT
;
467 mgmt
->u
.action
.u
.bss_tm_req
.disassoc_timer
=
468 host_to_le16(disassoc_timer
);
469 mgmt
->u
.action
.u
.bss_tm_req
.validity_interval
= 0;
471 pos
= mgmt
->u
.action
.u
.bss_tm_req
.variable
;
473 if (hostapd_drv_send_mlme(hapd
, buf
, pos
- buf
, 0) < 0) {
474 wpa_printf(MSG_DEBUG
, "Failed to send BSS Transition "
475 "Management Request frame");
483 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data
*hapd
,
489 struct ieee80211_mgmt
*mgmt
;
492 if (hwaddr_aton(cmd
, addr
))
498 url_len
= os_strlen(url
);
502 os_memset(buf
, 0, sizeof(buf
));
503 mgmt
= (struct ieee80211_mgmt
*) buf
;
504 mgmt
->frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
505 WLAN_FC_STYPE_ACTION
);
506 os_memcpy(mgmt
->da
, addr
, ETH_ALEN
);
507 os_memcpy(mgmt
->sa
, hapd
->own_addr
, ETH_ALEN
);
508 os_memcpy(mgmt
->bssid
, hapd
->own_addr
, ETH_ALEN
);
509 mgmt
->u
.action
.category
= WLAN_ACTION_WNM
;
510 mgmt
->u
.action
.u
.bss_tm_req
.action
= WNM_BSS_TRANS_MGMT_REQ
;
511 mgmt
->u
.action
.u
.bss_tm_req
.dialog_token
= 1;
512 mgmt
->u
.action
.u
.bss_tm_req
.req_mode
=
513 WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT
;
514 mgmt
->u
.action
.u
.bss_tm_req
.disassoc_timer
= host_to_le16(0);
515 mgmt
->u
.action
.u
.bss_tm_req
.validity_interval
= 0;
517 pos
= mgmt
->u
.action
.u
.bss_tm_req
.variable
;
519 /* Session Information URL */
521 os_memcpy(pos
, url
, url_len
);
524 if (hostapd_drv_send_mlme(hapd
, buf
, pos
- buf
, 0) < 0) {
525 wpa_printf(MSG_DEBUG
, "Failed to send BSS Transition "
526 "Management Request frame");
533 #endif /* CONFIG_WNM */
536 static int hostapd_ctrl_iface_get_config(struct hostapd_data
*hapd
,
537 char *buf
, size_t buflen
)
545 ret
= os_snprintf(pos
, end
- pos
, "bssid=" MACSTR
"\n"
547 MAC2STR(hapd
->own_addr
),
548 wpa_ssid_txt(hapd
->conf
->ssid
.ssid
,
549 hapd
->conf
->ssid
.ssid_len
));
550 if (ret
< 0 || ret
>= end
- pos
)
555 ret
= os_snprintf(pos
, end
- pos
, "wps_state=%s\n",
556 hapd
->conf
->wps_state
== 0 ? "disabled" :
557 (hapd
->conf
->wps_state
== 1 ? "not configured" :
559 if (ret
< 0 || ret
>= end
- pos
)
563 if (hapd
->conf
->wps_state
&& hapd
->conf
->wpa
&&
564 hapd
->conf
->ssid
.wpa_passphrase
) {
565 ret
= os_snprintf(pos
, end
- pos
, "passphrase=%s\n",
566 hapd
->conf
->ssid
.wpa_passphrase
);
567 if (ret
< 0 || ret
>= end
- pos
)
572 if (hapd
->conf
->wps_state
&& hapd
->conf
->wpa
&&
573 hapd
->conf
->ssid
.wpa_psk
&&
574 hapd
->conf
->ssid
.wpa_psk
->group
) {
575 char hex
[PMK_LEN
* 2 + 1];
576 wpa_snprintf_hex(hex
, sizeof(hex
),
577 hapd
->conf
->ssid
.wpa_psk
->psk
, PMK_LEN
);
578 ret
= os_snprintf(pos
, end
- pos
, "psk=%s\n", hex
);
579 if (ret
< 0 || ret
>= end
- pos
)
583 #endif /* CONFIG_WPS */
585 if (hapd
->conf
->wpa
&& hapd
->conf
->wpa_key_mgmt
) {
586 ret
= os_snprintf(pos
, end
- pos
, "key_mgmt=");
587 if (ret
< 0 || ret
>= end
- pos
)
591 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_PSK
) {
592 ret
= os_snprintf(pos
, end
- pos
, "WPA-PSK ");
593 if (ret
< 0 || ret
>= end
- pos
)
597 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_IEEE8021X
) {
598 ret
= os_snprintf(pos
, end
- pos
, "WPA-EAP ");
599 if (ret
< 0 || ret
>= end
- pos
)
603 #ifdef CONFIG_IEEE80211R
604 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_FT_PSK
) {
605 ret
= os_snprintf(pos
, end
- pos
, "FT-PSK ");
606 if (ret
< 0 || ret
>= end
- pos
)
610 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_FT_IEEE8021X
) {
611 ret
= os_snprintf(pos
, end
- pos
, "FT-EAP ");
612 if (ret
< 0 || ret
>= end
- pos
)
616 #endif /* CONFIG_IEEE80211R */
617 #ifdef CONFIG_IEEE80211W
618 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_PSK_SHA256
) {
619 ret
= os_snprintf(pos
, end
- pos
, "WPA-PSK-SHA256 ");
620 if (ret
< 0 || ret
>= end
- pos
)
624 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_IEEE8021X_SHA256
) {
625 ret
= os_snprintf(pos
, end
- pos
, "WPA-EAP-SHA256 ");
626 if (ret
< 0 || ret
>= end
- pos
)
630 #endif /* CONFIG_IEEE80211W */
632 ret
= os_snprintf(pos
, end
- pos
, "\n");
633 if (ret
< 0 || ret
>= end
- pos
)
638 if (hapd
->conf
->wpa
&& hapd
->conf
->wpa_group
== WPA_CIPHER_CCMP
) {
639 ret
= os_snprintf(pos
, end
- pos
, "group_cipher=CCMP\n");
640 if (ret
< 0 || ret
>= end
- pos
)
643 } else if (hapd
->conf
->wpa
&&
644 hapd
->conf
->wpa_group
== WPA_CIPHER_GCMP
) {
645 ret
= os_snprintf(pos
, end
- pos
, "group_cipher=GCMP\n");
646 if (ret
< 0 || ret
>= end
- pos
)
649 } else if (hapd
->conf
->wpa
&&
650 hapd
->conf
->wpa_group
== WPA_CIPHER_TKIP
) {
651 ret
= os_snprintf(pos
, end
- pos
, "group_cipher=TKIP\n");
652 if (ret
< 0 || ret
>= end
- pos
)
657 if ((hapd
->conf
->wpa
& WPA_PROTO_RSN
) && hapd
->conf
->rsn_pairwise
) {
658 ret
= os_snprintf(pos
, end
- pos
, "rsn_pairwise_cipher=");
659 if (ret
< 0 || ret
>= end
- pos
)
663 if (hapd
->conf
->rsn_pairwise
& WPA_CIPHER_CCMP
) {
664 ret
= os_snprintf(pos
, end
- pos
, "CCMP ");
665 if (ret
< 0 || ret
>= end
- pos
)
669 if (hapd
->conf
->rsn_pairwise
& WPA_CIPHER_GCMP
) {
670 ret
= os_snprintf(pos
, end
- pos
, "GCMP ");
671 if (ret
< 0 || ret
>= end
- pos
)
675 if (hapd
->conf
->rsn_pairwise
& WPA_CIPHER_TKIP
) {
676 ret
= os_snprintf(pos
, end
- pos
, "TKIP ");
677 if (ret
< 0 || ret
>= end
- pos
)
682 ret
= os_snprintf(pos
, end
- pos
, "\n");
683 if (ret
< 0 || ret
>= end
- pos
)
688 if ((hapd
->conf
->wpa
& WPA_PROTO_WPA
) && hapd
->conf
->wpa_pairwise
) {
689 ret
= os_snprintf(pos
, end
- pos
, "wpa_pairwise_cipher=");
690 if (ret
< 0 || ret
>= end
- pos
)
694 if (hapd
->conf
->wpa_pairwise
& WPA_CIPHER_CCMP
) {
695 ret
= os_snprintf(pos
, end
- pos
, "CCMP ");
696 if (ret
< 0 || ret
>= end
- pos
)
700 if (hapd
->conf
->wpa_pairwise
& WPA_CIPHER_GCMP
) {
701 ret
= os_snprintf(pos
, end
- pos
, "GCMP ");
702 if (ret
< 0 || ret
>= end
- pos
)
706 if (hapd
->conf
->wpa_pairwise
& WPA_CIPHER_TKIP
) {
707 ret
= os_snprintf(pos
, end
- pos
, "TKIP ");
708 if (ret
< 0 || ret
>= end
- pos
)
713 ret
= os_snprintf(pos
, end
- pos
, "\n");
714 if (ret
< 0 || ret
>= end
- pos
)
723 static int hostapd_ctrl_iface_set(struct hostapd_data
*hapd
, char *cmd
)
728 value
= os_strchr(cmd
, ' ');
733 wpa_printf(MSG_DEBUG
, "CTRL_IFACE SET '%s'='%s'", cmd
, value
);
735 #ifdef CONFIG_WPS_TESTING
736 } else if (os_strcasecmp(cmd
, "wps_version_number") == 0) {
738 val
= strtol(value
, NULL
, 0);
739 if (val
< 0 || val
> 0xff) {
741 wpa_printf(MSG_DEBUG
, "WPS: Invalid "
742 "wps_version_number %ld", val
);
744 wps_version_number
= val
;
745 wpa_printf(MSG_DEBUG
, "WPS: Testing - force WPS "
747 (wps_version_number
& 0xf0) >> 4,
748 wps_version_number
& 0x0f);
749 hostapd_wps_update_ie(hapd
);
751 } else if (os_strcasecmp(cmd
, "wps_testing_dummy_cred") == 0) {
752 wps_testing_dummy_cred
= atoi(value
);
753 wpa_printf(MSG_DEBUG
, "WPS: Testing - dummy_cred=%d",
754 wps_testing_dummy_cred
);
755 #endif /* CONFIG_WPS_TESTING */
756 #ifdef CONFIG_INTERWORKING
757 } else if (os_strcasecmp(cmd
, "gas_frag_limit") == 0) {
758 int val
= atoi(value
);
762 hapd
->gas_frag_limit
= val
;
763 #endif /* CONFIG_INTERWORKING */
765 ret
= hostapd_set_iface(hapd
->iconf
, hapd
->conf
, cmd
, value
);
772 static int hostapd_ctrl_iface_get(struct hostapd_data
*hapd
, char *cmd
,
773 char *buf
, size_t buflen
)
777 wpa_printf(MSG_DEBUG
, "CTRL_IFACE GET '%s'", cmd
);
779 if (os_strcmp(cmd
, "version") == 0) {
780 res
= os_snprintf(buf
, buflen
, "%s", VERSION_STR
);
781 if (res
< 0 || (unsigned int) res
>= buflen
)
790 static int hostapd_ctrl_iface_enable(struct hostapd_iface
*iface
)
792 if (hostapd_enable_iface(iface
) < 0) {
793 wpa_printf(MSG_ERROR
, "Enabling of interface failed");
800 static int hostapd_ctrl_iface_reload(struct hostapd_iface
*iface
)
802 if (hostapd_reload_iface(iface
) < 0) {
803 wpa_printf(MSG_ERROR
, "Reloading of interface failed");
810 static int hostapd_ctrl_iface_disable(struct hostapd_iface
*iface
)
812 if (hostapd_disable_iface(iface
) < 0) {
813 wpa_printf(MSG_ERROR
, "Disabling of interface failed");
820 static void hostapd_ctrl_iface_receive(int sock
, void *eloop_ctx
,
823 struct hostapd_data
*hapd
= eloop_ctx
;
826 struct sockaddr_un from
;
827 socklen_t fromlen
= sizeof(from
);
829 const int reply_size
= 4096;
831 int level
= MSG_DEBUG
;
833 res
= recvfrom(sock
, buf
, sizeof(buf
) - 1, 0,
834 (struct sockaddr
*) &from
, &fromlen
);
836 perror("recvfrom(ctrl_iface)");
840 if (os_strcmp(buf
, "PING") == 0)
841 level
= MSG_EXCESSIVE
;
842 wpa_hexdump_ascii(level
, "RX ctrl_iface", (u8
*) buf
, res
);
844 reply
= os_malloc(reply_size
);
846 sendto(sock
, "FAIL\n", 5, 0, (struct sockaddr
*) &from
,
851 os_memcpy(reply
, "OK\n", 3);
854 if (os_strcmp(buf
, "PING") == 0) {
855 os_memcpy(reply
, "PONG\n", 5);
857 } else if (os_strncmp(buf
, "RELOG", 5) == 0) {
858 if (wpa_debug_reopen_file() < 0)
860 } else if (os_strcmp(buf
, "MIB") == 0) {
861 reply_len
= ieee802_11_get_mib(hapd
, reply
, reply_size
);
862 if (reply_len
>= 0) {
863 res
= wpa_get_mib(hapd
->wpa_auth
, reply
+ reply_len
,
864 reply_size
- reply_len
);
870 if (reply_len
>= 0) {
871 res
= ieee802_1x_get_mib(hapd
, reply
+ reply_len
,
872 reply_size
- reply_len
);
878 #ifndef CONFIG_NO_RADIUS
879 if (reply_len
>= 0) {
880 res
= radius_client_get_mib(hapd
->radius
,
882 reply_size
- reply_len
);
888 #endif /* CONFIG_NO_RADIUS */
889 } else if (os_strcmp(buf
, "STA-FIRST") == 0) {
890 reply_len
= hostapd_ctrl_iface_sta_first(hapd
, reply
,
892 } else if (os_strncmp(buf
, "STA ", 4) == 0) {
893 reply_len
= hostapd_ctrl_iface_sta(hapd
, buf
+ 4, reply
,
895 } else if (os_strncmp(buf
, "STA-NEXT ", 9) == 0) {
896 reply_len
= hostapd_ctrl_iface_sta_next(hapd
, buf
+ 9, reply
,
898 } else if (os_strcmp(buf
, "ATTACH") == 0) {
899 if (hostapd_ctrl_iface_attach(hapd
, &from
, fromlen
))
901 } else if (os_strcmp(buf
, "DETACH") == 0) {
902 if (hostapd_ctrl_iface_detach(hapd
, &from
, fromlen
))
904 } else if (os_strncmp(buf
, "LEVEL ", 6) == 0) {
905 if (hostapd_ctrl_iface_level(hapd
, &from
, fromlen
,
908 } else if (os_strncmp(buf
, "NEW_STA ", 8) == 0) {
909 if (hostapd_ctrl_iface_new_sta(hapd
, buf
+ 8))
911 } else if (os_strncmp(buf
, "DEAUTHENTICATE ", 15) == 0) {
912 if (hostapd_ctrl_iface_deauthenticate(hapd
, buf
+ 15))
914 } else if (os_strncmp(buf
, "DISASSOCIATE ", 13) == 0) {
915 if (hostapd_ctrl_iface_disassociate(hapd
, buf
+ 13))
917 #ifdef CONFIG_IEEE80211W
919 } else if (os_strncmp(buf
, "SA_QUERY ", 9) == 0) {
920 if (hostapd_ctrl_iface_sa_query(hapd
, buf
+ 9))
922 #endif /* NEED_AP_MLME */
923 #endif /* CONFIG_IEEE80211W */
925 } else if (os_strncmp(buf
, "WPS_PIN ", 8) == 0) {
926 if (hostapd_ctrl_iface_wps_pin(hapd
, buf
+ 8))
928 } else if (os_strncmp(buf
, "WPS_CHECK_PIN ", 14) == 0) {
929 reply_len
= hostapd_ctrl_iface_wps_check_pin(
930 hapd
, buf
+ 14, reply
, reply_size
);
931 } else if (os_strcmp(buf
, "WPS_PBC") == 0) {
932 if (hostapd_wps_button_pushed(hapd
, NULL
))
934 } else if (os_strcmp(buf
, "WPS_CANCEL") == 0) {
935 if (hostapd_wps_cancel(hapd
))
937 } else if (os_strncmp(buf
, "WPS_AP_PIN ", 11) == 0) {
938 reply_len
= hostapd_ctrl_iface_wps_ap_pin(hapd
, buf
+ 11,
940 } else if (os_strncmp(buf
, "WPS_CONFIG ", 11) == 0) {
941 if (hostapd_ctrl_iface_wps_config(hapd
, buf
+ 11) < 0)
943 #ifdef CONFIG_WPS_NFC
944 } else if (os_strncmp(buf
, "WPS_NFC_TAG_READ ", 17) == 0) {
945 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd
, buf
+ 17))
947 } else if (os_strncmp(buf
, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
948 reply_len
= hostapd_ctrl_iface_wps_nfc_config_token(
949 hapd
, buf
+ 21, reply
, reply_size
);
950 } else if (os_strncmp(buf
, "WPS_NFC_TOKEN ", 14) == 0) {
951 reply_len
= hostapd_ctrl_iface_wps_nfc_token(
952 hapd
, buf
+ 14, reply
, reply_size
);
953 #endif /* CONFIG_WPS_NFC */
954 #endif /* CONFIG_WPS */
956 } else if (os_strncmp(buf
, "DISASSOC_IMMINENT ", 18) == 0) {
957 if (hostapd_ctrl_iface_disassoc_imminent(hapd
, buf
+ 18))
959 } else if (os_strncmp(buf
, "ESS_DISASSOC ", 13) == 0) {
960 if (hostapd_ctrl_iface_ess_disassoc(hapd
, buf
+ 13))
962 #endif /* CONFIG_WNM */
963 } else if (os_strcmp(buf
, "GET_CONFIG") == 0) {
964 reply_len
= hostapd_ctrl_iface_get_config(hapd
, reply
,
966 } else if (os_strncmp(buf
, "SET ", 4) == 0) {
967 if (hostapd_ctrl_iface_set(hapd
, buf
+ 4))
969 } else if (os_strncmp(buf
, "GET ", 4) == 0) {
970 reply_len
= hostapd_ctrl_iface_get(hapd
, buf
+ 4, reply
,
972 } else if (os_strncmp(buf
, "ENABLE", 6) == 0) {
973 if (hostapd_ctrl_iface_enable(hapd
->iface
))
975 } else if (os_strncmp(buf
, "RELOAD", 6) == 0) {
976 if (hostapd_ctrl_iface_reload(hapd
->iface
))
978 } else if (os_strncmp(buf
, "DISABLE", 7) == 0) {
979 if (hostapd_ctrl_iface_disable(hapd
->iface
))
982 os_memcpy(reply
, "UNKNOWN COMMAND\n", 16);
987 os_memcpy(reply
, "FAIL\n", 5);
990 sendto(sock
, reply
, reply_len
, 0, (struct sockaddr
*) &from
, fromlen
);
995 static char * hostapd_ctrl_iface_path(struct hostapd_data
*hapd
)
1000 if (hapd
->conf
->ctrl_interface
== NULL
)
1003 len
= os_strlen(hapd
->conf
->ctrl_interface
) +
1004 os_strlen(hapd
->conf
->iface
) + 2;
1005 buf
= os_malloc(len
);
1009 os_snprintf(buf
, len
, "%s/%s",
1010 hapd
->conf
->ctrl_interface
, hapd
->conf
->iface
);
1011 buf
[len
- 1] = '\0';
1016 static void hostapd_ctrl_iface_msg_cb(void *ctx
, int level
,
1017 const char *txt
, size_t len
)
1019 struct hostapd_data
*hapd
= ctx
;
1022 hostapd_ctrl_iface_send(hapd
, level
, txt
, len
);
1026 int hostapd_ctrl_iface_init(struct hostapd_data
*hapd
)
1028 struct sockaddr_un addr
;
1032 if (hapd
->ctrl_sock
> -1) {
1033 wpa_printf(MSG_DEBUG
, "ctrl_iface already exists!");
1037 if (hapd
->conf
->ctrl_interface
== NULL
)
1040 if (mkdir(hapd
->conf
->ctrl_interface
, S_IRWXU
| S_IRWXG
) < 0) {
1041 if (errno
== EEXIST
) {
1042 wpa_printf(MSG_DEBUG
, "Using existing control "
1043 "interface directory.");
1045 perror("mkdir[ctrl_interface]");
1050 if (hapd
->conf
->ctrl_interface_gid_set
&&
1051 chown(hapd
->conf
->ctrl_interface
, -1,
1052 hapd
->conf
->ctrl_interface_gid
) < 0) {
1053 perror("chown[ctrl_interface]");
1059 * Android is using umask 0077 which would leave the control interface
1060 * directory without group access. This breaks things since Wi-Fi
1061 * framework assumes that this directory can be accessed by other
1062 * applications in the wifi group. Fix this by adding group access even
1063 * if umask value would prevent this.
1065 if (chmod(hapd
->conf
->ctrl_interface
, S_IRWXU
| S_IRWXG
) < 0) {
1066 wpa_printf(MSG_ERROR
, "CTRL: Could not chmod directory: %s",
1068 /* Try to continue anyway */
1070 #endif /* ANDROID */
1072 if (os_strlen(hapd
->conf
->ctrl_interface
) + 1 +
1073 os_strlen(hapd
->conf
->iface
) >= sizeof(addr
.sun_path
))
1076 s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
1078 perror("socket(PF_UNIX)");
1082 os_memset(&addr
, 0, sizeof(addr
));
1084 addr
.sun_len
= sizeof(addr
);
1085 #endif /* __FreeBSD__ */
1086 addr
.sun_family
= AF_UNIX
;
1087 fname
= hostapd_ctrl_iface_path(hapd
);
1090 os_strlcpy(addr
.sun_path
, fname
, sizeof(addr
.sun_path
));
1091 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1092 wpa_printf(MSG_DEBUG
, "ctrl_iface bind(PF_UNIX) failed: %s",
1094 if (connect(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1095 wpa_printf(MSG_DEBUG
, "ctrl_iface exists, but does not"
1096 " allow connections - assuming it was left"
1097 "over from forced program termination");
1098 if (unlink(fname
) < 0) {
1099 perror("unlink[ctrl_iface]");
1100 wpa_printf(MSG_ERROR
, "Could not unlink "
1101 "existing ctrl_iface socket '%s'",
1105 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) <
1107 perror("hostapd-ctrl-iface: bind(PF_UNIX)");
1110 wpa_printf(MSG_DEBUG
, "Successfully replaced leftover "
1111 "ctrl_iface socket '%s'", fname
);
1113 wpa_printf(MSG_INFO
, "ctrl_iface exists and seems to "
1114 "be in use - cannot override it");
1115 wpa_printf(MSG_INFO
, "Delete '%s' manually if it is "
1116 "not used anymore", fname
);
1123 if (hapd
->conf
->ctrl_interface_gid_set
&&
1124 chown(fname
, -1, hapd
->conf
->ctrl_interface_gid
) < 0) {
1125 perror("chown[ctrl_interface/ifname]");
1129 if (chmod(fname
, S_IRWXU
| S_IRWXG
) < 0) {
1130 perror("chmod[ctrl_interface/ifname]");
1135 hapd
->ctrl_sock
= s
;
1136 eloop_register_read_sock(s
, hostapd_ctrl_iface_receive
, hapd
,
1138 hapd
->msg_ctx
= hapd
;
1139 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb
);
1154 void hostapd_ctrl_iface_deinit(struct hostapd_data
*hapd
)
1156 struct wpa_ctrl_dst
*dst
, *prev
;
1158 if (hapd
->ctrl_sock
> -1) {
1160 eloop_unregister_read_sock(hapd
->ctrl_sock
);
1161 close(hapd
->ctrl_sock
);
1162 hapd
->ctrl_sock
= -1;
1163 fname
= hostapd_ctrl_iface_path(hapd
);
1168 if (hapd
->conf
->ctrl_interface
&&
1169 rmdir(hapd
->conf
->ctrl_interface
) < 0) {
1170 if (errno
== ENOTEMPTY
) {
1171 wpa_printf(MSG_DEBUG
, "Control interface "
1172 "directory not empty - leaving it "
1175 perror("rmdir[ctrl_interface]");
1180 dst
= hapd
->ctrl_dst
;
1189 static int hostapd_ctrl_iface_add(struct hapd_interfaces
*interfaces
,
1192 if (hostapd_add_iface(interfaces
, buf
) < 0) {
1193 wpa_printf(MSG_ERROR
, "Adding interface %s failed", buf
);
1200 static int hostapd_ctrl_iface_remove(struct hapd_interfaces
*interfaces
,
1203 if (hostapd_remove_iface(interfaces
, buf
) < 0) {
1204 wpa_printf(MSG_ERROR
, "Removing interface %s failed", buf
);
1211 static void hostapd_global_ctrl_iface_receive(int sock
, void *eloop_ctx
,
1214 void *interfaces
= eloop_ctx
;
1217 struct sockaddr_un from
;
1218 socklen_t fromlen
= sizeof(from
);
1222 res
= recvfrom(sock
, buf
, sizeof(buf
) - 1, 0,
1223 (struct sockaddr
*) &from
, &fromlen
);
1225 perror("recvfrom(ctrl_iface)");
1230 os_memcpy(reply
, "OK\n", 3);
1233 if (os_strcmp(buf
, "PING") == 0) {
1234 os_memcpy(reply
, "PONG\n", 5);
1236 } else if (os_strncmp(buf
, "ADD ", 4) == 0) {
1237 if (hostapd_ctrl_iface_add(interfaces
, buf
+ 4) < 0)
1239 } else if (os_strncmp(buf
, "REMOVE ", 7) == 0) {
1240 if (hostapd_ctrl_iface_remove(interfaces
, buf
+ 7) < 0)
1243 wpa_printf(MSG_DEBUG
, "Unrecognized global ctrl_iface command "
1248 if (reply_len
< 0) {
1249 os_memcpy(reply
, "FAIL\n", 5);
1253 sendto(sock
, reply
, reply_len
, 0, (struct sockaddr
*) &from
, fromlen
);
1257 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces
*interface
)
1262 if (interface
->global_iface_path
== NULL
)
1265 len
= os_strlen(interface
->global_iface_path
) +
1266 os_strlen(interface
->global_iface_name
) + 2;
1267 buf
= os_malloc(len
);
1271 os_snprintf(buf
, len
, "%s/%s", interface
->global_iface_path
,
1272 interface
->global_iface_name
);
1273 buf
[len
- 1] = '\0';
1278 int hostapd_global_ctrl_iface_init(struct hapd_interfaces
*interface
)
1280 struct sockaddr_un addr
;
1284 if (interface
->global_iface_path
== NULL
) {
1285 wpa_printf(MSG_DEBUG
, "ctrl_iface not configured!");
1289 if (mkdir(interface
->global_iface_path
, S_IRWXU
| S_IRWXG
) < 0) {
1290 if (errno
== EEXIST
) {
1291 wpa_printf(MSG_DEBUG
, "Using existing control "
1292 "interface directory.");
1294 perror("mkdir[ctrl_interface]");
1299 if (os_strlen(interface
->global_iface_path
) + 1 +
1300 os_strlen(interface
->global_iface_name
) >= sizeof(addr
.sun_path
))
1303 s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
1305 perror("socket(PF_UNIX)");
1309 os_memset(&addr
, 0, sizeof(addr
));
1311 addr
.sun_len
= sizeof(addr
);
1312 #endif /* __FreeBSD__ */
1313 addr
.sun_family
= AF_UNIX
;
1314 fname
= hostapd_global_ctrl_iface_path(interface
);
1317 os_strlcpy(addr
.sun_path
, fname
, sizeof(addr
.sun_path
));
1318 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1319 wpa_printf(MSG_DEBUG
, "ctrl_iface bind(PF_UNIX) failed: %s",
1321 if (connect(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1322 wpa_printf(MSG_DEBUG
, "ctrl_iface exists, but does not"
1323 " allow connections - assuming it was left"
1324 "over from forced program termination");
1325 if (unlink(fname
) < 0) {
1326 perror("unlink[ctrl_iface]");
1327 wpa_printf(MSG_ERROR
, "Could not unlink "
1328 "existing ctrl_iface socket '%s'",
1332 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) <
1334 perror("bind(PF_UNIX)");
1337 wpa_printf(MSG_DEBUG
, "Successfully replaced leftover "
1338 "ctrl_iface socket '%s'", fname
);
1340 wpa_printf(MSG_INFO
, "ctrl_iface exists and seems to "
1341 "be in use - cannot override it");
1342 wpa_printf(MSG_INFO
, "Delete '%s' manually if it is "
1343 "not used anymore", fname
);
1350 if (chmod(fname
, S_IRWXU
| S_IRWXG
) < 0) {
1351 perror("chmod[ctrl_interface/ifname]");
1356 interface
->global_ctrl_sock
= s
;
1357 eloop_register_read_sock(s
, hostapd_global_ctrl_iface_receive
,
1373 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces
*interfaces
)
1377 if (interfaces
->global_ctrl_sock
> -1) {
1378 eloop_unregister_read_sock(interfaces
->global_ctrl_sock
);
1379 close(interfaces
->global_ctrl_sock
);
1380 interfaces
->global_ctrl_sock
= -1;
1381 fname
= hostapd_global_ctrl_iface_path(interfaces
);
1387 if (interfaces
->global_iface_path
&&
1388 rmdir(interfaces
->global_iface_path
) < 0) {
1389 if (errno
== ENOTEMPTY
) {
1390 wpa_printf(MSG_DEBUG
, "Control interface "
1391 "directory not empty - leaving it "
1394 perror("rmdir[ctrl_interface]");
1397 os_free(interfaces
->global_iface_path
);
1398 interfaces
->global_iface_path
= NULL
;
1403 static void hostapd_ctrl_iface_send(struct hostapd_data
*hapd
, int level
,
1404 const char *buf
, size_t len
)
1406 struct wpa_ctrl_dst
*dst
, *next
;
1412 dst
= hapd
->ctrl_dst
;
1413 if (hapd
->ctrl_sock
< 0 || dst
== NULL
)
1416 os_snprintf(levelstr
, sizeof(levelstr
), "<%d>", level
);
1417 io
[0].iov_base
= levelstr
;
1418 io
[0].iov_len
= os_strlen(levelstr
);
1419 io
[1].iov_base
= (char *) buf
;
1420 io
[1].iov_len
= len
;
1421 os_memset(&msg
, 0, sizeof(msg
));
1428 if (level
>= dst
->debug_level
) {
1429 wpa_hexdump(MSG_DEBUG
, "CTRL_IFACE monitor send",
1430 (u8
*) dst
->addr
.sun_path
, dst
->addrlen
-
1431 offsetof(struct sockaddr_un
, sun_path
));
1432 msg
.msg_name
= &dst
->addr
;
1433 msg
.msg_namelen
= dst
->addrlen
;
1434 if (sendmsg(hapd
->ctrl_sock
, &msg
, 0) < 0) {
1436 wpa_printf(MSG_INFO
, "CTRL_IFACE monitor[%d]: "
1438 idx
, errno
, strerror(errno
));
1440 if (dst
->errors
> 10 || _errno
== ENOENT
) {
1441 hostapd_ctrl_iface_detach(
1453 #endif /* CONFIG_NATIVE_WINDOWS */