Coverage Report

Created: 2026-09-28 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Common++/src/IpAddress.cpp
Line
Count
Source
1
0
#define LOG_MODULE CommonLogModuleIpUtils
2
3
#include <algorithm>
4
#include <sstream>
5
#include <stdexcept>
6
#include <bitset>
7
#include "Logger.h"
8
#include "IpUtils.h"
9
#include "IpAddress.h"
10
#include "EndianPortable.h"
11
12
// for AF_INET, AF_INET6
13
#if !defined(_WIN32)
14
# include <sys/socket.h>
15
#endif
16
17
namespace pcpp
18
{
19
20
  const IPv4Address IPv4Address::Zero;
21
  const IPv6Address IPv6Address::Zero;
22
23
  const IPv4Address IPv4Address::MulticastRangeLowerBound("224.0.0.0");
24
  const IPv4Address IPv4Address::MulticastRangeUpperBound("239.255.255.255");
25
  const IPv6Address IPv6Address::MulticastRangeLowerBound("ff00:0000:0000:0000:0000:0000:0000:0000");
26
27
  // ~~~~~~~~~~~
28
  // IPv4Address
29
  // ~~~~~~~~~~~
30
31
  std::string IPv4Address::toString() const
32
0
  {
33
0
    char addrBuffer[INET_ADDRSTRLEN];
34
35
0
    if (inet_ntop(AF_INET, toBytes(), addrBuffer, sizeof(addrBuffer)) != nullptr)
36
0
    {
37
0
      return addrBuffer;
38
0
    }
39
40
0
    return {};
41
0
  }
42
43
  bool IPv4Address::isMulticast() const
44
0
  {
45
0
    return !operator<(MulticastRangeLowerBound) &&
46
0
           (operator<(MulticastRangeUpperBound) || operator==(MulticastRangeUpperBound));
47
0
  }
48
49
  IPv4Address::IPv4Address(const uint8_t* bytes, size_t size)
50
0
  {
51
0
    if (bytes == nullptr)
52
0
    {
53
0
      throw std::invalid_argument("Buffer pointer is null");
54
0
    }
55
56
0
    if (size < 4)
57
0
    {
58
0
      throw std::out_of_range("Buffer size is smaller than IPv4 address size");
59
0
    }
60
0
    memcpy(m_Bytes.data(), bytes, 4 * sizeof(uint8_t));
61
0
  }
62
63
  IPv4Address::IPv4Address(const std::string& addrAsString)
64
4
  {
65
4
    if (inet_pton(AF_INET, addrAsString.data(), m_Bytes.data()) <= 0)
66
0
    {
67
0
      throw std::invalid_argument("Not a valid IPv4 address: " + addrAsString);
68
0
    }
69
4
  }
70
71
  bool IPv4Address::matchNetwork(const IPv4Network& network) const
72
0
  {
73
0
    return network.includes(*this);
74
0
  }
75
76
  bool IPv4Address::matchNetwork(const std::string& network) const
77
0
  {
78
0
    try
79
0
    {
80
0
      auto ipv4Network = IPv4Network(network);
81
0
      return ipv4Network.includes(*this);
82
0
    }
83
0
    catch (const std::invalid_argument& e)
84
0
    {
85
0
      (void)e;  // Suppress the unreferenced local variable warning when PCPP_LOG_ERROR is disabled
86
0
      PCPP_LOG_ERROR(e.what());
87
0
      return false;
88
0
    }
89
0
  }
90
91
  bool IPv4Address::isValidIPv4Address(const std::string& addrAsString)
92
0
  {
93
0
    sockaddr_in sa_in{};
94
0
    return inet_pton(AF_INET, addrAsString.data(), &(sa_in.sin_addr)) > 0;
95
0
  }
96
97
  // ~~~~~~~~~~~
98
  // IPv6Address
99
  // ~~~~~~~~~~~
100
101
  std::string IPv6Address::toString() const
102
0
  {
103
0
    char addrBuffer[INET6_ADDRSTRLEN];
104
105
0
    if (inet_ntop(AF_INET6, toBytes(), addrBuffer, sizeof(addrBuffer)) != nullptr)
106
0
    {
107
0
      return addrBuffer;
108
0
    }
109
110
0
    return {};
111
0
  }
112
113
  bool IPv6Address::isMulticast() const
114
0
  {
115
0
    return !operator<(MulticastRangeLowerBound);
116
0
  }
117
118
  IPv6Address::IPv6Address(const uint8_t* bytes, size_t size)
119
0
  {
120
0
    if (bytes == nullptr)
121
0
    {
122
0
      throw std::invalid_argument("Buffer pointer is null");
123
0
    }
124
125
0
    if (size < 16)
126
0
    {
127
0
      throw std::out_of_range("Buffer size is smaller than IPv6 address size");
128
0
    }
129
0
    std::memcpy(m_Bytes.data(), bytes, 16 * sizeof(uint8_t));
130
0
  }
131
132
  IPv6Address::IPv6Address(const std::string& addrAsString)
133
2
  {
134
2
    if (inet_pton(AF_INET6, addrAsString.data(), m_Bytes.data()) <= 0)
135
0
    {
136
0
      throw std::invalid_argument("Not a valid IPv6 address: " + addrAsString);
137
0
    }
138
2
  }
139
140
  void IPv6Address::copyTo(uint8_t** arr, size_t& length) const
141
0
  {
142
0
    const size_t addrLen = m_Bytes.size() * sizeof(uint8_t);
143
0
    length = addrLen;
144
    // cppcheck-suppress ctunullpointer
145
0
    *arr = new uint8_t[addrLen];
146
0
    memcpy(*arr, m_Bytes.data(), addrLen);
147
0
  }
148
149
  size_t IPv6Address::copyTo(uint8_t* buffer, size_t size) const
150
0
  {
151
0
    const size_t requiredSize = m_Bytes.size();
152
153
0
    if (buffer == nullptr)
154
0
    {
155
0
      if (size != 0)
156
0
      {
157
0
        throw std::invalid_argument("Buffer is null but size is not zero");
158
0
      }
159
160
0
      return requiredSize;
161
0
    }
162
163
0
    if (size < requiredSize)
164
0
    {
165
0
      return requiredSize;
166
0
    }
167
168
0
    std::memcpy(buffer, m_Bytes.data(), requiredSize);
169
0
    return requiredSize;
170
0
  }
171
172
  bool IPv6Address::copyToNewBuffer(uint8_t** buffer, size_t& size) const
173
0
  {
174
0
    if (buffer == nullptr)
175
0
    {
176
0
      throw std::invalid_argument("Buffer pointer is null");
177
0
    }
178
179
0
    size = copyTo(nullptr, 0);
180
0
    *buffer = new uint8_t[size];
181
0
    if (copyTo(*buffer, size) != size)
182
0
    {
183
0
      delete[] *buffer;
184
0
      *buffer = nullptr;
185
0
      size = 0;
186
0
      return false;
187
0
    }
188
189
0
    return true;
190
0
  }
191
192
  bool IPv6Address::matchNetwork(const IPv6Network& network) const
193
0
  {
194
0
    return network.includes(*this);
195
0
  }
196
197
  bool IPv6Address::matchNetwork(const std::string& network) const
198
0
  {
199
0
    try
200
0
    {
201
0
      auto ipv6Network = IPv6Network(network);
202
0
      return ipv6Network.includes(*this);
203
0
    }
204
0
    catch (const std::invalid_argument& e)
205
0
    {
206
0
      (void)e;  // Suppress the unreferenced local variable warning when PCPP_LOG_ERROR is disabled
207
0
      PCPP_LOG_ERROR(e.what());
208
0
      return false;
209
0
    }
210
0
  }
211
212
  bool IPv6Address::isValidIPv6Address(const std::string& addrAsString)
213
0
  {
214
0
    sockaddr_in6 sa_in6{};
215
0
    return inet_pton(AF_INET6, addrAsString.data(), &(sa_in6.sin6_addr)) > 0;
216
0
  }
217
218
  // ~~~~~~~~~
219
  // IPAddress
220
  // ~~~~~~~~~
221
222
  IPAddress::IPAddress(const std::string& addrAsString)
223
0
  {
224
0
    if (IPv4Address::isValidIPv4Address(addrAsString))
225
0
    {
226
0
      m_Type = IPv4AddressType;
227
0
      m_IPv4 = IPv4Address(addrAsString);
228
0
    }
229
0
    else if (IPv6Address::isValidIPv6Address(addrAsString))
230
0
    {
231
0
      m_Type = IPv6AddressType;
232
0
      m_IPv6 = IPv6Address(addrAsString);
233
0
    }
234
0
    else
235
0
    {
236
0
      throw std::invalid_argument("Not a valid IP address: " + addrAsString);
237
0
    }
238
0
  }
239
240
  // ~~~~~~~~~~~
241
  // IPv4Network
242
  // ~~~~~~~~~~~
243
244
  bool IPv4Network::isValidNetmask(const IPv4Address& maskAddress)
245
0
  {
246
0
    if (maskAddress == IPv4Address::Zero)
247
0
    {
248
0
      return true;
249
0
    }
250
251
0
    const uint32_t maskAsInt = be32toh(maskAddress.toInt());
252
0
    const std::bitset<32> bitset(maskAsInt);
253
0
    auto bitsetCount = bitset.count();
254
255
0
    if (bitsetCount == 32)
256
0
    {
257
0
      return true;
258
0
    }
259
260
0
    return maskAsInt << bitsetCount == 0;
261
0
  }
262
263
  void IPv4Network::initFromAddressAndPrefixLength(const IPv4Address& address, uint8_t prefixLen)
264
0
  {
265
0
    m_Mask = be32toh(0xffff'ffff ^ (prefixLen < 32 ? 0xffff'ffff >> prefixLen : 0));
266
0
    m_NetworkPrefix = address.toInt() & m_Mask;
267
0
  }
