/src/PcapPlusPlus/Packet++/src/UdpLayer.cpp
Line | Count | Source |
1 | 135k | #define LOG_MODULE PacketLogModuleUdpLayer |
2 | | |
3 | | #include "EndianPortable.h" |
4 | | #include "UdpLayer.h" |
5 | | #include "PayloadLayer.h" |
6 | | #include "IPv4Layer.h" |
7 | | #include "IPv6Layer.h" |
8 | | #include "DnsLayer.h" |
9 | | #include "DhcpLayer.h" |
10 | | #include "DhcpV6Layer.h" |
11 | | #include "DoIpLayer.h" |
12 | | #include "VxlanLayer.h" |
13 | | #include "SipLayer.h" |
14 | | #include "RadiusLayer.h" |
15 | | #include "GtpLayer.h" |
16 | | #include "NtpLayer.h" |
17 | | #include "SomeIpLayer.h" |
18 | | #include "WakeOnLanLayer.h" |
19 | | #include "WireGuardLayer.h" |
20 | | #include "PacketUtils.h" |
21 | | #include "Logger.h" |
22 | | #include <sstream> |
23 | | |
24 | | namespace pcpp |
25 | | { |
26 | | |
27 | | UdpLayer::UdpLayer(uint16_t portSrc, uint16_t portDst) |
28 | 0 | { |
29 | 0 | const size_t headerLen = sizeof(udphdr); |
30 | 0 | m_DataLen = headerLen; |
31 | 0 | m_Data = new uint8_t[headerLen]; |
32 | 0 | memset(m_Data, 0, headerLen); |
33 | 0 | udphdr* udpHdr = reinterpret_cast<udphdr*>(m_Data); |
34 | 0 | udpHdr->portDst = htobe16(portDst); |
35 | 0 | udpHdr->portSrc = htobe16(portSrc); |
36 | 0 | m_Protocol = UDP; |
37 | 0 | } |
38 | | |
39 | | uint16_t UdpLayer::getSrcPort() const |
40 | 511k | { |
41 | 511k | return be16toh(getUdpHeader()->portSrc); |
42 | 511k | } |
43 | | |
44 | | uint16_t UdpLayer::getDstPort() const |
45 | 511k | { |
46 | 511k | return be16toh(getUdpHeader()->portDst); |
47 | 511k | } |
48 | | |
49 | | uint16_t UdpLayer::calculateChecksum(bool writeResultToPacket) |
50 | 67.6k | { |
51 | 67.6k | udphdr* udpHdr = reinterpret_cast<udphdr*>(m_Data); |
52 | 67.6k | uint16_t checksumRes = 0; |
53 | 67.6k | uint16_t currChecksumValue = udpHdr->headerChecksum; |
54 | | |
55 | 67.6k | if (m_PrevLayer != nullptr) |
56 | 67.6k | { |
57 | 67.6k | udpHdr->headerChecksum = 0; |
58 | 67.6k | PCPP_LOG_DEBUG("UDP data len = " << m_DataLen); |
59 | | |
60 | 67.6k | if (m_PrevLayer->getProtocol() == IPv4) |
61 | 65.1k | { |
62 | 65.1k | IPv4Address srcIP = static_cast<IPv4Layer*>(m_PrevLayer)->getSrcIPv4Address(); |
63 | 65.1k | IPv4Address dstIP = static_cast<IPv4Layer*>(m_PrevLayer)->getDstIPv4Address(); |
64 | | |
65 | 65.1k | checksumRes = pcpp::computePseudoHdrChecksum((uint8_t*)udpHdr, getDataLen(), IPAddress::IPv4AddressType, |
66 | 65.1k | PACKETPP_IPPROTO_UDP, srcIP, dstIP); |
67 | | |
68 | 65.1k | PCPP_LOG_DEBUG("calculated IPv4 UDP checksum = 0x" << std::uppercase << std::hex << checksumRes); |
69 | 65.1k | } |
70 | 2.46k | else if (m_PrevLayer->getProtocol() == IPv6) |
71 | 2.41k | { |
72 | 2.41k | IPv6Address srcIP = static_cast<IPv6Layer*>(m_PrevLayer)->getSrcIPv6Address(); |
73 | 2.41k | IPv6Address dstIP = static_cast<IPv6Layer*>(m_PrevLayer)->getDstIPv6Address(); |
74 | | |
75 | 2.41k | checksumRes = computePseudoHdrChecksum((uint8_t*)udpHdr, getDataLen(), IPAddress::IPv6AddressType, |
76 | 2.41k | PACKETPP_IPPROTO_UDP, srcIP, dstIP); |
77 | | |
78 | 2.41k | PCPP_LOG_DEBUG("calculated IPv6 UDP checksum = 0xX" << std::uppercase << std::hex << checksumRes); |
79 | 2.41k | } |
80 | 67.6k | } |
81 | | |
82 | 67.6k | if (checksumRes == 0) |
83 | 209 | checksumRes = 0xffff; |
84 | | |
85 | 67.6k | if (writeResultToPacket) |
86 | 67.6k | udpHdr->headerChecksum = htobe16(checksumRes); |
87 | 0 | else |
88 | 0 | udpHdr->headerChecksum = currChecksumValue; |
89 | | |
90 | 67.6k | return checksumRes; |
91 | 67.6k | } |
92 | | |
93 | | void UdpLayer::parseNextLayer() |
94 | 377k | { |
95 | 377k | if (m_DataLen <= sizeof(udphdr)) |
96 | 732 | return; |
97 | | |
98 | 376k | uint16_t portDst = getDstPort(); |
99 | 376k | uint16_t portSrc = getSrcPort(); |
100 | | |
101 | 376k | uint8_t* udpData = m_Data + sizeof(udphdr); |
102 | 376k | size_t udpDataLen = m_DataLen - sizeof(udphdr); |
103 | | |
104 | 376k | if (DhcpLayer::isDhcpPorts(portSrc, portDst)) |
105 | 18.5k | { |
106 | 18.5k | constructNextLayer<DhcpLayer>(udpData, udpDataLen); |
107 | 18.5k | } |
108 | 357k | else if (VxlanLayer::isVxlanPort(portDst)) |
109 | 9.90k | { |
110 | 9.90k | constructNextLayer<VxlanLayer>(udpData, udpDataLen); |
111 | 9.90k | } |
112 | 347k | else if (DnsLayer::isDataValid(udpData, udpDataLen) && |
113 | 339k | (DnsLayer::isDnsPort(portDst) || DnsLayer::isDnsPort(portSrc))) |
114 | 86.1k | { |
115 | 86.1k | constructNextLayer<DnsLayer>(udpData, udpDataLen); |
116 | 86.1k | } |
117 | 261k | else if (SipLayer::isSipPort(portDst) || SipLayer::isSipPort(portSrc)) |
118 | 36.5k | { |
119 | | // Resolves the overload of parseSipLayer, without static_casting a function pointer. |
120 | 36.5k | auto* (*fac)(uint8_t*, size_t, Layer*, Packet*, uint16_t, uint16_t) = SipLayer::parseSipLayer; |
121 | 36.5k | tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(fac, udpData, udpDataLen, portSrc, portDst); |
122 | 36.5k | } |
123 | 225k | else if ((RadiusLayer::isRadiusPort(portDst) || RadiusLayer::isRadiusPort(portSrc)) && |
124 | 25.7k | RadiusLayer::isDataValid(udpData, udpDataLen)) |
125 | 22.4k | { |
126 | 22.4k | constructNextLayer<RadiusLayer>(udpData, udpDataLen); |
127 | 22.4k | } |
128 | 202k | else if ((GtpV1Layer::isGTPv1Port(portDst) || GtpV1Layer::isGTPv1Port(portSrc)) && |
129 | 23.2k | GtpV1Layer::isGTPv1(udpData, udpDataLen)) |
130 | 13.8k | { |
131 | 13.8k | constructNextLayer<GtpV1Layer>(udpData, udpDataLen); |
132 | 13.8k | } |
133 | 188k | else if ((GtpV2Layer::isGTPv2Port(portDst) || GtpV2Layer::isGTPv2Port(portSrc)) && |
134 | 1.18k | GtpV2Layer::isDataValid(udpData, udpDataLen)) |
135 | 1.06k | { |
136 | 1.06k | constructNextLayer<GtpV2Layer>(udpData, udpDataLen); |
137 | 1.06k | } |
138 | 187k | else if ((DhcpV6Layer::isDhcpV6Port(portSrc) || DhcpV6Layer::isDhcpV6Port(portDst)) && |
139 | 5.65k | (DhcpV6Layer::isDataValid(udpData, udpDataLen))) |
140 | 5.65k | { |
141 | 5.65k | constructNextLayer<DhcpV6Layer>(udpData, udpDataLen); |
142 | 5.65k | } |
143 | 182k | else if ((NtpLayer::isNTPPort(portSrc) || NtpLayer::isNTPPort(portDst)) && |
144 | 13.3k | NtpLayer::isDataValid(udpData, udpDataLen)) |
145 | 13.0k | { |
146 | 13.0k | constructNextLayer<NtpLayer>(udpData, udpDataLen); |
147 | 13.0k | } |
148 | 169k | else if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && |
149 | 237 | (DoIpLayer::isDataValid(udpData, udpDataLen))) |
150 | 0 | { |
151 | 0 | tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(DoIpLayer::parseDoIpLayer, udpData, udpDataLen); |
152 | 0 | } |
153 | 169k | else if (SomeIpLayer::isSomeIpPort(portSrc) || SomeIpLayer::isSomeIpPort(portDst)) |
154 | 61.2k | { |
155 | 61.2k | constructNextLayerFromFactory(SomeIpLayer::parseSomeIpLayer, udpData, udpDataLen); |
156 | 61.2k | } |
157 | 107k | else if ((WakeOnLanLayer::isWakeOnLanPort(portDst) && WakeOnLanLayer::isDataValid(udpData, udpDataLen))) |
158 | 873 | { |
159 | 873 | constructNextLayer<WakeOnLanLayer>(udpData, udpDataLen); |
160 | 873 | } |
161 | 106k | else if ((WireGuardLayer::isWireGuardPorts(portDst, portSrc) && |
162 | 2.61k | WireGuardLayer::isDataValid(udpData, udpDataLen))) |
163 | 2.39k | { |
164 | 2.39k | tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(WireGuardLayer::parseWireGuardLayer, udpData, |
165 | 2.39k | udpDataLen); |
166 | 2.39k | } |
167 | | |
168 | | // If a valid layer was found, return immediately |
169 | 376k | if (hasNextLayer()) |
170 | 271k | { |
171 | 271k | return; |
172 | 271k | } |
173 | | |
174 | | // Here, heuristics for all protocols should be invoked to determine the correct layer |
175 | 104k | { |
176 | | // Resolves the overload of parseSipLayer, without static_casting a function pointer. |
177 | 104k | auto* (*fac)(uint8_t*, size_t, Layer*, Packet*) = SipLayer::parseSipLayer; |
178 | 104k | tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(fac, udpData, udpDataLen); |
179 | 104k | } |
180 | | |
181 | 104k | if (!hasNextLayer()) |
182 | 0 | { |
183 | 0 | constructNextLayer<PayloadLayer>(udpData, udpDataLen); |
184 | 0 | } |
185 | 104k | } |
186 | | |
187 | | void UdpLayer::computeCalculateFields() |
188 | 67.6k | { |
189 | 67.6k | udphdr* udpHdr = reinterpret_cast<udphdr*>(m_Data); |
190 | 67.6k | udpHdr->length = htobe16(m_DataLen); |
191 | 67.6k | calculateChecksum(true); |
192 | 67.6k | } |
193 | | |
194 | | std::string UdpLayer::toString() const |
195 | 135k | { |
196 | 135k | std::ostringstream srcPortStream; |
197 | 135k | srcPortStream << getSrcPort(); |
198 | 135k | std::ostringstream dstPortStream; |
199 | 135k | dstPortStream << getDstPort(); |
200 | | |
201 | 135k | return "UDP Layer, Src port: " + srcPortStream.str() + ", Dst port: " + dstPortStream.str(); |
202 | 135k | } |
203 | | |
204 | | } // namespace pcpp |