summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog19
-rw-r--r--debian/control4
-rwxr-xr-xext/installfiles/mac/ZeroTier One.pkgproj2
-rw-r--r--include/ZeroTierOne.h33
-rw-r--r--linux-build-farm/debian-jessie/x64/Dockerfile2
-rw-r--r--linux-build-farm/debian-jessie/x86/Dockerfile2
-rw-r--r--linux-build-farm/debian-stretch/x64/Dockerfile2
-rw-r--r--linux-build-farm/debian-stretch/x86/Dockerfile2
-rw-r--r--linux-build-farm/debian-wheezy/x64/Dockerfile2
-rw-r--r--linux-build-farm/debian-wheezy/x86/Dockerfile2
-rw-r--r--linux-build-farm/fedora-22/x64/Dockerfile1
-rw-r--r--linux-build-farm/fedora-22/x86/Dockerfile1
-rwxr-xr-xlinux-build-farm/make-rpm-repos.sh29
-rw-r--r--linux-build-farm/ubuntu-trusty/x64/Dockerfile2
-rw-r--r--linux-build-farm/ubuntu-trusty/x86/Dockerfile2
-rw-r--r--linux-build-farm/ubuntu-wily/x64/Dockerfile2
-rw-r--r--linux-build-farm/ubuntu-wily/x86/Dockerfile2
-rw-r--r--linux-build-farm/ubuntu-xenial/x64/Dockerfile2
-rw-r--r--linux-build-farm/ubuntu-xenial/x86/Dockerfile2
-rw-r--r--node/IncomingPacket.cpp30
-rw-r--r--node/Node.cpp13
-rw-r--r--node/Node.hpp13
-rw-r--r--node/Packet.hpp50
-rw-r--r--node/Switch.cpp7
-rw-r--r--node/Topology.hpp53
-rw-r--r--osdep/ManagedRoute.cpp4
-rw-r--r--osdep/ManagedRoute.hpp4
-rw-r--r--osdep/OSXEthernetTap.cpp4
-rw-r--r--service/ControlPlane.cpp4
-rw-r--r--service/OneService.cpp66
-rw-r--r--version.h2
-rw-r--r--zerotier-one.spec8
32 files changed, 322 insertions, 49 deletions
diff --git a/debian/changelog b/debian/changelog
index c6e9eb90..3b33c1e2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,22 @@
+zerotier-one (1.1.12) unstable; urgency=medium
+
+ * See https://github.com/zerotier/ZeroTierOne for release notes.
+
+ -- Adam Ierymenko <adam.ierymenko@zerotier.com> Tue, 12 Jul 2016 03:02:22 -0700
+
+zerotier-one (1.1.10) unstable; urgency=medium
+
+ * See https://github.com/zerotier/ZeroTierOne for release notes.
+ * ZeroTier Debian packages no longer depend on http-parser since its ABI is too unstable.
+
+ -- Adam Ierymenko <adam.ierymenko@zerotier.com> Tue, 12 Jul 2016 12:29:00 -0700
+
+zerotier-one (1.1.8) unstable; urgency=low
+
+ * See https://github.com/zerotier/ZeroTierOne for release notes.
+
+ -- Adam Ierymenko <adam.ierymenko@zerotier.com> Fri, 08 Jul 2016 01:56:00 -0700
+
zerotier-one (1.1.6) unstable; urgency=medium
* First Debian release on ZeroTier, Inc. private apt repository.
diff --git a/debian/control b/debian/control
index cfe50682..46b8307f 100644
--- a/debian/control
+++ b/debian/control
@@ -3,14 +3,14 @@ Maintainer: Adam Ierymenko <adam.ierymenko@zerotier.com>
Section: net
Priority: optional
Standards-Version: 3.9.6
-Build-Depends: debhelper (>= 9), libhttp-parser-dev (>= 2.1), liblz4-dev, libnatpmp-dev, dh-systemd, ruby-ronn
+Build-Depends: debhelper (>= 9), liblz4-dev, libnatpmp-dev, dh-systemd, ruby-ronn
Vcs-Git: git://github.com/zerotier/ZeroTierOne
Vcs-Browser: https://github.com/zerotier/ZeroTierOne
Homepage: https://www.zerotier.com/
Package: zerotier-one
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, libhttp-parser2.1, liblz4-1, libnatpmp1, iproute2
+Depends: ${shlibs:Depends}, ${misc:Depends}, liblz4-1, libnatpmp1, iproute2
Homepage: https://www.zerotier.com/
Description: ZeroTier network virtualization service
ZeroTier One lets you join ZeroTier virtual networks and
diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj
index e090c574..acbc3cfb 100755
--- a/ext/installfiles/mac/ZeroTier One.pkgproj
+++ b/ext/installfiles/mac/ZeroTier One.pkgproj
@@ -759,7 +759,7 @@
<key>OVERWRITE_PERMISSIONS</key>
<false/>
<key>VERSION</key>
- <string>1.1.6</string>
+ <string>1.1.12</string>
</dict>
<key>PROJECT_COMMENTS</key>
<dict>
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h
index d46c64b8..2d7b007b 100644
--- a/include/ZeroTierOne.h
+++ b/include/ZeroTierOne.h
@@ -117,6 +117,11 @@ extern "C" {
#define ZT_MAX_PEER_NETWORK_PATHS 4
/**
+ * Maximum number of trusted physical network paths
+ */
+#define ZT_MAX_TRUSTED_PATHS 16
+
+/**
* Maximum number of hops in a ZeroTier circuit test
*
* This is more or less the max that can be fit in a given packet (with
@@ -888,6 +893,11 @@ typedef struct
uint64_t lastReceive;
/**
+ * Is this a trusted path? If so this will be its nonzero ID.
+ */
+ uint64_t trustedPathId;
+
+ /**
* Is path active?
*/
int active;
@@ -1838,6 +1848,29 @@ void ZT_Node_clusterHandleIncomingMessage(ZT_Node *node,const void *msg,unsigned
void ZT_Node_clusterStatus(ZT_Node *node,ZT_ClusterStatus *cs);
/**
+ * Set trusted paths
+ *
+ * A trusted path is a physical network (network/bits) over which both
+ * encryption and authentication can be skipped to improve performance.
+ * Each trusted path must have a non-zero unique ID that is the same across
+ * all participating nodes.
+ *
+ * We don't recommend using trusted paths at all unless you really *need*
+ * near-bare-metal performance. Even on a LAN authentication and encryption
+ * are never a bad thing, and anything that introduces an "escape hatch"
+ * for encryption should be treated with the utmost care.
+ *
+ * Calling with NULL pointers for networks and ids and a count of zero clears
+ * all trusted paths.
+ *
+ * @param node Node instance
+ * @param networks Array of [count] networks
+ * @param ids Array of [count] corresponding non-zero path IDs (zero path IDs are ignored)
+ * @param count Number of trusted paths-- values greater than ZT_MAX_TRUSTED_PATHS are clipped
+ */
+void ZT_Node_setTrustedPaths(ZT_Node *node,const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count);
+
+/**
* Do things in the background until Node dies
*
* This function can be called from one or more background threads to process
diff --git a/linux-build-farm/debian-jessie/x64/Dockerfile b/linux-build-farm/debian-jessie/x64/Dockerfile
index 9591eff6..316c1d83 100644
--- a/linux-build-farm/debian-jessie/x64/Dockerfile
+++ b/linux-build-farm/debian-jessie/x64/Dockerfile
@@ -7,4 +7,6 @@ RUN apt-get install -y build-essential debhelper libhttp-parser-dev liblz4-dev l
RUN ln -sf /usr/bin/clang++-3.5 /usr/bin/clang++
RUN ln -sf /usr/bin/clang-3.5 /usr/bin/clang
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
diff --git a/linux-build-farm/debian-jessie/x86/Dockerfile b/linux-build-farm/debian-jessie/x86/Dockerfile
index 9ed826ff..3ad83329 100644
--- a/linux-build-farm/debian-jessie/x86/Dockerfile
+++ b/linux-build-farm/debian-jessie/x86/Dockerfile
@@ -7,4 +7,6 @@ RUN apt-get install -y build-essential debhelper libhttp-parser-dev liblz4-dev l
RUN ln -sf /usr/bin/clang++-3.5 /usr/bin/clang++
RUN ln -sf /usr/bin/clang-3.5 /usr/bin/clang
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
diff --git a/linux-build-farm/debian-stretch/x64/Dockerfile b/linux-build-farm/debian-stretch/x64/Dockerfile
index c5fdc2a1..c973c2b7 100644
--- a/linux-build-farm/debian-stretch/x64/Dockerfile
+++ b/linux-build-farm/debian-stretch/x64/Dockerfile
@@ -7,4 +7,6 @@ RUN apt-get install -y build-essential debhelper libhttp-parser-dev liblz4-dev l
#RUN ln -sf /usr/bin/clang++-3.5 /usr/bin/clang++
#RUN ln -sf /usr/bin/clang-3.5 /usr/bin/clang
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
diff --git a/linux-build-farm/debian-stretch/x86/Dockerfile b/linux-build-farm/debian-stretch/x86/Dockerfile
index 159e83c7..bfc7a86f 100644
--- a/linux-build-farm/debian-stretch/x86/Dockerfile
+++ b/linux-build-farm/debian-stretch/x86/Dockerfile
@@ -7,4 +7,6 @@ RUN apt-get install -y build-essential debhelper libhttp-parser-dev liblz4-dev l
#RUN ln -sf /usr/bin/clang++-3.5 /usr/bin/clang++
#RUN ln -sf /usr/bin/clang-3.5 /usr/bin/clang
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
diff --git a/linux-build-farm/debian-wheezy/x64/Dockerfile b/linux-build-farm/debian-wheezy/x64/Dockerfile
index 5663f1e1..77e1c325 100644
--- a/linux-build-farm/debian-wheezy/x64/Dockerfile
+++ b/linux-build-farm/debian-wheezy/x64/Dockerfile
@@ -4,6 +4,8 @@ MAINTAINER Adam Ierymenko <adam.ierymenko@zerotier.com>
RUN apt-get update
RUN apt-get install -y build-essential debhelper ruby-ronn g++ make devscripts
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
RUN mv -f /ZeroTierOne/debian/control.wheezy /ZeroTierOne/debian/control
diff --git a/linux-build-farm/debian-wheezy/x86/Dockerfile b/linux-build-farm/debian-wheezy/x86/Dockerfile
index 7b7a632a..1f0117d2 100644
--- a/linux-build-farm/debian-wheezy/x86/Dockerfile
+++ b/linux-build-farm/debian-wheezy/x86/Dockerfile
@@ -7,6 +7,8 @@
FROM zerotier/zt1-build-debian-wheezy-x86-base
MAINTAINER Adam Ierymenko <adam.ierymenko@zerotier.com>
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
RUN mv -f /ZeroTierOne/debian/control.wheezy /ZeroTierOne/debian/control
diff --git a/linux-build-farm/fedora-22/x64/Dockerfile b/linux-build-farm/fedora-22/x64/Dockerfile
index 6874355c..6da0a921 100644
--- a/linux-build-farm/fedora-22/x64/Dockerfile
+++ b/linux-build-farm/fedora-22/x64/Dockerfile
@@ -5,5 +5,6 @@ RUN yum update -y
RUN yum install -y make rpmdevtools gcc-c++ rubygem-ronn json-parser-devel lz4-devel http-parser-devel libnatpmp-devel
RUN rpm --erase http-parser-devel
+RUN yum install -y rubygem-ronn ruby
ADD zt1-src.tar.gz /
diff --git a/linux-build-farm/fedora-22/x86/Dockerfile b/linux-build-farm/fedora-22/x86/Dockerfile
index cb264482..3c24b844 100644
--- a/linux-build-farm/fedora-22/x86/Dockerfile
+++ b/linux-build-farm/fedora-22/x86/Dockerfile
@@ -14,5 +14,6 @@ MAINTAINER Adam Ierymenko <adam.ierymenko@zerotier.com>
RUN echo 'i686-redhat-linux' >/etc/rpm/platform
RUN rpm --erase http-parser-devel
+RUN yum install -y rubygem-ronn ruby
ADD zt1-src.tar.gz /
diff --git a/linux-build-farm/make-rpm-repos.sh b/linux-build-farm/make-rpm-repos.sh
index d669501b..0ed1cfe4 100755
--- a/linux-build-farm/make-rpm-repos.sh
+++ b/linux-build-farm/make-rpm-repos.sh
@@ -31,5 +31,34 @@ for db in `find /tmp/zt-rpm-repo -mindepth 2 -maxdepth 2 -type d`; do
createrepo --database $db
done
+# Stupid RHEL stuff
+cd /tmp/zt-rpm-repo/el
+ln -sf 6 6Client
+ln -sf 6 6Workstation
+ln -sf 6 6Server
+ln -sf 6 6.0
+ln -sf 6 6.1
+ln -sf 6 6.2
+ln -sf 6 6.3
+ln -sf 6 6.4
+ln -sf 6 6.5
+ln -sf 6 6.6
+ln -sf 6 6.7
+ln -sf 6 6.8
+ln -sf 6 6.9
+ln -sf 7 7Client
+ln -sf 7 7Workstation
+ln -sf 7 7Server
+ln -sf 7 7.0
+ln -sf 7 7.1
+ln -sf 7 7.2
+ln -sf 7 7.3
+ln -sf 7 7.4
+ln -sf 7 7.5
+ln -sf 7 7.6
+ln -sf 7 7.7
+ln -sf 7 7.8
+ln -sf 7 7.9
+
echo
echo Repo created in /tmp/zt-rpm-repo
diff --git a/linux-build-farm/ubuntu-trusty/x64/Dockerfile b/linux-build-farm/ubuntu-trusty/x64/Dockerfile
index 6ec65d2f..f84cc6e3 100644
--- a/linux-build-farm/ubuntu-trusty/x64/Dockerfile
+++ b/linux-build-farm/ubuntu-trusty/x64/Dockerfile
@@ -7,4 +7,6 @@ RUN apt-get install -y build-essential debhelper libhttp-parser-dev liblz4-dev l
RUN ln -sf /usr/bin/clang++-3.6 /usr/bin/clang++
RUN ln -sf /usr/bin/clang-3.6 /usr/bin/clang
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
diff --git a/linux-build-farm/ubuntu-trusty/x86/Dockerfile b/linux-build-farm/ubuntu-trusty/x86/Dockerfile
index 271c19bb..6be3ae87 100644
--- a/linux-build-farm/ubuntu-trusty/x86/Dockerfile
+++ b/linux-build-farm/ubuntu-trusty/x86/Dockerfile
@@ -7,4 +7,6 @@ RUN apt-get install -y build-essential debhelper libhttp-parser-dev liblz4-dev l
RUN ln -sf /usr/bin/clang++-3.6 /usr/bin/clang++
RUN ln -sf /usr/bin/clang-3.6 /usr/bin/clang
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
diff --git a/linux-build-farm/ubuntu-wily/x64/Dockerfile b/linux-build-farm/ubuntu-wily/x64/Dockerfile
index f56344cf..99b8d34c 100644
--- a/linux-build-farm/ubuntu-wily/x64/Dockerfile
+++ b/linux-build-farm/ubuntu-wily/x64/Dockerfile
@@ -7,4 +7,6 @@ RUN apt-get install -y build-essential debhelper libhttp-parser-dev liblz4-dev l
RUN ln -sf /usr/bin/clang++-3.7 /usr/bin/clang++
RUN ln -sf /usr/bin/clang-3.7 /usr/bin/clang
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
diff --git a/linux-build-farm/ubuntu-wily/x86/Dockerfile b/linux-build-farm/ubuntu-wily/x86/Dockerfile
index 24bb1116..86ad14f2 100644
--- a/linux-build-farm/ubuntu-wily/x86/Dockerfile
+++ b/linux-build-farm/ubuntu-wily/x86/Dockerfile
@@ -7,4 +7,6 @@ RUN apt-get install -y build-essential debhelper libhttp-parser-dev liblz4-dev l
RUN ln -sf /usr/bin/clang++-3.7 /usr/bin/clang++
RUN ln -sf /usr/bin/clang-3.7 /usr/bin/clang
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
diff --git a/linux-build-farm/ubuntu-xenial/x64/Dockerfile b/linux-build-farm/ubuntu-xenial/x64/Dockerfile
index 03a65c55..fa665a0a 100644
--- a/linux-build-farm/ubuntu-xenial/x64/Dockerfile
+++ b/linux-build-farm/ubuntu-xenial/x64/Dockerfile
@@ -9,4 +9,6 @@ RUN apt-get install -y build-essential debhelper libhttp-parser-dev liblz4-dev l
RUN rm -f /usr/bin/clang++ /usr/bin/clang
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
diff --git a/linux-build-farm/ubuntu-xenial/x86/Dockerfile b/linux-build-farm/ubuntu-xenial/x86/Dockerfile
index 3d04a57d..d01eec9b 100644
--- a/linux-build-farm/ubuntu-xenial/x86/Dockerfile
+++ b/linux-build-farm/ubuntu-xenial/x86/Dockerfile
@@ -9,4 +9,6 @@ RUN apt-get install -y build-essential debhelper libhttp-parser-dev liblz4-dev l
RUN rm -f /usr/bin/clang++ /usr/bin/clang
+RUN dpkg --purge libhttp-parser-dev
+
ADD zt1-src.tar.gz /
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index 871297f7..231f0d06 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -42,9 +42,24 @@ namespace ZeroTier {
bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,bool deferred)
{
- const Address sourceAddress(source());
try {
- if ((cipher() == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)&&(verb() == Packet::VERB_HELLO)) {
+ const Address sourceAddress(source());
+
+ // Check for trusted paths or unencrypted HELLOs (HELLO is the only packet sent in the clear)
+ const unsigned int c = cipher();
+ bool trusted = false;
+ if (c == ZT_PROTO_CIPHER_SUITE__NO_CRYPTO_TRUSTED_PATH) {
+ // If this is marked as a packet via a trusted path, check source address and path ID.
+ // Obviously if no trusted paths are configured this always returns false and such
+ // packets are dropped on the floor.
+ if (RR->topology->shouldInboundPathBeTrusted(_remoteAddress,trustedPathId())) {
+ trusted = true;
+ TRACE("TRUSTED PATH packet approved from %s(%s), trusted path ID %llx",sourceAddress.toString().c_str(),_remoteAddress.toString().c_str(),trustedPathId());
+ } else {
+ TRACE("dropped packet from %s(%s), cipher set to trusted path mode but path %llx@%s is not trusted!",sourceAddress.toString().c_str(),_remoteAddress.toString().c_str(),trustedPathId(),_remoteAddress.toString().c_str());
+ return true;
+ }
+ } else if ((c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)&&(verb() == Packet::VERB_HELLO)) {
// Unencrypted HELLOs require some potentially expensive verification, so
// do this in the background if background processing is enabled.
if ((RR->dpEnabled > 0)&&(!deferred)) {
@@ -61,12 +76,15 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,bool deferred)
SharedPtr<Peer> peer(RR->topology->getPeer(sourceAddress));
if (peer) {
- if (!dearmor(peer->key())) {
- TRACE("dropped packet from %s(%s), MAC authentication failed (size: %u)",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),size());
- return true;
+ if (!trusted) {
+ if (!dearmor(peer->key())) {
+ TRACE("dropped packet from %s(%s), MAC authentication failed (size: %u)",sourceAddress.toString().c_str(),_remoteAddress.toString().c_str(),size());
+ return true;
+ }
}
+
if (!uncompress()) {
- TRACE("dropped packet from %s(%s), compressed data invalid",peer->address().toString().c_str(),_remoteAddress.toString().c_str());
+ TRACE("dropped packet from %s(%s), compressed data invalid",sourceAddress.toString().c_str(),_remoteAddress.toString().c_str());
return true;
}
diff --git a/node/Node.cpp b/node/Node.cpp
index bedbba94..13085028 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -447,6 +447,7 @@ ZT_PeerList *Node::peers() const
p->paths[p->pathCount].lastReceive = path->lastReceived();
p->paths[p->pathCount].active = path->active(_now) ? 1 : 0;
p->paths[p->pathCount].preferred = ((bestPath)&&(*path == *bestPath)) ? 1 : 0;
+ p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust(path->address());
++p->pathCount;
}
}
@@ -745,6 +746,11 @@ void Node::postCircuitTestReport(const ZT_CircuitTestReport *report)
(reinterpret_cast<void (*)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *)>((*i)->_internalPtr))(reinterpret_cast<ZT_Node *>(this),*i,report);
}
+void Node::setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count)
+{
+ RR->topology->setTrustedPaths(reinterpret_cast<const InetAddress *>(networks),ids,count);
+}
+
} // namespace ZeroTier
/****************************************************************************/
@@ -1014,6 +1020,13 @@ void ZT_Node_clusterStatus(ZT_Node *node,ZT_ClusterStatus *cs)
} catch ( ... ) {}
}
+void ZT_Node_setTrustedPaths(ZT_Node *node,const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count)
+{
+ try {
+ reinterpret_cast<ZeroTier::Node *>(node)->setTrustedPaths(networks,ids,count);
+ } catch ( ... ) {}
+}
+
void ZT_Node_backgroundThreadMain(ZT_Node *node)
{
try {
diff --git a/node/Node.hpp b/node/Node.hpp
index 6ac23ca0..0a39d1ee 100644
--- a/node/Node.hpp
+++ b/node/Node.hpp
@@ -248,26 +248,15 @@ public:
*/
inline int configureVirtualNetworkPort(uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,nwid,nuptr,op,nc); }
- /**
- * @return True if we appear to be online
- */
inline bool online() const throw() { return _online; }
#ifdef ZT_TRACE
void postTrace(const char *module,unsigned int line,const char *fmt,...);
#endif
- /**
- * @return Next 64-bit random number (not for cryptographic use)
- */
uint64_t prng();
-
- /**
- * Post a circuit test report to any listeners for a given test ID
- *
- * @param report Report (includes test ID)
- */
void postCircuitTestReport(const ZT_CircuitTestReport *report);
+ void setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count);
private:
inline SharedPtr<Network> _network(uint64_t nwid) const
diff --git a/node/Packet.hpp b/node/Packet.hpp
index 79fff344..3d95b0ba 100644
--- a/node/Packet.hpp
+++ b/node/Packet.hpp
@@ -57,11 +57,13 @@
* + Supports in-band world (root server definition) updates
* + Clustering! (Though this will work with protocol v4 clients.)
* + Otherwise backward compatible with protocol v4
- * 6 - 1.1.5 ... CURRENT
+ * 6 - 1.1.5 ... 1.1.10
* + Deprecate old dictionary-based network config format
* + Introduce new binary serialized network config and meta-data
+ * 7 - 1.1.10 -- CURRENT
+ * + Introduce trusted paths for local SDN use
*/
-#define ZT_PROTO_VERSION 6
+#define ZT_PROTO_VERSION 7
/**
* Minimum supported protocol version
@@ -100,10 +102,21 @@
#define ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012 1
/**
- * DEPRECATED payload encrypted flag, will be removed for re-use soon.
+ * Cipher suite: NONE
*
- * This has been replaced by the three-bit cipher suite selection field where
- * a value of 0 indicates unencrypted (but authenticated) messages.
+ * This differs from POLY1305/NONE in that *no* crypto is done, not even
+ * authentication. This is for trusted local LAN interconnects for internal
+ * SDN use within a data center.
+ *
+ * For this mode the MAC field becomes a trusted path ID and must match the
+ * configured ID of a trusted path or the packet is discarded.
+ */
+#define ZT_PROTO_CIPHER_SUITE__NO_CRYPTO_TRUSTED_PATH 2
+
+/**
+ * DEPRECATED payload encrypted flag, may be re-used in the future.
+ *
+ * This has been replaced by the three-bit cipher suite selection field.
*/
#define ZT_PROTO_FLAG_ENCRYPTED 0x80
@@ -337,7 +350,7 @@ namespace ZeroTier {
* <[5] destination ZT address>
* <[5] source ZT address>
* <[1] flags/cipher/hops>
- * <[8] 64-bit MAC>
+ * <[8] 64-bit MAC (or trusted path ID in trusted path mode)>
* [... -- begin encryption envelope -- ...]
* <[1] encrypted flags (MS 3 bits) and verb (LS 5 bits)>
* [... verb-specific payload ...]
@@ -1218,7 +1231,6 @@ public:
*/
inline unsigned int cipher() const
{
- // Note: this uses the new cipher spec field, which is incompatible with <1.0.0 peers
return (((unsigned int)(*this)[ZT_PACKET_IDX_FLAGS] & 0x38) >> 3);
}
@@ -1229,13 +1241,31 @@ public:
{
unsigned char &b = (*this)[ZT_PACKET_IDX_FLAGS];
b = (b & 0xc7) | (unsigned char)((c << 3) & 0x38); // bits: FFCCCHHH
- // DEPRECATED "encrypted" flag -- used by pre-1.0.3 peers
+ // Set DEPRECATED "encrypted" flag -- used by pre-1.0.3 peers
if (c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)
b |= ZT_PROTO_FLAG_ENCRYPTED;
else b &= (~ZT_PROTO_FLAG_ENCRYPTED);
}
/**
+ * Get the trusted path ID for this packet (only meaningful if cipher is trusted path)
+ *
+ * @return Trusted path ID (from MAC field)
+ */
+ inline uint64_t trustedPathId() const { return at<uint64_t>(ZT_PACKET_IDX_MAC); }
+
+ /**
+ * Set this packet's trusted path ID and set the cipher spec to trusted path
+ *
+ * @param tpid Trusted path ID
+ */
+ inline void setTrusted(const uint64_t tpid)
+ {
+ setCipher(ZT_PROTO_CIPHER_SUITE__NO_CRYPTO_TRUSTED_PATH);
+ setAt(ZT_PACKET_IDX_MAC,tpid);
+ }
+
+ /**
* Get this packet's unique ID (the IV field interpreted as uint64_t)
*
* @return Packet ID
@@ -1278,6 +1308,10 @@ public:
/**
* Verify and (if encrypted) decrypt packet
*
+ * This does not handle trusted path mode packets and will return false
+ * for these. These are handled in IncomingPacket if the sending physical
+ * address and MAC field match a trusted path.
+ *
* @param key 32-byte key
* @return False if packet is invalid or failed MAC authenticity check
*/
diff --git a/node/Switch.cpp b/node/Switch.cpp
index b134cc69..bf3afe33 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -849,7 +849,12 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid)
unsigned int chunkSize = std::min(tmp.size(),(unsigned int)ZT_UDP_DEFAULT_PAYLOAD_MTU);
tmp.setFragmented(chunkSize < tmp.size());
- tmp.armor(peer->key(),encrypt);
+ const uint64_t trustedPathId = RR->topology->getOutboundPathTrust(viaPath->address());
+ if (trustedPathId) {
+ tmp.setTrusted(trustedPathId);
+ } else {
+ tmp.armor(peer->key(),encrypt);
+ }
if (viaPath->send(RR,tmp.data(),chunkSize,now)) {
if (chunkSize < tmp.size()) {
diff --git a/node/Topology.hpp b/node/Topology.hpp
index 86fbb011..03c491e5 100644
--- a/node/Topology.hpp
+++ b/node/Topology.hpp
@@ -28,6 +28,7 @@
#include <utility>
#include "Constants.hpp"
+#include "../include/ZeroTierOne.h"
#include "Address.hpp"
#include "Identity.hpp"
@@ -252,12 +253,64 @@ public:
*/
inline bool amRoot() const throw() { return _amRoot; }
+ /**
+ * Get the outbound trusted path ID for a physical address, or 0 if none
+ *
+ * @param physicalAddress Physical address to which we are sending the packet
+ * @return Trusted path ID or 0 if none (0 is not a valid trusted path ID)
+ */
+ inline uint64_t getOutboundPathTrust(const InetAddress &physicalAddress)
+ {
+ for(unsigned int i=0;i<_trustedPathCount;++i) {
+ if (_trustedPathNetworks[i].containsAddress(physicalAddress))
+ return _trustedPathIds[i];
+ }
+ return 0;
+ }
+
+ /**
+ * Check whether in incoming trusted path marked packet is valid
+ *
+ * @param physicalAddress Originating physical address
+ * @param trustedPathId Trusted path ID from packet (from MAC field)
+ */
+ inline bool shouldInboundPathBeTrusted(const InetAddress &physicalAddress,const uint64_t trustedPathId)
+ {
+ for(unsigned int i=0;i<_trustedPathCount;++i) {
+ if ((_trustedPathIds[i] == trustedPathId)&&(_trustedPathNetworks[i].containsAddress(physicalAddress)))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set trusted paths in this topology
+ *
+ * @param networks Array of networks (prefix/netmask bits)
+ * @param ids Array of trusted path IDs
+ * @param count Number of trusted paths (if larger than ZT_MAX_TRUSTED_PATHS overflow is ignored)
+ */
+ inline void setTrustedPaths(const InetAddress *networks,const uint64_t *ids,unsigned int count)
+ {
+ if (count > ZT_MAX_TRUSTED_PATHS)
+ count = ZT_MAX_TRUSTED_PATHS;
+ Mutex::Lock _l(_lock);
+ for(unsigned int i=0;i<count;++i) {
+ _trustedPathIds[i] = ids[i];
+ _trustedPathNetworks[i] = networks[i];
+ }
+ _trustedPathCount = count;
+ }
+
private:
Identity _getIdentity(const Address &zta);
void _setWorld(const World &newWorld);
const RuntimeEnvironment *const RR;
+ uint64_t _trustedPathIds[ZT_MAX_TRUSTED_PATHS];
+ InetAddress _trustedPathNetworks[ZT_MAX_TRUSTED_PATHS];
+ unsigned int _trustedPathCount;
World _world;
Hashtable< Address,SharedPtr<Peer> > _peers;
std::vector< Address > _rootAddresses;
diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp
index 54990122..ae2f8943 100644
--- a/osdep/ManagedRoute.cpp
+++ b/osdep/ManagedRoute.cpp
@@ -57,6 +57,8 @@
#define ZT_LINUX_IP_COMMAND "/sbin/ip"
#define ZT_LINUX_IP_COMMAND_2 "/usr/sbin/ip"
+// NOTE: BSD is mostly tested on Apple/Mac but is likely to work on other BSD too
+
namespace ZeroTier {
namespace {
@@ -413,7 +415,7 @@ bool ManagedRoute::sync()
// Shadow system route if it exists, also delete any obsolete shadows
// and replace them with the new state. sync() is called periodically to
// allow us to do that if underlying connectivity changes.
- if ((_systemVia != newSystemVia)||(!strcmp(_systemDevice,newSystemDevice))) {
+ if ( ((_systemVia != newSystemVia)||(strcmp(_systemDevice,newSystemDevice))) && (strcmp(_device,newSystemDevice)) ) {
if ((_systemVia)&&(_systemDevice[0])) {
_routeCmd("delete",leftt,_systemVia,_systemDevice,(const char *)0);
_routeCmd("delete",rightt,_systemVia,_systemDevice,(const char *)0);
diff --git a/osdep/ManagedRoute.hpp b/osdep/ManagedRoute.hpp
index 5dde12ad..63310f24 100644
--- a/osdep/ManagedRoute.hpp
+++ b/osdep/ManagedRoute.hpp
@@ -54,8 +54,8 @@ public:
* "device name."
*
* @param target Route target (e.g. 0.0.0.0/0 for default)
- * @param via Route next L3 hop or NULL InetAddress if local
- * @param device Device name/ID if 'via' is null and route is local, otherwise ignored
+ * @param via Route next L3 hop or NULL InetAddress if local in which case it will be routed via device
+ * @param device Name or hex LUID of ZeroTier device (e.g. zt#)
* @return True if route was successfully set
*/
inline bool set(const InetAddress &target,const InetAddress &via,const char *device)
diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp
index e8c5c1ea..56934c96 100644
--- a/osdep/OSXEthernetTap.cpp
+++ b/osdep/OSXEthernetTap.cpp
@@ -474,7 +474,7 @@ bool OSXEthernetTap::addIp(const InetAddress &ip)
long cpid = (long)vfork();
if (cpid == 0) {
- ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0);
+ ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toString().c_str(),"alias",(const char *)0);
::_exit(-1);
} else if (cpid > 0) {
int exitcode = -1;
@@ -494,7 +494,7 @@ bool OSXEthernetTap::removeIp(const InetAddress &ip)
if (*i == ip) {
long cpid = (long)vfork();
if (cpid == 0) {
- execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"inet",ip.toIpString().c_str(),"-alias",(const char *)0);
+ execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toIpString().c_str(),"-alias",(const char *)0);
_exit(-1);
} else if (cpid > 0) {
int exitcode = -1;
diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp
index 0e2b530d..a10697a9 100644
--- a/service/ControlPlane.cpp
+++ b/service/ControlPlane.cpp
@@ -190,13 +190,15 @@ static std::string _jsonEnumerate(unsigned int depth,const ZT_PeerPhysicalPath *
"%s\t\"lastSend\": %llu,\n"
"%s\t\"lastReceive\": %llu,\n"
"%s\t\"active\": %s,\n"
- "%s\t\"preferred\": %s\n"
+ "%s\t\"preferred\": %s,\n"
+ "%s\t\"trustedPathId\": %llu\n"
"%s}",
prefix,_jsonEscape(reinterpret_cast<const InetAddress *>(&(pp[i].address))->toString()).c_str(),
prefix,pp[i].lastSend,
prefix,pp[i].lastReceive,
prefix,(pp[i].active == 0) ? "false" : "true",
prefix,(pp[i].preferred == 0) ? "false" : "true",
+ prefix,pp[i].trustedPathId,
prefix);
buf.append(json);
}
diff --git a/service/OneService.cpp b/service/OneService.cpp
index c1b24050..13820f5c 100644
--- a/service/OneService.cpp
+++ b/service/OneService.cpp
@@ -759,6 +759,38 @@ public:
for(int i=0;i<3;++i)
_portsBE[i] = Utils::hton((uint16_t)_ports[i]);
+ {
+ FILE *trustpaths = fopen((_homePath + ZT_PATH_SEPARATOR_S + "trustedpaths").c_str(),"r");
+ uint64_t ids[ZT_MAX_TRUSTED_PATHS];
+ InetAddress addresses[ZT_MAX_TRUSTED_PATHS];
+ if (trustpaths) {
+ char buf[1024];
+ unsigned int count = 0;
+ while ((fgets(buf,sizeof(buf),trustpaths))&&(count < ZT_MAX_TRUSTED_PATHS)) {
+ int fno = 0;
+ char *saveptr = (char *)0;
+ uint64_t trustedPathId = 0;
+ InetAddress trustedPathNetwork;
+ for(char *f=Utils::stok(buf,"=\r\n \t",&saveptr);(f);f=Utils::stok((char *)0,"=\r\n \t",&saveptr)) {
+ if (fno == 0) {
+ trustedPathId = Utils::hexStrToU64(f);
+ } else if (fno == 1) {
+ trustedPathNetwork = InetAddress(f);
+ } else break;
+ ++fno;
+ }
+ if ( (trustedPathId != 0) && ((trustedPathNetwork.ss_family == AF_INET)||(trustedPathNetwork.ss_family == AF_INET6)) && (trustedPathNetwork.ipScope() != InetAddress::IP_SCOPE_GLOBAL) && (trustedPathNetwork.netmaskBits() > 0) ) {
+ ids[count] = trustedPathId;
+ addresses[count] = trustedPathNetwork;
+ ++count;
+ }
+ }
+ fclose(trustpaths);
+ if (count)
+ _node->setTrustedPaths(reinterpret_cast<const struct sockaddr_storage *>(addresses),ids,count);
+ }
+ }
+
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
_controller = new SqliteNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str(),(_homePath + ZT_PATH_SEPARATOR_S + "circuitTestResults.d").c_str());
_node->setNetconfMaster((void *)_controller);
@@ -1041,13 +1073,13 @@ public:
// Begin private implementation methods
// Checks if a managed IP or route target is allowed
- bool checkIfManagedIsAllowed(const NetworkState &n,const InetAddress &addr)
+ bool checkIfManagedIsAllowed(const NetworkState &n,const InetAddress &target)
{
if (!n.settings.allowManaged)
return false;
- if (addr.isDefaultRoute())
+ if (target.isDefaultRoute())
return n.settings.allowDefault;
- switch(addr.ipScope()) {
+ switch(target.ipScope()) {
case InetAddress::IP_SCOPE_NONE:
case InetAddress::IP_SCOPE_MULTICAST:
case InetAddress::IP_SCOPE_LOOPBACK:
@@ -1060,6 +1092,16 @@ public:
}
}
+ // Match only an IP from a vector of IPs -- used in syncManagedStuff()
+ bool matchIpOnly(const std::vector<InetAddress> &ips,const InetAddress &ip) const
+ {
+ for(std::vector<InetAddress>::const_iterator i(ips.begin());i!=ips.end();++i) {
+ if (i->ipsEqual(ip))
+ return true;
+ }
+ return false;
+ }
+
// Apply or update managed IPs for a configured network (be sure n.tap exists)
void syncManagedStuff(NetworkState &n,bool syncIps,bool syncRoutes)
{
@@ -1075,18 +1117,18 @@ public:
std::sort(newManagedIps.begin(),newManagedIps.end());
newManagedIps.erase(std::unique(newManagedIps.begin(),newManagedIps.end()),newManagedIps.end());
- for(std::vector<InetAddress>::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) {
- if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) {
- if (!n.tap->addIp(*ip))
- fprintf(stderr,"ERROR: unable to add ip address %s"ZT_EOL_S, ip->toString().c_str());
- }
- }
for(std::vector<InetAddress>::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) {
if (std::find(newManagedIps.begin(),newManagedIps.end(),*ip) == newManagedIps.end()) {
if (!n.tap->removeIp(*ip))
fprintf(stderr,"ERROR: unable to remove ip address %s"ZT_EOL_S, ip->toString().c_str());
}
}
+ for(std::vector<InetAddress>::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) {
+ if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) {
+ if (!n.tap->addIp(*ip))
+ fprintf(stderr,"ERROR: unable to add ip address %s"ZT_EOL_S, ip->toString().c_str());
+ }
+ }
n.managedIps.swap(newManagedIps);
}
@@ -1099,10 +1141,12 @@ public:
Utils::scopy(tapdev,sizeof(tapdev),n.tap->deviceName().c_str());
#endif
+ std::vector<InetAddress> myIps(n.tap->ips());
+
// Nuke applied routes that are no longer in n.config.routes[] and/or are not allowed
for(std::list<ManagedRoute>::iterator mr(n.managedRoutes.begin());mr!=n.managedRoutes.end();) {
bool haveRoute = false;
- if (checkIfManagedIsAllowed(n,mr->target())) {
+ if ( (checkIfManagedIsAllowed(n,mr->target())) && ((mr->via().ss_family != mr->target().ss_family)||(!matchIpOnly(myIps,mr->via()))) ) {
for(unsigned int i=0;i<n.config.routeCount;++i) {
const InetAddress *const target = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].target));
const InetAddress *const via = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].via));
@@ -1124,7 +1168,7 @@ public:
const InetAddress *const target = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].target));
const InetAddress *const via = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].via));
- if (!checkIfManagedIsAllowed(n,*target))
+ if ( (!checkIfManagedIsAllowed(n,*target)) || ((via->ss_family == target->ss_family)&&(matchIpOnly(myIps,*via))) )
continue;
bool haveRoute = false;
diff --git a/version.h b/version.h
index 012660dd..9ef01d6d 100644
--- a/version.h
+++ b/version.h
@@ -32,6 +32,6 @@
/**
* Revision
*/
-#define ZEROTIER_ONE_VERSION_REVISION 8
+#define ZEROTIER_ONE_VERSION_REVISION 12
#endif
diff --git a/zerotier-one.spec b/zerotier-one.spec
index beda4cca..36856bd4 100644
--- a/zerotier-one.spec
+++ b/zerotier-one.spec
@@ -1,5 +1,5 @@
Name: zerotier-one
-Version: 1.1.6
+Version: 1.1.12
Release: 0.1%{?dist}
Summary: ZeroTier One network virtualization service
@@ -149,6 +149,12 @@ esac
%endif
%changelog
+* Tue Jul 12 2016 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.1.10-0.1
+- see https://github.com/zerotier/ZeroTierOne for release notes
+
+* Fri Jul 08 2016 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.1.8-0.1
+- see https://github.com/zerotier/ZeroTierOne for release notes
+
* Sat Jun 25 2016 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.1.6-0.1
- now builds on CentOS 6 as well as newer distros, and some cleanup