|
|
|
|
@ -28,70 +28,131 @@
|
|
|
|
|
#ifndef _ZT_ADDRESS_HPP |
|
|
|
|
#define _ZT_ADDRESS_HPP |
|
|
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
#include <stdlib.h> |
|
|
|
|
#include <stdint.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
#include <string> |
|
|
|
|
#include "Utils.hpp" |
|
|
|
|
#include "MAC.hpp" |
|
|
|
|
#include "Constants.hpp" |
|
|
|
|
#include "Buffer.hpp" |
|
|
|
|
|
|
|
|
|
namespace ZeroTier { |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ZeroTier address, which doubles as the last 5 octets of the MAC on taps |
|
|
|
|
* |
|
|
|
|
* Natural sort order will differ on big vs. little endian machines, but that |
|
|
|
|
* won't matter when it's used as a local map/set key. |
|
|
|
|
* A ZeroTier address |
|
|
|
|
*/ |
|
|
|
|
class Address |
|
|
|
|
{ |
|
|
|
|
private: |
|
|
|
|
union { |
|
|
|
|
unsigned char o[ZT_ADDRESS_LENGTH]; |
|
|
|
|
uint64_t v; |
|
|
|
|
} _a; |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
Address() |
|
|
|
|
throw() |
|
|
|
|
throw() : |
|
|
|
|
_a(0) |
|
|
|
|
{ |
|
|
|
|
_a.v = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Address(const Address &a) |
|
|
|
|
throw() : |
|
|
|
|
_a(a._a) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Address(uint64_t a) |
|
|
|
|
throw() : |
|
|
|
|
_a(a & 0xffffffffffULL) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param bits Raw address -- 5 bytes, big-endian byte order |
|
|
|
|
*/ |
|
|
|
|
Address(const void *bits) |
|
|
|
|
throw() |
|
|
|
|
{ |
|
|
|
|
setTo(bits); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline Address &operator=(const Address &a) |
|
|
|
|
throw() |
|
|
|
|
{ |
|
|
|
|
_a.v = a._a.v; |
|
|
|
|
_a = a._a; |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline Address &operator=(const uint64_t a) |
|
|
|
|
throw() |
|
|
|
|
{ |
|
|
|
|
_a = (a & 0xffffffffffULL); |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create from a ZeroTier MAC |
|
|
|
|
* |
|
|
|
|
* @param m MAC (assumed to be a ZeroTier MAC) |
|
|
|
|
* @param bits Raw address -- 5 bytes, big-endian byte order |
|
|
|
|
*/ |
|
|
|
|
Address(const MAC &m) |
|
|
|
|
inline void setTo(const void *bits) |
|
|
|
|
throw() |
|
|
|
|
{ |
|
|
|
|
_a.v = 0; |
|
|
|
|
for(int i=0;i<ZT_ADDRESS_LENGTH;++i) |
|
|
|
|
_a.o[i] = m.data[i + 1]; |
|
|
|
|
const unsigned char *b = (const unsigned char *)bits; |
|
|
|
|
uint64_t a = ((uint64_t)*b++) << 32; |
|
|
|
|
a |= ((uint64_t)*b++) << 24; |
|
|
|
|
a |= ((uint64_t)*b++) << 16; |
|
|
|
|
a |= ((uint64_t)*b++) << 8; |
|
|
|
|
a |= ((uint64_t)*b); |
|
|
|
|
_a = a; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param bits Raw address -- 5 bytes in length |
|
|
|
|
* @param bits Buffer to hold 5-byte address in big-endian byte order |
|
|
|
|
*/ |
|
|
|
|
Address(const void *bits) |
|
|
|
|
inline void copyTo(void *bits) const |
|
|
|
|
throw() |
|
|
|
|
{ |
|
|
|
|
_a.v = 0; |
|
|
|
|
for(int i=0;i<ZT_ADDRESS_LENGTH;++i) |
|
|
|
|
_a.o[i] = ((const unsigned char *)bits)[i]; |
|
|
|
|
unsigned char *b = (unsigned char *)bits; |
|
|
|
|
*(b++) = (unsigned char)((_a >> 32) & 0xff); |
|
|
|
|
*(b++) = (unsigned char)((_a >> 24) & 0xff); |
|
|
|
|
*(b++) = (unsigned char)((_a >> 16) & 0xff); |
|
|
|
|
*(b++) = (unsigned char)((_a >> 8) & 0xff); |
|
|
|
|
*b = (unsigned char)(_a & 0xff); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline Address &operator=(const Address &a) |
|
|
|
|
/**
|
|
|
|
|
* Append to a buffer in big-endian byte order |
|
|
|
|
* |
|
|
|
|
* @param b Buffer to append to |
|
|
|
|
*/ |
|
|
|
|
template<unsigned int C> |
|
|
|
|
inline void appendTo(Buffer<C> &b) const |
|
|
|
|
throw(std::out_of_range) |
|
|
|
|
{ |
|
|
|
|
b.append((unsigned char)((_a >> 32) & 0xff)); |
|
|
|
|
b.append((unsigned char)((_a >> 24) & 0xff)); |
|
|
|
|
b.append((unsigned char)((_a >> 16) & 0xff)); |
|
|
|
|
b.append((unsigned char)((_a >> 8) & 0xff)); |
|
|
|
|
b.append((unsigned char)(_a & 0xff)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return String containing address as 5 binary bytes |
|
|
|
|
*/ |
|
|
|
|
inline std::string toBinaryString() const |
|
|
|
|
{ |
|
|
|
|
std::string b; |
|
|
|
|
b.push_back((char)((_a >> 32) & 0xff)); |
|
|
|
|
b.push_back((char)((_a >> 24) & 0xff)); |
|
|
|
|
b.push_back((char)((_a >> 16) & 0xff)); |
|
|
|
|
b.push_back((char)((_a >> 8) & 0xff)); |
|
|
|
|
b.push_back((char)(_a & 0xff)); |
|
|
|
|
return b; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return Integer containing address (0 to 2^40) |
|
|
|
|
*/ |
|
|
|
|
inline uint64_t toInt() const |
|
|
|
|
throw() |
|
|
|
|
{ |
|
|
|
|
_a.v = a._a.v; |
|
|
|
|
return *this; |
|
|
|
|
return _a; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -103,9 +164,7 @@ public:
|
|
|
|
|
throw() |
|
|
|
|
{ |
|
|
|
|
MAC m; |
|
|
|
|
m.data[0] = ZT_MAC_FIRST_OCTET; |
|
|
|
|
for(int i=1;i<6;++i) |
|
|
|
|
m.data[i] = _a.o[i - 1]; |
|
|
|
|
copyTo(m.data); |
|
|
|
|
return m; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -114,18 +173,15 @@ public:
|
|
|
|
|
*/ |
|
|
|
|
inline std::string toString() const |
|
|
|
|
{ |
|
|
|
|
return Utils::hex(_a.o,ZT_ADDRESS_LENGTH); |
|
|
|
|
char buf[16]; |
|
|
|
|
sprintf(buf,"%.10llx",_a); |
|
|
|
|
return std::string(buf); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set address to zero |
|
|
|
|
*/ |
|
|
|
|
inline void zero() throw() { _a.v = 0; } |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return True if this address is not zero |
|
|
|
|
*/ |
|
|
|
|
inline operator bool() const throw() { return (_a.v); } |
|
|
|
|
inline operator bool() const throw() { return (_a); } |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return Sum of all bytes in address |
|
|
|
|
@ -133,10 +189,7 @@ public:
|
|
|
|
|
inline unsigned int sum() const |
|
|
|
|
throw() |
|
|
|
|
{ |
|
|
|
|
unsigned int s = 0; |
|
|
|
|
for(unsigned int i=0;i<ZT_ADDRESS_LENGTH;++i) |
|
|
|
|
s += _a.o[i]; |
|
|
|
|
return s; |
|
|
|
|
return (unsigned int)(((_a >> 32) & 0xff) + ((_a >> 24) & 0xff) + ((_a >> 16) & 0xff) + ((_a >> 8) & 0xff) + (_a & 0xff)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -151,23 +204,24 @@ public:
|
|
|
|
|
inline bool isReserved() const |
|
|
|
|
throw() |
|
|
|
|
{ |
|
|
|
|
return ((!_a.v)||(_a.o[0] == ZT_ADDRESS_RESERVED_PREFIX)); |
|
|
|
|
return ((!_a)||((_a >> 32) == ZT_ADDRESS_RESERVED_PREFIX)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline unsigned char *data() throw() { return _a.o; } |
|
|
|
|
inline const unsigned char *data() const throw() { return _a.o; } |
|
|
|
|
|
|
|
|
|
inline unsigned int size() const throw() { return ZT_ADDRESS_LENGTH; } |
|
|
|
|
/**
|
|
|
|
|
* @param i Value from 0 to 4 (inclusive) |
|
|
|
|
* @return Byte at said position (address interpreted in big-endian order) |
|
|
|
|
*/ |
|
|
|
|
inline unsigned char operator[](unsigned int i) const throw() { return (unsigned char)((_a >> (32 - (i * 8))) & 0xff); } |
|
|
|
|
|
|
|
|
|
inline unsigned char &operator[](unsigned int i) throw() { return _a.o[i]; } |
|
|
|
|
inline unsigned char operator[](unsigned int i) const throw() { return _a.o[i]; } |
|
|
|
|
inline bool operator==(const Address &a) const throw() { return (_a == a._a); } |
|
|
|
|
inline bool operator!=(const Address &a) const throw() { return (_a != a._a); } |
|
|
|
|
inline bool operator>(const Address &a) const throw() { return (_a > a._a); } |
|
|
|
|
inline bool operator<(const Address &a) const throw() { return (_a < a._a); } |
|
|
|
|
inline bool operator>=(const Address &a) const throw() { return (_a >= a._a); } |
|
|
|
|
inline bool operator<=(const Address &a) const throw() { return (_a <= a._a); } |
|
|
|
|
|
|
|
|
|
inline bool operator==(const Address &a) const throw() { return (_a.v == a._a.v); } |
|
|
|
|
inline bool operator!=(const Address &a) const throw() { return (_a.v != a._a.v); } |
|
|
|
|
inline bool operator<(const Address &a) const throw() { return (_a.v < a._a.v); } |
|
|
|
|
inline bool operator>(const Address &a) const throw() { return (_a.v > a._a.v); } |
|
|
|
|
inline bool operator<=(const Address &a) const throw() { return (_a.v <= a._a.v); } |
|
|
|
|
inline bool operator>=(const Address &a) const throw() { return (_a.v >= a._a.v); } |
|
|
|
|
private: |
|
|
|
|
uint64_t _a; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
} // namespace ZeroTier
|
|
|
|
|
|