#include <linux/wireless.h>
#include <linux/rtnetlink.h>
#include <linux/bitmap.h>
+#include <net/net_namespace.h>
#include <net/cfg80211.h>
#include "ieee80211_common.h"
netif_rx(skb);
}
-int ieee80211_radar_status(struct ieee80211_hw *hw, int channel,
- int radar, int radar_type)
-{
- struct sk_buff *skb;
- struct ieee80211_radar_info *msg;
- struct ieee80211_local *local = hw_to_local(hw);
-
- if (!local->apdev)
- return 0;
-
- skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
- sizeof(struct ieee80211_radar_info));
-
- if (!skb)
- return -ENOMEM;
- skb_reserve(skb, sizeof(struct ieee80211_frame_info));
-
- msg = (struct ieee80211_radar_info *)
- skb_put(skb, sizeof(struct ieee80211_radar_info));
- msg->channel = channel;
- msg->radar = radar;
- msg->radar_type = radar_type;
-
- ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_radar);
- return 0;
-}
-EXPORT_SYMBOL(ieee80211_radar_status);
-
void ieee80211_key_threshold_notify(struct net_device *dev,
struct ieee80211_key *key,
struct sta_info *sta)
switch (sdata->type) {
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
- sdata->u.sta.prev_bssid_set = 0;
+ sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
break;
}
}
conf.if_id = dev->ifindex;
conf.type = sdata->type;
- conf.mac_addr = dev->dev_addr;
+ if (sdata->type == IEEE80211_IF_TYPE_MNTR)
+ conf.mac_addr = NULL;
+ else
+ conf.mac_addr = dev->dev_addr;
res = local->ops->add_interface(local_to_hw(local), &conf);
if (res) {
if (sdata->type == IEEE80211_IF_TYPE_MNTR)
} else {
ieee80211_if_config(dev);
ieee80211_reset_erp_info(dev);
+ ieee80211_enable_keys(sdata);
}
if (sdata->type == IEEE80211_IF_TYPE_STA &&
case IEEE80211_IF_TYPE_IBSS:
sdata->u.sta.state = IEEE80211_DISABLED;
del_timer_sync(&sdata->u.sta.timer);
+ /*
+ * Holding the sub_if_lock for writing here blocks
+ * out the receive path and makes sure it's not
+ * currently processing a packet that may get
+ * added to the queue.
+ */
+ write_lock_bh(&local->sub_if_lock);
skb_queue_purge(&sdata->u.sta.skb_queue);
+ write_unlock_bh(&local->sub_if_lock);
+
if (!local->ops->hw_scan &&
local->scan_dev == sdata->dev) {
local->sta_scanning = 0;
local->monitors--;
if (!local->monitors)
local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
+ } else {
+ /* disable all keys for as long as this netdev is down */
+ ieee80211_disable_keys(sdata);
}
local->open_count--;
unsigned short flags;
netif_tx_lock_nested(local->mdev, TX_LOCK_MASTER);
- if (((dev->flags & IFF_ALLMULTI) != 0) ^ (sdata->allmulti != 0)) {
- if (sdata->allmulti) {
- sdata->allmulti = 0;
+ if (((dev->flags & IFF_ALLMULTI) != 0) ^
+ ((sdata->flags & IEEE80211_SDATA_ALLMULTI) != 0)) {
+ if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
local->iff_allmultis--;
- } else {
- sdata->allmulti = 1;
+ else
local->iff_allmultis++;
- }
+ sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
}
- if (((dev->flags & IFF_PROMISC) != 0) ^ (sdata->promisc != 0)) {
- if (sdata->promisc) {
- sdata->promisc = 0;
+ if (((dev->flags & IFF_PROMISC) != 0) ^
+ ((sdata->flags & IEEE80211_SDATA_PROMISC) != 0)) {
+ if (sdata->flags & IEEE80211_SDATA_PROMISC)
local->iff_promiscs--;
- } else {
- sdata->promisc = 1;
+ else
local->iff_promiscs++;
- }
+ sdata->flags ^= IEEE80211_SDATA_PROMISC;
}
if (dev->mc_count != sdata->mc_count) {
local->mc_count = local->mc_count - sdata->mc_count +
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (local->ops->erp_ie_changed)
local->ops->erp_ie_changed(local_to_hw(local), changes,
- sdata->use_protection,
- !sdata->short_preamble);
+ !!(sdata->flags & IEEE80211_SDATA_USE_PROTECTION),
+ !(sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE));
}
void ieee80211_reset_erp_info(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- sdata->short_preamble = 0;
- sdata->use_protection = 0;
+ sdata->flags &= ~(IEEE80211_SDATA_USE_PROTECTION |
+ IEEE80211_SDATA_SHORT_PREAMBLE);
ieee80211_erp_info_change_notify(dev,
IEEE80211_ERP_CHANGE_PROTECTION |
IEEE80211_ERP_CHANGE_PREAMBLE);
}
EXPORT_SYMBOL(ieee80211_get_mc_list_item);
-static void ieee80211_stat_refresh(unsigned long data)
-{
- struct ieee80211_local *local = (struct ieee80211_local *) data;
- struct sta_info *sta;
- struct ieee80211_sub_if_data *sdata;
-
- if (!local->stat_time)
- return;
-
- /* go through all stations */
- read_lock_bh(&local->sta_lock);
- list_for_each_entry(sta, &local->sta_list, list) {
- sta->channel_use = (sta->channel_use_raw / local->stat_time) /
- CHAN_UTIL_PER_10MS;
- sta->channel_use_raw = 0;
- }
- read_unlock_bh(&local->sta_lock);
-
- /* go through all subinterfaces */
- read_lock(&local->sub_if_lock);
- list_for_each_entry(sdata, &local->sub_if_list, list) {
- sdata->channel_use = (sdata->channel_use_raw /
- local->stat_time) / CHAN_UTIL_PER_10MS;
- sdata->channel_use_raw = 0;
- }
- read_unlock(&local->sub_if_lock);
-
- /* hardware interface */
- local->channel_use = (local->channel_use_raw /
- local->stat_time) / CHAN_UTIL_PER_10MS;
- local->channel_use_raw = 0;
-
- local->stat_timer.expires = jiffies + HZ * local->stat_time / 100;
- add_timer(&local->stat_timer);
-}
-
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
struct sk_buff *skb,
struct ieee80211_tx_status *status)
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
pkt_data->ifindex = control->ifindex;
- pkt_data->mgmt_iface = (control->type == IEEE80211_IF_TYPE_MGMT);
- pkt_data->req_tx_status = !!(control->flags & IEEE80211_TXCTL_REQ_TX_STATUS);
- pkt_data->do_not_encrypt = !!(control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT);
- pkt_data->requeue = !!(control->flags & IEEE80211_TXCTL_REQUEUE);
+ pkt_data->flags = 0;
+ if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS)
+ pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
+ if (control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)
+ pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
+ if (control->flags & IEEE80211_TXCTL_REQUEUE)
+ pkt_data->flags |= IEEE80211_TXPD_REQUEUE;
+ if (control->type == IEEE80211_IF_TYPE_MGMT)
+ pkt_data->flags |= IEEE80211_TXPD_MGMT_IFACE;
pkt_data->queue = control->queue;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
if (!key)
goto no_key;
- switch (key->alg) {
+ switch (key->conf.alg) {
case ALG_WEP:
iv_len = WEP_IV_LEN;
mic_len = WEP_ICV_LEN;
goto no_key;
}
- if (skb->len >= mic_len && key->force_sw_encrypt)
+ if (skb->len >= mic_len &&
+ !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
skb_trim(skb, skb->len - mic_len);
if (skb->len >= iv_len && skb->len > hdrlen) {
memmove(skb->data + iv_len, skb->data, hdrlen);
INIT_LIST_HEAD(&local->sub_if_list);
INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
- init_timer(&local->stat_timer);
- local->stat_timer.function = ieee80211_stat_refresh;
- local->stat_timer.data = (unsigned long) local;
ieee80211_rx_bss_list_init(mdev);
sta_info_init(local);
rtnl_unlock();
- if (local->stat_time)
- del_timer_sync(&local->stat_timer);
-
ieee80211_rx_bss_list_deinit(local->mdev);
ieee80211_clear_tx_pending(local);
sta_info_stop(local);