diff options
Diffstat (limited to 'net/ieee80211')
-rw-r--r-- | net/ieee80211/ieee80211_rx.c | 314 |
1 files changed, 134 insertions, 180 deletions
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index fcf05bf677b8..6b005cb0caa0 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c | |||
@@ -917,174 +917,24 @@ 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 |
921 | *frame, struct ieee80211_rx_stats *stats) | 921 | *info_element, u16 length, |
922 | { | 922 | struct ieee80211_network *network) |
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_is_ofdm_rate(u8 rate) | ||
1024 | { | ||
1025 | switch (rate & ~IEEE80211_BASIC_RATE_MASK) { | ||
1026 | case IEEE80211_OFDM_RATE_6MB: | ||
1027 | case IEEE80211_OFDM_RATE_9MB: | ||
1028 | case IEEE80211_OFDM_RATE_12MB: | ||
1029 | case IEEE80211_OFDM_RATE_18MB: | ||
1030 | case IEEE80211_OFDM_RATE_24MB: | ||
1031 | case IEEE80211_OFDM_RATE_36MB: | ||
1032 | case IEEE80211_OFDM_RATE_48MB: | ||
1033 | case IEEE80211_OFDM_RATE_54MB: | ||
1034 | return 1; | ||
1035 | } | ||
1036 | return 0; | ||
1037 | } | ||
1038 | |||
1039 | static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response | ||
1040 | *beacon, | ||
1041 | struct ieee80211_network *network, | ||
1042 | struct ieee80211_rx_stats *stats) | ||
1043 | { | 923 | { |
924 | u8 i; | ||
1044 | #ifdef CONFIG_IEEE80211_DEBUG | 925 | #ifdef CONFIG_IEEE80211_DEBUG |
1045 | char rates_str[64]; | 926 | char rates_str[64]; |
1046 | char *p; | 927 | char *p; |
1047 | #endif | 928 | #endif |
1048 | struct ieee80211_info_element *info_element; | ||
1049 | u16 left; | ||
1050 | u8 i; | ||
1051 | network->qos_data.active = 0; | ||
1052 | network->qos_data.supported = 0; | ||
1053 | network->qos_data.param_count = 0; | ||
1054 | |||
1055 | /* Pull out fixed field data */ | ||
1056 | memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); | ||
1057 | network->capability = le16_to_cpu(beacon->capability); | ||
1058 | network->last_scanned = jiffies; | ||
1059 | network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]); | ||
1060 | network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]); | ||
1061 | network->beacon_interval = le16_to_cpu(beacon->beacon_interval); | ||
1062 | /* Where to pull this? beacon->listen_interval; */ | ||
1063 | network->listen_interval = 0x0A; | ||
1064 | network->rates_len = network->rates_ex_len = 0; | ||
1065 | network->last_associate = 0; | ||
1066 | network->ssid_len = 0; | ||
1067 | network->flags = 0; | ||
1068 | network->atim_window = 0; | ||
1069 | network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? | ||
1070 | 0x3 : 0x0; | ||
1071 | 929 | ||
1072 | if (stats->freq == IEEE80211_52GHZ_BAND) { | 930 | while (length >= sizeof(*info_element)) { |
1073 | /* for A band (No DS info) */ | 931 | if (sizeof(*info_element) + info_element->len > length) { |
1074 | network->channel = stats->received_channel; | 932 | IEEE80211_DEBUG_MGMT("Info elem: parse failed: " |
1075 | } else | 933 | "info_element->len + 2 > left : " |
1076 | network->flags |= NETWORK_HAS_CCK; | 934 | "info_element->len+2=%zd left=%d, id=%d.\n", |
1077 | 935 | info_element->len + | |
1078 | network->wpa_ie_len = 0; | 936 | sizeof(*info_element), |
1079 | network->rsn_ie_len = 0; | 937 | length, info_element->id); |
1080 | |||
1081 | info_element = beacon->info_element; | ||
1082 | left = stats->len - sizeof(*beacon); | ||
1083 | while (left >= sizeof(*info_element)) { | ||
1084 | if (sizeof(*info_element) + info_element->len > left) { | ||
1085 | IEEE80211_DEBUG_SCAN | ||
1086 | ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n", | ||
1087 | info_element->len + sizeof(*info_element), left); | ||
1088 | return 1; | 938 | return 1; |
1089 | } | 939 | } |
1090 | 940 | ||
@@ -1104,7 +954,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i | |||
1104 | memset(network->ssid + network->ssid_len, 0, | 954 | memset(network->ssid + network->ssid_len, 0, |
1105 | IW_ESSID_MAX_SIZE - network->ssid_len); | 955 | IW_ESSID_MAX_SIZE - network->ssid_len); |
1106 | 956 | ||
1107 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n", | 957 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n", |
1108 | network->ssid, network->ssid_len); | 958 | network->ssid, network->ssid_len); |
1109 | break; | 959 | break; |
1110 | 960 | ||
@@ -1131,7 +981,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i | |||
1131 | } | 981 | } |
1132 | } | 982 | } |
1133 | 983 | ||
1134 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n", | 984 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n", |
1135 | rates_str, network->rates_len); | 985 | rates_str, network->rates_len); |
1136 | break; | 986 | break; |
1137 | 987 | ||
@@ -1158,47 +1008,46 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i | |||
1158 | } | 1008 | } |
1159 | } | 1009 | } |
1160 | 1010 | ||
1161 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n", | 1011 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n", |
1162 | rates_str, network->rates_ex_len); | 1012 | rates_str, network->rates_ex_len); |
1163 | break; | 1013 | break; |
1164 | 1014 | ||
1165 | case MFIE_TYPE_DS_SET: | 1015 | case MFIE_TYPE_DS_SET: |
1166 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n", | 1016 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n", |
1167 | info_element->data[0]); | 1017 | info_element->data[0]); |
1168 | if (stats->freq == IEEE80211_24GHZ_BAND) | 1018 | network->channel = info_element->data[0]; |
1169 | network->channel = info_element->data[0]; | ||
1170 | break; | 1019 | break; |
1171 | 1020 | ||
1172 | case MFIE_TYPE_FH_SET: | 1021 | case MFIE_TYPE_FH_SET: |
1173 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n"); | 1022 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n"); |
1174 | break; | 1023 | break; |
1175 | 1024 | ||
1176 | case MFIE_TYPE_CF_SET: | 1025 | case MFIE_TYPE_CF_SET: |
1177 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n"); | 1026 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n"); |
1178 | break; | 1027 | break; |
1179 | 1028 | ||
1180 | case MFIE_TYPE_TIM: | 1029 | case MFIE_TYPE_TIM: |
1181 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n"); | 1030 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n"); |
1182 | break; | 1031 | break; |
1183 | 1032 | ||
1184 | case MFIE_TYPE_ERP_INFO: | 1033 | case MFIE_TYPE_ERP_INFO: |
1185 | network->erp_value = info_element->data[0]; | 1034 | network->erp_value = info_element->data[0]; |
1186 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_ERP_SET: %d\n", | 1035 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", |
1187 | network->erp_value); | 1036 | network->erp_value); |
1188 | break; | 1037 | break; |
1189 | 1038 | ||
1190 | case MFIE_TYPE_IBSS_SET: | 1039 | case MFIE_TYPE_IBSS_SET: |
1191 | network->atim_window = info_element->data[0]; | 1040 | network->atim_window = info_element->data[0]; |
1192 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: %d\n", | 1041 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n", |
1193 | network->atim_window); | 1042 | network->atim_window); |
1194 | break; | 1043 | break; |
1195 | 1044 | ||
1196 | case MFIE_TYPE_CHALLENGE: | 1045 | case MFIE_TYPE_CHALLENGE: |
1197 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n"); | 1046 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n"); |
1198 | break; | 1047 | break; |
1199 | 1048 | ||
1200 | case MFIE_TYPE_GENERIC: | 1049 | case MFIE_TYPE_GENERIC: |
1201 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", | 1050 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n", |
1202 | info_element->len); | 1051 | info_element->len); |
1203 | if (!ieee80211_parse_qos_info_param_IE(info_element, | 1052 | if (!ieee80211_parse_qos_info_param_IE(info_element, |
1204 | network)) | 1053 | network)) |
@@ -1217,7 +1066,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i | |||
1217 | break; | 1066 | break; |
1218 | 1067 | ||
1219 | case MFIE_TYPE_RSN: | 1068 | case MFIE_TYPE_RSN: |
1220 | IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n", | 1069 | IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n", |
1221 | info_element->len); | 1070 | info_element->len); |
1222 | network->rsn_ie_len = min(info_element->len + 2, | 1071 | network->rsn_ie_len = min(info_element->len + 2, |
1223 | MAX_WPA_IE_LEN); | 1072 | MAX_WPA_IE_LEN); |
@@ -1231,16 +1080,121 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i | |||
1231 | break; | 1080 | break; |
1232 | 1081 | ||
1233 | default: | 1082 | default: |
1234 | IEEE80211_DEBUG_SCAN("unsupported IE %d\n", | 1083 | IEEE80211_DEBUG_MGMT("unsupported IE %d\n", |
1235 | info_element->id); | 1084 | info_element->id); |
1236 | break; | 1085 | break; |
1237 | } | 1086 | } |
1238 | 1087 | ||
1239 | left -= sizeof(*info_element) + info_element->len; | 1088 | length -= sizeof(*info_element) + info_element->len; |
1240 | info_element = (struct ieee80211_info_element *) | 1089 | info_element = |
1241 | &info_element->data[info_element->len]; | 1090 | (struct ieee80211_info_element *)&info_element-> |
1091 | data[info_element->len]; | ||
1092 | } | ||
1093 | |||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response | ||
1098 | *frame, struct ieee80211_rx_stats *stats) | ||
1099 | { | ||
1100 | struct ieee80211_network network_resp; | ||
1101 | struct ieee80211_network *network = &network_resp; | ||
1102 | struct net_device *dev = ieee->dev; | ||
1103 | |||
1104 | network->flags = 0; | ||
1105 | network->qos_data.active = 0; | ||
1106 | network->qos_data.supported = 0; | ||
1107 | network->qos_data.param_count = 0; | ||
1108 | network->qos_data.old_param_count = 0; | ||
1109 | |||
1110 | //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF); | ||
1111 | network->atim_window = le16_to_cpu(frame->aid); | ||
1112 | network->listen_interval = le16_to_cpu(frame->status); | ||
1113 | memcpy(network->bssid, frame->header.addr3, ETH_ALEN); | ||
1114 | network->capability = le16_to_cpu(frame->capability); | ||
1115 | network->last_scanned = jiffies; | ||
1116 | network->rates_len = network->rates_ex_len = 0; | ||
1117 | network->last_associate = 0; | ||
1118 | network->ssid_len = 0; | ||
1119 | network->erp_value = | ||
1120 | (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0; | ||
1121 | |||
1122 | if (stats->freq == IEEE80211_52GHZ_BAND) { | ||
1123 | /* for A band (No DS info) */ | ||
1124 | network->channel = stats->received_channel; | ||
1125 | } else | ||
1126 | network->flags |= NETWORK_HAS_CCK; | ||
1127 | |||
1128 | network->wpa_ie_len = 0; | ||
1129 | network->rsn_ie_len = 0; | ||
1130 | |||
1131 | if (ieee80211_parse_info_param | ||
1132 | (frame->info_element, stats->len - sizeof(*frame), network)) | ||
1133 | return 1; | ||
1134 | |||
1135 | network->mode = 0; | ||
1136 | if (stats->freq == IEEE80211_52GHZ_BAND) | ||
1137 | network->mode = IEEE_A; | ||
1138 | else { | ||
1139 | if (network->flags & NETWORK_HAS_OFDM) | ||
1140 | network->mode |= IEEE_G; | ||
1141 | if (network->flags & NETWORK_HAS_CCK) | ||
1142 | network->mode |= IEEE_B; | ||
1242 | } | 1143 | } |
1243 | 1144 | ||
1145 | if (ieee80211_is_empty_essid(network->ssid, network->ssid_len)) | ||
1146 | network->flags |= NETWORK_EMPTY_ESSID; | ||
1147 | |||
1148 | memcpy(&network->stats, stats, sizeof(network->stats)); | ||
1149 | |||
1150 | if (ieee->handle_assoc_response != NULL) | ||
1151 | ieee->handle_assoc_response(dev, frame, network); | ||
1152 | |||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1156 | /***************************************************/ | ||
1157 | |||
1158 | static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response | ||
1159 | *beacon, | ||
1160 | struct ieee80211_network *network, | ||
1161 | struct ieee80211_rx_stats *stats) | ||
1162 | { | ||
1163 | network->qos_data.active = 0; | ||
1164 | network->qos_data.supported = 0; | ||
1165 | network->qos_data.param_count = 0; | ||
1166 | network->qos_data.old_param_count = 0; | ||
1167 | |||
1168 | /* Pull out fixed field data */ | ||
1169 | memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); | ||
1170 | network->capability = le16_to_cpu(beacon->capability); | ||
1171 | network->last_scanned = jiffies; | ||
1172 | network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]); | ||
1173 | network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]); | ||
1174 | network->beacon_interval = le16_to_cpu(beacon->beacon_interval); | ||
1175 | /* Where to pull this? beacon->listen_interval; */ | ||
1176 | network->listen_interval = 0x0A; | ||
1177 | network->rates_len = network->rates_ex_len = 0; | ||
1178 | network->last_associate = 0; | ||
1179 | network->ssid_len = 0; | ||
1180 | network->flags = 0; | ||
1181 | network->atim_window = 0; | ||
1182 | network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? | ||
1183 | 0x3 : 0x0; | ||
1184 | |||
1185 | if (stats->freq == IEEE80211_52GHZ_BAND) { | ||
1186 | /* for A band (No DS info) */ | ||
1187 | network->channel = stats->received_channel; | ||
1188 | } else | ||
1189 | network->flags |= NETWORK_HAS_CCK; | ||
1190 | |||
1191 | network->wpa_ie_len = 0; | ||
1192 | network->rsn_ie_len = 0; | ||
1193 | |||
1194 | if (ieee80211_parse_info_param | ||
1195 | (beacon->info_element, stats->len - sizeof(*beacon), network)) | ||
1196 | return 1; | ||
1197 | |||
1244 | network->mode = 0; | 1198 | network->mode = 0; |
1245 | if (stats->freq == IEEE80211_52GHZ_BAND) | 1199 | if (stats->freq == IEEE80211_52GHZ_BAND) |
1246 | network->mode = IEEE_A; | 1200 | network->mode = IEEE_A; |