aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
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