mac80211: clean up eapol handling in TX path
authorJohannes Berg <johannes@sipsolutions.net>
Wed, 19 Dec 2007 00:31:23 +0000 (01:31 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 22:59:46 +0000 (14:59 -0800)
The previous patch left only one user of the ieee80211_is_eapol()
function and that user can be eliminated easily by introducing
a new "frame is EAPOL" flag to handle the frame specially (we
already have this information) instead of doing the (expensive)
ieee80211_is_eapol() all the time.

Also, allow unencrypted frames to be sent when they are injected.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/mac80211.h
net/mac80211/ieee80211.c
net/mac80211/ieee80211_i.h
net/mac80211/tx.c
net/mac80211/util.c

index 3bd970f29f29d1fbe81a73d4dcf7bdc4cbb8fff0..2606ca282c5ec0a47d4d1b22e29a381b4a7db52f 100644 (file)
@@ -307,6 +307,7 @@ struct ieee80211_tx_control {
                                                  * using the through
                                                  * set_retry_limit configured
                                                  * long retry value */
+#define IEEE80211_TXCTL_EAPOL_FRAME    (1<<11) /* internal to mac80211 */
        u32 flags;                             /* tx control flags defined
                                                * above */
        u8 key_idx;             /* keyidx from hw->set_key(), undefined if
index c0dbf77547f7ffdb76fd8ab2a7541d6850924aa9..9c14e3d303c549229eccc6d922350e87670ce9fb 100644 (file)
@@ -732,6 +732,8 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
                pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
        if (control->flags & IEEE80211_TXCTL_REQUEUE)
                pkt_data->flags |= IEEE80211_TXPD_REQUEUE;
+       if (control->flags & IEEE80211_TXCTL_EAPOL_FRAME)
+               pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME;
        pkt_data->queue = control->queue;
 
        hdrlen = ieee80211_get_hdrlen_from_skb(skb);
index 214109b8d95aa05b23ffd6a4c133bf64a2978845..baf53c047127d0d08db6d127744b56e0a2806e60 100644 (file)
@@ -164,6 +164,7 @@ struct ieee80211_txrx_data {
 #define IEEE80211_TXPD_REQ_TX_STATUS   BIT(0)
 #define IEEE80211_TXPD_DO_NOT_ENCRYPT  BIT(1)
 #define IEEE80211_TXPD_REQUEUE         BIT(2)
+#define IEEE80211_TXPD_EAPOL_FRAME     BIT(3)
 /* Stored in sk_buff->cb */
 struct ieee80211_tx_packet_data {
        int ifindex;
@@ -798,7 +799,6 @@ 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);
-int ieee80211_is_eapol(const struct sk_buff *skb, int hdrlen);
 int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
                             int rate, int erp, int short_preamble);
 void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx,
index 6dbd91842881ee27901c636ed856d04ffe2e1357..e177a8dc23b98d8e56ec8fb8b0f833f48fe3f773 100644 (file)
@@ -437,7 +437,8 @@ ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
        else if ((key = rcu_dereference(tx->sdata->default_key)))
                tx->key = key;
        else if (tx->sdata->drop_unencrypted &&
-                !ieee80211_is_eapol(tx->skb, ieee80211_get_hdrlen(fc))) {
+                !(tx->u.tx.control->flags & IEEE80211_TXCTL_EAPOL_FRAME) &&
+                !(tx->flags & IEEE80211_TXRXD_TX_INJECTED)) {
                I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
                return TXRX_DROP;
        } else {
@@ -1241,6 +1242,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
                control.flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
        if (pkt_data->flags & IEEE80211_TXPD_REQUEUE)
                control.flags |= IEEE80211_TXCTL_REQUEUE;
+       if (pkt_data->flags & IEEE80211_TXPD_EAPOL_FRAME)
+               control.flags |= IEEE80211_TXCTL_EAPOL_FRAME;
        control.queue = pkt_data->queue;
 
        ret = ieee80211_tx(odev, skb, &control);
@@ -1514,6 +1517,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
        pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
        memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
        pkt_data->ifindex = dev->ifindex;
+       if (ethertype == ETH_P_PAE)
+               pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME;
 
        skb->dev = local->mdev;
        dev->stats.tx_packets++;
index fb7fd896cd0d81f74ed07df845034a8f49e13d18..2b02b2b9d645880dd1670f2784e4921d73eaf369 100644 (file)
@@ -40,10 +40,6 @@ const unsigned char rfc1042_header[] =
 const unsigned char bridge_tunnel_header[] =
        { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
 
-/* No encapsulation header if EtherType < 0x600 (=length) */
-static const unsigned char eapol_header[] =
-       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
-
 
 static int rate_list_match(const int *rate_list, int rate)
 {
@@ -223,19 +219,6 @@ int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
 }
 EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
 
-int ieee80211_is_eapol(const struct sk_buff *skb, int hdrlen)
-{
-       if (unlikely(skb->len < 10))
-               return 0;
-
-       if (unlikely(skb->len >= hdrlen + sizeof(eapol_header) &&
-                    memcmp(skb->data + hdrlen, eapol_header,
-                           sizeof(eapol_header)) == 0))
-               return 1;
-
-       return 0;
-}
-
 void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;