/src/PcapPlusPlus/Packet++/header/IcmpV6Layer.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include "Layer.h" |
4 | | |
5 | | /// @file |
6 | | |
7 | | /// @namespace pcpp |
8 | | /// @brief The main namespace for the PcapPlusPlus lib |
9 | | namespace pcpp |
10 | | { |
11 | | /// An enum representing the available ICMPv6 message types |
12 | | enum class ICMPv6MessageType : int |
13 | | { |
14 | | /// Unknown ICMPv6 message |
15 | | ICMPv6_UNKNOWN_MESSAGE = 0, |
16 | | /// Destination Unreachable Message |
17 | | ICMPv6_DESTINATION_UNREACHABLE = 1, |
18 | | /// Packet Too Big Message |
19 | | ICMPv6_PACKET_TOO_BIG = 2, |
20 | | /// Time Exceeded Message |
21 | | ICMPv6_TIME_EXCEEDED = 3, |
22 | | /// Parameter Problem Message |
23 | | ICMPv6_PARAMETER_PROBLEM = 4, |
24 | | /// Private Experimentation Message |
25 | | ICMPv6_PRIVATE_EXPERIMENTATION1 = 100, |
26 | | /// Private Experimentation Message |
27 | | ICMPv6_PRIVATE_EXPERIMENTATION2 = 101, |
28 | | /// Reserved for expansion of ICMPv6 error messages |
29 | | ICMPv6_RESERVED_EXPANSION_ERROR = 127, |
30 | | /// Echo Request Message |
31 | | ICMPv6_ECHO_REQUEST = 128, |
32 | | /// Echo Reply Message |
33 | | ICMPv6_ECHO_REPLY = 129, |
34 | | /// Multicast Listener Query Message |
35 | | ICMPv6_MULTICAST_LISTENER_QUERY = 130, |
36 | | /// Multicast Listener Report Message |
37 | | ICMPv6_MULTICAST_LISTENER_REPORT = 131, |
38 | | /// Multicast Listener Done Message |
39 | | ICMPv6_MULTICAST_LISTENER_DONE = 132, |
40 | | /// Router Solicitation Message |
41 | | ICMPv6_ROUTER_SOLICITATION = 133, |
42 | | /// Router Advertisement Message |
43 | | ICMPv6_ROUTER_ADVERTISEMENT = 134, |
44 | | /// Neighbor Solicitation Message |
45 | | ICMPv6_NEIGHBOR_SOLICITATION = 135, |
46 | | /// Neighbor Advertisement Message |
47 | | ICMPv6_NEIGHBOR_ADVERTISEMENT = 136, |
48 | | /// Redirect Message |
49 | | ICMPv6_REDIRECT_MESSAGE = 137, |
50 | | /// Router Renumbering Message |
51 | | ICMPv6_ROUTER_RENUMBERING = 138, |
52 | | /// Node Information Query Message |
53 | | ICMPv6_ICMP_NODE_INFORMATION_QUERY = 139, |
54 | | /// Node Information Reply Message |
55 | | ICMPv6_ICMP_NODE_INFORMATION_RESPONSE = 140, |
56 | | /// Inverse Neighbor Discovery Solicitation Message |
57 | | ICMPv6_INVERSE_NEIGHBOR_DISCOVERY_SOLICITATION_MESSAGE = 141, |
58 | | /// Inverse Neighbor Discovery Advertisement Message |
59 | | ICMPv6_INVERSE_NEIGHBOR_DISCOVERY_ADVERTISEMENT_MESSAGE = 142, |
60 | | /// Multicast Listener Report Message |
61 | | ICMPv6_MULTICAST_LISTENER_DISCOVERY_REPORTS = 143, |
62 | | /// Home Agent Address Discovery Request Message |
63 | | ICMPv6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST_MESSAGE = 144, |
64 | | /// Home Agent Address Discovery Reply Message |
65 | | ICMPv6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY_MESSAGE = 145, |
66 | | /// Mobile Prefix Solicitation Message |
67 | | ICMPv6_MOBILE_PREFIX_SOLICITATION = 146, |
68 | | /// Mobile Prefix Advertisement Message |
69 | | ICMPv6_MOBILE_PREFIX_ADVERTISEMENT = 147, |
70 | | /// Certification Path Solicitation Message |
71 | | ICMPv6_CERTIFICATION_PATH_SOLICITATION = 148, |
72 | | /// Certification Path Advertisement Message |
73 | | ICMPv6_CERTIFICATION_PATH_ADVERTISEMENT = 149, |
74 | | /// ICMP Experimental Mobility Subtype Format and Registry Message |
75 | | ICMPv6_EXPERIMENTAL_MOBILITY = 150, |
76 | | /// Multicast Router Advertisement Message |
77 | | ICMPv6_MULTICAST_ROUTER_ADVERTISEMENT = 151, |
78 | | /// Multicast Router Solicitation Message |
79 | | ICMPv6_MULTICAST_ROUTER_SOLICITATION = 152, |
80 | | /// Multicast Router Termination Message |
81 | | ICMPv6_MULTICAST_ROUTER_TERMINATION = 153, |
82 | | /// RPL Control Message |
83 | | ICMPv6_RPL_CONTROL_MESSAGE = 155, |
84 | | /// Private Experimentation Message |
85 | | ICMPv6_PRIVATE_EXPERIMENTATION3 = 200, |
86 | | /// Private Experimentation Message |
87 | | ICMPv6_PRIVATE_EXPERIMENTATION4 = 201, |
88 | | /// Reserved for expansion of ICMPv6 informational messages |
89 | | ICMPv6_RESERVED_EXPANSION_INFORMATIONAL = 255 |
90 | | }; |
91 | | |
92 | | /// @struct icmpv6hdr |
93 | | /// Represents an ICMPv6 protocol header |
94 | | #pragma pack(push, 1) |
95 | | struct icmpv6hdr |
96 | | { |
97 | | /// Type of the message. Values in the range from 0 to 127 (high-order bit is 0) indicate an error message, |
98 | | /// while values in the range from 128 to 255 (high-order bit is 1) indicate an information message. |
99 | | uint8_t type; |
100 | | /// The code field value depends on the message type and provides an additional level of message granularity |
101 | | uint8_t code; |
102 | | /// The checksum field provides a minimal level of integrity verification for the ICMP message |
103 | | uint16_t checksum; |
104 | | }; |
105 | | #pragma pack(pop) |
106 | | static_assert(sizeof(icmpv6hdr) == 4, "icmpv6hdr size is not 4 bytes"); |
107 | | |
108 | | /// @struct icmpv6_echo_hdr |
109 | | /// ICMP echo request/reply message structure |
110 | | #pragma pack(push, 1) |
111 | | typedef struct icmpv6_echo_hdr : icmpv6hdr |
112 | | { |
113 | | /// the echo request identifier |
114 | | uint16_t id; |
115 | | /// the echo request sequence number |
116 | | uint16_t sequence; |
117 | | } icmpv6_echo_hdr; |
118 | | #pragma pack(pop) |
119 | | static_assert(sizeof(icmpv6_echo_hdr) == 8, "icmpv6_echo_hdr size is not 8 bytes"); |
120 | | |
121 | | /// @class IcmpV6Layer |
122 | | /// Base class for ICMPv6 protocol layers which provides common logic for ICMPv6 messages. |
123 | | class IcmpV6Layer : public Layer |
124 | | { |
125 | | public: |
126 | | /// A constructor that creates the layer from an existing packet raw data |
127 | | /// @param data A pointer to the raw data |
128 | | /// @param dataLen Size of the data in bytes |
129 | | /// @param prevLayer A pointer to the previous layer |
130 | | /// @param packet A pointer to the Packet instance where layer will be stored in |
131 | | IcmpV6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) |
132 | 403 | : Layer(data, dataLen, prevLayer, packet, ICMPv6) |
133 | 403 | {} |
134 | | |
135 | | /// A constructor that allocates a new ICMPv6 layer with type, code and data |
136 | | /// @param[in] msgType Message type of the ICMPv6 layer |
137 | | /// @param[in] code Code field of the ICMPv6 layer |
138 | | /// @param[in] data A pointer to the payload to set |
139 | | /// @param[in] dataLen The length of the payload |
140 | | IcmpV6Layer(ICMPv6MessageType msgType, uint8_t code, const uint8_t* data, size_t dataLen); |
141 | | |
142 | | ~IcmpV6Layer() override = default; |
143 | | |
144 | | /// A static method that creates an ICMPv6 layer from packet raw data |
145 | | /// @param[in] data A pointer to the raw data |
146 | | /// @param[in] dataLen Size of the data in bytes |
147 | | /// @param[in] prevLayer A pointer to the previous layer |
148 | | /// @param[in] packet A pointer to the Packet instance where layer will be stored |
149 | | /// @return Layer* A newly allocated ICMPv6 layer |
150 | | static Layer* parseIcmpV6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
151 | | |
152 | | /// @param[in] type Type to check |
153 | | /// @return True if the layer if of the given type, false otherwise |
154 | | bool isMessageOfType(ICMPv6MessageType type) const |
155 | 0 | { |
156 | 0 | return getMessageType() == type; |
157 | 0 | } |
158 | | |
159 | | /// @return Get the ICMPv6 Message Type |
160 | | ICMPv6MessageType getMessageType() const; |
161 | | |
162 | | /// @return Get the code header field |
163 | | uint8_t getCode() const; |
164 | | |
165 | | /// @return Get the checksum header field in host representation |
166 | | uint16_t getChecksum() const; |
167 | | |
168 | | /// Does nothing for this layer. ICMPv6 is the last layer. |
169 | | void parseNextLayer() override |
170 | 403 | {} |
171 | | |
172 | | /// @return The size of the ICMPv6 message |
173 | | size_t getHeaderLen() const override |
174 | 125 | { |
175 | 125 | return m_DataLen; |
176 | 125 | } |
177 | | |
178 | | /// Calculate ICMPv6 checksum field |
179 | | void computeCalculateFields() override; |
180 | | |
181 | | OsiModelLayer getOsiModelLayer() const override |
182 | 95 | { |
183 | 95 | return OsiModelNetworkLayer; |
184 | 95 | } |
185 | | |
186 | | std::string toString() const override; |
187 | | |
188 | | protected: |
189 | 0 | IcmpV6Layer() = default; |
190 | | |
191 | | private: |
192 | | void calculateChecksum(); |
193 | | icmpv6hdr* getIcmpv6Header() const |
194 | 350 | { |
195 | 350 | return reinterpret_cast<icmpv6hdr*>(m_Data); |
196 | 350 | } |
197 | | }; |
198 | | |
199 | | /// @class ICMPv6EchoLayer |
200 | | /// Represents an ICMPv6 echo request/reply protocol layer |
201 | | class ICMPv6EchoLayer : public IcmpV6Layer |
202 | | { |
203 | | public: |
204 | | /// An enum representing ICMPv6 echo message types |
205 | | enum ICMPv6EchoType |
206 | | { |
207 | | /// Echo Request Type |
208 | | REQUEST, |
209 | | /// Echo Reply Type |
210 | | REPLY |
211 | | }; |
212 | | |
213 | | /// A constructor that creates the layer from an existing packet raw data |
214 | | /// @param[in] data A pointer to the raw data |
215 | | /// @param[in] dataLen Size of the data in bytes |
216 | | /// @param[in] prevLayer A pointer to the previous layer |
217 | | /// @param[in] packet A pointer to the Packet instance where layer will be stored in |
218 | | ICMPv6EchoLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) |
219 | 0 | : IcmpV6Layer(data, dataLen, prevLayer, packet) |
220 | 0 | {} |
221 | | |
222 | | /// A constructor for a new echo request/reply layer |
223 | | /// @param[in] echoType The type of the echo message |
224 | | /// @param[in] id Echo request identifier |
225 | | /// @param[in] sequence Echo request sequence number |
226 | | /// @param[in] data A pointer to echo request payload to set |
227 | | /// @param[in] dataLen The length of the echo request payload |
228 | | ICMPv6EchoLayer(ICMPv6EchoType echoType, uint16_t id, uint16_t sequence, const uint8_t* data, size_t dataLen); |
229 | | |
230 | | ~ICMPv6EchoLayer() override = default; |
231 | | |
232 | | /// @return Identifier in host representation |
233 | | uint16_t getIdentifier() const; |
234 | | |
235 | | /// @return Sequence number in host representation |
236 | | uint16_t getSequenceNr() const; |
237 | | |
238 | | /// @return Size of the data in bytes |
239 | | size_t getEchoDataLen() const |
240 | 0 | { |
241 | 0 | return m_DataLen - sizeof(icmpv6_echo_hdr); |
242 | 0 | } |
243 | | |
244 | | /// @return Pointer to the beginning of the data |
245 | | uint8_t* getEchoDataPtr() const |
246 | 0 | { |
247 | 0 | return m_Data + sizeof(icmpv6_echo_hdr); |
248 | 0 | } |
249 | | |
250 | | std::string toString() const override; |
251 | | |
252 | | private: |
253 | | icmpv6_echo_hdr* getEchoHeader() const |
254 | 0 | { |
255 | 0 | return reinterpret_cast<icmpv6_echo_hdr*>(m_Data); |
256 | 0 | } |
257 | | }; |
258 | | |
259 | | } // namespace pcpp |