aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaja Mani <rmani@qca.qualcomm.com>2013-02-07 13:24:53 (GMT)
committerJouni Malinen <j@w1.fi>2013-02-07 13:24:53 (GMT)
commit3140803b6d004c32c9e1bbb6288d04a14eb75a9b (patch)
treeafc75439844eed2386a41e64b1e0e5e6309d527c
parent409ca9a84daee279d743d87f9b78d61ecccbc401 (diff)
downloadhostap-3140803b6d004c32c9e1bbb6288d04a14eb75a9b.zip
hostap-3140803b6d004c32c9e1bbb6288d04a14eb75a9b.tar.gz
hostap-3140803b6d004c32c9e1bbb6288d04a14eb75a9b.tar.bz2
nl80211: Add ctrl_iface message for AP mode connection rejection
When AP mode operation reject the client, nl80211 layer advertises the connect failed event with the reason for failures (for example, max client reached, etc.) using NL80211_CMD_CONN_FAILED. This patch adds some debug messages whenever such an event is received from the nl80211 layer and also the same event is posted to the upper layer via wpa_msg(). Signed-off-by: Raja Mani <rmani@qca.qualcomm.com>
-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;