268
269
  void IPv4Network::initFromAddressAndNetmask(const IPv4Address& address, const IPv4Address& netmaskAddress)
270
0
  {
271
0
    m_Mask = netmaskAddress.toInt();
272
0
    m_NetworkPrefix = address.toInt() & m_Mask;
273
0
  }
274
275
  IPv4Network::IPv4Network(const IPv4Address& address, uint8_t prefixLen)
276
0
  {
277
0
    if (prefixLen > 32)
278
0
    {
279
0
      throw std::invalid_argument("prefixLen must be an integer between 0 and 32");
280
0
    }
281
282
0
    initFromAddressAndPrefixLength(address, prefixLen);
283
0
  }
284
285
  IPv4Network::IPv4Network(const IPv4Address& address, const std::string& netmask)
286
0
  {
287
0
    IPv4Address netmaskAddr;
288
0
    try
289
0
    {
290
0
      netmaskAddr = IPv4Address(netmask);
291
0
    }
292
0
    catch (const std::exception&)
293
0
    {
294
0
      throw std::invalid_argument("Netmask is not valid IPv4 format: " + netmask);
295
0
    }
296
0
    if (!isValidNetmask(netmaskAddr))
297
0
    {
298
0
      throw std::invalid_argument("Netmask is not valid IPv4 format: " + netmask);
299
0
    }
300
0
    initFromAddressAndNetmask(address, netmaskAddr);
301
0
  }
