Staging: wlan-ng: p80211conv.c copy code from wlan-ng-devel branch to not drop packets
authorRichard Kennedy <richard@rsk.demon.co.uk>
Mon, 3 Nov 2008 11:24:54 +0000 (11:24 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 6 Jan 2009 21:52:00 +0000 (13:52 -0800)
allow card to correctly receive network packets,
without this change all incoming packets are dropped.
code copied from the latest wlan-ng-devel tree.

Signed-off-by: Richard Kennedy <richard@rsk.demon.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/wlan-ng/p80211conv.c

index e7cc89f..5d3d081 100644 (file)
@@ -377,6 +377,14 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb
             (memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0))) {
                WLAN_LOG_DEBUG(3, "802.3 ENCAP len: %d\n", payload_length);
                /* 802.3 Encapsulated */
+               /* Test for an overlength frame */
+               if ( payload_length > (netdev->mtu + WLAN_ETHHDR_LEN)) {
+                       /* A bogus length ethfrm has been encap'd. */
+                       /* Is someone trying an oflow attack? */
+                       WLAN_LOG_ERROR("ENCAP frame too large (%d > %d)\n",
+                               payload_length, netdev->mtu + WLAN_ETHHDR_LEN);
+                       return 1;
+               }
 
                /* Chop off the 802.11 header.  it's already sane. */
                skb_pull(skb, payload_offset);
@@ -396,6 +404,15 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb
                /* it's a SNAP + RFC1042 frame && protocol is in STT */
                /* build 802.3 + RFC1042 */
 
+               /* Test for an overlength frame */
+               if ( payload_length > netdev->mtu ) {
+                       /* A bogus length ethfrm has been sent. */
+                       /* Is someone trying an oflow attack? */
+                       WLAN_LOG_ERROR("SNAP frame too large (%d > %d)\n",
+                               payload_length, netdev->mtu);
+                       return 1;
+               }
+
                /* chop 802.11 header from skb. */
                skb_pull(skb, payload_offset);
 
@@ -416,6 +433,18 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb
                /* it's an 802.1h frame || (an RFC1042 && protocol is not in STT) */
                /* build a DIXII + RFC894 */
 
+               /* Test for an overlength frame */
+               if ((payload_length - sizeof(wlan_llc_t) - sizeof(wlan_snap_t))
+                   > netdev->mtu) {
+                       /* A bogus length ethfrm has been sent. */
+                       /* Is someone trying an oflow attack? */
+                       WLAN_LOG_ERROR("DIXII frame too large (%ld > %d)\n",
+                                       (long int) (payload_length - sizeof(wlan_llc_t) -
+                                                   sizeof(wlan_snap_t)),
+                                       netdev->mtu);
+                       return 1;
+               }
+
                /* chop 802.11 header from skb. */
                skb_pull(skb, payload_offset);
 
@@ -440,6 +469,16 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb
                /*  build an 802.3 frame */
                /* allocate space and setup hostbuf */
 
+               /* Test for an overlength frame */
+               if ( payload_length > netdev->mtu ) {
+                       /* A bogus length ethfrm has been sent. */
+                       /* Is someone trying an oflow attack? */
+                       WLAN_LOG_ERROR("OTHER frame too large (%d > %d)\n",
+                               payload_length,
+                               netdev->mtu);
+                       return 1;
+               }
+
                /* Chop off the 802.11 header. */
                skb_pull(skb, payload_offset);
 
@@ -454,8 +493,16 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb
 
        }
 
+        /*
+         * Note that eth_type_trans() expects an skb w/ skb->data pointing
+         * at the MAC header, it then sets the following skb members:
+         * skb->mac_header,
+         * skb->data, and
+         * skb->pkt_type.
+         * It then _returns_ the value that _we're_ supposed to stuff in
+         * skb->protocol.  This is nuts.
+         */
        skb->protocol = eth_type_trans(skb, netdev);
-       skb_reset_mac_header(skb);
 
         /* jkriegl: process signal and noise as set in hfa384x_int_rx() */
        /* jkriegl: only process signal/noise if requested by iwspy */