]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Fix offchannel TX not to retransmit pending frame on callback
authorJouni Malinen <jouni@qca.qualcomm.com>
Tue, 3 Jun 2014 12:35:01 +0000 (15:35 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 4 Jun 2014 13:07:59 +0000 (16:07 +0300)
If the offchannel TX frame command was offloaded to the driver in
offchannel_send_action(), we must not send another copy of the frame if
a remain-on-channel event happens to be delivered between this TX
command and the matching TX status event. It was possible for the
duplicated frame to cause problems, e.g., with P2P invitation exchange
if the same Invitation Request frame got sent twice and only the first
one getting accepted by the peer.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
wpa_supplicant/offchannel.c
wpa_supplicant/wpa_supplicant_i.h

index 40cbea1dba4b91455b4e96887cb19d0073e11a60..77683b618eee31a02baf9429f74798599db604d5 100644 (file)
@@ -55,11 +55,12 @@ static void wpas_send_action_cb(void *eloop_ctx, void *timeout_ctx)
 
        without_roc = wpa_s->pending_action_without_roc;
        wpa_s->pending_action_without_roc = 0;
-       wpa_printf(MSG_DEBUG, "Off-channel: Send Action callback "
-                  "(without_roc=%d pending_action_tx=%p)",
-                  without_roc, wpa_s->pending_action_tx);
+       wpa_printf(MSG_DEBUG,
+                  "Off-channel: Send Action callback (without_roc=%d pending_action_tx=%p pending_action_tx_done=%d)",
+                  without_roc, wpa_s->pending_action_tx,
+                  !!wpa_s->pending_action_tx_done);
 
-       if (wpa_s->pending_action_tx == NULL)
+       if (wpa_s->pending_action_tx == NULL || wpa_s->pending_action_tx_done)
                return;
 
        /*
@@ -235,6 +236,7 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
                           MAC2STR(wpa_s->pending_action_dst));
                wpabuf_free(wpa_s->pending_action_tx);
        }
+       wpa_s->pending_action_tx_done = 0;
        wpa_s->pending_action_tx = wpabuf_alloc(len);
        if (wpa_s->pending_action_tx == NULL) {
                wpa_printf(MSG_DEBUG, "Off-channel: Failed to allocate Action "
@@ -251,18 +253,22 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
 
        if (freq != 0 && wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) {
                struct wpa_supplicant *iface;
+               int ret;
 
                iface = wpas_get_tx_interface(wpa_s,
                                              wpa_s->pending_action_src);
                wpa_s->action_tx_wait_time = wait_time;
 
-               return wpa_drv_send_action(
+               ret = wpa_drv_send_action(
                        iface, wpa_s->pending_action_freq,
                        wait_time, wpa_s->pending_action_dst,
                        wpa_s->pending_action_src, wpa_s->pending_action_bssid,
                        wpabuf_head(wpa_s->pending_action_tx),
                        wpabuf_len(wpa_s->pending_action_tx),
                        wpa_s->pending_action_no_cck);
+               if (ret == 0)
+                       wpa_s->pending_action_tx_done = 1;
+               return ret;
        }
 
        if (freq) {
index 3ae439dcb6ce912320832075be83cfc41bb24f0d..a83c8cdf315e2b8c923abbcba5cf462a323165ac 100644 (file)
@@ -654,6 +654,7 @@ struct wpa_supplicant {
        unsigned int pending_action_freq;
        int pending_action_no_cck;
        int pending_action_without_roc;
+       unsigned int pending_action_tx_done:1;
        void (*pending_action_tx_status_cb)(struct wpa_supplicant *wpa_s,
                                            unsigned int freq, const u8 *dst,
                                            const u8 *src, const u8 *bssid,