@@ -401,6 +401,39 @@ bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
401
401
return true ;
402
402
}
403
403
404
+ uint32_t CNetAddr::GetNetClass () const {
405
+ uint32_t net_class = NET_IPV6;
406
+ if (IsLocal ()) {
407
+ net_class = 255 ;
408
+ }
409
+ if (IsInternal ()) {
410
+ net_class = NET_INTERNAL;
411
+ } else if (!IsRoutable ()) {
412
+ net_class = NET_UNROUTABLE;
413
+ } else if (IsIPv4 () || IsRFC6145 () || IsRFC6052 () || IsRFC3964 () || IsRFC4380 ()) {
414
+ net_class = NET_IPV4;
415
+ } else if (IsTor ()) {
416
+ net_class = NET_ONION;
417
+ }
418
+ return net_class;
419
+ }
420
+
421
+ uint32_t CNetAddr::GetMappedAS (const std::vector<bool > &asmap) const {
422
+ uint32_t net_class = GetNetClass ();
423
+ if (asmap.size () == 0 || (net_class != NET_IPV4 && net_class != NET_IPV6)) {
424
+ return 0 ; // Indicates not found, safe because AS0 is reserved per RFC7607.
425
+ }
426
+ std::vector<bool > ip_bits (128 );
427
+ for (int8_t byte_i = 0 ; byte_i < 16 ; ++byte_i) {
428
+ uint8_t cur_byte = GetByte (15 - byte_i);
429
+ for (uint8_t bit_i = 0 ; bit_i < 8 ; ++bit_i) {
430
+ ip_bits[byte_i * 8 + bit_i] = (cur_byte >> (7 - bit_i)) & 1 ;
431
+ }
432
+ }
433
+ uint32_t mapped_as = Interpret (asmap, ip_bits);
434
+ return mapped_as;
435
+ }
436
+
404
437
/* *
405
438
* Get the canonical identifier of our network group
406
439
*
@@ -414,53 +447,58 @@ bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
414
447
std::vector<unsigned char > CNetAddr::GetGroup (const std::vector<bool > &asmap) const
415
448
{
416
449
std::vector<unsigned char > vchRet;
417
- int nClass = NET_IPV6;
450
+ uint32_t net_class = GetNetClass ();
451
+ // If non-empty asmap is supplied and the address is IPv4/IPv6,
452
+ // return ASN to be used for bucketing.
453
+ uint32_t asn = GetMappedAS (asmap);
454
+ if (asn != 0 ) { // Either asmap was empty, or address has non-asmappable net class (e.g. TOR).
455
+ vchRet.push_back (NET_IPV6); // IPv4 and IPv6 with same ASN should be in the same bucket
456
+ for (int i = 0 ; i < 4 ; i++) {
457
+ vchRet.push_back ((asn >> (8 * i)) & 0xFF );
458
+ }
459
+ return vchRet;
460
+ }
461
+
462
+ vchRet.push_back (net_class);
418
463
int nStartByte = 0 ;
419
464
int nBits = 16 ;
420
465
421
466
// all local addresses belong to the same group
422
467
if (IsLocal ())
423
468
{
424
- nClass = 255 ;
425
469
nBits = 0 ;
426
470
}
427
471
// all internal-usage addresses get their own group
428
472
if (IsInternal ())
429
473
{
430
- nClass = NET_INTERNAL;
431
474
nStartByte = sizeof (g_internal_prefix);
432
475
nBits = (sizeof (ip) - sizeof (g_internal_prefix)) * 8 ;
433
476
}
434
477
// all other unroutable addresses belong to the same group
435
478
else if (!IsRoutable ())
436
479
{
437
- nClass = NET_UNROUTABLE;
438
480
nBits = 0 ;
439
481
}
440
482
// for IPv4 addresses, '1' + the 16 higher-order bits of the IP
441
483
// includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
442
484
else if (IsIPv4 () || IsRFC6145 () || IsRFC6052 ())
443
485
{
444
- nClass = NET_IPV4;
445
486
nStartByte = 12 ;
446
487
}
447
488
// for 6to4 tunnelled addresses, use the encapsulated IPv4 address
448
489
else if (IsRFC3964 ())
449
490
{
450
- nClass = NET_IPV4;
451
491
nStartByte = 2 ;
452
492
}
453
493
// for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address
454
494
else if (IsRFC4380 ())
455
495
{
456
- vchRet.push_back (NET_IPV4);
457
496
vchRet.push_back (GetByte (3 ) ^ 0xFF );
458
497
vchRet.push_back (GetByte (2 ) ^ 0xFF );
459
498
return vchRet;
460
499
}
461
500
else if (IsTor ())
462
501
{
463
- nClass = NET_ONION;
464
502
nStartByte = 6 ;
465
503
nBits = 4 ;
466
504
}
@@ -471,29 +509,6 @@ std::vector<unsigned char> CNetAddr::GetGroup(const std::vector<bool> &asmap) co
471
509
else
472
510
nBits = 32 ;
473
511
474
- // If asmap is supplied and the address is IPv4/IPv6,
475
- // ignore nBits and use 32/128 bits to obtain ASN from asmap.
476
- // ASN is then returned to be used for bucketing.
477
- if (asmap.size () != 0 && (nClass == NET_IPV4 || nClass == NET_IPV6)) {
478
- nClass = NET_IPV6;
479
- std::vector<bool > ip_bits (128 );
480
- for (int8_t byte_i = 0 ; byte_i < 16 ; ++byte_i) {
481
- uint8_t cur_byte = GetByte (15 - byte_i);
482
- for (uint8_t bit_i = 0 ; bit_i < 8 ; ++bit_i) {
483
- ip_bits[byte_i * 8 + bit_i] = (cur_byte >> (7 - bit_i)) & 1 ;
484
- }
485
- }
486
-
487
- uint32_t asn = Interpret (asmap, ip_bits);
488
- vchRet.push_back (nClass);
489
- for (int i = 0 ; i < 4 ; i++) {
490
- vchRet.push_back ((asn >> (8 * i)) & 0xFF );
491
- }
492
- return vchRet;
493
- }
494
-
495
- vchRet.push_back (nClass);
496
-
497
512
// push our ip onto vchRet byte by byte...
498
513
while (nBits >= 8 )
499
514
{
0 commit comments