From 64b7d9ef82d73038509b686a46ce5816847089af Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 1 Jun 2017 07:15:46 -0700 Subject: New clustering work. --- attic/DBM.cpp | 243 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ attic/DBM.hpp | 168 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 411 insertions(+) create mode 100644 attic/DBM.cpp create mode 100644 attic/DBM.hpp (limited to 'attic') diff --git a/attic/DBM.cpp b/attic/DBM.cpp new file mode 100644 index 00000000..54f017e0 --- /dev/null +++ b/attic/DBM.cpp @@ -0,0 +1,243 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * 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 . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#include "DBM.hpp" + +#include "../version.h" + +#include "../node/Salsa20.hpp" +#include "../node/Poly1305.hpp" +#include "../node/SHA512.hpp" + +#include "../osdep/OSUtils.hpp" + +#define ZT_STORED_OBJECT_TYPE__CLUSTER_NODE_STATUS (ZT_STORED_OBJECT__MAX_TYPE_ID + 1) +#define ZT_STORED_OBJECT_TYPE__CLUSTER_DEFINITION (ZT_STORED_OBJECT__MAX_TYPE_ID + 2) + +namespace ZeroTier { + +// We generate the cluster ID from our address and version info since this is +// not at all designed to allow interoperation between versions (or endians) +// in the same cluster. +static inline uint64_t _mkClusterId(const Address &myAddress) +{ + uint64_t x = ZEROTIER_ONE_VERSION_MAJOR; + x <<= 8; + x += ZEROTIER_ONE_VERSION_MINOR; + x <<= 8; + x += ZEROTIER_ONE_VERSION_REVISION; + x <<= 40; + x ^= myAddress.toInt(); +#if __BYTE_ORDER == __BIG_ENDIAN + ++x; +#endif; + return x; +} + +void DBM::onUpdate(uint64_t from,const _MapKey &k,const _MapValue &v,uint64_t rev) +{ + char p[4096]; + char tmp[ZT_DBM_MAX_VALUE_SIZE]; + if (_persistentPath((ZT_StoredObjectType)k.type,k.key,p,sizeof(p))) { + // Reduce unnecessary disk writes + FILE *f = fopen(p,"r"); + if (f) { + long n = (long)fread(tmp,1,sizeof(tmp),f); + fclose(f); + if ((n == (long)v.len)&&(!memcmp(v.data,tmp,n))) + return; + } + + // Write to disk if file has changed or was not already present + f = fopen(p,"w"); + if (f) { + if (fwrite(data,len,1,f) != 1) + fprintf(stderr,"WARNING: error writing to %s (I/O error)" ZT_EOL_S,p); + fclose(f); + if (type == ZT_STORED_OBJECT_IDENTITY_SECRET) + OSUtils::lockDownFile(p,false); + } else { + fprintf(stderr,"WARNING: error writing to %s (cannot open)" ZT_EOL_S,p); + } + } +} + +void DBM::onDelete(uint64_t from,const _MapKey &k) +{ + char p[4096]; + if (_persistentPath((ZT_StoredObjectType)k.type,k.key,p,sizeof(p))) + OSUtils::rm(p); +} + +DBM::_vsdm_cryptor::_vsdm_cryptor(const Identity &secretIdentity) +{ + uint8_t s512[64]; + SHA512::hash(h512,secretIdentity.privateKeyPair().priv.data,ZT_C25519_PRIVATE_KEY_LEN); + memcpy(_key,s512,sizeof(_key)); +} + +void DBM::_vsdm_cryptor::encrypt(void *d,unsigned long l) +{ + if (l >= 24) { // sanity check + uint8_t key[32]; + uint8_t authKey[32]; + uint8_t auth[16]; + + uint8_t *const iv = reinterpret_cast(d) + (l - 16); + Utils::getSecureRandom(iv,16); + memcpy(key,_key,32); + for(unsigned long i=0;i<8;++i) + _key[i] ^= iv[i]; + + Salsa20 s20(key,iv + 8); + memset(authKey,0,32); + s20.crypt12(authKey,authKey,32); + s20.crypt12(d,d,l - 24); + + Poly1305::compute(auth,d,l - 24,authKey); + memcpy(reinterpret_cast(d) + (l - 24),auth,8); + } +} + +bool DBM::_vsdm_cryptor::decrypt(void *d,unsigned long l) +{ + if (l >= 24) { // sanity check + uint8_t key[32]; + uint8_t authKey[32]; + uint8_t auth[16]; + + uint8_t *const iv = reinterpret_cast(d) + (l - 16); + memcpy(key,_key,32); + for(unsigned long i=0;i<8;++i) + _key[i] ^= iv[i]; + + Salsa20 s20(key,iv + 8); + memset(authKey,0,32); + s20.crypt12(authKey,authKey,32); + + Poly1305::compute(auth,d,l - 24,authKey); + if (!Utils::secureEq(reinterpret_cast(d) + (l - 24),auth,8)) + return false; + + s20.crypt12(d,d,l - 24); + + return true; + } + return false; +} + +DBM::DBM(const Identity &secretIdentity,uint64_t clusterMemberId,const std::string &basePath,Node *node) : + _basePath(basePath), + _node(node), + _startTime(OSUtils::now()), + _m(_mkClusterId(secretIdentity.address()),clusterMemberId,false,_vsdm_cryptor(secretIdentity),_vsdm_watcher(this)) +{ +} + +DBM::~DBM() +{ +} + +void DBM::put(const ZT_StoredObjectType type,const uint64_t key,const void *data,unsigned int len) +{ + char p[4096]; + if (_m.put(_MapKey(key,(uint16_t)type),Value(OSUtils::now(),(uint16_t)len,data))) { + if (_persistentPath(type,key,p,sizeof(p))) { + FILE *f = fopen(p,"w"); + if (f) { + if (fwrite(data,len,1,f) != 1) + fprintf(stderr,"WARNING: error writing to %s (I/O error)" ZT_EOL_S,p); + fclose(f); + if (type == ZT_STORED_OBJECT_IDENTITY_SECRET) + OSUtils::lockDownFile(p,false); + } else { + fprintf(stderr,"WARNING: error writing to %s (cannot open)" ZT_EOL_S,p); + } + } + } +} + +bool DBM::get(const ZT_StoredObjectType type,const uint64_t key,Value &value) +{ + char p[4096]; + if (_m.get(_MapKey(key,(uint16_t)type),value)) + return true; + if (_persistentPath(type,key,p,sizeof(p))) { + FILE *f = fopen(p,"r"); + if (f) { + long n = (long)fread(value.data,1,sizeof(value.data),f); + value.len = (n > 0) ? (uint16_t)n : (uint16_t)0; + fclose(f); + value.ts = OSUtils::getLastModified(p); + _m.put(_MapKey(key,(uint16_t)type),value); + return true; + } + } + return false; +} + +void DBM::del(const ZT_StoredObjectType type,const uint64_t key) +{ + char p[4096]; + _m.del(_MapKey(key,(uint16_t)type)); + if (_persistentPath(type,key,p,sizeof(p))) + OSUtils::rm(p); +} + +void DBM::clean() +{ +} + +bool DBM::_persistentPath(const ZT_StoredObjectType type,const uint64_t key,char *p,unsigned int maxlen) +{ + switch(type) { + case ZT_STORED_OBJECT_IDENTITY_PUBLIC: + Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "identity.public",_basePath.c_str()); + return true; + case ZT_STORED_OBJECT_IDENTITY_SECRET: + Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "identity.secret",_basePath.c_str()); + return true; + case ZT_STORED_OBJECT_IDENTITY: + Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "iddb.d" ZT_PATH_SEPARATOR_S "%.10llx",_basePath.c_str(),key); + return true; + case ZT_STORED_OBJECT_NETWORK_CONFIG: + Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.conf",_basePath.c_str(),key); + return true; + case ZT_STORED_OBJECT_PLANET: + Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "planet",_basePath.c_str()); + return true; + case ZT_STORED_OBJECT_MOON: + Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "moons.d" ZT_PATH_SEPARATOR_S "%.16llx.moon",_basePath.c_str(),key); + return true; + case (ZT_StoredObjectType)ZT_STORED_OBJECT_TYPE__CLUSTER_DEFINITION: + Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "cluster",_basePath.c_str()); + return true; + default: + return false; + } +} + +} // namespace ZeroTier diff --git a/attic/DBM.hpp b/attic/DBM.hpp new file mode 100644 index 00000000..c6d5b8c0 --- /dev/null +++ b/attic/DBM.hpp @@ -0,0 +1,168 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * 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 . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#ifndef ZT_DBM_HPP___ +#define ZT_DBM_HPP___ + +#include +#include +#include +#include + +#include + +#include "../node/Constants.hpp" +#include "../node/Mutex.hpp" +#include "../node/Utils.hpp" +#include "../node/Identity.hpp" +#include "../node/Peer.hpp" + +#include "../ext/vsdm/vsdm.hpp" + +// The Peer is the largest structure we persist here +#define ZT_DBM_MAX_VALUE_SIZE sizeof(Peer) + +namespace ZeroTier { + +class Node; +class DBM; + +class DBM +{ +public: + ZT_PACKED_STRUCT(struct Value + { + Value(const uint64_t t,const uint16_t l,const void *d) : + ts(t), + l(l) + { + memcpy(data,d,l); + } + uint64_t ts; + uint16_t len; + uint8_t data[ZT_DBM_MAX_VALUE_SIZE]; + }); + +private: + ZT_PACKED_STRUCT(struct _MapKey + { + _MapKey() : obj(0),type(0) {} + _MapKey(const uint16_t t,const uint64_t o) : obj(o),type(t) {} + uint64_t obj; + uint16_t type; + inline bool operator==(const _MapKey &k) const { return ((obj == k.obj)&&(type == k.type)); } + }); + struct _MapHasher + { + inline std::size_t operator()(const _MapKey &k) const { return (std::size_t)((k.obj ^ (k.obj >> 32)) + (uint64_t)k.type); } + }; + + void onUpdate(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev); + void onDelete(uint64_t from,const _MapKey &k); + + class _vsdm_watcher + { + public: + _vsdm_watcher(DBM *p) : _parent(p) {} + inline void add(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev) { _parent->onUpdate(from,k,v,rev); } + inline void update(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev) { _parent->onUpdate(from,k,v,rev); } + inline void del(uint64_t from,const _MapKey &k) { _parent->onDelete(from,k); } + private: + DBM *_parent; + }; + class _vsdm_serializer + { + public: + static inline unsigned long objectSize(const _MapKey &k) { return 10; } + static inline unsigned long objectSize(const Value &v) { return (10 + v.len); } + static inline const char *objectData(const _MapKey &k) { return reinterpret_cast(&k); } + static inline const char *objectData(const Value &v) { return reinterpret_cast(&v); } + static inline bool objectDeserialize(const char *d,unsigned long l,_MapKey &k) + { + if (l == 10) { + memcpy(&k,d,10); + return true; + } + return false; + } + static inline bool objectDeserialize(const char *d,unsigned long l,Value &v) + { + if ((l >= 10)&&(l <= (10 + ZT_DBM_MAX_VALUE_SIZE))) { + memcpy(&v,d,l); + return true; + } + return false; + } + }; + class _vsdm_cryptor + { + public: + _vsdm_cryptor(const Identity &secretIdentity); + static inline unsigned long overhead() { return 24; } + void encrypt(void *d,unsigned long l); + bool decrypt(void *d,unsigned long l); + uint8_t _key[32]; + }; + + typedef vsdm< _MapKey,Value,16384,_vsdm_watcher,_vsdm_serializer,_vsdm_cryptor,_MapHasher > _Map; + + friend class _Map; + +public: + ZT_PACKED_STRUCT(struct ClusterPeerStatus + { + uint64_t startTime; + uint64_t currentTime; + uint64_t clusterPeersConnected; + uint64_t ztPeersConnected; + uint16_t platform; + uint16_t arch; + }); + + DBM(const Identity &secretIdentity,uint64_t clusterMemberId,const std::string &basePath,Node *node); + + ~DBM(); + + void put(const ZT_StoredObjectType type,const uint64_t key,const void *data,unsigned int len); + + bool get(const ZT_StoredObjectType type,const uint64_t key,Value &value); + + void del(const ZT_StoredObjectType type,const uint64_t key); + + void clean(); + +private: + bool DBM::_persistentPath(const ZT_StoredObjectType type,const uint64_t key,char *p,unsigned int maxlen); + + const std::string _basePath; + Node *const _node; + uint64_t _startTime; + _Map _m; +}; + +} // namespace ZeroTier + +#endif -- cgit v1.2.3