mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-07 19:24:13 +00:00
Fix for ZTO-33 (Jira), only assign routes if there is a viable source IP.
This commit is contained in:
parent
317263b31c
commit
90f18f7ee7
@ -453,6 +453,52 @@ struct InetAddress : public sockaddr_storage
|
||||
*/
|
||||
bool isNetwork() const;
|
||||
|
||||
/**
|
||||
* Find the total number of prefix bits that match between this IP and another
|
||||
*
|
||||
* @param b Second IP to compare with
|
||||
* @return Number of matching prefix bits or 0 if none match or IPs are of different families (e.g. v4 and v6)
|
||||
*/
|
||||
inline unsigned int matchingPrefixBits(const InetAddress &b) const
|
||||
{
|
||||
unsigned int c = 0;
|
||||
if (ss_family == b.ss_family) {
|
||||
switch(ss_family) {
|
||||
case AF_INET: {
|
||||
uint32_t ip0 = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
|
||||
uint32_t ip1 = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(&b)->sin_addr.s_addr);
|
||||
while ((ip0 >> 31) == (ip1 >> 31)) {
|
||||
ip0 <<= 1;
|
||||
ip1 <<= 1;
|
||||
if (++c == 32)
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
const uint8_t *ip0 = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
|
||||
const uint8_t *ip1 = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&b)->sin6_addr.s6_addr);
|
||||
for(unsigned int i=0;i<16;++i) {
|
||||
if (ip0[i] == ip1[i]) {
|
||||
c += 8;
|
||||
} else {
|
||||
uint8_t ip0b = ip0[i];
|
||||
uint8_t ip1b = ip1[i];
|
||||
uint8_t bit = 0x80;
|
||||
while (bit != 0) {
|
||||
if ((ip0b & bit) != (ip1b & bit))
|
||||
break;
|
||||
++c;
|
||||
bit >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 14-bit (0-16383) hash of this IP's first 24 or 48 bits (for V4 or V6) for rate limiting code, or 0 if non-IP
|
||||
*/
|
||||
|
@ -94,6 +94,22 @@ public:
|
||||
static const CPUIDRegisters CPUID;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Compute the log2 (most significant bit set) of a 32-bit integer
|
||||
*
|
||||
* @param v Integer to compute
|
||||
* @return log2 or 0 if v is 0
|
||||
*/
|
||||
static inline unsigned int log2(uint32_t v)
|
||||
{
|
||||
uint32_t r = (v > 0xffff) << 4; v >>= r;
|
||||
uint32_t shift = (v > 0xff) << 3; v >>= shift; r |= shift;
|
||||
shift = (v > 0xf) << 2; v >>= shift; r |= shift;
|
||||
shift = (v > 0x3) << 1; v >>= shift; r |= shift;
|
||||
r |= (v >> 1);
|
||||
return (unsigned int)r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a time-invariant binary comparison
|
||||
*
|
||||
|
@ -1949,21 +1949,21 @@ public:
|
||||
const InetAddress *const target = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].target));
|
||||
const InetAddress *const via = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].via));
|
||||
|
||||
// Make sure we are allowed to set this managed route.
|
||||
if ( (!checkIfManagedIsAllowed(n,*target)) || ((via->ss_family == target->ss_family)&&(matchIpOnly(myIps,*via))) )
|
||||
continue;
|
||||
|
||||
// Find an IP on the interface that can be a source IP, abort if no IPs assigned.
|
||||
const InetAddress *src = NULL;
|
||||
for (unsigned int j=0; j<n.config.assignedAddressCount; ++j) {
|
||||
const InetAddress *const tmp = reinterpret_cast<const InetAddress *>(&(n.config.assignedAddresses[j]));
|
||||
if (target->isV4() && tmp->isV4()) {
|
||||
src = reinterpret_cast<InetAddress *>(&(n.config.assignedAddresses[j]));
|
||||
break;
|
||||
} else if (target->isV6() && tmp->isV6()) {
|
||||
src = reinterpret_cast<InetAddress *>(&(n.config.assignedAddresses[j]));
|
||||
break;
|
||||
unsigned int mostMatchingPrefixBits = 0;
|
||||
for(std::vector<InetAddress>::const_iterator i(myIps.begin());i!=myIps.end();++i) {
|
||||
const unsigned int matchingPrefixBits = i->matchingPrefixBits(*target);
|
||||
if (matchingPrefixBits >= mostMatchingPrefixBits) {
|
||||
mostMatchingPrefixBits = matchingPrefixBits;
|
||||
src = &(*i);
|
||||
}
|
||||
}
|
||||
if (!src)
|
||||
src = &NULL_INET_ADDR;
|
||||
|
||||
if ( (!checkIfManagedIsAllowed(n,*target)) || ((via->ss_family == target->ss_family)&&(matchIpOnly(myIps,*via))) )
|
||||
continue;
|
||||
|
||||
// Ignore routes implied by local managed IPs since adding the IP adds the route
|
||||
|
Loading…
x
Reference in New Issue
Block a user