Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1699 commits) bnx2/bnx2x: Unsupported Ethtool operations should return -EINVAL. vlan: Calling vlan_hwaccel_do_receive() is always valid. tproxy: use the interface primary IP address as a default value for --on-ip tproxy: added IPv6 support to the socket match cxgb3: function namespace cleanup tproxy: added IPv6 support to the TPROXY target tproxy: added IPv6 socket lookup function to nf_tproxy_core be2net: Changes to use only priority codes allowed by f/w tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled tproxy: added tproxy sockopt interface in the IPV6 layer tproxy: added udp6_lib_lookup function tproxy: added const specifiers to udp lookup functions tproxy: split off ipv6 defragmentation to a separate module l2tp: small cleanup nf_nat: restrict ICMP translation for embedded header can: mcp251x: fix generation of error frames can: mcp251x: fix endless loop in interrupt handler if CANINTF_MERRF is set can-raw: add msg_flags to distinguish local traffic 9p: client code cleanup rds: make local functions/variables static ... Fix up conflicts in net/core/dev.c, drivers/net/pcmcia/smc91c92_cs.c and drivers/net/wireless/ath/ath9k/debug.c as per David
This commit is contained in:
@@ -253,11 +253,16 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
|
||||
WARN_ON(err);
|
||||
wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
wiphy_net_set(&rdev->wiphy, net);
|
||||
|
||||
return err;
|
||||
err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev));
|
||||
WARN_ON(err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
|
||||
@@ -428,7 +433,7 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
|
||||
/* sanity check ifmodes */
|
||||
WARN_ON(!ifmodes);
|
||||
ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1;
|
||||
ifmodes &= ((1 << NUM_NL80211_IFTYPES) - 1) & ~1;
|
||||
if (WARN_ON(ifmodes != wiphy->interface_modes))
|
||||
wiphy->interface_modes = ifmodes;
|
||||
|
||||
@@ -683,8 +688,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
|
||||
INIT_LIST_HEAD(&wdev->event_list);
|
||||
spin_lock_init(&wdev->event_lock);
|
||||
INIT_LIST_HEAD(&wdev->action_registrations);
|
||||
spin_lock_init(&wdev->action_registrations_lock);
|
||||
INIT_LIST_HEAD(&wdev->mgmt_registrations);
|
||||
spin_lock_init(&wdev->mgmt_registrations_lock);
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
list_add_rcu(&wdev->list, &rdev->netdev_list);
|
||||
@@ -724,6 +729,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
dev->ethtool_ops = &cfg80211_ethtool_ops;
|
||||
|
||||
if ((wdev->iftype == NL80211_IFTYPE_STATION ||
|
||||
wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
|
||||
wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
|
||||
dev->priv_flags |= IFF_DONT_BRIDGE;
|
||||
break;
|
||||
@@ -732,6 +738,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
cfg80211_leave_ibss(rdev, dev, true);
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
wdev_lock(wdev);
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
@@ -804,7 +811,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
sysfs_remove_link(&dev->dev.kobj, "phy80211");
|
||||
list_del_rcu(&wdev->list);
|
||||
rdev->devlist_generation++;
|
||||
cfg80211_mlme_purge_actions(wdev);
|
||||
cfg80211_mlme_purge_registrations(wdev);
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
kfree(wdev->wext.keys);
|
||||
#endif
|
||||
@@ -910,52 +917,3 @@ static void __exit cfg80211_exit(void)
|
||||
destroy_workqueue(cfg80211_wq);
|
||||
}
|
||||
module_exit(cfg80211_exit);
|
||||
|
||||
static int ___wiphy_printk(const char *level, const struct wiphy *wiphy,
|
||||
struct va_format *vaf)
|
||||
{
|
||||
if (!wiphy)
|
||||
return printk("%s(NULL wiphy *): %pV", level, vaf);
|
||||
|
||||
return printk("%s%s: %pV", level, wiphy_name(wiphy), vaf);
|
||||
}
|
||||
|
||||
int __wiphy_printk(const char *level, const struct wiphy *wiphy,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
int r;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
|
||||
r = ___wiphy_printk(level, wiphy, &vaf);
|
||||
va_end(args);
|
||||
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(__wiphy_printk);
|
||||
|
||||
#define define_wiphy_printk_level(func, kern_level) \
|
||||
int func(const struct wiphy *wiphy, const char *fmt, ...) \
|
||||
{ \
|
||||
struct va_format vaf; \
|
||||
va_list args; \
|
||||
int r; \
|
||||
\
|
||||
va_start(args, fmt); \
|
||||
\
|
||||
vaf.fmt = fmt; \
|
||||
vaf.va = &args; \
|
||||
\
|
||||
r = ___wiphy_printk(kern_level, wiphy, &vaf); \
|
||||
va_end(args); \
|
||||
\
|
||||
return r; \
|
||||
} \
|
||||
EXPORT_SYMBOL(func);
|
||||
|
||||
define_wiphy_printk_level(wiphy_debug, KERN_DEBUG);
|
||||
|
@@ -86,7 +86,7 @@ struct cfg80211_registered_device *wiphy_to_dev(struct wiphy *wiphy)
|
||||
static inline
|
||||
bool wiphy_idx_valid(int wiphy_idx)
|
||||
{
|
||||
return (wiphy_idx >= 0);
|
||||
return wiphy_idx >= 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,10 @@ extern struct mutex cfg80211_mutex;
|
||||
extern struct list_head cfg80211_rdev_list;
|
||||
extern int cfg80211_rdev_list_generation;
|
||||
|
||||
#define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex))
|
||||
static inline void assert_cfg80211_lock(void)
|
||||
{
|
||||
lockdep_assert_held(&cfg80211_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* You can use this to mark a wiphy_idx as not having an associated wiphy.
|
||||
@@ -202,8 +205,8 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
|
||||
mutex_unlock(&wdev->mtx);
|
||||
}
|
||||
|
||||
#define ASSERT_RDEV_LOCK(rdev) WARN_ON(!mutex_is_locked(&(rdev)->mtx));
|
||||
#define ASSERT_WDEV_LOCK(wdev) WARN_ON(!mutex_is_locked(&(wdev)->mtx));
|
||||
#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx)
|
||||
#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
|
||||
|
||||
enum cfg80211_event_type {
|
||||
EVENT_CONNECT_RESULT,
|
||||
@@ -331,16 +334,17 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
const u8 *resp_ie, size_t resp_ie_len,
|
||||
u16 status, bool wextev,
|
||||
struct cfg80211_bss *bss);
|
||||
int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid,
|
||||
const u8 *match_data, int match_len);
|
||||
void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid);
|
||||
void cfg80211_mlme_purge_actions(struct wireless_dev *wdev);
|
||||
int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
bool channel_type_valid,
|
||||
const u8 *buf, size_t len, u64 *cookie);
|
||||
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
|
||||
u16 frame_type, const u8 *match_data,
|
||||
int match_len);
|
||||
void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
|
||||
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
|
||||
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
bool channel_type_valid,
|
||||
const u8 *buf, size_t len, u64 *cookie);
|
||||
|
||||
/* SME */
|
||||
int __cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
@@ -371,7 +375,7 @@ bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev);
|
||||
/* internal helpers */
|
||||
int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
||||
struct key_params *params, int key_idx,
|
||||
const u8 *mac_addr);
|
||||
bool pairwise, const u8 *mac_addr);
|
||||
void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
|
||||
size_t ie_len, u16 reason, bool from_ap);
|
||||
void cfg80211_sme_scan_done(struct net_device *dev);
|
||||
|
@@ -88,6 +88,25 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
||||
if (wdev->ssid_len)
|
||||
return -EALREADY;
|
||||
|
||||
if (!params->basic_rates) {
|
||||
/*
|
||||
* If no rates were explicitly configured,
|
||||
* use the mandatory rate set for 11b or
|
||||
* 11a for maximum compatibility.
|
||||
*/
|
||||
struct ieee80211_supported_band *sband =
|
||||
rdev->wiphy.bands[params->channel->band];
|
||||
int j;
|
||||
u32 flag = params->channel->band == IEEE80211_BAND_5GHZ ?
|
||||
IEEE80211_RATE_MANDATORY_A :
|
||||
IEEE80211_RATE_MANDATORY_B;
|
||||
|
||||
for (j = 0; j < sband->n_bitrates; j++) {
|
||||
if (sband->bitrates[j].flags & flag)
|
||||
params->basic_rates |= BIT(j);
|
||||
}
|
||||
}
|
||||
|
||||
if (WARN_ON(wdev->connect_keys))
|
||||
kfree(wdev->connect_keys);
|
||||
wdev->connect_keys = connkeys;
|
||||
@@ -141,7 +160,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
|
||||
*/
|
||||
if (rdev->ops->del_key)
|
||||
for (i = 0; i < 6; i++)
|
||||
rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
|
||||
rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
|
||||
|
||||
if (wdev->current_bss) {
|
||||
cfg80211_unhold_bss(wdev->current_bss);
|
||||
|
@@ -149,7 +149,7 @@ void __cfg80211_send_deauth(struct net_device *dev,
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
|
||||
const u8 *bssid = mgmt->bssid;
|
||||
int i;
|
||||
bool found = false;
|
||||
bool found = false, was_current = false;
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
@@ -159,6 +159,7 @@ void __cfg80211_send_deauth(struct net_device *dev,
|
||||
cfg80211_put_bss(&wdev->current_bss->pub);
|
||||
wdev->current_bss = NULL;
|
||||
found = true;
|
||||
was_current = true;
|
||||
} else for (i = 0; i < MAX_AUTH_BSSES; i++) {
|
||||
if (wdev->auth_bsses[i] &&
|
||||
memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
|
||||
@@ -183,7 +184,7 @@ void __cfg80211_send_deauth(struct net_device *dev,
|
||||
|
||||
nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
|
||||
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTED) {
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) {
|
||||
u16 reason_code;
|
||||
bool from_ap;
|
||||
|
||||
@@ -747,31 +748,53 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_new_sta);
|
||||
|
||||
struct cfg80211_action_registration {
|
||||
struct cfg80211_mgmt_registration {
|
||||
struct list_head list;
|
||||
|
||||
u32 nlpid;
|
||||
|
||||
int match_len;
|
||||
|
||||
__le16 frame_type;
|
||||
|
||||
u8 match[];
|
||||
};
|
||||
|
||||
int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid,
|
||||
const u8 *match_data, int match_len)
|
||||
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
|
||||
u16 frame_type, const u8 *match_data,
|
||||
int match_len)
|
||||
{
|
||||
struct cfg80211_action_registration *reg, *nreg;
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
struct cfg80211_mgmt_registration *reg, *nreg;
|
||||
int err = 0;
|
||||
u16 mgmt_type;
|
||||
|
||||
if (!wdev->wiphy->mgmt_stypes)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
|
||||
return -EINVAL;
|
||||
|
||||
if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
|
||||
return -EINVAL;
|
||||
|
||||
mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
|
||||
if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type)))
|
||||
return -EINVAL;
|
||||
|
||||
nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
|
||||
if (!nreg)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_bh(&wdev->action_registrations_lock);
|
||||
spin_lock_bh(&wdev->mgmt_registrations_lock);
|
||||
|
||||
list_for_each_entry(reg, &wdev->action_registrations, list) {
|
||||
list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
|
||||
int mlen = min(match_len, reg->match_len);
|
||||
|
||||
if (frame_type != le16_to_cpu(reg->frame_type))
|
||||
continue;
|
||||
|
||||
if (memcmp(reg->match, match_data, mlen) == 0) {
|
||||
err = -EALREADY;
|
||||
break;
|
||||
@@ -786,140 +809,212 @@ int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid,
|
||||
memcpy(nreg->match, match_data, match_len);
|
||||
nreg->match_len = match_len;
|
||||
nreg->nlpid = snd_pid;
|
||||
list_add(&nreg->list, &wdev->action_registrations);
|
||||
nreg->frame_type = cpu_to_le16(frame_type);
|
||||
list_add(&nreg->list, &wdev->mgmt_registrations);
|
||||
|
||||
if (rdev->ops->mgmt_frame_register)
|
||||
rdev->ops->mgmt_frame_register(wiphy, wdev->netdev,
|
||||
frame_type, true);
|
||||
|
||||
out:
|
||||
spin_unlock_bh(&wdev->action_registrations_lock);
|
||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid)
|
||||
void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid)
|
||||
{
|
||||
struct cfg80211_action_registration *reg, *tmp;
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
struct cfg80211_mgmt_registration *reg, *tmp;
|
||||
|
||||
spin_lock_bh(&wdev->action_registrations_lock);
|
||||
spin_lock_bh(&wdev->mgmt_registrations_lock);
|
||||
|
||||
list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
|
||||
if (reg->nlpid == nlpid) {
|
||||
list_del(®->list);
|
||||
kfree(reg);
|
||||
list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
|
||||
if (reg->nlpid != nlpid)
|
||||
continue;
|
||||
|
||||
if (rdev->ops->mgmt_frame_register) {
|
||||
u16 frame_type = le16_to_cpu(reg->frame_type);
|
||||
|
||||
rdev->ops->mgmt_frame_register(wiphy, wdev->netdev,
|
||||
frame_type, false);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_bh(&wdev->action_registrations_lock);
|
||||
}
|
||||
|
||||
void cfg80211_mlme_purge_actions(struct wireless_dev *wdev)
|
||||
{
|
||||
struct cfg80211_action_registration *reg, *tmp;
|
||||
|
||||
spin_lock_bh(&wdev->action_registrations_lock);
|
||||
|
||||
list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
|
||||
list_del(®->list);
|
||||
kfree(reg);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&wdev->action_registrations_lock);
|
||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||
}
|
||||
|
||||
int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
bool channel_type_valid,
|
||||
const u8 *buf, size_t len, u64 *cookie)
|
||||
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
|
||||
{
|
||||
struct cfg80211_mgmt_registration *reg, *tmp;
|
||||
|
||||
spin_lock_bh(&wdev->mgmt_registrations_lock);
|
||||
|
||||
list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
|
||||
list_del(®->list);
|
||||
kfree(reg);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||
}
|
||||
|
||||
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
bool channel_type_valid,
|
||||
const u8 *buf, size_t len, u64 *cookie)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
const struct ieee80211_mgmt *mgmt;
|
||||
u16 stype;
|
||||
|
||||
if (rdev->ops->action == NULL)
|
||||
if (!wdev->wiphy->mgmt_stypes)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!rdev->ops->mgmt_tx)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (len < 24 + 1)
|
||||
return -EINVAL;
|
||||
|
||||
mgmt = (const struct ieee80211_mgmt *) buf;
|
||||
if (!ieee80211_is_action(mgmt->frame_control))
|
||||
|
||||
if (!ieee80211_is_mgmt(mgmt->frame_control))
|
||||
return -EINVAL;
|
||||
if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
|
||||
/* Verify that we are associated with the destination AP */
|
||||
|
||||
stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
|
||||
if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4)))
|
||||
return -EINVAL;
|
||||
|
||||
if (ieee80211_is_action(mgmt->frame_control) &&
|
||||
mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
|
||||
int err = 0;
|
||||
|
||||
wdev_lock(wdev);
|
||||
|
||||
if (!wdev->current_bss ||
|
||||
memcmp(wdev->current_bss->pub.bssid, mgmt->bssid,
|
||||
ETH_ALEN) != 0 ||
|
||||
(wdev->iftype == NL80211_IFTYPE_STATION &&
|
||||
memcmp(wdev->current_bss->pub.bssid, mgmt->da,
|
||||
ETH_ALEN) != 0)) {
|
||||
wdev_unlock(wdev);
|
||||
return -ENOTCONN;
|
||||
}
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
if (!wdev->current_bss) {
|
||||
err = -ENOTCONN;
|
||||
break;
|
||||
}
|
||||
|
||||
if (memcmp(wdev->current_bss->pub.bssid,
|
||||
mgmt->bssid, ETH_ALEN)) {
|
||||
err = -ENOTCONN;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* check for IBSS DA must be done by driver as
|
||||
* cfg80211 doesn't track the stations
|
||||
*/
|
||||
if (wdev->iftype == NL80211_IFTYPE_ADHOC)
|
||||
break;
|
||||
|
||||
/* for station, check that DA is the AP */
|
||||
if (memcmp(wdev->current_bss->pub.bssid,
|
||||
mgmt->da, ETH_ALEN)) {
|
||||
err = -ENOTCONN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
if (memcmp(mgmt->bssid, dev->dev_addr, ETH_ALEN))
|
||||
err = -EINVAL;
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
wdev_unlock(wdev);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Transmit the Action frame as requested by user space */
|
||||
return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type,
|
||||
channel_type_valid, buf, len, cookie);
|
||||
return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, channel_type,
|
||||
channel_type_valid, buf, len, cookie);
|
||||
}
|
||||
|
||||
bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf,
|
||||
size_t len, gfp_t gfp)
|
||||
bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
|
||||
size_t len, gfp_t gfp)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
struct cfg80211_action_registration *reg;
|
||||
const u8 *action_data;
|
||||
int action_data_len;
|
||||
struct cfg80211_mgmt_registration *reg;
|
||||
const struct ieee80211_txrx_stypes *stypes =
|
||||
&wiphy->mgmt_stypes[wdev->iftype];
|
||||
struct ieee80211_mgmt *mgmt = (void *)buf;
|
||||
const u8 *data;
|
||||
int data_len;
|
||||
bool result = false;
|
||||
__le16 ftype = mgmt->frame_control &
|
||||
cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
|
||||
u16 stype;
|
||||
|
||||
/* frame length - min size excluding category */
|
||||
action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1);
|
||||
stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
|
||||
|
||||
/* action data starts with category */
|
||||
action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1;
|
||||
if (!(stypes->rx & BIT(stype)))
|
||||
return false;
|
||||
|
||||
spin_lock_bh(&wdev->action_registrations_lock);
|
||||
data = buf + ieee80211_hdrlen(mgmt->frame_control);
|
||||
data_len = len - ieee80211_hdrlen(mgmt->frame_control);
|
||||
|
||||
list_for_each_entry(reg, &wdev->action_registrations, list) {
|
||||
if (reg->match_len > action_data_len)
|
||||
spin_lock_bh(&wdev->mgmt_registrations_lock);
|
||||
|
||||
list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
|
||||
if (reg->frame_type != ftype)
|
||||
continue;
|
||||
|
||||
if (memcmp(reg->match, action_data, reg->match_len))
|
||||
if (reg->match_len > data_len)
|
||||
continue;
|
||||
|
||||
if (memcmp(reg->match, data, reg->match_len))
|
||||
continue;
|
||||
|
||||
/* found match! */
|
||||
|
||||
/* Indicate the received Action frame to user space */
|
||||
if (nl80211_send_action(rdev, dev, reg->nlpid, freq,
|
||||
buf, len, gfp))
|
||||
if (nl80211_send_mgmt(rdev, dev, reg->nlpid, freq,
|
||||
buf, len, gfp))
|
||||
continue;
|
||||
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&wdev->action_registrations_lock);
|
||||
spin_unlock_bh(&wdev->mgmt_registrations_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_rx_action);
|
||||
EXPORT_SYMBOL(cfg80211_rx_mgmt);
|
||||
|
||||
void cfg80211_action_tx_status(struct net_device *dev, u64 cookie,
|
||||
const u8 *buf, size_t len, bool ack, gfp_t gfp)
|
||||
void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie,
|
||||
const u8 *buf, size_t len, bool ack, 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 TX status of the Action frame to user space */
|
||||
nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp);
|
||||
nl80211_send_mgmt_tx_status(rdev, dev, cookie, buf, len, ack, gfp);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_action_tx_status);
|
||||
EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
|
||||
|
||||
void cfg80211_cqm_rssi_notify(struct net_device *dev,
|
||||
enum nl80211_cqm_rssi_threshold_event rssi_event,
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -74,13 +74,13 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo, gfp_t gfp);
|
||||
|
||||
int nl80211_send_action(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, u32 nlpid, int freq,
|
||||
const u8 *buf, size_t len, gfp_t gfp);
|
||||
void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, u64 cookie,
|
||||
const u8 *buf, size_t len, bool ack,
|
||||
gfp_t gfp);
|
||||
int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, u32 nlpid, int freq,
|
||||
const u8 *buf, size_t len, gfp_t gfp);
|
||||
void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, u64 cookie,
|
||||
const u8 *buf, size_t len, bool ack,
|
||||
gfp_t gfp);
|
||||
|
||||
void
|
||||
nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
|
||||
|
@@ -14,6 +14,7 @@
|
||||
* See COPYING for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/ieee80211_radiotap.h>
|
||||
#include <asm/unaligned.h>
|
||||
@@ -45,7 +46,7 @@ static const struct radiotap_align_size rtap_namespace_sizes[] = {
|
||||
};
|
||||
|
||||
static const struct ieee80211_radiotap_namespace radiotap_ns = {
|
||||
.n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]),
|
||||
.n_bits = ARRAY_SIZE(rtap_namespace_sizes),
|
||||
.align_size = rtap_namespace_sizes,
|
||||
};
|
||||
|
||||
@@ -200,7 +201,7 @@ int ieee80211_radiotap_iterator_next(
|
||||
{
|
||||
while (1) {
|
||||
int hit = 0;
|
||||
int pad, align, size, subns, vnslen;
|
||||
int pad, align, size, subns;
|
||||
uint32_t oui;
|
||||
|
||||
/* if no more EXT bits, that's it */
|
||||
@@ -260,6 +261,27 @@ int ieee80211_radiotap_iterator_next(
|
||||
if (pad)
|
||||
iterator->_arg += align - pad;
|
||||
|
||||
if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) {
|
||||
int vnslen;
|
||||
|
||||
if ((unsigned long)iterator->_arg + size -
|
||||
(unsigned long)iterator->_rtheader >
|
||||
(unsigned long)iterator->_max_length)
|
||||
return -EINVAL;
|
||||
|
||||
oui = (*iterator->_arg << 16) |
|
||||
(*(iterator->_arg + 1) << 8) |
|
||||
*(iterator->_arg + 2);
|
||||
subns = *(iterator->_arg + 3);
|
||||
|
||||
find_ns(iterator, oui, subns);
|
||||
|
||||
vnslen = get_unaligned_le16(iterator->_arg + 4);
|
||||
iterator->_next_ns_data = iterator->_arg + size + vnslen;
|
||||
if (!iterator->current_namespace)
|
||||
size += vnslen;
|
||||
}
|
||||
|
||||
/*
|
||||
* this is what we will return to user, but we need to
|
||||
* move on first so next call has something fresh to test
|
||||
@@ -286,40 +308,25 @@ int ieee80211_radiotap_iterator_next(
|
||||
/* these special ones are valid in each bitmap word */
|
||||
switch (iterator->_arg_index % 32) {
|
||||
case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
|
||||
iterator->_bitmap_shifter >>= 1;
|
||||
iterator->_arg_index++;
|
||||
|
||||
iterator->_reset_on_ext = 1;
|
||||
|
||||
vnslen = get_unaligned_le16(iterator->this_arg + 4);
|
||||
iterator->_next_ns_data = iterator->_arg + vnslen;
|
||||
oui = (*iterator->this_arg << 16) |
|
||||
(*(iterator->this_arg + 1) << 8) |
|
||||
*(iterator->this_arg + 2);
|
||||
subns = *(iterator->this_arg + 3);
|
||||
|
||||
find_ns(iterator, oui, subns);
|
||||
|
||||
iterator->is_radiotap_ns = 0;
|
||||
/* allow parsers to show this information */
|
||||
/*
|
||||
* If parser didn't register this vendor
|
||||
* namespace with us, allow it to show it
|
||||
* as 'raw. Do do that, set argument index
|
||||
* to vendor namespace.
|
||||
*/
|
||||
iterator->this_arg_index =
|
||||
IEEE80211_RADIOTAP_VENDOR_NAMESPACE;
|
||||
iterator->this_arg_size += vnslen;
|
||||
if ((unsigned long)iterator->this_arg +
|
||||
iterator->this_arg_size -
|
||||
(unsigned long)iterator->_rtheader >
|
||||
(unsigned long)(unsigned long)iterator->_max_length)
|
||||
return -EINVAL;
|
||||
hit = 1;
|
||||
break;
|
||||
if (!iterator->current_namespace)
|
||||
hit = 1;
|
||||
goto next_entry;
|
||||
case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
|
||||
iterator->_bitmap_shifter >>= 1;
|
||||
iterator->_arg_index++;
|
||||
|
||||
iterator->_reset_on_ext = 1;
|
||||
iterator->current_namespace = &radiotap_ns;
|
||||
iterator->is_radiotap_ns = 1;
|
||||
break;
|
||||
goto next_entry;
|
||||
case IEEE80211_RADIOTAP_EXT:
|
||||
/*
|
||||
* bit 31 was set, there is more
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <net/cfg80211.h>
|
||||
@@ -73,7 +74,11 @@ const struct ieee80211_regdomain *cfg80211_regdomain;
|
||||
* - last_request
|
||||
*/
|
||||
static DEFINE_MUTEX(reg_mutex);
|
||||
#define assert_reg_lock() WARN_ON(!mutex_is_locked(®_mutex))
|
||||
|
||||
static inline void assert_reg_lock(void)
|
||||
{
|
||||
lockdep_assert_held(®_mutex);
|
||||
}
|
||||
|
||||
/* Used to queue up regulatory hints */
|
||||
static LIST_HEAD(reg_requests_list);
|
||||
@@ -181,14 +186,6 @@ static bool is_alpha2_set(const char *alpha2)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_alpha_upper(char letter)
|
||||
{
|
||||
/* ASCII A - Z */
|
||||
if (letter >= 65 && letter <= 90)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_unknown_alpha2(const char *alpha2)
|
||||
{
|
||||
if (!alpha2)
|
||||
@@ -220,7 +217,7 @@ static bool is_an_alpha2(const char *alpha2)
|
||||
{
|
||||
if (!alpha2)
|
||||
return false;
|
||||
if (is_alpha_upper(alpha2[0]) && is_alpha_upper(alpha2[1]))
|
||||
if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -1399,6 +1396,11 @@ static DECLARE_WORK(reg_work, reg_todo);
|
||||
|
||||
static void queue_regulatory_request(struct regulatory_request *request)
|
||||
{
|
||||
if (isalpha(request->alpha2[0]))
|
||||
request->alpha2[0] = toupper(request->alpha2[0]);
|
||||
if (isalpha(request->alpha2[1]))
|
||||
request->alpha2[1] = toupper(request->alpha2[1]);
|
||||
|
||||
spin_lock(®_requests_lock);
|
||||
list_add_tail(&request->list, ®_requests_list);
|
||||
spin_unlock(®_requests_lock);
|
||||
|
@@ -650,14 +650,14 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
|
||||
bss = container_of(pub, struct cfg80211_internal_bss, pub);
|
||||
|
||||
spin_lock_bh(&dev->bss_lock);
|
||||
if (!list_empty(&bss->list)) {
|
||||
list_del_init(&bss->list);
|
||||
dev->bss_generation++;
|
||||
rb_erase(&bss->rbn, &dev->bss_tree);
|
||||
|
||||
list_del(&bss->list);
|
||||
dev->bss_generation++;
|
||||
rb_erase(&bss->rbn, &dev->bss_tree);
|
||||
|
||||
kref_put(&bss->ref, bss_release);
|
||||
}
|
||||
spin_unlock_bh(&dev->bss_lock);
|
||||
|
||||
kref_put(&bss->ref, bss_release);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_unlink_bss);
|
||||
|
||||
|
@@ -411,7 +411,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
|
||||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
|
||||
wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
|
||||
return;
|
||||
|
||||
if (wdev->sme_state != CFG80211_SME_CONNECTING)
|
||||
@@ -548,7 +549,8 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
|
||||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
|
||||
wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
|
||||
return;
|
||||
|
||||
if (wdev->sme_state != CFG80211_SME_CONNECTED)
|
||||
@@ -644,7 +646,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
|
||||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
|
||||
wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
|
||||
return;
|
||||
|
||||
if (wdev->sme_state != CFG80211_SME_CONNECTED)
|
||||
@@ -695,7 +698,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
|
||||
*/
|
||||
if (rdev->ops->del_key)
|
||||
for (i = 0; i < 6; i++)
|
||||
rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
|
||||
rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
|
||||
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
memset(&wrqu, 0, sizeof(wrqu));
|
||||
|
@@ -35,6 +35,14 @@ SHOW_FMT(index, "%d", wiphy_idx);
|
||||
SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
|
||||
SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
|
||||
|
||||
static ssize_t name_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf) {
|
||||
struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
|
||||
return sprintf(buf, "%s\n", dev_name(&wiphy->dev));
|
||||
}
|
||||
|
||||
|
||||
static ssize_t addresses_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
@@ -57,6 +65,7 @@ static struct device_attribute ieee80211_dev_attrs[] = {
|
||||
__ATTR_RO(macaddress),
|
||||
__ATTR_RO(address_mask),
|
||||
__ATTR_RO(addresses),
|
||||
__ATTR_RO(name),
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -110,6 +119,13 @@ static int wiphy_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const void *wiphy_namespace(struct device *d)
|
||||
{
|
||||
struct wiphy *wiphy = container_of(d, struct wiphy, dev);
|
||||
|
||||
return wiphy_net(wiphy);
|
||||
}
|
||||
|
||||
struct class ieee80211_class = {
|
||||
.name = "ieee80211",
|
||||
.owner = THIS_MODULE,
|
||||
@@ -120,6 +136,8 @@ struct class ieee80211_class = {
|
||||
#endif
|
||||
.suspend = wiphy_suspend,
|
||||
.resume = wiphy_resume,
|
||||
.ns_type = &net_ns_type_operations,
|
||||
.namespace = wiphy_namespace,
|
||||
};
|
||||
|
||||
int wiphy_sysfs_init(void)
|
||||
|
@@ -144,19 +144,25 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
|
||||
|
||||
int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
||||
struct key_params *params, int key_idx,
|
||||
const u8 *mac_addr)
|
||||
bool pairwise, const u8 *mac_addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (key_idx > 5)
|
||||
return -EINVAL;
|
||||
|
||||
if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
|
||||
return -EINVAL;
|
||||
|
||||
if (pairwise && !mac_addr)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Disallow pairwise keys with non-zero index unless it's WEP
|
||||
* (because current deployments use pairwise WEP keys with
|
||||
* non-zero indizes but 802.11i clearly specifies to use zero)
|
||||
*/
|
||||
if (mac_addr && key_idx &&
|
||||
if (pairwise && key_idx &&
|
||||
params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
|
||||
params->cipher != WLAN_CIPHER_SUITE_WEP104)
|
||||
return -EINVAL;
|
||||
@@ -183,7 +189,14 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
/*
|
||||
* We don't know anything about this algorithm,
|
||||
* allow using it -- but the driver must check
|
||||
* all parameters! We still check below whether
|
||||
* or not the driver supports this algorithm,
|
||||
* of course.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if (params->seq) {
|
||||
@@ -221,7 +234,7 @@ const unsigned char bridge_tunnel_header[] __aligned(2) =
|
||||
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
|
||||
EXPORT_SYMBOL(bridge_tunnel_header);
|
||||
|
||||
unsigned int ieee80211_hdrlen(__le16 fc)
|
||||
unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc)
|
||||
{
|
||||
unsigned int hdrlen = 24;
|
||||
|
||||
@@ -319,7 +332,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
|
||||
cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
|
||||
case cpu_to_le16(IEEE80211_FCTL_TODS):
|
||||
if (unlikely(iftype != NL80211_IFTYPE_AP &&
|
||||
iftype != NL80211_IFTYPE_AP_VLAN))
|
||||
iftype != NL80211_IFTYPE_AP_VLAN &&
|
||||
iftype != NL80211_IFTYPE_P2P_GO))
|
||||
return -1;
|
||||
break;
|
||||
case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
|
||||
@@ -347,7 +361,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
|
||||
break;
|
||||
case cpu_to_le16(IEEE80211_FCTL_FROMDS):
|
||||
if ((iftype != NL80211_IFTYPE_STATION &&
|
||||
iftype != NL80211_IFTYPE_MESH_POINT) ||
|
||||
iftype != NL80211_IFTYPE_P2P_CLIENT &&
|
||||
iftype != NL80211_IFTYPE_MESH_POINT) ||
|
||||
(is_multicast_ether_addr(dst) &&
|
||||
!compare_ether_addr(src, addr)))
|
||||
return -1;
|
||||
@@ -424,6 +439,7 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
|
||||
switch (iftype) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
|
||||
/* DA BSSID SA */
|
||||
memcpy(hdr.addr1, skb->data, ETH_ALEN);
|
||||
@@ -432,6 +448,7 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
|
||||
hdrlen = 24;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
|
||||
/* BSSID SA DA */
|
||||
memcpy(hdr.addr1, bssid, ETH_ALEN);
|
||||
@@ -666,7 +683,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (!wdev->connect_keys->params[i].cipher)
|
||||
continue;
|
||||
if (rdev->ops->add_key(wdev->wiphy, dev, i, NULL,
|
||||
if (rdev->ops->add_key(wdev->wiphy, dev, i, false, NULL,
|
||||
&wdev->connect_keys->params[i])) {
|
||||
printk(KERN_ERR "%s: failed to set key %d\n",
|
||||
dev->name, i);
|
||||
@@ -771,7 +788,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
|
||||
/* if it's part of a bridge, reject changing type to station/ibss */
|
||||
if ((dev->priv_flags & IFF_BRIDGE_PORT) &&
|
||||
(ntype == NL80211_IFTYPE_ADHOC || ntype == NL80211_IFTYPE_STATION))
|
||||
(ntype == NL80211_IFTYPE_ADHOC ||
|
||||
ntype == NL80211_IFTYPE_STATION ||
|
||||
ntype == NL80211_IFTYPE_P2P_CLIENT))
|
||||
return -EBUSY;
|
||||
|
||||
if (ntype != otype) {
|
||||
@@ -782,6 +801,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
cfg80211_leave_ibss(rdev, dev, false);
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, true);
|
||||
break;
|
||||
@@ -810,9 +830,11 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
if (dev->ieee80211_ptr->use_4addr)
|
||||
break;
|
||||
/* fall through */
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
dev->priv_flags |= IFF_DONT_BRIDGE;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
case NL80211_IFTYPE_WDS:
|
||||
@@ -823,7 +845,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
/* monitor can't bridge anyway */
|
||||
break;
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
case __NL80211_IFTYPE_AFTER_LAST:
|
||||
case NUM_NL80211_IFTYPES:
|
||||
/* not happening */
|
||||
break;
|
||||
}
|
||||
|
@@ -432,14 +432,17 @@ int cfg80211_wext_giwretry(struct net_device *dev,
|
||||
EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
|
||||
|
||||
static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *addr,
|
||||
bool remove, bool tx_key, int idx,
|
||||
struct key_params *params)
|
||||
struct net_device *dev, bool pairwise,
|
||||
const u8 *addr, bool remove, bool tx_key,
|
||||
int idx, struct key_params *params)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err, i;
|
||||
bool rejoin = false;
|
||||
|
||||
if (pairwise && !addr)
|
||||
return -EINVAL;
|
||||
|
||||
if (!wdev->wext.keys) {
|
||||
wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
|
||||
GFP_KERNEL);
|
||||
@@ -478,7 +481,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
||||
__cfg80211_leave_ibss(rdev, wdev->netdev, true);
|
||||
rejoin = true;
|
||||
}
|
||||
err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
|
||||
|
||||
if (!pairwise && addr &&
|
||||
!(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
|
||||
err = -ENOENT;
|
||||
else
|
||||
err = rdev->ops->del_key(&rdev->wiphy, dev, idx,
|
||||
pairwise, addr);
|
||||
}
|
||||
wdev->wext.connect.privacy = false;
|
||||
/*
|
||||
@@ -507,12 +516,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
||||
if (addr)
|
||||
tx_key = false;
|
||||
|
||||
if (cfg80211_validate_key_settings(rdev, params, idx, addr))
|
||||
if (cfg80211_validate_key_settings(rdev, params, idx, pairwise, addr))
|
||||
return -EINVAL;
|
||||
|
||||
err = 0;
|
||||
if (wdev->current_bss)
|
||||
err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
|
||||
err = rdev->ops->add_key(&rdev->wiphy, dev, idx,
|
||||
pairwise, addr, params);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -563,17 +573,17 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
||||
}
|
||||
|
||||
static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *addr,
|
||||
bool remove, bool tx_key, int idx,
|
||||
struct key_params *params)
|
||||
struct net_device *dev, bool pairwise,
|
||||
const u8 *addr, bool remove, bool tx_key,
|
||||
int idx, struct key_params *params)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* devlist mutex needed for possible IBSS re-join */
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = __cfg80211_set_encryption(rdev, dev, addr, remove,
|
||||
tx_key, idx, params);
|
||||
err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
|
||||
remove, tx_key, idx, params);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
@@ -635,7 +645,7 @@ int cfg80211_wext_siwencode(struct net_device *dev,
|
||||
else if (!remove)
|
||||
return -EINVAL;
|
||||
|
||||
return cfg80211_set_encryption(rdev, dev, NULL, remove,
|
||||
return cfg80211_set_encryption(rdev, dev, false, NULL, remove,
|
||||
wdev->wext.default_key == -1,
|
||||
idx, ¶ms);
|
||||
}
|
||||
@@ -725,7 +735,9 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
|
||||
}
|
||||
|
||||
return cfg80211_set_encryption(
|
||||
rdev, dev, addr, remove,
|
||||
rdev, dev,
|
||||
!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
|
||||
addr, remove,
|
||||
ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
|
||||
idx, ¶ms);
|
||||
}
|
||||
@@ -1354,6 +1366,10 @@ struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
|
||||
}
|
||||
|
||||
wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
|
||||
if (sinfo.filled & STATION_INFO_RX_DROP_MISC)
|
||||
wstats.discard.misc = sinfo.rx_dropped_misc;
|
||||
if (sinfo.filled & STATION_INFO_TX_FAILED)
|
||||
wstats.discard.retries = sinfo.tx_failed;
|
||||
|
||||
return &wstats;
|
||||
}
|
||||
|
@@ -611,7 +611,7 @@ struct iw_statistics *get_wireless_stats(struct net_device *dev)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
if (dev->ieee80211_ptr && dev->ieee80211_ptr &&
|
||||
if (dev->ieee80211_ptr &&
|
||||
dev->ieee80211_ptr->wiphy &&
|
||||
dev->ieee80211_ptr->wiphy->wext &&
|
||||
dev->ieee80211_ptr->wiphy->wext->get_wireless_stats)
|
||||
|
@@ -197,6 +197,8 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
|
||||
wdev->wext.connect.ssid_len = len;
|
||||
|
||||
wdev->wext.connect.crypto.control_port = false;
|
||||
wdev->wext.connect.crypto.control_port_ethertype =
|
||||
cpu_to_be16(ETH_P_PAE);
|
||||
|
||||
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
||||
out:
|
||||
|
Reference in New Issue
Block a user