@@ -546,6 +546,22 @@ void CNetAddr::SetIP(const CNetAddr& ipIn)
546
546
memcpy (ip, ipIn.ip , sizeof (ip));
547
547
}
548
548
549
+ void CNetAddr::SetRaw (Network network, const uint8_t *ip_in)
550
+ {
551
+ switch (network)
552
+ {
553
+ case NET_IPV4:
554
+ memcpy (ip, pchIPv4, 12 );
555
+ memcpy (ip+12 , ip_in, 4 );
556
+ break ;
557
+ case NET_IPV6:
558
+ memcpy (ip, ip_in, 16 );
559
+ break ;
560
+ default :
561
+ assert (!" invalid network" );
562
+ }
563
+ }
564
+
549
565
static const unsigned char pchOnionCat[] = {0xFD ,0x87 ,0xD8 ,0x7E ,0xEB ,0x43 };
550
566
551
567
bool CNetAddr::SetSpecial (const std::string &strName)
@@ -569,13 +585,12 @@ CNetAddr::CNetAddr()
569
585
570
586
CNetAddr::CNetAddr (const struct in_addr & ipv4Addr)
571
587
{
572
- memcpy (ip, pchIPv4, 12 );
573
- memcpy (ip+12 , &ipv4Addr, 4 );
588
+ SetRaw (NET_IPV4, (const uint8_t *)&ipv4Addr);
574
589
}
575
590
576
591
CNetAddr::CNetAddr (const struct in6_addr & ipv6Addr)
577
592
{
578
- memcpy (ip, &ipv6Addr, 16 );
593
+ SetRaw (NET_IPV6, ( const uint8_t *) &ipv6Addr);
579
594
}
580
595
581
596
CNetAddr::CNetAddr (const char *pszIp, bool fAllowLookup )
@@ -1120,3 +1135,105 @@ void CService::SetPort(unsigned short portIn)
1120
1135
{
1121
1136
port = portIn;
1122
1137
}
1138
+
1139
+ CSubNet::CSubNet ():
1140
+ valid(false )
1141
+ {
1142
+ memset (netmask, 0 , sizeof (netmask));
1143
+ }
1144
+
1145
+ CSubNet::CSubNet (const std::string &strSubnet, bool fAllowLookup )
1146
+ {
1147
+ size_t slash = strSubnet.find_last_of (' /' );
1148
+ std::vector<CNetAddr> vIP;
1149
+
1150
+ valid = true ;
1151
+ // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
1152
+ memset (netmask, 255 , sizeof (netmask));
1153
+
1154
+ std::string strAddress = strSubnet.substr (0 , slash);
1155
+ if (LookupHost (strAddress.c_str (), vIP, 1 , fAllowLookup ))
1156
+ {
1157
+ network = vIP[0 ];
1158
+ if (slash != strSubnet.npos )
1159
+ {
1160
+ std::string strNetmask = strSubnet.substr (slash + 1 );
1161
+ int32_t n;
1162
+ // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
1163
+ int noffset = network.IsIPv4 () ? (12 * 8 ) : 0 ;
1164
+ if (ParseInt32 (strNetmask, &n)) // If valid number, assume /24 symtex
1165
+ {
1166
+ if (n >= 0 && n <= (128 - noffset)) // Only valid if in range of bits of address
1167
+ {
1168
+ n += noffset;
1169
+ // Clear bits [n..127]
1170
+ for (; n < 128 ; ++n)
1171
+ netmask[n>>3 ] &= ~(1 <<(n&7 ));
1172
+ }
1173
+ else
1174
+ {
1175
+ valid = false ;
1176
+ }
1177
+ }
1178
+ else // If not a valid number, try full netmask syntax
1179
+ {
1180
+ if (LookupHost (strNetmask.c_str (), vIP, 1 , false )) // Never allow lookup for netmask
1181
+ {
1182
+ // Remember: GetByte returns bytes in reversed order
1183
+ // Copy only the *last* four bytes in case of IPv4, the rest of the mask should stay 1's as
1184
+ // we don't want pchIPv4 to be part of the mask.
1185
+ int asize = network.IsIPv4 () ? 4 : 16 ;
1186
+ for (int x=0 ; x<asize; ++x)
1187
+ netmask[15 -x] = vIP[0 ].GetByte (x);
1188
+ }
1189
+ else
1190
+ {
1191
+ valid = false ;
1192
+ }
1193
+ }
1194
+ }
1195
+ }
1196
+ else
1197
+ {
1198
+ valid = false ;
1199
+ }
1200
+ }
1201
+
1202
+ bool CSubNet::Match (const CNetAddr &addr) const
1203
+ {
1204
+ if (!valid || !addr.IsValid ())
1205
+ return false ;
1206
+ for (int x=0 ; x<16 ; ++x)
1207
+ if ((addr.GetByte (x) & netmask[15 -x]) != network.GetByte (x))
1208
+ return false ;
1209
+ return true ;
1210
+ }
1211
+
1212
+ std::string CSubNet::ToString () const
1213
+ {
1214
+ std::string strNetmask;
1215
+ if (network.IsIPv4 ())
1216
+ strNetmask = strprintf (" %u.%u.%u.%u" , netmask[12 ], netmask[13 ], netmask[14 ], netmask[15 ]);
1217
+ else
1218
+ strNetmask = strprintf (" %x:%x:%x:%x:%x:%x:%x:%x" ,
1219
+ netmask[0 ] << 8 | netmask[1 ], netmask[2 ] << 8 | netmask[3 ],
1220
+ netmask[4 ] << 8 | netmask[5 ], netmask[6 ] << 8 | netmask[7 ],
1221
+ netmask[8 ] << 8 | netmask[9 ], netmask[10 ] << 8 | netmask[11 ],
1222
+ netmask[12 ] << 8 | netmask[13 ], netmask[14 ] << 8 | netmask[15 ]);
1223
+ return network.ToString () + " /" + strNetmask;
1224
+ }
1225
+
1226
+ bool CSubNet::IsValid () const
1227
+ {
1228
+ return valid;
1229
+ }
1230
+
1231
+ bool operator ==(const CSubNet& a, const CSubNet& b)
1232
+ {
1233
+ return a.valid == b.valid && a.network == b.network && !memcmp (a.netmask , b.netmask , 16 );
1234
+ }
1235
+
1236
+ bool operator !=(const CSubNet& a, const CSubNet& b)
1237
+ {
1238
+ return !(a==b);
1239
+ }
0 commit comments