📄 ieee80211_rx.c
字号:
} } IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n", rates_str, network->rates_ex_len); break; case MFIE_TYPE_DS_SET: IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n", info_element->data[0]); network->channel = info_element->data[0]; break; case MFIE_TYPE_FH_SET: IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n"); break; case MFIE_TYPE_CF_SET: IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n"); break; case MFIE_TYPE_TIM: IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n"); break; case MFIE_TYPE_ERP_INFO: network->erp_value = info_element->data[0]; IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", network->erp_value); break; case MFIE_TYPE_IBSS_SET: network->atim_window = info_element->data[0]; IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n", network->atim_window); break; case MFIE_TYPE_CHALLENGE: IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n"); break; case MFIE_TYPE_GENERIC: IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n", info_element->len); if (!ieee80211_parse_qos_info_param_IE(info_element, network)) break; if (info_element->len >= 4 && info_element->data[0] == 0x00 && info_element->data[1] == 0x50 && info_element->data[2] == 0xf2 && info_element->data[3] == 0x01) { network->wpa_ie_len = min(info_element->len + 2, MAX_WPA_IE_LEN); memcpy(network->wpa_ie, info_element, network->wpa_ie_len); } break; case MFIE_TYPE_RSN: IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n", info_element->len); network->rsn_ie_len = min(info_element->len + 2, MAX_WPA_IE_LEN); memcpy(network->rsn_ie, info_element, network->rsn_ie_len); break; case MFIE_TYPE_QOS_PARAMETER: printk(KERN_ERR "QoS Error need to parse QOS_PARAMETER IE\n"); break; default: IEEE80211_DEBUG_MGMT("unsupported IE %d\n", info_element->id); break; } length -= sizeof(*info_element) + info_element->len; info_element = (struct ieee80211_info_element *)&info_element-> data[info_element->len]; } return 0;}static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response *frame, struct ieee80211_rx_stats *stats){ struct ieee80211_network network_resp; struct ieee80211_network *network = &network_resp; struct net_device *dev = ieee->dev; network->flags = 0; network->qos_data.active = 0; network->qos_data.supported = 0; network->qos_data.param_count = 0; network->qos_data.old_param_count = 0; //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF); network->atim_window = le16_to_cpu(frame->aid); 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 inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response *beacon, struct ieee80211_network *network, struct ieee80211_rx_stats *stats){ 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 (" MAC_FMT ")' " "network.\n", escape_essid(network->ssid, network->ssid_len), MAC_ARG(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) && !memcmp(src->bssid, dst->bssid, ETH_ALEN) && !memcmp(src->ssid, dst->ssid, src->ssid_len));}static inline void update_network(struct ieee80211_network *dst, struct ieee80211_network *src){ int qos_active; u8 old_param; memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); 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; 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(int fc){ return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);}static inline 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; 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; IEEE80211_DEBUG_SCAN("'%s' (" MAC_FMT "): %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), MAC_ARG(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' (" MAC_FMT ") via %s.\n", escape_essid(info_element->data, info_element->len), MAC_ARG(beacon->header.addr3), is_beacon(le16_to_cpu (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' (" MAC_FMT ") from " "network list.\n", escape_essid(target->ssid, target->ssid_len), MAC_ARG(target->bssid)); } 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' (" MAC_FMT ") via %s.\n", escape_essid(network.ssid, network.ssid_len), MAC_ARG(network.bssid), is_beacon(le16_to_cpu (beacon->header. frame_ctl)) ? "BEACON" : "PROBE RESPONSE");#endif memcpy(target, &network, sizeof(*target)); list_add_tail(&target->list, &ieee->network_list); } else { IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n", escape_essid(target->ssid, target->ssid_len), MAC_ARG(target->bssid), is_beacon(le16_to_cpu (beacon->header. frame_ctl)) ? "BEACON" : "PROBE RESPONSE"); update_network(target, &network); } spin_unlock_irqrestore(&ieee->lock, flags); if (is_beacon(le16_to_cpu(beacon->header.frame_ctl))) { if (ieee->handle_beacon != NULL) ieee->handle_beacon(dev, beacon, &network); } else { if (ieee->handle_probe_response != NULL) ieee->handle_probe_response(dev, beacon, &network); }}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("recieved 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("recieved 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_DEAUTH: printk("DEAUTH from AP\n"); if (ieee->handle_deauth != NULL) ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *) header); break; default: IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); IEEE80211_WARNING("%s: Unknown management packet: %d\n", ieee->dev->name, WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); break; }}EXPORT_SYMBOL(ieee80211_rx_mgt);EXPORT_SYMBOL(ieee80211_rx);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -