ath9k: always set common->macaddr to the MAC adress of a virtual interface
authorFelix Fietkau <nbd@openwrt.org>
Tue, 16 Apr 2013 10:51:57 +0000 (12:51 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 22 Apr 2013 19:20:15 +0000 (15:20 -0400)
In some cases it can be useful to change the MAC address of a virtual
interface to something that's completely different from the EEPROM
stored MAC address. In this case it is a bad idea to use the EEPROM MAC
address for calculating the BSSID mask, as that would make it too wide.

In one case a few devices have been observed to send ACKs for many
packets on the channel not directed at them, which results in a neat
Denial of Service attack on the channel.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/main.c

index 86d35726edb423cbc4e4c42810654df27b108f81..1915f12328b3e8d50be163f0180092bc4c25bd17 100644 (file)
@@ -658,11 +658,10 @@ enum sc_op_flags {
 struct ath_rate_table;
 
 struct ath9k_vif_iter_data {
-       const u8 *hw_macaddr; /* phy's hardware address, set
-                              * before starting iteration for
-                              * valid bssid mask.
-                              */
+       u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
        u8 mask[ETH_ALEN]; /* bssid mask */
+       bool has_hw_macaddr;
+
        int naps;      /* number of AP vifs */
        int nmeshes;   /* number of mesh vifs */
        int nstations; /* number of station vifs */
index a383483d03878d7f0908408e55ffd4a1a5c885be..6963862a187275601b11a8270e3ecd7e6d2b995a 100644 (file)
@@ -839,10 +839,14 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
        struct ath9k_vif_iter_data *iter_data = data;
        int i;
 
-       if (iter_data->hw_macaddr)
+       if (iter_data->has_hw_macaddr) {
                for (i = 0; i < ETH_ALEN; i++)
                        iter_data->mask[i] &=
                                ~(iter_data->hw_macaddr[i] ^ mac[i]);
+       } else {
+               memcpy(iter_data->hw_macaddr, mac, ETH_ALEN);
+               iter_data->has_hw_macaddr = true;
+       }
 
        switch (vif->type) {
        case NL80211_IFTYPE_AP:
@@ -891,7 +895,6 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
         * together with the BSSID mask when matching addresses.
         */
        memset(iter_data, 0, sizeof(*iter_data));
-       iter_data->hw_macaddr = common->macaddr;
        memset(&iter_data->mask, 0xff, ETH_ALEN);
 
        if (vif)
@@ -901,6 +904,8 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
        ieee80211_iterate_active_interfaces_atomic(
                sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
                ath9k_vif_iter, iter_data);
+
+       memcpy(common->macaddr, iter_data->hw_macaddr, ETH_ALEN);
 }
 
 /* Called with sc->mutex held. */