Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6

This commit is contained in:
Jeff Garzik 2006-01-28 16:07:32 -05:00
commit 4f975b3243
11 changed files with 426 additions and 67 deletions

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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,

View File

@ -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 */

View File

@ -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);

View File

@ -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;
}

View File

@ -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:

View File

@ -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);
}

View File

@ -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;
}