From 9036ca22a57e98db98ef661f3e79ad3b3a482a38 Mon Sep 17 00:00:00 2001 From: Alexander Egorenkov Date: Fri, 12 Mar 2010 13:02:51 +0100 Subject: [PATCH] Update WCID attribute for group key in HOSTAP mode; Reset WCID attribute in HOSTAP mode during key deleting; Key setting/deleting functions should return 0 on failure; Added constants RT2860_WCID_RESERVED and RT2860_WCID_MCAST; Test for WCID 0(mcast/bcast) during new association and key setting/deleting --- rt2860.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 88 insertions(+), 32 deletions(-) diff --git a/rt2860.c b/rt2860.c index d1f2ab4..3bb1a83 100644 --- a/rt2860.c +++ b/rt2860.c @@ -59,6 +59,9 @@ #define RT2860_TX_WATCHDOG_TIMEOUT 5 +#define RT2860_WCID_RESERVED 0xff +#define RT2860_WCID_MCAST 0x00 + /* * Data structures and types */ @@ -1302,10 +1305,6 @@ static void rt2860_init_locked(void *priv) rt2860_asic_updateprot(sc); - /* clear key tables */ - - rt2860_asic_clear_keytables(sc); - /* clear beacon frame space (entries = 8, entry size = 512) */ rt2860_io_mac_set_region_4(sc, RT2860_REG_BEACON_BASE(0), 0, 1024); @@ -2009,25 +2008,25 @@ static void rt2860_newassoc(struct ieee80211_node *ni, int isnew) struct rt2860_softc *sc; struct ieee80211com *ic; struct ifnet *ifp; - uint16_t associd; uint8_t wcid; ic = ni->ni_ic; ifp = ic->ic_ifp; sc = ifp->if_softc; - associd = (ni != NULL) ? ni->ni_associd : 0; - wcid = RT2860_AID2WCID(associd); - RT2860_DPRINTF(sc, RT2860_DEBUG_NODE, - "%s: new association: wcid=0x%02x, " + "%s: new association: associd=0x%04x, " "mac addr=%s, QoS %s, ERP %s, HT %s\n", - device_get_nameunit(sc->dev), wcid, + device_get_nameunit(sc->dev), ni->ni_associd, ether_sprintf(ni->ni_macaddr), (ni->ni_flags & IEEE80211_NODE_QOS) ? "enabled" : "disabled", (ni->ni_flags & IEEE80211_NODE_ERP) ? "enabled" : "disabled", (ni->ni_flags & IEEE80211_NODE_HT) ? "enabled" : "disabled"); + wcid = RT2860_AID2WCID(ni->ni_associd); + if (wcid == 0) + return; + rt2860_io_mac_write_multi(sc, RT2860_REG_WCID(wcid), ni->ni_macaddr, IEEE80211_ADDR_LEN); @@ -2160,19 +2159,14 @@ static int rt2860_key_set(struct ieee80211com *ic, if (k->wk_cipher->ic_cipher != IEEE80211_CIPHER_WEP && k->wk_cipher->ic_cipher != IEEE80211_CIPHER_TKIP && k->wk_cipher->ic_cipher != IEEE80211_CIPHER_AES_CCM) - return EINVAL; + return 0; ifp = ic->ic_ifp; sc = ifp->if_softc; - - if (ic->ic_opmode != IEEE80211_M_HOSTAP) - ni = ic->ic_bss; - else - ni = ieee80211_find_node(&ic->ic_sta, mac); - + ni = ieee80211_find_node(&ic->ic_sta, mac); associd = (ni != NULL) ? ni->ni_associd : 0; - if ((ic->ic_opmode == IEEE80211_M_HOSTAP) && (ni != NULL)) + if (ni != NULL) ieee80211_free_node(ni); switch (k->wk_cipher->ic_cipher) @@ -2193,20 +2187,24 @@ static int rt2860_key_set(struct ieee80211com *ic, break; default: - return EINVAL; + return 0; } RT2860_DPRINTF(sc, RT2860_DEBUG_KEY, - "%s: set key: keyix=%d, keylen=%d, associd=0x%04x, mode=%d, group=%d\n", - device_get_nameunit(sc->dev), k->wk_keyix, k->wk_keylen, associd, mode, - (k->wk_flags & IEEE80211_KEY_GROUP) ? 1 : 0); + "%s: set key: keyix=%d, keylen=%d, macaddr=%s, associd=0x%04x, mode=%d, group=%d\n", + device_get_nameunit(sc->dev), k->wk_keyix, k->wk_keylen, ether_sprintf(mac), + associd, mode, (k->wk_flags & IEEE80211_KEY_GROUP) ? 1 : 0); if (!(k->wk_flags & IEEE80211_KEY_GROUP)) { /* install pairwise key */ vapid = 0; + wcid = RT2860_AID2WCID(associd); + if (wcid == 0) + return 0; + key_base = RT2860_REG_PKEY(wcid); if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_WEP) @@ -2270,6 +2268,8 @@ static int rt2860_key_set(struct ieee80211com *ic, (mode << RT2860_REG_CIPHER_MODE_SHIFT) | RT2860_REG_PKEY_ENABLE; rt2860_io_mac_write(sc, RT2860_REG_WCID_ATTR(wcid), tmp); + + k->wk_pad = wcid; } if ((k->wk_flags & IEEE80211_KEY_GROUP) || @@ -2278,6 +2278,7 @@ static int rt2860_key_set(struct ieee80211com *ic, /* install group key */ vapid = 0; + wcid = RT2860_WCID_MCAST; key_base = RT2860_REG_SKEY(vapid, k->wk_keyix); keymode_base = RT2860_REG_SKEY_MODE(vapid); @@ -2307,6 +2308,51 @@ static int rt2860_key_set(struct ieee80211com *ic, tmp |= (mode << (k->wk_keyix * 4 + 16 * (vapid % 2))); rt2860_io_mac_write(sc, keymode_base, tmp); + + if (ic->ic_opmode == IEEE80211_M_HOSTAP) + { + if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_WEP) + { + memset(iv, 0, 8); + + iv[3] = (k->wk_keyix << 6); + } + else + { + if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) + { + iv[0] = (k->wk_keytsc >> 8); + iv[1] = ((iv[0] | 0x20) & 0x7f); + iv[2] = k->wk_keytsc; + } + else + { + /* AES CCMP */ + + iv[0] = k->wk_keytsc; + iv[1] = k->wk_keytsc >> 8; + iv[2] = 0; + } + + iv[3] = ((k->wk_keyix << 6) | IEEE80211_WEP_EXTIV); + iv[4] = (k->wk_keytsc >> 16); + iv[5] = (k->wk_keytsc >> 24); + iv[6] = (k->wk_keytsc >> 32); + iv[7] = (k->wk_keytsc >> 40); + + RT2860_DPRINTF(sc, RT2860_DEBUG_KEY, + "%s: set key: iv=%02x %02x %02x %02x %02x %02x %02x %02x\n", + device_get_nameunit(sc->dev), + iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]); + } + + rt2860_io_mac_write_multi(sc, RT2860_REG_IVEIV(wcid), iv, 8); + + tmp = ((vapid & RT2860_REG_VAP_MASK) << RT2860_REG_VAP_SHIFT) | + (mode << RT2860_REG_CIPHER_MODE_SHIFT) | RT2860_REG_PKEY_ENABLE; + + rt2860_io_mac_write(sc, RT2860_REG_WCID_ATTR(wcid), tmp); + } } return 1; @@ -2319,18 +2365,14 @@ static int rt2860_key_delete(struct ieee80211com *ic, const struct ieee80211_key *k) { struct rt2860_softc *sc; - struct ieee80211_node *ni; - uint16_t associd; uint8_t vapid, wcid; uint32_t tmp; sc = ic->ic_ifp->if_softc; - ni = ic->ic_bss; - associd = (ni != NULL) ? ni->ni_associd : 0; RT2860_DPRINTF(sc, RT2860_DEBUG_KEY, - "%s: delete key: keyix=%d, keylen=%d, associd=0x%04x, group=%d\n", - device_get_nameunit(sc->dev), k->wk_keyix, k->wk_keylen, associd, + "%s: delete key: keyix=%d, keylen=%d, wcid=0x%02x, group=%d\n", + device_get_nameunit(sc->dev), k->wk_keyix, k->wk_keylen, k->wk_pad, (k->wk_flags & IEEE80211_KEY_GROUP) ? 1 : 0); if (!(k->wk_flags & IEEE80211_KEY_GROUP)) @@ -2338,7 +2380,10 @@ static int rt2860_key_delete(struct ieee80211com *ic, /* remove pairwise key */ vapid = 0; - wcid = RT2860_AID2WCID(associd); + + wcid = k->wk_pad; + if (wcid == 0) + return 0; tmp = ((vapid & RT2860_REG_VAP_MASK) << RT2860_REG_VAP_SHIFT) | (RT2860_REG_CIPHER_MODE_NONE << RT2860_REG_CIPHER_MODE_SHIFT) | RT2860_REG_PKEY_ENABLE; @@ -2350,6 +2395,7 @@ static int rt2860_key_delete(struct ieee80211com *ic, /* remove group key */ vapid = 0; + wcid = RT2860_WCID_MCAST; tmp = rt2860_io_mac_read(sc, RT2860_REG_SKEY_MODE(vapid)); @@ -2357,6 +2403,14 @@ static int rt2860_key_delete(struct ieee80211com *ic, tmp |= (RT2860_REG_CIPHER_MODE_NONE << (k->wk_keyix * 4 + 16 * (vapid % 2))); rt2860_io_mac_write(sc, RT2860_REG_SKEY_MODE(vapid), tmp); + + if (ic->ic_opmode == IEEE80211_M_HOSTAP) + { + tmp = ((vapid & RT2860_REG_VAP_MASK) << RT2860_REG_VAP_SHIFT) | + (RT2860_REG_CIPHER_MODE_NONE << RT2860_REG_CIPHER_MODE_SHIFT) | RT2860_REG_PKEY_ENABLE; + + rt2860_io_mac_write(sc, RT2860_REG_WCID_ATTR(wcid), tmp); + } } return 1; @@ -3647,8 +3701,10 @@ static int rt2860_tx_frame(struct rt2860_softc *sc, /* management frames do not need encryption */ - wcid = (type == IEEE80211_FC0_TYPE_DATA) ? - RT2860_AID2WCID(ni->ni_associd) : 0xff; + if (type == IEEE80211_FC0_TYPE_DATA) + wcid = !IEEE80211_IS_MULTICAST(wh->i_addr1) ? RT2860_AID2WCID(ni->ni_associd) : RT2860_WCID_MCAST; + else + wcid = RT2860_WCID_RESERVED; /* calculate MPDU length without padding */ @@ -5161,7 +5217,7 @@ static void rt2860_drain_fifo_stats(struct rt2860_softc *sc) /* if no ACK was requested, no feedback is available */ - if (!(stats & RT2860_REG_TX_STA_FIFO_ACK_REQ) || wcid == 0xff) + if (!(stats & RT2860_REG_TX_STA_FIFO_ACK_REQ) || wcid == RT2860_WCID_RESERVED) continue; /* update AMRR statistic */ -- 2.11.4.GIT