302
303
  IPv4Network::IPv4Network(const std::string& addressAndNetmask)
304
0
  {
305
0
    std::stringstream stream(addressAndNetmask);
306
0
    std::string networkPrefixStr;
307
0
    std::string netmaskStr;
308
0
    std::getline(stream, networkPrefixStr, '/');
309
0
    std::getline(stream, netmaskStr);
310
311
0
    if (netmaskStr.empty())
312
0
    {
313
0
      throw std::invalid_argument(
314
0
          "The input should be in the format of <address>/<netmask> or <address>/<prefixLength>");
315
0
    }
316
317
0
    IPv4Address networkPrefix;
318
0
    try
319
0
    {
320
0
      networkPrefix = IPv4Address(networkPrefixStr);
321
0
    }
322
0
    catch (const std::invalid_argument&)
323
0
    {
324
0
      throw std::invalid_argument("The input doesn't contain a valid IPv4 network prefix: " + networkPrefixStr);
325
0
    }
326
327
0
    if (std::all_of(netmaskStr.begin(), netmaskStr.end(), ::isdigit))
328
0
    {
329
0
      const uint32_t prefixLen = std::stoi(netmaskStr);
330
0
      if (prefixLen > 32)
331
0
      {
332
0
        throw std::invalid_argument("Prefix length must be an integer between 0 and 32");
333
0
      }
334
335
0
      initFromAddressAndPrefixLength(networkPrefix, prefixLen);
336
0
    }
337
0
    else
338
0
    {
339
0
      IPv4Address netmaskAddr;
340
0
      try
341
0
      {
342
0
        netmaskAddr = IPv4Address(netmaskStr);
343
0
      }
344
0
      catch (const std::invalid_argument&)
345
0
      {
346
0
        throw std::invalid_argument("Netmask is not valid IPv4 format: " + netmaskStr);
347
0
      }
348
0
      if (!isValidNetmask(netmaskAddr))
349
0
      {
350
0
        throw std::invalid_argument("Netmask is not valid IPv4 format: " + netmaskStr);
351
0
      }
352
0
      initFromAddressAndNetmask(networkPrefix, netmaskAddr);
353
0
    }
354
0
  }
