Remove unnecessary EVENT_RX_ACTION
This driver event was used separately for some Action frames, but all the driver wrappers converted to this from information that would have been enough to indicate an EVENT_RX_MGMT event. In addition, the received event was then converted back to a full IEEE 802.11 management frame for processing in most cases. This is unnecessary complexity, so get rid of the extra path and use EVENT_RX_MGMT for Action frames as well as other management frame subtypes. Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
1450e1e319
commit
dbfb8e82ff
11 changed files with 173 additions and 297 deletions
|
@ -558,39 +558,48 @@ fail:
|
||||||
|
|
||||||
|
|
||||||
static void hostapd_action_rx(struct hostapd_data *hapd,
|
static void hostapd_action_rx(struct hostapd_data *hapd,
|
||||||
struct rx_action *action)
|
struct rx_mgmt *drv_mgmt)
|
||||||
{
|
{
|
||||||
|
struct ieee80211_mgmt *mgmt;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
size_t plen __maybe_unused;
|
||||||
|
u16 fc;
|
||||||
|
|
||||||
|
if (drv_mgmt->frame_len < 24 + 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
plen = drv_mgmt->frame_len - 24 - 1;
|
||||||
|
|
||||||
|
mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame;
|
||||||
|
fc = le_to_host16(mgmt->frame_control);
|
||||||
|
if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION)
|
||||||
|
return; /* handled by the driver */
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
|
wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
|
||||||
action->category, (int) action->len);
|
mgmt->u.action.category, (int) plen);
|
||||||
|
|
||||||
sta = ap_get_sta(hapd, action->sa);
|
sta = ap_get_sta(hapd, mgmt->sa);
|
||||||
if (sta == NULL) {
|
if (sta == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
|
wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
if (action->category == WLAN_ACTION_FT) {
|
if (mgmt->u.action.category == WLAN_ACTION_FT) {
|
||||||
wpa_printf(MSG_DEBUG, "%s: FT_ACTION length %d",
|
const u8 *payload = drv_mgmt->frame + 24 + 1;
|
||||||
__func__, (int) action->len);
|
wpa_ft_action_rx(sta->wpa_sm, payload, plen);
|
||||||
wpa_ft_action_rx(sta->wpa_sm, action->data, action->len);
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
if (action->category == WLAN_ACTION_SA_QUERY && action->len >= 4) {
|
if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY && plen >= 4) {
|
||||||
wpa_printf(MSG_DEBUG, "%s: SA_QUERY_ACTION length %d",
|
ieee802_11_sa_query_action(
|
||||||
__func__, (int) action->len);
|
hapd, mgmt->sa,
|
||||||
ieee802_11_sa_query_action(hapd, action->sa,
|
mgmt->u.action.u.sa_query_resp.action,
|
||||||
*(action->data + 1),
|
mgmt->u.action.u.sa_query_resp.trans_id);
|
||||||
action->data + 2);
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
#ifdef CONFIG_WNM
|
#ifdef CONFIG_WNM
|
||||||
if (action->category == WLAN_ACTION_WNM) {
|
if (mgmt->u.action.category == WLAN_ACTION_WNM) {
|
||||||
wpa_printf(MSG_DEBUG, "%s: WNM_ACTION length %d",
|
ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len);
|
||||||
__func__, (int) action->len);
|
|
||||||
ieee802_11_rx_wnm_action_ap(hapd, action);
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_WNM */
|
#endif /* CONFIG_WNM */
|
||||||
}
|
}
|
||||||
|
@ -683,51 +692,6 @@ static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_rx_action(struct hostapd_data *hapd,
|
|
||||||
struct rx_action *rx_action)
|
|
||||||
{
|
|
||||||
struct rx_mgmt rx_mgmt;
|
|
||||||
u8 *buf;
|
|
||||||
struct ieee80211_hdr *hdr;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "EVENT_RX_ACTION DA=" MACSTR " SA=" MACSTR
|
|
||||||
" BSSID=" MACSTR " category=%u",
|
|
||||||
MAC2STR(rx_action->da), MAC2STR(rx_action->sa),
|
|
||||||
MAC2STR(rx_action->bssid), rx_action->category);
|
|
||||||
wpa_hexdump(MSG_MSGDUMP, "Received action frame contents",
|
|
||||||
rx_action->data, rx_action->len);
|
|
||||||
|
|
||||||
buf = os_zalloc(24 + 1 + rx_action->len);
|
|
||||||
if (buf == NULL)
|
|
||||||
return -1;
|
|
||||||
hdr = (struct ieee80211_hdr *) buf;
|
|
||||||
hdr->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
|
||||||
WLAN_FC_STYPE_ACTION);
|
|
||||||
if (rx_action->protected == 1)
|
|
||||||
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
|
|
||||||
else if (rx_action->category == WLAN_ACTION_SA_QUERY) {
|
|
||||||
/*
|
|
||||||
* Assume frame was protected; it would have been dropped if
|
|
||||||
* not.
|
|
||||||
*/
|
|
||||||
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
|
|
||||||
}
|
|
||||||
os_memcpy(hdr->addr1, rx_action->da, ETH_ALEN);
|
|
||||||
os_memcpy(hdr->addr2, rx_action->sa, ETH_ALEN);
|
|
||||||
os_memcpy(hdr->addr3, rx_action->bssid, ETH_ALEN);
|
|
||||||
buf[24] = rx_action->category;
|
|
||||||
os_memcpy(buf + 24 + 1, rx_action->data, rx_action->len);
|
|
||||||
os_memset(&rx_mgmt, 0, sizeof(rx_mgmt));
|
|
||||||
rx_mgmt.frame = buf;
|
|
||||||
rx_mgmt.frame_len = 24 + 1 + rx_action->len;
|
|
||||||
ret = hostapd_mgmt_rx(hapd, &rx_mgmt);
|
|
||||||
os_free(buf);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
|
static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
|
||||||
size_t len, u16 stype, int ok)
|
size_t len, u16 stype, int ok)
|
||||||
{
|
{
|
||||||
|
@ -966,10 +930,14 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
data->rx_from_unknown.addr,
|
data->rx_from_unknown.addr,
|
||||||
data->rx_from_unknown.wds);
|
data->rx_from_unknown.wds);
|
||||||
break;
|
break;
|
||||||
case EVENT_RX_MGMT:
|
|
||||||
hostapd_mgmt_rx(hapd, &data->rx_mgmt);
|
|
||||||
break;
|
|
||||||
#endif /* NEED_AP_MLME */
|
#endif /* NEED_AP_MLME */
|
||||||
|
case EVENT_RX_MGMT:
|
||||||
|
#ifdef NEED_AP_MLME
|
||||||
|
if (hostapd_mgmt_rx(hapd, &data->rx_mgmt) > 0)
|
||||||
|
break;
|
||||||
|
#endif /* NEED_AP_MLME */
|
||||||
|
hostapd_action_rx(hapd, &data->rx_mgmt);
|
||||||
|
break;
|
||||||
case EVENT_RX_PROBE_REQ:
|
case EVENT_RX_PROBE_REQ:
|
||||||
if (data->rx_probe_req.sa == NULL ||
|
if (data->rx_probe_req.sa == NULL ||
|
||||||
data->rx_probe_req.ie == NULL)
|
data->rx_probe_req.ie == NULL)
|
||||||
|
@ -1008,16 +976,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
break;
|
break;
|
||||||
hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
|
hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
|
||||||
break;
|
break;
|
||||||
case EVENT_RX_ACTION:
|
|
||||||
if (data->rx_action.da == NULL || data->rx_action.sa == NULL ||
|
|
||||||
data->rx_action.bssid == NULL)
|
|
||||||
break;
|
|
||||||
#ifdef NEED_AP_MLME
|
|
||||||
if (hostapd_rx_action(hapd, &data->rx_action) > 0)
|
|
||||||
break;
|
|
||||||
#endif /* NEED_AP_MLME */
|
|
||||||
hostapd_action_rx(hapd, &data->rx_action);
|
|
||||||
break;
|
|
||||||
case EVENT_AUTH:
|
case EVENT_AUTH:
|
||||||
hostapd_notif_auth(hapd, &data->auth);
|
hostapd_notif_auth(hapd, &data->auth);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1564,27 +1564,6 @@ static int robust_action_frame(u8 category)
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_WNM
|
|
||||||
static int hostapd_wnm_action(struct hostapd_data *hapd, struct sta_info *sta,
|
|
||||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
|
||||||
{
|
|
||||||
struct rx_action action;
|
|
||||||
if (len < IEEE80211_HDRLEN + 2)
|
|
||||||
return 0;
|
|
||||||
os_memset(&action, 0, sizeof(action));
|
|
||||||
action.da = mgmt->da;
|
|
||||||
action.sa = mgmt->sa;
|
|
||||||
action.bssid = mgmt->bssid;
|
|
||||||
action.category = mgmt->u.action.category;
|
|
||||||
action.data = (const u8 *) &mgmt->u.action.u.wnm_sleep_req.action;
|
|
||||||
action.len = len - IEEE80211_HDRLEN - 1;
|
|
||||||
action.freq = hapd->iface->freq;
|
|
||||||
ieee802_11_rx_wnm_action_ap(hapd, &action);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_WNM */
|
|
||||||
|
|
||||||
|
|
||||||
static int handle_action(struct hostapd_data *hapd,
|
static int handle_action(struct hostapd_data *hapd,
|
||||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -1636,7 +1615,8 @@ static int handle_action(struct hostapd_data *hapd,
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
#ifdef CONFIG_WNM
|
#ifdef CONFIG_WNM
|
||||||
case WLAN_ACTION_WNM:
|
case WLAN_ACTION_WNM:
|
||||||
return hostapd_wnm_action(hapd, sta, mgmt, len);
|
ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
|
||||||
|
return 1;
|
||||||
#endif /* CONFIG_WNM */
|
#endif /* CONFIG_WNM */
|
||||||
case WLAN_ACTION_PUBLIC:
|
case WLAN_ACTION_PUBLIC:
|
||||||
if (hapd->public_action_cb) {
|
if (hapd->public_action_cb) {
|
||||||
|
|
|
@ -367,30 +367,36 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
|
||||||
|
|
||||||
|
|
||||||
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
||||||
struct rx_action *action)
|
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||||
{
|
{
|
||||||
if (action->len < 1 || action->data == NULL)
|
u8 action;
|
||||||
|
const u8 *payload;
|
||||||
|
size_t plen;
|
||||||
|
|
||||||
|
if (len < IEEE80211_HDRLEN + 2)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
switch (action->data[0]) {
|
payload = &mgmt->u.action.category;
|
||||||
|
payload++;
|
||||||
|
action = *payload++;
|
||||||
|
plen = (((const u8 *) mgmt) + len) - payload;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
case WNM_BSS_TRANS_MGMT_QUERY:
|
case WNM_BSS_TRANS_MGMT_QUERY:
|
||||||
ieee802_11_rx_bss_trans_mgmt_query(hapd, action->sa,
|
ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload,
|
||||||
action->data + 1,
|
plen);
|
||||||
action->len - 1);
|
|
||||||
return 0;
|
return 0;
|
||||||
case WNM_BSS_TRANS_MGMT_RESP:
|
case WNM_BSS_TRANS_MGMT_RESP:
|
||||||
ieee802_11_rx_bss_trans_mgmt_resp(hapd, action->sa,
|
ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload,
|
||||||
action->data + 1,
|
plen);
|
||||||
action->len - 1);
|
|
||||||
return 0;
|
return 0;
|
||||||
case WNM_SLEEP_MODE_REQ:
|
case WNM_SLEEP_MODE_REQ:
|
||||||
ieee802_11_rx_wnmsleep_req(hapd, action->sa, action->data + 1,
|
ieee802_11_rx_wnmsleep_req(hapd, mgmt->sa, payload, plen);
|
||||||
action->len - 1);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WNM: Unsupported WNM Action %u from " MACSTR,
|
wpa_printf(MSG_DEBUG, "WNM: Unsupported WNM Action %u from " MACSTR,
|
||||||
action->data[0], MAC2STR(action->sa));
|
action, MAC2STR(mgmt->sa));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,10 @@
|
||||||
#ifndef WNM_AP_H
|
#ifndef WNM_AP_H
|
||||||
#define WNM_AP_H
|
#define WNM_AP_H
|
||||||
|
|
||||||
struct rx_action;
|
|
||||||
struct sta_info;
|
struct sta_info;
|
||||||
|
|
||||||
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
||||||
struct rx_action *action);
|
const struct ieee80211_mgmt *mgmt, size_t len);
|
||||||
int wnm_send_disassoc_imminent(struct hostapd_data *hapd,
|
int wnm_send_disassoc_imminent(struct hostapd_data *hapd,
|
||||||
struct sta_info *sta, int disassoc_timer);
|
struct sta_info *sta, int disassoc_timer);
|
||||||
int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
|
int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
|
||||||
|
|
|
@ -2216,7 +2216,7 @@ struct wpa_driver_ops {
|
||||||
*
|
*
|
||||||
* This command is used to request the driver to remain awake on the
|
* This command is used to request the driver to remain awake on the
|
||||||
* specified channel for the specified duration and report received
|
* specified channel for the specified duration and report received
|
||||||
* Action frames with EVENT_RX_ACTION events. Optionally, received
|
* Action frames with EVENT_RX_MGMT events. Optionally, received
|
||||||
* Probe Request frames may also be requested to be reported by calling
|
* Probe Request frames may also be requested to be reported by calling
|
||||||
* probe_req_report(). These will be reported with EVENT_RX_PROBE_REQ.
|
* probe_req_report(). These will be reported with EVENT_RX_PROBE_REQ.
|
||||||
*
|
*
|
||||||
|
@ -3101,15 +3101,6 @@ enum wpa_event_type {
|
||||||
*/
|
*/
|
||||||
EVENT_RX_MGMT,
|
EVENT_RX_MGMT,
|
||||||
|
|
||||||
/**
|
|
||||||
* EVENT_RX_ACTION - Action frame received
|
|
||||||
*
|
|
||||||
* This event is used to indicate when an Action frame has been
|
|
||||||
* received. Information about the received frame is included in
|
|
||||||
* union wpa_event_data::rx_action.
|
|
||||||
*/
|
|
||||||
EVENT_RX_ACTION,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EVENT_REMAIN_ON_CHANNEL - Remain-on-channel duration started
|
* EVENT_REMAIN_ON_CHANNEL - Remain-on-channel duration started
|
||||||
*
|
*
|
||||||
|
@ -3763,42 +3754,6 @@ union wpa_event_data {
|
||||||
const u8 *frame;
|
const u8 *frame;
|
||||||
size_t frame_len;
|
size_t frame_len;
|
||||||
u32 datarate;
|
u32 datarate;
|
||||||
int ssi_signal; /* dBm */
|
|
||||||
} rx_mgmt;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct rx_action - Data for EVENT_RX_ACTION events
|
|
||||||
*/
|
|
||||||
struct rx_action {
|
|
||||||
/**
|
|
||||||
* da - Destination address of the received Action frame
|
|
||||||
*/
|
|
||||||
const u8 *da;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sa - Source address of the received Action frame
|
|
||||||
*/
|
|
||||||
const u8 *sa;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* bssid - Address 3 of the received Action frame
|
|
||||||
*/
|
|
||||||
const u8 *bssid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* category - Action frame category
|
|
||||||
*/
|
|
||||||
u8 category;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* data - Action frame body after category field
|
|
||||||
*/
|
|
||||||
const u8 *data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* len - Length of data in octets
|
|
||||||
*/
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* freq - Frequency (in MHz) on which the frame was received
|
* freq - Frequency (in MHz) on which the frame was received
|
||||||
|
@ -3809,14 +3764,7 @@ union wpa_event_data {
|
||||||
* ssi_signal - Signal strength in dBm (or 0 if not available)
|
* ssi_signal - Signal strength in dBm (or 0 if not available)
|
||||||
*/
|
*/
|
||||||
int ssi_signal;
|
int ssi_signal;
|
||||||
|
} rx_mgmt;
|
||||||
/**
|
|
||||||
* protected - Whether frame was protected (PMF)
|
|
||||||
*
|
|
||||||
* 0 = unknown, 1 = yes, -1 = not
|
|
||||||
*/
|
|
||||||
int protected;
|
|
||||||
} rx_action;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct remain_on_channel - Data for EVENT_REMAIN_ON_CHANNEL events
|
* struct remain_on_channel - Data for EVENT_REMAIN_ON_CHANNEL events
|
||||||
|
|
|
@ -806,16 +806,10 @@ static void atheros_raw_recv_11r(void *ctx, const u8 *src_addr, const u8 *buf,
|
||||||
drv_event_assoc(drv->hapd, mgmt->sa, iebuf, ielen, 1);
|
drv_event_assoc(drv->hapd, mgmt->sa, iebuf, ielen, 1);
|
||||||
break;
|
break;
|
||||||
case WLAN_FC_STYPE_ACTION:
|
case WLAN_FC_STYPE_ACTION:
|
||||||
if (&mgmt->u.action.category > buf + len)
|
|
||||||
break;
|
|
||||||
os_memset(&event, 0, sizeof(event));
|
os_memset(&event, 0, sizeof(event));
|
||||||
event.rx_action.da = mgmt->da;
|
event.rx_mgmt.frame = buf;
|
||||||
event.rx_action.sa = mgmt->sa;
|
event.rx_mgmt.frame_len = len;
|
||||||
event.rx_action.bssid = mgmt->bssid;
|
wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event);
|
||||||
event.rx_action.category = mgmt->u.action.category;
|
|
||||||
event.rx_action.data = &mgmt->u.action.category;
|
|
||||||
event.rx_action.len = buf + len - event.rx_action.data;
|
|
||||||
wpa_supplicant_event(drv->hapd, EVENT_RX_ACTION, &event);
|
|
||||||
break;
|
break;
|
||||||
case WLAN_FC_STYPE_AUTH:
|
case WLAN_FC_STYPE_AUTH:
|
||||||
if (len - IEEE80211_HDRLEN < sizeof(mgmt->u.auth))
|
if (len - IEEE80211_HDRLEN < sizeof(mgmt->u.auth))
|
||||||
|
@ -954,16 +948,10 @@ static void atheros_raw_recv_11v(void *ctx, const u8 *src_addr, const u8 *buf,
|
||||||
|
|
||||||
switch (stype) {
|
switch (stype) {
|
||||||
case WLAN_FC_STYPE_ACTION:
|
case WLAN_FC_STYPE_ACTION:
|
||||||
if (&mgmt->u.action.category > buf + len)
|
|
||||||
break;
|
|
||||||
os_memset(&event, 0, sizeof(event));
|
os_memset(&event, 0, sizeof(event));
|
||||||
event.rx_action.da = mgmt->da;
|
event.rx_mgmt.frame = buf;
|
||||||
event.rx_action.sa = mgmt->sa;
|
event.rx_mgmt.frame_len = len;
|
||||||
event.rx_action.bssid = mgmt->bssid;
|
wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event);
|
||||||
event.rx_action.category = mgmt->u.action.category;
|
|
||||||
event.rx_action.data = &mgmt->u.action.category;
|
|
||||||
event.rx_action.len = buf + len - event.rx_action.data;
|
|
||||||
wpa_supplicant_event(drv->hapd, EVENT_RX_ACTION, &event);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -49,7 +49,6 @@ const char * event_to_string(enum wpa_event_type event)
|
||||||
E2S(TX_STATUS);
|
E2S(TX_STATUS);
|
||||||
E2S(RX_FROM_UNKNOWN);
|
E2S(RX_FROM_UNKNOWN);
|
||||||
E2S(RX_MGMT);
|
E2S(RX_MGMT);
|
||||||
E2S(RX_ACTION);
|
|
||||||
E2S(REMAIN_ON_CHANNEL);
|
E2S(REMAIN_ON_CHANNEL);
|
||||||
E2S(CANCEL_REMAIN_ON_CHANNEL);
|
E2S(CANCEL_REMAIN_ON_CHANNEL);
|
||||||
E2S(MLME_RX);
|
E2S(MLME_RX);
|
||||||
|
|
|
@ -1602,7 +1602,7 @@ static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv,
|
||||||
wpa_printf(MSG_MSGDUMP, "nl80211: Frame event");
|
wpa_printf(MSG_MSGDUMP, "nl80211: Frame event");
|
||||||
mgmt = (const struct ieee80211_mgmt *) frame;
|
mgmt = (const struct ieee80211_mgmt *) frame;
|
||||||
if (len < 24) {
|
if (len < 24) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Too short action frame");
|
wpa_printf(MSG_DEBUG, "nl80211: Too short management frame");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1614,31 +1614,16 @@ static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv,
|
||||||
|
|
||||||
os_memset(&event, 0, sizeof(event));
|
os_memset(&event, 0, sizeof(event));
|
||||||
if (freq) {
|
if (freq) {
|
||||||
event.rx_action.freq = nla_get_u32(freq);
|
event.rx_mgmt.freq = nla_get_u32(freq);
|
||||||
rx_freq = drv->last_mgmt_freq = event.rx_action.freq;
|
rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
|
||||||
}
|
}
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"nl80211: RX frame freq=%d ssi_signal=%d stype=%u len=%u",
|
"nl80211: RX frame freq=%d ssi_signal=%d stype=%u len=%u",
|
||||||
rx_freq, ssi_signal, stype, (unsigned int) len);
|
rx_freq, ssi_signal, stype, (unsigned int) len);
|
||||||
if (stype == WLAN_FC_STYPE_ACTION) {
|
event.rx_mgmt.frame = frame;
|
||||||
event.rx_action.da = mgmt->da;
|
event.rx_mgmt.frame_len = len;
|
||||||
event.rx_action.sa = mgmt->sa;
|
event.rx_mgmt.ssi_signal = ssi_signal;
|
||||||
event.rx_action.bssid = mgmt->bssid;
|
wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
|
||||||
event.rx_action.category = mgmt->u.action.category;
|
|
||||||
event.rx_action.data = &mgmt->u.action.category + 1;
|
|
||||||
event.rx_action.len = frame + len - event.rx_action.data;
|
|
||||||
event.rx_action.ssi_signal = ssi_signal;
|
|
||||||
if (host_to_le16(WLAN_FC_ISWEP) & mgmt->frame_control)
|
|
||||||
event.rx_action.protected = 1;
|
|
||||||
else
|
|
||||||
event.rx_action.protected = -1;
|
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_RX_ACTION, &event);
|
|
||||||
} else {
|
|
||||||
event.rx_mgmt.frame = frame;
|
|
||||||
event.rx_mgmt.frame_len = len;
|
|
||||||
event.rx_mgmt.ssi_signal = ssi_signal;
|
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2707,6 +2707,87 @@ static void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
|
||||||
|
const struct ieee80211_mgmt *mgmt,
|
||||||
|
size_t len, int freq)
|
||||||
|
{
|
||||||
|
const u8 *payload;
|
||||||
|
size_t plen;
|
||||||
|
u8 category;
|
||||||
|
|
||||||
|
if (len < IEEE80211_HDRLEN + 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
payload = &mgmt->u.action.category;
|
||||||
|
category = *payload++;
|
||||||
|
plen = (((const u8 *) mgmt) + len) - payload;
|
||||||
|
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR
|
||||||
|
" Category=%u DataLen=%d freq=%d MHz",
|
||||||
|
MAC2STR(mgmt->sa), category, (int) plen, freq);
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211R
|
||||||
|
if (category == WLAN_ACTION_FT) {
|
||||||
|
ft_rx_action(wpa_s, payload, plen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211W
|
||||||
|
#ifdef CONFIG_SME
|
||||||
|
if (category == WLAN_ACTION_SA_QUERY) {
|
||||||
|
sme_sa_query_rx(wpa_s, mgmt->sa, payload, plen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SME */
|
||||||
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
|
||||||
|
#ifdef CONFIG_WNM
|
||||||
|
if (mgmt->u.action.category == WLAN_ACTION_WNM) {
|
||||||
|
ieee802_11_rx_wnm_action(wpa_s, mgmt, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_WNM */
|
||||||
|
|
||||||
|
#ifdef CONFIG_GAS
|
||||||
|
if (mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
|
||||||
|
gas_query_rx(wpa_s->gas, mgmt->da, mgmt->sa, mgmt->bssid,
|
||||||
|
payload, plen, freq) == 0)
|
||||||
|
return;
|
||||||
|
#endif /* CONFIG_GAS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_TDLS
|
||||||
|
if (category == WLAN_ACTION_PUBLIC && plen >= 4 &&
|
||||||
|
payload[0] == WLAN_TDLS_DISCOVERY_RESPONSE) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
"TDLS: Received Discovery Response from " MACSTR,
|
||||||
|
MAC2STR(mgmt->sa));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TDLS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_INTERWORKING
|
||||||
|
if (category == WLAN_ACTION_QOS && plen >= 1 &&
|
||||||
|
payload[0] == QOS_QOS_MAP_CONFIG) {
|
||||||
|
const u8 *pos = payload + 1;
|
||||||
|
size_t qlen = plen - 1;
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from "
|
||||||
|
MACSTR, MAC2STR(mgmt->sa));
|
||||||
|
if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) == 0 &&
|
||||||
|
qlen > 2 && pos[0] == WLAN_EID_QOS_MAP_SET &&
|
||||||
|
pos[1] <= qlen - 2 && pos[1] >= 16)
|
||||||
|
wpas_qos_map_set(wpa_s, pos + 2, pos[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_INTERWORKING */
|
||||||
|
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
|
||||||
|
category, payload, plen, freq);
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
union wpa_event_data *data)
|
union wpa_event_data *data)
|
||||||
{
|
{
|
||||||
|
@ -2956,7 +3037,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
data->ch_switch.cf2);
|
data->ch_switch.cf2);
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_AP */
|
#endif /* CONFIG_AP */
|
||||||
#if defined(CONFIG_AP) || defined(CONFIG_IBSS_RSN)
|
|
||||||
case EVENT_RX_MGMT: {
|
case EVENT_RX_MGMT: {
|
||||||
u16 fc, stype;
|
u16 fc, stype;
|
||||||
const struct ieee80211_mgmt *mgmt;
|
const struct ieee80211_mgmt *mgmt;
|
||||||
|
@ -2991,6 +3071,14 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IBSS_RSN */
|
#endif /* CONFIG_IBSS_RSN */
|
||||||
|
|
||||||
|
if (stype == WLAN_FC_STYPE_ACTION) {
|
||||||
|
wpas_event_rx_mgmt_action(
|
||||||
|
wpa_s, mgmt, data->rx_mgmt.frame_len,
|
||||||
|
data->rx_mgmt.freq);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "AP: ignore received "
|
wpa_dbg(wpa_s, MSG_DEBUG, "AP: ignore received "
|
||||||
"management frame in non-AP mode");
|
"management frame in non-AP mode");
|
||||||
break;
|
break;
|
||||||
|
@ -3013,79 +3101,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
#endif /* CONFIG_AP */
|
#endif /* CONFIG_AP */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_AP || CONFIG_IBSS_RSN */
|
|
||||||
case EVENT_RX_ACTION:
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR
|
|
||||||
" Category=%u DataLen=%d freq=%d MHz",
|
|
||||||
MAC2STR(data->rx_action.sa),
|
|
||||||
data->rx_action.category, (int) data->rx_action.len,
|
|
||||||
data->rx_action.freq);
|
|
||||||
#ifdef CONFIG_IEEE80211R
|
|
||||||
if (data->rx_action.category == WLAN_ACTION_FT) {
|
|
||||||
ft_rx_action(wpa_s, data->rx_action.data,
|
|
||||||
data->rx_action.len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_IEEE80211R */
|
|
||||||
#ifdef CONFIG_IEEE80211W
|
|
||||||
#ifdef CONFIG_SME
|
|
||||||
if (data->rx_action.category == WLAN_ACTION_SA_QUERY) {
|
|
||||||
sme_sa_query_rx(wpa_s, data->rx_action.sa,
|
|
||||||
data->rx_action.data,
|
|
||||||
data->rx_action.len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_SME */
|
|
||||||
#endif /* CONFIG_IEEE80211W */
|
|
||||||
#ifdef CONFIG_WNM
|
|
||||||
if (data->rx_action.category == WLAN_ACTION_WNM) {
|
|
||||||
ieee802_11_rx_wnm_action(wpa_s, &data->rx_action);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_WNM */
|
|
||||||
#ifdef CONFIG_GAS
|
|
||||||
if (data->rx_action.category == WLAN_ACTION_PUBLIC &&
|
|
||||||
gas_query_rx(wpa_s->gas, data->rx_action.da,
|
|
||||||
data->rx_action.sa, data->rx_action.bssid,
|
|
||||||
data->rx_action.data, data->rx_action.len,
|
|
||||||
data->rx_action.freq) == 0)
|
|
||||||
break;
|
|
||||||
#endif /* CONFIG_GAS */
|
|
||||||
#ifdef CONFIG_TDLS
|
|
||||||
if (data->rx_action.category == WLAN_ACTION_PUBLIC &&
|
|
||||||
data->rx_action.len >= 4 &&
|
|
||||||
data->rx_action.data[0] == WLAN_TDLS_DISCOVERY_RESPONSE) {
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "TDLS: Received Discovery "
|
|
||||||
"Response from " MACSTR,
|
|
||||||
MAC2STR(data->rx_action.sa));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_TDLS */
|
|
||||||
#ifdef CONFIG_INTERWORKING
|
|
||||||
if (data->rx_action.category == WLAN_ACTION_QOS &&
|
|
||||||
data->rx_action.len >= 1 &&
|
|
||||||
data->rx_action.data[0] == QOS_QOS_MAP_CONFIG) {
|
|
||||||
const u8 *pos = data->rx_action.data + 1;
|
|
||||||
size_t len = data->rx_action.len - 1;
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from "
|
|
||||||
MACSTR, MAC2STR(data->rx_action.sa));
|
|
||||||
if (os_memcmp(data->rx_action.sa, wpa_s->bssid,
|
|
||||||
ETH_ALEN) == 0 &&
|
|
||||||
len > 2 && pos[0] == WLAN_EID_QOS_MAP_SET &&
|
|
||||||
pos[1] <= len - 2 && pos[1] >= 16)
|
|
||||||
wpas_qos_map_set(wpa_s, pos + 2, pos[1]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_INTERWORKING */
|
|
||||||
#ifdef CONFIG_P2P
|
|
||||||
wpas_p2p_rx_action(wpa_s, data->rx_action.da,
|
|
||||||
data->rx_action.sa,
|
|
||||||
data->rx_action.bssid,
|
|
||||||
data->rx_action.category,
|
|
||||||
data->rx_action.data,
|
|
||||||
data->rx_action.len, data->rx_action.freq);
|
|
||||||
#endif /* CONFIG_P2P */
|
|
||||||
break;
|
|
||||||
case EVENT_RX_PROBE_REQ:
|
case EVENT_RX_PROBE_REQ:
|
||||||
if (data->rx_probe_req.sa == NULL ||
|
if (data->rx_probe_req.sa == NULL ||
|
||||||
data->rx_probe_req.ie == NULL)
|
data->rx_probe_req.ie == NULL)
|
||||||
|
|
|
@ -181,7 +181,7 @@ static void wnm_sleep_mode_exit_success(struct wpa_supplicant *wpa_s,
|
||||||
/* Install GTK/IGTK */
|
/* Install GTK/IGTK */
|
||||||
|
|
||||||
/* point to key data field */
|
/* point to key data field */
|
||||||
ptr = (u8 *) frm + 1 + 1 + 2;
|
ptr = (u8 *) frm + 1 + 2;
|
||||||
end = ptr + key_len_total;
|
end = ptr + key_len_total;
|
||||||
wpa_hexdump_key(MSG_DEBUG, "WNM: Key Data", ptr, key_len_total);
|
wpa_hexdump_key(MSG_DEBUG, "WNM: Key Data", ptr, key_len_total);
|
||||||
|
|
||||||
|
@ -237,16 +237,16 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_supplicant *wpa_s,
|
||||||
* Action [1] | Diaglog Token [1] | Key Data Len [2] | Key Data |
|
* Action [1] | Diaglog Token [1] | Key Data Len [2] | Key Data |
|
||||||
* WNM-Sleep Mode IE | TFS Response IE
|
* WNM-Sleep Mode IE | TFS Response IE
|
||||||
*/
|
*/
|
||||||
u8 *pos = (u8 *) frm; /* point to action field */
|
u8 *pos = (u8 *) frm; /* point to payload after the action field */
|
||||||
u16 key_len_total = le_to_host16(*((u16 *)(frm+2)));
|
u16 key_len_total = le_to_host16(*((u16 *)(frm+2)));
|
||||||
struct wnm_sleep_element *wnmsleep_ie = NULL;
|
struct wnm_sleep_element *wnmsleep_ie = NULL;
|
||||||
/* multiple TFS Resp IE (assuming consecutive) */
|
/* multiple TFS Resp IE (assuming consecutive) */
|
||||||
u8 *tfsresp_ie_start = NULL;
|
u8 *tfsresp_ie_start = NULL;
|
||||||
u8 *tfsresp_ie_end = NULL;
|
u8 *tfsresp_ie_end = NULL;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "action=%d token = %d key_len_total = %d",
|
wpa_printf(MSG_DEBUG, "WNM-Sleep Mode Response token=%u key_len_total=%d",
|
||||||
frm[0], frm[1], key_len_total);
|
frm[0], key_len_total);
|
||||||
pos += 4 + key_len_total;
|
pos += 3 + key_len_total;
|
||||||
if (pos > frm + len) {
|
if (pos > frm + len) {
|
||||||
wpa_printf(MSG_INFO, "WNM: Too short frame for Key Data field");
|
wpa_printf(MSG_INFO, "WNM: Too short frame for Key Data field");
|
||||||
return;
|
return;
|
||||||
|
@ -752,22 +752,23 @@ int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
|
|
||||||
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
|
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
|
||||||
struct rx_action *action)
|
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||||
{
|
{
|
||||||
const u8 *pos, *end;
|
const u8 *pos, *end;
|
||||||
u8 act;
|
u8 act;
|
||||||
|
|
||||||
if (action->data == NULL || action->len == 0)
|
if (len < IEEE80211_HDRLEN + 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pos = action->data;
|
pos = &mgmt->u.action.category;
|
||||||
end = pos + action->len;
|
pos++;
|
||||||
act = *pos++;
|
act = *pos++;
|
||||||
|
end = ((const u8 *) mgmt) + len;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WNM: RX action %u from " MACSTR,
|
wpa_printf(MSG_DEBUG, "WNM: RX action %u from " MACSTR,
|
||||||
act, MAC2STR(action->sa));
|
act, MAC2STR(mgmt->sa));
|
||||||
if (wpa_s->wpa_state < WPA_ASSOCIATED ||
|
if (wpa_s->wpa_state < WPA_ASSOCIATED ||
|
||||||
os_memcmp(action->sa, wpa_s->bssid, ETH_ALEN) != 0) {
|
os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0) {
|
||||||
wpa_printf(MSG_DEBUG, "WNM: Ignore unexpected WNM Action "
|
wpa_printf(MSG_DEBUG, "WNM: Ignore unexpected WNM Action "
|
||||||
"frame");
|
"frame");
|
||||||
return;
|
return;
|
||||||
|
@ -776,10 +777,10 @@ void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
|
||||||
switch (act) {
|
switch (act) {
|
||||||
case WNM_BSS_TRANS_MGMT_REQ:
|
case WNM_BSS_TRANS_MGMT_REQ:
|
||||||
ieee802_11_rx_bss_trans_mgmt_req(wpa_s, pos, end,
|
ieee802_11_rx_bss_trans_mgmt_req(wpa_s, pos, end,
|
||||||
!(action->da[0] & 0x01));
|
!(mgmt->da[0] & 0x01));
|
||||||
break;
|
break;
|
||||||
case WNM_SLEEP_MODE_RESP:
|
case WNM_SLEEP_MODE_RESP:
|
||||||
ieee802_11_rx_wnmsleep_resp(wpa_s, action->data, action->len);
|
ieee802_11_rx_wnmsleep_resp(wpa_s, pos, end - pos);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_ERROR, "WNM: Unknown request");
|
wpa_printf(MSG_ERROR, "WNM: Unknown request");
|
||||||
|
|
|
@ -9,9 +9,6 @@
|
||||||
#ifndef WNM_STA_H
|
#ifndef WNM_STA_H
|
||||||
#define WNM_STA_H
|
#define WNM_STA_H
|
||||||
|
|
||||||
struct rx_action;
|
|
||||||
struct wpa_supplicant;
|
|
||||||
|
|
||||||
struct tsf_info {
|
struct tsf_info {
|
||||||
u8 present;
|
u8 present;
|
||||||
u8 tsf_offset[2];
|
u8 tsf_offset[2];
|
||||||
|
@ -78,7 +75,7 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
|
||||||
u8 action, u16 intval, struct wpabuf *tfs_req);
|
u8 action, u16 intval, struct wpabuf *tfs_req);
|
||||||
|
|
||||||
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
|
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
|
||||||
struct rx_action *action);
|
const struct ieee80211_mgmt *mgmt, size_t len);
|
||||||
|
|
||||||
void wnm_scan_response(struct wpa_supplicant *wpa_s,
|
void wnm_scan_response(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_scan_results *scan_res);
|
struct wpa_scan_results *scan_res);
|
||||||
|
|
Loading…
Reference in a new issue