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