Commit ab3d59d2 authored by John W. Linville's avatar John W. Linville

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless

Conflicts:
	drivers/net/wireless/mwifiex/cfg80211.c
parents 42d36074 8c6e3093
...@@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { ...@@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
{ USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
{ USB_DEVICE(0x040D, 0x3801) }, /* VIA */ { USB_DEVICE(0x040D, 0x3801) }, /* VIA */
{ USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */
{ USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */
{ USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */
{ USB_DEVICE(0x0cf3, 0x7015), { USB_DEVICE(0x0cf3, 0x7015),
......
...@@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) ...@@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
} }
bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
bf->bf_next = NULL;
list_del(&bf->list); list_del(&bf->list);
spin_unlock_bh(&sc->tx.txbuflock); spin_unlock_bh(&sc->tx.txbuflock);
...@@ -1774,6 +1775,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, ...@@ -1774,6 +1775,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
list_add_tail(&bf->list, &bf_head); list_add_tail(&bf->list, &bf_head);
bf->bf_state.bf_type = 0; bf->bf_state.bf_type = 0;
bf->bf_next = NULL;
bf->bf_lastbf = bf; bf->bf_lastbf = bf;
ath_tx_fill_desc(sc, bf, txq, fi->framelen); ath_tx_fill_desc(sc, bf, txq, fi->framelen);
ath_tx_txqaddbuf(sc, txq, &bf_head, false); ath_tx_txqaddbuf(sc, txq, &bf_head, false);
......
...@@ -5404,6 +5404,8 @@ static void b43_bcma_remove(struct bcma_device *core) ...@@ -5404,6 +5404,8 @@ static void b43_bcma_remove(struct bcma_device *core)
cancel_work_sync(&wldev->restart_work); cancel_work_sync(&wldev->restart_work);
B43_WARN_ON(!wl); B43_WARN_ON(!wl);
if (!wldev->fw.ucode.data)
return; /* NULL if firmware never loaded */
if (wl->current_dev == wldev && wl->hw_registred) { if (wl->current_dev == wldev && wl->hw_registred) {
b43_leds_stop(wldev); b43_leds_stop(wldev);
ieee80211_unregister_hw(wl->hw); ieee80211_unregister_hw(wl->hw);
...@@ -5478,6 +5480,8 @@ static void b43_ssb_remove(struct ssb_device *sdev) ...@@ -5478,6 +5480,8 @@ static void b43_ssb_remove(struct ssb_device *sdev)
cancel_work_sync(&wldev->restart_work); cancel_work_sync(&wldev->restart_work);
B43_WARN_ON(!wl); B43_WARN_ON(!wl);
if (!wldev->fw.ucode.data)
return; /* NULL if firmware never loaded */
if (wl->current_dev == wldev && wl->hw_registred) { if (wl->current_dev == wldev && wl->hw_registred) {
b43_leds_stop(wldev); b43_leds_stop(wldev);
ieee80211_unregister_hw(wl->hw); ieee80211_unregister_hw(wl->hw);
......
...@@ -3366,7 +3366,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, ...@@ -3366,7 +3366,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
if (!request || !request->n_ssids || !request->n_match_sets) { if (!request || !request->n_ssids || !request->n_match_sets) {
WL_ERR("Invalid sched scan req!! n_ssids:%d\n", WL_ERR("Invalid sched scan req!! n_ssids:%d\n",
request->n_ssids); request ? request->n_ssids : 0);
return -EINVAL; return -EINVAL;
} }
......
...@@ -1826,8 +1826,6 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, ...@@ -1826,8 +1826,6 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
return -EBUSY; return -EBUSY;
} }
priv->scan_request = request;
if (priv->user_scan_cfg) { if (priv->user_scan_cfg) {
dev_err(priv->adapter->dev, "cmd: Scan already in process..\n"); dev_err(priv->adapter->dev, "cmd: Scan already in process..\n");
return -EBUSY; return -EBUSY;
...@@ -1840,6 +1838,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, ...@@ -1840,6 +1838,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
return -ENOMEM; return -ENOMEM;
} }
priv->scan_request = request;
priv->user_scan_cfg->num_ssids = request->n_ssids; priv->user_scan_cfg->num_ssids = request->n_ssids;
priv->user_scan_cfg->ssid_list = request->ssids; priv->user_scan_cfg->ssid_list = request->ssids;
...@@ -1876,6 +1876,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, ...@@ -1876,6 +1876,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
ret = mwifiex_scan_networks(priv, priv->user_scan_cfg); ret = mwifiex_scan_networks(priv, priv->user_scan_cfg);
if (ret) { if (ret) {
dev_err(priv->adapter->dev, "scan failed: %d\n", ret); dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
priv->scan_request = NULL;
kfree(priv->user_scan_cfg);
priv->user_scan_cfg = NULL;
return ret; return ret;
} }
......
...@@ -1864,21 +1864,18 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, ...@@ -1864,21 +1864,18 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
struct cfg80211_ssid *req_ssid) struct cfg80211_ssid *req_ssid)
{ {
struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_adapter *adapter = priv->adapter;
int ret = 0; int ret;
struct mwifiex_user_scan_cfg *scan_cfg; struct mwifiex_user_scan_cfg *scan_cfg;
if (!req_ssid)
return -1;
if (adapter->scan_processing) { if (adapter->scan_processing) {
dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); dev_err(adapter->dev, "cmd: Scan already in process...\n");
return ret; return -EBUSY;
} }
if (priv->scan_block) { if (priv->scan_block) {
dev_dbg(adapter->dev, dev_err(adapter->dev,
"cmd: Scan is blocked during association...\n"); "cmd: Scan is blocked during association...\n");
return ret; return -EBUSY;
} }
scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
......
...@@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = { ...@@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = {
.disconnect = rt2x00usb_disconnect, .disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend, .suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume, .resume = rt2x00usb_resume,
.reset_resume = rt2x00usb_resume,
.disable_hub_initiated_lpm = 1, .disable_hub_initiated_lpm = 1,
}; };
......
...@@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = { ...@@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = {
.disconnect = rt2x00usb_disconnect, .disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend, .suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume, .resume = rt2x00usb_resume,
.reset_resume = rt2x00usb_resume,
.disable_hub_initiated_lpm = 1, .disable_hub_initiated_lpm = 1,
}; };
......
...@@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = { ...@@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = {
.disconnect = rt2x00usb_disconnect, .disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend, .suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume, .resume = rt2x00usb_resume,
.reset_resume = rt2x00usb_resume,
.disable_hub_initiated_lpm = 1, .disable_hub_initiated_lpm = 1,
}; };
......
...@@ -673,7 +673,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw) ...@@ -673,7 +673,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw)
set_hal_start(rtlhal); set_hal_start(rtlhal);
/* Start bulk IN */ /* Start bulk IN */
_rtl_usb_receive(hw); err = _rtl_usb_receive(hw);
} }
return err; return err;
......
...@@ -2665,6 +2665,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); ...@@ -2665,6 +2665,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
*/ */
unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
/**
* ieee80211_get_mesh_hdrlen - get mesh extension header length
* @meshhdr: the mesh extension header, only the flags field
* (first byte) will be accessed
* Returns the length of the extension header, which is always at
* least 6 bytes and at most 18 if address 5 and 6 are present.
*/
unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
/** /**
* DOC: Data path helpers * DOC: Data path helpers
* *
......
...@@ -1110,7 +1110,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, ...@@ -1110,7 +1110,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
sdata->u.ibss.ibss_join_req = jiffies; sdata->u.ibss.ibss_join_req = jiffies;
memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
sdata->u.ibss.ssid_len = params->ssid_len; sdata->u.ibss.ssid_len = params->ssid_len;
mutex_unlock(&sdata->u.ibss.mtx); mutex_unlock(&sdata->u.ibss.mtx);
......
...@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) ...@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
if (ieee80211_is_action(hdr->frame_control)) { if (ieee80211_is_action(hdr->frame_control)) {
u8 category; u8 category;
/* make sure category field is present */
if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
return RX_DROP_MONITOR;
mgmt = (struct ieee80211_mgmt *)hdr; mgmt = (struct ieee80211_mgmt *)hdr;
category = mgmt->u.action.category; category = mgmt->u.action.category;
if (category != WLAN_CATEGORY_MESH_ACTION && if (category != WLAN_CATEGORY_MESH_ACTION &&
...@@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) ...@@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
*/ */
if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
ieee80211_is_data_present(hdr->frame_control)) { ieee80211_is_data_present(hdr->frame_control)) {
u16 ethertype; unsigned int hdrlen;
u8 *payload; __be16 ethertype;
payload = rx->skb->data + hdrlen = ieee80211_hdrlen(hdr->frame_control);
ieee80211_hdrlen(hdr->frame_control);
ethertype = (payload[6] << 8) | payload[7]; if (rx->skb->len < hdrlen + 8)
if (cpu_to_be16(ethertype) == return RX_DROP_MONITOR;
rx->sdata->control_port_protocol)
skb_copy_bits(rx->skb, hdrlen + 6, &ethertype, 2);
if (ethertype == rx->sdata->control_port_protocol)
return RX_CONTINUE; return RX_CONTINUE;
} }
...@@ -1467,11 +1474,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) ...@@ -1467,11 +1474,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
hdr = (struct ieee80211_hdr *)rx->skb->data; hdr = (struct ieee80211_hdr *)rx->skb->data;
fc = hdr->frame_control; fc = hdr->frame_control;
if (ieee80211_is_ctl(fc))
return RX_CONTINUE;
sc = le16_to_cpu(hdr->seq_ctrl); sc = le16_to_cpu(hdr->seq_ctrl);
frag = sc & IEEE80211_SCTL_FRAG; frag = sc & IEEE80211_SCTL_FRAG;
if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
(rx->skb)->len < 24 ||
is_multicast_ether_addr(hdr->addr1))) { is_multicast_ether_addr(hdr->addr1))) {
/* not fragmented */ /* not fragmented */
goto out; goto out;
...@@ -1894,6 +1904,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) ...@@ -1894,6 +1904,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
hdr = (struct ieee80211_hdr *) skb->data; hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_hdrlen(hdr->frame_control); hdrlen = ieee80211_hdrlen(hdr->frame_control);
/* make sure fixed part of mesh header is there, also checks skb len */
if (!pskb_may_pull(rx->skb, hdrlen + 6))
return RX_DROP_MONITOR;
mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
/* make sure full mesh header is there, also checks skb len */
if (!pskb_may_pull(rx->skb,
hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
return RX_DROP_MONITOR;
/* reload pointers */
hdr = (struct ieee80211_hdr *) skb->data;
mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
/* frame is in RMC, don't forward */ /* frame is in RMC, don't forward */
...@@ -1902,7 +1926,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) ...@@ -1902,7 +1926,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
return RX_DROP_MONITOR; return RX_DROP_MONITOR;
if (!ieee80211_is_data(hdr->frame_control)) if (!ieee80211_is_data(hdr->frame_control) ||
!(status->rx_flags & IEEE80211_RX_RA_MATCH))
return RX_CONTINUE; return RX_CONTINUE;
if (!mesh_hdr->ttl) if (!mesh_hdr->ttl)
...@@ -1916,9 +1941,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) ...@@ -1916,9 +1941,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
if (is_multicast_ether_addr(hdr->addr1)) { if (is_multicast_ether_addr(hdr->addr1)) {
mpp_addr = hdr->addr3; mpp_addr = hdr->addr3;
proxied_addr = mesh_hdr->eaddr1; proxied_addr = mesh_hdr->eaddr1;
} else { } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
/* has_a4 already checked in ieee80211_rx_mesh_check */
mpp_addr = hdr->addr4; mpp_addr = hdr->addr4;
proxied_addr = mesh_hdr->eaddr2; proxied_addr = mesh_hdr->eaddr2;
} else {
return RX_DROP_MONITOR;
} }
rcu_read_lock(); rcu_read_lock();
...@@ -1946,12 +1974,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) ...@@ -1946,12 +1974,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
} }
skb_set_queue_mapping(skb, q); skb_set_queue_mapping(skb, q);
if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
goto out;
if (!--mesh_hdr->ttl) { if (!--mesh_hdr->ttl) {
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
return RX_DROP_MONITOR; goto out;
} }
if (!ifmsh->mshcfg.dot11MeshForwarding) if (!ifmsh->mshcfg.dot11MeshForwarding)
...@@ -2358,6 +2383,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) ...@@ -2358,6 +2383,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
} }
break; break;
case WLAN_CATEGORY_SELF_PROTECTED: case WLAN_CATEGORY_SELF_PROTECTED:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.self_prot.action_code)))
break;
switch (mgmt->u.action.u.self_prot.action_code) { switch (mgmt->u.action.u.self_prot.action_code) {
case WLAN_SP_MESH_PEERING_OPEN: case WLAN_SP_MESH_PEERING_OPEN:
case WLAN_SP_MESH_PEERING_CLOSE: case WLAN_SP_MESH_PEERING_CLOSE:
...@@ -2376,6 +2405,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) ...@@ -2376,6 +2405,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
} }
break; break;
case WLAN_CATEGORY_MESH_ACTION: case WLAN_CATEGORY_MESH_ACTION:
if (len < (IEEE80211_MIN_ACTION_SIZE +
sizeof(mgmt->u.action.u.mesh_action.action_code)))
break;
if (!ieee80211_vif_is_mesh(&sdata->vif)) if (!ieee80211_vif_is_mesh(&sdata->vif))
break; break;
if (mesh_action_is_path_sel(mgmt) && if (mesh_action_is_path_sel(mgmt) &&
...@@ -2918,10 +2951,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, ...@@ -2918,10 +2951,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
local->dot11ReceivedFragmentCount++; local->dot11ReceivedFragmentCount++;
if (ieee80211_is_mgmt(fc)) if (ieee80211_is_mgmt(fc)) {
err = skb_linearize(skb); /* drop frame if too short for header */
else if (skb->len < ieee80211_hdrlen(fc))
err = -ENOBUFS;
else
err = skb_linearize(skb);
} else {
err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
}
if (err) { if (err) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
......
...@@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, ...@@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
break; break;
} }
if (id != WLAN_EID_VENDOR_SPECIFIC && switch (id) {
id != WLAN_EID_QUIET && case WLAN_EID_SSID:
test_bit(id, seen_elems)) { case WLAN_EID_SUPP_RATES:
elems->parse_error = true; case WLAN_EID_FH_PARAMS:
left -= elen; case WLAN_EID_DS_PARAMS:
pos += elen; case WLAN_EID_CF_PARAMS:
continue; case WLAN_EID_TIM:
case WLAN_EID_IBSS_PARAMS:
case WLAN_EID_CHALLENGE:
case WLAN_EID_RSN:
case WLAN_EID_ERP_INFO:
case WLAN_EID_EXT_SUPP_RATES:
case WLAN_EID_HT_CAPABILITY:
case WLAN_EID_HT_OPERATION:
case WLAN_EID_VHT_CAPABILITY:
case WLAN_EID_VHT_OPERATION:
case WLAN_EID_MESH_ID:
case WLAN_EID_MESH_CONFIG:
case WLAN_EID_PEER_MGMT:
case WLAN_EID_PREQ:
case WLAN_EID_PREP:
case WLAN_EID_PERR:
case WLAN_EID_RANN:
case WLAN_EID_CHANNEL_SWITCH:
case WLAN_EID_EXT_CHANSWITCH_ANN:
case WLAN_EID_COUNTRY:
case WLAN_EID_PWR_CONSTRAINT:
case WLAN_EID_TIMEOUT_INTERVAL:
if (test_bit(id, seen_elems)) {
elems->parse_error = true;
left -= elen;
pos += elen;
continue;
}
break;
} }
if (calc_crc && id < 64 && (filter & (1ULL << id))) if (calc_crc && id < 64 && (filter & (1ULL << id)))
......
...@@ -529,8 +529,7 @@ int wiphy_register(struct wiphy *wiphy) ...@@ -529,8 +529,7 @@ int wiphy_register(struct wiphy *wiphy)
for (i = 0; i < sband->n_channels; i++) { for (i = 0; i < sband->n_channels; i++) {
sband->channels[i].orig_flags = sband->channels[i].orig_flags =
sband->channels[i].flags; sband->channels[i].flags;
sband->channels[i].orig_mag = sband->channels[i].orig_mag = INT_MAX;
sband->channels[i].max_antenna_gain;
sband->channels[i].orig_mpwr = sband->channels[i].orig_mpwr =
sband->channels[i].max_power; sband->channels[i].max_power;
sband->channels[i].band = band; sband->channels[i].band = band;
......
...@@ -908,7 +908,7 @@ static void handle_channel(struct wiphy *wiphy, ...@@ -908,7 +908,7 @@ static void handle_channel(struct wiphy *wiphy,
map_regdom_flags(reg_rule->flags) | bw_flags; map_regdom_flags(reg_rule->flags) | bw_flags;
chan->max_antenna_gain = chan->orig_mag = chan->max_antenna_gain = chan->orig_mag =
(int) MBI_TO_DBI(power_rule->max_antenna_gain); (int) MBI_TO_DBI(power_rule->max_antenna_gain);
chan->max_power = chan->orig_mpwr = chan->max_reg_power = chan->max_power = chan->orig_mpwr =
(int) MBM_TO_DBM(power_rule->max_eirp); (int) MBM_TO_DBM(power_rule->max_eirp);
return; return;
} }
...@@ -1331,7 +1331,8 @@ static void handle_channel_custom(struct wiphy *wiphy, ...@@ -1331,7 +1331,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); chan->max_reg_power = chan->max_power =
(int) MBM_TO_DBM(power_rule->max_eirp);
} }
static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band,
......
...@@ -311,23 +311,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) ...@@ -311,23 +311,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
} }
EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
{ {
int ae = meshhdr->flags & MESH_FLAGS_AE; int ae = meshhdr->flags & MESH_FLAGS_AE;
/* 7.1.3.5a.2 */ /* 802.11-2012, 8.2.4.7.3 */
switch (ae) { switch (ae) {
default:
case 0: case 0:
return 6; return 6;
case MESH_FLAGS_AE_A4: case MESH_FLAGS_AE_A4:
return 12; return 12;
case MESH_FLAGS_AE_A5_A6: case MESH_FLAGS_AE_A5_A6:
return 18; return 18;
case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
return 24;
default:
return 6;
} }
} }
EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
enum nl80211_iftype iftype) enum nl80211_iftype iftype)
...@@ -375,6 +373,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, ...@@ -375,6 +373,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
/* make sure meshdr->flags is on the linear part */ /* make sure meshdr->flags is on the linear part */
if (!pskb_may_pull(skb, hdrlen + 1)) if (!pskb_may_pull(skb, hdrlen + 1))
return -1; return -1;
if (meshdr->flags & MESH_FLAGS_AE_A4)
return -1;
if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
skb_copy_bits(skb, hdrlen + skb_copy_bits(skb, hdrlen +
offsetof(struct ieee80211s_hdr, eaddr1), offsetof(struct ieee80211s_hdr, eaddr1),
...@@ -399,6 +399,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, ...@@ -399,6 +399,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
/* make sure meshdr->flags is on the linear part */ /* make sure meshdr->flags is on the linear part */
if (!pskb_may_pull(skb, hdrlen + 1)) if (!pskb_may_pull(skb, hdrlen + 1))
return -1; return -1;
if (meshdr->flags & MESH_FLAGS_AE_A5_A6)
return -1;
if (meshdr->flags & MESH_FLAGS_AE_A4) if (meshdr->flags & MESH_FLAGS_AE_A4)
skb_copy_bits(skb, hdrlen + skb_copy_bits(skb, hdrlen +
offsetof(struct ieee80211s_hdr, eaddr1), offsetof(struct ieee80211s_hdr, eaddr1),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment