aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-03-27 15:59:49 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:54:28 -0400
commita3b8b0569fbef725597f05278ec58083321f6e9d (patch)
treecb3beb05c841a9564a3fdd44d540570c7b89c9f6
parent53b46b8444f600cc1744521ea096ea0c5d494dd0 (diff)
nl80211: Add Michael MIC failure event
Define a new nl80211 event, NL80211_CMD_MICHAEL_MIC_FAILURE, to be used to notify user space about locally detected Michael MIC failures. This matches with the MLME-MICHAELMICFAILURE.indication() primitive. Since we do not actually have TSC in the skb anymore when mac80211_ev_michael_mic_failure() is called, that function is changed to take in the TSC as an optional parameter instead of as a requirement to include the TSC after the hdr field (which we did not really follow). For now, TSC is not included in the events from mac80211, but it could be added at some point. Signed-off-by: Jouni Malinen <j@w1.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/linux/nl80211.h28
-rw-r--r--include/net/cfg80211.h16
-rw-r--r--net/mac80211/event.c17
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/rx.c2
-rw-r--r--net/mac80211/wpa.c2
-rw-r--r--net/wireless/mlme.c10
-rw-r--r--net/wireless/nl80211.c40
-rw-r--r--net/wireless/nl80211.h5
9 files changed, 111 insertions, 11 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index cbe8ce3bf486..27f230f063b3 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -199,6 +199,14 @@
199 * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to 199 * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to
200 * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives). 200 * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives).
201 * 201 *
202 * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael
203 * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the
204 * event includes %NL80211_ATTR_MAC to describe the source MAC address of
205 * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key
206 * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and
207 * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this
208 * event matches with MLME-MICHAELMICFAILURE.indication() primitive
209 *
202 * @NL80211_CMD_MAX: highest used command number 210 * @NL80211_CMD_MAX: highest used command number
203 * @__NL80211_CMD_AFTER_LAST: internal use 211 * @__NL80211_CMD_AFTER_LAST: internal use
204 */ 212 */
@@ -260,6 +268,8 @@ enum nl80211_commands {
260 NL80211_CMD_DEAUTHENTICATE, 268 NL80211_CMD_DEAUTHENTICATE,
261 NL80211_CMD_DISASSOCIATE, 269 NL80211_CMD_DISASSOCIATE,
262 270
271 NL80211_CMD_MICHAEL_MIC_FAILURE,
272
263 /* add new commands above here */ 273 /* add new commands above here */
264 274
265 /* used to define NL80211_CMD_MAX below */ 275 /* used to define NL80211_CMD_MAX below */
@@ -408,6 +418,9 @@ enum nl80211_commands {
408 * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and 418 * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and
409 * %NL80211_CMD_DISASSOCIATE, u16 419 * %NL80211_CMD_DISASSOCIATE, u16
410 * 420 *
421 * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as
422 * a u32
423 *
411 * @NL80211_ATTR_MAX: highest attribute number currently defined 424 * @NL80211_ATTR_MAX: highest attribute number currently defined
412 * @__NL80211_ATTR_AFTER_LAST: internal use 425 * @__NL80211_ATTR_AFTER_LAST: internal use
413 */ 426 */
@@ -492,6 +505,8 @@ enum nl80211_attrs {
492 NL80211_ATTR_AUTH_TYPE, 505 NL80211_ATTR_AUTH_TYPE,
493 NL80211_ATTR_REASON_CODE, 506 NL80211_ATTR_REASON_CODE,
494 507
508 NL80211_ATTR_KEY_TYPE,
509
495 /* add attributes here, update the policy in nl80211.c */ 510 /* add attributes here, update the policy in nl80211.c */
496 511
497 __NL80211_ATTR_AFTER_LAST, 512 __NL80211_ATTR_AFTER_LAST,
@@ -1062,4 +1077,17 @@ enum nl80211_auth_type {
1062 NL80211_AUTHTYPE_FT, 1077 NL80211_AUTHTYPE_FT,
1063 NL80211_AUTHTYPE_NETWORK_EAP, 1078 NL80211_AUTHTYPE_NETWORK_EAP,
1064}; 1079};
1080
1081/**
1082 * enum nl80211_key_type - Key Type
1083 * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key
1084 * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key
1085 * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS)
1086 */
1087enum nl80211_key_type {
1088 NL80211_KEYTYPE_GROUP,
1089 NL80211_KEYTYPE_PAIRWISE,
1090 NL80211_KEYTYPE_PEERKEY,
1091};
1092
1065#endif /* __LINUX_NL80211_H */ 1093#endif /* __LINUX_NL80211_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ec33096fc655..f8bf0c86650b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -957,4 +957,20 @@ void cfg80211_hold_bss(struct cfg80211_bss *bss);
957 */ 957 */
958void cfg80211_unhold_bss(struct cfg80211_bss *bss); 958void cfg80211_unhold_bss(struct cfg80211_bss *bss);
959 959
960/**
961 * cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP)
962 * @dev: network device
963 * @addr: The source MAC address of the frame
964 * @key_type: The key type that the received frame used
965 * @key_id: Key identifier (0..3)
966 * @tsc: The TSC value of the frame that generated the MIC failure (6 octets)
967 *
968 * This function is called whenever the local MAC detects a MIC failure in a
969 * received frame. This matches with MLME-MICHAELMICFAILURE.indication()
970 * primitive.
971 */
972void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
973 enum nl80211_key_type key_type, int key_id,
974 const u8 *tsc);
975
960#endif /* __NET_CFG80211_H */ 976#endif /* __NET_CFG80211_H */
diff --git a/net/mac80211/event.c b/net/mac80211/event.c
index 0d95561c0ee0..f288d01a6344 100644
--- a/net/mac80211/event.c
+++ b/net/mac80211/event.c
@@ -12,12 +12,12 @@
12#include "ieee80211_i.h" 12#include "ieee80211_i.h"
13 13
14/* 14/*
15 * indicate a failed Michael MIC to userspace; the passed packet 15 * Indicate a failed Michael MIC to userspace. If the caller knows the TSC of
16 * (in the variable hdr) must be long enough to extract the TKIP 16 * the frame that generated the MIC failure (i.e., if it was provided by the
17 * fields like TSC 17 * driver or is still in the frame), it should provide that information.
18 */ 18 */
19void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, 19void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
20 struct ieee80211_hdr *hdr) 20 struct ieee80211_hdr *hdr, const u8 *tsc)
21{ 21{
22 union iwreq_data wrqu; 22 union iwreq_data wrqu;
23 char *buf = kmalloc(128, GFP_ATOMIC); 23 char *buf = kmalloc(128, GFP_ATOMIC);
@@ -34,8 +34,9 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke
34 kfree(buf); 34 kfree(buf);
35 } 35 }
36 36
37 /* 37 cfg80211_michael_mic_failure(sdata->dev, hdr->addr2,
38 * TODO: re-add support for sending MIC failure indication 38 (hdr->addr1[0] & 0x01) ?
39 * with all info via nl80211 39 NL80211_KEYTYPE_GROUP :
40 */ 40 NL80211_KEYTYPE_PAIRWISE,
41 keyidx, tsc);
41} 42}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e6ed78cb16b3..312347d102c8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1060,7 +1060,7 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
1060int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, 1060int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
1061 int rate, int erp, int short_preamble); 1061 int rate, int erp, int short_preamble);
1062void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, 1062void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
1063 struct ieee80211_hdr *hdr); 1063 struct ieee80211_hdr *hdr, const u8 *tsc);
1064void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); 1064void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata);
1065void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, 1065void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
1066 int encrypt); 1066 int encrypt);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5fa7aedd90ed..19c4b4589fee 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1932,7 +1932,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
1932 !ieee80211_is_auth(hdr->frame_control)) 1932 !ieee80211_is_auth(hdr->frame_control))
1933 goto ignore; 1933 goto ignore;
1934 1934
1935 mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr); 1935 mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL);
1936 ignore: 1936 ignore:
1937 dev_kfree_skb(rx->skb); 1937 dev_kfree_skb(rx->skb);
1938 rx->skb = NULL; 1938 rx->skb = NULL;
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 4f8bfea278f2..dcfae8884b86 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -122,7 +122,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
122 return RX_DROP_UNUSABLE; 122 return RX_DROP_UNUSABLE;
123 123
124 mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, 124 mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx,
125 (void *) skb->data); 125 (void *) skb->data, NULL);
126 return RX_DROP_UNUSABLE; 126 return RX_DROP_UNUSABLE;
127 } 127 }
128 128
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 33ff7cca496b..1407244a647e 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -43,3 +43,13 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
43 nl80211_send_disassoc(rdev, dev, buf, len); 43 nl80211_send_disassoc(rdev, dev, buf, len);
44} 44}
45EXPORT_SYMBOL(cfg80211_send_disassoc); 45EXPORT_SYMBOL(cfg80211_send_disassoc);
46
47void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
48 enum nl80211_key_type key_type, int key_id,
49 const u8 *tsc)
50{
51 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
52 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
53 nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc);
54}
55EXPORT_SYMBOL(cfg80211_michael_mic_failure);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 195424eee77d..1394115cde95 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3430,6 +3430,46 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
3430 NL80211_CMD_DISASSOCIATE); 3430 NL80211_CMD_DISASSOCIATE);
3431} 3431}
3432 3432
3433void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
3434 struct net_device *netdev, const u8 *addr,
3435 enum nl80211_key_type key_type, int key_id,
3436 const u8 *tsc)
3437{
3438 struct sk_buff *msg;
3439 void *hdr;
3440
3441 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
3442 if (!msg)
3443 return;
3444
3445 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
3446 if (!hdr) {
3447 nlmsg_free(msg);
3448 return;
3449 }
3450
3451 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3452 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
3453 if (addr)
3454 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
3455 NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type);
3456 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id);
3457 if (tsc)
3458 NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc);
3459
3460 if (genlmsg_end(msg, hdr) < 0) {
3461 nlmsg_free(msg);
3462 return;
3463 }
3464
3465 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL);
3466 return;
3467
3468 nla_put_failure:
3469 genlmsg_cancel(msg, hdr);
3470 nlmsg_free(msg);
3471}
3472
3433/* initialisation/exit functions */ 3473/* initialisation/exit functions */
3434 3474
3435int nl80211_init(void) 3475int nl80211_init(void)
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 55686fc264f0..e4b92cccd157 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -23,5 +23,10 @@ extern void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
23extern void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, 23extern void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
24 struct net_device *netdev, 24 struct net_device *netdev,
25 const u8 *buf, size_t len); 25 const u8 *buf, size_t len);
26extern void
27nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
28 struct net_device *netdev, const u8 *addr,
29 enum nl80211_key_type key_type,
30 int key_id, const u8 *tsc);
26 31
27#endif /* __NET_WIRELESS_NL80211_H */ 32#endif /* __NET_WIRELESS_NL80211_H */