mac80211: restructuring data Rx handlers
This patch restructures the Rx handlers chain by incorporating previously handlers ieee80211_rx_h_802_1x_pae and ieee80211_rx_h_drop_unencrypted into ieee80211_rx_h_data, already in 802.3 form. this scheme follows more precisely after the IEEE802.11 data plane archituecture, and will prevent code duplication to IEEE8021.11n A-MSDU handler. added function: - ieee80211_data_to_8023: transfering 802.11 data frames to 802.3 frame - ieee80211_deliver_skb: delivering the 802.3 frames to upper stack eliminated handlers: - ieee80211_rx_h_drop_unencrypted: now function ieee80211_drop_unencrypted - ieee80211_rx_h_802_1x_pae: now function ieee80211_802_1x_pae changed handlers: - ieee80211_rx_h_data: now contains calls to four above function Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ece8edddf0
commit
76ee65bfaa
|
@ -792,7 +792,7 @@ extern void *mac80211_wiphy_privid; /* for wiphy privid */
|
||||||
extern const unsigned char rfc1042_header[6];
|
extern const unsigned char rfc1042_header[6];
|
||||||
extern const unsigned char bridge_tunnel_header[6];
|
extern const unsigned char bridge_tunnel_header[6];
|
||||||
u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len);
|
u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len);
|
||||||
int ieee80211_is_eapol(const struct sk_buff *skb);
|
int ieee80211_is_eapol(const struct sk_buff *skb, int hdrlen);
|
||||||
int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
|
int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
|
||||||
int rate, int erp, int short_preamble);
|
int rate, int erp, int short_preamble);
|
||||||
void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx,
|
void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx,
|
||||||
|
|
|
@ -962,68 +962,64 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
|
||||||
return TXRX_CONTINUE;
|
return TXRX_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ieee80211_txrx_result
|
static int
|
||||||
ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx)
|
ieee80211_drop_802_1x_pae(struct ieee80211_txrx_data *rx, int hdrlen)
|
||||||
{
|
{
|
||||||
if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) &&
|
if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb, hdrlen) &&
|
||||||
rx->sdata->type != IEEE80211_IF_TYPE_STA &&
|
rx->sdata->type != IEEE80211_IF_TYPE_STA &&
|
||||||
(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
|
(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
|
||||||
return TXRX_CONTINUE;
|
return 0;
|
||||||
|
|
||||||
if (unlikely(rx->sdata->ieee802_1x &&
|
if (unlikely(rx->sdata->ieee802_1x &&
|
||||||
(rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
|
(rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
|
||||||
(rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
|
(rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
|
||||||
(!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) &&
|
(!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) &&
|
||||||
!ieee80211_is_eapol(rx->skb))) {
|
!ieee80211_is_eapol(rx->skb, hdrlen))) {
|
||||||
#ifdef CONFIG_MAC80211_DEBUG
|
#ifdef CONFIG_MAC80211_DEBUG
|
||||||
struct ieee80211_hdr *hdr =
|
printk(KERN_DEBUG "%s: dropped frame "
|
||||||
(struct ieee80211_hdr *) rx->skb->data;
|
"(unauthorized port)\n", rx->dev->name);
|
||||||
DECLARE_MAC_BUF(mac);
|
|
||||||
printk(KERN_DEBUG "%s: dropped frame from %s"
|
|
||||||
" (unauthorized port)\n", rx->dev->name,
|
|
||||||
print_mac(mac, hdr->addr2));
|
|
||||||
#endif /* CONFIG_MAC80211_DEBUG */
|
#endif /* CONFIG_MAC80211_DEBUG */
|
||||||
return TXRX_DROP;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TXRX_CONTINUE;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ieee80211_txrx_result
|
static int
|
||||||
ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx)
|
ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx, int hdrlen)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Pass through unencrypted frames if the hardware has
|
* Pass through unencrypted frames if the hardware has
|
||||||
* decrypted them already.
|
* decrypted them already.
|
||||||
*/
|
*/
|
||||||
if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED)
|
if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED)
|
||||||
return TXRX_CONTINUE;
|
return 0;
|
||||||
|
|
||||||
/* Drop unencrypted frames if key is set. */
|
/* Drop unencrypted frames if key is set. */
|
||||||
if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) &&
|
if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) &&
|
||||||
(rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
|
(rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
|
||||||
(rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
|
(rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
|
||||||
(rx->key || rx->sdata->drop_unencrypted) &&
|
(rx->key || rx->sdata->drop_unencrypted) &&
|
||||||
(rx->sdata->eapol == 0 || !ieee80211_is_eapol(rx->skb)))) {
|
(rx->sdata->eapol == 0 ||
|
||||||
|
!ieee80211_is_eapol(rx->skb, hdrlen)))) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
printk(KERN_DEBUG "%s: RX non-WEP frame, but expected "
|
printk(KERN_DEBUG "%s: RX non-WEP frame, but expected "
|
||||||
"encryption\n", rx->dev->name);
|
"encryption\n", rx->dev->name);
|
||||||
return TXRX_DROP;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
return TXRX_CONTINUE;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ieee80211_txrx_result
|
static int
|
||||||
ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
|
||||||
{
|
{
|
||||||
struct net_device *dev = rx->dev;
|
struct net_device *dev = rx->dev;
|
||||||
struct ieee80211_local *local = rx->local;
|
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
|
||||||
u16 fc, hdrlen, ethertype;
|
u16 fc, hdrlen, ethertype;
|
||||||
u8 *payload;
|
u8 *payload;
|
||||||
u8 dst[ETH_ALEN];
|
u8 dst[ETH_ALEN];
|
||||||
u8 src[ETH_ALEN];
|
u8 src[ETH_ALEN];
|
||||||
struct sk_buff *skb = rx->skb, *skb2;
|
struct sk_buff *skb = rx->skb;
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
DECLARE_MAC_BUF(mac);
|
DECLARE_MAC_BUF(mac);
|
||||||
DECLARE_MAC_BUF(mac2);
|
DECLARE_MAC_BUF(mac2);
|
||||||
|
@ -1031,11 +1027,9 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
||||||
DECLARE_MAC_BUF(mac4);
|
DECLARE_MAC_BUF(mac4);
|
||||||
|
|
||||||
fc = rx->fc;
|
fc = rx->fc;
|
||||||
if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
|
|
||||||
return TXRX_CONTINUE;
|
|
||||||
|
|
||||||
if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
|
if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
|
||||||
return TXRX_DROP;
|
return -1;
|
||||||
|
|
||||||
hdrlen = ieee80211_get_hdrlen(fc);
|
hdrlen = ieee80211_get_hdrlen(fc);
|
||||||
|
|
||||||
|
@ -1064,7 +1058,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
||||||
print_mac(mac, hdr->addr1),
|
print_mac(mac, hdr->addr1),
|
||||||
print_mac(mac2, hdr->addr2),
|
print_mac(mac2, hdr->addr2),
|
||||||
print_mac(mac3, hdr->addr3));
|
print_mac(mac3, hdr->addr3));
|
||||||
return TXRX_DROP;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
|
case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
|
||||||
|
@ -1081,7 +1075,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
||||||
print_mac(mac2, hdr->addr2),
|
print_mac(mac2, hdr->addr2),
|
||||||
print_mac(mac3, hdr->addr3),
|
print_mac(mac3, hdr->addr3),
|
||||||
print_mac(mac4, hdr->addr4));
|
print_mac(mac4, hdr->addr4));
|
||||||
return TXRX_DROP;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IEEE80211_FCTL_FROMDS:
|
case IEEE80211_FCTL_FROMDS:
|
||||||
|
@ -1092,7 +1086,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
||||||
if (sdata->type != IEEE80211_IF_TYPE_STA ||
|
if (sdata->type != IEEE80211_IF_TYPE_STA ||
|
||||||
(is_multicast_ether_addr(dst) &&
|
(is_multicast_ether_addr(dst) &&
|
||||||
!compare_ether_addr(src, dev->dev_addr)))
|
!compare_ether_addr(src, dev->dev_addr)))
|
||||||
return TXRX_DROP;
|
return -1;
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
/* DA SA BSSID */
|
/* DA SA BSSID */
|
||||||
|
@ -1108,21 +1102,20 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
||||||
print_mac(mac2, hdr->addr2),
|
print_mac(mac2, hdr->addr2),
|
||||||
print_mac(mac3, hdr->addr3));
|
print_mac(mac3, hdr->addr3));
|
||||||
}
|
}
|
||||||
return TXRX_DROP;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
payload = skb->data + hdrlen;
|
|
||||||
|
|
||||||
if (unlikely(skb->len - hdrlen < 8)) {
|
if (unlikely(skb->len - hdrlen < 8)) {
|
||||||
if (net_ratelimit()) {
|
if (net_ratelimit()) {
|
||||||
printk(KERN_DEBUG "%s: RX too short data frame "
|
printk(KERN_DEBUG "%s: RX too short data frame "
|
||||||
"payload\n", dev->name);
|
"payload\n", dev->name);
|
||||||
}
|
}
|
||||||
return TXRX_DROP;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
payload = skb->data + hdrlen;
|
||||||
ethertype = (payload[6] << 8) | payload[7];
|
ethertype = (payload[6] << 8) | payload[7];
|
||||||
|
|
||||||
if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
|
if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
|
||||||
|
@ -1143,12 +1136,19 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
||||||
memcpy(ehdr->h_source, src, ETH_ALEN);
|
memcpy(ehdr->h_source, src, ETH_ALEN);
|
||||||
ehdr->h_proto = len;
|
ehdr->h_proto = len;
|
||||||
}
|
}
|
||||||
skb->dev = dev;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
skb2 = NULL;
|
static void
|
||||||
|
ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
|
||||||
|
{
|
||||||
|
struct net_device *dev = rx->dev;
|
||||||
|
struct ieee80211_local *local = rx->local;
|
||||||
|
struct sk_buff *skb, *xmit_skb;
|
||||||
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
|
||||||
dev->stats.rx_packets++;
|
skb = rx->skb;
|
||||||
dev->stats.rx_bytes += skb->len;
|
xmit_skb = NULL;
|
||||||
|
|
||||||
if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
|
if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
|
||||||
|| sdata->type == IEEE80211_IF_TYPE_VLAN) &&
|
|| sdata->type == IEEE80211_IF_TYPE_VLAN) &&
|
||||||
|
@ -1156,8 +1156,8 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
||||||
if (is_multicast_ether_addr(skb->data)) {
|
if (is_multicast_ether_addr(skb->data)) {
|
||||||
/* send multicast frames both to higher layers in
|
/* send multicast frames both to higher layers in
|
||||||
* local net stack and back to the wireless media */
|
* local net stack and back to the wireless media */
|
||||||
skb2 = skb_copy(skb, GFP_ATOMIC);
|
xmit_skb = skb_copy(skb, GFP_ATOMIC);
|
||||||
if (!skb2 && net_ratelimit())
|
if (!xmit_skb && net_ratelimit())
|
||||||
printk(KERN_DEBUG "%s: failed to clone "
|
printk(KERN_DEBUG "%s: failed to clone "
|
||||||
"multicast frame\n", dev->name);
|
"multicast frame\n", dev->name);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1172,7 +1172,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
||||||
* AP, so send the frame directly to it and
|
* AP, so send the frame directly to it and
|
||||||
* do not pass the frame to local net stack.
|
* do not pass the frame to local net stack.
|
||||||
*/
|
*/
|
||||||
skb2 = skb;
|
xmit_skb = skb;
|
||||||
skb = NULL;
|
skb = NULL;
|
||||||
}
|
}
|
||||||
if (dsta)
|
if (dsta)
|
||||||
|
@ -1187,13 +1187,45 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
||||||
netif_rx(skb);
|
netif_rx(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skb2) {
|
if (xmit_skb) {
|
||||||
/* send to wireless media */
|
/* send to wireless media */
|
||||||
skb2->protocol = __constant_htons(ETH_P_802_3);
|
xmit_skb->protocol = __constant_htons(ETH_P_802_3);
|
||||||
skb_set_network_header(skb2, 0);
|
skb_set_network_header(xmit_skb, 0);
|
||||||
skb_set_mac_header(skb2, 0);
|
skb_set_mac_header(xmit_skb, 0);
|
||||||
dev_queue_xmit(skb2);
|
dev_queue_xmit(xmit_skb);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ieee80211_txrx_result
|
||||||
|
ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
|
||||||
|
{
|
||||||
|
struct net_device *dev = rx->dev;
|
||||||
|
u16 fc;
|
||||||
|
int err, hdrlen;
|
||||||
|
|
||||||
|
fc = rx->fc;
|
||||||
|
if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
|
||||||
|
return TXRX_CONTINUE;
|
||||||
|
|
||||||
|
if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
|
||||||
|
return TXRX_DROP;
|
||||||
|
|
||||||
|
hdrlen = ieee80211_get_hdrlen(fc);
|
||||||
|
|
||||||
|
if ((ieee80211_drop_802_1x_pae(rx, hdrlen)) ||
|
||||||
|
(ieee80211_drop_unencrypted(rx, hdrlen)))
|
||||||
|
return TXRX_DROP;
|
||||||
|
|
||||||
|
err = ieee80211_data_to_8023(rx);
|
||||||
|
if (unlikely(err))
|
||||||
|
return TXRX_DROP;
|
||||||
|
|
||||||
|
rx->skb->dev = dev;
|
||||||
|
|
||||||
|
dev->stats.rx_packets++;
|
||||||
|
dev->stats.rx_bytes += rx->skb->len;
|
||||||
|
|
||||||
|
ieee80211_deliver_skb(rx);
|
||||||
|
|
||||||
return TXRX_QUEUED;
|
return TXRX_QUEUED;
|
||||||
}
|
}
|
||||||
|
@ -1347,8 +1379,6 @@ ieee80211_rx_handler ieee80211_rx_handlers[] =
|
||||||
* are not passed to user space by these functions
|
* are not passed to user space by these functions
|
||||||
*/
|
*/
|
||||||
ieee80211_rx_h_remove_qos_control,
|
ieee80211_rx_h_remove_qos_control,
|
||||||
ieee80211_rx_h_802_1x_pae,
|
|
||||||
ieee80211_rx_h_drop_unencrypted,
|
|
||||||
ieee80211_rx_h_data,
|
ieee80211_rx_h_data,
|
||||||
ieee80211_rx_h_mgmt,
|
ieee80211_rx_h_mgmt,
|
||||||
NULL
|
NULL
|
||||||
|
|
|
@ -420,7 +420,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
|
||||||
return TXRX_CONTINUE;
|
return TXRX_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ieee80211_txrx_result
|
static ieee80211_txrx_result
|
||||||
ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
|
ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
|
||||||
{
|
{
|
||||||
|
@ -433,13 +432,15 @@ ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
|
||||||
return ieee80211_tx_h_multicast_ps_buf(tx);
|
return ieee80211_tx_h_multicast_ps_buf(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static ieee80211_txrx_result
|
static ieee80211_txrx_result
|
||||||
ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
|
ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
|
||||||
{
|
{
|
||||||
struct ieee80211_key *key;
|
struct ieee80211_key *key;
|
||||||
|
const struct ieee80211_hdr *hdr;
|
||||||
|
u16 fc;
|
||||||
|
|
||||||
|
hdr = (const struct ieee80211_hdr *) tx->skb->data;
|
||||||
|
fc = le16_to_cpu(hdr->frame_control);
|
||||||
|
|
||||||
if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
|
if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
|
||||||
tx->key = NULL;
|
tx->key = NULL;
|
||||||
|
@ -448,7 +449,8 @@ ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
|
||||||
else if ((key = rcu_dereference(tx->sdata->default_key)))
|
else if ((key = rcu_dereference(tx->sdata->default_key)))
|
||||||
tx->key = key;
|
tx->key = key;
|
||||||
else if (tx->sdata->drop_unencrypted &&
|
else if (tx->sdata->drop_unencrypted &&
|
||||||
!(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) {
|
!(tx->sdata->eapol &&
|
||||||
|
ieee80211_is_eapol(tx->skb, ieee80211_get_hdrlen(fc)))) {
|
||||||
I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
|
I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
|
||||||
return TXRX_DROP;
|
return TXRX_DROP;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -218,23 +218,11 @@ int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
|
EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
|
||||||
|
|
||||||
int ieee80211_is_eapol(const struct sk_buff *skb)
|
int ieee80211_is_eapol(const struct sk_buff *skb, int hdrlen)
|
||||||
{
|
{
|
||||||
const struct ieee80211_hdr *hdr;
|
|
||||||
u16 fc;
|
|
||||||
int hdrlen;
|
|
||||||
|
|
||||||
if (unlikely(skb->len < 10))
|
if (unlikely(skb->len < 10))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
hdr = (const struct ieee80211_hdr *) skb->data;
|
|
||||||
fc = le16_to_cpu(hdr->frame_control);
|
|
||||||
|
|
||||||
if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
hdrlen = ieee80211_get_hdrlen(fc);
|
|
||||||
|
|
||||||
if (unlikely(skb->len >= hdrlen + sizeof(eapol_header) &&
|
if (unlikely(skb->len >= hdrlen + sizeof(eapol_header) &&
|
||||||
memcmp(skb->data + hdrlen, eapol_header,
|
memcmp(skb->data + hdrlen, eapol_header,
|
||||||
sizeof(eapol_header)) == 0))
|
sizeof(eapol_header)) == 0))
|
||||||
|
|
Loading…
Reference in New Issue