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:
Linus Torvalds
2010-10-23 11:47:02 -07:00
1341 changed files with 157132 additions and 83883 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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(&reg->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(&reg->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(&reg->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

View File

@@ -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,

View File

@@ -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

View File

@@ -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(&reg_mutex))
static inline void assert_reg_lock(void)
{
lockdep_assert_held(&reg_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(&reg_requests_lock);
list_add_tail(&request->list, &reg_requests_list);
spin_unlock(&reg_requests_lock);

View File

@@ -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);

View File

@@ -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));

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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, &params);
}
@@ -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, &params);
}
@@ -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;
}

View File

@@ -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)

View File

@@ -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: