aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-04-25 16:36:46 -0700
committerDavid S. Miller <davem@davemloft.net>2009-04-25 16:36:46 -0700
commit495a1b4eff1a216a3ea171ac137f1807e6555f52 (patch)
tree72d059d6d66fac6a74df33bac2eb40dcd0ea0732 /net
parentad8affd972a705a38e769859c50ee8e749b631da (diff)
parentd3feaf5ad12259927039a675cfb25dc342b403ab (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: net/mac80211/pm.c
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/Kconfig16
-rw-r--r--net/mac80211/cfg.c59
-rw-r--r--net/mac80211/debugfs.c8
-rw-r--r--net/mac80211/event.c17
-rw-r--r--net/mac80211/ht.c84
-rw-r--r--net/mac80211/ibss.c347
-rw-r--r--net/mac80211/ieee80211_i.h85
-rw-r--r--net/mac80211/iface.c16
-rw-r--r--net/mac80211/main.c122
-rw-r--r--net/mac80211/mlme.c445
-rw-r--r--net/mac80211/pm.c121
-rw-r--r--net/mac80211/rx.c2
-rw-r--r--net/mac80211/scan.c28
-rw-r--r--net/mac80211/spectmgmt.c2
-rw-r--r--net/mac80211/sta_info.c71
-rw-r--r--net/mac80211/sta_info.h3
-rw-r--r--net/mac80211/tx.c35
-rw-r--r--net/mac80211/util.c240
-rw-r--r--net/mac80211/wext.c270
-rw-r--r--net/mac80211/wpa.c2
-rw-r--r--net/rfkill/rfkill-input.c69
-rw-r--r--net/rfkill/rfkill.c54
-rw-r--r--net/wimax/op-rfkill.c9
-rw-r--r--net/wireless/Makefile2
-rw-r--r--net/wireless/core.c27
-rw-r--r--net/wireless/core.h15
-rw-r--r--net/wireless/ibss.c369
-rw-r--r--net/wireless/mlme.c50
-rw-r--r--net/wireless/nl80211.c639
-rw-r--r--net/wireless/nl80211.h32
-rw-r--r--net/wireless/reg.c35
-rw-r--r--net/wireless/scan.c53
-rw-r--r--net/wireless/util.c6
-rw-r--r--net/wireless/wext-compat.c236
34 files changed, 2383 insertions, 1186 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index ecc3faf9f11..9cbf545e95a 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -11,6 +11,22 @@ config MAC80211
This option enables the hardware independent IEEE 802.11
networking stack.
+config MAC80211_DEFAULT_PS
+ bool "enable powersave by default"
+ depends on MAC80211
+ default y
+ help
+ This option enables powersave mode by default.
+
+ If this causes your applications to misbehave you should fix your
+ applications instead -- they need to register their network
+ latency requirement, see Documentation/power/pm_qos_interface.txt.
+
+config MAC80211_DEFAULT_PS_VALUE
+ int
+ default 1 if MAC80211_DEFAULT_PS
+ default 0
+
menu "Rate control algorithm selection"
depends on MAC80211 != n
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e677b751d46..5e1c230744b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1167,7 +1167,8 @@ static int ieee80211_scan(struct wiphy *wiphy,
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_ADHOC &&
- sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
+ (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon))
return -EOPNOTSUPP;
return ieee80211_request_scan(sdata, req);
@@ -1267,25 +1268,62 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_deauth_request *req)
{
- struct ieee80211_sub_if_data *sdata;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- /* TODO: req->ie */
+ /* TODO: req->ie, req->peer_addr */
return ieee80211_sta_deauthenticate(sdata, req->reason_code);
}
static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_disassoc_request *req)
{
- struct ieee80211_sub_if_data *sdata;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- /* TODO: req->ie */
+ /* TODO: req->ie, req->peer_addr */
return ieee80211_sta_disassociate(sdata, req->reason_code);
}
+static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ibss_params *params)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ return ieee80211_ibss_join(sdata, params);
+}
+
+static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ return ieee80211_ibss_leave(sdata);
+}
+
+static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+
+ if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
+ int err;
+
+ if (local->ops->set_rts_threshold) {
+ err = local->ops->set_rts_threshold(
+ local_to_hw(local), wiphy->rts_threshold);
+ if (err)
+ return err;
+ }
+ }
+
+ if (changed & WIPHY_PARAM_RETRY_SHORT)
+ local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
+ if (changed & WIPHY_PARAM_RETRY_LONG)
+ local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
+ if (changed &
+ (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG))
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
+
+ return 0;
+}
+
struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -1322,4 +1360,7 @@ struct cfg80211_ops mac80211_config_ops = {
.assoc = ieee80211_assoc,
.deauth = ieee80211_deauth,
.disassoc = ieee80211_disassoc,
+ .join_ibss = ieee80211_join_ibss,
+ .leave_ibss = ieee80211_leave_ibss,
+ .set_wiphy_params = ieee80211_set_wiphy_params,
};
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 210b9b6fecd..5001328be46 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -52,13 +52,13 @@ static const struct file_operations name## _ops = { \
DEBUGFS_READONLY_FILE(frequency, 20, "%d",
local->hw.conf.channel->center_freq);
DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
- local->rts_threshold);
+ local->hw.wiphy->rts_threshold);
DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
- local->fragmentation_threshold);
+ local->hw.wiphy->frag_threshold);
DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
- local->hw.conf.short_frame_max_tx_count);
+ local->hw.wiphy->retry_short);
DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
- local->hw.conf.long_frame_max_tx_count);
+ local->hw.wiphy->retry_long);
DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
local->total_ps_buffered);
DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x",
diff --git a/net/mac80211/event.c b/net/mac80211/event.c
index 0d95561c0ee..f288d01a634 100644
--- a/net/mac80211/event.c
+++ b/net/mac80211/event.c
@@ -12,12 +12,12 @@
#include "ieee80211_i.h"
/*
- * indicate a failed Michael MIC to userspace; the passed packet
- * (in the variable hdr) must be long enough to extract the TKIP
- * fields like TSC
+ * Indicate a failed Michael MIC to userspace. If the caller knows the TSC of
+ * the frame that generated the MIC failure (i.e., if it was provided by the
+ * driver or is still in the frame), it should provide that information.
*/
void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
- struct ieee80211_hdr *hdr)
+ struct ieee80211_hdr *hdr, const u8 *tsc)
{
union iwreq_data wrqu;
char *buf = kmalloc(128, GFP_ATOMIC);
@@ -34,8 +34,9 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke
kfree(buf);
}
- /*
- * TODO: re-add support for sending MIC failure indication
- * with all info via nl80211
- */
+ cfg80211_michael_mic_failure(sdata->dev, hdr->addr2,
+ (hdr->addr1[0] & 0x01) ?
+ NL80211_KEYTYPE_GROUP :
+ NL80211_KEYTYPE_PAIRWISE,
+ keyidx, tsc);
}
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 4e3c72f20de..0891bfb0699 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -14,7 +14,6 @@
*/
#include <linux/ieee80211.h>
-#include <net/wireless.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
#include "rate.h"
@@ -83,89 +82,6 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
ht_cap->mcs.rx_mask[32/8] |= 1;
}
-/*
- * ieee80211_enable_ht should be called only after the operating band
- * has been determined as ht configuration depends on the hw's
- * HT abilities for a specific band.
- */
-u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_ht_info *hti,
- u16 ap_ht_cap_flags)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_supported_band *sband;
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_bss_ht_conf ht;
- struct sta_info *sta;
- u32 changed = 0;
- bool enable_ht = true, ht_changed;
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
-
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
- memset(&ht, 0, sizeof(ht));
-
- /* HT is not supported */
- if (!sband->ht_cap.ht_supported)
- enable_ht = false;
-
- /* check that channel matches the right operating channel */
- if (local->hw.conf.channel->center_freq !=
- ieee80211_channel_to_frequency(hti->control_chan))
- enable_ht = false;
-
- if (enable_ht) {
- channel_type = NL80211_CHAN_HT20;
-
- if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
- (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
- (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
- switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
- case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
- channel_type = NL80211_CHAN_HT40PLUS;
- break;
- case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
- channel_type = NL80211_CHAN_HT40MINUS;
- break;
- }
- }
- }
-
- ht_changed = conf_is_ht(&local->hw.conf) != enable_ht ||
- channel_type != local->hw.conf.channel_type;
-
- local->oper_channel_type = channel_type;
-
- if (ht_changed) {
- /* channel_type change automatically detected */
- ieee80211_hw_config(local, 0);
-
- rcu_read_lock();
-
- sta = sta_info_get(local, ifmgd->bssid);
- if (sta)
- rate_control_rate_update(local, sband, sta,
- IEEE80211_RC_HT_CHANGED);
-
- rcu_read_unlock();
-
- }
-
- /* disable HT */
- if (!enable_ht)
- return 0;
-
- ht.operation_mode = le16_to_cpu(hti->operation_mode);
-
- /* if bss configuration changed store the new one */
- if (memcmp(&sdata->vif.bss_conf.ht, &ht, sizeof(ht))) {
- changed |= BSS_CHANGED_HT;
- sdata->vif.bss_conf.ht = ht;
- }
-
- return changed;
-}
-
void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta)
{
int i;
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 3201e1f9636..6030e003180 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -59,74 +59,59 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
sdata->u.ibss.bssid, 0);
}
-static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
- const u8 *bssid, const int beacon_int,
- const int freq,
- const size_t supp_rates_len,
- const u8 *supp_rates,
- const u16 capability, u64 tsf)
+static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
+ const u8 *bssid, const int beacon_int,
+ struct ieee80211_channel *chan,
+ const size_t supp_rates_len,
+ const u8 *supp_rates,
+ const u16 capability, u64 tsf)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
- int res = 0, rates, i, j;
+ int rates, i, j;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
u8 *pos;
struct ieee80211_supported_band *sband;
- union iwreq_data wrqu;
if (local->ops->reset_tsf) {
/* Reset own TSF to allow time synchronization work. */
local->ops->reset_tsf(local_to_hw(local));
}
- if ((ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET) &&
- memcmp(ifibss->bssid, bssid, ETH_ALEN) == 0)
- return res;
+ skb = ifibss->skb;
+ rcu_assign_pointer(ifibss->presp, NULL);
+ synchronize_rcu();
+ skb->data = skb->head;
+ skb->len = 0;
+ skb_reset_tail_pointer(skb);
+ skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
- skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
- "response\n", sdata->dev->name);
- return -ENOMEM;
- }
-
- if (!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET)) {
- /* Remove possible STA entries from other IBSS networks. */
- sta_info_flush_delayed(sdata);
- }
+ if (memcmp(ifibss->bssid, bssid, ETH_ALEN))
+ sta_info_flush(sdata->local, sdata);
memcpy(ifibss->bssid, bssid, ETH_ALEN);
- res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
- if (res)
- return res;
local->hw.conf.beacon_int = beacon_int >= 10 ? beacon_int : 10;
- sdata->drop_unencrypted = capability &
- WLAN_CAPABILITY_PRIVACY ? 1 : 0;
-
- res = ieee80211_set_freq(sdata, freq);
+ sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
- if (res)
- return res;
+ ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ local->oper_channel = chan;
+ local->oper_channel_type = NL80211_CHAN_NO_HT;
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+ sband = local->hw.wiphy->bands[chan->band];
/* Build IBSS probe response */
-
- skb_reserve(skb, local->hw.extra_tx_headroom);
-
- mgmt = (struct ieee80211_mgmt *)
- skb_put(skb, 24 + sizeof(mgmt->u.beacon));
+ mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon));
memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
memset(mgmt->da, 0xff, ETH_ALEN);
memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
- mgmt->u.beacon.beacon_int =
- cpu_to_le16(local->hw.conf.beacon_int);
+ mgmt->u.beacon.beacon_int = cpu_to_le16(local->hw.conf.beacon_int);
mgmt->u.beacon.timestamp = cpu_to_le64(tsf);
mgmt->u.beacon.capab_info = cpu_to_le16(capability);
@@ -147,7 +132,7 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
pos = skb_put(skb, 2 + 1);
*pos++ = WLAN_EID_DS_PARAMS;
*pos++ = 1;
- *pos++ = ieee80211_frequency_to_channel(freq);
+ *pos++ = ieee80211_frequency_to_channel(chan->center_freq);
}
pos = skb_put(skb, 2 + 2);
@@ -165,12 +150,15 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
memcpy(pos, &supp_rates[8], rates);
}
- ifibss->probe_resp = skb;
+ if (ifibss->ie_len)
+ memcpy(skb_put(skb, ifibss->ie_len),
+ ifibss->ie, ifibss->ie_len);
+
+ rcu_assign_pointer(ifibss->presp, skb);
ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
IEEE80211_IFCC_BEACON_ENABLED);
-
rates = 0;
for (i = 0; i < supp_rates_len; i++) {
int bitrate = (supp_rates[i] & 0x7f) * 5;
@@ -181,27 +169,24 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
ieee80211_sta_def_wmm_params(sdata, supp_rates_len, supp_rates);
- ifibss->flags |= IEEE80211_IBSS_PREV_BSSID_SET;
ifibss->state = IEEE80211_IBSS_MLME_JOINED;
- mod_timer(&ifibss->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
+ mod_timer(&ifibss->timer,
+ round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
- memset(&wrqu, 0, sizeof(wrqu));
- memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
- wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL);
-
- return res;
+ cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
+ mgmt, skb->len, 0, GFP_KERNEL);
+ cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
}
-static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_bss *bss)
+static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_bss *bss)
{
- return __ieee80211_sta_join_ibss(sdata,
- bss->cbss.bssid,
- bss->cbss.beacon_interval,
- bss->cbss.channel->center_freq,
- bss->supp_rates_len, bss->supp_rates,
- bss->cbss.capability,
- bss->cbss.tsf);
+ __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid,
+ bss->cbss.beacon_interval,
+ bss->cbss.channel,
+ bss->supp_rates_len, bss->supp_rates,
+ bss->cbss.capability,
+ bss->cbss.tsf);
}
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -277,7 +262,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
goto put_bss;
/* we use a fixed BSSID */
- if (sdata->u.ibss.flags & IEEE80211_IBSS_BSSID_SET)
+ if (sdata->u.ibss.bssid)
goto put_bss;
/* not an IBSS */
@@ -369,13 +354,14 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta;
int band = local->hw.conf.channel->band;
- /* TODO: Could consider removing the least recently used entry and
- * allow new one to be added. */
+ /*
+ * XXX: Consider removing the least recently used entry and
+ * allow new one to be added.
+ */
if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: No room for a new IBSS STA "
- "entry %pM\n", sdata->dev->name, addr);
- }
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n",
+ sdata->dev->name, addr);
return NULL;
}
@@ -432,14 +418,15 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- mod_timer(&ifibss->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
+ mod_timer(&ifibss->timer,
+ round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT);
+
if (ieee80211_sta_active_ibss(sdata))
return;
- if ((ifibss->flags & IEEE80211_IBSS_BSSID_SET) &&
- (!(ifibss->flags & IEEE80211_IBSS_AUTO_CHANNEL_SEL)))
+ if (ifibss->fixed_channel)
return;
printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
@@ -455,7 +442,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
ieee80211_request_scan(sdata, &sdata->local->int_scan_req);
}
-static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
@@ -466,7 +453,7 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
u16 capability;
int i;
- if (ifibss->flags & IEEE80211_IBSS_BSSID_SET) {
+ if (ifibss->fixed_bssid) {
memcpy(bssid, ifibss->bssid, ETH_ALEN);
} else {
/* Generate random, not broadcast, locally administered BSSID. Mix in
@@ -482,7 +469,7 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n",
sdata->dev->name, bssid);
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ sband = local->hw.wiphy->bands[ifibss->channel->band];
if (local->hw.conf.beacon_int == 0)
local->hw.conf.beacon_int = 100;
@@ -500,24 +487,20 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
*pos++ = (u8) (rate / 5);
}
- return __ieee80211_sta_join_ibss(sdata,
- bssid, local->hw.conf.beacon_int,
- local->hw.conf.channel->center_freq,
- sband->n_bitrates, supp_rates,
- capability, 0);
+ __ieee80211_sta_join_ibss(sdata, bssid, local->hw.conf.beacon_int,
+ ifibss->channel, sband->n_bitrates,
+ supp_rates, capability, 0);
}
-static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
struct ieee80211_bss *bss;
+ struct ieee80211_channel *chan = NULL;
const u8 *bssid = NULL;
int active_ibss;
- if (ifibss->ssid_len == 0)
- return -EINVAL;
-
active_ibss = ieee80211_sta_active_ibss(sdata);
#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
@@ -525,11 +508,15 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
if (active_ibss)
- return 0;
+ return;
- if (ifibss->flags & IEEE80211_IBSS_BSSID_SET)
+ if (ifibss->fixed_bssid)
+ bssid = ifibss->bssid;
+ if (ifibss->fixed_channel)
+ chan = ifibss->channel;
+ if (!is_zero_ether_addr(ifibss->bssid))
bssid = ifibss->bssid;
- bss = (void *)cfg80211_get_bss(local->hw.wiphy, NULL, bssid,
+ bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid,
ifibss->ssid, ifibss->ssid_len,
WLAN_CAPABILITY_IBSS,
WLAN_CAPABILITY_IBSS);
@@ -540,18 +527,14 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
"%pM\n", bss->cbss.bssid, ifibss->bssid);
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
- if (bss &&
- (!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET) ||
- memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN))) {
- int ret;
-
+ if (bss && memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN)) {
printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
" based on configured SSID\n",
sdata->dev->name, bss->cbss.bssid);
- ret = ieee80211_sta_join_ibss(sdata, bss);
+ ieee80211_sta_join_ibss(sdata, bss);
ieee80211_rx_bss_put(local, bss);
- return ret;
+ return;
} else if (bss)
ieee80211_rx_bss_put(local, bss);
@@ -562,29 +545,31 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
/* Selected IBSS not found in current scan results - try to scan */
if (ifibss->state == IEEE80211_IBSS_MLME_JOINED &&
!ieee80211_sta_active_ibss(sdata)) {
- mod_timer(&ifibss->timer, jiffies +
- IEEE80211_IBSS_MERGE_INTERVAL);
- } else if (time_after(jiffies, local->last_scan_completed +
+ mod_timer(&ifibss->timer,
+ round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
+ } else if (time_after(jiffies, ifibss->last_scan_completed +
IEEE80211_SCAN_INTERVAL)) {
printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
"join\n", sdata->dev->name);
/* XXX maybe racy? */
if (local->scan_req)
- return -EBUSY;
+ return;
memcpy(local->int_scan_req.ssids[0].ssid,
ifibss->ssid, IEEE80211_MAX_SSID_LEN);
- local->int_scan_req.ssids[0].ssid_len = ifibss->ssid_len;
- return ieee80211_request_scan(sdata, &local->int_scan_req);
+ local->int_scan_req.ssids[0].ssid_len =
+ ifibss->ssid_len;
+ ieee80211_request_scan(sdata, &local->int_scan_req);
} else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) {
int interval = IEEE80211_SCAN_INTERVAL;
if (time_after(jiffies, ifibss->ibss_join_req +
IEEE80211_IBSS_JOIN_TIMEOUT)) {
- if (!(local->oper_channel->flags &
- IEEE80211_CHAN_NO_IBSS))
- return ieee80211_sta_create_ibss(sdata);
+ if (!(local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS)) {
+ ieee80211_sta_create_ibss(sdata);
+ return;
+ }
printk(KERN_DEBUG "%s: IBSS not allowed on"
" %d MHz\n", sdata->dev->name,
local->hw.conf.channel->center_freq);
@@ -595,11 +580,9 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
}
ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
- mod_timer(&ifibss->timer, jiffies + interval);
- return 0;
+ mod_timer(&ifibss->timer,
+ round_jiffies(jiffies + interval));
}
-
- return 0;
}
static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
@@ -614,7 +597,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
u8 *pos, *end;
if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
- len < 24 + 2 || !ifibss->probe_resp)
+ len < 24 + 2 || !ifibss->presp)
return;
if (local->ops->tx_last_beacon)
@@ -649,13 +632,13 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
}
if (pos[1] != 0 &&
(pos[1] != ifibss->ssid_len ||
- memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len) != 0)) {
+ !memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) {
/* Ignore ProbeReq for foreign SSID */
return;
}
/* Reply with ProbeResp */
- skb = skb_copy(ifibss->probe_resp, GFP_KERNEL);
+ skb = skb_copy(ifibss->presp, GFP_KERNEL);
if (!skb)
return;
@@ -794,89 +777,21 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
setup_timer(&ifibss->timer, ieee80211_ibss_timer,
(unsigned long) sdata);
skb_queue_head_init(&ifibss->skb_queue);
-
- ifibss->flags |= IEEE80211_IBSS_AUTO_BSSID_SEL |
- IEEE80211_IBSS_AUTO_CHANNEL_SEL;
-}
-
-int ieee80211_ibss_commit(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
-
- ifibss->flags &= ~IEEE80211_IBSS_PREV_BSSID_SET;
-
- if (ifibss->ssid_len)
- ifibss->flags |= IEEE80211_IBSS_SSID_SET;
- else
- ifibss->flags &= ~IEEE80211_IBSS_SSID_SET;
-
- ifibss->ibss_join_req = jiffies;
- ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
- set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
-
- return 0;
-}
-
-int ieee80211_ibss_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
-{
- struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
-
- if (len > IEEE80211_MAX_SSID_LEN)
- return -EINVAL;
-
- if (ifibss->ssid_len != len || memcmp(ifibss->ssid, ssid, len) != 0) {
- memset(ifibss->ssid, 0, sizeof(ifibss->ssid));
- memcpy(ifibss->ssid, ssid, len);
- ifibss->ssid_len = len;
- }
-
- return ieee80211_ibss_commit(sdata);
-}
-
-int ieee80211_ibss_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
-{
- struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
-
- memcpy(ssid, ifibss->ssid, ifibss->ssid_len);
- *len = ifibss->ssid_len;
-
- return 0;
-}
-
-int ieee80211_ibss_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
-{
- struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
-
- if (is_valid_ether_addr(bssid)) {
- memcpy(ifibss->bssid, bssid, ETH_ALEN);
- ifibss->flags |= IEEE80211_IBSS_BSSID_SET;
- } else {
- memset(ifibss->bssid, 0, ETH_ALEN);
- ifibss->flags &= ~IEEE80211_IBSS_BSSID_SET;
- }
-
- if (netif_running(sdata->dev)) {
- if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) {
- printk(KERN_DEBUG "%s: Failed to config new BSSID to "
- "the low-level driver\n", sdata->dev->name);
- }
- }
-
- return ieee80211_ibss_commit(sdata);
}
/* scan finished notification */
void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
{
- struct ieee80211_sub_if_data *sdata = local->scan_sdata;
- struct ieee80211_if_ibss *ifibss;
+ struct ieee80211_sub_if_data *sdata;
- if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) {
- ifibss = &sdata->u.ibss;
- if ((!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET)) ||
- !ieee80211_sta_active_ibss(sdata))
- ieee80211_sta_find_ibss(sdata);
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
+ continue;
+ sdata->u.ibss.last_scan_completed = jiffies;
+ ieee80211_sta_find_ibss(sdata);
}
+ mutex_unlock(&local->iflist_mtx);
}
ieee80211_rx_result
@@ -906,3 +821,71 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
return RX_DROP_MONITOR;
}
+
+int ieee80211