@@ -789,9 +789,41 @@ CSubNet::CSubNet(const CNetAddr &addr, int32_t mask)
789
789
network.ip [x] &= netmask[x];
790
790
}
791
791
792
+ /* *
793
+ * @returns The number of 1-bits in the prefix of the specified subnet mask. If
794
+ * the specified subnet mask is not a valid one, -1.
795
+ */
796
+ static inline int NetmaskBits (uint8_t x)
797
+ {
798
+ switch (x) {
799
+ case 0x00 : return 0 ;
800
+ case 0x80 : return 1 ;
801
+ case 0xc0 : return 2 ;
802
+ case 0xe0 : return 3 ;
803
+ case 0xf0 : return 4 ;
804
+ case 0xf8 : return 5 ;
805
+ case 0xfc : return 6 ;
806
+ case 0xfe : return 7 ;
807
+ case 0xff : return 8 ;
808
+ default : return -1 ;
809
+ }
810
+ }
811
+
792
812
CSubNet::CSubNet (const CNetAddr &addr, const CNetAddr &mask)
793
813
{
794
814
valid = true ;
815
+ // Check if `mask` contains 1-bits after 0-bits (which is an invalid netmask).
816
+ bool zeros_found = false ;
817
+ for (size_t i = mask.IsIPv4 () ? 12 : 0 ; i < sizeof (mask.ip ); ++i) {
818
+ const int num_bits = NetmaskBits (mask.ip [i]);
819
+ if (num_bits == -1 || (zeros_found && num_bits != 0 )) {
820
+ valid = false ;
821
+ return ;
822
+ }
823
+ if (num_bits < 8 ) {
824
+ zeros_found = true ;
825
+ }
826
+ }
795
827
network = addr;
796
828
// Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
797
829
memset (netmask, 255 , sizeof (netmask));
@@ -828,62 +860,18 @@ bool CSubNet::Match(const CNetAddr &addr) const
828
860
return true ;
829
861
}
830
862
831
- /* *
832
- * @returns The number of 1-bits in the prefix of the specified subnet mask. If
833
- * the specified subnet mask is not a valid one, -1.
834
- */
835
- static inline int NetmaskBits (uint8_t x)
836
- {
837
- switch (x) {
838
- case 0x00 : return 0 ;
839
- case 0x80 : return 1 ;
840
- case 0xc0 : return 2 ;
841
- case 0xe0 : return 3 ;
842
- case 0xf0 : return 4 ;
843
- case 0xf8 : return 5 ;
844
- case 0xfc : return 6 ;
845
- case 0xfe : return 7 ;
846
- case 0xff : return 8 ;
847
- default : return -1 ;
848
- }
849
- }
850
-
851
863
std::string CSubNet::ToString () const
852
864
{
853
- /* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */
854
- int cidr = 0 ;
855
- bool valid_cidr = true ;
856
- int n = network.IsIPv4 () ? 12 : 0 ;
857
- for (; n < 16 && netmask[n] == 0xff ; ++n)
858
- cidr += 8 ;
859
- if (n < 16 ) {
860
- int bits = NetmaskBits (netmask[n]);
861
- if (bits < 0 )
862
- valid_cidr = false ;
863
- else
864
- cidr += bits;
865
- ++n;
866
- }
867
- for (; n < 16 && valid_cidr; ++n)
868
- if (netmask[n] != 0x00 )
869
- valid_cidr = false ;
870
-
871
- /* Format output */
872
- std::string strNetmask;
873
- if (valid_cidr) {
874
- strNetmask = strprintf (" %u" , cidr);
875
- } else {
876
- if (network.IsIPv4 ())
877
- strNetmask = strprintf (" %u.%u.%u.%u" , netmask[12 ], netmask[13 ], netmask[14 ], netmask[15 ]);
878
- else
879
- strNetmask = strprintf (" %x:%x:%x:%x:%x:%x:%x:%x" ,
880
- netmask[0 ] << 8 | netmask[1 ], netmask[2 ] << 8 | netmask[3 ],
881
- netmask[4 ] << 8 | netmask[5 ], netmask[6 ] << 8 | netmask[7 ],
882
- netmask[8 ] << 8 | netmask[9 ], netmask[10 ] << 8 | netmask[11 ],
883
- netmask[12 ] << 8 | netmask[13 ], netmask[14 ] << 8 | netmask[15 ]);
865
+ uint8_t cidr = 0 ;
866
+
867
+ for (size_t i = network.IsIPv4 () ? 12 : 0 ; i < sizeof (netmask); ++i) {
868
+ if (netmask[i] == 0x00 ) {
869
+ break ;
870
+ }
871
+ cidr += NetmaskBits (netmask[i]);
884
872
}
885
873
886
- return network.ToString () + " / " + strNetmask ;
874
+ return network.ToString () + strprintf ( " /%u " , cidr) ;
887
875
}
888
876
889
877
bool CSubNet::IsValid () const
0 commit comments