2 * Packet dump helper functions
4 * Copyright (C) 2020, Broadcom.
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:
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
21 * <<Broadcom-WL-IPTag/Open:>>
30 #include <bcmendian.h>
32 #include <dngl_stats.h>
40 #include <dhd_linux_pktdump.h>
41 #include <dhd_config.h>
43 #define DHD_PKTDUMP(arg) printk arg
44 #define DHD_PKTDUMP_MEM(arg) printk arg
45 #define PACKED_STRUCT __attribute__ ((packed))
47 #define EAPOL_HDR_LEN 4
52 #define EAPOL_LOGOFF 2
57 #define EAPOL_RC4_KEY 1
58 #define EAPOL_WPA2_KEY 2 /* 802.11i/WPA2 */
59 #define EAPOL_WPA_KEY 254 /* WPA */
61 /* EAPOL-Key header field size */
62 #define AKW_BLOCK_LEN 8
63 #define WPA_KEY_REPLAY_LEN 8
64 #define WPA_KEY_NONCE_LEN 32
65 #define WPA_KEY_IV_LEN 16
66 #define WPA_KEY_RSC_LEN 8
67 #define WPA_KEY_ID_LEN 8
68 #define WPA_KEY_MIC_LEN 16
69 #define WPA_MAX_KEY_SIZE 32
70 #define WPA_KEY_DATA_LEN (WPA_MAX_KEY_SIZE + AKW_BLOCK_LEN)
72 /* Key information bit */
73 #define KEYINFO_TYPE_MASK (1 << 3)
74 #define KEYINFO_INSTALL_MASK (1 << 6)
75 #define KEYINFO_KEYACK_MASK (1 << 7)
76 #define KEYINFO_KEYMIC_MASK (1 << 8)
77 #define KEYINFO_SECURE_MASK (1 << 9)
78 #define KEYINFO_ERROR_MASK (1 << 10)
79 #define KEYINFO_REQ_MASK (1 << 11)
82 #define EAP_CODE_REQUEST 1 /* Request */
83 #define EAP_CODE_RESPONSE 2 /* Response */
84 #define EAP_CODE_SUCCESS 3 /* Success */
85 #define EAP_CODE_FAILURE 4 /* Failure */
88 #define EAP_TYPE_RSVD 0 /* Reserved */
89 #define EAP_TYPE_IDENT 1 /* Identify */
90 #define EAP_TYPE_NOTI 2 /* Notification */
91 #define EAP_TYPE_TLS 13 /* EAP-TLS */
92 #define EAP_TYPE_LEAP 17 /* Cisco-LEAP */
93 #define EAP_TYPE_TTLS 21 /* EAP-TTLS */
94 #define EAP_TYPE_AKA 23 /* EAP-AKA */
95 #define EAP_TYPE_PEAP 25 /* EAP-PEAP */
96 #define EAP_TYPE_FAST 43 /* EAP-FAST */
97 #define EAP_TYPE_PSK 47 /* EAP-PSK */
98 #define EAP_TYPE_AKAP 50 /* EAP-AKA' */
99 #define EAP_TYPE_EXP 254 /* Reserved for Expended Type */
102 #define EAP_HDR_LEN 5
103 #define EAP_WSC_NONCE_OFFSET 10
104 #define EAP_WSC_DATA_OFFSET (OFFSETOF(eap_wsc_fmt_t, data))
105 #define EAP_WSC_MIN_DATA_LEN ((EAP_HDR_LEN) + (EAP_WSC_DATA_OFFSET))
106 #define WFA_VID "\x00\x37\x2A" /* WFA SMI code */
107 #define WFA_VID_LEN 3 /* WFA VID length */
108 #define WFA_VTYPE 1u /* WFA Vendor type */
111 #define WSC_OPCODE_UPNP 0
112 #define WSC_OPCODE_START 1
113 #define WSC_OPCODE_ACK 2
114 #define WSC_OPCODE_NACK 3
115 #define WSC_OPCODE_MSG 4
116 #define WSC_OPCODE_DONE 5
117 #define WSC_OPCODE_FRAG_ACK 6
120 #define WSC_FLAG_MF 1 /* more fragements */
121 #define WSC_FLAG_LF 2 /* length field */
123 /* WSC message code */
124 #define WSC_ATTR_MSG 0x1022
125 #define WSC_MSG_M1 0x04
126 #define WSC_MSG_M2 0x05
127 #define WSC_MSG_M3 0x07
128 #define WSC_MSG_M4 0x08
129 #define WSC_MSG_M5 0x09
130 #define WSC_MSG_M6 0x0A
131 #define WSC_MSG_M7 0x0B
132 #define WSC_MSG_M8 0x0C
135 typedef enum pkt_cnt_type
{
136 PKT_CNT_TYPE_INVALID
= 0,
137 PKT_CNT_TYPE_ARP
= 1,
138 PKT_CNT_TYPE_DNS
= 2,
142 typedef struct pkt_cnt
{
148 typedef struct pkt_cnt_log
{
151 timer_list_compat_t pktcnt_timer
;
156 #define PKT_CNT_TIMER_INTERNVAL_MS 5000 /* packet count timeout(ms) */
157 #define PKT_CNT_RSN_VALID(rsn) \
158 (((rsn) > (PKT_CNT_RSN_INVALID)) && ((rsn) < (PKT_CNT_RSN_MAX)))
160 #ifdef DHD_PKTDUMP_ROAM
161 static const char pkt_cnt_msg
[][20] = {
170 static const char tx_pktfate
[][30] = {
171 "TX_PKT_FATE_ACKED", /* 0: WLFC_CTL_PKTFLAG_DISCARD */
172 "TX_PKT_FATE_FW_QUEUED", /* 1: WLFC_CTL_PKTFLAG_D11SUPPRESS */
173 "TX_PKT_FATE_FW_QUEUED", /* 2: WLFC_CTL_PKTFLAG_WLSUPPRESS */
174 "TX_PKT_FATE_FW_DROP_INVALID", /* 3: WLFC_CTL_PKTFLAG_TOSSED_BYWLC */
175 "TX_PKT_FATE_SENT", /* 4: WLFC_CTL_PKTFLAG_DISCARD_NOACK */
176 "TX_PKT_FATE_FW_DROP_OTHER", /* 5: WLFC_CTL_PKTFLAG_SUPPRESS_ACKED */
177 "TX_PKT_FATE_FW_DROP_EXPTIME", /* 6: WLFC_CTL_PKTFLAG_EXPIRED */
178 "TX_PKT_FATE_FW_DROP_OTHER", /* 7: WLFC_CTL_PKTFLAG_DROPPED */
179 "TX_PKT_FATE_FW_PKT_FREE", /* 8: WLFC_CTL_PKTFLAG_MKTFREE */
182 #define DBGREPLAY " Replay Counter: %02x%02x%02x%02x%02x%02x%02x%02x"
183 #define REPLAY_FMT(key) ((const eapol_key_hdr_t *)(key))->replay[0], \
184 ((const eapol_key_hdr_t *)(key))->replay[1], \
185 ((const eapol_key_hdr_t *)(key))->replay[2], \
186 ((const eapol_key_hdr_t *)(key))->replay[3], \
187 ((const eapol_key_hdr_t *)(key))->replay[4], \
188 ((const eapol_key_hdr_t *)(key))->replay[5], \
189 ((const eapol_key_hdr_t *)(key))->replay[6], \
190 ((const eapol_key_hdr_t *)(key))->replay[7]
191 #define TXFATE_FMT " TX_PKTHASH:0x%X TX_PKT_FATE:%s"
192 #define TX_PKTHASH(pkthash) ((pkthash) ? (*pkthash) : (0))
193 #define TX_FATE_STR(fate) (((*fate) <= (WLFC_CTL_PKTFLAG_MKTFREE)) ? \
194 (tx_pktfate[(*fate)]) : "TX_PKT_FATE_FW_DROP_OTHER")
195 #define TX_FATE(fate) ((fate) ? (TX_FATE_STR(fate)) : "N/A")
196 #define TX_FATE_ACKED(fate) ((fate) ? ((*fate) == (WLFC_CTL_PKTFLAG_DISCARD)) : (0))
198 #define EAP_PRINT(x, args...) \
200 if (dump_msg_level & DUMP_EAPOL_VAL) { \
202 DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s)"TXFATE_FMT"\n", \
204 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
205 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
207 DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s)\n", \
209 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf)); \
214 #define EAP_PRINT_REPLAY(x, args...) \
216 if (dump_msg_level & DUMP_EAPOL_VAL) { \
218 DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s)"DBGREPLAY TXFATE_FMT"\n", \
220 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
221 REPLAY_FMT(eap_key), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
223 DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s)"DBGREPLAY"\n", \
225 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
226 REPLAY_FMT(eap_key))); \
231 #define EAP_PRINT_OTHER(x, args...) \
233 if (dump_msg_level & DUMP_EAPOL_VAL) { \
235 DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s) " \
236 "ver %d, type %d"TXFATE_FMT"\n", \
238 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
239 eapol_hdr->version, eapol_hdr->type, \
240 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
242 DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s) " \
243 "ver %d, type %d\n", \
245 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
246 eapol_hdr->version, eapol_hdr->type)); \
251 #define EAP_PRINT_OTHER_4WAY(x, args...) \
253 if (dump_msg_level & DUMP_EAPOL_VAL) { \
255 DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s) " \
256 "ver %d type %d keytype %d keyinfo 0x%02X"TXFATE_FMT"\n", \
258 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
259 eapol_hdr->version, eapol_hdr->type, eap_key->type, \
260 (uint32)hton16(eap_key->key_info), \
261 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
263 DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s) " \
264 "ver %d type %d keytype %d keyinfo 0x%02X\n", \
266 tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
267 eapol_hdr->version, eapol_hdr->type, eap_key->type, \
268 (uint32)hton16(eap_key->key_info))); \
273 #define UDP_PORT_DNS 53 /* UDP DNS port */
276 typedef struct eapol_header
{
277 struct ether_header eth
; /* 802.3/Ethernet header */
278 uint8 version
; /* EAPOL protocol version */
279 uint8 type
; /* EAPOL type */
280 uint16 length
; /* Length of body */
281 uint8 body
[1]; /* Body (optional) */
282 } PACKED_STRUCT eapol_header_t
;
285 typedef struct eap_header_fmt
{
291 } PACKED_STRUCT eap_header_fmt_t
;
294 typedef struct eap_wsc_fmt
{
300 } PACKED_STRUCT eap_wsc_fmt_t
;
303 typedef struct eapol_key_hdr
{
304 uint8 type
; /* Key Descriptor Type */
305 uint16 key_info
; /* Key Information (unaligned) */
306 uint16 key_len
; /* Key Length (unaligned) */
307 uint8 replay
[WPA_KEY_REPLAY_LEN
]; /* Replay Counter */
308 uint8 nonce
[WPA_KEY_NONCE_LEN
]; /* Nonce */
309 uint8 iv
[WPA_KEY_IV_LEN
]; /* Key IV */
310 uint8 rsc
[WPA_KEY_RSC_LEN
]; /* Key RSC */
311 uint8 id
[WPA_KEY_ID_LEN
]; /* WPA:Key ID, 802.11i/WPA2: Reserved */
312 uint8 mic
[WPA_KEY_MIC_LEN
]; /* Key MIC */
313 uint16 data_len
; /* Key Data Length */
314 uint8 data
[WPA_KEY_DATA_LEN
]; /* Key data */
315 } PACKED_STRUCT eapol_key_hdr_t
;
317 typedef struct hdr_fmt
{
319 struct bcmudp_hdr udph
;
320 } PACKED_STRUCT hdr_fmt_t
;
323 dhd_is_4way_msg(uint8
*pktdata
)
325 eapol_header_t
*eapol_hdr
;
326 eapol_key_hdr_t
*eap_key
;
327 msg_eapol_t type
= EAPOL_OTHER
;
328 bool pair
, ack
, mic
, kerr
, req
, sec
, install
;
332 DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__
));
336 eapol_hdr
= (eapol_header_t
*)pktdata
;
337 eap_key
= (eapol_key_hdr_t
*)(eapol_hdr
->body
);
338 if (eap_key
->type
!= EAPOL_WPA2_KEY
) {
342 key_info
= hton16(eap_key
->key_info
);
343 pair
= !!(key_info
& KEYINFO_TYPE_MASK
);
344 ack
= !!(key_info
& KEYINFO_KEYACK_MASK
);
345 mic
= !!(key_info
& KEYINFO_KEYMIC_MASK
);
346 kerr
= !!(key_info
& KEYINFO_ERROR_MASK
);
347 req
= !!(key_info
& KEYINFO_REQ_MASK
);
348 sec
= !!(key_info
& KEYINFO_SECURE_MASK
);
349 install
= !!(key_info
& KEYINFO_INSTALL_MASK
);
351 if (pair
&& !install
&& ack
&& !mic
&& !sec
&& !kerr
&& !req
) {
352 type
= EAPOL_4WAY_M1
;
353 } else if (pair
&& !install
&& !ack
&& mic
&& !sec
&& !kerr
&& !req
) {
354 type
= EAPOL_4WAY_M2
;
355 } else if (pair
&& ack
&& mic
&& sec
&& !kerr
&& !req
) {
356 type
= EAPOL_4WAY_M3
;
357 } else if (pair
&& !install
&& !ack
&& mic
&& sec
&& !req
&& !kerr
) {
358 type
= EAPOL_4WAY_M4
;
359 } else if (!pair
&& !install
&& ack
&& mic
&& sec
&& !req
&& !kerr
) {
360 type
= EAPOL_GROUPKEY_M1
;
361 } else if (!pair
&& !install
&& !ack
&& mic
&& sec
&& !req
&& !kerr
) {
362 type
= EAPOL_GROUPKEY_M2
;
371 dhd_dump_pkt(dhd_pub_t
*dhdp
, int ifidx
, uint8
*pktdata
, uint32 pktlen
,
372 bool tx
, uint32
*pkthash
, uint16
*pktfate
)
374 struct ether_header
*eh
;
377 if (!pktdata
|| pktlen
< ETHER_HDR_LEN
) {
381 #if defined(BCMPCIE) && defined(DHD_PKT_LOGGING)
382 if (tx
&& !pkthash
&& !pktfate
) {
385 #endif /* BCMPCIE && DHD_PKT_LOGGING */
387 eh
= (struct ether_header
*)pktdata
;
388 ether_type
= ntoh16(eh
->ether_type
);
389 if (ether_type
== ETHER_TYPE_802_1X
) {
390 dhd_dump_eapol_message(dhdp
, ifidx
, pktdata
, pktlen
,
391 tx
, pkthash
, pktfate
);
393 if (ether_type
== ETHER_TYPE_IP
) {
394 if (dhd_check_dhcp(pktdata
)) {
395 dhd_dhcp_dump(dhdp
, ifidx
, pktdata
, tx
, pkthash
, pktfate
);
396 } else if (dhd_check_icmp(pktdata
)) {
397 dhd_icmp_dump(dhdp
, ifidx
, pktdata
, tx
, pkthash
, pktfate
);
398 } else if (dhd_check_dns(pktdata
)) {
399 dhd_dns_dump(dhdp
, ifidx
, pktdata
, tx
, pkthash
, pktfate
);
402 if (ether_type
== ETHER_TYPE_ARP
) {
403 if (dhd_check_arp(pktdata
)) {
404 dhd_arp_dump(dhdp
, ifidx
, pktdata
, tx
, pkthash
, pktfate
);
407 dhd_trx_pkt_dump(dhdp
, ifidx
, pktdata
, pktlen
, tx
);
410 #ifdef DHD_PKTDUMP_ROAM
412 dhd_dump_pkt_cnts_inc(dhd_pub_t
*dhdp
, bool tx
, uint16
*pktfate
, uint16 pkttype
)
414 pkt_cnts_log_t
*pktcnts
;
418 DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__
));
422 pktcnts
= (pkt_cnts_log_t
*)(dhdp
->pktcnts
);
424 DHD_ERROR(("%s: pktcnts is NULL\n", __FUNCTION__
));
428 if (!pktcnts
->enabled
|| (tx
&& !pktfate
)) {
432 if (pkttype
== PKT_CNT_TYPE_ARP
) {
433 cnt
= (pkt_cnt_t
*)&pktcnts
->arp_cnt
;
434 } else if (pkttype
== PKT_CNT_TYPE_DNS
) {
435 cnt
= (pkt_cnt_t
*)&pktcnts
->dns_cnt
;
437 /* invalid packet type */
442 TX_FATE_ACKED(pktfate
) ? cnt
->tx_cnt
++ : cnt
->tx_err_cnt
++;
449 dhd_dump_pkt_timer(unsigned long data
)
451 dhd_pub_t
*dhdp
= (dhd_pub_t
*)data
;
452 pkt_cnts_log_t
*pktcnts
= (pkt_cnts_log_t
*)(dhdp
->pktcnts
);
454 pktcnts
->enabled
= FALSE
;
456 /* print out the packet counter value */
457 DHD_PKTDUMP(("============= PACKET COUNT SUMMARY ============\n"));
458 DHD_PKTDUMP(("- Reason: %s\n", pkt_cnt_msg
[pktcnts
->reason
]));
459 DHD_PKTDUMP(("- Duration: %d msec(s)\n", PKT_CNT_TIMER_INTERNVAL_MS
));
460 DHD_PKTDUMP(("- ARP PACKETS: tx_success:%d tx_fail:%d rx_cnt:%d\n",
461 pktcnts
->arp_cnt
.tx_cnt
, pktcnts
->arp_cnt
.tx_err_cnt
,
462 pktcnts
->arp_cnt
.rx_cnt
));
463 DHD_PKTDUMP(("- DNS PACKETS: tx_success:%d tx_fail:%d rx_cnt:%d\n",
464 pktcnts
->dns_cnt
.tx_cnt
, pktcnts
->dns_cnt
.tx_err_cnt
,
465 pktcnts
->dns_cnt
.rx_cnt
));
466 DHD_PKTDUMP(("============= END OF COUNT SUMMARY ============\n"));
470 dhd_dump_mod_pkt_timer(dhd_pub_t
*dhdp
, uint16 rsn
)
472 pkt_cnts_log_t
*pktcnts
;
474 if (!dhdp
|| !dhdp
->pktcnts
) {
475 DHD_ERROR(("%s: dhdp or dhdp->pktcnts is NULL\n",
480 if (!PKT_CNT_RSN_VALID(rsn
)) {
481 DHD_ERROR(("%s: invalid reason code %d\n",
486 pktcnts
= (pkt_cnts_log_t
*)(dhdp
->pktcnts
);
487 if (timer_pending(&pktcnts
->pktcnt_timer
)) {
488 del_timer_sync(&pktcnts
->pktcnt_timer
);
491 bzero(&pktcnts
->arp_cnt
, sizeof(pkt_cnt_t
));
492 bzero(&pktcnts
->dns_cnt
, sizeof(pkt_cnt_t
));
493 pktcnts
->reason
= rsn
;
494 pktcnts
->enabled
= TRUE
;
495 mod_timer(&pktcnts
->pktcnt_timer
,
496 jiffies
+ msecs_to_jiffies(PKT_CNT_TIMER_INTERNVAL_MS
));
497 DHD_PKTDUMP(("%s: Arm the pktcnt timer. reason=%d\n",
502 dhd_dump_pkt_init(dhd_pub_t
*dhdp
)
504 pkt_cnts_log_t
*pktcnts
;
507 DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__
));
511 pktcnts
= (pkt_cnts_log_t
*)MALLOCZ(dhdp
->osh
, sizeof(pkt_cnts_log_t
));
513 DHD_ERROR(("%s: failed to allocate memory for pktcnts\n",
519 init_timer_compat(&pktcnts
->pktcnt_timer
, dhd_dump_pkt_timer
, dhdp
);
520 dhdp
->pktcnts
= pktcnts
;
524 dhd_dump_pkt_deinit(dhd_pub_t
*dhdp
)
526 pkt_cnts_log_t
*pktcnts
;
528 if (!dhdp
|| !dhdp
->pktcnts
) {
529 DHD_ERROR(("%s: dhdp or pktcnts is NULL\n", __FUNCTION__
));
533 pktcnts
= (pkt_cnts_log_t
*)(dhdp
->pktcnts
);
534 pktcnts
->enabled
= FALSE
;
535 del_timer_sync(&pktcnts
->pktcnt_timer
);
536 MFREE(dhdp
->osh
, dhdp
->pktcnts
, sizeof(pkt_cnts_log_t
));
537 dhdp
->pktcnts
= NULL
;
541 dhd_dump_pkt_clear(dhd_pub_t
*dhdp
)
543 pkt_cnts_log_t
*pktcnts
;
545 if (!dhdp
|| !dhdp
->pktcnts
) {
546 DHD_ERROR(("%s: dhdp or pktcnts is NULL\n", __FUNCTION__
));
550 pktcnts
= (pkt_cnts_log_t
*)(dhdp
->pktcnts
);
551 pktcnts
->enabled
= FALSE
;
552 del_timer_sync(&pktcnts
->pktcnt_timer
);
554 bzero(&pktcnts
->arp_cnt
, sizeof(pkt_cnt_t
));
555 bzero(&pktcnts
->dns_cnt
, sizeof(pkt_cnt_t
));
559 dhd_dump_pkt_enabled(dhd_pub_t
*dhdp
)
561 pkt_cnts_log_t
*pktcnts
;
563 if (!dhdp
|| !dhdp
->pktcnts
) {
567 pktcnts
= (pkt_cnts_log_t
*)(dhdp
->pktcnts
);
569 return pktcnts
->enabled
;
573 dhd_dump_pkt_cnts_inc(dhd_pub_t
*dhdp
, bool tx
, uint16
*pktfate
, uint16 pkttype
) { }
575 dhd_dump_pkt_enabled(dhd_pub_t
*dhdp
) { return FALSE
; }
576 #endif /* DHD_PKTDUMP_ROAM */
578 #ifdef DHD_8021X_DUMP
580 dhd_dump_wsc_message(dhd_pub_t
*dhd
, int ifidx
, uint8
*pktdata
,
581 uint32 pktlen
, bool tx
, uint32
*pkthash
, uint16
*pktfate
)
583 eapol_header_t
*eapol_hdr
;
584 eap_header_fmt_t
*eap_hdr
;
585 eap_wsc_fmt_t
*eap_wsc
;
589 char seabuf
[ETHER_ADDR_STR_LEN
]="";
590 char deabuf
[ETHER_ADDR_STR_LEN
]="";
593 DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__
));
597 if (pktlen
< (ETHER_HDR_LEN
+ EAPOL_HDR_LEN
)) {
598 DHD_ERROR(("%s: invalid pkt length\n", __FUNCTION__
));
602 bcm_ether_ntoa((struct ether_addr
*)pktdata
, deabuf
);
603 bcm_ether_ntoa((struct ether_addr
*)(pktdata
+6), seabuf
);
605 eapol_hdr
= (eapol_header_t
*)pktdata
;
606 eap_hdr
= (eap_header_fmt_t
*)(eapol_hdr
->body
);
607 if (eap_hdr
->type
!= EAP_TYPE_EXP
) {
611 eap_len
= ntoh16(eap_hdr
->len
);
612 if (eap_len
< EAP_WSC_MIN_DATA_LEN
) {
616 eap_wsc
= (eap_wsc_fmt_t
*)(eap_hdr
->data
);
617 if (bcmp(eap_wsc
->oui
, (const uint8
*)WFA_VID
, WFA_VID_LEN
) ||
618 (ntoh32(eap_wsc
->ouitype
) != WFA_VTYPE
)) {
622 if (eap_wsc
->flags
) {
626 ifname
= dhd_ifname(dhd
, ifidx
);
627 cond
= (tx
&& pktfate
) ? FALSE
: TRUE
;
629 if (eap_wsc
->opcode
== WSC_OPCODE_MSG
) {
630 const uint8
*tlv_buf
= (const uint8
*)(eap_wsc
->data
);
633 uint16 wsc_data_len
= (uint16
)(eap_len
- EAP_HDR_LEN
- EAP_WSC_DATA_OFFSET
);
634 bcm_xtlv_opts_t opt
= BCM_XTLV_OPTION_IDBE
| BCM_XTLV_OPTION_LENBE
;
636 msg
= bcm_get_data_from_xtlv_buf(tlv_buf
, wsc_data_len
,
637 WSC_ATTR_MSG
, &msglen
, opt
);
641 dhd
->conf
->eapol_status
= EAPOL_STATUS_WPS_M1
;
642 DHD_STATLOG_DATA(dhd
, ST(WPS_M1
), ifidx
, tx
, cond
);
643 EAP_PRINT("EAP Packet, WPS M1");
646 dhd
->conf
->eapol_status
= EAPOL_STATUS_WPS_M2
;
647 DHD_STATLOG_DATA(dhd
, ST(WPS_M2
), ifidx
, tx
, cond
);
648 EAP_PRINT("EAP Packet, WPS M2");
651 dhd
->conf
->eapol_status
= EAPOL_STATUS_WPS_M3
;
652 DHD_STATLOG_DATA(dhd
, ST(WPS_M3
), ifidx
, tx
, cond
);
653 EAP_PRINT("EAP Packet, WPS M3");
656 dhd
->conf
->eapol_status
= EAPOL_STATUS_WPS_M4
;
657 DHD_STATLOG_DATA(dhd
, ST(WPS_M4
), ifidx
, tx
, cond
);
658 EAP_PRINT("EAP Packet, WPS M4");
661 dhd
->conf
->eapol_status
= EAPOL_STATUS_WPS_M5
;
662 DHD_STATLOG_DATA(dhd
, ST(WPS_M5
), ifidx
, tx
, cond
);
663 EAP_PRINT("EAP Packet, WPS M5");
666 dhd
->conf
->eapol_status
= EAPOL_STATUS_WPS_M6
;
667 DHD_STATLOG_DATA(dhd
, ST(WPS_M6
), ifidx
, tx
, cond
);
668 EAP_PRINT("EAP Packet, WPS M6");
671 dhd
->conf
->eapol_status
= EAPOL_STATUS_WPS_M7
;
672 DHD_STATLOG_DATA(dhd
, ST(WPS_M7
), ifidx
, tx
, cond
);
673 EAP_PRINT("EAP Packet, WPS M7");
676 dhd
->conf
->eapol_status
= EAPOL_STATUS_WPS_M8
;
677 DHD_STATLOG_DATA(dhd
, ST(WPS_M8
), ifidx
, tx
, cond
);
678 EAP_PRINT("EAP Packet, WPS M8");
684 } else if (eap_wsc
->opcode
== WSC_OPCODE_START
) {
685 dhd
->conf
->eapol_status
= EAPOL_STATUS_WSC_START
;
686 DHD_STATLOG_DATA(dhd
, ST(WSC_START
), ifidx
, tx
, cond
);
687 EAP_PRINT("EAP Packet, WSC Start");
688 } else if (eap_wsc
->opcode
== WSC_OPCODE_DONE
) {
689 dhd
->conf
->eapol_status
= EAPOL_STATUS_WSC_DONE
;
690 DHD_STATLOG_DATA(dhd
, ST(WSC_DONE
), ifidx
, tx
, cond
);
691 EAP_PRINT("EAP Packet, WSC Done");
696 dhd_dump_eap_packet(dhd_pub_t
*dhd
, int ifidx
, uint8
*pktdata
,
697 uint32 pktlen
, bool tx
, uint32
*pkthash
, uint16
*pktfate
)
699 eapol_header_t
*eapol_hdr
;
700 eap_header_fmt_t
*eap_hdr
;
703 char seabuf
[ETHER_ADDR_STR_LEN
]="";
704 char deabuf
[ETHER_ADDR_STR_LEN
]="";
707 DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__
));
711 bcm_ether_ntoa((struct ether_addr
*)pktdata
, deabuf
);
712 bcm_ether_ntoa((struct ether_addr
*)(pktdata
+6), seabuf
);
714 eapol_hdr
= (eapol_header_t
*)pktdata
;
715 eap_hdr
= (eap_header_fmt_t
*)(eapol_hdr
->body
);
716 ifname
= dhd_ifname(dhd
, ifidx
);
717 cond
= (tx
&& pktfate
) ? FALSE
: TRUE
;
719 if (eap_hdr
->code
== EAP_CODE_REQUEST
||
720 eap_hdr
->code
== EAP_CODE_RESPONSE
) {
721 bool isreq
= (eap_hdr
->code
== EAP_CODE_REQUEST
);
722 switch (eap_hdr
->type
) {
725 dhd
->conf
->eapol_status
= EAPOL_STATUS_REQID
;
726 DHD_STATLOG_DATA(dhd
, ST(EAP_REQ_IDENTITY
), ifidx
, tx
, cond
);
727 EAP_PRINT("EAP Packet, Request, Identity");
729 dhd
->conf
->eapol_status
= EAPOL_STATUS_RSPID
;
730 DHD_STATLOG_DATA(dhd
, ST(EAP_RESP_IDENTITY
), ifidx
, tx
, cond
);
731 EAP_PRINT("EAP Packet, Response, Identity");
736 DHD_STATLOG_DATA(dhd
, ST(EAP_REQ_TLS
), ifidx
, tx
, cond
);
737 EAP_PRINT("EAP Packet, Request, TLS");
739 DHD_STATLOG_DATA(dhd
, ST(EAP_RESP_TLS
), ifidx
, tx
, cond
);
740 EAP_PRINT("EAP Packet, Response, TLS");
745 DHD_STATLOG_DATA(dhd
, ST(EAP_REQ_LEAP
), ifidx
, tx
, cond
);
746 EAP_PRINT("EAP Packet, Request, LEAP");
748 DHD_STATLOG_DATA(dhd
, ST(EAP_RESP_LEAP
), ifidx
, tx
, cond
);
749 EAP_PRINT("EAP Packet, Response, LEAP");
754 DHD_STATLOG_DATA(dhd
, ST(EAP_REQ_TTLS
), ifidx
, tx
, cond
);
755 EAP_PRINT("EAP Packet, Request, TTLS");
757 DHD_STATLOG_DATA(dhd
, ST(EAP_RESP_TTLS
), ifidx
, tx
, cond
);
758 EAP_PRINT("EAP Packet, Response, TTLS");
763 DHD_STATLOG_DATA(dhd
, ST(EAP_REQ_AKA
), ifidx
, tx
, cond
);
764 EAP_PRINT("EAP Packet, Request, AKA");
766 DHD_STATLOG_DATA(dhd
, ST(EAP_RESP_AKA
), ifidx
, tx
, cond
);
767 EAP_PRINT("EAP Packet, Response, AKA");
772 DHD_STATLOG_DATA(dhd
, ST(EAP_REQ_PEAP
), ifidx
, tx
, cond
);
773 EAP_PRINT("EAP Packet, Request, PEAP");
775 DHD_STATLOG_DATA(dhd
, ST(EAP_RESP_PEAP
), ifidx
, tx
, cond
);
776 EAP_PRINT("EAP Packet, Response, PEAP");
781 DHD_STATLOG_DATA(dhd
, ST(EAP_REQ_FAST
), ifidx
, tx
, cond
);
782 EAP_PRINT("EAP Packet, Request, FAST");
784 DHD_STATLOG_DATA(dhd
, ST(EAP_RESP_FAST
), ifidx
, tx
, cond
);
785 EAP_PRINT("EAP Packet, Response, FAST");
790 DHD_STATLOG_DATA(dhd
, ST(EAP_REQ_PSK
), ifidx
, tx
, cond
);
791 EAP_PRINT("EAP Packet, Request, PSK");
793 DHD_STATLOG_DATA(dhd
, ST(EAP_RESP_PSK
), ifidx
, tx
, cond
);
794 EAP_PRINT("EAP Packet, Response, PSK");
799 DHD_STATLOG_DATA(dhd
, ST(EAP_REQ_AKAP
), ifidx
, tx
, cond
);
800 EAP_PRINT("EAP Packet, Request, AKAP");
802 DHD_STATLOG_DATA(dhd
, ST(EAP_RESP_AKAP
), ifidx
, tx
, cond
);
803 EAP_PRINT("EAP Packet, Response, AKAP");
807 dhd_dump_wsc_message(dhd
, ifidx
, pktdata
, pktlen
, tx
,
813 } else if (eap_hdr
->code
== EAP_CODE_SUCCESS
) {
814 DHD_STATLOG_DATA(dhd
, ST(EAP_SUCCESS
), ifidx
, tx
, cond
);
815 EAP_PRINT("EAP Packet, Success");
816 } else if (eap_hdr
->code
== EAP_CODE_FAILURE
) {
817 DHD_STATLOG_DATA(dhd
, ST(EAP_FAILURE
), ifidx
, tx
, cond
);
818 EAP_PRINT("EAP Packet, Failure");
823 dhd_dump_eapol_4way_message(dhd_pub_t
*dhd
, int ifidx
, uint8
*pktdata
, bool tx
,
824 uint32
*pkthash
, uint16
*pktfate
)
826 eapol_header_t
*eapol_hdr
;
827 eapol_key_hdr_t
*eap_key
;
831 char seabuf
[ETHER_ADDR_STR_LEN
]="";
832 char deabuf
[ETHER_ADDR_STR_LEN
]="";
835 DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__
));
839 bcm_ether_ntoa((struct ether_addr
*)pktdata
, deabuf
);
840 bcm_ether_ntoa((struct ether_addr
*)(pktdata
+6), seabuf
);
842 type
= dhd_is_4way_msg(pktdata
);
843 ifname
= dhd_ifname(dhd
, ifidx
);
844 eapol_hdr
= (eapol_header_t
*)pktdata
;
845 eap_key
= (eapol_key_hdr_t
*)(eapol_hdr
->body
);
846 cond
= (tx
&& pktfate
) ? FALSE
: TRUE
;
848 if (eap_key
->type
!= EAPOL_WPA2_KEY
) {
849 EAP_PRINT_OTHER("NON EAPOL_WPA2_KEY");
855 dhd
->conf
->eapol_status
= EAPOL_STATUS_4WAY_M1
;
856 DHD_STATLOG_DATA(dhd
, ST(EAPOL_M1
), ifidx
, tx
, cond
);
857 EAP_PRINT("EAPOL Packet, 4-way handshake, M1");
860 dhd
->conf
->eapol_status
= EAPOL_STATUS_4WAY_M2
;
861 DHD_STATLOG_DATA(dhd
, ST(EAPOL_M2
), ifidx
, tx
, cond
);
862 EAP_PRINT("EAPOL Packet, 4-way handshake, M2");
865 dhd
->conf
->eapol_status
= EAPOL_STATUS_4WAY_M3
;
866 DHD_STATLOG_DATA(dhd
, ST(EAPOL_M3
), ifidx
, tx
, cond
);
867 EAP_PRINT("EAPOL Packet, 4-way handshake, M3");
870 dhd
->conf
->eapol_status
= EAPOL_STATUS_4WAY_M4
;
871 DHD_STATLOG_DATA(dhd
, ST(EAPOL_M4
), ifidx
, tx
, cond
);
872 EAP_PRINT("EAPOL Packet, 4-way handshake, M4");
874 case EAPOL_GROUPKEY_M1
:
875 DHD_STATLOG_DATA(dhd
, ST(EAPOL_GROUPKEY_M1
), ifidx
, tx
, cond
);
876 EAP_PRINT_REPLAY("EAPOL Packet, GROUP Key handshake, M1");
878 case EAPOL_GROUPKEY_M2
:
879 DHD_STATLOG_DATA(dhd
, ST(EAPOL_GROUPKEY_M2
), ifidx
, tx
, cond
);
880 EAP_PRINT_REPLAY("EAPOL Packet, GROUP Key handshake, M2");
881 if (ifidx
== 0 && tx
&& pktfate
) {
882 dhd_dump_mod_pkt_timer(dhd
, PKT_CNT_RSN_GRPKEY_UP
);
886 DHD_STATLOG_DATA(dhd
, ST(8021X_OTHER
), ifidx
, tx
, cond
);
887 EAP_PRINT_OTHER("OTHER 4WAY");
893 dhd_dump_eapol_message(dhd_pub_t
*dhd
, int ifidx
, uint8
*pktdata
,
894 uint32 pktlen
, bool tx
, uint32
*pkthash
, uint16
*pktfate
)
897 eapol_header_t
*eapol_hdr
= (eapol_header_t
*)pktdata
;
899 char seabuf
[ETHER_ADDR_STR_LEN
]="";
900 char deabuf
[ETHER_ADDR_STR_LEN
]="";
903 DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__
));
907 bcm_ether_ntoa((struct ether_addr
*)pktdata
, deabuf
);
908 bcm_ether_ntoa((struct ether_addr
*)(pktdata
+6), seabuf
);
910 eapol_hdr
= (eapol_header_t
*)pktdata
;
911 ifname
= dhd_ifname(dhd
, ifidx
);
912 cond
= (tx
&& pktfate
) ? FALSE
: TRUE
;
914 if (eapol_hdr
->type
== EAP_PACKET
) {
915 dhd_dump_eap_packet(dhd
, ifidx
, pktdata
, pktlen
, tx
,
917 } else if (eapol_hdr
->type
== EAPOL_START
) {
918 DHD_STATLOG_DATA(dhd
, ST(EAPOL_START
), ifidx
, tx
, cond
);
919 EAP_PRINT("EAP Packet, EAPOL-Start");
920 } else if (eapol_hdr
->type
== EAPOL_KEY
) {
921 dhd_dump_eapol_4way_message(dhd
, ifidx
, pktdata
, tx
,
924 DHD_STATLOG_DATA(dhd
, ST(8021X_OTHER
), ifidx
, tx
, cond
);
925 EAP_PRINT_OTHER("OTHER 8021X");
928 #endif /* DHD_8021X_DUMP */
931 dhd_check_dhcp(uint8
*pktdata
)
933 hdr_fmt_t
*b
= (hdr_fmt_t
*)&pktdata
[ETHER_HDR_LEN
];
934 struct ipv4_hdr
*iph
= &b
->iph
;
936 /* check IP header */
937 if ((IPV4_HLEN(iph
) < IPV4_HLEN_MIN
) ||
938 IP_VER(iph
) != IP_VER_4
||
939 IPV4_PROT(iph
) != IP_PROT_UDP
) {
943 /* check UDP port for bootp (67, 68) */
944 if (b
->udph
.src_port
!= htons(DHCP_PORT_SERVER
) &&
945 b
->udph
.src_port
!= htons(DHCP_PORT_CLIENT
) &&
946 b
->udph
.dst_port
!= htons(DHCP_PORT_SERVER
) &&
947 b
->udph
.dst_port
!= htons(DHCP_PORT_CLIENT
)) {
951 /* check header length */
952 if (ntohs(iph
->tot_len
) < ntohs(b
->udph
.len
) + sizeof(struct bcmudp_hdr
)) {
959 #define BOOTP_CHADDR_LEN 16
960 #define BOOTP_SNAME_LEN 64
961 #define BOOTP_FILE_LEN 128
962 #define BOOTP_MIN_DHCP_OPT_LEN 312
963 #define BOOTP_MAGIC_COOKIE_LEN 4
965 #define DHCP_MSGTYPE_DISCOVER 1
966 #define DHCP_MSGTYPE_OFFER 2
967 #define DHCP_MSGTYPE_REQUEST 3
968 #define DHCP_MSGTYPE_DECLINE 4
969 #define DHCP_MSGTYPE_ACK 5
970 #define DHCP_MSGTYPE_NAK 6
971 #define DHCP_MSGTYPE_RELEASE 7
972 #define DHCP_MSGTYPE_INFORM 8
974 #define DHCP_PRINT(str) \
977 DHD_PKTDUMP(("[dhd-%s] " str " %8s[%8s] [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
978 ifname, typestr, opstr, tx?sabuf:dabuf, tx?seabuf:deabuf, \
979 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
980 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
982 DHD_PKTDUMP(("[dhd-%s] " str " %8s[%8s] [RX] : %s(%s) %s %s(%s)\n", \
983 ifname, typestr, opstr, tx?sabuf:dabuf, tx?seabuf:deabuf, \
984 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf)); \
988 typedef struct bootp_fmt
{
990 struct bcmudp_hdr udph
;
995 uint32 transaction_id
;
1002 uint8 hw_address
[BOOTP_CHADDR_LEN
];
1003 uint8 server_name
[BOOTP_SNAME_LEN
];
1004 uint8 file_name
[BOOTP_FILE_LEN
];
1005 uint8 options
[BOOTP_MIN_DHCP_OPT_LEN
];
1006 } PACKED_STRUCT bootp_fmt_t
;
1008 static const uint8 bootp_magic_cookie
[4] = { 99, 130, 83, 99 };
1009 static char dhcp_ops
[][10] = {
1010 "NA", "REQUEST", "REPLY"
1012 static char dhcp_types
[][10] = {
1013 "NA", "DISCOVER", "OFFER", "REQUEST", "DECLINE", "ACK", "NAK", "RELEASE", "INFORM"
1016 #ifdef DHD_STATUS_LOGGING
1017 static const int dhcp_types_stat
[9] = {
1018 ST(INVALID
), ST(DHCP_DISCOVER
), ST(DHCP_OFFER
), ST(DHCP_REQUEST
),
1019 ST(DHCP_DECLINE
), ST(DHCP_ACK
), ST(DHCP_NAK
), ST(DHCP_RELEASE
),
1022 #endif /* DHD_STATUS_LOGGING */
1025 dhd_dhcp_dump(dhd_pub_t
*dhdp
, int ifidx
, uint8
*pktdata
, bool tx
,
1026 uint32
*pkthash
, uint16
*pktfate
)
1028 bootp_fmt_t
*b
= (bootp_fmt_t
*)&pktdata
[ETHER_HDR_LEN
];
1029 struct ipv4_hdr
*iph
= &b
->iph
;
1030 uint8
*ptr
, *opt
, *end
= (uint8
*) b
+ ntohs(b
->iph
.tot_len
);
1031 int dhcp_type
= 0, len
, opt_len
;
1032 char *ifname
= NULL
, *typestr
= NULL
, *opstr
= NULL
;
1034 char sabuf
[20]="", dabuf
[20]="";
1035 char seabuf
[ETHER_ADDR_STR_LEN
]="";
1036 char deabuf
[ETHER_ADDR_STR_LEN
]="";
1038 if (!(dump_msg_level
& DUMP_DHCP_VAL
))
1040 bcm_ip_ntoa((struct ipv4_addr
*)iph
->src_ip
, sabuf
);
1041 bcm_ip_ntoa((struct ipv4_addr
*)iph
->dst_ip
, dabuf
);
1042 bcm_ether_ntoa((struct ether_addr
*)pktdata
, deabuf
);
1043 bcm_ether_ntoa((struct ether_addr
*)(pktdata
+6), seabuf
);
1045 ifname
= dhd_ifname(dhdp
, ifidx
);
1046 cond
= (tx
&& pktfate
) ? FALSE
: TRUE
;
1047 len
= ntohs(b
->udph
.len
) - sizeof(struct bcmudp_hdr
);
1048 opt_len
= len
- (sizeof(*b
) - sizeof(struct ipv4_hdr
) -
1049 sizeof(struct bcmudp_hdr
) - sizeof(b
->options
));
1051 /* parse bootp options */
1052 if (opt_len
>= BOOTP_MAGIC_COOKIE_LEN
&&
1053 !memcmp(b
->options
, bootp_magic_cookie
, BOOTP_MAGIC_COOKIE_LEN
)) {
1054 ptr
= &b
->options
[BOOTP_MAGIC_COOKIE_LEN
];
1055 while (ptr
< end
&& *ptr
!= 0xff) {
1064 if (*opt
== DHCP_OPT_MSGTYPE
) {
1067 typestr
= dhcp_types
[dhcp_type
];
1068 opstr
= dhcp_ops
[b
->op
];
1069 DHD_STATLOG_DATA(dhdp
, dhcp_types_stat
[dhcp_type
],
1078 #endif /* DHD_DHCP_DUMP */
1081 dhd_check_icmp(uint8
*pktdata
)
1083 uint8
*pkt
= (uint8
*)&pktdata
[ETHER_HDR_LEN
];
1084 struct ipv4_hdr
*iph
= (struct ipv4_hdr
*)pkt
;
1086 /* check IP header */
1087 if ((IPV4_HLEN(iph
) < IPV4_HLEN_MIN
) ||
1088 IP_VER(iph
) != IP_VER_4
||
1089 IPV4_PROT(iph
) != IP_PROT_ICMP
) {
1093 /* check header length */
1094 if (ntohs(iph
->tot_len
) - IPV4_HLEN(iph
) < sizeof(struct bcmicmp_hdr
)) {
1100 #ifdef DHD_ICMP_DUMP
1101 #define ICMP_TYPE_DEST_UNREACH 3
1102 #define ICMP_ECHO_SEQ_OFFSET 6
1103 #define ICMP_ECHO_SEQ(h) (*(uint16 *)((uint8 *)(h) + (ICMP_ECHO_SEQ_OFFSET)))
1104 #define ICMP_PING_PRINT(str) \
1107 DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) SEQNUM=%d" \
1108 TXFATE_FMT"\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1109 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, seqnum, \
1110 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1112 DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] : %s(%s) %s %s(%s) SEQNUM=%d\n", \
1113 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1114 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, seqnum)); \
1118 #define ICMP_PRINT(str) \
1121 DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) TYPE=%d, CODE=%d" \
1122 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1123 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, type, code, \
1124 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1126 DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] : %s(%s) %s %s(%s) TYPE=%d," \
1127 " CODE=%d\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1128 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, type, code)); \
1133 dhd_icmp_dump(dhd_pub_t
*dhdp
, int ifidx
, uint8
*pktdata
, bool tx
,
1134 uint32
*pkthash
, uint16
*pktfate
)
1136 uint8
*pkt
= (uint8
*)&pktdata
[ETHER_HDR_LEN
];
1137 struct ipv4_hdr
*iph
= (struct ipv4_hdr
*)pkt
;
1138 struct bcmicmp_hdr
*icmph
;
1141 uint16 seqnum
, type
, code
;
1142 char sabuf
[20]="", dabuf
[20]="";
1143 char seabuf
[ETHER_ADDR_STR_LEN
]="";
1144 char deabuf
[ETHER_ADDR_STR_LEN
]="";
1146 if (!(dump_msg_level
& DUMP_ICMP_VAL
))
1149 ifname
= dhd_ifname(dhdp
, ifidx
);
1150 cond
= (tx
&& pktfate
) ? FALSE
: TRUE
;
1151 icmph
= (struct bcmicmp_hdr
*)((uint8
*)pkt
+ sizeof(struct ipv4_hdr
));
1155 bcm_ip_ntoa((struct ipv4_addr
*)iph
->src_ip
, sabuf
);
1156 bcm_ip_ntoa((struct ipv4_addr
*)iph
->dst_ip
, dabuf
);
1157 bcm_ether_ntoa((struct ether_addr
*)pktdata
, deabuf
);
1158 bcm_ether_ntoa((struct ether_addr
*)(pktdata
+6), seabuf
);
1159 if (type
== ICMP_TYPE_ECHO_REQUEST
) {
1160 seqnum
= ntoh16(ICMP_ECHO_SEQ(icmph
));
1161 DHD_STATLOG_DATA(dhdp
, ST(ICMP_PING_REQ
), ifidx
, tx
, cond
);
1162 ICMP_PING_PRINT("PING REQUEST");
1163 } else if (type
== ICMP_TYPE_ECHO_REPLY
) {
1164 seqnum
= ntoh16(ICMP_ECHO_SEQ(icmph
));
1165 DHD_STATLOG_DATA(dhdp
, ST(ICMP_PING_RESP
), ifidx
, tx
, cond
);
1166 ICMP_PING_PRINT("PING REPLY ");
1167 } else if (type
== ICMP_TYPE_DEST_UNREACH
) {
1168 DHD_STATLOG_DATA(dhdp
, ST(ICMP_DEST_UNREACH
), ifidx
, tx
, cond
);
1169 ICMP_PRINT("ICMP DEST UNREACH");
1171 DHD_STATLOG_DATA(dhdp
, ST(ICMP_OTHER
), ifidx
, tx
, cond
);
1172 ICMP_PRINT("ICMP OTHER");
1175 #endif /* DHD_ICMP_DUMP */
1178 dhd_check_arp(uint8
*pktdata
)
1180 uint8
*pkt
= (uint8
*)&pktdata
[ETHER_HDR_LEN
];
1181 struct bcmarp
*arph
= (struct bcmarp
*)pkt
;
1183 /* validation check */
1184 if (arph
->htype
!= hton16(HTYPE_ETHERNET
) ||
1185 arph
->hlen
!= ETHER_ADDR_LEN
||
1194 /* On Hikey, due to continuous ARP prints
1195 * DPC not scheduled. Hence rate limit the prints.
1197 #define DHD_PKTDUMP_ARP DHD_ERROR_RLMT
1199 #define DHD_PKTDUMP_ARP DHD_PKTDUMP
1200 #endif /* BOARD_HIKEY */
1202 #define ARP_PRINT(str) \
1205 if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
1206 DHD_PKTDUMP(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
1207 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1208 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
1209 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1211 DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
1212 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1213 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
1214 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1217 DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] : %s(%s) %s %s(%s)\n", \
1218 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1219 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf)); \
1223 #define ARP_PRINT_OTHER(str) \
1226 if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
1227 DHD_PKTDUMP(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) op_code=%d" \
1228 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1229 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode, \
1230 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1232 DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) op_code=%d" \
1233 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1234 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode, \
1235 TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1238 DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] : %s(%s) %s %s(%s) op_code=%d\n", \
1239 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1240 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode)); \
1245 dhd_arp_dump(dhd_pub_t
*dhdp
, int ifidx
, uint8
*pktdata
, bool tx
,
1246 uint32
*pkthash
, uint16
*pktfate
)
1248 uint8
*pkt
= (uint8
*)&pktdata
[ETHER_HDR_LEN
];
1249 struct bcmarp
*arph
= (struct bcmarp
*)pkt
;
1252 bool cond
, dump_enabled
;
1253 char sabuf
[20]="", dabuf
[20]="";
1254 char seabuf
[ETHER_ADDR_STR_LEN
]="";
1255 char deabuf
[ETHER_ADDR_STR_LEN
]="";
1257 if (!(dump_msg_level
& DUMP_ARP_VAL
))
1260 ifname
= dhd_ifname(dhdp
, ifidx
);
1261 opcode
= ntoh16(arph
->oper
);
1262 cond
= (tx
&& pktfate
) ? FALSE
: TRUE
;
1263 dump_enabled
= dhd_dump_pkt_enabled(dhdp
);
1264 bcm_ip_ntoa((struct ipv4_addr
*)arph
->src_ip
, sabuf
);
1265 bcm_ip_ntoa((struct ipv4_addr
*)arph
->dst_ip
, dabuf
);
1266 bcm_ether_ntoa((struct ether_addr
*)arph
->dst_eth
, deabuf
);
1267 bcm_ether_ntoa((struct ether_addr
*)arph
->src_eth
, seabuf
);
1268 if (opcode
== ARP_OPC_REQUEST
) {
1269 DHD_STATLOG_DATA(dhdp
, ST(ARP_REQ
), ifidx
, tx
, cond
);
1270 ARP_PRINT("ARP REQUEST ");
1271 } else if (opcode
== ARP_OPC_REPLY
) {
1272 DHD_STATLOG_DATA(dhdp
, ST(ARP_RESP
), ifidx
, tx
, cond
);
1273 ARP_PRINT("ARP RESPONSE");
1275 ARP_PRINT_OTHER("ARP OTHER");
1279 dhd_dump_pkt_cnts_inc(dhdp
, tx
, pktfate
, PKT_CNT_TYPE_ARP
);
1282 #endif /* DHD_ARP_DUMP */
1285 dhd_check_dns(uint8
*pktdata
)
1287 hdr_fmt_t
*dnsh
= (hdr_fmt_t
*)&pktdata
[ETHER_HDR_LEN
];
1288 struct ipv4_hdr
*iph
= &dnsh
->iph
;
1290 /* check IP header */
1291 if ((IPV4_HLEN(iph
) < IPV4_HLEN_MIN
) ||
1292 IP_VER(iph
) != IP_VER_4
||
1293 IPV4_PROT(iph
) != IP_PROT_UDP
) {
1297 /* check UDP port for DNS */
1298 if (dnsh
->udph
.src_port
!= hton16(UDP_PORT_DNS
) &&
1299 dnsh
->udph
.dst_port
!= hton16(UDP_PORT_DNS
)) {
1303 /* check header length */
1304 if (ntoh16(iph
->tot_len
) < (ntoh16(dnsh
->udph
.len
) +
1305 sizeof(struct bcmudp_hdr
))) {
1312 typedef struct dns_fmt
{
1313 struct ipv4_hdr iph
;
1314 struct bcmudp_hdr udph
;
1321 } PACKED_STRUCT dns_fmt_t
;
1323 #define DNS_QR_LOC 15
1324 #define DNS_OPCODE_LOC 11
1325 #define DNS_RCODE_LOC 0
1326 #define DNS_QR_MASK ((0x1) << (DNS_QR_LOC))
1327 #define DNS_OPCODE_MASK ((0xF) << (DNS_OPCODE_LOC))
1328 #define DNS_RCODE_MASK ((0xF) << (DNS_RCODE_LOC))
1329 #define GET_DNS_QR(flags) (((flags) & (DNS_QR_MASK)) >> (DNS_QR_LOC))
1330 #define GET_DNS_OPCODE(flags) (((flags) & (DNS_OPCODE_MASK)) >> (DNS_OPCODE_LOC))
1331 #define GET_DNS_RCODE(flags) (((flags) & (DNS_RCODE_MASK)) >> (DNS_RCODE_LOC))
1332 #define DNS_UNASSIGNED_OPCODE(flags) ((GET_DNS_OPCODE(flags) >= (6)))
1334 static const char dns_opcode_types
[][11] = {
1335 "QUERY", "IQUERY", "STATUS", "UNASSIGNED", "NOTIFY", "UPDATE"
1338 #define DNSOPCODE(op) \
1339 (DNS_UNASSIGNED_OPCODE(flags) ? "UNASSIGNED" : dns_opcode_types[op])
1341 #define DNS_REQ_PRINT(str) \
1344 if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
1345 DHD_PKTDUMP(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s" \
1346 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1347 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
1348 id, DNSOPCODE(opcode), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1350 DHD_PKTDUMP_MEM(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s" \
1351 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1352 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
1353 id, DNSOPCODE(opcode), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1356 DHD_PKTDUMP_MEM(("[dhd-%s] " str " [RX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s\n", \
1357 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, tx?"->":"<-", \
1358 tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode))); \
1362 #define DNS_RESP_PRINT(str) \
1365 if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
1366 DHD_PKTDUMP(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d" \
1367 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1368 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode), \
1369 GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1371 DHD_PKTDUMP_MEM(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d" \
1372 TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1373 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode), \
1374 GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
1377 DHD_PKTDUMP_MEM(("[dhd-%s] " str " [RX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d\n", \
1378 ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
1379 tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
1380 id, DNSOPCODE(opcode), GET_DNS_RCODE(flags))); \
1385 dhd_dns_dump(dhd_pub_t
*dhdp
, int ifidx
, uint8
*pktdata
, bool tx
,
1386 uint32
*pkthash
, uint16
*pktfate
)
1388 dns_fmt_t
*dnsh
= (dns_fmt_t
*)&pktdata
[ETHER_HDR_LEN
];
1389 struct ipv4_hdr
*iph
= &dnsh
->iph
;
1390 uint16 flags
, opcode
, id
;
1392 bool cond
, dump_enabled
;
1393 char sabuf
[20]="", dabuf
[20]="";
1394 char seabuf
[ETHER_ADDR_STR_LEN
]="";
1395 char deabuf
[ETHER_ADDR_STR_LEN
]="";
1397 if (!(dump_msg_level
& DUMP_DNS_VAL
))
1400 ifname
= dhd_ifname(dhdp
, ifidx
);
1401 cond
= (tx
&& pktfate
) ? FALSE
: TRUE
;
1402 dump_enabled
= dhd_dump_pkt_enabled(dhdp
);
1403 flags
= hton16(dnsh
->flags
);
1404 opcode
= GET_DNS_OPCODE(flags
);
1405 id
= hton16(dnsh
->id
);
1406 bcm_ip_ntoa((struct ipv4_addr
*)iph
->src_ip
, sabuf
);
1407 bcm_ip_ntoa((struct ipv4_addr
*)iph
->dst_ip
, dabuf
);
1408 bcm_ether_ntoa((struct ether_addr
*)pktdata
, deabuf
);
1409 bcm_ether_ntoa((struct ether_addr
*)(pktdata
+6), seabuf
);
1410 if (GET_DNS_QR(flags
)) {
1412 DHD_STATLOG_DATA(dhdp
, ST(DNS_RESP
), ifidx
, tx
, cond
);
1413 DNS_RESP_PRINT("DNS RESPONSE");
1416 DHD_STATLOG_DATA(dhdp
, ST(DNS_QUERY
), ifidx
, tx
, cond
);
1417 DNS_REQ_PRINT("DNS REQUEST");
1421 dhd_dump_pkt_cnts_inc(dhdp
, tx
, pktfate
, PKT_CNT_TYPE_DNS
);
1424 #endif /* DHD_DNS_DUMP */
1428 dhd_trx_pkt_dump(dhd_pub_t
*dhdp
, int ifidx
, uint8
*pktdata
, uint32 pktlen
, bool tx
)
1430 struct ether_header
*eh
;
1432 char *pkttype
= "UNKNOWN";
1434 if (!(dump_msg_level
& DUMP_TRX_VAL
))
1438 DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__
));
1443 DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__
));
1447 eh
= (struct ether_header
*)pktdata
;
1448 protocol
= hton16(eh
->ether_type
);
1449 BCM_REFERENCE(pktlen
);
1455 case ETHER_TYPE_ARP
:
1458 case ETHER_TYPE_BRCM
:
1461 case ETHER_TYPE_802_1X
:
1464 case ETHER_TYPE_WAI
:
1471 if (protocol
!= ETHER_TYPE_BRCM
) {
1472 if (pktdata
[0] == 0xFF) {
1473 DHD_PKTDUMP(("[dhd-%s] %s BROADCAST DUMP - %s\n",
1474 dhd_ifname(dhdp
, ifidx
), tx
?"TX":"RX", pkttype
));
1475 } else if (pktdata
[0] & 1) {
1476 DHD_PKTDUMP(("[dhd-%s] %s MULTICAST DUMP " MACDBG
" - %s\n",
1477 dhd_ifname(dhdp
, ifidx
), tx
?"TX":"RX", MAC2STRDBG(pktdata
), pkttype
));
1479 DHD_PKTDUMP(("[dhd-%s] %s DUMP - %s\n",
1480 dhd_ifname(dhdp
, ifidx
), tx
?"TX":"RX", pkttype
));
1482 #ifdef DHD_RX_FULL_DUMP
1483 prhex("Data", pktdata
, pktlen
);
1484 #endif /* DHD_RX_FULL_DUMP */
1487 DHD_PKTDUMP(("[dhd-%s] %s DUMP - %s\n",
1488 dhd_ifname(dhdp
, ifidx
), tx
?"TX":"RX", pkttype
));
1491 #endif /* DHD_RX_DUMP */