Skip to content

Commit

Permalink
wireless: move some utility functions from mac80211 to cfg80211
Browse files Browse the repository at this point in the history
The patch moves some utility functions from mac80211 to cfg80211.
Because these functions are doing generic 802.11 operations so they
are not mac80211 specific. The moving allows some fullmac drivers
to be also benefit from these utility functions.

Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Zhu Yi authored and John W. Linville committed May 22, 2009
1 parent a971be2 commit e31a16d
Show file tree
Hide file tree
Showing 14 changed files with 375 additions and 230 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ar9170/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1555,7 +1555,7 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,

switch (key->alg) {
case ALG_WEP:
if (key->keylen == LEN_WEP40)
if (key->keylen == WLAN_KEY_LEN_WEP40)
ktype = AR9170_ENC_ALG_WEP64;
else
ktype = AR9170_ENC_ALG_WEP128;
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/ath/ath5k/pcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1038,9 +1038,9 @@ int ath5k_keycache_type(const struct ieee80211_key_conf *key)
case ALG_CCMP:
return AR5K_KEYTABLE_TYPE_CCM;
case ALG_WEP:
if (key->keylen == LEN_WEP40)
if (key->keylen == WLAN_KEY_LEN_WEP40)
return AR5K_KEYTABLE_TYPE_40;
else if (key->keylen == LEN_WEP104)
else if (key->keylen == WLAN_KEY_LEN_WEP104)
return AR5K_KEYTABLE_TYPE_104;
return -EINVAL;
default:
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/wireless/ath/ath9k/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -2472,14 +2472,14 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
}
break;
case ATH9K_CIPHER_WEP:
if (k->kv_len < LEN_WEP40) {
if (k->kv_len < WLAN_KEY_LEN_WEP40) {
DPRINTF(ah->ah_sc, ATH_DBG_ANY,
"WEP key length %u too small\n", k->kv_len);
return false;
}
if (k->kv_len <= LEN_WEP40)
if (k->kv_len <= WLAN_KEY_LEN_WEP40)
keyType = AR_KEYTABLE_TYPE_40;
else if (k->kv_len <= LEN_WEP104)
else if (k->kv_len <= WLAN_KEY_LEN_WEP104)
keyType = AR_KEYTABLE_TYPE_104;
else
keyType = AR_KEYTABLE_TYPE_128;
Expand All @@ -2498,7 +2498,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
key2 = get_unaligned_le32(k->kv_val + 6);
key3 = get_unaligned_le16(k->kv_val + 10);
key4 = get_unaligned_le32(k->kv_val + 12);
if (k->kv_len <= LEN_WEP104)
if (k->kv_len <= WLAN_KEY_LEN_WEP104)
key4 &= 0xff;

/*
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/b43/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3637,7 +3637,7 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
err = -EINVAL;
switch (key->alg) {
case ALG_WEP:
if (key->keylen == LEN_WEP40)
if (key->keylen == WLAN_KEY_LEN_WEP40)
algorithm = B43_SEC_ALGO_WEP40;
else
algorithm = B43_SEC_ALGO_WEP104;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2x00crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
{
switch (key->alg) {
case ALG_WEP:
if (key->keylen == LEN_WEP40)
if (key->keylen == WLAN_KEY_LEN_WEP40)
return CIPHER_WEP64;
else
return CIPHER_WEP128;
Expand Down
9 changes: 9 additions & 0 deletions include/linux/ieee80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ struct ieee80211s_hdr {
/* Mesh flags */
#define MESH_FLAGS_AE_A4 0x1
#define MESH_FLAGS_AE_A5_A6 0x2
#define MESH_FLAGS_AE 0x3
#define MESH_FLAGS_PS_DEEP 0x4

/**
Expand Down Expand Up @@ -1085,6 +1086,14 @@ enum ieee80211_spectrum_mgmt_actioncode {
WLAN_ACTION_SPCT_CHL_SWITCH = 4,
};

/* Security key length */
enum ieee80211_key_len {
WLAN_KEY_LEN_WEP40 = 5,
WLAN_KEY_LEN_WEP104 = 13,
WLAN_KEY_LEN_CCMP = 16,
WLAN_KEY_LEN_TKIP = 32,
};

/*
* IEEE 802.11-2007 7.3.2.9 Country information element
*
Expand Down
47 changes: 47 additions & 0 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1244,6 +1244,53 @@ extern int ieee80211_radiotap_iterator_init(
extern int ieee80211_radiotap_iterator_next(
struct ieee80211_radiotap_iterator *iterator);

extern const unsigned char rfc1042_header[6];
extern const unsigned char bridge_tunnel_header[6];

/**
* ieee80211_get_hdrlen_from_skb - get header length from data
*
* Given an skb with a raw 802.11 header at the data pointer this function
* returns the 802.11 header length in bytes (not including encryption
* headers). If the data in the sk_buff is too short to contain a valid 802.11
* header the function returns 0.
*
* @skb: the frame
*/
unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);

/**
* ieee80211_hdrlen - get header length in bytes from frame control
* @fc: frame control field in little-endian format
*/
unsigned int ieee80211_hdrlen(__le16 fc);

/**
* ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
* @skb: the 802.11 data frame
* @addr: the device MAC address
* @iftype: the virtual interface type
*/
int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
enum nl80211_iftype iftype);

