AP: Add explicit EAPOL TX status event
The new event can be used when EAPOL TX status can't be reported as a complete 802.11 frame but is instead reported as just the EAPOL data as originally passed to hapd_send_eapol(). Signed-hostap: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
6589774746
commit
dd840f793c
10 changed files with 95 additions and 10 deletions
|
@ -504,6 +504,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EVENT_EAPOL_TX_STATUS:
|
||||||
|
hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
|
||||||
|
data->eapol_tx_status.data,
|
||||||
|
data->eapol_tx_status.data_len,
|
||||||
|
data->eapol_tx_status.ack);
|
||||||
|
break;
|
||||||
case EVENT_DRIVER_CLIENT_POLL_OK:
|
case EVENT_DRIVER_CLIENT_POLL_OK:
|
||||||
hostapd_client_poll_ok(hapd, data->client_poll.addr);
|
hostapd_client_poll_ok(hapd, data->client_poll.addr);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1733,6 +1733,29 @@ void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||||
|
const u8 *data, size_t len, int ack)
|
||||||
|
{
|
||||||
|
struct sta_info *sta;
|
||||||
|
struct hostapd_iface *iface = hapd->iface;
|
||||||
|
|
||||||
|
sta = ap_get_sta(hapd, dst);
|
||||||
|
if (sta == NULL && iface->num_bss > 1) {
|
||||||
|
size_t j;
|
||||||
|
for (j = 0; j < iface->num_bss; j++) {
|
||||||
|
hapd = iface->bss[j];
|
||||||
|
sta = ap_get_sta(hapd, dst);
|
||||||
|
if (sta)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sta == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
|
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
|
||||||
{
|
{
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
|
|
@ -62,6 +62,8 @@ u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
|
void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
|
||||||
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||||
const u8 *buf, size_t len, int ack);
|
const u8 *buf, size_t len, int ack);
|
||||||
|
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||||
|
const u8 *data, size_t len, int ack);
|
||||||
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
|
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
|
||||||
int wds);
|
int wds);
|
||||||
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
|
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
|
||||||
|
|
|
@ -1766,15 +1766,13 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
const u8 *buf, size_t len, int ack)
|
const u8 *buf, size_t len, int ack)
|
||||||
{
|
{
|
||||||
struct ieee80211_hdr *hdr;
|
struct ieee80211_hdr *hdr;
|
||||||
struct ieee802_1x_hdr *xhdr;
|
|
||||||
struct ieee802_1x_eapol_key *key;
|
|
||||||
u8 *pos;
|
u8 *pos;
|
||||||
const unsigned char rfc1042_hdr[ETH_ALEN] =
|
const unsigned char rfc1042_hdr[ETH_ALEN] =
|
||||||
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
if (sta == NULL)
|
if (sta == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2 + sizeof(*xhdr))
|
if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *) buf;
|
hdr = (struct ieee80211_hdr *) buf;
|
||||||
|
@ -1786,16 +1784,30 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
return 0;
|
return 0;
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
xhdr = (struct ieee802_1x_hdr *) pos;
|
return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos,
|
||||||
pos += sizeof(*xhdr);
|
ack);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
const u8 *buf, int len, int ack)
|
||||||
|
{
|
||||||
|
const struct ieee802_1x_hdr *xhdr =
|
||||||
|
(const struct ieee802_1x_hdr *) buf;
|
||||||
|
const u8 *pos = buf + sizeof(*xhdr);
|
||||||
|
struct ieee802_1x_eapol_key *key;
|
||||||
|
|
||||||
|
if (len < (int) sizeof(*xhdr))
|
||||||
|
return 0;
|
||||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d "
|
wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d "
|
||||||
"type=%d length=%d - ack=%d",
|
"type=%d length=%d - ack=%d",
|
||||||
MAC2STR(sta->addr), xhdr->version, xhdr->type,
|
MAC2STR(sta->addr), xhdr->version, xhdr->type,
|
||||||
be_to_host16(xhdr->length), ack);
|
be_to_host16(xhdr->length), ack);
|
||||||
|
|
||||||
if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY &&
|
if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY)
|
||||||
pos + sizeof(struct wpa_eapol_key) <= buf + len) {
|
return 0;
|
||||||
|
|
||||||
|
if (pos + sizeof(struct wpa_eapol_key) <= buf + len) {
|
||||||
const struct wpa_eapol_key *wpa;
|
const struct wpa_eapol_key *wpa;
|
||||||
wpa = (const struct wpa_eapol_key *) pos;
|
wpa = (const struct wpa_eapol_key *) pos;
|
||||||
if (wpa->type == EAPOL_KEY_TYPE_RSN ||
|
if (wpa->type == EAPOL_KEY_TYPE_RSN ||
|
||||||
|
@ -1809,8 +1821,7 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
* retransmitted in case of failure. Try to re-send failed EAPOL-Key
|
* retransmitted in case of failure. Try to re-send failed EAPOL-Key
|
||||||
* packets couple of times because otherwise STA keys become
|
* packets couple of times because otherwise STA keys become
|
||||||
* unsynchronized with AP. */
|
* unsynchronized with AP. */
|
||||||
if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack &&
|
if (!ack && pos + sizeof(*key) <= buf + len) {
|
||||||
pos + sizeof(*key) <= buf + len) {
|
|
||||||
key = (struct ieee802_1x_eapol_key *) pos;
|
key = (struct ieee802_1x_eapol_key *) pos;
|
||||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||||
HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key "
|
HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key "
|
||||||
|
|
|
@ -68,6 +68,8 @@ int ieee802_1x_init(struct hostapd_data *hapd);
|
||||||
void ieee802_1x_deinit(struct hostapd_data *hapd);
|
void ieee802_1x_deinit(struct hostapd_data *hapd);
|
||||||
int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
const u8 *buf, size_t len, int ack);
|
const u8 *buf, size_t len, int ack);
|
||||||
|
int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
const u8 *data, int len, int ack);
|
||||||
u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len);
|
u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len);
|
||||||
u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
|
u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
|
||||||
int idx);
|
int idx);
|
||||||
|
|
|
@ -2877,7 +2877,12 @@ enum wpa_event_type {
|
||||||
* This event indicates that the station responded to the poll
|
* This event indicates that the station responded to the poll
|
||||||
* initiated with @poll_client.
|
* initiated with @poll_client.
|
||||||
*/
|
*/
|
||||||
EVENT_DRIVER_CLIENT_POLL_OK
|
EVENT_DRIVER_CLIENT_POLL_OK,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVENT_EAPOL_TX_STATUS - notify of EAPOL TX status
|
||||||
|
*/
|
||||||
|
EVENT_EAPOL_TX_STATUS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -3440,6 +3445,23 @@ union wpa_event_data {
|
||||||
struct client_poll {
|
struct client_poll {
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
} client_poll;
|
} client_poll;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct eapol_tx_status
|
||||||
|
* @dst: Original destination
|
||||||
|
* @data: Data starting with IEEE 802.1X header (!)
|
||||||
|
* @data_len: Length of data
|
||||||
|
* @ack: Indicates ack or lost frame
|
||||||
|
*
|
||||||
|
* This corresponds to hapd_send_eapol if the frame sent
|
||||||
|
* there isn't just reported as EVENT_TX_STATUS.
|
||||||
|
*/
|
||||||
|
struct eapol_tx_status {
|
||||||
|
const u8 *dst;
|
||||||
|
const u8 *data;
|
||||||
|
int data_len;
|
||||||
|
int ack;
|
||||||
|
} eapol_tx_status;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -82,6 +82,7 @@ const char * event_to_string(enum wpa_event_type event)
|
||||||
E2S(DRIVER_GTK_REKEY);
|
E2S(DRIVER_GTK_REKEY);
|
||||||
E2S(SCHED_SCAN_STOPPED);
|
E2S(SCHED_SCAN_STOPPED);
|
||||||
E2S(DRIVER_CLIENT_POLL_OK);
|
E2S(DRIVER_CLIENT_POLL_OK);
|
||||||
|
E2S(EAPOL_TX_STATUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
|
|
|
@ -564,6 +564,16 @@ void ap_tx_status(void *ctx, const u8 *addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ap_eapol_tx_status(void *ctx, const u8 *dst,
|
||||||
|
const u8 *data, size_t len, int ack)
|
||||||
|
{
|
||||||
|
#ifdef NEED_AP_MLME
|
||||||
|
struct wpa_supplicant *wpa_s = ctx;
|
||||||
|
hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack);
|
||||||
|
#endif /* NEED_AP_MLME */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ap_client_poll_ok(void *ctx, const u8 *addr)
|
void ap_client_poll_ok(void *ctx, const u8 *addr)
|
||||||
{
|
{
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
|
|
|
@ -41,6 +41,8 @@ int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
|
||||||
size_t buflen, int verbose);
|
size_t buflen, int verbose);
|
||||||
void ap_tx_status(void *ctx, const u8 *addr,
|
void ap_tx_status(void *ctx, const u8 *addr,
|
||||||
const u8 *buf, size_t len, int ack);
|
const u8 *buf, size_t len, int ack);
|
||||||
|
void ap_eapol_tx_status(void *ctx, const u8 *dst,
|
||||||
|
const u8 *data, size_t len, int ack);
|
||||||
void ap_client_poll_ok(void *ctx, const u8 *addr);
|
void ap_client_poll_ok(void *ctx, const u8 *addr);
|
||||||
void ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds);
|
void ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds);
|
||||||
void ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt);
|
void ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt);
|
||||||
|
|
|
@ -2158,6 +2158,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
#endif /* CONFIG_AP */
|
#endif /* CONFIG_AP */
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_AP
|
#ifdef CONFIG_AP
|
||||||
|
case EVENT_EAPOL_TX_STATUS:
|
||||||
|
ap_eapol_tx_status(wpa_s, data->eapol_tx_status.dst,
|
||||||
|
data->eapol_tx_status.data,
|
||||||
|
data->eapol_tx_status.data_len,
|
||||||
|
data->eapol_tx_status.ack);
|
||||||
|
break;
|
||||||
case EVENT_DRIVER_CLIENT_POLL_OK:
|
case EVENT_DRIVER_CLIENT_POLL_OK:
|
||||||
ap_client_poll_ok(wpa_s, data->client_poll.addr);
|
ap_client_poll_ok(wpa_s, data->client_poll.addr);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue