Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/etherdevice.h>
0003 #include <linux/slab.h>
0004 #include <linux/export.h>
0005 #include <net/lib80211.h>
0006 #include <linux/if_arp.h>
0007 
0008 #include "hostap_80211.h"
0009 #include "hostap.h"
0010 #include "hostap_ap.h"
0011 
0012 /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
0013 /* Ethernet-II snap header (RFC1042 for most EtherTypes) */
0014 static unsigned char rfc1042_header[] =
0015 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
0016 /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
0017 static unsigned char bridge_tunnel_header[] =
0018 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
0019 /* No encapsulation header if EtherType < 0x600 (=length) */
0020 
0021 void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
0022               struct hostap_80211_rx_status *rx_stats)
0023 {
0024     struct ieee80211_hdr *hdr;
0025     u16 fc;
0026 
0027     hdr = (struct ieee80211_hdr *) skb->data;
0028 
0029     printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
0030            "jiffies=%ld\n",
0031            name, rx_stats->signal, rx_stats->noise, rx_stats->rate,
0032            skb->len, jiffies);
0033 
0034     if (skb->len < 2)
0035         return;
0036 
0037     fc = le16_to_cpu(hdr->frame_control);
0038     printk(KERN_DEBUG "   FC=0x%04x (type=%d:%d)%s%s",
0039            fc, (fc & IEEE80211_FCTL_FTYPE) >> 2,
0040            (fc & IEEE80211_FCTL_STYPE) >> 4,
0041            fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
0042            fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
0043 
0044     if (skb->len < IEEE80211_DATA_HDR3_LEN) {
0045         printk("\n");
0046         return;
0047     }
0048 
0049     printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
0050            le16_to_cpu(hdr->seq_ctrl));
0051 
0052     printk(KERN_DEBUG "   A1=%pM", hdr->addr1);
0053     printk(" A2=%pM", hdr->addr2);
0054     printk(" A3=%pM", hdr->addr3);
0055     if (skb->len >= 30)
0056         printk(" A4=%pM", hdr->addr4);
0057     printk("\n");
0058 }
0059 
0060 
0061 /* Send RX frame to netif with 802.11 (and possible prism) header.
0062  * Called from hardware or software IRQ context. */
0063 int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
0064             struct hostap_80211_rx_status *rx_stats, int type)
0065 {
0066     struct hostap_interface *iface;
0067     local_info_t *local;
0068     int hdrlen, phdrlen, head_need, tail_need;
0069     u16 fc;
0070     int prism_header, ret;
0071     struct ieee80211_hdr *fhdr;
0072 
0073     iface = netdev_priv(dev);
0074     local = iface->local;
0075 
0076     if (dev->type == ARPHRD_IEEE80211_PRISM) {
0077         if (local->monitor_type == PRISM2_MONITOR_PRISM) {
0078             prism_header = 1;
0079             phdrlen = sizeof(struct linux_wlan_ng_prism_hdr);
0080         } else { /* local->monitor_type == PRISM2_MONITOR_CAPHDR */
0081             prism_header = 2;
0082             phdrlen = sizeof(struct linux_wlan_ng_cap_hdr);
0083         }
0084     } else if (dev->type == ARPHRD_IEEE80211_RADIOTAP) {
0085         prism_header = 3;
0086         phdrlen = sizeof(struct hostap_radiotap_rx);
0087     } else {
0088         prism_header = 0;
0089         phdrlen = 0;
0090     }
0091 
0092     fhdr = (struct ieee80211_hdr *) skb->data;
0093     fc = le16_to_cpu(fhdr->frame_control);
0094 
0095     if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
0096         printk(KERN_DEBUG "%s: dropped management frame with header "
0097                "version %d\n", dev->name, fc & IEEE80211_FCTL_VERS);
0098         dev_kfree_skb_any(skb);
0099         return 0;
0100     }
0101 
0102     hdrlen = hostap_80211_get_hdrlen(fhdr->frame_control);
0103 
0104     /* check if there is enough room for extra data; if not, expand skb
0105      * buffer to be large enough for the changes */
0106     head_need = phdrlen;
0107     tail_need = 0;
0108 #ifdef PRISM2_ADD_BOGUS_CRC
0109     tail_need += 4;
0110 #endif /* PRISM2_ADD_BOGUS_CRC */
0111 
0112     head_need -= skb_headroom(skb);
0113     tail_need -= skb_tailroom(skb);
0114 
0115     if (head_need > 0 || tail_need > 0) {
0116         if (pskb_expand_head(skb, head_need > 0 ? head_need : 0,
0117                      tail_need > 0 ? tail_need : 0,
0118                      GFP_ATOMIC)) {
0119             printk(KERN_DEBUG "%s: prism2_rx_80211 failed to "
0120                    "reallocate skb buffer\n", dev->name);
0121             dev_kfree_skb_any(skb);
0122             return 0;
0123         }
0124     }
0125 
0126     /* We now have an skb with enough head and tail room, so just insert
0127      * the extra data */
0128 
0129 #ifdef PRISM2_ADD_BOGUS_CRC
0130     memset(skb_put(skb, 4), 0xff, 4); /* Prism2 strips CRC */
0131 #endif /* PRISM2_ADD_BOGUS_CRC */
0132 
0133     if (prism_header == 1) {
0134         struct linux_wlan_ng_prism_hdr *hdr;
0135         hdr = skb_push(skb, phdrlen);
0136         memset(hdr, 0, phdrlen);
0137         hdr->msgcode = LWNG_CAP_DID_BASE;
0138         hdr->msglen = sizeof(*hdr);
0139         memcpy(hdr->devname, dev->name, sizeof(hdr->devname));
0140 #define LWNG_SETVAL(f,i,s,l,d) \
0141 hdr->f.did = LWNG_CAP_DID_BASE | (i << 12); \
0142 hdr->f.status = s; hdr->f.len = l; hdr->f.data = d
0143         LWNG_SETVAL(hosttime, 1, 0, 4, jiffies);
0144         LWNG_SETVAL(mactime, 2, 0, 4, rx_stats->mac_time);
0145         LWNG_SETVAL(channel, 3, 1 /* no value */, 4, 0);
0146         LWNG_SETVAL(rssi, 4, 1 /* no value */, 4, 0);
0147         LWNG_SETVAL(sq, 5, 1 /* no value */, 4, 0);
0148         LWNG_SETVAL(signal, 6, 0, 4, rx_stats->signal);
0149         LWNG_SETVAL(noise, 7, 0, 4, rx_stats->noise);
0150         LWNG_SETVAL(rate, 8, 0, 4, rx_stats->rate / 5);
0151         LWNG_SETVAL(istx, 9, 0, 4, 0);
0152         LWNG_SETVAL(frmlen, 10, 0, 4, skb->len - phdrlen);
0153 #undef LWNG_SETVAL
0154     } else if (prism_header == 2) {
0155         struct linux_wlan_ng_cap_hdr *hdr;
0156         hdr = skb_push(skb, phdrlen);
0157         memset(hdr, 0, phdrlen);
0158         hdr->version    = htonl(LWNG_CAPHDR_VERSION);
0159         hdr->length     = htonl(phdrlen);
0160         hdr->mactime    = __cpu_to_be64(rx_stats->mac_time);
0161         hdr->hosttime   = __cpu_to_be64(jiffies);
0162         hdr->phytype    = htonl(4); /* dss_dot11_b */
0163         hdr->channel    = htonl(local->channel);
0164         hdr->datarate   = htonl(rx_stats->rate);
0165         hdr->antenna    = htonl(0); /* unknown */
0166         hdr->priority   = htonl(0); /* unknown */
0167         hdr->ssi_type   = htonl(3); /* raw */
0168         hdr->ssi_signal = htonl(rx_stats->signal);
0169         hdr->ssi_noise  = htonl(rx_stats->noise);
0170         hdr->preamble   = htonl(0); /* unknown */
0171         hdr->encoding   = htonl(1); /* cck */
0172     } else if (prism_header == 3) {
0173         struct hostap_radiotap_rx *hdr;
0174         hdr = skb_push(skb, phdrlen);
0175         memset(hdr, 0, phdrlen);
0176         hdr->hdr.it_len = cpu_to_le16(phdrlen);
0177         hdr->hdr.it_present =
0178             cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
0179                     (1 << IEEE80211_RADIOTAP_CHANNEL) |
0180                     (1 << IEEE80211_RADIOTAP_RATE) |
0181                     (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
0182                     (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE));
0183         hdr->tsft = cpu_to_le64(rx_stats->mac_time);
0184         hdr->chan_freq = cpu_to_le16(freq_list[local->channel - 1]);
0185         hdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_CCK |
0186                          IEEE80211_CHAN_2GHZ);
0187         hdr->rate = rx_stats->rate / 5;
0188         hdr->dbm_antsignal = rx_stats->signal;
0189         hdr->dbm_antnoise = rx_stats->noise;
0190     }
0191 
0192     ret = skb->len - phdrlen;
0193     skb->dev = dev;
0194     skb_reset_mac_header(skb);
0195     skb_pull(skb, hdrlen);
0196     if (prism_header)
0197         skb_pull(skb, phdrlen);
0198     skb->pkt_type = PACKET_OTHERHOST;
0199     skb->protocol = cpu_to_be16(ETH_P_802_2);
0200     memset(skb->cb, 0, sizeof(skb->cb));
0201     netif_rx(skb);
0202 
0203     return ret;
0204 }
0205 
0206 
0207 /* Called only as a tasklet (software IRQ) */
0208 static void monitor_rx(struct net_device *dev, struct sk_buff *skb,
0209                struct hostap_80211_rx_status *rx_stats)
0210 {
0211     int len;
0212 
0213     len = prism2_rx_80211(dev, skb, rx_stats, PRISM2_RX_MONITOR);
0214     dev->stats.rx_packets++;
0215     dev->stats.rx_bytes += len;
0216 }
0217 
0218 
0219 /* Called only as a tasklet (software IRQ) */
0220 static struct prism2_frag_entry *
0221 prism2_frag_cache_find(local_info_t *local, unsigned int seq,
0222                unsigned int frag, u8 *src, u8 *dst)
0223 {
0224     struct prism2_frag_entry *entry;
0225     int i;
0226 
0227     for (i = 0; i < PRISM2_FRAG_CACHE_LEN; i++) {
0228         entry = &local->frag_cache[i];
0229         if (entry->skb != NULL &&
0230             time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
0231             printk(KERN_DEBUG "%s: expiring fragment cache entry "
0232                    "seq=%u last_frag=%u\n",
0233                    local->dev->name, entry->seq, entry->last_frag);
0234             dev_kfree_skb(entry->skb);
0235             entry->skb = NULL;
0236         }
0237 
0238         if (entry->skb != NULL && entry->seq == seq &&
0239             (entry->last_frag + 1 == frag || frag == -1) &&
0240             memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
0241             memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
0242             return entry;
0243     }
0244 
0245     return NULL;
0246 }
0247 
0248 
0249 /* Called only as a tasklet (software IRQ) */
0250 static struct sk_buff *
0251 prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
0252 {
0253     struct sk_buff *skb = NULL;
0254     u16 sc;
0255     unsigned int frag, seq;
0256     struct prism2_frag_entry *entry;
0257 
0258     sc = le16_to_cpu(hdr->seq_ctrl);
0259     frag = sc & IEEE80211_SCTL_FRAG;
0260     seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
0261 
0262     if (frag == 0) {
0263         /* Reserve enough space to fit maximum frame length */
0264         skb = dev_alloc_skb(local->dev->mtu +
0265                     sizeof(struct ieee80211_hdr) +
0266                     8 /* LLC */ +
0267                     2 /* alignment */ +
0268                     8 /* WEP */ + ETH_ALEN /* WDS */);
0269         if (skb == NULL)
0270             return NULL;
0271 
0272         entry = &local->frag_cache[local->frag_next_idx];
0273         local->frag_next_idx++;
0274         if (local->frag_next_idx >= PRISM2_FRAG_CACHE_LEN)
0275             local->frag_next_idx = 0;
0276 
0277         if (entry->skb != NULL)
0278             dev_kfree_skb(entry->skb);
0279 
0280         entry->first_frag_time = jiffies;
0281         entry->seq = seq;
0282         entry->last_frag = frag;
0283         entry->skb = skb;
0284         memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
0285         memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
0286     } else {
0287         /* received a fragment of a frame for which the head fragment
0288          * should have already been received */
0289         entry = prism2_frag_cache_find(local, seq, frag, hdr->addr2,
0290                            hdr->addr1);
0291         if (entry != NULL) {
0292             entry->last_frag = frag;
0293             skb = entry->skb;
0294         }
0295     }
0296 
0297     return skb;
0298 }
0299 
0300 
0301 /* Called only as a tasklet (software IRQ) */
0302 static int prism2_frag_cache_invalidate(local_info_t *local,
0303                     struct ieee80211_hdr *hdr)
0304 {
0305     u16 sc;
0306     unsigned int seq;
0307     struct prism2_frag_entry *entry;
0308 
0309     sc = le16_to_cpu(hdr->seq_ctrl);
0310     seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
0311 
0312     entry = prism2_frag_cache_find(local, seq, -1, hdr->addr2, hdr->addr1);
0313 
0314     if (entry == NULL) {
0315         printk(KERN_DEBUG "%s: could not invalidate fragment cache "
0316                "entry (seq=%u)\n",
0317                local->dev->name, seq);
0318         return -1;
0319     }
0320 
0321     entry->skb = NULL;
0322     return 0;
0323 }
0324 
0325 
0326 static struct hostap_bss_info *__hostap_get_bss(local_info_t *local, u8 *bssid,
0327                         u8 *ssid, size_t ssid_len)
0328 {
0329     struct list_head *ptr;
0330     struct hostap_bss_info *bss;
0331 
0332     list_for_each(ptr, &local->bss_list) {
0333         bss = list_entry(ptr, struct hostap_bss_info, list);
0334         if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
0335             (ssid == NULL ||
0336              (ssid_len == bss->ssid_len &&
0337               memcmp(ssid, bss->ssid, ssid_len) == 0))) {
0338             list_move(&bss->list, &local->bss_list);
0339             return bss;
0340         }
0341     }
0342 
0343     return NULL;
0344 }
0345 
0346 
0347 static struct hostap_bss_info *__hostap_add_bss(local_info_t *local, u8 *bssid,
0348                         u8 *ssid, size_t ssid_len)
0349 {
0350     struct hostap_bss_info *bss;
0351 
0352     if (local->num_bss_info >= HOSTAP_MAX_BSS_COUNT) {
0353         bss = list_entry(local->bss_list.prev,
0354                  struct hostap_bss_info, list);
0355         list_del(&bss->list);
0356         local->num_bss_info--;
0357     } else {
0358         bss = kmalloc(sizeof(*bss), GFP_ATOMIC);
0359         if (bss == NULL)
0360             return NULL;
0361     }
0362 
0363     memset(bss, 0, sizeof(*bss));
0364     memcpy(bss->bssid, bssid, ETH_ALEN);
0365     memcpy(bss->ssid, ssid, ssid_len);
0366     bss->ssid_len = ssid_len;
0367     local->num_bss_info++;
0368     list_add(&bss->list, &local->bss_list);
0369     return bss;
0370 }
0371 
0372 
0373 static void __hostap_expire_bss(local_info_t *local)
0374 {
0375     struct hostap_bss_info *bss;
0376 
0377     while (local->num_bss_info > 0) {
0378         bss = list_entry(local->bss_list.prev,
0379                  struct hostap_bss_info, list);
0380         if (!time_after(jiffies, bss->last_update + 60 * HZ))
0381             break;
0382 
0383         list_del(&bss->list);
0384         local->num_bss_info--;
0385         kfree(bss);
0386     }
0387 }
0388 
0389 
0390 /* Both IEEE 802.11 Beacon and Probe Response frames have similar structure, so
0391  * the same routine can be used to parse both of them. */
0392 static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,
0393                  int stype)
0394 {
0395     struct hostap_ieee80211_mgmt *mgmt;
0396     int left, chan = 0;
0397     u8 *pos;
0398     u8 *ssid = NULL, *wpa = NULL, *rsn = NULL;
0399     size_t ssid_len = 0, wpa_len = 0, rsn_len = 0;
0400     struct hostap_bss_info *bss;
0401 
0402     if (skb->len < IEEE80211_MGMT_HDR_LEN + sizeof(mgmt->u.beacon))
0403         return;
0404 
0405     mgmt = (struct hostap_ieee80211_mgmt *) skb->data;
0406     pos = mgmt->u.beacon.variable;
0407     left = skb->len - (pos - skb->data);
0408 
0409     while (left >= 2) {
0410         if (2 + pos[1] > left)
0411             return; /* parse failed */
0412         switch (*pos) {
0413         case WLAN_EID_SSID:
0414             ssid = pos + 2;
0415             ssid_len = pos[1];
0416             break;
0417         case WLAN_EID_VENDOR_SPECIFIC:
0418             if (pos[1] >= 4 &&
0419                 pos[2] == 0x00 && pos[3] == 0x50 &&
0420                 pos[4] == 0xf2 && pos[5] == 1) {
0421                 wpa = pos;
0422                 wpa_len = pos[1] + 2;
0423             }
0424             break;
0425         case WLAN_EID_RSN:
0426             rsn = pos;
0427             rsn_len = pos[1] + 2;
0428             break;
0429         case WLAN_EID_DS_PARAMS:
0430             if (pos[1] >= 1)
0431                 chan = pos[2];
0432             break;
0433         }
0434         left -= 2 + pos[1];
0435         pos += 2 + pos[1];
0436     }
0437 
0438     if (wpa_len > MAX_WPA_IE_LEN)
0439         wpa_len = MAX_WPA_IE_LEN;
0440     if (rsn_len > MAX_WPA_IE_LEN)
0441         rsn_len = MAX_WPA_IE_LEN;
0442     if (ssid_len > sizeof(bss->ssid))
0443         ssid_len = sizeof(bss->ssid);
0444 
0445     spin_lock(&local->lock);
0446     bss = __hostap_get_bss(local, mgmt->bssid, ssid, ssid_len);
0447     if (bss == NULL)
0448         bss = __hostap_add_bss(local, mgmt->bssid, ssid, ssid_len);
0449     if (bss) {
0450         bss->last_update = jiffies;
0451         bss->count++;
0452         bss->capab_info = le16_to_cpu(mgmt->u.beacon.capab_info);
0453         if (wpa) {
0454             memcpy(bss->wpa_ie, wpa, wpa_len);
0455             bss->wpa_ie_len = wpa_len;
0456         } else
0457             bss->wpa_ie_len = 0;
0458         if (rsn) {
0459             memcpy(bss->rsn_ie, rsn, rsn_len);
0460             bss->rsn_ie_len = rsn_len;
0461         } else
0462             bss->rsn_ie_len = 0;
0463         bss->chan = chan;
0464     }
0465     __hostap_expire_bss(local);
0466     spin_unlock(&local->lock);
0467 }
0468 
0469 
0470 static int
0471 hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
0472              struct hostap_80211_rx_status *rx_stats, u16 type,
0473              u16 stype)
0474 {
0475     if (local->iw_mode == IW_MODE_MASTER)
0476         hostap_update_sta_ps(local, (struct ieee80211_hdr *) skb->data);
0477 
0478     if (local->hostapd && type == IEEE80211_FTYPE_MGMT) {
0479         if (stype == IEEE80211_STYPE_BEACON &&
0480             local->iw_mode == IW_MODE_MASTER) {
0481             struct sk_buff *skb2;
0482             /* Process beacon frames also in kernel driver to
0483              * update STA(AP) table statistics */
0484             skb2 = skb_clone(skb, GFP_ATOMIC);
0485             if (skb2)
0486                 hostap_rx(skb2->dev, skb2, rx_stats);
0487         }
0488 
0489         /* send management frames to the user space daemon for
0490          * processing */
0491         local->apdevstats.rx_packets++;
0492         local->apdevstats.rx_bytes += skb->len;
0493         if (local->apdev == NULL)
0494             return -1;
0495         prism2_rx_80211(local->apdev, skb, rx_stats, PRISM2_RX_MGMT);
0496         return 0;
0497     }
0498 
0499     if (local->iw_mode == IW_MODE_MASTER) {
0500         if (type != IEEE80211_FTYPE_MGMT &&
0501             type != IEEE80211_FTYPE_CTL) {
0502             printk(KERN_DEBUG "%s: unknown management frame "
0503                    "(type=0x%02x, stype=0x%02x) dropped\n",
0504                    skb->dev->name, type >> 2, stype >> 4);
0505             return -1;
0506         }
0507 
0508         hostap_rx(skb->dev, skb, rx_stats);
0509         return 0;
0510     } else if (type == IEEE80211_FTYPE_MGMT &&
0511            (stype == IEEE80211_STYPE_BEACON ||
0512             stype == IEEE80211_STYPE_PROBE_RESP)) {
0513         hostap_rx_sta_beacon(local, skb, stype);
0514         return -1;
0515     } else if (type == IEEE80211_FTYPE_MGMT &&
0516            (stype == IEEE80211_STYPE_ASSOC_RESP ||
0517             stype == IEEE80211_STYPE_REASSOC_RESP)) {
0518         /* Ignore (Re)AssocResp silently since these are not currently
0519          * needed but are still received when WPA/RSN mode is enabled.
0520          */
0521         return -1;
0522     } else {
0523         printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: dropped unhandled"
0524                " management frame in non-Host AP mode (type=%d:%d)\n",
0525                skb->dev->name, type >> 2, stype >> 4);
0526         return -1;
0527     }
0528 }
0529 
0530 
0531 /* Called only as a tasklet (software IRQ) */
0532 static struct net_device *prism2_rx_get_wds(local_info_t *local,
0533                            u8 *addr)
0534 {
0535     struct hostap_interface *iface = NULL;
0536     struct list_head *ptr;
0537 
0538     read_lock_bh(&local->iface_lock);
0539     list_for_each(ptr, &local->hostap_interfaces) {
0540         iface = list_entry(ptr, struct hostap_interface, list);
0541         if (iface->type == HOSTAP_INTERFACE_WDS &&
0542             memcmp(iface->u.wds.remote_addr, addr, ETH_ALEN) == 0)
0543             break;
0544         iface = NULL;
0545     }
0546     read_unlock_bh(&local->iface_lock);
0547 
0548     return iface ? iface->dev : NULL;
0549 }
0550 
0551 
0552 static int
0553 hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr, u16 fc,
0554             struct net_device **wds)
0555 {
0556     /* FIX: is this really supposed to accept WDS frames only in Master
0557      * mode? What about Repeater or Managed with WDS frames? */
0558     if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) !=
0559         (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS) &&
0560         (local->iw_mode != IW_MODE_MASTER || !(fc & IEEE80211_FCTL_TODS)))
0561         return 0; /* not a WDS frame */
0562 
0563     /* Possible WDS frame: either IEEE 802.11 compliant (if FromDS)
0564      * or own non-standard frame with 4th address after payload */
0565     if (!ether_addr_equal(hdr->addr1, local->dev->dev_addr) &&
0566         (hdr->addr1[0] != 0xff || hdr->addr1[1] != 0xff ||
0567          hdr->addr1[2] != 0xff || hdr->addr1[3] != 0xff ||
0568          hdr->addr1[4] != 0xff || hdr->addr1[5] != 0xff)) {
0569         /* RA (or BSSID) is not ours - drop */
0570         PDEBUG(DEBUG_EXTRA2, "%s: received WDS frame with "
0571                "not own or broadcast %s=%pM\n",
0572                local->dev->name,
0573                fc & IEEE80211_FCTL_FROMDS ? "RA" : "BSSID",
0574                hdr->addr1);
0575         return -1;
0576     }
0577 
0578     /* check if the frame came from a registered WDS connection */
0579     *wds = prism2_rx_get_wds(local, hdr->addr2);
0580     if (*wds == NULL && fc & IEEE80211_FCTL_FROMDS &&
0581         (local->iw_mode != IW_MODE_INFRA ||
0582          !(local->wds_type & HOSTAP_WDS_AP_CLIENT) ||
0583          memcmp(hdr->addr2, local->bssid, ETH_ALEN) != 0)) {
0584         /* require that WDS link has been registered with TA or the
0585          * frame is from current AP when using 'AP client mode' */
0586         PDEBUG(DEBUG_EXTRA, "%s: received WDS[4 addr] frame "
0587                "from unknown TA=%pM\n",
0588                local->dev->name, hdr->addr2);
0589         if (local->ap && local->ap->autom_ap_wds)
0590             hostap_wds_link_oper(local, hdr->addr2, WDS_ADD);
0591         return -1;
0592     }
0593 
0594     if (*wds && !(fc & IEEE80211_FCTL_FROMDS) && local->ap &&
0595         hostap_is_sta_assoc(local->ap, hdr->addr2)) {
0596         /* STA is actually associated with us even though it has a
0597          * registered WDS link. Assume it is in 'AP client' mode.
0598          * Since this is a 3-addr frame, assume it is not (bogus) WDS
0599          * frame and process it like any normal ToDS frame from
0600          * associated STA. */
0601         *wds = NULL;
0602     }
0603 
0604     return 0;
0605 }
0606 
0607 
0608 static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
0609 {
0610     struct net_device *dev = local->dev;
0611     u16 fc, ethertype;
0612     struct ieee80211_hdr *hdr;
0613     u8 *pos;
0614 
0615     if (skb->len < 24)
0616         return 0;
0617 
0618     hdr = (struct ieee80211_hdr *) skb->data;
0619     fc = le16_to_cpu(hdr->frame_control);
0620 
0621     /* check that the frame is unicast frame to us */
0622     if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
0623         IEEE80211_FCTL_TODS &&
0624         ether_addr_equal(hdr->addr1, dev->dev_addr) &&
0625         ether_addr_equal(hdr->addr3, dev->dev_addr)) {
0626         /* ToDS frame with own addr BSSID and DA */
0627     } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
0628            IEEE80211_FCTL_FROMDS &&
0629            ether_addr_equal(hdr->addr1, dev->dev_addr)) {
0630         /* FromDS frame with own addr as DA */
0631     } else
0632         return 0;
0633 
0634     if (skb->len < 24 + 8)
0635         return 0;
0636 
0637     /* check for port access entity Ethernet type */
0638     pos = skb->data + 24;
0639     ethertype = (pos[6] << 8) | pos[7];
0640     if (ethertype == ETH_P_PAE)
0641         return 1;
0642 
0643     return 0;
0644 }
0645 
0646 
0647 /* Called only as a tasklet (software IRQ) */
0648 static int
0649 hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
0650             struct lib80211_crypt_data *crypt)
0651 {
0652     struct ieee80211_hdr *hdr;
0653     int res, hdrlen;
0654 
0655     if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
0656         return 0;
0657 
0658     hdr = (struct ieee80211_hdr *) skb->data;
0659     hdrlen = hostap_80211_get_hdrlen(hdr->frame_control);
0660 
0661     if (local->tkip_countermeasures &&
0662         strcmp(crypt->ops->name, "TKIP") == 0) {
0663         if (net_ratelimit()) {
0664             printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
0665                    "received packet from %pM\n",
0666                    local->dev->name, hdr->addr2);
0667         }
0668         return -1;
0669     }
0670 
0671     atomic_inc(&crypt->refcnt);
0672     res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
0673     atomic_dec(&crypt->refcnt);
0674     if (res < 0) {
0675         printk(KERN_DEBUG "%s: decryption failed (SA=%pM) res=%d\n",
0676                local->dev->name, hdr->addr2, res);
0677         local->comm_tallies.rx_discards_wep_undecryptable++;
0678         return -1;
0679     }
0680 
0681     return res;
0682 }
0683 
0684 
0685 /* Called only as a tasklet (software IRQ) */
0686 static int
0687 hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
0688                  int keyidx, struct lib80211_crypt_data *crypt)
0689 {
0690     struct ieee80211_hdr *hdr;
0691     int res, hdrlen;
0692 
0693     if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
0694         return 0;
0695 
0696     hdr = (struct ieee80211_hdr *) skb->data;
0697     hdrlen = hostap_80211_get_hdrlen(hdr->frame_control);
0698 
0699     atomic_inc(&crypt->refcnt);
0700     res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
0701     atomic_dec(&crypt->refcnt);
0702     if (res < 0) {
0703         printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
0704                " (SA=%pM keyidx=%d)\n",
0705                local->dev->name, hdr->addr2, keyidx);
0706         return -1;
0707     }
0708 
0709     return 0;
0710 }
0711 
0712 
0713 /* All received frames are sent to this function. @skb contains the frame in
0714  * IEEE 802.11 format, i.e., in the format it was sent over air.
0715  * This function is called only as a tasklet (software IRQ). */
0716 void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
0717              struct hostap_80211_rx_status *rx_stats)
0718 {
0719     struct hostap_interface *iface;
0720     local_info_t *local;
0721     struct ieee80211_hdr *hdr;
0722     size_t hdrlen;
0723     u16 fc, type, stype, sc;
0724     struct net_device *wds = NULL;
0725     unsigned int frag;
0726     u8 *payload;
0727     struct sk_buff *skb2 = NULL;
0728     u16 ethertype;
0729     int frame_authorized = 0;
0730     int from_assoc_ap = 0;
0731     u8 dst[ETH_ALEN];
0732     u8 src[ETH_ALEN];
0733     struct lib80211_crypt_data *crypt = NULL;
0734     void *sta = NULL;
0735     int keyidx = 0;
0736 
0737     iface = netdev_priv(dev);
0738     local = iface->local;
0739     iface->stats.rx_packets++;
0740     iface->stats.rx_bytes += skb->len;
0741 
0742     /* dev is the master radio device; change this to be the default
0743      * virtual interface (this may be changed to WDS device below) */
0744     dev = local->ddev;
0745     iface = netdev_priv(dev);
0746 
0747     hdr = (struct ieee80211_hdr *) skb->data;
0748 
0749     if (skb->len < 10)
0750         goto rx_dropped;
0751 
0752     fc = le16_to_cpu(hdr->frame_control);
0753     type = fc & IEEE80211_FCTL_FTYPE;
0754     stype = fc & IEEE80211_FCTL_STYPE;
0755     sc = le16_to_cpu(hdr->seq_ctrl);
0756     frag = sc & IEEE80211_SCTL_FRAG;
0757     hdrlen = hostap_80211_get_hdrlen(hdr->frame_control);
0758 
0759     /* Put this code here so that we avoid duplicating it in all
0760      * Rx paths. - Jean II */
0761 #ifdef IW_WIRELESS_SPY      /* defined in iw_handler.h */
0762     /* If spy monitoring on */
0763     if (iface->spy_data.spy_number > 0) {
0764         struct iw_quality wstats;
0765         wstats.level = rx_stats->signal;
0766         wstats.noise = rx_stats->noise;
0767         wstats.updated = IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED
0768             | IW_QUAL_QUAL_INVALID | IW_QUAL_DBM;
0769         /* Update spy records */
0770         wireless_spy_update(dev, hdr->addr2, &wstats);
0771     }
0772 #endif /* IW_WIRELESS_SPY */
0773     hostap_update_rx_stats(local->ap, hdr, rx_stats);
0774 
0775     if (local->iw_mode == IW_MODE_MONITOR) {
0776         monitor_rx(dev, skb, rx_stats);
0777         return;
0778     }
0779 
0780     if (local->host_decrypt) {
0781         int idx = 0;
0782         if (skb->len >= hdrlen + 3)
0783             idx = skb->data[hdrlen + 3] >> 6;
0784         crypt = local->crypt_info.crypt[idx];
0785         sta = NULL;
0786 
0787         /* Use station specific key to override default keys if the
0788          * receiver address is a unicast address ("individual RA"). If
0789          * bcrx_sta_key parameter is set, station specific key is used
0790          * even with broad/multicast targets (this is against IEEE
0791          * 802.11, but makes it easier to use different keys with
0792          * stations that do not support WEP key mapping). */
0793 
0794         if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
0795             (void) hostap_handle_sta_crypto(local, hdr, &crypt,
0796                             &sta);
0797 
0798         /* allow NULL decrypt to indicate an station specific override
0799          * for default encryption */
0800         if (crypt && (crypt->ops == NULL ||
0801                   crypt->ops->decrypt_mpdu == NULL))
0802             crypt = NULL;
0803 
0804         if (!crypt && (fc & IEEE80211_FCTL_PROTECTED)) {
0805 #if 0
0806             /* This seems to be triggered by some (multicast?)
0807              * frames from other than current BSS, so just drop the
0808              * frames silently instead of filling system log with
0809              * these reports. */
0810             printk(KERN_DEBUG "%s: WEP decryption failed (not set)"
0811                    " (SA=%pM)\n",
0812                    local->dev->name, hdr->addr2);
0813 #endif
0814             local->comm_tallies.rx_discards_wep_undecryptable++;
0815             goto rx_dropped;
0816         }
0817     }
0818 
0819     if (type != IEEE80211_FTYPE_DATA) {
0820         if (type == IEEE80211_FTYPE_MGMT &&
0821             stype == IEEE80211_STYPE_AUTH &&
0822             fc & IEEE80211_FCTL_PROTECTED && local->host_decrypt &&
0823             (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
0824         {
0825             printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
0826                    "from %pM\n", dev->name, hdr->addr2);
0827             /* TODO: could inform hostapd about this so that it
0828              * could send auth failure report */
0829             goto rx_dropped;
0830         }
0831 
0832         if (hostap_rx_frame_mgmt(local, skb, rx_stats, type, stype))
0833             goto rx_dropped;
0834         else
0835             goto rx_exit;
0836     }
0837 
0838     /* Data frame - extract src/dst addresses */
0839     if (skb->len < IEEE80211_DATA_HDR3_LEN)
0840         goto rx_dropped;
0841 
0842     switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
0843     case IEEE80211_FCTL_FROMDS:
0844         memcpy(dst, hdr->addr1, ETH_ALEN);
0845         memcpy(src, hdr->addr3, ETH_ALEN);
0846         break;
0847     case IEEE80211_FCTL_TODS:
0848         memcpy(dst, hdr->addr3, ETH_ALEN);
0849         memcpy(src, hdr->addr2, ETH_ALEN);
0850         break;
0851     case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
0852         if (skb->len < IEEE80211_DATA_HDR4_LEN)
0853             goto rx_dropped;
0854         memcpy(dst, hdr->addr3, ETH_ALEN);
0855         memcpy(src, hdr->addr4, ETH_ALEN);
0856         break;
0857     default:
0858         memcpy(dst, hdr->addr1, ETH_ALEN);
0859         memcpy(src, hdr->addr2, ETH_ALEN);
0860         break;
0861     }
0862 
0863     if (hostap_rx_frame_wds(local, hdr, fc, &wds))
0864         goto rx_dropped;
0865     if (wds)
0866         skb->dev = dev = wds;
0867 
0868     if (local->iw_mode == IW_MODE_MASTER && !wds &&
0869         (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
0870         IEEE80211_FCTL_FROMDS &&
0871         local->stadev &&
0872         memcmp(hdr->addr2, local->assoc_ap_addr, ETH_ALEN) == 0) {
0873         /* Frame from BSSID of the AP for which we are a client */
0874         skb->dev = dev = local->stadev;
0875         from_assoc_ap = 1;
0876     }
0877 
0878     if ((local->iw_mode == IW_MODE_MASTER ||
0879          local->iw_mode == IW_MODE_REPEAT) &&
0880         !from_assoc_ap) {
0881         switch (hostap_handle_sta_rx(local, dev, skb, rx_stats,
0882                          wds != NULL)) {
0883         case AP_RX_CONTINUE_NOT_AUTHORIZED:
0884             frame_authorized = 0;
0885             break;
0886         case AP_RX_CONTINUE:
0887             frame_authorized = 1;
0888             break;
0889         case AP_RX_DROP:
0890             goto rx_dropped;
0891         case AP_RX_EXIT:
0892             goto rx_exit;
0893         }
0894     }
0895 
0896     /* Nullfunc frames may have PS-bit set, so they must be passed to
0897      * hostap_handle_sta_rx() before being dropped here. */
0898     if (stype != IEEE80211_STYPE_DATA &&
0899         stype != IEEE80211_STYPE_DATA_CFACK &&
0900         stype != IEEE80211_STYPE_DATA_CFPOLL &&
0901         stype != IEEE80211_STYPE_DATA_CFACKPOLL) {
0902         if (stype != IEEE80211_STYPE_NULLFUNC)
0903             printk(KERN_DEBUG "%s: RX: dropped data frame "
0904                    "with no data (type=0x%02x, subtype=0x%02x)\n",
0905                    dev->name, type >> 2, stype >> 4);
0906         goto rx_dropped;
0907     }
0908 
0909     /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
0910 
0911     if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
0912         (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
0913         goto rx_dropped;
0914     hdr = (struct ieee80211_hdr *) skb->data;
0915 
0916     /* skb: hdr + (possibly fragmented) plaintext payload */
0917 
0918     if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
0919         (frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
0920         int flen;
0921         struct sk_buff *frag_skb =
0922             prism2_frag_cache_get(local, hdr);
0923         if (!frag_skb) {
0924             printk(KERN_DEBUG "%s: Rx cannot get skb from "
0925                    "fragment cache (morefrag=%d seq=%u frag=%u)\n",
0926                    dev->name, (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
0927                    (sc & IEEE80211_SCTL_SEQ) >> 4, frag);
0928             goto rx_dropped;
0929         }
0930 
0931         flen = skb->len;
0932         if (frag != 0)
0933             flen -= hdrlen;
0934 
0935         if (frag_skb->tail + flen > frag_skb->end) {
0936             printk(KERN_WARNING "%s: host decrypted and "
0937                    "reassembled frame did not fit skb\n",
0938                    dev->name);
0939             prism2_frag_cache_invalidate(local, hdr);
0940             goto rx_dropped;
0941         }
0942 
0943         if (frag == 0) {
0944             /* copy first fragment (including full headers) into
0945              * beginning of the fragment cache skb */
0946             skb_copy_from_linear_data(skb, skb_put(frag_skb, flen),
0947                           flen);
0948         } else {
0949             /* append frame payload to the end of the fragment
0950              * cache skb */
0951             skb_copy_from_linear_data_offset(skb, hdrlen,
0952                              skb_put(frag_skb,
0953                                  flen), flen);
0954         }
0955         dev_kfree_skb(skb);
0956         skb = NULL;
0957 
0958         if (fc & IEEE80211_FCTL_MOREFRAGS) {
0959             /* more fragments expected - leave the skb in fragment
0960              * cache for now; it will be delivered to upper layers
0961              * after all fragments have been received */
0962             goto rx_exit;
0963         }
0964 
0965         /* this was the last fragment and the frame will be
0966          * delivered, so remove skb from fragment cache */
0967         skb = frag_skb;
0968         hdr = (struct ieee80211_hdr *) skb->data;
0969         prism2_frag_cache_invalidate(local, hdr);
0970     }
0971 
0972     /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
0973      * encrypted/authenticated */
0974 
0975     if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
0976         hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt))
0977         goto rx_dropped;
0978 
0979     hdr = (struct ieee80211_hdr *) skb->data;
0980     if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) {
0981         if (local->ieee_802_1x &&
0982             hostap_is_eapol_frame(local, skb)) {
0983             /* pass unencrypted EAPOL frames even if encryption is
0984              * configured */
0985             PDEBUG(DEBUG_EXTRA2, "%s: RX: IEEE 802.1X - passing "
0986                    "unencrypted EAPOL frame\n", local->dev->name);
0987         } else {
0988             printk(KERN_DEBUG "%s: encryption configured, but RX "
0989                    "frame not encrypted (SA=%pM)\n",
0990                    local->dev->name, hdr->addr2);
0991             goto rx_dropped;
0992         }
0993     }
0994 
0995     if (local->drop_unencrypted && !(fc & IEEE80211_FCTL_PROTECTED) &&
0996         !hostap_is_eapol_frame(local, skb)) {
0997         if (net_ratelimit()) {
0998             printk(KERN_DEBUG "%s: dropped unencrypted RX data "
0999                    "frame from %pM (drop_unencrypted=1)\n",
1000                    dev->name, hdr->addr2);
1001         }
1002         goto rx_dropped;
1003     }
1004 
1005     /* skb: hdr + (possible reassembled) full plaintext payload */
1006 
1007     payload = skb->data + hdrlen;
1008     ethertype = (payload[6] << 8) | payload[7];
1009 
1010     /* If IEEE 802.1X is used, check whether the port is authorized to send
1011      * the received frame. */
1012     if (local->ieee_802_1x && local->iw_mode == IW_MODE_MASTER) {
1013         if (ethertype == ETH_P_PAE) {
1014             PDEBUG(DEBUG_EXTRA2, "%s: RX: IEEE 802.1X frame\n",
1015                    dev->name);
1016             if (local->hostapd && local->apdev) {
1017                 /* Send IEEE 802.1X frames to the user
1018                  * space daemon for processing */
1019                 prism2_rx_80211(local->apdev, skb, rx_stats,
1020                         PRISM2_RX_MGMT);
1021                 local->apdevstats.rx_packets++;
1022                 local->apdevstats.rx_bytes += skb->len;
1023                 goto rx_exit;
1024             }
1025         } else if (!frame_authorized) {
1026             printk(KERN_DEBUG "%s: dropped frame from "
1027                    "unauthorized port (IEEE 802.1X): "
1028                    "ethertype=0x%04x\n",
1029                    dev->name, ethertype);
1030             goto rx_dropped;
1031         }
1032     }
1033 
1034     /* convert hdr + possible LLC headers into Ethernet header */
1035     if (skb->len - hdrlen >= 8 &&
1036         ((memcmp(payload, rfc1042_header, 6) == 0 &&
1037           ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
1038          memcmp(payload, bridge_tunnel_header, 6) == 0)) {
1039         /* remove RFC1042 or Bridge-Tunnel encapsulation and
1040          * replace EtherType */
1041         skb_pull(skb, hdrlen + 6);
1042         memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
1043         memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
1044     } else {
1045         __be16 len;
1046         /* Leave Ethernet header part of hdr and full payload */
1047         skb_pull(skb, hdrlen);
1048         len = htons(skb->len);
1049         memcpy(skb_push(skb, 2), &len, 2);
1050         memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
1051         memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
1052     }
1053 
1054     if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
1055             IEEE80211_FCTL_TODS) &&
1056         skb->len >= ETH_HLEN + ETH_ALEN) {
1057         /* Non-standard frame: get addr4 from its bogus location after
1058          * the payload */
1059         skb_copy_from_linear_data_offset(skb, skb->len - ETH_ALEN,
1060                          skb->data + ETH_ALEN,
1061                          ETH_ALEN);
1062         skb_trim(skb, skb->len - ETH_ALEN);
1063     }
1064 
1065     dev->stats.rx_packets++;
1066     dev->stats.rx_bytes += skb->len;
1067 
1068     if (local->iw_mode == IW_MODE_MASTER && !wds &&
1069         local->ap->bridge_packets) {
1070         if (dst[0] & 0x01) {
1071             /* copy multicast frame both to the higher layers and
1072              * to the wireless media */
1073             local->ap->bridged_multicast++;
1074             skb2 = skb_clone(skb, GFP_ATOMIC);
1075             if (skb2 == NULL)
1076                 printk(KERN_DEBUG "%s: skb_clone failed for "
1077                        "multicast frame\n", dev->name);
1078         } else if (hostap_is_sta_authorized(local->ap, dst)) {
1079             /* send frame directly to the associated STA using
1080              * wireless media and not passing to higher layers */
1081             local->ap->bridged_unicast++;
1082             skb2 = skb;
1083             skb = NULL;
1084         }
1085     }
1086 
1087     if (skb2 != NULL) {
1088         /* send to wireless media */
1089         skb2->dev = dev;
1090         skb2->protocol = cpu_to_be16(ETH_P_802_3);
1091         skb_reset_mac_header(skb2);
1092         skb_reset_network_header(skb2);
1093         /* skb2->network_header += ETH_HLEN; */
1094         dev_queue_xmit(skb2);
1095     }
1096 
1097     if (skb) {
1098         skb->protocol = eth_type_trans(skb, dev);
1099         memset(skb->cb, 0, sizeof(skb->cb));
1100         netif_rx(skb);
1101     }
1102 
1103  rx_exit:
1104     if (sta)
1105         hostap_handle_sta_release(sta);
1106     return;
1107 
1108  rx_dropped:
1109     dev_kfree_skb(skb);
1110 
1111     dev->stats.rx_dropped++;
1112     goto rx_exit;
1113 }
1114 
1115 
1116 EXPORT_SYMBOL(hostap_80211_rx);