提交 31b59eae 编写于 作者: J James Ketrenos 提交者: Jeff Garzik

[PATCH] ieee80211: Added handle_deauth() callback, enhanced tkip/ccmp support...

[PATCH] ieee80211: Added handle_deauth() callback, enhanced tkip/ccmp support of varying hw/sw offload

tree de81b55e78e85997642c651ea677078d0554a14f
parent c8030da8c159f8b82712172a6748a42523aea83a
author James Ketrenos <jketreno@linux.intel.com> 1127104380 -0500
committer James Ketrenos <jketreno@linux.intel.com> 1127315225 -0500

Added handle_deauth() callback.
Enhanced crypt_{tkip,ccmp} to support varying splits of HW/SW offload.
Changed channel freq to u32 from u16.
Signed-off-by: NJeff Garzik <jgarzik@pobox.com>
上级 31696160
...@@ -808,7 +808,7 @@ enum { ...@@ -808,7 +808,7 @@ enum {
}; };
struct ieee80211_channel { struct ieee80211_channel {
u16 freq; u32 freq;
u8 channel; u8 channel;
u8 flags; u8 flags;
u8 max_power; u8 max_power;
...@@ -862,6 +862,7 @@ struct ieee80211_device { ...@@ -862,6 +862,7 @@ struct ieee80211_device {
int host_mc_decrypt; int host_mc_decrypt;
int host_open_frag; int host_open_frag;
int host_build_iv;
int ieee802_1x; /* is IEEE 802.1X used */ int ieee802_1x; /* is IEEE 802.1X used */
/* WPA data */ /* WPA data */
...@@ -914,6 +915,8 @@ struct ieee80211_device { ...@@ -914,6 +915,8 @@ struct ieee80211_device {
/* Typical STA methods */ /* Typical STA methods */
int (*handle_auth) (struct net_device * dev, int (*handle_auth) (struct net_device * dev,
struct ieee80211_auth * auth); struct ieee80211_auth * auth);
int (*handle_deauth) (struct net_device * dev,
struct ieee80211_auth * auth);
int (*handle_disassoc) (struct net_device * dev, int (*handle_disassoc) (struct net_device * dev,
struct ieee80211_disassoc * assoc); struct ieee80211_disassoc * assoc);
int (*handle_beacon) (struct net_device * dev, int (*handle_beacon) (struct net_device * dev,
......
...@@ -36,6 +36,8 @@ struct ieee80211_crypto_ops { ...@@ -36,6 +36,8 @@ struct ieee80211_crypto_ops {
/* deinitialize crypto context and free allocated private data */ /* deinitialize crypto context and free allocated private data */
void (*deinit) (void *priv); void (*deinit) (void *priv);
int (*build_iv) (struct sk_buff * skb, int hdr_len, void *priv);
/* encrypt/decrypt return < 0 on error or >= 0 on success. The return /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
* value from decrypt_mpdu is passed as the keyidx value for * value from decrypt_mpdu is passed as the keyidx value for
* decrypt_msdu. skb must have enough head and tail room for the * decrypt_msdu. skb must have enough head and tail room for the
......
...@@ -191,26 +191,18 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, ...@@ -191,26 +191,18 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
ieee80211_ccmp_aes_encrypt(tfm, b0, s0); ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
} }
static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
{ {
struct ieee80211_ccmp_data *key = priv; struct ieee80211_ccmp_data *key = priv;
int data_len, i, blocks, last, len; int i;
u8 *pos, *mic; u8 *pos;
struct ieee80211_hdr_4addr *hdr;
u8 *b0 = key->tx_b0;
u8 *b = key->tx_b;
u8 *e = key->tx_e;
u8 *s0 = key->tx_s0;
if (skb_headroom(skb) < CCMP_HDR_LEN || if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
return -1; return -1;
data_len = skb->len - hdr_len;
pos = skb_push(skb, CCMP_HDR_LEN); pos = skb_push(skb, CCMP_HDR_LEN);
memmove(pos, pos + CCMP_HDR_LEN, hdr_len); memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
pos += hdr_len; pos += hdr_len;
mic = skb_put(skb, CCMP_MIC_LEN);
i = CCMP_PN_LEN - 1; i = CCMP_PN_LEN - 1;
while (i >= 0) { while (i >= 0) {
...@@ -229,6 +221,30 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) ...@@ -229,6 +221,30 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
*pos++ = key->tx_pn[1]; *pos++ = key->tx_pn[1];
*pos++ = key->tx_pn[0]; *pos++ = key->tx_pn[0];
return CCMP_HDR_LEN;
}
static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_ccmp_data *key = priv;
int data_len, i, blocks, last, len;
u8 *pos, *mic;
struct ieee80211_hdr_4addr *hdr;
u8 *b0 = key->tx_b0;
u8 *b = key->tx_b;
u8 *e = key->tx_e;
u8 *s0 = key->tx_s0;
if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
return -1;
data_len = skb->len - hdr_len;
len = ieee80211_ccmp_hdr(skb, hdr_len, priv);
if (len < 0)
return -1;
pos = skb->data + hdr_len + CCMP_HDR_LEN;
mic = skb_put(skb, CCMP_MIC_LEN);
hdr = (struct ieee80211_hdr_4addr *)skb->data; hdr = (struct ieee80211_hdr_4addr *)skb->data;
ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
...@@ -429,6 +445,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = { ...@@ -429,6 +445,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
.name = "CCMP", .name = "CCMP",
.init = ieee80211_ccmp_init, .init = ieee80211_ccmp_init,
.deinit = ieee80211_ccmp_deinit, .deinit = ieee80211_ccmp_deinit,
.build_iv = ieee80211_ccmp_hdr,
.encrypt_mpdu = ieee80211_ccmp_encrypt, .encrypt_mpdu = ieee80211_ccmp_encrypt,
.decrypt_mpdu = ieee80211_ccmp_decrypt, .decrypt_mpdu = ieee80211_ccmp_decrypt,
.encrypt_msdu = NULL, .encrypt_msdu = NULL,
......
...@@ -260,35 +260,27 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK, ...@@ -260,35 +260,27 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
#endif #endif
} }
static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
{ {
struct ieee80211_tkip_data *tkey = priv; struct ieee80211_tkip_data *tkey = priv;
int len; int len;
u8 rc4key[16], *pos, *icv; u8 *rc4key, *pos, *icv;
struct ieee80211_hdr_4addr *hdr; struct ieee80211_hdr_4addr *hdr;
u32 crc; u32 crc;
struct scatterlist sg;
hdr = (struct ieee80211_hdr_4addr *)skb->data; hdr = (struct ieee80211_hdr_4addr *)skb->data;
if (tkey->ieee->tkip_countermeasures) { if (skb_headroom(skb) < 8 || skb->len < hdr_len)
if (net_ratelimit()) { return NULL;
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
"TX packet to " MAC_FMT "\n",
tkey->ieee->dev->name, MAC_ARG(hdr->addr1));
}
return -1;
}
if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
skb->len < hdr_len)
return -1;
if (!tkey->tx_phase1_done) { if (!tkey->tx_phase1_done) {
tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
tkey->tx_iv32); tkey->tx_iv32);
tkey->tx_phase1_done = 1; tkey->tx_phase1_done = 1;
} }
rc4key = kmalloc(16, GFP_ATOMIC);
if (!rc4key)
return NULL;
tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
len = skb->len - hdr_len; len = skb->len - hdr_len;
...@@ -297,9 +289,9 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) ...@@ -297,9 +289,9 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
pos += hdr_len; pos += hdr_len;
icv = skb_put(skb, 4); icv = skb_put(skb, 4);
*pos++ = rc4key[0]; *pos++ = *rc4key;
*pos++ = rc4key[1]; *pos++ = *(rc4key + 1);
*pos++ = rc4key[2]; *pos++ = *(rc4key + 2);
*pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ; *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
*pos++ = tkey->tx_iv32 & 0xff; *pos++ = tkey->tx_iv32 & 0xff;
*pos++ = (tkey->tx_iv32 >> 8) & 0xff; *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
...@@ -312,6 +304,38 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) ...@@ -312,6 +304,38 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
icv[2] = crc >> 16; icv[2] = crc >> 16;
icv[3] = crc >> 24; icv[3] = crc >> 24;
return rc4key;
}
static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_tkip_data *tkey = priv;
int len;
const u8 *rc4key;
u8 *pos;
struct scatterlist sg;
if (tkey->ieee->tkip_countermeasures) {
if (net_ratelimit()) {
struct ieee80211_hdr_4addr *hdr =
(struct ieee80211_hdr_4addr *)skb->data;
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
"TX packet to " MAC_FMT "\n",
tkey->ieee->dev->name, MAC_ARG(hdr->addr1));
}
return -1;
}
if (skb_tailroom(skb) < 4 || skb->len < hdr_len)
return -1;
len = skb->len - hdr_len;
pos = skb->data + hdr_len;
rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv);
if (!rc4key)
return -1;
crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
sg.page = virt_to_page(pos); sg.page = virt_to_page(pos);
sg.offset = offset_in_page(pos); sg.offset = offset_in_page(pos);
......
...@@ -1534,6 +1534,12 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee, ...@@ -1534,6 +1534,12 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
header); header);
break; break;
case IEEE80211_STYPE_DEAUTH:
printk("DEAUTH from AP\n");
if (ieee->handle_deauth != NULL)
ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *)
header);
break;
default: default:
IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n", IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
WLAN_FC_GET_STYPE(le16_to_cpu WLAN_FC_GET_STYPE(le16_to_cpu
......
...@@ -227,7 +227,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -227,7 +227,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
rts_required; rts_required;
unsigned long flags; unsigned long flags;
struct net_device_stats *stats = &ieee->stats; struct net_device_stats *stats = &ieee->stats;
int ether_type, encrypt, host_encrypt, host_encrypt_msdu; int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
int bytes, fc, hdr_len; int bytes, fc, hdr_len;
struct sk_buff *skb_frag; struct sk_buff *skb_frag;
struct ieee80211_hdr_3addr header = { /* Ensure zero initialized */ struct ieee80211_hdr_3addr header = { /* Ensure zero initialized */
...@@ -263,8 +263,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -263,8 +263,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
ieee->sec.encrypt; ieee->sec.encrypt;
host_encrypt = ieee->host_encrypt && encrypt; host_encrypt = ieee->host_encrypt && encrypt;
host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt; host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt;
host_build_iv = ieee->host_build_iv && encrypt;
if (!encrypt && ieee->ieee802_1x && if (!encrypt && ieee->ieee802_1x &&
ieee->drop_unencrypted && ether_type != ETH_P_PAE) { ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
...@@ -310,8 +312,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -310,8 +312,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len + int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
crypt->ops->extra_msdu_postfix_len; crypt->ops->extra_msdu_postfix_len;
struct sk_buff *skb_new = dev_alloc_skb(len); struct sk_buff *skb_new = dev_alloc_skb(len);
if (unlikely(!skb_new)) if (unlikely(!skb_new))
goto failed; goto failed;
skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len); skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
memcpy(skb_put(skb_new, hdr_len), &header, hdr_len); memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
snapped = 1; snapped = 1;
...@@ -418,7 +422,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -418,7 +422,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
for (; i < nr_frags; i++) { for (; i < nr_frags; i++) {
skb_frag = txb->fragments[i]; skb_frag = txb->fragments[i];
if (host_encrypt) if (host_encrypt || host_build_iv)
skb_reserve(skb_frag, skb_reserve(skb_frag,
crypt->ops->extra_mpdu_prefix_len); crypt->ops->extra_mpdu_prefix_len);
...@@ -453,6 +457,16 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -453,6 +457,16 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
* to insert the IV between the header and the payload */ * to insert the IV between the header and the payload */
if (host_encrypt) if (host_encrypt)
ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
else if (host_build_iv) {
struct ieee80211_crypt_data *crypt;
crypt = ieee->crypt[ieee->tx_keyidx];
atomic_inc(&crypt->refcnt);
if (crypt->ops->build_iv)
crypt->ops->build_iv(skb_frag, hdr_len,
crypt->priv);
atomic_dec(&crypt->refcnt);
}
if (ieee->config & if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册