📄 rx.c
字号:
break; case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): /* RA TA DA SA */ memcpy(dst, hdr->addr3, ETH_ALEN); memcpy(src, hdr->addr4, ETH_ALEN); if (unlikely(sdata->type != IEEE80211_IF_TYPE_WDS)) { if (net_ratelimit()) printk(KERN_DEBUG "%s: dropped FromDS&ToDS " "frame (RA=%s TA=%s DA=%s SA=%s)\n", rx->dev->name, print_mac(mac, hdr->addr1), print_mac(mac2, hdr->addr2), print_mac(mac3, hdr->addr3), print_mac(mac4, hdr->addr4)); return TXRX_DROP; } break; case IEEE80211_FCTL_FROMDS: /* DA BSSID SA */ memcpy(dst, hdr->addr1, ETH_ALEN); memcpy(src, hdr->addr3, ETH_ALEN); if (sdata->type != IEEE80211_IF_TYPE_STA || (is_multicast_ether_addr(dst) && !compare_ether_addr(src, dev->dev_addr))) return TXRX_DROP; break; case 0: /* DA SA BSSID */ memcpy(dst, hdr->addr1, ETH_ALEN); memcpy(src, hdr->addr2, ETH_ALEN); if (sdata->type != IEEE80211_IF_TYPE_IBSS) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: dropped IBSS frame " "(DA=%s SA=%s BSSID=%s)\n", dev->name, print_mac(mac, hdr->addr1), print_mac(mac2, hdr->addr2), print_mac(mac3, hdr->addr3)); } return TXRX_DROP; } break; } payload = skb->data + hdrlen; if (unlikely(skb->len - hdrlen < 8)) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: RX too short data frame " "payload\n", dev->name); } return TXRX_DROP; } ethertype = (payload[6] << 8) | payload[7]; if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || compare_ether_addr(payload, bridge_tunnel_header) == 0)) { /* remove RFC1042 or Bridge-Tunnel encapsulation and * replace EtherType */ skb_pull(skb, hdrlen + 6); memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); } else { struct ethhdr *ehdr; __be16 len; skb_pull(skb, hdrlen); len = htons(skb->len); ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr)); memcpy(ehdr->h_dest, dst, ETH_ALEN); memcpy(ehdr->h_source, src, ETH_ALEN); ehdr->h_proto = len; } skb->dev = dev; skb2 = NULL; dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP || sdata->type == IEEE80211_IF_TYPE_VLAN) && (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) { if (is_multicast_ether_addr(skb->data)) { /* send multicast frames both to higher layers in * local net stack and back to the wireless media */ skb2 = skb_copy(skb, GFP_ATOMIC); if (!skb2 && net_ratelimit()) printk(KERN_DEBUG "%s: failed to clone " "multicast frame\n", dev->name); } else { struct sta_info *dsta; dsta = sta_info_get(local, skb->data); if (dsta && !dsta->dev) { if (net_ratelimit()) printk(KERN_DEBUG "Station with null " "dev structure!\n"); } else if (dsta && dsta->dev == dev) { /* Destination station is associated to this * AP, so send the frame directly to it and * do not pass the frame to local net stack. */ skb2 = skb; skb = NULL; } if (dsta) sta_info_put(dsta); } } if (skb) { /* deliver to local stack */ skb->protocol = eth_type_trans(skb, dev); memset(skb->cb, 0, sizeof(skb->cb)); netif_rx(skb); } if (skb2) { /* send to wireless media */ skb2->protocol = __constant_htons(ETH_P_802_3); skb_set_network_header(skb2, 0); skb_set_mac_header(skb2, 0); dev_queue_xmit(skb2); } return TXRX_QUEUED;}static ieee80211_txrx_resultieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx){ struct ieee80211_sub_if_data *sdata; if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) return TXRX_DROP; sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); if ((sdata->type == IEEE80211_IF_TYPE_STA || sdata->type == IEEE80211_IF_TYPE_IBSS) && !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status); else return TXRX_DROP; return TXRX_QUEUED;}static inline ieee80211_txrx_result __ieee80211_invoke_rx_handlers( struct ieee80211_local *local, ieee80211_rx_handler *handlers, struct ieee80211_txrx_data *rx, struct sta_info *sta){ ieee80211_rx_handler *handler; ieee80211_txrx_result res = TXRX_DROP; for (handler = handlers; *handler != NULL; handler++) { res = (*handler)(rx); switch (res) { case TXRX_CONTINUE: continue; case TXRX_DROP: I802_DEBUG_INC(local->rx_handlers_drop); if (sta) sta->rx_dropped++; break; case TXRX_QUEUED: I802_DEBUG_INC(local->rx_handlers_queued); break; } break; } if (res == TXRX_DROP) dev_kfree_skb(rx->skb); return res;}static inline void ieee80211_invoke_rx_handlers(struct ieee80211_local *local, ieee80211_rx_handler *handlers, struct ieee80211_txrx_data *rx, struct sta_info *sta){ if (__ieee80211_invoke_rx_handlers(local, handlers, rx, sta) == TXRX_CONTINUE) dev_kfree_skb(rx->skb);}static void ieee80211_rx_michael_mic_report(struct net_device *dev, struct ieee80211_hdr *hdr, struct sta_info *sta, struct ieee80211_txrx_data *rx){ int keyidx, hdrlen; DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); hdrlen = ieee80211_get_hdrlen_from_skb(rx->skb); if (rx->skb->len >= hdrlen + 4) keyidx = rx->skb->data[hdrlen + 3] >> 6; else keyidx = -1; if (net_ratelimit()) printk(KERN_DEBUG "%s: TKIP hwaccel reported Michael MIC " "failure from %s to %s keyidx=%d\n", dev->name, print_mac(mac, hdr->addr2), print_mac(mac2, hdr->addr1), keyidx); if (!sta) { /* * Some hardware seem to generate incorrect Michael MIC * reports; ignore them to avoid triggering countermeasures. */ if (net_ratelimit()) printk(KERN_DEBUG "%s: ignored spurious Michael MIC " "error for unknown address %s\n", dev->name, print_mac(mac, hdr->addr2)); goto ignore; } if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) { if (net_ratelimit()) printk(KERN_DEBUG "%s: ignored spurious Michael MIC " "error for a frame with no PROTECTED flag (src " "%s)\n", dev->name, print_mac(mac, hdr->addr2)); goto ignore; } if (rx->sdata->type == IEEE80211_IF_TYPE_AP && keyidx) { /* * APs with pairwise keys should never receive Michael MIC * errors for non-zero keyidx because these are reserved for * group keys and only the AP is sending real multicast * frames in the BSS. */ if (net_ratelimit()) printk(KERN_DEBUG "%s: ignored Michael MIC error for " "a frame with non-zero keyidx (%d)" " (src %s)\n", dev->name, keyidx, print_mac(mac, hdr->addr2)); goto ignore; } if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA && ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) { if (net_ratelimit()) printk(KERN_DEBUG "%s: ignored spurious Michael MIC " "error for a frame that cannot be encrypted " "(fc=0x%04x) (src %s)\n", dev->name, rx->fc, print_mac(mac, hdr->addr2)); goto ignore; } mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr); ignore: dev_kfree_skb(rx->skb); rx->skb = NULL;}ieee80211_rx_handler ieee80211_rx_handlers[] ={ ieee80211_rx_h_if_stats, ieee80211_rx_h_passive_scan, ieee80211_rx_h_check, ieee80211_rx_h_decrypt, ieee80211_rx_h_sta_process, ieee80211_rx_h_defragment, ieee80211_rx_h_ps_poll, ieee80211_rx_h_michael_mic_verify, /* this must be after decryption - so header is counted in MPDU mic * must be before pae and data, so QOS_DATA format frames * are not passed to user space by these functions */ ieee80211_rx_h_remove_qos_control, ieee80211_rx_h_802_1x_pae, ieee80211_rx_h_drop_unencrypted, ieee80211_rx_h_data, ieee80211_rx_h_mgmt, NULL};/* main receive path */static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, u8 *bssid, struct ieee80211_txrx_data *rx, struct ieee80211_hdr *hdr){ int multicast = is_multicast_ether_addr(hdr->addr1); switch (sdata->type) { case IEEE80211_IF_TYPE_STA: if (!bssid) return 0; if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) return 0; rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; } else if (!multicast && compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { if (!(sdata->dev->flags & IFF_PROMISC)) return 0; rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; } break; case IEEE80211_IF_TYPE_IBSS: if (!bssid) return 0; if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) return 0; rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; } else if (!multicast && compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { if (!(sdata->dev->flags & IFF_PROMISC)) return 0; rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; } else if (!rx->sta) rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb, bssid, hdr->addr2); break; case IEEE80211_IF_TYPE_VLAN: case IEEE80211_IF_TYPE_AP: if (!bssid) { if (compare_ether_addr(sdata->dev->dev_addr, hdr->addr1)) return 0; } else if (!ieee80211_bssid_match(bssid, sdata->dev->dev_addr)) { if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) return 0; rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; } if (sdata->dev == sdata->local->mdev && !(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) /* do not receive anything via * master device when not scanning */ return 0; break; case IEEE80211_IF_TYPE_WDS: if (bssid || (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) return 0; if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) return 0; break; case IEEE80211_IF_TYPE_MNTR: /* take everything */ break; case IEEE80211_IF_TYPE_INVALID: /* should never get here */ WARN_ON(1); break; } return 1;}/* * This is the receive path handler. It is called by a low level driver when an * 802.11 MPDU is received from the hardware. */void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_rx_status *status){ struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; struct sta_info *sta; struct ieee80211_hdr *hdr; struct ieee80211_txrx_data rx; u16 type; int prepres; struct ieee80211_sub_if_data *prev = NULL; struct sk_buff *skb_new; u8 *bssid; /* * key references and virtual interfaces are protected using RCU * and this requires that we are in a read-side RCU section during * receive processing */ rcu_read_lock(); /* * Frames with failed FCS/PLCP checksum are not returned, * all other frames are returned without radiotap header * if it was previously present. * Also, frames with less than 16 bytes are dropped. */ skb = ieee80211_rx_monitor(local, skb, status); if (!skb) { rcu_read_unlock(); return; } hdr = (struct ieee80211_hdr *) skb->data; memset(&rx, 0, sizeof(rx)); rx.skb = skb; rx.local = local; rx.u.rx.status = status; rx.fc = le16_to_cpu(hdr->frame_control); type = rx.fc & IEEE80211_FCTL_FTYPE; if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT) local->dot11ReceivedFragmentCount++; sta = rx.sta = sta_info_get(local, hdr->addr2); if (sta) { rx.dev = rx.sta->dev; rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev); } if ((status->flag & RX_FLAG_MMIC_ERROR)) { ieee80211_rx_michael_mic_report(local->mdev, hdr, sta, &rx); goto end; } if (unlikely(local->sta_scanning)) rx.flags |= IEEE80211_TXRXD_RXIN_SCAN; if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx, sta) != TXRX_CONTINUE) goto end; skb = rx.skb; if (sta && !(sta->flags & (WLAN_STA_WDS | WLAN_STA_ASSOC_AP)) && !atomic_read(&local->iff_promiscs) && !is_multicast_ether_addr(hdr->addr1)) { rx.flags |= IEEE80211_TXRXD_RXRA_MATCH; ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx, rx.sta); sta_info_put(sta); rcu_read_unlock(); return; } bssid = ieee80211_get_bssid(hdr, skb->len); list_for_each_entry_rcu(sdata, &local->interfaces, list) { if (!netif_running(sdata->dev)) continue; if (sdata->type == IEEE80211_IF_TYPE_MNTR) continue; rx.flags |= IEEE80211_TXRXD_RXRA_MATCH; prepres = prepare_for_handlers(sdata, bssid, &rx, hdr); /* prepare_for_handlers can change sta */ sta = rx.sta; if (!prepres) continue; /* * frame is destined for this interface, but if it's not * also for the previous one we handle that after the * loop to avoid copying the SKB once too much */ if (!prev) { prev = sdata; continue; } /* * frame was destined for the previous interface * so invoke RX handlers for it */ skb_new = skb_copy(skb, GFP_ATOMIC); if (!skb_new) { if (net_ratelimit()) printk(KERN_DEBUG "%s: failed to copy " "multicast frame for %s", wiphy_name(local->hw.wiphy), prev->dev->name); continue; } rx.skb = skb_new; rx.dev = prev->dev; rx.sdata = prev; ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx, sta); prev = sdata; } if (prev) { rx.skb = skb; rx.dev = prev->dev; rx.sdata = prev; ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx, sta); } else dev_kfree_skb(skb); end: rcu_read_unlock(); if (sta) sta_info_put(sta);}EXPORT_SYMBOL(__ieee80211_rx);/* This is a version of the rx handler that can be called from hard irq * context. Post the skb on the queue and schedule the tasklet */void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_rx_status *status){ struct ieee80211_local *local = hw_to_local(hw); BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)); skb->dev = local->mdev; /* copy status into skb->cb for use by tasklet */ memcpy(skb->cb, status, sizeof(*status)); skb->pkt_type = IEEE80211_RX_MSG; skb_queue_tail(&local->skb_queue, skb); tasklet_schedule(&local->tasklet);}EXPORT_SYMBOL(ieee80211_rx_irqsafe);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -