]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP: Add explicit EAPOL TX status event
authorJohannes Berg <johannes.berg@intel.com>
Sat, 19 Nov 2011 11:00:30 +0000 (13:00 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 19 Nov 2011 11:00:30 +0000 (13:00 +0200)
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>

src/ap/drv_callbacks.c
src/ap/ieee802_11.c
src/ap/ieee802_11.h
src/ap/ieee802_1x.c
src/ap/ieee802_1x.h
src/drivers/driver.h
src/drivers/driver_common.c
wpa_supplicant/ap.c
wpa_supplicant/ap.h
wpa_supplicant/events.c

index 3b6c57c4564c98e796a0d4b6a795aa54d2edc38a..299357085fcb4b6d5536b894091ceff22c1f9bc3 100644 (file)
@@ -504,6 +504,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                        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:
                hostapd_client_poll_ok(hapd, data->client_poll.addr);
                break;
index 108261a03507ca74676604967a9eb56ce63063a1..e1d816980432f4eb52cecdec48004ee562985068 100644 (file)
@@ -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)
 {
        struct sta_info *sta;
index b3580600865aa78b3fe31d99cbde48c494eb1d20..43042a503c27d41d1614ed4f644c0025f0ddd6ab 100644 (file)
@@ -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 hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
                       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,
                                int wds);
 u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
index dc0c39af9fd461e2370ff7d82071973f3195b823..0cf7f2c58a2cddd11ec14ccc8a9ac5e4229f64c6 100644 (file)
@@ -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)
 {
        struct ieee80211_hdr *hdr;
-       struct ieee802_1x_hdr *xhdr;
-       struct ieee802_1x_eapol_key *key;
        u8 *pos;
        const unsigned char rfc1042_hdr[ETH_ALEN] =
                { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 
        if (sta == NULL)
                return -1;
-       if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2 + sizeof(*xhdr))
+       if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2)
                return 0;
 
        hdr = (struct ieee80211_hdr *) buf;
@@ -1786,16 +1784,30 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
                return 0;
        pos += 2;
 
-       xhdr = (struct ieee802_1x_hdr *) pos;
-       pos += sizeof(*xhdr);
+       return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos,
+                                         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 "
                   "type=%d length=%d - ack=%d",
                   MAC2STR(sta->addr), xhdr->version, xhdr->type,
                   be_to_host16(xhdr->length), ack);
 
-       if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY &&
-           pos + sizeof(struct wpa_eapol_key) <= buf + len) {
+       if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY)
+               return 0;
+
+       if (pos + sizeof(struct wpa_eapol_key) <= buf + len) {
                const struct wpa_eapol_key *wpa;
                wpa = (const struct wpa_eapol_key *) pos;
                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
         * packets couple of times because otherwise STA keys become
         * unsynchronized with AP. */
-       if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack &&
-           pos + sizeof(*key) <= buf + len) {
+       if (!ack && pos + sizeof(*key) <= buf + len) {
                key = (struct ieee802_1x_eapol_key *) pos;
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
                               HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key "
index 1a4d2eb0f2c10b9e60338a2b03c8661396b66500..267e22a4b807545ca5b851db52a1b22dbb02eec2 100644 (file)
@@ -68,6 +68,8 @@ int ieee802_1x_init(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,
                         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_radius_class(struct eapol_state_machine *sm, size_t *len,
                                 int idx);
index bd0c611784e5b38050bfe2d4d3bfaf6e6d455621..dbf3c6e047aaab48e1b6db400ef2a8a99a67635b 100644 (file)
@@ -2877,7 +2877,12 @@ enum wpa_event_type {
         * This event indicates that the station responded to the poll
         * 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 {
                u8 addr[ETH_ALEN];
        } 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;
 };
 
 /**
index 009a9832d38d576c9cb04f4386d599fe83cdd8e4..26ca8d6295da63b1f40dfa38aa2010dc6f5eb5b4 100644 (file)
@@ -82,6 +82,7 @@ const char * event_to_string(enum wpa_event_type event)
        E2S(DRIVER_GTK_REKEY);
        E2S(SCHED_SCAN_STOPPED);
        E2S(DRIVER_CLIENT_POLL_OK);
+       E2S(EAPOL_TX_STATUS);
        }
 
        return "UNKNOWN";
index 91c9126ab3eb222f16854f3315e6797b43898468..7acbefe56c65985aa0442b8befeafdf0f6b8599e 100644 (file)
@@ -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)
 {
 #ifdef NEED_AP_MLME
index 567e784e594d220acaf3175d1d72ffb4ba565178..aa4c362c2afd265f1e46b5b8d2b85b29d0a4fac8 100644 (file)
@@ -41,6 +41,8 @@ int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
                                 size_t buflen, int verbose);
 void ap_tx_status(void *ctx, const u8 *addr,
                  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_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds);
 void ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt);
index b2e95eec9a1b0e491eef2054a45a951de2270b5c..70106003e54165a8b96ccb25ff200cff92358d8b 100644 (file)
@@ -2158,6 +2158,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 #endif /* CONFIG_AP */
                break;
 #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:
                ap_client_poll_ok(wpa_s, data->client_poll.addr);
                break;