1 | /* $Id: VBoxPktDmp.h 82968 2020-02-04 10:35:17Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * VBoxPktDmp.h - Dump Ethernet frame into debug log.
|
---|
4 | */
|
---|
5 |
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2016-2020 Oracle Corporation
|
---|
8 | *
|
---|
9 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
10 | * available from http://www.virtualbox.org. This file is free software;
|
---|
11 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
12 | * General Public License (GPL) as published by the Free Software
|
---|
13 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
14 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
15 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
16 | *
|
---|
17 | * The contents of this file may alternatively be used under the terms
|
---|
18 | * of the Common Development and Distribution License Version 1.0
|
---|
19 | * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
|
---|
20 | * VirtualBox OSE distribution, in which case the provisions of the
|
---|
21 | * CDDL are applicable instead of those of the GPL.
|
---|
22 | *
|
---|
23 | * You may elect to license modified versions of this file under the
|
---|
24 | * terms and conditions of either the GPL or the CDDL or both.
|
---|
25 | */
|
---|
26 |
|
---|
27 | #ifndef VBOX_INCLUDED_VBoxPktDmp_h
|
---|
28 | #define VBOX_INCLUDED_VBoxPktDmp_h
|
---|
29 | #ifndef RT_WITHOUT_PRAGMA_ONCE
|
---|
30 | # pragma once
|
---|
31 | #endif
|
---|
32 |
|
---|
33 | #include <iprt/net.h>
|
---|
34 | #include <iprt/log.h>
|
---|
35 | #if defined(LOG_ENABLED) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
|
---|
36 | # include <iprt/asm.h>
|
---|
37 | #endif
|
---|
38 |
|
---|
39 |
|
---|
40 | DECLINLINE(const char *) vboxEthTypeStr(uint16_t uType)
|
---|
41 | {
|
---|
42 | switch (uType)
|
---|
43 | {
|
---|
44 | case RTNET_ETHERTYPE_IPV4: return "IP";
|
---|
45 | case RTNET_ETHERTYPE_IPV6: return "IPv6";
|
---|
46 | case RTNET_ETHERTYPE_ARP: return "ARP";
|
---|
47 | }
|
---|
48 | return "unknown";
|
---|
49 | }
|
---|
50 |
|
---|
51 |
|
---|
52 | DECLINLINE(void) vboxEthPacketDump(const char *pcszInstance, const char *pcszText, const uint8_t *pcPacket, uint32_t cb)
|
---|
53 | {
|
---|
54 | #if defined(LOG_ENABLED) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
|
---|
55 | AssertReturnVoid(cb >= 14);
|
---|
56 |
|
---|
57 | const uint8_t *pHdr = pcPacket;
|
---|
58 | const uint8_t *pEnd = pcPacket + cb;
|
---|
59 | AssertReturnVoid(pEnd - pHdr >= 14);
|
---|
60 | uint16_t uEthType = RT_N2H_U16(*(uint16_t*)(pHdr+12));
|
---|
61 | Log2(("%s: %s (%d bytes), %RTmac => %RTmac, EthType=%s(0x%x)\n", pcszInstance,
|
---|
62 | pcszText, cb, pHdr+6, pHdr, vboxEthTypeStr(uEthType), uEthType));
|
---|
63 | pHdr += sizeof(RTNETETHERHDR);
|
---|
64 | if (uEthType == RTNET_ETHERTYPE_VLAN)
|
---|
65 | {
|
---|
66 | AssertReturnVoid(pEnd - pHdr >= 4);
|
---|
67 | uEthType = RT_N2H_U16(*(uint16_t*)(pHdr+2));
|
---|
68 | Log2((" + VLAN: id=%d EthType=%s(0x%x)\n", RT_N2H_U16(*(uint16_t*)(pHdr)) & 0xFFF,
|
---|
69 | vboxEthTypeStr(uEthType), uEthType));
|
---|
70 | pHdr += 2 * sizeof(uint16_t);
|
---|
71 | }
|
---|
72 | uint8_t uProto = 0xFF;
|
---|
73 | switch (uEthType)
|
---|
74 | {
|
---|
75 | case RTNET_ETHERTYPE_IPV6:
|
---|
76 | AssertReturnVoid(pEnd - pHdr >= 40);
|
---|
77 | uProto = pHdr[6];
|
---|
78 | Log2((" + IPv6: %RTnaipv6 => %RTnaipv6\n", pHdr+8, pHdr+24));
|
---|
79 | pHdr += 40;
|
---|
80 | break;
|
---|
81 | case RTNET_ETHERTYPE_IPV4:
|
---|
82 | AssertReturnVoid(pEnd - pHdr >= 20);
|
---|
83 | uProto = pHdr[9];
|
---|
84 | Log2((" + IP: %RTnaipv4 => %RTnaipv4\n", *(uint32_t*)(pHdr+12), *(uint32_t*)(pHdr+16)));
|
---|
85 | pHdr += (pHdr[0] & 0xF) * 4;
|
---|
86 | break;
|
---|
87 | case RTNET_ETHERTYPE_ARP:
|
---|
88 | AssertReturnVoid(pEnd - pHdr >= 28);
|
---|
89 | AssertReturnVoid(RT_N2H_U16(*(uint16_t*)(pHdr+2)) == RTNET_ETHERTYPE_IPV4);
|
---|
90 | switch (RT_N2H_U16(*(uint16_t*)(pHdr+6)))
|
---|
91 | {
|
---|
92 | case 1: /* ARP request */
|
---|
93 | Log2((" + ARP-REQ: who-has %RTnaipv4 tell %RTnaipv4\n",
|
---|
94 | *(uint32_t*)(pHdr+24), *(uint32_t*)(pHdr+14)));
|
---|
95 | break;
|
---|
96 | case 2: /* ARP reply */
|
---|
97 | Log2((" + ARP-RPL: %RTnaipv4 is-at %RTmac\n",
|
---|
98 | *(uint32_t*)(pHdr+14), pHdr+8));
|
---|
99 | break;
|
---|
100 | default:
|
---|
101 | Log2((" + ARP: unknown op %d\n", RT_N2H_U16(*(uint16_t*)(pHdr+6))));
|
---|
102 | break;
|
---|
103 | }
|
---|
104 | break;
|
---|
105 | /* There is no default case as uProto is initialized with 0xFF */
|
---|
106 | }
|
---|
107 | while (uProto != 0xFF)
|
---|
108 | {
|
---|
109 | switch (uProto)
|
---|
110 | {
|
---|
111 | case 0: /* IPv6 Hop-by-Hop option*/
|
---|
112 | case 60: /* IPv6 Destination option*/
|
---|
113 | case 43: /* IPv6 Routing option */
|
---|
114 | case 44: /* IPv6 Fragment option */
|
---|
115 | Log2((" + IPv6 option (%d): <not implemented>\n", uProto));
|
---|
116 | uProto = pHdr[0];
|
---|
117 | pHdr += pHdr[1] * 8 + 8; /* Skip to the next extension/protocol */
|
---|
118 | break;
|
---|
119 | case 51: /* IPv6 IPsec AH */
|
---|
120 | Log2((" + IPv6 IPsec AH: <not implemented>\n"));
|
---|
121 | uProto = pHdr[0];
|
---|
122 | pHdr += (pHdr[1] + 2) * 4; /* Skip to the next extension/protocol */
|
---|
123 | break;
|
---|
124 | case 50: /* IPv6 IPsec ESP */
|
---|
125 | /* Cannot decode IPsec, fall through */
|
---|
126 | Log2((" + IPv6 IPsec ESP: <not implemented>\n"));
|
---|
127 | uProto = 0xFF;
|
---|
128 | break;
|
---|
129 | case 59: /* No Next Header */
|
---|
130 | Log2((" + IPv6 No Next Header\n"));
|
---|
131 | uProto = 0xFF;
|
---|
132 | break;
|
---|
133 | case 58: /* IPv6-ICMP */
|
---|
134 | switch (pHdr[0])
|
---|
135 | {
|
---|
136 | case 1: Log2((" + IPv6-ICMP: destination unreachable, code %d\n", pHdr[1])); break;
|
---|
137 | case 128: Log2((" + IPv6-ICMP: echo request\n")); break;
|
---|
138 | case 129: Log2((" + IPv6-ICMP: echo reply\n")); break;
|
---|
139 | default: Log2((" + IPv6-ICMP: unknown type %d, code %d\n", pHdr[0], pHdr[1])); break;
|
---|
140 | }
|
---|
141 | uProto = 0xFF;
|
---|
142 | break;
|
---|
143 | case 1: /* ICMP */
|
---|
144 | switch (pHdr[0])
|
---|
145 | {
|
---|
146 | case 0: Log2((" + ICMP: echo reply\n")); break;
|
---|
147 | case 8: Log2((" + ICMP: echo request\n")); break;
|
---|
148 | case 3: Log2((" + ICMP: destination unreachable, code %d\n", pHdr[1])); break;
|
---|
149 | default: Log2((" + ICMP: unknown type %d, code %d\n", pHdr[0], pHdr[1])); break;
|
---|
150 | }
|
---|
151 | uProto = 0xFF;
|
---|
152 | break;
|
---|
153 | case 6: /* TCP */
|
---|
154 | Log2((" + TCP: src=%d dst=%d seq=%x ack=%x\n",
|
---|
155 | RT_N2H_U16(*(uint16_t*)(pHdr)), RT_N2H_U16(*(uint16_t*)(pHdr+2)),
|
---|
156 | RT_N2H_U32(*(uint32_t*)(pHdr+4)), RT_N2H_U32(*(uint32_t*)(pHdr+8))));
|
---|
157 | uProto = 0xFF;
|
---|
158 | break;
|
---|
159 | case 17: /* UDP */
|
---|
160 | Log2((" + UDP: src=%d dst=%d\n",
|
---|
161 | RT_N2H_U16(*(uint16_t*)(pHdr)), RT_N2H_U16(*(uint16_t*)(pHdr+2))));
|
---|
162 | uProto = 0xFF;
|
---|
163 | break;
|
---|
164 | default:
|
---|
165 | Log2((" + Unknown: proto=0x%x\n", uProto));
|
---|
166 | uProto = 0xFF;
|
---|
167 | break;
|
---|
168 | }
|
---|
169 | }
|
---|
170 | Log3(("%.*Rhxd\n", cb, pcPacket));
|
---|
171 | #else
|
---|
172 | RT_NOREF4(pcszInstance, pcszText, pcPacket, cb);
|
---|
173 | #endif
|
---|
174 | }
|
---|
175 |
|
---|
176 | #endif /* !VBOX_INCLUDED_VBoxPktDmp_h */
|
---|