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