1 /*
2 * Packet dump helper functions
3 *
4 * Copyright (C) 2020, Broadcom.
5 *
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
11 *
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
19 *
20 *
21 * <<Broadcom-WL-IPTag/Open:>>
22 *
23 * $Id$
24 */
25
26 #include <typedefs.h>
27 #include <ethernet.h>
28 #include <bcmutils.h>
29 #include <bcmevent.h>
30 #include <bcmendian.h>
31 #include <bcmtlv.h>
32 #include <dngl_stats.h>
33 #include <dhd.h>
34 #include <dhd_dbg.h>
35 #include <bcmip.h>
36 #include <bcmudp.h>
37 #include <bcmdhcp.h>
38 #include <bcmarp.h>
39 #include <bcmicmp.h>
40 #include <dhd_linux_pktdump.h>
41 #include <dhd_config.h>
42 #include <wl_android.h>
43
44 #define DHD_PKTDUMP(arg) printk arg
45 #define DHD_PKTDUMP_MEM(arg) printk arg
46 #define PACKED_STRUCT __attribute__ ((packed))
47
48 #define EAPOL_HDR_LEN 4
49
50 /* EAPOL types */
51 #define EAP_PACKET 0
52 #define EAPOL_START 1
53 #define EAPOL_LOGOFF 2
54 #define EAPOL_KEY 3
55 #define EAPOL_ASF 4
56
57 /* EAPOL-Key types */
58 #define EAPOL_RC4_KEY 1
59 #define EAPOL_WPA2_KEY 2 /* 802.11i/WPA2 */
60 #define EAPOL_WPA_KEY 254 /* WPA */
61
62 /* EAPOL-Key header field size */
63 #define AKW_BLOCK_LEN 8
64 #define WPA_KEY_REPLAY_LEN 8
65 #define WPA_KEY_NONCE_LEN 32
66 #define WPA_KEY_IV_LEN 16
67 #define WPA_KEY_RSC_LEN 8
68 #define WPA_KEY_ID_LEN 8
69 #define WPA_KEY_MIC_LEN 16
70 #define WPA_MAX_KEY_SIZE 32
71 #define WPA_KEY_DATA_LEN (WPA_MAX_KEY_SIZE + AKW_BLOCK_LEN)
72
73 /* Key information bit */
74 #define KEYINFO_TYPE_MASK (1 << 3)
75 #define KEYINFO_INSTALL_MASK (1 << 6)
76 #define KEYINFO_KEYACK_MASK (1 << 7)
77 #define KEYINFO_KEYMIC_MASK (1 << 8)
78 #define KEYINFO_SECURE_MASK (1 << 9)
79 #define KEYINFO_ERROR_MASK (1 << 10)
80 #define KEYINFO_REQ_MASK (1 << 11)
81
82 /* EAP Code */
83 #define EAP_CODE_REQUEST 1 /* Request */
84 #define EAP_CODE_RESPONSE 2 /* Response */
85 #define EAP_CODE_SUCCESS 3 /* Success */
86 #define EAP_CODE_FAILURE 4 /* Failure */
87
88 /* EAP Type */
89 #define EAP_TYPE_RSVD 0 /* Reserved */
90 #define EAP_TYPE_IDENT 1 /* Identify */
91 #define EAP_TYPE_NOTI 2 /* Notification */
92 #define EAP_TYPE_TLS 13 /* EAP-TLS */
93 #define EAP_TYPE_LEAP 17 /* Cisco-LEAP */
94 #define EAP_TYPE_TTLS 21 /* EAP-TTLS */
95 #define EAP_TYPE_AKA 23 /* EAP-AKA */
96 #define EAP_TYPE_PEAP 25 /* EAP-PEAP */
97 #define EAP_TYPE_FAST 43 /* EAP-FAST */
98 #define EAP_TYPE_PSK 47 /* EAP-PSK */
99 #define EAP_TYPE_AKAP 50 /* EAP-AKA' */
100 #define EAP_TYPE_EXP 254 /* Reserved for Expended Type */
101
102 /* WSC */
103 #define EAP_HDR_LEN 5
104 #define EAP_WSC_NONCE_OFFSET 10
105 #define EAP_WSC_DATA_OFFSET (OFFSETOF(eap_wsc_fmt_t, data))
106 #define EAP_WSC_MIN_DATA_LEN ((EAP_HDR_LEN) + (EAP_WSC_DATA_OFFSET))
107 #define WFA_VID "\x00\x37\x2A" /* WFA SMI code */
108 #define WFA_VID_LEN 3 /* WFA VID length */
109 #define WFA_VTYPE 1u /* WFA Vendor type */
110
111 /* WSC opcode */
112 #define WSC_OPCODE_UPNP 0
113 #define WSC_OPCODE_START 1
114 #define WSC_OPCODE_ACK 2
115 #define WSC_OPCODE_NACK 3
116 #define WSC_OPCODE_MSG 4
117 #define WSC_OPCODE_DONE 5
118 #define WSC_OPCODE_FRAG_ACK 6
119
120 /* WSC flag */
121 #define WSC_FLAG_MF 1 /* more fragements */
122 #define WSC_FLAG_LF 2 /* length field */
123
124 /* WSC message code */
125 #define WSC_ATTR_MSG 0x1022
126 #define WSC_MSG_M1 0x04
127 #define WSC_MSG_M2 0x05
128 #define WSC_MSG_M3 0x07
129 #define WSC_MSG_M4 0x08
130 #define WSC_MSG_M5 0x09
131 #define WSC_MSG_M6 0x0A
132 #define WSC_MSG_M7 0x0B
133 #define WSC_MSG_M8 0x0C
134
135 /* Debug prints */
136 typedef enum pkt_cnt_type {
137 PKT_CNT_TYPE_INVALID = 0,
138 PKT_CNT_TYPE_ARP = 1,
139 PKT_CNT_TYPE_DNS = 2,
140 PKT_CNT_TYPE_MAX = 3
141 } pkt_cnt_type_t;
142
143 typedef struct pkt_cnt {
144 uint32 tx_cnt;
145 uint32 tx_err_cnt;
146 uint32 rx_cnt;
147 } pkt_cnt_t;
148
149 typedef struct pkt_cnt_log {
150 bool enabled;
151 uint16 reason;
152 timer_list_compat_t pktcnt_timer;
153 pkt_cnt_t arp_cnt;
154 pkt_cnt_t dns_cnt;
155 } pkt_cnts_log_t;
156
157 #define PKT_CNT_TIMER_INTERNVAL_MS 5000 /* packet count timeout(ms) */
158 #define PKT_CNT_RSN_VALID(rsn) \
159 (((rsn) > (PKT_CNT_RSN_INVALID)) && ((rsn) < (PKT_CNT_RSN_MAX)))
160
161 #ifdef DHD_PKTDUMP_ROAM
162 static const char pkt_cnt_msg[][20] = {
163 "INVALID",
164 "ROAM_SUCCESS",
165 "GROUP_KEY_UPDATE",
166 "CONNECT_SUCCESS",
167 "INVALID"
168 };
169 #endif
170
171 static const char tx_pktfate[][30] = {
172 "TX_PKT_FATE_ACKED", /* 0: WLFC_CTL_PKTFLAG_DISCARD */
173 "TX_PKT_FATE_FW_QUEUED", /* 1: WLFC_CTL_PKTFLAG_D11SUPPRESS */
174 "TX_PKT_FATE_FW_QUEUED", /* 2: WLFC_CTL_PKTFLAG_WLSUPPRESS */
175 "TX_PKT_FATE_FW_DROP_INVALID", /* 3: WLFC_CTL_PKTFLAG_TOSSED_BYWLC */
176 "TX_PKT_FATE_SENT", /* 4: WLFC_CTL_PKTFLAG_DISCARD_NOACK */
177 "TX_PKT_FATE_FW_DROP_OTHER", /* 5: WLFC_CTL_PKTFLAG_SUPPRESS_ACKED */
178 "TX_PKT_FATE_FW_DROP_EXPTIME", /* 6: WLFC_CTL_PKTFLAG_EXPIRED */
179 "TX_PKT_FATE_FW_DROP_OTHER", /* 7: WLFC_CTL_PKTFLAG_DROPPED */
180 "TX_PKT_FATE_FW_PKT_FREE", /* 8: WLFC_CTL_PKTFLAG_MKTFREE */
181 };
182
183 #define DBGREPLAY " Replay Counter: %02x%02x%02x%02x%02x%02x%02x%02x"
184 #define REPLAY_FMT(key) ((const eapol_key_hdr_t *)(key))->replay[0], \
185 ((const eapol_key_hdr_t *)(key))->replay[1], \
186 ((const eapol_key_hdr_t *)(key))->replay[2], \
187 ((const eapol_key_hdr_t *)(key))->replay[3], \
188 ((const eapol_key_hdr_t *)(key))->replay[4], \
189 ((const eapol_key_hdr_t *)(key))->replay[5], \
190 ((const eapol_key_hdr_t *)(key))->replay[6], \
191 ((const eapol_key_hdr_t *)(key))->replay[7]
192 #define TXFATE_FMT " TX_PKTHASH:0x%X TX_PKT_FATE:%s"
193 #define TX_PKTHASH(pkthash) ((pkthash) ? (*pkthash) : (0))
194 #define TX_FATE_STR(fate) (((*fate) <= (WLFC_CTL_PKTFLAG_MKTFREE)) ? \
195 (tx_pktfate[(*fate)]) : "TX_PKT_FATE_FW_DROP_OTHER")
196 #define TX_FATE(fate) ((fate) ? (TX_FATE_STR(fate)) : "N/A")
197 #define TX_FATE_ACKED(fate) ((fate) ? ((*fate) == (WLFC_CTL_PKTFLAG_DISCARD)) : (0))
198
199 #define EAP_PRINT(x, args...) \
200 do { \
201 if (dump_msg_level & DUMP_EAPOL_VAL) { \
202 if (tx) { \
203 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] 802_1X " x " [TX] : (%s) %s (%s)"TXFATE_FMT"\n", \
204 ifname, ## args, \
205 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
206 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
207 } else { \
208 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] 802_1X " x " [RX] : (%s) %s (%s)\n", \
209 ifname, ## args, \
210 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf)); \
211 } \
212 } \
213 } while (0)
214
215 #define EAP_PRINT_REPLAY(x, args...) \
216 do { \
217 if (dump_msg_level & DUMP_EAPOL_VAL) { \
218 if (tx) { \
219 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] 802_1X " x " [TX] : (%s) %s (%s)"DBGREPLAY TXFATE_FMT"\n", \
220 ifname, ## args, \
221 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
222 REPLAY_FMT(eap_key), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
223 } else { \
224 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] 802_1X " x " [RX] : (%s) %s (%s)"DBGREPLAY"\n", \
225 ifname, ## args, \
226 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
227 REPLAY_FMT(eap_key))); \
228 } \
229 } \
230 } while (0)
231
232 #define EAP_PRINT_OTHER(x, args...) \
233 do { \
234 if (dump_msg_level & DUMP_EAPOL_VAL) { \
235 if (tx) { \
236 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] 802_1X " x " [TX] : (%s) %s (%s) " \
237 "ver %d, type %d"TXFATE_FMT"\n", \
238 ifname, ## args, \
239 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
240 eapol_hdr->version, eapol_hdr->type, \
241 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
242 } else { \
243 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] 802_1X " x " [RX] : (%s) %s (%s) " \
244 "ver %d, type %d\n", \
245 ifname, ## args, \
246 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
247 eapol_hdr->version, eapol_hdr->type)); \
248 } \
249 } \
250 } while (0)
251
252 #define EAP_PRINT_OTHER_4WAY(x, args...) \
253 do { \
254 if (dump_msg_level & DUMP_EAPOL_VAL) { \
255 if (tx) { \
256 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] 802_1X " x " [TX] : (%s) %s (%s) " \
257 "ver %d type %d keytype %d keyinfo 0x%02X"TXFATE_FMT"\n", \
258 ifname, ## args, \
259 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
260 eapol_hdr->version, eapol_hdr->type, eap_key->type, \
261 (uint32)hton16(eap_key->key_info), \
262 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
263 } else { \
264 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] 802_1X " x " [RX] : (%s) %s (%s) " \
265 "ver %d type %d keytype %d keyinfo 0x%02X\n", \
266 ifname, ## args, \
267 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
268 eapol_hdr->version, eapol_hdr->type, eap_key->type, \
269 (uint32)hton16(eap_key->key_info))); \
270 } \
271 } \
272 } while (0)
273
274 #define UDP_PORT_DNS 53 /* UDP DNS port */
275
276 /* EAPOL header */
277 typedef struct eapol_header {
278 struct ether_header eth; /* 802.3/Ethernet header */
279 uint8 version; /* EAPOL protocol version */
280 uint8 type; /* EAPOL type */
281 uint16 length; /* Length of body */
282 uint8 body[1]; /* Body (optional) */
283 } PACKED_STRUCT eapol_header_t;
284
285 /* EAP header */
286 typedef struct eap_header_fmt {
287 uint8 code;
288 uint8 id;
289 uint16 len;
290 uint8 type;
291 uint8 data[1];
292 } PACKED_STRUCT eap_header_fmt_t;
293
294 /* WSC EAP format */
295 typedef struct eap_wsc_fmt {
296 uint8 oui[3];
297 uint32 ouitype;
298 uint8 opcode;
299 uint8 flags;
300 uint8 data[1];
301 } PACKED_STRUCT eap_wsc_fmt_t;
302
303 /* EAPOL-Key */
304 typedef struct eapol_key_hdr {
305 uint8 type; /* Key Descriptor Type */
306 uint16 key_info; /* Key Information (unaligned) */
307 uint16 key_len; /* Key Length (unaligned) */
308 uint8 replay[WPA_KEY_REPLAY_LEN]; /* Replay Counter */
309 uint8 nonce[WPA_KEY_NONCE_LEN]; /* Nonce */
310 uint8 iv[WPA_KEY_IV_LEN]; /* Key IV */
311 uint8 rsc[WPA_KEY_RSC_LEN]; /* Key RSC */
312 uint8 id[WPA_KEY_ID_LEN]; /* WPA:Key ID, 802.11i/WPA2: Reserved */
313 uint8 mic[WPA_KEY_MIC_LEN]; /* Key MIC */
314 uint16 data_len; /* Key Data Length */
315 uint8 data[WPA_KEY_DATA_LEN]; /* Key data */
316 } PACKED_STRUCT eapol_key_hdr_t;
317
318 typedef struct hdr_fmt {
319 struct ipv4_hdr iph;
320 struct bcmudp_hdr udph;
321 } PACKED_STRUCT hdr_fmt_t;
322
323 msg_eapol_t
dhd_is_4way_msg(uint8 * pktdata)324 dhd_is_4way_msg(uint8 *pktdata)
325 {
326 eapol_header_t *eapol_hdr;
327 eapol_key_hdr_t *eap_key;
328 msg_eapol_t type = EAPOL_OTHER;
329 bool pair, ack, mic, kerr, req, sec, install;
330 uint16 key_info;
331
332 if (!pktdata) {
333 DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__));
334 return type;
335 }
336
337 eapol_hdr = (eapol_header_t *)pktdata;
338 eap_key = (eapol_key_hdr_t *)(eapol_hdr->body);
339 if (eap_key->type != EAPOL_WPA2_KEY && eap_key->type != EAPOL_WPA_KEY) {
340 return type;
341 }
342
343 key_info = hton16(eap_key->key_info);
344 pair = !!(key_info & KEYINFO_TYPE_MASK);
345 ack = !!(key_info & KEYINFO_KEYACK_MASK);
346 mic = !!(key_info & KEYINFO_KEYMIC_MASK);
347 kerr = !!(key_info & KEYINFO_ERROR_MASK);
348 req = !!(key_info & KEYINFO_REQ_MASK);
349 sec = !!(key_info & KEYINFO_SECURE_MASK);
350 install = !!(key_info & KEYINFO_INSTALL_MASK);
351
352 if (eap_key->type == EAPOL_WPA2_KEY) {
353 if (pair && !install && ack && !mic && !sec && !kerr && !req) {
354 type = EAPOL_4WAY_M1;
355 } else if (pair && !install && !ack && mic && !sec && !kerr && !req) {
356 type = EAPOL_4WAY_M2;
357 } else if (pair && ack && mic && sec && !kerr && !req) {
358 type = EAPOL_4WAY_M3;
359 } else if (pair && !install && !ack && mic && sec && !req && !kerr) {
360 type = EAPOL_4WAY_M4;
361 } else if (!pair && !install && ack && mic && sec && !req && !kerr) {
362 type = EAPOL_GROUPKEY_M1;
363 } else if (!pair && !install && !ack && mic && sec && !req && !kerr) {
364 type = EAPOL_GROUPKEY_M2;
365 } else {
366 type = EAPOL_OTHER;
367 if (dump_msg_level & DUMP_EAPOL_VAL) {
368 printf("WPA2: key_info=0x%x, pair=%d, ack=%d, mic=%d, sec=%d, kerr=%d, req=%d\n",
369 key_info, pair, ack, mic, sec, kerr, req);
370 }
371 }
372 }
373 else if (eap_key->type == EAPOL_WPA_KEY) {
374 if (pair && !install && ack && !mic && !sec && !kerr && !req) {
375 type = EAPOL_4WAY_M1;
376 } else if (pair && !install && !ack && mic && !sec && !kerr && !req && eap_key->data_len) {
377 type = EAPOL_4WAY_M2;
378 } else if (pair && install && ack && mic && !sec && !kerr && !req) {
379 type = EAPOL_4WAY_M3;
380 } else if (pair && !install && !ack && mic && !sec && !req && !kerr) {
381 type = EAPOL_4WAY_M4;
382 } else if (!pair && !install && ack && mic && sec && !req && !kerr) {
383 type = EAPOL_GROUPKEY_M1;
384 } else if (!pair && !install && !ack && mic && sec && !req && !kerr) {
385 type = EAPOL_GROUPKEY_M2;
386 } else {
387 type = EAPOL_OTHER;
388 if (dump_msg_level & DUMP_EAPOL_VAL) {
389 printf("WPA: key_info=0x%x, pair=%d, ack=%d, mic=%d, sec=%d, kerr=%d, req=%d\n",
390 key_info, pair, ack, mic, sec, kerr, req);
391 }
392 }
393 }
394 else {
395 type = EAPOL_OTHER;
396 if (dump_msg_level & DUMP_EAPOL_VAL) {
397 printf("OTHER: key_info=0x%x, pair=%d, ack=%d, mic=%d, sec=%d, kerr=%d, req=%d\n",
398 key_info, pair, ack, mic, sec, kerr, req);
399 }
400 }
401
402 return type;
403 }
404
405 void
dhd_dump_pkt(dhd_pub_t * dhdp,int ifidx,uint8 * pktdata,uint32 pktlen,bool tx,uint32 * pkthash,uint16 * pktfate)406 dhd_dump_pkt(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, uint32 pktlen,
407 bool tx, uint32 *pkthash, uint16 *pktfate)
408 {
409 struct ether_header *eh;
410 uint16 ether_type;
411
412 if (!pktdata || pktlen < ETHER_HDR_LEN) {
413 return;
414 }
415
416 #if defined(BCMPCIE) && defined(DHD_PKT_LOGGING)
417 if (tx && !pkthash && !pktfate) {
418 return;
419 }
420 #endif /* BCMPCIE && DHD_PKT_LOGGING */
421
422 eh = (struct ether_header *)pktdata;
423 ether_type = ntoh16(eh->ether_type);
424 if (ether_type == ETHER_TYPE_802_1X) {
425 dhd_dump_eapol_message(dhdp, ifidx, pktdata, pktlen,
426 tx, pkthash, pktfate);
427 }
428 if (ether_type == ETHER_TYPE_IP) {
429 if (dhd_check_dhcp(pktdata)) {
430 dhd_dhcp_dump(dhdp, ifidx, pktdata, tx, pkthash, pktfate);
431 } else if (dhd_check_icmp(pktdata)) {
432 dhd_icmp_dump(dhdp, ifidx, pktdata, tx, pkthash, pktfate);
433 } else if (dhd_check_dns(pktdata)) {
434 dhd_dns_dump(dhdp, ifidx, pktdata, tx, pkthash, pktfate);
435 }
436 }
437 if (ether_type == ETHER_TYPE_ARP) {
438 if (dhd_check_arp(pktdata, ether_type)) {
439 dhd_arp_dump(dhdp, ifidx, pktdata, tx, pkthash, pktfate);
440 }
441 }
442 dhd_trx_pkt_dump(dhdp, ifidx, pktdata, pktlen, tx);
443 }
444
445 #ifdef DHD_PKTDUMP_ROAM
446 static void
dhd_dump_pkt_cnts_inc(dhd_pub_t * dhdp,bool tx,uint16 * pktfate,uint16 pkttype)447 dhd_dump_pkt_cnts_inc(dhd_pub_t *dhdp, bool tx, uint16 *pktfate, uint16 pkttype)
448 {
449 pkt_cnts_log_t *pktcnts;
450 pkt_cnt_t *cnt;
451
452 if (!dhdp) {
453 DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
454 return;
455 }
456
457 pktcnts = (pkt_cnts_log_t *)(dhdp->pktcnts);
458 if (!pktcnts) {
459 DHD_ERROR(("%s: pktcnts is NULL\n", __FUNCTION__));
460 return;
461 }
462
463 if (!pktcnts->enabled || (tx && !pktfate)) {
464 return;
465 }
466
467 if (pkttype == PKT_CNT_TYPE_ARP) {
468 cnt = (pkt_cnt_t *)&pktcnts->arp_cnt;
469 } else if (pkttype == PKT_CNT_TYPE_DNS) {
470 cnt = (pkt_cnt_t *)&pktcnts->dns_cnt;
471 } else {
472 /* invalid packet type */
473 return;
474 }
475
476 if (tx) {
477 TX_FATE_ACKED(pktfate) ? cnt->tx_cnt++ : cnt->tx_err_cnt++;
478 } else {
479 cnt->rx_cnt++;
480 }
481 }
482
483 static void
dhd_dump_pkt_timer(unsigned long data)484 dhd_dump_pkt_timer(unsigned long data)
485 {
486 dhd_pub_t *dhdp = (dhd_pub_t *)data;
487 pkt_cnts_log_t *pktcnts = (pkt_cnts_log_t *)(dhdp->pktcnts);
488
489 pktcnts->enabled = FALSE;
490
491 /* print out the packet counter value */
492 DHD_PKTDUMP(("============= PACKET COUNT SUMMARY ============\n"));
493 DHD_PKTDUMP(("- Reason: %s\n", pkt_cnt_msg[pktcnts->reason]));
494 DHD_PKTDUMP(("- Duration: %d msec(s)\n", PKT_CNT_TIMER_INTERNVAL_MS));
495 DHD_PKTDUMP(("- ARP PACKETS: tx_success:%d tx_fail:%d rx_cnt:%d\n",
496 pktcnts->arp_cnt.tx_cnt, pktcnts->arp_cnt.tx_err_cnt,
497 pktcnts->arp_cnt.rx_cnt));
498 DHD_PKTDUMP(("- DNS PACKETS: tx_success:%d tx_fail:%d rx_cnt:%d\n",
499 pktcnts->dns_cnt.tx_cnt, pktcnts->dns_cnt.tx_err_cnt,
500 pktcnts->dns_cnt.rx_cnt));
501 DHD_PKTDUMP(("============= END OF COUNT SUMMARY ============\n"));
502 }
503
504 void
dhd_dump_mod_pkt_timer(dhd_pub_t * dhdp,uint16 rsn)505 dhd_dump_mod_pkt_timer(dhd_pub_t *dhdp, uint16 rsn)
506 {
507 pkt_cnts_log_t *pktcnts;
508
509 if (!dhdp || !dhdp->pktcnts) {
510 DHD_ERROR(("%s: dhdp or dhdp->pktcnts is NULL\n",
511 __FUNCTION__));
512 return;
513 }
514
515 if (!PKT_CNT_RSN_VALID(rsn)) {
516 DHD_ERROR(("%s: invalid reason code %d\n",
517 __FUNCTION__, rsn));
518 return;
519 }
520
521 pktcnts = (pkt_cnts_log_t *)(dhdp->pktcnts);
522 if (timer_pending(&pktcnts->pktcnt_timer)) {
523 del_timer_sync(&pktcnts->pktcnt_timer);
524 }
525
526 bzero(&pktcnts->arp_cnt, sizeof(pkt_cnt_t));
527 bzero(&pktcnts->dns_cnt, sizeof(pkt_cnt_t));
528 pktcnts->reason = rsn;
529 pktcnts->enabled = TRUE;
530 mod_timer(&pktcnts->pktcnt_timer,
531 jiffies + msecs_to_jiffies(PKT_CNT_TIMER_INTERNVAL_MS));
532 DHD_PKTDUMP(("%s: Arm the pktcnt timer. reason=%d\n",
533 __FUNCTION__, rsn));
534 }
535
536 void
dhd_dump_pkt_init(dhd_pub_t * dhdp)537 dhd_dump_pkt_init(dhd_pub_t *dhdp)
538 {
539 pkt_cnts_log_t *pktcnts;
540
541 if (!dhdp) {
542 DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
543 return;
544 }
545
546 pktcnts = (pkt_cnts_log_t *)MALLOCZ(dhdp->osh, sizeof(pkt_cnts_log_t));
547 if (!pktcnts) {
548 DHD_ERROR(("%s: failed to allocate memory for pktcnts\n",
549 __FUNCTION__));
550 return;
551 }
552
553 /* init timers */
554 init_timer_compat(&pktcnts->pktcnt_timer, dhd_dump_pkt_timer, dhdp);
555 dhdp->pktcnts = pktcnts;
556 }
557
558 void
dhd_dump_pkt_deinit(dhd_pub_t * dhdp)559 dhd_dump_pkt_deinit(dhd_pub_t *dhdp)
560 {
561 pkt_cnts_log_t *pktcnts;
562
563 if (!dhdp || !dhdp->pktcnts) {
564 DHD_ERROR(("%s: dhdp or pktcnts is NULL\n", __FUNCTION__));
565 return;
566 }
567
568 pktcnts = (pkt_cnts_log_t *)(dhdp->pktcnts);
569 pktcnts->enabled = FALSE;
570 del_timer_sync(&pktcnts->pktcnt_timer);
571 MFREE(dhdp->osh, dhdp->pktcnts, sizeof(pkt_cnts_log_t));
572 dhdp->pktcnts = NULL;
573 }
574
575 void
dhd_dump_pkt_clear(dhd_pub_t * dhdp)576 dhd_dump_pkt_clear(dhd_pub_t *dhdp)
577 {
578 pkt_cnts_log_t *pktcnts;
579
580 if (!dhdp || !dhdp->pktcnts) {
581 DHD_ERROR(("%s: dhdp or pktcnts is NULL\n", __FUNCTION__));
582 return;
583 }
584
585 pktcnts = (pkt_cnts_log_t *)(dhdp->pktcnts);
586 pktcnts->enabled = FALSE;
587 del_timer_sync(&pktcnts->pktcnt_timer);
588 pktcnts->reason = 0;
589 bzero(&pktcnts->arp_cnt, sizeof(pkt_cnt_t));
590 bzero(&pktcnts->dns_cnt, sizeof(pkt_cnt_t));
591 }
592
593 bool
dhd_dump_pkt_enabled(dhd_pub_t * dhdp)594 dhd_dump_pkt_enabled(dhd_pub_t *dhdp)
595 {
596 pkt_cnts_log_t *pktcnts;
597
598 if (!dhdp || !dhdp->pktcnts) {
599 return FALSE;
600 }
601
602 pktcnts = (pkt_cnts_log_t *)(dhdp->pktcnts);
603
604 return pktcnts->enabled;
605 }
606 #else
607 static INLINE void
dhd_dump_pkt_cnts_inc(dhd_pub_t * dhdp,bool tx,uint16 * pktfate,uint16 pkttype)608 dhd_dump_pkt_cnts_inc(dhd_pub_t *dhdp, bool tx, uint16 *pktfate, uint16 pkttype) { }
609 static INLINE bool
dhd_dump_pkt_enabled(dhd_pub_t * dhdp)610 dhd_dump_pkt_enabled(dhd_pub_t *dhdp) { return FALSE; }
611 #endif /* DHD_PKTDUMP_ROAM */
612
613 #ifdef DHD_8021X_DUMP
614 static void
dhd_dump_wsc_message(dhd_pub_t * dhd,int ifidx,uint8 * pktdata,uint32 pktlen,bool tx,uint32 * pkthash,uint16 * pktfate)615 dhd_dump_wsc_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata,
616 uint32 pktlen, bool tx, uint32 *pkthash, uint16 *pktfate)
617 {
618 eapol_header_t *eapol_hdr;
619 eap_header_fmt_t *eap_hdr;
620 eap_wsc_fmt_t *eap_wsc;
621 char *ifname;
622 uint16 eap_len;
623 bool cond;
624 char seabuf[ETHER_ADDR_STR_LEN]="";
625 char deabuf[ETHER_ADDR_STR_LEN]="";
626
627 if (!pktdata) {
628 DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__));
629 return;
630 }
631
632 if (pktlen < (ETHER_HDR_LEN + EAPOL_HDR_LEN)) {
633 DHD_ERROR(("%s: invalid pkt length\n", __FUNCTION__));
634 return;
635 }
636
637 bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
638 bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
639
640 eapol_hdr = (eapol_header_t *)pktdata;
641 eap_hdr = (eap_header_fmt_t *)(eapol_hdr->body);
642 if (eap_hdr->type != EAP_TYPE_EXP) {
643 return;
644 }
645
646 eap_len = ntoh16(eap_hdr->len);
647 if (eap_len < EAP_WSC_MIN_DATA_LEN) {
648 return;
649 }
650
651 eap_wsc = (eap_wsc_fmt_t *)(eap_hdr->data);
652 if (bcmp(eap_wsc->oui, (const uint8 *)WFA_VID, WFA_VID_LEN) ||
653 (ntoh32(eap_wsc->ouitype) != WFA_VTYPE)) {
654 return;
655 }
656
657 if (eap_wsc->flags) {
658 return;
659 }
660
661 ifname = dhd_ifname(dhd, ifidx);
662 cond = (tx && pktfate) ? FALSE : TRUE;
663
664 if (eap_wsc->opcode == WSC_OPCODE_MSG) {
665 const uint8 *tlv_buf = (const uint8 *)(eap_wsc->data);
666 const uint8 *msg;
667 uint16 msglen;
668 uint16 wsc_data_len = (uint16)(eap_len - EAP_HDR_LEN - EAP_WSC_DATA_OFFSET);
669 bcm_xtlv_opts_t opt = BCM_XTLV_OPTION_IDBE | BCM_XTLV_OPTION_LENBE;
670
671 msg = bcm_get_data_from_xtlv_buf(tlv_buf, wsc_data_len,
672 WSC_ATTR_MSG, &msglen, opt);
673 if (msg && msglen) {
674 switch (*msg) {
675 case WSC_MSG_M1:
676 #ifdef WL_EXT_IAPSTA
677 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_WPS_M1);
678 #endif
679 DHD_STATLOG_DATA(dhd, ST(WPS_M1), ifidx, tx, cond);
680 EAP_PRINT("EAP Packet, WPS M1");
681 break;
682 case WSC_MSG_M2:
683 #ifdef WL_EXT_IAPSTA
684 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_WPS_M2);
685 #endif
686 DHD_STATLOG_DATA(dhd, ST(WPS_M2), ifidx, tx, cond);
687 EAP_PRINT("EAP Packet, WPS M2");
688 break;
689 case WSC_MSG_M3:
690 #ifdef WL_EXT_IAPSTA
691 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_WPS_M3);
692 #endif
693 DHD_STATLOG_DATA(dhd, ST(WPS_M3), ifidx, tx, cond);
694 EAP_PRINT("EAP Packet, WPS M3");
695 break;
696 case WSC_MSG_M4:
697 #ifdef WL_EXT_IAPSTA
698 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_WPS_M4);
699 #endif
700 DHD_STATLOG_DATA(dhd, ST(WPS_M4), ifidx, tx, cond);
701 EAP_PRINT("EAP Packet, WPS M4");
702 break;
703 case WSC_MSG_M5:
704 #ifdef WL_EXT_IAPSTA
705 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_WPS_M5);
706 #endif
707 DHD_STATLOG_DATA(dhd, ST(WPS_M5), ifidx, tx, cond);
708 EAP_PRINT("EAP Packet, WPS M5");
709 break;
710 case WSC_MSG_M6:
711 #ifdef WL_EXT_IAPSTA
712 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_WPS_M6);
713 #endif
714 DHD_STATLOG_DATA(dhd, ST(WPS_M6), ifidx, tx, cond);
715 EAP_PRINT("EAP Packet, WPS M6");
716 break;
717 case WSC_MSG_M7:
718 #ifdef WL_EXT_IAPSTA
719 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_WPS_M7);
720 #endif
721 DHD_STATLOG_DATA(dhd, ST(WPS_M7), ifidx, tx, cond);
722 EAP_PRINT("EAP Packet, WPS M7");
723 break;
724 case WSC_MSG_M8:
725 #ifdef WL_EXT_IAPSTA
726 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_WPS_M8);
727 #endif
728 DHD_STATLOG_DATA(dhd, ST(WPS_M8), ifidx, tx, cond);
729 EAP_PRINT("EAP Packet, WPS M8");
730 break;
731 default:
732 break;
733 }
734 }
735 } else if (eap_wsc->opcode == WSC_OPCODE_START) {
736 #ifdef WL_EXT_IAPSTA
737 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_WSC_START);
738 #endif
739 DHD_STATLOG_DATA(dhd, ST(WSC_START), ifidx, tx, cond);
740 EAP_PRINT("EAP Packet, WSC Start");
741 } else if (eap_wsc->opcode == WSC_OPCODE_DONE) {
742 #ifdef WL_EXT_IAPSTA
743 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_WSC_DONE);
744 #endif
745 DHD_STATLOG_DATA(dhd, ST(WSC_DONE), ifidx, tx, cond);
746 EAP_PRINT("EAP Packet, WSC Done");
747 }
748 }
749
750 static void
dhd_dump_eap_packet(dhd_pub_t * dhd,int ifidx,uint8 * pktdata,uint32 pktlen,bool tx,uint32 * pkthash,uint16 * pktfate)751 dhd_dump_eap_packet(dhd_pub_t *dhd, int ifidx, uint8 *pktdata,
752 uint32 pktlen, bool tx, uint32 *pkthash, uint16 *pktfate)
753 {
754 eapol_header_t *eapol_hdr;
755 eap_header_fmt_t *eap_hdr;
756 char *ifname;
757 bool cond;
758 char seabuf[ETHER_ADDR_STR_LEN]="";
759 char deabuf[ETHER_ADDR_STR_LEN]="";
760
761 if (!pktdata) {
762 DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__));
763 return;
764 }
765
766 bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
767 bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
768
769 eapol_hdr = (eapol_header_t *)pktdata;
770 eap_hdr = (eap_header_fmt_t *)(eapol_hdr->body);
771 ifname = dhd_ifname(dhd, ifidx);
772 cond = (tx && pktfate) ? FALSE : TRUE;
773
774 if (eap_hdr->code == EAP_CODE_REQUEST ||
775 eap_hdr->code == EAP_CODE_RESPONSE) {
776 bool isreq = (eap_hdr->code == EAP_CODE_REQUEST);
777 switch (eap_hdr->type) {
778 case EAP_TYPE_IDENT:
779 if (isreq) {
780 #ifdef WL_EXT_IAPSTA
781 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_REQID);
782 #endif
783 DHD_STATLOG_DATA(dhd, ST(EAP_REQ_IDENTITY), ifidx, tx, cond);
784 EAP_PRINT("EAP Packet, Request, Identity");
785 } else {
786 #ifdef WL_EXT_IAPSTA
787 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_RSPID);
788 #endif
789 DHD_STATLOG_DATA(dhd, ST(EAP_RESP_IDENTITY), ifidx, tx, cond);
790 EAP_PRINT("EAP Packet, Response, Identity");
791 }
792 break;
793 case EAP_TYPE_TLS:
794 if (isreq) {
795 DHD_STATLOG_DATA(dhd, ST(EAP_REQ_TLS), ifidx, tx, cond);
796 EAP_PRINT("EAP Packet, Request, TLS");
797 } else {
798 DHD_STATLOG_DATA(dhd, ST(EAP_RESP_TLS), ifidx, tx, cond);
799 EAP_PRINT("EAP Packet, Response, TLS");
800 }
801 break;
802 case EAP_TYPE_LEAP:
803 if (isreq) {
804 DHD_STATLOG_DATA(dhd, ST(EAP_REQ_LEAP), ifidx, tx, cond);
805 EAP_PRINT("EAP Packet, Request, LEAP");
806 } else {
807 DHD_STATLOG_DATA(dhd, ST(EAP_RESP_LEAP), ifidx, tx, cond);
808 EAP_PRINT("EAP Packet, Response, LEAP");
809 }
810 break;
811 case EAP_TYPE_TTLS:
812 if (isreq) {
813 DHD_STATLOG_DATA(dhd, ST(EAP_REQ_TTLS), ifidx, tx, cond);
814 EAP_PRINT("EAP Packet, Request, TTLS");
815 } else {
816 DHD_STATLOG_DATA(dhd, ST(EAP_RESP_TTLS), ifidx, tx, cond);
817 EAP_PRINT("EAP Packet, Response, TTLS");
818 }
819 break;
820 case EAP_TYPE_AKA:
821 if (isreq) {
822 DHD_STATLOG_DATA(dhd, ST(EAP_REQ_AKA), ifidx, tx, cond);
823 EAP_PRINT("EAP Packet, Request, AKA");
824 } else {
825 DHD_STATLOG_DATA(dhd, ST(EAP_RESP_AKA), ifidx, tx, cond);
826 EAP_PRINT("EAP Packet, Response, AKA");
827 }
828 break;
829 case EAP_TYPE_PEAP:
830 if (isreq) {
831 DHD_STATLOG_DATA(dhd, ST(EAP_REQ_PEAP), ifidx, tx, cond);
832 EAP_PRINT("EAP Packet, Request, PEAP");
833 } else {
834 DHD_STATLOG_DATA(dhd, ST(EAP_RESP_PEAP), ifidx, tx, cond);
835 EAP_PRINT("EAP Packet, Response, PEAP");
836 }
837 break;
838 case EAP_TYPE_FAST:
839 if (isreq) {
840 DHD_STATLOG_DATA(dhd, ST(EAP_REQ_FAST), ifidx, tx, cond);
841 EAP_PRINT("EAP Packet, Request, FAST");
842 } else {
843 DHD_STATLOG_DATA(dhd, ST(EAP_RESP_FAST), ifidx, tx, cond);
844 EAP_PRINT("EAP Packet, Response, FAST");
845 }
846 break;
847 case EAP_TYPE_PSK:
848 if (isreq) {
849 DHD_STATLOG_DATA(dhd, ST(EAP_REQ_PSK), ifidx, tx, cond);
850 EAP_PRINT("EAP Packet, Request, PSK");
851 } else {
852 DHD_STATLOG_DATA(dhd, ST(EAP_RESP_PSK), ifidx, tx, cond);
853 EAP_PRINT("EAP Packet, Response, PSK");
854 }
855 break;
856 case EAP_TYPE_AKAP:
857 if (isreq) {
858 DHD_STATLOG_DATA(dhd, ST(EAP_REQ_AKAP), ifidx, tx, cond);
859 EAP_PRINT("EAP Packet, Request, AKAP");
860 } else {
861 DHD_STATLOG_DATA(dhd, ST(EAP_RESP_AKAP), ifidx, tx, cond);
862 EAP_PRINT("EAP Packet, Response, AKAP");
863 }
864 break;
865 case EAP_TYPE_EXP:
866 dhd_dump_wsc_message(dhd, ifidx, pktdata, pktlen, tx,
867 pkthash, pktfate);
868 break;
869 default:
870 break;
871 }
872 } else if (eap_hdr->code == EAP_CODE_SUCCESS) {
873 DHD_STATLOG_DATA(dhd, ST(EAP_SUCCESS), ifidx, tx, cond);
874 EAP_PRINT("EAP Packet, Success");
875 } else if (eap_hdr->code == EAP_CODE_FAILURE) {
876 DHD_STATLOG_DATA(dhd, ST(EAP_FAILURE), ifidx, tx, cond);
877 EAP_PRINT("EAP Packet, Failure");
878 }
879 }
880
881 static void
dhd_dump_eapol_4way_message(dhd_pub_t * dhd,int ifidx,uint8 * pktdata,bool tx,uint32 * pkthash,uint16 * pktfate)882 dhd_dump_eapol_4way_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata, bool tx,
883 uint32 *pkthash, uint16 *pktfate)
884 {
885 eapol_header_t *eapol_hdr;
886 eapol_key_hdr_t *eap_key;
887 msg_eapol_t type;
888 char *ifname;
889 bool cond;
890 char seabuf[ETHER_ADDR_STR_LEN]="";
891 char deabuf[ETHER_ADDR_STR_LEN]="";
892
893 if (!pktdata) {
894 DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__));
895 return;
896 }
897
898 bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
899 bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
900
901 type = dhd_is_4way_msg(pktdata);
902 ifname = dhd_ifname(dhd, ifidx);
903 eapol_hdr = (eapol_header_t *)pktdata;
904 eap_key = (eapol_key_hdr_t *)(eapol_hdr->body);
905 cond = (tx && pktfate) ? FALSE : TRUE;
906
907 if (eap_key->type != EAPOL_WPA2_KEY && eap_key->type != EAPOL_WPA_KEY) {
908 EAP_PRINT_OTHER("NON EAPOL_WPA2_KEY %d", eap_key->type);
909 return;
910 }
911
912 switch (type) {
913 case EAPOL_4WAY_M1:
914 #ifdef WL_EXT_IAPSTA
915 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_4WAY_M1);
916 #endif
917 DHD_STATLOG_DATA(dhd, ST(EAPOL_M1), ifidx, tx, cond);
918 EAP_PRINT("EAPOL Packet, 4-way handshake, M1");
919 break;
920 case EAPOL_4WAY_M2:
921 #ifdef WL_EXT_IAPSTA
922 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_4WAY_M2);
923 #endif
924 DHD_STATLOG_DATA(dhd, ST(EAPOL_M2), ifidx, tx, cond);
925 EAP_PRINT("EAPOL Packet, 4-way handshake, M2");
926 break;
927 case EAPOL_4WAY_M3:
928 #ifdef WL_EXT_IAPSTA
929 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_4WAY_M3);
930 #endif
931 DHD_STATLOG_DATA(dhd, ST(EAPOL_M3), ifidx, tx, cond);
932 EAP_PRINT("EAPOL Packet, 4-way handshake, M3");
933 break;
934 case EAPOL_4WAY_M4:
935 #ifdef WL_EXT_IAPSTA
936 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_4WAY_M4);
937 #endif
938 DHD_STATLOG_DATA(dhd, ST(EAPOL_M4), ifidx, tx, cond);
939 EAP_PRINT("EAPOL Packet, 4-way handshake, M4");
940 break;
941 case EAPOL_GROUPKEY_M1:
942 #ifdef WL_EXT_IAPSTA
943 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_GROUPKEY_M1);
944 #endif
945 DHD_STATLOG_DATA(dhd, ST(EAPOL_GROUPKEY_M1), ifidx, tx, cond);
946 EAP_PRINT_REPLAY("EAPOL Packet, GROUP Key handshake, M1");
947 break;
948 case EAPOL_GROUPKEY_M2:
949 #ifdef WL_EXT_IAPSTA
950 wl_ext_update_eapol_status(dhd, ifidx, EAPOL_STATUS_GROUPKEY_M2);
951 #endif
952 DHD_STATLOG_DATA(dhd, ST(EAPOL_GROUPKEY_M2), ifidx, tx, cond);
953 EAP_PRINT_REPLAY("EAPOL Packet, GROUP Key handshake, M2");
954 if (ifidx == 0 && tx && pktfate) {
955 dhd_dump_mod_pkt_timer(dhd, PKT_CNT_RSN_GRPKEY_UP);
956 }
957 break;
958 default:
959 DHD_STATLOG_DATA(dhd, ST(8021X_OTHER), ifidx, tx, cond);
960 EAP_PRINT_OTHER("OTHER 4WAY type=%d", type);
961 break;
962 }
963 }
964
965 void
dhd_dump_eapol_message(dhd_pub_t * dhd,int ifidx,uint8 * pktdata,uint32 pktlen,bool tx,uint32 * pkthash,uint16 * pktfate)966 dhd_dump_eapol_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata,
967 uint32 pktlen, bool tx, uint32 *pkthash, uint16 *pktfate)
968 {
969 char *ifname;
970 eapol_header_t *eapol_hdr = (eapol_header_t *)pktdata;
971 bool cond;
972 char seabuf[ETHER_ADDR_STR_LEN]="";
973 char deabuf[ETHER_ADDR_STR_LEN]="";
974
975 if (!pktdata) {
976 DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__));
977 return;
978 }
979
980 bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
981 bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
982
983 eapol_hdr = (eapol_header_t *)pktdata;
984 ifname = dhd_ifname(dhd, ifidx);
985 cond = (tx && pktfate) ? FALSE : TRUE;
986
987 if (eapol_hdr->type == EAP_PACKET) {
988 dhd_dump_eap_packet(dhd, ifidx, pktdata, pktlen, tx,
989 pkthash, pktfate);
990 } else if (eapol_hdr->type == EAPOL_START) {
991 DHD_STATLOG_DATA(dhd, ST(EAPOL_START), ifidx, tx, cond);
992 EAP_PRINT("EAP Packet, EAPOL-Start");
993 } else if (eapol_hdr->type == EAPOL_KEY) {
994 dhd_dump_eapol_4way_message(dhd, ifidx, pktdata, tx,
995 pkthash, pktfate);
996 } else {
997 DHD_STATLOG_DATA(dhd, ST(8021X_OTHER), ifidx, tx, cond);
998 EAP_PRINT_OTHER("OTHER 8021X");
999 }
1000 }
1001 #endif /* DHD_8021X_DUMP */
1002
1003 bool
dhd_check_ip_prot(uint8 * pktdata,uint16 ether_type)1004 dhd_check_ip_prot(uint8 *pktdata, uint16 ether_type)
1005 {
1006 hdr_fmt_t *b = (hdr_fmt_t *)&pktdata[ETHER_HDR_LEN];
1007 struct ipv4_hdr *iph = &b->iph;
1008
1009 /* check IP header */
1010 if ((ether_type != ETHER_TYPE_IP) ||
1011 (IPV4_HLEN(iph) < IPV4_HLEN_MIN) ||
1012 (IP_VER(iph) != IP_VER_4)) {
1013 return FALSE;
1014 }
1015
1016 return TRUE;
1017 }
1018
1019 bool
dhd_check_dhcp(uint8 * pktdata)1020 dhd_check_dhcp(uint8 *pktdata)
1021 {
1022 hdr_fmt_t *b = (hdr_fmt_t *)&pktdata[ETHER_HDR_LEN];
1023 struct ipv4_hdr *iph = &b->iph;
1024
1025 if (IPV4_PROT(iph) != IP_PROT_UDP) {
1026 return FALSE;
1027 }
1028
1029 /* check UDP port for bootp (67, 68) */
1030 if (b->udph.src_port != htons(DHCP_PORT_SERVER) &&
1031 b->udph.src_port != htons(DHCP_PORT_CLIENT) &&
1032 b->udph.dst_port != htons(DHCP_PORT_SERVER) &&
1033 b->udph.dst_port != htons(DHCP_PORT_CLIENT)) {
1034 return FALSE;
1035 }
1036
1037 /* check header length */
1038 if (ntohs(iph->tot_len) < ntohs(b->udph.len) + sizeof(struct bcmudp_hdr)) {
1039 return FALSE;
1040 }
1041 return TRUE;
1042 }
1043
1044 #ifdef DHD_DHCP_DUMP
1045 #define BOOTP_CHADDR_LEN 16
1046 #define BOOTP_SNAME_LEN 64
1047 #define BOOTP_FILE_LEN 128
1048 #define BOOTP_MIN_DHCP_OPT_LEN 312
1049 #define BOOTP_MAGIC_COOKIE_LEN 4
1050
1051 #define DHCP_MSGTYPE_DISCOVER 1
1052 #define DHCP_MSGTYPE_OFFER 2
1053 #define DHCP_MSGTYPE_REQUEST 3
1054 #define DHCP_MSGTYPE_DECLINE 4
1055 #define DHCP_MSGTYPE_ACK 5
1056 #define DHCP_MSGTYPE_NAK 6
1057 #define DHCP_MSGTYPE_RELEASE 7
1058 #define DHCP_MSGTYPE_INFORM 8
1059
1060 #define DHCP_PRINT(str) \
1061 do { \
1062 if (tx) { \
1063 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] " str " %8s[%8s] [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
1064 ifname, typestr, opstr, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1065 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
1066 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1067 } else { \
1068 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] " str " %8s[%8s] [RX] : %s(%s) %s %s(%s)\n", \
1069 ifname, typestr, opstr, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1070 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf)); \
1071 } \
1072 } while (0)
1073
1074 typedef struct bootp_fmt {
1075 struct ipv4_hdr iph;
1076 struct bcmudp_hdr udph;
1077 uint8 op;
1078 uint8 htype;
1079 uint8 hlen;
1080 uint8 hops;
1081 uint32 transaction_id;
1082 uint16 secs;
1083 uint16 flags;
1084 uint32 client_ip;
1085 uint32 assigned_ip;
1086 uint32 server_ip;
1087 uint32 relay_ip;
1088 uint8 hw_address[BOOTP_CHADDR_LEN];
1089 uint8 server_name[BOOTP_SNAME_LEN];
1090 uint8 file_name[BOOTP_FILE_LEN];
1091 uint8 options[BOOTP_MIN_DHCP_OPT_LEN];
1092 } PACKED_STRUCT bootp_fmt_t;
1093
1094 static const uint8 bootp_magic_cookie[4] = { 99, 130, 83, 99 };
1095 static char dhcp_ops[][10] = {
1096 "NA", "REQUEST", "REPLY"
1097 };
1098 static char dhcp_types[][10] = {
1099 "NA", "DISCOVER", "OFFER", "REQUEST", "DECLINE", "ACK", "NAK", "RELEASE", "INFORM"
1100 };
1101
1102 #ifdef DHD_STATUS_LOGGING
1103 static const int dhcp_types_stat[9] = {
1104 ST(INVALID), ST(DHCP_DISCOVER), ST(DHCP_OFFER), ST(DHCP_REQUEST),
1105 ST(DHCP_DECLINE), ST(DHCP_ACK), ST(DHCP_NAK), ST(DHCP_RELEASE),
1106 ST(DHCP_INFORM)
1107 };
1108 #endif /* DHD_STATUS_LOGGING */
1109
1110 void
dhd_dhcp_dump(dhd_pub_t * dhdp,int ifidx,uint8 * pktdata,bool tx,uint32 * pkthash,uint16 * pktfate)1111 dhd_dhcp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
1112 uint32 *pkthash, uint16 *pktfate)
1113 {
1114 bootp_fmt_t *b = (bootp_fmt_t *)&pktdata[ETHER_HDR_LEN];
1115 struct ipv4_hdr *iph = &b->iph;
1116 uint8 *ptr, *opt, *end = (uint8 *) b + ntohs(b->iph.tot_len);
1117 int dhcp_type = 0, len, opt_len;
1118 char *ifname = NULL, *typestr = NULL, *opstr = NULL;
1119 bool cond;
1120 char sabuf[20]="", dabuf[20]="";
1121 char seabuf[ETHER_ADDR_STR_LEN]="";
1122 char deabuf[ETHER_ADDR_STR_LEN]="";
1123
1124 if (!(dump_msg_level & DUMP_DHCP_VAL))
1125 return;
1126 bcm_ip_ntoa((struct ipv4_addr *)iph->src_ip, sabuf);
1127 bcm_ip_ntoa((struct ipv4_addr *)iph->dst_ip, dabuf);
1128 bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
1129 bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
1130
1131 ifname = dhd_ifname(dhdp, ifidx);
1132 cond = (tx && pktfate) ? FALSE : TRUE;
1133 len = ntohs(b->udph.len) - sizeof(struct bcmudp_hdr);
1134 opt_len = len - (sizeof(*b) - sizeof(struct ipv4_hdr) -
1135 sizeof(struct bcmudp_hdr) - sizeof(b->options));
1136
1137 /* parse bootp options */
1138 if (opt_len >= BOOTP_MAGIC_COOKIE_LEN &&
1139 !memcmp(b->options, bootp_magic_cookie, BOOTP_MAGIC_COOKIE_LEN)) {
1140 ptr = &b->options[BOOTP_MAGIC_COOKIE_LEN];
1141 while (ptr < end && *ptr != 0xff) {
1142 opt = ptr++;
1143 if (*opt == 0) {
1144 continue;
1145 }
1146 ptr += *ptr + 1;
1147 if (ptr >= end) {
1148 break;
1149 }
1150 if (*opt == DHCP_OPT_MSGTYPE) {
1151 if (opt[1]) {
1152 dhcp_type = opt[2];
1153 typestr = dhcp_types[dhcp_type];
1154 opstr = dhcp_ops[b->op];
1155 DHD_STATLOG_DATA(dhdp, dhcp_types_stat[dhcp_type],
1156 ifidx, tx, cond);
1157 DHCP_PRINT("DHCP");
1158 break;
1159 }
1160 }
1161 }
1162 }
1163 }
1164 #endif /* DHD_DHCP_DUMP */
1165
1166 bool
dhd_check_icmp(uint8 * pktdata)1167 dhd_check_icmp(uint8 *pktdata)
1168 {
1169 uint8 *pkt = (uint8 *)&pktdata[ETHER_HDR_LEN];
1170 struct ipv4_hdr *iph = (struct ipv4_hdr *)pkt;
1171
1172 if (IPV4_PROT(iph) != IP_PROT_ICMP) {
1173 return FALSE;
1174 }
1175
1176 /* check header length */
1177 if (ntohs(iph->tot_len) - IPV4_HLEN(iph) < sizeof(struct bcmicmp_hdr)) {
1178 return FALSE;
1179 }
1180 return TRUE;
1181 }
1182
1183 #ifdef DHD_ICMP_DUMP
1184 #define ICMP_TYPE_DEST_UNREACH 3
1185 #define ICMP_ECHO_SEQ_OFFSET 6
1186 #define ICMP_ECHO_SEQ(h) (*(uint16 *)((uint8 *)(h) + (ICMP_ECHO_SEQ_OFFSET)))
1187 #define ICMP_PING_PRINT(str) \
1188 do { \
1189 if (tx) { \
1190 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] "str " [TX] : %s(%s) %s %s(%s) SEQNUM=%d" \
1191 TXFATE_FMT"\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1192 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, seqnum, \
1193 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1194 } else { \
1195 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] "str " [RX] : %s(%s) %s %s(%s) SEQNUM=%d\n", \
1196 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1197 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, seqnum)); \
1198 } \
1199 } while (0)
1200
1201 #define ICMP_PRINT(str) \
1202 do { \
1203 if (tx) { \
1204 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] "str " [TX] : %s(%s) %s %s(%s) TYPE=%d, CODE=%d" \
1205 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1206 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, type, code, \
1207 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1208 } else { \
1209 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] "str " [RX] : %s(%s) %s %s(%s) TYPE=%d," \
1210 " CODE=%d\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1211 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, type, code)); \
1212 } \
1213 } while (0)
1214
1215 void
dhd_icmp_dump(dhd_pub_t * dhdp,int ifidx,uint8 * pktdata,bool tx,uint32 * pkthash,uint16 * pktfate)1216 dhd_icmp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
1217 uint32 *pkthash, uint16 *pktfate)
1218 {
1219 uint8 *pkt = (uint8 *)&pktdata[ETHER_HDR_LEN];
1220 struct ipv4_hdr *iph = (struct ipv4_hdr *)pkt;
1221 struct bcmicmp_hdr *icmph;
1222 char *ifname;
1223 bool cond;
1224 uint16 seqnum, type, code;
1225 char sabuf[20]="", dabuf[20]="";
1226 char seabuf[ETHER_ADDR_STR_LEN]="";
1227 char deabuf[ETHER_ADDR_STR_LEN]="";
1228
1229 if (!(dump_msg_level & DUMP_ICMP_VAL))
1230 return;
1231
1232 ifname = dhd_ifname(dhdp, ifidx);
1233 cond = (tx && pktfate) ? FALSE : TRUE;
1234 icmph = (struct bcmicmp_hdr *)((uint8 *)pkt + sizeof(struct ipv4_hdr));
1235 seqnum = 0;
1236 type = icmph->type;
1237 code = icmph->code;
1238 bcm_ip_ntoa((struct ipv4_addr *)iph->src_ip, sabuf);
1239 bcm_ip_ntoa((struct ipv4_addr *)iph->dst_ip, dabuf);
1240 bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
1241 bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
1242 if (type == ICMP_TYPE_ECHO_REQUEST) {
1243 seqnum = ntoh16(ICMP_ECHO_SEQ(icmph));
1244 DHD_STATLOG_DATA(dhdp, ST(ICMP_PING_REQ), ifidx, tx, cond);
1245 ICMP_PING_PRINT("PING REQUEST");
1246 } else if (type == ICMP_TYPE_ECHO_REPLY) {
1247 seqnum = ntoh16(ICMP_ECHO_SEQ(icmph));
1248 DHD_STATLOG_DATA(dhdp, ST(ICMP_PING_RESP), ifidx, tx, cond);
1249 ICMP_PING_PRINT("PING REPLY ");
1250 } else if (type == ICMP_TYPE_DEST_UNREACH) {
1251 DHD_STATLOG_DATA(dhdp, ST(ICMP_DEST_UNREACH), ifidx, tx, cond);
1252 ICMP_PRINT("ICMP DEST UNREACH");
1253 } else {
1254 DHD_STATLOG_DATA(dhdp, ST(ICMP_OTHER), ifidx, tx, cond);
1255 ICMP_PRINT("ICMP OTHER");
1256 }
1257 }
1258 #endif /* DHD_ICMP_DUMP */
1259
1260 bool
dhd_check_arp(uint8 * pktdata,uint16 ether_type)1261 dhd_check_arp(uint8 *pktdata, uint16 ether_type)
1262 {
1263 uint8 *pkt = (uint8 *)&pktdata[ETHER_HDR_LEN];
1264 struct bcmarp *arph = (struct bcmarp *)pkt;
1265
1266 /* validation check */
1267 if ((ether_type != ETHER_TYPE_ARP) ||
1268 (arph->htype != hton16(HTYPE_ETHERNET)) ||
1269 (arph->hlen != ETHER_ADDR_LEN) ||
1270 (arph->plen != 4)) {
1271 return FALSE;
1272 }
1273 return TRUE;
1274 }
1275
1276 #ifdef DHD_ARP_DUMP
1277 #ifdef BOARD_HIKEY
1278 /* On Hikey, due to continuous ARP prints
1279 * DPC not scheduled. Hence rate limit the prints.
1280 */
1281 #define DHD_PKTDUMP_ARP DHD_ERROR_RLMT
1282 #else
1283 #define DHD_PKTDUMP_ARP DHD_PKTDUMP
1284 #endif /* BOARD_HIKEY */
1285
1286 #define ARP_PRINT(str) \
1287 do { \
1288 if (tx) { \
1289 if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
1290 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] "str " [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
1291 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1292 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
1293 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1294 } else { \
1295 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] "str " [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
1296 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1297 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
1298 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1299 } \
1300 } else { \
1301 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] "str " [RX] : %s(%s) %s %s(%s)\n", \
1302 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1303 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf)); \
1304 } \
1305 } while (0) \
1306
1307 #define ARP_PRINT_OTHER(str) \
1308 do { \
1309 if (tx) { \
1310 if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
1311 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] "str " [TX] : %s(%s) %s %s(%s) op_code=%d" \
1312 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1313 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode, \
1314 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1315 } else { \
1316 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] "str " [TX] : %s(%s) %s %s(%s) op_code=%d" \
1317 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1318 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode, \
1319 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1320 } \
1321 } else { \
1322 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] "str " [RX] : %s(%s) %s %s(%s) op_code=%d\n", \
1323 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1324 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode)); \
1325 } \
1326 } while (0)
1327
1328 void
dhd_arp_dump(dhd_pub_t * dhdp,int ifidx,uint8 * pktdata,bool tx,uint32 * pkthash,uint16 * pktfate)1329 dhd_arp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
1330 uint32 *pkthash, uint16 *pktfate)
1331 {
1332 uint8 *pkt = (uint8 *)&pktdata[ETHER_HDR_LEN];
1333 struct bcmarp *arph = (struct bcmarp *)pkt;
1334 char *ifname;
1335 uint16 opcode;
1336 bool cond, dump_enabled;
1337 char sabuf[20]="", dabuf[20]="";
1338 char seabuf[ETHER_ADDR_STR_LEN]="";
1339 char deabuf[ETHER_ADDR_STR_LEN]="";
1340
1341 if (!(dump_msg_level & DUMP_ARP_VAL))
1342 return;
1343
1344 ifname = dhd_ifname(dhdp, ifidx);
1345 opcode = ntoh16(arph->oper);
1346 cond = (tx && pktfate) ? FALSE : TRUE;
1347 dump_enabled = dhd_dump_pkt_enabled(dhdp);
1348 bcm_ip_ntoa((struct ipv4_addr *)arph->src_ip, sabuf);
1349 bcm_ip_ntoa((struct ipv4_addr *)arph->dst_ip, dabuf);
1350 bcm_ether_ntoa((struct ether_addr *)arph->dst_eth, deabuf);
1351 bcm_ether_ntoa((struct ether_addr *)arph->src_eth, seabuf);
1352 if (opcode == ARP_OPC_REQUEST) {
1353 DHD_STATLOG_DATA(dhdp, ST(ARP_REQ), ifidx, tx, cond);
1354 ARP_PRINT("ARP REQUEST ");
1355 } else if (opcode == ARP_OPC_REPLY) {
1356 DHD_STATLOG_DATA(dhdp, ST(ARP_RESP), ifidx, tx, cond);
1357 ARP_PRINT("ARP RESPONSE");
1358 } else {
1359 ARP_PRINT_OTHER("ARP OTHER");
1360 }
1361
1362 if (ifidx == 0) {
1363 dhd_dump_pkt_cnts_inc(dhdp, tx, pktfate, PKT_CNT_TYPE_ARP);
1364 }
1365 }
1366 #endif /* DHD_ARP_DUMP */
1367
1368 bool
dhd_check_dns(uint8 * pktdata)1369 dhd_check_dns(uint8 *pktdata)
1370 {
1371 hdr_fmt_t *dnsh = (hdr_fmt_t *)&pktdata[ETHER_HDR_LEN];
1372 struct ipv4_hdr *iph = &dnsh->iph;
1373
1374 if (IPV4_PROT(iph) != IP_PROT_UDP) {
1375 return FALSE;
1376 }
1377
1378 /* check UDP port for DNS */
1379 if (dnsh->udph.src_port != hton16(UDP_PORT_DNS) &&
1380 dnsh->udph.dst_port != hton16(UDP_PORT_DNS)) {
1381 return FALSE;
1382 }
1383
1384 /* check header length */
1385 if (ntoh16(iph->tot_len) < (ntoh16(dnsh->udph.len) +
1386 sizeof(struct bcmudp_hdr))) {
1387 return FALSE;
1388 }
1389 return TRUE;
1390 }
1391
1392 #ifdef DHD_DNS_DUMP
1393 typedef struct dns_fmt {
1394 struct ipv4_hdr iph;
1395 struct bcmudp_hdr udph;
1396 uint16 id;
1397 uint16 flags;
1398 uint16 qdcount;
1399 uint16 ancount;
1400 uint16 nscount;
1401 uint16 arcount;
1402 } PACKED_STRUCT dns_fmt_t;
1403
1404 #define DNS_QR_LOC 15
1405 #define DNS_OPCODE_LOC 11
1406 #define DNS_RCODE_LOC 0
1407 #define DNS_QR_MASK ((0x1) << (DNS_QR_LOC))
1408 #define DNS_OPCODE_MASK ((0xF) << (DNS_OPCODE_LOC))
1409 #define DNS_RCODE_MASK ((0xF) << (DNS_RCODE_LOC))
1410 #define GET_DNS_QR(flags) (((flags) & (DNS_QR_MASK)) >> (DNS_QR_LOC))
1411 #define GET_DNS_OPCODE(flags) (((flags) & (DNS_OPCODE_MASK)) >> (DNS_OPCODE_LOC))
1412 #define GET_DNS_RCODE(flags) (((flags) & (DNS_RCODE_MASK)) >> (DNS_RCODE_LOC))
1413 #define DNS_UNASSIGNED_OPCODE(flags) ((GET_DNS_OPCODE(flags) >= (6)))
1414
1415 static const char dns_opcode_types[][11] = {
1416 "QUERY", "IQUERY", "STATUS", "UNASSIGNED", "NOTIFY", "UPDATE"
1417 };
1418
1419 #define DNSOPCODE(op) \
1420 (DNS_UNASSIGNED_OPCODE(flags) ? "UNASSIGNED" : dns_opcode_types[op])
1421
1422 #define DNS_REQ_PRINT(str) \
1423 do { \
1424 if (tx) { \
1425 if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
1426 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s" \
1427 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1428 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
1429 id, DNSOPCODE(opcode), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1430 } else { \
1431 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s" \
1432 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1433 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
1434 id, DNSOPCODE(opcode), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1435 } \
1436 } else { \
1437 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] " str " [RX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s\n", \
1438 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, tx?"->":"<-", \
1439 tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode))); \
1440 } \
1441 } while (0)
1442
1443 #define DNS_RESP_PRINT(str) \
1444 do { \
1445 if (tx) { \
1446 if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
1447 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d" \
1448 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1449 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode), \
1450 GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1451 } else { \
1452 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d" \
1453 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1454 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode), \
1455 GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1456 } \
1457 } else { \
1458 DHD_PKTDUMP_MEM((DHD_LOG_PREFIX "[%s] " str " [RX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d\n", \
1459 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1460 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
1461 id, DNSOPCODE(opcode), GET_DNS_RCODE(flags))); \
1462 } \
1463 } while (0)
1464
1465 void
dhd_dns_dump(dhd_pub_t * dhdp,int ifidx,uint8 * pktdata,bool tx,uint32 * pkthash,uint16 * pktfate)1466 dhd_dns_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
1467 uint32 *pkthash, uint16 *pktfate)
1468 {
1469 dns_fmt_t *dnsh = (dns_fmt_t *)&pktdata[ETHER_HDR_LEN];
1470 struct ipv4_hdr *iph = &dnsh->iph;
1471 uint16 flags, opcode, id;
1472 char *ifname;
1473 bool cond, dump_enabled;
1474 char sabuf[20]="", dabuf[20]="";
1475 char seabuf[ETHER_ADDR_STR_LEN]="";
1476 char deabuf[ETHER_ADDR_STR_LEN]="";
1477
1478 if (!(dump_msg_level & DUMP_DNS_VAL))
1479 return;
1480
1481 ifname = dhd_ifname(dhdp, ifidx);
1482 cond = (tx && pktfate) ? FALSE : TRUE;
1483 dump_enabled = dhd_dump_pkt_enabled(dhdp);
1484 flags = hton16(dnsh->flags);
1485 opcode = GET_DNS_OPCODE(flags);
1486 id = hton16(dnsh->id);
1487 bcm_ip_ntoa((struct ipv4_addr *)iph->src_ip, sabuf);
1488 bcm_ip_ntoa((struct ipv4_addr *)iph->dst_ip, dabuf);
1489 bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
1490 bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
1491 if (GET_DNS_QR(flags)) {
1492 /* Response */
1493 DHD_STATLOG_DATA(dhdp, ST(DNS_RESP), ifidx, tx, cond);
1494 DNS_RESP_PRINT("DNS RESPONSE");
1495 } else {
1496 /* Request */
1497 DHD_STATLOG_DATA(dhdp, ST(DNS_QUERY), ifidx, tx, cond);
1498 DNS_REQ_PRINT("DNS REQUEST");
1499 }
1500
1501 if (ifidx == 0) {
1502 dhd_dump_pkt_cnts_inc(dhdp, tx, pktfate, PKT_CNT_TYPE_DNS);
1503 }
1504 }
1505 #endif /* DHD_DNS_DUMP */
1506
1507 #ifdef DHD_TRX_DUMP
1508 void
dhd_trx_pkt_dump(dhd_pub_t * dhdp,int ifidx,uint8 * pktdata,uint32 pktlen,bool tx)1509 dhd_trx_pkt_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, uint32 pktlen, bool tx)
1510 {
1511 struct ether_header *eh;
1512 uint16 protocol;
1513 char *pkttype = "UNKNOWN";
1514
1515 if (!(dump_msg_level & DUMP_TRX_VAL))
1516 return;
1517
1518 if (!dhdp) {
1519 DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
1520 return;
1521 }
1522
1523 if (!pktdata) {
1524 DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__));
1525 return;
1526 }
1527
1528 eh = (struct ether_header *)pktdata;
1529 protocol = hton16(eh->ether_type);
1530 BCM_REFERENCE(pktlen);
1531
1532 switch (protocol) {
1533 case ETHER_TYPE_IP:
1534 pkttype = "IP";
1535 break;
1536 case ETHER_TYPE_ARP:
1537 pkttype = "ARP";
1538 break;
1539 case ETHER_TYPE_BRCM:
1540 pkttype = "BRCM";
1541 break;
1542 case ETHER_TYPE_802_1X:
1543 pkttype = "802.1X";
1544 break;
1545 case ETHER_TYPE_WAI:
1546 pkttype = "WAPI";
1547 break;
1548 default:
1549 break;
1550 }
1551
1552 if (protocol != ETHER_TYPE_BRCM) {
1553 if (pktdata[0] == 0xFF) {
1554 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] %s BROADCAST DUMP - %s\n",
1555 dhd_ifname(dhdp, ifidx), tx?"TX":"RX", pkttype));
1556 } else if (pktdata[0] & 1) {
1557 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] %s MULTICAST DUMP " MACDBG " - %s\n",
1558 dhd_ifname(dhdp, ifidx), tx?"TX":"RX", MAC2STRDBG(pktdata), pkttype));
1559 } else {
1560 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] %s DUMP - %s\n",
1561 dhd_ifname(dhdp, ifidx), tx?"TX":"RX", pkttype));
1562 }
1563 #ifdef DHD_RX_FULL_DUMP
1564 prhex("Data", pktdata, pktlen);
1565 #endif /* DHD_RX_FULL_DUMP */
1566 }
1567 else {
1568 DHD_PKTDUMP((DHD_LOG_PREFIX "[%s] %s DUMP - %s\n",
1569 dhd_ifname(dhdp, ifidx), tx?"TX":"RX", pkttype));
1570 }
1571 }
1572 #endif /* DHD_RX_DUMP */
1573