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.c167
1 files changed, 155 insertions, 12 deletions
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 7ac6a7165d9c..a7f2a642a512 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:
@@ -930,6 +937,45 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
930 return rc; 937 return rc;
931} 938}
932 939
940#ifdef CONFIG_IEEE80211_DEBUG
941#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
942
943static const char *get_info_element_string(u16 id)
944{
945 switch (id) {
946 MFIE_STRING(SSID);
947 MFIE_STRING(RATES);
948 MFIE_STRING(FH_SET);
949 MFIE_STRING(DS_SET);
950 MFIE_STRING(CF_SET);
951 MFIE_STRING(TIM);
952 MFIE_STRING(IBSS_SET);
953 MFIE_STRING(COUNTRY);
954 MFIE_STRING(HOP_PARAMS);
955 MFIE_STRING(HOP_TABLE);
956 MFIE_STRING(REQUEST);
957 MFIE_STRING(CHALLENGE);
958 MFIE_STRING(POWER_CONSTRAINT);
959 MFIE_STRING(POWER_CAPABILITY);
960 MFIE_STRING(TPC_REQUEST);
961 MFIE_STRING(TPC_REPORT);
962 MFIE_STRING(SUPP_CHANNELS);
963 MFIE_STRING(CSA);
964 MFIE_STRING(MEASURE_REQUEST);
965 MFIE_STRING(MEASURE_REPORT);
966 MFIE_STRING(QUIET);
967 MFIE_STRING(IBSS_DFS);
968 MFIE_STRING(ERP_INFO);
969 MFIE_STRING(RSN);
970 MFIE_STRING(RATES_EX);
971 MFIE_STRING(GENERIC);
972 MFIE_STRING(QOS_PARAMETER);
973 default:
974 return "UNKNOWN";
975 }
976}
977#endif
978
933static int ieee80211_parse_info_param(struct ieee80211_info_element 979static int ieee80211_parse_info_param(struct ieee80211_info_element
934 *info_element, u16 length, 980 *info_element, u16 length,
935 struct ieee80211_network *network) 981 struct ieee80211_network *network)
@@ -1040,7 +1086,9 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1040 break; 1086 break;
1041 1087
1042 case MFIE_TYPE_TIM: 1088 case MFIE_TYPE_TIM:
1043 IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n"); 1089 network->tim.tim_count = info_element->data[0];
1090 network->tim.tim_period = info_element->data[1];
1091 IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n");
1044 break; 1092 break;
1045 1093
1046 case MFIE_TYPE_ERP_INFO: 1094 case MFIE_TYPE_ERP_INFO:
@@ -1091,10 +1139,49 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
1091 printk(KERN_ERR 1139 printk(KERN_ERR
1092 "QoS Error need to parse QOS_PARAMETER IE\n"); 1140 "QoS Error need to parse QOS_PARAMETER IE\n");
1093 break; 1141 break;
1142 /* 802.11h */
1143 case MFIE_TYPE_POWER_CONSTRAINT:
1144 network->power_constraint = info_element->data[0];
1145 network->flags |= NETWORK_HAS_POWER_CONSTRAINT;
1146 break;
1147
1148 case MFIE_TYPE_CSA:
1149 network->power_constraint = info_element->data[0];
1150 network->flags |= NETWORK_HAS_CSA;
1151 break;
1152
1153 case MFIE_TYPE_QUIET:
1154 network->quiet.count = info_element->data[0];
1155 network->quiet.period = info_element->data[1];
1156 network->quiet.duration = info_element->data[2];
1157 network->quiet.offset = info_element->data[3];
1158 network->flags |= NETWORK_HAS_QUIET;
1159 break;
1160
1161 case MFIE_TYPE_IBSS_DFS:
1162 if (network->ibss_dfs)
1163 break;
1164 network->ibss_dfs =
1165 kmalloc(info_element->len, GFP_ATOMIC);
1166 if (!network->ibss_dfs)
1167 return 1;
1168 memcpy(network->ibss_dfs, info_element->data,
1169 info_element->len);
1170 network->flags |= NETWORK_HAS_IBSS_DFS;
1171 break;
1172
1173 case MFIE_TYPE_TPC_REPORT:
1174 network->tpc_report.transmit_power =
1175 info_element->data[0];
1176 network->tpc_report.link_margin = info_element->data[1];
1177 network->flags |= NETWORK_HAS_TPC_REPORT;
1178 break;
1094 1179
1095 default: 1180 default:
1096 IEEE80211_DEBUG_MGMT("unsupported IE %d\n", 1181 IEEE80211_DEBUG_MGMT
1097 info_element->id); 1182 ("Unsupported info element: %s (%d)\n",
1183 get_info_element_string(info_element->id),
1184 info_element->id);
1098 break; 1185 break;
1099 } 1186 }
1100 1187
@@ -1110,7 +1197,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 1197static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
1111 *frame, struct ieee80211_rx_stats *stats) 1198 *frame, struct ieee80211_rx_stats *stats)
1112{ 1199{
1113 struct ieee80211_network network_resp; 1200 struct ieee80211_network network_resp = {
1201 .ibss_dfs = NULL,
1202 };
1114 struct ieee80211_network *network = &network_resp; 1203 struct ieee80211_network *network = &network_resp;
1115 struct net_device *dev = ieee->dev; 1204 struct net_device *dev = ieee->dev;
1116 1205
@@ -1253,7 +1342,22 @@ static void update_network(struct ieee80211_network *dst,
1253 int qos_active; 1342 int qos_active;
1254 u8 old_param; 1343 u8 old_param;
1255 1344
1256 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); 1345 ieee80211_network_reset(dst);
1346 dst->ibss_dfs = src->ibss_dfs;
1347
1348 /* We only update the statistics if they were created by receiving
1349 * the network information on the actual channel the network is on.
1350 *
1351 * This keeps beacons received on neighbor channels from bringing
1352 * down the signal level of an AP. */
1353 if (dst->channel == src->stats.received_channel)
1354 memcpy(&dst->stats, &src->stats,
1355 sizeof(struct ieee80211_rx_stats));
1356 else
1357 IEEE80211_DEBUG_SCAN("Network " MAC_FMT " info received "
1358 "off channel (%d vs. %d)\n", MAC_ARG(src->bssid),
1359 dst->channel, src->stats.received_channel);
1360
1257 dst->capability = src->capability; 1361 dst->capability = src->capability;
1258 memcpy(dst->rates, src->rates, src->rates_len); 1362 memcpy(dst->rates, src->rates, src->rates_len);
1259 dst->rates_len = src->rates_len; 1363 dst->rates_len = src->rates_len;
@@ -1269,6 +1373,7 @@ static void update_network(struct ieee80211_network *dst,
1269 dst->listen_interval = src->listen_interval; 1373 dst->listen_interval = src->listen_interval;
1270 dst->atim_window = src->atim_window; 1374 dst->atim_window = src->atim_window;
1271 dst->erp_value = src->erp_value; 1375 dst->erp_value = src->erp_value;
1376 dst->tim = src->tim;
1272 1377
1273 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); 1378 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
1274 dst->wpa_ie_len = src->wpa_ie_len; 1379 dst->wpa_ie_len = src->wpa_ie_len;
@@ -1313,7 +1418,9 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1313 *stats) 1418 *stats)
1314{ 1419{
1315 struct net_device *dev = ieee->dev; 1420 struct net_device *dev = ieee->dev;
1316 struct ieee80211_network network; 1421 struct ieee80211_network network = {
1422 .ibss_dfs = NULL,
1423 };
1317 struct ieee80211_network *target; 1424 struct ieee80211_network *target;
1318 struct ieee80211_network *oldest = NULL; 1425 struct ieee80211_network *oldest = NULL;
1319#ifdef CONFIG_IEEE80211_DEBUG 1426#ifdef CONFIG_IEEE80211_DEBUG
@@ -1386,6 +1493,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1386 escape_essid(target->ssid, 1493 escape_essid(target->ssid,
1387 target->ssid_len), 1494 target->ssid_len),
1388 MAC_ARG(target->bssid)); 1495 MAC_ARG(target->bssid));
1496 ieee80211_network_reset(target);
1389 } else { 1497 } else {
1390 /* Otherwise just pull from the free list */ 1498 /* Otherwise just pull from the free list */
1391 target = list_entry(ieee->network_free_list.next, 1499 target = list_entry(ieee->network_free_list.next,
@@ -1402,6 +1510,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1402 "BEACON" : "PROBE RESPONSE"); 1510 "BEACON" : "PROBE RESPONSE");
1403#endif 1511#endif
1404 memcpy(target, &network, sizeof(*target)); 1512 memcpy(target, &network, sizeof(*target));
1513 network.ibss_dfs = NULL;
1405 list_add_tail(&target->list, &ieee->network_list); 1514 list_add_tail(&target->list, &ieee->network_list);
1406 } else { 1515 } else {
1407 IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n", 1516 IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
@@ -1411,6 +1520,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
1411 is_beacon(beacon->header.frame_ctl) ? 1520 is_beacon(beacon->header.frame_ctl) ?
1412 "BEACON" : "PROBE RESPONSE"); 1521 "BEACON" : "PROBE RESPONSE");
1413 update_network(target, &network); 1522 update_network(target, &network);
1523 network.ibss_dfs = NULL;
1414 } 1524 }
1415 1525
1416 spin_unlock_irqrestore(&ieee->lock, flags); 1526 spin_unlock_irqrestore(&ieee->lock, flags);
@@ -1495,10 +1605,43 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1495 header); 1605 header);
1496 break; 1606 break;
1497 1607
1608 case IEEE80211_STYPE_ACTION:
1609 IEEE80211_DEBUG_MGMT("ACTION\n");
1610 if (ieee->handle_action)
1611 ieee->handle_action(ieee->dev,
1612 (struct ieee80211_action *)
1613 header, stats);
1614 break;
1615
1616 case IEEE80211_STYPE_REASSOC_REQ:
1617 IEEE80211_DEBUG_MGMT("received reassoc (%d)\n",
1618 WLAN_FC_GET_STYPE(le16_to_cpu
1619 (header->frame_ctl)));
1620
1621 IEEE80211_WARNING("%s: IEEE80211_REASSOC_REQ received\n",
1622 ieee->dev->name);
1623 if (ieee->handle_reassoc_request != NULL)
1624 ieee->handle_reassoc_request(ieee->dev,
1625 (struct ieee80211_reassoc_request *)
1626 header);
1627 break;
1628
1629 case IEEE80211_STYPE_ASSOC_REQ:
1630 IEEE80211_DEBUG_MGMT("received assoc (%d)\n",
1631 WLAN_FC_GET_STYPE(le16_to_cpu
1632 (header->frame_ctl)));
1633
1634 IEEE80211_WARNING("%s: IEEE80211_ASSOC_REQ received\n",
1635 ieee->dev->name);
1636 if (ieee->handle_assoc_request != NULL)
1637 ieee->handle_assoc_request(ieee->dev);
1638 break;
1639
1498 case IEEE80211_STYPE_DEAUTH: 1640 case IEEE80211_STYPE_DEAUTH:
1499 printk("DEAUTH from AP\n"); 1641 IEEE80211_DEBUG_MGMT("DEAUTH\n");
1500 if (ieee->handle_deauth != NULL) 1642 if (ieee->handle_deauth != NULL)
1501 ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *) 1643 ieee->handle_deauth(ieee->dev,
1644 (struct ieee80211_deauth *)
1502 header); 1645 header);
1503 break; 1646 break;
1504 default: 1647 default: