summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--node/IncomingPacket.cpp44
-rw-r--r--node/Node.cpp4
-rw-r--r--node/Packet.hpp25
-rw-r--r--node/RuntimeEnvironment.hpp5
-rw-r--r--node/SelfAwareness.hpp (renamed from node/ExternalSurface.hpp)28
-rw-r--r--node/Topology.hpp17
6 files changed, 83 insertions, 40 deletions
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index f63b33b2..99f66561 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -39,6 +39,7 @@
#include "Switch.hpp"
#include "Peer.hpp"
#include "NetworkConfigMaster.hpp"
+#include "SelfAwareness.hpp"
namespace ZeroTier {
@@ -174,7 +175,23 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION];
const unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO_IDX_REVISION);
const uint64_t timestamp = at<uint64_t>(ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP);
- const Identity id(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY);
+
+ Identity id;
+ unsigned int destAddrPtr = id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY) + ZT_PROTO_VERB_HELLO_IDX_IDENTITY;
+
+ unsigned int destAddrType = ZT_PROTO_DEST_ADDRESS_TYPE_NONE;
+ if (destAddrPtr < size()) // ZeroTier One < 1.0.3 did not include this field
+ destAddrType = (*this)[destAddrPtr++];
+
+ InetAddress destAddr;
+ switch(destAddrType) {
+ case ZT_PROTO_DEST_ADDRESS_TYPE_IPV4:
+ destAddr.set(field(destAddrPtr,4),4,at<uint16_t>(destAddrPtr + 4));
+ break;
+ case ZT_PROTO_DEST_ADDRESS_TYPE_IPV6:
+ destAddr.set(field(destAddrPtr,16),16,at<uint16_t>(destAddrPtr + 16));
+ break;
+ }
if (source() != id.address()) {
TRACE("dropped HELLO from %s(%s): identity not for sending address",source().toString().c_str(),_remoteAddress.toString().c_str());
@@ -245,11 +262,13 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_HELLO,0,Packet::VERB_NOP);
peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision);
- // Won't get HELLO *from* supernodes, so skip this for now here. It's done in OK(HELLO).
- //if (RR->topology->isSupernode(id.address()))
- // RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision);
+ if (RR->topology->isSupernode(id.address())) {
+ RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision);
+ RR->sa->iam(destAddr);
+ }
Packet outp(id.address(),RR->identity.address(),Packet::VERB_OK);
+
outp.append((unsigned char)Packet::VERB_HELLO);
outp.append(packetId());
outp.append(timestamp);
@@ -257,6 +276,23 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR);
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
+
+ switch(_remoteAddress.ss_family) {
+ case AF_INET:
+ outp.append((unsigned char)ZT_PROTO_DEST_ADDRESS_TYPE_IPV4);
+ outp.append(_remoteAddress.rawIpData(),4);
+ outp.append((uint16_t)_remoteAddress.port());
+ break;
+ case AF_INET6:
+ outp.append((unsigned char)ZT_PROTO_DEST_ADDRESS_TYPE_IPV6);
+ outp.append(_remoteAddress.rawIpData(),16);
+ outp.append((uint16_t)_remoteAddress.port());
+ break;
+ default:
+ outp.append((unsigned char)ZT_PROTO_DEST_ADDRESS_TYPE_NONE);
+ break;
+ }
+
outp.armor(peer->key(),true);
RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation);
} catch (std::exception &ex) {
diff --git a/node/Node.cpp b/node/Node.cpp
index 2167d9c1..59bb3dd3 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -41,6 +41,7 @@
#include "Logger.hpp"
#include "Address.hpp"
#include "Identity.hpp"
+#include "SelfAwareness.hpp"
namespace ZeroTier {
@@ -77,7 +78,9 @@ Node::Node(
RR->mc = new Multicaster(RR);
RR->antiRec = new AntiRecursion();
RR->topology = new Topology(RR);
+ RR->sa = new SelfAwareness(RR);
} catch ( ... ) {
+ delete RR->sa;
delete RR->topology;
delete RR->antiRec;
delete RR->mc;
@@ -91,6 +94,7 @@ Node::Node(
Node::~Node()
{
+ delete RR->sa;
delete RR->topology;
delete RR->antiRec;
delete RR->mc;
diff --git a/node/Packet.hpp b/node/Packet.hpp
index 7439dddc..20a5b145 100644
--- a/node/Packet.hpp
+++ b/node/Packet.hpp
@@ -175,6 +175,12 @@
*/
#define ZT_PROTO_BEACON_IDX_ADDRESS 8
+// Destination address types from HELLO and OK(HELLO)
+#define ZT_PROTO_DEST_ADDRESS_TYPE_NONE 0
+#define ZT_PROTO_DEST_ADDRESS_TYPE_ETHERNET 1
+#define ZT_PROTO_DEST_ADDRESS_TYPE_IPV4 4
+#define ZT_PROTO_DEST_ADDRESS_TYPE_IPV6 6
+
// Field incides for parsing verbs -------------------------------------------
// Some verbs have variable-length fields. Those aren't fully defined here
@@ -467,6 +473,23 @@ public:
* <[2] software revision>
* <[8] timestamp (ms since epoch)>
* <[...] binary serialized identity (see Identity)>
+ * <[1] destination address type>
+ * [<[...] destination address>]
+ *
+ * This is the only message that ever must be sent in the clear, since it
+ * is used to push an identity to a new peer.
+ *
+ * The destination address is the wire address to which this packet is
+ * being sent, and in OK is *also* the destination address of the OK
+ * packet. This can be used by the receiver to detect NAT, learn its real
+ * external address if behind NAT, and detect changes to its external
+ * address that require re-establishing connectivity.
+ *
+ * Destination address types and formats (not all of these are used now):
+ * 0 - None -- no destination address data present
+ * 1 - Ethernet address -- format: <[6] Ethernet MAC>
+ * 4 - 6-byte IPv4 address -- format: <[4] IP>, <[2] port>
+ * 6 - 18-byte IPv6 address -- format: <[16] IP>, <[2] port>
*
* OK payload:
* <[8] timestamp (echoed from original HELLO)>
@@ -474,6 +497,8 @@ public:
* <[1] software major version (of responder)>
* <[1] software minor version (of responder)>
* <[2] software revision (of responder)>
+ * <[1] destination address type (for this OK, not copied from HELLO)>
+ * [<[...] destination address>]
*
* ERROR has no payload.
*/
diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp
index 9600b9dc..1ca483ef 100644
--- a/node/RuntimeEnvironment.hpp
+++ b/node/RuntimeEnvironment.hpp
@@ -44,6 +44,7 @@ class Node;
class Multicaster;
class AntiRecursion;
class NetworkConfigMaster;
+class SelfAwareness;
/**
* Holds global state for an instance of ZeroTier::Node
@@ -69,7 +70,8 @@ public:
sw((Switch *)0),
mc((Multicaster *)0),
antiRec((AntiRecursion *)0),
- topology((Topology *)0)
+ topology((Topology *)0),
+ sa((SelfAwareness *)0)
{
}
@@ -96,6 +98,7 @@ public:
Multicaster *mc;
AntiRecursion *antiRec;
Topology *topology;
+ SelfAwareness *sa;
};
} // namespace ZeroTier
diff --git a/node/ExternalSurface.hpp b/node/SelfAwareness.hpp
index b29c5128..93af34f4 100644
--- a/node/ExternalSurface.hpp
+++ b/node/SelfAwareness.hpp
@@ -25,40 +25,32 @@
* LLC. Start here: http://www.zerotier.com/
*/
-#ifndef ZT_EXTERNALSURFACE_HPP
-#define ZT_EXTERNALSURFACE_HPP
+#ifndef ZT_SELFAWARENESS_HPP
+#define ZT_SELFAWARENESS_HPP
#include "InetAddress.hpp"
namespace ZeroTier {
+class RuntimeEnvironment;
+
/**
* Tracks changes to this peer's real world addresses
*/
-class ExternalSurface
+class SelfAwareness
{
public:
- ExternalSurface() {}
+ SelfAwareness(const RuntimeEnvironment *renv);
+ ~SelfAwareness();
/**
- * Revise our external surface image, return true if it changed
+ * Called when a trusted remote peer informs us of our external network address
*
- * @param remote Remote address as reflected by any trusted peer
- * @return True if our external surface has changed
+ * @param physicalAddress Physical address as reflected by any trusted peer
*/
- inline bool update(const InetAddress &remote)
- throw()
- {
- const unsigned long idx = (remote.isV4() ? 0 : 2) | (remote.isLinkLocal() ? 1 : 0);
- if (_s[idx] != remote) {
- _s[idx] = remote;
- return true;
- }
- return false;
- }
+ void iam(const InetAddress &physicalAddress);
private:
- InetAddress _s[4]; // global v4, link-local v4, global v6, link-local v6
};
} // namespace ZeroTier
diff --git a/node/Topology.hpp b/node/Topology.hpp
index ca86b2e3..6dee11bc 100644
--- a/node/Topology.hpp
+++ b/node/Topology.hpp
@@ -45,7 +45,6 @@
#include "InetAddress.hpp"
#include "Utils.hpp"
#include "Dictionary.hpp"
-#include "ExternalSurface.hpp"
namespace ZeroTier {
@@ -322,20 +321,6 @@ public:
#endif
/**
- * Update our knowledge of exterior network addresses
- *
- * If the remote peer in question is trusted, this will update our internal
- * instance of ExternalSurface. If our surface has changed, this triggers a
- * partial or total reset of ephemeral peer addresses and a renegotiation of
- * new ones using supernodes / relays.
- *
- * @param remotePeer Remote peer address
- * @param mirroredAddress Real-world network address the remote peer told us we have
- * @param now Current time
- */
- bool updateSurface(const SharedPtr<Peer> &remotePeer,const InetAddress &mirroredAddress,uint64_t now);
-
- /**
* Validate a root topology dictionary against the identities specified in Defaults
*
* @param rt Root topology dictionary
@@ -356,8 +341,6 @@ private:
std::vector< Address > _supernodeAddresses;
std::vector< SharedPtr<Peer> > _supernodePeers;
- ExternalSurface _surface;
-
Mutex _lock;
// Set to true if my identity is in _supernodes