Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
This commit is contained in:
commit
4f975b3243
|
@ -220,6 +220,7 @@ struct ieee80211_snap_hdr {
|
|||
/* Authentication algorithms */
|
||||
#define WLAN_AUTH_OPEN 0
|
||||
#define WLAN_AUTH_SHARED_KEY 1
|
||||
#define WLAN_AUTH_LEAP 2
|
||||
|
||||
#define WLAN_AUTH_CHALLENGE_LEN 128
|
||||
|
||||
|
@ -299,6 +300,23 @@ enum ieee80211_reasoncode {
|
|||
WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
|
||||
};
|
||||
|
||||
/* Action categories - 802.11h */
|
||||
enum ieee80211_actioncategories {
|
||||
WLAN_ACTION_SPECTRUM_MGMT = 0,
|
||||
/* Reserved 1-127 */
|
||||
/* Error 128-255 */
|
||||
};
|
||||
|
||||
/* Action details - 802.11h */
|
||||
enum ieee80211_actiondetails {
|
||||
WLAN_ACTION_CATEGORY_MEASURE_REQUEST = 0,
|
||||
WLAN_ACTION_CATEGORY_MEASURE_REPORT = 1,
|
||||
WLAN_ACTION_CATEGORY_TPC_REQUEST = 2,
|
||||
WLAN_ACTION_CATEGORY_TPC_REPORT = 3,
|
||||
WLAN_ACTION_CATEGORY_CHANNEL_SWITCH = 4,
|
||||
/* 5 - 255 Reserved */
|
||||
};
|
||||
|
||||
#define IEEE80211_STATMASK_SIGNAL (1<<0)
|
||||
#define IEEE80211_STATMASK_RSSI (1<<1)
|
||||
#define IEEE80211_STATMASK_NOISE (1<<2)
|
||||
|
@ -377,6 +395,8 @@ struct ieee80211_rx_stats {
|
|||
u8 mask;
|
||||
u8 freq;
|
||||
u16 len;
|
||||
u64 tsf;
|
||||
u32 beacon_time;
|
||||
};
|
||||
|
||||
/* IEEE 802.11 requires that STA supports concurrent reception of at least
|
||||
|
@ -608,6 +628,28 @@ struct ieee80211_auth {
|
|||
struct ieee80211_info_element info_element[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_channel_switch {
|
||||
u8 id;
|
||||
u8 len;
|
||||
u8 mode;
|
||||
u8 channel;
|
||||
u8 count;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_action {
|
||||
struct ieee80211_hdr_3addr header;
|
||||
u8 category;
|
||||
u8 action;
|
||||
union {
|
||||
struct ieee80211_action_exchange {
|
||||
u8 token;
|
||||
struct ieee80211_info_element info_element[0];
|
||||
} exchange;
|
||||
struct ieee80211_channel_switch channel_switch;
|
||||
|
||||
} format;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_disassoc {
|
||||
struct ieee80211_hdr_3addr header;
|
||||
__le16 reason;
|
||||
|
@ -692,7 +734,15 @@ struct ieee80211_txb {
|
|||
/* QoS structure */
|
||||
#define NETWORK_HAS_QOS_PARAMETERS (1<<3)
|
||||
#define NETWORK_HAS_QOS_INFORMATION (1<<4)
|
||||
#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | NETWORK_HAS_QOS_INFORMATION)
|
||||
#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | \
|
||||
NETWORK_HAS_QOS_INFORMATION)
|
||||
|
||||
/* 802.11h */
|
||||
#define NETWORK_HAS_POWER_CONSTRAINT (1<<5)
|
||||
#define NETWORK_HAS_CSA (1<<6)
|
||||
#define NETWORK_HAS_QUIET (1<<7)
|
||||
#define NETWORK_HAS_IBSS_DFS (1<<8)
|
||||
#define NETWORK_HAS_TPC_REPORT (1<<9)
|
||||
|
||||
#define QOS_QUEUE_NUM 4
|
||||
#define QOS_OUI_LEN 3
|
||||
|
@ -748,6 +798,91 @@ struct ieee80211_tim_parameters {
|
|||
|
||||
/*******************************************************/
|
||||
|
||||
enum { /* ieee80211_basic_report.map */
|
||||
IEEE80211_BASIC_MAP_BSS = (1 << 0),
|
||||
IEEE80211_BASIC_MAP_OFDM = (1 << 1),
|
||||
IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2),
|
||||
IEEE80211_BASIC_MAP_RADAR = (1 << 3),
|
||||
IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4),
|
||||
/* Bits 5-7 are reserved */
|
||||
|
||||
};
|
||||
struct ieee80211_basic_report {
|
||||
u8 channel;
|
||||
__le64 start_time;
|
||||
__le16 duration;
|
||||
u8 map;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum { /* ieee80211_measurement_request.mode */
|
||||
/* Bit 0 is reserved */
|
||||
IEEE80211_MEASUREMENT_ENABLE = (1 << 1),
|
||||
IEEE80211_MEASUREMENT_REQUEST = (1 << 2),
|
||||
IEEE80211_MEASUREMENT_REPORT = (1 << 3),
|
||||
/* Bits 4-7 are reserved */
|
||||
};
|
||||
|
||||
enum {
|
||||
IEEE80211_REPORT_BASIC = 0, /* required */
|
||||
IEEE80211_REPORT_CCA = 1, /* optional */
|
||||
IEEE80211_REPORT_RPI = 2, /* optional */
|
||||
/* 3-255 reserved */
|
||||
};
|
||||
|
||||
struct ieee80211_measurement_params {
|
||||
u8 channel;
|
||||
__le64 start_time;
|
||||
__le16 duration;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_measurement_request {
|
||||
struct ieee80211_info_element ie;
|
||||
u8 token;
|
||||
u8 mode;
|
||||
u8 type;
|
||||
struct ieee80211_measurement_params params[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_measurement_report {
|
||||
struct ieee80211_info_element ie;
|
||||
u8 token;
|
||||
u8 mode;
|
||||
u8 type;
|
||||
union {
|
||||
struct ieee80211_basic_report basic[0];
|
||||
} u;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_tpc_report {
|
||||
u8 transmit_power;
|
||||
u8 link_margin;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_channel_map {
|
||||
u8 channel;
|
||||
u8 map;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_ibss_dfs {
|
||||
struct ieee80211_info_element ie;
|
||||
u8 owner[ETH_ALEN];
|
||||
u8 recovery_interval;
|
||||
struct ieee80211_channel_map channel_map[0];
|
||||
};
|
||||
|
||||
struct ieee80211_csa {
|
||||
u8 mode;
|
||||
u8 channel;
|
||||
u8 count;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_quiet {
|
||||
u8 count;
|
||||
u8 period;
|
||||
u8 duration;
|
||||
u8 offset;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_network {
|
||||
/* These entries are used to identify a unique network */
|
||||
u8 bssid[ETH_ALEN];
|
||||
|
@ -767,7 +902,7 @@ struct ieee80211_network {
|
|||
u8 rates_ex_len;
|
||||
unsigned long last_scanned;
|
||||
u8 mode;
|
||||
u8 flags;
|
||||
u32 flags;
|
||||
u32 last_associate;
|
||||
u32 time_stamp[2];
|
||||
u16 beacon_interval;
|
||||
|
@ -779,6 +914,25 @@ struct ieee80211_network {
|
|||
u8 rsn_ie[MAX_WPA_IE_LEN];
|
||||
size_t rsn_ie_len;
|
||||
struct ieee80211_tim_parameters tim;
|
||||
|
||||
/* 802.11h info */
|
||||
|
||||
/* Power Constraint - mandatory if spctrm mgmt required */
|
||||
u8 power_constraint;
|
||||
|
||||
/* TPC Report - mandatory if spctrm mgmt required */
|
||||
struct ieee80211_tpc_report tpc_report;
|
||||
|
||||
/* IBSS DFS - mandatory if spctrm mgmt required and IBSS
|
||||
* NOTE: This is variable length and so must be allocated dynamically */
|
||||
struct ieee80211_ibss_dfs *ibss_dfs;
|
||||
|
||||
/* Channel Switch Announcement - optional if spctrm mgmt required */
|
||||
struct ieee80211_csa csa;
|
||||
|
||||
/* Quiet - optional if spctrm mgmt required */
|
||||
struct ieee80211_quiet quiet;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
|
@ -924,7 +1078,10 @@ struct ieee80211_device {
|
|||
int (*handle_auth) (struct net_device * dev,
|
||||
struct ieee80211_auth * auth);
|
||||
int (*handle_deauth) (struct net_device * dev,
|
||||
struct ieee80211_auth * auth);
|
||||
struct ieee80211_deauth * auth);
|
||||
int (*handle_action) (struct net_device * dev,
|
||||
struct ieee80211_action * action,
|
||||
struct ieee80211_rx_stats * stats);
|
||||
int (*handle_disassoc) (struct net_device * dev,
|
||||
struct ieee80211_disassoc * assoc);
|
||||
int (*handle_beacon) (struct net_device * dev,
|
||||
|
@ -1093,6 +1250,7 @@ extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
|
|||
extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
|
||||
struct ieee80211_hdr_4addr *header,
|
||||
struct ieee80211_rx_stats *stats);
|
||||
extern void ieee80211_network_reset(struct ieee80211_network *network);
|
||||
|
||||
/* ieee80211_geo.c */
|
||||
extern const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device
|
||||
|
@ -1105,6 +1263,11 @@ extern int ieee80211_is_valid_channel(struct ieee80211_device *ieee,
|
|||
extern int ieee80211_channel_to_index(struct ieee80211_device *ieee,
|
||||
u8 channel);
|
||||
extern u8 ieee80211_freq_to_channel(struct ieee80211_device *ieee, u32 freq);
|
||||
extern u8 ieee80211_get_channel_flags(struct ieee80211_device *ieee,
|
||||
u8 channel);
|
||||
extern const struct ieee80211_channel *ieee80211_get_channel(struct
|
||||
ieee80211_device
|
||||
*ieee, u8 channel);
|
||||
|
||||
/* ieee80211_wx.c */
|
||||
extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
|
||||
|
|
|
@ -47,7 +47,8 @@ struct ieee80211_crypto_ops {
|
|||
/* deinitialize crypto context and free allocated private data */
|
||||
void (*deinit) (void *priv);
|
||||
|
||||
int (*build_iv) (struct sk_buff * skb, int hdr_len, void *priv);
|
||||
int (*build_iv) (struct sk_buff * skb, int hdr_len,
|
||||
u8 *key, int keylen, void *priv);
|
||||
|
||||
/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
|
||||
* value from decrypt_mpdu is passed as the keyidx value for
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <linux/string.h>
|
||||
#include <net/ieee80211.h>
|
||||
|
||||
|
||||
MODULE_AUTHOR("Jouni Malinen");
|
||||
MODULE_DESCRIPTION("HostAP crypto");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -33,11 +32,11 @@ static DEFINE_SPINLOCK(ieee80211_crypto_lock);
|
|||
|
||||
void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
|
||||
{
|
||||
struct ieee80211_crypt_data *entry, *next;
|
||||
struct ieee80211_crypt_data *entry, *next;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) {
|
||||
list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) {
|
||||
if (atomic_read(&entry->refcnt) != 0 && !force)
|
||||
continue;
|
||||
|
||||
|
@ -141,9 +140,9 @@ int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
|
|||
spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
|
||||
return -EINVAL;
|
||||
|
||||
found:
|
||||
found:
|
||||
printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
|
||||
"'%s'\n", ops->name);
|
||||
"'%s'\n", ops->name);
|
||||
list_del(&alg->list);
|
||||
spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
|
||||
kfree(alg);
|
||||
|
@ -163,7 +162,7 @@ struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
|
|||
spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
|
||||
return NULL;
|
||||
|
||||
found:
|
||||
found:
|
||||
spin_unlock_irqrestore(&ieee80211_crypto_lock, flags);
|
||||
return alg->ops;
|
||||
}
|
||||
|
|
|
@ -190,7 +190,8 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
|
|||
ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
|
||||
}
|
||||
|
||||
static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
|
||||
static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
|
||||
u8 *aeskey, int keylen, void *priv)
|
||||
{
|
||||
struct ieee80211_ccmp_data *key = priv;
|
||||
int i;
|
||||
|
@ -199,6 +200,9 @@ static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
|
|||
if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
|
||||
return -1;
|
||||
|
||||
if (aeskey != NULL && keylen >= CCMP_TK_LEN)
|
||||
memcpy(aeskey, key->key, CCMP_TK_LEN);
|
||||
|
||||
pos = skb_push(skb, CCMP_HDR_LEN);
|
||||
memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
|
||||
pos += hdr_len;
|
||||
|
@ -238,7 +242,7 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
|||
return -1;
|
||||
|
||||
data_len = skb->len - hdr_len;
|
||||
len = ieee80211_ccmp_hdr(skb, hdr_len, priv);
|
||||
len = ieee80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
|
|
|
@ -80,10 +80,9 @@ static void *ieee80211_tkip_init(int key_idx)
|
|||
{
|
||||
struct ieee80211_tkip_data *priv;
|
||||
|
||||
priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
|
||||
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
|
||||
if (priv == NULL)
|
||||
goto fail;
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
|
||||
priv->key_idx = key_idx;
|
||||
|
||||
|
@ -271,34 +270,33 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
|
|||
#endif
|
||||
}
|
||||
|
||||
static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
|
||||
static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
|
||||
u8 * rc4key, int keylen, void *priv)
|
||||
{
|
||||
struct ieee80211_tkip_data *tkey = priv;
|
||||
int len;
|
||||
u8 *rc4key, *pos, *icv;
|
||||
u8 *pos;
|
||||
struct ieee80211_hdr_4addr *hdr;
|
||||
u32 crc;
|
||||
|
||||
hdr = (struct ieee80211_hdr_4addr *)skb->data;
|
||||
|
||||
if (skb_headroom(skb) < 8 || skb->len < hdr_len)
|
||||
return NULL;
|
||||
return -1;
|
||||
|
||||
if (rc4key == NULL || keylen < 16)
|
||||
return -1;
|
||||
|
||||
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;
|
||||
pos = skb_push(skb, 8);
|
||||
memmove(pos, pos + 8, hdr_len);
|
||||
pos += hdr_len;
|
||||
icv = skb_put(skb, 4);
|
||||
|
||||
*pos++ = *rc4key;
|
||||
*pos++ = *(rc4key + 1);
|
||||
|
@ -309,28 +307,28 @@ static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
|
|||
*pos++ = (tkey->tx_iv32 >> 16) & 0xff;
|
||||
*pos++ = (tkey->tx_iv32 >> 24) & 0xff;
|
||||
|
||||
crc = ~crc32_le(~0, pos, len);
|
||||
icv[0] = crc;
|
||||
icv[1] = crc >> 8;
|
||||
icv[2] = crc >> 16;
|
||||
icv[3] = crc >> 24;
|
||||
tkey->tx_iv16++;
|
||||
if (tkey->tx_iv16 == 0) {
|
||||
tkey->tx_phase1_done = 0;
|
||||
tkey->tx_iv32++;
|
||||
}
|
||||
|
||||
return rc4key;
|
||||
return 8;
|
||||
}
|
||||
|
||||
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;
|
||||
u8 rc4key[16], *pos, *icv;
|
||||
u32 crc;
|
||||
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 "
|
||||
printk(KERN_DEBUG ": TKIP countermeasures: dropped "
|
||||
"TX packet to " MAC_FMT "\n",
|
||||
MAC_ARG(hdr->addr1));
|
||||
}
|
||||
|
@ -343,22 +341,23 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
|||
len = skb->len - hdr_len;
|
||||
pos = skb->data + hdr_len;
|
||||
|
||||
rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv);
|
||||
if (!rc4key)
|
||||
if ((ieee80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
|
||||
return -1;
|
||||
|
||||
icv = skb_put(skb, 4);
|
||||
|
||||
crc = ~crc32_le(~0, pos, len);
|
||||
icv[0] = crc;
|
||||
icv[1] = crc >> 8;
|
||||
icv[2] = crc >> 16;
|
||||
icv[3] = crc >> 24;
|
||||
|
||||
crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
|
||||
sg.page = virt_to_page(pos);
|
||||
sg.offset = offset_in_page(pos);
|
||||
sg.length = len + 4;
|
||||
crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
|
||||
|
||||
tkey->tx_iv16++;
|
||||
if (tkey->tx_iv16 == 0) {
|
||||
tkey->tx_phase1_done = 0;
|
||||
tkey->tx_iv32++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -379,7 +378,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
|||
|
||||
if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "TKIP countermeasures: dropped "
|
||||
printk(KERN_DEBUG ": TKIP countermeasures: dropped "
|
||||
"received packet from " MAC_FMT "\n",
|
||||
MAC_ARG(hdr->addr2));
|
||||
}
|
||||
|
@ -695,6 +694,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
|
|||
.name = "TKIP",
|
||||
.init = ieee80211_tkip_init,
|
||||
.deinit = ieee80211_tkip_deinit,
|
||||
.build_iv = ieee80211_tkip_hdr,
|
||||
.encrypt_mpdu = ieee80211_tkip_encrypt,
|
||||
.decrypt_mpdu = ieee80211_tkip_decrypt,
|
||||
.encrypt_msdu = ieee80211_michael_mic_add,
|
||||
|
|
|
@ -76,7 +76,8 @@ static void prism2_wep_deinit(void *priv)
|
|||
}
|
||||
|
||||
/* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */
|
||||
static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, void *priv)
|
||||
static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len,
|
||||
u8 *key, int keylen, void *priv)
|
||||
{
|
||||
struct prism2_wep_data *wep = priv;
|
||||
u32 klen, len;
|
||||
|
@ -131,7 +132,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
|
|||
return -1;
|
||||
|
||||
/* add the IV to the frame */
|
||||
if (prism2_wep_build_iv(skb, hdr_len, priv))
|
||||
if (prism2_wep_build_iv(skb, hdr_len, NULL, 0, priv))
|
||||
return -1;
|
||||
|
||||
/* Copy the IV into the first 3 bytes of the key */
|
||||
|
|
|
@ -58,13 +58,15 @@ int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
|
|||
* this is a B only channel, we don't see it
|
||||
* as valid. */
|
||||
if ((ieee->geo.bg[i].channel == channel) &&
|
||||
!(ieee->geo.bg[i].flags & IEEE80211_CH_INVALID) &&
|
||||
(!(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)
|
||||
if ((ieee->geo.a[i].channel == channel) &&
|
||||
!(ieee->geo.a[i].flags & IEEE80211_CH_INVALID))
|
||||
return IEEE80211_52GHZ_BAND;
|
||||
|
||||
return 0;
|
||||
|
@ -133,6 +135,41 @@ const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee)
|
|||
return &ieee->geo;
|
||||
}
|
||||
|
||||
u8 ieee80211_get_channel_flags(struct ieee80211_device * ieee, u8 channel)
|
||||
{
|
||||
int index = ieee80211_channel_to_index(ieee, channel);
|
||||
|
||||
if (index == -1)
|
||||
return IEEE80211_CH_INVALID;
|
||||
|
||||
if (channel <= IEEE80211_24GHZ_CHANNELS)
|
||||
return ieee->geo.bg[index].flags;
|
||||
|
||||
return ieee->geo.a[index].flags;
|
||||
}
|
||||
|
||||
static const struct ieee80211_channel bad_channel = {
|
||||
.channel = 0,
|
||||
.flags = IEEE80211_CH_INVALID,
|
||||
.max_power = 0,
|
||||
};
|
||||
|
||||
const struct ieee80211_channel *ieee80211_get_channel(struct ieee80211_device
|
||||
*ieee, u8 channel)
|
||||
{
|
||||
int index = ieee80211_channel_to_index(ieee, channel);
|
||||
|
||||
if (index == -1)
|
||||
return &bad_channel;
|
||||
|
||||
if (channel <= IEEE80211_24GHZ_CHANNELS)
|
||||
return &ieee->geo.bg[index];
|
||||
|
||||
return &ieee->geo.a[index];
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ieee80211_get_channel);
|
||||
EXPORT_SYMBOL(ieee80211_get_channel_flags);
|
||||
EXPORT_SYMBOL(ieee80211_is_valid_channel);
|
||||
EXPORT_SYMBOL(ieee80211_freq_to_channel);
|
||||
EXPORT_SYMBOL(ieee80211_channel_to_index);
|
||||
|
|
|
@ -82,10 +82,28 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ieee80211_network_reset(struct ieee80211_network *network)
|
||||
{
|
||||
if (!network)
|
||||
return;
|
||||
|
||||
if (network->ibss_dfs) {
|
||||
kfree(network->ibss_dfs);
|
||||
network->ibss_dfs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ieee->networks)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_NETWORK_COUNT; i++)
|
||||
if (ieee->networks[i].ibss_dfs)
|
||||
kfree(ieee->networks[i].ibss_dfs);
|
||||
|
||||
kfree(ieee->networks);
|
||||
ieee->networks = NULL;
|
||||
}
|
||||
|
|
|
@ -754,7 +754,14 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
|
|||
memset(skb->cb, 0, sizeof(skb->cb));
|
||||
skb->dev = dev;
|
||||
skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
|
||||
netif_rx(skb);
|
||||
if (netif_rx(skb) == NET_RX_DROP) {
|
||||
/* netif_rx always succeeds, but it might drop
|
||||
* the packet. If it drops the packet, we log that
|
||||
* in our stats. */
|
||||
IEEE80211_DEBUG_DROP
|
||||
("RX: netif_rx dropped the packet\n");
|
||||
stats->rx_dropped++;
|
||||
}
|
||||
}
|
||||
|
||||
rx_exit:
|
||||
|
@ -930,6 +937,45 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
|
|||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211_DEBUG
|
||||
#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
|
||||
|
||||
static const char *get_info_element_string(u16 id)
|
||||
{
|
||||
switch (id) {
|
||||
MFIE_STRING(SSID);
|
||||
MFIE_STRING(RATES);
|
||||
MFIE_STRING(FH_SET);
|
||||
MFIE_STRING(DS_SET);
|
||||
MFIE_STRING(CF_SET);
|
||||
MFIE_STRING(TIM);
|
||||
MFIE_STRING(IBSS_SET);
|
||||
MFIE_STRING(COUNTRY);
|
||||
MFIE_STRING(HOP_PARAMS);
|
||||
MFIE_STRING(HOP_TABLE);
|
||||
MFIE_STRING(REQUEST);
|
||||
MFIE_STRING(CHALLENGE);
|
||||
MFIE_STRING(POWER_CONSTRAINT);
|
||||
MFIE_STRING(POWER_CAPABILITY);
|
||||
MFIE_STRING(TPC_REQUEST);
|
||||
MFIE_STRING(TPC_REPORT);
|
||||
MFIE_STRING(SUPP_CHANNELS);
|
||||
MFIE_STRING(CSA);
|
||||
MFIE_STRING(MEASURE_REQUEST);
|
||||
MFIE_STRING(MEASURE_REPORT);
|
||||
MFIE_STRING(QUIET);
|
||||
MFIE_STRING(IBSS_DFS);
|
||||
MFIE_STRING(ERP_INFO);
|
||||
MFIE_STRING(RSN);
|
||||
MFIE_STRING(RATES_EX);
|
||||
MFIE_STRING(GENERIC);
|
||||
MFIE_STRING(QOS_PARAMETER);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ieee80211_parse_info_param(struct ieee80211_info_element
|
||||
*info_element, u16 length,
|
||||
struct ieee80211_network *network)
|
||||
|
@ -1040,7 +1086,9 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
|
|||
break;
|
||||
|
||||
case MFIE_TYPE_TIM:
|
||||
IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n");
|
||||
network->tim.tim_count = info_element->data[0];
|
||||
network->tim.tim_period = info_element->data[1];
|
||||
IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n");
|
||||
break;
|
||||
|
||||
case MFIE_TYPE_ERP_INFO:
|
||||
|
@ -1091,10 +1139,49 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
|
|||
printk(KERN_ERR
|
||||
"QoS Error need to parse QOS_PARAMETER IE\n");
|
||||
break;
|
||||
/* 802.11h */
|
||||
case MFIE_TYPE_POWER_CONSTRAINT:
|
||||
network->power_constraint = info_element->data[0];
|
||||
network->flags |= NETWORK_HAS_POWER_CONSTRAINT;
|
||||
break;
|
||||
|
||||
case MFIE_TYPE_CSA:
|
||||
network->power_constraint = info_element->data[0];
|
||||
network->flags |= NETWORK_HAS_CSA;
|
||||
break;
|
||||
|
||||
case MFIE_TYPE_QUIET:
|
||||
network->quiet.count = info_element->data[0];
|
||||
network->quiet.period = info_element->data[1];
|
||||
network->quiet.duration = info_element->data[2];
|
||||
network->quiet.offset = info_element->data[3];
|
||||
network->flags |= NETWORK_HAS_QUIET;
|
||||
break;
|
||||
|
||||
case MFIE_TYPE_IBSS_DFS:
|
||||
if (network->ibss_dfs)
|
||||
break;
|
||||
network->ibss_dfs =
|
||||
kmalloc(info_element->len, GFP_ATOMIC);
|
||||
if (!network->ibss_dfs)
|
||||
return 1;
|
||||
memcpy(network->ibss_dfs, info_element->data,
|
||||
info_element->len);
|
||||
network->flags |= NETWORK_HAS_IBSS_DFS;
|
||||
break;
|
||||
|
||||
case MFIE_TYPE_TPC_REPORT:
|
||||
network->tpc_report.transmit_power =
|
||||
info_element->data[0];
|
||||
network->tpc_report.link_margin = info_element->data[1];
|
||||
network->flags |= NETWORK_HAS_TPC_REPORT;
|
||||
break;
|
||||
|
||||
default:
|
||||
IEEE80211_DEBUG_MGMT("unsupported IE %d\n",
|
||||
info_element->id);
|
||||
IEEE80211_DEBUG_MGMT
|
||||
("Unsupported info element: %s (%d)\n",
|
||||
get_info_element_string(info_element->id),
|
||||
info_element->id);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1110,7 +1197,9 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
|
|||
static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
|
||||
*frame, struct ieee80211_rx_stats *stats)
|
||||
{
|
||||
struct ieee80211_network network_resp;
|
||||
struct ieee80211_network network_resp = {
|
||||
.ibss_dfs = NULL,
|
||||
};
|
||||
struct ieee80211_network *network = &network_resp;
|
||||
struct net_device *dev = ieee->dev;
|
||||
|
||||
|
@ -1253,6 +1342,9 @@ static void update_network(struct ieee80211_network *dst,
|
|||
int qos_active;
|
||||
u8 old_param;
|
||||
|
||||
ieee80211_network_reset(dst);
|
||||
dst->ibss_dfs = src->ibss_dfs;
|
||||
|
||||
memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
|
||||
dst->capability = src->capability;
|
||||
memcpy(dst->rates, src->rates, src->rates_len);
|
||||
|
@ -1269,6 +1361,7 @@ static void update_network(struct ieee80211_network *dst,
|
|||
dst->listen_interval = src->listen_interval;
|
||||
dst->atim_window = src->atim_window;
|
||||
dst->erp_value = src->erp_value;
|
||||
dst->tim = src->tim;
|
||||
|
||||
memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
|
||||
dst->wpa_ie_len = src->wpa_ie_len;
|
||||
|
@ -1313,7 +1406,9 @@ static void ieee80211_process_probe_response(struct ieee80211_device
|
|||
*stats)
|
||||
{
|
||||
struct net_device *dev = ieee->dev;
|
||||
struct ieee80211_network network;
|
||||
struct ieee80211_network network = {
|
||||
.ibss_dfs = NULL,
|
||||
};
|
||||
struct ieee80211_network *target;
|
||||
struct ieee80211_network *oldest = NULL;
|
||||
#ifdef CONFIG_IEEE80211_DEBUG
|
||||
|
@ -1388,6 +1483,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
|
|||
escape_essid(target->ssid,
|
||||
target->ssid_len),
|
||||
MAC_ARG(target->bssid));
|
||||
ieee80211_network_reset(target);
|
||||
} else {
|
||||
/* Otherwise just pull from the free list */
|
||||
target = list_entry(ieee->network_free_list.next,
|
||||
|
@ -1406,6 +1502,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
|
|||
"BEACON" : "PROBE RESPONSE");
|
||||
#endif
|
||||
memcpy(target, &network, sizeof(*target));
|
||||
network.ibss_dfs = NULL;
|
||||
list_add_tail(&target->list, &ieee->network_list);
|
||||
} else {
|
||||
IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
|
||||
|
@ -1417,6 +1514,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
|
|||
frame_ctl)) ?
|
||||
"BEACON" : "PROBE RESPONSE");
|
||||
update_network(target, &network);
|
||||
network.ibss_dfs = NULL;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
|
@ -1501,10 +1599,19 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
|
|||
header);
|
||||
break;
|
||||
|
||||
case IEEE80211_STYPE_ACTION:
|
||||
IEEE80211_DEBUG_MGMT("ACTION\n");
|
||||
if (ieee->handle_action)
|
||||
ieee->handle_action(ieee->dev,
|
||||
(struct ieee80211_action *)
|
||||
header, stats);
|
||||
break;
|
||||
|
||||
case IEEE80211_STYPE_DEAUTH:
|
||||
printk("DEAUTH from AP\n");
|
||||
IEEE80211_DEBUG_MGMT("DEAUTH\n");
|
||||
if (ieee->handle_deauth != NULL)
|
||||
ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *)
|
||||
ieee->handle_deauth(ieee->dev,
|
||||
(struct ieee80211_deauth *)
|
||||
header);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -56,7 +56,18 @@ Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
|
|||
`--------------------------------------------------| |------'
|
||||
Total: 28 non-data bytes `----.----'
|
||||
|
|
||||
.- 'Frame data' expands to <---------------------------'
|
||||
.- 'Frame data' expands, if WEP enabled, to <----------'
|
||||
|
|
||||
V
|
||||
,-----------------------.
|
||||
Bytes | 4 | 0-2296 | 4 |
|
||||
|-----|-----------|-----|
|
||||
Desc. | IV | Encrypted | ICV |
|
||||
| | Packet | |
|
||||
`-----| |-----'
|
||||
`-----.-----'
|
||||
|
|
||||
.- 'Encrypted Packet' expands to
|
||||
|
|
||||
V
|
||||
,---------------------------------------------------.
|
||||
|
@ -65,18 +76,7 @@ Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
|
|||
Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
|
||||
| DSAP | SSAP | | | | Packet |
|
||||
| 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
|
||||
`-----------------------------------------| |
|
||||
Total: 8 non-data bytes `----.----'
|
||||
|
|
||||
.- 'IP Packet' expands, if WEP enabled, to <--'
|
||||
|
|
||||
V
|
||||
,-----------------------.
|
||||
Bytes | 4 | 0-2296 | 4 |
|
||||
|-----|-----------|-----|
|
||||
Desc. | IV | Encrypted | ICV |
|
||||
| | IP Packet | |
|
||||
`-----------------------'
|
||||
`----------------------------------------------------
|
||||
Total: 8 non-data bytes
|
||||
|
||||
802.3 Ethernet Data Frame
|
||||
|
@ -470,7 +470,9 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
atomic_inc(&crypt->refcnt);
|
||||
if (crypt->ops->build_iv)
|
||||
crypt->ops->build_iv(skb_frag, hdr_len,
|
||||
crypt->priv);
|
||||
ieee->sec.keys[ieee->sec.active_key],
|
||||
ieee->sec.key_sizes[ieee->sec.active_key],
|
||||
crypt->priv);
|
||||
atomic_dec(&crypt->refcnt);
|
||||
}
|
||||
|
||||
|
|
|
@ -149,9 +149,7 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
|
|||
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
|
||||
|
@ -179,6 +177,13 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
|
|||
iwe.u.qual.noise = network->stats.noise;
|
||||
}
|
||||
|
||||
if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) {
|
||||
iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
|
||||
iwe.u.qual.level = 0;
|
||||
} else {
|
||||
iwe.u.qual.level = network->stats.signal;
|
||||
}
|
||||
|
||||
start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
|
||||
|
||||
iwe.cmd = IWEVCUSTOM;
|
||||
|
@ -229,6 +234,28 @@ static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
|
|||
if (iwe.u.data.length)
|
||||
start = iwe_stream_add_point(start, stop, &iwe, custom);
|
||||
|
||||
/* Add spectrum management information */
|
||||
iwe.cmd = -1;
|
||||
p = custom;
|
||||
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
|
||||
|
||||
if (ieee80211_get_channel_flags(ieee, network->channel) &
|
||||
IEEE80211_CH_INVALID) {
|
||||
iwe.cmd = IWEVCUSTOM;
|
||||
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
|
||||
}
|
||||
|
||||
if (ieee80211_get_channel_flags(ieee, network->channel) &
|
||||
IEEE80211_CH_RADAR_DETECT) {
|
||||
iwe.cmd = IWEVCUSTOM;
|
||||
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
|
||||
}
|
||||
|
||||
if (iwe.cmd == IWEVCUSTOM) {
|
||||
iwe.u.data.length = p - custom;
|
||||
start = iwe_stream_add_point(start, stop, &iwe, custom);
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue