/src/PcapPlusPlus/Packet++/header/IPv6Layer.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include "Layer.h" |
4 | | #include "IPLayer.h" |
5 | | #include "IPv6Extensions.h" |
6 | | #include "IpAddress.h" |
7 | | |
8 | | /// @file |
9 | | |
10 | | /** |
11 | | * \namespace pcpp |
12 | | * \brief The main namespace for the PcapPlusPlus lib |
13 | | */ |
14 | | namespace pcpp |
15 | | { |
16 | | |
17 | | /** |
18 | | * @struct ip6_hdr |
19 | | * Represents IPv6 protocol header |
20 | | */ |
21 | | #pragma pack(push, 1) |
22 | | struct ip6_hdr |
23 | | { |
24 | | #if (BYTE_ORDER == LITTLE_ENDIAN) |
25 | | /** Traffic class */ |
26 | | uint8_t trafficClass:4, |
27 | | /** IP version number, has the value of 6 for IPv6 */ |
28 | | ipVersion:4; |
29 | | #else |
30 | | /** IP version number, has the value of 6 for IPv6 */ |
31 | | uint8_t ipVersion:4, |
32 | | /** Traffic class */ |
33 | | trafficClass:4; |
34 | | #endif |
35 | | /** Flow label */ |
36 | | uint8_t flowLabel[3]; |
37 | | /** The size of the payload in octets, including any extension headers */ |
38 | | uint16_t payloadLength; |
39 | | /** Specifies the type of the next header (protocol). Must be one of ::IPProtocolTypes */ |
40 | | uint8_t nextHeader; |
41 | | /** Replaces the time to live field of IPv4 */ |
42 | | uint8_t hopLimit; |
43 | | /** Source address */ |
44 | | uint8_t ipSrc[16]; |
45 | | /** Destination address */ |
46 | | uint8_t ipDst[16]; |
47 | | }; |
48 | | #pragma pack(pop) |
49 | | |
50 | | |
51 | | /** |
52 | | * @class IPv6Layer |
53 | | * Represents an IPv6 protocol layer |
54 | | */ |
55 | | class IPv6Layer : public Layer, public IPLayer |
56 | | { |
57 | | public: |
58 | | /** |
59 | | * A constructor that creates the layer from an existing packet raw data |
60 | | * @param[in] data A pointer to the raw data (will be casted to @ref ip6_hdr) |
61 | | * @param[in] dataLen Size of the data in bytes |
62 | | * @param[in] prevLayer A pointer to the previous layer |
63 | | * @param[in] packet A pointer to the Packet instance where layer will be stored in |
64 | | */ |
65 | | IPv6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
66 | | |
67 | | /** |
68 | | * A constructor that allocates a new IPv6 header with empty fields |
69 | | */ |
70 | | IPv6Layer(); |
71 | | |
72 | | /** |
73 | | * A constructor that allocates a new IPv6 header with source and destination IPv6 addresses |
74 | | * @param[in] srcIP Source IPv6 address |
75 | | * @param[in] dstIP Destination IPv6 address |
76 | | */ |
77 | | IPv6Layer(const IPv6Address& srcIP, const IPv6Address& dstIP); |
78 | | |
79 | | /** |
80 | | * A copy constructor that copies the entire header from the other IPv6Layer (including IPv6 extensions) |
81 | | */ |
82 | | IPv6Layer(const IPv6Layer& other); |
83 | | |
84 | | /** |
85 | | * A destructor for this layer |
86 | | */ |
87 | | ~IPv6Layer(); |
88 | | |
89 | | /** |
90 | | * An assignment operator that first delete all data from current layer and then copy the entire header from the other IPv6Layer (including IPv6 extensions) |
91 | | */ |
92 | | IPv6Layer& operator=(const IPv6Layer& other); |
93 | | |
94 | | /** |
95 | | * Get a pointer to the IPv6 header. Notice this points directly to the data, so every change will change the actual packet data |
96 | | * @return A pointer to the @ref ip6_hdr |
97 | | */ |
98 | 951k | ip6_hdr* getIPv6Header() const { return (ip6_hdr*)m_Data; } |
99 | | |
100 | | /** |
101 | | * Get the source IP address in the form of IPAddress. This method is very similar to getSrcIPv6Address(), |
102 | | * but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses |
103 | | * @return An IPAddress containing the source address |
104 | | */ |
105 | 2.35k | IPAddress getSrcIPAddress() const { return getSrcIPv6Address(); } |
106 | | |
107 | | /** |
108 | | * Get the source IP address in the form of IPv6Address |
109 | | * @return An IPv6Address containing the source address |
110 | | */ |
111 | 130k | IPv6Address getSrcIPv6Address() const { return getIPv6Header()->ipSrc; } |
112 | | |
113 | | /** |
114 | | * Set the source IP address |
115 | | * @param[in] ipAddr The IP address to set |
116 | | */ |
117 | 0 | void setSrcIPv6Address(const IPv6Address& ipAddr) { ipAddr.copyTo(getIPv6Header()->ipSrc); } |
118 | | |
119 | | |
120 | | /** |
121 | | * Set the dest IP address |
122 | | * @param[in] ipAddr The IP address to set |
123 | | */ |
124 | 0 | void setDstIPv6Address(const IPv6Address& ipAddr) { ipAddr.copyTo(getIPv6Header()->ipDst); } |
125 | | |
126 | | /** |
127 | | * Get the destination IP address in the form of IPAddress. This method is very similar to getDstIPv6Address(), |
128 | | * but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses |
129 | | * @return An IPAddress containing the destination address |
130 | | */ |
131 | 2.35k | IPAddress getDstIPAddress() const { return getDstIPv6Address(); } |
132 | | |
133 | | /** |
134 | | * Get the destination IP address in the form of IPv6Address |
135 | | * @return An IPv6Address containing the destination address |
136 | | */ |
137 | 130k | IPv6Address getDstIPv6Address() const { return getIPv6Header()->ipDst; } |
138 | | |
139 | | /** |
140 | | * @return Number of IPv6 extensions in this layer |
141 | | */ |
142 | | size_t getExtensionCount() const; |
143 | | |
144 | | /** |
145 | | * A templated getter for an IPv6 extension of a type TIPv6Extension. TIPv6Extension has to be one of the supported IPv6 extensions, |
146 | | * meaning a class that inherits IPv6Extension. If the requested extension type isn't found NULL is returned |
147 | | * @return A pointer to the extension instance or NULL if the requested extension type isn't found |
148 | | */ |
149 | | template<class TIPv6Extension> |
150 | | TIPv6Extension* getExtensionOfType() const; |
151 | | |
152 | | /** |
153 | | * Add a new extension of type TIPv6Extension to the layer. This is a templated method and TIPv6Extension has to be one of |
154 | | * the supported IPv6 extensions, meaning a class that inherits IPv6Extension. If the extension is added successfully a pointer |
155 | | * to the newly added extension object is returned, otherwise NULL is returned |
156 | | * @param[in] extensionHeader The extension object to add. Notice the object passed here is read-only, meaning its data is copied |
157 | | * but the object itself isn't modified |
158 | | * @return If the extension is added successfully a pointer to the newly added extension object is returned. Otherwise NULL is |
159 | | * returned |
160 | | */ |
161 | | template<class TIPv6Extension> |
162 | | TIPv6Extension* addExtension(const TIPv6Extension& extensionHeader); |
163 | | |
164 | | /** |
165 | | * Remove all IPv6 extensions in this layer |
166 | | */ |
167 | | void removeAllExtensions(); |
168 | | |
169 | | /** |
170 | | * @return True if this packet is an IPv6 fragment, meaning if it has an IPv6FragmentationHeader extension |
171 | | */ |
172 | | bool isFragment() const; |
173 | | |
174 | | /** |
175 | | * The static method makes validation of input data |
176 | | * @param[in] data The pointer to the beginning of byte stream of IP packet |
177 | | * @param[in] dataLen The length of byte stream |
178 | | * @return True if the data is valid and can represent the IPv6 packet |
179 | | */ |
180 | | static inline bool isDataValid(const uint8_t* data, size_t dataLen); |
181 | | |
182 | | |
183 | | // implement abstract methods |
184 | | |
185 | | /** |
186 | | * Currently identifies the following next layers: |
187 | | * - UdpLayer |
188 | | * - TcpLayer |
189 | | * - IPv4Layer (IP-in-IP) |
190 | | * - IPv6Layer (IP-in-IP) |
191 | | * - GreLayer |
192 | | * - AuthenticationHeaderLayer (IPSec) |
193 | | * - ESPLayer (IPSec) |
194 | | * |
195 | | * Otherwise sets PayloadLayer |
196 | | */ |
197 | | void parseNextLayer(); |
198 | | |
199 | | /** |
200 | | * @return Size of @ref ip6_hdr |
201 | | */ |
202 | 511k | size_t getHeaderLen() const { return sizeof(ip6_hdr) + m_ExtensionsLen; } |
203 | | |
204 | | /** |
205 | | * Calculate the following fields: |
206 | | * - ip6_hdr#payloadLength = size of payload (all data minus header size) |
207 | | * - ip6_hdr#ipVersion = 6 |
208 | | * - ip6_hdr#nextHeader = calculated if next layer is known: ::PACKETPP_IPPROTO_TCP for TCP, ::PACKETPP_IPPROTO_UDP for UDP, ::PACKETPP_IPPROTO_ICMP for ICMP |
209 | | */ |
210 | | void computeCalculateFields(); |
211 | | |
212 | | std::string toString() const; |
213 | | |
214 | 44.4k | OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; } |
215 | | |
216 | | private: |
217 | | void initLayer(); |
218 | | void parseExtensions(); |
219 | | void deleteExtensions(); |
220 | | |
221 | | IPv6Extension* m_FirstExtension; |
222 | | IPv6Extension* m_LastExtension; |
223 | | size_t m_ExtensionsLen; |
224 | | }; |
225 | | |
226 | | |
227 | | template<class TIPv6Extension> |
228 | | TIPv6Extension* IPv6Layer::getExtensionOfType() const |
229 | 0 | { |
230 | 0 | IPv6Extension* curExt = m_FirstExtension; |
231 | 0 | while (curExt != NULL && dynamic_cast<TIPv6Extension*>(curExt) == NULL) |
232 | 0 | curExt = curExt->getNextHeader(); |
233 | |
|
234 | 0 | return (TIPv6Extension*)curExt; |
235 | 0 | } |
236 | | |
237 | | template<class TIPv6Extension> |
238 | | TIPv6Extension* IPv6Layer::addExtension(const TIPv6Extension& extensionHeader) |
239 | | { |
240 | | int offsetToAddHeader = (int)getHeaderLen(); |
241 | | if (!extendLayer(offsetToAddHeader, extensionHeader.getExtensionLen())) |
242 | | { |
243 | | return NULL; |
244 | | } |
245 | | |
246 | | TIPv6Extension* newHeader = new TIPv6Extension(this, (size_t)offsetToAddHeader); |
247 | | (*newHeader) = extensionHeader; |
248 | | |
249 | | if (m_FirstExtension != NULL) |
250 | | { |
251 | | newHeader->getBaseHeader()->nextHeader = m_LastExtension->getBaseHeader()->nextHeader; |
252 | | m_LastExtension->getBaseHeader()->nextHeader = newHeader->getExtensionType(); |
253 | | m_LastExtension->setNextHeader(newHeader); |
254 | | m_LastExtension = newHeader; |
255 | | } |
256 | | else |
257 | | { |
258 | | m_FirstExtension = newHeader; |
259 | | m_LastExtension = newHeader; |
260 | | newHeader->getBaseHeader()->nextHeader = getIPv6Header()->nextHeader; |
261 | | getIPv6Header()->nextHeader = newHeader->getExtensionType(); |
262 | | } |
263 | | |
264 | | m_ExtensionsLen += newHeader->getExtensionLen(); |
265 | | |
266 | | return newHeader; |
267 | | } |
268 | | |
269 | | // implementation of inline methods |
270 | | |
271 | | bool IPv6Layer::isDataValid(const uint8_t* data, size_t dataLen) |
272 | 232k | { |
273 | 232k | return data && dataLen >= sizeof(ip6_hdr); |
274 | 232k | } |
275 | | |
276 | | } // namespace pcpp |