diff options
-rw-r--r-- | include/linux/nl80211.h | 93 | ||||
-rw-r--r-- | include/net/cfg80211.h | 56 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 12 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/iface.c | 6 | ||||
-rw-r--r-- | net/mac80211/main.c | 37 | ||||
-rw-r--r-- | net/mac80211/rx.c | 137 | ||||
-rw-r--r-- | net/mac80211/status.c | 2 | ||||
-rw-r--r-- | net/mac80211/util.c | 6 | ||||
-rw-r--r-- | net/wireless/core.c | 8 | ||||
-rw-r--r-- | net/wireless/core.h | 21 | ||||
-rw-r--r-- | net/wireless/mlme.c | 144 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 108 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 14 | ||||
-rw-r--r-- | net/wireless/util.c | 2 |
15 files changed, 452 insertions, 195 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 2c8701687336..8af1e66c3cf9 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -40,6 +40,43 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * DOC: Frame transmission/registration support | ||
44 | * | ||
45 | * Frame transmission and registration support exists to allow userspace | ||
46 | * management entities such as wpa_supplicant react to management frames | ||
47 | * that are not being handled by the kernel. This includes, for example, | ||
48 | * certain classes of action frames that cannot be handled in the kernel | ||
49 | * for various reasons. | ||
50 | * | ||
51 | * Frame registration is done on a per-interface basis and registrations | ||
52 | * cannot be removed other than by closing the socket. It is possible to | ||
53 | * specify a registration filter to register, for example, only for a | ||
54 | * certain type of action frame. In particular with action frames, those | ||
55 | * that userspace registers for will not be returned as unhandled by the | ||
56 | * driver, so that the registered application has to take responsibility | ||
57 | * for doing that. | ||
58 | * | ||
59 | * The type of frame that can be registered for is also dependent on the | ||
60 | * driver and interface type. The frame types are advertised in wiphy | ||
61 | * attributes so applications know what to expect. | ||
62 | * | ||
63 | * NOTE: When an interface changes type while registrations are active, | ||
64 | * these registrations are ignored until the interface type is | ||
65 | * changed again. This means that changing the interface type can | ||
66 | * lead to a situation that couldn't otherwise be produced, but | ||
67 | * any such registrations will be dormant in the sense that they | ||
68 | * will not be serviced, i.e. they will not receive any frames. | ||
69 | * | ||
70 | * Frame transmission allows userspace to send for example the required | ||
71 | * responses to action frames. It is subject to some sanity checking, | ||
72 | * but many frames can be transmitted. When a frame was transmitted, its | ||
73 | * status is indicated to the sending socket. | ||
74 | * | ||
75 | * For more technical details, see the corresponding command descriptions | ||
76 | * below. | ||
77 | */ | ||
78 | |||
79 | /** | ||
43 | * enum nl80211_commands - supported nl80211 commands | 80 | * enum nl80211_commands - supported nl80211 commands |
44 | * | 81 | * |
45 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors | 82 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors |
@@ -301,16 +338,18 @@ | |||
301 | * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface | 338 | * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface |
302 | * and @NL80211_ATTR_TX_RATES the set of allowed rates. | 339 | * and @NL80211_ATTR_TX_RATES the set of allowed rates. |
303 | * | 340 | * |
304 | * @NL80211_CMD_REGISTER_ACTION: Register for receiving certain action frames | 341 | * @NL80211_CMD_REGISTER_FRAME: Register for receiving certain mgmt frames |
305 | * (via @NL80211_CMD_ACTION) for processing in userspace. This command | 342 | * (via @NL80211_CMD_FRAME) for processing in userspace. This command |
306 | * requires an interface index and a match attribute containing the first | 343 | * requires an interface index, a frame type attribute (optional for |
307 | * few bytes of the frame that should match, e.g. a single byte for only | 344 | * backward compatibility reasons, if not given assumes action frames) |
308 | * a category match or four bytes for vendor frames including the OUI. | 345 | * and a match attribute containing the first few bytes of the frame |
309 | * The registration cannot be dropped, but is removed automatically | 346 | * that should match, e.g. a single byte for only a category match or |
310 | * when the netlink socket is closed. Multiple registrations can be made. | 347 | * four bytes for vendor frames including the OUI. The registration |
311 | * @NL80211_CMD_ACTION: Action frame TX request and RX notification. This | 348 | * cannot be dropped, but is removed automatically when the netlink |
312 | * command is used both as a request to transmit an Action frame and as an | 349 | * socket is closed. Multiple registrations can be made. |
313 | * event indicating reception of an Action frame that was not processed in | 350 | * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This |
351 | * command is used both as a request to transmit a management frame and | ||
352 | * as an event indicating reception of a frame that was not processed in | ||
314 | * kernel code, but is for us (i.e., which may need to be processed in a | 353 | * kernel code, but is for us (i.e., which may need to be processed in a |
315 | * user space application). %NL80211_ATTR_FRAME is used to specify the | 354 | * user space application). %NL80211_ATTR_FRAME is used to specify the |
316 | * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and | 355 | * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and |
@@ -320,8 +359,8 @@ | |||
320 | * operational channel). When called, this operation returns a cookie | 359 | * operational channel). When called, this operation returns a cookie |
321 | * (%NL80211_ATTR_COOKIE) that will be included with the TX status event | 360 | * (%NL80211_ATTR_COOKIE) that will be included with the TX status event |
322 | * pertaining to the TX request. | 361 | * pertaining to the TX request. |
323 | * @NL80211_CMD_ACTION_TX_STATUS: Report TX status of an Action frame | 362 | * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame |
324 | * transmitted with %NL80211_CMD_ACTION. %NL80211_ATTR_COOKIE identifies | 363 | * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies |
325 | * the TX command and %NL80211_ATTR_FRAME includes the contents of the | 364 | * the TX command and %NL80211_ATTR_FRAME includes the contents of the |
326 | * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged | 365 | * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged |
327 | * the frame. | 366 | * the frame. |
@@ -429,9 +468,12 @@ enum nl80211_commands { | |||
429 | 468 | ||
430 | NL80211_CMD_SET_TX_BITRATE_MASK, | 469 | NL80211_CMD_SET_TX_BITRATE_MASK, |
431 | 470 | ||
432 | NL80211_CMD_REGISTER_ACTION, | 471 | NL80211_CMD_REGISTER_FRAME, |
433 | NL80211_CMD_ACTION, | 472 | NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME, |
434 | NL80211_CMD_ACTION_TX_STATUS, | 473 | NL80211_CMD_FRAME, |
474 | NL80211_CMD_ACTION = NL80211_CMD_FRAME, | ||
475 | NL80211_CMD_FRAME_TX_STATUS, | ||
476 | NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS, | ||
435 | 477 | ||
436 | NL80211_CMD_SET_POWER_SAVE, | 478 | NL80211_CMD_SET_POWER_SAVE, |
437 | NL80211_CMD_GET_POWER_SAVE, | 479 | NL80211_CMD_GET_POWER_SAVE, |
@@ -708,7 +750,16 @@ enum nl80211_commands { | |||
708 | * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. | 750 | * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. |
709 | * | 751 | * |
710 | * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain | 752 | * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain |
711 | * at least one byte, currently used with @NL80211_CMD_REGISTER_ACTION. | 753 | * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. |
754 | * @NL80211_ATTR_FRAME_TYPE: A u16 indicating the frame type/subtype for the | ||
755 | * @NL80211_CMD_REGISTER_FRAME command. | ||
756 | * @NL80211_ATTR_TX_FRAME_TYPES: wiphy capability attribute, which is a | ||
757 | * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing | ||
758 | * information about which frame types can be transmitted with | ||
759 | * %NL80211_CMD_FRAME. | ||
760 | * @NL80211_ATTR_RX_FRAME_TYPES: wiphy capability attribute, which is a | ||
761 | * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing | ||
762 | * information about which frame types can be registered for RX. | ||
712 | * | 763 | * |
713 | * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was | 764 | * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was |
714 | * acknowledged by the recipient. | 765 | * acknowledged by the recipient. |
@@ -891,6 +942,10 @@ enum nl80211_attrs { | |||
891 | NL80211_ATTR_WIPHY_TX_POWER_SETTING, | 942 | NL80211_ATTR_WIPHY_TX_POWER_SETTING, |
892 | NL80211_ATTR_WIPHY_TX_POWER_LEVEL, | 943 | NL80211_ATTR_WIPHY_TX_POWER_LEVEL, |
893 | 944 | ||
945 | NL80211_ATTR_TX_FRAME_TYPES, | ||
946 | NL80211_ATTR_RX_FRAME_TYPES, | ||
947 | NL80211_ATTR_FRAME_TYPE, | ||
948 | |||
894 | /* add attributes here, update the policy in nl80211.c */ | 949 | /* add attributes here, update the policy in nl80211.c */ |
895 | 950 | ||
896 | __NL80211_ATTR_AFTER_LAST, | 951 | __NL80211_ATTR_AFTER_LAST, |
@@ -947,7 +1002,7 @@ enum nl80211_attrs { | |||
947 | * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames | 1002 | * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames |
948 | * @NL80211_IFTYPE_MESH_POINT: mesh point | 1003 | * @NL80211_IFTYPE_MESH_POINT: mesh point |
949 | * @NL80211_IFTYPE_MAX: highest interface type number currently defined | 1004 | * @NL80211_IFTYPE_MAX: highest interface type number currently defined |
950 | * @__NL80211_IFTYPE_AFTER_LAST: internal use | 1005 | * @NUM_NL80211_IFTYPES: number of defined interface types |
951 | * | 1006 | * |
952 | * These values are used with the %NL80211_ATTR_IFTYPE | 1007 | * These values are used with the %NL80211_ATTR_IFTYPE |
953 | * to set the type of an interface. | 1008 | * to set the type of an interface. |
@@ -964,8 +1019,8 @@ enum nl80211_iftype { | |||
964 | NL80211_IFTYPE_MESH_POINT, | 1019 | NL80211_IFTYPE_MESH_POINT, |
965 | 1020 | ||
966 | /* keep last */ | 1021 | /* keep last */ |
967 | __NL80211_IFTYPE_AFTER_LAST, | 1022 | NUM_NL80211_IFTYPES, |
968 | NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1 | 1023 | NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1 |
969 | }; | 1024 | }; |
970 | 1025 | ||
971 | /** | 1026 | /** |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2b403c7ee32e..6a98b1b3bfde 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1020,7 +1020,7 @@ struct cfg80211_pmksa { | |||
1020 | * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. | 1020 | * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. |
1021 | * This allows the operation to be terminated prior to timeout based on | 1021 | * This allows the operation to be terminated prior to timeout based on |
1022 | * the duration value. | 1022 | * the duration value. |
1023 | * @action: Transmit an action frame | 1023 | * @mgmt_tx: Transmit a management frame |
1024 | * | 1024 | * |
1025 | * @testmode_cmd: run a test mode command | 1025 | * @testmode_cmd: run a test mode command |
1026 | * | 1026 | * |
@@ -1172,7 +1172,7 @@ struct cfg80211_ops { | |||
1172 | struct net_device *dev, | 1172 | struct net_device *dev, |
1173 | u64 cookie); | 1173 | u64 cookie); |
1174 | 1174 | ||
1175 | int (*action)(struct wiphy *wiphy, struct net_device *dev, | 1175 | int (*mgmt_tx)(struct wiphy *wiphy, struct net_device *dev, |
1176 | struct ieee80211_channel *chan, | 1176 | struct ieee80211_channel *chan, |
1177 | enum nl80211_channel_type channel_type, | 1177 | enum nl80211_channel_type channel_type, |
1178 | bool channel_type_valid, | 1178 | bool channel_type_valid, |
@@ -1236,6 +1236,10 @@ struct mac_address { | |||
1236 | u8 addr[ETH_ALEN]; | 1236 | u8 addr[ETH_ALEN]; |
1237 | }; | 1237 | }; |
1238 | 1238 | ||
1239 | struct ieee80211_txrx_stypes { | ||
1240 | u16 tx, rx; | ||
1241 | }; | ||
1242 | |||
1239 | /** | 1243 | /** |
1240 | * struct wiphy - wireless hardware description | 1244 | * struct wiphy - wireless hardware description |
1241 | * @reg_notifier: the driver's regulatory notification callback | 1245 | * @reg_notifier: the driver's regulatory notification callback |
@@ -1286,6 +1290,10 @@ struct mac_address { | |||
1286 | * @privid: a pointer that drivers can use to identify if an arbitrary | 1290 | * @privid: a pointer that drivers can use to identify if an arbitrary |
1287 | * wiphy is theirs, e.g. in global notifiers | 1291 | * wiphy is theirs, e.g. in global notifiers |
1288 | * @bands: information about bands/channels supported by this device | 1292 | * @bands: information about bands/channels supported by this device |
1293 | * | ||
1294 | * @mgmt_stypes: bitmasks of frame subtypes that can be subscribed to or | ||
1295 | * transmitted through nl80211, points to an array indexed by interface | ||
1296 | * type | ||
1289 | */ | 1297 | */ |
1290 | struct wiphy { | 1298 | struct wiphy { |
1291 | /* assign these fields before you register the wiphy */ | 1299 | /* assign these fields before you register the wiphy */ |
@@ -1294,9 +1302,12 @@ struct wiphy { | |||
1294 | u8 perm_addr[ETH_ALEN]; | 1302 | u8 perm_addr[ETH_ALEN]; |
1295 | u8 addr_mask[ETH_ALEN]; | 1303 | u8 addr_mask[ETH_ALEN]; |
1296 | 1304 | ||
1297 | u16 n_addresses; | ||
1298 | struct mac_address *addresses; | 1305 | struct mac_address *addresses; |
1299 | 1306 | ||
1307 | const struct ieee80211_txrx_stypes *mgmt_stypes; | ||
1308 | |||
1309 | u16 n_addresses; | ||
1310 | |||
1300 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ | 1311 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ |
1301 | u16 interface_modes; | 1312 | u16 interface_modes; |
1302 | 1313 | ||
@@ -1492,8 +1503,8 @@ struct cfg80211_cached_keys; | |||
1492 | * set by driver (if supported) on add_interface BEFORE registering the | 1503 | * set by driver (if supported) on add_interface BEFORE registering the |
1493 | * netdev and may otherwise be used by driver read-only, will be update | 1504 | * netdev and may otherwise be used by driver read-only, will be update |
1494 | * by cfg80211 on change_interface | 1505 | * by cfg80211 on change_interface |
1495 | * @action_registrations: list of registrations for action frames | 1506 | * @mgmt_registrations: list of registrations for management frames |
1496 | * @action_registrations_lock: lock for the list | 1507 | * @mgmt_registrations_lock: lock for the list |
1497 | * @mtx: mutex used to lock data in this struct | 1508 | * @mtx: mutex used to lock data in this struct |
1498 | * @cleanup_work: work struct used for cleanup that can't be done directly | 1509 | * @cleanup_work: work struct used for cleanup that can't be done directly |
1499 | */ | 1510 | */ |
@@ -1505,8 +1516,8 @@ struct wireless_dev { | |||
1505 | struct list_head list; | 1516 | struct list_head list; |
1506 | struct net_device *netdev; | 1517 | struct net_device *netdev; |
1507 | 1518 | ||
1508 | struct list_head action_registrations; | 1519 | struct list_head mgmt_registrations; |
1509 | spinlock_t action_registrations_lock; | 1520 | spinlock_t mgmt_registrations_lock; |
1510 | 1521 | ||
1511 | struct mutex mtx; | 1522 | struct mutex mtx; |
1512 | 1523 | ||
@@ -2373,38 +2384,39 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | |||
2373 | struct station_info *sinfo, gfp_t gfp); | 2384 | struct station_info *sinfo, gfp_t gfp); |
2374 | 2385 | ||
2375 | /** | 2386 | /** |
2376 | * cfg80211_rx_action - notification of received, unprocessed Action frame | 2387 | * cfg80211_rx_mgmt - notification of received, unprocessed management frame |
2377 | * @dev: network device | 2388 | * @dev: network device |
2378 | * @freq: Frequency on which the frame was received in MHz | 2389 | * @freq: Frequency on which the frame was received in MHz |
2379 | * @buf: Action frame (header + body) | 2390 | * @buf: Management frame (header + body) |
2380 | * @len: length of the frame data | 2391 | * @len: length of the frame data |
2381 | * @gfp: context flags | 2392 | * @gfp: context flags |
2382 | * Returns %true if a user space application is responsible for rejecting the | 2393 | * |
2383 | * unrecognized Action frame; %false if no such application is registered | 2394 | * Returns %true if a user space application has registered for this frame. |
2384 | * (i.e., the driver is responsible for rejecting the unrecognized Action | 2395 | * For action frames, that makes it responsible for rejecting unrecognized |
2385 | * frame) | 2396 | * action frames; %false otherwise, in which case for action frames the |
2397 | * driver is responsible for rejecting the frame. | ||
2386 | * | 2398 | * |
2387 | * This function is called whenever an Action frame is received for a station | 2399 | * This function is called whenever an Action frame is received for a station |
2388 | * mode interface, but is not processed in kernel. | 2400 | * mode interface, but is not processed in kernel. |
2389 | */ | 2401 | */ |
2390 | bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, | 2402 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, |
2391 | size_t len, gfp_t gfp); | 2403 | size_t len, gfp_t gfp); |
2392 | 2404 | ||
2393 | /** | 2405 | /** |
2394 | * cfg80211_action_tx_status - notification of TX status for Action frame | 2406 | * cfg80211_mgmt_tx_status - notification of TX status for management frame |
2395 | * @dev: network device | 2407 | * @dev: network device |
2396 | * @cookie: Cookie returned by cfg80211_ops::action() | 2408 | * @cookie: Cookie returned by cfg80211_ops::mgmt_tx() |
2397 | * @buf: Action frame (header + body) | 2409 | * @buf: Management frame (header + body) |
2398 | * @len: length of the frame data | 2410 | * @len: length of the frame data |
2399 | * @ack: Whether frame was acknowledged | 2411 | * @ack: Whether frame was acknowledged |
2400 | * @gfp: context flags | 2412 | * @gfp: context flags |
2401 | * | 2413 | * |
2402 | * This function is called whenever an Action frame was requested to be | 2414 | * This function is called whenever a management frame was requested to be |
2403 | * transmitted with cfg80211_ops::action() to report the TX status of the | 2415 | * transmitted with cfg80211_ops::mgmt_tx() to report the TX status of the |
2404 | * transmission attempt. | 2416 | * transmission attempt. |
2405 | */ | 2417 | */ |
2406 | void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, | 2418 | void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie, |
2407 | const u8 *buf, size_t len, bool ack, gfp_t gfp); | 2419 | const u8 *buf, size_t len, bool ack, gfp_t gfp); |
2408 | 2420 | ||
2409 | 2421 | ||
2410 | /** | 2422 | /** |
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 | ||
1524 | static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | 1524 | static 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 | ||
175 | struct ieee80211_rx_data { | 176 | struct 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 | } |
418 | EXPORT_SYMBOL(ieee80211_napi_complete); | 418 | EXPORT_SYMBOL(ieee80211_napi_complete); |
419 | 419 | ||
420 | /* There isn't a lot of sense in it, but you can transmit anything you like */ | ||
421 | static const struct ieee80211_txrx_stypes | ||
422 | ieee80211_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 | |||
420 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 455 | struct 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 | ||
1942 | static ieee80211_rx_result debug_noinline | 1942 | static ieee80211_rx_result debug_noinline |
1943 | ieee80211_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 | |||
1967 | static ieee80211_rx_result debug_noinline | ||
1943 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | 1968 | ieee80211_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 | |||
2100 | static ieee80211_rx_result debug_noinline | ||
2101 | ieee80211_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 | |||
2130 | static ieee80211_rx_result debug_noinline | ||
2131 | ieee80211_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 | ||
2116 | static ieee80211_rx_result debug_noinline | 2177 | static 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 | } |
diff --git a/net/wireless/core.c b/net/wireless/core.c index c70909c3eae4..d52630bbab04 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -433,7 +433,7 @@ int wiphy_register(struct wiphy *wiphy) | |||
433 | 433 | ||
434 | /* sanity check ifmodes */ | 434 | /* sanity check ifmodes */ |
435 | WARN_ON(!ifmodes); | 435 | WARN_ON(!ifmodes); |
436 | ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; | 436 | ifmodes &= ((1 << NUM_NL80211_IFTYPES) - 1) & ~1; |
437 | if (WARN_ON(ifmodes != wiphy->interface_modes)) | 437 | if (WARN_ON(ifmodes != wiphy->interface_modes)) |
438 | wiphy->interface_modes = ifmodes; | 438 | wiphy->interface_modes = ifmodes; |
439 | 439 | ||
@@ -685,8 +685,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
685 | INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); | 685 | INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); |
686 | INIT_LIST_HEAD(&wdev->event_list); | 686 | INIT_LIST_HEAD(&wdev->event_list); |
687 | spin_lock_init(&wdev->event_lock); | 687 | spin_lock_init(&wdev->event_lock); |
688 | INIT_LIST_HEAD(&wdev->action_registrations); | 688 | INIT_LIST_HEAD(&wdev->mgmt_registrations); |
689 | spin_lock_init(&wdev->action_registrations_lock); | 689 | spin_lock_init(&wdev->mgmt_registrations_lock); |
690 | 690 | ||
691 | mutex_lock(&rdev->devlist_mtx); | 691 | mutex_lock(&rdev->devlist_mtx); |
692 | list_add_rcu(&wdev->list, &rdev->netdev_list); | 692 | list_add_rcu(&wdev->list, &rdev->netdev_list); |
@@ -806,7 +806,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
806 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); | 806 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); |
807 | list_del_rcu(&wdev->list); | 807 | list_del_rcu(&wdev->list); |
808 | rdev->devlist_generation++; | 808 | rdev->devlist_generation++; |
809 | cfg80211_mlme_purge_actions(wdev); | 809 | cfg80211_mlme_purge_registrations(wdev); |
810 | #ifdef CONFIG_CFG80211_WEXT | 810 | #ifdef CONFIG_CFG80211_WEXT |
811 | kfree(wdev->wext.keys); | 811 | kfree(wdev->wext.keys); |
812 | #endif | 812 | #endif |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 63d57ae399c3..58ab2c791d28 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -331,16 +331,17 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
331 | const u8 *resp_ie, size_t resp_ie_len, | 331 | const u8 *resp_ie, size_t resp_ie_len, |
332 | u16 status, bool wextev, | 332 | u16 status, bool wextev, |
333 | struct cfg80211_bss *bss); | 333 | struct cfg80211_bss *bss); |
334 | int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, | 334 | int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, |
335 | const u8 *match_data, int match_len); | 335 | u16 frame_type, const u8 *match_data, |
336 | void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid); | 336 | int match_len); |
337 | void cfg80211_mlme_purge_actions(struct wireless_dev *wdev); | 337 | void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid); |
338 | int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | 338 | void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); |
339 | struct net_device *dev, | 339 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
340 | struct ieee80211_channel *chan, | 340 | struct net_device *dev, |
341 | enum nl80211_channel_type channel_type, | 341 | struct ieee80211_channel *chan, |
342 | bool channel_type_valid, | 342 | enum nl80211_channel_type channel_type, |
343 | const u8 *buf, size_t len, u64 *cookie); | 343 | bool channel_type_valid, |
344 | const u8 *buf, size_t len, u64 *cookie); | ||
344 | 345 | ||
345 | /* SME */ | 346 | /* SME */ |
346 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 347 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index ee0af32ed59e..8515b1e5c578 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -748,31 +748,51 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | |||
748 | } | 748 | } |
749 | EXPORT_SYMBOL(cfg80211_new_sta); | 749 | EXPORT_SYMBOL(cfg80211_new_sta); |
750 | 750 | ||
751 | struct cfg80211_action_registration { | 751 | struct cfg80211_mgmt_registration { |
752 | struct list_head list; | 752 | struct list_head list; |
753 | 753 | ||
754 | u32 nlpid; | 754 | u32 nlpid; |
755 | 755 | ||
756 | int match_len; | 756 | int match_len; |
757 | 757 | ||
758 | __le16 frame_type; | ||
759 | |||
758 | u8 match[]; | 760 | u8 match[]; |
759 | }; | 761 | }; |
760 | 762 | ||
761 | int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, | 763 | int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, |
762 | const u8 *match_data, int match_len) | 764 | u16 frame_type, const u8 *match_data, |
765 | int match_len) | ||
763 | { | 766 | { |
764 | struct cfg80211_action_registration *reg, *nreg; | 767 | struct cfg80211_mgmt_registration *reg, *nreg; |
765 | int err = 0; | 768 | int err = 0; |
769 | u16 mgmt_type; | ||
770 | |||
771 | if (!wdev->wiphy->mgmt_stypes) | ||
772 | return -EOPNOTSUPP; | ||
773 | |||
774 | if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) | ||
775 | return -EINVAL; | ||
776 | |||
777 | if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) | ||
778 | return -EINVAL; | ||
779 | |||
780 | mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4; | ||
781 | if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type))) | ||
782 | return -EINVAL; | ||
766 | 783 | ||
767 | nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); | 784 | nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); |
768 | if (!nreg) | 785 | if (!nreg) |
769 | return -ENOMEM; | 786 | return -ENOMEM; |
770 | 787 | ||
771 | spin_lock_bh(&wdev->action_registrations_lock); | 788 | spin_lock_bh(&wdev->mgmt_registrations_lock); |
772 | 789 | ||
773 | list_for_each_entry(reg, &wdev->action_registrations, list) { | 790 | list_for_each_entry(reg, &wdev->mgmt_registrations, list) { |
774 | int mlen = min(match_len, reg->match_len); | 791 | int mlen = min(match_len, reg->match_len); |
775 | 792 | ||
793 | if (frame_type != le16_to_cpu(reg->frame_type)) | ||
794 | continue; | ||
795 | |||
776 | if (memcmp(reg->match, match_data, mlen) == 0) { | 796 | if (memcmp(reg->match, match_data, mlen) == 0) { |
777 | err = -EALREADY; | 797 | err = -EALREADY; |
778 | break; | 798 | break; |
@@ -787,62 +807,75 @@ int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, | |||
787 | memcpy(nreg->match, match_data, match_len); | 807 | memcpy(nreg->match, match_data, match_len); |
788 | nreg->match_len = match_len; | 808 | nreg->match_len = match_len; |
789 | nreg->nlpid = snd_pid; | 809 | nreg->nlpid = snd_pid; |
790 | list_add(&nreg->list, &wdev->action_registrations); | 810 | nreg->frame_type = cpu_to_le16(frame_type); |
811 | list_add(&nreg->list, &wdev->mgmt_registrations); | ||
791 | 812 | ||
792 | out: | 813 | out: |
793 | spin_unlock_bh(&wdev->action_registrations_lock); | 814 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
794 | return err; | 815 | return err; |
795 | } | 816 | } |
796 | 817 | ||
797 | void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid) | 818 | void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid) |
798 | { | 819 | { |
799 | struct cfg80211_action_registration *reg, *tmp; | 820 | struct cfg80211_mgmt_registration *reg, *tmp; |
800 | 821 | ||
801 | spin_lock_bh(&wdev->action_registrations_lock); | 822 | spin_lock_bh(&wdev->mgmt_registrations_lock); |
802 | 823 | ||
803 | list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { | 824 | list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { |
804 | if (reg->nlpid == nlpid) { | 825 | if (reg->nlpid == nlpid) { |
805 | list_del(®->list); | 826 | list_del(®->list); |
806 | kfree(reg); | 827 | kfree(reg); |
807 | } | 828 | } |
808 | } | 829 | } |
809 | 830 | ||
810 | spin_unlock_bh(&wdev->action_registrations_lock); | 831 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
811 | } | 832 | } |
812 | 833 | ||
813 | void cfg80211_mlme_purge_actions(struct wireless_dev *wdev) | 834 | void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev) |
814 | { | 835 | { |
815 | struct cfg80211_action_registration *reg, *tmp; | 836 | struct cfg80211_mgmt_registration *reg, *tmp; |
816 | 837 | ||
817 | spin_lock_bh(&wdev->action_registrations_lock); | 838 | spin_lock_bh(&wdev->mgmt_registrations_lock); |
818 | 839 | ||
819 | list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { | 840 | list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { |
820 | list_del(®->list); | 841 | list_del(®->list); |
821 | kfree(reg); | 842 | kfree(reg); |
822 | } | 843 | } |
823 | 844 | ||
824 | spin_unlock_bh(&wdev->action_registrations_lock); | 845 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
825 | } | 846 | } |
826 | 847 | ||
827 | int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | 848 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
828 | struct net_device *dev, | 849 | struct net_device *dev, |
829 | struct ieee80211_channel *chan, | 850 | struct ieee80211_channel *chan, |
830 | enum nl80211_channel_type channel_type, | 851 | enum nl80211_channel_type channel_type, |
831 | bool channel_type_valid, | 852 | bool channel_type_valid, |
832 | const u8 *buf, size_t len, u64 *cookie) | 853 | const u8 *buf, size_t len, u64 *cookie) |
833 | { | 854 | { |
834 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 855 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
835 | const struct ieee80211_mgmt *mgmt; | 856 | const struct ieee80211_mgmt *mgmt; |
857 | u16 stype; | ||
858 | |||
859 | if (!wdev->wiphy->mgmt_stypes) | ||
860 | return -EOPNOTSUPP; | ||
836 | 861 | ||
837 | if (rdev->ops->action == NULL) | 862 | if (!rdev->ops->mgmt_tx) |
838 | return -EOPNOTSUPP; | 863 | return -EOPNOTSUPP; |
864 | |||
839 | if (len < 24 + 1) | 865 | if (len < 24 + 1) |
840 | return -EINVAL; | 866 | return -EINVAL; |
841 | 867 | ||
842 | mgmt = (const struct ieee80211_mgmt *) buf; | 868 | mgmt = (const struct ieee80211_mgmt *) buf; |
843 | if (!ieee80211_is_action(mgmt->frame_control)) | 869 | |
870 | if (!ieee80211_is_mgmt(mgmt->frame_control)) | ||
844 | return -EINVAL; | 871 | return -EINVAL; |
845 | if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { | 872 | |
873 | stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; | ||
874 | if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4))) | ||
875 | return -EINVAL; | ||
876 | |||
877 | if (ieee80211_is_action(mgmt->frame_control) && | ||
878 | mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { | ||
846 | /* Verify that we are associated with the destination AP */ | 879 | /* Verify that we are associated with the destination AP */ |
847 | wdev_lock(wdev); | 880 | wdev_lock(wdev); |
848 | 881 | ||
@@ -863,64 +896,75 @@ int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | |||
863 | return -EINVAL; | 896 | return -EINVAL; |
864 | 897 | ||
865 | /* Transmit the Action frame as requested by user space */ | 898 | /* Transmit the Action frame as requested by user space */ |
866 | return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type, | 899 | return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, channel_type, |
867 | channel_type_valid, buf, len, cookie); | 900 | channel_type_valid, buf, len, cookie); |
868 | } | 901 | } |
869 | 902 | ||
870 | bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, | 903 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, |
871 | size_t len, gfp_t gfp) | 904 | size_t len, gfp_t gfp) |
872 | { | 905 | { |
873 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 906 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
874 | struct wiphy *wiphy = wdev->wiphy; | 907 | struct wiphy *wiphy = wdev->wiphy; |
875 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 908 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
876 | struct cfg80211_action_registration *reg; | 909 | struct cfg80211_mgmt_registration *reg; |
877 | const u8 *action_data; | 910 | const struct ieee80211_txrx_stypes *stypes = |
878 | int action_data_len; | 911 | &wiphy->mgmt_stypes[wdev->iftype]; |
912 | struct ieee80211_mgmt *mgmt = (void *)buf; | ||
913 | const u8 *data; | ||
914 | int data_len; | ||
879 | bool result = false; | 915 | bool result = false; |
916 | __le16 ftype = mgmt->frame_control & | ||
917 | cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE); | ||
918 | u16 stype; | ||
880 | 919 | ||
881 | /* frame length - min size excluding category */ | 920 | stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4; |
882 | action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1); | ||
883 | 921 | ||
884 | /* action data starts with category */ | 922 | if (!(stypes->rx & BIT(stype))) |
885 | action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1; | 923 | return false; |
886 | 924 | ||
887 | spin_lock_bh(&wdev->action_registrations_lock); | 925 | data = buf + ieee80211_hdrlen(mgmt->frame_control); |
926 | data_len = len - ieee80211_hdrlen(mgmt->frame_control); | ||
927 | |||
928 | spin_lock_bh(&wdev->mgmt_registrations_lock); | ||
929 | |||
930 | list_for_each_entry(reg, &wdev->mgmt_registrations, list) { | ||
931 | if (reg->frame_type != ftype) | ||
932 | continue; | ||
888 | 933 | ||
889 | list_for_each_entry(reg, &wdev->action_registrations, list) { | 934 | if (reg->match_len > data_len) |
890 | if (reg->match_len > action_data_len) | ||
891 | continue; | 935 | continue; |
892 | 936 | ||
893 | if (memcmp(reg->match, action_data, reg->match_len)) | 937 | if (memcmp(reg->match, data, reg->match_len)) |
894 | continue; | 938 | continue; |
895 | 939 | ||
896 | /* found match! */ | 940 | /* found match! */ |
897 | 941 | ||
898 | /* Indicate the received Action frame to user space */ | 942 | /* Indicate the received Action frame to user space */ |
899 | if (nl80211_send_action(rdev, dev, reg->nlpid, freq, | 943 | if (nl80211_send_mgmt(rdev, dev, reg->nlpid, freq, |
900 | buf, len, gfp)) | 944 | buf, len, gfp)) |
901 | continue; | 945 | continue; |
902 | 946 | ||
903 | result = true; | 947 | result = true; |
904 | break; | 948 | break; |
905 | } | 949 | } |
906 | 950 | ||
907 | spin_unlock_bh(&wdev->action_registrations_lock); | 951 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
908 | 952 | ||
909 | return result; | 953 | return result; |
910 | } | 954 | } |
911 | EXPORT_SYMBOL(cfg80211_rx_action); | 955 | EXPORT_SYMBOL(cfg80211_rx_mgmt); |
912 | 956 | ||
913 | void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, | 957 | void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie, |
914 | const u8 *buf, size_t len, bool ack, gfp_t gfp) | 958 | const u8 *buf, size_t len, bool ack, gfp_t gfp) |
915 | { | 959 | { |
916 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 960 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
917 | struct wiphy *wiphy = wdev->wiphy; | 961 | struct wiphy *wiphy = wdev->wiphy; |
918 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 962 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
919 | 963 | ||
920 | /* Indicate TX status of the Action frame to user space */ | 964 | /* Indicate TX status of the Action frame to user space */ |
921 | nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); | 965 | nl80211_send_mgmt_tx_status(rdev, dev, cookie, buf, len, ack, gfp); |
922 | } | 966 | } |
923 | EXPORT_SYMBOL(cfg80211_action_tx_status); | 967 | EXPORT_SYMBOL(cfg80211_mgmt_tx_status); |
924 | 968 | ||
925 | void cfg80211_cqm_rssi_notify(struct net_device *dev, | 969 | void cfg80211_cqm_rssi_notify(struct net_device *dev, |
926 | enum nl80211_cqm_rssi_threshold_event rssi_event, | 970 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index bb5b78eebeb2..927ffbd2aebc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -156,6 +156,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
156 | 156 | ||
157 | [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, | 157 | [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, |
158 | [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, | 158 | [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, |
159 | [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, | ||
159 | }; | 160 | }; |
160 | 161 | ||
161 | /* policy for the attributes */ | 162 | /* policy for the attributes */ |
@@ -437,6 +438,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
437 | struct ieee80211_rate *rate; | 438 | struct ieee80211_rate *rate; |
438 | int i; | 439 | int i; |
439 | u16 ifmodes = dev->wiphy.interface_modes; | 440 | u16 ifmodes = dev->wiphy.interface_modes; |
441 | const struct ieee80211_txrx_stypes *mgmt_stypes = | ||
442 | dev->wiphy.mgmt_stypes; | ||
440 | 443 | ||
441 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); | 444 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); |
442 | if (!hdr) | 445 | if (!hdr) |
@@ -587,7 +590,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
587 | CMD(flush_pmksa, FLUSH_PMKSA); | 590 | CMD(flush_pmksa, FLUSH_PMKSA); |
588 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | 591 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); |
589 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); | 592 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); |
590 | CMD(action, ACTION); | 593 | CMD(mgmt_tx, FRAME); |
591 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | 594 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { |
592 | i++; | 595 | i++; |
593 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); | 596 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); |
@@ -608,6 +611,53 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
608 | 611 | ||
609 | nla_nest_end(msg, nl_cmds); | 612 | nla_nest_end(msg, nl_cmds); |
610 | 613 | ||
614 | if (mgmt_stypes) { | ||
615 | u16 stypes; | ||
616 | struct nlattr *nl_ftypes, *nl_ifs; | ||
617 | enum nl80211_iftype ift; | ||
618 | |||
619 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); | ||
620 | if (!nl_ifs) | ||
621 | goto nla_put_failure; | ||
622 | |||
623 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | ||
624 | nl_ftypes = nla_nest_start(msg, ift); | ||
625 | if (!nl_ftypes) | ||
626 | goto nla_put_failure; | ||
627 | i = 0; | ||
628 | stypes = mgmt_stypes[ift].tx; | ||
629 | while (stypes) { | ||
630 | if (stypes & 1) | ||
631 | NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, | ||
632 | (i << 4) | IEEE80211_FTYPE_MGMT); | ||
633 | stypes >>= 1; | ||
634 | i++; | ||
635 | } | ||
636 | nla_nest_end(msg, nl_ftypes); | ||
637 | } | ||
638 | |||
639 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); | ||
640 | if (!nl_ifs) | ||
641 | goto nla_put_failure; | ||
642 | |||
643 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | ||
644 | nl_ftypes = nla_nest_start(msg, ift); | ||
645 | if (!nl_ftypes) | ||
646 | goto nla_put_failure; | ||
647 | i = 0; | ||
648 | stypes = mgmt_stypes[ift].rx; | ||
649 | while (stypes) { | ||
650 | if (stypes & 1) | ||
651 | NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, | ||
652 | (i << 4) | IEEE80211_FTYPE_MGMT); | ||
653 | stypes >>= 1; | ||
654 | i++; | ||
655 | } | ||
656 | nla_nest_end(msg, nl_ftypes); | ||
657 | } | ||
658 | nla_nest_end(msg, nl_ifs); | ||
659 | } | ||
660 | |||
611 | return genlmsg_end(msg, hdr); | 661 | return genlmsg_end(msg, hdr); |
612 | 662 | ||
613 | nla_put_failure: | 663 | nla_put_failure: |
@@ -4732,17 +4782,18 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
4732 | return err; | 4782 | return err; |
4733 | } | 4783 | } |
4734 | 4784 | ||
4735 | static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | 4785 | static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) |
4736 | { | 4786 | { |
4737 | struct cfg80211_registered_device *rdev; | 4787 | struct cfg80211_registered_device *rdev; |
4738 | struct net_device *dev; | 4788 | struct net_device *dev; |
4789 | u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION; | ||
4739 | int err; | 4790 | int err; |
4740 | 4791 | ||
4741 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) | 4792 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) |
4742 | return -EINVAL; | 4793 | return -EINVAL; |
4743 | 4794 | ||
4744 | if (nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]) < 1) | 4795 | if (info->attrs[NL80211_ATTR_FRAME_TYPE]) |
4745 | return -EINVAL; | 4796 | frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]); |
4746 | 4797 | ||
4747 | rtnl_lock(); | 4798 | rtnl_lock(); |
4748 | 4799 | ||
@@ -4757,12 +4808,13 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | |||
4757 | } | 4808 | } |
4758 | 4809 | ||
4759 | /* not much point in registering if we can't reply */ | 4810 | /* not much point in registering if we can't reply */ |
4760 | if (!rdev->ops->action) { | 4811 | if (!rdev->ops->mgmt_tx) { |
4761 | err = -EOPNOTSUPP; | 4812 | err = -EOPNOTSUPP; |
4762 | goto out; | 4813 | goto out; |
4763 | } | 4814 | } |
4764 | 4815 | ||
4765 | err = cfg80211_mlme_register_action(dev->ieee80211_ptr, info->snd_pid, | 4816 | err = cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid, |
4817 | frame_type, | ||
4766 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), | 4818 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), |
4767 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); | 4819 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); |
4768 | out: | 4820 | out: |
@@ -4773,7 +4825,7 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | |||
4773 | return err; | 4825 | return err; |
4774 | } | 4826 | } |
4775 | 4827 | ||
4776 | static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | 4828 | static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) |
4777 | { | 4829 | { |
4778 | struct cfg80211_registered_device *rdev; | 4830 | struct cfg80211_registered_device *rdev; |
4779 | struct net_device *dev; | 4831 | struct net_device *dev; |
@@ -4796,7 +4848,7 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | |||
4796 | if (err) | 4848 | if (err) |
4797 | goto unlock_rtnl; | 4849 | goto unlock_rtnl; |
4798 | 4850 | ||
4799 | if (!rdev->ops->action) { | 4851 | if (!rdev->ops->mgmt_tx) { |
4800 | err = -EOPNOTSUPP; | 4852 | err = -EOPNOTSUPP; |
4801 | goto out; | 4853 | goto out; |
4802 | } | 4854 | } |
@@ -4839,17 +4891,17 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | |||
4839 | } | 4891 | } |
4840 | 4892 | ||
4841 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 4893 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
4842 | NL80211_CMD_ACTION); | 4894 | NL80211_CMD_FRAME); |
4843 | 4895 | ||
4844 | if (IS_ERR(hdr)) { | 4896 | if (IS_ERR(hdr)) { |
4845 | err = PTR_ERR(hdr); | 4897 | err = PTR_ERR(hdr); |
4846 | goto free_msg; | 4898 | goto free_msg; |
4847 | } | 4899 | } |
4848 | err = cfg80211_mlme_action(rdev, dev, chan, channel_type, | 4900 | err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, channel_type, |
4849 | channel_type_valid, | 4901 | channel_type_valid, |
4850 | nla_data(info->attrs[NL80211_ATTR_FRAME]), | 4902 | nla_data(info->attrs[NL80211_ATTR_FRAME]), |
4851 | nla_len(info->attrs[NL80211_ATTR_FRAME]), | 4903 | nla_len(info->attrs[NL80211_ATTR_FRAME]), |
4852 | &cookie); | 4904 | &cookie); |
4853 | if (err) | 4905 | if (err) |
4854 | goto free_msg; | 4906 | goto free_msg; |
4855 | 4907 | ||
@@ -5348,14 +5400,14 @@ static struct genl_ops nl80211_ops[] = { | |||
5348 | .flags = GENL_ADMIN_PERM, | 5400 | .flags = GENL_ADMIN_PERM, |
5349 | }, | 5401 | }, |
5350 | { | 5402 | { |
5351 | .cmd = NL80211_CMD_REGISTER_ACTION, | 5403 | .cmd = NL80211_CMD_REGISTER_FRAME, |
5352 | .doit = nl80211_register_action, | 5404 | .doit = nl80211_register_mgmt, |
5353 | .policy = nl80211_policy, | 5405 | .policy = nl80211_policy, |
5354 | .flags = GENL_ADMIN_PERM, | 5406 | .flags = GENL_ADMIN_PERM, |
5355 | }, | 5407 | }, |
5356 | { | 5408 | { |
5357 | .cmd = NL80211_CMD_ACTION, | 5409 | .cmd = NL80211_CMD_FRAME, |
5358 | .doit = nl80211_action, | 5410 | .doit = nl80211_tx_mgmt, |
5359 | .policy = nl80211_policy, | 5411 | .policy = nl80211_policy, |
5360 | .flags = GENL_ADMIN_PERM, | 5412 | .flags = GENL_ADMIN_PERM, |
5361 | }, | 5413 | }, |
@@ -6055,9 +6107,9 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
6055 | nl80211_mlme_mcgrp.id, gfp); | 6107 | nl80211_mlme_mcgrp.id, gfp); |
6056 | } | 6108 | } |
6057 | 6109 | ||
6058 | int nl80211_send_action(struct cfg80211_registered_device *rdev, | 6110 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
6059 | struct net_device *netdev, u32 nlpid, | 6111 | struct net_device *netdev, u32 nlpid, |
6060 | int freq, const u8 *buf, size_t len, gfp_t gfp) | 6112 | int freq, const u8 *buf, size_t len, gfp_t gfp) |
6061 | { | 6113 | { |
6062 | struct sk_buff *msg; | 6114 | struct sk_buff *msg; |
6063 | void *hdr; | 6115 | void *hdr; |
@@ -6067,7 +6119,7 @@ int nl80211_send_action(struct cfg80211_registered_device *rdev, | |||
6067 | if (!msg) | 6119 | if (!msg) |
6068 | return -ENOMEM; | 6120 | return -ENOMEM; |
6069 | 6121 | ||
6070 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION); | 6122 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME); |
6071 | if (!hdr) { | 6123 | if (!hdr) { |
6072 | nlmsg_free(msg); | 6124 | nlmsg_free(msg); |
6073 | return -ENOMEM; | 6125 | return -ENOMEM; |
@@ -6095,10 +6147,10 @@ int nl80211_send_action(struct cfg80211_registered_device *rdev, | |||
6095 | return -ENOBUFS; | 6147 | return -ENOBUFS; |
6096 | } | 6148 | } |
6097 | 6149 | ||
6098 | void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | 6150 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, |
6099 | struct net_device *netdev, u64 cookie, | 6151 | struct net_device *netdev, u64 cookie, |
6100 | const u8 *buf, size_t len, bool ack, | 6152 | const u8 *buf, size_t len, bool ack, |
6101 | gfp_t gfp) | 6153 | gfp_t gfp) |
6102 | { | 6154 | { |
6103 | struct sk_buff *msg; | 6155 | struct sk_buff *msg; |
6104 | void *hdr; | 6156 | void *hdr; |
@@ -6107,7 +6159,7 @@ void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | |||
6107 | if (!msg) | 6159 | if (!msg) |
6108 | return; | 6160 | return; |
6109 | 6161 | ||
6110 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION_TX_STATUS); | 6162 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME_TX_STATUS); |
6111 | if (!hdr) { | 6163 | if (!hdr) { |
6112 | nlmsg_free(msg); | 6164 | nlmsg_free(msg); |
6113 | return; | 6165 | return; |
@@ -6194,7 +6246,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
6194 | 6246 | ||
6195 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) | 6247 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) |
6196 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) | 6248 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) |
6197 | cfg80211_mlme_unregister_actions(wdev, notify->pid); | 6249 | cfg80211_mlme_unregister_socket(wdev, notify->pid); |
6198 | 6250 | ||
6199 | rcu_read_unlock(); | 6251 | rcu_read_unlock(); |
6200 | 6252 | ||
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 2ad7fbc7d9f1..30d2f939150d 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -74,13 +74,13 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
74 | struct net_device *dev, const u8 *mac_addr, | 74 | struct net_device *dev, const u8 *mac_addr, |
75 | struct station_info *sinfo, gfp_t gfp); | 75 | struct station_info *sinfo, gfp_t gfp); |
76 | 76 | ||
77 | int nl80211_send_action(struct cfg80211_registered_device *rdev, | 77 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
78 | struct net_device *netdev, u32 nlpid, int freq, | 78 | struct net_device *netdev, u32 nlpid, int freq, |
79 | const u8 *buf, size_t len, gfp_t gfp); | 79 | const u8 *buf, size_t len, gfp_t gfp); |
80 | void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | 80 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, |
81 | struct net_device *netdev, u64 cookie, | 81 | struct net_device *netdev, u64 cookie, |
82 | const u8 *buf, size_t len, bool ack, | 82 | const u8 *buf, size_t len, bool ack, |
83 | gfp_t gfp); | 83 | gfp_t gfp); |
84 | 84 | ||
85 | void | 85 | void |
86 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | 86 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 1eb24162be61..8d961cc4ae98 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -823,7 +823,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
823 | /* monitor can't bridge anyway */ | 823 | /* monitor can't bridge anyway */ |
824 | break; | 824 | break; |
825 | case NL80211_IFTYPE_UNSPECIFIED: | 825 | case NL80211_IFTYPE_UNSPECIFIED: |
826 | case __NL80211_IFTYPE_AFTER_LAST: | 826 | case NUM_NL80211_IFTYPES: |
827 | /* not happening */ | 827 | /* not happening */ |
828 | break; | 828 | break; |
829 | } | 829 | } |