• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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