📄 ieee80211_rx.c
字号:
network->listen_interval = le16_to_cpu(frame->status); memcpy(network->bssid, frame->header.addr3, ETH_ALEN); network->capability = le16_to_cpu(frame->capability); network->last_scanned = jiffies; network->rates_len = network->rates_ex_len = 0; network->last_associate = 0; network->ssid_len = 0; network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0; if (stats->freq == IEEE80211_52GHZ_BAND) { /* for A band (No DS info) */ network->channel = stats->received_channel; } else network->flags |= NETWORK_HAS_CCK; network->wpa_ie_len = 0; network->rsn_ie_len = 0; if (ieee80211_parse_info_param (frame->info_element, stats->len - sizeof(*frame), network)) return 1; network->mode = 0; if (stats->freq == IEEE80211_52GHZ_BAND) network->mode = IEEE_A; else { if (network->flags & NETWORK_HAS_OFDM) network->mode |= IEEE_G; if (network->flags & NETWORK_HAS_CCK) network->mode |= IEEE_B; } if (ieee80211_is_empty_essid(network->ssid, network->ssid_len)) network->flags |= NETWORK_EMPTY_ESSID; memcpy(&network->stats, stats, sizeof(network->stats)); if (ieee->handle_assoc_response != NULL) ieee->handle_assoc_response(dev, frame, network); return 0;}/***************************************************/static int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response *beacon, struct ieee80211_network *network, struct ieee80211_rx_stats *stats){ DECLARE_MAC_BUF(mac); network->qos_data.active = 0; network->qos_data.supported = 0; network->qos_data.param_count = 0; network->qos_data.old_param_count = 0; /* Pull out fixed field data */ memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); network->capability = le16_to_cpu(beacon->capability); network->last_scanned = jiffies; network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]); network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]); network->beacon_interval = le16_to_cpu(beacon->beacon_interval); /* Where to pull this? beacon->listen_interval; */ network->listen_interval = 0x0A; network->rates_len = network->rates_ex_len = 0; network->last_associate = 0; network->ssid_len = 0; network->flags = 0; network->atim_window = 0; network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0; if (stats->freq == IEEE80211_52GHZ_BAND) { /* for A band (No DS info) */ network->channel = stats->received_channel; } else network->flags |= NETWORK_HAS_CCK; network->wpa_ie_len = 0; network->rsn_ie_len = 0; if (ieee80211_parse_info_param (beacon->info_element, stats->len - sizeof(*beacon), network)) return 1; network->mode = 0; if (stats->freq == IEEE80211_52GHZ_BAND) network->mode = IEEE_A; else { if (network->flags & NETWORK_HAS_OFDM) network->mode |= IEEE_G; if (network->flags & NETWORK_HAS_CCK) network->mode |= IEEE_B; } if (network->mode == 0) { IEEE80211_DEBUG_SCAN("Filtered out '%s (%s)' " "network.\n", escape_essid(network->ssid, network->ssid_len), print_mac(mac, network->bssid)); return 1; } if (ieee80211_is_empty_essid(network->ssid, network->ssid_len)) network->flags |= NETWORK_EMPTY_ESSID; memcpy(&network->stats, stats, sizeof(network->stats)); return 0;}static inline int is_same_network(struct ieee80211_network *src, struct ieee80211_network *dst){ /* A network is only a duplicate if the channel, BSSID, and ESSID * all match. We treat all <hidden> with the same BSSID and channel * as one network */ return ((src->ssid_len == dst->ssid_len) && (src->channel == dst->channel) && !compare_ether_addr(src->bssid, dst->bssid) && !memcmp(src->ssid, dst->ssid, src->ssid_len));}static void update_network(struct ieee80211_network *dst, struct ieee80211_network *src){ int qos_active; u8 old_param; DECLARE_MAC_BUF(mac); ieee80211_network_reset(dst); dst->ibss_dfs = src->ibss_dfs; /* We only update the statistics if they were created by receiving * the network information on the actual channel the network is on. * * This keeps beacons received on neighbor channels from bringing * down the signal level of an AP. */ if (dst->channel == src->stats.received_channel) memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); else IEEE80211_DEBUG_SCAN("Network %s info received " "off channel (%d vs. %d)\n", print_mac(mac, src->bssid), dst->channel, src->stats.received_channel); dst->capability = src->capability; memcpy(dst->rates, src->rates, src->rates_len); dst->rates_len = src->rates_len; memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); dst->rates_ex_len = src->rates_ex_len; dst->mode = src->mode; dst->flags = src->flags; dst->time_stamp[0] = src->time_stamp[0]; dst->time_stamp[1] = src->time_stamp[1]; dst->beacon_interval = src->beacon_interval; dst->listen_interval = src->listen_interval; dst->atim_window = src->atim_window; dst->erp_value = src->erp_value; dst->tim = src->tim; memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); dst->wpa_ie_len = src->wpa_ie_len; memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len); dst->rsn_ie_len = src->rsn_ie_len; dst->last_scanned = jiffies; qos_active = src->qos_data.active; old_param = dst->qos_data.old_param_count; if (dst->flags & NETWORK_HAS_QOS_MASK) memcpy(&dst->qos_data, &src->qos_data, sizeof(struct ieee80211_qos_data)); else { dst->qos_data.supported = src->qos_data.supported; dst->qos_data.param_count = src->qos_data.param_count; } if (dst->qos_data.supported == 1) { if (dst->ssid_len) IEEE80211_DEBUG_QOS ("QoS the network %s is QoS supported\n", dst->ssid); else IEEE80211_DEBUG_QOS ("QoS the network is QoS supported\n"); } dst->qos_data.active = qos_active; dst->qos_data.old_param_count = old_param; /* dst->last_associate is not overwritten */}static inline int is_beacon(__le16 fc){ return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);}static void ieee80211_process_probe_response(struct ieee80211_device *ieee, struct ieee80211_probe_response *beacon, struct ieee80211_rx_stats *stats){ struct net_device *dev = ieee->dev; struct ieee80211_network network = { .ibss_dfs = NULL, }; struct ieee80211_network *target; struct ieee80211_network *oldest = NULL;#ifdef CONFIG_IEEE80211_DEBUG struct ieee80211_info_element *info_element = beacon->info_element;#endif unsigned long flags; DECLARE_MAC_BUF(mac); IEEE80211_DEBUG_SCAN("'%s' (%s" "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", escape_essid(info_element->data, info_element->len), print_mac(mac, beacon->header.addr3), (beacon->capability & (1 << 0xf)) ? '1' : '0', (beacon->capability & (1 << 0xe)) ? '1' : '0', (beacon->capability & (1 << 0xd)) ? '1' : '0', (beacon->capability & (1 << 0xc)) ? '1' : '0', (beacon->capability & (1 << 0xb)) ? '1' : '0', (beacon->capability & (1 << 0xa)) ? '1' : '0', (beacon->capability & (1 << 0x9)) ? '1' : '0', (beacon->capability & (1 << 0x8)) ? '1' : '0', (beacon->capability & (1 << 0x7)) ? '1' : '0', (beacon->capability & (1 << 0x6)) ? '1' : '0', (beacon->capability & (1 << 0x5)) ? '1' : '0', (beacon->capability & (1 << 0x4)) ? '1' : '0', (beacon->capability & (1 << 0x3)) ? '1' : '0', (beacon->capability & (1 << 0x2)) ? '1' : '0', (beacon->capability & (1 << 0x1)) ? '1' : '0', (beacon->capability & (1 << 0x0)) ? '1' : '0'); if (ieee80211_network_init(ieee, beacon, &network, stats)) { IEEE80211_DEBUG_SCAN("Dropped '%s' (%s) via %s.\n", escape_essid(info_element->data, info_element->len), print_mac(mac, beacon->header.addr3), is_beacon(beacon->header.frame_ctl) ? "BEACON" : "PROBE RESPONSE"); return; } /* The network parsed correctly -- so now we scan our known networks * to see if we can find it in our list. * * NOTE: This search is definitely not optimized. Once its doing * the "right thing" we'll optimize it for efficiency if * necessary */ /* Search for this entry in the list and update it if it is * already there. */ spin_lock_irqsave(&ieee->lock, flags); list_for_each_entry(target, &ieee->network_list, list) { if (is_same_network(target, &network)) break; if ((oldest == NULL) || (target->last_scanned < oldest->last_scanned)) oldest = target; } /* If we didn't find a match, then get a new network slot to initialize * with this beacon's information */ if (&target->list == &ieee->network_list) { if (list_empty(&ieee->network_free_list)) { /* If there are no more slots, expire the oldest */ list_del(&oldest->list); target = oldest; IEEE80211_DEBUG_SCAN("Expired '%s' (%s) from " "network list.\n", escape_essid(target->ssid, target->ssid_len), print_mac(mac, target->bssid)); ieee80211_network_reset(target); } else { /* Otherwise just pull from the free list */ target = list_entry(ieee->network_free_list.next, struct ieee80211_network, list); list_del(ieee->network_free_list.next); }#ifdef CONFIG_IEEE80211_DEBUG IEEE80211_DEBUG_SCAN("Adding '%s' (%s) via %s.\n", escape_essid(network.ssid, network.ssid_len), print_mac(mac, network.bssid), is_beacon(beacon->header.frame_ctl) ? "BEACON" : "PROBE RESPONSE");#endif memcpy(target, &network, sizeof(*target)); network.ibss_dfs = NULL; list_add_tail(&target->list, &ieee->network_list); } else { IEEE80211_DEBUG_SCAN("Updating '%s' (%s) via %s.\n", escape_essid(target->ssid, target->ssid_len), print_mac(mac, target->bssid), is_beacon(beacon->header.frame_ctl) ? "BEACON" : "PROBE RESPONSE"); update_network(target, &network); network.ibss_dfs = NULL; } spin_unlock_irqrestore(&ieee->lock, flags); if (is_beacon(beacon->header.frame_ctl)) { if (ieee->handle_beacon != NULL) ieee->handle_beacon(dev, beacon, target); } else { if (ieee->handle_probe_response != NULL) ieee->handle_probe_response(dev, beacon, target); }}void ieee80211_rx_mgt(struct ieee80211_device *ieee, struct ieee80211_hdr_4addr *header, struct ieee80211_rx_stats *stats){ switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) { case IEEE80211_STYPE_ASSOC_RESP: IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); ieee80211_handle_assoc_resp(ieee, (struct ieee80211_assoc_response *) header, stats); break; case IEEE80211_STYPE_REASSOC_RESP: IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); break; case IEEE80211_STYPE_PROBE_REQ: IEEE80211_DEBUG_MGMT("received auth (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); if (ieee->handle_probe_request != NULL) ieee->handle_probe_request(ieee->dev, (struct ieee80211_probe_request *) header, stats); break; case IEEE80211_STYPE_PROBE_RESP: IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); IEEE80211_DEBUG_SCAN("Probe response\n"); ieee80211_process_probe_response(ieee, (struct ieee80211_probe_response *) header, stats); break; case IEEE80211_STYPE_BEACON: IEEE80211_DEBUG_MGMT("received BEACON (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); IEEE80211_DEBUG_SCAN("Beacon\n"); ieee80211_process_probe_response(ieee, (struct ieee80211_probe_response *) header, stats); break; case IEEE80211_STYPE_AUTH: IEEE80211_DEBUG_MGMT("received auth (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); if (ieee->handle_auth != NULL) ieee->handle_auth(ieee->dev, (struct ieee80211_auth *)header); break; case IEEE80211_STYPE_DISASSOC: if (ieee->handle_disassoc != NULL) ieee->handle_disassoc(ieee->dev, (struct ieee80211_disassoc *) header); break; case IEEE80211_STYPE_ACTION: IEEE80211_DEBUG_MGMT("ACTION\n"); if (ieee->handle_action) ieee->handle_action(ieee->dev, (struct ieee80211_action *) header, stats); break; case IEEE80211_STYPE_REASSOC_REQ: IEEE80211_DEBUG_MGMT("received reassoc (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); IEEE80211_DEBUG_MGMT("%s: IEEE80211_REASSOC_REQ received\n", ieee->dev->name); if (ieee->handle_reassoc_request != NULL) ieee->handle_reassoc_request(ieee->dev, (struct ieee80211_reassoc_request *) header); break; case IEEE80211_STYPE_ASSOC_REQ: IEEE80211_DEBUG_MGMT("received assoc (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); IEEE80211_DEBUG_MGMT("%s: IEEE80211_ASSOC_REQ received\n", ieee->dev->name); if (ieee->handle_assoc_request != NULL) ieee->handle_assoc_request(ieee->dev); break; case IEEE80211_STYPE_DEAUTH: IEEE80211_DEBUG_MGMT("DEAUTH\n"); if (ieee->handle_deauth != NULL) ieee->handle_deauth(ieee->dev, (struct ieee80211_deauth *) header); break; default: IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); IEEE80211_DEBUG_MGMT("%s: Unknown management packet: %d\n", ieee->dev->name, WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); break; }}EXPORT_SYMBOL_GPL(ieee80211_rx_any);EXPORT_SYMBOL(ieee80211_rx_mgt);EXPORT_SYMBOL(ieee80211_rx);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -