diff options
author | David S. Miller <davem@davemloft.net> | 2010-02-26 02:26:21 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-26 02:26:21 -0500 |
commit | 19bc291c99f018bd4f2c38bbf69144086dca903f (patch) | |
tree | 9d3cf9bc0c5a78e363dc0547da8bcd1e7c394265 /net/mac80211 | |
parent | 04488734806948624dabc4514f96f14cd75b9a50 (diff) | |
parent | 4a6967b88af02eebeedfbb91bc09160750225bb5 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts:
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/rt2x00/rt2800pci.c
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 12 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 6 | ||||
-rw-r--r-- | net/mac80211/iface.c | 2 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 35 | ||||
-rw-r--r-- | net/mac80211/rx.c | 140 | ||||
-rw-r--r-- | net/mac80211/status.c | 7 |
6 files changed, 157 insertions, 45 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 | ||
1451 | static 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 | |||
1451 | struct cfg80211_ops mac80211_config_ops = { | 1460 | struct 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, | |||
966 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | 966 | int 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); |
969 | int 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); | ||
969 | ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, | 973 | ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, |
970 | struct sk_buff *skb); | 974 | struct sk_buff *skb); |
971 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 975 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 09fff4662e80..0793d7a8d743 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1031,7 +1031,7 @@ static int netdev_notify(struct notifier_block *nb, | |||
1031 | 1031 | ||
1032 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1032 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1033 | 1033 | ||
1034 | memcpy(sdata->name, sdata->name, IFNAMSIZ); | 1034 | memcpy(sdata->name, dev->name, IFNAMSIZ); |
1035 | 1035 | ||
1036 | ieee80211_debugfs_rename_netdev(sdata); | 1036 | ieee80211_debugfs_rename_netdev(sdata); |
1037 | return 0; | 1037 | return 0; |
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 | |||
2088 | int 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 c9755f3d986c..b5c48de81d8b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.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 2007 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 |
@@ -1397,6 +1397,21 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | |||
1397 | ieee80211_is_data(fc) && | 1397 | ieee80211_is_data(fc) && |
1398 | (rx->key || rx->sdata->drop_unencrypted))) | 1398 | (rx->key || rx->sdata->drop_unencrypted))) |
1399 | return -EACCES; | 1399 | return -EACCES; |
1400 | |||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | static int | ||
1405 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | ||
1406 | { | ||
1407 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | ||
1408 | __le16 fc = hdr->frame_control; | ||
1409 | int res; | ||
1410 | |||
1411 | res = ieee80211_drop_unencrypted(rx, fc); | ||
1412 | if (unlikely(res)) | ||
1413 | return res; | ||
1414 | |||
1400 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | 1415 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { |
1401 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | 1416 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && |
1402 | rx->key)) | 1417 | rx->key)) |
@@ -1855,23 +1870,25 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1855 | struct ieee80211_local *local = rx->local; | 1870 | struct ieee80211_local *local = rx->local; |
1856 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1871 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1857 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1872 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1873 | struct sk_buff *nskb; | ||
1874 | struct ieee80211_rx_status *status; | ||
1858 | int len = rx->skb->len; | 1875 | int len = rx->skb->len; |
1859 | 1876 | ||
1860 | if (!ieee80211_is_action(mgmt->frame_control)) | 1877 | if (!ieee80211_is_action(mgmt->frame_control)) |
1861 | return RX_CONTINUE; | 1878 | return RX_CONTINUE; |
1862 | 1879 | ||
1863 | if (!rx->sta) | 1880 | /* drop too small frames */ |
1864 | return RX_DROP_MONITOR; | 1881 | if (len < IEEE80211_MIN_ACTION_SIZE) |
1882 | return RX_DROP_UNUSABLE; | ||
1865 | 1883 | ||
1866 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1884 | if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) |
1867 | return RX_DROP_MONITOR; | 1885 | return RX_DROP_UNUSABLE; |
1868 | 1886 | ||
1869 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) | 1887 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1870 | return RX_DROP_MONITOR; | 1888 | return RX_DROP_UNUSABLE; |
1871 | 1889 | ||
1872 | /* all categories we currently handle have action_code */ | 1890 | if (ieee80211_drop_unencrypted_mgmt(rx)) |
1873 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | 1891 | return RX_DROP_UNUSABLE; |
1874 | return RX_DROP_MONITOR; | ||
1875 | 1892 | ||
1876 | switch (mgmt->u.action.category) { | 1893 | switch (mgmt->u.action.category) { |
1877 | case WLAN_CATEGORY_BACK: | 1894 | case WLAN_CATEGORY_BACK: |
@@ -1884,7 +1901,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1884 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1901 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
1885 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1902 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
1886 | sdata->vif.type != NL80211_IFTYPE_AP) | 1903 | sdata->vif.type != NL80211_IFTYPE_AP) |
1887 | return RX_DROP_MONITOR; | 1904 | break; |
1905 | |||
1906 | /* verify action_code is present */ | ||
1907 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
1908 | break; | ||
1888 | 1909 | ||
1889 | switch (mgmt->u.action.u.addba_req.action_code) { | 1910 | switch (mgmt->u.action.u.addba_req.action_code) { |
1890 | case WLAN_ACTION_ADDBA_REQ: | 1911 | case WLAN_ACTION_ADDBA_REQ: |
@@ -1892,45 +1913,49 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1892 | sizeof(mgmt->u.action.u.addba_req))) | 1913 | sizeof(mgmt->u.action.u.addba_req))) |
1893 | return RX_DROP_MONITOR; | 1914 | return RX_DROP_MONITOR; |
1894 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); | 1915 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); |
1895 | break; | 1916 | goto handled; |
1896 | case WLAN_ACTION_ADDBA_RESP: | 1917 | case WLAN_ACTION_ADDBA_RESP: |
1897 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1918 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1898 | sizeof(mgmt->u.action.u.addba_resp))) | 1919 | sizeof(mgmt->u.action.u.addba_resp))) |
1899 | return RX_DROP_MONITOR; | 1920 | break; |
1900 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); | 1921 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); |
1901 | break; | 1922 | goto handled; |
1902 | case WLAN_ACTION_DELBA: | 1923 | case WLAN_ACTION_DELBA: |
1903 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1924 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1904 | sizeof(mgmt->u.action.u.delba))) | 1925 | sizeof(mgmt->u.action.u.delba))) |
1905 | return RX_DROP_MONITOR; | 1926 | break; |
1906 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); | 1927 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); |
1907 | break; | 1928 | goto handled; |
1908 | } | 1929 | } |
1909 | break; | 1930 | break; |
1910 | case WLAN_CATEGORY_SPECTRUM_MGMT: | 1931 | case WLAN_CATEGORY_SPECTRUM_MGMT: |
1911 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | 1932 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) |
1912 | return RX_DROP_MONITOR; | 1933 | break; |
1913 | 1934 | ||
1914 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1935 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1915 | return RX_DROP_MONITOR; | 1936 | break; |
1937 | |||
1938 | /* verify action_code is present */ | ||
1939 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
1940 | break; | ||
1916 | 1941 | ||
1917 | switch (mgmt->u.action.u.measurement.action_code) { | 1942 | switch (mgmt->u.action.u.measurement.action_code) { |
1918 | case WLAN_ACTION_SPCT_MSR_REQ: | 1943 | case WLAN_ACTION_SPCT_MSR_REQ: |
1919 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1944 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1920 | sizeof(mgmt->u.action.u.measurement))) | 1945 | sizeof(mgmt->u.action.u.measurement))) |
1921 | return RX_DROP_MONITOR; | 1946 | break; |
1922 | ieee80211_process_measurement_req(sdata, mgmt, len); | 1947 | ieee80211_process_measurement_req(sdata, mgmt, len); |
1923 | break; | 1948 | goto handled; |
1924 | case WLAN_ACTION_SPCT_CHL_SWITCH: | 1949 | case WLAN_ACTION_SPCT_CHL_SWITCH: |
1925 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1950 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1926 | sizeof(mgmt->u.action.u.chan_switch))) | 1951 | sizeof(mgmt->u.action.u.chan_switch))) |
1927 | return RX_DROP_MONITOR; | 1952 | break; |
1928 | 1953 | ||
1929 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1954 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1930 | return RX_DROP_MONITOR; | 1955 | break; |
1931 | 1956 | ||
1932 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) | 1957 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) |
1933 | return RX_DROP_MONITOR; | 1958 | break; |
1934 | 1959 | ||
1935 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); | 1960 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); |
1936 | } | 1961 | } |
@@ -1938,30 +1963,64 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1938 | case WLAN_CATEGORY_SA_QUERY: | 1963 | case WLAN_CATEGORY_SA_QUERY: |
1939 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1964 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1940 | sizeof(mgmt->u.action.u.sa_query))) | 1965 | sizeof(mgmt->u.action.u.sa_query))) |
1941 | return RX_DROP_MONITOR; | 1966 | break; |
1967 | |||
1942 | switch (mgmt->u.action.u.sa_query.action) { | 1968 | switch (mgmt->u.action.u.sa_query.action) { |
1943 | case WLAN_ACTION_SA_QUERY_REQUEST: | 1969 | case WLAN_ACTION_SA_QUERY_REQUEST: |
1944 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1970 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1945 | return RX_DROP_MONITOR; | 1971 | break; |
1946 | ieee80211_process_sa_query_req(sdata, mgmt, len); | 1972 | ieee80211_process_sa_query_req(sdata, mgmt, len); |
1947 | break; | 1973 | goto handled; |
1948 | case WLAN_ACTION_SA_QUERY_RESPONSE: | ||
1949 | /* | ||
1950 | * SA Query response is currently only used in AP mode | ||
1951 | * and it is processed in user space. | ||
1952 | */ | ||
1953 | return RX_CONTINUE; | ||
1954 | } | 1974 | } |
1955 | break; | 1975 | break; |
1956 | default: | 1976 | } |
1957 | /* do not process rejected action frames */ | ||
1958 | if (mgmt->u.action.category & 0x80) | ||
1959 | return RX_DROP_MONITOR; | ||
1960 | 1977 | ||
1961 | return RX_CONTINUE; | 1978 | /* |
1979 | * For AP mode, hostapd is responsible for handling any action | ||
1980 | * frames that we didn't handle, including returning unknown | ||
1981 | * ones. For all other modes we will return them to the sender, | ||
1982 | * setting the 0x80 bit in the action category, as required by | ||
1983 | * 802.11-2007 7.3.1.11. | ||
1984 | */ | ||
1985 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
1986 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
1987 | return RX_DROP_MONITOR; | ||
1988 | |||
1989 | /* | ||
1990 | * Getting here means the kernel doesn't know how to handle | ||
1991 | * it, but maybe userspace does ... include returned frames | ||
1992 | * so userspace can register for those to know whether ones | ||
1993 | * it transmitted were processed or returned. | ||
1994 | */ | ||
1995 | status = IEEE80211_SKB_RXCB(rx->skb); | ||
1996 | |||
1997 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
1998 | cfg80211_rx_action(rx->sdata->dev, status->freq, | ||
1999 | rx->skb->data, rx->skb->len, | ||
2000 | GFP_ATOMIC)) | ||
2001 | goto handled; | ||
2002 | |||
2003 | /* do not return rejected action frames */ | ||
2004 | if (mgmt->u.action.category & 0x80) | ||
2005 | return RX_DROP_UNUSABLE; | ||
2006 | |||
2007 | nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0, | ||
2008 | GFP_ATOMIC); | ||
2009 | if (nskb) { | ||
2010 | struct ieee80211_mgmt *mgmt = (void *)nskb->data; | ||
2011 | |||
2012 | mgmt->u.action.category |= 0x80; | ||
2013 | memcpy(mgmt->da, mgmt->sa, ETH_ALEN); | ||
2014 | memcpy(mgmt->sa, rx->sdata->vif.addr, ETH_ALEN); | ||
2015 | |||
2016 | memset(nskb->cb, 0, sizeof(nskb->cb)); | ||
2017 | |||
2018 | ieee80211_tx_skb(rx->sdata, nskb); | ||
1962 | } | 2019 | } |
1963 | 2020 | ||
1964 | rx->sta->rx_packets++; | 2021 | handled: |
2022 | if (rx->sta) | ||
2023 | rx->sta->rx_packets++; | ||
1965 | dev_kfree_skb(rx->skb); | 2024 | dev_kfree_skb(rx->skb); |
1966 | return RX_QUEUED; | 2025 | return RX_QUEUED; |
1967 | } | 2026 | } |
@@ -1970,14 +2029,13 @@ static ieee80211_rx_result debug_noinline | |||
1970 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | 2029 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) |
1971 | { | 2030 | { |
1972 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 2031 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1973 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
1974 | ieee80211_rx_result rxs; | 2032 | ieee80211_rx_result rxs; |
1975 | 2033 | ||
1976 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 2034 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1977 | return RX_DROP_MONITOR; | 2035 | return RX_DROP_MONITOR; |
1978 | 2036 | ||
1979 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) | 2037 | if (ieee80211_drop_unencrypted_mgmt(rx)) |
1980 | return RX_DROP_MONITOR; | 2038 | return RX_DROP_UNUSABLE; |
1981 | 2039 | ||
1982 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); | 2040 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); |
1983 | if (rxs != RX_CONTINUE) | 2041 | if (rxs != RX_CONTINUE) |
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 | ||