Coverage Report

Created: 2023-01-17 06:15

/src/PcapPlusPlus/Common++/header/IpAddress.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef PCAPPP_IP_ADDRESSES
2
#define PCAPPP_IP_ADDRESSES
3
4
#include <stdint.h>
5
#include <string.h>
6
#include <string>
7
#include <algorithm>
8
#include <ostream>
9
10
/// @file
11
12
13
/**
14
 * \namespace pcpp
15
 * \brief The main namespace for the PcapPlusPlus lib
16
 */
17
namespace pcpp
18
{
19
20
  // The implementation of the classes is based on document N4771 "Working Draft, C++ Extensions for Networking"
21
  // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4771.pdf
22
23
  /**
24
   * @class IPv4Address
25
   * Represents an IPv4 address (of type XXX.XXX.XXX.XXX)
26
   */
27
  class IPv4Address
28
  {
29
  public:
30
    /**
31
     * A default constructor that creates an instance of the class with unspecified/zero address
32
     */
33
    IPv4Address() { memset(m_Bytes, 0, sizeof(m_Bytes)); }
34
35
    /**
36
     * A constructor that creates an instance of the class out of 4-byte integer value.
37
     * @param[in] addrAsInt The address as 4-byte integer in network byte order
38
     */
39
    IPv4Address(uint32_t addrAsInt) { memcpy(m_Bytes, &addrAsInt, sizeof(m_Bytes)); }
40
41
    /**
42
     * A constructor that creates an instance of the class out of 4-byte array.
43
     * @param[in] bytes The address as 4-byte array in network byte order
44
     */
45
    IPv4Address(const uint8_t bytes[4]) { memcpy(m_Bytes, bytes, sizeof(m_Bytes)); }
46
47
    /**
48
     * A constructor that creates an instance of the class out of std::string value
49
     * If the string doesn't represent a valid IPv4 address, an instance will store an unspecified address
50
     * @param[in] addrAsString The std::string representation of the address
51
     */
52
    IPv4Address(const std::string& addrAsString);
53
54
    /**
55
     * Converts the IPv4 address into a 4B integer
56
     * @return a 4B integer in network byte order representing the IPv4 address
57
     */
58
    inline uint32_t toInt() const;
59
60
    /**
61
     * Returns a pointer to 4-byte array representing the IPv4 address
62
     */
63
    const uint8_t* toBytes() const { return m_Bytes; }
64
65
    /**
66
     * Returns a std::string representation of the address
67
     * @return A string representation of the address
68
     */
69
    std::string toString() const;
70
71
    /**
72
     * Determine whether the address is a multicast address
73
     * @return True if an address is multicast
74
     */
75
    bool isMulticast() const;
76
77
    /**
78
     * Determine whether the address is valid (it's not an unspecified/zero)
79
     * @return True if an address is not unspecified/zero
80
     */
81
0
    bool isValid() const { return toInt() != 0; }
82
83
    /**
84
     * Overload of the equal-to operator
85
     * @param[in] rhs The object to compare with
86
     * @return True if the addresses are equal, false otherwise
87
     */
88
    bool operator==(const IPv4Address& rhs) const { return toInt() == rhs.toInt(); }
89
90
    /**
91
     * Overload of the less-than operator
92
     * @param[in] rhs The object to compare with
93
     * @return True if the address value is lower than the other address value, false otherwise
94
     */
95
    bool operator<(const IPv4Address& rhs) const
96
    {
97
      uint32_t intVal = toInt();
98
      std::reverse((uint8_t*)(&intVal), (uint8_t*)(&intVal) + sizeof(intVal));
99
100
      uint32_t rhsIntVal = rhs.toInt();
101
      std::reverse((uint8_t*)(&rhsIntVal), (uint8_t*)(&rhsIntVal) + sizeof(rhsIntVal));
102
103
      return intVal < rhsIntVal;
104
    }
105
106
    /**
107
     * Overload of the not-equal-to operator
108
     * @param[in] rhs The object to compare with
109
     * @return True if the addresses are not equal, false otherwise
110
     */
111
    bool operator!=(const IPv4Address& rhs) const { return !(*this == rhs); }
112
113
    /**
114
     * Checks whether the address matches a subnet.
115
     * For example: if subnet is 10.1.1.1/24 and address is 10.1.1.9 then the method will return true
116
     * Another example: if subnet is 10.1.1.1/16 and address is 11.1.1.9 then the method will return false
117
     * @param[in] subnet A string in X.X.X.X/Y format representing the masked subnet to compare with the address
118
     */
119
    bool matchSubnet(const std::string& subnet) const;
120
121
    /**
122
     * Checks whether the address matches a subnet.
123
     * For example: if subnet is 10.1.1.X, subnet mask is 255.255.255.0 and address is 10.1.1.9 then the method will return true
124
     * Another example: if subnet is 10.1.X.X, subnet mask is 255.0.0.0 and address is 11.1.1.9 then the method will return false
125
     * @param[in] subnet The subnet to be verified. Notice it's an IPv4Address type, so subnets with don't-cares (like 10.0.0.X) must have some number
126
     * (it'll be ignored if subnet mask is correct)
127
     * @param[in] subnetMask A string representing the subnet mask to compare the address with the subnet
128
     */
129
    bool matchSubnet(const IPv4Address& subnet, const std::string& subnetMask) const;
130
131
    /**
132
     * Checks whether the address matches a subnet.
133
     * For example: if subnet is 10.1.1.X, subnet mask is 255.255.255.0 and address is 10.1.1.9 then the method will return true
134
     * Another example: if subnet is 10.1.X.X, subnet mask is 255.0.0.0 and address is 11.1.1.9 then the method will return false
135
     * @param[in] subnet The subnet to be verified. Notice it's an IPv4Address type, so subnets with don't-cares (like 10.0.0.X) must have some number
136
     * (it'll be ignored if subnet mask is correct)
137
     * @param[in] subnetMask The subnet mask to compare the address with the subnet
138
     */
139
    bool matchSubnet(const IPv4Address& subnet, const IPv4Address& subnetMask) const;
140
141
    /**
142
     * A static value representing a zero value of IPv4 address, meaning address of value "0.0.0.0"
143
     * Notice this value can be omitted in the user code because the default constructor creates an instance with an unspecified/zero address.
144
     * In order to check whether the address is zero the method isValid can be used
145
     */
146
    static const IPv4Address Zero;
147
148
    /**
149
     * A static values representing the lower and upper bound of IPv4 multicast ranges. The bounds are inclusive.
150
     * MulticastRangeLowerBound is initialized to "224.0.0.0".
151
     * MulticastRangeUpperBound is initialized to "239.255.255.255".
152
     * In order to check whether the address is a multicast address the isMulticast method can be used.
153
     */
154
    static const IPv4Address MulticastRangeLowerBound;
155
    static const IPv4Address MulticastRangeUpperBound;
156
157
  private:
158
    uint8_t m_Bytes[4];
159
  }; // class IPv4Address
160
161
162
  // Implementation of inline methods
163
164
  uint32_t IPv4Address::toInt() const
165
0
  {
166
0
    uint32_t addr;
167
0
    memcpy(&addr, m_Bytes, sizeof(m_Bytes));
168
0
    return addr;
169
0
  }
170
171
  /**
172
   * @class IPv6Address
173
   * Represents an IPv6 address (of type xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx).
174
   */
175
  class IPv6Address
176
  {
177
  public:
178
    /**
179
     * A default constructor that creates an instance of the class with unspecified/zero address
180
     */
181
    IPv6Address() { memset(m_Bytes, 0, sizeof(m_Bytes)); }
182
183
    /**
184
     * A constructor that creates an instance of the class out of 16-byte array.
185
     * @param[in] bytes The address as 16-byte array in network byte order
186
     */
187
    IPv6Address(const uint8_t bytes[16]) { memcpy(m_Bytes, bytes, sizeof(m_Bytes)); }
188
189
    /**
190
     * A constructor that creates an instance of the class out of std::string value
191
     * If the string doesn't represent a valid IPv6 address, an instance will store an unspecified address
192
     * @param[in] addrAsString The std::string representation of the address
193
     */
194
    IPv6Address(const std::string& addrAsString);
195
196
    /**
197
     * Returns a pointer to 16-byte array representing the IPv6 address
198
     */
199
0
    const uint8_t* toBytes() const { return m_Bytes; }
200
201
    /**
202
     * Returns a std::string representation of the address
203
     * @return A string representation of the address
204
     */
205
    std::string toString() const;
206
207
    /**
208
     * Determine whether the address is a multicast address
209
     * @return True if an address is multicast
210
     */
211
    bool isMulticast() const;
212
213
    /**
214
     * Determine whether the address is unspecified
215
     */
216
0
    bool isValid() const { return *this != Zero; }
217
218
    /**
219
     * Overload of the equal-to operator
220
     * @param[in] rhs The object to compare with
221
     * @return True if the addresses are equal, false otherwise
222
     */
223
0
    bool operator==(const IPv6Address& rhs) const { return memcmp(toBytes(), rhs.toBytes(), sizeof(m_Bytes)) == 0; }
224
225
    /**
226
     * Overload of the less-than operator
227
     * @param[in] rhs The object to compare with
228
     * @return True if the address value is lower than the other address value, false otherwise
229
     */
230
    bool operator<(const IPv6Address& rhs) const { return memcmp(toBytes(), rhs.toBytes(), sizeof(m_Bytes)) < 0; }
231
232
    /**
233
     * Overload of the not-equal-to operator
234
     * @param[in] rhs The object to compare with
235
     * @return True if the addresses are not equal, false otherwise
236
     */
237
0
    bool operator!=(const IPv6Address &rhs) const { return !(*this == rhs); }
238
239
240
    /**
241
     * Allocates a byte array and copies address value into it. Array deallocation is user responsibility
242
     * @param[in] arr A pointer to where array will be allocated
243
     * @param[out] length Returns the length in bytes of the array that was allocated
244
     */
245
    void copyTo(uint8_t** arr, size_t& length) const;
246
247
    /**
248
     * Gets a pointer to an already allocated byte array and copies the address value to it.
249
     * This method assumes array allocated size is at least 16 (the size of an IPv6 address)
250
     * @param[in] arr A pointer to the array which address will be copied to
251
     */
252
    void copyTo(uint8_t* arr) const { memcpy(arr, m_Bytes, sizeof(m_Bytes)); }
253
254
    /**
255
      * Checks whether the address matches a subnet.
256
      * For example: if subnet is 2001:3CA1:010F:001A::, prefixLength is 64, and address is 2001:3CA1:010F:001A:121B:0000:0000:0010, then the method will return true
257
      * Another example: if subnet is 2001:3CA1:010F:001A::, prefixLength is 70 and address is 2001:3CA1:010F:001A:121B:0000:0000:0010 then the method will return false
258
      * @param[in] subnet The subnet to be verified
259
      * @param[in] prefixLength How many bits to use in the mask
260
      */
261
    bool matchSubnet(const IPv6Address& subnet, uint8_t prefixLength) const;
262
263
    /**
264
     * A static value representing a zero value of IPv6 address, meaning address of value "0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"
265
     * Notice this value can be omitted in the user code because the default constructor creates an instance with an unspecified/zero address.
266
     * In order to check whether the address is zero the method isValid can be used
267
     */
268
    static const IPv6Address Zero;
269
270
    /**
271
     * A static value representing the lower bound of IPv6 multicast ranges. The bound is inclusive.
272
     * MulticastRangeLowerBound is initialized to "ff00:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0".
273
     * In order to check whether the address is a multicast address the isMulticast method can be used.
274
     */
275
    static const IPv6Address MulticastRangeLowerBound;
276
277
  private:
278
    uint8_t m_Bytes[16];
279
  }; // class IPv6Address
280
281
282
  ///**
283
  // * @class IPAddress
284
  // * The class is a version-independent representation for an IP address
285
  // */
286
  class IPAddress
287
  {
288
  public:
289
    /**
290
     * An enum representing the address type: IPv4 or IPv6
291
     */
292
    enum AddressType
293
    {
294
      /**
295
       * IPv4 address type
296
       */
297
      IPv4AddressType,
298
      /**
299
       * IPv6 address type
300
       */
301
      IPv6AddressType
302
    };
303
304
    /**
305
     * A default constructor that creates an instance of the class with unspecified IPv4 address
306
     */
307
    IPAddress() : m_Type(IPv4AddressType) {}
308
309
    /**
310
     * A constructor that creates an instance of the class out of IPv4Address.
311
     * @param[in] addr A const reference to instance of IPv4Address
312
     */
313
    IPAddress(const IPv4Address& addr) : m_Type(IPv4AddressType), m_IPv4(addr) {}
314
315
    /**
316
     * A constructor that creates an instance of the class out of IPv6Address.
317
     * @param[in] addr A const reference to instance of IPv6Address
318
     */
319
    IPAddress(const IPv6Address& addr) : m_Type(IPv6AddressType), m_IPv6(addr) {}
320
321
    /**
322
     * A constructor that creates an instance of the class out of std::string value
323
     * If the string doesn't represent a valid IPv4 or IPv6 address, an instance will store an unspecified address
324
     * @param[in] addrAsString The std::string representation of the address
325
     */
326
    IPAddress(const std::string& addrAsString);
327
328
    /**
329
     * Overload of an assignment operator.
330
     * @param[in] addr A const reference to instance of IPv4Address
331
     * @return A reference to the assignee
332
     */
333
    inline IPAddress& operator=(const IPv4Address& addr);
334
335
    /**
336
     * Overload of an assignment operator.
337
     * @param[in] addr A const reference to instance of IPv6Address
338
     * @return A reference to the assignee
339
     */
340
    inline IPAddress& operator=(const IPv6Address& addr);
341
342
    /**
343
     * Gets the address type: IPv4 or IPv6
344
     * @return The address type
345
     */
346
0
    AddressType getType() const { return static_cast<AddressType>(m_Type); }
347
348
    /**
349
     * Returns a std::string representation of the address
350
     * @return A string representation of the address
351
     */
352
    std::string toString() const { return (getType() == IPv4AddressType) ? m_IPv4.toString() : m_IPv6.toString(); }
353
354
    /**
355
     * @return Determine whether the address is unspecified
356
     */
357
0
    bool isValid() const { return (getType() == IPv4AddressType) ? m_IPv4.isValid() : m_IPv6.isValid(); }
358
359
    /**
360
     * @return Determine whether the object contains an IP version 4 address
361
     */
362
    bool isIPv4() const { return getType() == IPv4AddressType; }
363
364
    /**
365
     * @return Determine whether the object contains an IP version 6 address
366
     */
367
    bool isIPv6() const { return getType() == IPv6AddressType; }
368
369
    /**
370
     * Determine whether the address is a multicast address
371
     * @return True if an address is multicast
372
     */
373
    bool isMulticast() const { return (getType() == IPv4AddressType) ? m_IPv4.isMulticast() : m_IPv6.isMulticast(); }
374
375
    /**
376
     * Get a reference to IPv4 address instance
377
     * @return The const reference to IPv4Address instance
378
     */
379
0
    const IPv4Address& getIPv4() const { return m_IPv4; }
380
381
    /**
382
     * Get a reference to IPv6 address instance
383
     * @return The const reference to IPv6Address instance
384
     */
385
    const IPv6Address& getIPv6() const { return m_IPv6; }
386
387
    /**
388
     * Overload of the equal-to operator
389
     * @param[in] rhs The object to compare with
390
     * @return True if the addresses are equal, false otherwise
391
     */
392
    inline bool operator==(const IPAddress& rhs) const;
393
394
    /**
395
     * Overload of the less-than operator
396
     * @param[in] rhs The object to compare with
397
     * @return True if the address value is lower than the other address value, false otherwise
398
     */
399
    inline bool operator<(const IPAddress& rhs) const;
400
401
    /**
402
     * Overload of the not-equal-to operator
403
     * @param[in] rhs The object to compare with
404
     * @return True if the addresses are not equal, false otherwise
405
     */
406
    bool operator!=(const IPAddress& rhs) const { return !(*this == rhs); }
407
408
  private:
409
    uint8_t m_Type;
410
    IPv4Address m_IPv4;
411
    IPv6Address m_IPv6;
412
  };
413
414
415
  // implementation of inline methods
416
417
  bool IPAddress::operator==(const IPAddress& rhs) const
418
  {
419
    if (isIPv4())
420
      return rhs.isIPv4() ? (m_IPv4 == rhs.m_IPv4) : false;
421
422
    return rhs.isIPv6() ? m_IPv6 == rhs.m_IPv6 : false;
423
  }
424
425
  bool IPAddress::operator<(const IPAddress& rhs) const
426
  {
427
    if(isIPv4())
428
    {
429
      // treat IPv4 as less than IPv6
430
      // If current obj is IPv4 and other is IPv6 return true
431
      return rhs.isIPv4() ? (m_IPv4 < rhs.m_IPv4) : true;
432
    }
433
    return rhs.isIPv6() ? m_IPv6 < rhs.m_IPv6 : false;
434
  }
435
436
  IPAddress& IPAddress::operator=(const IPv4Address& addr)
437
  {
438
    m_Type = IPv4AddressType;
439
    m_IPv4 = addr;
440
    return *this;
441
  }
442
443
  IPAddress& IPAddress::operator=(const IPv6Address& addr)
444
  {
445
    m_Type = IPv6AddressType;
446
    m_IPv6 = addr;
447
    return *this;
448
  }
449
450
} // namespace pcpp
451
452
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv4Address& ipv4Address)
453
{
454
  os << ipv4Address.toString();
455
  return os;
456
}
457
458
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv6Address& ipv6Address)
459
{
460
  os << ipv6Address.toString();
461
  return os;
462
}
463
464
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPAddress& ipAddress)
465
{
466
  os << ipAddress.toString();
467
  return os;
468
}
469
470
#endif /* PCAPPP_IPADDRESS */