/src/PcapPlusPlus/Packet++/src/UdpLayer.cpp
Line | Count | Source |
1 | 114k | #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 | 474k | { |
41 | 474k | return be16toh(getUdpHeader()->portSrc); |
42 | 474k | } |
43 | | |
44 | | uint16_t UdpLayer::getDstPort() const |
45 | 474k | { |
46 | 474k | return be16toh(getUdpHeader()->portDst); |
47 | 474k | } |
48 | | |
49 | | uint16_t UdpLayer::calculateChecksum(bool writeResultToPacket) |
50 | 57.4k | { |
51 | 57.4k | udphdr* udpHdr = reinterpret_cast<udphdr*>(m_Data); |
52 | 57.4k | uint16_t checksumRes = 0; |
53 | 57.4k | uint16_t currChecksumValue = udpHdr->headerChecksum; |
54 | | |
55 | 57.4k | if (m_PrevLayer != nullptr) |
56 | 57.4k | { |
57 | 57.4k | udpHdr->headerChecksum = 0; |
58 | 57.4k | PCPP_LOG_DEBUG("UDP data len = " << m_DataLen); |
59 | | |
60 | 57.4k | if (m_PrevLayer->getProtocol() == IPv4) |
61 | 50.9k | { |
62 | 50.9k | IPv4Address srcIP = static_cast<IPv4Layer*>(m_PrevLayer)->getSrcIPv4Address(); |
63 | 50.9k | IPv4Address dstIP = static_cast<IPv4Layer*>(m_PrevLayer)->getDstIPv4Address(); |
64 | | |
65 | 50.9k | checksumRes = pcpp::computePseudoHdrChecksum((uint8_t*)udpHdr, getDataLen(), IPAddress::IPv4AddressType, |
66 | 50.9k | PACKETPP_IPPROTO_UDP, srcIP, dstIP); |
67 | | |
68 | 50.9k | PCPP_LOG_DEBUG("calculated IPv4 UDP checksum = 0x" << std::uppercase << std::hex << checksumRes); |
69 | 50.9k | } |
70 | 6.47k | else if (m_PrevLayer->getProtocol() == IPv6) |
71 | 6.47k | { |
72 | 6.47k | IPv6Address srcIP = static_cast<IPv6Layer*>(m_PrevLayer)->getSrcIPv6Address(); |
73 | 6.47k | IPv6Address dstIP = static_cast<IPv6Layer*>(m_PrevLayer)->getDstIPv6Address(); |
74 | | |
75 | 6.47k | checksumRes = computePseudoHdrChecksum((uint8_t*)udpHdr, getDataLen(), IPAddress::IPv6AddressType, |
76 | 6.47k | PACKETPP_IPPROTO_UDP, srcIP, dstIP); |
77 | | |
78 | 6.47k | PCPP_LOG_DEBUG("calculated IPv6 UDP checksum = 0xX" << std::uppercase << std::hex << checksumRes); |
79 | 6.47k | } |
80 | 57.4k | } |
81 | | |
82 | 57.4k | if (checksumRes == 0) |
83 | 34 | checksumRes = 0xffff; |
84 | | |
85 | 57.4k | if (writeResultToPacket) |
86 | 57.4k | udpHdr->headerChecksum = htobe16(checksumRes); |
87 | 0 | else |
88 | 0 | udpHdr->headerChecksum = currChecksumValue; |
89 | | |
90 | 57.4k | return checksumRes; |
91 | 57.4k | } |
92 | | |
93 | | void UdpLayer::parseNextLayer() |
94 | 360k | { |
95 | 360k | if (m_DataLen <= sizeof(udphdr)) |
96 | 106 | return; |
97 | | |
98 | 360k | uint16_t portDst = getDstPort(); |
99 | 360k | uint16_t portSrc = getSrcPort(); |
100 | | |
101 | 360k | uint8_t* udpData = m_Data + sizeof(udphdr); |
102 | 360k | size_t udpDataLen = m_DataLen - sizeof(udphdr); |
103 | | |
104 | 360k | if (DhcpLayer::isDhcpPorts(portSrc, portDst)) |
105 | 15.9k | { |
106 | 15.9k | tryConstructNextLayerWithFallback<DhcpLayer, PayloadLayer>(udpData, udpDataLen); |
107 | 15.9k | } |
108 | 344k | else if (VxlanLayer::isVxlanPort(portDst)) |
109 | 0 | { |
110 | 0 | tryConstructNextLayerWithFallback<VxlanLayer, PayloadLayer>(udpData, udpDataLen); |
111 | 0 | } |
112 | 344k | else if (DnsLayer::isDataValid(udpData, udpDataLen) && |
113 | 303k | (DnsLayer::isDnsPort(portDst) || DnsLayer::isDnsPort(portSrc))) |
114 | 58.1k | { |
115 | 58.1k | constructNextLayer<DnsLayer>(udpData, udpDataLen); |
116 | 58.1k | } |
117 | 285k | else if (SipLayer::isSipPort(portDst) || SipLayer::isSipPort(portSrc)) |
118 | 74.5k | { |
119 | | // Resolves the overload of parseSipLayer, without static_casting a function pointer. |
120 | 74.5k | auto* (*fac)(uint8_t*, size_t, Layer*, Packet*, uint16_t, uint16_t) = SipLayer::parseSipLayer; |
121 | 74.5k | tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(fac, udpData, udpDataLen, portSrc, portDst); |
122 | 74.5k | } |
123 | 211k | else if ((RadiusLayer::isRadiusPort(portDst) || RadiusLayer::isRadiusPort(portSrc)) && |
124 | 13.7k | RadiusLayer::isDataValid(udpData, udpDataLen)) |
125 | 12.8k | { |
126 | 12.8k | constructNextLayer<RadiusLayer>(udpData, udpDataLen); |
127 | 12.8k | } |
128 | 198k | else if ((GtpV1Layer::isGTPv1Port(portDst) || GtpV1Layer::isGTPv1Port(portSrc)) && |
129 | 34.9k | GtpV1Layer::isGTPv1(udpData, udpDataLen)) |
130 | 34.5k | { |
131 | 34.5k | constructNextLayer<GtpV1Layer>(udpData, udpDataLen); |
132 | 34.5k | } |
133 | 163k | else if ((GtpV2Layer::isGTPv2Port(portDst) || GtpV2Layer::isGTPv2Port(portSrc)) && |
134 | 16 | GtpV2Layer::isDataValid(udpData, udpDataLen)) |
135 | 6 | { |
136 | 6 | constructNextLayer<GtpV2Layer>(udpData, udpDataLen); |
137 | 6 | } |
138 | 163k | else if ((DhcpV6Layer::isDhcpV6Port(portSrc) || DhcpV6Layer::isDhcpV6Port(portDst)) && |
139 | 21.1k | (DhcpV6Layer::isDataValid(udpData, udpDataLen))) |
140 | 20.8k | { |
141 | 20.8k | constructNextLayer<DhcpV6Layer>(udpData, udpDataLen); |
142 | 20.8k | } |
143 | 143k | else if ((NtpLayer::isNTPPort(portSrc) || NtpLayer::isNTPPort(portDst)) && |
144 | 17.2k | NtpLayer::isDataValid(udpData, udpDataLen)) |
145 | 17.1k | { |
146 | 17.1k | constructNextLayer<NtpLayer>(udpData, udpDataLen); |
147 | 17.1k | } |
148 | 125k | else if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && |
149 | 49.5k | (DoIpLayer::isDataValid(udpData, udpDataLen))) |
150 | 44.9k | { |
151 | 44.9k | tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(DoIpLayer::parseDoIpLayer, udpData, udpDataLen); |
152 | 44.9k | } |
153 | 80.9k | else if (SomeIpLayer::isSomeIpPort(portSrc) || SomeIpLayer::isSomeIpPort(portDst)) |
154 | 36.1k | { |
155 | 36.1k | constructNextLayerFromFactory(SomeIpLayer::parseSomeIpLayer, udpData, udpDataLen); |
156 | 36.1k | } |
157 | 44.8k | else if ((WakeOnLanLayer::isWakeOnLanPort(portDst) && WakeOnLanLayer::isDataValid(udpData, udpDataLen))) |
158 | 495 | { |
159 | 495 | constructNextLayer<WakeOnLanLayer>(udpData, udpDataLen); |
160 | 495 | } |
161 | 44.3k | else if ((WireGuardLayer::isWireGuardPorts(portDst, portSrc) && |
162 | 2.22k | WireGuardLayer::isDataValid(udpData, udpDataLen))) |
163 | 2.08k | { |
164 | 2.08k | tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(WireGuardLayer::parseWireGuardLayer, udpData, |
165 | 2.08k | udpDataLen); |
166 | 2.08k | } |
167 | | |
168 | | // If a valid layer was found, return immediately |
169 | 360k | if (hasNextLayer()) |
170 | 317k | { |
171 | 317k | return; |
172 | 317k | } |
173 | | |
174 | | // Here, heuristics for all protocols should be invoked to determine the correct layer |
175 | 42.2k | { |
176 | | // Resolves the overload of parseSipLayer, without static_casting a function pointer. |
177 | 42.2k | auto* (*fac)(uint8_t*, size_t, Layer*, Packet*) = SipLayer::parseSipLayer; |
178 | 42.2k | tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(fac, udpData, udpDataLen); |
179 | 42.2k | } |
180 | | |
181 | 42.2k | if (!hasNextLayer()) |
182 | 0 | { |
183 | 0 | constructNextLayer<PayloadLayer>(udpData, udpDataLen); |
184 | 0 | } |
185 | 42.2k | } |
186 | | |
187 | | void UdpLayer::computeCalculateFields() |
188 | 57.4k | { |
189 | 57.4k | udphdr* udpHdr = reinterpret_cast<udphdr*>(m_Data); |
190 | 57.4k | udpHdr->length = htobe16(m_DataLen); |
191 | 57.4k | calculateChecksum(true); |
192 | 57.4k | } |
193 | | |
194 | | std::string UdpLayer::toString() const |
195 | 114k | { |
196 | 114k | std::ostringstream srcPortStream; |
197 | 114k | srcPortStream << getSrcPort(); |
198 | 114k | std::ostringstream dstPortStream; |
199 | 114k | dstPortStream << getDstPort(); |
200 | | |
201 | 114k | return "UDP Layer, Src port: " + srcPortStream.str() + ", Dst port: " + dstPortStream.str(); |
202 | 114k | } |
203 | | |
204 | | } // namespace pcpp |