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>
This commit is contained in:
Raja Mani 2013-02-07 15:24:53 +02:00 committed by Jouni Malinen
parent 409ca9a84d
commit 3140803b6d
7 changed files with 102 additions and 1 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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 */

View file

@ -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;
};
/**

View file

@ -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";

View file

@ -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);

View file

@ -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;