355
356
  uint8_t IPv4Network::getPrefixLen() const
357
0
  {
358
0
    const std::bitset<32> bitset(m_Mask);
359
0
    return bitset.count();
360
0
  }
361
362
  IPv4Address IPv4Network::getLowestAddress() const
363
0
  {
364
0
    const std::bitset<32> bitset(m_Mask);
365
0
    return bitset.count() < 32 ? m_NetworkPrefix + htobe32(1) : m_NetworkPrefix;
366
0
  }
367
368
  IPv4Address IPv4Network::getHighestAddress() const
369
0
  {
370
0
    auto tempAddress = static_cast<uint32_t>(m_NetworkPrefix | ~m_Mask);
371
0
    const std::bitset<32> bitset(m_Mask);
372
0
    return bitset.count() < 32 ? tempAddress - htobe32(1) : tempAddress;
373
0
  }
374
375
  uint64_t IPv4Network::getTotalAddressCount() const
376
0
  {
377
0
    const std::bitset<32> bitset(~static_cast<uint64_t>(m_Mask));
378
0
    return 1ULL << bitset.count();
379
0
  }
380
381
  bool IPv4Network::includes(const IPv4Address& address) const
382
0
  {
383
0
    return (address.toInt() & m_Mask) == m_NetworkPrefix;
384
0
  }
385
386
  bool IPv4Network::includes(const IPv4Network& network) const
387
0
  {
388
0
    const uint32_t lowestAddress = network.m_NetworkPrefix;
389
0
    const uint32_t highestAddress = network.m_NetworkPrefix | ~network.m_Mask;
390
0
    return ((lowestAddress & m_Mask) == m_NetworkPrefix && (highestAddress & m_Mask) == m_NetworkPrefix);
391
0
  }
392
393
  std::string IPv4Network::toString() const
394
0
  {
395
0
    std::ostringstream stream;
396
0
    stream << getNetworkPrefix() << "/" << static_cast<int>(getPrefixLen());
397
0
    return stream.str();
398
0
  }
399
400
  // ~~~~~~~~~~~
401
  // IPv6Network
402
  // ~~~~~~~~~~~
403
404
0
#define IPV6_ADDR_SIZE 16
405
406
  bool IPv6Network::isValidNetmask(const IPv6Address& netmask)
407
0
  {
408
0
    if (netmask == IPv6Address::Zero)
409
0
    {
410
0
      return true;
411
0
    }
412
413
0
    const uint8_t* addressAsBytes = netmask.toBytes();
414
0
    int expectingValue = 1;
415
0
    for (auto byteIndex = 0; byteIndex < IPV6_ADDR_SIZE; byteIndex++)
416
0
    {
417
0
      auto curByte = addressAsBytes[byteIndex];
418
0
      if (expectingValue == 1)
419
0
      {
420
0
        if (curByte == 0xff)
421
0
        {
422
0
          continue;
423
0
        }
424
0
        const std::bitset<8> bitset(curByte);
425
0
        if (((curByte << bitset.count()) & 0xff) != 0)
426
0
        {
427
0
          return false;
428
0
        }
429
0
        expectingValue = 0;
430
0
      }
431
0
      else if (expectingValue == 0 && curByte != 0)
432
0
      {
433
0
        return false;
434
0
      }
435
0
    }
436
437
0
    return true;
438
0
  }
439
440
  void IPv6Network::initFromAddressAndPrefixLength(const IPv6Address& address, uint8_t prefixLen)
