2 * hostapd / UNIX domain socket -based control interface
3 * Copyright (c) 2004-2010, 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_OOB
254 static int hostapd_ctrl_iface_wps_oob(struct hostapd_data
*hapd
, char *txt
)
256 char *path
, *method
, *name
;
258 path
= os_strchr(txt
, ' ');
263 method
= os_strchr(path
, ' ');
268 name
= os_strchr(method
, ' ');
272 return hostapd_wps_start_oob(hapd
, txt
, path
, method
, name
);
274 #endif /* CONFIG_WPS_OOB */
277 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data
*hapd
, char *txt
,
278 char *buf
, size_t buflen
)
284 pos
= os_strchr(txt
, ' ');
288 if (os_strcmp(txt
, "disable") == 0) {
289 hostapd_wps_ap_pin_disable(hapd
);
290 return os_snprintf(buf
, buflen
, "OK\n");
293 if (os_strcmp(txt
, "random") == 0) {
296 pin_txt
= hostapd_wps_ap_pin_random(hapd
, timeout
);
299 return os_snprintf(buf
, buflen
, "%s", pin_txt
);
302 if (os_strcmp(txt
, "get") == 0) {
303 pin_txt
= hostapd_wps_ap_pin_get(hapd
);
306 return os_snprintf(buf
, buflen
, "%s", pin_txt
);
309 if (os_strcmp(txt
, "set") == 0) {
314 pos
= os_strchr(pos
, ' ');
319 if (os_strlen(pin
) > buflen
)
321 if (hostapd_wps_ap_pin_set(hapd
, pin
, timeout
) < 0)
323 return os_snprintf(buf
, buflen
, "%s", pin
);
330 static int hostapd_ctrl_iface_wps_config(struct hostapd_data
*hapd
, char *txt
)
333 char *ssid
, *auth
, *encr
= NULL
, *key
= NULL
;
336 pos
= os_strchr(txt
, ' ');
342 pos
= os_strchr(pos
, ' ');
346 pos
= os_strchr(pos
, ' ');
353 return hostapd_wps_config_ap(hapd
, ssid
, auth
, encr
, key
);
355 #endif /* CONFIG_WPS */
358 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data
*hapd
,
364 struct ieee80211_mgmt
*mgmt
;
367 if (hwaddr_aton(cmd
, addr
))
373 url_len
= os_strlen(url
);
377 os_memset(buf
, 0, sizeof(buf
));
378 mgmt
= (struct ieee80211_mgmt
*) buf
;
379 mgmt
->frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
380 WLAN_FC_STYPE_ACTION
);
381 os_memcpy(mgmt
->da
, addr
, ETH_ALEN
);
382 os_memcpy(mgmt
->sa
, hapd
->own_addr
, ETH_ALEN
);
383 os_memcpy(mgmt
->bssid
, hapd
->own_addr
, ETH_ALEN
);
384 mgmt
->u
.action
.category
= WLAN_ACTION_WNM
;
385 mgmt
->u
.action
.u
.bss_tm_req
.action
= WNM_BSS_TRANS_MGMT_REQ
;
386 mgmt
->u
.action
.u
.bss_tm_req
.dialog_token
= 1;
387 mgmt
->u
.action
.u
.bss_tm_req
.req_mode
=
388 WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT
;
389 mgmt
->u
.action
.u
.bss_tm_req
.disassoc_timer
= host_to_le16(0);
390 mgmt
->u
.action
.u
.bss_tm_req
.validity_interval
= 0;
392 pos
= mgmt
->u
.action
.u
.bss_tm_req
.variable
;
394 /* Session Information URL */
396 os_memcpy(pos
, url
, url_len
);
399 if (hostapd_drv_send_mlme(hapd
, buf
, pos
- buf
, 0) < 0) {
400 wpa_printf(MSG_DEBUG
, "Failed to send BSS Transition "
401 "Management Request frame");
409 static int hostapd_ctrl_iface_get_config(struct hostapd_data
*hapd
,
410 char *buf
, size_t buflen
)
418 ret
= os_snprintf(pos
, end
- pos
, "bssid=" MACSTR
"\n"
420 MAC2STR(hapd
->own_addr
),
421 hapd
->conf
->ssid
.ssid
);
422 if (ret
< 0 || ret
>= end
- pos
)
427 ret
= os_snprintf(pos
, end
- pos
, "wps_state=%s\n",
428 hapd
->conf
->wps_state
== 0 ? "disabled" :
429 (hapd
->conf
->wps_state
== 1 ? "not configured" :
431 if (ret
< 0 || ret
>= end
- pos
)
435 if (hapd
->conf
->wps_state
&& hapd
->conf
->wpa
&&
436 hapd
->conf
->ssid
.wpa_passphrase
) {
437 ret
= os_snprintf(pos
, end
- pos
, "passphrase=%s\n",
438 hapd
->conf
->ssid
.wpa_passphrase
);
439 if (ret
< 0 || ret
>= end
- pos
)
444 if (hapd
->conf
->wps_state
&& hapd
->conf
->wpa
&&
445 hapd
->conf
->ssid
.wpa_psk
&&
446 hapd
->conf
->ssid
.wpa_psk
->group
) {
447 char hex
[PMK_LEN
* 2 + 1];
448 wpa_snprintf_hex(hex
, sizeof(hex
),
449 hapd
->conf
->ssid
.wpa_psk
->psk
, PMK_LEN
);
450 ret
= os_snprintf(pos
, end
- pos
, "psk=%s\n", hex
);
451 if (ret
< 0 || ret
>= end
- pos
)
455 #endif /* CONFIG_WPS */
457 if (hapd
->conf
->wpa
&& hapd
->conf
->wpa_key_mgmt
) {
458 ret
= os_snprintf(pos
, end
- pos
, "key_mgmt=");
459 if (ret
< 0 || ret
>= end
- pos
)
463 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_PSK
) {
464 ret
= os_snprintf(pos
, end
- pos
, "WPA-PSK ");
465 if (ret
< 0 || ret
>= end
- pos
)
469 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_IEEE8021X
) {
470 ret
= os_snprintf(pos
, end
- pos
, "WPA-EAP ");
471 if (ret
< 0 || ret
>= end
- pos
)
475 #ifdef CONFIG_IEEE80211R
476 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_FT_PSK
) {
477 ret
= os_snprintf(pos
, end
- pos
, "FT-PSK ");
478 if (ret
< 0 || ret
>= end
- pos
)
482 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_FT_IEEE8021X
) {
483 ret
= os_snprintf(pos
, end
- pos
, "FT-EAP ");
484 if (ret
< 0 || ret
>= end
- pos
)
488 #endif /* CONFIG_IEEE80211R */
489 #ifdef CONFIG_IEEE80211W
490 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_PSK_SHA256
) {
491 ret
= os_snprintf(pos
, end
- pos
, "WPA-PSK-SHA256 ");
492 if (ret
< 0 || ret
>= end
- pos
)
496 if (hapd
->conf
->wpa_key_mgmt
& WPA_KEY_MGMT_IEEE8021X_SHA256
) {
497 ret
= os_snprintf(pos
, end
- pos
, "WPA-EAP-SHA256 ");
498 if (ret
< 0 || ret
>= end
- pos
)
502 #endif /* CONFIG_IEEE80211W */
504 ret
= os_snprintf(pos
, end
- pos
, "\n");
505 if (ret
< 0 || ret
>= end
- pos
)
510 if (hapd
->conf
->wpa
&& hapd
->conf
->wpa_group
== WPA_CIPHER_CCMP
) {
511 ret
= os_snprintf(pos
, end
- pos
, "group_cipher=CCMP\n");
512 if (ret
< 0 || ret
>= end
- pos
)
515 } else if (hapd
->conf
->wpa
&&
516 hapd
->conf
->wpa_group
== WPA_CIPHER_TKIP
) {
517 ret
= os_snprintf(pos
, end
- pos
, "group_cipher=TKIP\n");
518 if (ret
< 0 || ret
>= end
- pos
)
523 if ((hapd
->conf
->wpa
& WPA_PROTO_RSN
) && hapd
->conf
->rsn_pairwise
) {
524 ret
= os_snprintf(pos
, end
- pos
, "rsn_pairwise_cipher=");
525 if (ret
< 0 || ret
>= end
- pos
)
529 if (hapd
->conf
->rsn_pairwise
& WPA_CIPHER_CCMP
) {
530 ret
= os_snprintf(pos
, end
- pos
, "CCMP ");
531 if (ret
< 0 || ret
>= end
- pos
)
535 if (hapd
->conf
->rsn_pairwise
& WPA_CIPHER_TKIP
) {
536 ret
= os_snprintf(pos
, end
- pos
, "TKIP ");
537 if (ret
< 0 || ret
>= end
- pos
)
542 ret
= os_snprintf(pos
, end
- pos
, "\n");
543 if (ret
< 0 || ret
>= end
- pos
)
548 if ((hapd
->conf
->wpa
& WPA_PROTO_WPA
) && hapd
->conf
->wpa_pairwise
) {
549 ret
= os_snprintf(pos
, end
- pos
, "wpa_pairwise_cipher=");
550 if (ret
< 0 || ret
>= end
- pos
)
554 if (hapd
->conf
->wpa_pairwise
& WPA_CIPHER_CCMP
) {
555 ret
= os_snprintf(pos
, end
- pos
, "CCMP ");
556 if (ret
< 0 || ret
>= end
- pos
)
560 if (hapd
->conf
->wpa_pairwise
& WPA_CIPHER_TKIP
) {
561 ret
= os_snprintf(pos
, end
- pos
, "TKIP ");
562 if (ret
< 0 || ret
>= end
- pos
)
567 ret
= os_snprintf(pos
, end
- pos
, "\n");
568 if (ret
< 0 || ret
>= end
- pos
)
577 static int hostapd_ctrl_iface_set(struct hostapd_data
*hapd
, char *cmd
)
582 value
= os_strchr(cmd
, ' ');
587 wpa_printf(MSG_DEBUG
, "CTRL_IFACE SET '%s'='%s'", cmd
, value
);
589 #ifdef CONFIG_WPS_TESTING
590 } else if (os_strcasecmp(cmd
, "wps_version_number") == 0) {
592 val
= strtol(value
, NULL
, 0);
593 if (val
< 0 || val
> 0xff) {
595 wpa_printf(MSG_DEBUG
, "WPS: Invalid "
596 "wps_version_number %ld", val
);
598 wps_version_number
= val
;
599 wpa_printf(MSG_DEBUG
, "WPS: Testing - force WPS "
601 (wps_version_number
& 0xf0) >> 4,
602 wps_version_number
& 0x0f);
603 hostapd_wps_update_ie(hapd
);
605 } else if (os_strcasecmp(cmd
, "wps_testing_dummy_cred") == 0) {
606 wps_testing_dummy_cred
= atoi(value
);
607 wpa_printf(MSG_DEBUG
, "WPS: Testing - dummy_cred=%d",
608 wps_testing_dummy_cred
);
609 #endif /* CONFIG_WPS_TESTING */
611 ret
= hostapd_set_iface(hapd
->iconf
, hapd
->conf
, cmd
, value
);
618 static int hostapd_ctrl_iface_get(struct hostapd_data
*hapd
, char *cmd
,
619 char *buf
, size_t buflen
)
623 wpa_printf(MSG_DEBUG
, "CTRL_IFACE GET '%s'", cmd
);
625 if (os_strcmp(cmd
, "version") == 0) {
626 res
= os_snprintf(buf
, buflen
, "%s", VERSION_STR
);
627 if (res
< 0 || (unsigned int) res
>= buflen
)
636 static void hostapd_ctrl_iface_receive(int sock
, void *eloop_ctx
,
639 struct hostapd_data
*hapd
= eloop_ctx
;
642 struct sockaddr_un from
;
643 socklen_t fromlen
= sizeof(from
);
645 const int reply_size
= 4096;
647 int level
= MSG_DEBUG
;
649 res
= recvfrom(sock
, buf
, sizeof(buf
) - 1, 0,
650 (struct sockaddr
*) &from
, &fromlen
);
652 perror("recvfrom(ctrl_iface)");
656 if (os_strcmp(buf
, "PING") == 0)
657 level
= MSG_EXCESSIVE
;
658 wpa_hexdump_ascii(level
, "RX ctrl_iface", (u8
*) buf
, res
);
660 reply
= os_malloc(reply_size
);
662 sendto(sock
, "FAIL\n", 5, 0, (struct sockaddr
*) &from
,
667 os_memcpy(reply
, "OK\n", 3);
670 if (os_strcmp(buf
, "PING") == 0) {
671 os_memcpy(reply
, "PONG\n", 5);
673 } else if (os_strncmp(buf
, "RELOG", 5) == 0) {
674 if (wpa_debug_reopen_file() < 0)
676 } else if (os_strcmp(buf
, "MIB") == 0) {
677 reply_len
= ieee802_11_get_mib(hapd
, reply
, reply_size
);
678 if (reply_len
>= 0) {
679 res
= wpa_get_mib(hapd
->wpa_auth
, reply
+ reply_len
,
680 reply_size
- reply_len
);
686 if (reply_len
>= 0) {
687 res
= ieee802_1x_get_mib(hapd
, reply
+ reply_len
,
688 reply_size
- reply_len
);
694 #ifndef CONFIG_NO_RADIUS
695 if (reply_len
>= 0) {
696 res
= radius_client_get_mib(hapd
->radius
,
698 reply_size
- reply_len
);
704 #endif /* CONFIG_NO_RADIUS */
705 } else if (os_strcmp(buf
, "STA-FIRST") == 0) {
706 reply_len
= hostapd_ctrl_iface_sta_first(hapd
, reply
,
708 } else if (os_strncmp(buf
, "STA ", 4) == 0) {
709 reply_len
= hostapd_ctrl_iface_sta(hapd
, buf
+ 4, reply
,
711 } else if (os_strncmp(buf
, "STA-NEXT ", 9) == 0) {
712 reply_len
= hostapd_ctrl_iface_sta_next(hapd
, buf
+ 9, reply
,
714 } else if (os_strcmp(buf
, "ATTACH") == 0) {
715 if (hostapd_ctrl_iface_attach(hapd
, &from
, fromlen
))
717 } else if (os_strcmp(buf
, "DETACH") == 0) {
718 if (hostapd_ctrl_iface_detach(hapd
, &from
, fromlen
))
720 } else if (os_strncmp(buf
, "LEVEL ", 6) == 0) {
721 if (hostapd_ctrl_iface_level(hapd
, &from
, fromlen
,
724 } else if (os_strncmp(buf
, "NEW_STA ", 8) == 0) {
725 if (hostapd_ctrl_iface_new_sta(hapd
, buf
+ 8))
727 } else if (os_strncmp(buf
, "DEAUTHENTICATE ", 15) == 0) {
728 if (hostapd_ctrl_iface_deauthenticate(hapd
, buf
+ 15))
730 } else if (os_strncmp(buf
, "DISASSOCIATE ", 13) == 0) {
731 if (hostapd_ctrl_iface_disassociate(hapd
, buf
+ 13))
733 #ifdef CONFIG_IEEE80211W
735 } else if (os_strncmp(buf
, "SA_QUERY ", 9) == 0) {
736 if (hostapd_ctrl_iface_sa_query(hapd
, buf
+ 9))
738 #endif /* NEED_AP_MLME */
739 #endif /* CONFIG_IEEE80211W */
741 } else if (os_strncmp(buf
, "WPS_PIN ", 8) == 0) {
742 if (hostapd_ctrl_iface_wps_pin(hapd
, buf
+ 8))
744 } else if (os_strncmp(buf
, "WPS_CHECK_PIN ", 14) == 0) {
745 reply_len
= hostapd_ctrl_iface_wps_check_pin(
746 hapd
, buf
+ 14, reply
, reply_size
);
747 } else if (os_strcmp(buf
, "WPS_PBC") == 0) {
748 if (hostapd_wps_button_pushed(hapd
, NULL
))
750 #ifdef CONFIG_WPS_OOB
751 } else if (os_strncmp(buf
, "WPS_OOB ", 8) == 0) {
752 if (hostapd_ctrl_iface_wps_oob(hapd
, buf
+ 8))
754 #endif /* CONFIG_WPS_OOB */
755 } else if (os_strncmp(buf
, "WPS_AP_PIN ", 11) == 0) {
756 reply_len
= hostapd_ctrl_iface_wps_ap_pin(hapd
, buf
+ 11,
758 } else if (os_strncmp(buf
, "WPS_CONFIG ", 11) == 0) {
759 if (hostapd_ctrl_iface_wps_config(hapd
, buf
+ 11) < 0)
761 #endif /* CONFIG_WPS */
762 } else if (os_strncmp(buf
, "ESS_DISASSOC ", 13) == 0) {
763 if (hostapd_ctrl_iface_ess_disassoc(hapd
, buf
+ 13))
765 } else if (os_strcmp(buf
, "GET_CONFIG") == 0) {
766 reply_len
= hostapd_ctrl_iface_get_config(hapd
, reply
,
768 } else if (os_strncmp(buf
, "SET ", 4) == 0) {
769 if (hostapd_ctrl_iface_set(hapd
, buf
+ 4))
771 } else if (os_strncmp(buf
, "GET ", 4) == 0) {
772 reply_len
= hostapd_ctrl_iface_get(hapd
, buf
+ 4, reply
,
775 os_memcpy(reply
, "UNKNOWN COMMAND\n", 16);
780 os_memcpy(reply
, "FAIL\n", 5);
783 sendto(sock
, reply
, reply_len
, 0, (struct sockaddr
*) &from
, fromlen
);
788 static char * hostapd_ctrl_iface_path(struct hostapd_data
*hapd
)
793 if (hapd
->conf
->ctrl_interface
== NULL
)
796 len
= os_strlen(hapd
->conf
->ctrl_interface
) +
797 os_strlen(hapd
->conf
->iface
) + 2;
798 buf
= os_malloc(len
);
802 os_snprintf(buf
, len
, "%s/%s",
803 hapd
->conf
->ctrl_interface
, hapd
->conf
->iface
);
809 static void hostapd_ctrl_iface_msg_cb(void *ctx
, int level
,
810 const char *txt
, size_t len
)
812 struct hostapd_data
*hapd
= ctx
;
815 hostapd_ctrl_iface_send(hapd
, level
, txt
, len
);
819 int hostapd_ctrl_iface_init(struct hostapd_data
*hapd
)
821 struct sockaddr_un addr
;
825 if (hapd
->ctrl_sock
> -1) {
826 wpa_printf(MSG_DEBUG
, "ctrl_iface already exists!");
830 if (hapd
->conf
->ctrl_interface
== NULL
)
833 if (mkdir(hapd
->conf
->ctrl_interface
, S_IRWXU
| S_IRWXG
) < 0) {
834 if (errno
== EEXIST
) {
835 wpa_printf(MSG_DEBUG
, "Using existing control "
836 "interface directory.");
838 perror("mkdir[ctrl_interface]");
843 if (hapd
->conf
->ctrl_interface_gid_set
&&
844 chown(hapd
->conf
->ctrl_interface
, 0,
845 hapd
->conf
->ctrl_interface_gid
) < 0) {
846 perror("chown[ctrl_interface]");
850 if (os_strlen(hapd
->conf
->ctrl_interface
) + 1 +
851 os_strlen(hapd
->conf
->iface
) >= sizeof(addr
.sun_path
))
854 s
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
856 perror("socket(PF_UNIX)");
860 os_memset(&addr
, 0, sizeof(addr
));
862 addr
.sun_len
= sizeof(addr
);
863 #endif /* __FreeBSD__ */
864 addr
.sun_family
= AF_UNIX
;
865 fname
= hostapd_ctrl_iface_path(hapd
);
868 os_strlcpy(addr
.sun_path
, fname
, sizeof(addr
.sun_path
));
869 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
870 wpa_printf(MSG_DEBUG
, "ctrl_iface bind(PF_UNIX) failed: %s",
872 if (connect(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
873 wpa_printf(MSG_DEBUG
, "ctrl_iface exists, but does not"
874 " allow connections - assuming it was left"
875 "over from forced program termination");
876 if (unlink(fname
) < 0) {
877 perror("unlink[ctrl_iface]");
878 wpa_printf(MSG_ERROR
, "Could not unlink "
879 "existing ctrl_iface socket '%s'",
883 if (bind(s
, (struct sockaddr
*) &addr
, sizeof(addr
)) <
885 perror("bind(PF_UNIX)");
888 wpa_printf(MSG_DEBUG
, "Successfully replaced leftover "
889 "ctrl_iface socket '%s'", fname
);
891 wpa_printf(MSG_INFO
, "ctrl_iface exists and seems to "
892 "be in use - cannot override it");
893 wpa_printf(MSG_INFO
, "Delete '%s' manually if it is "
894 "not used anymore", fname
);
901 if (hapd
->conf
->ctrl_interface_gid_set
&&
902 chown(fname
, 0, hapd
->conf
->ctrl_interface_gid
) < 0) {
903 perror("chown[ctrl_interface/ifname]");
907 if (chmod(fname
, S_IRWXU
| S_IRWXG
) < 0) {
908 perror("chmod[ctrl_interface/ifname]");
914 eloop_register_read_sock(s
, hostapd_ctrl_iface_receive
, hapd
,
916 hapd
->msg_ctx
= hapd
;
917 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb
);
932 void hostapd_ctrl_iface_deinit(struct hostapd_data
*hapd
)
934 struct wpa_ctrl_dst
*dst
, *prev
;
936 if (hapd
->ctrl_sock
> -1) {
938 eloop_unregister_read_sock(hapd
->ctrl_sock
);
939 close(hapd
->ctrl_sock
);
940 hapd
->ctrl_sock
= -1;
941 fname
= hostapd_ctrl_iface_path(hapd
);
946 if (hapd
->conf
->ctrl_interface
&&
947 rmdir(hapd
->conf
->ctrl_interface
) < 0) {
948 if (errno
== ENOTEMPTY
) {
949 wpa_printf(MSG_DEBUG
, "Control interface "
950 "directory not empty - leaving it "
953 perror("rmdir[ctrl_interface]");
958 dst
= hapd
->ctrl_dst
;
967 static void hostapd_ctrl_iface_send(struct hostapd_data
*hapd
, int level
,
968 const char *buf
, size_t len
)
970 struct wpa_ctrl_dst
*dst
, *next
;
976 dst
= hapd
->ctrl_dst
;
977 if (hapd
->ctrl_sock
< 0 || dst
== NULL
)
980 os_snprintf(levelstr
, sizeof(levelstr
), "<%d>", level
);
981 io
[0].iov_base
= levelstr
;
982 io
[0].iov_len
= os_strlen(levelstr
);
983 io
[1].iov_base
= (char *) buf
;
985 os_memset(&msg
, 0, sizeof(msg
));
992 if (level
>= dst
->debug_level
) {
993 wpa_hexdump(MSG_DEBUG
, "CTRL_IFACE monitor send",
994 (u8
*) dst
->addr
.sun_path
, dst
->addrlen
-
995 offsetof(struct sockaddr_un
, sun_path
));
996 msg
.msg_name
= &dst
->addr
;
997 msg
.msg_namelen
= dst
->addrlen
;
998 if (sendmsg(hapd
->ctrl_sock
, &msg
, 0) < 0) {
1000 wpa_printf(MSG_INFO
, "CTRL_IFACE monitor[%d]: "
1002 idx
, errno
, strerror(errno
));
1004 if (dst
->errors
> 10 || _errno
== ENOENT
) {
1005 hostapd_ctrl_iface_detach(
1017 #endif /* CONFIG_NATIVE_WINDOWS */