diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/chan.c | 56 | ||||
-rw-r--r-- | net/wireless/core.c | 3 | ||||
-rw-r--r-- | net/wireless/core.h | 27 | ||||
-rw-r--r-- | net/wireless/ibss.c | 5 | ||||
-rw-r--r-- | net/wireless/mlme.c | 52 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 328 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 6 | ||||
-rw-r--r-- | net/wireless/reg.c | 6 | ||||
-rw-r--r-- | net/wireless/sme.c | 36 | ||||
-rw-r--r-- | net/wireless/util.c | 24 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 15 | ||||
-rw-r--r-- | net/wireless/wext-core.c | 134 | ||||
-rw-r--r-- | net/wireless/wext-sme.c | 2 |
13 files changed, 482 insertions, 212 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index bf1737fc9a7e..d92d088026bf 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -10,38 +10,6 @@ #include "core.h" struct ieee80211_channel * -rdev_fixed_channel(struct cfg80211_registered_device *rdev, - struct wireless_dev *for_wdev) -{ - struct wireless_dev *wdev; - struct ieee80211_channel *result = NULL; - - WARN_ON(!mutex_is_locked(&rdev->devlist_mtx)); - - list_for_each_entry(wdev, &rdev->netdev_list, list) { - if (wdev == for_wdev) - continue; - - /* - * Lock manually to tell lockdep about allowed - * nesting here if for_wdev->mtx is held already. - * This is ok as it's all under the rdev devlist - * mutex and as such can only be done once at any - * given time. - */ - mutex_lock_nested(&wdev->mtx, SINGLE_DEPTH_NESTING); - if (wdev->current_bss) - result = wdev->current_bss->pub.channel; - wdev_unlock(wdev); - - if (result) - break; - } - - return result; -} - -struct ieee80211_channel * rdev_freq_to_chan(struct cfg80211_registered_device *rdev, int freq, enum nl80211_channel_type channel_type) { @@ -75,15 +43,22 @@ rdev_freq_to_chan(struct cfg80211_registered_device *rdev, return chan; } -int rdev_set_freq(struct cfg80211_registered_device *rdev, - struct wireless_dev *for_wdev, - int freq, enum nl80211_channel_type channel_type) +int cfg80211_set_freq(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, int freq, + enum nl80211_channel_type channel_type) { struct ieee80211_channel *chan; int result; - if (rdev_fixed_channel(rdev, for_wdev)) - return -EBUSY; + if (wdev->iftype == NL80211_IFTYPE_MONITOR) + wdev = NULL; + + if (wdev) { + ASSERT_WDEV_LOCK(wdev); + + if (!netif_running(wdev->netdev)) + return -ENETDOWN; + } if (!rdev->ops->set_channel) return -EOPNOTSUPP; @@ -92,11 +67,14 @@ int rdev_set_freq(struct cfg80211_registered_device *rdev, if (!chan) return -EINVAL; - result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type); + result = rdev->ops->set_channel(&rdev->wiphy, + wdev ? wdev->netdev : NULL, + chan, channel_type); if (result) return result; - rdev->channel = chan; + if (wdev) + wdev->channel = chan; return 0; } diff --git a/net/wireless/core.c b/net/wireless/core.c index 6ac70c101523..37d0e0ab4432 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -705,7 +705,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, wdev->ps = true; else wdev->ps = false; - wdev->ps_timeout = 100; + /* allow mac80211 to determine the timeout */ + wdev->ps_timeout = -1; if (rdev->ops->set_power_mgmt) if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, wdev->ps, diff --git a/net/wireless/core.h b/net/wireless/core.h index d52da913145a..ae930acf75e9 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -70,9 +70,6 @@ struct cfg80211_registered_device { struct work_struct conn_work; struct work_struct event_work; - /* current channel */ - struct ieee80211_channel *channel; - /* must be last because of the way we do wiphy_priv(), * and it should at least be aligned to NETDEV_ALIGN */ struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); @@ -293,13 +290,15 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx); + const u8 *key, int key_len, int key_idx, + bool local_state_change); int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_auth_type auth_type, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx); + const u8 *key, int key_len, int key_idx, + bool local_state_change); int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, @@ -315,13 +314,16 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct cfg80211_crypto_settings *crypt); int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason); + const u8 *ie, int ie_len, u16 reason, + bool local_state_change); int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason); + const u8 *ie, int ie_len, u16 reason, + bool local_state_change); int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason); + const u8 *ie, int ie_len, u16 reason, + bool local_state_change); void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, struct net_device *dev); void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, @@ -383,14 +385,11 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); struct ieee80211_channel * -rdev_fixed_channel(struct cfg80211_registered_device *rdev, - struct wireless_dev *for_wdev); -struct ieee80211_channel * rdev_freq_to_chan(struct cfg80211_registered_device *rdev, int freq, enum nl80211_channel_type channel_type); -int rdev_set_freq(struct cfg80211_registered_device *rdev, - struct wireless_dev *for_wdev, - int freq, enum nl80211_channel_type channel_type); +int cfg80211_set_freq(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, int freq, + enum nl80211_channel_type channel_type); u16 cfg80211_calculate_bitrate(struct rate_info *rate); diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 6a5acf750174..adcabba02e20 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -81,15 +81,10 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, struct cfg80211_cached_keys *connkeys) { struct wireless_dev *wdev = dev->ieee80211_ptr; - struct ieee80211_channel *chan; int err; ASSERT_WDEV_LOCK(wdev); - chan = rdev_fixed_channel(rdev, wdev); - if (chan && chan != params->channel) - return -EBUSY; - if (wdev->ssid_len) return -EALREADY; diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 22139fa46115..48ead6f0426d 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -378,7 +378,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx) + const u8 *key, int key_len, int key_idx, + bool local_state_change) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_auth_request req; @@ -408,6 +409,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, memset(&req, 0, sizeof(req)); + req.local_state_change = local_state_change; req.ie = ie; req.ie_len = ie_len; req.auth_type = auth_type; @@ -434,12 +436,18 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, goto out; } - wdev->authtry_bsses[slot] = bss; + if (local_state_change) + wdev->auth_bsses[slot] = bss; + else + wdev->authtry_bsses[slot] = bss; cfg80211_hold_bss(bss); err = rdev->ops->auth(&rdev->wiphy, dev, &req); if (err) { - wdev->authtry_bsses[slot] = NULL; + if (local_state_change) + wdev->auth_bsses[slot] = NULL; + else + wdev->authtry_bsses[slot] = NULL; cfg80211_unhold_bss(bss); } @@ -454,14 +462,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, enum nl80211_auth_type auth_type, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx) + const u8 *key, int key_len, int key_idx, + bool local_state_change) { int err; wdev_lock(dev->ieee80211_ptr); err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, ssid, ssid_len, ie, ie_len, - key, key_len, key_idx); + key, key_len, key_idx, local_state_change); wdev_unlock(dev->ieee80211_ptr); return err; @@ -555,7 +564,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason) + const u8 *ie, int ie_len, u16 reason, + bool local_state_change) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_deauth_request req; @@ -565,6 +575,7 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, memset(&req, 0, sizeof(req)); req.reason_code = reason; + req.local_state_change = local_state_change; req.ie = ie; req.ie_len = ie_len; if (wdev->current_bss && @@ -591,13 +602,15 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason) + const u8 *ie, int ie_len, u16 reason, + bool local_state_change) { struct wireless_dev *wdev = dev->ieee80211_ptr; int err; wdev_lock(wdev); - err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason); + err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason, + local_state_change); wdev_unlock(wdev); return err; @@ -605,7 +618,8 @@ int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason) + const u8 *ie, int ie_len, u16 reason, + bool local_state_change) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_disassoc_request req; @@ -620,6 +634,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, memset(&req, 0, sizeof(req)); req.reason_code = reason; + req.local_state_change = local_state_change; req.ie = ie; req.ie_len = ie_len; if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) @@ -632,13 +647,15 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason) + const u8 *ie, int ie_len, u16 reason, + bool local_state_change) { struct wireless_dev *wdev = dev->ieee80211_ptr; int err; wdev_lock(wdev); - err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason); + err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason, + local_state_change); wdev_unlock(wdev); return err; @@ -895,3 +912,16 @@ void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); } EXPORT_SYMBOL(cfg80211_action_tx_status); + +void cfg80211_cqm_rssi_notify(struct net_device *dev, + enum nl80211_cqm_rssi_threshold_event rssi_event, + gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + /* Indicate roaming trigger event to user space */ + nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp); +} +EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 030cf153bea2..aaa1aad566cd 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -150,6 +150,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { .len = IEEE80211_MAX_DATA_LEN }, [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, + [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, + [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, + [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 }, }; /* policy for the attributes */ @@ -586,6 +589,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, i++; NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); } + CMD(set_channel, SET_CHANNEL); #undef CMD @@ -686,10 +690,90 @@ static int parse_txq_params(struct nlattr *tb[], return 0; } +static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) +{ + /* + * You can only set the channel explicitly for AP, mesh + * and WDS type interfaces; all others have their channel + * managed via their respective "establish a connection" + * command (connect, join, ...) + * + * Monitors are special as they are normally slaved to + * whatever else is going on, so they behave as though + * you tried setting the wiphy channel itself. + */ + return !wdev || + wdev->iftype == NL80211_IFTYPE_AP || + wdev->iftype == NL80211_IFTYPE_WDS || + wdev->iftype == NL80211_IFTYPE_MESH_POINT || + wdev->iftype == NL80211_IFTYPE_MONITOR; +} + +static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, + struct genl_info *info) +{ + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + u32 freq; + int result; + + if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) + return -EINVAL; + + if (!nl80211_can_set_dev_channel(wdev)) + return -EOPNOTSUPP; + + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { + channel_type = nla_get_u32(info->attrs[ + NL80211_ATTR_WIPHY_CHANNEL_TYPE]); + if (channel_type != NL80211_CHAN_NO_HT && + channel_type != NL80211_CHAN_HT20 && + channel_type != NL80211_CHAN_HT40PLUS && + channel_type != NL80211_CHAN_HT40MINUS) + return -EINVAL; + } + + freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); + + mutex_lock(&rdev->devlist_mtx); + if (wdev) { + wdev_lock(wdev); + result = cfg80211_set_freq(rdev, wdev, freq, channel_type); + wdev_unlock(wdev); + } else { + result = cfg80211_set_freq(rdev, NULL, freq, channel_type); + } + mutex_unlock(&rdev->devlist_mtx); + + return result; +} + +static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev; + struct net_device *netdev; + int result; + + rtnl_lock(); + + result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev); + if (result) + goto unlock; + + result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info); + + unlock: + rtnl_unlock(); + + return result; +} + static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev; - int result = 0, rem_txq_params = 0; + struct net_device *netdev = NULL; + struct wireless_dev *wdev; + int result, rem_txq_params = 0; struct nlattr *nl_txq_params; u32 changed; u8 retry_short = 0, retry_long = 0; @@ -698,16 +782,50 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) rtnl_lock(); + /* + * Try to find the wiphy and netdev. Normally this + * function shouldn't need the netdev, but this is + * done for backward compatibility -- previously + * setting the channel was done per wiphy, but now + * it is per netdev. Previous userland like hostapd + * also passed a netdev to set_wiphy, so that it is + * possible to let that go to the right netdev! + */ mutex_lock(&cfg80211_mutex); - rdev = __cfg80211_rdev_from_info(info); - if (IS_ERR(rdev)) { - mutex_unlock(&cfg80211_mutex); - result = PTR_ERR(rdev); - goto unlock; + if (info->attrs[NL80211_ATTR_IFINDEX]) { + int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); + + netdev = dev_get_by_index(genl_info_net(info), ifindex); + if (netdev && netdev->ieee80211_ptr) { + rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy); + mutex_lock(&rdev->mtx); + } else + netdev = NULL; } - mutex_lock(&rdev->mtx); + if (!netdev) { + rdev = __cfg80211_rdev_from_info(info); + if (IS_ERR(rdev)) { + mutex_unlock(&cfg80211_mutex); + result = PTR_ERR(rdev); + goto unlock; + } + wdev = NULL; + netdev = NULL; + result = 0; + + mutex_lock(&rdev->mtx); + } else if (netif_running(netdev) && + nl80211_can_set_dev_channel(netdev->ieee80211_ptr)) + wdev = netdev->ieee80211_ptr; + else + wdev = NULL; + + /* + * end workaround code, by now the rdev is available + * and locked, and wdev may or may not be NULL. + */ if (info->attrs[NL80211_ATTR_WIPHY_NAME]) result = cfg80211_dev_rename( @@ -746,26 +864,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) } if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { - enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; - u32 freq; - - result = -EINVAL; - - if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { - channel_type = nla_get_u32(info->attrs[ - NL80211_ATTR_WIPHY_CHANNEL_TYPE]); - if (channel_type != NL80211_CHAN_NO_HT && - channel_type != NL80211_CHAN_HT20 && - channel_type != NL80211_CHAN_HT40PLUS && - channel_type != NL80211_CHAN_HT40MINUS) - goto bad_res; - } - - freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); - - mutex_lock(&rdev->devlist_mtx); - result = rdev_set_freq(rdev, NULL, freq, channel_type); - mutex_unlock(&rdev->devlist_mtx); + result = __nl80211_set_channel(rdev, wdev, info); if (result) goto bad_res; } @@ -862,6 +961,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) bad_res: mutex_unlock(&rdev->mtx); + if (netdev) + dev_put(netdev); unlock: rtnl_unlock(); return result; @@ -2096,7 +2197,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) goto out_rtnl; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { err = -EINVAL; goto out; } @@ -2439,6 +2541,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) params.use_cts_prot = -1; params.use_short_preamble = -1; params.use_short_slot_time = -1; + params.ap_isolate = -1; if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) params.use_cts_prot = @@ -2455,6 +2558,8 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) params.basic_rates_len = nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); } + if (info->attrs[NL80211_ATTR_AP_ISOLATE]) + params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]); rtnl_lock(); @@ -3392,6 +3497,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) int err, ssid_len, ie_len = 0; enum nl80211_auth_type auth_type; struct key_parse key; + bool local_state_change; if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) return -EINVAL; @@ -3470,9 +3576,12 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) goto out; } + local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; + err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, ssid, ssid_len, ie, ie_len, - key.p.key, key.p.key_len, key.idx); + key.p.key, key.p.key_len, key.idx, + local_state_change); out: cfg80211_unlock_rdev(rdev); @@ -3551,9 +3660,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev; struct net_device *dev; - struct wireless_dev *wdev; struct cfg80211_crypto_settings crypto; - struct ieee80211_channel *chan, *fixedchan; + struct ieee80211_channel *chan; const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; int err, ssid_len, ie_len = 0; bool use_mfp = false; @@ -3596,16 +3704,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) goto out; } - mutex_lock(&rdev->devlist_mtx); - wdev = dev->ieee80211_ptr; - fixedchan = rdev_fixed_channel(rdev, wdev); - if (fixedchan && chan != fixedchan) { - err = -EBUSY; - mutex_unlock(&rdev->devlist_mtx); - goto out; - } - mutex_unlock(&rdev->devlist_mtx); - ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); @@ -3649,6 +3747,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) const u8 *ie = NULL, *bssid; int err, ie_len = 0; u16 reason_code; + bool local_state_change; if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) return -EINVAL; @@ -3694,7 +3793,10 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); } - err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code); + local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; + + err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, + local_state_change); out: cfg80211_unlock_rdev(rdev); @@ -3711,6 +3813,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) const u8 *ie = NULL, *bssid; int err, ie_len = 0; u16 reason_code; + bool local_state_change; if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) return -EINVAL; @@ -3756,7 +3859,10 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); } - err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code); + local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; + + err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, + local_state_change); out: cfg80211_unlock_rdev(rdev); @@ -4779,6 +4885,84 @@ unlock_rtnl: return err; } +static struct nla_policy +nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = { + [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, + [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, + [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, +}; + +static int nl80211_set_cqm_rssi(struct genl_info *info, + s32 threshold, u32 hysteresis) +{ + struct cfg80211_registered_device *rdev; + struct wireless_dev *wdev; + struct net_device *dev; + int err; + + if (threshold > 0) + return -EINVAL; + + rtnl_lock(); + + err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); + if (err) + goto unlock_rdev; + + wdev = dev->ieee80211_ptr; + + if (!rdev->ops->set_cqm_rssi_config) { + err = -EOPNOTSUPP; + goto unlock_rdev; + } + + if (wdev->iftype != NL80211_IFTYPE_STATION) { + err = -EOPNOTSUPP; + goto unlock_rdev; + } + + err = rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev, + threshold, hysteresis); + +unlock_rdev: + cfg80211_unlock_rdev(rdev); + dev_put(dev); + rtnl_unlock(); + + return err; +} + +static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) +{ + struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1]; + struct nlattr *cqm; + int err; + + cqm = info->attrs[NL80211_ATTR_CQM]; + if (!cqm) { + err = -EINVAL; + goto out; + } + + err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, cqm, + nl80211_attr_cqm_policy); + if (err) + goto out; + + if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] && + attrs[NL80211_ATTR_CQM_RSSI_HYST]) { + s32 threshold; + u32 hysteresis; + threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); + hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); + err = nl80211_set_cqm_rssi(info, threshold, hysteresis); + } else + err = -EINVAL; + +out: + return err; +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -5083,6 +5267,18 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, /* can be retrieved by unprivileged users */ }, + { + .cmd = NL80211_CMD_SET_CQM, + .doit = nl80211_set_cqm, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_SET_CHANNEL, + .doit = nl80211_set_channel, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, }; static struct genl_multicast_group nl80211_mlme_mcgrp = { @@ -5833,6 +6029,52 @@ void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, nlmsg_free(msg); } +void +nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + enum nl80211_cqm_rssi_threshold_event rssi_event, + gfp_t gfp) +{ + struct sk_buff *msg; + struct nlattr *pinfoattr; + void *hdr; + + msg = nlmsg_new(NLMSG_GOODSIZE, gfp); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM); + if (!hdr) { + nlmsg_free(msg); + return; + } + + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + + pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); + if (!pinfoattr) + goto nla_put_failure; + + NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, + rssi_event); + + nla_nest_end(msg, pinfoattr); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_mlme_mcgrp.id, gfp); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + static int nl80211_netlink_notify(struct notifier_block * nb, unsigned long state, void *_notify) diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 4ca511102c6c..2ad7fbc7d9f1 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -82,4 +82,10 @@ void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, const u8 *buf, size_t len, bool ack, gfp_t gfp); +void +nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + enum nl80211_cqm_rssi_threshold_event rssi_event, + gfp_t gfp); + #endif /* __NET_WIRELESS_NL80211_H */ diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 422da20d1e5b..8f0d97dd3109 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2356,10 +2356,10 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) rdev->country_ie_alpha2[1]); } else printk(KERN_INFO "cfg80211: Current regulatory " - "domain intersected: \n"); + "domain intersected:\n"); } else - printk(KERN_INFO "cfg80211: Current regulatory " - "domain intersected: \n"); + printk(KERN_INFO "cfg80211: Current regulatory " + "domain intersected:\n"); } else if (is_world_regdom(rd->alpha2)) printk(KERN_INFO "cfg80211: World regulatory " "domain updated:\n"); diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f4dfd5f5f2ea..72222f0074db 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -171,7 +171,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) params->ssid, params->ssid_len, NULL, 0, params->key, params->key_len, - params->key_idx); + params->key_idx, false); case CFG80211_CONN_ASSOCIATE_NEXT: BUG_ON(!rdev->ops->assoc); wdev->conn->state = CFG80211_CONN_ASSOCIATING; @@ -186,12 +186,13 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) if (err) __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, NULL, 0, - WLAN_REASON_DEAUTH_LEAVING); + WLAN_REASON_DEAUTH_LEAVING, + false); return err; case CFG80211_CONN_DEAUTH_ASSOC_FAIL: __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, NULL, 0, - WLAN_REASON_DEAUTH_LEAVING); + WLAN_REASON_DEAUTH_LEAVING, false); /* return an error so that we call __cfg80211_connect_result() */ return -EINVAL; default: @@ -517,12 +518,16 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, ev->type = EVENT_CONNECT_RESULT; if (bssid) memcpy(ev->cr.bssid, bssid, ETH_ALEN); - ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev); - ev->cr.req_ie_len = req_ie_len; - memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len); - ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; - ev->cr.resp_ie_len = resp_ie_len; - memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); + if (req_ie_len) { + ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev); + ev->cr.req_ie_len = req_ie_len; + memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len); + } + if (resp_ie_len) { + ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; + ev->cr.resp_ie_len = resp_ie_len; + memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); + } ev->cr.status = status; spin_lock_irqsave(&wdev->event_lock, flags); @@ -676,7 +681,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, continue; bssid = wdev->auth_bsses[i]->pub.bssid; ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, - WLAN_REASON_DEAUTH_LEAVING); + WLAN_REASON_DEAUTH_LEAVING, + false); WARN(ret, "deauth failed: %d\n", ret); } } @@ -735,7 +741,6 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, const u8 *prev_bssid) { struct wireless_dev *wdev = dev->ieee80211_ptr; - struct ieee80211_channel *chan; struct cfg80211_bss *bss = NULL; int err; @@ -744,10 +749,6 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, if (wdev->sme_state != CFG80211_SME_IDLE) return -EALREADY; - chan = rdev_fixed_channel(rdev, wdev); - if (chan && chan != connect->channel) - return -EBUSY; - if (WARN_ON(wdev->connect_keys)) { kfree(wdev->connect_keys); wdev->connect_keys = NULL; @@ -935,7 +936,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, /* wdev->conn->params.bssid must be set if > SCANNING */ err = __cfg80211_mlme_deauth(rdev, dev, wdev->conn->params.bssid, - NULL, 0, reason); + NULL, 0, reason, false); if (err) return err; } else { @@ -991,7 +992,8 @@ void cfg80211_sme_disassoc(struct net_device *dev, int idx) memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); if (__cfg80211_mlme_deauth(rdev, dev, bssid, - NULL, 0, WLAN_REASON_DEAUTH_LEAVING)) { + NULL, 0, WLAN_REASON_DEAUTH_LEAVING, + false)) { /* whatever -- assume gone anyway */ cfg80211_unhold_bss(wdev->auth_bsses[idx]); cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); diff --git a/net/wireless/util.c b/net/wireless/util.c index d3574a4eb3ba..3416373a9c0c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -331,11 +331,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, if (iftype == NL80211_IFTYPE_MESH_POINT) { struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); - hdrlen += ieee80211_get_mesh_hdrlen(meshdr); + /* make sure meshdr->flags is on the linear part */ + if (!pskb_may_pull(skb, hdrlen + 1)) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { - memcpy(dst, meshdr->eaddr1, ETH_ALEN); - memcpy(src, meshdr->eaddr2, ETH_ALEN); + skb_copy_bits(skb, hdrlen + + offsetof(struct ieee80211s_hdr, eaddr1), + dst, ETH_ALEN); + skb_copy_bits(skb, hdrlen + + offsetof(struct ieee80211s_hdr, eaddr2), + src, ETH_ALEN); } + hdrlen += ieee80211_get_mesh_hdrlen(meshdr); } break; case cpu_to_le16(IEEE80211_FCTL_FROMDS): @@ -347,9 +354,14 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, if (iftype == NL80211_IFTYPE_MESH_POINT) { struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); - hdrlen += ieee80211_get_mesh_hdrlen(meshdr); + /* make sure meshdr->flags is on the linear part */ + if (!pskb_may_pull(skb, hdrlen + 1)) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A4) - memcpy(src, meshdr->eaddr1, ETH_ALEN); + skb_copy_bits(skb, hdrlen + + offsetof(struct ieee80211s_hdr, eaddr1), + src, ETH_ALEN); + hdrlen += ieee80211_get_mesh_hdrlen(meshdr); } break; case cpu_to_le16(0): @@ -358,7 +370,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, break; } - if (unlikely(skb->len - hdrlen < 8)) + if (!pskb_may_pull(skb, hdrlen + 8)) return -1; payload = skb->data + hdrlen; diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index a60a2773b497..96342993cf93 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -782,16 +782,22 @@ int cfg80211_wext_siwfreq(struct net_device *dev, return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra); case NL80211_IFTYPE_ADHOC: return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); - default: + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_WDS: + case NL80211_IFTYPE_MESH_POINT: freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); if (freq < 0) return freq; if (freq == 0) return -EINVAL; + wdev_lock(wdev); mutex_lock(&rdev->devlist_mtx); - err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT); + err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); mutex_unlock(&rdev->devlist_mtx); + wdev_unlock(wdev); return err; + default: + return -EOPNOTSUPP; } } EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq); @@ -801,7 +807,6 @@ int cfg80211_wext_giwfreq(struct net_device *dev, struct iw_freq *freq, char *extra) { struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); switch (wdev->iftype) { case NL80211_IFTYPE_STATION: @@ -809,9 +814,9 @@ int cfg80211_wext_giwfreq(struct net_device *dev, case NL80211_IFTYPE_ADHOC: return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); default: - if (!rdev->channel) + if (!wdev->channel) return -EINVAL; - freq->m = rdev->channel->center_freq; + freq->m = wdev->channel->center_freq; freq->e = 6; return 0; } diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 4f5a47091fde..0ef17bc42bac 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -29,226 +29,226 @@ typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, * know about. */ static const struct iw_ioctl_description standard_ioctl[] = { - [SIOCSIWCOMMIT - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWCOMMIT)] = { .header_type = IW_HEADER_TYPE_NULL, }, - [SIOCGIWNAME - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWNAME)] = { .header_type = IW_HEADER_TYPE_CHAR, .flags = IW_DESCR_FLAG_DUMP, }, - [SIOCSIWNWID - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWNWID)] = { .header_type = IW_HEADER_TYPE_PARAM, .flags = IW_DESCR_FLAG_EVENT, }, - [SIOCGIWNWID - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWNWID)] = { .header_type = IW_HEADER_TYPE_PARAM, .flags = IW_DESCR_FLAG_DUMP, }, - [SIOCSIWFREQ - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWFREQ)] = { .header_type = IW_HEADER_TYPE_FREQ, .flags = IW_DESCR_FLAG_EVENT, }, - [SIOCGIWFREQ - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWFREQ)] = { .header_type = IW_HEADER_TYPE_FREQ, .flags = IW_DESCR_FLAG_DUMP, }, - [SIOCSIWMODE - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWMODE)] = { .header_type = IW_HEADER_TYPE_UINT, .flags = IW_DESCR_FLAG_EVENT, }, - [SIOCGIWMODE - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWMODE)] = { .header_type = IW_HEADER_TYPE_UINT, .flags = IW_DESCR_FLAG_DUMP, }, - [SIOCSIWSENS - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWSENS)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCGIWSENS - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWSENS)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCSIWRANGE - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWRANGE)] = { .header_type = IW_HEADER_TYPE_NULL, }, - [SIOCGIWRANGE - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWRANGE)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = sizeof(struct iw_range), .flags = IW_DESCR_FLAG_DUMP, }, - [SIOCSIWPRIV - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWPRIV)] = { .header_type = IW_HEADER_TYPE_NULL, }, - [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */ + [IW_IOCTL_IDX(SIOCGIWPRIV)] = { /* (handled directly by us) */ .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct iw_priv_args), .max_tokens = 16, .flags = IW_DESCR_FLAG_NOMAX, }, - [SIOCSIWSTATS - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWSTATS)] = { .header_type = IW_HEADER_TYPE_NULL, }, - [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */ + [IW_IOCTL_IDX(SIOCGIWSTATS)] = { /* (handled directly by us) */ .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = sizeof(struct iw_statistics), .flags = IW_DESCR_FLAG_DUMP, }, - [SIOCSIWSPY - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWSPY)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct sockaddr), .max_tokens = IW_MAX_SPY, }, - [SIOCGIWSPY - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWSPY)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality), .max_tokens = IW_MAX_SPY, }, - [SIOCSIWTHRSPY - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWTHRSPY)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct iw_thrspy), .min_tokens = 1, .max_tokens = 1, }, - [SIOCGIWTHRSPY - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWTHRSPY)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct iw_thrspy), .min_tokens = 1, .max_tokens = 1, }, - [SIOCSIWAP - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWAP)] = { .header_type = IW_HEADER_TYPE_ADDR, }, - [SIOCGIWAP - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWAP)] = { .header_type = IW_HEADER_TYPE_ADDR, .flags = IW_DESCR_FLAG_DUMP, }, - [SIOCSIWMLME - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWMLME)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_mlme), .max_tokens = sizeof(struct iw_mlme), }, - [SIOCGIWAPLIST - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWAPLIST)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality), .max_tokens = IW_MAX_AP, .flags = IW_DESCR_FLAG_NOMAX, }, - [SIOCSIWSCAN - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWSCAN)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = 0, .max_tokens = sizeof(struct iw_scan_req), }, - [SIOCGIWSCAN - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWSCAN)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_SCAN_MAX_DATA, .flags = IW_DESCR_FLAG_NOMAX, }, - [SIOCSIWESSID - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWESSID)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE, .flags = IW_DESCR_FLAG_EVENT, }, - [SIOCGIWESSID - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWESSID)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE, .flags = IW_DESCR_FLAG_DUMP, }, - [SIOCSIWNICKN - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWNICKN)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE, }, - [SIOCGIWNICKN - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWNICKN)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE, }, - [SIOCSIWRATE - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWRATE)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCGIWRATE - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWRATE)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCSIWRTS - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWRTS)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCGIWRTS - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWRTS)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCSIWFRAG - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWFRAG)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCGIWFRAG - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWFRAG)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCSIWTXPOW - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWTXPOW)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCGIWTXPOW - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWTXPOW)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCSIWRETRY - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWRETRY)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCGIWRETRY - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWRETRY)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCSIWENCODE - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWENCODE)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ENCODING_TOKEN_MAX, .flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT, }, - [SIOCGIWENCODE - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWENCODE)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ENCODING_TOKEN_MAX, .flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT, }, - [SIOCSIWPOWER - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWPOWER)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCGIWPOWER - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWPOWER)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCSIWGENIE - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWGENIE)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, - [SIOCGIWGENIE - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWGENIE)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, - [SIOCSIWAUTH - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWAUTH)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCGIWAUTH - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWAUTH)] = { .header_type = IW_HEADER_TYPE_PARAM, }, - [SIOCSIWENCODEEXT - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWENCODEEXT)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_encode_ext), .max_tokens = sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, }, - [SIOCGIWENCODEEXT - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCGIWENCODEEXT)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_encode_ext), .max_tokens = sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, }, - [SIOCSIWPMKSA - SIOCIWFIRST] = { + [IW_IOCTL_IDX(SIOCSIWPMKSA)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_pmksa), @@ -262,44 +262,44 @@ static const unsigned standard_ioctl_num = ARRAY_SIZE(standard_ioctl); * we know about. */ static const struct iw_ioctl_description standard_event[] = { - [IWEVTXDROP - IWEVFIRST] = { + [IW_EVENT_IDX(IWEVTXDROP)] = { .header_type = IW_HEADER_TYPE_ADDR, }, - [IWEVQUAL - IWEVFIRST] = { + [IW_EVENT_IDX(IWEVQUAL)] = { .header_type = IW_HEADER_TYPE_QUAL, }, - [IWEVCUSTOM - IWEVFIRST] = { + [IW_EVENT_IDX(IWEVCUSTOM)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_CUSTOM_MAX, }, - [IWEVREGISTERED - IWEVFIRST] = { + [IW_EVENT_IDX(IWEVREGISTERED)] = { .header_type = IW_HEADER_TYPE_ADDR, }, - [IWEVEXPIRED - IWEVFIRST] = { + [IW_EVENT_IDX(IWEVEXPIRED)] = { .header_type = IW_HEADER_TYPE_ADDR, }, - [IWEVGENIE - IWEVFIRST] = { + [IW_EVENT_IDX(IWEVGENIE)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, - [IWEVMICHAELMICFAILURE - IWEVFIRST] = { + [IW_EVENT_IDX(IWEVMICHAELMICFAILURE)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = sizeof(struct iw_michaelmicfailure), }, - [IWEVASSOCREQIE - IWEVFIRST] = { + [IW_EVENT_IDX(IWEVASSOCREQIE)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, - [IWEVASSOCRESPIE - IWEVFIRST] = { + [IW_EVENT_IDX(IWEVASSOCRESPIE)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, - [IWEVPMKIDCAND - IWEVFIRST] = { + [IW_EVENT_IDX(IWEVPMKIDCAND)] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = sizeof(struct iw_pmkid_cand), @@ -450,11 +450,11 @@ void wireless_send_event(struct net_device * dev, /* Get the description of the Event */ if (cmd <= SIOCIWLAST) { - cmd_index = cmd - SIOCIWFIRST; + cmd_index = IW_IOCTL_IDX(cmd); if (cmd_index < standard_ioctl_num) descr = &(standard_ioctl[cmd_index]); } else { - cmd_index = cmd - IWEVFIRST; + cmd_index = IW_EVENT_IDX(cmd); if (cmd_index < standard_event_num) descr = &(standard_event[cmd_index]); } @@ -663,7 +663,7 @@ static iw_handler get_handler(struct net_device *dev, unsigned int cmd) return NULL; /* Try as a standard command */ - index = cmd - SIOCIWFIRST; + index = IW_IOCTL_IDX(cmd); if (index < handlers->num_standard) return handlers->standard[index]; @@ -955,9 +955,9 @@ static int ioctl_standard_call(struct net_device * dev, int ret = -EINVAL; /* Get the description of the IOCTL */ - if ((cmd - SIOCIWFIRST) >= standard_ioctl_num) + if (IW_IOCTL_IDX(cmd) >= standard_ioctl_num) return -EOPNOTSUPP; - descr = &(standard_ioctl[cmd - SIOCIWFIRST]); + descr = &(standard_ioctl[IW_IOCTL_IDX(cmd)]); /* Check if we have a pointer to user space data or not */ if (descr->header_type != IW_HEADER_TYPE_POINT) { @@ -1013,7 +1013,7 @@ static int compat_standard_call(struct net_device *dev, struct iw_point iwp; int err; - descr = standard_ioctl + (cmd - SIOCIWFIRST); + descr = standard_ioctl + IW_IOCTL_IDX(cmd); if (descr->header_type != IW_HEADER_TYPE_POINT) return ioctl_standard_call(dev, iwr, cmd, info, handler); diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index d5c6140f4cb8..9818198add8a 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -108,7 +108,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, /* SSID is not set, we just want to switch channel */ if (chan && !wdev->wext.connect.ssid_len) { - err = rdev_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); + err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); goto out; } |