2013-07-04 20:56:19 +00:00
/*
2015-02-17 21:11:34 +00:00
* ZeroTier One - Network Virtualization Everywhere
* Copyright ( C ) 2011 - 2015 ZeroTier , Inc .
2013-07-04 20:56:19 +00:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*
* - -
*
* ZeroTier may be used and distributed under the terms of the GPLv3 , which
* are available at : http : //www.gnu.org/licenses/gpl-3.0.html
*
* If you would like to embed ZeroTier into a commercial application or
* redistribute it in a modified binary form , please contact ZeroTier Networks
* LLC . Start here : http : //www.zerotier.com/
*/
2013-08-06 04:05:39 +00:00
# include <stdio.h>
# include <string.h>
2013-07-29 17:56:20 +00:00
# include <stdlib.h>
# include <math.h>
2014-04-07 22:39:33 +00:00
# include "Constants.hpp"
2013-10-18 16:01:48 +00:00
# include "Network.hpp"
2013-07-29 17:56:20 +00:00
# include "RuntimeEnvironment.hpp"
2013-07-04 20:56:19 +00:00
# include "Switch.hpp"
2013-07-30 15:14:53 +00:00
# include "Packet.hpp"
2013-10-16 21:47:26 +00:00
# include "Buffer.hpp"
2015-04-15 22:12:09 +00:00
# include "NetworkController.hpp"
2013-07-04 20:56:19 +00:00
namespace ZeroTier {
2015-04-06 22:47:57 +00:00
const ZeroTier : : MulticastGroup Network : : BROADCAST ( ZeroTier : : MAC ( 0xffffffffffffULL ) , 0 ) ;
2014-05-23 22:13:34 +00:00
2015-04-02 02:09:18 +00:00
Network : : Network ( const RuntimeEnvironment * renv , uint64_t nwid ) :
RR ( renv ) ,
_id ( nwid ) ,
_mac ( renv - > identity . address ( ) , nwid ) ,
_enabled ( true ) ,
2015-04-15 20:09:20 +00:00
_portInitialized ( false ) ,
2015-04-02 02:09:18 +00:00
_lastConfigUpdate ( 0 ) ,
_destroyed ( false ) ,
2015-04-06 23:52:52 +00:00
_netconfFailure ( NETCONF_FAILURE_NONE ) ,
_portError ( 0 )
2013-08-08 14:41:17 +00:00
{
2015-04-02 02:09:18 +00:00
char confn [ 128 ] , mcdbn [ 128 ] ;
Utils : : snprintf ( confn , sizeof ( confn ) , " networks.d/%.16llx.conf " , _id ) ;
Utils : : snprintf ( mcdbn , sizeof ( mcdbn ) , " networks.d/%.16llx.mcerts " , _id ) ;
if ( _id = = ZT_TEST_NETWORK_ID ) {
applyConfiguration ( NetworkConfig : : createTestNetworkConfig ( RR - > identity . address ( ) ) ) ;
// Save a one-byte CR to persist membership in the test network
RR - > node - > dataStorePut ( confn , " \n " , 1 , false ) ;
} else {
bool gotConf = false ;
try {
std : : string conf ( RR - > node - > dataStoreGet ( confn ) ) ;
if ( conf . length ( ) ) {
setConfiguration ( Dictionary ( conf ) , false ) ;
2015-04-14 22:32:05 +00:00
_lastConfigUpdate = 0 ; // we still want to re-request a new config from the network
2015-04-02 02:09:18 +00:00
gotConf = true ;
}
} catch ( . . . ) { } // ignore invalids, we'll re-request
if ( ! gotConf ) {
// Save a one-byte CR to persist membership while we request a real netconf
RR - > node - > dataStorePut ( confn , " \n " , 1 , false ) ;
}
try {
std : : string mcdb ( RR - > node - > dataStoreGet ( mcdbn ) ) ;
if ( mcdb . length ( ) > 6 ) {
const char * p = mcdb . data ( ) ;
const char * e = p + mcdb . length ( ) ;
if ( ! memcmp ( " ZTMCD0 " , p , 6 ) ) {
p + = 6 ;
while ( p ! = e ) {
CertificateOfMembership com ;
com . deserialize2 ( p , e ) ;
if ( ! com )
break ;
_membershipCertificates . insert ( std : : pair < Address , CertificateOfMembership > ( com . issuedTo ( ) , com ) ) ;
}
}
}
} catch ( . . . ) { } // ignore invalid MCDB, we'll re-learn from peers
2013-08-08 14:41:17 +00:00
}
2015-04-02 02:09:18 +00:00
2015-04-15 20:09:20 +00:00
if ( ! _portInitialized ) {
ZT1_VirtualNetworkConfig ctmp ;
_externalConfig ( & ctmp ) ;
_portError = RR - > node - > configureVirtualNetworkPort ( _id , ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_UP , & ctmp ) ;
_portInitialized = true ;
}
2013-08-08 14:41:17 +00:00
}
2013-08-06 05:28:56 +00:00
Network : : ~ Network ( )
{
2015-04-07 01:27:24 +00:00
ZT1_VirtualNetworkConfig ctmp ;
_externalConfig ( & ctmp ) ;
2015-04-06 23:52:52 +00:00
2015-04-02 02:15:21 +00:00
char n [ 128 ] ;
2014-08-22 00:49:05 +00:00
if ( _destroyed ) {
2015-04-07 01:27:24 +00:00
RR - > node - > configureVirtualNetworkPort ( _id , ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY , & ctmp ) ;
2015-04-02 02:09:18 +00:00
Utils : : snprintf ( n , sizeof ( n ) , " networks.d/%.16llx.conf " , _id ) ;
RR - > node - > dataStoreDelete ( n ) ;
Utils : : snprintf ( n , sizeof ( n ) , " networks.d/%.16llx.mcerts " , _id ) ;
RR - > node - > dataStoreDelete ( n ) ;
2013-08-06 05:28:56 +00:00
} else {
2015-04-07 01:27:24 +00:00
RR - > node - > configureVirtualNetworkPort ( _id , ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN , & ctmp ) ;
2013-08-06 05:28:56 +00:00
clean ( ) ;
2015-04-02 02:15:21 +00:00
std : : string buf ( " ZTMCD0 " ) ;
Utils : : snprintf ( n , sizeof ( n ) , " networks.d/%.16llx.mcerts " , _id ) ;
Mutex : : Lock _l ( _lock ) ;
2015-04-06 22:47:57 +00:00
if ( ( ! _config ) | | ( _config - > isPublic ( ) ) | | ( _membershipCertificates . size ( ) = = 0 ) ) {
2015-04-02 02:15:21 +00:00
RR - > node - > dataStoreDelete ( n ) ;
return ;
}
for ( std : : map < Address , CertificateOfMembership > : : iterator c ( _membershipCertificates . begin ( ) ) ; c ! = _membershipCertificates . end ( ) ; + + c )
c - > second . serialize2 ( buf ) ;
RR - > node - > dataStorePut ( n , buf , true ) ;
2013-08-06 05:28:56 +00:00
}
}
2015-04-07 02:41:55 +00:00
std : : vector < MulticastGroup > Network : : allMulticastGroups ( ) const
{
Mutex : : Lock _l ( _lock ) ;
std : : vector < MulticastGroup > mgs ( _myMulticastGroups ) ;
std : : vector < MulticastGroup > : : iterator oldend ( mgs . end ( ) ) ;
for ( std : : map < MulticastGroup , uint64_t > : : const_iterator i ( _multicastGroupsBehindMe . begin ( ) ) ; i ! = _multicastGroupsBehindMe . end ( ) ; + + i ) {
if ( ! std : : binary_search ( mgs . begin ( ) , oldend , i - > first ) )
mgs . push_back ( i - > first ) ;
}
2015-04-15 20:09:20 +00:00
if ( ( _config ) & & ( _config - > enableBroadcast ( ) ) )
mgs . push_back ( Network : : BROADCAST ) ;
2015-04-07 02:41:55 +00:00
std : : sort ( mgs . begin ( ) , mgs . end ( ) ) ;
return mgs ;
}
bool Network : : subscribedToMulticastGroup ( const MulticastGroup & mg , bool includeBridgedGroups ) const
{
Mutex : : Lock _l ( _lock ) ;
if ( std : : binary_search ( _myMulticastGroups . begin ( ) , _myMulticastGroups . end ( ) , mg ) )
return true ;
else if ( includeBridgedGroups )
return ( _multicastGroupsBehindMe . find ( mg ) ! = _multicastGroupsBehindMe . end ( ) ) ;
else return false ;
}
2015-04-07 01:27:24 +00:00
void Network : : multicastSubscribe ( const MulticastGroup & mg )
2014-06-13 21:06:34 +00:00
{
2015-04-15 20:09:20 +00:00
{
Mutex : : Lock _l ( _lock ) ;
if ( std : : binary_search ( _myMulticastGroups . begin ( ) , _myMulticastGroups . end ( ) , mg ) )
return ;
_myMulticastGroups . push_back ( mg ) ;
std : : sort ( _myMulticastGroups . begin ( ) , _myMulticastGroups . end ( ) ) ;
}
2015-04-08 02:35:16 +00:00
_announceMulticastGroups ( ) ;
2015-04-07 01:27:24 +00:00
}
2014-10-04 01:27:42 +00:00
2015-04-07 01:27:24 +00:00
void Network : : multicastUnsubscribe ( const MulticastGroup & mg )
{
2015-04-07 01:28:18 +00:00
Mutex : : Lock _l ( _lock ) ;
std : : vector < MulticastGroup > nmg ;
for ( std : : vector < MulticastGroup > : : const_iterator i ( _myMulticastGroups . begin ( ) ) ; i ! = _myMulticastGroups . end ( ) ; + + i ) {
if ( * i ! = mg )
nmg . push_back ( * i ) ;
2014-10-04 01:27:42 +00:00
}
2015-04-07 01:28:18 +00:00
if ( nmg . size ( ) ! = _myMulticastGroups . size ( ) )
_myMulticastGroups . swap ( nmg ) ;
2015-04-07 01:27:24 +00:00
}
2014-10-04 01:27:42 +00:00
2014-10-03 23:14:34 +00:00
bool Network : : applyConfiguration ( const SharedPtr < NetworkConfig > & conf )
2013-07-29 17:56:20 +00:00
{
2015-04-15 20:09:20 +00:00
if ( _destroyed ) // sanity check
2014-08-22 00:49:05 +00:00
return false ;
2013-09-04 13:27:56 +00:00
try {
2014-10-03 23:14:34 +00:00
if ( ( conf - > networkId ( ) = = _id ) & & ( conf - > issuedTo ( ) = = RR - > identity . address ( ) ) ) {
2015-04-06 23:52:52 +00:00
ZT1_VirtualNetworkConfig ctmp ;
2015-04-15 20:09:20 +00:00
bool portInitialized ;
{
Mutex : : Lock _l ( _lock ) ;
_config = conf ;
_lastConfigUpdate = RR - > node - > now ( ) ;
_netconfFailure = NETCONF_FAILURE_NONE ;
_externalConfig ( & ctmp ) ;
portInitialized = _portInitialized ;
_portInitialized = true ;
}
_portError = RR - > node - > configureVirtualNetworkPort ( _id , ( portInitialized ) ? ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_UP , & ctmp ) ;
2014-01-28 07:13:36 +00:00
return true ;
2013-10-18 16:01:48 +00:00
} else {
2015-04-08 23:49:21 +00:00
TRACE ( " ignored invalid configuration for network %.16llx (configuration contains mismatched network ID or issued-to address) " , ( unsigned long long ) _id ) ;
2013-08-06 04:05:39 +00:00
}
2013-10-18 16:01:48 +00:00
} catch ( std : : exception & exc ) {
2015-04-08 23:49:21 +00:00
TRACE ( " ignored invalid configuration for network %.16llx (%s) " , ( unsigned long long ) _id , exc . what ( ) ) ;
2013-09-04 13:27:56 +00:00
} catch ( . . . ) {
2015-04-08 23:49:21 +00:00
TRACE ( " ignored invalid configuration for network %.16llx (unknown exception) " , ( unsigned long long ) _id ) ;
2013-07-30 15:14:53 +00:00
}
2014-01-28 07:13:36 +00:00
return false ;
2013-07-29 17:56:20 +00:00
}
2015-01-06 01:47:59 +00:00
int Network : : setConfiguration ( const Dictionary & conf , bool saveToDisk )
2014-10-03 23:14:34 +00:00
{
try {
2015-04-06 22:47:57 +00:00
const SharedPtr < NetworkConfig > newConfig ( new NetworkConfig ( conf ) ) ; // throws if invalid
2015-01-06 01:47:59 +00:00
{
Mutex : : Lock _l ( _lock ) ;
if ( ( _config ) & & ( * _config = = * newConfig ) )
2015-01-09 21:35:20 +00:00
return 1 ; // OK config, but duplicate of what we already have
2015-01-06 01:47:59 +00:00
}
2014-10-03 23:14:34 +00:00
if ( applyConfiguration ( newConfig ) ) {
if ( saveToDisk ) {
2015-04-02 02:09:18 +00:00
char n [ 128 ] ;
Utils : : snprintf ( n , sizeof ( n ) , " networks.d/%.16llx.conf " , _id ) ;
RR - > node - > dataStorePut ( n , conf . toString ( ) , true ) ;
2014-10-03 23:14:34 +00:00
}
2015-01-06 01:47:59 +00:00
return 2 ; // OK and configuration has changed
2014-10-03 23:14:34 +00:00
}
} catch ( . . . ) {
2015-04-08 23:49:21 +00:00
TRACE ( " ignored invalid configuration for network %.16llx (dictionary decode failed) " , ( unsigned long long ) _id ) ;
2014-10-03 23:14:34 +00:00
}
2015-01-06 01:47:59 +00:00
return 0 ;
2014-10-03 23:14:34 +00:00
}
2013-07-29 17:56:20 +00:00
void Network : : requestConfiguration ( )
{
2015-04-15 22:12:09 +00:00
if ( _id = = ZT_TEST_NETWORK_ID ) // pseudo-network-ID, uses locally generated static config
2014-10-03 23:14:34 +00:00
return ;
2014-09-24 20:53:03 +00:00
if ( controller ( ) = = RR - > identity . address ( ) ) {
2015-04-15 22:12:09 +00:00
if ( RR - > localNetworkController ) {
2015-04-02 02:09:18 +00:00
SharedPtr < NetworkConfig > nconf ( config2 ( ) ) ;
Dictionary newconf ;
2015-04-16 01:32:25 +00:00
switch ( RR - > localNetworkController - > doNetworkConfigRequest ( InetAddress ( ) , RR - > identity , RR - > identity , _id , Dictionary ( ) , ( nconf ) ? nconf - > revision ( ) : ( uint64_t ) 0 , newconf ) ) {
2015-04-15 22:12:09 +00:00
case NetworkController : : NETCONF_QUERY_OK :
2015-04-02 02:09:18 +00:00
this - > setConfiguration ( newconf , true ) ;
return ;
2015-04-15 22:12:09 +00:00
case NetworkController : : NETCONF_QUERY_OBJECT_NOT_FOUND :
2015-04-02 02:09:18 +00:00
this - > setNotFound ( ) ;
return ;
2015-04-15 22:12:09 +00:00
case NetworkController : : NETCONF_QUERY_ACCESS_DENIED :
2015-04-02 02:09:18 +00:00
this - > setAccessDenied ( ) ;
return ;
default :
return ;
}
} else {
this - > setNotFound ( ) ;
return ;
}
2013-08-05 20:06:16 +00:00
}
2013-09-24 21:35:05 +00:00
2015-04-15 22:12:09 +00:00
TRACE ( " requesting netconf for network %.16llx from controller %s " , ( unsigned long long ) _id , controller ( ) . toString ( ) . c_str ( ) ) ;
2014-09-24 20:53:03 +00:00
Packet outp ( controller ( ) , RR - > identity . address ( ) , Packet : : VERB_NETWORK_CONFIG_REQUEST ) ;
2013-07-30 15:14:53 +00:00
outp . append ( ( uint64_t ) _id ) ;
2013-08-06 04:05:39 +00:00
outp . append ( ( uint16_t ) 0 ) ; // no meta-data
2015-01-06 01:51:50 +00:00
{
Mutex : : Lock _l ( _lock ) ;
if ( _config )
2015-04-02 02:09:18 +00:00
outp . append ( ( uint64_t ) _config - > revision ( ) ) ;
2015-01-06 01:51:50 +00:00
else outp . append ( ( uint64_t ) 0 ) ;
}
2014-09-24 20:53:03 +00:00
RR - > sw - > send ( outp , true ) ;
2013-07-29 17:56:20 +00:00
}
2014-10-01 00:26:34 +00:00
void Network : : addMembershipCertificate ( const CertificateOfMembership & cert , bool forceAccept )
2013-08-06 04:05:39 +00:00
{
2013-10-25 17:43:04 +00:00
if ( ! cert ) // sanity check
return ;
2014-11-13 20:40:51 +00:00
Mutex : : Lock _l ( _lock ) ;
CertificateOfMembership & old = _membershipCertificates [ cert . issuedTo ( ) ] ;
// Nothing to do if the cert hasn't changed -- we get duplicates due to zealous cert pushing
if ( old = = cert )
return ;
// Check signature, log and return if cert is invalid
2014-10-01 00:26:34 +00:00
if ( ! forceAccept ) {
2014-10-14 19:37:35 +00:00
if ( cert . signedBy ( ) ! = controller ( ) ) {
2015-04-08 23:49:21 +00:00
TRACE ( " rejected network membership certificate for %.16llx signed by %s: signer not a controller of this network " , ( unsigned long long ) _id , cert . signedBy ( ) . toString ( ) . c_str ( ) ) ;
2014-10-01 00:26:34 +00:00
return ;
2014-10-14 19:37:35 +00:00
}
2014-10-01 00:26:34 +00:00
SharedPtr < Peer > signer ( RR - > topology - > getPeer ( cert . signedBy ( ) ) ) ;
2014-10-14 19:37:35 +00:00
if ( ! signer ) {
2015-04-15 22:12:09 +00:00
// This would be rather odd, since this is our controller... could happen
2014-10-14 19:37:35 +00:00
// if we get packets before we've gotten config.
RR - > sw - > requestWhois ( cert . signedBy ( ) ) ;
2014-10-01 00:26:34 +00:00
return ;
2014-10-14 19:37:35 +00:00
}
if ( ! cert . verify ( signer - > identity ( ) ) ) {
2015-04-08 23:49:21 +00:00
TRACE ( " rejected network membership certificate for %.16llx signed by %s: signature check failed " , ( unsigned long long ) _id , cert . signedBy ( ) . toString ( ) . c_str ( ) ) ;
2014-10-14 19:37:35 +00:00
return ;
}
2014-10-01 00:26:34 +00:00
}
2014-11-13 20:40:51 +00:00
// If we made it past authentication, update cert
2015-01-07 01:16:54 +00:00
if ( cert . revision ( ) ! = old . revision ( ) )
2013-10-17 10:41:52 +00:00
old = cert ;
2013-08-06 04:05:39 +00:00
}
2014-10-09 19:42:25 +00:00
bool Network : : peerNeedsOurMembershipCertificate ( const Address & to , uint64_t now )
{
Mutex : : Lock _l ( _lock ) ;
if ( ( _config ) & & ( ! _config - > isPublic ( ) ) & & ( _config - > com ( ) ) ) {
2015-01-07 01:16:54 +00:00
uint64_t & lastPushed = _lastPushedMembershipCertificate [ to ] ;
if ( ( now - lastPushed ) > ( ZT_NETWORK_AUTOCONF_DELAY / 2 ) ) {
lastPushed = now ;
return true ;
2014-10-09 19:42:25 +00:00
}
}
return false ;
}
2013-07-29 21:11:00 +00:00
void Network : : clean ( )
{
2015-04-08 22:26:45 +00:00
const uint64_t now = RR - > node - > now ( ) ;
2014-09-30 23:28:25 +00:00
Mutex : : Lock _l ( _lock ) ;
2014-08-22 00:49:05 +00:00
2014-09-30 23:28:25 +00:00
if ( _destroyed )
return ;
2014-08-22 00:49:05 +00:00
2014-09-30 23:28:25 +00:00
if ( ( _config ) & & ( _config - > isPublic ( ) ) ) {
// Open (public) networks do not track certs or cert pushes at all.
_membershipCertificates . clear ( ) ;
_lastPushedMembershipCertificate . clear ( ) ;
} else if ( _config ) {
// Clean certificates that are no longer valid from the cache.
for ( std : : map < Address , CertificateOfMembership > : : iterator c = ( _membershipCertificates . begin ( ) ) ; c ! = _membershipCertificates . end ( ) ; ) {
if ( _config - > com ( ) . agreesWith ( c - > second ) )
+ + c ;
else _membershipCertificates . erase ( c + + ) ;
2013-08-06 04:05:39 +00:00
}
2014-09-30 23:28:25 +00:00
// Clean entries from the last pushed tracking map if they're so old as
// to be no longer relevant.
2015-01-07 01:16:54 +00:00
uint64_t forgetIfBefore = now - ( ZT_PEER_ACTIVITY_TIMEOUT * 16 ) ; // arbitrary reasonable cutoff
2014-09-30 23:28:25 +00:00
for ( std : : map < Address , uint64_t > : : iterator lp ( _lastPushedMembershipCertificate . begin ( ) ) ; lp ! = _lastPushedMembershipCertificate . end ( ) ; ) {
if ( lp - > second < forgetIfBefore )
_lastPushedMembershipCertificate . erase ( lp + + ) ;
else + + lp ;
2013-08-03 16:53:46 +00:00
}
2013-07-29 21:11:00 +00:00
}
2014-09-30 23:28:25 +00:00
// Clean learned multicast groups if we haven't heard from them in a while
for ( std : : map < MulticastGroup , uint64_t > : : iterator mg ( _multicastGroupsBehindMe . begin ( ) ) ; mg ! = _multicastGroupsBehindMe . end ( ) ; ) {
if ( ( now - mg - > second ) > ( ZT_MULTICAST_LIKE_EXPIRE * 2 ) )
_multicastGroupsBehindMe . erase ( mg + + ) ;
else + + mg ;
2014-06-13 21:06:34 +00:00
}
}
2015-04-08 22:26:45 +00:00
bool Network : : updateAndCheckMulticastBalance ( const MulticastGroup & mg , unsigned int bytes )
{
const uint64_t now = RR - > node - > now ( ) ;
Mutex : : Lock _l ( _lock ) ;
if ( ! _config )
return false ;
std : : map < MulticastGroup , BandwidthAccount > : : iterator bal ( _multicastRateAccounts . find ( mg ) ) ;
if ( bal = = _multicastRateAccounts . end ( ) ) {
NetworkConfig : : MulticastRate r ( _config - > multicastRate ( mg ) ) ;
bal = _multicastRateAccounts . insert ( std : : pair < MulticastGroup , BandwidthAccount > ( mg , BandwidthAccount ( r . preload , r . maxBalance , r . accrual , now ) ) ) . first ;
}
return bal - > second . deduct ( bytes , now ) ;
}
2014-09-26 19:23:43 +00:00
void Network : : learnBridgeRoute ( const MAC & mac , const Address & addr )
2013-07-04 20:56:19 +00:00
{
2014-09-26 19:23:43 +00:00
Mutex : : Lock _l ( _lock ) ;
_remoteBridgeRoutes [ mac ] = addr ;
2013-10-16 21:47:26 +00:00
2014-09-26 19:23:43 +00:00
// If _remoteBridgeRoutes exceeds sanity limit, trim worst offenders until below -- denial of service circuit breaker
while ( _remoteBridgeRoutes . size ( ) > ZT_MAX_BRIDGE_ROUTES ) {
std : : map < Address , unsigned long > counts ;
Address maxAddr ;
unsigned long maxCount = 0 ;
for ( std : : map < MAC , Address > : : iterator br ( _remoteBridgeRoutes . begin ( ) ) ; br ! = _remoteBridgeRoutes . end ( ) ; + + br ) {
unsigned long c = + + counts [ br - > second ] ;
if ( c > maxCount ) {
maxCount = c ;
maxAddr = br - > second ;
}
}
for ( std : : map < MAC , Address > : : iterator br ( _remoteBridgeRoutes . begin ( ) ) ; br ! = _remoteBridgeRoutes . end ( ) ; ) {
if ( br - > second = = maxAddr )
_remoteBridgeRoutes . erase ( br + + ) ;
else + + br ;
}
2013-07-04 20:56:19 +00:00
}
}
2015-04-07 01:27:24 +00:00
void Network : : learnBridgedMulticastGroup ( const MulticastGroup & mg , uint64_t now )
{
Mutex : : Lock _l ( _lock ) ;
2015-04-24 22:05:28 +00:00
unsigned long tmp = ( unsigned long ) _multicastGroupsBehindMe . size ( ) ;
2015-04-07 01:27:24 +00:00
_multicastGroupsBehindMe [ mg ] = now ;
if ( tmp ! = _multicastGroupsBehindMe . size ( ) )
_announceMulticastGroups ( ) ;
}
2014-09-26 19:23:43 +00:00
void Network : : setEnabled ( bool enabled )
2013-10-07 21:00:53 +00:00
{
2014-09-26 19:23:43 +00:00
Mutex : : Lock _l ( _lock ) ;
2015-04-15 00:57:51 +00:00
if ( _enabled ! = enabled ) {
_enabled = enabled ;
ZT1_VirtualNetworkConfig ctmp ;
_externalConfig ( & ctmp ) ;
_portError = RR - > node - > configureVirtualNetworkPort ( _id , ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE , & ctmp ) ;
}
2014-09-26 19:23:43 +00:00
}
2013-10-07 21:00:53 +00:00
2014-09-26 19:23:43 +00:00
void Network : : destroy ( )
{
Mutex : : Lock _l ( _lock ) ;
_enabled = false ;
_destroyed = true ;
2013-10-07 21:00:53 +00:00
}
2015-04-06 23:52:52 +00:00
ZT1_VirtualNetworkStatus Network : : _status ( ) const
{
// assumes _lock is locked
if ( _portError )
return ZT1_NETWORK_STATUS_PORT_ERROR ;
switch ( _netconfFailure ) {
case NETCONF_FAILURE_ACCESS_DENIED :
return ZT1_NETWORK_STATUS_ACCESS_DENIED ;
case NETCONF_FAILURE_NOT_FOUND :
return ZT1_NETWORK_STATUS_NOT_FOUND ;
case NETCONF_FAILURE_NONE :
2015-04-15 20:09:20 +00:00
return ( ( _config ) ? ZT1_NETWORK_STATUS_OK : ZT1_NETWORK_STATUS_REQUESTING_CONFIGURATION ) ;
2015-04-06 23:52:52 +00:00
default :
return ZT1_NETWORK_STATUS_PORT_ERROR ;
}
}
void Network : : _externalConfig ( ZT1_VirtualNetworkConfig * ec ) const
{
// assumes _lock is locked
ec - > nwid = _id ;
2015-04-14 22:16:04 +00:00
ec - > mac = _mac . toInt ( ) ;
2015-04-06 23:52:52 +00:00
if ( _config )
Utils : : scopy ( ec - > name , sizeof ( ec - > name ) , _config - > name ( ) . c_str ( ) ) ;
else ec - > name [ 0 ] = ( char ) 0 ;
ec - > status = _status ( ) ;
ec - > type = ( _config ) ? ( _config - > isPrivate ( ) ? ZT1_NETWORK_TYPE_PRIVATE : ZT1_NETWORK_TYPE_PUBLIC ) : ZT1_NETWORK_TYPE_PRIVATE ;
ec - > mtu = ZT_IF_MTU ;
ec - > dhcp = 0 ;
ec - > bridge = ( _config ) ? ( ( _config - > allowPassiveBridging ( ) | | ( std : : find ( _config - > activeBridges ( ) . begin ( ) , _config - > activeBridges ( ) . end ( ) , RR - > identity . address ( ) ) ! = _config - > activeBridges ( ) . end ( ) ) ) ? 1 : 0 ) : 0 ;
ec - > broadcastEnabled = ( _config ) ? ( _config - > enableBroadcast ( ) ? 1 : 0 ) : 0 ;
ec - > portError = _portError ;
2015-04-15 00:57:51 +00:00
ec - > enabled = ( _enabled ) ? 1 : 0 ;
2015-04-06 23:52:52 +00:00
ec - > netconfRevision = ( _config ) ? ( unsigned long ) _config - > revision ( ) : 0 ;
2015-04-14 22:16:04 +00:00
ec - > multicastSubscriptionCount = std : : min ( ( unsigned int ) _myMulticastGroups . size ( ) , ( unsigned int ) ZT1_MAX_NETWORK_MULTICAST_SUBSCRIPTIONS ) ;
2015-04-06 23:52:52 +00:00
for ( unsigned int i = 0 ; i < ec - > multicastSubscriptionCount ; + + i ) {
ec - > multicastSubscriptions [ i ] . mac = _myMulticastGroups [ i ] . mac ( ) . toInt ( ) ;
ec - > multicastSubscriptions [ i ] . adi = _myMulticastGroups [ i ] . adi ( ) ;
}
if ( _config ) {
ec - > assignedAddressCount = ( unsigned int ) _config - > staticIps ( ) . size ( ) ;
for ( unsigned long i = 0 ; i < ZT1_MAX_ZT_ASSIGNED_ADDRESSES ; + + i ) {
if ( i < _config - > staticIps ( ) . size ( ) )
memcpy ( & ( ec - > assignedAddresses [ i ] ) , & ( _config - > staticIps ( ) [ i ] ) , sizeof ( struct sockaddr_storage ) ) ;
}
} else ec - > assignedAddressCount = 0 ;
}
2015-05-13 23:55:18 +00:00
bool Network : : _isAllowed ( const Address & peer ) const
{
// Assumes _lock is locked
try {
if ( ! _config )
return false ;
if ( _config - > isPublic ( ) )
return true ;
std : : map < Address , CertificateOfMembership > : : const_iterator pc ( _membershipCertificates . find ( peer ) ) ;
if ( pc = = _membershipCertificates . end ( ) )
return false ; // no certificate on file
return _config - > com ( ) . agreesWith ( pc - > second ) ; // is other cert valid against ours?
} catch ( std : : exception & exc ) {
TRACE ( " isAllowed() check failed for peer %s: unexpected exception: %s " , peer . toString ( ) . c_str ( ) , exc . what ( ) ) ;
} catch ( . . . ) {
TRACE ( " isAllowed() check failed for peer %s: unexpected exception: unknown exception " , peer . toString ( ) . c_str ( ) ) ;
}
return false ; // default position on any failure
}
2015-04-07 01:27:24 +00:00
// Used in Network::_announceMulticastGroups()
class _AnnounceMulticastGroupsToPeersWithActiveDirectPaths
{
public :
_AnnounceMulticastGroupsToPeersWithActiveDirectPaths ( const RuntimeEnvironment * renv , Network * nw ) :
RR ( renv ) ,
2015-04-08 22:26:45 +00:00
_now ( renv - > node - > now ( ) ) ,
2015-04-07 01:27:24 +00:00
_network ( nw ) ,
_supernodeAddresses ( renv - > topology - > supernodeAddresses ( ) )
{ }
inline void operator ( ) ( Topology & t , const SharedPtr < Peer > & p )
{
2015-05-13 23:55:18 +00:00
if ( ( ( p - > hasActiveDirectPath ( _now ) ) & & ( _network - > _isAllowed ( p - > address ( ) ) ) ) | | ( std : : find ( _supernodeAddresses . begin ( ) , _supernodeAddresses . end ( ) , p - > address ( ) ) ! = _supernodeAddresses . end ( ) ) ) {
2015-04-07 01:27:24 +00:00
Packet outp ( p - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_MULTICAST_LIKE ) ;
std : : vector < MulticastGroup > mgs ( _network - > allMulticastGroups ( ) ) ;
for ( std : : vector < MulticastGroup > : : iterator mg ( mgs . begin ( ) ) ; mg ! = mgs . end ( ) ; + + mg ) {
if ( ( outp . size ( ) + 18 ) > ZT_UDP_DEFAULT_PAYLOAD_MTU ) {
outp . armor ( p - > key ( ) , true ) ;
p - > send ( RR , outp . data ( ) , outp . size ( ) , _now ) ;
outp . reset ( p - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_MULTICAST_LIKE ) ;
}
// network ID, MAC, ADI
outp . append ( ( uint64_t ) _network - > id ( ) ) ;
mg - > mac ( ) . appendTo ( outp ) ;
outp . append ( ( uint32_t ) mg - > adi ( ) ) ;
}
if ( outp . size ( ) > ZT_PROTO_MIN_PACKET_LENGTH ) {
outp . armor ( p - > key ( ) , true ) ;
p - > send ( RR , outp . data ( ) , outp . size ( ) , _now ) ;
}
}
}
private :
const RuntimeEnvironment * RR ;
uint64_t _now ;
Network * _network ;
std : : vector < Address > _supernodeAddresses ;
} ;
void Network : : _announceMulticastGroups ( )
{
2015-05-13 23:55:18 +00:00
// Assumes _lock is locked
2015-04-07 01:27:24 +00:00
_AnnounceMulticastGroupsToPeersWithActiveDirectPaths afunc ( RR , this ) ;
RR - > topology - > eachPeer < _AnnounceMulticastGroupsToPeersWithActiveDirectPaths & > ( afunc ) ;
}
2013-07-04 20:56:19 +00:00
} // namespace ZeroTier