aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2010-02-15 05:53:10 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-02-15 16:14:15 -0500
commit026331c4d9b526561ea96f95fac4bfc52b69e316 (patch)
treea82b0a92a7f03a1d151a9db123320689c73d98c7 /net/mac80211
parent8404080568613d93ad7cf0a16dfb68459b42a264 (diff)
cfg80211/mac80211: allow registering for and sending action frames
This implements a new command to register for action frames that userspace wants to handle instead of the in-kernel rejection. It is then responsible for rejecting ones that it decided not to handle. There is no unregistration, but the socket can be closed for that. Frames that are not registered for will not be forwarded to userspace and will be rejected by the kernel, the cfg80211 API helps implementing that. Additionally, this patch adds a new command that allows doing action frame transmission from userspace. It can be used either to exchange action frames on the current operational channel (e.g., with the AP with which we are currently associated) or to exchange off-channel Public Action frames with the remain-on-channel command. Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c12
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/mlme.c35
-rw-r--r--net/mac80211/rx.c42
-rw-r--r--net/mac80211/status.c7
5 files changed, 88 insertions, 14 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e1731b7c2523..b7116ef84a3b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * mac80211 configuration hooks for cfg80211 2 * mac80211 configuration hooks for cfg80211
3 * 3 *
4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 * 5 *
6 * This file is GPLv2 as found in COPYING. 6 * This file is GPLv2 as found in COPYING.
7 */ 7 */
@@ -1448,6 +1448,15 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
1448 return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); 1448 return ieee80211_wk_cancel_remain_on_channel(sdata, cookie);
1449} 1449}
1450 1450
1451static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev,
1452 struct ieee80211_channel *chan,
1453 enum nl80211_channel_type channel_type,
1454 const u8 *buf, size_t len, u64 *cookie)
1455{
1456 return ieee80211_mgd_action(IEEE80211_DEV_TO_SUB_IF(dev), chan,
1457 channel_type, buf, len, cookie);
1458}
1459
1451struct cfg80211_ops mac80211_config_ops = { 1460struct cfg80211_ops mac80211_config_ops = {
1452 .add_virtual_intf = ieee80211_add_iface, 1461 .add_virtual_intf = ieee80211_add_iface,
1453 .del_virtual_intf = ieee80211_del_iface, 1462 .del_virtual_intf = ieee80211_del_iface,
@@ -1496,4 +1505,5 @@ struct cfg80211_ops mac80211_config_ops = {
1496 .set_bitrate_mask = ieee80211_set_bitrate_mask, 1505 .set_bitrate_mask = ieee80211_set_bitrate_mask,
1497 .remain_on_channel = ieee80211_remain_on_channel, 1506 .remain_on_channel = ieee80211_remain_on_channel,
1498 .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, 1507 .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
1508 .action = ieee80211_action,
1499}; 1509};
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9dd98b674cbc..241533e1bc03 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2,7 +2,7 @@
2 * Copyright 2002-2005, Instant802 Networks, Inc. 2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2005, Devicescape Software, Inc. 3 * Copyright 2005, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -966,6 +966,10 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
966int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, 966int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
967 struct cfg80211_disassoc_request *req, 967 struct cfg80211_disassoc_request *req,
968 void *cookie); 968 void *cookie);
969int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
970 struct ieee80211_channel *chan,
971 enum nl80211_channel_type channel_type,
972 const u8 *buf, size_t len, u64 *cookie);
969ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, 973ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
970 struct sk_buff *skb); 974 struct sk_buff *skb);
971void ieee80211_send_pspoll(struct ieee80211_local *local, 975void ieee80211_send_pspoll(struct ieee80211_local *local,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index bfc4a5070013..41812a15eea0 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2084,3 +2084,38 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2084 2084
2085 return 0; 2085 return 0;
2086} 2086}
2087
2088int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
2089 struct ieee80211_channel *chan,
2090 enum nl80211_channel_type channel_type,
2091 const u8 *buf, size_t len, u64 *cookie)
2092{
2093 struct ieee80211_local *local = sdata->local;
2094 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2095 struct sk_buff *skb;
2096
2097 /* Check that we are on the requested channel for transmission */
2098 if ((chan != local->tmp_channel ||
2099 channel_type != local->tmp_channel_type) &&
2100 (chan != local->oper_channel ||
2101 channel_type != local->oper_channel_type))
2102 return -EBUSY;
2103
2104 skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
2105 if (!skb)
2106 return -ENOMEM;
2107 skb_reserve(skb, local->hw.extra_tx_headroom);
2108
2109 memcpy(skb_put(skb, len), buf, len);
2110
2111 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
2112 IEEE80211_SKB_CB(skb)->flags |=
2113 IEEE80211_TX_INTFL_DONT_ENCRYPT;
2114 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX |
2115 IEEE80211_TX_CTL_REQ_TX_STATUS;
2116 skb->dev = sdata->dev;
2117 ieee80211_tx_skb(sdata, skb);
2118
2119 *cookie = (unsigned long) skb;
2120 return 0;
2121}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a177472adc13..a6080d8d72bb 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1856,28 +1856,25 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1856 struct ieee80211_sub_if_data *sdata = rx->sdata; 1856 struct ieee80211_sub_if_data *sdata = rx->sdata;
1857 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; 1857 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
1858 struct sk_buff *nskb; 1858 struct sk_buff *nskb;
1859 struct ieee80211_rx_status *status;
1859 int len = rx->skb->len; 1860 int len = rx->skb->len;
1860 1861
1861 if (!ieee80211_is_action(mgmt->frame_control)) 1862 if (!ieee80211_is_action(mgmt->frame_control))
1862 return RX_CONTINUE; 1863 return RX_CONTINUE;
1863 1864
1864 if (!rx->sta) 1865 /* drop too small frames */
1866 if (len < IEEE80211_MIN_ACTION_SIZE)
1865 return RX_DROP_UNUSABLE; 1867 return RX_DROP_UNUSABLE;
1866 1868
1867 if (!(rx->flags & IEEE80211_RX_RA_MATCH)) 1869 if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
1868 return RX_DROP_UNUSABLE; 1870 return RX_DROP_UNUSABLE;
1869 1871
1870 if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) 1872 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
1871 return RX_DROP_UNUSABLE; 1873 return RX_DROP_UNUSABLE;
1872 1874
1873 /* drop too small frames */ 1875 if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
1874 if (len < IEEE80211_MIN_ACTION_SIZE)
1875 return RX_DROP_UNUSABLE; 1876 return RX_DROP_UNUSABLE;
1876 1877
1877 /* return action frames that have *only* category */
1878 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
1879 goto return_frame;
1880
1881 switch (mgmt->u.action.category) { 1878 switch (mgmt->u.action.category) {
1882 case WLAN_CATEGORY_BACK: 1879 case WLAN_CATEGORY_BACK:
1883 /* 1880 /*
@@ -1891,6 +1888,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1891 sdata->vif.type != NL80211_IFTYPE_AP) 1888 sdata->vif.type != NL80211_IFTYPE_AP)
1892 break; 1889 break;
1893 1890
1891 /* verify action_code is present */
1892 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
1893 break;
1894
1894 switch (mgmt->u.action.u.addba_req.action_code) { 1895 switch (mgmt->u.action.u.addba_req.action_code) {
1895 case WLAN_ACTION_ADDBA_REQ: 1896 case WLAN_ACTION_ADDBA_REQ:
1896 if (len < (IEEE80211_MIN_ACTION_SIZE + 1897 if (len < (IEEE80211_MIN_ACTION_SIZE +
@@ -1919,6 +1920,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1919 if (sdata->vif.type != NL80211_IFTYPE_STATION) 1920 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1920 break; 1921 break;
1921 1922
1923 /* verify action_code is present */
1924 if (len < IEEE80211_MIN_ACTION_SIZE + 1)
1925 break;
1926
1922 switch (mgmt->u.action.u.measurement.action_code) { 1927 switch (mgmt->u.action.u.measurement.action_code) {
1923 case WLAN_ACTION_SPCT_MSR_REQ: 1928 case WLAN_ACTION_SPCT_MSR_REQ:
1924 if (len < (IEEE80211_MIN_ACTION_SIZE + 1929 if (len < (IEEE80211_MIN_ACTION_SIZE +
@@ -1954,7 +1959,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1954 } 1959 }
1955 break; 1960 break;
1956 } 1961 }
1957 return_frame: 1962
1958 /* 1963 /*
1959 * For AP mode, hostapd is responsible for handling any action 1964 * For AP mode, hostapd is responsible for handling any action
1960 * frames that we didn't handle, including returning unknown 1965 * frames that we didn't handle, including returning unknown
@@ -1966,6 +1971,20 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1966 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 1971 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1967 return RX_DROP_MONITOR; 1972 return RX_DROP_MONITOR;
1968 1973
1974 /*
1975 * Getting here means the kernel doesn't know how to handle
1976 * it, but maybe userspace does ... include returned frames
1977 * so userspace can register for those to know whether ones
1978 * it transmitted were processed or returned.
1979 */
1980 status = IEEE80211_SKB_RXCB(rx->skb);
1981
1982 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
1983 cfg80211_rx_action(rx->sdata->dev, status->freq,
1984 rx->skb->data, rx->skb->len,
1985 GFP_ATOMIC))
1986 goto handled;
1987
1969 /* do not return rejected action frames */ 1988 /* do not return rejected action frames */
1970 if (mgmt->u.action.category & 0x80) 1989 if (mgmt->u.action.category & 0x80)
1971 return RX_DROP_UNUSABLE; 1990 return RX_DROP_UNUSABLE;
@@ -1985,7 +2004,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1985 } 2004 }
1986 2005
1987 handled: 2006 handled:
1988 rx->sta->rx_packets++; 2007 if (rx->sta)
2008 rx->sta->rx_packets++;
1989 dev_kfree_skb(rx->skb); 2009 dev_kfree_skb(rx->skb);
1990 return RX_QUEUED; 2010 return RX_QUEUED;
1991} 2011}
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index ded98730c111..56d5b9a6ec5b 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -2,7 +2,7 @@
2 * Copyright 2002-2005, Instant802 Networks, Inc. 2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -288,6 +288,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
288 msecs_to_jiffies(10)); 288 msecs_to_jiffies(10));
289 } 289 }
290 290
291 if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX)
292 cfg80211_action_tx_status(
293 skb->dev, (unsigned long) skb, skb->data, skb->len,
294 !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
295
291 /* this was a transmitted frame, but now we want to reuse it */ 296 /* this was a transmitted frame, but now we want to reuse it */
292 skb_orphan(skb); 297 skb_orphan(skb);
293 298