|
@@ -917,174 +917,24 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
-static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
|
|
|
- *frame, struct ieee80211_rx_stats *stats)
|
|
|
-{
|
|
|
- struct ieee80211_network network_resp;
|
|
|
- struct ieee80211_network *network = &network_resp;
|
|
|
- struct ieee80211_info_element *info_element;
|
|
|
- struct net_device *dev = ieee->dev;
|
|
|
- u16 left;
|
|
|
-
|
|
|
- network->flags = 0;
|
|
|
- network->qos_data.active = 0;
|
|
|
- network->qos_data.supported = 0;
|
|
|
- network->qos_data.param_count = 0;
|
|
|
- network->qos_data.old_param_count = 0;
|
|
|
-
|
|
|
- //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
|
|
|
- network->atim_window = le16_to_cpu(frame->aid);
|
|
|
- network->listen_interval = le16_to_cpu(frame->status);
|
|
|
-
|
|
|
- info_element = frame->info_element;
|
|
|
- left = stats->len - sizeof(*frame);
|
|
|
-
|
|
|
- while (left >= sizeof(struct ieee80211_info_element)) {
|
|
|
- if (sizeof(struct ieee80211_info_element) +
|
|
|
- info_element->len > left) {
|
|
|
- IEEE80211_DEBUG_QOS("ASSOC RESP: parse failed: "
|
|
|
- "info_element->len + 2 > left : "
|
|
|
- "info_element->len+2=%zd left=%d, id=%d.\n",
|
|
|
- info_element->len +
|
|
|
- sizeof(struct
|
|
|
- ieee80211_info_element),
|
|
|
- left, info_element->id);
|
|
|
- return 1;
|
|
|
- }
|
|
|
-
|
|
|
- switch (info_element->id) {
|
|
|
- case MFIE_TYPE_SSID:
|
|
|
- if (ieee80211_is_empty_essid(info_element->data,
|
|
|
- info_element->len)) {
|
|
|
- network->flags |= NETWORK_EMPTY_ESSID;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- network->ssid_len = min(info_element->len,
|
|
|
- (u8) IW_ESSID_MAX_SIZE);
|
|
|
- memcpy(network->ssid, info_element->data,
|
|
|
- network->ssid_len);
|
|
|
- if (network->ssid_len < IW_ESSID_MAX_SIZE)
|
|
|
- memset(network->ssid + network->ssid_len, 0,
|
|
|
- IW_ESSID_MAX_SIZE - network->ssid_len);
|
|
|
-
|
|
|
- IEEE80211_DEBUG_QOS("MFIE_TYPE_SSID: '%s' len=%d.\n",
|
|
|
- network->ssid, network->ssid_len);
|
|
|
- break;
|
|
|
-
|
|
|
- case MFIE_TYPE_TIM:
|
|
|
- IEEE80211_DEBUG_QOS("MFIE_TYPE_TIM: ignored\n");
|
|
|
- break;
|
|
|
-
|
|
|
- case MFIE_TYPE_IBSS_SET:
|
|
|
- IEEE80211_DEBUG_QOS("MFIE_TYPE_IBSS_SET: ignored\n");
|
|
|
- break;
|
|
|
-
|
|
|
- case MFIE_TYPE_CHALLENGE:
|
|
|
- IEEE80211_DEBUG_QOS("MFIE_TYPE_CHALLENGE: ignored\n");
|
|
|
- break;
|
|
|
-
|
|
|
- case MFIE_TYPE_GENERIC:
|
|
|
- IEEE80211_DEBUG_QOS("MFIE_TYPE_GENERIC: %d bytes\n",
|
|
|
- info_element->len);
|
|
|
- ieee80211_parse_qos_info_param_IE(info_element,
|
|
|
- network);
|
|
|
- break;
|
|
|
-
|
|
|
- case MFIE_TYPE_RSN:
|
|
|
- IEEE80211_DEBUG_QOS("MFIE_TYPE_RSN: %d bytes\n",
|
|
|
- info_element->len);
|
|
|
- break;
|
|
|
-
|
|
|
- case MFIE_TYPE_QOS_PARAMETER:
|
|
|
- printk("QoS Error need to parse QOS_PARAMETER IE\n");
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- IEEE80211_DEBUG_QOS("unsupported IE %d\n",
|
|
|
- info_element->id);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- left -= sizeof(struct ieee80211_info_element) +
|
|
|
- info_element->len;
|
|
|
- info_element = (struct ieee80211_info_element *)
|
|
|
- &info_element->data[info_element->len];
|
|
|
- }
|
|
|
-
|
|
|
- if (ieee->handle_assoc_response != NULL)
|
|
|
- ieee->handle_assoc_response(dev, frame, network);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/***************************************************/
|
|
|
-
|
|
|
-static inline int ieee80211_is_ofdm_rate(u8 rate)
|
|
|
-{
|
|
|
- switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
|
|
|
- case IEEE80211_OFDM_RATE_6MB:
|
|
|
- case IEEE80211_OFDM_RATE_9MB:
|
|
|
- case IEEE80211_OFDM_RATE_12MB:
|
|
|
- case IEEE80211_OFDM_RATE_18MB:
|
|
|
- case IEEE80211_OFDM_RATE_24MB:
|
|
|
- case IEEE80211_OFDM_RATE_36MB:
|
|
|
- case IEEE80211_OFDM_RATE_48MB:
|
|
|
- case IEEE80211_OFDM_RATE_54MB:
|
|
|
- return 1;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
|
|
|
- *beacon,
|
|
|
- struct ieee80211_network *network,
|
|
|
- struct ieee80211_rx_stats *stats)
|
|
|
+static int ieee80211_parse_info_param(struct ieee80211_info_element
|
|
|
+ *info_element, u16 length,
|
|
|
+ struct ieee80211_network *network)
|
|
|
{
|
|
|
+ u8 i;
|
|
|
#ifdef CONFIG_IEEE80211_DEBUG
|
|
|
char rates_str[64];
|
|
|
char *p;
|
|
|
#endif
|
|
|
- struct ieee80211_info_element *info_element;
|
|
|
- u16 left;
|
|
|
- u8 i;
|
|
|
- network->qos_data.active = 0;
|
|
|
- network->qos_data.supported = 0;
|
|
|
- network->qos_data.param_count = 0;
|
|
|
-
|
|
|
- /* Pull out fixed field data */
|
|
|
- memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
|
|
|
- network->capability = le16_to_cpu(beacon->capability);
|
|
|
- network->last_scanned = jiffies;
|
|
|
- network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
|
|
|
- network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
|
|
|
- network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
|
|
|
- /* Where to pull this? beacon->listen_interval; */
|
|
|
- network->listen_interval = 0x0A;
|
|
|
- network->rates_len = network->rates_ex_len = 0;
|
|
|
- network->last_associate = 0;
|
|
|
- network->ssid_len = 0;
|
|
|
- network->flags = 0;
|
|
|
- network->atim_window = 0;
|
|
|
- network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
|
|
|
- 0x3 : 0x0;
|
|
|
|
|
|
- if (stats->freq == IEEE80211_52GHZ_BAND) {
|
|
|
- /* for A band (No DS info) */
|
|
|
- network->channel = stats->received_channel;
|
|
|
- } else
|
|
|
- network->flags |= NETWORK_HAS_CCK;
|
|
|
-
|
|
|
- network->wpa_ie_len = 0;
|
|
|
- network->rsn_ie_len = 0;
|
|
|
-
|
|
|
- info_element = beacon->info_element;
|
|
|
- left = stats->len - sizeof(*beacon);
|
|
|
- while (left >= sizeof(*info_element)) {
|
|
|
- if (sizeof(*info_element) + info_element->len > left) {
|
|
|
- IEEE80211_DEBUG_SCAN
|
|
|
- ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n",
|
|
|
- info_element->len + sizeof(*info_element), left);
|
|
|
+ while (length >= sizeof(*info_element)) {
|
|
|
+ if (sizeof(*info_element) + info_element->len > length) {
|
|
|
+ IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
|
|
|
+ "info_element->len + 2 > left : "
|
|
|
+ "info_element->len+2=%zd left=%d, id=%d.\n",
|
|
|
+ info_element->len +
|
|
|
+ sizeof(*info_element),
|
|
|
+ length, info_element->id);
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
@@ -1104,7 +954,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i
|
|
|
memset(network->ssid + network->ssid_len, 0,
|
|
|
IW_ESSID_MAX_SIZE - network->ssid_len);
|
|
|
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
|
|
|
network->ssid, network->ssid_len);
|
|
|
break;
|
|
|
|
|
@@ -1131,7 +981,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
|
|
|
rates_str, network->rates_len);
|
|
|
break;
|
|
|
|
|
@@ -1158,47 +1008,46 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
|
|
|
rates_str, network->rates_ex_len);
|
|
|
break;
|
|
|
|
|
|
case MFIE_TYPE_DS_SET:
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
|
|
|
info_element->data[0]);
|
|
|
- if (stats->freq == IEEE80211_24GHZ_BAND)
|
|
|
- network->channel = info_element->data[0];
|
|
|
+ network->channel = info_element->data[0];
|
|
|
break;
|
|
|
|
|
|
case MFIE_TYPE_FH_SET:
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
|
|
|
break;
|
|
|
|
|
|
case MFIE_TYPE_CF_SET:
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
|
|
|
break;
|
|
|
|
|
|
case MFIE_TYPE_TIM:
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n");
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n");
|
|
|
break;
|
|
|
|
|
|
case MFIE_TYPE_ERP_INFO:
|
|
|
network->erp_value = info_element->data[0];
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_ERP_SET: %d\n",
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
|
|
|
network->erp_value);
|
|
|
break;
|
|
|
|
|
|
case MFIE_TYPE_IBSS_SET:
|
|
|
network->atim_window = info_element->data[0];
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: %d\n",
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
|
|
|
network->atim_window);
|
|
|
break;
|
|
|
|
|
|
case MFIE_TYPE_CHALLENGE:
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
|
|
|
break;
|
|
|
|
|
|
case MFIE_TYPE_GENERIC:
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
|
|
|
info_element->len);
|
|
|
if (!ieee80211_parse_qos_info_param_IE(info_element,
|
|
|
network))
|
|
@@ -1217,7 +1066,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i
|
|
|
break;
|
|
|
|
|
|
case MFIE_TYPE_RSN:
|
|
|
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
|
|
|
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
|
|
|
info_element->len);
|
|
|
network->rsn_ie_len = min(info_element->len + 2,
|
|
|
MAX_WPA_IE_LEN);
|
|
@@ -1231,16 +1080,121 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
- IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
|
|
|
+ IEEE80211_DEBUG_MGMT("unsupported IE %d\n",
|
|
|
info_element->id);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- left -= sizeof(*info_element) + info_element->len;
|
|
|
- info_element = (struct ieee80211_info_element *)
|
|
|
- &info_element->data[info_element->len];
|
|
|
+ length -= sizeof(*info_element) + info_element->len;
|
|
|
+ info_element =
|
|
|
+ (struct ieee80211_info_element *)&info_element->
|
|
|
+ data[info_element->len];
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
|
|
|
+ *frame, struct ieee80211_rx_stats *stats)
|
|
|
+{
|
|
|
+ struct ieee80211_network network_resp;
|
|
|
+ struct ieee80211_network *network = &network_resp;
|
|
|
+ struct net_device *dev = ieee->dev;
|
|
|
+
|
|
|
+ network->flags = 0;
|
|
|
+ network->qos_data.active = 0;
|
|
|
+ network->qos_data.supported = 0;
|
|
|
+ network->qos_data.param_count = 0;
|
|
|
+ network->qos_data.old_param_count = 0;
|
|
|
+
|
|
|
+ //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
|
|
|
+ network->atim_window = le16_to_cpu(frame->aid);
|
|
|
+ network->listen_interval = le16_to_cpu(frame->status);
|
|
|
+ memcpy(network->bssid, frame->header.addr3, ETH_ALEN);
|
|
|
+ network->capability = le16_to_cpu(frame->capability);
|
|
|
+ network->last_scanned = jiffies;
|
|
|
+ network->rates_len = network->rates_ex_len = 0;
|
|
|
+ network->last_associate = 0;
|
|
|
+ network->ssid_len = 0;
|
|
|
+ network->erp_value =
|
|
|
+ (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0;
|
|
|
+
|
|
|
+ if (stats->freq == IEEE80211_52GHZ_BAND) {
|
|
|
+ /* for A band (No DS info) */
|
|
|
+ network->channel = stats->received_channel;
|
|
|
+ } else
|
|
|
+ network->flags |= NETWORK_HAS_CCK;
|
|
|
+
|
|
|
+ network->wpa_ie_len = 0;
|
|
|
+ network->rsn_ie_len = 0;
|
|
|
+
|
|
|
+ if (ieee80211_parse_info_param
|
|
|
+ (frame->info_element, stats->len - sizeof(*frame), network))
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ network->mode = 0;
|
|
|
+ if (stats->freq == IEEE80211_52GHZ_BAND)
|
|
|
+ network->mode = IEEE_A;
|
|
|
+ else {
|
|
|
+ if (network->flags & NETWORK_HAS_OFDM)
|
|
|
+ network->mode |= IEEE_G;
|
|
|
+ if (network->flags & NETWORK_HAS_CCK)
|
|
|
+ network->mode |= IEEE_B;
|
|
|
}
|
|
|
|
|
|
+ if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
|
|
|
+ network->flags |= NETWORK_EMPTY_ESSID;
|
|
|
+
|
|
|
+ memcpy(&network->stats, stats, sizeof(network->stats));
|
|
|
+
|
|
|
+ if (ieee->handle_assoc_response != NULL)
|
|
|
+ ieee->handle_assoc_response(dev, frame, network);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/***************************************************/
|
|
|
+
|
|
|
+static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
|
|
|
+ *beacon,
|
|
|
+ struct ieee80211_network *network,
|
|
|
+ struct ieee80211_rx_stats *stats)
|
|
|
+{
|
|
|
+ network->qos_data.active = 0;
|
|
|
+ network->qos_data.supported = 0;
|
|
|
+ network->qos_data.param_count = 0;
|
|
|
+ network->qos_data.old_param_count = 0;
|
|
|
+
|
|
|
+ /* Pull out fixed field data */
|
|
|
+ memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
|
|
|
+ network->capability = le16_to_cpu(beacon->capability);
|
|
|
+ network->last_scanned = jiffies;
|
|
|
+ network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
|
|
|
+ network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
|
|
|
+ network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
|
|
|
+ /* Where to pull this? beacon->listen_interval; */
|
|
|
+ network->listen_interval = 0x0A;
|
|
|
+ network->rates_len = network->rates_ex_len = 0;
|
|
|
+ network->last_associate = 0;
|
|
|
+ network->ssid_len = 0;
|
|
|
+ network->flags = 0;
|
|
|
+ network->atim_window = 0;
|
|
|
+ network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
|
|
|
+ 0x3 : 0x0;
|
|
|
+
|
|
|
+ if (stats->freq == IEEE80211_52GHZ_BAND) {
|
|
|
+ /* for A band (No DS info) */
|
|
|
+ network->channel = stats->received_channel;
|
|
|
+ } else
|
|
|
+ network->flags |= NETWORK_HAS_CCK;
|
|
|
+
|
|
|
+ network->wpa_ie_len = 0;
|
|
|
+ network->rsn_ie_len = 0;
|
|
|
+
|
|
|
+ if (ieee80211_parse_info_param
|
|
|
+ (beacon->info_element, stats->len - sizeof(*beacon), network))
|
|
|
+ return 1;
|
|
|
+
|
|
|
network->mode = 0;
|
|
|
if (stats->freq == IEEE80211_52GHZ_BAND)
|
|
|
network->mode = IEEE_A;
|