aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-11-04 06:18:12 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-11-09 16:05:49 -0500
commit28946da763e8b8d8ffd01ab861b684a4afb4bc3b (patch)
treec4e1cd440702b81c2192a164356da4ba769a29a6 /net/wireless/nl80211.c
parent665c93a93e35cafcd8c84073824f1ef1b19f0a7d (diff)
nl80211: allow subscribing to unexpected class3 frames
To implement AP mode without monitor interfaces we need to be able to send a deauth to stations that send frames without being associated. Enable this by adding a new nl80211 event for such frames that an application can subscribe to. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2bcaa579cebf..9910c3cb9a85 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5832,6 +5832,23 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
5832 return err; 5832 return err;
5833} 5833}
5834 5834
5835static int nl80211_register_unexpected_frame(struct sk_buff *skb,
5836 struct genl_info *info)
5837{
5838 struct net_device *dev = info->user_ptr[1];
5839 struct wireless_dev *wdev = dev->ieee80211_ptr;
5840
5841 if (wdev->iftype != NL80211_IFTYPE_AP &&
5842 wdev->iftype != NL80211_IFTYPE_P2P_GO)
5843 return -EINVAL;
5844
5845 if (wdev->ap_unexpected_nlpid)
5846 return -EBUSY;
5847
5848 wdev->ap_unexpected_nlpid = info->snd_pid;
5849 return 0;
5850}
5851
5835#define NL80211_FLAG_NEED_WIPHY 0x01 5852#define NL80211_FLAG_NEED_WIPHY 0x01
5836#define NL80211_FLAG_NEED_NETDEV 0x02 5853#define NL80211_FLAG_NEED_NETDEV 0x02
5837#define NL80211_FLAG_NEED_RTNL 0x04 5854#define NL80211_FLAG_NEED_RTNL 0x04
@@ -6387,6 +6404,14 @@ static struct genl_ops nl80211_ops[] = {
6387 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 6404 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
6388 NL80211_FLAG_NEED_RTNL, 6405 NL80211_FLAG_NEED_RTNL,
6389 }, 6406 },
6407 {
6408 .cmd = NL80211_CMD_UNEXPECTED_FRAME,
6409 .doit = nl80211_register_unexpected_frame,
6410 .policy = nl80211_policy,
6411 .flags = GENL_ADMIN_PERM,
6412 .internal_flags = NL80211_FLAG_NEED_NETDEV |
6413 NL80211_FLAG_NEED_RTNL,
6414 },
6390}; 6415};
6391 6416
6392static struct genl_multicast_group nl80211_mlme_mcgrp = { 6417static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -7171,6 +7196,47 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev,
7171 nlmsg_free(msg); 7196 nlmsg_free(msg);
7172} 7197}
7173 7198
7199bool nl80211_unexpected_frame(struct net_device *dev, const u8 *addr, gfp_t gfp)
7200{
7201 struct wireless_dev *wdev = dev->ieee80211_ptr;
7202 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
7203 struct sk_buff *msg;
7204 void *hdr;
7205 int err;
7206 u32 nlpid = ACCESS_ONCE(wdev->ap_unexpected_nlpid);
7207
7208 if (!nlpid)
7209 return false;
7210
7211 msg = nlmsg_new(100, gfp);
7212 if (!msg)
7213 return true;
7214
7215 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UNEXPECTED_FRAME);
7216 if (!hdr) {
7217 nlmsg_free(msg);
7218 return true;
7219 }
7220
7221 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
7222 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
7223 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
7224
7225 err = genlmsg_end(msg, hdr);
7226 if (err < 0) {
7227 nlmsg_free(msg);
7228 return true;
7229 }
7230
7231 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid);
7232 return true;
7233
7234 nla_put_failure:
7235 genlmsg_cancel(msg, hdr);
7236 nlmsg_free(msg);
7237 return true;
7238}
7239
7174int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, 7240int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
7175 struct net_device *netdev, u32 nlpid, 7241 struct net_device *netdev, u32 nlpid,
7176 int freq, const u8 *buf, size_t len, gfp_t gfp) 7242 int freq, const u8 *buf, size_t len, gfp_t gfp)