diff options
-rw-r--r-- | net/ieee80211/ieee80211_rx.c | 267 |
1 files changed, 99 insertions, 168 deletions
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 2f4b16c1c143..3bf04d6d2b13 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c | |||
@@ -917,158 +917,23 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element | |||
917 | return rc; | 917 | return rc; |
918 | } | 918 | } |
919 | 919 | ||
920 | static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response | 920 | static int ieee80211_parse_info_param(struct ieee80211_info_element *info_element, |
921 | *frame, struct ieee80211_rx_stats *stats) | 921 | u16 length, struct ieee80211_network *network) |
922 | { | ||
923 | struct ieee80211_network network_resp; | ||
924 | struct ieee80211_network *network = &network_resp; | ||
925 | struct ieee80211_info_element *info_element; | ||
926 | struct net_device *dev = ieee->dev; | ||
927 | u16 left; | ||
928 | |||
929 | network->flags = 0; | ||
930 | network->qos_data.active = 0; | ||
931 | network->qos_data.supported = 0; | ||
932 | network->qos_data.param_count = 0; | ||
933 | network->qos_data.old_param_count = 0; | ||
934 | |||
935 | //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF); | ||
936 | network->atim_window = le16_to_cpu(frame->aid); | ||
937 | network->listen_interval = le16_to_cpu(frame->status); | ||
938 | |||
939 | info_element = frame->info_element; | ||
940 | left = stats->len - sizeof(*frame); | ||
941 | |||
942 | while (left >= sizeof(struct ieee80211_info_element)) { | ||
943 | if (sizeof(struct ieee80211_info_element) + | ||
944 | info_element->len > left) { | ||
945 | IEEE80211_DEBUG_QOS("ASSOC RESP: parse failed: " | ||
946 | "info_element->len + 2 > left : " | ||
947 | "info_element->len+2=%zd left=%d, id=%d.\n", | ||
948 | info_element->len + | ||
949 | sizeof(struct | ||
950 | ieee80211_info_element), | ||
951 | left, info_element->id); | ||
952 | return 1; | ||
953 | } | ||
954 | |||
955 | switch (info_element->id) { | ||
956 | case MFIE_TYPE_SSID: | ||
957 | if (ieee80211_is_empty_essid(info_element->data, | ||
958 | info_element->len)) { | ||
959 | network->flags |= NETWORK_EMPTY_ESSID; | ||
960 | break; | ||
961 | } | ||
962 | |||
963 | network->ssid_len = min(info_element->len, | ||
964 | (u8) IW_ESSID_MAX_SIZE); | ||
965 | memcpy(network->ssid, info_element->data, | ||
966 | network->ssid_len); | ||
967 | if (network->ssid_len < IW_ESSID_MAX_SIZE) | ||
968 | memset(network->ssid + network->ssid_len, 0, | ||
969 | IW_ESSID_MAX_SIZE - network->ssid_len); | ||
970 | |||
971 | IEEE80211_DEBUG_QOS("MFIE_TYPE_SSID: '%s' len=%d.\n", | ||
972 | network->ssid, network->ssid_len); | ||
973 | break; | ||
974 | |||
975 | case MFIE_TYPE_TIM: | ||
976 | IEEE80211_DEBUG_QOS("MFIE_TYPE_TIM: ignored\n"); | ||
977 | break; | ||
978 | |||
979 | case MFIE_TYPE_IBSS_SET: | ||
980 | IEEE80211_DEBUG_QOS("MFIE_TYPE_IBSS_SET: ignored\n"); | ||
981 | break; | ||
982 | |||
983 | case MFIE_TYPE_CHALLENGE: | ||
984 | IEEE80211_DEBUG_QOS("MFIE_TYPE_CHALLENGE: ignored\n"); | ||
985 | break; | ||
986 | |||
987 | case MFIE_TYPE_GENERIC: | ||
988 | IEEE80211_DEBUG_QOS("MFIE_TYPE_GENERIC: %d bytes\n", | ||
989 | info_element->len); | ||
990 | ieee80211_parse_qos_info_param_IE(info_element, | ||
991 | network); | ||
992 | break; | ||
993 | |||
994 | case MFIE_TYPE_RSN: | ||
995 | IEEE80211_DEBUG_QOS("MFIE_TYPE_RSN: %d bytes\n", | ||
996 | info_element->len); | ||
997 | break; | ||
998 | |||
999 | case MFIE_TYPE_QOS_PARAMETER: | ||
1000 | printk("QoS Error need to parse QOS_PARAMETER IE\n"); | ||
1001 | break; | ||
1002 | |||
1003 | default: | ||
1004 | IEEE80211_DEBUG_QOS("unsupported IE %d\n", | ||
1005 | info_element->id); | ||
1006 | break; | ||
1007 | } | ||
1008 | |||
1009 | left -= sizeof(struct ieee80211_info_element) + | ||
1010 | info_element->len; | ||
1011 | info_element = (struct ieee80211_info_element *) | ||
1012 | &info_element->data[info_element->len]; | ||
1013 | } | ||
1014 | |||
1015 | if (ieee->handle_assoc_response != NULL) | ||
1016 | ieee->handle_assoc_response(dev, frame, network); | ||
1017 | |||
1018 | return 0; | ||
1019 | } | ||
1020 | |||
1021 | /***************************************************/ | ||
1022 | |||
1023 | static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response | ||
1024 | *beacon, | ||
1025 | struct ieee80211_network *network, | ||
1026 | struct ieee80211_rx_stats *stats) | ||
1027 | { | 922 | { |
923 | u8 i; | ||
1028 | #ifdef CONFIG_IEEE80211_DEBUG | 924 | #ifdef CONFIG_IEEE80211_DEBUG |
1029 | char rates_str[64]; | 925 | char rates_str[64]; |
1030 | char *p; | 926 | char *p; |
1031 | #endif | 927 | #endif |
1032 | struct ieee80211_info_element *info_element; | ||
1033 | u16 left; | ||
1034 | u8 i; | ||
1035 | network->qos_data.active = 0; | ||
1036 | network->qos_data.supported = 0; | ||
1037 | network->qos_data.param_count = 0; | ||
1038 | 928 | ||
1039 | /* Pull out fixed field data */ | 929 | while (length >= sizeof(*info_element)) { |
1040 | memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); | 930 | if (sizeof(*info_element) + info_element->len > length) { |
1041 | network->capability = le16_to_cpu(beacon->capability); | 931 | IEEE80211_DEBUG_MGMT("Info elem: parse failed: " |
1042 | network->last_scanned = jiffies; | 932 | "info_element->len + 2 > left : " |
1043 | network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]); | 933 | "info_element->len+2=%zd left=%d, id=%d.\n", |
1044 | network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]); | 934 | info_element->len + |
1045 | network->beacon_interval = le16_to_cpu(beacon->beacon_interval); | 935 | sizeof(*info_element), |
1046 | /* Where to pull this? beacon->listen_interval; */ | 936 | length, info_element->id); |
1047 | network->listen_interval = 0x0A; | ||
1048 | network->rates_len = network->rates_ex_len = 0; | ||
1049 | network->last_associate = 0; | ||
1050 | network->ssid_len = 0; | ||
1051 | network->flags = 0; | ||
1052 | network->atim_window = 0; | ||
1053 | network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? | ||
1054 | 0x3 : 0x0; | ||
1055 | |||
1056 | if (stats->freq == IEEE80211_52GHZ_BAND) { | ||
1057 | /* for A band (No DS info) */ | ||
1058 | network->channel = stats->received_channel; | ||
1059 | } else | ||
1060 | network->flags |= NETWORK_HAS_CCK; | ||
1061 | |||
1062 | network->wpa_ie_len = 0; | ||
1063 | network->rsn_ie_len = 0; | ||
1064 | |||
1065 | info_element = beacon->info_element; | ||
1066 | left = stats->len - sizeof(*beacon); | ||
1067 | while (left >= sizeof(*info_element)) { | ||
1068 | if (sizeof(*info_element) + info_element->len > left) { | ||
1069 | IEEE80211_DEBUG_SCAN | ||
1070 | ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n", | ||
1071 | info_element->len + sizeof(*info_element), left); | ||
1072 | return 1; | 937 | return 1; |
1073 | } | 938 | } |
1074 | 939 | ||
@@ -1088,8 +953,8 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i | |||
1088 | memset(network->ssid + network->ssid_len, 0, | 953 | memset(network->ssid + network->ssid_len, 0, |
1089 | IW_ESSID_MAX_SIZE - network->ssid_len); | 954 | IW_ESSID_MAX_SIZE - network->ssid_len); |
1090 | 955 | ||
1091 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n", | 956 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n", |
1092 | network->ssid, network->ssid_len); | 957 | network->ssid, network->ssid_len); |
1093 | break; | 958 | break; |
1094 | 959 | ||
1095 | case MFIE_TYPE_RATES: | 960 | case MFIE_TYPE_RATES: |
@@ -1115,7 +980,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i | |||
1115 | } | 980 | } |
1116 | } | 981 | } |
1117 | 982 | ||
1118 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n", | 983 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n", |
1119 | rates_str, network->rates_len); | 984 | rates_str, network->rates_len); |
1120 | break; | 985 | break; |
1121 | 986 | ||
@@ -1142,47 +1007,46 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i | |||
1142 | } | 1007 | } |
1143 | } | 1008 | } |
1144 | 1009 | ||
1145 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n", | 1010 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n", |
1146 | rates_str, network->rates_ex_len); | 1011 | rates_str, network->rates_ex_len); |
1147 | break; | 1012 | break; |
1148 | 1013 | ||
1149 | case MFIE_TYPE_DS_SET: | 1014 | case MFIE_TYPE_DS_SET: |
1150 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n", | 1015 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n", |
1151 | info_element->data[0]); | 1016 | info_element->data[0]); |
1152 | if (stats->freq == IEEE80211_24GHZ_BAND) | 1017 | network->channel = info_element->data[0]; |
1153 | network->channel = info_element->data[0]; | ||
1154 | break; | 1018 | break; |
1155 | 1019 | ||
1156 | case MFIE_TYPE_FH_SET: | 1020 | case MFIE_TYPE_FH_SET: |
1157 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n"); | 1021 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n"); |
1158 | break; | 1022 | break; |
1159 | 1023 | ||
1160 | case MFIE_TYPE_CF_SET: | 1024 | case MFIE_TYPE_CF_SET: |
1161 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n"); | 1025 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n"); |
1162 | break; | 1026 | break; |
1163 | 1027 | ||
1164 | case MFIE_TYPE_TIM: | 1028 | case MFIE_TYPE_TIM: |
1165 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n"); | 1029 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n"); |
1166 | break; | 1030 | break; |
1167 | 1031 | ||
1168 | case MFIE_TYPE_ERP_INFO: | 1032 | case MFIE_TYPE_ERP_INFO: |
1169 | network->erp_value = info_element->data[0]; | 1033 | network->erp_value = info_element->data[0]; |
1170 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_ERP_SET: %d\n", | 1034 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", |
1171 | network->erp_value); | 1035 | network->erp_value); |
1172 | break; | 1036 | break; |
1173 | 1037 | ||
1174 | case MFIE_TYPE_IBSS_SET: | 1038 | case MFIE_TYPE_IBSS_SET: |
1175 | network->atim_window = info_element->data[0]; | 1039 | network->atim_window = info_element->data[0]; |
1176 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: %d\n", | 1040 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n", |
1177 | network->atim_window); | 1041 | network->atim_window); |
1178 | break; | 1042 | break; |
1179 | 1043 | ||
1180 | case MFIE_TYPE_CHALLENGE: | 1044 | case MFIE_TYPE_CHALLENGE: |
1181 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n"); | 1045 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n"); |
1182 | break; | 1046 | break; |
1183 | 1047 | ||
1184 | case MFIE_TYPE_GENERIC: | 1048 | case MFIE_TYPE_GENERIC: |
1185 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", | 1049 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n", |
1186 | info_element->len); | 1050 | info_element->len); |
1187 | if (!ieee80211_parse_qos_info_param_IE(info_element, | 1051 | if (!ieee80211_parse_qos_info_param_IE(info_element, |
1188 | network)) | 1052 | network)) |
@@ -1201,7 +1065,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i | |||
1201 | break; | 1065 | break; |
1202 | 1066 | ||
1203 | case MFIE_TYPE_RSN: | 1067 | case MFIE_TYPE_RSN: |
1204 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n", | 1068 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n", |
1205 | info_element->len); | 1069 | info_element->len); |
1206 | network->rsn_ie_len = min(info_element->len + 2, | 1070 | network->rsn_ie_len = min(info_element->len + 2, |
1207 | MAX_WPA_IE_LEN); | 1071 | MAX_WPA_IE_LEN); |
@@ -1210,21 +1074,88 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i | |||
1210 | break; | 1074 | break; |
1211 | 1075 | ||
1212 | case MFIE_TYPE_QOS_PARAMETER: | 1076 | case MFIE_TYPE_QOS_PARAMETER: |
1213 | printk(KERN_ERR | 1077 | printk(KERN_ERR "QoS Error need to parse QOS_PARAMETER IE\n"); |
1214 | "QoS Error need to parse QOS_PARAMETER IE\n"); | ||
1215 | break; | 1078 | break; |
1216 | 1079 | ||
1217 | default: | 1080 | default: |
1218 | IEEE80211_DEBUG_SCAN("unsupported IE %d\n", | 1081 | IEEE80211_DEBUG_MGMT("unsupported IE %d\n", |
1219 | info_element->id); | 1082 | info_element->id); |
1220 | break; | 1083 | break; |
1221 | } | 1084 | } |
1222 | 1085 | ||
1223 | left -= sizeof(*info_element) + info_element->len; | 1086 | length -= sizeof(*info_element) + info_element->len; |
1224 | info_element = (struct ieee80211_info_element *) | 1087 | info_element = (struct ieee80211_info_element *) &info_element->data[info_element->len]; |
1225 | &info_element->data[info_element->len]; | ||
1226 | } | 1088 | } |
1227 | 1089 | ||
1090 | return 0; | ||
1091 | } | ||
1092 | |||
1093 | static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response | ||
1094 | *frame, struct ieee80211_rx_stats *stats) | ||
1095 | { | ||
1096 | struct ieee80211_network network_resp; | ||
1097 | struct ieee80211_network *network = &network_resp; | ||
1098 | struct net_device *dev = ieee->dev; | ||
1099 | |||
1100 | network->flags = 0; | ||
1101 | network->qos_data.active = 0; | ||
1102 | network->qos_data.supported = 0; | ||
1103 | network->qos_data.param_count = 0; | ||
1104 | network->qos_data.old_param_count = 0; | ||
1105 | |||
1106 | //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF); | ||
1107 | network->atim_window = le16_to_cpu(frame->aid); | ||
1108 | network->listen_interval = le16_to_cpu(frame->status); | ||
1109 | |||
1110 | if(ieee80211_parse_info_param(frame->info_element, stats->len - sizeof(*frame), network)) | ||
1111 | return 1; | ||
1112 | |||
1113 | if (ieee->handle_assoc_response != NULL) | ||
1114 | ieee->handle_assoc_response(dev, frame, network); | ||
1115 | |||
1116 | return 0; | ||
1117 | } | ||
1118 | |||
1119 | /***************************************************/ | ||
1120 | |||
1121 | static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response | ||
1122 | *beacon, | ||
1123 | struct ieee80211_network *network, | ||
1124 | struct ieee80211_rx_stats *stats) | ||
1125 | { | ||
1126 | network->qos_data.active = 0; | ||
1127 | network->qos_data.supported = 0; | ||
1128 | network->qos_data.param_count = 0; | ||
1129 | |||
1130 | /* Pull out fixed field data */ | ||
1131 | memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); | ||
1132 | network->capability = le16_to_cpu(beacon->capability); | ||
1133 | network->last_scanned = jiffies; | ||
1134 | network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]); | ||
1135 | network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]); | ||
1136 | network->beacon_interval = le16_to_cpu(beacon->beacon_interval); | ||
1137 | /* Where to pull this? beacon->listen_interval; */ | ||
1138 | network->listen_interval = 0x0A; | ||
1139 | network->rates_len = network->rates_ex_len = 0; | ||
1140 | network->last_associate = 0; | ||
1141 | network->ssid_len = 0; | ||
1142 | network->flags = 0; | ||
1143 | network->atim_window = 0; | ||
1144 | network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? | ||
1145 | 0x3 : 0x0; | ||
1146 | |||
1147 | if (stats->freq == IEEE80211_52GHZ_BAND) { | ||
1148 | /* for A band (No DS info) */ | ||
1149 | network->channel = stats->received_channel; | ||
1150 | } else | ||
1151 | network->flags |= NETWORK_HAS_CCK; | ||
1152 | |||
1153 | network->wpa_ie_len = 0; | ||
1154 | network->rsn_ie_len = 0; | ||
1155 | |||
1156 | if(ieee80211_parse_info_param(beacon->info_element, stats->len - sizeof(*beacon), network)) | ||
1157 | return 1; | ||
1158 | |||
1228 | network->mode = 0; | 1159 | network->mode = 0; |
1229 | if (stats->freq == IEEE80211_52GHZ_BAND) | 1160 | if (stats->freq == IEEE80211_52GHZ_BAND) |
1230 | network->mode = IEEE_A; | 1161 | network->mode = IEEE_A; |