Remove the GPL notification from files contributed by Jouni Malinen
[mech_eap.git] / wlantest / rx_data.c
1 /*
2  * Received Data frame processing
3  * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "utils/includes.h"
10 #include <linux/if_ether.h>
11
12 #include "utils/common.h"
13 #include "common/defs.h"
14 #include "common/ieee802_11_defs.h"
15 #include "wlantest.h"
16
17
18 static const char * data_stype(u16 stype)
19 {
20         switch (stype) {
21         case WLAN_FC_STYPE_DATA:
22                 return "DATA";
23         case WLAN_FC_STYPE_DATA_CFACK:
24                 return "DATA-CFACK";
25         case WLAN_FC_STYPE_DATA_CFPOLL:
26                 return "DATA-CFPOLL";
27         case WLAN_FC_STYPE_DATA_CFACKPOLL:
28                 return "DATA-CFACKPOLL";
29         case WLAN_FC_STYPE_NULLFUNC:
30                 return "NULLFUNC";
31         case WLAN_FC_STYPE_CFACK:
32                 return "CFACK";
33         case WLAN_FC_STYPE_CFPOLL:
34                 return "CFPOLL";
35         case WLAN_FC_STYPE_CFACKPOLL:
36                 return "CFACKPOLL";
37         case WLAN_FC_STYPE_QOS_DATA:
38                 return "QOSDATA";
39         case WLAN_FC_STYPE_QOS_DATA_CFACK:
40                 return "QOSDATA-CFACK";
41         case WLAN_FC_STYPE_QOS_DATA_CFPOLL:
42                 return "QOSDATA-CFPOLL";
43         case WLAN_FC_STYPE_QOS_DATA_CFACKPOLL:
44                 return "QOSDATA-CFACKPOLL";
45         case WLAN_FC_STYPE_QOS_NULL:
46                 return "QOS-NULL";
47         case WLAN_FC_STYPE_QOS_CFPOLL:
48                 return "QOS-CFPOLL";
49         case WLAN_FC_STYPE_QOS_CFACKPOLL:
50                 return "QOS-CFACKPOLL";
51         }
52         return "??";
53 }
54
55
56 static void rx_data_eth(struct wlantest *wt, const u8 *bssid,
57                         const u8 *sta_addr, const u8 *dst, const u8 *src,
58                         u16 ethertype, const u8 *data, size_t len, int prot,
59                         const u8 *peer_addr)
60 {
61         switch (ethertype) {
62         case ETH_P_PAE:
63                 rx_data_eapol(wt, dst, src, data, len, prot);
64                 break;
65         case ETH_P_IP:
66                 rx_data_ip(wt, bssid, sta_addr, dst, src, data, len,
67                            peer_addr);
68                 break;
69         case 0x890d:
70                 rx_data_80211_encap(wt, bssid, sta_addr, dst, src, data, len);
71                 break;
72         }
73 }
74
75
76 static void rx_data_process(struct wlantest *wt, const u8 *bssid,
77                             const u8 *sta_addr,
78                             const u8 *dst, const u8 *src,
79                             const u8 *data, size_t len, int prot,
80                             const u8 *peer_addr)
81 {
82         if (len == 0)
83                 return;
84
85         if (len >= 8 && os_memcmp(data, "\xaa\xaa\x03\x00\x00\x00", 6) == 0) {
86                 rx_data_eth(wt, bssid, sta_addr, dst, src,
87                             WPA_GET_BE16(data + 6), data + 8, len - 8, prot,
88                             peer_addr);
89                 return;
90         }
91
92         wpa_hexdump(MSG_DEBUG, "Unrecognized LLC", data, len > 8 ? 8 : len);
93 }
94
95
96 static void rx_data_bss_prot_group(struct wlantest *wt,
97                                    const struct ieee80211_hdr *hdr,
98                                    const u8 *qos, const u8 *dst, const u8 *src,
99                                    const u8 *data, size_t len)
100 {
101         struct wlantest_bss *bss;
102         int keyid;
103         u8 *decrypted;
104         size_t dlen;
105         u8 pn[6];
106
107         bss = bss_get(wt, hdr->addr2);
108         if (bss == NULL)
109                 return;
110         if (len < 4) {
111                 wpa_printf(MSG_INFO, "Too short group addressed data frame");
112                 return;
113         }
114
115         if (bss->group_cipher & (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP) &&
116             !(data[3] & 0x20)) {
117                     wpa_printf(MSG_INFO, "Expected TKIP/CCMP frame from "
118                                MACSTR " did not have ExtIV bit set to 1",
119                                MAC2STR(bss->bssid));
120                     return;
121         }
122
123         if (bss->group_cipher == WPA_CIPHER_TKIP) {
124                 if (data[3] & 0x1f) {
125                         wpa_printf(MSG_INFO, "TKIP frame from " MACSTR " used "
126                                    "non-zero reserved bit",
127                                    MAC2STR(bss->bssid));
128                 }
129                 if (data[1] != ((data[0] | 0x20) & 0x7f)) {
130                         wpa_printf(MSG_INFO, "TKIP frame from " MACSTR " used "
131                                    "incorrect WEPSeed[1] (was 0x%x, expected "
132                                    "0x%x)",
133                                    MAC2STR(bss->bssid), data[1],
134                                    (data[0] | 0x20) & 0x7f);
135                 }
136         } else if (bss->group_cipher == WPA_CIPHER_CCMP) {
137                 if (data[2] != 0 || (data[3] & 0x1f) != 0) {
138                         wpa_printf(MSG_INFO, "CCMP frame from " MACSTR " used "
139                                    "non-zero reserved bit",
140                                    MAC2STR(bss->bssid));
141                 }
142         }
143
144         keyid = data[3] >> 6;
145         if (bss->gtk_len[keyid] == 0 && bss->group_cipher != WPA_CIPHER_WEP40)
146         {
147                 wpa_printf(MSG_MSGDUMP, "No GTK known to decrypt the frame "
148                            "(A2=" MACSTR " KeyID=%d)",
149                            MAC2STR(hdr->addr2), keyid);
150                 return;
151         }
152
153         if (bss->group_cipher == WPA_CIPHER_TKIP)
154                 tkip_get_pn(pn, data);
155         else if (bss->group_cipher == WPA_CIPHER_WEP40)
156                 goto skip_replay_det;
157         else
158                 ccmp_get_pn(pn, data);
159         if (os_memcmp(pn, bss->rsc[keyid], 6) <= 0) {
160                 u16 seq_ctrl = le_to_host16(hdr->seq_ctrl);
161                 wpa_printf(MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR
162                            " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u",
163                            MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
164                            MAC2STR(hdr->addr3),
165                            WLAN_GET_SEQ_SEQ(seq_ctrl),
166                            WLAN_GET_SEQ_FRAG(seq_ctrl));
167                 wpa_hexdump(MSG_INFO, "RX PN", pn, 6);
168                 wpa_hexdump(MSG_INFO, "RSC", bss->rsc[keyid], 6);
169         }
170
171 skip_replay_det:
172         if (bss->group_cipher == WPA_CIPHER_TKIP)
173                 decrypted = tkip_decrypt(bss->gtk[keyid], hdr, data, len,
174                                          &dlen);
175         else if (bss->group_cipher == WPA_CIPHER_WEP40)
176                 decrypted = wep_decrypt(wt, hdr, data, len, &dlen);
177         else
178                 decrypted = ccmp_decrypt(bss->gtk[keyid], hdr, data, len,
179                                          &dlen);
180         if (decrypted) {
181                 rx_data_process(wt, bss->bssid, NULL, dst, src, decrypted,
182                                 dlen, 1, NULL);
183                 os_memcpy(bss->rsc[keyid], pn, 6);
184                 write_pcap_decrypted(wt, (const u8 *) hdr, 24 + (qos ? 2 : 0),
185                                      decrypted, dlen);
186         }
187         os_free(decrypted);
188 }
189
190
191 static void rx_data_bss_prot(struct wlantest *wt,
192                              const struct ieee80211_hdr *hdr, const u8 *qos,
193                              const u8 *dst, const u8 *src, const u8 *data,
194                              size_t len)
195 {
196         struct wlantest_bss *bss;
197         struct wlantest_sta *sta, *sta2;
198         int keyid;
199         u16 fc = le_to_host16(hdr->frame_control);
200         u8 *decrypted;
201         size_t dlen;
202         int tid;
203         u8 pn[6], *rsc;
204         struct wlantest_tdls *tdls = NULL;
205         const u8 *tk = NULL;
206
207         if (hdr->addr1[0] & 0x01) {
208                 rx_data_bss_prot_group(wt, hdr, qos, dst, src, data, len);
209                 return;
210         }
211
212         if (fc & WLAN_FC_TODS) {
213                 bss = bss_get(wt, hdr->addr1);
214                 if (bss == NULL)
215                         return;
216                 sta = sta_get(bss, hdr->addr2);
217                 if (sta)
218                         sta->counters[WLANTEST_STA_COUNTER_PROT_DATA_TX]++;
219         } else if (fc & WLAN_FC_FROMDS) {
220                 bss = bss_get(wt, hdr->addr2);
221                 if (bss == NULL)
222                         return;
223                 sta = sta_get(bss, hdr->addr1);
224         } else {
225                 bss = bss_get(wt, hdr->addr3);
226                 if (bss == NULL)
227                         return;
228                 sta = sta_find(bss, hdr->addr2);
229                 sta2 = sta_find(bss, hdr->addr1);
230                 if (sta == NULL || sta2 == NULL)
231                         return;
232                 dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list)
233                 {
234                         if ((tdls->init == sta && tdls->resp == sta2) ||
235                             (tdls->init == sta2 && tdls->resp == sta)) {
236                                 if (!tdls->link_up)
237                                         wpa_printf(MSG_DEBUG, "TDLS: Link not "
238                                                    "up, but Data frame seen");
239                                 tk = tdls->tpk.tk;
240                                 break;
241                         }
242                 }
243         }
244         if ((sta == NULL ||
245              (!sta->ptk_set && sta->pairwise_cipher != WPA_CIPHER_WEP40)) &&
246             tk == NULL) {
247                 wpa_printf(MSG_MSGDUMP, "No PTK known to decrypt the frame");
248                 return;
249         }
250
251         if (len < 4) {
252                 wpa_printf(MSG_INFO, "Too short encrypted data frame");
253                 return;
254         }
255
256         if (sta->pairwise_cipher & (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP) &&
257             !(data[3] & 0x20)) {
258                     wpa_printf(MSG_INFO, "Expected TKIP/CCMP frame from "
259                                MACSTR " did not have ExtIV bit set to 1",
260                                MAC2STR(src));
261                     return;
262         }
263
264         if (tk == NULL && sta->pairwise_cipher == WPA_CIPHER_TKIP) {
265                 if (data[3] & 0x1f) {
266                         wpa_printf(MSG_INFO, "TKIP frame from " MACSTR " used "
267                                    "non-zero reserved bit",
268                                    MAC2STR(hdr->addr2));
269                 }
270                 if (data[1] != ((data[0] | 0x20) & 0x7f)) {
271                         wpa_printf(MSG_INFO, "TKIP frame from " MACSTR " used "
272                                    "incorrect WEPSeed[1] (was 0x%x, expected "
273                                    "0x%x)",
274                                    MAC2STR(hdr->addr2), data[1],
275                                    (data[0] | 0x20) & 0x7f);
276                 }
277         } else if (tk || sta->pairwise_cipher == WPA_CIPHER_CCMP) {
278                 if (data[2] != 0 || (data[3] & 0x1f) != 0) {
279                         wpa_printf(MSG_INFO, "CCMP frame from " MACSTR " used "
280                                    "non-zero reserved bit",
281                                    MAC2STR(hdr->addr2));
282                 }
283         }
284
285         keyid = data[3] >> 6;
286         if (keyid != 0) {
287                 wpa_printf(MSG_INFO, "Unexpected non-zero KeyID %d in "
288                            "individually addressed Data frame from " MACSTR,
289                            keyid, MAC2STR(hdr->addr2));
290         }
291
292         if (qos)
293                 tid = qos[0] & 0x0f;
294         else
295                 tid = 0;
296         if (tk) {
297                 if (os_memcmp(hdr->addr2, tdls->init->addr, ETH_ALEN) == 0)
298                         rsc = tdls->rsc_init[tid];
299                 else
300                         rsc = tdls->rsc_resp[tid];
301         } else if (fc & WLAN_FC_TODS)
302                 rsc = sta->rsc_tods[tid];
303         else
304                 rsc = sta->rsc_fromds[tid];
305
306
307         if (tk == NULL && sta->pairwise_cipher == WPA_CIPHER_TKIP)
308                 tkip_get_pn(pn, data);
309         else if (sta->pairwise_cipher == WPA_CIPHER_WEP40)
310                 goto skip_replay_det;
311         else
312                 ccmp_get_pn(pn, data);
313         if (os_memcmp(pn, rsc, 6) <= 0) {
314                 u16 seq_ctrl = le_to_host16(hdr->seq_ctrl);
315                 wpa_printf(MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR
316                            " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u",
317                            MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
318                            MAC2STR(hdr->addr3),
319                            WLAN_GET_SEQ_SEQ(seq_ctrl),
320                            WLAN_GET_SEQ_FRAG(seq_ctrl));
321                 wpa_hexdump(MSG_INFO, "RX PN", pn, 6);
322                 wpa_hexdump(MSG_INFO, "RSC", rsc, 6);
323         }
324
325 skip_replay_det:
326         if (tk)
327                 decrypted = ccmp_decrypt(tk, hdr, data, len, &dlen);
328         else if (sta->pairwise_cipher == WPA_CIPHER_TKIP)
329                 decrypted = tkip_decrypt(sta->ptk.tk1, hdr, data, len, &dlen);
330         else if (sta->pairwise_cipher == WPA_CIPHER_WEP40)
331                 decrypted = wep_decrypt(wt, hdr, data, len, &dlen);
332         else
333                 decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data, len, &dlen);
334         if (decrypted) {
335                 u16 fc = le_to_host16(hdr->frame_control);
336                 const u8 *peer_addr = NULL;
337                 if (!(fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)))
338                         peer_addr = hdr->addr1;
339                 os_memcpy(rsc, pn, 6);
340                 rx_data_process(wt, bss->bssid, sta->addr, dst, src, decrypted,
341                                 dlen, 1, peer_addr);
342                 write_pcap_decrypted(wt, (const u8 *) hdr, 24 + (qos ? 2 : 0),
343                                      decrypted, dlen);
344         }
345         os_free(decrypted);
346 }
347
348
349 static void rx_data_bss(struct wlantest *wt, const struct ieee80211_hdr *hdr,
350                         const u8 *qos, const u8 *dst, const u8 *src,
351                         const u8 *data, size_t len)
352 {
353         u16 fc = le_to_host16(hdr->frame_control);
354         int prot = !!(fc & WLAN_FC_ISWEP);
355
356         if (qos) {
357                 u8 ack = (qos[0] & 0x60) >> 5;
358                 wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR
359                            " len=%u%s tid=%u%s%s",
360                            MAC2STR(src), MAC2STR(dst), (unsigned int) len,
361                            prot ? " Prot" : "", qos[0] & 0x0f,
362                            (qos[0] & 0x10) ? " EOSP" : "",
363                            ack == 0 ? "" :
364                            (ack == 1 ? " NoAck" :
365                             (ack == 2 ? " NoExpAck" : " BA")));
366         } else {
367                 wpa_printf(MSG_MSGDUMP, "BSS DATA: " MACSTR " -> " MACSTR
368                            " len=%u%s",
369                            MAC2STR(src), MAC2STR(dst), (unsigned int) len,
370                            prot ? " Prot" : "");
371         }
372
373         if (prot)
374                 rx_data_bss_prot(wt, hdr, qos, dst, src, data, len);
375         else {
376                 const u8 *bssid, *sta_addr, *peer_addr;
377                 if (fc & WLAN_FC_TODS) {
378                         bssid = hdr->addr1;
379                         sta_addr = hdr->addr2;
380                         peer_addr = NULL;
381                 } else if (fc & WLAN_FC_FROMDS) {
382                         bssid = hdr->addr2;
383                         sta_addr = hdr->addr1;
384                         peer_addr = NULL;
385                 } else {
386                         bssid = hdr->addr3;
387                         sta_addr = hdr->addr2;
388                         peer_addr = hdr->addr1;
389                 }
390                 rx_data_process(wt, bssid, sta_addr, dst, src, data, len, 0,
391                                 peer_addr);
392         }
393 }
394
395
396 static struct wlantest_tdls * get_tdls(struct wlantest *wt, const u8 *bssid,
397                                        const u8 *sta1_addr,
398                                        const u8 *sta2_addr)
399 {
400         struct wlantest_bss *bss;
401         struct wlantest_sta *sta1, *sta2;
402         struct wlantest_tdls *tdls;
403
404         bss = bss_find(wt, bssid);
405         if (bss == NULL)
406                 return NULL;
407         sta1 = sta_find(bss, sta1_addr);
408         if (sta1 == NULL)
409                 return NULL;
410         sta2 = sta_find(bss, sta2_addr);
411         if (sta2 == NULL)
412                 return NULL;
413
414         dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) {
415                 if ((tdls->init == sta1 && tdls->resp == sta2) ||
416                     (tdls->init == sta2 && tdls->resp == sta1))
417                         return tdls;
418         }
419
420         return NULL;
421 }
422
423
424 static void add_direct_link(struct wlantest *wt, const u8 *bssid,
425                             const u8 *sta1_addr, const u8 *sta2_addr)
426 {
427         struct wlantest_tdls *tdls;
428
429         tdls = get_tdls(wt, bssid, sta1_addr, sta2_addr);
430         if (tdls == NULL)
431                 return;
432
433         if (tdls->link_up)
434                 tdls->counters[WLANTEST_TDLS_COUNTER_VALID_DIRECT_LINK]++;
435         else
436                 tdls->counters[WLANTEST_TDLS_COUNTER_INVALID_DIRECT_LINK]++;
437 }
438
439
440 static void add_ap_path(struct wlantest *wt, const u8 *bssid,
441                         const u8 *sta1_addr, const u8 *sta2_addr)
442 {
443         struct wlantest_tdls *tdls;
444
445         tdls = get_tdls(wt, bssid, sta1_addr, sta2_addr);
446         if (tdls == NULL)
447                 return;
448
449         if (tdls->link_up)
450                 tdls->counters[WLANTEST_TDLS_COUNTER_INVALID_AP_PATH]++;
451         else
452                 tdls->counters[WLANTEST_TDLS_COUNTER_VALID_AP_PATH]++;
453 }
454
455
456 void rx_data(struct wlantest *wt, const u8 *data, size_t len)
457 {
458         const struct ieee80211_hdr *hdr;
459         u16 fc, stype;
460         size_t hdrlen;
461         const u8 *qos = NULL;
462
463         if (len < 24)
464                 return;
465
466         hdr = (const struct ieee80211_hdr *) data;
467         fc = le_to_host16(hdr->frame_control);
468         stype = WLAN_FC_GET_STYPE(fc);
469         hdrlen = 24;
470         if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
471             (WLAN_FC_TODS | WLAN_FC_FROMDS))
472                 hdrlen += ETH_ALEN;
473         if (stype & 0x08) {
474                 qos = data + hdrlen;
475                 hdrlen += 2;
476         }
477         if (len < hdrlen)
478                 return;
479         wt->rx_data++;
480
481         switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) {
482         case 0:
483                 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s IBSS DA=" MACSTR " SA="
484                            MACSTR " BSSID=" MACSTR,
485                            data_stype(WLAN_FC_GET_STYPE(fc)),
486                            fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
487                            fc & WLAN_FC_ISWEP ? " Prot" : "",
488                            MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
489                            MAC2STR(hdr->addr3));
490                 add_direct_link(wt, hdr->addr3, hdr->addr1, hdr->addr2);
491                 rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr2,
492                             data + hdrlen, len - hdrlen);
493                 break;
494         case WLAN_FC_FROMDS:
495                 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s FromDS DA=" MACSTR
496                            " BSSID=" MACSTR " SA=" MACSTR,
497                            data_stype(WLAN_FC_GET_STYPE(fc)),
498                            fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
499                            fc & WLAN_FC_ISWEP ? " Prot" : "",
500                            MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
501                            MAC2STR(hdr->addr3));
502                 add_ap_path(wt, hdr->addr2, hdr->addr1, hdr->addr3);
503                 rx_data_bss(wt, hdr, qos, hdr->addr1, hdr->addr3,
504                             data + hdrlen, len - hdrlen);
505                 break;
506         case WLAN_FC_TODS:
507                 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s ToDS BSSID=" MACSTR
508                            " SA=" MACSTR " DA=" MACSTR,
509                            data_stype(WLAN_FC_GET_STYPE(fc)),
510                            fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
511                            fc & WLAN_FC_ISWEP ? " Prot" : "",
512                            MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
513                            MAC2STR(hdr->addr3));
514                 add_ap_path(wt, hdr->addr1, hdr->addr3, hdr->addr2);
515                 rx_data_bss(wt, hdr, qos, hdr->addr3, hdr->addr2,
516                             data + hdrlen, len - hdrlen);
517                 break;
518         case WLAN_FC_TODS | WLAN_FC_FROMDS:
519                 wpa_printf(MSG_EXCESSIVE, "DATA %s%s%s WDS RA=" MACSTR " TA="
520                            MACSTR " DA=" MACSTR " SA=" MACSTR,
521                            data_stype(WLAN_FC_GET_STYPE(fc)),
522                            fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
523                            fc & WLAN_FC_ISWEP ? " Prot" : "",
524                            MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
525                            MAC2STR(hdr->addr3),
526                            MAC2STR((const u8 *) (hdr + 1)));
527                 break;
528         }
529 }