2013-07-04 20:56:19 +00:00
/*
2015-02-17 21:11:34 +00:00
* ZeroTier One - Network Virtualization Everywhere
2016-01-12 22:04:55 +00:00
* Copyright ( C ) 2011 - 2016 ZeroTier , Inc . https : //www.zerotier.com/
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/>.
*/
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"
2016-08-05 22:02:01 +00:00
# include "Membership.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-10-01 18:11:52 +00:00
class Peer ;
2016-04-19 19:09:35 +00:00
class _MulticastAnnounceAll ;
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 > ;
2016-04-19 19:09:35 +00:00
friend class _MulticastAnnounceAll ; // internal function object
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
2016-01-12 19:04:35 +00:00
* @ param uptr Arbitrary pointer used by externally - facing API ( for user use )
2013-09-04 13:27:56 +00:00
*/
2016-01-12 19:04:35 +00:00
Network ( const RuntimeEnvironment * renv , uint64_t nwid , void * uptr ) ;
2015-04-02 02:09:18 +00:00
~ Network ( ) ;
2013-07-29 21:11:00 +00:00
2016-08-04 20:01:14 +00:00
/**
* Apply filters to an outgoing packet
*
* This applies filters from our network config and , if that doesn ' t match ,
* our capabilities in ascending order of capability ID . If there is a match
* certain actions may be taken such as pushing credentials to ztDest and
* sending a copy of the packet to a TEE or REDIRECT target .
*
2016-08-24 22:26:18 +00:00
* @ param noRedirect If true , do not TEE or REDIRECT - - this is set for secondary filtrations done in multicast and bridge send paths
2016-08-04 20:01:14 +00:00
* @ param ztSource Source ZeroTier address
* @ param ztDest Destination ZeroTier address
* @ param macSource Ethernet layer source address
* @ param macDest Ethernet layer destination address
* @ param frameData Ethernet frame data
* @ param frameLen Ethernet frame payload length
* @ param etherType 16 - bit ethernet type ID
* @ param vlanId 16 - bit VLAN ID
* @ return True if packet should be sent to destination peer
*/
bool filterOutgoingPacket (
2016-08-24 22:26:18 +00:00
const bool noRedirect ,
2016-08-04 20:01:14 +00:00
const Address & ztSource ,
const Address & ztDest ,
const MAC & macSource ,
const MAC & macDest ,
const uint8_t * frameData ,
const unsigned int frameLen ,
const unsigned int etherType ,
const unsigned int vlanId ) ;
/**
* Apply filters to an incoming packet
*
* This applies filters from our network config and , if that doesn ' t match ,
* the peer ' s capabilities in ascending order of capability ID . If there is
* a match certain actions may be taken such as sending a copy of the packet
* to a TEE or REDIRECT target .
*
2016-08-05 22:02:01 +00:00
* @ param sourcePeer Source Peer
2016-08-04 20:01:14 +00:00
* @ param ztDest Destination ZeroTier address
* @ param macSource Ethernet layer source address
* @ param macDest Ethernet layer destination address
* @ param frameData Ethernet frame data
* @ param frameLen Ethernet frame payload length
* @ param etherType 16 - bit ethernet type ID
* @ param vlanId 16 - bit VLAN ID
* @ return True if packet should be accepted locally
*/
bool filterIncomingPacket (
2016-08-05 22:02:01 +00:00
const SharedPtr < Peer > & sourcePeer ,
2016-08-04 20:01:14 +00:00
const Address & ztDest ,
const MAC & macSource ,
const MAC & macDest ,
const uint8_t * frameData ,
const unsigned int frameLen ,
const unsigned int etherType ,
const unsigned int vlanId ) ;
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
*/
2015-10-01 18:37:02 +00:00
inline Address controller ( ) const 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 ) ;
2015-10-01 18:37:02 +00:00
/**
* Announce multicast groups to a peer if that peer is authorized on this network
*
* @ param peer Peer to try to announce multicast groups to
* @ return True if peer was authorized and groups were announced
*/
bool tryAnnounceMulticastGroupsTo ( const SharedPtr < Peer > & peer ) ;
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
*/
2016-04-12 19:11:34 +00:00
bool applyConfiguration ( const NetworkConfig & conf ) ;
2014-10-03 23:14:34 +00:00
/**
* Set or update this network ' s configuration
2014-01-28 07:13:36 +00:00
*
2016-06-16 19:28:43 +00:00
* @ param nconf Network configuration
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
*/
2016-06-16 19:28:43 +00:00
int setConfiguration ( const NetworkConfig & nconf , bool saveToDisk ) ;
2014-01-28 07:13:36 +00:00
2016-08-09 20:14:38 +00:00
/**
* Handle an inbound network config chunk
*
* Only chunks whose inRePacketId matches the packet ID of the last request
* are handled . If this chunk completes the config , it is decoded and
* setConfiguration ( ) is called .
*
* @ param inRePacketId In - re packet ID from OK ( NETWORK_CONFIG_REQUEST )
* @ param data Chunk data
* @ param chunkSize Size of data [ ]
* @ param chunkIndex Index of chunk in full config
* @ param totalSize Total size of network config
*/
void handleInboundConfigChunk ( const uint64_t inRePacketId , const void * data , unsigned int chunkSize , unsigned int chunkIndex , unsigned int totalSize ) ;
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
2016-08-24 21:28:16 +00:00
*
* There is a circuit breaker here to prevent this from being done more often
* than once per second . This is to prevent things like NETWORK_CONFIG_REFRESH
* from causing multiple requests .
2013-07-29 17:56:20 +00:00
*/
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
/**
2016-04-12 19:11:34 +00:00
* Get current network config
2013-10-18 16:01:48 +00:00
*
2016-04-12 19:11:34 +00:00
* This returns a const reference to the network config in place , which is safe
* to concurrently access but * may * change during access . Normally this isn ' t a
* problem , but if it is use configCopy ( ) .
2013-10-18 16:01:48 +00:00
*
2016-04-12 19:11:34 +00:00
* @ return Network configuration ( may be a null config if we don ' t have one yet )
2013-09-25 21:41:49 +00:00
*/
2016-04-12 19:16:29 +00:00
inline const NetworkConfig & config ( ) const { return _config ; }
2013-09-25 21:41:49 +00:00
2013-09-30 17:51:56 +00:00
/**
2016-04-12 19:11:34 +00:00
* @ return A thread - safe copy of our NetworkConfig instead of a const reference
2013-09-30 17:51:56 +00:00
*/
2016-04-12 19:11:34 +00:00
inline NetworkConfig configCopy ( ) const
2013-10-18 16:01:48 +00:00
{
Mutex : : Lock _l ( _lock ) ;
2016-04-12 19:16:29 +00:00
return _config ;
2013-10-18 16:01:48 +00:00
}
2013-09-30 17:51:56 +00:00
2014-01-28 07:13:36 +00:00
/**
2016-04-12 19:11:34 +00:00
* @ return True if this network has a valid config
2014-01-28 07:13:36 +00:00
*/
2016-04-12 19:11:34 +00:00
inline bool hasConfig ( ) const { return ( _config ) ; }
2014-01-28 07:13:36 +00:00
2014-06-11 04:41:34 +00:00
/**
2016-04-12 19:11:34 +00:00
* @ return Ethernet MAC address for this network ' s local interface
2014-06-11 04:41:34 +00:00
*/
2016-04-12 19:11:34 +00:00
inline const MAC & mac ( ) const throw ( ) { return _mac ; }
2014-06-11 04:41:34 +00:00
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
2016-08-09 00:33:26 +00:00
/**
* @ param com Certificate of membership
* @ return 0 = = OK , 1 = = waiting for WHOIS , - 1 = = BAD signature or credential
*/
inline int addCredential ( const CertificateOfMembership & com )
{
if ( com . networkId ( ) ! = _id )
return - 1 ;
Mutex : : Lock _l ( _lock ) ;
return _memberships [ com . issuedTo ( ) ] . addCredential ( RR , com ) ;
}
/**
* @ param cap Capability
* @ return 0 = = OK , 1 = = waiting for WHOIS , - 1 = = BAD signature or credential
*/
inline int addCredential ( const Capability & cap )
{
if ( cap . networkId ( ) ! = _id )
return - 1 ;
Mutex : : Lock _l ( _lock ) ;
return _memberships [ cap . issuedTo ( ) ] . addCredential ( RR , cap ) ;
}
/**
* @ param cap Tag
* @ return 0 = = OK , 1 = = waiting for WHOIS , - 1 = = BAD signature or credential
*/
inline int addCredential ( const Tag & tag )
{
if ( tag . networkId ( ) ! = _id )
return - 1 ;
Mutex : : Lock _l ( _lock ) ;
return _memberships [ tag . issuedTo ( ) ] . addCredential ( RR , tag ) ;
}
2016-08-23 20:46:36 +00:00
/**
* Blacklist COM , tags , and capabilities before this time
*
* @ param ts Blacklist cutoff
*/
inline void blacklistBefore ( const Address & peerAddress , const uint64_t ts )
{
Mutex : : Lock _l ( _lock ) ;
_memberships [ peerAddress ] . blacklistBefore ( ts ) ;
}
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 ( ) ;
2016-01-12 19:04:35 +00:00
/**
2016-01-12 19:34:22 +00:00
* @ return Pointer to user PTR ( modifiable user ptr used in API )
2016-01-12 19:04:35 +00:00
*/
2016-01-12 21:17:30 +00:00
inline void * * userPtr ( ) throw ( ) { return & _uPtr ; }
2016-01-12 19:04:35 +00:00
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 ( ) ;
2016-08-08 23:50:00 +00:00
void _announceMulticastGroupsTo ( const SharedPtr < Peer > & peer , const std : : vector < MulticastGroup > & allMulticastGroups ) ;
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 ;
2016-01-12 21:17:30 +00:00
void * _uPtr ;
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 _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
2016-08-09 20:14:38 +00:00
uint64_t _inboundConfigPacketId ;
std : : map < unsigned int , std : : string > _inboundConfigChunks ;
2016-04-12 19:11:34 +00:00
NetworkConfig _config ;
2013-08-03 16:53:46 +00:00
volatile uint64_t _lastConfigUpdate ;
2016-08-24 21:28:16 +00:00
volatile uint64_t _lastRequestedConfiguration ;
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
2016-08-05 22:02:01 +00:00
Hashtable < Address , Membership > _memberships ;
2013-07-04 20:56:19 +00:00
Mutex _lock ;
AtomicCounter __refCount ;
} ;
} // naemspace ZeroTier
# endif