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