aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211/ieee80211_rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee80211/ieee80211_rx.c')
-rw-r--r--net/ieee80211/ieee80211_rx.c241
1 files changed, 229 insertions, 12 deletions
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 7ac6a7165d9c..604b7b0097bc 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -369,8 +369,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
369 369
370 /* Put this code here so that we avoid duplicating it in all 370 /* Put this code here so that we avoid duplicating it in all
371 * Rx paths. - Jean II */ 371 * Rx paths. - Jean II */
372#ifdef CONFIG_WIRELESS_EXT
372#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ 373#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
373#ifdef CONFIG_NET_RADIO
374 /* If spy monitoring on */ 374 /* If spy monitoring on */
375 if (ieee->spy_data.spy_number > 0) { 375 if (ieee->spy_data.spy_number > 0) {
376 struct iw_quality wstats; 376 struct iw_quality wstats;
@@ -397,8 +397,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
397 /* Update spy records */ 397 /* Update spy records */
398 wireless_spy_update(ieee->dev, hdr->addr2, &wstats); 398 wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
399 } 399 }
400#endif /* CONFIG_NET_RADIO */
401#endif /* IW_WIRELESS_SPY */ 400#endif /* IW_WIRELESS_SPY */
401#endif /* CONFIG_WIRELESS_EXT */
402 402
403#ifdef NOT_YET 403#ifdef NOT_YET
404 hostap_update_rx_stats(local->ap, hdr, rx_stats); 404 hostap_update_rx_stats(local->ap, hdr, rx_stats);
@@ -574,7 +574,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
574 /* skb: hdr + (possibly fragmented) plaintext payload */ 574 /* skb: hdr + (possibly fragmented) plaintext payload */
575 // PR: FIXME: hostap has additional conditions in the "if" below: 575 // PR: FIXME: hostap has additional conditions in the "if" below:
576 // ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) && 576 // ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
577 if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) { 577 if ((frag != 0) || (fc & IEEE80211_FCTL_MOREFRAGS)) {
578 int flen; 578 int flen;
579 struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr); 579 struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
580 IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag); 580 IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
@@ -754,7 +754,14 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
754 memset(skb->cb, 0, sizeof(skb->cb)); 754 memset(skb->cb, 0, sizeof(skb->cb));
755 skb->dev = dev; 755 skb->dev = dev;
756 skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ 756 skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
757 netif_rx(skb); 757 if (netif_rx(skb) == NET_RX_DROP) {
758 /* netif_rx always succeeds, but it might drop
759 * the packet. If it drops the packet, we log that
760 * in our stats. */
761 IEEE80211_DEBUG_DROP
762 ("RX: netif_rx dropped the packet\n");
763 stats->rx_dropped++;
764 }
758 } 765 }
759 766
760 rx_exit: 767 rx_exit:
@@ -773,6 +780,80 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
773 return 0; 780 return 0;
774} 781}
775 782
783/* Filter out unrelated packets, call ieee80211_rx[_mgt] */
784int ieee80211_rx_any(struct ieee80211_device *ieee,
785 struct sk_buff *skb, struct ieee80211_rx_stats *stats)
786{
787 struct ieee80211_hdr_4addr *hdr;
788 int is_packet_for_us;
789 u16 fc;
790
791 if (ieee->iw_mode == IW_MODE_MONITOR)
792 return ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL;
793
794 hdr = (struct ieee80211_hdr_4addr *)skb->data;
795 fc = le16_to_cpu(hdr->frame_ctl);
796
797 if ((fc & IEEE80211_FCTL_VERS) != 0)
798 return -EINVAL;
799
800 switch (fc & IEEE80211_FCTL_FTYPE) {
801 case IEEE80211_FTYPE_MGMT:
802 ieee80211_rx_mgt(ieee, hdr, stats);
803 return 0;
804 case IEEE80211_FTYPE_DATA:
805 break;
806 case IEEE80211_FTYPE_CTL:
807 return 0;
808 default:
809 return -EINVAL;
810 }
811
812 is_packet_for_us = 0;
813 switch (ieee->iw_mode) {
814 case IW_MODE_ADHOC:
815 /* our BSS and not from/to DS */
816 if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0)
817 if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) {
818 /* promisc: get all */
819 if (ieee->dev->flags & IFF_PROMISC)
820 is_packet_for_us = 1;
821 /* to us */
822 else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
823 is_packet_for_us = 1;
824 /* mcast */
825 else if (is_multicast_ether_addr(hdr->addr1))
826 is_packet_for_us = 1;
827 }
828 break;
829 case IW_MODE_INFRA:
830 /* our BSS (== from our AP) and from DS */
831 if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0)
832 if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) {
833 /* promisc: get all */
834 if (ieee->dev->flags & IFF_PROMISC)
835 is_packet_for_us = 1;
836 /* to us */
837 else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
838 is_packet_for_us = 1;
839 /* mcast */
840 else if (is_multicast_ether_addr(hdr->addr1)) {
841 /* not our own packet bcasted from AP */
842 if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN))
843 is_packet_for_us = 1;
844 }
845 }
846 break;
847 default:
848 /* ? */
849 break;
850 }
851
852 if (is_packet_for_us)
853 return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL);
854 return 0;
855}
856
776#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 857#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
777 858
778static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; 859static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
@@ -930,6 +1011,45 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
930 return rc; 1011 return rc;
931} 1012}
932 1013
1014#ifdef CONFIG_IEEE80211_DEBUG
1015#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
1016
1017static const char *get_info_element_string(u16 id)
1018{
1019 switch (id) {
1020 MFIE_STRING(SSID);
1021 MFIE_STRING(RATES);
1022 MFIE_STRING(FH_SET);
1023 MFIE_STRING(DS_SET);
1024 MFIE_STRING(CF_SET);
1025 MFIE_STRING(TIM);
1026 MFIE_STRING(IBSS_SET);
1027 MFIE_STRING(COUNTRY);
1028 MFIE_STRING(HOP_PARAMS);
1029 MFIE_STRING(HOP_TABLE);
1030 MFIE_STRING(REQUEST);
1031 MFIE_STRING(CHALLENGE);
1032 MFIE_STRING(POWER_CONSTRAINT);
1033 MFIE_STRING(POWER_CAPABILITY);
1034 MFIE_STRING(TPC_REQUEST);
1035 MFIE_STRING(TPC_REPORT);
1036 MFIE_STRING(SUPP_CHANNELS);
1037 MFIE_STRING(CSA);
1038 MFIE_STRING(MEASURE_REQUEST);
1039 MFIE_STRING(MEASURE_REPORT);
1040 MFIE_STRING(QUIET);
1041 MFIE_STRING(IBSS_DFS);
1042 MFIE_STRING(ERP_INFO);
1043 MFIE_STRING(RSN);
1044 MFIE_STRING(RATES_EX);
1045 MFIE_STRING(GENERIC);
1046 MFIE_STRING(QOS_PARAMETER);
1047 default:
1048 return "UNKNOWN";
1049 }
1050}
1051#endif
1052
933static int ieee80211_parse_info_param(struct ieee80211_info_element 1053static int ieee80211_parse_info_param(struct ieee80211_info_element
934 *info_element, u16 length, 1054 *info_element, u16 length,
935 struct ieee80211_network *network) 1055 struct ieee80211_network *network)
@@ -1040,7 +1160,9 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1040 break; 1160 break;
1041 1161
1042 case MFIE_TYPE_TIM: 1162 case MFIE_TYPE_TIM:
1043 IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n"); 1163 network->tim.tim_count = info_element->data[0];
1164 network->tim.tim_period = info_element->data[1];
1165 IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n");
1044 break; 1166 break;
1045 1167
1046 case MFIE_TYPE_ERP_INFO: 1168 case MFIE_TYPE_ERP_INFO:
@@ -1091,10 +1213,49 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1091 printk(KERN_ERR 1213 printk(KERN_ERR
1092 "QoS Error need to parse QOS_PARAMETER IE\n"); 1214 "QoS Error need to parse QOS_PARAMETER IE\n");
1093 break; 1215 break;
1216 /* 802.11h */
1217 case MFIE_TYPE_POWER_CONSTRAINT:
1218 network->power_constraint = info_element->data[0];
1219 network->flags |= NETWORK_HAS_POWER_CONSTRAINT;
1220 break;
1221
1222 case MFIE_TYPE_CSA:
1223 network->power_constraint = info_element->data[0];
1224 network->flags |= NETWORK_HAS_CSA;
1225 break;
1226
1227 case MFIE_TYPE_QUIET:
1228 network->quiet.count = info_element->data[0];
1229 network->quiet.period = info_element->data[1];
1230 network->quiet.duration = info_element->data[2];
1231 network->quiet.offset = info_element->data[3];
1232 network->flags |= NETWORK_HAS_QUIET;
1233 break;
1234
1235 case MFIE_TYPE_IBSS_DFS:
1236 if (network->ibss_dfs)
1237 break;
1238 network->ibss_dfs =
1239 kmalloc(info_element->len, GFP_ATOMIC);
1240 if (!network->ibss_dfs)
1241 return 1;
1242 memcpy(network->ibss_dfs, info_element->data,
1243 info_element->len);
1244 network->flags |= NETWORK_HAS_IBSS_DFS;
1245 break;
1246
1247 case MFIE_TYPE_TPC_REPORT:
1248 network->tpc_report.transmit_power =
1249 info_element->data[0];
1250 network->tpc_report.link_margin = info_element->data[1];
1251 network->flags |= NETWORK_HAS_TPC_REPORT;
1252 break;
1094 1253
1095 default: 1254 default:
1096 IEEE80211_DEBUG_MGMT("unsupported IE %d\n", 1255 IEEE80211_DEBUG_MGMT
1097 info_element->id); 1256 ("Unsupported info element: %s (%d)\n",
1257 get_info_element_string(info_element->id),
1258 info_element->id);
1098 break; 1259 break;
1099 } 1260 }
1100 1261
@@ -1110,7 +1271,9 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1110static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response 1271static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
1111 *frame, struct ieee80211_rx_stats *stats) 1272 *frame, struct ieee80211_rx_stats *stats)
1112{ 1273{
1113 struct ieee80211_network network_resp; 1274 struct ieee80211_network network_resp = {
1275 .ibss_dfs = NULL,
1276 };
1114 struct ieee80211_network *network = &network_resp; 1277 struct ieee80211_network *network = &network_resp;
1115 struct net_device *dev = ieee->dev; 1278 struct net_device *dev = ieee->dev;
1116 1279
@@ -1253,7 +1416,22 @@ static void update_network(struct ieee80211_network *dst,
1253 int qos_active; 1416 int qos_active;
1254 u8 old_param; 1417 u8 old_param;
1255 1418
1256 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); 1419 ieee80211_network_reset(dst);
1420 dst->ibss_dfs = src->ibss_dfs;
1421
1422 /* We only update the statistics if they were created by receiving
1423 * the network information on the actual channel the network is on.
1424 *
1425 * This keeps beacons received on neighbor channels from bringing
1426 * down the signal level of an AP. */
1427 if (dst->channel == src->stats.received_channel)
1428 memcpy(&dst->stats, &src->stats,
1429 sizeof(struct ieee80211_rx_stats));
1430 else
1431 IEEE80211_DEBUG_SCAN("Network " MAC_FMT " info received "
1432 "off channel (%d vs. %d)\n", MAC_ARG(src->bssid),
1433 dst->channel, src->stats.received_channel);
1434
1257 dst->capability = src->capability; 1435 dst->capability = src->capability;
1258 memcpy(dst->rates, src->rates, src->rates_len); 1436 memcpy(dst->rates, src->rates, src->rates_len);
1259 dst->rates_len = src->rates_len; 1437 dst->rates_len = src->rates_len;
@@ -1269,6 +1447,7 @@ static void update_network(struct ieee80211_network *dst,
1269 dst->listen_interval = src->listen_interval; 1447 dst->listen_interval = src->listen_interval;
1270 dst->atim_window = src->atim_window; 1448 dst->atim_window = src->atim_window;
1271 dst->erp_value = src->erp_value; 1449 dst->erp_value = src->erp_value;
1450 dst->tim = src->tim;
1272 1451
1273 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); 1452 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
1274 dst->wpa_ie_len = src->wpa_ie_len; 1453 dst->wpa_ie_len = src->wpa_ie_len;
@@ -1313,7 +1492,9 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1313 *stats) 1492 *stats)
1314{ 1493{
1315 struct net_device *dev = ieee->dev; 1494 struct net_device *dev = ieee->dev;
1316 struct ieee80211_network network; 1495 struct ieee80211_network network = {
1496 .ibss_dfs = NULL,
1497 };
1317 struct ieee80211_network *target; 1498 struct ieee80211_network *target;
1318 struct ieee80211_network *oldest = NULL; 1499 struct ieee80211_network *oldest = NULL;
1319#ifdef CONFIG_IEEE80211_DEBUG 1500#ifdef CONFIG_IEEE80211_DEBUG
@@ -1386,6 +1567,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1386 escape_essid(target->ssid, 1567 escape_essid(target->ssid,
1387 target->ssid_len), 1568 target->ssid_len),
1388 MAC_ARG(target->bssid)); 1569 MAC_ARG(target->bssid));
1570 ieee80211_network_reset(target);
1389 } else { 1571 } else {
1390 /* Otherwise just pull from the free list */ 1572 /* Otherwise just pull from the free list */
1391 target = list_entry(ieee->network_free_list.next, 1573 target = list_entry(ieee->network_free_list.next,
@@ -1402,6 +1584,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1402 "BEACON" : "PROBE RESPONSE"); 1584 "BEACON" : "PROBE RESPONSE");
1403#endif 1585#endif
1404 memcpy(target, &network, sizeof(*target)); 1586 memcpy(target, &network, sizeof(*target));
1587 network.ibss_dfs = NULL;
1405 list_add_tail(&target->list, &ieee->network_list); 1588 list_add_tail(&target->list, &ieee->network_list);
1406 } else { 1589 } else {
1407 IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n", 1590 IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
@@ -1411,6 +1594,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1411 is_beacon(beacon->header.frame_ctl) ? 1594 is_beacon(beacon->header.frame_ctl) ?
1412 "BEACON" : "PROBE RESPONSE"); 1595 "BEACON" : "PROBE RESPONSE");
1413 update_network(target, &network); 1596 update_network(target, &network);
1597 network.ibss_dfs = NULL;
1414 } 1598 }
1415 1599
1416 spin_unlock_irqrestore(&ieee->lock, flags); 1600 spin_unlock_irqrestore(&ieee->lock, flags);
@@ -1495,10 +1679,43 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1495 header); 1679 header);
1496 break; 1680 break;
1497 1681
1682 case IEEE80211_STYPE_ACTION:
1683 IEEE80211_DEBUG_MGMT("ACTION\n");
1684 if (ieee->handle_action)
1685 ieee->handle_action(ieee->dev,
1686 (struct ieee80211_action *)
1687 header, stats);
1688 break;
1689
1690 case IEEE80211_STYPE_REASSOC_REQ:
1691 IEEE80211_DEBUG_MGMT("received reassoc (%d)\n",
1692 WLAN_FC_GET_STYPE(le16_to_cpu
1693 (header->frame_ctl)));
1694
1695 IEEE80211_WARNING("%s: IEEE80211_REASSOC_REQ received\n",
1696 ieee->dev->name);
1697 if (ieee->handle_reassoc_request != NULL)
1698 ieee->handle_reassoc_request(ieee->dev,
1699 (struct ieee80211_reassoc_request *)
1700 header);
1701 break;
1702
1703 case IEEE80211_STYPE_ASSOC_REQ:
1704 IEEE80211_DEBUG_MGMT("received assoc (%d)\n",
1705 WLAN_FC_GET_STYPE(le16_to_cpu
1706 (header->frame_ctl)));
1707
1708 IEEE80211_WARNING("%s: IEEE80211_ASSOC_REQ received\n",
1709 ieee->dev->name);
1710 if (ieee->handle_assoc_request != NULL)
1711 ieee->handle_assoc_request(ieee->dev);
1712 break;
1713
1498 case IEEE80211_STYPE_DEAUTH: 1714 case IEEE80211_STYPE_DEAUTH:
1499 printk("DEAUTH from AP\n"); 1715 IEEE80211_DEBUG_MGMT("DEAUTH\n");
1500 if (ieee->handle_deauth != NULL) 1716 if (ieee->handle_deauth != NULL)
1501 ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *) 1717 ieee->handle_deauth(ieee->dev,
1718 (struct ieee80211_deauth *)
1502 header); 1719 header);
1503 break; 1720 break;
1504 default: 1721 default: