You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge ../bleed-2.6
This commit is contained in:
@@ -1625,12 +1625,9 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
|
||||
|
||||
memset(&ndst, 0, sizeof(ndst));
|
||||
|
||||
for (cpu = 0; cpu < NR_CPUS; cpu++) {
|
||||
for_each_cpu(cpu) {
|
||||
struct neigh_statistics *st;
|
||||
|
||||
if (!cpu_possible(cpu))
|
||||
continue;
|
||||
|
||||
st = per_cpu_ptr(tbl->stats, cpu);
|
||||
ndst.ndts_allocs += st->allocs;
|
||||
ndst.ndts_destroys += st->destroys;
|
||||
|
||||
+230
-278
File diff suppressed because it is too large
Load Diff
@@ -122,6 +122,8 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
|
||||
* __alloc_skb - allocate a network buffer
|
||||
* @size: size to allocate
|
||||
* @gfp_mask: allocation mask
|
||||
* @fclone: allocate from fclone cache instead of head cache
|
||||
* and allocate a cloned (child) skb
|
||||
*
|
||||
* Allocate a new &sk_buff. The returned buffer has no headroom and a
|
||||
* tail room of size bytes. The object has a reference count of one.
|
||||
|
||||
+1
-1
@@ -940,7 +940,7 @@ static struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
|
||||
int noblock, int *errcode)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned int gfp_mask;
|
||||
gfp_t gfp_mask;
|
||||
long timeo;
|
||||
int err;
|
||||
|
||||
|
||||
+1
-1
@@ -495,7 +495,7 @@ void dccp_send_close(struct sock *sk, const int active)
|
||||
{
|
||||
struct dccp_sock *dp = dccp_sk(sk);
|
||||
struct sk_buff *skb;
|
||||
const unsigned int prio = active ? GFP_KERNEL : GFP_ATOMIC;
|
||||
const gfp_t prio = active ? GFP_KERNEL : GFP_ATOMIC;
|
||||
|
||||
skb = alloc_skb(sk->sk_prot->max_header, prio);
|
||||
if (skb == NULL)
|
||||
|
||||
@@ -719,22 +719,9 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
if (saddr->sdn_flags & ~SDF_WILD)
|
||||
return -EINVAL;
|
||||
|
||||
#if 1
|
||||
if (!capable(CAP_NET_BIND_SERVICE) && (saddr->sdn_objnum ||
|
||||
(saddr->sdn_flags & SDF_WILD)))
|
||||
return -EACCES;
|
||||
#else
|
||||
/*
|
||||
* Maybe put the default actions in the default security ops for
|
||||
* dn_prot_sock ? Would be nice if the capable call would go there
|
||||
* too.
|
||||
*/
|
||||
if (security_dn_prot_sock(saddr) &&
|
||||
!capable(CAP_NET_BIND_SERVICE) ||
|
||||
saddr->sdn_objnum || (saddr->sdn_flags & SDF_WILD))
|
||||
return -EACCES;
|
||||
#endif
|
||||
|
||||
|
||||
if (!(saddr->sdn_flags & SDF_WILD)) {
|
||||
if (dn_ntohs(saddr->sdn_nodeaddrl)) {
|
||||
|
||||
@@ -7,5 +7,6 @@ ieee80211-objs := \
|
||||
ieee80211_module.o \
|
||||
ieee80211_tx.o \
|
||||
ieee80211_rx.o \
|
||||
ieee80211_wx.o
|
||||
ieee80211_wx.o \
|
||||
ieee80211_geo.o
|
||||
|
||||
|
||||
@@ -41,6 +41,12 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
|
||||
{
|
||||
struct list_head *ptr, *n;
|
||||
struct ieee80211_crypt_data *entry;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
|
||||
if (list_empty(&ieee->crypt_deinit_list))
|
||||
goto unlock;
|
||||
|
||||
for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
|
||||
ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
|
||||
@@ -57,6 +63,18 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
|
||||
}
|
||||
kfree(entry);
|
||||
}
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
}
|
||||
|
||||
/* After this, crypt_deinit_list won't accept new members */
|
||||
void ieee80211_crypt_quiescing(struct ieee80211_device *ieee)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
ieee->crypt_quiesced = 1;
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
}
|
||||
|
||||
void ieee80211_crypt_deinit_handler(unsigned long data)
|
||||
@@ -64,16 +82,16 @@ void ieee80211_crypt_deinit_handler(unsigned long data)
|
||||
struct ieee80211_device *ieee = (struct ieee80211_device *)data;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
ieee80211_crypt_deinit_entries(ieee, 0);
|
||||
if (!list_empty(&ieee->crypt_deinit_list)) {
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
if (!list_empty(&ieee->crypt_deinit_list) && !ieee->crypt_quiesced) {
|
||||
printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
|
||||
"deletion list\n", ieee->dev->name);
|
||||
ieee->crypt_deinit_timer.expires = jiffies + HZ;
|
||||
add_timer(&ieee->crypt_deinit_timer);
|
||||
}
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
|
||||
}
|
||||
|
||||
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
|
||||
@@ -93,10 +111,12 @@ void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
|
||||
* locking. */
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
list_add(&tmp->list, &ieee->crypt_deinit_list);
|
||||
if (!timer_pending(&ieee->crypt_deinit_timer)) {
|
||||
ieee->crypt_deinit_timer.expires = jiffies + HZ;
|
||||
add_timer(&ieee->crypt_deinit_timer);
|
||||
if (!ieee->crypt_quiesced) {
|
||||
list_add(&tmp->list, &ieee->crypt_deinit_list);
|
||||
if (!timer_pending(&ieee->crypt_deinit_timer)) {
|
||||
ieee->crypt_deinit_timer.expires = jiffies + HZ;
|
||||
add_timer(&ieee->crypt_deinit_timer);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
}
|
||||
@@ -191,18 +211,18 @@ static void ieee80211_crypt_null_deinit(void *priv)
|
||||
}
|
||||
|
||||
static struct ieee80211_crypto_ops ieee80211_crypt_null = {
|
||||
.name = "NULL",
|
||||
.init = ieee80211_crypt_null_init,
|
||||
.deinit = ieee80211_crypt_null_deinit,
|
||||
.encrypt_mpdu = NULL,
|
||||
.decrypt_mpdu = NULL,
|
||||
.encrypt_msdu = NULL,
|
||||
.decrypt_msdu = NULL,
|
||||
.set_key = NULL,
|
||||
.get_key = NULL,
|
||||
.extra_prefix_len = 0,
|
||||
.extra_postfix_len = 0,
|
||||
.owner = THIS_MODULE,
|
||||
.name = "NULL",
|
||||
.init = ieee80211_crypt_null_init,
|
||||
.deinit = ieee80211_crypt_null_deinit,
|
||||
.encrypt_mpdu = NULL,
|
||||
.decrypt_mpdu = NULL,
|
||||
.encrypt_msdu = NULL,
|
||||
.decrypt_msdu = NULL,
|
||||
.set_key = NULL,
|
||||
.get_key = NULL,
|
||||
.extra_mpdu_prefix_len = 0,
|
||||
.extra_mpdu_postfix_len = 0,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init ieee80211_crypto_init(void)
|
||||
@@ -249,6 +269,7 @@ static void __exit ieee80211_crypto_deinit(void)
|
||||
EXPORT_SYMBOL(ieee80211_crypt_deinit_entries);
|
||||
EXPORT_SYMBOL(ieee80211_crypt_deinit_handler);
|
||||
EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit);
|
||||
EXPORT_SYMBOL(ieee80211_crypt_quiescing);
|
||||
|
||||
EXPORT_SYMBOL(ieee80211_register_crypto_ops);
|
||||
EXPORT_SYMBOL(ieee80211_unregister_crypto_ops);
|
||||
|
||||
@@ -119,7 +119,7 @@ static inline void xor_block(u8 * b, u8 * a, size_t len)
|
||||
}
|
||||
|
||||
static void ccmp_init_blocks(struct crypto_tfm *tfm,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct ieee80211_hdr_4addr *hdr,
|
||||
u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
|
||||
{
|
||||
u8 *pos, qc = 0;
|
||||
@@ -191,26 +191,18 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
|
||||
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;
|
||||
int data_len, i, blocks, last, len;
|
||||
u8 *pos, *mic;
|
||||
struct ieee80211_hdr *hdr;
|
||||
u8 *b0 = key->tx_b0;
|
||||
u8 *b = key->tx_b;
|
||||
u8 *e = key->tx_e;
|
||||
u8 *s0 = key->tx_s0;
|
||||
int i;
|
||||
u8 *pos;
|
||||
|
||||
if (skb_headroom(skb) < CCMP_HDR_LEN ||
|
||||
skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
|
||||
if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
|
||||
return -1;
|
||||
|
||||
data_len = skb->len - hdr_len;
|
||||
pos = skb_push(skb, CCMP_HDR_LEN);
|
||||
memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
|
||||
pos += hdr_len;
|
||||
mic = skb_put(skb, CCMP_MIC_LEN);
|
||||
|
||||
i = CCMP_PN_LEN - 1;
|
||||
while (i >= 0) {
|
||||
@@ -229,7 +221,31 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||
*pos++ = key->tx_pn[1];
|
||||
*pos++ = key->tx_pn[0];
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
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;
|
||||
ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
|
||||
|
||||
blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
|
||||
@@ -258,7 +274,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||
{
|
||||
struct ieee80211_ccmp_data *key = priv;
|
||||
u8 keyidx, *pos;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u8 *b0 = key->rx_b0;
|
||||
u8 *b = key->rx_b;
|
||||
u8 *a = key->rx_a;
|
||||
@@ -272,7 +288,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
pos = skb->data + hdr_len;
|
||||
keyidx = pos[3];
|
||||
if (!(keyidx & (1 << 5))) {
|
||||
@@ -426,19 +442,20 @@ static char *ieee80211_ccmp_print_stats(char *p, void *priv)
|
||||
}
|
||||
|
||||
static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
|
||||
.name = "CCMP",
|
||||
.init = ieee80211_ccmp_init,
|
||||
.deinit = ieee80211_ccmp_deinit,
|
||||
.encrypt_mpdu = ieee80211_ccmp_encrypt,
|
||||
.decrypt_mpdu = ieee80211_ccmp_decrypt,
|
||||
.encrypt_msdu = NULL,
|
||||
.decrypt_msdu = NULL,
|
||||
.set_key = ieee80211_ccmp_set_key,
|
||||
.get_key = ieee80211_ccmp_get_key,
|
||||
.print_stats = ieee80211_ccmp_print_stats,
|
||||
.extra_prefix_len = CCMP_HDR_LEN,
|
||||
.extra_postfix_len = CCMP_MIC_LEN,
|
||||
.owner = THIS_MODULE,
|
||||
.name = "CCMP",
|
||||
.init = ieee80211_ccmp_init,
|
||||
.deinit = ieee80211_ccmp_deinit,
|
||||
.build_iv = ieee80211_ccmp_hdr,
|
||||
.encrypt_mpdu = ieee80211_ccmp_encrypt,
|
||||
.decrypt_mpdu = ieee80211_ccmp_decrypt,
|
||||
.encrypt_msdu = NULL,
|
||||
.decrypt_msdu = NULL,
|
||||
.set_key = ieee80211_ccmp_set_key,
|
||||
.get_key = ieee80211_ccmp_get_key,
|
||||
.print_stats = ieee80211_ccmp_print_stats,
|
||||
.extra_mpdu_prefix_len = CCMP_HDR_LEN,
|
||||
.extra_mpdu_postfix_len = CCMP_MIC_LEN,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init ieee80211_crypto_ccmp_init(void)
|
||||
|
||||
@@ -59,8 +59,24 @@ struct ieee80211_tkip_data {
|
||||
|
||||
/* scratch buffers for virt_to_page() (crypto API) */
|
||||
u8 rx_hdr[16], tx_hdr[16];
|
||||
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
static unsigned long ieee80211_tkip_set_flags(unsigned long flags, void *priv)
|
||||
{
|
||||
struct ieee80211_tkip_data *_priv = priv;
|
||||
unsigned long old_flags = _priv->flags;
|
||||
_priv->flags = flags;
|
||||
return old_flags;
|
||||
}
|
||||
|
||||
static unsigned long ieee80211_tkip_get_flags(void *priv)
|
||||
{
|
||||
struct ieee80211_tkip_data *_priv = priv;
|
||||
return _priv->flags;
|
||||
}
|
||||
|
||||
static void *ieee80211_tkip_init(int key_idx)
|
||||
{
|
||||
struct ieee80211_tkip_data *priv;
|
||||
@@ -69,6 +85,7 @@ static void *ieee80211_tkip_init(int key_idx)
|
||||
if (priv == NULL)
|
||||
goto fail;
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
|
||||
priv->key_idx = key_idx;
|
||||
|
||||
priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
|
||||
@@ -255,25 +272,27 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
|
||||
#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;
|
||||
int len;
|
||||
u8 rc4key[16], *pos, *icv;
|
||||
struct ieee80211_hdr *hdr;
|
||||
u8 *rc4key, *pos, *icv;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u32 crc;
|
||||
struct scatterlist sg;
|
||||
|
||||
if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
|
||||
skb->len < hdr_len)
|
||||
return -1;
|
||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
|
||||
if (skb_headroom(skb) < 8 || skb->len < hdr_len)
|
||||
return NULL;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
if (!tkey->tx_phase1_done) {
|
||||
tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
|
||||
tkey->tx_iv32);
|
||||
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);
|
||||
|
||||
len = skb->len - hdr_len;
|
||||
@@ -282,9 +301,9 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||
pos += hdr_len;
|
||||
icv = skb_put(skb, 4);
|
||||
|
||||
*pos++ = rc4key[0];
|
||||
*pos++ = rc4key[1];
|
||||
*pos++ = rc4key[2];
|
||||
*pos++ = *rc4key;
|
||||
*pos++ = *(rc4key + 1);
|
||||
*pos++ = *(rc4key + 2);
|
||||
*pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
|
||||
*pos++ = tkey->tx_iv32 & 0xff;
|
||||
*pos++ = (tkey->tx_iv32 >> 8) & 0xff;
|
||||
@@ -297,6 +316,38 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||
icv[2] = crc >> 16;
|
||||
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->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
|
||||
if (net_ratelimit()) {
|
||||
struct ieee80211_hdr_4addr *hdr =
|
||||
(struct ieee80211_hdr_4addr *)skb->data;
|
||||
printk(KERN_DEBUG "TKIP countermeasures: dropped "
|
||||
"TX packet to " MAC_FMT "\n",
|
||||
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);
|
||||
sg.page = virt_to_page(pos);
|
||||
sg.offset = offset_in_page(pos);
|
||||
@@ -319,16 +370,26 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
||||
u8 keyidx, *pos;
|
||||
u32 iv32;
|
||||
u16 iv16;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u8 icv[4];
|
||||
u32 crc;
|
||||
struct scatterlist sg;
|
||||
int plen;
|
||||
|
||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
|
||||
if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "TKIP countermeasures: dropped "
|
||||
"received packet from " MAC_FMT "\n",
|
||||
MAC_ARG(hdr->addr2));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (skb->len < hdr_len + 8 + 4)
|
||||
return -1;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
pos = skb->data + hdr_len;
|
||||
keyidx = pos[3];
|
||||
if (!(keyidx & (1 << 5))) {
|
||||
@@ -441,9 +502,9 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
|
||||
|
||||
static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
|
||||
{
|
||||
struct ieee80211_hdr *hdr11;
|
||||
struct ieee80211_hdr_4addr *hdr11;
|
||||
|
||||
hdr11 = (struct ieee80211_hdr *)skb->data;
|
||||
hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
switch (le16_to_cpu(hdr11->frame_ctl) &
|
||||
(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
|
||||
case IEEE80211_FCTL_TODS:
|
||||
@@ -490,9 +551,9 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if WIRELESS_EXT >= 18
|
||||
static void ieee80211_michael_mic_failure(struct net_device *dev,
|
||||
struct ieee80211_hdr *hdr, int keyidx)
|
||||
struct ieee80211_hdr_4addr *hdr,
|
||||
int keyidx)
|
||||
{
|
||||
union iwreq_data wrqu;
|
||||
struct iw_michaelmicfailure ev;
|
||||
@@ -510,28 +571,6 @@ static void ieee80211_michael_mic_failure(struct net_device *dev,
|
||||
wrqu.data.length = sizeof(ev);
|
||||
wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
|
||||
}
|
||||
#elif WIRELESS_EXT >= 15
|
||||
static void ieee80211_michael_mic_failure(struct net_device *dev,
|
||||
struct ieee80211_hdr *hdr, int keyidx)
|
||||
{
|
||||
union iwreq_data wrqu;
|
||||
char buf[128];
|
||||
|
||||
/* TODO: needed parameters: count, keyid, key type, TSC */
|
||||
sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
|
||||
MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
|
||||
MAC_ARG(hdr->addr2));
|
||||
memset(&wrqu, 0, sizeof(wrqu));
|
||||
wrqu.data.length = strlen(buf);
|
||||
wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
|
||||
}
|
||||
#else /* WIRELESS_EXT >= 15 */
|
||||
static inline void ieee80211_michael_mic_failure(struct net_device *dev,
|
||||
struct ieee80211_hdr *hdr,
|
||||
int keyidx)
|
||||
{
|
||||
}
|
||||
#endif /* WIRELESS_EXT >= 15 */
|
||||
|
||||
static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
|
||||
int hdr_len, void *priv)
|
||||
@@ -547,8 +586,8 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
|
||||
skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
|
||||
return -1;
|
||||
if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
|
||||
struct ieee80211_hdr *hdr;
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
|
||||
"MSDU from " MAC_FMT " keyidx=%d\n",
|
||||
skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
|
||||
@@ -654,19 +693,22 @@ static char *ieee80211_tkip_print_stats(char *p, void *priv)
|
||||
}
|
||||
|
||||
static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
|
||||
.name = "TKIP",
|
||||
.init = ieee80211_tkip_init,
|
||||
.deinit = ieee80211_tkip_deinit,
|
||||
.encrypt_mpdu = ieee80211_tkip_encrypt,
|
||||
.decrypt_mpdu = ieee80211_tkip_decrypt,
|
||||
.encrypt_msdu = ieee80211_michael_mic_add,
|
||||
.decrypt_msdu = ieee80211_michael_mic_verify,
|
||||
.set_key = ieee80211_tkip_set_key,
|
||||
.get_key = ieee80211_tkip_get_key,
|
||||
.print_stats = ieee80211_tkip_print_stats,
|
||||
.extra_prefix_len = 4 + 4, /* IV + ExtIV */
|
||||
.extra_postfix_len = 8 + 4, /* MIC + ICV */
|
||||
.owner = THIS_MODULE,
|
||||
.name = "TKIP",
|
||||
.init = ieee80211_tkip_init,
|
||||
.deinit = ieee80211_tkip_deinit,
|
||||
.encrypt_mpdu = ieee80211_tkip_encrypt,
|
||||
.decrypt_mpdu = ieee80211_tkip_decrypt,
|
||||
.encrypt_msdu = ieee80211_michael_mic_add,
|
||||
.decrypt_msdu = ieee80211_michael_mic_verify,
|
||||
.set_key = ieee80211_tkip_set_key,
|
||||
.get_key = ieee80211_tkip_get_key,
|
||||
.print_stats = ieee80211_tkip_print_stats,
|
||||
.extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
|
||||
.extra_mpdu_postfix_len = 4, /* ICV */
|
||||
.extra_msdu_postfix_len = 8, /* MIC */
|
||||
.get_flags = ieee80211_tkip_get_flags,
|
||||
.set_flags = ieee80211_tkip_set_flags,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init ieee80211_crypto_tkip_init(void)
|
||||
|
||||
@@ -229,19 +229,19 @@ static char *prism2_wep_print_stats(char *p, void *priv)
|
||||
}
|
||||
|
||||
static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
|
||||
.name = "WEP",
|
||||
.init = prism2_wep_init,
|
||||
.deinit = prism2_wep_deinit,
|
||||
.encrypt_mpdu = prism2_wep_encrypt,
|
||||
.decrypt_mpdu = prism2_wep_decrypt,
|
||||
.encrypt_msdu = NULL,
|
||||
.decrypt_msdu = NULL,
|
||||
.set_key = prism2_wep_set_key,
|
||||
.get_key = prism2_wep_get_key,
|
||||
.print_stats = prism2_wep_print_stats,
|
||||
.extra_prefix_len = 4, /* IV */
|
||||
.extra_postfix_len = 4, /* ICV */
|
||||
.owner = THIS_MODULE,
|
||||
.name = "WEP",
|
||||
.init = prism2_wep_init,
|
||||
.deinit = prism2_wep_deinit,
|
||||
.encrypt_mpdu = prism2_wep_encrypt,
|
||||
.decrypt_mpdu = prism2_wep_decrypt,
|
||||
.encrypt_msdu = NULL,
|
||||
.decrypt_msdu = NULL,
|
||||
.set_key = prism2_wep_set_key,
|
||||
.get_key = prism2_wep_get_key,
|
||||
.print_stats = prism2_wep_print_stats,
|
||||
.extra_mpdu_prefix_len = 4, /* IV */
|
||||
.extra_mpdu_postfix_len = 4, /* ICV */
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init ieee80211_crypto_wep_init(void)
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/******************************************************************************
|
||||
|
||||
Copyright(c) 2005 Intel Corporation. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of version 2 of the GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in the
|
||||
file called LICENSE.
|
||||
|
||||
Contact Information:
|
||||
James P. Ketrenos <ipw2100-admin@linux.intel.com>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
******************************************************************************/
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/config.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include <net/ieee80211.h>
|
||||
|
||||
int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Driver needs to initialize the geography map before using
|
||||
* these helper functions */
|
||||
BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
|
||||
|
||||
if (ieee->freq_band & IEEE80211_24GHZ_BAND)
|
||||
for (i = 0; i < ieee->geo.bg_channels; i++)
|
||||
/* NOTE: If G mode is currently supported but
|
||||
* this is a B only channel, we don't see it
|
||||
* as valid. */
|
||||
if ((ieee->geo.bg[i].channel == channel) &&
|
||||
(!(ieee->mode & IEEE_G) ||
|
||||
!(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
|
||||
return IEEE80211_24GHZ_BAND;
|
||||
|
||||
if (ieee->freq_band & IEEE80211_52GHZ_BAND)
|
||||
for (i = 0; i < ieee->geo.a_channels; i++)
|
||||
if (ieee->geo.a[i].channel == channel)
|
||||
return IEEE80211_52GHZ_BAND;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Driver needs to initialize the geography map before using
|
||||
* these helper functions */
|
||||
BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
|
||||
|
||||
if (ieee->freq_band & IEEE80211_24GHZ_BAND)
|
||||
for (i = 0; i < ieee->geo.bg_channels; i++)
|
||||
if (ieee->geo.bg[i].channel == channel)
|
||||
return i;
|
||||
|
||||
if (ieee->freq_band & IEEE80211_52GHZ_BAND)
|
||||
for (i = 0; i < ieee->geo.a_channels; i++)
|
||||
if (ieee->geo.a[i].channel == channel)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Driver needs to initialize the geography map before using
|
||||
* these helper functions */
|
||||
BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
|
||||
|
||||
freq /= 100000;
|
||||
|
||||
if (ieee->freq_band & IEEE80211_24GHZ_BAND)
|
||||
for (i = 0; i < ieee->geo.bg_channels; i++)
|
||||
if (ieee->geo.bg[i].freq == freq)
|
||||
return ieee->geo.bg[i].channel;
|
||||
|
||||
if (ieee->freq_band & IEEE80211_52GHZ_BAND)
|
||||
for (i = 0; i < ieee->geo.a_channels; i++)
|
||||
if (ieee->geo.a[i].freq == freq)
|
||||
return ieee->geo.a[i].channel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_set_geo(struct ieee80211_device *ieee,
|
||||
const struct ieee80211_geo *geo)
|
||||
{
|
||||
memcpy(ieee->geo.name, geo->name, 3);
|
||||
ieee->geo.name[3] = '\0';
|
||||
ieee->geo.bg_channels = geo->bg_channels;
|
||||
ieee->geo.a_channels = geo->a_channels;
|
||||
memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
|
||||
sizeof(struct ieee80211_channel));
|
||||
memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
|
||||
sizeof(struct ieee80211_channel));
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee)
|
||||
{
|
||||
return &ieee->geo;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ieee80211_is_valid_channel);
|
||||
EXPORT_SYMBOL(ieee80211_freq_to_channel);
|
||||
EXPORT_SYMBOL(ieee80211_channel_to_index);
|
||||
EXPORT_SYMBOL(ieee80211_set_geo);
|
||||
EXPORT_SYMBOL(ieee80211_get_geo);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Copyright(c) 2004 Intel Corporation. All rights reserved.
|
||||
Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
|
||||
|
||||
Portions of this file are based on the WEP enablement code provided by the
|
||||
Host AP project hostap-drivers v0.1.3
|
||||
@@ -53,12 +53,15 @@
|
||||
|
||||
#include <net/ieee80211.h>
|
||||
|
||||
MODULE_DESCRIPTION("802.11 data/management/control stack");
|
||||
MODULE_AUTHOR
|
||||
("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
#define DRV_DESCRIPTION "802.11 data/management/control stack"
|
||||
#define DRV_NAME "ieee80211"
|
||||
#define DRV_VERSION IEEE80211_VERSION
|
||||
#define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
|
||||
|
||||
#define DRV_NAME "ieee80211"
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
MODULE_AUTHOR(DRV_COPYRIGHT);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
|
||||
{
|
||||
@@ -126,26 +129,34 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
|
||||
|
||||
/* Default fragmentation threshold is maximum payload size */
|
||||
ieee->fts = DEFAULT_FTS;
|
||||
ieee->rts = DEFAULT_FTS;
|
||||
ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
|
||||
ieee->open_wep = 1;
|
||||
|
||||
/* Default to enabling full open WEP with host based encrypt/decrypt */
|
||||
ieee->host_encrypt = 1;
|
||||
ieee->host_decrypt = 1;
|
||||
ieee->host_mc_decrypt = 1;
|
||||
|
||||
/* Host fragementation in Open mode. Default is enabled.
|
||||
* Note: host fragmentation is always enabled if host encryption
|
||||
* is enabled. For cards can do hardware encryption, they must do
|
||||
* hardware fragmentation as well. So we don't need a variable
|
||||
* like host_enc_frag. */
|
||||
ieee->host_open_frag = 1;
|
||||
ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
|
||||
|
||||
INIT_LIST_HEAD(&ieee->crypt_deinit_list);
|
||||
init_timer(&ieee->crypt_deinit_timer);
|
||||
ieee->crypt_deinit_timer.data = (unsigned long)ieee;
|
||||
ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
|
||||
ieee->crypt_quiesced = 0;
|
||||
|
||||
spin_lock_init(&ieee->lock);
|
||||
|
||||
ieee->wpa_enabled = 0;
|
||||
ieee->tkip_countermeasures = 0;
|
||||
ieee->drop_unencrypted = 0;
|
||||
ieee->privacy_invoked = 0;
|
||||
ieee->ieee802_1x = 1;
|
||||
|
||||
return dev;
|
||||
|
||||
@@ -161,6 +172,7 @@ void free_ieee80211(struct net_device *dev)
|
||||
|
||||
int i;
|
||||
|
||||
ieee80211_crypt_quiescing(ieee);
|
||||
del_timer_sync(&ieee->crypt_deinit_timer);
|
||||
ieee80211_crypt_deinit_entries(ieee, 1);
|
||||
|
||||
@@ -195,38 +207,26 @@ static int show_debug_level(char *page, char **start, off_t offset,
|
||||
static int store_debug_level(struct file *file, const char __user * buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
char buf[] = "0x00000000";
|
||||
char *p = (char *)buf;
|
||||
char buf[] = "0x00000000\n";
|
||||
unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
|
||||
unsigned long val;
|
||||
|
||||
if (count > sizeof(buf) - 1)
|
||||
count = sizeof(buf) - 1;
|
||||
|
||||
if (copy_from_user(buf, buffer, count))
|
||||
if (copy_from_user(buf, buffer, len))
|
||||
return count;
|
||||
buf[count] = 0;
|
||||
/*
|
||||
* what a FPOS... What, sscanf(buf, "%i", &val) would be too
|
||||
* scary?
|
||||
*/
|
||||
if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
|
||||
p++;
|
||||
if (p[0] == 'x' || p[0] == 'X')
|
||||
p++;
|
||||
val = simple_strtoul(p, &p, 16);
|
||||
} else
|
||||
val = simple_strtoul(p, &p, 10);
|
||||
if (p == buf)
|
||||
buf[len] = 0;
|
||||
if (sscanf(buf, "%li", &val) != 1)
|
||||
printk(KERN_INFO DRV_NAME
|
||||
": %s is not in hex or decimal form.\n", buf);
|
||||
else
|
||||
ieee80211_debug_level = val;
|
||||
|
||||
return strlen(buf);
|
||||
return strnlen(buf, len);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211_DEBUG */
|
||||
|
||||
static int __init ieee80211_init(void)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211_DEBUG
|
||||
struct proc_dir_entry *e;
|
||||
|
||||
ieee80211_debug_level = debug;
|
||||
@@ -246,26 +246,33 @@ static int __init ieee80211_init(void)
|
||||
e->read_proc = show_debug_level;
|
||||
e->write_proc = store_debug_level;
|
||||
e->data = NULL;
|
||||
#endif /* CONFIG_IEEE80211_DEBUG */
|
||||
|
||||
printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
|
||||
printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ieee80211_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211_DEBUG
|
||||
if (ieee80211_proc) {
|
||||
remove_proc_entry("debug_level", ieee80211_proc);
|
||||
remove_proc_entry(DRV_NAME, proc_net);
|
||||
ieee80211_proc = NULL;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211_DEBUG */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211_DEBUG
|
||||
#include <linux/moduleparam.h>
|
||||
module_param(debug, int, 0444);
|
||||
MODULE_PARM_DESC(debug, "debug output mask");
|
||||
#endif /* CONFIG_IEEE80211_DEBUG */
|
||||
|
||||
module_exit(ieee80211_exit);
|
||||
module_init(ieee80211_init);
|
||||
#endif
|
||||
|
||||
const char *escape_essid(const char *essid, u8 essid_len)
|
||||
{
|
||||
|
||||
+464
-146
File diff suppressed because it is too large
Load Diff
+236
-83
@@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
|
||||
Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
|
||||
Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of version 2 of the GNU General Public License as
|
||||
@@ -128,7 +128,7 @@ payload of each frame is reduced to 492 bytes.
|
||||
static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
|
||||
static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
|
||||
|
||||
static inline int ieee80211_put_snap(u8 * data, u16 h_proto)
|
||||
static inline int ieee80211_copy_snap(u8 * data, u16 h_proto)
|
||||
{
|
||||
struct ieee80211_snap_hdr *snap;
|
||||
u8 *oui;
|
||||
@@ -157,31 +157,14 @@ static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
|
||||
struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
|
||||
int res;
|
||||
|
||||
#ifdef CONFIG_IEEE80211_CRYPT_TKIP
|
||||
struct ieee80211_hdr *header;
|
||||
|
||||
if (ieee->tkip_countermeasures &&
|
||||
crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
|
||||
header = (struct ieee80211_hdr *)frag->data;
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
|
||||
"TX packet to " MAC_FMT "\n",
|
||||
ieee->dev->name, MAC_ARG(header->addr1));
|
||||
}
|
||||
if (crypt == NULL)
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* To encrypt, frame format is:
|
||||
* IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
|
||||
|
||||
// PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
|
||||
/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
|
||||
* call both MSDU and MPDU encryption functions from here. */
|
||||
atomic_inc(&crypt->refcnt);
|
||||
res = 0;
|
||||
if (crypt->ops->encrypt_msdu)
|
||||
res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
|
||||
if (res == 0 && crypt->ops->encrypt_mpdu)
|
||||
if (crypt->ops && crypt->ops->encrypt_mpdu)
|
||||
res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
|
||||
|
||||
atomic_dec(&crypt->refcnt);
|
||||
@@ -207,7 +190,7 @@ void ieee80211_txb_free(struct ieee80211_txb *txb)
|
||||
}
|
||||
|
||||
static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
|
||||
gfp_t gfp_mask)
|
||||
int headroom, gfp_t gfp_mask)
|
||||
{
|
||||
struct ieee80211_txb *txb;
|
||||
int i;
|
||||
@@ -221,11 +204,13 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
|
||||
txb->frag_size = txb_size;
|
||||
|
||||
for (i = 0; i < nr_frags; i++) {
|
||||
txb->fragments[i] = dev_alloc_skb(txb_size);
|
||||
txb->fragments[i] = __dev_alloc_skb(txb_size + headroom,
|
||||
gfp_mask);
|
||||
if (unlikely(!txb->fragments[i])) {
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
skb_reserve(txb->fragments[i], headroom);
|
||||
}
|
||||
if (unlikely(i != nr_frags)) {
|
||||
while (i >= 0)
|
||||
@@ -236,25 +221,31 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
|
||||
return txb;
|
||||
}
|
||||
|
||||
/* SKBs are added to the ieee->tx_queue. */
|
||||
/* Incoming skb is converted to a txb which consists of
|
||||
* a block of 802.11 fragment packets (stored as skbs) */
|
||||
int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct ieee80211_device *ieee = netdev_priv(dev);
|
||||
struct ieee80211_txb *txb = NULL;
|
||||
struct ieee80211_hdr *frag_hdr;
|
||||
int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
|
||||
struct ieee80211_hdr_3addr *frag_hdr;
|
||||
int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
|
||||
rts_required;
|
||||
unsigned long flags;
|
||||
struct net_device_stats *stats = &ieee->stats;
|
||||
int ether_type, encrypt;
|
||||
int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
|
||||
int bytes, fc, hdr_len;
|
||||
struct sk_buff *skb_frag;
|
||||
struct ieee80211_hdr header = { /* Ensure zero initialized */
|
||||
struct ieee80211_hdr_3addr header = { /* Ensure zero initialized */
|
||||
.duration_id = 0,
|
||||
.seq_ctl = 0
|
||||
};
|
||||
u8 dest[ETH_ALEN], src[ETH_ALEN];
|
||||
|
||||
struct ieee80211_crypt_data *crypt;
|
||||
int priority = skb->priority;
|
||||
int snapped = 0;
|
||||
|
||||
if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))
|
||||
return NETDEV_TX_BUSY;
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
|
||||
@@ -276,7 +267,11 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
crypt = ieee->crypt[ieee->tx_keyidx];
|
||||
|
||||
encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
|
||||
ieee->host_encrypt && crypt && crypt->ops;
|
||||
ieee->sec.encrypt;
|
||||
|
||||
host_encrypt = ieee->host_encrypt && encrypt && crypt;
|
||||
host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt;
|
||||
host_build_iv = ieee->host_build_iv && encrypt && crypt;
|
||||
|
||||
if (!encrypt && ieee->ieee802_1x &&
|
||||
ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
|
||||
@@ -285,8 +280,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
|
||||
/* Save source and destination addresses */
|
||||
memcpy(&dest, skb->data, ETH_ALEN);
|
||||
memcpy(&src, skb->data + ETH_ALEN, ETH_ALEN);
|
||||
memcpy(dest, skb->data, ETH_ALEN);
|
||||
memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);
|
||||
|
||||
/* Advance the SKB to the start of the payload */
|
||||
skb_pull(skb, sizeof(struct ethhdr));
|
||||
@@ -294,7 +289,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
/* Determine total amount of storage required for TXB packets */
|
||||
bytes = skb->len + SNAP_SIZE + sizeof(u16);
|
||||
|
||||
if (encrypt)
|
||||
if (host_encrypt)
|
||||
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
|
||||
IEEE80211_FCTL_PROTECTED;
|
||||
else
|
||||
@@ -302,70 +297,144 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
if (ieee->iw_mode == IW_MODE_INFRA) {
|
||||
fc |= IEEE80211_FCTL_TODS;
|
||||
/* To DS: Addr1 = BSSID, Addr2 = SA,
|
||||
Addr3 = DA */
|
||||
memcpy(&header.addr1, ieee->bssid, ETH_ALEN);
|
||||
memcpy(&header.addr2, &src, ETH_ALEN);
|
||||
memcpy(&header.addr3, &dest, ETH_ALEN);
|
||||
/* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
|
||||
memcpy(header.addr1, ieee->bssid, ETH_ALEN);
|
||||
memcpy(header.addr2, src, ETH_ALEN);
|
||||
memcpy(header.addr3, dest, ETH_ALEN);
|
||||
} else if (ieee->iw_mode == IW_MODE_ADHOC) {
|
||||
/* not From/To DS: Addr1 = DA, Addr2 = SA,
|
||||
Addr3 = BSSID */
|
||||
memcpy(&header.addr1, dest, ETH_ALEN);
|
||||
memcpy(&header.addr2, src, ETH_ALEN);
|
||||
memcpy(&header.addr3, ieee->bssid, ETH_ALEN);
|
||||
/* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
|
||||
memcpy(header.addr1, dest, ETH_ALEN);
|
||||
memcpy(header.addr2, src, ETH_ALEN);
|
||||
memcpy(header.addr3, ieee->bssid, ETH_ALEN);
|
||||
}
|
||||
header.frame_ctl = cpu_to_le16(fc);
|
||||
hdr_len = IEEE80211_3ADDR_LEN;
|
||||
|
||||
/* Determine fragmentation size based on destination (multicast
|
||||
* and broadcast are not fragmented) */
|
||||
if (is_multicast_ether_addr(dest) || is_broadcast_ether_addr(dest))
|
||||
frag_size = MAX_FRAG_THRESHOLD;
|
||||
else
|
||||
frag_size = ieee->fts;
|
||||
/* Encrypt msdu first on the whole data packet. */
|
||||
if ((host_encrypt || host_encrypt_msdu) &&
|
||||
crypt && crypt->ops && crypt->ops->encrypt_msdu) {
|
||||
int res = 0;
|
||||
int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
|
||||
crypt->ops->extra_msdu_postfix_len;
|
||||
struct sk_buff *skb_new = dev_alloc_skb(len);
|
||||
|
||||
/* Determine amount of payload per fragment. Regardless of if
|
||||
* this stack is providing the full 802.11 header, one will
|
||||
* eventually be affixed to this fragment -- so we must account for
|
||||
* it when determining the amount of payload space. */
|
||||
bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
|
||||
if (ieee->config &
|
||||
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
|
||||
bytes_per_frag -= IEEE80211_FCS_LEN;
|
||||
if (unlikely(!skb_new))
|
||||
goto failed;
|
||||
|
||||
/* Each fragment may need to have room for encryptiong pre/postfix */
|
||||
if (encrypt)
|
||||
bytes_per_frag -= crypt->ops->extra_prefix_len +
|
||||
crypt->ops->extra_postfix_len;
|
||||
skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
|
||||
memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
|
||||
snapped = 1;
|
||||
ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
|
||||
ether_type);
|
||||
memcpy(skb_put(skb_new, skb->len), skb->data, skb->len);
|
||||
res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
|
||||
if (res < 0) {
|
||||
IEEE80211_ERROR("msdu encryption failed\n");
|
||||
dev_kfree_skb_any(skb_new);
|
||||
goto failed;
|
||||
}
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = skb_new;
|
||||
bytes += crypt->ops->extra_msdu_prefix_len +
|
||||
crypt->ops->extra_msdu_postfix_len;
|
||||
skb_pull(skb, hdr_len);
|
||||
}
|
||||
|
||||
/* Number of fragments is the total bytes_per_frag /
|
||||
* payload_per_fragment */
|
||||
nr_frags = bytes / bytes_per_frag;
|
||||
bytes_last_frag = bytes % bytes_per_frag;
|
||||
if (bytes_last_frag)
|
||||
if (host_encrypt || ieee->host_open_frag) {
|
||||
/* Determine fragmentation size based on destination (multicast
|
||||
* and broadcast are not fragmented) */
|
||||
if (is_multicast_ether_addr(dest) ||
|
||||
is_broadcast_ether_addr(dest))
|
||||
frag_size = MAX_FRAG_THRESHOLD;
|
||||
else
|
||||
frag_size = ieee->fts;
|
||||
|
||||
/* Determine amount of payload per fragment. Regardless of if
|
||||
* this stack is providing the full 802.11 header, one will
|
||||
* eventually be affixed to this fragment -- so we must account
|
||||
* for it when determining the amount of payload space. */
|
||||
bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
|
||||
if (ieee->config &
|
||||
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
|
||||
bytes_per_frag -= IEEE80211_FCS_LEN;
|
||||
|
||||
/* Each fragment may need to have room for encryptiong
|
||||
* pre/postfix */
|
||||
if (host_encrypt)
|
||||
bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
|
||||
crypt->ops->extra_mpdu_postfix_len;
|
||||
|
||||
/* Number of fragments is the total
|
||||
* bytes_per_frag / payload_per_fragment */
|
||||
nr_frags = bytes / bytes_per_frag;
|
||||
bytes_last_frag = bytes % bytes_per_frag;
|
||||
if (bytes_last_frag)
|
||||
nr_frags++;
|
||||
else
|
||||
bytes_last_frag = bytes_per_frag;
|
||||
} else {
|
||||
nr_frags = 1;
|
||||
bytes_per_frag = bytes_last_frag = bytes;
|
||||
frag_size = bytes + IEEE80211_3ADDR_LEN;
|
||||
}
|
||||
|
||||
rts_required = (frag_size > ieee->rts
|
||||
&& ieee->config & CFG_IEEE80211_RTS);
|
||||
if (rts_required)
|
||||
nr_frags++;
|
||||
else
|
||||
bytes_last_frag = bytes_per_frag;
|
||||
|
||||
/* When we allocate the TXB we allocate enough space for the reserve
|
||||
* and full fragment bytes (bytes_per_frag doesn't include prefix,
|
||||
* postfix, header, FCS, etc.) */
|
||||
txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
|
||||
txb = ieee80211_alloc_txb(nr_frags, frag_size,
|
||||
ieee->tx_headroom, GFP_ATOMIC);
|
||||
if (unlikely(!txb)) {
|
||||
printk(KERN_WARNING "%s: Could not allocate TXB\n",
|
||||
ieee->dev->name);
|
||||
goto failed;
|
||||
}
|
||||
txb->encrypted = encrypt;
|
||||
txb->payload_size = bytes;
|
||||
if (host_encrypt)
|
||||
txb->payload_size = frag_size * (nr_frags - 1) +
|
||||
bytes_last_frag;
|
||||
else
|
||||
txb->payload_size = bytes;
|
||||
|
||||
for (i = 0; i < nr_frags; i++) {
|
||||
if (rts_required) {
|
||||
skb_frag = txb->fragments[0];
|
||||
frag_hdr =
|
||||
(struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
|
||||
|
||||
/*
|
||||
* Set header frame_ctl to the RTS.
|
||||
*/
|
||||
header.frame_ctl =
|
||||
cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
|
||||
memcpy(frag_hdr, &header, hdr_len);
|
||||
|
||||
/*
|
||||
* Restore header frame_ctl to the original data setting.
|
||||
*/
|
||||
header.frame_ctl = cpu_to_le16(fc);
|
||||
|
||||
if (ieee->config &
|
||||
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
|
||||
skb_put(skb_frag, 4);
|
||||
|
||||
txb->rts_included = 1;
|
||||
i = 1;
|
||||
} else
|
||||
i = 0;
|
||||
|
||||
for (; i < nr_frags; i++) {
|
||||
skb_frag = txb->fragments[i];
|
||||
|
||||
if (encrypt)
|
||||
skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
|
||||
if (host_encrypt || host_build_iv)
|
||||
skb_reserve(skb_frag,
|
||||
crypt->ops->extra_mpdu_prefix_len);
|
||||
|
||||
frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len);
|
||||
frag_hdr =
|
||||
(struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
|
||||
memcpy(frag_hdr, &header, hdr_len);
|
||||
|
||||
/* If this is not the last fragment, then add the MOREFRAGS
|
||||
@@ -379,11 +448,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
bytes = bytes_last_frag;
|
||||
}
|
||||
|
||||
/* Put a SNAP header on the first fragment */
|
||||
if (i == 0) {
|
||||
ieee80211_put_snap(skb_put
|
||||
(skb_frag, SNAP_SIZE + sizeof(u16)),
|
||||
ether_type);
|
||||
if (i == 0 && !snapped) {
|
||||
ieee80211_copy_snap(skb_put
|
||||
(skb_frag, SNAP_SIZE + sizeof(u16)),
|
||||
ether_type);
|
||||
bytes -= SNAP_SIZE + sizeof(u16);
|
||||
}
|
||||
|
||||
@@ -394,8 +462,19 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
/* Encryption routine will move the header forward in order
|
||||
* to insert the IV between the header and the payload */
|
||||
if (encrypt)
|
||||
if (host_encrypt)
|
||||
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 &
|
||||
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
|
||||
skb_put(skb_frag, 4);
|
||||
@@ -407,11 +486,20 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
if (txb) {
|
||||
if ((*ieee->hard_start_xmit) (txb, dev) == 0) {
|
||||
int ret = (*ieee->hard_start_xmit) (txb, dev, priority);
|
||||
if (ret == 0) {
|
||||
stats->tx_packets++;
|
||||
stats->tx_bytes += txb->payload_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ret == NETDEV_TX_BUSY) {
|
||||
printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; "
|
||||
"driver should report queue full via "
|
||||
"ieee_device->is_queue_full.\n",
|
||||
ieee->dev->name);
|
||||
}
|
||||
|
||||
ieee80211_txb_free(txb);
|
||||
}
|
||||
|
||||
@@ -422,7 +510,72 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
netif_stop_queue(dev);
|
||||
stats->tx_errors++;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* Incoming 802.11 strucure is converted to a TXB
|
||||
* a block of 802.11 fragment packets (stored as skbs) */
|
||||
int ieee80211_tx_frame(struct ieee80211_device *ieee,
|
||||
struct ieee80211_hdr *frame, int len)
|
||||
{
|
||||
struct ieee80211_txb *txb = NULL;
|
||||
unsigned long flags;
|
||||
struct net_device_stats *stats = &ieee->stats;
|
||||
struct sk_buff *skb_frag;
|
||||
int priority = -1;
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
|
||||
/* If there is no driver handler to take the TXB, dont' bother
|
||||
* creating it... */
|
||||
if (!ieee->hard_start_xmit) {
|
||||
printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
|
||||
goto success;
|
||||
}
|
||||
|
||||
if (unlikely(len < 24)) {
|
||||
printk(KERN_WARNING "%s: skb too small (%d).\n",
|
||||
ieee->dev->name, len);
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* When we allocate the TXB we allocate enough space for the reserve
|
||||
* and full fragment bytes (bytes_per_frag doesn't include prefix,
|
||||
* postfix, header, FCS, etc.) */
|
||||
txb = ieee80211_alloc_txb(1, len, ieee->tx_headroom, GFP_ATOMIC);
|
||||
if (unlikely(!txb)) {
|
||||
printk(KERN_WARNING "%s: Could not allocate TXB\n",
|
||||
ieee->dev->name);
|
||||
goto failed;
|
||||
}
|
||||
txb->encrypted = 0;
|
||||
txb->payload_size = len;
|
||||
|
||||
skb_frag = txb->fragments[0];
|
||||
|
||||
memcpy(skb_put(skb_frag, len), frame, len);
|
||||
|
||||
if (ieee->config &
|
||||
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
|
||||
skb_put(skb_frag, 4);
|
||||
|
||||
success:
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
|
||||
if (txb) {
|
||||
if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) {
|
||||
stats->tx_packets++;
|
||||
stats->tx_bytes += txb->payload_size;
|
||||
return 0;
|
||||
}
|
||||
ieee80211_txb_free(txb);
|
||||
}
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
stats->tx_errors++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ieee80211_tx_frame);
|
||||
EXPORT_SYMBOL(ieee80211_txb_free);
|
||||
|
||||
+318
-56
@@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
|
||||
Copyright(c) 2004 Intel Corporation. All rights reserved.
|
||||
Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
|
||||
|
||||
Portions of this file are based on the WEP enablement code provided by the
|
||||
Host AP project hostap-drivers v0.1.3
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
#include <net/ieee80211.h>
|
||||
#include <linux/wireless.h>
|
||||
@@ -140,18 +141,41 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
|
||||
start = iwe_stream_add_point(start, stop, &iwe, custom);
|
||||
|
||||
/* Add quality statistics */
|
||||
/* TODO: Fix these values... */
|
||||
iwe.cmd = IWEVQUAL;
|
||||
iwe.u.qual.qual = network->stats.signal;
|
||||
iwe.u.qual.level = network->stats.rssi;
|
||||
iwe.u.qual.noise = network->stats.noise;
|
||||
iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
|
||||
if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
|
||||
iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
|
||||
if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
|
||||
iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
|
||||
IW_QUAL_NOISE_UPDATED;
|
||||
|
||||
if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
|
||||
iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
|
||||
IW_QUAL_LEVEL_INVALID;
|
||||
iwe.u.qual.qual = 0;
|
||||
iwe.u.qual.level = 0;
|
||||
} else {
|
||||
iwe.u.qual.level = network->stats.rssi;
|
||||
if (ieee->perfect_rssi == ieee->worst_rssi)
|
||||
iwe.u.qual.qual = 100;
|
||||
else
|
||||
iwe.u.qual.qual =
|
||||
(100 *
|
||||
(ieee->perfect_rssi - ieee->worst_rssi) *
|
||||
(ieee->perfect_rssi - ieee->worst_rssi) -
|
||||
(ieee->perfect_rssi - network->stats.rssi) *
|
||||
(15 * (ieee->perfect_rssi - ieee->worst_rssi) +
|
||||
62 * (ieee->perfect_rssi - network->stats.rssi))) /
|
||||
((ieee->perfect_rssi - ieee->worst_rssi) *
|
||||
(ieee->perfect_rssi - ieee->worst_rssi));
|
||||
if (iwe.u.qual.qual > 100)
|
||||
iwe.u.qual.qual = 100;
|
||||
else if (iwe.u.qual.qual < 1)
|
||||
iwe.u.qual.qual = 0;
|
||||
}
|
||||
|
||||
if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
|
||||
iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
|
||||
if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
|
||||
iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
|
||||
iwe.u.qual.noise = 0;
|
||||
} else {
|
||||
iwe.u.qual.noise = network->stats.noise;
|
||||
}
|
||||
|
||||
start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
|
||||
|
||||
@@ -162,7 +186,7 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
|
||||
if (iwe.u.data.length)
|
||||
start = iwe_stream_add_point(start, stop, &iwe, custom);
|
||||
|
||||
if (ieee->wpa_enabled && network->wpa_ie_len) {
|
||||
if (network->wpa_ie_len) {
|
||||
char buf[MAX_WPA_IE_LEN * 2 + 30];
|
||||
|
||||
u8 *p = buf;
|
||||
@@ -177,7 +201,7 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
|
||||
start = iwe_stream_add_point(start, stop, &iwe, buf);
|
||||
}
|
||||
|
||||
if (ieee->wpa_enabled && network->rsn_ie_len) {
|
||||
if (network->rsn_ie_len) {
|
||||
char buf[MAX_WPA_IE_LEN * 2 + 30];
|
||||
|
||||
u8 *p = buf;
|
||||
@@ -197,8 +221,8 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
|
||||
iwe.cmd = IWEVCUSTOM;
|
||||
p = custom;
|
||||
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
|
||||
" Last beacon: %lums ago",
|
||||
(jiffies - network->last_scanned) / (HZ / 100));
|
||||
" Last beacon: %dms ago",
|
||||
jiffies_to_msecs(jiffies - network->last_scanned));
|
||||
iwe.u.data.length = p - custom;
|
||||
if (iwe.u.data.length)
|
||||
start = iwe_stream_add_point(start, stop, &iwe, custom);
|
||||
@@ -228,13 +252,13 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
|
||||
ev = ipw2100_translate_scan(ieee, ev, stop, network);
|
||||
else
|
||||
IEEE80211_DEBUG_SCAN("Not showing network '%s ("
|
||||
MAC_FMT ")' due to age (%lums).\n",
|
||||
MAC_FMT ")' due to age (%dms).\n",
|
||||
escape_essid(network->ssid,
|
||||
network->ssid_len),
|
||||
MAC_ARG(network->bssid),
|
||||
(jiffies -
|
||||
network->last_scanned) / (HZ /
|
||||
100));
|
||||
jiffies_to_msecs(jiffies -
|
||||
network->
|
||||
last_scanned));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
@@ -258,6 +282,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
||||
};
|
||||
int i, key, key_provided, len;
|
||||
struct ieee80211_crypt_data **crypt;
|
||||
int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
|
||||
|
||||
IEEE80211_DEBUG_WX("SET_ENCODE\n");
|
||||
|
||||
@@ -298,15 +323,17 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
||||
|
||||
if (i == WEP_KEYS) {
|
||||
sec.enabled = 0;
|
||||
sec.encrypt = 0;
|
||||
sec.level = SEC_LEVEL_0;
|
||||
sec.flags |= SEC_ENABLED | SEC_LEVEL;
|
||||
sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
|
||||
}
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
sec.enabled = 1;
|
||||
sec.flags |= SEC_ENABLED;
|
||||
sec.encrypt = 1;
|
||||
sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
|
||||
|
||||
if (*crypt != NULL && (*crypt)->ops != NULL &&
|
||||
strcmp((*crypt)->ops->name, "WEP") != 0) {
|
||||
@@ -315,7 +342,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
||||
ieee80211_crypt_delayed_deinit(ieee, crypt);
|
||||
}
|
||||
|
||||
if (*crypt == NULL) {
|
||||
if (*crypt == NULL && host_crypto) {
|
||||
struct ieee80211_crypt_data *new_crypt;
|
||||
|
||||
/* take WEP into use */
|
||||
@@ -355,49 +382,56 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
||||
key, escape_essid(sec.keys[key], len),
|
||||
erq->length, len);
|
||||
sec.key_sizes[key] = len;
|
||||
(*crypt)->ops->set_key(sec.keys[key], len, NULL,
|
||||
(*crypt)->priv);
|
||||
if (*crypt)
|
||||
(*crypt)->ops->set_key(sec.keys[key], len, NULL,
|
||||
(*crypt)->priv);
|
||||
sec.flags |= (1 << key);
|
||||
/* This ensures a key will be activated if no key is
|
||||
* explicitely set */
|
||||
if (key == sec.active_key)
|
||||
sec.flags |= SEC_ACTIVE_KEY;
|
||||
} else {
|
||||
len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
|
||||
NULL, (*crypt)->priv);
|
||||
if (len == 0) {
|
||||
/* Set a default key of all 0 */
|
||||
IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
|
||||
key);
|
||||
memset(sec.keys[key], 0, 13);
|
||||
(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
|
||||
(*crypt)->priv);
|
||||
sec.key_sizes[key] = 13;
|
||||
sec.flags |= (1 << key);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (host_crypto) {
|
||||
len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
|
||||
NULL, (*crypt)->priv);
|
||||
if (len == 0) {
|
||||
/* Set a default key of all 0 */
|
||||
IEEE80211_DEBUG_WX("Setting key %d to all "
|
||||
"zero.\n", key);
|
||||
memset(sec.keys[key], 0, 13);
|
||||
(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
|
||||
(*crypt)->priv);
|
||||
sec.key_sizes[key] = 13;
|
||||
sec.flags |= (1 << key);
|
||||
}
|
||||
}
|
||||
/* No key data - just set the default TX key index */
|
||||
if (key_provided) {
|
||||
IEEE80211_DEBUG_WX
|
||||
("Setting key %d to default Tx key.\n", key);
|
||||
IEEE80211_DEBUG_WX("Setting key %d to default Tx "
|
||||
"key.\n", key);
|
||||
ieee->tx_keyidx = key;
|
||||
sec.active_key = key;
|
||||
sec.flags |= SEC_ACTIVE_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
|
||||
sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
|
||||
sec.flags |= SEC_AUTH_MODE;
|
||||
IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
|
||||
"OPEN" : "SHARED KEY");
|
||||
if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
|
||||
ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
|
||||
sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
|
||||
WLAN_AUTH_SHARED_KEY;
|
||||
sec.flags |= SEC_AUTH_MODE;
|
||||
IEEE80211_DEBUG_WX("Auth: %s\n",
|
||||
sec.auth_mode == WLAN_AUTH_OPEN ?
|
||||
"OPEN" : "SHARED KEY");
|
||||
}
|
||||
|
||||
/* For now we just support WEP, so only set that security level...
|
||||
* TODO: When WPA is added this is one place that needs to change */
|
||||
sec.flags |= SEC_LEVEL;
|
||||
sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
|
||||
sec.encode_alg[key] = SEC_ALG_WEP;
|
||||
|
||||
done:
|
||||
if (ieee->set_security)
|
||||
ieee->set_security(dev, &sec);
|
||||
|
||||
@@ -422,6 +456,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
|
||||
struct iw_point *erq = &(wrqu->encoding);
|
||||
int len, key;
|
||||
struct ieee80211_crypt_data *crypt;
|
||||
struct ieee80211_security *sec = &ieee->sec;
|
||||
|
||||
IEEE80211_DEBUG_WX("GET_ENCODE\n");
|
||||
|
||||
@@ -436,23 +471,16 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
|
||||
crypt = ieee->crypt[key];
|
||||
erq->flags = key + 1;
|
||||
|
||||
if (crypt == NULL || crypt->ops == NULL) {
|
||||
if (!sec->enabled) {
|
||||
erq->length = 0;
|
||||
erq->flags |= IW_ENCODE_DISABLED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(crypt->ops->name, "WEP") != 0) {
|
||||
/* only WEP is supported with wireless extensions, so just
|
||||
* report that encryption is used */
|
||||
erq->length = 0;
|
||||
erq->flags |= IW_ENCODE_ENABLED;
|
||||
return 0;
|
||||
}
|
||||
len = sec->key_sizes[key];
|
||||
memcpy(keybuf, sec->keys[key], len);
|
||||
|
||||
len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
|
||||
erq->length = (len >= 0 ? len : 0);
|
||||
|
||||
erq->flags |= IW_ENCODE_ENABLED;
|
||||
|
||||
if (ieee->open_wep)
|
||||
@@ -463,6 +491,240 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct net_device *dev = ieee->dev;
|
||||
struct iw_point *encoding = &wrqu->encoding;
|
||||
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
|
||||
int i, idx, ret = 0;
|
||||
int group_key = 0;
|
||||
const char *alg, *module;
|
||||
struct ieee80211_crypto_ops *ops;
|
||||
struct ieee80211_crypt_data **crypt;
|
||||
|
||||
struct ieee80211_security sec = {
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
idx = encoding->flags & IW_ENCODE_INDEX;
|
||||
if (idx) {
|
||||
if (idx < 1 || idx > WEP_KEYS)
|
||||
return -EINVAL;
|
||||
idx--;
|
||||
} else
|
||||
idx = ieee->tx_keyidx;
|
||||
|
||||
if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
|
||||
crypt = &ieee->crypt[idx];
|
||||
group_key = 1;
|
||||
} else {
|
||||
if (idx != 0)
|
||||
return -EINVAL;
|
||||
if (ieee->iw_mode == IW_MODE_INFRA)
|
||||
crypt = &ieee->crypt[idx];
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
|
||||
if ((encoding->flags & IW_ENCODE_DISABLED) ||
|
||||
ext->alg == IW_ENCODE_ALG_NONE) {
|
||||
if (*crypt)
|
||||
ieee80211_crypt_delayed_deinit(ieee, crypt);
|
||||
|
||||
for (i = 0; i < WEP_KEYS; i++)
|
||||
if (ieee->crypt[i] != NULL)
|
||||
break;
|
||||
|
||||
if (i == WEP_KEYS) {
|
||||
sec.enabled = 0;
|
||||
sec.encrypt = 0;
|
||||
sec.level = SEC_LEVEL_0;
|
||||
sec.flags |= SEC_LEVEL;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
sec.enabled = 1;
|
||||
sec.encrypt = 1;
|
||||
|
||||
if (group_key ? !ieee->host_mc_decrypt :
|
||||
!(ieee->host_encrypt || ieee->host_decrypt ||
|
||||
ieee->host_encrypt_msdu))
|
||||
goto skip_host_crypt;
|
||||
|
||||
switch (ext->alg) {
|
||||
case IW_ENCODE_ALG_WEP:
|
||||
alg = "WEP";
|
||||
module = "ieee80211_crypt_wep";
|
||||
break;
|
||||
case IW_ENCODE_ALG_TKIP:
|
||||
alg = "TKIP";
|
||||
module = "ieee80211_crypt_tkip";
|
||||
break;
|
||||
case IW_ENCODE_ALG_CCMP:
|
||||
alg = "CCMP";
|
||||
module = "ieee80211_crypt_ccmp";
|
||||
break;
|
||||
default:
|
||||
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
|
||||
dev->name, ext->alg);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ops = ieee80211_get_crypto_ops(alg);
|
||||
if (ops == NULL) {
|
||||
request_module(module);
|
||||
ops = ieee80211_get_crypto_ops(alg);
|
||||
}
|
||||
if (ops == NULL) {
|
||||
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
|
||||
dev->name, ext->alg);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (*crypt == NULL || (*crypt)->ops != ops) {
|
||||
struct ieee80211_crypt_data *new_crypt;
|
||||
|
||||
ieee80211_crypt_delayed_deinit(ieee, crypt);
|
||||
|
||||
new_crypt = (struct ieee80211_crypt_data *)
|
||||
kmalloc(sizeof(*new_crypt), GFP_KERNEL);
|
||||
if (new_crypt == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
|
||||
new_crypt->ops = ops;
|
||||
if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
|
||||
new_crypt->priv = new_crypt->ops->init(idx);
|
||||
if (new_crypt->priv == NULL) {
|
||||
kfree(new_crypt);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
*crypt = new_crypt;
|
||||
}
|
||||
|
||||
if (ext->key_len > 0 && (*crypt)->ops->set_key &&
|
||||
(*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
|
||||
(*crypt)->priv) < 0) {
|
||||
IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
skip_host_crypt:
|
||||
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
|
||||
ieee->tx_keyidx = idx;
|
||||
sec.active_key = idx;
|
||||
sec.flags |= SEC_ACTIVE_KEY;
|
||||
}
|
||||
|
||||
if (ext->alg != IW_ENCODE_ALG_NONE) {
|
||||
memcpy(sec.keys[idx], ext->key, ext->key_len);
|
||||
sec.key_sizes[idx] = ext->key_len;
|
||||
sec.flags |= (1 << idx);
|
||||
if (ext->alg == IW_ENCODE_ALG_WEP) {
|
||||
sec.encode_alg[idx] = SEC_ALG_WEP;
|
||||
sec.flags |= SEC_LEVEL;
|
||||
sec.level = SEC_LEVEL_1;
|
||||
} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
|
||||
sec.encode_alg[idx] = SEC_ALG_TKIP;
|
||||
sec.flags |= SEC_LEVEL;
|
||||
sec.level = SEC_LEVEL_2;
|
||||
} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
|
||||
sec.encode_alg[idx] = SEC_ALG_CCMP;
|
||||
sec.flags |= SEC_LEVEL;
|
||||
sec.level = SEC_LEVEL_3;
|
||||
}
|
||||
/* Don't set sec level for group keys. */
|
||||
if (group_key)
|
||||
sec.flags &= ~SEC_LEVEL;
|
||||
}
|
||||
done:
|
||||
if (ieee->set_security)
|
||||
ieee->set_security(ieee->dev, &sec);
|
||||
|
||||
/*
|
||||
* Do not reset port if card is in Managed mode since resetting will
|
||||
* generate new IEEE 802.11 authentication which may end up in looping
|
||||
* with IEEE 802.1X. If your hardware requires a reset after WEP
|
||||
* configuration (for example... Prism2), implement the reset_port in
|
||||
* the callbacks structures used to initialize the 802.11 stack.
|
||||
*/
|
||||
if (ieee->reset_on_keychange &&
|
||||
ieee->iw_mode != IW_MODE_INFRA &&
|
||||
ieee->reset_port && ieee->reset_port(dev)) {
|
||||
IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct iw_point *encoding = &wrqu->encoding;
|
||||
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
|
||||
struct ieee80211_security *sec = &ieee->sec;
|
||||
int idx, max_key_len;
|
||||
|
||||
max_key_len = encoding->length - sizeof(*ext);
|
||||
if (max_key_len < 0)
|
||||
return -EINVAL;
|
||||
|
||||
idx = encoding->flags & IW_ENCODE_INDEX;
|
||||
if (idx) {
|
||||
if (idx < 1 || idx > WEP_KEYS)
|
||||
return -EINVAL;
|
||||
idx--;
|
||||
} else
|
||||
idx = ieee->tx_keyidx;
|
||||
|
||||
if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
|
||||
if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
|
||||
return -EINVAL;
|
||||
|
||||
encoding->flags = idx + 1;
|
||||
memset(ext, 0, sizeof(*ext));
|
||||
|
||||
if (!sec->enabled) {
|
||||
ext->alg = IW_ENCODE_ALG_NONE;
|
||||
ext->key_len = 0;
|
||||
encoding->flags |= IW_ENCODE_DISABLED;
|
||||
} else {
|
||||
if (sec->encode_alg[idx] == SEC_ALG_WEP)
|
||||
ext->alg = IW_ENCODE_ALG_WEP;
|
||||
else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
|
||||
ext->alg = IW_ENCODE_ALG_TKIP;
|
||||
else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
|
||||
ext->alg = IW_ENCODE_ALG_CCMP;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
ext->key_len = sec->key_sizes[idx];
|
||||
memcpy(ext->key, sec->keys[idx], ext->key_len);
|
||||
encoding->flags |= IW_ENCODE_ENABLED;
|
||||
if (ext->key_len &&
|
||||
(ext->alg == IW_ENCODE_ALG_TKIP ||
|
||||
ext->alg == IW_ENCODE_ALG_CCMP))
|
||||
ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
|
||||
EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
|
||||
|
||||
EXPORT_SYMBOL(ieee80211_wx_get_scan);
|
||||
EXPORT_SYMBOL(ieee80211_wx_set_encode);
|
||||
EXPORT_SYMBOL(ieee80211_wx_get_encode);
|
||||
|
||||
+2
-1
@@ -715,6 +715,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
|
||||
break;
|
||||
ret = 0;
|
||||
if (ifa->ifa_mask != sin->sin_addr.s_addr) {
|
||||
u32 old_mask = ifa->ifa_mask;
|
||||
inet_del_ifa(in_dev, ifap, 0);
|
||||
ifa->ifa_mask = sin->sin_addr.s_addr;
|
||||
ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
|
||||
@@ -728,7 +729,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
|
||||
if ((dev->flags & IFF_BROADCAST) &&
|
||||
(ifa->ifa_prefixlen < 31) &&
|
||||
(ifa->ifa_broadcast ==
|
||||
(ifa->ifa_local|~ifa->ifa_mask))) {
|
||||
(ifa->ifa_local|~old_mask))) {
|
||||
ifa->ifa_broadcast = (ifa->ifa_local |
|
||||
~sin->sin_addr.s_addr);
|
||||
}
|
||||
|
||||
+1
-1
@@ -2404,7 +2404,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
|
||||
prefix = htonl(l->key);
|
||||
|
||||
list_for_each_entry_rcu(fa, &li->falh, fa_list) {
|
||||
const struct fib_info *fi = rcu_dereference(fa->fa_info);
|
||||
const struct fib_info *fi = fa->fa_info;
|
||||
unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
|
||||
|
||||
if (fa->fa_type == RTN_BROADCAST
|
||||
|
||||
+1
-4
@@ -1108,12 +1108,9 @@ void __init icmp_init(struct net_proto_family *ops)
|
||||
struct inet_sock *inet;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NR_CPUS; i++) {
|
||||
for_each_cpu(i) {
|
||||
int err;
|
||||
|
||||
if (!cpu_possible(i))
|
||||
continue;
|
||||
|
||||
err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
|
||||
&per_cpu(__icmp_socket, i));
|
||||
|
||||
|
||||
@@ -1023,10 +1023,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page,
|
||||
int alloclen;
|
||||
|
||||
skb_prev = skb;
|
||||
if (skb_prev)
|
||||
fraggap = skb_prev->len - maxfraglen;
|
||||
else
|
||||
fraggap = 0;
|
||||
fraggap = skb_prev->len - maxfraglen;
|
||||
|
||||
alloclen = fragheaderlen + hh_len + fraggap + 15;
|
||||
skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user