allow larger beacon interval values - useful for big mesh networks (patch by sven...
[openwrt.git] / package / madwifi / patches / 309-micfail_detect.patch
1 --- a/ath/if_ath.c
2 +++ b/ath/if_ath.c
3 @@ -6457,6 +6457,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@ -308,7 +308,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
This page took 0.04897 seconds and 5 git commands to generate.