Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 10247
b: refs/heads/master
c: 1264fc0
h: refs/heads/master
i:
  10245: 7868cd2
  10243: a472341
  10239: 12a7403
v: v3
  • Loading branch information
James Ketrenos authored and Jeff Garzik committed Sep 22, 2005
1 parent 5938262 commit c7e755f
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 76 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3f552bbf8614d2d26f488ca0d3e188bdec484bf4
refs/heads/master: 1264fc0498e1e20f97b1ab690e523e7a7fc50eab
2 changes: 2 additions & 0 deletions trunk/include/net/ieee80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,9 @@ struct ieee80211_device {

/* If the host performs {en,de}cryption, then set to 1 */
int host_encrypt;
int host_encrypt_msdu;
int host_decrypt;
int host_open_frag;
int ieee802_1x; /* is IEEE 802.1X used */

/* WPA data */
Expand Down
3 changes: 2 additions & 1 deletion trunk/include/net/ieee80211_crypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ struct ieee80211_crypto_ops {
* extra_postfix_len; encrypt need not use all this space, but
* the result must start at the beginning of the buffer and correct
* length must be returned */
int extra_prefix_len, extra_postfix_len;
int extra_mpdu_prefix_len, extra_mpdu_postfix_len;
int extra_msdu_prefix_len, extra_msdu_postfix_len;

struct module *owner;
};
Expand Down
4 changes: 2 additions & 2 deletions trunk/net/ieee80211/ieee80211_crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@ static struct ieee80211_crypto_ops ieee80211_crypt_null = {
.decrypt_msdu = NULL,
.set_key = NULL,
.get_key = NULL,
.extra_prefix_len = 0,
.extra_postfix_len = 0,
.extra_mpdu_prefix_len = 0,
.extra_mpdu_postfix_len = 0,
.owner = THIS_MODULE,
};

Expand Down
4 changes: 2 additions & 2 deletions trunk/net/ieee80211/ieee80211_crypt_ccmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,8 @@ static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
.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,
.extra_mpdu_prefix_len = CCMP_HDR_LEN,
.extra_mpdu_postfix_len = CCMP_MIC_LEN,
.owner = THIS_MODULE,
};

Expand Down
5 changes: 3 additions & 2 deletions trunk/net/ieee80211/ieee80211_crypt_tkip.c
Original file line number Diff line number Diff line change
Expand Up @@ -690,8 +690,9 @@ static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
.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 */
.extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
.extra_mpdu_postfix_len = 4, /* ICV */
.extra_msdu_postfix_len = 8, /* MIC */
.owner = THIS_MODULE,
};

Expand Down
4 changes: 2 additions & 2 deletions trunk/net/ieee80211/ieee80211_crypt_wep.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
.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 */
.extra_mpdu_prefix_len = 4, /* IV */
.extra_mpdu_postfix_len = 4, /* ICV */
.owner = THIS_MODULE,
};

Expand Down
7 changes: 6 additions & 1 deletion trunk/net/ieee80211/ieee80211_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
/* Default to enabling full open WEP with host based encrypt/decrypt */
ieee->host_encrypt = 1;
ieee->host_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);
Expand All @@ -147,7 +153,6 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
ieee->tkip_countermeasures = 0;
ieee->drop_unencrypted = 0;
ieee->privacy_invoked = 0;
ieee->ieee802_1x = 1;

return dev;

Expand Down
148 changes: 83 additions & 65 deletions trunk/net/ieee80211/ieee80211_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -159,15 +159,9 @@ static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,

/* 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->encrypt_mpdu)
res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);

atomic_dec(&crypt->refcnt);
Expand Down Expand Up @@ -222,7 +216,7 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
return txb;
}

/* Incoming skb is converted to a txb which consist of
/* 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)
{
Expand All @@ -233,16 +227,16 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
rts_required;
unsigned long flags;
struct net_device_stats *stats = &ieee->stats;
int ether_type, encrypt, host_encrypt;
int ether_type, encrypt, host_encrypt, host_encrypt_msdu;
int bytes, fc, hdr_len;
struct sk_buff *skb_frag;
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 snapped = 0;

spin_lock_irqsave(&ieee->lock, flags);

Expand All @@ -266,6 +260,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
ieee->sec.encrypt;
host_encrypt = ieee->host_encrypt && encrypt;
host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt;

if (!encrypt && ieee->ieee802_1x &&
ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
Expand All @@ -291,57 +286,88 @@ 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 */
/* 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 */
/* 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);
if (unlikely(!skb_new))
goto failed;
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);
}

/* 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 (host_encrypt || ieee->host_open_frag) {
/* Determine fragmentation size based on destination (multicast
* and broadcast are not fragmented) */
if (is_multicast_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_prefix_len +
crypt->ops->extra_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;
/* 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,
Expand All @@ -353,7 +379,11 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
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;

if (rts_required) {
skb_frag = txb->fragments[0];
Expand Down Expand Up @@ -385,7 +415,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
skb_frag = txb->fragments[i];

if (host_encrypt)
skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
skb_reserve(skb_frag,
crypt->ops->extra_mpdu_prefix_len);

frag_hdr =
(struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
Expand All @@ -402,11 +433,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);
}

Expand All @@ -420,19 +450,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
if (host_encrypt)
ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);

/* ipw2200/2915 Hardware encryption doesn't support TKIP MIC */
if (!ieee->host_encrypt && encrypt &&
(ieee->sec.level == SEC_LEVEL_2) &&
crypt && crypt->ops && crypt->ops->encrypt_msdu) {
int res = 0;
res = crypt->ops->encrypt_msdu(skb_frag, hdr_len,
crypt->priv);
if (res < 0) {
IEEE80211_ERROR("TKIP MIC encryption failed\n");
goto failed;
}
}

if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
skb_put(skb_frag, 4);
Expand All @@ -444,7 +461,8 @@ 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);
if (ret == 0) {
stats->tx_packets++;
stats->tx_bytes += txb->payload_size;
return 0;
Expand Down

0 comments on commit c7e755f

Please sign in to comment.