/**
* ieee80211_data_from_8023 - convert an 802.3 frame to 802.11
* @skb: the 802.3 frame
* @addr: the device MAC address
* @iftype: the virtual interface type
* @bssid: the network bssid (used only for iftype STATION and ADHOC)
* @qos: build 802.11 QoS data frame
*/
int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr,
enum nl80211_iftype iftype, u8 *bssid, bool qos);

/**
* cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
* @skb: the data frame
*/
unsigned int cfg80211_classify8021d(struct sk_buff *skb);

/*
* Regulatory helper functions for wiphys
*/
Expand Down
28 changes: 0 additions & 28 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -671,16 +671,6 @@ enum ieee80211_key_alg {
ALG_AES_CMAC,
};

/**
* enum ieee80211_key_len - key length
* @LEN_WEP40: WEP 5-byte long key
* @LEN_WEP104: WEP 13-byte long key
*/
enum ieee80211_key_len {
LEN_WEP40 = 5,
LEN_WEP104 = 13,
};

/**
* enum ieee80211_key_flags - key flags
*
Expand Down Expand Up @@ -1811,24 +1801,6 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
struct sk_buff *
ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif);

/**
* ieee80211_get_hdrlen_from_skb - get header length from data
*
* Given an skb with a raw 802.11 header at the data pointer this function
* returns the 802.11 header length in bytes (not including encryption
* headers). If the data in the sk_buff is too short to contain a valid 802.11
* header the function returns 0.
*
* @skb: the frame
*/
unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);

/**
* ieee80211_hdrlen - get header length in bytes from frame control
* @fc: frame control field in little-endian format
*/
unsigned int ieee80211_hdrlen(__le16 fc);

/**
* ieee80211_get_tkip_key - get a TKIP rc4 for skb
*
Expand Down
2 changes: 0 additions & 2 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -1085,8 +1085,6 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw)

/* utility functions/constants */
extern void *mac80211_wiphy_privid; /* for wiphy privid */
extern const unsigned char rfc1042_header[6];
extern const unsigned char bridge_tunnel_header[6];
u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
enum nl80211_iftype type);
int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
Expand Down
4 changes: 0 additions & 4 deletions net/mac80211/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,8 @@ struct mesh_rmc {
#define PLINK_CATEGORY 30
#define MESH_PATH_SEL_CATEGORY 32

/* Mesh Header Flags */
#define IEEE80211S_FLAGS_AE 0x3

/* Public interfaces */
/* Various */
int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
struct ieee80211_sub_if_data *sdata);
int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
Expand Down
89 changes: 4 additions & 85 deletions net/mac80211/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1247,93 +1247,12 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
}

static int
ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
__ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
{
struct net_device *dev = rx->dev;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
u16 hdrlen, ethertype;
u8 *payload;
u8 dst[ETH_ALEN];
u8 src[ETH_ALEN] __aligned(2);
struct sk_buff *skb = rx->skb;
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);

if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
return -1;

hdrlen = ieee80211_hdrlen(hdr->frame_control);

/* convert IEEE 802.11 header + possible LLC headers into Ethernet
* header
* IEEE 802.11 address fields:
* ToDS FromDS Addr1 Addr2 Addr3 Addr4
* 0 0 DA SA BSSID n/a
* 0 1 DA BSSID SA n/a
* 1 0 BSSID SA DA n/a
* 1 1 RA TA DA SA
*/
memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN);

switch (hdr->frame_control &
cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
case cpu_to_le16(IEEE80211_FCTL_TODS):
if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
return -1;
break;
case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT))
return -1;
if (ieee80211_vif_is_mesh(&sdata->vif)) {
struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *)
(skb->data + hdrlen);
hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
memcpy(dst, meshdr->eaddr1, ETH_ALEN);
memcpy(src, meshdr->eaddr2, ETH_ALEN);
}
}
break;
case cpu_to_le16(IEEE80211_FCTL_FROMDS):
if (sdata->vif.type != NL80211_IFTYPE_STATION ||
(is_multicast_ether_addr(dst) &&
!compare_ether_addr(src, dev->dev_addr)))
return -1;
break;
case cpu_to_le16(0):
if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
return -1;
break;
}

if (unlikely(skb->len - hdrlen < 8))
return -1;

payload = skb->data + hdrlen;
ethertype = (payload[6] << 8) | payload[7];

if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
compare_ether_addr(payload, bridge_tunnel_header) == 0)) {
/* remove RFC1042 or Bridge-Tunnel encapsulation and
* replace EtherType */
skb_pull(skb, hdrlen + 6);
memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
} else {
struct ethhdr *ehdr;
__be16 len;

skb_pull(skb, hdrlen);
len = htons(skb->len);
ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
memcpy(ehdr->h_dest, dst, ETH_ALEN);
memcpy(ehdr->h_source, src, ETH_ALEN);
ehdr->h_proto = len;
}
return 0;
return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type);
}

/*
Expand Down Expand Up @@ -1472,7 +1391,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
if (!(rx->flags & IEEE80211_RX_AMSDU))
return RX_CONTINUE;

err = ieee80211_data_to_8023(rx);
err = __ieee80211_data_to_8023(rx);
if (unlikely(err))
return RX_DROP_UNUSABLE;

Expand Down Expand Up @@ -1658,7 +1577,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
return RX_DROP_MONITOR;

err = ieee80211_data_to_8023(rx);
err = __ieee80211_data_to_8023(rx);
if (unlikely(err))
return RX_DROP_UNUSABLE;

Expand Down
Loading

0 comments on commit e31a16d

Please sign in to comment.