|
@@ -45,276 +45,6 @@
|
|
|
#include "rtllib.h"
|
|
|
#include "dot11d.h"
|
|
|
|
|
|
-#if defined CONFIG_CFG_80211
|
|
|
-#include <linux/crc32.h>
|
|
|
-
|
|
|
-struct ieee80211_channel *rtllib_get_channel(struct wiphy *wiphy,
|
|
|
- int freq)
|
|
|
-{
|
|
|
- enum ieee80211_band band;
|
|
|
- struct ieee80211_supported_band *sband;
|
|
|
- int i;
|
|
|
-
|
|
|
- for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
|
|
- sband = wiphy->bands[band];
|
|
|
-
|
|
|
- if (!sband)
|
|
|
- continue;
|
|
|
-
|
|
|
- for (i = 0; i < sband->n_channels; i++) {
|
|
|
- if (sband->channels[i].center_freq == freq)
|
|
|
- return &sband->channels[i];
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-int rtllib_channel_to_frequency(int chan)
|
|
|
-{
|
|
|
- if (chan < 14)
|
|
|
- return 2407 + chan * 5;
|
|
|
-
|
|
|
- if (chan == 14)
|
|
|
- return 2484;
|
|
|
-
|
|
|
- /* FIXME: 802.11j 17.3.8.3.2 */
|
|
|
- return (chan + 1000) * 5;
|
|
|
-}
|
|
|
-
|
|
|
-u32 rtllib_parse_elems_crc(u8 *start, size_t len,
|
|
|
- struct ieee802_11_elems *elems,
|
|
|
- u64 filter, u32 crc)
|
|
|
-{
|
|
|
- size_t left = len;
|
|
|
- u8 *pos = start;
|
|
|
- bool calc_crc = filter != 0;
|
|
|
-
|
|
|
- memset(elems, 0, sizeof(*elems));
|
|
|
- elems->ie_start = start;
|
|
|
- elems->total_len = len;
|
|
|
-
|
|
|
- while (left >= 2) {
|
|
|
- u8 id, elen;
|
|
|
-
|
|
|
- id = *pos++;
|
|
|
- elen = *pos++;
|
|
|
- left -= 2;
|
|
|
-
|
|
|
- if (elen > left)
|
|
|
- break;
|
|
|
-
|
|
|
- if (calc_crc && id < 64 && (filter & BIT(id)))
|
|
|
- crc = crc32_be(crc, pos - 2, elen + 2);
|
|
|
-
|
|
|
- switch (id) {
|
|
|
- case WLAN_EID_SSID:
|
|
|
- elems->ssid = pos;
|
|
|
- elems->ssid_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_SUPP_RATES:
|
|
|
- elems->supp_rates = pos;
|
|
|
- elems->supp_rates_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_FH_PARAMS:
|
|
|
- elems->fh_params = pos;
|
|
|
- elems->fh_params_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_DS_PARAMS:
|
|
|
- elems->ds_params = pos;
|
|
|
- elems->ds_params_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_CF_PARAMS:
|
|
|
- elems->cf_params = pos;
|
|
|
- elems->cf_params_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_TIM:
|
|
|
- if (elen >= sizeof(struct ieee80211_tim_ie)) {
|
|
|
- elems->tim = (void *)pos;
|
|
|
- elems->tim_len = elen;
|
|
|
- }
|
|
|
- break;
|
|
|
- case WLAN_EID_IBSS_PARAMS:
|
|
|
- elems->ibss_params = pos;
|
|
|
- elems->ibss_params_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_CHALLENGE:
|
|
|
- elems->challenge = pos;
|
|
|
- elems->challenge_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_VENDOR_SPECIFIC:
|
|
|
- if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
|
|
|
- pos[2] == 0xf2) {
|
|
|
- /* Microsoft OUI (00:50:F2) */
|
|
|
-
|
|
|
- if (calc_crc)
|
|
|
- crc = crc32_be(crc, pos - 2, elen + 2);
|
|
|
-
|
|
|
- if (pos[3] == 1) {
|
|
|
- /* OUI Type 1 - WPA IE */
|
|
|
- elems->wpa = pos;
|
|
|
- elems->wpa_len = elen;
|
|
|
- } else if (elen >= 5 && pos[3] == 2) {
|
|
|
- /* OUI Type 2 - WMM IE */
|
|
|
- if (pos[4] == 0) {
|
|
|
- elems->wmm_info = pos;
|
|
|
- elems->wmm_info_len = elen;
|
|
|
- } else if (pos[4] == 1) {
|
|
|
- elems->wmm_param = pos;
|
|
|
- elems->wmm_param_len = elen;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
- case WLAN_EID_RSN:
|
|
|
- elems->rsn = pos;
|
|
|
- elems->rsn_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_ERP_INFO:
|
|
|
- elems->erp_info = pos;
|
|
|
- elems->erp_info_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_EXT_SUPP_RATES:
|
|
|
- elems->ext_supp_rates = pos;
|
|
|
- elems->ext_supp_rates_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_HT_CAPABILITY:
|
|
|
- if (elen >= sizeof(struct ieee80211_ht_cap))
|
|
|
- elems->ht_cap_elem = (void *)pos;
|
|
|
- break;
|
|
|
- case WLAN_EID_HT_INFORMATION:
|
|
|
- if (elen >= sizeof(struct ieee80211_ht_info))
|
|
|
- elems->ht_info_elem = (void *)pos;
|
|
|
- break;
|
|
|
- case WLAN_EID_MESH_ID:
|
|
|
- elems->mesh_id = pos;
|
|
|
- elems->mesh_id_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_MESH_CONFIG:
|
|
|
- elems->mesh_config = pos;
|
|
|
- elems->mesh_config_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_PEER_LINK:
|
|
|
- elems->peer_link = pos;
|
|
|
- elems->peer_link_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_PREQ:
|
|
|
- elems->preq = pos;
|
|
|
- elems->preq_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_PREP:
|
|
|
- elems->prep = pos;
|
|
|
- elems->prep_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_PERR:
|
|
|
- elems->perr = pos;
|
|
|
- elems->perr_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_CHANNEL_SWITCH:
|
|
|
- elems->ch_switch_elem = pos;
|
|
|
- elems->ch_switch_elem_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_QUIET:
|
|
|
- if (!elems->quiet_elem) {
|
|
|
- elems->quiet_elem = pos;
|
|
|
- elems->quiet_elem_len = elen;
|
|
|
- }
|
|
|
- elems->num_of_quiet_elem++;
|
|
|
- break;
|
|
|
- case WLAN_EID_COUNTRY:
|
|
|
- elems->country_elem = pos;
|
|
|
- elems->country_elem_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_PWR_CONSTRAINT:
|
|
|
- elems->pwr_constr_elem = pos;
|
|
|
- elems->pwr_constr_elem_len = elen;
|
|
|
- break;
|
|
|
- case WLAN_EID_TIMEOUT_INTERVAL:
|
|
|
- elems->timeout_int = pos;
|
|
|
- elems->timeout_int_len = elen;
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- left -= elen;
|
|
|
- pos += elen;
|
|
|
- }
|
|
|
-
|
|
|
- return crc;
|
|
|
-}
|
|
|
-
|
|
|
-void rtllib_parse_elems(u8 *start, size_t len,
|
|
|
- struct ieee802_11_elems *elems)
|
|
|
-{
|
|
|
- rtllib_parse_elems_crc(start, len, elems, 0, 0);
|
|
|
-}
|
|
|
-
|
|
|
-void ieee80211_scan_rx(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_status)
|
|
|
-{
|
|
|
- struct rtllib_hdr_4addr *header = (struct rtllib_hdr_4addr *)skb->data ;
|
|
|
- struct ieee80211_mgmt *mgmt;
|
|
|
- struct ieee80211_bss *bss;
|
|
|
- u8 *elements;
|
|
|
- struct ieee80211_channel *channel;
|
|
|
- size_t baselen;
|
|
|
- int freq;
|
|
|
- __le16 fc;
|
|
|
- bool presp, beacon = false;
|
|
|
- struct ieee802_11_elems elems;
|
|
|
- s32 signal = 0;
|
|
|
-
|
|
|
- if (skb->len < 2)
|
|
|
- return;
|
|
|
-
|
|
|
- mgmt = (struct ieee80211_mgmt *) skb->data;
|
|
|
- fc = mgmt->frame_control;
|
|
|
-
|
|
|
- if (skb->len < 24)
|
|
|
- return;
|
|
|
-
|
|
|
- presp = (WLAN_FC_GET_STYPE(header->frame_ctl) == RTLLIB_STYPE_PROBE_RESP);
|
|
|
- if (presp) {
|
|
|
- /* ignore ProbeResp to foreign address */
|
|
|
- if (memcmp(mgmt->da, ieee->dev->dev_addr, ETH_ALEN))
|
|
|
- return ;;
|
|
|
-
|
|
|
- presp = true;
|
|
|
- elements = mgmt->u.probe_resp.variable;
|
|
|
- baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
|
|
|
- } else {
|
|
|
- beacon = (WLAN_FC_GET_STYPE(header->frame_ctl) == RTLLIB_STYPE_BEACON);
|
|
|
- baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
|
|
|
- elements = mgmt->u.beacon.variable;
|
|
|
- }
|
|
|
-
|
|
|
- if (!presp && !beacon)
|
|
|
- return;
|
|
|
-
|
|
|
- if (baselen > skb->len)
|
|
|
- return;
|
|
|
-
|
|
|
- rtllib_parse_elems(elements, skb->len - baselen, &elems);
|
|
|
-
|
|
|
- if (elems.ds_params && elems.ds_params_len == 1)
|
|
|
- freq = rtllib_channel_to_frequency(elems.ds_params[0]);
|
|
|
- else
|
|
|
- return;
|
|
|
-
|
|
|
- channel = rtllib_get_channel(ieee->wdev.wiphy, freq);
|
|
|
-
|
|
|
- if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
|
|
|
- return;
|
|
|
-
|
|
|
- signal = rx_status->signal * 100;
|
|
|
-
|
|
|
- bss = (void *)cfg80211_inform_bss_frame(ieee->wdev.wiphy, channel,
|
|
|
- mgmt, skb->len, signal, GFP_ATOMIC);
|
|
|
-
|
|
|
- return;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
static inline void rtllib_monitor_rx(struct rtllib_device *ieee,
|
|
|
struct sk_buff *skb,struct rtllib_rx_stats *rx_status,
|
|
|
size_t hdr_length)
|
|
@@ -499,7 +229,6 @@ rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-#ifndef CONFIG_CFG_80211
|
|
|
/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
|
|
|
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
|
|
|
static unsigned char rfc1042_header[] =
|
|
@@ -508,7 +237,6 @@ static unsigned char rfc1042_header[] =
|
|
|
static unsigned char bridge_tunnel_header[] =
|
|
|
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
|
|
|
/* No encapsulation header if EtherType < 0x600 (=length) */
|
|
|
-#endif
|
|
|
|
|
|
/* Called by rtllib_rx_frame_decrypt */
|
|
|
static int rtllib_is_eapol_frame(struct rtllib_device *ieee,
|