aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ap/drv_callbacks.c24
-rw-r--r--src/ap/hostapd.h2
-rw-r--r--src/common/wpa_ctrl.h2
-rw-r--r--src/drivers/driver.h24
-rw-r--r--src/drivers/driver_common.c1
-rw-r--r--src/drivers/driver_nl80211.c40
-rw-r--r--wpa_supplicant/events.c10
7 files changed, 102 insertions, 1 deletions
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 8980bec..6d22d49 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -13,6 +13,7 @@
#include "drivers/driver.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
+#include "common/wpa_ctrl.h"
#include "crypto/random.h"
#include "p2p/p2p.h"
#include "wps/wps.h"
@@ -393,6 +394,22 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
}
+void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
+ const u8 *addr, int reason_code)
+{
+ switch (reason_code) {
+ case MAX_CLIENT_REACHED:
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_MAX_STA MACSTR,
+ MAC2STR(addr));
+ break;
+ case BLOCKED_CLIENT:
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_BLOCKED_STA MACSTR,
+ MAC2STR(addr));
+ break;
+ }
+}
+
+
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
const u8 *bssid, const u8 *ie, size_t ie_len,
int ssi_signal)
@@ -828,6 +845,13 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->ch_switch.ht_enabled,
data->ch_switch.ch_offset);
break;
+ case EVENT_CONNECT_FAILED_REASON:
+ if (!data)
+ break;
+ hostapd_event_connect_failed_reason(
+ hapd, data->connect_failed_reason.addr,
+ data->connect_failed_reason.code);
+ break;
default:
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
break;
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 2827232..8ab4f3e 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -305,6 +305,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *ie, size_t ielen, int reassoc);
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
+void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
+ const u8 *addr, int reason_code);
int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
const u8 *bssid, const u8 *ie, size_t ie_len,
int ssi_signal);
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index bb9b558..46e8dc7 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -146,6 +146,8 @@ extern "C" {
#define AP_STA_CONNECTED "AP-STA-CONNECTED "
#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
+#define AP_REJECTED_MAX_STA "AP-REJECTED-MAX-STA "
+#define AP_REJECTED_BLOCKED_STA "AP-REJECTED-BLOCKED-STA "
/* BSS command information masks */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index b981172..b57ea75 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -3056,7 +3056,16 @@ enum wpa_event_type {
*
* This event can be used to request a WNM operation to be performed.
*/
- EVENT_WNM
+ EVENT_WNM,
+
+ /**
+ * EVENT_CONNECT_FAILED_REASON - Connection failure reason in AP mode
+ *
+ * This event indicates that the driver reported a connection failure
+ * with the specified client (for example, max client reached, etc.) in
+ * AP mode.
+ */
+ EVENT_CONNECT_FAILED_REASON
};
@@ -3681,6 +3690,19 @@ union wpa_event_data {
int ht_enabled;
int ch_offset;
} ch_switch;
+
+ /**
+ * struct connect_failed - Data for EVENT_CONNECT_FAILED_REASON
+ * @addr: Remote client address
+ * @code: Reason code for connection failure
+ */
+ struct connect_failed_reason {
+ u8 addr[ETH_ALEN];
+ enum {
+ MAX_CLIENT_REACHED,
+ BLOCKED_CLIENT
+ } code;
+ } connect_failed_reason;
};
/**
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index 418cf1a..565a01b 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -79,6 +79,7 @@ const char * event_to_string(enum wpa_event_type event)
E2S(EAPOL_TX_STATUS);
E2S(CH_SWITCH);
E2S(WNM);
+ E2S(CONNECT_FAILED_REASON);
}
return "UNKNOWN";
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 593bca5..e4b70fe 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -2153,6 +2153,43 @@ static void nl80211_tdls_oper_event(struct wpa_driver_nl80211_data *drv,
}
+static void nl80211_connect_failed_event(struct wpa_driver_nl80211_data *drv,
+ struct nlattr **tb)
+{
+ union wpa_event_data data;
+ u32 reason;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Connect failed event");
+
+ if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_CONN_FAILED_REASON])
+ return;
+
+ os_memset(&data, 0, sizeof(data));
+ os_memcpy(data.connect_failed_reason.addr,
+ nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
+
+ reason = nla_get_u32(tb[NL80211_ATTR_CONN_FAILED_REASON]);
+ switch (reason) {
+ case NL80211_CONN_FAIL_MAX_CLIENTS:
+ wpa_printf(MSG_DEBUG, "nl80211: Max client reached");
+ data.connect_failed_reason.code = MAX_CLIENT_REACHED;
+ break;
+ case NL80211_CONN_FAIL_BLOCKED_CLIENT:
+ wpa_printf(MSG_DEBUG, "nl80211: Blocked client " MACSTR
+ " tried to connect",
+ MAC2STR(data.connect_failed_reason.addr));
+ data.connect_failed_reason.code = BLOCKED_CLIENT;
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "nl8021l: Unknown connect failed reason "
+ "%u", reason);
+ return;
+ }
+
+ wpa_supplicant_event(drv->ctx, EVENT_CONNECT_FAILED_REASON, &data);
+}
+
+
static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb,
int wds)
{
@@ -2290,6 +2327,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
case NL80211_CMD_TDLS_OPER:
nl80211_tdls_oper_event(drv, tb);
break;
+ case NL80211_CMD_CONN_FAILED:
+ nl80211_connect_failed_event(drv, tb);
+ break;
default:
wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
"(cmd=%d)", cmd);
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 3196352..c3e54d3 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2962,6 +2962,16 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpas_wps_start_pbc(wpa_s, NULL, 0);
#endif /* CONFIG_WPS */
break;
+ case EVENT_CONNECT_FAILED_REASON:
+#ifdef CONFIG_AP
+ if (!wpa_s->ap_iface || !data)
+ break;
+ hostapd_event_connect_failed_reason(
+ wpa_s->ap_iface->bss[0],
+ data->connect_failed_reason.addr,
+ data->connect_failed_reason.code);
+#endif /* CONFIG_AP */
+ break;
default:
wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
break;