aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-03-19 07:39:21 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-03-27 20:13:02 -0400
commit6039f6d23fe792d615da5449e9fa1c6b43caacf6 (patch)
treeaf94d1ad78ce1e82d76328ea9a67b351f0a9174b
parenta299542e97ec1939fdca7db6d3d82c0aa9bf8b9a (diff)
nl80211: Event notifications for MLME events
Add new nl80211 event notifications (and a new multicast group, "mlme") for informing user space about received and processed Authentication, (Re)Association Response, Deauthentication, and Disassociation frames in station and IBSS modes (i.e., MLME SAP interface primitives MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm, MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11 management frame since we already have the frame in that format and it includes all the needed information. This is the initial step in providing MLME SAP interface for authentication and association with nl80211. In other words, kernel code will act as the MLME and a user space application can control it as the SME. Signed-off-by: Jouni Malinen <j@w1.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/linux/nl80211.h36
-rw-r--r--include/net/cfg80211.h46
-rw-r--r--net/mac80211/mlme.c9
-rw-r--r--net/wireless/Makefile2
-rw-r--r--net/wireless/mlme.c46
-rw-r--r--net/wireless/nl80211.c72
-rw-r--r--net/wireless/nl80211.h12
7 files changed, 219 insertions, 4 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 3700d927e245..5ce68ae8314e 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -161,6 +161,25 @@
161 * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on 161 * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on
162 * to (%NL80211_ATTR_REG_ALPHA2). 162 * to (%NL80211_ATTR_REG_ALPHA2).
163 * 163 *
164 * @NL80211_CMD_AUTHENTICATE: authentication notification (on the "mlme"
165 * multicast group). This event reports reception of an Authentication
166 * frame in station and IBSS modes when the local MLME processed the
167 * frame, i.e., it was for the local STA and was received in correct
168 * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the
169 * MLME SAP interface (kernel providing MLME, userspace SME). The
170 * included NL80211_ATTR_FRAME attribute contains the management frame
171 * (including both the header and frame body, but not FCS).
172 * @NL80211_CMD_ASSOCIATE: association notification; like
173 * NL80211_CMD_AUTHENTICATE but for Association Response and Reassociation
174 * Response frames (similar to MLME-ASSOCIATE.confirm or
175 * MLME-REASSOCIATE.confirm primitives).
176 * @NL80211_CMD_DEAUTHENTICATE: deauthentication notification; like
177 * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to
178 * MLME-DEAUTHENTICATE.indication primitive).
179 * @NL80211_CMD_DISASSOCIATE: disassociation notification; like
180 * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to
181 * MLME-DISASSOCIATE.indication primitive).
182 *
164 * @NL80211_CMD_MAX: highest used command number 183 * @NL80211_CMD_MAX: highest used command number
165 * @__NL80211_CMD_AFTER_LAST: internal use 184 * @__NL80211_CMD_AFTER_LAST: internal use
166 */ 185 */
@@ -217,6 +236,11 @@ enum nl80211_commands {
217 236
218 NL80211_CMD_REG_CHANGE, 237 NL80211_CMD_REG_CHANGE,
219 238
239 NL80211_CMD_AUTHENTICATE,
240 NL80211_CMD_ASSOCIATE,
241 NL80211_CMD_DEAUTHENTICATE,
242 NL80211_CMD_DISASSOCIATE,
243
220 /* add new commands above here */ 244 /* add new commands above here */
221 245
222 /* used to define NL80211_CMD_MAX below */ 246 /* used to define NL80211_CMD_MAX below */
@@ -230,8 +254,11 @@ enum nl80211_commands {
230 */ 254 */
231#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS 255#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS
232#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE 256#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE
233
234#define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE 257#define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE
258#define NL80211_CMD_AUTHENTICATE NL80211_CMD_AUTHENTICATE
259#define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE
260#define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE
261#define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE
235 262
236/** 263/**
237 * enum nl80211_attrs - nl80211 netlink attributes 264 * enum nl80211_attrs - nl80211 netlink attributes
@@ -353,6 +380,10 @@ enum nl80211_commands {
353 * an array of command numbers (i.e. a mapping index to command number) 380 * an array of command numbers (i.e. a mapping index to command number)
354 * that the driver for the given wiphy supports. 381 * that the driver for the given wiphy supports.
355 * 382 *
383 * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header
384 * and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and
385 * NL80211_CMD_ASSOCIATE events
386 *
356 * @NL80211_ATTR_MAX: highest attribute number currently defined 387 * @NL80211_ATTR_MAX: highest attribute number currently defined
357 * @__NL80211_ATTR_AFTER_LAST: internal use 388 * @__NL80211_ATTR_AFTER_LAST: internal use
358 */ 389 */
@@ -432,6 +463,8 @@ enum nl80211_attrs {
432 463
433 NL80211_ATTR_SUPPORTED_COMMANDS, 464 NL80211_ATTR_SUPPORTED_COMMANDS,
434 465
466 NL80211_ATTR_FRAME,
467
435 /* add attributes here, update the policy in nl80211.c */ 468 /* add attributes here, update the policy in nl80211.c */
436 469
437 __NL80211_ATTR_AFTER_LAST, 470 __NL80211_ATTR_AFTER_LAST,
@@ -451,6 +484,7 @@ enum nl80211_attrs {
451#define NL80211_ATTR_IE NL80211_ATTR_IE 484#define NL80211_ATTR_IE NL80211_ATTR_IE
452#define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR 485#define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR
453#define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE 486#define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE
487#define NL80211_ATTR_FRAME NL80211_ATTR_FRAME
454 488
455#define NL80211_MAX_SUPP_RATES 32 489#define NL80211_MAX_SUPP_RATES 32
456#define NL80211_MAX_SUPP_REG_RULES 32 490#define NL80211_MAX_SUPP_REG_RULES 32
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 50f3fd9ff524..ad44016021b1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -807,4 +807,50 @@ void cfg80211_put_bss(struct cfg80211_bss *bss);
807 */ 807 */
808void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); 808void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss);
809 809
810/**
811 * cfg80211_send_rx_auth - notification of processed authentication
812 * @dev: network device
813 * @buf: authentication frame (header + body)
814 * @len: length of the frame data
815 *
816 * This function is called whenever an authentication has been processed in
817 * station mode.
818 */
819void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
820
821/**
822 * cfg80211_send_rx_assoc - notification of processed association
823 * @dev: network device
824 * @buf: (re)association response frame (header + body)
825 * @len: length of the frame data
826 *
827 * This function is called whenever a (re)association response has been
828 * processed in station mode.
829 */
830void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len);
831
832/**
833 * cfg80211_send_rx_deauth - notification of processed deauthentication
834 * @dev: network device
835 * @buf: deauthentication frame (header + body)
836 * @len: length of the frame data
837 *
838 * This function is called whenever deauthentication has been processed in
839 * station mode.
840 */
841void cfg80211_send_rx_deauth(struct net_device *dev, const u8 *buf,
842 size_t len);
843
844/**
845 * cfg80211_send_rx_disassoc - notification of processed disassociation
846 * @dev: network device
847 * @buf: disassociation response frame (header + body)
848 * @len: length of the frame data
849 *
850 * This function is called whenever disassociation has been processed in
851 * station mode.
852 */
853void cfg80211_send_rx_disassoc(struct net_device *dev, const u8 *buf,
854 size_t len);
855
810#endif /* __NET_CFG80211_H */ 856#endif /* __NET_CFG80211_H */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1f49b63d8dd2..6dc7a61bc18b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1085,11 +1085,13 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1085 case WLAN_AUTH_OPEN: 1085 case WLAN_AUTH_OPEN:
1086 case WLAN_AUTH_LEAP: 1086 case WLAN_AUTH_LEAP:
1087 ieee80211_auth_completed(sdata); 1087 ieee80211_auth_completed(sdata);
1088 cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
1088 break; 1089 break;
1089 case WLAN_AUTH_SHARED_KEY: 1090 case WLAN_AUTH_SHARED_KEY:
1090 if (ifmgd->auth_transaction == 4) 1091 if (ifmgd->auth_transaction == 4) {
1091 ieee80211_auth_completed(sdata); 1092 ieee80211_auth_completed(sdata);
1092 else 1093 cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
1094 } else
1093 ieee80211_auth_challenge(sdata, mgmt, len); 1095 ieee80211_auth_challenge(sdata, mgmt, len);
1094 break; 1096 break;
1095 } 1097 }
@@ -1125,6 +1127,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1125 1127
1126 ieee80211_set_disassoc(sdata, true, false, 0); 1128 ieee80211_set_disassoc(sdata, true, false, 0);
1127 ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED; 1129 ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED;
1130 cfg80211_send_rx_deauth(sdata->dev, (u8 *) mgmt, len);
1128} 1131}
1129 1132
1130 1133
@@ -1154,6 +1157,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1154 } 1157 }
1155 1158
1156 ieee80211_set_disassoc(sdata, false, false, reason_code); 1159 ieee80211_set_disassoc(sdata, false, false, reason_code);
1160 cfg80211_send_rx_disassoc(sdata->dev, (u8 *) mgmt, len);
1157} 1161}
1158 1162
1159 1163
@@ -1370,6 +1374,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1370 ieee80211_set_associated(sdata, changed); 1374 ieee80211_set_associated(sdata, changed);
1371 1375
1372 ieee80211_associated(sdata); 1376 ieee80211_associated(sdata);
1377 cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len);
1373} 1378}
1374 1379
1375 1380
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index c157b4d8014b..6d1e7b27b752 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -5,7 +5,7 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
5obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o 5obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o 6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
7 7
8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o 8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o
9cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o 9cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o
10 10
11ccflags-y += -D__CHECK_ENDIAN__ 11ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
new file mode 100644
index 000000000000..bec5721b6f99
--- /dev/null
+++ b/net/wireless/mlme.c
@@ -0,0 +1,46 @@
1/*
2 * cfg80211 MLME SAP interface
3 *
4 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
5 */
6
7#include <linux/kernel.h>
8#include <linux/module.h>
9#include <linux/netdevice.h>
10#include <linux/nl80211.h>
11#include <net/cfg80211.h>
12#include "core.h"
13#include "nl80211.h"
14
15void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
16{
17 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
18 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
19 nl80211_send_rx_auth(rdev, dev, buf, len);
20}
21EXPORT_SYMBOL(cfg80211_send_rx_auth);
22
23void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
24{
25 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
26 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
27 nl80211_send_rx_assoc(rdev, dev, buf, len);
28}
29EXPORT_SYMBOL(cfg80211_send_rx_assoc);
30
31void cfg80211_send_rx_deauth(struct net_device *dev, const u8 *buf, size_t len)
32{
33 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
34 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
35 nl80211_send_rx_deauth(rdev, dev, buf, len);
36}
37EXPORT_SYMBOL(cfg80211_send_rx_deauth);
38
39void cfg80211_send_rx_disassoc(struct net_device *dev, const u8 *buf,
40 size_t len)
41{
42 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
43 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
44 nl80211_send_rx_disassoc(rdev, dev, buf, len);
45}
46EXPORT_SYMBOL(cfg80211_send_rx_disassoc);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a3ecf8d73898..c034c2418cb3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2830,6 +2830,9 @@ static struct genl_ops nl80211_ops[] = {
2830 .dumpit = nl80211_dump_scan, 2830 .dumpit = nl80211_dump_scan,
2831 }, 2831 },
2832}; 2832};
2833static struct genl_multicast_group nl80211_mlme_mcgrp = {
2834 .name = "mlme",
2835};
2833 2836
2834/* multicast groups */ 2837/* multicast groups */
2835static struct genl_multicast_group nl80211_config_mcgrp = { 2838static struct genl_multicast_group nl80211_config_mcgrp = {
@@ -2975,6 +2978,71 @@ nla_put_failure:
2975 nlmsg_free(msg); 2978 nlmsg_free(msg);
2976} 2979}
2977 2980
2981static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
2982 struct net_device *netdev,
2983 const u8 *buf, size_t len,
2984 enum nl80211_commands cmd)
2985{
2986 struct sk_buff *msg;
2987 void *hdr;
2988
2989 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
2990 if (!msg)
2991 return;
2992
2993 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
2994 if (!hdr) {
2995 nlmsg_free(msg);
2996 return;
2997 }
2998
2999 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3000 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
3001 NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf);
3002
3003 if (genlmsg_end(msg, hdr) < 0) {
3004 nlmsg_free(msg);
3005 return;
3006 }
3007
3008 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL);
3009 return;
3010
3011 nla_put_failure:
3012 genlmsg_cancel(msg, hdr);
3013 nlmsg_free(msg);
3014}
3015
3016void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
3017 struct net_device *netdev, const u8 *buf, size_t len)
3018{
3019 nl80211_send_mlme_event(rdev, netdev, buf, len,
3020 NL80211_CMD_AUTHENTICATE);
3021}
3022
3023void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
3024 struct net_device *netdev, const u8 *buf,
3025 size_t len)
3026{
3027 nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE);
3028}
3029
3030void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev,
3031 struct net_device *netdev, const u8 *buf,
3032 size_t len)
3033{
3034 nl80211_send_mlme_event(rdev, netdev, buf, len,
3035 NL80211_CMD_DEAUTHENTICATE);
3036}
3037
3038void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev,
3039 struct net_device *netdev, const u8 *buf,
3040 size_t len)
3041{
3042 nl80211_send_mlme_event(rdev, netdev, buf, len,
3043 NL80211_CMD_DISASSOCIATE);
3044}
3045
2978/* initialisation/exit functions */ 3046/* initialisation/exit functions */
2979 3047
2980int nl80211_init(void) 3048int nl80211_init(void)
@@ -3003,6 +3071,10 @@ int nl80211_init(void)
3003 if (err) 3071 if (err)
3004 goto err_out; 3072 goto err_out;
3005 3073
3074 err = genl_register_mc_group(&nl80211_fam, &nl80211_mlme_mcgrp);
3075 if (err)
3076 goto err_out;
3077
3006 return 0; 3078 return 0;
3007 err_out: 3079 err_out:
3008 genl_unregister_family(&nl80211_fam); 3080 genl_unregister_family(&nl80211_fam);
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 5b5fe1339de0..b77af4ab80be 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -11,5 +11,17 @@ extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
11extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, 11extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
12 struct net_device *netdev); 12 struct net_device *netdev);
13extern void nl80211_send_reg_change_event(struct regulatory_request *request); 13extern void nl80211_send_reg_change_event(struct regulatory_request *request);
14extern void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
15 struct net_device *netdev,
16 const u8 *buf, size_t len);
17extern void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
18 struct net_device *netdev,
19 const u8 *buf, size_t len);
20extern void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev,
21 struct net_device *netdev,
22 const u8 *buf, size_t len);
23extern void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev,
24 struct net_device *netdev,
25 const u8 *buf, size_t len);
14 26
15#endif /* __NET_WIRELESS_NL80211_H */ 27#endif /* __NET_WIRELESS_NL80211_H */