Coverage Report

Created: 2024-02-25 06:29

/src/PcapPlusPlus/Common++/header/IpAddress.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include <stdint.h>
4
#include <string.h>
5
#include <string>
6
#include <algorithm>
7
#include <ostream>
8
9
#ifndef PCPP_DEPRECATED
10
#if defined(__GNUC__) || defined(__clang__)
11
#define PCPP_DEPRECATED __attribute__((deprecated))
12
#elif defined(_MSC_VER)
13
#define PCPP_DEPRECATED __declspec(deprecated)
14
#else
15
#pragma message("WARNING: DEPRECATED feature is not implemented for this compiler")
16
#define PCPP_DEPRECATED
17
#endif
18
#endif
19
20
/// @file
21
22
23
/**
24
 * \namespace pcpp
25
 * \brief The main namespace for the PcapPlusPlus lib
26
 */
27
namespace pcpp
28
{
29
30
  // forward declarations
31
  class IPv4Network;
32
  class IPv6Network;
33
34
  // The implementation of the classes is based on document N4771 "Working Draft, C++ Extensions for Networking"
35
  // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4771.pdf
36
37
  /**
38
   * @class IPv4Address
39
   * Represents an IPv4 address (of type XXX.XXX.XXX.XXX)
40
   */
41
  class IPv4Address
42
  {
43
  public:
44
    /**
45
     * A default constructor that creates an instance of the class with unspecified/zero address
46
     */
47
78.0k
    IPv4Address() { memset(m_Bytes, 0, sizeof(m_Bytes)); }
48
49
    /**
50
     * A constructor that creates an instance of the class out of 4-byte integer value.
51
     * @param[in] addrAsInt The address as 4-byte integer in network byte order
52
     */
53
1.02M
    IPv4Address(uint32_t addrAsInt) { memcpy(m_Bytes, &addrAsInt, sizeof(m_Bytes)); }
54
55
    /**
56
     * A constructor that creates an instance of the class out of 4-byte array.
57
     * @param[in] bytes The address as 4-byte array in network byte order
58
     */
59
9.97k
    IPv4Address(const uint8_t bytes[4]) { memcpy(m_Bytes, bytes, sizeof(m_Bytes)); }
60
61
    /**
62
     * A constructor that creates an instance of the class out of std::string value
63
     * If the string doesn't represent a valid IPv4 address, an instance will store an unspecified address
64
     * @param[in] addrAsString The std::string representation of the address
65
     */
66
    IPv4Address(const std::string& addrAsString);
67
68
    /**
69
     * Converts the IPv4 address into a 4B integer
70
     * @return a 4B integer in network byte order representing the IPv4 address
71
     */
72
    inline uint32_t toInt() const;
73
74
    /**
75
     * Returns a pointer to 4-byte array representing the IPv4 address
76
     */
77
826k
    const uint8_t* toBytes() const { return m_Bytes; }
78
79
    /**
80
     * Returns a std::string representation of the address
81
     * @return A string representation of the address
82
     */
83
    std::string toString() const;
84
85
    /**
86
     * Determine whether the address is a multicast address
87
     * @return True if an address is multicast
88
     */
89
    bool isMulticast() const;
90
91
    /**
92
     * Determine whether the address is valid (it's not an unspecified/zero)
93
     * @return True if an address is not unspecified/zero
94
     */
95
49.8k
    bool isValid() const { return toInt() != 0; }
96
97
    /**
98
     * Overload of the equal-to operator
99
     * @param[in] rhs The object to compare with
100
     * @return True if the addresses are equal, false otherwise
101
     */
102
0
    bool operator==(const IPv4Address& rhs) const { return toInt() == rhs.toInt(); }
103
104
    /**
105
     * Overload of the less-than operator
106
     * @param[in] rhs The object to compare with
107
     * @return True if the address value is lower than the other address value, false otherwise
108
     */
109
    bool operator<(const IPv4Address& rhs) const
110
0
    {
111
0
      uint32_t intVal = toInt();
112
0
      std::reverse((uint8_t*)(&intVal), (uint8_t*)(&intVal) + sizeof(intVal));
113
114
0
      uint32_t rhsIntVal = rhs.toInt();
115
0
      std::reverse((uint8_t*)(&rhsIntVal), (uint8_t*)(&rhsIntVal) + sizeof(rhsIntVal));
116
117
0
      return intVal < rhsIntVal;
118
0
    }
119
120
    /**
121
     * Overload of the not-equal-to operator
122
     * @param[in] rhs The object to compare with
123
     * @return True if the addresses are not equal, false otherwise
124
     */
125
0
    bool operator!=(const IPv4Address& rhs) const { return !(*this == rhs); }
126
127
    /**
128
     * Checks whether the address matches a network.
129
     * @param network An IPv4Network network
130
     * @return True if the address matches the network or false otherwise
131
     */
132
    bool matchNetwork(const IPv4Network& network) const;
133
134
    /**
135
     * Checks whether the address matches a network.
136
     * For example: this method will return true for address 10.1.1.9 and network which is one of:
137
     * 10.1.1.1/24, 10.1.1.1/255.255.255.0
138
     * Another example: this method will return false for address 11.1.1.9 and network which is one of:
139
     * 10.1.1.1/16, 10.1.1.1/255.255.0.0
140
     * @param[in] network A string in one of these formats:
141
     *  - X.X.X.X/Y where X.X.X.X is a valid IP address and Y is a number between 0 and 32
142
     *  - X.X.X.X/Y.Y.Y.Y where X.X.X.X is a valid IP address and Y.Y.Y.Y is a valid netmask
143
     * @return True if the address matches the network or false if it doesn't or if the network is invalid
144
     */
145
    bool matchNetwork(const std::string& network) const;
146
147
    /**
148
     * @deprecated This method is deprecated, please use matchNetwork(const IPv4Network& network)
149
     */
150
    PCPP_DEPRECATED bool matchSubnet(const IPv4Address& subnet, const std::string& subnetMask) const;
151
152
    /**
153
     * @deprecated This method is deprecated, please use matchNetwork(const IPv4Network& network)
154
     */
155
    PCPP_DEPRECATED bool matchSubnet(const IPv4Address& subnet, const IPv4Address& subnetMask) const;
156
157
    /**
158
     * A static value representing a zero value of IPv4 address, meaning address of value "0.0.0.0"
159
     * Notice this value can be omitted in the user code because the default constructor creates an instance with an unspecified/zero address.
160
     * In order to check whether the address is zero the method isValid can be used
161
     */
162
    static const IPv4Address Zero;
163
164
    /**
165
     * A static values representing the lower and upper bound of IPv4 multicast ranges. The bounds are inclusive.
166
     * MulticastRangeLowerBound is initialized to "224.0.0.0".
167
     * MulticastRangeUpperBound is initialized to "239.255.255.255".
168
     * In order to check whether the address is a multicast address the isMulticast method can be used.
169
     */
170
    static const IPv4Address MulticastRangeLowerBound;
171
    static const IPv4Address MulticastRangeUpperBound;
172
173
  private:
174
    uint8_t m_Bytes[4];
175
  }; // class IPv4Address
176
177
178
  // Implementation of inline methods
179
180
  uint32_t IPv4Address::toInt() const
181
343k
  {
182
343k
    uint32_t addr;
183
343k
    memcpy(&addr, m_Bytes, sizeof(m_Bytes));
184
343k
    return addr;
185
343k
  }
186
187
  /**
188
   * @class IPv6Address
189
   * Represents an IPv6 address (of type xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx).
190
   */
191
  class IPv6Address
192
  {
193
  public:
194
    /**
195
     * A default constructor that creates an instance of the class with unspecified/zero address
196
     */
197
296k
    IPv6Address() { memset(m_Bytes, 0, sizeof(m_Bytes)); }
198
199
    /**
200
     * A constructor that creates an instance of the class out of 16-byte array.
201
     * @param[in] bytes The address as 16-byte array in network byte order
202
     */
203
265k
    IPv6Address(const uint8_t bytes[16]) { memcpy(m_Bytes, bytes, sizeof(m_Bytes)); }
204
205
    /**
206
     * A constructor that creates an instance of the class out of std::string value
207
     * If the string doesn't represent a valid IPv6 address, an instance will store an unspecified address
208
     * @param[in] addrAsString The std::string representation of the address
209
     */
210
    IPv6Address(const std::string& addrAsString);
211
212
    /**
213
     * Returns a pointer to 16-byte array representing the IPv6 address
214
     */
215
179k
    const uint8_t* toBytes() const { return m_Bytes; }
216
217
    /**
218
     * Returns a std::string representation of the address
219
     * @return A string representation of the address
220
     */
221
    std::string toString() const;
222
223
    /**
224
     * Determine whether the address is a multicast address
225
     * @return True if an address is multicast
226
     */
227
    bool isMulticast() const;
228
229
    /**
230
     * Determine whether the address is unspecified
231
     */
232
0
    bool isValid() const { return *this != Zero; }
233
234
    /**
235
     * Overload of the equal-to operator
236
     * @param[in] rhs The object to compare with
237
     * @return True if the addresses are equal, false otherwise
238
     */
239
0
    bool operator==(const IPv6Address& rhs) const { return memcmp(toBytes(), rhs.toBytes(), sizeof(m_Bytes)) == 0; }
240
241
    /**
242
     * Overload of the less-than operator
243
     * @param[in] rhs The object to compare with
244
     * @return True if the address value is lower than the other address value, false otherwise
245
     */
246
0
    bool operator<(const IPv6Address& rhs) const { return memcmp(toBytes(), rhs.toBytes(), sizeof(m_Bytes)) < 0; }
247
248
    /**
249
     * Overload of the not-equal-to operator
250
     * @param[in] rhs The object to compare with
251
     * @return True if the addresses are not equal, false otherwise
252
     */
253
0
    bool operator!=(const IPv6Address &rhs) const { return !(*this == rhs); }
254
255
256
    /**
257
     * Allocates a byte array and copies address value into it. Array deallocation is user responsibility
258
     * @param[in] arr A pointer to where array will be allocated
259
     * @param[out] length Returns the length in bytes of the array that was allocated
260
     */
261
    void copyTo(uint8_t** arr, size_t& length) const;
262
263
    /**
264
     * Gets a pointer to an already allocated byte array and copies the address value to it.
265
     * This method assumes array allocated size is at least 16 (the size of an IPv6 address)
266
     * @param[in] arr A pointer to the array which address will be copied to
267
     */
268
83.1k
    void copyTo(uint8_t* arr) const { memcpy(arr, m_Bytes, sizeof(m_Bytes)); }
269
270
    /**
271
     * Checks whether the address matches a network.
272
     * @param network An IPv6Network network
273
     * @return True if the address matches the network or false otherwise
274
     */
275
    bool matchNetwork(const IPv6Network& network) const;
276
277
    /**
278
     * Checks whether the address matches a network.
279
     * For example: this method will return true for address d6e5:83dc:0c58:bc5d:1449:5898:: and network
280
     * which is one of:
281
     * d6e5:83dc:0c58:bc5d::/64, d6e5:83dc:0c58:bc5d::/ffff:ffff:ffff:ffff::
282
     * Another example: this method will return false for address d6e5:83dc:: and network which is one of:
283
     * d6e5:83dc:0c58:bc5d::/64, d6e5:83dc:0c58:bc5d::/ffff:ffff:ffff:ffff::
284
     * @param[in] network A string in one of these formats:
285
     *  - IPV6_ADDRESS/Y where IPV6_ADDRESS is a valid IPv6 address and Y is a number between 0 and 128
286
     *  - IPV6_ADDRESS/IPV6_NETMASK where IPV6_ADDRESS is a valid IPv6 address and IPV6_NETMASK is a valid
287
     *    IPv6 netmask
288
     * @return True if the address matches the network or false if it doesn't or if the network is invalid
289
     */
290
    bool matchNetwork(const std::string& network) const;
291
292
    /**
293
      * @deprecated This method is deprecated, please use matchNetwork(const IPv6Network& network)
294
      */
295
    PCPP_DEPRECATED bool matchSubnet(const IPv6Address& subnet, uint8_t prefixLength) const;
296
297
    /**
298
     * 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"
299
     * Notice this value can be omitted in the user code because the default constructor creates an instance with an unspecified/zero address.
300
     * In order to check whether the address is zero the method isValid can be used
301
     */
302
    static const IPv6Address Zero;
303
304
    /**
305
     * A static value representing the lower bound of IPv6 multicast ranges. The bound is inclusive.
306
     * MulticastRangeLowerBound is initialized to "ff00:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0".
307
     * In order to check whether the address is a multicast address the isMulticast method can be used.
308
     */
309
    static const IPv6Address MulticastRangeLowerBound;
310
311
  private:
312
    uint8_t m_Bytes[16];
313
  }; // class IPv6Address
314
315
316
  /**
317
   * @class IPAddress
318
   * The class is a version-independent representation for an IP address
319
   */
320
  class IPAddress
321
  {
322
  public:
323
    /**
324
     * An enum representing the address type: IPv4 or IPv6
325
     */
326
    enum AddressType
327
    {
328
      /**
329
       * IPv4 address type
330
       */
331
      IPv4AddressType,
332
      /**
333
       * IPv6 address type
334
       */
335
      IPv6AddressType
336
    };
337
338
    /**
339
     * A default constructor that creates an instance of the class with unspecified IPv4 address
340
     */
341
0
    IPAddress() : m_Type(IPv4AddressType) {}
342
343
    /**
344
     * A constructor that creates an instance of the class out of IPv4Address.
345
     * @param[in] addr A const reference to instance of IPv4Address
346
     */
347
296k
    IPAddress(const IPv4Address& addr) : m_Type(IPv4AddressType), m_IPv4(addr) {}
348
349
    /**
350
     * A constructor that creates an instance of the class out of IPv6Address.
351
     * @param[in] addr A const reference to instance of IPv6Address
352
     */
353
78.0k
    IPAddress(const IPv6Address& addr) : m_Type(IPv6AddressType), m_IPv6(addr) {}
354
355
    /**
356
     * A constructor that creates an instance of the class out of std::string value
357
     * If the string doesn't represent a valid IPv4 or IPv6 address, an instance will store an unspecified address
358
     * @param[in] addrAsString The std::string representation of the address
359
     */
360
    IPAddress(const std::string& addrAsString);
361
362
    /**
363
     * Overload of an assignment operator.
364
     * @param[in] addr A const reference to instance of IPv4Address
365
     * @return A reference to the assignee
366
     */
367
    inline IPAddress& operator=(const IPv4Address& addr);
368
369
    /**
370
     * Overload of an assignment operator.
371
     * @param[in] addr A const reference to instance of IPv6Address
372
     * @return A reference to the assignee
373
     */
374
    inline IPAddress& operator=(const IPv6Address& addr);
375
376
    /**
377
     * Gets the address type: IPv4 or IPv6
378
     * @return The address type
379
     */
380
0
    AddressType getType() const { return static_cast<AddressType>(m_Type); }
381
382
    /**
383
     * Returns a std::string representation of the address
384
     * @return A string representation of the address
385
     */
386
0
    std::string toString() const { return (getType() == IPv4AddressType) ? m_IPv4.toString() : m_IPv6.toString(); }
387
388
    /**
389
     * @return Determine whether the address is unspecified
390
     */
391
0
    bool isValid() const { return (getType() == IPv4AddressType) ? m_IPv4.isValid() : m_IPv6.isValid(); }
392
393
    /**
394
     * @return Determine whether the object contains an IP version 4 address
395
     */
396
0
    bool isIPv4() const { return getType() == IPv4AddressType; }
397
398
    /**
399
     * @return Determine whether the object contains an IP version 6 address
400
     */
401
0
    bool isIPv6() const { return getType() == IPv6AddressType; }
402
403
    /**
404
     * Determine whether the address is a multicast address
405
     * @return True if an address is multicast
406
     */
407
0
    bool isMulticast() const { return (getType() == IPv4AddressType) ? m_IPv4.isMulticast() : m_IPv6.isMulticast(); }
408
409
    /**
410
     * Get a reference to IPv4 address instance
411
     * @return The const reference to IPv4Address instance
412
     */
413
292k
    const IPv4Address& getIPv4() const { return m_IPv4; }
414
415
    /**
416
     * Get a reference to IPv6 address instance
417
     * @return The const reference to IPv6Address instance
418
     */
419
75.3k
    const IPv6Address& getIPv6() const { return m_IPv6; }
420
421
    /**
422
     * Overload of the equal-to operator
423
     * @param[in] rhs The object to compare with
424
     * @return True if the addresses are equal, false otherwise
425
     */
426
    inline bool operator==(const IPAddress& rhs) const;
427
428
    /**
429
     * Overload of the less-than operator
430
     * @param[in] rhs The object to compare with
431
     * @return True if the address value is lower than the other address value, false otherwise
432
     */
433
    inline bool operator<(const IPAddress& rhs) const;
434
435
    /**
436
     * Overload of the not-equal-to operator
437
     * @param[in] rhs The object to compare with
438
     * @return True if the addresses are not equal, false otherwise
439
     */
440
0
    bool operator!=(const IPAddress& rhs) const { return !(*this == rhs); }
441
442
  private:
443
    uint8_t m_Type;
444
    IPv4Address m_IPv4;
445
    IPv6Address m_IPv6;
446
  };
447
448
449
  // implementation of inline methods
450
451
  bool IPAddress::operator==(const IPAddress& rhs) const
452
0
  {
453
0
    if (isIPv4())
454
0
      return rhs.isIPv4() ? (m_IPv4 == rhs.m_IPv4) : false;
455
0
456
0
    return rhs.isIPv6() ? m_IPv6 == rhs.m_IPv6 : false;
457
0
  }
458
459
  bool IPAddress::operator<(const IPAddress& rhs) const
460
0
  {
461
0
    if(isIPv4())
462
0
    {
463
0
      // treat IPv4 as less than IPv6
464
0
      // If current obj is IPv4 and other is IPv6 return true
465
0
      return rhs.isIPv4() ? (m_IPv4 < rhs.m_IPv4) : true;
466
0
    }
467
0
    return rhs.isIPv6() ? m_IPv6 < rhs.m_IPv6 : false;
468
0
  }
469
470
  IPAddress& IPAddress::operator=(const IPv4Address& addr)
471
0
  {
472
0
    m_Type = IPv4AddressType;
473
0
    m_IPv4 = addr;
474
0
    return *this;
475
0
  }
476
477
  IPAddress& IPAddress::operator=(const IPv6Address& addr)
478
0
  {
479
0
    m_Type = IPv6AddressType;
480
0
    m_IPv6 = addr;
481
0
    return *this;
482
0
  }
483
484
485
  /**
486
   * @class IPv4Network
487
   * A class representing IPv4 network definition
488
   */
489
  class IPv4Network
490
  {
491
  public:
492
    /**
493
     * A constructor that creates an instance of the class out of an address representing the network prefix
494
     * and a prefix length
495
     * @param address An address representing the network prefix. If the address is invalid std::invalid_argument
496
     * exception is thrown
497
     * @param prefixLen A number between 0 and 32 representing the prefix length. If another value is provided
498
     * std::invalid_argument exception is thrown
499
     */
500
    IPv4Network(const IPv4Address& address, uint8_t prefixLen);
501
502
    /**
503
     * A constructor that creates an instance of the class out of an address representing the network prefix
504
     * and a netmask
505
     * @param address An address representing the network prefix. If the address is invalid std::invalid_argument
506
     * exception is thrown
507
     * @param netmask A string representing a netmask in the format of X.X.X.X, for example: 255.255.0.0.
508
     * Please notice that netmasks that start with zeros are invalid, for example: 0.0.255.255. The only netmask
509
     * starting with zeros that is valid is 0.0.0.0. If the netmask is invalid std::invalid_argument
510
     * exception is thrown
511
     */
512
    IPv4Network(const IPv4Address& address, const std::string& netmask);
513
514
    /**
515
     * A constructor that creates an instance of the class out of a string representing the network prefix and
516
     * a prefix length or a netmask
517
     * @param addressAndNetmask A string in one of these formats:
518
     *  - X.X.X.X/Y where X.X.X.X is a valid IPv4 address representing the network prefix and Y is a number between
519
     *    0 and 32 representing the network prefix
520
     *  - X.X.X.X/Y.Y.Y.Y where X.X.X.X is a valid IPv4 address representing the network prefix and Y.Y.Y.Y is
521
     *    a valid netmask
522
     *  For any invalid value std::invalid_argument is thrown
523
     */
524
    IPv4Network(const std::string& addressAndNetmask);
525
526
    /**
527
     * @return The prefix length, for example: the prefix length of 10.10.10.10/255.0.0.0 is 8
528
     */
529
    uint8_t getPrefixLen() const;
530
531
    /**
532
     * @return The netmask, for example: the netmask of 10.10.10.10/8 is 255.0.0.0
533
     */
534
0
    std::string getNetmask() const { return IPv4Address(m_Mask).toString(); }
535
536
    /**
537
     * @return The network prefix, for example: the network prefix of 10.10.10.10/16 is 10.10.0.0
538
    */
539
0
    IPv4Address getNetworkPrefix() const { return IPv4Address(m_NetworkPrefix); }
540
541
    /**
542
     * @return The lowest non-reserved IPv4 address in this network, for example: the lowest address
543
     * in 10.10.10.10/16 is 10.10.0.1
544
     */
545
    IPv4Address getLowestAddress() const;
546
547
    /**
548
     * @return The highest non-reserved IPv4 address in this network, for example: the highest address
549
     * in 10.10.10.10/16 is 10.10.255.254
550
     */
551
    IPv4Address getHighestAddress() const;
552
553
    /**
554
     * @return The number of addresses in this network including reserved addresses, for example:
555
     * the number of addresses in 10.10.0.0/24 is 256
556
     */
557
    uint64_t getTotalAddressCount() const;
558
559
    /**
560
     * @param address An IPv4 address
561
     * @return True is the address belongs to the network, false otherwise or if the address isn't valid
562
     */
563
    bool includes(const IPv4Address& address) const;
564
565
    /**
566
     * @param network An IPv4 network
567
     * @return True is the input network is completely included within this network, false otherwise, for example:
568
     * 10.10.10.10/16 includes 10.10.10.10/24 but doesn't include 10.10.10.10/8
569
     */
570
    bool includes(const IPv4Network& network) const;
571
572
    /**
573
     * @return A string representation of the network in a format of NETWORK_PREFIX/PREFIX_LEN, for example:
574
     * 192.168.0.0/16
575
     */
576
    std::string toString() const;
577
578
  private:
579
    uint32_t m_NetworkPrefix;
580
    uint32_t m_Mask;
581
582
    bool isValidNetmask(const std::string& netmask);
583
    void initFromAddressAndPrefixLength(const IPv4Address& address, uint8_t prefixLen);
584
    void initFromAddressAndNetmask(const IPv4Address& address, const std::string& netmask);
585
  };
586
587
588
  /**
589
   * @class IPv6Network
590
   * A class representing IPv6 network definition
591
   */
592
  class IPv6Network
593
  {
594
  public:
595
    /**
596
     * A constructor that creates an instance of the class out of an address representing the network prefix
597
     * and a prefix length
598
     * @param address An address representing the network prefix. If the address is invalid std::invalid_argument
599
     * exception is thrown
600
     * @param prefixLen A number between 0 and 128 representing the prefix length. If another value is provided
601
     * std::invalid_argument exception is thrown
602
     */
603
    IPv6Network(const IPv6Address& address, uint8_t prefixLen);
604
605
    /**
606
     * A constructor that creates an instance of the class out of an address representing the network prefix
607
     * and a netmask
608
     * @param address An address representing the network prefix. If the address is invalid std::invalid_argument
609
     * exception is thrown
610
     * @param netmask A string representing a netmask in valid IPv6 format, for example: ffff:ffff::.
611
     * Please notice that netmasks that start with zeros are invalid, for example: 0:ffff::. The only netmask
612
     * starting with zeros that is valid is all zeros (::). If the netmask is invalid std::invalid_argument
613
     * exception is thrown
614
     */
615
    IPv6Network(const IPv6Address& address, const std::string& netmask);
616
617
    /**
618
     * A constructor that creates an instance of the class out of a string representing the network prefix and
619
     * a prefix length or a netmask
620
     * @param addressAndNetmask A string in one of these formats:
621
     *  - IPV6_ADDRESS/Y where IPV6_ADDRESS is a valid IPv6 address representing the network prefix and Y is
622
     *    a number between 0 and 128 representing the network prefix
623
     *  - IPV6_ADDRESS/IPV6_NETMASK where IPV6_ADDRESS is a valid IPv6 address representing the network prefix
624
     *    and IPV6_NETMASK is a valid IPv6 netmask
625
     *  For any invalid value std::invalid_argument is thrown
626
     */
627
    IPv6Network(const std::string& addressAndNetmask);
628
629
    /**
630
     * @return The prefix length, for example: the prefix length of 3546::/ffff:: is 16
631
     */
632
    uint8_t getPrefixLen() const;
633
634
    /**
635
     * @return The netmask, for example: the netmask of 3546::/16 is ffff::
636
     */
637
0
    std::string getNetmask() const { return IPv6Address(m_Mask).toString(); }
638
639
    /**
640
     * @return The network prefix, for example: the network prefix of 3546:f321::/16 is 3546::
641
    */
642
0
    IPv6Address getNetworkPrefix() const { return IPv6Address(m_NetworkPrefix); }
643
644
    /**
645
    * @return The lowest non-reserved IPv6 address in this network, for example: the lowest address in 3546::/16 is
646
    * 3546::1
647
    */
648
    IPv6Address getLowestAddress() const;
649
650
    /**
651
     * @return The highest IPv6 address in this network, for example: the highest address in 3546::/16 is
652
     * 3546:ffff:ffff:ffff:ffff:ffff:ffff:ffff
653
     */
654
    IPv6Address getHighestAddress() const;
655
656
    /**
657
     * @return The number of addresses in this network, for example: the number of addresses in 16ff::/120 is 256.
658
     * If the number of addresses exceeds the size of uint64_t a std::out_of_range exception is thrown
659
     */
660
    uint64_t getTotalAddressCount() const;
661
662
    /**
663
     * @param address An IPv6 address
664
     * @return True is the address belongs to the network, false otherwise or if the address isn't valid
665
     */
666
    bool includes(const IPv6Address& address) const;
667
668
    /**
669
     * @param network An IPv6 network
670
     * @return True is the input network is completely included within this network, false otherwise, for example:
671
     * 3546::/64 includes 3546::/120 but doesn't include 3546::/16
672
     */
673
    bool includes(const IPv6Network& network) const;
674
675
    /**
676
     * @return A string representation of the network in a format of NETWORK_PREFIX/PREFIX_LEN, for example:
677
     * fda7:9f81:6c23:275::/64
678
     */
679
    std::string toString() const;
680
681
  private:
682
    uint8_t m_NetworkPrefix[16];
683
    uint8_t m_Mask[16];
684
685
    bool isValidNetmask(const std::string& netmask);
686
    void initFromAddressAndPrefixLength(const IPv6Address& address, uint8_t prefixLen);
687
    void initFromAddressAndNetmask(const IPv6Address& address, const std::string& netmask);
688
  };
689
690
691
  /**
692
   * @class IPNetwork
693
   * A class representing version independent IP network definition, both IPv4 and IPv6 are included
694
   */
695
  class IPNetwork
696
  {
697
  public:
698
    /**
699
     * A constructor that creates an instance of the class out of an address representing the network prefix
700
     * and a prefix length
701
     * @param address An address representing the network prefix. If the address is invalid std::invalid_argument
702
     * exception is thrown
703
     * @param prefixLen A number representing the prefix length. If the value isn't in the range allowed for the
704
     * network (0 - 32 for IPv4 networks or 0 - 128 for IPv6 networks) and std::invalid_argument exception is thrown
705
     */
706
    IPNetwork(const IPAddress& address, uint8_t prefixLen)
707
0
    {
708
0
      if (address.isIPv4())
709
0
      {
710
0
        m_IPv4Network = new IPv4Network(address.getIPv4(), prefixLen);
711
0
        m_IPv6Network = nullptr;
712
0
      }
713
0
      else
714
0
      {
715
0
        m_IPv6Network = new IPv6Network(address.getIPv6(), prefixLen);
716
0
        m_IPv4Network = nullptr;
717
0
      }
718
0
    }
719
720
    /**
721
     * A constructor that creates an instance of the class out of an address representing the network prefix
722
     * and a netmask
723
     * @param address An address representing the network prefix. If the address is invalid std::invalid_argument
724
     * exception is thrown
725
     * @param netmask A string representing a netmask in valid format, for example: ffff:ffff:: for IPv6 networks
726
     * or 255.255.0.0 for IPv4 networks.
727
     * Please notice that netmasks that start with zeros are invalid, for example: 0:ffff:: or 0.255.255.255.
728
     * The only netmask starting with zeros that is valid is all zeros (:: or 0.0.0.0).
729
     * If the netmask is invalid std::invalid_argument exception is thrown
730
     */
731
    IPNetwork(const IPAddress& address, const std::string& netmask)
732
0
    {
733
0
      if (address.isIPv4())
734
0
      {
735
0
        m_IPv4Network = new IPv4Network(address.getIPv4(), netmask);
736
0
        m_IPv6Network = nullptr;
737
0
      }
738
0
      else
739
0
      {
740
0
        m_IPv6Network = new IPv6Network(address.getIPv6(), netmask);
741
0
        m_IPv4Network = nullptr;
742
0
      }
743
0
    }
744
745
    /**
746
     * A constructor that creates an instance of the class out of a string representing the network prefix and
747
     * a prefix length or a netmask
748
     * @param addressAndNetmask A string in one of these formats:
749
     *  - IP_ADDRESS/Y where IP_ADDRESS is a valid IP address representing the network prefix and Y is
750
     *    a number representing the network prefix
751
     *  - IP_ADDRESS/NETMASK where IP_ADDRESS is a valid IP address representing the network prefix and NETMASK
752
     *    is a valid netmask for this type of network (IPv4 or IPv6 network)
753
     *  For any invalid value std::invalid_argument is thrown
754
     */
755
    IPNetwork(const std::string& addressAndNetmask)
756
0
    {
757
0
      try
758
0
      {
759
0
        m_IPv4Network = new IPv4Network(addressAndNetmask);
760
0
        m_IPv6Network = nullptr;
761
0
      }
762
0
      catch (const std::invalid_argument&)
763
0
      {
764
0
        m_IPv6Network = new IPv6Network(addressAndNetmask);
765
0
        m_IPv4Network = nullptr;
766
0
      }
767
0
    }
768
769
    /**
770
     * A copy c'tor for this class
771
     * @param other The instance to copy from
772
     */
773
    IPNetwork(const IPNetwork& other)
774
0
    {
775
0
      m_IPv4Network = nullptr;
776
0
      m_IPv6Network = nullptr;
777
0
778
0
      if (other.m_IPv4Network)
779
0
      {
780
0
        m_IPv4Network = new IPv4Network(*other.m_IPv4Network);
781
0
      }
782
0
783
0
      if (other.m_IPv6Network)
784
0
      {
785
0
        m_IPv6Network = new IPv6Network(*other.m_IPv6Network);
786
0
      }
787
0
    }
788
789
    /**
790
     * A destructor for this class
791
     */
792
    ~IPNetwork()
793
0
    {
794
0
      if (m_IPv4Network)
795
0
      {
796
0
        delete m_IPv4Network;
797
0
      }
798
0
799
0
      if (m_IPv6Network)
800
0
      {
801
0
        delete m_IPv6Network;
802
0
      }
803
0
    }
804
805
    /**
806
     * Overload of an assignment operator.
807
     * @param[in] other An instance of IPNetwork to assign
808
     * @return A reference to the assignee
809
     */
810
    IPNetwork& operator=(const IPNetwork& other)
811
0
    {
812
0
      if (other.isIPv4Network())
813
0
      {
814
0
        return this->operator=(*other.m_IPv4Network);
815
0
      }
816
0
      else
817
0
      {
818
0
        return this->operator=(*other.m_IPv6Network);
819
0
      }
820
0
    }
821
822
    /**
823
     * Overload of an assignment operator.
824
     * @param[in] other An instance of IPv4Network to assign
825
     * @return A reference to the assignee
826
     */
827
    IPNetwork& operator=(const IPv4Network& other)
828
0
    {
829
0
      if (m_IPv4Network)
830
0
      {
831
0
        delete m_IPv4Network;
832
0
        m_IPv4Network = nullptr;
833
0
      }
834
0
835
0
      if (m_IPv6Network)
836
0
      {
837
0
        delete m_IPv6Network;
838
0
        m_IPv6Network = nullptr;
839
0
      }
840
0
841
0
      m_IPv4Network = new IPv4Network(other);
842
0
843
0
      return *this;
844
0
    }
845
846
    /**
847
     * Overload of an assignment operator.
848
     * @param[in] other An instance of IPv6Network to assign
849
     * @return A reference to the assignee
850
     */
851
    IPNetwork& operator=(const IPv6Network& other)
852
0
    {
853
0
      if (m_IPv4Network)
854
0
      {
855
0
        delete m_IPv4Network;
856
0
        m_IPv4Network = nullptr;
857
0
      }
858
0
859
0
      if (m_IPv6Network)
860
0
      {
861
0
        delete m_IPv6Network;
862
0
        m_IPv6Network = nullptr;
863
0
      }
864
0
865
0
      m_IPv6Network = new IPv6Network(other);
866
0
867
0
      return *this;
868
0
    }
869
870
    /**
871
     * @return The prefix length, for example: the prefix length of 3546::/ffff:: is 16, the prefix length of
872
     * 10.10.10.10/255.0.0.0 is 8
873
     */
874
    uint8_t getPrefixLen() const
875
0
    {
876
0
      return (m_IPv4Network != nullptr ? m_IPv4Network->getPrefixLen() : m_IPv6Network->getPrefixLen());
877
0
    }
878
879
    /**
880
    * @return The netmask, for example: the netmask of 3546::/16 is ffff::, the netmask of 10.10.10.10/8 is 255.0.0.0
881
    */
882
    std::string getNetmask() const
883
0
    {
884
0
      return (m_IPv4Network != nullptr ? m_IPv4Network->getNetmask() : m_IPv6Network->getNetmask());
885
0
    }
886
887
    /**
888
     * @return The network prefix, for example: the network prefix of 3546:f321::/16 is 3546::, the network prefix
889
     * of 10.10.10.10/16 is 10.10.0.0
890
    */
891
    IPAddress getNetworkPrefix() const
892
0
    {
893
0
      return (m_IPv4Network != nullptr ? IPAddress(m_IPv4Network->getNetworkPrefix()) : IPAddress(m_IPv6Network->getNetworkPrefix()));
894
0
    }
895
896
    /**
897
    * @return The lowest non-reserved IP address in this network, for example: the lowest address in 3546::/16 is
898
    * 3546::1, the lowest address in 10.10.10.10/16 is 10.10.0.1
899
    */
900
    IPAddress getLowestAddress() const
901
0
    {
902
0
      return (m_IPv4Network != nullptr ? IPAddress(m_IPv4Network->getLowestAddress()) : IPAddress(m_IPv6Network->getLowestAddress()));
903
0
    }
904
905
    /**
906
     * @return The highest non-reserved IP address in this network, for example: the highest address in 3546::/16 is
907
     * 3546:ffff:ffff:ffff:ffff:ffff:ffff:ffff, the highest address in 10.10.10.10/16 is 10.10.255.254
908
     */
909
    IPAddress getHighestAddress() const
910
0
    {
911
0
      return (m_IPv4Network != nullptr ? IPAddress(m_IPv4Network->getHighestAddress()) : IPAddress(m_IPv6Network->getHighestAddress()));
912
0
    }
913
914
    /**
915
     * @return The number of addresses in this network, for example: the number of addresses in 16ff::/120 is 256,
916
     * the number of addresses in 10.10.0.0/24 is 256. If the number of addresses exceeds the size of uint64_t
917
     * a std::out_of_range exception is thrown
918
     */
919
    uint64_t getTotalAddressCount() const
920
0
    {
921
0
      return (m_IPv4Network != nullptr ? m_IPv4Network->getTotalAddressCount() : m_IPv6Network->getTotalAddressCount());
922
0
    }
923
924
    /**
925
     * @return True if this is an IPv4 network, false otherwise
926
     */
927
    bool isIPv4Network() const
928
0
    {
929
0
      return m_IPv4Network != nullptr;
930
0
    }
931
932
    /**
933
     * @return True if this is an IPv6 network, false otherwise
934
     */
935
    bool isIPv6Network() const
936
0
    {
937
0
      return m_IPv6Network != nullptr;
938
0
    }
939
940
    /**
941
     * @param address An IP address
942
     * @return True is the address belongs to the network, false otherwise or if the address isn't valid
943
     */
944
    bool includes(const IPAddress& address) const
945
0
    {
946
0
      if (m_IPv4Network != nullptr)
947
0
      {
948
0
        if (address.isIPv6())
949
0
        {
950
0
          return false;
951
0
        }
952
0
953
0
        return m_IPv4Network->includes(address.getIPv4());
954
0
      }
955
0
      else
956
0
      {
957
0
        if (address.isIPv4())
958
0
        {
959
0
          return false;
960
0
        }
961
0
962
0
        return m_IPv6Network->includes(address.getIPv6());
963
0
      }
964
0
    }
965
966
    /**
967
     * @param network An IP network
968
     * @return True is the input network is completely included within this network, false otherwise
969
     */
970
    bool includes(const IPNetwork& network) const
971
0
    {
972
0
      if (m_IPv4Network != nullptr)
973
0
      {
974
0
        if (network.isIPv6Network())
975
0
        {
976
0
          return false;
977
0
        }
978
0
979
0
        return m_IPv4Network->includes(*network.m_IPv4Network);
980
0
      }
981
0
      else
982
0
      {
983
0
        if (network.isIPv4Network())
984
0
        {
985
0
          return false;
986
0
        }
987
0
988
0
        return m_IPv6Network->includes(*network.m_IPv6Network);
989
0
      }
990
0
    }
991
992
    /**
993
     * @return A string representation of the network in a format of NETWORK_PREFIX/PREFIX_LEN, for example:
994
     * fda7:9f81:6c23:275::/64 or 192.168.0.0/16
995
     */
996
    std::string toString() const
997
0
    {
998
0
      return (m_IPv4Network != nullptr ? m_IPv4Network->toString() : m_IPv6Network->toString());
999
0
    }
1000
1001
  private:
1002
    IPv4Network* m_IPv4Network;
1003
    IPv6Network* m_IPv6Network;
1004
  };
1005
} // namespace pcpp
1006
1007
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv4Address& ipv4Address)
1008
0
{
1009
0
  os << ipv4Address.toString();
1010
0
  return os;
1011
0
}
1012
1013
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv6Address& ipv6Address)
1014
0
{
1015
0
  os << ipv6Address.toString();
1016
0
  return os;
1017
0
}
1018
1019
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPAddress& ipAddress)
1020
0
{
1021
0
  os << ipAddress.toString();
1022
0
  return os;
1023
0
}
1024
1025
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv4Network& network)
1026
0
{
1027
0
  os << network.toString();
1028
0
  return os;
1029
0
}
1030
1031
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv6Network& network)
1032
0
{
1033
0
  os << network.toString();
1034
0
  return os;
1035
0
}
1036
1037
inline std::ostream& operator<<(std::ostream& os, const pcpp::IPNetwork& network)
1038
0
{
1039
0
  os << network.toString();
1040
0
  return os;
1041
0
}