diff --git a/node/Network.hpp b/node/Network.hpp index 1d8b92c6e..7c038811e 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -328,6 +328,24 @@ public: t->put(from,to,etherType,data,len); } + /** + * Call injectPacketFromHost() on tap if it exists + * + * @param from Source MAC + * @param to Destination MAC + * @param etherType Ethernet frame type + * @param data Packet data + * @param len Packet length + */ + inline bool tapInjectPacketFromHost(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) + { + Mutex::Lock _l(_lock); + EthernetTap *t = _tap; + if (t) + return t->injectPacketFromHost(from,to,etherType,data,len); + return false; + } + /** * @return Tap device name or empty string if still initializing */ diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index ddb98cce5..e45407a5a 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -35,6 +35,25 @@ namespace ZeroTier { // a starting and max balance of 64k. const NetworkConfig::MulticastRate NetworkConfig::DEFAULT_MULTICAST_RATE(32768,32768,64); +SharedPtr NetworkConfig::createTestNetworkConfig(const Address &self) +{ + SharedPtr nc(new NetworkConfig()); + + memset(nc->_etWhitelist,0,sizeof(nc->_etWhitelist)); + nc->_etWhitelist[0] |= 1; // allow all + nc->_nwid = ZT_TEST_NETWORK_ID; + nc->_timestamp = Utils::now(); + nc->_issuedTo = self; + nc->_multicastLimit = ZT_MULTICAST_DEFAULT_LIMIT; + nc->_allowPassiveBridging = false; + nc->_private = false; + nc->_enableBroadcast = true; + nc->_name = "ZT_TEST_NETWORK"; + nc->_description = "Built-in dummy test network"; + + return nc; +} + std::set NetworkConfig::allowedEtherTypes() const { std::set ets; diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index e0e9b3a9b..547018402 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -71,9 +71,9 @@ namespace ZeroTier { */ class NetworkConfig { -public: friend class SharedPtr; +public: /** * Tuple of multicast rate parameters */ @@ -91,6 +91,17 @@ public: */ static const MulticastRate DEFAULT_MULTICAST_RATE; + /** + * Create an instance of a NetworkConfig for the test network ID + * + * The test network ID is defined as ZT_TEST_NETWORK_ID. This is a + * "fake" network with no real netconf master and default options. + * + * @param self This node's ZT address + * @return Configured instance of netconf for test network ID + */ + static SharedPtr createTestNetworkConfig(const Address &self); + /** * @param d Dictionary containing configuration * @throws std::invalid_argument Invalid configuration diff --git a/node/Node.cpp b/node/Node.cpp index fd1daab3f..9f95eaa77 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -1011,6 +1011,22 @@ bool Node::updateCheck() return false; } +bool Node::injectPacketFromHost(uint64_t nwid,const unsigned char *from,const unsigned char *to,unsigned int etherType,const void *data,unsigned int len) +{ + if (!running()) + return false; + if ((!from)||(!to)) + return false; + + _NodeImpl *impl = (_NodeImpl *)_impl; + RuntimeEnvironment *RR = (RuntimeEnvironment *)&(impl->renv); + + SharedPtr network(RR->nc->network(nwid)); + if (network) + return network->tapInjectPacketFromHost(MAC(from,6),MAC(to,6),etherType,data,len); + return false; +} + class _VersionStringMaker { public: diff --git a/node/Node.hpp b/node/Node.hpp index 858a37372..259cdea2e 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -227,6 +227,23 @@ public: bool updateCheck() throw(); + /** + * Inject a packet into a network's tap as if it came from the host + * + * This is primarily for debugging, and at the moment is only supported on + * the test/dummy Ethernet tap implementation. Attempting to use it for real + * devices will fail and return 'false.' + * + * @param nwid Network ID + * @param from Source MAC address (must be 6 bytes in length) + * @param to Destination MAC address (must be 6 bytes in length) + * @param etherType Ethernet frame type + * @param data Frame data + * @param len Length of frame in bytes + * @return True on success; false if not a member of network, injection not supported, or data too large + */ + bool injectPacketFromHost(uint64_t nwid,const unsigned char *from,const unsigned char *to,unsigned int etherType,const void *data,unsigned int len); + static const char *versionString() throw(); static unsigned int versionMajor() throw(); static unsigned int versionMinor() throw();