@ -23,62 +23,76 @@
namespace ZeroTier {
SharedPtr < NetworkConfig > NetworkConfig : : createTestNetworkConfig ( const Address & self )
namespace {
struct ZT_VirtualNetworkStaticDevice_SortByAddress
{
inline bool operator ( ) ( const ZT_VirtualNetworkStaticDevice & a , const ZT_VirtualNetworkStaticDevice & b )
{
return ( a . address < b . address ) ;
}
} ;
struct ZT_VirtualNetworkRule_SortByRuleNo
{
inline bool operator ( ) ( const ZT_VirtualNetworkRule & a , const ZT_VirtualNetworkRule & b )
{
return ( a . ruleNo < b . ruleNo ) ;
}
} ;
} // anonymous namespace
NetworkConfig NetworkConfig : : createTestNetworkConfig ( const Address & self )
{
SharedPtr < NetworkConfig > nc ( new NetworkConfig ( ) ) ;
memset ( nc - > _etWhitelist , 0 , sizeof ( nc - > _etWhitelist ) ) ;
nc - > _etWhitelist [ 0 ] | = 1 ; // allow all
nc - > _nwid = ZT_TEST_NETWORK_ID ;
nc - > _timestamp = 1 ;
nc - > _revision = 1 ;
nc - > _issuedTo = self ;
nc - > _multicastLimit = ZT_MULTICAST_DEFAULT_LIMIT ;
nc - > _allowPassiveBridging = false ;
nc - > _private = false ;
nc - > _enableBroadcast = true ;
nc - > _name = " ZT_TEST_NETWORK " ;
NetworkConfig nc ;
nc . _nwid = ZT_TEST_NETWORK_ID ;
nc . _timestamp = 1 ;
nc . _revision = 1 ;
nc . _issuedTo = self ;
nc . _multicastLimit = ZT_MULTICAST_DEFAULT_LIMIT ;
nc . _allowPassiveBridging = false ;
nc . _type = ZT_NETWORK_TYPE_PUBLIC ;
nc . _enableBroadcast = true ;
nc . _rules [ nc . _ruleCount ] . ruleNo = 0 ;
nc . _rules [ nc . _ruleCount ] . vlanId = - 1 ;
nc . _rules [ nc . _ruleCount ] . vlanPcp = - 1 ;
nc . _rules [ nc . _ruleCount ] . etherType = - 1 ;
nc . _rules [ nc . _ruleCount ] . ipTos = - 1 ;
nc . _rules [ nc . _ruleCount ] . ipProtocol = - 1 ;
nc . _rules [ nc . _ruleCount ] . ipSourcePort = - 1 ;
nc . _rules [ nc . _ruleCount ] . ipDestPort = - 1 ;
nc . _rules [ nc . _ruleCount ] . action = ZT_NETWORK_RULE_ACTION_ACCEPT ;
+ + nc . _ruleCount ;
Utils : : snprintf ( nc . _name , sizeof ( nc . _name ) , " ZT_TEST_NETWORK " ) ;
// Make up a V4 IP from 'self' in the 10.0.0.0/8 range -- no
// guarantee of uniqueness but collisions are unlikely.
uint32_t ip = ( uint32_t ) ( ( self . toInt ( ) & 0x00ffffff ) | 0x0a000000 ) ; // 10.x.x.x
if ( ( ip & 0x000000ff ) = = 0x000000ff ) ip ^ = 0x00000001 ; // but not ending in .255
if ( ( ip & 0x000000ff ) = = 0x00000000 ) ip ^ = 0x00000001 ; // or .0
nc - > _staticIps . push_back ( InetAddress ( Utils : : hton ( ip ) , 8 ) ) ;
nc . _staticIps [ 0 ] = InetAddress ( Utils : : hton ( ip ) , 8 ) ;
// Assign an RFC4193-compliant IPv6 address -- will never collide
nc - > _staticIps . push_back ( InetAddress : : makeIpv6rfc4193 ( ZT_TEST_NETWORK_ID , self . toInt ( ) ) ) ;
nc . _staticIps [ 1 ] = InetAddress : : makeIpv6rfc4193 ( ZT_TEST_NETWORK_ID , self . toInt ( ) ) ;
nc . _staticIpCount = 2 ;
return nc ;
}
std : : vector < unsigned int > NetworkConfig : : allowedEtherTypes ( ) const
{
std : : vector < unsigned int > ets ;
if ( ( _etWhitelist [ 0 ] & 1 ) ! = 0 ) {
ets . push_back ( 0 ) ;
} else {
for ( unsigned int i = 0 ; i < sizeof ( _etWhitelist ) ; + + i ) {
if ( _etWhitelist [ i ] ) {
unsigned char b = _etWhitelist [ i ] ;
unsigned int et = i * 8 ;
while ( b ) {
if ( ( b & 1 ) )
ets . push_back ( et ) ;
b > > = 1 ;
+ + et ;
}
}
}
}
return ets ;
}
# ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
void NetworkConfig : : _ fromDictionary( const Dictionary & d )
void NetworkConfig : : fromDictionary ( const Dictionary & d )
{
static const std : : string zero ( " 0 " ) ;
static const std : : string one ( " 1 " ) ;
memset ( this , 0 , sizeof ( NetworkConfig ) ) ;
// NOTE: d.get(name) throws if not found, d.get(name,default) returns default
_nwid = Utils : : hexStrToU64 ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID , " 0 " ) . c_str ( ) ) ;
@ -87,26 +101,32 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
_timestamp = Utils : : hexStrToU64 ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP , " 0 " ) . c_str ( ) ) ;
_revision = Utils : : hexStrToU64 ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_REVISION , " 1 " ) . c_str ( ) ) ; // older controllers don't send this, so default to 1
memset ( _etWhitelist , 0 , sizeof ( _etWhitelist ) ) ;
std : : vector < std : : string > ets ( Utils : : split ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES , " " ) . c_str ( ) , " , " , " " , " " ) ) ;
for ( std : : vector < std : : string > : : const_iterator et ( ets . begin ( ) ) ; et ! = ets . end ( ) ; + + et ) {
unsigned int tmp = Utils : : hexStrToUInt ( et - > c_str ( ) ) & 0xffff ;
_etWhitelist [ tmp > > 3 ] | = ( 1 < < ( tmp & 7 ) ) ;
}
_issuedTo = Address ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO , " 0 " ) ) ;
_multicastLimit = Utils : : hexStrToUInt ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT , zero ) . c_str ( ) ) ;
if ( _multicastLimit = = 0 ) _multicastLimit = ZT_MULTICAST_DEFAULT_LIMIT ;
_allowPassiveBridging = ( Utils : : hexStrToUInt ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING , zero ) . c_str ( ) ) ! = 0 ) ;
_private = ( Utils : : hexStrToUInt ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_PRIVATE , one ) . c_str ( ) ) ! = 0 ) ;
_enableBroadcast = ( Utils : : hexStrToUInt ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST , one ) . c_str ( ) ) ! = 0 ) ;
_name = d . get ( ZT_NETWORKCONFIG_DICT_KEY_NAME , " " ) ;
if ( _name . length ( ) > ZT_MAX_NETWORK_SHORT_NAME_LENGTH )
throw std : : invalid_argument ( " network short name too long (max: 255 characters) " ) ;
_type = ( Utils : : hexStrToUInt ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_PRIVATE , one ) . c_str ( ) ) ! = 0 ) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC ;
std : : string nametmp ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_NAME , " " ) ) ;
for ( unsigned long i = 0 ; ( ( i < ZT_MAX_NETWORK_SHORT_NAME_LENGTH ) & & ( i < nametmp . length ( ) ) ) ; + + i )
_name [ i ] = ( char ) nametmp [ i ] ;
// we zeroed the entire structure above and _name is ZT_MAX_NETWORK_SHORT_NAME_LENGTH+1, so it will always null-terminate
std : : vector < std : : string > activeBridgesSplit ( Utils : : split ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES , " " ) . c_str ( ) , " , " , " " , " " ) ) ;
for ( std : : vector < std : : string > : : const_iterator a ( activeBridgesSplit . begin ( ) ) ; a ! = activeBridgesSplit . end ( ) ; + + a ) {
if ( a - > length ( ) = = ZT_ADDRESS_LENGTH_HEX ) { // ignore empty or garbage fields
Address tmp ( * a ) ;
if ( ! tmp . isReserved ( ) ) {
if ( ( _activeBridgeCount < ZT_MAX_NETWORK_ACTIVE_BRIDGES ) & & ( std : : find ( & ( _activeBridges [ 0 ] ) , & ( _activeBridges [ _activeBridgeCount ] ) , tmp ) = = & ( _activeBridges [ _activeBridgeCount ] ) ) )
_activeBridges [ _activeBridgeCount + + ] = tmp ;
}
}
}
std : : sort ( & ( _activeBridges [ 0 ] ) , & ( _activeBridges [ _activeBridgeCount ] ) ) ;
// In dictionary IPs are split into V4 and V6 addresses, but we don't really
// need that so merge them here.
std : : string ipAddrs ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC , std : : string ( ) ) ) ;
{
std : : string v6s ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC , std : : string ( ) ) ) ;
@ -116,7 +136,6 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
ipAddrs . append ( v6s ) ;
}
}
std : : vector < std : : string > ipAddrsSplit ( Utils : : split ( ipAddrs . c_str ( ) , " , " , " " , " " ) ) ;
for ( std : : vector < std : : string > : : const_iterator ipstr ( ipAddrsSplit . begin ( ) ) ; ipstr ! = ipAddrsSplit . end ( ) ; + + ipstr ) {
InetAddress addr ( * ipstr ) ;
@ -132,70 +151,83 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
default : // ignore unrecognized address types or junk/empty fields
continue ;
}
if ( addr . isNetwork ( ) )
_localRoutes . push_back ( addr ) ;
else _staticIps . push_back ( addr ) ;
if ( addr . isNetwork ( ) ) {
if ( ( _localRouteCount < ZT_MAX_NETWORK_LOCAL_ROUTES ) & & ( std : : find ( & ( _localRoutes [ 0 ] ) , & ( _localRoutes [ _localRouteCount ] ) , addr ) = = & ( _localRoutes [ _localRouteCount ] ) ) )
_localRoutes [ _localRouteCount + + ] = addr ;
} else {
if ( ( _staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES ) & & ( std : : find ( & ( _staticIps [ 0 ] ) , & ( _staticIps [ _staticIpCount ] ) , addr ) = = & ( _staticIps [ _staticIpCount ] ) ) )
_staticIps [ _staticIpCount + + ] = addr ;
}
}
if ( _localRoutes . size ( ) > ZT_MAX_ZT_ASSIGNED_ADDRESSES ) throw std : : invalid_argument ( " too many ZT-assigned routes " ) ;
if ( _staticIps . size ( ) > ZT_MAX_ZT_ASSIGNED_ADDRESSES ) throw std : : invalid_argument ( " too many ZT-assigned IP addresses " ) ;
std : : sort ( _localRoutes . begin ( ) , _localRoutes . end ( ) ) ;
_localRoutes . erase ( std : : unique ( _localRoutes . begin ( ) , _localRoutes . end ( ) ) , _localRoutes . end ( ) ) ;
std : : sort ( _staticIps . begin ( ) , _staticIps . end ( ) ) ;
_staticIps . erase ( std : : unique ( _staticIps . begin ( ) , _staticIps . end ( ) ) , _staticIps . end ( ) ) ;
std : : sort ( & ( _localRoutes [ 0 ] ) , & ( _localRoutes [ _localRouteCount ] ) ) ;
std : : sort ( & ( _staticIps [ 0 ] ) , & ( _staticIps [ _staticIpCount ] ) ) ;
std : : vector < std : : string > gatewaysSplit ( Utils : : split ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS , " " ) . c_str ( ) , " , " , " " , " " ) ) ;
for ( std : : vector < std : : string > : : const_iterator gwstr ( gatewaysSplit . begin ( ) ) ; gwstr ! = gatewaysSplit . end ( ) ; + + gwstr ) {
InetAddress gw ( * gwstr ) ;
if ( ( std : : find ( _gateways . begin ( ) , _gateways . end ( ) , gw ) = = _gateways . end ( ) ) & & ( ( gw . ss_family = = AF_INET ) | | ( gw . ss_family = = AF_INET6 ) ) )
_gateways . push_back ( gw ) ;
if ( ( gw ) & & ( _gatewayCount < ZT_MAX_NETWORK_GATEWAYS ) & & ( std : : find ( & ( _gateways [ 0 ] ) , & ( _gateways [ _gatewayCount ] ) , gw ) = = & ( _gateways [ _gatewayCount ] ) ) )
_gateways [ _gatewayCount + + ] = gw ;
}
std : : sort ( & ( _gateways [ 0 ] ) , & ( _gateways [ _gatewayCount ] ) ) ;
std : : vector < std : : string > activeBridgesSplit ( Utils : : split ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES , " " ) . c_str ( ) , " , " , " " , " " ) ) ;
for ( std : : vector < std : : string > : : const_iterator a ( activeBridgesSplit . begin ( ) ) ; a ! = activeBridgesSplit . end ( ) ; + + a ) {
if ( a - > length ( ) = = ZT_ADDRESS_LENGTH_HEX ) { // ignore empty or garbage fields
Address tmp ( * a ) ;
if ( ! tmp . isReserved ( ) )
_activeBridges . push_back ( tmp ) ;
std : : vector < std : : string > relaysSplit ( Utils : : split ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_RELAYS , " " ) . c_str ( ) , " , " , " " , " " ) ) ;
for ( std : : vector < std : : string > : : const_iterator r ( relaysSplit . begin ( ) ) ; r ! = relaysSplit . end ( ) ; + + r ) {
if ( r - > length ( ) > = ZT_ADDRESS_LENGTH_HEX ) {
Address addr ( r - > substr ( 0 , ZT_ADDRESS_LENGTH_HEX ) . c_str ( ) ) ;
InetAddress phys [ 2 ] ;
unsigned int physCount = 0 ;
const std : : size_t semi ( r - > find ( ' ; ' ) ) ;
if ( ( semi > ZT_ADDRESS_LENGTH_HEX ) & & ( semi < ( r - > length ( ) - 2 ) ) ) {
std : : vector < std : : string > phySplit ( Utils : : split ( r - > substr ( semi + 1 ) . c_str ( ) , " , " , " " , " " ) ) ;
for ( std : : vector < std : : string > : : const_iterator p ( phySplit . begin ( ) ) ; ( ( p ! = phySplit . end ( ) ) & & ( physCount < 2 ) ) ; + + p ) {
phys [ physCount ] = InetAddress ( * p ) ;
if ( phys [ physCount ] )
+ + physCount ;
else phys [ physCount ] . zero ( ) ;
}
}
unsigned int p = _staticCount ;
for ( unsigned int i = 0 ; i < _staticCount ; + + i ) {
if ( _static [ p ] . address = = addr . toInt ( ) ) {
p = i ;
break ;
}
}
if ( ( p = = _staticCount ) & & ( _staticCount < ZT_MAX_NETWORK_STATIC_DEVICES ) )
+ + _staticCount ;
if ( p < ZT_MAX_NETWORK_STATIC_DEVICES ) {
_static [ p ] . address = Address ( r - > c_str ( ) ) ;
for ( unsigned int i = 0 ; i < physCount ; + + i )
_static [ p ] . physical [ i ] = phys [ i ] ;
_static [ p ] . flags | = ZT_NETWORK_STATIC_DEVICE_IS_RELAY ;
}
}
}
std : : sort ( _activeBridges . begin ( ) , _activeBridges . end ( ) ) ;
_activeBridges . erase ( std : : unique ( _activeBridges . begin ( ) , _activeBridges . end ( ) ) , _activeBridges . end ( ) ) ;
std : : sort ( & ( _static [ 0 ] ) , & ( _static [ _staticCount ] ) , ZT_VirtualNetworkStaticDevice_SortByAddress ( ) ) ;
std : : vector < std : : string > relaysSplit ( Utils : : split ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_RELAYS , " " ) . c_str ( ) , " , " , " " , " " ) ) ;
for ( std : : vector < std : : string > : : const_iterator r ( relaysSplit . begin ( ) ) ; r ! = relaysSplit . end ( ) ; + + r ) {
std : : size_t semi ( r - > find ( ' ; ' ) ) ; // address;ip/port,...
if ( semi = = ZT_ADDRESS_LENGTH_HEX ) {
std : : pair < Address , InetAddress > relay (
Address ( r - > substr ( 0 , semi ) ) ,
( ( r - > length ( ) > ( semi + 1 ) ) ? InetAddress ( r - > substr ( semi + 1 ) ) : InetAddress ( ) ) ) ;
if ( ( relay . first ) & & ( ! relay . first . isReserved ( ) ) )
_relays . push_back ( relay ) ;
std : : vector < std : : string > ets ( Utils : : split ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES , " " ) . c_str ( ) , " , " , " " , " " ) ) ;
int rno = 0 ;
for ( std : : vector < std : : string > : : const_iterator et ( ets . begin ( ) ) ; et ! = ets . end ( ) ; + + et ) {
unsigned int et2 = Utils : : hexStrToUInt ( et - > c_str ( ) ) & 0xffff ;
if ( _ruleCount < ZT_MAX_NETWORK_RULES ) {
memset ( & ( _rules [ _ruleCount ] ) , 0 , sizeof ( ZT_VirtualNetworkRule ) ) ;
_rules [ _ruleCount ] . ruleNo = rno ; rno + = 10 ;
_rules [ _ruleCount ] . vlanId = - 1 ;
_rules [ _ruleCount ] . vlanPcp = - 1 ;
_rules [ _ruleCount ] . etherType = ( et2 = = 0 ) ? - 1 : ( int ) et2 ;
_rules [ _ruleCount ] . ipTos = - 1 ;
_rules [ _ruleCount ] . ipProtocol = - 1 ;
_rules [ _ruleCount ] . ipSourcePort = - 1 ;
_rules [ _ruleCount ] . ipDestPort = - 1 ;
_rules [ _ruleCount ] . action = ZT_NETWORK_RULE_ACTION_ACCEPT ;
+ + _ruleCount ;
}
}
std : : sort ( _relays . begin ( ) , _relays . end ( ) ) ;
_relays . erase ( std : : unique ( _relays . begin ( ) , _relays . end ( ) ) , _relays . end ( ) ) ;
_com . fromString ( d . get ( ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP , std : : string ( ) ) ) ;
}
bool NetworkConfig : : operator = = ( const NetworkConfig & nc ) const
{
if ( _nwid ! = nc . _nwid ) return false ;
if ( _timestamp ! = nc . _timestamp ) return false ;
if ( memcmp ( _etWhitelist , nc . _etWhitelist , sizeof ( _etWhitelist ) ) ) return false ;
if ( _issuedTo ! = nc . _issuedTo ) return false ;
if ( _multicastLimit ! = nc . _multicastLimit ) return false ;
if ( _allowPassiveBridging ! = nc . _allowPassiveBridging ) return false ;
if ( _private ! = nc . _private ) return false ;
if ( _enableBroadcast ! = nc . _enableBroadcast ) return false ;
if ( _name ! = nc . _name ) return false ;
if ( _localRoutes ! = nc . _localRoutes ) return false ;
if ( _staticIps ! = nc . _staticIps ) return false ;
if ( _gateways ! = nc . _gateways ) return false ;
if ( _activeBridges ! = nc . _activeBridges ) return false ;
if ( _relays ! = nc . _relays ) return false ;
if ( _com ! = nc . _com ) return false ;
return true ;
}
# endif // ZT_SUPPORT_OLD_STYLE_NETCONF
} // namespace ZeroTier