From 76ee65bfaa1435320a72989a6413467ce446ae23 Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Thu, 22 Nov 2007 19:49:12 +0200 Subject: 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 Acked-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: David S. Miller --- net/mac80211/rx.c | 124 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 47 deletions(-) (limited to 'net/mac80211/rx.c') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a26aa7f5049..478d85563bd 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -962,68 +962,64 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx) return TXRX_CONTINUE; } -static ieee80211_txrx_result -ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx) +static int +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->flags & IEEE80211_TXRXD_RXRA_MATCH)) - return TXRX_CONTINUE; + return 0; if (unlikely(rx->sdata->ieee802_1x && (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) && - !ieee80211_is_eapol(rx->skb))) { + !ieee80211_is_eapol(rx->skb, hdrlen))) { #ifdef CONFIG_MAC80211_DEBUG - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) rx->skb->data; - DECLARE_MAC_BUF(mac); - printk(KERN_DEBUG "%s: dropped frame from %s" - " (unauthorized port)\n", rx->dev->name, - print_mac(mac, hdr->addr2)); + printk(KERN_DEBUG "%s: dropped frame " + "(unauthorized port)\n", rx->dev->name); #endif /* CONFIG_MAC80211_DEBUG */ - return TXRX_DROP; + return -EACCES; } - return TXRX_CONTINUE; + return 0; } -static ieee80211_txrx_result -ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx) +static int +ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx, int hdrlen) { /* * Pass through unencrypted frames if the hardware has * decrypted them already. */ if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED) - return TXRX_CONTINUE; + return 0; /* Drop unencrypted frames if key is set. */ if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) && (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && (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()) printk(KERN_DEBUG "%s: RX non-WEP frame, but expected " "encryption\n", rx->dev->name); - return TXRX_DROP; + return -EACCES; } - return TXRX_CONTINUE; + return 0; } -static ieee80211_txrx_result -ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) +static int +ieee80211_data_to_8023(struct ieee80211_txrx_data *rx) { struct net_device *dev = rx->dev; - struct ieee80211_local *local = rx->local; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; u16 fc, hdrlen, ethertype; u8 *payload; u8 dst[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); DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); @@ -1031,11 +1027,9 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) DECLARE_MAC_BUF(mac4); 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; + return -1; 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(mac2, hdr->addr2), print_mac(mac3, hdr->addr3)); - return TXRX_DROP; + return -1; } break; 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(mac3, hdr->addr3), print_mac(mac4, hdr->addr4)); - return TXRX_DROP; + return -1; } break; case IEEE80211_FCTL_FROMDS: @@ -1092,7 +1086,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) if (sdata->type != IEEE80211_IF_TYPE_STA || (is_multicast_ether_addr(dst) && !compare_ether_addr(src, dev->dev_addr))) - return TXRX_DROP; + return -1; break; case 0: /* DA SA BSSID */ @@ -1108,21 +1102,20 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) print_mac(mac2, hdr->addr2), print_mac(mac3, hdr->addr3)); } - return TXRX_DROP; + return -1; } break; } - payload = skb->data + hdrlen; - if (unlikely(skb->len - hdrlen < 8)) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: RX too short data frame " "payload\n", dev->name); } - return TXRX_DROP; + return -1; } + payload = skb->data + hdrlen; ethertype = (payload[6] << 8) | payload[7]; 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); 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++; - dev->stats.rx_bytes += skb->len; + skb = rx->skb; + xmit_skb = NULL; if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP || 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)) { /* send multicast frames both to higher layers in * local net stack and back to the wireless media */ - skb2 = skb_copy(skb, GFP_ATOMIC); - if (!skb2 && net_ratelimit()) + xmit_skb = skb_copy(skb, GFP_ATOMIC); + if (!xmit_skb && net_ratelimit()) printk(KERN_DEBUG "%s: failed to clone " "multicast frame\n", dev->name); } else { @@ -1172,7 +1172,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) * AP, so send the frame directly to it and * do not pass the frame to local net stack. */ - skb2 = skb; + xmit_skb = skb; skb = NULL; } if (dsta) @@ -1187,13 +1187,45 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) netif_rx(skb); } - if (skb2) { + if (xmit_skb) { /* send to wireless media */ - skb2->protocol = __constant_htons(ETH_P_802_3); - skb_set_network_header(skb2, 0); - skb_set_mac_header(skb2, 0); - dev_queue_xmit(skb2); + xmit_skb->protocol = __constant_htons(ETH_P_802_3); + skb_set_network_header(xmit_skb, 0); + skb_set_mac_header(xmit_skb, 0); + 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; } @@ -1347,8 +1379,6 @@ ieee80211_rx_handler ieee80211_rx_handlers[] = * are not passed to user space by these functions */ ieee80211_rx_h_remove_qos_control, - ieee80211_rx_h_802_1x_pae, - ieee80211_rx_h_drop_unencrypted, ieee80211_rx_h_data, ieee80211_rx_h_mgmt, NULL -- cgit v1.2.3