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
);
357 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data
*hapd
,
358 char *cmd
, char *reply
,
366 pos
= os_strchr(cmd
, ' ');
371 if (os_strcmp(cmd
, "WPS") == 0)
373 else if (os_strcmp(cmd
, "NDEF") == 0)
378 if (os_strcmp(pos
, "WPS-CR") == 0)
379 buf
= hostapd_wps_nfc_hs_cr(hapd
, ndef
);
385 res
= wpa_snprintf_hex_uppercase(reply
, max_len
, wpabuf_head(buf
),
396 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data
*hapd
,
400 * Since NFC connection handover provided full WPS Credential, there is
401 * no need for additional operations within hostapd. Just report this in
404 wpa_printf(MSG_DEBUG
, "NFC: Connection handover reported: %s", cmd
);
408 #endif /* CONFIG_WPS_NFC */
411 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data
*hapd
, char *txt
,
412 char *buf
, size_t buflen
)
418 pos
= os_strchr(txt
, ' ');
422 if (os_strcmp(txt
, "disable") == 0) {
423 hostapd_wps_ap_pin_disable(hapd
);
424 return os_snprintf(buf
, buflen
, "OK\n");
427 if (os_strcmp(txt
, "random") == 0) {
430 pin_txt
= hostapd_wps_ap_pin_random(hapd
, timeout
);
433 return os_snprintf(buf
, buflen
, "%s", pin_txt
);
436 if (os_strcmp(txt
, "get") == 0) {
437 pin_txt
= hostapd_wps_ap_pin_get(hapd
);
440 return os_snprintf(buf
, buflen
, "%s", pin_txt
);
443 if (os_strcmp(txt
, "set") == 0) {
448 pos
= os_strchr(pos
, ' ');
453 if (os_strlen(pin
) > buflen
)
455 if (hostapd_wps_ap_pin_set(hapd
, pin
, timeout
) < 0)
457 return os_snprintf(buf
, buflen
, "%s", pin
);
464 static int hostapd_ctrl_iface_wps_config(struct hostapd_data
*hapd
, char *txt
)
467 char *ssid
, *auth
, *encr
= NULL
, *key
= NULL
;
470 pos
= os_strchr(txt
, ' ');
476 pos
= os_strchr(pos
, ' ');
480 pos
= os_strchr(pos
, ' ');
487 return hostapd_wps_config_ap(hapd
, ssid
, auth
, encr
, key
);
489 #endif /* CONFIG_WPS */
494 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data
*hapd
,
499 struct ieee80211_mgmt
*mgmt
;
502 if (hwaddr_aton(cmd
, addr
))
506 disassoc_timer
= atoi(cmd
+ 17);
508 os_memset(buf
, 0, sizeof(buf
));
509 mgmt
= (struct ieee80211_mgmt
*) buf
;
510 mgmt
->frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
511 WLAN_FC_STYPE_ACTION
);
512 os_memcpy(mgmt
->da
, addr
, ETH_ALEN
);
513 os_memcpy(mgmt
->sa
, hapd
->own_addr
, ETH_ALEN
);
514 os_memcpy(mgmt
->bssid
, hapd
->own_addr
, ETH_ALEN
);
515 mgmt
->u
.action
.category
= WLAN_ACTION_WNM
;
516 mgmt
->u
.action
.u
.bss_tm_req
.action
= WNM_BSS_TRANS_MGMT_REQ
;
517 mgmt
->u
.action
.u
.bss_tm_req
.dialog_token
= 1;
518 mgmt
->u
.action
.u
.bss_tm_req
.req_mode
=
519 WNM_BSS_TM_REQ_DISASSOC_IMMINENT
;
520 mgmt
->u
.action
.u
.bss_tm_req
.disassoc_timer
=
521 host_to_le16(disassoc_timer
);
522 mgmt
->u
.action
.u
.bss_tm_req
.validity_interval
= 0;
524 pos
= mgmt
->u
.action
.u
.bss_tm_req
.variable
;
526 if (hostapd_drv_send_mlme(hapd
, buf
, pos
- buf
, 0) < 0) {
527 wpa_printf(MSG_DEBUG
, "Failed to send BSS Transition "
528 "Management Request frame");
536 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data
*hapd
,
542 struct ieee80211_mgmt
*mgmt
;
545 if (hwaddr_aton(cmd
, addr
))
551 url_len
= os_strlen(url
);
555 os_memset(buf
, 0, sizeof(buf
));
556 mgmt
= (struct ieee80211_mgmt
*) buf
;
557 mgmt
->frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
558 WLAN_FC_STYPE_ACTION
);
559 os_memcpy(mgmt
->da
, addr
, ETH_ALEN
);
560 os_memcpy(mgmt
->sa
, hapd
->own_addr
, ETH_ALEN
);
561 os_memcpy(mgmt
->bssid
, hapd
->own_addr
, ETH_ALEN
);
562 mgmt
->u
.action
.category
= WLAN_ACTION_WNM
;
563 mgmt
->u
.action
.u
.bss_tm_req
.action
= WNM_BSS_TRANS_MGMT_REQ
;
564 mgmt
->u
.action
.u
.bss_tm_req
.dialog_token
= 1;
565 mgmt
->u
.action
.u
.bss_tm_req
.req_mode
=
566 WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT
;
567 mgmt
->u
.action
.u
.bss_tm_req
.disassoc_timer
= host_to_le16(0);
568 mgmt
->u
.action
.u
.bss_tm_req
.validity_interval
= 0;
570 pos
= mgmt
->u
.action
.u
.bss_tm_req
.variable
;
572 /* Session Information URL */
574 os_memcpy(pos
, url
, url_len
);
577 if (hostapd_drv_send_mlme(hapd
, buf
, pos
- buf
, 0) < 0) {
578 wpa_printf(MSG_DEBUG
, "Failed to send BSS Transition "
579 "Management Request frame");
586 #endif /* CONFIG_WNM */
589 static int hostapd_ctrl_iface_get_config(struct hostapd_data
*hapd
,
590 char *buf
, size_t buflen
)
598 ret
= os_snprintf(pos
, end
- pos
, "bssid=" MACSTR
"\n"
600 MAC2STR(hapd
->own_addr
),
601 wpa_ssid_txt(hapd
->conf
->ssid
.ssid
,
602 hapd
->conf
->ssid
.ssid_len
));
603 if (ret
< 0 || ret
>= end
- pos
)
608 ret
= os_snprintf(pos
, end
- pos
, "wps_state=%s\n",
609 hapd
->conf
->wps_state
== 0 ? "disabled" :
610 (hapd
->conf
->wps_state
== 1 ? "not configured" :
612 if (ret
< 0 || ret
>= end
- pos
)
616 if (hapd
->conf
->wps_state
&& hapd
->conf
->wpa
&&
617 hapd
->conf
->ssid
.wpa_passphrase
) {
618 ret
= os_snprintf(pos
, end
- pos
, "passphrase=%s\n",
619 hapd
->conf
->ssid
.wpa_passphrase
);
620 if (ret
< 0 || ret
>= end
- pos
)
625 if (hapd
->conf
->wps_state
&& hapd
->conf
->wpa
&&
626 hapd
->conf
->ssid
.wpa_psk
&&
627 hapd
->conf
->ssid
.wpa_psk
->group
) {
628 char hex
[PMK_LEN
* 2 + 1];
629 wpa_snprintf_hex(hex
, sizeof(hex
),
630 hapd
->conf
->ssid
.wpa_psk
->psk
, PMK_LEN
);
631 ret
= os_snprintf(pos
, end
- pos
, "psk=%s\n", hex
);
632 if (ret
< 0 || ret
>= end
- pos
)
636 #endif /* CONFIG_WPS */
638 if (hapd
->conf
->wpa
&& hapd
->conf
->wpa_key_mgmt
) {
639 ret
= os_snprintf(pos
, end
- pos
, "key_mgmt=");
640 if (ret
< 0 || ret
>= end
- pos
)
644 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_PSK
) {
645 ret
= os_snprintf(pos
, end
- pos
, "WPA-PSK ");
646 if (ret
< 0 || ret
>= end
- pos
)
650 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_IEEE8021X
) {
651 ret
= os_snprintf(pos
, end
- pos
, "WPA-EAP ");
652 if (ret
< 0 || ret
>= end
- pos
)
656 #ifdef CONFIG_IEEE80211R
657 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_FT_PSK
) {
658 ret
= os_snprintf(pos
, end
- pos
, "FT-PSK ");
659 if (ret
< 0 || ret
>= end
- pos
)
663 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_FT_IEEE8021X
) {
664 ret
= os_snprintf(pos
, end
- pos
, "FT-EAP ");
665 if (ret
< 0 || ret
>= end
- pos
)
669 #endif /* CONFIG_IEEE80211R */
670 #ifdef CONFIG_IEEE80211W
671 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_PSK_SHA256
) {
672 ret
= os_snprintf(pos
, end
- pos
, "WPA-PSK-SHA256 ");
673 if (ret
< 0 || ret
>= end
- pos
)
677 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_IEEE8021X_SHA256
) {
678 ret
= os_snprintf(pos
, end
- pos
, "WPA-EAP-SHA256 ");
679 if (ret
< 0 || ret
>= end
- pos
)
683 #endif /* CONFIG_IEEE80211W */
685 ret
= os_snprintf(pos
, end
- pos
, "\n");
686 if (ret
< 0 || ret
>= end
- pos
)
691 if (hapd
->conf
->wpa
) {
692 ret
= os_snprintf(pos
, end
- pos
, "group_cipher=%s\n",
693 wpa_cipher_txt(hapd
->conf
->wpa_group
));
694 if (ret
< 0 || ret
>= end
- pos
)
699 if ((hapd
->conf
->wpa
& WPA_PROTO_RSN
) && hapd
->conf
->rsn_pairwise
) {
700 ret
= os_snprintf(pos
, end
- pos
, "rsn_pairwise_cipher=");
701 if (ret
< 0 || ret
>= end
- pos
)
705 ret
= wpa_write_ciphers(pos
, end
, hapd
->conf
->rsn_pairwise
,
711 ret
= os_snprintf(pos
, end
- pos
, "\n");
712 if (ret
< 0 || ret
>= end
- pos
)
717 if ((hapd
->conf
->wpa
& WPA_PROTO_WPA
) && hapd
->conf
->wpa_pairwise
) {
718 ret
= os_snprintf(pos
, end
- pos
, "wpa_pairwise_cipher=");
719 if (ret
< 0 || ret
>= end
- pos
)
723 ret
= wpa_write_ciphers(pos
, end
, hapd
->conf
->rsn_pairwise
,
729 ret
= os_snprintf(pos
, end
- pos
, "\n");
730 if (ret
< 0 || ret
>= end
- pos
)
739 static int hostapd_ctrl_iface_set(struct hostapd_data
*hapd
, char *cmd
)
744 value
= os_strchr(cmd
, ' ');
749 wpa_printf(MSG_DEBUG
, "CTRL_IFACE SET '%s'='%s'", cmd
, value
);
751 #ifdef CONFIG_WPS_TESTING
752 } else if (os_strcasecmp(cmd
, "wps_version_number") == 0) {
754 val
= strtol(value
, NULL
, 0);
755 if (val
< 0 || val
> 0xff) {
757 wpa_printf(MSG_DEBUG
, "WPS: Invalid "
758 "wps_version_number %ld", val
);
760 wps_version_number
= val
;
761 wpa_printf(MSG_DEBUG
, "WPS: Testing - force WPS "
763 (wps_version_number
& 0xf0) >> 4,
764 wps_version_number
& 0x0f);
765 hostapd_wps_update_ie(hapd
);
767 } else if (os_strcasecmp(cmd
, "wps_testing_dummy_cred") == 0) {
768 wps_testing_dummy_cred
= atoi(value
);
769 wpa_printf(MSG_DEBUG
, "WPS: Testing - dummy_cred=%d",
770 wps_testing_dummy_cred
);
771 #endif /* CONFIG_WPS_TESTING */
772 #ifdef CONFIG_INTERWORKING
773 } else if (os_strcasecmp(cmd
, "gas_frag_limit") == 0) {
774 int val
= atoi(value
);
778 hapd
->gas_frag_limit
= val
;
779 #endif /* CONFIG_INTERWORKING */
781 ret
= hostapd_set_iface(hapd
->iconf
, hapd
->conf
, cmd
, value
);
788 static int hostapd_ctrl_iface_get(struct hostapd_data
*hapd
, char *cmd
,
789 char *buf
, size_t buflen
)
793 wpa_printf(MSG_DEBUG
, "CTRL_IFACE GET '%s'", cmd
);
795 if (os_strcmp(cmd
, "version") == 0) {
796 res
= os_snprintf(buf
, buflen
, "%s", VERSION_STR
);
797 if (res
< 0 || (unsigned int) res
>= buflen
)
806 static int hostapd_ctrl_iface_enable(struct hostapd_iface
*iface
)
808 if (hostapd_enable_iface(iface
) < 0) {
809 wpa_printf(MSG_ERROR
, "Enabling of interface failed");
816 static int hostapd_ctrl_iface_reload(struct hostapd_iface
*iface
)
818 if (hostapd_reload_iface(iface
) < 0) {
819 wpa_printf(MSG_ERROR
, "Reloading of interface failed");
826 static int hostapd_ctrl_iface_disable(struct hostapd_iface
*iface
)
828 if (hostapd_disable_iface(iface
) < 0) {
829 wpa_printf(MSG_ERROR
, "Disabling of interface failed");
836 static void hostapd_ctrl_iface_receive(int sock
, void *eloop_ctx
,
839 struct hostapd_data
*hapd
= eloop_ctx
;
842 struct sockaddr_un from
;
843 socklen_t fromlen
= sizeof(from
);
845 const int reply_size
= 4096;
847 int level
= MSG_DEBUG
;
849 res
= recvfrom(sock
, buf
, sizeof(buf
) - 1, 0,
850 (struct sockaddr
*) &from
, &fromlen
);
852 perror("recvfrom(ctrl_iface)");
856 if (os_strcmp(buf
, "PING") == 0)
857 level
= MSG_EXCESSIVE
;
858 wpa_hexdump_ascii(level
, "RX ctrl_iface", (u8
*) buf
, res
);
860 reply
= os_malloc(reply_size
);
862 sendto(sock
, "FAIL\n", 5, 0, (struct sockaddr
*) &from
,
867 os_memcpy(reply
, "OK\n", 3);
870 if (os_strcmp(buf
, "PING") == 0) {
871 os_memcpy(reply
, "PONG\n", 5);
873 } else if (os_strncmp(buf
, "RELOG", 5) == 0) {
874 if (wpa_debug_reopen_file() < 0)
876 } else if (os_strcmp(buf
, "MIB") == 0) {
877 reply_len
= ieee802_11_get_mib(hapd
, reply
, reply_size
);
878 if (reply_len
>= 0) {
879 res
= wpa_get_mib(hapd
->wpa_auth
, reply
+ reply_len
,
880 reply_size
- reply_len
);
886 if (reply_len
>= 0) {
887 res
= ieee802_1x_get_mib(hapd
, reply
+ reply_len
,
888 reply_size
- reply_len
);
894 #ifndef CONFIG_NO_RADIUS
895 if (reply_len
>= 0) {
896 res
= radius_client_get_mib(hapd
->radius
,
898 reply_size
- reply_len
);
904 #endif /* CONFIG_NO_RADIUS */
905 } else if (os_strcmp(buf
, "STA-FIRST") == 0) {
906 reply_len
= hostapd_ctrl_iface_sta_first(hapd
, reply
,
908 } else if (os_strncmp(buf
, "STA ", 4) == 0) {
909 reply_len
= hostapd_ctrl_iface_sta(hapd
, buf
+ 4, reply
,
911 } else if (os_strncmp(buf
, "STA-NEXT ", 9) == 0) {
912 reply_len
= hostapd_ctrl_iface_sta_next(hapd
, buf
+ 9, reply
,
914 } else if (os_strcmp(buf
, "ATTACH") == 0) {
915 if (hostapd_ctrl_iface_attach(hapd
, &from
, fromlen
))
917 } else if (os_strcmp(buf
, "DETACH") == 0) {
918 if (hostapd_ctrl_iface_detach(hapd
, &from
, fromlen
))
920 } else if (os_strncmp(buf
, "LEVEL ", 6) == 0) {
921 if (hostapd_ctrl_iface_level(hapd
, &from
, fromlen
,
924 } else if (os_strncmp(buf
, "NEW_STA ", 8) == 0) {
925 if (hostapd_ctrl_iface_new_sta(hapd
, buf
+ 8))
927 } else if (os_strncmp(buf
, "DEAUTHENTICATE ", 15) == 0) {
928 if (hostapd_ctrl_iface_deauthenticate(hapd
, buf
+ 15))
930 } else if (os_strncmp(buf
, "DISASSOCIATE ", 13) == 0) {
931 if (hostapd_ctrl_iface_disassociate(hapd
, buf
+ 13))
933 #ifdef CONFIG_IEEE80211W
935 } else if (os_strncmp(buf
, "SA_QUERY ", 9) == 0) {
936 if (hostapd_ctrl_iface_sa_query(hapd
, buf
+ 9))
938 #endif /* NEED_AP_MLME */
939 #endif /* CONFIG_IEEE80211W */
941 } else if (os_strncmp(buf
, "WPS_PIN ", 8) == 0) {
942 if (hostapd_ctrl_iface_wps_pin(hapd
, buf
+ 8))
944 } else if (os_strncmp(buf
, "WPS_CHECK_PIN ", 14) == 0) {
945 reply_len
= hostapd_ctrl_iface_wps_check_pin(
946 hapd
, buf
+ 14, reply
, reply_size
);
947 } else if (os_strcmp(buf
, "WPS_PBC") == 0) {
948 if (hostapd_wps_button_pushed(hapd
, NULL
))
950 } else if (os_strcmp(buf
, "WPS_CANCEL") == 0) {
951 if (hostapd_wps_cancel(hapd
))
953 } else if (os_strncmp(buf
, "WPS_AP_PIN ", 11) == 0) {
954 reply_len
= hostapd_ctrl_iface_wps_ap_pin(hapd
, buf
+ 11,
956 } else if (os_strncmp(buf
, "WPS_CONFIG ", 11) == 0) {
957 if (hostapd_ctrl_iface_wps_config(hapd
, buf
+ 11) < 0)
959 #ifdef CONFIG_WPS_NFC
960 } else if (os_strncmp(buf
, "WPS_NFC_TAG_READ ", 17) == 0) {
961 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd
, buf
+ 17))
963 } else if (os_strncmp(buf
, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
964 reply_len
= hostapd_ctrl_iface_wps_nfc_config_token(
965 hapd
, buf
+ 21, reply
, reply_size
);
966 } else if (os_strncmp(buf
, "WPS_NFC_TOKEN ", 14) == 0) {
967 reply_len
= hostapd_ctrl_iface_wps_nfc_token(
968 hapd
, buf
+ 14, reply
, reply_size
);
969 } else if (os_strncmp(buf
, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
970 reply_len
= hostapd_ctrl_iface_nfc_get_handover_sel(
971 hapd
, buf
+ 21, reply
, reply_size
);
972 } else if (os_strncmp(buf
, "NFC_REPORT_HANDOVER ", 20) == 0) {
973 if (hostapd_ctrl_iface_nfc_report_handover(hapd
, buf
+ 20))
975 #endif /* CONFIG_WPS_NFC */
976 #endif /* CONFIG_WPS */
978 } else if (os_strncmp(buf
, "DISASSOC_IMMINENT ", 18) == 0) {
979 if (hostapd_ctrl_iface_disassoc_imminent(hapd
, buf
+ 18))
981 } else if (os_strncmp(buf
, "ESS_DISASSOC ", 13) == 0) {
982 if (hostapd_ctrl_iface_ess_disassoc(hapd
, buf
+ 13))
984 #endif /* CONFIG_WNM */
985 } else if (os_strcmp(buf
, "GET_CONFIG") == 0) {
986 reply_len
= hostapd_ctrl_iface_get_config(hapd
, reply
,
988 } else if (os_strncmp(buf
, "SET ", 4) == 0) {
989 if (hostapd_ctrl_iface_set(hapd
, buf
+ 4))
991 } else if (os_strncmp(buf
, "GET ", 4) == 0) {
992 reply_len
= hostapd_ctrl_iface_get(hapd
, buf
+ 4, reply
,
994 } else if (os_strncmp(buf
, "ENABLE", 6) == 0) {
995 if (hostapd_ctrl_iface_enable(hapd
->iface
))
997 } else if (os_strncmp(buf
, "RELOAD", 6) == 0) {
998 if (hostapd_ctrl_iface_reload(hapd
->iface
))
1000 } else if (os_strncmp(buf
, "DISABLE", 7) == 0) {
1001 if (hostapd_ctrl_iface_disable(hapd
->iface
))
1004 os_memcpy(reply
, "UNKNOWN COMMAND\n", 16);
1008 if (reply_len
< 0) {
1009 os_memcpy(reply
, "FAIL\n", 5);
1012 sendto(sock
, reply
, reply_len
, 0, (struct sockaddr
*) &from
, fromlen
);
1017 static char * hostapd_ctrl_iface_path(struct hostapd_data
*hapd
)
1022 if (hapd
->conf
->ctrl_interface
== NULL
)
1025 len
= os_strlen(hapd
->conf
->ctrl_interface
) +
1026 os_strlen(hapd
->conf
->iface
) + 2;
1027 buf
= os_malloc(len
);
1031 os_snprintf(buf
, len
, "%s/%s",
1032 hapd
->conf
->ctrl_interface
, hapd
->conf
->iface
);
1033 buf
[len
- 1] = '\0';
1038 static void hostapd_ctrl_iface_msg_cb(void *ctx
, int level
,
1039 const char *txt
, size_t len
)
1041 struct hostapd_data
*hapd
= ctx
;
1044 hostapd_ctrl_iface_send(hapd
, level
, txt
, len
);
1048 int hostapd_ctrl_iface_init(struct hostapd_data
*hapd
)
1050 struct sockaddr_un addr
;
1054 if (hapd
->ctrl_sock
> -1) {
1055 wpa_printf(MSG_DEBUG
, "ctrl_iface already exists!");
1059 if (hapd
->conf
->ctrl_interface
== NULL
)
1062 if (mkdir(hapd
->conf
->ctrl_interface
, S_IRWXU
| S_IRWXG
) < 0) {
1063 if (errno
== EEXIST
) {
1064 wpa_printf(MSG_DEBUG
, "Using existing control "
1065 "interface directory.");
1067 perror("mkdir[ctrl_interface]");
1072 if (hapd
->conf
->ctrl_interface_gid_set
&&
1073 chown(hapd
->conf
->ctrl_interface
, -1,
1074 hapd
->conf
->ctrl_interface_gid
) < 0) {
1075 perror("chown[ctrl_interface]");
1081 * Android is using umask 0077 which would leave the control interface
1082 * directory without group access. This breaks things since Wi-Fi
1083 * framework assumes that this directory can be accessed by other
1084 * applications in the wifi group. Fix this by adding group access even
1085 * if umask value would prevent this.
1087 if (chmod(hapd
->conf
->ctrl_interface
, S_IRWXU
| S_IRWXG
) < 0) {
1088 wpa_printf(MSG_ERROR
, "CTRL: Could not chmod directory: %s",
1090 /* Try to continue anyway */
1092 #endif /* ANDROID */
1094 if (os_strlen(hapd
->conf
->ctrl_interface
) + 1 +
1095 os_strlen(hapd
->conf
->iface
) >= sizeof(addr
.sun_path
))
1098 s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
1100 perror("socket(PF_UNIX)");
1104 os_memset(&addr
, 0, sizeof(addr
));
1106 addr
.sun_len
= sizeof(addr
);
1107 #endif /* __FreeBSD__ */
1108 addr
.sun_family
= AF_UNIX
;
1109 fname
= hostapd_ctrl_iface_path(hapd
);
1112 os_strlcpy(addr
.sun_path
, fname
, sizeof(addr
.sun_path
));
1113 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1114 wpa_printf(MSG_DEBUG
, "ctrl_iface bind(PF_UNIX) failed: %s",
1116 if (connect(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1117 wpa_printf(MSG_DEBUG
, "ctrl_iface exists, but does not"
1118 " allow connections - assuming it was left"
1119 "over from forced program termination");
1120 if (unlink(fname
) < 0) {
1121 perror("unlink[ctrl_iface]");
1122 wpa_printf(MSG_ERROR
, "Could not unlink "
1123 "existing ctrl_iface socket '%s'",
1127 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) <
1129 perror("hostapd-ctrl-iface: bind(PF_UNIX)");
1132 wpa_printf(MSG_DEBUG
, "Successfully replaced leftover "
1133 "ctrl_iface socket '%s'", fname
);
1135 wpa_printf(MSG_INFO
, "ctrl_iface exists and seems to "
1136 "be in use - cannot override it");
1137 wpa_printf(MSG_INFO
, "Delete '%s' manually if it is "
1138 "not used anymore", fname
);
1145 if (hapd
->conf
->ctrl_interface_gid_set
&&
1146 chown(fname
, -1, hapd
->conf
->ctrl_interface_gid
) < 0) {
1147 perror("chown[ctrl_interface/ifname]");
1151 if (chmod(fname
, S_IRWXU
| S_IRWXG
) < 0) {
1152 perror("chmod[ctrl_interface/ifname]");
1157 hapd
->ctrl_sock
= s
;
1158 eloop_register_read_sock(s
, hostapd_ctrl_iface_receive
, hapd
,
1160 hapd
->msg_ctx
= hapd
;
1161 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb
);
1176 void hostapd_ctrl_iface_deinit(struct hostapd_data
*hapd
)
1178 struct wpa_ctrl_dst
*dst
, *prev
;
1180 if (hapd
->ctrl_sock
> -1) {
1182 eloop_unregister_read_sock(hapd
->ctrl_sock
);
1183 close(hapd
->ctrl_sock
);
1184 hapd
->ctrl_sock
= -1;
1185 fname
= hostapd_ctrl_iface_path(hapd
);
1190 if (hapd
->conf
->ctrl_interface
&&
1191 rmdir(hapd
->conf
->ctrl_interface
) < 0) {
1192 if (errno
== ENOTEMPTY
) {
1193 wpa_printf(MSG_DEBUG
, "Control interface "
1194 "directory not empty - leaving it "
1197 perror("rmdir[ctrl_interface]");
1202 dst
= hapd
->ctrl_dst
;
1211 static int hostapd_ctrl_iface_add(struct hapd_interfaces
*interfaces
,
1214 if (hostapd_add_iface(interfaces
, buf
) < 0) {
1215 wpa_printf(MSG_ERROR
, "Adding interface %s failed", buf
);
1222 static int hostapd_ctrl_iface_remove(struct hapd_interfaces
*interfaces
,
1225 if (hostapd_remove_iface(interfaces
, buf
) < 0) {
1226 wpa_printf(MSG_ERROR
, "Removing interface %s failed", buf
);
1233 static void hostapd_global_ctrl_iface_receive(int sock
, void *eloop_ctx
,
1236 void *interfaces
= eloop_ctx
;
1239 struct sockaddr_un from
;
1240 socklen_t fromlen
= sizeof(from
);
1244 res
= recvfrom(sock
, buf
, sizeof(buf
) - 1, 0,
1245 (struct sockaddr
*) &from
, &fromlen
);
1247 perror("recvfrom(ctrl_iface)");
1252 os_memcpy(reply
, "OK\n", 3);
1255 if (os_strcmp(buf
, "PING") == 0) {
1256 os_memcpy(reply
, "PONG\n", 5);
1258 } else if (os_strncmp(buf
, "ADD ", 4) == 0) {
1259 if (hostapd_ctrl_iface_add(interfaces
, buf
+ 4) < 0)
1261 } else if (os_strncmp(buf
, "REMOVE ", 7) == 0) {
1262 if (hostapd_ctrl_iface_remove(interfaces
, buf
+ 7) < 0)
1265 wpa_printf(MSG_DEBUG
, "Unrecognized global ctrl_iface command "
1270 if (reply_len
< 0) {
1271 os_memcpy(reply
, "FAIL\n", 5);
1275 sendto(sock
, reply
, reply_len
, 0, (struct sockaddr
*) &from
, fromlen
);
1279 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces
*interface
)
1284 if (interface
->global_iface_path
== NULL
)
1287 len
= os_strlen(interface
->global_iface_path
) +
1288 os_strlen(interface
->global_iface_name
) + 2;
1289 buf
= os_malloc(len
);
1293 os_snprintf(buf
, len
, "%s/%s", interface
->global_iface_path
,
1294 interface
->global_iface_name
);
1295 buf
[len
- 1] = '\0';
1300 int hostapd_global_ctrl_iface_init(struct hapd_interfaces
*interface
)
1302 struct sockaddr_un addr
;
1306 if (interface
->global_iface_path
== NULL
) {
1307 wpa_printf(MSG_DEBUG
, "ctrl_iface not configured!");
1311 if (mkdir(interface
->global_iface_path
, S_IRWXU
| S_IRWXG
) < 0) {
1312 if (errno
== EEXIST
) {
1313 wpa_printf(MSG_DEBUG
, "Using existing control "
1314 "interface directory.");
1316 perror("mkdir[ctrl_interface]");
1321 if (os_strlen(interface
->global_iface_path
) + 1 +
1322 os_strlen(interface
->global_iface_name
) >= sizeof(addr
.sun_path
))
1325 s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
1327 perror("socket(PF_UNIX)");
1331 os_memset(&addr
, 0, sizeof(addr
));
1333 addr
.sun_len
= sizeof(addr
);
1334 #endif /* __FreeBSD__ */
1335 addr
.sun_family
= AF_UNIX
;
1336 fname
= hostapd_global_ctrl_iface_path(interface
);
1339 os_strlcpy(addr
.sun_path
, fname
, sizeof(addr
.sun_path
));
1340 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1341 wpa_printf(MSG_DEBUG
, "ctrl_iface bind(PF_UNIX) failed: %s",
1343 if (connect(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1344 wpa_printf(MSG_DEBUG
, "ctrl_iface exists, but does not"
1345 " allow connections - assuming it was left"
1346 "over from forced program termination");
1347 if (unlink(fname
) < 0) {
1348 perror("unlink[ctrl_iface]");
1349 wpa_printf(MSG_ERROR
, "Could not unlink "
1350 "existing ctrl_iface socket '%s'",
1354 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) <
1356 perror("bind(PF_UNIX)");
1359 wpa_printf(MSG_DEBUG
, "Successfully replaced leftover "
1360 "ctrl_iface socket '%s'", fname
);
1362 wpa_printf(MSG_INFO
, "ctrl_iface exists and seems to "
1363 "be in use - cannot override it");
1364 wpa_printf(MSG_INFO
, "Delete '%s' manually if it is "
1365 "not used anymore", fname
);
1372 if (chmod(fname
, S_IRWXU
| S_IRWXG
) < 0) {
1373 perror("chmod[ctrl_interface/ifname]");
1378 interface
->global_ctrl_sock
= s
;
1379 eloop_register_read_sock(s
, hostapd_global_ctrl_iface_receive
,
1395 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces
*interfaces
)
1399 if (interfaces
->global_ctrl_sock
> -1) {
1400 eloop_unregister_read_sock(interfaces
->global_ctrl_sock
);
1401 close(interfaces
->global_ctrl_sock
);
1402 interfaces
->global_ctrl_sock
= -1;
1403 fname
= hostapd_global_ctrl_iface_path(interfaces
);
1409 if (interfaces
->global_iface_path
&&
1410 rmdir(interfaces
->global_iface_path
) < 0) {
1411 if (errno
== ENOTEMPTY
) {
1412 wpa_printf(MSG_DEBUG
, "Control interface "
1413 "directory not empty - leaving it "
1416 perror("rmdir[ctrl_interface]");
1419 os_free(interfaces
->global_iface_path
);
1420 interfaces
->global_iface_path
= NULL
;
1425 static void hostapd_ctrl_iface_send(struct hostapd_data
*hapd
, int level
,
1426 const char *buf
, size_t len
)
1428 struct wpa_ctrl_dst
*dst
, *next
;
1434 dst
= hapd
->ctrl_dst
;
1435 if (hapd
->ctrl_sock
< 0 || dst
== NULL
)
1438 os_snprintf(levelstr
, sizeof(levelstr
), "<%d>", level
);
1439 io
[0].iov_base
= levelstr
;
1440 io
[0].iov_len
= os_strlen(levelstr
);
1441 io
[1].iov_base
= (char *) buf
;
1442 io
[1].iov_len
= len
;
1443 os_memset(&msg
, 0, sizeof(msg
));
1450 if (level
>= dst
->debug_level
) {
1451 wpa_hexdump(MSG_DEBUG
, "CTRL_IFACE monitor send",
1452 (u8
*) dst
->addr
.sun_path
, dst
->addrlen
-
1453 offsetof(struct sockaddr_un
, sun_path
));
1454 msg
.msg_name
= &dst
->addr
;
1455 msg
.msg_namelen
= dst
->addrlen
;
1456 if (sendmsg(hapd
->ctrl_sock
, &msg
, 0) < 0) {
1458 wpa_printf(MSG_INFO
, "CTRL_IFACE monitor[%d]: "
1460 idx
, errno
, strerror(errno
));
1462 if (dst
->errors
> 10 || _errno
== ENOENT
) {
1463 hostapd_ctrl_iface_detach(
1475 #endif /* CONFIG_NATIVE_WINDOWS */