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