Add connect fail reason code from the driver to assoc reject event
Add support to report a vendor specific connect fail reason code fetched from the driver to users by adding the reason code to the event CTRL-EVENT-ASSOC-REJECT. Fetch the connect fail reason code when the driver sends a failure connection result and append the reason code, if available, to assoc reject event. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
7423fa6e8f
commit
60c902f408
5 changed files with 173 additions and 4 deletions
|
@ -5062,6 +5062,34 @@ struct freq_survey {
|
||||||
#define SURVEY_HAS_CHAN_TIME_RX BIT(3)
|
#define SURVEY_HAS_CHAN_TIME_RX BIT(3)
|
||||||
#define SURVEY_HAS_CHAN_TIME_TX BIT(4)
|
#define SURVEY_HAS_CHAN_TIME_TX BIT(4)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum sta_connect_fail_reason_codes - STA connect failure reason code values
|
||||||
|
* @STA_CONNECT_FAIL_REASON_UNSPECIFIED: No reason code specified for
|
||||||
|
* connection failure.
|
||||||
|
* @STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: No Probe Response frame received
|
||||||
|
* for unicast Probe Request frame.
|
||||||
|
* @STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: STA failed to send auth request.
|
||||||
|
* @STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: AP didn't send ACK for
|
||||||
|
* auth request.
|
||||||
|
* @STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: Auth response is not
|
||||||
|
* received from AP.
|
||||||
|
* @STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: STA failed to send
|
||||||
|
* Association Request frame.
|
||||||
|
* @STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: AP didn't send ACK for
|
||||||
|
* Association Request frame.
|
||||||
|
* @STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: Association Response
|
||||||
|
* frame is not received from AP.
|
||||||
|
*/
|
||||||
|
enum sta_connect_fail_reason_codes {
|
||||||
|
STA_CONNECT_FAIL_REASON_UNSPECIFIED = 0,
|
||||||
|
STA_CONNECT_FAIL_REASON_NO_BSS_FOUND = 1,
|
||||||
|
STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL = 2,
|
||||||
|
STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED = 3,
|
||||||
|
STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED = 4,
|
||||||
|
STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL = 5,
|
||||||
|
STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED = 6,
|
||||||
|
STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* union wpa_event_data - Additional data for wpa_supplicant_event() calls
|
* union wpa_event_data - Additional data for wpa_supplicant_event() calls
|
||||||
|
@ -5463,6 +5491,11 @@ union wpa_event_data {
|
||||||
* FILS ERP messages
|
* FILS ERP messages
|
||||||
*/
|
*/
|
||||||
u16 fils_erp_next_seq_num;
|
u16 fils_erp_next_seq_num;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reason_code - Connection failure reason code from the driver
|
||||||
|
*/
|
||||||
|
enum sta_connect_fail_reason_codes reason_code;
|
||||||
} assoc_reject;
|
} assoc_reject;
|
||||||
|
|
||||||
struct timeout_event {
|
struct timeout_event {
|
||||||
|
|
|
@ -174,6 +174,7 @@ struct wpa_driver_nl80211_data {
|
||||||
unsigned int control_port_ap:1;
|
unsigned int control_port_ap:1;
|
||||||
unsigned int multicast_registrations:1;
|
unsigned int multicast_registrations:1;
|
||||||
unsigned int no_rrm:1;
|
unsigned int no_rrm:1;
|
||||||
|
unsigned int get_sta_info_vendor_cmd_avail:1;
|
||||||
|
|
||||||
u64 vendor_scan_cookie;
|
u64 vendor_scan_cookie;
|
||||||
u64 remain_on_chan_cookie;
|
u64 remain_on_chan_cookie;
|
||||||
|
|
|
@ -994,6 +994,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
|
||||||
case QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE:
|
case QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE:
|
||||||
drv->add_sta_node_vendor_cmd_avail = 1;
|
drv->add_sta_node_vendor_cmd_avail = 1;
|
||||||
break;
|
break;
|
||||||
|
case QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO:
|
||||||
|
drv->get_sta_info_vendor_cmd_avail = 1;
|
||||||
|
break;
|
||||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,6 +296,94 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_DRIVER_NL80211_QCA
|
||||||
|
|
||||||
|
static int qca_drv_connect_fail_reason_code_handler(struct nl_msg *msg,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[NL80211_ATTR_MAX + 1];
|
||||||
|
struct nlattr *tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1];
|
||||||
|
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||||
|
u32 *reason_code = arg;
|
||||||
|
|
||||||
|
*reason_code = 0;
|
||||||
|
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
||||||
|
genlmsg_attrlen(gnlh, 0), NULL);
|
||||||
|
|
||||||
|
if (!tb[NL80211_ATTR_VENDOR_DATA]) {
|
||||||
|
wpa_printf(MSG_ERROR, "%s: Vendor data not found", __func__);
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
nla_parse(tb_sta_info, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX,
|
||||||
|
nla_data(tb[NL80211_ATTR_VENDOR_DATA]),
|
||||||
|
nla_len(tb[NL80211_ATTR_VENDOR_DATA]), NULL);
|
||||||
|
|
||||||
|
if (!tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE]) {
|
||||||
|
wpa_printf(MSG_INFO, "%s: Vendor attr not found", __func__);
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
*reason_code = nla_get_u32(tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE]);
|
||||||
|
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static enum qca_sta_connect_fail_reason_codes
|
||||||
|
drv_get_connect_fail_reason_code(struct wpa_driver_nl80211_data *drv)
|
||||||
|
{
|
||||||
|
enum qca_sta_connect_fail_reason_codes reason_code;
|
||||||
|
struct nl_msg *msg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
|
||||||
|
if (!msg || nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
|
||||||
|
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
|
||||||
|
QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO)) {
|
||||||
|
nlmsg_free(msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = send_and_recv_msgs(drv, msg,
|
||||||
|
qca_drv_connect_fail_reason_code_handler,
|
||||||
|
&reason_code, NULL, NULL);
|
||||||
|
if (ret)
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Get connect fail reason_code failed: ret=%d (%s)",
|
||||||
|
ret, strerror(-ret));
|
||||||
|
|
||||||
|
return reason_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static enum sta_connect_fail_reason_codes
|
||||||
|
convert_connect_fail_reason_codes(enum qca_sta_connect_fail_reason_codes
|
||||||
|
reason_code)
|
||||||
|
{
|
||||||
|
switch (reason_code) {
|
||||||
|
case QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND:
|
||||||
|
return STA_CONNECT_FAIL_REASON_NO_BSS_FOUND;
|
||||||
|
case QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL:
|
||||||
|
return STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL;
|
||||||
|
case QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED:
|
||||||
|
return STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED;
|
||||||
|
case QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED:
|
||||||
|
return STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED;
|
||||||
|
case QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL:
|
||||||
|
return STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL;
|
||||||
|
case QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED:
|
||||||
|
return STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED;
|
||||||
|
case QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED:
|
||||||
|
return STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED;
|
||||||
|
default:
|
||||||
|
return STA_CONNECT_FAIL_REASON_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||||
|
|
||||||
|
|
||||||
static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
|
static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
|
||||||
enum nl80211_commands cmd, struct nlattr *status,
|
enum nl80211_commands cmd, struct nlattr *status,
|
||||||
struct nlattr *addr, struct nlattr *req_ie,
|
struct nlattr *addr, struct nlattr *req_ie,
|
||||||
|
@ -385,6 +473,17 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
|
||||||
if (fils_erp_next_seq_num)
|
if (fils_erp_next_seq_num)
|
||||||
event.assoc_reject.fils_erp_next_seq_num =
|
event.assoc_reject.fils_erp_next_seq_num =
|
||||||
nla_get_u16(fils_erp_next_seq_num);
|
nla_get_u16(fils_erp_next_seq_num);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DRIVER_NL80211_QCA
|
||||||
|
if (drv->get_sta_info_vendor_cmd_avail) {
|
||||||
|
enum qca_sta_connect_fail_reason_codes reason_code;
|
||||||
|
|
||||||
|
reason_code = drv_get_connect_fail_reason_code(drv);
|
||||||
|
event.assoc_reject.reason_code =
|
||||||
|
convert_connect_fail_reason_codes(reason_code);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||||
|
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
|
wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4425,6 +4425,31 @@ static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char * connect_fail_reason(enum sta_connect_fail_reason_codes code)
|
||||||
|
{
|
||||||
|
switch (code) {
|
||||||
|
case STA_CONNECT_FAIL_REASON_UNSPECIFIED:
|
||||||
|
return "";
|
||||||
|
case STA_CONNECT_FAIL_REASON_NO_BSS_FOUND:
|
||||||
|
return "no_bss_found";
|
||||||
|
case STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL:
|
||||||
|
return "auth_tx_fail";
|
||||||
|
case STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED:
|
||||||
|
return "auth_no_ack_received";
|
||||||
|
case STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED:
|
||||||
|
return "auth_no_resp_received";
|
||||||
|
case STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL:
|
||||||
|
return "assoc_req_tx_fail";
|
||||||
|
case STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED:
|
||||||
|
return "assoc_no_ack_received";
|
||||||
|
case STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED:
|
||||||
|
return "assoc_no_resp_received";
|
||||||
|
default:
|
||||||
|
return "unknown_reason";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s,
|
static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s,
|
||||||
union wpa_event_data *data)
|
union wpa_event_data *data)
|
||||||
{
|
{
|
||||||
|
@ -4444,21 +4469,29 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
if (data->assoc_reject.bssid)
|
if (data->assoc_reject.bssid)
|
||||||
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
|
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
|
||||||
"bssid=" MACSTR " status_code=%u%s%s%s",
|
"bssid=" MACSTR " status_code=%u%s%s%s%s%s",
|
||||||
MAC2STR(data->assoc_reject.bssid),
|
MAC2STR(data->assoc_reject.bssid),
|
||||||
data->assoc_reject.status_code,
|
data->assoc_reject.status_code,
|
||||||
data->assoc_reject.timed_out ? " timeout" : "",
|
data->assoc_reject.timed_out ? " timeout" : "",
|
||||||
data->assoc_reject.timeout_reason ? "=" : "",
|
data->assoc_reject.timeout_reason ? "=" : "",
|
||||||
data->assoc_reject.timeout_reason ?
|
data->assoc_reject.timeout_reason ?
|
||||||
data->assoc_reject.timeout_reason : "");
|
data->assoc_reject.timeout_reason : "",
|
||||||
|
data->assoc_reject.reason_code !=
|
||||||
|
STA_CONNECT_FAIL_REASON_UNSPECIFIED ?
|
||||||
|
" qca_driver_reason=" : "",
|
||||||
|
connect_fail_reason(data->assoc_reject.reason_code));
|
||||||
else
|
else
|
||||||
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
|
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
|
||||||
"status_code=%u%s%s%s",
|
"status_code=%u%s%s%s%s%s",
|
||||||
data->assoc_reject.status_code,
|
data->assoc_reject.status_code,
|
||||||
data->assoc_reject.timed_out ? " timeout" : "",
|
data->assoc_reject.timed_out ? " timeout" : "",
|
||||||
data->assoc_reject.timeout_reason ? "=" : "",
|
data->assoc_reject.timeout_reason ? "=" : "",
|
||||||
data->assoc_reject.timeout_reason ?
|
data->assoc_reject.timeout_reason ?
|
||||||
data->assoc_reject.timeout_reason : "");
|
data->assoc_reject.timeout_reason : "",
|
||||||
|
data->assoc_reject.reason_code !=
|
||||||
|
STA_CONNECT_FAIL_REASON_UNSPECIFIED ?
|
||||||
|
" qca_driver_reason=" : "",
|
||||||
|
connect_fail_reason(data->assoc_reject.reason_code));
|
||||||
wpa_s->assoc_status_code = data->assoc_reject.status_code;
|
wpa_s->assoc_status_code = data->assoc_reject.status_code;
|
||||||
wpas_notify_assoc_status_code(wpa_s);
|
wpas_notify_assoc_status_code(wpa_s);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue