aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-08-12 09:38:38 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-24 16:27:56 -0400
commit2e161f78e5f63a7f9fd25a766bb7f816a01eb14a (patch)
treebefd44feeb1f47da1f41e6fc310a223ad67030ff /net/mac80211
parentac4c977d16d843f12901595c91773dddb65768a9 (diff)
cfg80211/mac80211: extensible frame processing
Allow userspace to register for more than just action frames by giving the frame subtype, and make it possible to use this in various modes as well. With some tweaks and some added functionality this will, in the future, also be usable in AP mode and be able to replace the cooked monitor interface currently used in that case. Signed-off-by: Johannes Berg <johannes.berg@intel.com> 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.h1
-rw-r--r--net/mac80211/iface.c6
-rw-r--r--net/mac80211/main.c37
-rw-r--r--net/mac80211/rx.c137
-rw-r--r--net/mac80211/status.c2
-rw-r--r--net/mac80211/util.c6
7 files changed, 147 insertions, 54 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index f9a317766136..94787d21282c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1521,11 +1521,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
1521 return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); 1521 return ieee80211_wk_cancel_remain_on_channel(sdata, cookie);
1522} 1522}
1523 1523
1524static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, 1524static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1525 struct ieee80211_channel *chan, 1525 struct ieee80211_channel *chan,
1526 enum nl80211_channel_type channel_type, 1526 enum nl80211_channel_type channel_type,
1527 bool channel_type_valid, 1527 bool channel_type_valid,
1528 const u8 *buf, size_t len, u64 *cookie) 1528 const u8 *buf, size_t len, u64 *cookie)
1529{ 1529{
1530 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1530 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1531 struct ieee80211_local *local = sdata->local; 1531 struct ieee80211_local *local = sdata->local;
@@ -1625,6 +1625,6 @@ struct cfg80211_ops mac80211_config_ops = {
1625 .set_bitrate_mask = ieee80211_set_bitrate_mask, 1625 .set_bitrate_mask = ieee80211_set_bitrate_mask,
1626 .remain_on_channel = ieee80211_remain_on_channel, 1626 .remain_on_channel = ieee80211_remain_on_channel,
1627 .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, 1627 .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
1628 .action = ieee80211_action, 1628 .mgmt_tx = ieee80211_mgmt_tx,
1629 .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, 1629 .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
1630}; 1630};
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 1bf05bfd149d..e73ae51dc036 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -170,6 +170,7 @@ typedef unsigned __bitwise__ ieee80211_rx_result;
170#define IEEE80211_RX_RA_MATCH BIT(1) 170#define IEEE80211_RX_RA_MATCH BIT(1)
171#define IEEE80211_RX_AMSDU BIT(2) 171#define IEEE80211_RX_AMSDU BIT(2)
172#define IEEE80211_RX_FRAGMENTED BIT(3) 172#define IEEE80211_RX_FRAGMENTED BIT(3)
173#define IEEE80211_MALFORMED_ACTION_FRM BIT(4)
173/* only add flags here that do not change with subframes of an aMPDU */ 174/* only add flags here that do not change with subframes of an aMPDU */
174 175
175struct ieee80211_rx_data { 176struct ieee80211_rx_data {
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 9459aeee0ddc..86f434f234ae 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -177,7 +177,7 @@ static int ieee80211_open(struct net_device *dev)
177 /* no special treatment */ 177 /* no special treatment */
178 break; 178 break;
179 case NL80211_IFTYPE_UNSPECIFIED: 179 case NL80211_IFTYPE_UNSPECIFIED:
180 case __NL80211_IFTYPE_AFTER_LAST: 180 case NUM_NL80211_IFTYPES:
181 /* cannot happen */ 181 /* cannot happen */
182 WARN_ON(1); 182 WARN_ON(1);
183 break; 183 break;
@@ -634,7 +634,7 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
634 case NL80211_IFTYPE_MONITOR: 634 case NL80211_IFTYPE_MONITOR:
635 break; 635 break;
636 case NL80211_IFTYPE_UNSPECIFIED: 636 case NL80211_IFTYPE_UNSPECIFIED:
637 case __NL80211_IFTYPE_AFTER_LAST: 637 case NUM_NL80211_IFTYPES:
638 BUG(); 638 BUG();
639 break; 639 break;
640 } 640 }
@@ -886,7 +886,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
886 case NL80211_IFTYPE_AP_VLAN: 886 case NL80211_IFTYPE_AP_VLAN:
887 break; 887 break;
888 case NL80211_IFTYPE_UNSPECIFIED: 888 case NL80211_IFTYPE_UNSPECIFIED:
889 case __NL80211_IFTYPE_AFTER_LAST: 889 case NUM_NL80211_IFTYPES:
890 BUG(); 890 BUG();
891 break; 891 break;
892 } 892 }
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0afccda42a24..a53feac4618c 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -417,6 +417,41 @@ void ieee80211_napi_complete(struct ieee80211_hw *hw)
417} 417}
418EXPORT_SYMBOL(ieee80211_napi_complete); 418EXPORT_SYMBOL(ieee80211_napi_complete);
419 419
420/* There isn't a lot of sense in it, but you can transmit anything you like */
421static const struct ieee80211_txrx_stypes
422ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
423 [NL80211_IFTYPE_ADHOC] = {
424 .tx = 0xffff,
425 .rx = BIT(IEEE80211_STYPE_ACTION >> 4),
426 },
427 [NL80211_IFTYPE_STATION] = {
428 .tx = 0xffff,
429 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
430 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
431 },
432 [NL80211_IFTYPE_AP] = {
433 .tx = 0xffff,
434 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
435 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
436 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
437 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
438 BIT(IEEE80211_STYPE_AUTH >> 4) |
439 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
440 BIT(IEEE80211_STYPE_ACTION >> 4),
441 },
442 [NL80211_IFTYPE_AP_VLAN] = {
443 /* copy AP */
444 .tx = 0xffff,
445 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
446 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
447 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
448 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
449 BIT(IEEE80211_STYPE_AUTH >> 4) |
450 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
451 BIT(IEEE80211_STYPE_ACTION >> 4),
452 },
453};
454
420struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, 455struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
421 const struct ieee80211_ops *ops) 456 const struct ieee80211_ops *ops)
422{ 457{
@@ -446,6 +481,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
446 if (!wiphy) 481 if (!wiphy)
447 return NULL; 482 return NULL;
448 483
484 wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes;
485
449 wiphy->flags |= WIPHY_FLAG_NETNS_OK | 486 wiphy->flags |= WIPHY_FLAG_NETNS_OK |
450 WIPHY_FLAG_4ADDR_AP | 487 WIPHY_FLAG_4ADDR_AP |
451 WIPHY_FLAG_4ADDR_STATION; 488 WIPHY_FLAG_4ADDR_STATION;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 4fdbed58ca2f..aa41e382bbb3 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1940,13 +1940,36 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
1940} 1940}
1941 1941
1942static ieee80211_rx_result debug_noinline 1942static ieee80211_rx_result debug_noinline
1943ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
1944{
1945 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
1946
1947 /*
1948 * From here on, look only at management frames.
1949 * Data and control frames are already handled,
1950 * and unknown (reserved) frames are useless.
1951 */
1952 if (rx->skb->len < 24)
1953 return RX_DROP_MONITOR;
1954
1955 if (!ieee80211_is_mgmt(mgmt->frame_control))
1956 return RX_DROP_MONITOR;
1957
1958 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
1959 return RX_DROP_MONITOR;
1960
1961 if (ieee80211_drop_unencrypted_mgmt(rx))
1962 return RX_DROP_UNUSABLE;
1963
1964 return RX_CONTINUE;
1965}
1966
1967static ieee80211_rx_result debug_noinline
1943ieee80211_rx_h_action(struct ieee80211_rx_data *rx) 1968ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1944{ 1969{
1945 struct ieee80211_local *local = rx->local; 1970 struct ieee80211_local *local = rx->local;
1946 struct ieee80211_sub_if_data *sdata = rx->sdata; 1971 struct ieee80211_sub_if_data *sdata = rx->sdata;
1947 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; 1972 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
1948 struct sk_buff *nskb;
1949 struct ieee80211_rx_status *status;
1950 int len = rx->skb->len; 1973 int len = rx->skb->len;
1951 1974
1952 if (!ieee80211_is_action(mgmt->frame_control)) 1975 if (!ieee80211_is_action(mgmt->frame_control))
@@ -1962,9 +1985,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1962 if (!(rx->flags & IEEE80211_RX_RA_MATCH)) 1985 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
1963 return RX_DROP_UNUSABLE; 1986 return RX_DROP_UNUSABLE;
1964 1987
1965 if (ieee80211_drop_unencrypted_mgmt(rx))
1966 return RX_DROP_UNUSABLE;
1967
1968 switch (mgmt->u.action.category) { 1988 switch (mgmt->u.action.category) {
1969 case WLAN_CATEGORY_BACK: 1989 case WLAN_CATEGORY_BACK:
1970 /* 1990 /*
@@ -2055,17 +2075,36 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2055 goto queue; 2075 goto queue;
2056 } 2076 }
2057 2077
2078 return RX_CONTINUE;
2079
2058 invalid: 2080 invalid:
2059 /* 2081 rx->flags |= IEEE80211_MALFORMED_ACTION_FRM;
2060 * For AP mode, hostapd is responsible for handling any action 2082 /* will return in the next handlers */
2061 * frames that we didn't handle, including returning unknown 2083 return RX_CONTINUE;
2062 * ones. For all other modes we will return them to the sender, 2084
2063 * setting the 0x80 bit in the action category, as required by 2085 handled:
2064 * 802.11-2007 7.3.1.11. 2086 if (rx->sta)
2065 */ 2087 rx->sta->rx_packets++;
2066 if (sdata->vif.type == NL80211_IFTYPE_AP || 2088 dev_kfree_skb(rx->skb);
2067 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 2089 return RX_QUEUED;
2068 return RX_DROP_MONITOR; 2090
2091 queue:
2092 rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
2093 skb_queue_tail(&sdata->skb_queue, rx->skb);
2094 ieee80211_queue_work(&local->hw, &sdata->work);
2095 if (rx->sta)
2096 rx->sta->rx_packets++;
2097 return RX_QUEUED;
2098}
2099
2100static ieee80211_rx_result debug_noinline
2101ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
2102{
2103 struct ieee80211_rx_status *status;
2104
2105 /* skip known-bad action frames and return them in the next handler */
2106 if (rx->flags & IEEE80211_MALFORMED_ACTION_FRM)
2107 return RX_CONTINUE;
2069 2108
2070 /* 2109 /*
2071 * Getting here means the kernel doesn't know how to handle 2110 * Getting here means the kernel doesn't know how to handle
@@ -2075,10 +2114,44 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2075 */ 2114 */
2076 status = IEEE80211_SKB_RXCB(rx->skb); 2115 status = IEEE80211_SKB_RXCB(rx->skb);
2077 2116
2078 if (cfg80211_rx_action(rx->sdata->dev, status->freq, 2117 if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq,
2079 rx->skb->data, rx->skb->len, 2118 rx->skb->data, rx->skb->len,
2080 GFP_ATOMIC)) 2119 GFP_ATOMIC)) {
2081 goto handled; 2120 if (rx->sta)
2121 rx->sta->rx_packets++;
2122 dev_kfree_skb(rx->skb);
2123 return RX_QUEUED;
2124 }
2125
2126
2127 return RX_CONTINUE;
2128}
2129
2130static ieee80211_rx_result debug_noinline
2131ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
2132{
2133 struct ieee80211_local *local = rx->local;
2134 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
2135 struct sk_buff *nskb;
2136 struct ieee80211_sub_if_data *sdata = rx->sdata;
2137
2138 if (!ieee80211_is_action(mgmt->frame_control))
2139 return RX_CONTINUE;
2140
2141 /*
2142 * For AP mode, hostapd is responsible for handling any action
2143 * frames that we didn't handle, including returning unknown
2144 * ones. For all other modes we will return them to the sender,
2145 * setting the 0x80 bit in the action category, as required by
2146 * 802.11-2007 7.3.1.11.
2147 * Newer versions of hostapd shall also use the management frame
2148 * registration mechanisms, but older ones still use cooked
2149 * monitor interfaces so push all frames there.
2150 */
2151 if (!(rx->flags & IEEE80211_MALFORMED_ACTION_FRM) &&
2152 (sdata->vif.type == NL80211_IFTYPE_AP ||
2153 sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
2154 return RX_DROP_MONITOR;
2082 2155
2083 /* do not return rejected action frames */ 2156 /* do not return rejected action frames */
2084 if (mgmt->u.action.category & 0x80) 2157 if (mgmt->u.action.category & 0x80)
@@ -2097,20 +2170,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2097 2170
2098 ieee80211_tx_skb(rx->sdata, nskb); 2171 ieee80211_tx_skb(rx->sdata, nskb);
2099 } 2172 }
2100
2101 handled:
2102 if (rx->sta)
2103 rx->sta->rx_packets++;
2104 dev_kfree_skb(rx->skb); 2173 dev_kfree_skb(rx->skb);
2105 return RX_QUEUED; 2174 return RX_QUEUED;
2106
2107 queue:
2108 rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
2109 skb_queue_tail(&sdata->skb_queue, rx->skb);
2110 ieee80211_queue_work(&local->hw, &sdata->work);
2111 if (rx->sta)
2112 rx->sta->rx_packets++;
2113 return RX_QUEUED;
2114} 2175}
2115 2176
2116static ieee80211_rx_result debug_noinline 2177static ieee80211_rx_result debug_noinline
@@ -2121,15 +2182,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
2121 struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; 2182 struct ieee80211_mgmt *mgmt = (void *)rx->skb->data;
2122 __le16 stype; 2183 __le16 stype;
2123 2184
2124 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
2125 return RX_DROP_MONITOR;
2126
2127 if (rx->skb->len < 24)
2128 return RX_DROP_MONITOR;
2129
2130 if (ieee80211_drop_unencrypted_mgmt(rx))
2131 return RX_DROP_UNUSABLE;
2132
2133 rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); 2185 rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb);
2134 if (rxs != RX_CONTINUE) 2186 if (rxs != RX_CONTINUE)
2135 return rxs; 2187 return rxs;
@@ -2374,7 +2426,10 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
2374 if (res != RX_CONTINUE) 2426 if (res != RX_CONTINUE)
2375 goto rxh_next; 2427 goto rxh_next;
2376 2428
2429 CALL_RXH(ieee80211_rx_h_mgmt_check)
2377 CALL_RXH(ieee80211_rx_h_action) 2430 CALL_RXH(ieee80211_rx_h_action)
2431 CALL_RXH(ieee80211_rx_h_userspace_mgmt)
2432 CALL_RXH(ieee80211_rx_h_action_return)
2378 CALL_RXH(ieee80211_rx_h_mgmt) 2433 CALL_RXH(ieee80211_rx_h_mgmt)
2379 2434
2380 rxh_next: 2435 rxh_next:
@@ -2527,7 +2582,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
2527 break; 2582 break;
2528 case NL80211_IFTYPE_MONITOR: 2583 case NL80211_IFTYPE_MONITOR:
2529 case NL80211_IFTYPE_UNSPECIFIED: 2584 case NL80211_IFTYPE_UNSPECIFIED:
2530 case __NL80211_IFTYPE_AFTER_LAST: 2585 case NUM_NL80211_IFTYPES:
2531 /* should never get here */ 2586 /* should never get here */
2532 WARN_ON(1); 2587 WARN_ON(1);
2533 break; 2588 break;
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 10caec5ea8fa..67a35841bef0 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -296,7 +296,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
296 } 296 }
297 297
298 if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) 298 if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX)
299 cfg80211_action_tx_status( 299 cfg80211_mgmt_tx_status(
300 skb->dev, (unsigned long) skb, skb->data, skb->len, 300 skb->dev, (unsigned long) skb, skb->data, skb->len,
301 !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); 301 !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
302 302
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 748387d45bc0..cd2b485fed4f 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -471,7 +471,7 @@ void ieee80211_iterate_active_interfaces(
471 471
472 list_for_each_entry(sdata, &local->interfaces, list) { 472 list_for_each_entry(sdata, &local->interfaces, list) {
473 switch (sdata->vif.type) { 473 switch (sdata->vif.type) {
474 case __NL80211_IFTYPE_AFTER_LAST: 474 case NUM_NL80211_IFTYPES:
475 case NL80211_IFTYPE_UNSPECIFIED: 475 case NL80211_IFTYPE_UNSPECIFIED:
476 case NL80211_IFTYPE_MONITOR: 476 case NL80211_IFTYPE_MONITOR:
477 case NL80211_IFTYPE_AP_VLAN: 477 case NL80211_IFTYPE_AP_VLAN:
@@ -505,7 +505,7 @@ void ieee80211_iterate_active_interfaces_atomic(
505 505
506 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 506 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
507 switch (sdata->vif.type) { 507 switch (sdata->vif.type) {
508 case __NL80211_IFTYPE_AFTER_LAST: 508 case NUM_NL80211_IFTYPES:
509 case NL80211_IFTYPE_UNSPECIFIED: 509 case NL80211_IFTYPE_UNSPECIFIED:
510 case NL80211_IFTYPE_MONITOR: 510 case NL80211_IFTYPE_MONITOR:
511 case NL80211_IFTYPE_AP_VLAN: 511 case NL80211_IFTYPE_AP_VLAN:
@@ -1189,7 +1189,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1189 /* ignore virtual */ 1189 /* ignore virtual */
1190 break; 1190 break;
1191 case NL80211_IFTYPE_UNSPECIFIED: 1191 case NL80211_IFTYPE_UNSPECIFIED:
1192 case __NL80211_IFTYPE_AFTER_LAST: 1192 case NUM_NL80211_IFTYPES:
1193 WARN_ON(1); 1193 WARN_ON(1);
1194 break; 1194 break;
1195 } 1195 }