441
0
  {
442
0
    memset(m_Mask, 0, IPV6_ADDR_SIZE);
443
0
    int remainingPrefixLen = prefixLen;
444
0
    for (auto& byte : m_Mask)
445
0
    {
446
0
      if (remainingPrefixLen >= 8)
447
0
      {
448
0
        byte = 0xff;
449
0
      }
450
0
      else if (remainingPrefixLen > 0)
451
0
      {
452
0
        byte = 0xff << (8 - remainingPrefixLen);
453
0
      }
454
0
      else
455
0
      {
456
0
        break;
457
0
      }
458
459
0
      remainingPrefixLen -= 8;
460
0
    }
461
462
0
    address.copyTo(m_NetworkPrefix);
463
464
0
    for (auto byteIndex = 0; byteIndex < IPV6_ADDR_SIZE; byteIndex++)
465
0
    {
466
0
      m_NetworkPrefix[byteIndex] &= m_Mask[byteIndex];
467
0
    }
468
0
  }
469
470
  void IPv6Network::initFromAddressAndNetmask(const IPv6Address& address, const IPv6Address& netmaskAddr)
471
0
  {
472
0
    netmaskAddr.copyTo(m_Mask);
473
474
0
    address.copyTo(m_NetworkPrefix);
475
476
0
    for (auto byteIndex = 0; byteIndex < IPV6_ADDR_SIZE; byteIndex++)
477
0
    {
478
0
      m_NetworkPrefix[byteIndex] &= m_Mask[byteIndex];
479
0
    }
480
0
  }
481
482
  IPv6Network::IPv6Network(const IPv6Address& address, uint8_t prefixLen)
483
0
  {
484
0
    if (prefixLen > 128)
485
0
    {
486
0
      throw std::invalid_argument("prefixLen must be an integer between 0 and 128");
487
0
    }
488
489
0
    initFromAddressAndPrefixLength(address, prefixLen);
490
0
  }
491
492
  IPv6Network::IPv6Network(const IPv6Address& address, const std::string& netmask)
493
0
  {
494
0
    IPv6Address netmaskAddr;
495
0
    try
496
0
    {
497
0
      netmaskAddr = IPv6Address(netmask);
498
0
    }
499
0
    catch (const std::exception&)
500
0
    {
501
0
      throw std::invalid_argument("Netmask is not valid IPv6 format: " + netmask);
502
0
    }
503
0
    if (!isValidNetmask(netmaskAddr))
504
0
    {
505
0
      throw std::invalid_argument("Netmask is not valid IPv6 format: " + netmask);
506
0
    }
507
0
    initFromAddressAndNetmask(address, netmaskAddr);
508
0
  }
509
510
  IPv6Network::IPv6Network(const std::string& addressAndNetmask)
511
0
  {
512
0
    std::stringstream stream(addressAndNetmask);
513
0
    std::string networkPrefixStr;
514
0
    std::string netmaskStr;
515
0
    std::getline(stream, networkPrefixStr, '/');
516
0
    std::getline(stream, netmaskStr);
517
518
0
    if (netmaskStr.empty())
519
0
    {
520
0
      throw std::invalid_argument(
521
0
          "The input should be in the format of <address>/<netmask> or <address>/<prefixLength>");
522
0
    }
523
524
0
    IPv6Address networkPrefix;
525
0
    try
526
0
    {
527
0
      networkPrefix = IPv6Address(networkPrefixStr);
528
0
    }
529
0
    catch (const std::invalid_argument&)
530
0
    {
531
0
      throw std::invalid_argument("The input doesn't contain a valid IPv6 network prefix: " + networkPrefixStr);
532
0
    }
533
0
    if (std::all_of(netmaskStr.begin(), netmaskStr.end(), ::isdigit))
534
0
    {
535
0
      const uint32_t prefixLen = std::stoi(netmaskStr);
536
0
      if (prefixLen > 128)
537
0
      {
538
0
        throw std::invalid_argument("Prefix length must be an integer between 0 and 128");
539
0
      }
540
541
0
      initFromAddressAndPrefixLength(networkPrefix, prefixLen);
542
0
    }
543
0
    else
544
0
    {
545
0
      IPv6Address netmaskAddr;
546
0
      try
547
0
      {
548
0
        netmaskAddr = IPv6Address(netmaskStr);
549
0
      }
550
0
      catch (const std::exception&)
551
0
      {
552
0
        throw std::invalid_argument("Netmask is not valid IPv6 format: " + netmaskStr);
553
0
      }
554
0
      if (!isValidNetmask(netmaskAddr))
555
0
      {
556
0
        throw std::invalid_argument("Netmask is not valid IPv6 format: " + netmaskStr);
557
0
      }
558
0
      initFromAddressAndNetmask(networkPrefix, netmaskAddr);
559
0
    }
560
0
  }
