mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 09:01:08 +00:00
.
This commit is contained in:
parent
5e3c633f74
commit
cf831d9cd3
@ -428,7 +428,7 @@ public:
|
|||||||
ZT_ALWAYS_INLINE bool operator<=(const Identity &id) const { return !(id < *this); }
|
ZT_ALWAYS_INLINE bool operator<=(const Identity &id) const { return !(id < *this); }
|
||||||
ZT_ALWAYS_INLINE bool operator>=(const Identity &id) const { return !(*this < id); }
|
ZT_ALWAYS_INLINE bool operator>=(const Identity &id) const { return !(*this < id); }
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE unsigned long hashCode() const { return (unsigned long)_address.toInt(); }
|
ZT_ALWAYS_INLINE unsigned long hashCode() const { return ((unsigned long)(_address.toInt() << 8) + (unsigned long)_pub.c25519[0] + (unsigned long)_pub.c25519[1] + (unsigned long)_pub.c25519[2]); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Address _address;
|
Address _address;
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
* 11 - 2.0.0 ... CURRENT
|
* 11 - 2.0.0 ... CURRENT
|
||||||
* + Peer-to-peer multicast replication (optional)
|
* + Peer-to-peer multicast replication (optional)
|
||||||
* + Old planet/moon stuff is DEAD!
|
* + Old planet/moon stuff is DEAD!
|
||||||
* + AES256-GCM encryption is now the default
|
* + AES-256-GMAC-CTR encryption is now the default
|
||||||
* + NIST P-384 (type 1) identities now supported
|
* + NIST P-384 (type 1) identities now supported
|
||||||
* + Minimum proto version is now 8 (1.1.17 and newer)
|
* + Minimum proto version is now 8 (1.1.17 and newer)
|
||||||
* + WILL_RELAY allows mesh-like operation
|
* + WILL_RELAY allows mesh-like operation
|
||||||
@ -105,9 +105,9 @@
|
|||||||
#define ZT_PROTO_CIPHER_SUITE__NO_CRYPTO_TRUSTED_PATH 2
|
#define ZT_PROTO_CIPHER_SUITE__NO_CRYPTO_TRUSTED_PATH 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AES256/GCM
|
* AES-256-GMAC-CTR
|
||||||
*/
|
*/
|
||||||
#define ZT_PROTO_CIPHER_SUITE__AES256_GCM 3
|
#define ZT_PROTO_CIPHER_SUITE__AES256_GMAC_CTR 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Header flag indicating that a packet is fragmented
|
* Header flag indicating that a packet is fragmented
|
||||||
@ -395,9 +395,9 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Increment this packet's hop count
|
* Increment this packet's hop count
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE void incrementHops()
|
ZT_ALWAYS_INLINE unsigned int incrementHops()
|
||||||
{
|
{
|
||||||
(*this)[ZT_PACKET_FRAGMENT_IDX_HOPS] = (((*this)[ZT_PACKET_FRAGMENT_IDX_HOPS]) + 1) & ZT_PROTO_MAX_HOPS;
|
return (unsigned int)((*this)[ZT_PACKET_FRAGMENT_IDX_HOPS] = (((*this)[ZT_PACKET_FRAGMENT_IDX_HOPS]) + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1112,10 +1112,12 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Increment this packet's hop count
|
* Increment this packet's hop count
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE void incrementHops()
|
ZT_ALWAYS_INLINE unsigned char incrementHops()
|
||||||
{
|
{
|
||||||
unsigned char &b = (*this)[ZT_PACKET_IDX_FLAGS];
|
unsigned char &b = (*this)[ZT_PACKET_IDX_FLAGS];
|
||||||
b = (b & 0xf8) | ((b + 1) & 0x07);
|
const unsigned char h = (b + 1) & 0x07;
|
||||||
|
b = (b & 0xf8) | h;
|
||||||
|
return (unsigned int)h;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
3
root/Makefile
Normal file
3
root/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
all:
|
||||||
|
rm -f zerotier-root
|
||||||
|
c++ -std=c++11 -O3 -maes -mpclmul -msse -msse2 -msse3 -msse4.1 -pthread -o zerotier-root root.cpp ../node/*.cpp ../osdep/OSUtils.cpp -lresolv
|
152
root/root.cpp
152
root/root.cpp
@ -51,38 +51,174 @@
|
|||||||
#include "../node/Identity.hpp"
|
#include "../node/Identity.hpp"
|
||||||
#include "../node/InetAddress.hpp"
|
#include "../node/InetAddress.hpp"
|
||||||
#include "../node/Mutex.hpp"
|
#include "../node/Mutex.hpp"
|
||||||
|
#include "../node/SharedPtr.hpp"
|
||||||
#include "../osdep/OSUtils.hpp"
|
#include "../osdep/OSUtils.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
using namespace ZeroTier;
|
using namespace ZeroTier;
|
||||||
|
|
||||||
struct PeerInfo
|
struct PeerInfo
|
||||||
{
|
{
|
||||||
InetAddress address;
|
Identity id;
|
||||||
|
uint8_t key[32];
|
||||||
|
InetAddress ip4,ip6;
|
||||||
int64_t lastReceive;
|
int64_t lastReceive;
|
||||||
|
AtomicCounter __refCount;
|
||||||
|
|
||||||
|
ZT_ALWAYS_INLINE ~PeerInfo() { Utils::burn(key,sizeof(key)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IdentityHasher { ZT_ALWAYS_INLINE std::size_t operator()(const Identity &id) const { return (std::size_t)id.hashCode(); } };
|
||||||
struct AddressHasher { ZT_ALWAYS_INLINE std::size_t operator()(const Address &a) const { return (std::size_t)a.toInt(); } };
|
struct AddressHasher { ZT_ALWAYS_INLINE std::size_t operator()(const Address &a) const { return (std::size_t)a.toInt(); } };
|
||||||
struct InetAddressHasher { ZT_ALWAYS_INLINE std::size_t operator()(const InetAddress &ip) const { return (std::size_t)ip.hashCode(); } };
|
struct InetAddressHasher { ZT_ALWAYS_INLINE std::size_t operator()(const InetAddress &ip) const { return (std::size_t)ip.hashCode(); } };
|
||||||
|
|
||||||
|
static Identity self;
|
||||||
static std::atomic_bool run;
|
static std::atomic_bool run;
|
||||||
static std::unordered_map< Address,std::map< Identity,PeerInfo >,AddressHasher > peersByVirtAddr;
|
static std::unordered_map< Identity,SharedPtr<PeerInfo>,IdentityHasher > peersByIdentity;
|
||||||
static std::unordered_map< InetAddress,std::map< Identity,PeerInfo >,InetAddressHasher > peersByPhysAddr;
|
static std::unordered_map< Address,std::set< SharedPtr<PeerInfo> >,AddressHasher > peersByVirtAddr;
|
||||||
static Mutex peersByVirtAddr_l;
|
static std::unordered_map< InetAddress,std::set< SharedPtr<PeerInfo> >,InetAddressHasher > peersByPhysAddr;
|
||||||
static Mutex peersByAddress_l;
|
static std::mutex peersByIdentity_l;
|
||||||
|
static std::mutex peersByVirtAddr_l;
|
||||||
|
static std::mutex peersByPhysAddr_l;
|
||||||
|
|
||||||
static void handlePacket(const InetAddress *const ip,const Packet *const pkt)
|
static void handlePacket(const InetAddress *const ip,const Packet *const inpkt)
|
||||||
{
|
{
|
||||||
char stmp[128];
|
Packet pkt(*inpkt);
|
||||||
printf("%s\n",ip->toString(stmp));
|
char ipstr[128],ipstr2[128],astr[32];
|
||||||
|
const bool fragment = pkt[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] == ZT_PACKET_FRAGMENT_INDICATOR;
|
||||||
|
|
||||||
|
// See if this is destined for us and isn't a fragment / fragmented. (No packets
|
||||||
|
// understood by the root are fragments/fragmented.)
|
||||||
|
if ((!fragment)&&(!pkt.fragmented())&&(pkt.destination() == self.address())) {
|
||||||
|
SharedPtr<PeerInfo> peer;
|
||||||
|
|
||||||
|
// If this is an un-encrypted HELLO, either learn a new peer or verify
|
||||||
|
// that this is a peer we already know.
|
||||||
|
if ((pkt.cipher() == ZT_PROTO_CIPHER_SUITE__POLY1305_NONE)&&(pkt.verb() == Packet::VERB_HELLO)) {
|
||||||
|
Identity id;
|
||||||
|
if (id.deserialize(pkt,ZT_PROTO_VERB_HELLO_IDX_IDENTITY)) {
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> pbi_l(peersByIdentity_l);
|
||||||
|
auto pById = peersByIdentity.find(id);
|
||||||
|
if (pById != peersByIdentity.end()) {
|
||||||
|
peer = pById->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (peer) {
|
||||||
|
if (!pkt.dearmor(peer->key)) {
|
||||||
|
printf("%s HELLO rejected: packet authentication failed" ZT_EOL_S,ip->toString(ipstr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
peer.set(new PeerInfo);
|
||||||
|
if (id.agree(self,peer->key)) {
|
||||||
|
if (pkt.dearmor(peer->key)) {
|
||||||
|
if (id.locallyValidate()) {
|
||||||
|
peer->id = id;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> pbi_l(peersByIdentity_l);
|
||||||
|
peersByIdentity.emplace(id,peer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("%s HELLO rejected: invalid identity (locallyValidate() failed)" ZT_EOL_S,ip->toString(ipstr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("%s HELLO rejected: packet authentication failed" ZT_EOL_S,ip->toString(ipstr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("%s HELLO rejected: key agreement failed" ZT_EOL_S,ip->toString(ipstr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it wasn't a HELLO, check to see if any known identities for the sender's
|
||||||
|
// short ZT address successfully decrypt the packet.
|
||||||
|
if (!peer) {
|
||||||
|
std::lock_guard<std::mutex> pbv_l(peersByVirtAddr_l);
|
||||||
|
auto peers = peersByVirtAddr.find(pkt.source());
|
||||||
|
if (peers != peersByVirtAddr.end()) {
|
||||||
|
for(auto p=peers->second.begin();p!=peers->second.end();++p) {
|
||||||
|
if (pkt.dearmor((*p)->key)) {
|
||||||
|
peer = (*p);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
pkt = *inpkt; // dearmor() destroys contents of pkt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found the peer, update IP and/or time.
|
||||||
|
if (peer) {
|
||||||
|
InetAddress *const peerIp = (ip->ss_family == AF_INET) ? &(peer->ip4) : &(peer->ip6);
|
||||||
|
if (*peerIp != ip) {
|
||||||
|
std::lock_guard<std::mutex> pbp_l(peersByPhysAddr_l);
|
||||||
|
if (*peerIp) {
|
||||||
|
auto prev = peersByPhysAddr.find(*peerIp);
|
||||||
|
if (prev != peersByPhysAddr.end()) {
|
||||||
|
prev->second.erase(peer);
|
||||||
|
if (prev->second.empty())
|
||||||
|
peersByPhysAddr.erase(prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*peerIp = ip;
|
||||||
|
peersByPhysAddr[ip].emplace(peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
peer->lastReceive = OSUtils::now();
|
||||||
|
|
||||||
|
printf("%s has %s" ZT_EOL_S,ip->toString(ipstr),pkt.source().toString(astr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<InetAddress> toAddrs;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> pbv_l(peersByVirtAddr_l);
|
||||||
|
auto peers = peersByVirtAddr.find(inpkt->destination());
|
||||||
|
if (peers != peersByVirtAddr.end()) {
|
||||||
|
for(auto p=peers->second.begin();p!=peers->second.end();++p) {
|
||||||
|
if ((*p)->ip6)
|
||||||
|
toAddrs.push_back((*p)->ip6);
|
||||||
|
else if ((*p)->ip4)
|
||||||
|
toAddrs.push_back((*p)->ip4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (toAddrs.empty()) {
|
||||||
|
printf("%s not forwarding to %s: no destinations found" ZT_EOL_S,ip->toString(ipstr),pkt.destination().toString(astr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fragment) {
|
||||||
|
if (reinterpret_cast<Packet::Fragment *>(&pkt)->incrementHops() >= ZT_PROTO_MAX_HOPS) {
|
||||||
|
printf("%s refused to forward to %s: max hop count exceeded" ZT_EOL_S,ip->toString(ipstr),pkt.destination().toString(astr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pkt.incrementHops() >= ZT_PROTO_MAX_HOPS) {
|
||||||
|
printf("%s refused to forward to %s: max hop count exceeded" ZT_EOL_S,ip->toString(ipstr),pkt.destination().toString(astr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto i=toAddrs.begin();i!=toAddrs.end();++i) {
|
||||||
|
printf("%s -> %s for %s" ZT_EOL_S,ip->toString(ipstr),i->toString(ipstr2),pkt.destination().toString(astr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bindSocket(struct sockaddr *bindAddr)
|
static int bindSocket(struct sockaddr *bindAddr)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user