| 1 | --- a/ath/if_ath.c |
| 2 | +++ b/ath/if_ath.c |
| 3 | @@ -6457,6 +6457,7 @@ ath_rx_poll(struct net_device *dev, int |
| 4 | int type; |
| 5 | u_int phyerr; |
| 6 | u_int processed = 0, early_stop = 0; |
| 7 | + u_int mic_fail = 0; |
| 8 | |
| 9 | DPRINTF(sc, ATH_DEBUG_RX_PROC, "invoked\n"); |
| 10 | process_rx_again: |
| 11 | @@ -6558,24 +6559,8 @@ process_rx_again: |
| 12 | } |
| 13 | if (rs->rs_status & HAL_RXERR_MIC) { |
| 14 | sc->sc_stats.ast_rx_badmic++; |
| 15 | - /* |
| 16 | - * Do minimal work required to hand off |
| 17 | - * the 802.11 header for notification. |
| 18 | - */ |
| 19 | - /* XXX frag's and QoS frames */ |
| 20 | - if (len >= sizeof (struct ieee80211_frame)) { |
| 21 | - bus_dma_sync_single(sc->sc_bdev, |
| 22 | - bf->bf_skbaddr, len, |
| 23 | - BUS_DMA_FROMDEVICE); |
| 24 | -#if 0 |
| 25 | -/* XXX revalidate MIC, lookup ni to find VAP */ |
| 26 | - ieee80211_notify_michael_failure(ic, |
| 27 | - (struct ieee80211_frame *)skb->data, |
| 28 | - sc->sc_splitmic ? |
| 29 | - rs->rs_keyix - 32 : rs->rs_keyix |
| 30 | - ); |
| 31 | -#endif |
| 32 | - } |
| 33 | + mic_fail = 1; |
| 34 | + goto rx_accept; |
| 35 | } |
| 36 | /* |
| 37 | * Reject error frames if we have no vaps that |
| 38 | @@ -6614,8 +6599,9 @@ rx_accept: |
| 39 | /* |
| 40 | * Finished monitor mode handling, now reject |
| 41 | * error frames before passing to other vaps |
| 42 | + * Ignore MIC failures here, as we need to recheck them |
| 43 | */ |
| 44 | - if (rs->rs_status != 0) { |
| 45 | + if (rs->rs_status & ~(HAL_RXERR_MIC | HAL_RXERR_DECRYPT)) { |
| 46 | ieee80211_dev_kfree_skb(&skb); |
| 47 | goto rx_next; |
| 48 | } |
| 49 | @@ -6623,6 +6609,26 @@ rx_accept: |
| 50 | /* remove the CRC */ |
| 51 | skb_trim(skb, skb->len - IEEE80211_CRC_LEN); |
| 52 | |
| 53 | + if (mic_fail) { |
| 54 | + /* Ignore control frames which are reported with mic error */ |
| 55 | + if ((((struct ieee80211_frame *)skb->data)->i_fc[0] & |
| 56 | + IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) |
| 57 | + goto drop_micfail; |
| 58 | + |
| 59 | + ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) skb->data); |
| 60 | + |
| 61 | + if (ni && ni->ni_table) { |
| 62 | + ieee80211_check_mic(ni, skb); |
| 63 | + ieee80211_unref_node(&ni); |
| 64 | + } |
| 65 | + |
| 66 | +drop_micfail: |
| 67 | + dev_kfree_skb_any(skb); |
| 68 | + skb = NULL; |
| 69 | + mic_fail = 0; |
| 70 | + goto rx_next; |
| 71 | + } |
| 72 | + |
| 73 | /* |
| 74 | * From this point on we assume the frame is at least |
| 75 | * as large as ieee80211_frame_min; verify that. |
| 76 | @@ -6635,6 +6641,7 @@ rx_accept: |
| 77 | goto rx_next; |
| 78 | } |
| 79 | |
| 80 | + /* MIC failure. Drop the packet in any case */ |
| 81 | /* |
| 82 | * Normal receive. |
| 83 | */ |
| 84 | --- a/net80211/ieee80211_crypto_ccmp.c |
| 85 | +++ b/net80211/ieee80211_crypto_ccmp.c |
| 86 | @@ -73,7 +73,7 @@ static int ccmp_setkey(struct ieee80211_ |
| 87 | static int ccmp_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t); |
| 88 | static int ccmp_decap(struct ieee80211_key *, struct sk_buff *, int); |
| 89 | static int ccmp_enmic(struct ieee80211_key *, struct sk_buff *, int); |
| 90 | -static int ccmp_demic(struct ieee80211_key *, struct sk_buff *, int); |
| 91 | +static int ccmp_demic(struct ieee80211_key *, struct sk_buff *, int, int); |
| 92 | |
| 93 | static const struct ieee80211_cipher ccmp = { |
| 94 | .ic_name = "AES-CCM", |
| 95 | @@ -314,7 +314,7 @@ ccmp_decap(struct ieee80211_key *k, stru |
| 96 | * Verify and strip MIC from the frame. |
| 97 | */ |
| 98 | static int |
| 99 | -ccmp_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen) |
| 100 | +ccmp_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force) |
| 101 | { |
| 102 | return 1; |
| 103 | } |
| 104 | --- a/net80211/ieee80211_crypto.h |
| 105 | +++ b/net80211/ieee80211_crypto.h |
| 106 | @@ -145,7 +145,7 @@ struct ieee80211_cipher { |
| 107 | int (*ic_encap)(struct ieee80211_key *, struct sk_buff *, u_int8_t); |
| 108 | int (*ic_decap)(struct ieee80211_key *, struct sk_buff *, int); |
| 109 | int (*ic_enmic)(struct ieee80211_key *, struct sk_buff *, int); |
| 110 | - int (*ic_demic)(struct ieee80211_key *, struct sk_buff *, int); |
| 111 | + int (*ic_demic)(struct ieee80211_key *, struct sk_buff *, int, int); |
| 112 | }; |
| 113 | extern const struct ieee80211_cipher ieee80211_cipher_none; |
| 114 | |
| 115 | @@ -163,10 +163,10 @@ struct ieee80211_key *ieee80211_crypto_d |
| 116 | */ |
| 117 | static __inline int |
| 118 | ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k, |
| 119 | - struct sk_buff *skb, int hdrlen) |
| 120 | + struct sk_buff *skb, int hdrlen, int force) |
| 121 | { |
| 122 | const struct ieee80211_cipher *cip = k->wk_cipher; |
| 123 | - return (cip->ic_miclen > 0 ? cip->ic_demic(k, skb, hdrlen) : 1); |
| 124 | + return (cip->ic_miclen > 0 ? cip->ic_demic(k, skb, hdrlen, force) : 1); |
| 125 | } |
| 126 | |
| 127 | /* |
| 128 | --- a/net80211/ieee80211_crypto_none.c |
| 129 | +++ b/net80211/ieee80211_crypto_none.c |
| 130 | @@ -52,7 +52,7 @@ static int none_setkey(struct ieee80211_ |
| 131 | static int none_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t); |
| 132 | static int none_decap(struct ieee80211_key *, struct sk_buff *, int); |
| 133 | static int none_enmic(struct ieee80211_key *, struct sk_buff *, int); |
| 134 | -static int none_demic(struct ieee80211_key *, struct sk_buff *, int); |
| 135 | +static int none_demic(struct ieee80211_key *, struct sk_buff *, int, int); |
| 136 | |
| 137 | const struct ieee80211_cipher ieee80211_cipher_none = { |
| 138 | .ic_name = "NONE", |
| 139 | @@ -137,7 +137,7 @@ none_enmic(struct ieee80211_key *k, stru |
| 140 | } |
| 141 | |
| 142 | static int |
| 143 | -none_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen) |
| 144 | +none_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force) |
| 145 | { |
| 146 | struct ieee80211vap *vap = k->wk_private; |
| 147 | |
| 148 | --- a/net80211/ieee80211_crypto_tkip.c |
| 149 | +++ b/net80211/ieee80211_crypto_tkip.c |
| 150 | @@ -57,7 +57,7 @@ static int tkip_setkey(struct ieee80211_ |
| 151 | static int tkip_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t); |
| 152 | static int tkip_enmic(struct ieee80211_key *, struct sk_buff *, int); |
| 153 | static int tkip_decap(struct ieee80211_key *, struct sk_buff *, int); |
| 154 | -static int tkip_demic(struct ieee80211_key *, struct sk_buff *, int); |
| 155 | +static int tkip_demic(struct ieee80211_key *, struct sk_buff *, int, int); |
| 156 | |
| 157 | static const struct ieee80211_cipher tkip = { |
| 158 | .ic_name = "TKIP", |
| 159 | @@ -339,7 +339,7 @@ tkip_decap(struct ieee80211_key *k, stru |
| 160 | * Verify and strip MIC from the frame. |
| 161 | */ |
| 162 | static int |
| 163 | -tkip_demic(struct ieee80211_key *k, struct sk_buff *skb0, int hdrlen) |
| 164 | +tkip_demic(struct ieee80211_key *k, struct sk_buff *skb0, int hdrlen, int force) |
| 165 | { |
| 166 | struct tkip_ctx *ctx = k->wk_private; |
| 167 | struct sk_buff *skb; |
| 168 | @@ -355,7 +355,7 @@ tkip_demic(struct ieee80211_key *k, stru |
| 169 | } |
| 170 | wh = (struct ieee80211_frame *) skb0->data; |
| 171 | /* NB: skb left pointing at last in chain */ |
| 172 | - if (k->wk_flags & IEEE80211_KEY_SWMIC) { |
| 173 | + if ((k->wk_flags & IEEE80211_KEY_SWMIC) || force) { |
| 174 | struct ieee80211vap *vap = ctx->tc_vap; |
| 175 | u8 mic[IEEE80211_WEP_MICLEN]; |
| 176 | u8 mic0[IEEE80211_WEP_MICLEN]; |
| 177 | --- a/net80211/ieee80211_crypto_wep.c |
| 178 | +++ b/net80211/ieee80211_crypto_wep.c |
| 179 | @@ -54,7 +54,7 @@ static int wep_setkey(struct ieee80211_k |
| 180 | static int wep_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t); |
| 181 | static int wep_decap(struct ieee80211_key *, struct sk_buff *, int); |
| 182 | static int wep_enmic(struct ieee80211_key *, struct sk_buff *, int); |
| 183 | -static int wep_demic(struct ieee80211_key *, struct sk_buff *, int); |
| 184 | +static int wep_demic(struct ieee80211_key *, struct sk_buff *, int, int); |
| 185 | |
| 186 | static const struct ieee80211_cipher wep = { |
| 187 | .ic_name = "WEP", |
| 188 | @@ -244,7 +244,7 @@ wep_decap(struct ieee80211_key *k, struc |
| 189 | * Verify and strip MIC from the frame. |
| 190 | */ |
| 191 | static int |
| 192 | -wep_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen) |
| 193 | +wep_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force) |
| 194 | { |
| 195 | return 1; |
| 196 | } |
| 197 | --- a/net80211/ieee80211_input.c |
| 198 | +++ b/net80211/ieee80211_input.c |
| 199 | @@ -669,7 +669,7 @@ ieee80211_input(struct ieee80211vap * va |
| 200 | * Next strip any MSDU crypto bits. |
| 201 | */ |
| 202 | if (key != NULL && |
| 203 | - !ieee80211_crypto_demic(vap, key, skb, hdrspace)) { |
| 204 | + !ieee80211_crypto_demic(vap, key, skb, hdrspace, 0)) { |
| 205 | IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, |
| 206 | ni->ni_macaddr, "data", "%s", "demic error"); |
| 207 | IEEE80211_NODE_STAT(ni, rx_demicfail); |
| 208 | @@ -4293,6 +4293,47 @@ ath_eth_type_trans(struct sk_buff *skb, |
| 209 | } |
| 210 | #endif |
| 211 | |
| 212 | +/* |
| 213 | + * Process a frame w/ hw detected MIC failure. |
| 214 | + * The frame will be dropped in any case. |
| 215 | + */ |
| 216 | +void |
| 217 | +ieee80211_check_mic(struct ieee80211_node *ni, struct sk_buff *skb) |
| 218 | +{ |
| 219 | + struct ieee80211vap *vap = ni->ni_vap; |
| 220 | + |
| 221 | + struct ieee80211_frame *wh; |
| 222 | + struct ieee80211_key *key; |
| 223 | + int hdrspace; |
| 224 | + struct ieee80211com *ic = vap->iv_ic; |
| 225 | + |
| 226 | + if (skb->len < sizeof(struct ieee80211_frame_min)) { |
| 227 | + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, |
| 228 | + ni->ni_macaddr, NULL, |
| 229 | + "too short (1): len %u", skb->len); |
| 230 | + vap->iv_stats.is_rx_tooshort++; |
| 231 | + return; |
| 232 | + } |
| 233 | + |
| 234 | + wh = (struct ieee80211_frame *)skb->data; |
| 235 | + |
| 236 | + hdrspace = ieee80211_hdrspace(ic, wh); |
| 237 | + key = ieee80211_crypto_decap(ni, skb, hdrspace); |
| 238 | + if (key == NULL) { |
| 239 | + /* NB: stats+msgs handled in crypto_decap */ |
| 240 | + IEEE80211_NODE_STAT(ni, rx_wepfail); |
| 241 | + return; |
| 242 | + } |
| 243 | + |
| 244 | + if (!ieee80211_crypto_demic(vap, key, skb, hdrspace, 1)) { |
| 245 | + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, |
| 246 | + ni->ni_macaddr, "data", "%s", "demic error"); |
| 247 | + IEEE80211_NODE_STAT(ni, rx_demicfail); |
| 248 | + } |
| 249 | + return; |
| 250 | +} |
| 251 | +EXPORT_SYMBOL(ieee80211_check_mic); |
| 252 | + |
| 253 | #ifdef IEEE80211_DEBUG |
| 254 | /* |
| 255 | * Debugging support. |
| 256 | --- a/net80211/ieee80211_proto.h |
| 257 | +++ b/net80211/ieee80211_proto.h |
| 258 | @@ -90,6 +90,7 @@ int ieee80211_iserp_rateset(struct ieee8 |
| 259 | void ieee80211_set11gbasicrates(struct ieee80211_rateset *, enum ieee80211_phymode); |
| 260 | enum ieee80211_phymode ieee80211_get11gbasicrates(struct ieee80211_rateset *); |
| 261 | void ieee80211_send_pspoll(struct ieee80211_node *); |
| 262 | +void ieee80211_check_mic(struct ieee80211_node *, struct sk_buff *); |
| 263 | |
| 264 | /* |
| 265 | * Return the size of the 802.11 header for a management or data frame. |
| 266 | --- a/net80211/ieee80211_linux.c |
| 267 | +++ b/net80211/ieee80211_linux.c |
| 268 | @@ -337,8 +337,8 @@ ieee80211_notify_replay_failure(struct i |
| 269 | /* TODO: needed parameters: count, keyid, key type, src address, TSC */ |
| 270 | snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=" MAC_FMT ")", tag, |
| 271 | k->wk_keyix, |
| 272 | - IEEE80211_IS_MULTICAST(wh->i_addr1) ? "broad" : "uni", |
| 273 | - MAC_ADDR(wh->i_addr1)); |
| 274 | + IEEE80211_IS_MULTICAST(wh->i_addr2) ? "broad" : "uni", |
| 275 | + MAC_ADDR(wh->i_addr2)); |
| 276 | memset(&wrqu, 0, sizeof(wrqu)); |
| 277 | wrqu.data.length = strlen(buf); |
| 278 | wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); |
| 279 | --- a/net80211/ieee80211_output.c |
| 280 | +++ b/net80211/ieee80211_output.c |
| 281 | @@ -1074,13 +1074,16 @@ ieee80211_encap(struct ieee80211_node *n |
| 282 | cip = (struct ieee80211_cipher *) key->wk_cipher; |
| 283 | ciphdrsize = cip->ic_header; |
| 284 | tailsize += (cip->ic_trailer + cip->ic_miclen); |
| 285 | + |
| 286 | + /* add the 8 bytes MIC length */ |
| 287 | + if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) |
| 288 | + pktlen += IEEE80211_WEP_MICLEN; |
| 289 | } |
| 290 | |
| 291 | pdusize = vap->iv_fragthreshold - (hdrsize_nopad + ciphdrsize); |
| 292 | fragcnt = *framecnt = |
| 293 | - ((pktlen - (hdrsize_nopad + ciphdrsize)) / pdusize) + |
| 294 | - (((pktlen - (hdrsize_nopad + ciphdrsize)) % |
| 295 | - pdusize == 0) ? 0 : 1); |
| 296 | + ((pktlen - hdrsize_nopad) / pdusize) + |
| 297 | + (((pktlen - hdrsize_nopad) % pdusize == 0) ? 0 : 1); |
| 298 | |
| 299 | /* |
| 300 | * Allocate sk_buff for each subsequent fragment; First fragment |
| 301 | --- a/net80211/ieee80211_node.c |
| 302 | +++ b/net80211/ieee80211_node.c |
| 303 | @@ -2264,11 +2264,13 @@ ieee80211_node_leave(struct ieee80211_no |
| 304 | /* From this point onwards we can no longer find the node, |
| 305 | * so no more references are generated |
| 306 | */ |
| 307 | - ieee80211_remove_wds_addr(nt, ni->ni_macaddr); |
| 308 | - ieee80211_del_wds_node(nt, ni); |
| 309 | - IEEE80211_NODE_TABLE_LOCK_IRQ(nt); |
| 310 | - node_table_leave_locked(nt, ni); |
| 311 | - IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); |
| 312 | + if (nt) { |
| 313 | + ieee80211_remove_wds_addr(nt, ni->ni_macaddr); |
| 314 | + ieee80211_del_wds_node(nt, ni); |
| 315 | + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); |
| 316 | + node_table_leave_locked(nt, ni); |
| 317 | + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); |
| 318 | + } |
| 319 | |
| 320 | /* |
| 321 | * If node wasn't previously associated all |
| 322 | |