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 */
439 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data
*hapd
,
445 struct ieee80211_mgmt
*mgmt
;
448 if (hwaddr_aton(cmd
, addr
))
454 url_len
= os_strlen(url
);
458 os_memset(buf
, 0, sizeof(buf
));
459 mgmt
= (struct ieee80211_mgmt
*) buf
;
460 mgmt
->frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
461 WLAN_FC_STYPE_ACTION
);
462 os_memcpy(mgmt
->da
, addr
, ETH_ALEN
);
463 os_memcpy(mgmt
->sa
, hapd
->own_addr
, ETH_ALEN
);
464 os_memcpy(mgmt
->bssid
, hapd
->own_addr
, ETH_ALEN
);
465 mgmt
->u
.action
.category
= WLAN_ACTION_WNM
;
466 mgmt
->u
.action
.u
.bss_tm_req
.action
= WNM_BSS_TRANS_MGMT_REQ
;
467 mgmt
->u
.action
.u
.bss_tm_req
.dialog_token
= 1;
468 mgmt
->u
.action
.u
.bss_tm_req
.req_mode
=
469 WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT
;
470 mgmt
->u
.action
.u
.bss_tm_req
.disassoc_timer
= host_to_le16(0);
471 mgmt
->u
.action
.u
.bss_tm_req
.validity_interval
= 0;
473 pos
= mgmt
->u
.action
.u
.bss_tm_req
.variable
;
475 /* Session Information URL */
477 os_memcpy(pos
, url
, url_len
);
480 if (hostapd_drv_send_mlme(hapd
, buf
, pos
- buf
, 0) < 0) {
481 wpa_printf(MSG_DEBUG
, "Failed to send BSS Transition "
482 "Management Request frame");
490 static int hostapd_ctrl_iface_get_config(struct hostapd_data
*hapd
,
491 char *buf
, size_t buflen
)
499 ret
= os_snprintf(pos
, end
- pos
, "bssid=" MACSTR
"\n"
501 MAC2STR(hapd
->own_addr
),
502 wpa_ssid_txt(hapd
->conf
->ssid
.ssid
,
503 hapd
->conf
->ssid
.ssid_len
));
504 if (ret
< 0 || ret
>= end
- pos
)
509 ret
= os_snprintf(pos
, end
- pos
, "wps_state=%s\n",
510 hapd
->conf
->wps_state
== 0 ? "disabled" :
511 (hapd
->conf
->wps_state
== 1 ? "not configured" :
513 if (ret
< 0 || ret
>= end
- pos
)
517 if (hapd
->conf
->wps_state
&& hapd
->conf
->wpa
&&
518 hapd
->conf
->ssid
.wpa_passphrase
) {
519 ret
= os_snprintf(pos
, end
- pos
, "passphrase=%s\n",
520 hapd
->conf
->ssid
.wpa_passphrase
);
521 if (ret
< 0 || ret
>= end
- pos
)
526 if (hapd
->conf
->wps_state
&& hapd
->conf
->wpa
&&
527 hapd
->conf
->ssid
.wpa_psk
&&
528 hapd
->conf
->ssid
.wpa_psk
->group
) {
529 char hex
[PMK_LEN
* 2 + 1];
530 wpa_snprintf_hex(hex
, sizeof(hex
),
531 hapd
->conf
->ssid
.wpa_psk
->psk
, PMK_LEN
);
532 ret
= os_snprintf(pos
, end
- pos
, "psk=%s\n", hex
);
533 if (ret
< 0 || ret
>= end
- pos
)
537 #endif /* CONFIG_WPS */
539 if (hapd
->conf
->wpa
&& hapd
->conf
->wpa_key_mgmt
) {
540 ret
= os_snprintf(pos
, end
- pos
, "key_mgmt=");
541 if (ret
< 0 || ret
>= end
- pos
)
545 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_PSK
) {
546 ret
= os_snprintf(pos
, end
- pos
, "WPA-PSK ");
547 if (ret
< 0 || ret
>= end
- pos
)
551 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_IEEE8021X
) {
552 ret
= os_snprintf(pos
, end
- pos
, "WPA-EAP ");
553 if (ret
< 0 || ret
>= end
- pos
)
557 #ifdef CONFIG_IEEE80211R
558 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_FT_PSK
) {
559 ret
= os_snprintf(pos
, end
- pos
, "FT-PSK ");
560 if (ret
< 0 || ret
>= end
- pos
)
564 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_FT_IEEE8021X
) {
565 ret
= os_snprintf(pos
, end
- pos
, "FT-EAP ");
566 if (ret
< 0 || ret
>= end
- pos
)
570 #endif /* CONFIG_IEEE80211R */
571 #ifdef CONFIG_IEEE80211W
572 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_PSK_SHA256
) {
573 ret
= os_snprintf(pos
, end
- pos
, "WPA-PSK-SHA256 ");
574 if (ret
< 0 || ret
>= end
- pos
)
578 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_IEEE8021X_SHA256
) {
579 ret
= os_snprintf(pos
, end
- pos
, "WPA-EAP-SHA256 ");
580 if (ret
< 0 || ret
>= end
- pos
)
584 #endif /* CONFIG_IEEE80211W */
586 ret
= os_snprintf(pos
, end
- pos
, "\n");
587 if (ret
< 0 || ret
>= end
- pos
)
592 if (hapd
->conf
->wpa
&& hapd
->conf
->wpa_group
== WPA_CIPHER_CCMP
) {
593 ret
= os_snprintf(pos
, end
- pos
, "group_cipher=CCMP\n");
594 if (ret
< 0 || ret
>= end
- pos
)
597 } else if (hapd
->conf
->wpa
&&
598 hapd
->conf
->wpa_group
== WPA_CIPHER_GCMP
) {
599 ret
= os_snprintf(pos
, end
- pos
, "group_cipher=GCMP\n");
600 if (ret
< 0 || ret
>= end
- pos
)
603 } else if (hapd
->conf
->wpa
&&
604 hapd
->conf
->wpa_group
== WPA_CIPHER_TKIP
) {
605 ret
= os_snprintf(pos
, end
- pos
, "group_cipher=TKIP\n");
606 if (ret
< 0 || ret
>= end
- pos
)
611 if ((hapd
->conf
->wpa
& WPA_PROTO_RSN
) && hapd
->conf
->rsn_pairwise
) {
612 ret
= os_snprintf(pos
, end
- pos
, "rsn_pairwise_cipher=");
613 if (ret
< 0 || ret
>= end
- pos
)
617 if (hapd
->conf
->rsn_pairwise
& WPA_CIPHER_CCMP
) {
618 ret
= os_snprintf(pos
, end
- pos
, "CCMP ");
619 if (ret
< 0 || ret
>= end
- pos
)
623 if (hapd
->conf
->rsn_pairwise
& WPA_CIPHER_GCMP
) {
624 ret
= os_snprintf(pos
, end
- pos
, "GCMP ");
625 if (ret
< 0 || ret
>= end
- pos
)
629 if (hapd
->conf
->rsn_pairwise
& WPA_CIPHER_TKIP
) {
630 ret
= os_snprintf(pos
, end
- pos
, "TKIP ");
631 if (ret
< 0 || ret
>= end
- pos
)
636 ret
= os_snprintf(pos
, end
- pos
, "\n");
637 if (ret
< 0 || ret
>= end
- pos
)
642 if ((hapd
->conf
->wpa
& WPA_PROTO_WPA
) && hapd
->conf
->wpa_pairwise
) {
643 ret
= os_snprintf(pos
, end
- pos
, "wpa_pairwise_cipher=");
644 if (ret
< 0 || ret
>= end
- pos
)
648 if (hapd
->conf
->wpa_pairwise
& WPA_CIPHER_CCMP
) {
649 ret
= os_snprintf(pos
, end
- pos
, "CCMP ");
650 if (ret
< 0 || ret
>= end
- pos
)
654 if (hapd
->conf
->wpa_pairwise
& WPA_CIPHER_GCMP
) {
655 ret
= os_snprintf(pos
, end
- pos
, "GCMP ");
656 if (ret
< 0 || ret
>= end
- pos
)
660 if (hapd
->conf
->wpa_pairwise
& WPA_CIPHER_TKIP
) {
661 ret
= os_snprintf(pos
, end
- pos
, "TKIP ");
662 if (ret
< 0 || ret
>= end
- pos
)
667 ret
= os_snprintf(pos
, end
- pos
, "\n");
668 if (ret
< 0 || ret
>= end
- pos
)
677 static int hostapd_ctrl_iface_set(struct hostapd_data
*hapd
, char *cmd
)
682 value
= os_strchr(cmd
, ' ');
687 wpa_printf(MSG_DEBUG
, "CTRL_IFACE SET '%s'='%s'", cmd
, value
);
689 #ifdef CONFIG_WPS_TESTING
690 } else if (os_strcasecmp(cmd
, "wps_version_number") == 0) {
692 val
= strtol(value
, NULL
, 0);
693 if (val
< 0 || val
> 0xff) {
695 wpa_printf(MSG_DEBUG
, "WPS: Invalid "
696 "wps_version_number %ld", val
);
698 wps_version_number
= val
;
699 wpa_printf(MSG_DEBUG
, "WPS: Testing - force WPS "
701 (wps_version_number
& 0xf0) >> 4,
702 wps_version_number
& 0x0f);
703 hostapd_wps_update_ie(hapd
);
705 } else if (os_strcasecmp(cmd
, "wps_testing_dummy_cred") == 0) {
706 wps_testing_dummy_cred
= atoi(value
);
707 wpa_printf(MSG_DEBUG
, "WPS: Testing - dummy_cred=%d",
708 wps_testing_dummy_cred
);
709 #endif /* CONFIG_WPS_TESTING */
710 #ifdef CONFIG_INTERWORKING
711 } else if (os_strcasecmp(cmd
, "gas_frag_limit") == 0) {
712 int val
= atoi(value
);
716 hapd
->gas_frag_limit
= val
;
717 #endif /* CONFIG_INTERWORKING */
719 ret
= hostapd_set_iface(hapd
->iconf
, hapd
->conf
, cmd
, value
);
726 static int hostapd_ctrl_iface_get(struct hostapd_data
*hapd
, char *cmd
,
727 char *buf
, size_t buflen
)
731 wpa_printf(MSG_DEBUG
, "CTRL_IFACE GET '%s'", cmd
);
733 if (os_strcmp(cmd
, "version") == 0) {
734 res
= os_snprintf(buf
, buflen
, "%s", VERSION_STR
);
735 if (res
< 0 || (unsigned int) res
>= buflen
)
744 static int hostapd_ctrl_iface_enable(struct hostapd_iface
*iface
)
746 if (hostapd_enable_iface(iface
) < 0) {
747 wpa_printf(MSG_ERROR
, "Enabling of interface failed");
754 static int hostapd_ctrl_iface_reload(struct hostapd_iface
*iface
)
756 if (hostapd_reload_iface(iface
) < 0) {
757 wpa_printf(MSG_ERROR
, "Reloading of interface failed");
764 static int hostapd_ctrl_iface_disable(struct hostapd_iface
*iface
)
766 if (hostapd_disable_iface(iface
) < 0) {
767 wpa_printf(MSG_ERROR
, "Disabling of interface failed");
774 static void hostapd_ctrl_iface_receive(int sock
, void *eloop_ctx
,
777 struct hostapd_data
*hapd
= eloop_ctx
;
780 struct sockaddr_un from
;
781 socklen_t fromlen
= sizeof(from
);
783 const int reply_size
= 4096;
785 int level
= MSG_DEBUG
;
787 res
= recvfrom(sock
, buf
, sizeof(buf
) - 1, 0,
788 (struct sockaddr
*) &from
, &fromlen
);
790 perror("recvfrom(ctrl_iface)");
794 if (os_strcmp(buf
, "PING") == 0)
795 level
= MSG_EXCESSIVE
;
796 wpa_hexdump_ascii(level
, "RX ctrl_iface", (u8
*) buf
, res
);
798 reply
= os_malloc(reply_size
);
800 sendto(sock
, "FAIL\n", 5, 0, (struct sockaddr
*) &from
,
805 os_memcpy(reply
, "OK\n", 3);
808 if (os_strcmp(buf
, "PING") == 0) {
809 os_memcpy(reply
, "PONG\n", 5);
811 } else if (os_strncmp(buf
, "RELOG", 5) == 0) {
812 if (wpa_debug_reopen_file() < 0)
814 } else if (os_strcmp(buf
, "MIB") == 0) {
815 reply_len
= ieee802_11_get_mib(hapd
, reply
, reply_size
);
816 if (reply_len
>= 0) {
817 res
= wpa_get_mib(hapd
->wpa_auth
, reply
+ reply_len
,
818 reply_size
- reply_len
);
824 if (reply_len
>= 0) {
825 res
= ieee802_1x_get_mib(hapd
, reply
+ reply_len
,
826 reply_size
- reply_len
);
832 #ifndef CONFIG_NO_RADIUS
833 if (reply_len
>= 0) {
834 res
= radius_client_get_mib(hapd
->radius
,
836 reply_size
- reply_len
);
842 #endif /* CONFIG_NO_RADIUS */
843 } else if (os_strcmp(buf
, "STA-FIRST") == 0) {
844 reply_len
= hostapd_ctrl_iface_sta_first(hapd
, reply
,
846 } else if (os_strncmp(buf
, "STA ", 4) == 0) {
847 reply_len
= hostapd_ctrl_iface_sta(hapd
, buf
+ 4, reply
,
849 } else if (os_strncmp(buf
, "STA-NEXT ", 9) == 0) {
850 reply_len
= hostapd_ctrl_iface_sta_next(hapd
, buf
+ 9, reply
,
852 } else if (os_strcmp(buf
, "ATTACH") == 0) {
853 if (hostapd_ctrl_iface_attach(hapd
, &from
, fromlen
))
855 } else if (os_strcmp(buf
, "DETACH") == 0) {
856 if (hostapd_ctrl_iface_detach(hapd
, &from
, fromlen
))
858 } else if (os_strncmp(buf
, "LEVEL ", 6) == 0) {
859 if (hostapd_ctrl_iface_level(hapd
, &from
, fromlen
,
862 } else if (os_strncmp(buf
, "NEW_STA ", 8) == 0) {
863 if (hostapd_ctrl_iface_new_sta(hapd
, buf
+ 8))
865 } else if (os_strncmp(buf
, "DEAUTHENTICATE ", 15) == 0) {
866 if (hostapd_ctrl_iface_deauthenticate(hapd
, buf
+ 15))
868 } else if (os_strncmp(buf
, "DISASSOCIATE ", 13) == 0) {
869 if (hostapd_ctrl_iface_disassociate(hapd
, buf
+ 13))
871 #ifdef CONFIG_IEEE80211W
873 } else if (os_strncmp(buf
, "SA_QUERY ", 9) == 0) {
874 if (hostapd_ctrl_iface_sa_query(hapd
, buf
+ 9))
876 #endif /* NEED_AP_MLME */
877 #endif /* CONFIG_IEEE80211W */
879 } else if (os_strncmp(buf
, "WPS_PIN ", 8) == 0) {
880 if (hostapd_ctrl_iface_wps_pin(hapd
, buf
+ 8))
882 } else if (os_strncmp(buf
, "WPS_CHECK_PIN ", 14) == 0) {
883 reply_len
= hostapd_ctrl_iface_wps_check_pin(
884 hapd
, buf
+ 14, reply
, reply_size
);
885 } else if (os_strcmp(buf
, "WPS_PBC") == 0) {
886 if (hostapd_wps_button_pushed(hapd
, NULL
))
888 } else if (os_strcmp(buf
, "WPS_CANCEL") == 0) {
889 if (hostapd_wps_cancel(hapd
))
891 } else if (os_strncmp(buf
, "WPS_AP_PIN ", 11) == 0) {
892 reply_len
= hostapd_ctrl_iface_wps_ap_pin(hapd
, buf
+ 11,
894 } else if (os_strncmp(buf
, "WPS_CONFIG ", 11) == 0) {
895 if (hostapd_ctrl_iface_wps_config(hapd
, buf
+ 11) < 0)
897 #ifdef CONFIG_WPS_NFC
898 } else if (os_strncmp(buf
, "WPS_NFC_TAG_READ ", 17) == 0) {
899 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd
, buf
+ 17))
901 } else if (os_strncmp(buf
, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
902 reply_len
= hostapd_ctrl_iface_wps_nfc_config_token(
903 hapd
, buf
+ 21, reply
, reply_size
);
904 } else if (os_strncmp(buf
, "WPS_NFC_TOKEN ", 14) == 0) {
905 reply_len
= hostapd_ctrl_iface_wps_nfc_token(
906 hapd
, buf
+ 14, reply
, reply_size
);
907 #endif /* CONFIG_WPS_NFC */
908 #endif /* CONFIG_WPS */
909 } else if (os_strncmp(buf
, "ESS_DISASSOC ", 13) == 0) {
910 if (hostapd_ctrl_iface_ess_disassoc(hapd
, buf
+ 13))
912 } else if (os_strcmp(buf
, "GET_CONFIG") == 0) {
913 reply_len
= hostapd_ctrl_iface_get_config(hapd
, reply
,
915 } else if (os_strncmp(buf
, "SET ", 4) == 0) {
916 if (hostapd_ctrl_iface_set(hapd
, buf
+ 4))
918 } else if (os_strncmp(buf
, "GET ", 4) == 0) {
919 reply_len
= hostapd_ctrl_iface_get(hapd
, buf
+ 4, reply
,
921 } else if (os_strncmp(buf
, "ENABLE", 6) == 0) {
922 if (hostapd_ctrl_iface_enable(hapd
->iface
))
924 } else if (os_strncmp(buf
, "RELOAD", 6) == 0) {
925 if (hostapd_ctrl_iface_reload(hapd
->iface
))
927 } else if (os_strncmp(buf
, "DISABLE", 7) == 0) {
928 if (hostapd_ctrl_iface_disable(hapd
->iface
))
931 os_memcpy(reply
, "UNKNOWN COMMAND\n", 16);
936 os_memcpy(reply
, "FAIL\n", 5);
939 sendto(sock
, reply
, reply_len
, 0, (struct sockaddr
*) &from
, fromlen
);
944 static char * hostapd_ctrl_iface_path(struct hostapd_data
*hapd
)
949 if (hapd
->conf
->ctrl_interface
== NULL
)
952 len
= os_strlen(hapd
->conf
->ctrl_interface
) +
953 os_strlen(hapd
->conf
->iface
) + 2;
954 buf
= os_malloc(len
);
958 os_snprintf(buf
, len
, "%s/%s",
959 hapd
->conf
->ctrl_interface
, hapd
->conf
->iface
);
965 static void hostapd_ctrl_iface_msg_cb(void *ctx
, int level
,
966 const char *txt
, size_t len
)
968 struct hostapd_data
*hapd
= ctx
;
971 hostapd_ctrl_iface_send(hapd
, level
, txt
, len
);
975 int hostapd_ctrl_iface_init(struct hostapd_data
*hapd
)
977 struct sockaddr_un addr
;
981 if (hapd
->ctrl_sock
> -1) {
982 wpa_printf(MSG_DEBUG
, "ctrl_iface already exists!");
986 if (hapd
->conf
->ctrl_interface
== NULL
)
989 if (mkdir(hapd
->conf
->ctrl_interface
, S_IRWXU
| S_IRWXG
) < 0) {
990 if (errno
== EEXIST
) {
991 wpa_printf(MSG_DEBUG
, "Using existing control "
992 "interface directory.");
994 perror("mkdir[ctrl_interface]");
999 if (hapd
->conf
->ctrl_interface_gid_set
&&
1000 chown(hapd
->conf
->ctrl_interface
, -1,
1001 hapd
->conf
->ctrl_interface_gid
) < 0) {
1002 perror("chown[ctrl_interface]");
1008 * Android is using umask 0077 which would leave the control interface
1009 * directory without group access. This breaks things since Wi-Fi
1010 * framework assumes that this directory can be accessed by other
1011 * applications in the wifi group. Fix this by adding group access even
1012 * if umask value would prevent this.
1014 if (chmod(hapd
->conf
->ctrl_interface
, S_IRWXU
| S_IRWXG
) < 0) {
1015 wpa_printf(MSG_ERROR
, "CTRL: Could not chmod directory: %s",
1017 /* Try to continue anyway */
1019 #endif /* ANDROID */
1021 if (os_strlen(hapd
->conf
->ctrl_interface
) + 1 +
1022 os_strlen(hapd
->conf
->iface
) >= sizeof(addr
.sun_path
))
1025 s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
1027 perror("socket(PF_UNIX)");
1031 os_memset(&addr
, 0, sizeof(addr
));
1033 addr
.sun_len
= sizeof(addr
);
1034 #endif /* __FreeBSD__ */
1035 addr
.sun_family
= AF_UNIX
;
1036 fname
= hostapd_ctrl_iface_path(hapd
);
1039 os_strlcpy(addr
.sun_path
, fname
, sizeof(addr
.sun_path
));
1040 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1041 wpa_printf(MSG_DEBUG
, "ctrl_iface bind(PF_UNIX) failed: %s",
1043 if (connect(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1044 wpa_printf(MSG_DEBUG
, "ctrl_iface exists, but does not"
1045 " allow connections - assuming it was left"
1046 "over from forced program termination");
1047 if (unlink(fname
) < 0) {
1048 perror("unlink[ctrl_iface]");
1049 wpa_printf(MSG_ERROR
, "Could not unlink "
1050 "existing ctrl_iface socket '%s'",
1054 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) <
1056 perror("hostapd-ctrl-iface: bind(PF_UNIX)");
1059 wpa_printf(MSG_DEBUG
, "Successfully replaced leftover "
1060 "ctrl_iface socket '%s'", fname
);
1062 wpa_printf(MSG_INFO
, "ctrl_iface exists and seems to "
1063 "be in use - cannot override it");
1064 wpa_printf(MSG_INFO
, "Delete '%s' manually if it is "
1065 "not used anymore", fname
);
1072 if (hapd
->conf
->ctrl_interface_gid_set
&&
1073 chown(fname
, -1, hapd
->conf
->ctrl_interface_gid
) < 0) {
1074 perror("chown[ctrl_interface/ifname]");
1078 if (chmod(fname
, S_IRWXU
| S_IRWXG
) < 0) {
1079 perror("chmod[ctrl_interface/ifname]");
1084 hapd
->ctrl_sock
= s
;
1085 eloop_register_read_sock(s
, hostapd_ctrl_iface_receive
, hapd
,
1087 hapd
->msg_ctx
= hapd
;
1088 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb
);
1103 void hostapd_ctrl_iface_deinit(struct hostapd_data
*hapd
)
1105 struct wpa_ctrl_dst
*dst
, *prev
;
1107 if (hapd
->ctrl_sock
> -1) {
1109 eloop_unregister_read_sock(hapd
->ctrl_sock
);
1110 close(hapd
->ctrl_sock
);
1111 hapd
->ctrl_sock
= -1;
1112 fname
= hostapd_ctrl_iface_path(hapd
);
1117 if (hapd
->conf
->ctrl_interface
&&
1118 rmdir(hapd
->conf
->ctrl_interface
) < 0) {
1119 if (errno
== ENOTEMPTY
) {
1120 wpa_printf(MSG_DEBUG
, "Control interface "
1121 "directory not empty - leaving it "
1124 perror("rmdir[ctrl_interface]");
1129 dst
= hapd
->ctrl_dst
;
1138 static int hostapd_ctrl_iface_add(struct hapd_interfaces
*interfaces
,
1141 if (hostapd_add_iface(interfaces
, buf
) < 0) {
1142 wpa_printf(MSG_ERROR
, "Adding interface %s failed", buf
);
1149 static int hostapd_ctrl_iface_remove(struct hapd_interfaces
*interfaces
,
1152 if (hostapd_remove_iface(interfaces
, buf
) < 0) {
1153 wpa_printf(MSG_ERROR
, "Removing interface %s failed", buf
);
1160 static void hostapd_global_ctrl_iface_receive(int sock
, void *eloop_ctx
,
1163 void *interfaces
= eloop_ctx
;
1166 struct sockaddr_un from
;
1167 socklen_t fromlen
= sizeof(from
);
1171 res
= recvfrom(sock
, buf
, sizeof(buf
) - 1, 0,
1172 (struct sockaddr
*) &from
, &fromlen
);
1174 perror("recvfrom(ctrl_iface)");
1179 os_memcpy(reply
, "OK\n", 3);
1182 if (os_strcmp(buf
, "PING") == 0) {
1183 os_memcpy(reply
, "PONG\n", 5);
1185 } else if (os_strncmp(buf
, "ADD ", 4) == 0) {
1186 if (hostapd_ctrl_iface_add(interfaces
, buf
+ 4) < 0)
1188 } else if (os_strncmp(buf
, "REMOVE ", 7) == 0) {
1189 if (hostapd_ctrl_iface_remove(interfaces
, buf
+ 7) < 0)
1192 wpa_printf(MSG_DEBUG
, "Unrecognized global ctrl_iface command "
1197 if (reply_len
< 0) {
1198 os_memcpy(reply
, "FAIL\n", 5);
1202 sendto(sock
, reply
, reply_len
, 0, (struct sockaddr
*) &from
, fromlen
);
1206 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces
*interface
)
1211 if (interface
->global_iface_path
== NULL
)
1214 len
= os_strlen(interface
->global_iface_path
) +
1215 os_strlen(interface
->global_iface_name
) + 2;
1216 buf
= os_malloc(len
);
1220 os_snprintf(buf
, len
, "%s/%s", interface
->global_iface_path
,
1221 interface
->global_iface_name
);
1222 buf
[len
- 1] = '\0';
1227 int hostapd_global_ctrl_iface_init(struct hapd_interfaces
*interface
)
1229 struct sockaddr_un addr
;
1233 if (interface
->global_iface_path
== NULL
) {
1234 wpa_printf(MSG_DEBUG
, "ctrl_iface not configured!");
1238 if (mkdir(interface
->global_iface_path
, S_IRWXU
| S_IRWXG
) < 0) {
1239 if (errno
== EEXIST
) {
1240 wpa_printf(MSG_DEBUG
, "Using existing control "
1241 "interface directory.");
1243 perror("mkdir[ctrl_interface]");
1248 if (os_strlen(interface
->global_iface_path
) + 1 +
1249 os_strlen(interface
->global_iface_name
) >= sizeof(addr
.sun_path
))
1252 s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
1254 perror("socket(PF_UNIX)");
1258 os_memset(&addr
, 0, sizeof(addr
));
1260 addr
.sun_len
= sizeof(addr
);
1261 #endif /* __FreeBSD__ */
1262 addr
.sun_family
= AF_UNIX
;
1263 fname
= hostapd_global_ctrl_iface_path(interface
);
1266 os_strlcpy(addr
.sun_path
, fname
, sizeof(addr
.sun_path
));
1267 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1268 wpa_printf(MSG_DEBUG
, "ctrl_iface bind(PF_UNIX) failed: %s",
1270 if (connect(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1271 wpa_printf(MSG_DEBUG
, "ctrl_iface exists, but does not"
1272 " allow connections - assuming it was left"
1273 "over from forced program termination");
1274 if (unlink(fname
) < 0) {
1275 perror("unlink[ctrl_iface]");
1276 wpa_printf(MSG_ERROR
, "Could not unlink "
1277 "existing ctrl_iface socket '%s'",
1281 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) <
1283 perror("bind(PF_UNIX)");
1286 wpa_printf(MSG_DEBUG
, "Successfully replaced leftover "
1287 "ctrl_iface socket '%s'", fname
);
1289 wpa_printf(MSG_INFO
, "ctrl_iface exists and seems to "
1290 "be in use - cannot override it");
1291 wpa_printf(MSG_INFO
, "Delete '%s' manually if it is "
1292 "not used anymore", fname
);
1299 if (chmod(fname
, S_IRWXU
| S_IRWXG
) < 0) {
1300 perror("chmod[ctrl_interface/ifname]");
1305 interface
->global_ctrl_sock
= s
;
1306 eloop_register_read_sock(s
, hostapd_global_ctrl_iface_receive
,
1322 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces
*interfaces
)
1326 if (interfaces
->global_ctrl_sock
> -1) {
1327 eloop_unregister_read_sock(interfaces
->global_ctrl_sock
);
1328 close(interfaces
->global_ctrl_sock
);
1329 interfaces
->global_ctrl_sock
= -1;
1330 fname
= hostapd_global_ctrl_iface_path(interfaces
);
1336 if (interfaces
->global_iface_path
&&
1337 rmdir(interfaces
->global_iface_path
) < 0) {
1338 if (errno
== ENOTEMPTY
) {
1339 wpa_printf(MSG_DEBUG
, "Control interface "
1340 "directory not empty - leaving it "
1343 perror("rmdir[ctrl_interface]");
1346 os_free(interfaces
->global_iface_path
);
1347 interfaces
->global_iface_path
= NULL
;
1352 static void hostapd_ctrl_iface_send(struct hostapd_data
*hapd
, int level
,
1353 const char *buf
, size_t len
)
1355 struct wpa_ctrl_dst
*dst
, *next
;
1361 dst
= hapd
->ctrl_dst
;
1362 if (hapd
->ctrl_sock
< 0 || dst
== NULL
)
1365 os_snprintf(levelstr
, sizeof(levelstr
), "<%d>", level
);
1366 io
[0].iov_base
= levelstr
;
1367 io
[0].iov_len
= os_strlen(levelstr
);
1368 io
[1].iov_base
= (char *) buf
;
1369 io
[1].iov_len
= len
;
1370 os_memset(&msg
, 0, sizeof(msg
));
1377 if (level
>= dst
->debug_level
) {
1378 wpa_hexdump(MSG_DEBUG
, "CTRL_IFACE monitor send",
1379 (u8
*) dst
->addr
.sun_path
, dst
->addrlen
-
1380 offsetof(struct sockaddr_un
, sun_path
));
1381 msg
.msg_name
= &dst
->addr
;
1382 msg
.msg_namelen
= dst
->addrlen
;
1383 if (sendmsg(hapd
->ctrl_sock
, &msg
, 0) < 0) {
1385 wpa_printf(MSG_INFO
, "CTRL_IFACE monitor[%d]: "
1387 idx
, errno
, strerror(errno
));
1389 if (dst
->errors
> 10 || _errno
== ENOENT
) {
1390 hostapd_ctrl_iface_detach(
1402 #endif /* CONFIG_NATIVE_WINDOWS */