📄 ieee80211_rx.c
字号:
return 1; }#endif#ifndef CONFIG_IEEE80211_NOWEP if (ieee->host_decrypt) { int idx = 0; if (skb->len >= hdrlen + 3) idx = skb->data[hdrlen + 3] >> 6; crypt = ieee->crypt[idx];#ifdef NOT_YET sta = NULL; /* Use station specific key to override default keys if the * receiver address is a unicast address ("individual RA"). If * bcrx_sta_key parameter is set, station specific key is used * even with broad/multicast targets (this is against IEEE * 802.11, but makes it easier to use different keys with * stations that do not support WEP key mapping). */ if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) (void) hostap_handle_sta_crypto(local, hdr, &crypt, &sta);#endif /* allow NULL decrypt to indicate an station specific override * for default encryption */ if (crypt && (crypt->ops == NULL || crypt->ops->decrypt_mpdu == NULL)) crypt = NULL; if (!crypt && (fc & IEEE802_11_FCTL_WEP)) {#if 0 /* This seems to be triggered by some (multicast?) * frames from other than current BSS, so just drop the * frames silently instead of filling system log with * these reports. */ printk(KERN_DEBUG "%s: WEP decryption failed (not set)" " (SA=" MACSTR ")\n", ieee->dev->name, MAC2STR(hdr->addr2));#endif ieee->ieee_stats.rx_discards_wep_undecryptable++; goto rx_dropped; } }#endif /* CONFIG_IEEE80211_NOWEP */ if (type != WLAN_FC_TYPE_DATA) { if (type == WLAN_FC_TYPE_MGMT){ #ifndef CONFIG_IEEE80211_NOWEP if(fc & WLAN_FC_ISWEP && ieee->host_decrypt && ieee80211_rx_frame_decrypt(ieee,skb,crypt)){ printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth " "from " MACSTR "\n", dev->name, MAC2STR(hdr->addr2)); /* TODO: could inform hostapd about this so that it * could send auth failure report */ goto rx_dropped; } #endif err = ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype); if (err<0) goto rx_dropped; if (err==0){ ieee->stats.rx_bytes+=skb->len; ieee->stats.rx_packets++; } dev_kfree_skb_any(skb); goto rx_exit; } } /* Data frame - extract src/dst addresses */ if (skb->len < IEEE80211_DATA_HDR3_LEN) goto rx_dropped; switch (fc & (IEEE802_11_FCTL_FROMDS | IEEE802_11_FCTL_TODS)) { case IEEE802_11_FCTL_FROMDS: memcpy(dst, hdr->addr1, ETH_ALEN); memcpy(src, hdr->addr3, ETH_ALEN); break; case IEEE802_11_FCTL_TODS: memcpy(dst, hdr->addr3, ETH_ALEN); memcpy(src, hdr->addr2, ETH_ALEN); break; case IEEE802_11_FCTL_FROMDS | IEEE802_11_FCTL_TODS: if (skb->len < IEEE80211_DATA_HDR4_LEN) goto rx_dropped; memcpy(dst, hdr->addr3, ETH_ALEN); memcpy(src, hdr->addr4, ETH_ALEN); break; case 0: memcpy(dst, hdr->addr1, ETH_ALEN); memcpy(src, hdr->addr2, ETH_ALEN); break; } //IEEE80211DMESG("Frame from "MACSTR,MAC2STR(src));#ifdef NOT_YET if (hostap_rx_frame_wds(ieee, hdr, fc, &wds)) goto rx_dropped; if (wds) { skb->dev = dev = wds; stats = hostap_get_stats(dev); } if (ieee->iw_mode == IW_MODE_MASTER && !wds && (fc & (IEEE802_11_FCTL_TODS | IEEE802_11_FCTL_FROMDS)) == IEEE802_11_FCTL_FROMDS && ieee->stadev && memcmp(hdr->addr2, ieee->assoc_ap_addr, ETH_ALEN) == 0) { /* Frame from BSSID of the AP for which we are a client */ skb->dev = dev = ieee->stadev; stats = hostap_get_stats(dev); from_assoc_ap = 1; }#endif dev->last_rx = jiffies;#ifdef NOT_YET if ((ieee->iw_mode == IW_MODE_MASTER || ieee->iw_mode == IW_MODE_REPEAT) && !from_assoc_ap) { switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats, wds != NULL)) { case AP_RX_CONTINUE_NOT_AUTHORIZED: frame_authorized = 0; break; case AP_RX_CONTINUE: frame_authorized = 1; break; case AP_RX_DROP: goto rx_dropped; case AP_RX_EXIT: goto rx_exit; } }#endif /* Nullfunc frames may have PS-bit set, so they must be passed to * hostap_handle_sta_rx() before being dropped here. */ if (stype != IEEE802_11_STYPE_DATA && stype != IEEE802_11_STYPE_DATA_CFACK && stype != IEEE802_11_STYPE_DATA_CFPOLL && stype != IEEE802_11_STYPE_DATA_CFACKPOLL) { if (stype != IEEE802_11_STYPE_NULLFUNC) printk(KERN_DEBUG "%s: RX: dropped data frame " "with no data (type=0x%02x, subtype=0x%02x, len=%d)\n", dev->name, type, stype, skb->len); goto rx_dropped; } /* skb: hdr + (possibly fragmented, possibly encrypted) payload */#ifndef CONFIG_IEEE80211_NOWEP if (ieee->host_decrypt && (fc & IEEE802_11_FCTL_WEP) && (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) goto rx_dropped;#endif hdr = (struct ieee80211_hdr *) skb->data; /* skb: hdr + (possibly fragmented) plaintext payload */ // PR: FIXME: hostap has additional conditions in the "if" below: // ieee->host_decrypt && (fc & IEEE802_11_FCTL_WEP) && if ((frag != 0 || (fc & IEEE802_11_FCTL_MOREFRAGS))) { int flen; struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr); if (!frag_skb) { printk(KERN_DEBUG "%s: RX: cannot get skb from " "fragment cache (morefrag=%d seq=%u frag=%u)\n", dev->name, (fc & IEEE802_11_FCTL_MOREFRAGS) != 0, WLAN_GET_SEQ_SEQ(sc), frag); goto rx_dropped; } flen = skb->len; if (frag != 0) flen -= hdrlen; if (frag_skb->tail + flen > frag_skb->end) { printk(KERN_WARNING "%s: host decrypted and " "reassembled frame did not fit skb\n", dev->name); ieee80211_frag_cache_invalidate(ieee, hdr); goto rx_dropped; } if (frag == 0) { /* copy first fragment (including full headers) into * beginning of the fragment cache skb */ memcpy(skb_put(frag_skb, flen), skb->data, flen); } else { /* append frame payload to the end of the fragment * cache skb */ memcpy(skb_put(frag_skb, flen), skb->data + hdrlen, flen); } dev_kfree_skb_any(skb); skb = NULL; if (fc & IEEE802_11_FCTL_MOREFRAGS) { /* more fragments expected - leave the skb in fragment * cache for now; it will be delivered to upper layers * after all fragments have been received */ goto rx_exit; } /* 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; ieee80211_frag_cache_invalidate(ieee, hdr); } /* skb: hdr + (possible reassembled) full MSDU payload; possibly still * encrypted/authenticated */#ifndef CONFIG_IEEE80211_NOWEP if (ieee->host_decrypt && (fc & IEEE802_11_FCTL_WEP) && ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) goto rx_dropped; hdr = (struct ieee80211_hdr *) skb->data; if (crypt && !(fc & IEEE802_11_FCTL_WEP) && !ieee->open_wep) { if (/*ieee->ieee_802_1x &&*/ ieee80211_is_eapol_frame(ieee, skb)) { /* pass unencrypted EAPOL frames even if encryption is * configured */ printk(KERN_DEBUG "%s: RX: IEEE 802.1X - passing " "unencrypted EAPOL frame\n", ieee->dev->name); } else { printk(KERN_DEBUG "%s: encryption configured, but RX " "frame not encrypted (SA=" MACSTR ")\n", ieee->dev->name, MAC2STR(hdr->addr2)); goto rx_dropped; } } if (/*ieee->drop_unencrypted*/ crypt && !(fc & IEEE802_11_FCTL_WEP) && !ieee->open_wep && !ieee80211_is_eapol_frame(ieee, skb)) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: dropped unencrypted RX data " "frame from " MACSTR " (drop_unencrypted=1)\n", dev->name, MAC2STR(hdr->addr2)); } goto rx_dropped; }#endif /* CONFIG_IEEE80211_NOWEP */ /* skb: hdr + (possible reassembled) full plaintext payload */ payload = skb->data + hdrlen; ethertype = (payload[6] << 8) | payload[7];#ifdef NOT_YET /* If IEEE 802.1X is used, check whether the port is authorized to send * the received frame. */ if (ieee->ieee_802_1x && ieee->iw_mode == IW_MODE_MASTER) { if (ethertype == ETH_P_PAE) { printk(KERN_DEBUG "%s: RX: IEEE 802.1X frame\n", dev->name); if (ieee->hostapd && ieee->apdev) { /* Send IEEE 802.1X frames to the user * space daemon for processing */ prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT); ieee->apdevstats.rx_packets++; ieee->apdevstats.rx_bytes += skb->len; goto rx_exit; } } else if (!frame_authorized) { printk(KERN_DEBUG "%s: dropped frame from " "unauthorized port (IEEE 802.1X): " "ethertype=0x%04x\n", dev->name, ethertype); goto rx_dropped; } }#endif /* convert hdr + possible LLC headers into Ethernet header */ if (skb->len - hdrlen >= 8 && ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 && ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) { /* remove RFC1042 or Bridge-Tunnel encapsulation and * replace EtherType */ skb_pull(skb, hdrlen + SNAP_SIZE); memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); } else { u16 len; /* Leave Ethernet header part of hdr and full payload */ skb_pull(skb, hdrlen); len = htons(skb->len); memcpy(skb_push(skb, 2), &len, 2); memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); }#ifdef NOT_YET if (wds && ((fc & (IEEE802_11_FCTL_TODS | IEEE802_11_FCTL_FROMDS)) == IEEE802_11_FCTL_TODS) && skb->len >= ETH_HLEN + ETH_ALEN) { /* Non-standard frame: get addr4 from its bogus location after * the payload */ memcpy(skb->data + ETH_ALEN, skb->data + skb->len - ETH_ALEN, ETH_ALEN); skb_trim(skb, skb->len - ETH_ALEN); }#endif stats->rx_packets++; stats->rx_bytes += skb->len; skb2=NULL; /* here, by default, the frame will be sent on the * ethernet media. If in master mode we have to check * if we need to send back on the wireless media or both */ if (ieee->iw_mode == IW_MODE_MASTER) { spin_lock_irqsave(&ieee->lock,flags); unknow = (!is_associated(ieee,dst) && !is_bridged(ieee,dst)); //if (memcmp(ieee->dev->dev_addr ,dst,ETH_ALEN)==0) unknow = 0; if (is_broadcast(dst) || is_multicast(dst) || unknow){ /* enable sending also to wireless media*/ skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2 == NULL){ printk(KERN_DEBUG "%s: skb_clone failed for " "multicast frame\n", dev->name); } }else if (is_associated(ieee,dst)){ /* send only to the wireless media */ skb2=skb; skb=NULL; }#ifdef IEEE80211_DEBUG_MASTER_MODE IEEE80211DMESG("adr "MACSTR" assoc: %d unk:%d", MAC2STR(dst),is_associated(ieee,dst),unknow);#endif spin_unlock_irqrestore(&ieee->lock,flags); } 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; dev_queue_xmit(skb2); } if (skb) { skb->protocol = eth_type_trans(skb, dev); memset(skb->cb, 0, sizeof(skb->cb)); skb->dev = dev; skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ netif_rx(skb); } rx_exit:#ifdef NOT_YET if (sta) hostap_handle_sta_release(sta);#endif return 1; rx_dropped: stats->rx_dropped++; /* Returning 0 indicates to caller that we have not handled the SKB-- * so it is still allocated and can be used again by underlying * hardware as a DMA target */ return 0;}EXPORT_SYMBOL(ieee80211_r8180_rx);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -