Compare commits

...
Sign in to create a new pull request.

48 commits

Author SHA1 Message Date
Grant Limberg
fb7b07fc42 make sure the pg connstring is correct for cv2:// instances
Some checks failed
/ build_macos (push) Has been cancelled
/ build_windows (push) Has been cancelled
/ build_ubuntu (push) Has been cancelled
2025-04-03 14:48:13 -07:00
Grant Limberg
1d2130610c use the CV2 db instance if the path prefix is cv2:// 2025-04-03 14:38:58 -07:00
Grant Limberg
0b04f772ef make things compile 2025-04-03 14:26:09 -07:00
Grant Limberg
5c73fe9304 build fix 2025-04-03 10:45:06 -07:00
Grant Limberg
2af105000f
WIP: refactoring for CV2 db integration 2025-04-03 10:27:42 -07:00
Grant Limberg
cadfa0bc4d
Merge pull request #2445 from zerotier/docker-local-conf
Allow setting local.conf content from Docker environment variable
2025-04-03 09:42:11 -07:00
Grant Limberg
f2521c8536
Allow setting local.conf content from Docker environment variable 2025-03-26 11:23:46 -07:00
Grant Limberg
d353e0c6fa
Merge pull request #2442 from zerotier/dependabot/cargo/rustybits/ring-0.17.13
Bump ring from 0.17.8 to 0.17.13 in /rustybits
2025-03-19 08:30:23 -07:00
Grant Limberg
346731ea5d
Merge branch 'dev' into dependabot/cargo/rustybits/ring-0.17.13 2025-03-11 10:47:33 -07:00
Grant Limberg
2ef38d84d1
Merge pull request #2444 from zerotier:gl/temporal-sdk-fix
temporal sdk fix
2025-03-10 16:39:39 -07:00
Grant Limberg
5630d48a66 temporal sdk fix
missing WorkflowIdConflictPolicy
2025-03-10 16:35:10 -07:00
Grant Limberg
b44a9b8b62
Merge pull request #2443 from zerotier:gl/onelogin-fix
Fix AuthInfo Provider not being set
2025-03-10 16:20:06 -07:00
Grant Limberg
f5b0fc6a8f
Fix AuthInfo Provider not being set 2025-03-10 16:04:06 -07:00
dependabot[bot]
a20bc772f2
Bump ring from 0.17.8 to 0.17.13 in /rustybits
Bumps [ring](https://github.com/briansmith/ring) from 0.17.8 to 0.17.13.
- [Changelog](https://github.com/briansmith/ring/blob/main/RELEASES.md)
- [Commits](https://github.com/briansmith/ring/commits)

---
updated-dependencies:
- dependency-name: ring
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-07 17:04:31 +00:00
Travis LaDuke
010c4b0d64
Merge pull request #2441 from zerotier/laduke/update-actions
Run CI on pull requests
2025-03-05 09:18:20 -08:00
travisladuke
5998f1497a
Run CI on pull requests
If the PR is from an external repo,
the action won't run without approval.
right now we can't run the actions on external PRs.
2025-03-03 10:01:33 -08:00
Grant Limberg
a2162c01e3
Merge pull request #2430 from zerotier/dependabot/cargo/rustybits/openssl-0.10.70
Bump openssl from 0.10.68 to 0.10.70 in /rustybits
2025-02-04 15:45:25 -08:00
Grant Limberg
870c221690
Merge branch 'dev' into dependabot/cargo/rustybits/openssl-0.10.70 2025-02-04 15:38:52 -08:00
Grant Limberg
87ad848202
Merge pull request #2432 from zerotier:ci-update
Update upload-artifact action to use v4
2025-02-04 15:38:14 -08:00
Grant Limberg
b736b6835d
Update upload-artifact action to use v4
V3 is no longer supported and throws an error on use
2025-02-04 15:30:25 -08:00
dependabot[bot]
91bec01da8
Bump openssl from 0.10.68 to 0.10.70 in /rustybits
Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.68 to 0.10.70.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.68...openssl-v0.10.70)

---
updated-dependencies:
- dependency-name: openssl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-03 18:50:34 +00:00
Grant Limberg
b5c51796b9
Merge pull request #2417 from zerotier/rust-deps
update rust dependencies
2024-12-04 14:46:54 -08:00
Grant Limberg
724002f142
update rust dependencies 2024-12-04 13:43:34 -08:00
Grant Limberg
377a9d6f41
Merge pull request #2409 from zerotier/dependabot/cargo/rustybits/rustls-0.23.18
Bump rustls from 0.23.15 to 0.23.18 in /rustybits
2024-11-25 11:27:22 -08:00
dependabot[bot]
003b4cf876
Bump rustls from 0.23.15 to 0.23.18 in /rustybits
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.15 to 0.23.18.
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.15...v/0.23.18)

---
updated-dependencies:
- dependency-name: rustls
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-25 17:00:23 +00:00
Joseph Henry
b12dd19d44
Merge pull request #2405 from zerotier/jh-fix-openbsd-tap
Build fix for OpenBSD - See ticket #2397
2024-11-13 15:12:18 -08:00
Joseph Henry
82c6454950
Fix broken ifdef on OpenBSD
Some checks failed
/ build_macos (push) Has been cancelled
/ build_windows (push) Has been cancelled
/ build_ubuntu (push) Has been cancelled
2024-11-13 09:01:09 -08:00
Joseph Henry
969c0ee6e3
Omit CPU pinning code on OpenBSD 2024-11-12 14:40:24 -08:00
Joseph Henry
c092b63987
Merge pull request #2365 from zerotier/laduke/2361-phy-mtu
Lower ZT_MIN_PHYSMTU
2024-11-12 09:38:11 -08:00
Joseph Henry
47efee1df4
Merge branch 'dev' into laduke/2361-phy-mtu
Some checks failed
/ build_macos (push) Has been cancelled
/ build_windows (push) Has been cancelled
/ build_ubuntu (push) Has been cancelled
2024-11-12 06:20:29 -08:00
Joseph Henry
18a5452de8
Merge pull request #2395 from zerotier/core-objs
Move osutils/OSUtils.o into CORE_OBJS
2024-11-12 06:20:04 -08:00
Joseph Henry
c3794ba8d4
Merge branch 'dev' into core-objs
Some checks failed
/ build_macos (push) Has been cancelled
/ build_windows (push) Has been cancelled
/ build_ubuntu (push) Has been cancelled
2024-11-12 06:05:51 -08:00
Joseph Henry
75a5b4438b
Build fix for OpenBSD - See ticket #2397 2024-11-12 05:59:49 -08:00
Adam Ierymenko
185a3a2c76
Merge pull request #2396 from zerotier/1.14.2
Some checks failed
/ build_macos (push) Has been cancelled
/ build_windows (push) Has been cancelled
/ build_ubuntu (push) Has been cancelled
1.14.2
2024-10-25 14:37:17 -04:00
Adam Ierymenko
3fcef51137 Windows installer version bump.
Some checks failed
/ build_macos (push) Has been cancelled
/ build_windows (push) Has been cancelled
/ build_ubuntu (push) Has been cancelled
2024-10-25 14:14:01 -04:00
Grant Limberg
f959c2f4ca
Move osutils/OSUtils.o into CORE_OBJS
When building via `make core` to make libzerotiercore.a, you can't link unless OSUtils.cpp is also built & linked.
2024-10-25 09:32:13 -07:00
Adam Ierymenko
b7a6e106fd
Version increments. 2024-10-23 14:08:57 -04:00
Adam Ierymenko
7dca7fac11
Bump Rust library versions. 2024-10-23 11:03:18 -04:00
Adam Ierymenko
4ef2d4cc8e
Merge pull request #2376 from sh1ve/patch-1
Fix build error under certain character sets in Windows
2024-10-23 10:09:40 -04:00
travisladuke
55bbd2aec6 Lower ZT_MIN_PHYSMTU
regarding #2361
2024-10-18 15:44:34 -07:00
Grant Limberg
36b4659f77
Merge pull request #2379 from zerotier/docker-release
add `make docker-release`  command & update dockerfile
2024-10-02 13:21:20 -07:00
Grant Limberg
0b5666bde2
Merge remote-tracking branch 'origin/dev' into docker-release 2024-10-02 13:07:23 -07:00
Grant Limberg
e1c72e6d51
add make docker-release command & update dockerfile 2024-10-02 12:59:21 -07:00
sh1ve
5799d9a15b
Fix build error under certain character sets
Add some padding after non-ASCII comment
2024-09-29 23:49:38 +08:00
Joseph Henry
d9d58c8bde
Merge pull request #2371 from zerotier/jh-fix-bsd-tap-build-error
Fix build error for BSD tap driver
2024-09-18 08:49:28 -07:00
Joseph Henry
d34481d830
Fix build error for BSD tap driver
Some checks failed
/ build_macos (push) Has been cancelled
/ build_windows (push) Has been cancelled
/ build_ubuntu (push) Has been cancelled
2024-09-17 11:04:01 -07:00
Joseph Henry
4920b68d2c
Merge pull request #2364 from zerotier/jh-fix-for-lbm
Fix for low-bandwidth mode
2024-09-13 10:01:47 -07:00
Joseph Henry
5ce3d1e7a1
Fix for low-bandwidth mode
Some checks failed
/ build_macos (push) Has been cancelled
/ build_windows (push) Has been cancelled
/ build_ubuntu (push) Has been cancelled
2024-09-13 09:46:36 -07:00
30 changed files with 3451 additions and 2447 deletions

View file

@ -1,4 +1,7 @@
on: [ push ]
on:
pull_request:
push:
workflow_dispatch:
jobs:
build_ubuntu:

View file

@ -1,4 +1,5 @@
on:
pull_request:
push:
workflow_dispatch:
@ -44,7 +45,7 @@ jobs:
sudo ./.github/workflows/validate-linux.sh
- name: Archive test results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{github.sha}}-test-results
path: "*test-results*"

View file

@ -1,6 +1,6 @@
# vim: ft=dockerfile
FROM debian:bullseye
FROM debian:bookworm
ARG VERSION
@ -9,9 +9,9 @@ RUN mkdir -p /usr/share/zerotier && \
curl -o /usr/share/zerotier/tmp.asc "https://download.zerotier.com/contact%40zerotier.com.gpg" && \
gpg --no-default-keyring --keyring /usr/share/zerotier/zerotier.gpg --import /usr/share/zerotier/tmp.asc && \
rm -f /usr/share/zerotier/tmp.asc && \
echo "deb [signed-by=/usr/share/zerotier/zerotier.gpg] http://download.zerotier.com/debian/bullseye bullseye main" > /etc/apt/sources.list.d/zerotier.list
echo "deb [signed-by=/usr/share/zerotier/zerotier.gpg] http://download.zerotier.com/debian/bookworm bookworm main" > /etc/apt/sources.list.d/zerotier.list
RUN apt-get update -qq && apt-get install zerotier-one=${VERSION} curl iproute2 net-tools iputils-ping openssl libssl1.1 -y
RUN apt-get update -qq && apt-get install zerotier-one=${VERSION} curl iproute2 net-tools iputils-ping openssl libssl3 -y
RUN rm -rf /var/lib/zerotier-one
COPY entrypoint.sh.release /entrypoint.sh

View file

@ -64,6 +64,7 @@ You can control a few settings including the identity used and the authtoken use
- `ZEROTIER_API_SECRET`: replaces the `authtoken.secret` before booting and allows you to manage the control socket's authentication key.
- `ZEROTIER_IDENTITY_PUBLIC`: the `identity.public` file for zerotier-one. Use `zerotier-idtool` to generate one of these for you.
- `ZEROTIER_IDENTITY_SECRET`: the `identity.secret` file for zerotier-one. Use `zerotier-idtool` to generate one of these for you.
- `ZEROTIER_LOCAL_CONF`: Sets the the `local.conf` file content for zerotier-one
### Tips

View file

@ -1,6 +1,13 @@
ZeroTier Release Notes
======
# 2024-10-23 -- Version 1.14.2
* Fix for missing entitlement on macOS Sequoia.
* Fix for a problem correctly parsing local.conf to enable low bandwidth mode.
* Increment versions of some dependent libraries.
* Other fixes.
# 2024-09-12 -- Version 1.14.1
* Multithreaded packet I/O support! Currently this is just for Linux and must

1843
controller/CV1.cpp Normal file

File diff suppressed because it is too large Load diff

143
controller/CV1.hpp Normal file
View file

@ -0,0 +1,143 @@
/*
* 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 "ConnectionPool.hpp"
#include <pqxx/pqxx>
#include <memory>
#include <redis++/redis++.h>
#include "../node/Metrics.hpp"
#include "PostgreSQL.hpp"
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 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>,std::pair<int64_t,InetAddress>,_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>,std::pair<int64_t,InetAddress>,_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

512
controller/CV2.cpp Normal file
View file

@ -0,0 +1,512 @@
/*
* 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 "CV2.hpp"
#ifdef ZT_CONTROLLER_USE_LIBPQ
#include "../node/Constants.hpp"
#include "../node/SHA512.hpp"
#include "EmbeddedNetworkController.hpp"
#include "../version.h"
#include "CtlUtil.hpp"
#include <libpq-fe.h>
#include <sstream>
#include <iomanip>
#include <climits>
#include <chrono>
using json = nlohmann::json;
namespace {
}
using namespace ZeroTier;
CV2::CV2(const Identity &myId, const char *path, int listenPort)
: DB()
, _pool()
, _myId(myId)
, _myAddress(myId.address())
, _ready(0)
, _connected(1)
, _run(1)
, _waitNoticePrinted(false)
, _listenPort(listenPort)
{
char myAddress[64];
_myAddressStr = myId.address().toString(myAddress);
// replace cv2: with postgres: for the path/connstring
std::string _path(path);
if (_path.length() > 4 && _path.substr(0, 4) == "cv2:") {
_path = "postgres:" + _path.substr(4);
}
_connString = std::string(_path);
auto f = std::make_shared<PostgresConnFactory>(_connString);
_pool = std::make_shared<ConnectionPool<PostgresConnection> >(
15, 5, std::static_pointer_cast<ConnectionFactory>(f));
memset(_ssoPsk, 0, sizeof(_ssoPsk));
char *const ssoPskHex = getenv("ZT_SSO_PSK");
#ifdef ZT_TRACE
fprintf(stderr, "ZT_SSO_PSK: %s\n", ssoPskHex);
#endif
if (ssoPskHex) {
// SECURITY: note that ssoPskHex will always be null-terminated if libc actually
// returns something non-NULL. If the hex encodes something shorter than 48 bytes,
// it will be padded at the end with zeroes. If longer, it'll be truncated.
Utils::unhex(ssoPskHex, _ssoPsk, sizeof(_ssoPsk));
}
auto c = _pool->borrow();
pqxx::work txn{*c->c};
pqxx::row r{txn.exec1("SELECT version FROM ztc_database")};
int dbVersion = r[0].as<int>();
txn.commit();
// if (dbVersion < DB_MINIMUM_VERSION) {
// fprintf(stderr, "Central database schema version too low. This controller version requires a minimum schema version of %d. Please upgrade your Central instance", DB_MINIMUM_VERSION);
// exit(1);
// }
_pool->unborrow(c);
_readyLock.lock();
fprintf(stderr, "[%s] NOTICE: %.10llx controller PostgreSQL waiting for initial data download..." ZT_EOL_S, ::_timestr(), (unsigned long long)_myAddress.toInt());
_waitNoticePrinted = true;
initializeNetworks();
initializeMembers();
_heartbeatThread = std::thread(&CV2::heartbeat, this);
_membersDbWatcher = std::thread(&CV2::membersDbWatcher, this);
_networksDbWatcher = std::thread(&CV2::networksDbWatcher, this);
for (int i = 0; i < ZT_CENTRAL_CONTROLLER_COMMIT_THREADS; ++i) {
_commitThread[i] = std::thread(&CV2::commitThread, this);
}
_onlineNotificationThread = std::thread(&CV2::onlineNotificationThread, this);
}
CV2::~CV2()
{
_run = 0;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
_heartbeatThread.join();
_membersDbWatcher.join();
_networksDbWatcher.join();
_commitQueue.stop();
for (int i = 0; i < ZT_CENTRAL_CONTROLLER_COMMIT_THREADS; ++i) {
_commitThread[i].join();
}
_onlineNotificationThread.join();
}
bool CV2::waitForReady()
{
while (_ready < 2) {
_readyLock.lock();
_readyLock.unlock();
}
return true;
}
bool CV2::isReady()
{
return (_ready == 2) && _cldemote;
}
bool CV2::save(nlohmann::json &record,bool notifyListeners)
{
bool modified = false;
try {
if (!record.is_object()) {
fprintf(stderr, "record is not an object?!?\n");
return false;
}
const std::string objtype = record["objtype"];
if (objtype == "network") {
//fprintf(stderr, "network save\n");
const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL);
if (nwid) {
nlohmann::json old;
get(nwid,old);
if ((!old.is_object())||(!_compareRecords(old,record))) {
record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
_commitQueue.post(std::pair<nlohmann::json,bool>(record,notifyListeners));
modified = true;
}
}
} else if (objtype == "member") {
std::string networkId = record["nwid"];
std::string memberId = record["id"];
const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL);
const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL);
//fprintf(stderr, "member save %s-%s\n", networkId.c_str(), memberId.c_str());
if ((id)&&(nwid)) {
nlohmann::json network,old;
get(nwid,network,id,old);
if ((!old.is_object())||(!_compareRecords(old,record))) {
//fprintf(stderr, "commit queue post\n");
record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
_commitQueue.post(std::pair<nlohmann::json,bool>(record,notifyListeners));
modified = true;
} else {
//fprintf(stderr, "no change\n");
}
}
} else {
fprintf(stderr, "uhh waaat\n");
}
} catch (std::exception &e) {
fprintf(stderr, "Error on PostgreSQL::save: %s\n", e.what());
} catch (...) {
fprintf(stderr, "Unknown error on PostgreSQL::save\n");
}
return modified;
}
void CV2::eraseNetwork(const uint64_t networkId)
{
fprintf(stderr, "PostgreSQL::eraseNetwork\n");
char tmp2[24];
waitForReady();
Utils::hex(networkId, tmp2);
std::pair<nlohmann::json,bool> tmp;
tmp.first["id"] = tmp2;
tmp.first["objtype"] = "_delete_network";
tmp.second = true;
_commitQueue.post(tmp);
nlohmann::json nullJson;
_networkChanged(tmp.first, nullJson, true);
}
void CV2::eraseMember(const uint64_t networkId, const uint64_t memberId)
{
fprintf(stderr, "PostgreSQL::eraseMember\n");
char tmp2[24];
waitForReady();
std::pair<nlohmann::json,bool> tmp, nw;
Utils::hex(networkId, tmp2);
tmp.first["nwid"] = tmp2;
Utils::hex(memberId, tmp2);
tmp.first["id"] = tmp2;
tmp.first["objtype"] = "_delete_member";
tmp.second = true;
_commitQueue.post(tmp);
nlohmann::json nullJson;
_memberChanged(tmp.first, nullJson, true);
}
void CV2::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress)
{
std::lock_guard<std::mutex> l(_lastOnline_l);
std::pair<int64_t, InetAddress> &i = _lastOnline[std::pair<uint64_t,uint64_t>(networkId, memberId)];
i.first = OSUtils::now();
if (physicalAddress) {
i.second = physicalAddress;
}
}
AuthInfo CV2::getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL)
{
// TODO: Redo this for CV2
Metrics::db_get_sso_info++;
// NONCE is just a random character string. no semantic meaning
// state = HMAC SHA384 of Nonce based on shared sso key
//
// need nonce timeout in database? make sure it's used within X time
// X is 5 minutes for now. Make configurable later?
//
// how do we tell when a nonce is used? if auth_expiration_time is set
std::string networkId = member["nwid"];
std::string memberId = member["id"];
char authenticationURL[4096] = {0};
AuthInfo info;
info.enabled = true;
//if (memberId == "a10dccea52" && networkId == "8056c2e21c24673d") {
// fprintf(stderr, "invalid authinfo for grant's machine\n");
// info.version=1;
// return info;
//}
// fprintf(stderr, "PostgreSQL::updateMemberOnLoad: %s-%s\n", networkId.c_str(), memberId.c_str());
std::shared_ptr<PostgresConnection> c;
try {
// c = _pool->borrow();
// pqxx::work w(*c->c);
// char nonceBytes[16] = {0};
// std::string nonce = "";
// // check if the member exists first.
// pqxx::row count = w.exec_params1("SELECT count(id) FROM ztc_member WHERE id = $1 AND network_id = $2 AND deleted = false", memberId, networkId);
// if (count[0].as<int>() == 1) {
// // get active nonce, if exists.
// pqxx::result r = w.exec_params("SELECT nonce FROM ztc_sso_expiry "
// "WHERE network_id = $1 AND member_id = $2 "
// "AND ((NOW() AT TIME ZONE 'UTC') <= authentication_expiry_time) AND ((NOW() AT TIME ZONE 'UTC') <= nonce_expiration)",
// networkId, memberId);
// if (r.size() == 0) {
// // no active nonce.
// // find an unused nonce, if one exists.
// pqxx::result r = w.exec_params("SELECT nonce FROM ztc_sso_expiry "
// "WHERE network_id = $1 AND member_id = $2 "
// "AND authentication_expiry_time IS NULL AND ((NOW() AT TIME ZONE 'UTC') <= nonce_expiration)",
// networkId, memberId);
// if (r.size() == 1) {
// // we have an existing nonce. Use it
// nonce = r.at(0)[0].as<std::string>();
// Utils::unhex(nonce.c_str(), nonceBytes, sizeof(nonceBytes));
// } else if (r.empty()) {
// // create a nonce
// Utils::getSecureRandom(nonceBytes, 16);
// char nonceBuf[64] = {0};
// Utils::hex(nonceBytes, sizeof(nonceBytes), nonceBuf);
// nonce = std::string(nonceBuf);
// pqxx::result ir = w.exec_params0("INSERT INTO ztc_sso_expiry "
// "(nonce, nonce_expiration, network_id, member_id) VALUES "
// "($1, TO_TIMESTAMP($2::double precision/1000), $3, $4)",
// nonce, OSUtils::now() + 300000, networkId, memberId);
// w.commit();
// } else {
// // > 1 ?!? Thats an error!
// fprintf(stderr, "> 1 unused nonce!\n");
// exit(6);
// }
// } else if (r.size() == 1) {
// nonce = r.at(0)[0].as<std::string>();
// Utils::unhex(nonce.c_str(), nonceBytes, sizeof(nonceBytes));
// } else {
// // more than 1 nonce in use? Uhhh...
// fprintf(stderr, "> 1 nonce in use for network member?!?\n");
// exit(7);
// }
// r = w.exec_params(
// "SELECT oc.client_id, oc.authorization_endpoint, oc.issuer, oc.provider, oc.sso_impl_version "
// "FROM ztc_network AS n "
// "INNER JOIN ztc_org o "
// " ON o.owner_id = n.owner_id "
// "LEFT OUTER JOIN ztc_network_oidc_config noc "
// " ON noc.network_id = n.id "
// "LEFT OUTER JOIN ztc_oidc_config oc "
// " ON noc.client_id = oc.client_id AND oc.org_id = o.org_id "
// "WHERE n.id = $1 AND n.sso_enabled = true", networkId);
// std::string client_id = "";
// std::string authorization_endpoint = "";
// std::string issuer = "";
// std::string provider = "";
// uint64_t sso_version = 0;
// if (r.size() == 1) {
// client_id = r.at(0)[0].as<std::optional<std::string>>().value_or("");
// authorization_endpoint = r.at(0)[1].as<std::optional<std::string>>().value_or("");
// issuer = r.at(0)[2].as<std::optional<std::string>>().value_or("");
// provider = r.at(0)[3].as<std::optional<std::string>>().value_or("");
// sso_version = r.at(0)[4].as<std::optional<uint64_t>>().value_or(1);
// } else if (r.size() > 1) {
// fprintf(stderr, "ERROR: More than one auth endpoint for an organization?!?!? NetworkID: %s\n", networkId.c_str());
// } else {
// fprintf(stderr, "No client or auth endpoint?!?\n");
// }
// info.version = sso_version;
// // no catch all else because we don't actually care if no records exist here. just continue as normal.
// if ((!client_id.empty())&&(!authorization_endpoint.empty())) {
// uint8_t state[48];
// HMACSHA384(_ssoPsk, nonceBytes, sizeof(nonceBytes), state);
// char state_hex[256];
// Utils::hex(state, 48, state_hex);
// if (info.version == 0) {
// char url[2048] = {0};
// OSUtils::ztsnprintf(url, sizeof(authenticationURL),
// "%s?response_type=id_token&response_mode=form_post&scope=openid+email+profile&redirect_uri=%s&nonce=%s&state=%s&client_id=%s",
// authorization_endpoint.c_str(),
// url_encode(redirectURL).c_str(),
// nonce.c_str(),
// state_hex,
// client_id.c_str());
// info.authenticationURL = std::string(url);
// } else if (info.version == 1) {
// info.ssoClientID = client_id;
// info.issuerURL = issuer;
// info.ssoProvider = provider;
// info.ssoNonce = nonce;
// info.ssoState = std::string(state_hex) + "_" +networkId;
// info.centralAuthURL = redirectURL;
// #ifdef ZT_DEBUG
// fprintf(
// stderr,
// "ssoClientID: %s\nissuerURL: %s\nssoNonce: %s\nssoState: %s\ncentralAuthURL: %s\nprovider: %s\n",
// info.ssoClientID.c_str(),
// info.issuerURL.c_str(),
// info.ssoNonce.c_str(),
// info.ssoState.c_str(),
// info.centralAuthURL.c_str(),
// provider.c_str());
// #endif
// }
// } else {
// fprintf(stderr, "client_id: %s\nauthorization_endpoint: %s\n", client_id.c_str(), authorization_endpoint.c_str());
// }
// }
// _pool->unborrow(c);
} catch (std::exception &e) {
fprintf(stderr, "ERROR: Error updating member on load for network %s: %s\n", networkId.c_str(), e.what());
}
return info; //std::string(authenticationURL);
}
void CV2::initializeNetworks()
{
try {
// TODO: Update for CV2
if (++this->_ready == 2) {
if (_waitNoticePrinted) {
fprintf(stderr,"[%s] NOTICE: %.10llx controller PostgreSQL data download complete." ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt());
}
_readyLock.unlock();
}
fprintf(stderr, "network init done\n");
} catch (std::exception &e) {
fprintf(stderr, "ERROR: Error initializing networks: %s\n", e.what());
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
exit(-1);
}
}
void CV2::initializeMembers()
{
std::string memberId;
std::string networkId;
try {
// TODO: Update for CV2
if (++this->_ready == 2) {
if (_waitNoticePrinted) {
fprintf(stderr,"[%s] NOTICE: %.10llx controller PostgreSQL data download complete." ZT_EOL_S,_timestr(),(unsigned long long)_myAddress.toInt());
}
_readyLock.unlock();
}
fprintf(stderr, "member init done\n");
} catch (std::exception &e) {
fprintf(stderr, "ERROR: Error initializing member: %s-%s %s\n", networkId.c_str(), memberId.c_str(), e.what());
exit(-1);
}
}
void CV2::heartbeat()
{
char publicId[1024];
char hostnameTmp[1024];
_myId.toString(false,publicId);
if (gethostname(hostnameTmp, sizeof(hostnameTmp))!= 0) {
hostnameTmp[0] = (char)0;
} else {
for (int i = 0; i < (int)sizeof(hostnameTmp); ++i) {
if ((hostnameTmp[i] == '.')||(hostnameTmp[i] == 0)) {
hostnameTmp[i] = (char)0;
break;
}
}
}
const char *controllerId = _myAddressStr.c_str();
const char *publicIdentity = publicId;
const char *hostname = hostnameTmp;
// TODO: Update for CV2
while (_run == 1) {
std::this_thread::sleep_for(std::chrono::seconds(5));
}
fprintf(stderr, "Exited heartbeat thread\n");
}
void CV2::membersDbWatcher() {
auto c = _pool->borrow();
std::string stream = "member_" + _myAddressStr;
fprintf(stderr, "Listening to member stream: %s\n", stream.c_str());
MemberNotificationReceiver m(this, *c->c, stream);
while(_run == 1) {
c->c->await_notification(5, 0);
}
_pool->unborrow(c);
fprintf(stderr, "Exited membersDbWatcher\n");
}
void CV2::networksDbWatcher()
{
std::string stream = "network_" + _myAddressStr;
fprintf(stderr, "Listening to member stream: %s\n", stream.c_str());
auto c = _pool->borrow();
NetworkNotificationReceiver n(this, *c->c, stream);
while(_run == 1) {
c->c->await_notification(5,0);
}
_pool->unborrow(c);
fprintf(stderr, "Exited networksDbWatcher\n");
}
void CV2::commitThread()
{
// TODO: Update for CV2
}
void CV2::onlineNotificationThread() {
waitForReady();
_connected = 1;
nlohmann::json jtmp1, jtmp2;
while (_run == 1) {
// TODO: Update for CV2
}
fprintf(stderr, "%s: Fell out of run loop in onlineNotificationThread\n", _myAddressStr.c_str());
if (_run == 1) {
fprintf(stderr, "ERROR: %s onlineNotificationThread should still be running! Exiting Controller.\n", _myAddressStr.c_str());
exit(6);
}
}
#endif // ZT_CONTROLLER_USE_LIBPQ

112
controller/CV2.hpp Normal file
View file

@ -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 "ConnectionPool.hpp"
#include <pqxx/pqxx>
#include <memory>
#include <redis++/redis++.h>
#include "../node/Metrics.hpp"
#include "PostgreSQL.hpp"
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 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>,std::pair<int64_t,InetAddress>,_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

62
controller/CtlUtil.cpp Normal file
View file

@ -0,0 +1,62 @@
#include "CtlUtil.hpp"
#ifdef ZT_CONTROLLER_USE_LIBPQ
#include <sstream>
#include <iomanip>
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

16
controller/CtlUtil.hpp Normal file
View file

@ -0,0 +1,16 @@
#ifndef ZT_CTLUTIL_HPP
#define ZT_CTLUTIL_HPP
#include <vector>
#include <string>
namespace ZeroTier {
const char *_timestr();
std::vector<std::string> split(std::string str, char delim);
std::string url_encode(const std::string &value);
}
#endif // namespace ZeroTier

View file

@ -75,6 +75,10 @@ public:
*/
class DB
{
#ifdef ZT_CONTROLLER_USE_LIBPQ
friend class MemberNotificationReceiver;
friend class NetworkNotificationReceiver;
#endif
public:
class ChangeListener
{

View file

@ -40,7 +40,8 @@
#include "LFDB.hpp"
#include "FileDB.hpp"
#ifdef ZT_CONTROLLER_USE_LIBPQ
#include "PostgreSQL.hpp"
#include "CV1.hpp"
#include "CV2.hpp"
#endif
#include "../node/Node.hpp"
@ -534,7 +535,9 @@ void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender)
#ifdef ZT_CONTROLLER_USE_LIBPQ
if ((_path.length() > 9)&&(_path.substr(0,9) == "postgres:")) {
_db.addDB(std::shared_ptr<DB>(new PostgreSQL(_signingId,_path.substr(9).c_str(), _listenPort, _rc)));
_db.addDB(std::shared_ptr<DB>(new CV1(_signingId,_path.substr(9).c_str(), _listenPort, _rc)));
} else if ((_path.length() > 3)&&(_path.substr(0,3) == "cv2:")) {
_db.addDB(std::shared_ptr<DB>(new CV2(_signingId,_path.c_str(),_listenPort)));
} else {
#endif
_db.addDB(std::shared_ptr<DB>(new FileDB(_path.c_str())));
@ -1548,7 +1551,8 @@ void EmbeddedNetworkController::_request(
authInfo.add(ZT_AUTHINFO_DICT_KEY_CENTRAL_ENDPOINT_URL, info.centralAuthURL.c_str());
authInfo.add(ZT_AUTHINFO_DICT_KEY_NONCE, info.ssoNonce.c_str());
authInfo.add(ZT_AUTHINFO_DICT_KEY_STATE, info.ssoState.c_str());
authInfo.add(ZT_AUTHINFO_DICT_KEY_CLIENT_ID, info.ssoClientID.c_str());
authInfo.add(ZT_AUTHINFO_DICT_KEY_CLIENT_ID, info.ssoClientID.c_str());
authInfo.add(ZT_AUTHINFO_DICT_KEY_SSO_PROVIDER, info.ssoProvider.c_str());
_sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED, authInfo.data(), authInfo.sizeBytes());
}
DB::cleanMember(member);

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/*
* Copyright (c)2019 ZeroTier, Inc.
* 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.
@ -11,35 +11,22 @@
*/
/****/
#include "DB.hpp"
#ifdef ZT_CONTROLLER_USE_LIBPQ
#ifndef ZT_CONTROLLER_LIBPQ_HPP
#define ZT_CONTROLLER_LIBPQ_HPP
#define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4
#ifndef ZT_CONTROLLER_POSTGRESQL_HPP
#define ZT_CONTROLLER_POSTGRESQL_HPP
#include "DB.hpp"
#include "ConnectionPool.hpp"
#include <pqxx/pqxx>
#include <memory>
#include <redis++/redis++.h>
#include "../node/Metrics.hpp"
namespace ZeroTier {
extern "C" {
typedef struct pg_conn PGconn;
}
namespace smeeclient {
struct SmeeClient;
}
namespace ZeroTier {
struct RedisConfig;
class PostgresConnection : public Connection {
public:
@ -68,129 +55,32 @@ private:
std::string m_connString;
};
class PostgreSQL;
class MemberNotificationReceiver : public pqxx::notification_receiver {
public:
MemberNotificationReceiver(PostgreSQL *p, pqxx::connection &c, const std::string &channel);
MemberNotificationReceiver(DB *p, pqxx::connection &c, const std::string &channel);
virtual ~MemberNotificationReceiver() {
fprintf(stderr, "MemberNotificationReceiver destroyed\n");
}
virtual void operator() (const std::string &payload, int backendPid);
private:
PostgreSQL *_psql;
DB *_psql;
};
class NetworkNotificationReceiver : public pqxx::notification_receiver {
public:
NetworkNotificationReceiver(PostgreSQL *p, pqxx::connection &c, const std::string &channel);
NetworkNotificationReceiver(DB *p, pqxx::connection &c, const std::string &channel);
virtual ~NetworkNotificationReceiver() {
fprintf(stderr, "NetworkNotificationReceiver destroyed\n");
};
virtual void operator() (const std::string &payload, int packend_pid);
private:
PostgreSQL *_psql;
};
/**
* 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 PostgreSQL : public DB
{
friend class MemberNotificationReceiver;
friend class NetworkNotificationReceiver;
public:
PostgreSQL(const Identity &myId, const char *path, int listenPort, RedisConfig *rc);
virtual ~PostgreSQL();
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 AuthInfo getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL);
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>,std::pair<int64_t,InetAddress>,_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>,std::pair<int64_t,InetAddress>,_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;
DB *_psql;
};
} // namespace ZeroTier
#endif // ZT_CONTROLLER_LIBPQ_HPP
#endif // ZT_CONTROLLER_POSTGRESQL_HPP
#endif // ZT_CONTROLLER_USE_LIBPQ
#endif // ZT_CONTROLLER_USE_LIBPQ

6
debian/changelog vendored
View file

@ -1,3 +1,9 @@
zerotier-one (1.14.2) unstable; urgency=medium
* See RELEASE-NOTES.md for release notes.
-- Adam Ierymenko <adam.ierymenko@zerotier.com> Wed, 23 Oct 2024 01:00:00 -0700
zerotier-one (1.14.1) unstable; urgency=medium
* See RELEASE-NOTES.md for release notes.

View file

@ -9,15 +9,16 @@ mkztfile() {
file=$1
mode=$2
content=$3
echo "creating $file"
mkdir -p /var/lib/zerotier-one
echo "$content" > "/var/lib/zerotier-one/$file"
echo -n "$content" > "/var/lib/zerotier-one/$file"
chmod "$mode" "/var/lib/zerotier-one/$file"
}
if [ "x$ZEROTIER_API_SECRET" != "x" ]
then
mkztfile authtoken.secret 0600 "$ZEROTIER_API_SECRET"
mkztfile metricstoken.secret 0600 "$ZEROTIER_API_SECRET"
fi
if [ "x$ZEROTIER_IDENTITY_PUBLIC" != "x" ]
@ -30,6 +31,11 @@ then
mkztfile identity.secret 0600 "$ZEROTIER_IDENTITY_SECRET"
fi
if [ "x$ZEROTIER_LOCAL_CONF" != "x" ]
then
mkztfile local.conf 0644 "$ZEROTIER_LOCAL_CONF"
fi
mkztfile zerotier-one.port 0600 "9993"
killzerotier() {

View file

@ -701,7 +701,7 @@
<key>USE_HFS+_COMPRESSION</key>
<false/>
<key>VERSION</key>
<string>1.14.1</string>
<string>1.14.2</string>
</dict>
<key>TYPE</key>
<integer>0</integer>

View file

@ -24,10 +24,10 @@
<ROW Property="AiFeatIcoZeroTierOne" Value="ZeroTierIcon.exe" Type="8"/>
<ROW Property="MSIFASTINSTALL" MultiBuildValue="DefaultBuild:2"/>
<ROW Property="Manufacturer" Value="ZeroTier, Inc."/>
<ROW Property="ProductCode" Value="1033:{EC58088A-4E0F-4BD5-B0B2-FD81C803EEC4} " Type="16"/>
<ROW Property="ProductCode" Value="1033:{0143A36C-46C6-458D-AB9B-C8843E089323} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="ZeroTier One"/>
<ROW Property="ProductVersion" Value="1.14.0" Options="32"/>
<ROW Property="ProductVersion" Value="1.14.2" Options="32"/>
<ROW Property="REBOOT" MultiBuildValue="DefaultBuild:ReallySuppress"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND;AI_SETUPEXEPATH;SETUPEXEDIR"/>
<ROW Property="UpgradeCode" Value="{B0E2A5F3-88B6-4E77-B922-CB4739B4C4C8}"/>
@ -62,7 +62,7 @@
<ROW Directory="regid.201001.com.zerotier_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="REGID2~1.ZER|regid.2010-01.com.zerotier" DirectoryOptions="12"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="AI_CustomARPName" ComponentId="{8BC01817-02AC-4C44-A84C-0727BC5B6E22}" Directory_="APPDIR" Attributes="4" KeyPath="DisplayName" Options="1"/>
<ROW Component="AI_CustomARPName" ComponentId="{DFE7A60C-C2B9-41F6-9171-8955BA30E556}" Directory_="APPDIR" Attributes="4" KeyPath="DisplayName" Options="1"/>
<ROW Component="AI_DisableModify" ComponentId="{46FFA8C5-A0CB-4E05-9AD3-911D543DE8CA}" Directory_="APPDIR" Attributes="4" KeyPath="NoModify" Options="1"/>
<ROW Component="AI_ExePath" ComponentId="{8E02B36C-7A19-429B-A93E-77A9261AC918}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/>
<ROW Component="APPDIR" ComponentId="{4DD7907D-D7FE-4CD6-B1A0-B5C1625F5133}" Directory_="APPDIR" Attributes="0"/>
@ -498,7 +498,7 @@
<ROW XmlAttribute="xsischemaLocation" XmlElement="swidsoftware_identification_tag" Name="xsi:schemaLocation" Flags="14" Order="3" Value="http://standards.iso.org/iso/19770/-2/2008/schema.xsd software_identification_tag.xsd"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.XmlElementComponent">
<ROW XmlElement="swidbuild" ParentElement="swidnumeric" Name="swid:build" Condition="1" Order="2" Flags="14" Text="0" UpdateIndexInParent="0"/>
<ROW XmlElement="swidbuild" ParentElement="swidnumeric" Name="swid:build" Condition="1" Order="2" Flags="14" Text="2" UpdateIndexInParent="0"/>
<ROW XmlElement="swidentitlement_required_indicator" ParentElement="swidsoftware_identification_tag" Name="swid:entitlement_required_indicator" Condition="1" Order="0" Flags="14" Text="false" UpdateIndexInParent="0"/>
<ROW XmlElement="swidmajor" ParentElement="swidnumeric" Name="swid:major" Condition="1" Order="0" Flags="14" Text="1" UpdateIndexInParent="0"/>
<ROW XmlElement="swidminor" ParentElement="swidnumeric" Name="swid:minor" Condition="1" Order="1" Flags="14" Text="14" UpdateIndexInParent="0"/>

View file

@ -8,6 +8,7 @@
namespace prometheus {
// структура, в которую копируются значения метрик перед их сериализацией
struct ClientMetric {
// Label

View file

@ -84,7 +84,7 @@ extern "C" {
/**
* Minimum UDP payload size allowed
*/
#define ZT_MIN_PHYSMTU 1400
#define ZT_MIN_PHYSMTU 510
/**
* Maximum physical interface name length. This number is gigantic because of Windows.

View file

@ -57,9 +57,9 @@ ONE_OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connec
ifeq ($(ZT_CONTROLLER),1)
MACOS_VERSION_MIN=10.15
override CXXFLAGS=$(CFLAGS) -std=c++17 -stdlib=libc++
LIBS+=-L/usr/local/opt/libpqxx/lib -L/usr/local/opt/libpq/lib -L/usr/local/opt/openssl/lib/ -lpqxx -lpq -lssl -lcrypto -lgssapi_krb5 ext/redis-plus-plus-1.1.1/install/macos/lib/libredis++.a ext/hiredis-0.14.1/lib/macos/libhiredis.a
LIBS+=-L/opt/homebrew/lib -L/usr/local/opt/libpqxx/lib -L/usr/local/opt/libpq/lib -L/usr/local/opt/openssl/lib/ -lpqxx -lpq -lssl -lcrypto -lgssapi_krb5 ext/redis-plus-plus-1.1.1/install/macos/lib/libredis++.a ext/hiredis-0.14.1/lib/macos/libhiredis.a rustybits/target/libsmeeclient.a
DEFS+=-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER_USE_REDIS -DZT_CONTROLLER
INCLUDES+=-I/usr/local/opt/libpq/include -I/usr/local/opt/libpqxx/include -Iext/hiredis-0.14.1/include/ -Iext/redis-plus-plus-1.1.1/install/macos/include/sw/
INCLUDES+=-I/opt/homebrew/include -I/opt/homebrew/opt/libpq/include -I/usr/local/opt/libpq/include -I/usr/local/opt/libpqxx/include -Iext/hiredis-0.14.1/include/ -Iext/redis-plus-plus-1.1.1/install/macos/include/sw/ -Irustybits/target/
else
MACOS_VERSION_MIN=10.13
endif
@ -115,7 +115,11 @@ mac-agent: FORCE
osdep/MacDNSHelper.o: osdep/MacDNSHelper.mm
$(CXX) $(CXXFLAGS) -c osdep/MacDNSHelper.mm -o osdep/MacDNSHelper.o
ifeq ($(ZT_CONTROLLER),1)
one: zeroidc smeeclient $(CORE_OBJS) $(ONE_OBJS) one.o mac-agent
else
one: zeroidc $(CORE_OBJS) $(ONE_OBJS) one.o mac-agent
endif
$(CXX) $(CXXFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LIBS) rustybits/target/libzeroidc.a
# $(STRIP) zerotier-one
ln -sf zerotier-one zerotier-idtool
@ -126,6 +130,15 @@ zerotier-one: one
zeroidc: rustybits/target/libzeroidc.a
ifeq ($(ZT_CONTROLLER),1)
smeeclient: rustybits/target/libsmeeclient.a
rustybits/target/libsmeeclient.a: FORCE
cd rustybits && MACOSX_DEPLOYMENT_TARGET=$(MACOS_VERSION_MIN) cargo build -p smeeclient --target=x86_64-apple-darwin $(EXTRA_CARGO_FLAGS)
cd rustybits && MACOSX_DEPLOYMENT_TARGET=$(MACOS_VERSION_MIN) cargo build -p smeeclient --target=aarch64-apple-darwin $(EXTRA_CARGO_FLAGS)
cd rustybits && lipo -create target/x86_64-apple-darwin/$(RUST_VARIANT)/libsmeeclient.a target/aarch64-apple-darwin/$(RUST_VARIANT)/libsmeeclient.a -output target/libsmeeclient.a
endif
rustybits/target/libzeroidc.a: FORCE
cd rustybits && MACOSX_DEPLOYMENT_TARGET=$(MACOS_VERSION_MIN) cargo build -p zeroidc --target=x86_64-apple-darwin $(EXTRA_CARGO_FLAGS)
cd rustybits && MACOSX_DEPLOYMENT_TARGET=$(MACOS_VERSION_MIN) cargo build -p zeroidc --target=aarch64-apple-darwin $(EXTRA_CARGO_FLAGS)
@ -194,6 +207,9 @@ controller-run: _buildx FORCE
central-controller-docker: _buildx FORCE
docker buildx build --platform linux/arm64,linux/amd64 --no-cache -t registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=$(shell git name-rev --name-only HEAD) . --push
@echo Image: registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP}
docker-release: _buildx
docker buildx build --platform linux/386,linux/amd64,linux/arm/v7,linux/arm64,linux/mips64le,linux/ppc64le,linux/s390x -t zerotier/zerotier:${RELEASE_DOCKER_TAG} -t zerotier/zerotier:latest --build-arg VERSION=${RELEASE_VERSION} -f Dockerfile.release . --push
clean:
rm -rf MacEthernetTapAgent *.dSYM build-* *.a *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o $(CORE_OBJS) $(ONE_OBJS) zerotier-one zerotier-idtool zerotier-selftest zerotier-cli zerotier doc/node_modules zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_* rustybits/target/

View file

@ -30,7 +30,8 @@ CORE_OBJS=\
node/Trace.o \
node/Utils.o \
node/Bond.o \
node/PacketMultiplexer.o
node/PacketMultiplexer.o \
osdep/OSUtils.o
ONE_OBJS=\
controller/EmbeddedNetworkController.o \
@ -38,11 +39,13 @@ ONE_OBJS=\
controller/DB.o \
controller/FileDB.o \
controller/LFDB.o \
controller/CtlUtil.o \
controller/PostgreSQL.o \
controller/CV1.o \
controller/CV2.o \
osdep/EthernetTap.o \
osdep/ManagedRoute.o \
osdep/Http.o \
osdep/OSUtils.o \
service/SoftwareUpdater.o \
service/OneService.o

View file

@ -431,10 +431,13 @@ void BSDEthernetTap::threadMain()
// constructing itself.
Thread::sleep(500);
for (unsigned int i = 0; i < _concurrency; ++i) {
_rxThreads.push_back(std::thread([this, i, _pinning] {
#ifndef __OpenBSD__
bool pinning = _pinning;
if (_pinning) {
for (unsigned int i = 0; i < _concurrency; ++i) {
_rxThreads.push_back(std::thread([this, i, pinning] {
if (pinning) {
int pinCore = i % _concurrency;
fprintf(stderr, "Pinning thread %d to core %d\n", i, pinCore);
pthread_t self = pthread_self();
@ -449,6 +452,7 @@ void BSDEthernetTap::threadMain()
exit(1);
}
}
#endif // __OpenBSD__
uint8_t b[ZT_TAP_BUF_SIZE];
MAC to, from;
@ -495,8 +499,10 @@ void BSDEthernetTap::threadMain()
}
}
}
#ifndef __OpenBSD__
}));
}
#endif // __OpenBSD__
}
} // namespace ZeroTier

View file

@ -140,7 +140,7 @@ std::shared_ptr<EthernetTap> EthernetTap::newInstance(
#endif // __NetBSD__
#ifdef __OpenBSD__
return std::shared_ptr<EthernetTap>(new BSDEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
return std::shared_ptr<EthernetTap>(new BSDEthernetTap(homePath,concurrency,pinning,mac,mtu,metric,nwid,friendlyName,handler,arg));
#endif // __OpenBSD__
#endif // ZT_SDK?

1043
rustybits/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,10 @@ use serde::{Deserialize, Serialize};
use std::str::FromStr;
use std::time::Duration;
use temporal_client::{Client, ClientOptionsBuilder, RetryClient, WorkflowClientTrait, WorkflowOptions};
use temporal_sdk_core_protos::{coresdk::AsJsonPayloadExt, temporal::api::enums::v1::WorkflowIdReusePolicy};
use temporal_sdk_core_protos::{
coresdk::AsJsonPayloadExt,
temporal::api::enums::v1::{WorkflowIdConflictPolicy, WorkflowIdReusePolicy},
};
use url::Url;
use uuid::Uuid;
@ -72,6 +75,7 @@ impl SmeeClient {
println!("notifying network joined");
let options = WorkflowOptions {
id_reuse_policy: WorkflowIdReusePolicy::RejectDuplicate,
id_conflict_policy: WorkflowIdConflictPolicy::Fail,
execution_timeout: None,
run_timeout: None,
task_timeout: None,

View file

@ -2599,6 +2599,7 @@ public:
fprintf(stderr,"WARNING: using manually-specified secondary and/or tertiary ports. This can cause NAT issues." ZT_EOL_S);
}
_portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"],true);
_node->setLowBandwidthMode(OSUtils::jsonBool(settings["lowBandwidthMode"],false));
#if defined(__LINUX__) || defined(__FreeBSD__)
_multicoreEnabled = OSUtils::jsonBool(settings["multicoreEnabled"],false);
_concurrency = OSUtils::jsonInt(settings["concurrency"],1);

View file

@ -27,7 +27,7 @@
/**
* Revision
*/
#define ZEROTIER_ONE_VERSION_REVISION 1
#define ZEROTIER_ONE_VERSION_REVISION 2
/**
* Build version

View file

@ -1,5 +1,5 @@
Name: zerotier-one
Version: 1.14.1
Version: 1.14.2
Release: 1%{?dist}
Summary: ZeroTier network virtualization service
@ -155,6 +155,9 @@ chmod 0755 $RPM_BUILD_ROOT/etc/init.d/zerotier-one
%endif
%changelog
* Wed Oct 23 2024 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.14.2
- see https://github.com/zerotier/ZeroTierOne for release notes
* Tue Mar 19 2024 Adam Ierymenko <adam.ierymenko@zerotier.com> - 1.14.0
- see https://github.com/zerotier/ZeroTierOne for release notes