]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/wireless/hostap/hostap_80211_rx.c
[SK_BUFF]: unions of just one member don't get anything done, kill them
[net-next-2.6.git] / drivers / net / wireless / hostap / hostap_80211_rx.c
index b0501243b175f99090f2b7321cb15ba77be4b8bd..35a3a50724fee1c44036fc3d95bfa6281147cdc4 100644 (file)
@@ -1,15 +1,26 @@
 #include <linux/etherdevice.h>
+#include <net/ieee80211_crypt.h>
 
 #include "hostap_80211.h"
 #include "hostap.h"
+#include "hostap_ap.h"
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static unsigned char rfc1042_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static unsigned char bridge_tunnel_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+/* No encapsulation header if EtherType < 0x600 (=length) */
 
 void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
                          struct hostap_80211_rx_status *rx_stats)
 {
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u16 fc;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
        printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
               "jiffies=%ld\n",
@@ -51,7 +62,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
        int hdrlen, phdrlen, head_need, tail_need;
        u16 fc;
        int prism_header, ret;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
 
        iface = netdev_priv(dev);
        local = iface->local;
@@ -70,7 +81,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
                phdrlen = 0;
        }
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
 
        if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
@@ -156,7 +167,7 @@ hdr->f.status = s; hdr->f.len = l; hdr->f.data = d
 
        ret = skb->len - phdrlen;
        skb->dev = dev;
-       skb->mac.raw = skb->data;
+       skb_reset_mac_header(skb);
        skb_pull(skb, hdrlen);
        if (prism_header)
                skb_pull(skb, phdrlen);
@@ -215,7 +226,7 @@ prism2_frag_cache_find(local_info_t *local, unsigned int seq,
 
 /* Called only as a tasklet (software IRQ) */
 static struct sk_buff *
-prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
+prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
 {
        struct sk_buff *skb = NULL;
        u16 sc;
@@ -229,7 +240,7 @@ prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
        if (frag == 0) {
                /* Reserve enough space to fit maximum frame length */
                skb = dev_alloc_skb(local->dev->mtu +
-                                   sizeof(struct ieee80211_hdr) +
+                                   sizeof(struct ieee80211_hdr_4addr) +
                                    8 /* LLC */ +
                                    2 /* alignment */ +
                                    8 /* WEP */ + ETH_ALEN /* WDS */);
@@ -267,7 +278,7 @@ prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
 
 /* Called only as a tasklet (software IRQ) */
 static int prism2_frag_cache_invalidate(local_info_t *local,
-                                       struct ieee80211_hdr *hdr)
+                                       struct ieee80211_hdr_4addr *hdr)
 {
        u16 sc;
        unsigned int seq;
@@ -435,13 +446,13 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,
 }
 
 
-static inline int
+static int
 hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
                     struct hostap_80211_rx_status *rx_stats, u16 type,
                     u16 stype)
 {
        if (local->iw_mode == IW_MODE_MASTER) {
-               hostap_update_sta_ps(local, (struct ieee80211_hdr *)
+               hostap_update_sta_ps(local, (struct ieee80211_hdr_4addr *)
                                     skb->data);
        }
 
@@ -499,7 +510,7 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
 
 
 /* Called only as a tasklet (software IRQ) */
-static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
+static struct net_device *prism2_rx_get_wds(local_info_t *local,
                                                   u8 *addr)
 {
        struct hostap_interface *iface = NULL;
@@ -519,8 +530,8 @@ static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
 }
 
 
-static inline int
-hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr,
+static int
+hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
                    u16 fc, struct net_device **wds)
 {
        /* FIX: is this really supposed to accept WDS frames only in Master
@@ -579,13 +590,13 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
 {
        struct net_device *dev = local->dev;
        u16 fc, ethertype;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        u8 *pos;
 
        if (skb->len < 24)
                return 0;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        fc = le16_to_cpu(hdr->frame_ctl);
 
        /* check that the frame is unicast frame to us */
@@ -615,17 +626,17 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
 
 
 /* Called only as a tasklet (software IRQ) */
-static inline int
+static int
 hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
                        struct ieee80211_crypt_data *crypt)
 {
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        int res, hdrlen;
 
        if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
                return 0;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
        if (local->tkip_countermeasures &&
@@ -654,17 +665,17 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
 
 
 /* Called only as a tasklet (software IRQ) */
-static inline int
+static int
 hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
                             int keyidx, struct ieee80211_crypt_data *crypt)
 {
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        int res, hdrlen;
 
        if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
                return 0;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
        atomic_inc(&crypt->refcnt);
@@ -689,7 +700,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
 {
        struct hostap_interface *iface;
        local_info_t *local;
-       struct ieee80211_hdr *hdr;
+       struct ieee80211_hdr_4addr *hdr;
        size_t hdrlen;
        u16 fc, type, stype, sc;
        struct net_device *wds = NULL;
@@ -716,7 +727,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
        dev = local->ddev;
        iface = netdev_priv(dev);
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        stats = hostap_get_stats(dev);
 
        if (skb->len < 10)
@@ -737,7 +748,8 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
                struct iw_quality wstats;
                wstats.level = rx_stats->signal;
                wstats.noise = rx_stats->noise;
-               wstats.updated = 6;     /* No qual value */
+               wstats.updated = IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED
+                       | IW_QUAL_QUAL_INVALID | IW_QUAL_DBM;
                /* Update spy records */
                wireless_spy_update(dev, hdr->addr2, &wstats);
        }
@@ -889,7 +901,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
        if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
            (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
                goto rx_dropped;
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
        /* skb: hdr + (possibly fragmented) plaintext payload */
 
@@ -941,7 +953,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
                /* this was the last fragment and the frame will be
                 * delivered, so remove skb from fragment cache */
                skb = frag_skb;
-               hdr = (struct ieee80211_hdr *) skb->data;
+               hdr = (struct ieee80211_hdr_4addr *) skb->data;
                prism2_frag_cache_invalidate(local, hdr);
        }
 
@@ -952,7 +964,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
            hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt))
                goto rx_dropped;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr_4addr *) skb->data;
        if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) {
                if (local->ieee_802_1x &&
                    hostap_is_eapol_frame(local, skb)) {
@@ -1061,17 +1073,17 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
 
        if (skb2 != NULL) {
                /* send to wireless media */
-               skb2->protocol = __constant_htons(ETH_P_802_3);
-               skb2->mac.raw = skb2->nh.raw = skb2->data;
-               /* skb2->nh.raw = skb2->data + ETH_HLEN; */
                skb2->dev = dev;
+               skb2->protocol = __constant_htons(ETH_P_802_3);
+               skb_reset_mac_header(skb2);
+               skb_reset_network_header(skb2);
+               /* skb2->network_header += ETH_HLEN; */
                dev_queue_xmit(skb2);
        }
 
        if (skb) {
                skb->protocol = eth_type_trans(skb, dev);
                memset(skb->cb, 0, sizeof(skb->cb));
-               skb->dev = dev;
                netif_rx(skb);
        }