mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 03:53:44 +02: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
3 changed files with 73 additions and 11 deletions
|
@ -453,6 +453,52 @@ struct InetAddress : public sockaddr_storage
|
||||||
*/
|
*/
|
||||||
bool isNetwork() const;
|
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
|
* @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;
|
static const CPUIDRegisters CPUID;
|
||||||
#endif
|
#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
|
* 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 target = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].target));
|
||||||
const InetAddress *const via = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].via));
|
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;
|
const InetAddress *src = NULL;
|
||||||
for (unsigned int j=0; j<n.config.assignedAddressCount; ++j) {
|
unsigned int mostMatchingPrefixBits = 0;
|
||||||
const InetAddress *const tmp = reinterpret_cast<const InetAddress *>(&(n.config.assignedAddresses[j]));
|
for(std::vector<InetAddress>::const_iterator i(myIps.begin());i!=myIps.end();++i) {
|
||||||
if (target->isV4() && tmp->isV4()) {
|
const unsigned int matchingPrefixBits = i->matchingPrefixBits(*target);
|
||||||
src = reinterpret_cast<InetAddress *>(&(n.config.assignedAddresses[j]));
|
if (matchingPrefixBits >= mostMatchingPrefixBits) {
|
||||||
break;
|
mostMatchingPrefixBits = matchingPrefixBits;
|
||||||
} else if (target->isV6() && tmp->isV6()) {
|
src = &(*i);
|
||||||
src = reinterpret_cast<InetAddress *>(&(n.config.assignedAddresses[j]));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!src)
|
if (!src)
|
||||||
src = &NULL_INET_ADDR;
|
|
||||||
|
|
||||||
if ( (!checkIfManagedIsAllowed(n,*target)) || ((via->ss_family == target->ss_family)&&(matchIpOnly(myIps,*via))) )
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Ignore routes implied by local managed IPs since adding the IP adds the route
|
// Ignore routes implied by local managed IPs since adding the IP adds the route
|
||||||
|
|
Loading…
Add table
Reference in a new issue