diff options
author | Zhu Yi <yi.zhu@intel.com> | 2006-01-19 03:22:15 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-01-27 17:08:07 -0500 |
commit | d1b46b0fba8c1049135ee5d60910b04463dccc95 (patch) | |
tree | 1ec055eee19d523f5fdd7bbe696dc1f0c0dbd105 /net/ieee80211 | |
parent | 15f385982e3a4782fe8ed71a9a6beb64a2160c30 (diff) |
[PATCH] ieee80211: Add 802.11h information element parsing
Added default handlers for various 802.11h DFS and TPC information
elements. Moved all information elements into single location (called
from two places). Added debug message with information on unparsed IEs
if debug_level set. Added code to reset network IBSS DFS information
when appropriate. Added code to invoke driver callback for 802.11h
ACTION STYPE. Changed a few printk's to IEEE80211_DEBUG_MGMT.
Signed-off-by: James Ketrenos <jketreno@linux.intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/ieee80211')
-rw-r--r-- | net/ieee80211/ieee80211_rx.c | 109 |
1 files changed, 103 insertions, 6 deletions
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 4165da7ecff2..a4ebc22ee712 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c | |||
@@ -937,6 +937,45 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element | |||
937 | return rc; | 937 | return rc; |
938 | } | 938 | } |
939 | 939 | ||
940 | #ifdef CONFIG_IEEE80211_DEBUG | ||
941 | #define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x | ||
942 | |||
943 | static 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 | |||
940 | static int ieee80211_parse_info_param(struct ieee80211_info_element | 979 | static int ieee80211_parse_info_param(struct ieee80211_info_element |
941 | *info_element, u16 length, | 980 | *info_element, u16 length, |
942 | struct ieee80211_network *network) | 981 | struct ieee80211_network *network) |
@@ -1100,10 +1139,49 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element | |||
1100 | printk(KERN_ERR | 1139 | printk(KERN_ERR |
1101 | "QoS Error need to parse QOS_PARAMETER IE\n"); | 1140 | "QoS Error need to parse QOS_PARAMETER IE\n"); |
1102 | 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; | ||
1103 | 1179 | ||
1104 | default: | 1180 | default: |
1105 | IEEE80211_DEBUG_MGMT("unsupported IE %d\n", | 1181 | IEEE80211_DEBUG_MGMT |
1106 | info_element->id); | 1182 | ("Unsupported info element: %s (%d)\n", |
1183 | get_info_element_string(info_element->id), | ||
1184 | info_element->id); | ||
1107 | break; | 1185 | break; |
1108 | } | 1186 | } |
1109 | 1187 | ||
@@ -1119,7 +1197,9 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element | |||
1119 | static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response | 1197 | static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response |
1120 | *frame, struct ieee80211_rx_stats *stats) | 1198 | *frame, struct ieee80211_rx_stats *stats) |
1121 | { | 1199 | { |
1122 | struct ieee80211_network network_resp; | 1200 | struct ieee80211_network network_resp = { |
1201 | .ibss_dfs = NULL, | ||
1202 | }; | ||
1123 | struct ieee80211_network *network = &network_resp; | 1203 | struct ieee80211_network *network = &network_resp; |
1124 | struct net_device *dev = ieee->dev; | 1204 | struct net_device *dev = ieee->dev; |
1125 | 1205 | ||
@@ -1262,6 +1342,9 @@ static void update_network(struct ieee80211_network *dst, | |||
1262 | int qos_active; | 1342 | int qos_active; |
1263 | u8 old_param; | 1343 | u8 old_param; |
1264 | 1344 | ||
1345 | ieee80211_network_reset(dst); | ||
1346 | dst->ibss_dfs = src->ibss_dfs; | ||
1347 | |||
1265 | memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); | 1348 | memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); |
1266 | dst->capability = src->capability; | 1349 | dst->capability = src->capability; |
1267 | memcpy(dst->rates, src->rates, src->rates_len); | 1350 | memcpy(dst->rates, src->rates, src->rates_len); |
@@ -1323,7 +1406,9 @@ static void ieee80211_process_probe_response(struct ieee80211_device | |||
1323 | *stats) | 1406 | *stats) |
1324 | { | 1407 | { |
1325 | struct net_device *dev = ieee->dev; | 1408 | struct net_device *dev = ieee->dev; |
1326 | struct ieee80211_network network; | 1409 | struct ieee80211_network network = { |
1410 | .ibss_dfs = NULL, | ||
1411 | }; | ||
1327 | struct ieee80211_network *target; | 1412 | struct ieee80211_network *target; |
1328 | struct ieee80211_network *oldest = NULL; | 1413 | struct ieee80211_network *oldest = NULL; |
1329 | #ifdef CONFIG_IEEE80211_DEBUG | 1414 | #ifdef CONFIG_IEEE80211_DEBUG |
@@ -1398,6 +1483,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device | |||
1398 | escape_essid(target->ssid, | 1483 | escape_essid(target->ssid, |
1399 | target->ssid_len), | 1484 | target->ssid_len), |
1400 | MAC_ARG(target->bssid)); | 1485 | MAC_ARG(target->bssid)); |
1486 | ieee80211_network_reset(target); | ||
1401 | } else { | 1487 | } else { |
1402 | /* Otherwise just pull from the free list */ | 1488 | /* Otherwise just pull from the free list */ |
1403 | target = list_entry(ieee->network_free_list.next, | 1489 | target = list_entry(ieee->network_free_list.next, |
@@ -1416,6 +1502,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device | |||
1416 | "BEACON" : "PROBE RESPONSE"); | 1502 | "BEACON" : "PROBE RESPONSE"); |
1417 | #endif | 1503 | #endif |
1418 | memcpy(target, &network, sizeof(*target)); | 1504 | memcpy(target, &network, sizeof(*target)); |
1505 | network.ibss_dfs = NULL; | ||
1419 | list_add_tail(&target->list, &ieee->network_list); | 1506 | list_add_tail(&target->list, &ieee->network_list); |
1420 | } else { | 1507 | } else { |
1421 | IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n", | 1508 | IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n", |
@@ -1427,6 +1514,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device | |||
1427 | frame_ctl)) ? | 1514 | frame_ctl)) ? |
1428 | "BEACON" : "PROBE RESPONSE"); | 1515 | "BEACON" : "PROBE RESPONSE"); |
1429 | update_network(target, &network); | 1516 | update_network(target, &network); |
1517 | network.ibss_dfs = NULL; | ||
1430 | } | 1518 | } |
1431 | 1519 | ||
1432 | spin_unlock_irqrestore(&ieee->lock, flags); | 1520 | spin_unlock_irqrestore(&ieee->lock, flags); |
@@ -1511,10 +1599,19 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee, | |||
1511 | header); | 1599 | header); |
1512 | break; | 1600 | break; |
1513 | 1601 | ||
1602 | case IEEE80211_STYPE_ACTION: | ||
1603 | IEEE80211_DEBUG_MGMT("ACTION\n"); | ||
1604 | if (ieee->handle_action) | ||
1605 | ieee->handle_action(ieee->dev, | ||
1606 | (struct ieee80211_action *) | ||
1607 | header, stats); | ||
1608 | break; | ||
1609 | |||
1514 | case IEEE80211_STYPE_DEAUTH: | 1610 | case IEEE80211_STYPE_DEAUTH: |
1515 | printk("DEAUTH from AP\n"); | 1611 | IEEE80211_DEBUG_MGMT("DEAUTH\n"); |
1516 | if (ieee->handle_deauth != NULL) | 1612 | if (ieee->handle_deauth != NULL) |
1517 | ieee->handle_deauth(ieee->dev, (struct ieee80211_deauth *) | 1613 | ieee->handle_deauth(ieee->dev, |
1614 | (struct ieee80211_deauth *) | ||
1518 | header); | 1615 | header); |
1519 | break; | 1616 | break; |
1520 | default: | 1617 | default: |