561
562
  uint8_t IPv6Network::getPrefixLen() const
563
0
  {
564
0
    uint8_t result = 0;
565
0
    for (const auto& byte : m_Mask)
566
0
    {
567
0
      const std::bitset<8> bset(byte);
568
0
      result += static_cast<uint8_t>(bset.count());
569
0
    }
570
0
    return result;
571
0
  }
572
573
  IPv6Address IPv6Network::getLowestAddress() const
574
0
  {
575
0
    if (getPrefixLen() == 128)
576
0
    {
577
0
      return m_NetworkPrefix;
578
0
    }
579
580
0
    uint8_t lowestAddress[IPV6_ADDR_SIZE];
581
0
    memcpy(lowestAddress, m_NetworkPrefix, IPV6_ADDR_SIZE);
582
0
    lowestAddress[IPV6_ADDR_SIZE - 1]++;
583
0
    return lowestAddress;
584
0
  }
585
586
  IPv6Address IPv6Network::getHighestAddress() const
587
0
  {
588
0
    uint8_t result[IPV6_ADDR_SIZE];
589
590
0
    for (auto byteIndex = 0; byteIndex < IPV6_ADDR_SIZE; byteIndex++)
591
0
    {
592
0
      result[byteIndex] = m_NetworkPrefix[byteIndex] | ~m_Mask[byteIndex];
593
0
    }
594
595
0
    return result;
596
0
  }
597
598
  uint64_t IPv6Network::getTotalAddressCount() const
599
0
  {
600
0
    int numOfBitset = 0;
601
0
    for (const auto& byte : m_Mask)
602
0
    {
603
0
      const std::bitset<8> bitset(static_cast<uint8_t>(~byte));
604
0
      numOfBitset += static_cast<int>(bitset.count());
605
0
    }
606
607
0
    if (numOfBitset >= 64)
608
0
    {
609
0
      throw std::out_of_range("Number of addresses exceeds uint64_t");
610
0
    }
611
0
    return 1ULL << numOfBitset;
612
0
  }
613
614
  bool IPv6Network::includes(const IPv6Address& address) const
615
0
  {
616
0
    uint8_t maskedBytes[IPV6_ADDR_SIZE];
617
0
    address.copyTo(maskedBytes);
618
619
0
    for (auto byteIndex = 0; byteIndex < IPV6_ADDR_SIZE; byteIndex++)
620
0
    {
621
0
      maskedBytes[byteIndex] &= m_Mask[byteIndex];
622
0
    }
623
0
    return memcmp(m_NetworkPrefix, maskedBytes, IPV6_ADDR_SIZE) == 0;
624
0
  }
625
626
  bool IPv6Network::includes(const IPv6Network& network) const
627
0
  {
628
0
    return includes(network.getLowestAddress()) && includes(network.getHighestAddress());
629
0
  }
630
631
  std::string IPv6Network::toString() const
632
0
  {
633
0
    std::ostringstream stream;
634
0
    stream << getNetworkPrefix() << "/" << static_cast<int>(getPrefixLen());
635
0
    return stream.str();
636
0
  }
637
638
  void IPNetwork::NetworkVariant::swapTo(IPNetwork::NetworkVariant::Type newType) noexcept
639
0
  {
640
0
    if (m_Type == newType)
641
0
    {
642
0
      return;
643
0
    }
644
645
0
    destroyActiveMem();
646
647
0
    switch (newType)
648
0
    {
649
0
    case Type::IPv4:
650
0
      new (&m_IPv4Net) IPv4Network(IPv4Address::Zero);
651
0
      break;
652
0
    case Type::IPv6:
653
0
      new (&m_IPv6Net) IPv6Network(IPv6Address::Zero);
654
0
      break;
655
0
    }
656
0
    m_Type = newType;
657
0
  }
658
659
  void IPNetwork::NetworkVariant::destroyActiveMem() noexcept
660
0
  {
661
0
    switch (m_Type)
662
0
    {
663
0
    case Type::IPv4:
664
0
      m_IPv4Net.~IPv4Network();
665
0
      break;
666
0
    case Type::IPv6:
667
0
      m_IPv6Net.~IPv6Network();
668
0
      break;
669
0
    }
670
0
  }
671
672
}  // namespace pcpp