diff options
-rw-r--r-- | include/linux/nl80211.h | 28 | ||||
-rw-r--r-- | include/net/cfg80211.h | 16 | ||||
-rw-r--r-- | net/mac80211/event.c | 17 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/rx.c | 2 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 2 | ||||
-rw-r--r-- | net/wireless/mlme.c | 10 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 40 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 5 |
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 | */ | ||
1087 | enum 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 | */ |
958 | void cfg80211_unhold_bss(struct cfg80211_bss *bss); | 958 | void 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 | */ | ||
972 | void 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 | */ |
19 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, | 19 | void 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, | |||
1060 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | 1060 | int 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); |
1062 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, | 1062 | void 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); |
1064 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); | 1064 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); |
1065 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | 1065 | void 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 | } |
45 | EXPORT_SYMBOL(cfg80211_send_disassoc); | 45 | EXPORT_SYMBOL(cfg80211_send_disassoc); |
46 | |||
47 | void 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 | } | ||
55 | EXPORT_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 | ||
3433 | void 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 | ||
3435 | int nl80211_init(void) | 3475 | int 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, | |||
23 | extern void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | 23 | extern 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); |
26 | extern void | ||
27 | nl80211_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 */ |