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-12-07 00:49:20 +00:00
# ifndef ZT_NETWORK_HPP
# define ZT_NETWORK_HPP
2013-07-04 20:56:19 +00:00
2013-09-11 19:09:53 +00:00
# include <stdint.h>
2015-04-06 22:47:57 +00:00
# include "../include/ZeroTierOne.h"
2013-07-04 20:56:19 +00:00
# include <string>
2013-07-29 17:56:20 +00:00
# include <map>
2013-07-04 20:56:19 +00:00
# include <vector>
2013-09-11 20:08:31 +00:00
# include <algorithm>
2013-07-04 20:56:19 +00:00
# include <stdexcept>
2013-07-29 17:56:20 +00:00
# include "Constants.hpp"
2013-10-18 16:01:48 +00:00
# include "NonCopyable.hpp"
2015-09-04 20:42:19 +00:00
# include "Hashtable.hpp"
2013-07-04 20:56:19 +00:00
# include "Address.hpp"
# include "Mutex.hpp"
# include "SharedPtr.hpp"
# include "AtomicCounter.hpp"
# include "MulticastGroup.hpp"
2013-07-10 21:24:27 +00:00
# include "MAC.hpp"
2013-07-29 17:56:20 +00:00
# include "Dictionary.hpp"
2014-09-24 21:02:16 +00:00
# include "Multicaster.hpp"
2013-10-18 16:01:48 +00:00
# include "NetworkConfig.hpp"
2013-10-07 19:29:03 +00:00
# include "CertificateOfMembership.hpp"
2013-07-04 20:56:19 +00:00
namespace ZeroTier {
2013-07-29 17:56:20 +00:00
class RuntimeEnvironment ;
2015-05-13 23:55:18 +00:00
class _AnnounceMulticastGroupsToPeersWithActiveDirectPaths ;
2015-10-01 18:11:52 +00:00
class Peer ;
2013-07-04 20:56:19 +00:00
/**
2013-07-27 20:20:08 +00:00
* A virtual LAN
2013-07-04 20:56:19 +00:00
*/
2013-07-09 18:06:55 +00:00
class Network : NonCopyable
2013-07-04 20:56:19 +00:00
{
friend class SharedPtr < Network > ;
2015-05-13 23:55:18 +00:00
friend class _AnnounceMulticastGroupsToPeersWithActiveDirectPaths ;
2013-09-04 13:27:56 +00:00
2015-04-02 02:09:18 +00:00
public :
2013-09-04 13:27:56 +00:00
/**
2015-04-15 20:09:20 +00:00
* Broadcast multicast group : ff : ff : ff : ff : ff : ff / 0
*/
static const MulticastGroup BROADCAST ;
/**
* Construct a new network
*
* Note that init ( ) should be called immediately after the network is
* constructed to actually configure the port .
*
2013-10-18 16:01:48 +00:00
* @ param renv Runtime environment
2015-04-02 02:09:18 +00:00
* @ param nwid Network ID
2013-09-04 13:27:56 +00:00
*/
2015-04-02 02:09:18 +00:00
Network ( const RuntimeEnvironment * renv , uint64_t nwid ) ;
~ Network ( ) ;
2013-07-29 21:11:00 +00:00
2013-07-04 20:56:19 +00:00
/**
* @ return Network ID
*/
inline uint64_t id ( ) const throw ( ) { return _id ; }
/**
2015-04-15 22:12:09 +00:00
* @ return Address of network ' s controller ( most significant 40 bits of ID )
2013-07-04 20:56:19 +00:00
*/
2013-07-29 17:56:20 +00:00
inline Address controller ( ) throw ( ) { return Address ( _id > > 24 ) ; }
2013-07-04 20:56:19 +00:00
2015-10-01 18:11:52 +00:00
/**
* @ param nwid Network ID
* @ return Address of network ' s controller
*/
static inline Address controllerFor ( uint64_t nwid ) throw ( ) { return Address ( nwid > > 24 ) ; }
2013-08-03 16:53:46 +00:00
/**
2015-04-07 01:27:24 +00:00
* @ return Multicast group memberships for this network ' s port ( local , not learned via bridging )
2013-08-03 16:53:46 +00:00
*/
2015-04-02 02:09:18 +00:00
inline std : : vector < MulticastGroup > multicastGroups ( ) const
2013-07-04 20:56:19 +00:00
{
Mutex : : Lock _l ( _lock ) ;
2014-09-19 01:28:14 +00:00
return _myMulticastGroups ;
2013-07-04 20:56:19 +00:00
}
2015-04-07 01:27:24 +00:00
/**
* @ return All multicast groups including learned groups that are behind any bridges we ' re attached to
*/
2015-05-25 21:21:05 +00:00
inline std : : vector < MulticastGroup > allMulticastGroups ( ) const
{
Mutex : : Lock _l ( _lock ) ;
return _allMulticastGroups ( ) ;
}
2015-04-07 01:27:24 +00:00
2014-10-10 01:32:05 +00:00
/**
* @ param mg Multicast group
2015-04-07 02:41:55 +00:00
* @ param includeBridgedGroups If true , also include any groups we ' ve learned via bridging
2014-10-10 01:32:05 +00:00
* @ return True if this network endpoint / peer is a member
*/
2015-04-07 02:41:55 +00:00
bool subscribedToMulticastGroup ( const MulticastGroup & mg , bool includeBridgedGroups ) const ;
2014-10-10 01:32:05 +00:00
2015-04-07 01:27:24 +00:00
/**
* Subscribe to a multicast group
*
* @ param mg New multicast group
*/
void multicastSubscribe ( const MulticastGroup & mg ) ;
/**
* Unsubscribe from a multicast group
*
* @ param mg Multicast group
*/
void multicastUnsubscribe ( const MulticastGroup & mg ) ;
2013-07-29 17:56:20 +00:00
/**
2014-10-03 23:14:34 +00:00
* Apply a NetworkConfig to this network
2013-07-29 17:56:20 +00:00
*
2014-10-03 23:14:34 +00:00
* @ param conf Configuration in NetworkConfig form
* @ return True if configuration was accepted
*/
bool applyConfiguration ( const SharedPtr < NetworkConfig > & conf ) ;
/**
* Set or update this network ' s configuration
2014-01-28 07:13:36 +00:00
*
2014-10-03 23:14:34 +00:00
* This decodes a network configuration in key = value dictionary form ,
* applies it if valid , and persists it to disk if saveToDisk is true .
2014-01-28 07:13:36 +00:00
*
2013-07-29 17:56:20 +00:00
* @ param conf Configuration in key / value dictionary form
2013-10-16 21:47:26 +00:00
* @ param saveToDisk IF true ( default ) , write config to disk
2015-01-06 01:47:59 +00:00
* @ return 0 - - rejected , 1 - - accepted but not new , 2 - - accepted new config
2014-01-28 07:13:36 +00:00
*/
2015-01-06 01:47:59 +00:00
int setConfiguration ( const Dictionary & conf , bool saveToDisk = true ) ;
2014-01-28 07:13:36 +00:00
/**
2015-04-15 22:12:09 +00:00
* Set netconf failure to ' access denied ' - - called in IncomingPacket when controller reports this
2013-07-29 17:56:20 +00:00
*/
2014-01-28 07:13:36 +00:00
inline void setAccessDenied ( )
{
Mutex : : Lock _l ( _lock ) ;
_netconfFailure = NETCONF_FAILURE_ACCESS_DENIED ;
}
/**
2015-04-15 22:12:09 +00:00
* Set netconf failure to ' not found ' - - called by PacketDecider when controller reports this
2014-01-28 07:13:36 +00:00
*/
inline void setNotFound ( )
{
Mutex : : Lock _l ( _lock ) ;
_netconfFailure = NETCONF_FAILURE_NOT_FOUND ;
}
2013-07-29 17:56:20 +00:00
/**
* Causes this network to request an updated configuration from its master node now
*/
void requestConfiguration ( ) ;
2013-07-29 21:11:00 +00:00
/**
2015-10-01 18:11:52 +00:00
* @ param peer Peer to check
2013-08-06 04:05:39 +00:00
* @ return True if peer is allowed to communicate on this network
*/
2015-10-01 18:11:52 +00:00
inline bool isAllowed ( const SharedPtr < Peer > & peer ) const
2015-05-13 23:55:18 +00:00
{
Mutex : : Lock _l ( _lock ) ;
return _isAllowed ( peer ) ;
}
2013-07-29 21:11:00 +00:00
/**
2013-08-06 04:05:39 +00:00
* Perform cleanup and possibly save state
2013-07-29 21:11:00 +00:00
*/
void clean ( ) ;
2013-07-30 15:14:53 +00:00
/**
* @ return Time of last updated configuration or 0 if none
*/
2013-10-07 20:13:52 +00:00
inline uint64_t lastConfigUpdate ( ) const throw ( ) { return _lastConfigUpdate ; }
2013-07-30 15:14:53 +00:00
2013-08-08 14:41:17 +00:00
/**
* @ return Status of this network
*/
2015-09-24 23:21:36 +00:00
inline ZT_VirtualNetworkStatus status ( ) const
2015-04-06 23:52:52 +00:00
{
Mutex : : Lock _l ( _lock ) ;
return _status ( ) ;
}
/**
* @ param ec Buffer to fill with externally - visible network configuration
*/
2015-09-24 23:21:36 +00:00
inline void externalConfig ( ZT_VirtualNetworkConfig * ec ) const
2015-04-06 23:52:52 +00:00
{
Mutex : : Lock _l ( _lock ) ;
_externalConfig ( ec ) ;
}
2013-08-08 21:20:35 +00:00
2013-09-25 21:41:49 +00:00
/**
2013-10-18 16:01:48 +00:00
* Get current network config or throw exception
*
* This version never returns null . Instead it throws a runtime error if
* there is no current configuration . Callers should check isUp ( ) first or
* use config2 ( ) to get with the potential for null .
*
2014-06-27 00:05:07 +00:00
* Since it never returns null , it ' s safe to config ( ) - > whatever ( ) inside
* a try / catch block .
2013-10-18 16:01:48 +00:00
*
* @ return Network configuration ( never null )
* @ throws std : : runtime_error Network configuration unavailable
2013-09-25 21:41:49 +00:00
*/
2013-10-18 16:01:48 +00:00
inline SharedPtr < NetworkConfig > config ( ) const
2013-09-25 21:41:49 +00:00
{
2013-10-18 16:01:48 +00:00
Mutex : : Lock _l ( _lock ) ;
if ( _config )
return _config ;
throw std : : runtime_error ( " no configuration " ) ;
2013-09-25 21:41:49 +00:00
}
2013-09-30 17:51:56 +00:00
/**
2013-10-25 17:43:04 +00:00
* Get current network config or return NULL
*
2013-10-18 16:01:48 +00:00
* @ return Network configuration - - may be NULL
2013-09-30 17:51:56 +00:00
*/
2013-10-18 16:01:48 +00:00
inline SharedPtr < NetworkConfig > config2 ( ) const
throw ( )
{
Mutex : : Lock _l ( _lock ) ;
return _config ;
}
2013-09-30 17:51:56 +00:00
2014-01-28 07:13:36 +00:00
/**
* @ return Ethernet MAC address for this network ' s local interface
*/
2014-09-26 19:23:43 +00:00
inline const MAC & mac ( ) const throw ( ) { return _mac ; }
2014-01-28 07:13:36 +00:00
2014-06-11 04:41:34 +00:00
/**
* Shortcut for config ( ) - > permitsBridging ( ) , returns false if no config
*
* @ param peer Peer address to check
* @ return True if peer can bridge other Ethernet nodes into this network or network is in permissive bridging mode
*/
inline bool permitsBridging ( const Address & peer ) const
{
Mutex : : Lock _l ( _lock ) ;
if ( _config )
return _config - > permitsBridging ( peer ) ;
return false ;
}
2014-06-11 00:18:59 +00:00
/**
2014-09-26 19:23:43 +00:00
* Find the node on this network that has this MAC behind it ( if any )
*
2014-06-11 00:18:59 +00:00
* @ param mac MAC address
2014-09-26 19:23:43 +00:00
* @ return ZeroTier address of bridge to this MAC
2014-06-11 00:18:59 +00:00
*/
inline Address findBridgeTo ( const MAC & mac ) const
{
Mutex : : Lock _l ( _lock ) ;
2015-09-04 20:53:48 +00:00
const Address * const br = _remoteBridgeRoutes . get ( mac ) ;
if ( br )
return * br ;
return Address ( ) ;
2014-06-11 00:18:59 +00:00
}
/**
* Set a bridge route
*
* @ param mac MAC address of destination
* @ param addr Bridge this MAC is reachable behind
*/
void learnBridgeRoute ( const MAC & mac , const Address & addr ) ;
2014-06-13 21:06:34 +00:00
/**
* Learn a multicast group that is bridged to our tap device
*
* @ param mg Multicast group
2014-06-27 01:13:48 +00:00
* @ param now Current time
2014-06-13 21:06:34 +00:00
*/
2015-04-07 01:27:24 +00:00
void learnBridgedMulticastGroup ( const MulticastGroup & mg , uint64_t now ) ;
2014-06-13 21:06:34 +00:00
2014-06-27 00:05:07 +00:00
/**
* @ return True if traffic on this network ' s tap is enabled
*/
inline bool enabled ( ) const throw ( ) { return _enabled ; }
/**
* @ param enabled Should traffic be allowed on this network ?
*/
void setEnabled ( bool enabled ) ;
2014-08-22 00:49:05 +00:00
/**
* Destroy this network
*
* This causes the network to disable itself , destroy its tap device , and on
* delete to delete all trace of itself on disk and remove any persistent tap
* device instances . Call this when a network is being removed from the system .
*/
void destroy ( ) ;
2015-04-08 23:49:21 +00:00
inline bool operator = = ( const Network & n ) const throw ( ) { return ( _id = = n . _id ) ; }
inline bool operator ! = ( const Network & n ) const throw ( ) { return ( _id ! = n . _id ) ; }
inline bool operator < ( const Network & n ) const throw ( ) { return ( _id < n . _id ) ; }
inline bool operator > ( const Network & n ) const throw ( ) { return ( _id > n . _id ) ; }
inline bool operator < = ( const Network & n ) const throw ( ) { return ( _id < = n . _id ) ; }
inline bool operator > = ( const Network & n ) const throw ( ) { return ( _id > = n . _id ) ; }
2013-07-04 20:56:19 +00:00
private :
2015-09-24 23:21:36 +00:00
ZT_VirtualNetworkStatus _status ( ) const ;
void _externalConfig ( ZT_VirtualNetworkConfig * ec ) const ; // assumes _lock is locked
2015-10-01 18:11:52 +00:00
bool _isAllowed ( const SharedPtr < Peer > & peer ) const ;
2015-04-07 01:27:24 +00:00
void _announceMulticastGroups ( ) ;
2015-05-25 21:21:05 +00:00
std : : vector < MulticastGroup > _allMulticastGroups ( ) const ;
2015-04-06 23:52:52 +00:00
2015-04-02 02:09:18 +00:00
const RuntimeEnvironment * RR ;
2013-10-18 16:01:48 +00:00
uint64_t _id ;
2014-06-11 00:18:59 +00:00
MAC _mac ; // local MAC address
2015-04-15 20:09:20 +00:00
volatile bool _enabled ;
volatile bool _portInitialized ;
2014-06-11 00:18:59 +00:00
2015-09-04 20:53:48 +00:00
std : : vector < MulticastGroup > _myMulticastGroups ; // multicast groups that we belong to (according to tap)
Hashtable < MulticastGroup , uint64_t > _multicastGroupsBehindMe ; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge)
2015-09-04 21:14:32 +00:00
Hashtable < MAC , Address > _remoteBridgeRoutes ; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges)
2014-09-19 01:28:14 +00:00
SharedPtr < NetworkConfig > _config ; // Most recent network configuration, which is an immutable value-object
2013-08-03 16:53:46 +00:00
volatile uint64_t _lastConfigUpdate ;
2014-06-11 00:18:59 +00:00
2014-08-22 00:49:05 +00:00
volatile bool _destroyed ;
2014-06-11 00:18:59 +00:00
2015-04-06 23:52:52 +00:00
enum {
2014-01-28 07:13:36 +00:00
NETCONF_FAILURE_NONE ,
NETCONF_FAILURE_ACCESS_DENIED ,
NETCONF_FAILURE_NOT_FOUND ,
NETCONF_FAILURE_INIT_FAILED
} _netconfFailure ;
2015-04-15 20:09:20 +00:00
volatile int _portError ; // return value from port config callback
2014-06-11 00:18:59 +00:00
2013-07-04 20:56:19 +00:00
Mutex _lock ;
AtomicCounter __refCount ;
} ;
} // naemspace ZeroTier
# endif