aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */