Browse Source
# Conflicts: # controller/DB.hpp # controller/DBMirrorSet.cpp # controller/DBMirrorSet.hpp # controller/EmbeddedNetworkController.cpp # controller/FileDB.cpp # controller/FileDB.hpp # controller/LFDB.cpp # controller/LFDB.hpp # controller/PostgreSQL.cpp # controller/PostgreSQL.hpp # node/C25519.cpp # node/C25519.hpp # node/Capability.hpp # node/CertificateOfMembership.cpp # node/CertificateOfMembership.hpp # node/CertificateOfOwnership.hpp # node/Credential.hpp # node/Identity.cpp # node/Identity.hpp # node/IncomingPacket.cpp # node/Metrics.cpp # node/Metrics.hpp # node/Multicaster.cpp # node/Network.cpp # node/Node.cpp # node/Packet.cpp # node/Packet.hpp # node/Peer.cpp # node/Revocation.hpp # node/Switch.cpp # node/Tag.hpp # node/World.hpp # osdep/Http.hpp # service/OneService.cpppull/4/head
32 changed files with 3589 additions and 2164 deletions
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c)2019 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2026-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
#include "DB.hpp" |
||||
|
||||
#ifdef ZT_CONTROLLER_USE_LIBPQ |
||||
|
||||
#ifndef ZT_CONTROLLER_CV1_HPP |
||||
#define ZT_CONTROLLER_CV1_HPP |
||||
|
||||
#define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4 |
||||
|
||||
#include "../node/Metrics.hpp" |
||||
#include "ConnectionPool.hpp" |
||||
#include "PostgreSQL.hpp" |
||||
|
||||
#include <memory> |
||||
#include <pqxx/pqxx> |
||||
#include <redis++/redis++.h> |
||||
|
||||
namespace smeeclient { |
||||
struct SmeeClient; |
||||
} |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
struct RedisConfig; |
||||
|
||||
/**
|
||||
* A controller database driver that talks to PostgreSQL |
||||
* |
||||
* This is for use with ZeroTier Central. Others are free to build and use it |
||||
* but be aware that we might change it at any time. |
||||
*/ |
||||
class CV1 : public DB { |
||||
public: |
||||
CV1(const Identity& myId, const char* path, int listenPort, RedisConfig* rc); |
||||
virtual ~CV1(); |
||||
|
||||
virtual bool waitForReady(); |
||||
virtual bool isReady(); |
||||
virtual bool save(nlohmann::json& record, bool notifyListeners); |
||||
virtual void eraseNetwork(const uint64_t networkId); |
||||
virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); |
||||
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); |
||||
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch); |
||||
virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL); |
||||
|
||||
virtual bool ready() |
||||
{ |
||||
return _ready == 2; |
||||
} |
||||
|
||||
protected: |
||||
struct _PairHasher { |
||||
inline std::size_t operator()(const std::pair<uint64_t, uint64_t>& p) const |
||||
{ |
||||
return (std::size_t)(p.first ^ p.second); |
||||
} |
||||
}; |
||||
virtual void _memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners) |
||||
{ |
||||
DB::_memberChanged(old, memberConfig, notifyListeners); |
||||
} |
||||
|
||||
virtual void _networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners) |
||||
{ |
||||
DB::_networkChanged(old, networkConfig, notifyListeners); |
||||
} |
||||
|
||||
private: |
||||
void initializeNetworks(); |
||||
void initializeMembers(); |
||||
void heartbeat(); |
||||
void membersDbWatcher(); |
||||
void _membersWatcher_Postgres(); |
||||
void networksDbWatcher(); |
||||
void _networksWatcher_Postgres(); |
||||
|
||||
void _membersWatcher_Redis(); |
||||
void _networksWatcher_Redis(); |
||||
|
||||
void commitThread(); |
||||
void onlineNotificationThread(); |
||||
void onlineNotification_Postgres(); |
||||
void onlineNotification_Redis(); |
||||
uint64_t _doRedisUpdate(sw::redis::Transaction& tx, std::string& controllerId, std::unordered_map<std::pair<uint64_t, uint64_t>, NodeOnlineRecord, _PairHasher>& lastOnline); |
||||
|
||||
void configureSmee(); |
||||
void notifyNewMember(const std::string& networkID, const std::string& memberID); |
||||
|
||||
enum OverrideMode { ALLOW_PGBOUNCER_OVERRIDE = 0, NO_OVERRIDE = 1 }; |
||||
|
||||
std::shared_ptr<ConnectionPool<PostgresConnection> > _pool; |
||||
|
||||
const Identity _myId; |
||||
const Address _myAddress; |
||||
std::string _myAddressStr; |
||||
std::string _connString; |
||||
|
||||
BlockingQueue<std::pair<nlohmann::json, bool> > _commitQueue; |
||||
|
||||
std::thread _heartbeatThread; |
||||
std::thread _membersDbWatcher; |
||||
std::thread _networksDbWatcher; |
||||
std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS]; |
||||
std::thread _onlineNotificationThread; |
||||
|
||||
std::unordered_map<std::pair<uint64_t, uint64_t>, NodeOnlineRecord, _PairHasher> _lastOnline; |
||||
|
||||
mutable std::mutex _lastOnline_l; |
||||
mutable std::mutex _readyLock; |
||||
std::atomic<int> _ready, _connected, _run; |
||||
mutable volatile bool _waitNoticePrinted; |
||||
|
||||
int _listenPort; |
||||
uint8_t _ssoPsk[48]; |
||||
|
||||
RedisConfig* _rc; |
||||
std::shared_ptr<sw::redis::Redis> _redis; |
||||
std::shared_ptr<sw::redis::RedisCluster> _cluster; |
||||
bool _redisMemberStatus; |
||||
|
||||
smeeclient::SmeeClient* _smee; |
||||
}; |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // ZT_CONTROLLER_CV1_HPP
|
||||
|
||||
#endif // ZT_CONTROLLER_USE_LIBPQ
|
||||
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c)2025 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2026-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
#include "DB.hpp" |
||||
|
||||
#ifdef ZT_CONTROLLER_USE_LIBPQ |
||||
|
||||
#ifndef ZT_CONTROLLER_CV2_HPP |
||||
#define ZT_CONTROLLER_CV2_HPP |
||||
|
||||
#define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4 |
||||
|
||||
#include "../node/Metrics.hpp" |
||||
#include "ConnectionPool.hpp" |
||||
#include "PostgreSQL.hpp" |
||||
|
||||
#include <memory> |
||||
#include <pqxx/pqxx> |
||||
#include <redis++/redis++.h> |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
class CV2 : public DB { |
||||
public: |
||||
CV2(const Identity& myId, const char* path, int listenPort); |
||||
virtual ~CV2(); |
||||
|
||||
virtual bool waitForReady(); |
||||
virtual bool isReady(); |
||||
virtual bool save(nlohmann::json& record, bool notifyListeners); |
||||
virtual void eraseNetwork(const uint64_t networkId); |
||||
virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); |
||||
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); |
||||
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch); |
||||
virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL); |
||||
|
||||
virtual bool ready() |
||||
{ |
||||
return _ready == 2; |
||||
} |
||||
|
||||
protected: |
||||
struct _PairHasher { |
||||
inline std::size_t operator()(const std::pair<uint64_t, uint64_t>& p) const |
||||
{ |
||||
return (std::size_t)(p.first ^ p.second); |
||||
} |
||||
}; |
||||
virtual void _memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners) |
||||
{ |
||||
DB::_memberChanged(old, memberConfig, notifyListeners); |
||||
} |
||||
|
||||
virtual void _networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners) |
||||
{ |
||||
DB::_networkChanged(old, networkConfig, notifyListeners); |
||||
} |
||||
|
||||
private: |
||||
void initializeNetworks(); |
||||
void initializeMembers(); |
||||
void heartbeat(); |
||||
void membersDbWatcher(); |
||||
void networksDbWatcher(); |
||||
|
||||
void commitThread(); |
||||
void onlineNotificationThread(); |
||||
|
||||
// void notifyNewMember(const std::string &networkID, const std::string &memberID);
|
||||
|
||||
enum OverrideMode { ALLOW_PGBOUNCER_OVERRIDE = 0, NO_OVERRIDE = 1 }; |
||||
|
||||
std::shared_ptr<ConnectionPool<PostgresConnection> > _pool; |
||||
|
||||
const Identity _myId; |
||||
const Address _myAddress; |
||||
std::string _myAddressStr; |
||||
std::string _connString; |
||||
|
||||
BlockingQueue<std::pair<nlohmann::json, bool> > _commitQueue; |
||||
|
||||
std::thread _heartbeatThread; |
||||
std::thread _membersDbWatcher; |
||||
std::thread _networksDbWatcher; |
||||
std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS]; |
||||
std::thread _onlineNotificationThread; |
||||
|
||||
std::unordered_map<std::pair<uint64_t, uint64_t>, NodeOnlineRecord, _PairHasher> _lastOnline; |
||||
|
||||
mutable std::mutex _lastOnline_l; |
||||
mutable std::mutex _readyLock; |
||||
std::atomic<int> _ready, _connected, _run; |
||||
mutable volatile bool _waitNoticePrinted; |
||||
|
||||
int _listenPort; |
||||
uint8_t _ssoPsk[48]; |
||||
}; |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // ZT_CONTROLLER_CV2_HPP
|
||||
#endif // ZT_CONTROLLER_USE_LIBPQ
|
||||
@ -0,0 +1,64 @@
|
||||
#include "CtlUtil.hpp" |
||||
|
||||
#ifdef ZT_CONTROLLER_USE_LIBPQ |
||||
|
||||
#include <iomanip> |
||||
#include <sstream> |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
const char* _timestr() |
||||
{ |
||||
time_t t = time(0); |
||||
char* ts = ctime(&t); |
||||
char* p = ts; |
||||
if (! p) |
||||
return ""; |
||||
while (*p) { |
||||
if (*p == '\n') { |
||||
*p = (char)0; |
||||
break; |
||||
} |
||||
++p; |
||||
} |
||||
return ts; |
||||
} |
||||
|
||||
std::vector<std::string> split(std::string str, char delim) |
||||
{ |
||||
std::istringstream iss(str); |
||||
std::vector<std::string> tokens; |
||||
std::string item; |
||||
while (std::getline(iss, item, delim)) { |
||||
tokens.push_back(item); |
||||
} |
||||
return tokens; |
||||
} |
||||
|
||||
std::string url_encode(const std::string& value) |
||||
{ |
||||
std::ostringstream escaped; |
||||
escaped.fill('0'); |
||||
escaped << std::hex; |
||||
|
||||
for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) { |
||||
std::string::value_type c = (*i); |
||||
|
||||
// Keep alphanumeric and other accepted characters intact
|
||||
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { |
||||
escaped << c; |
||||
continue; |
||||
} |
||||
|
||||
// Any other characters are percent-encoded
|
||||
escaped << std::uppercase; |
||||
escaped << '%' << std::setw(2) << int((unsigned char)c); |
||||
escaped << std::nouppercase; |
||||
} |
||||
|
||||
return escaped.str(); |
||||
} |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif |
||||
@ -0,0 +1,16 @@
|
||||
#ifndef ZT_CTLUTIL_HPP |
||||
#define ZT_CTLUTIL_HPP |
||||
|
||||
#include <string> |
||||
#include <vector> |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
const char* _timestr(); |
||||
|
||||
std::vector<std::string> split(std::string str, char delim); |
||||
|
||||
std::string url_encode(const std::string& value); |
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // namespace ZeroTier
|
||||
@ -1,15 +1,17 @@
|
||||
FROM ubuntu:jammy |
||||
FROM debian:bookworm |
||||
|
||||
|
||||
RUN apt update && apt upgrade -y |
||||
|
||||
RUN apt update && apt upgrade -y |
||||
RUN apt -y install \ |
||||
netcat \ |
||||
netcat-traditional \ |
||||
postgresql-client \ |
||||
postgresql-client-common \ |
||||
libjemalloc2 \ |
||||
libpq5 \ |
||||
curl \ |
||||
binutils \ |
||||
linux-tools-gke \ |
||||
perf-tools-unstable \ |
||||
google-perftools |
||||
google-perftools \ |
||||
gnupg |
||||
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
DROP TABLE IF EXISTS network_memberships_ctl; |
||||
DROP TABLE IF EXISTS networks_ctl; |
||||
DROP TABLE IF EXISTS controllers_ctl; |
||||
@ -0,0 +1,47 @@
|
||||
-- inits controller db schema |
||||
|
||||
CREATE TABLE IF NOT EXISTS controllers_ctl ( |
||||
id text NOT NULL PRIMARY KEY, |
||||
hostname text, |
||||
last_heartbeat timestamp with time zone, |
||||
public_identity text NOT NULL, |
||||
version text |
||||
); |
||||
|
||||
CREATE TABLE IF NOT EXISTS networks_ctl ( |
||||
id character varying(22) NOT NULL PRIMARY KEY, |
||||
name text NOT NULL, |
||||
configuration jsonb DEFAULT '{}'::jsonb NOT NULL, |
||||
controller_id text REFERENCES controllers_ctl(id), |
||||
revision integer DEFAULT 0 NOT NULL, |
||||
last_modified timestamp with time zone DEFAULT now(), |
||||
creation_time timestamp with time zone DEFAULT now() |
||||
); |
||||
|
||||
CREATE TABLE IF NOT EXISTS network_memberships_ctl ( |
||||
device_id character varying(22) NOT NULL, |
||||
network_id character varying(22) NOT NULL REFERENCES networks_ctl(id), |
||||
authorized boolean, |
||||
active_bridge boolean, |
||||
ip_assignments text[], |
||||
no_auto_assign_ips boolean, |
||||
sso_exempt boolean, |
||||
authentication_expiry_time timestamp with time zone, |
||||
capabilities jsonb, |
||||
creation_time timestamp with time zone DEFAULT now(), |
||||
last_modified timestamp with time zone DEFAULT now(), |
||||
identity text DEFAULT ''::text, |
||||
last_authorized_credential text, |
||||
last_authorized_time timestamp with time zone, |
||||
last_deauthorized_time timestamp with time zone, |
||||
last_seen jsonb DEFAULT '{}'::jsonb NOT NULL, -- in the context of the network |
||||
remote_trace_level integer DEFAULT 0 NOT NULL, |
||||
remote_trace_target text DEFAULT ''::text NOT NULL, |
||||
revision integer DEFAULT 0 NOT NULL, |
||||
tags jsonb, |
||||
version_major integer DEFAULT 0 NOT NULL, |
||||
version_minor integer DEFAULT 0 NOT NULL, |
||||
version_revision integer DEFAULT 0 NOT NULL, |
||||
version_protocol integer DEFAULT 0 NOT NULL, |
||||
PRIMARY KEY (device_id, network_id) |
||||
); |
||||
@ -0,0 +1,3 @@
|
||||
ALTER TABLE network_memberships_ctl |
||||
DROP COLUMN os, |
||||
DROP COLUMN arch; |
||||
@ -0,0 +1,3 @@
|
||||
ALTER TABLE network_memberships_ctl |
||||
ADD COLUMN os TEXT NOT NULL DEFAULT 'unknown', |
||||
ADD COLUMN arch TEXT NOT NULL DEFAULT 'unknown'; |
||||
Loading…
Reference in new issue