Compare commits

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

40 commits

Author SHA1 Message Date
Joseph Henry
dcb4bc5ef4
Fix path typo: 3rdpatry
Some checks failed
/ build_macos (push) Has been cancelled
/ build_windows (push) Has been cancelled
/ build_ubuntu (push) Has been cancelled
2025-03-04 11:18:13 -08:00
Joseph Henry
47e05d5a23
Disable peer metrics for ExtOSDep builds 2025-03-04 10:34:57 -08:00
Joseph Henry
17abb58651
Add missing include to ExtOsDep.hpp 2025-03-04 10:26:31 -08:00
Joseph Henry
05b60bd818
Fix typo 2025-03-04 10:25:06 -08:00
Joseph Henry
269c8d415a
Style match 2025-02-26 11:16:03 -08:00
Joseph Henry
cd191778c2
Add custom management plane for 3rd party vendors 2025-02-26 10:27:23 -08:00
Joseph Henry
3e7aacf301
Expose routing() method in httplib so changes can be made in OneService 2025-02-26 09:56:08 -08:00
Joseph Henry
6b113c8270
Add auto-detection of platform integer size in prometheus 2025-02-26 09:55:08 -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
34 changed files with 1748 additions and 441 deletions

View file

@ -44,7 +44,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

@ -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

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

@ -917,6 +917,8 @@ public:
std::function<TaskQueue *(void)> new_task_queue;
bool routing(Request &req, Response &res, Stream &strm);
protected:
bool process_request(Stream &strm, bool close_connection,
bool &connection_closed,
@ -949,7 +951,6 @@ private:
int bind_internal(const std::string &host, int port, int socket_flags);
bool listen_internal();
bool routing(Request &req, Response &res, Stream &strm);
bool handle_file_request(const Request &req, Response &res,
bool head = false);
bool dispatch_request(Request &req, Response &res,

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

@ -5,7 +5,7 @@ option(PROMETHEUS_BUILD_EXAMPLES "Build with examples" OFF)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
if(WIN32)
if(WIN32)
# it prevent create Debug/ and Release folders in Visual Studio
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
@ -25,7 +25,7 @@ add_subdirectory("./core")
add_subdirectory("./simpleapi")
add_subdirectory("./3rdpatry/http-client-lite")
add_subdirectory("./3rdparty/http-client-lite")
if(PROMETHEUS_BUILD_EXAMPLES)
add_subdirectory("./examples")

View file

@ -6,70 +6,81 @@ It is a tool for quickly adding metrics (and profiling) functionality to C++ pro
1. Written in pure C++,
2. Header-only,
2. Cross-platform,
3. Compiles with C ++ 11, C ++ 14, C ++ 17 standards,
4. Has no third-party dependencies,
5. Several APIs for use in your projects,
6. Saving metrics to a file (and then works with node_exporter) or sending via http (uses built-in header-only http-client-lite library),
7. Possiblity to use different types for storing metrics data (default is uint32_t, but you can use double or uint64_t types if you want),
8. Five types of metrics are supported: counter, gauge, summary, histogram and benchmark,
3. Cross-platform,
4. Compiles with C ++ 11, C ++ 14, C ++ 17 standards,
5. Has no third-party dependencies,
6. Several APIs for use in your projects,
7. Saving metrics to a file (and then works with node_exporter) or sending via http (uses built-in header-only http-client-lite library),
8. Possiblity to use different types for storing metrics data (default is uint32_t, but you can use double or uint64_t types if you want),
9. Five types of metrics are supported: counter, gauge, summary, histogram and benchmark,
10. Has detailed examples of use (see examples folder)
## How it differs from the [jupp0r/prometheus-cpp](https://github.com/jupp0r/prometheus-cpp) project:
1. I need a simple header only wariant library without dependencies to write metrics to a .prom file,
2. I need the fastest possible work using integer values of counters (original project use only floating pointer values),
3. The origianl project have problems on compilers that do not know how to do LTO optimization,
4. I did not like the python style of the original project and the large amount of extra code in it and I wanted to make it lighter and more c++ classic.
## How to use it:
The library has two API:
1. Complex API for those who want to control everything,
2. Simple API for those who want to quickly add metrics to their C ++ (and it is actually just a wrapper around the complex API).
### Let's start with a simple API because it's simple:
To add it to your C++ project add these lines to your CMakeLists.txt file:
```
add_subdirectory("prometheus-cpp-lite/core")
add_subdirectory("prometheus-cpp-lite/3rdpatry/http-client-lite")
add_subdirectory("prometheus-cpp-lite/3rdparty/http-client-lite")
add_subdirectory("prometheus-cpp-lite/simpleapi")
target_link_libraries(your_target prometheus-cpp-simpleapi)
```
The simplest way to create a metric would be like this:
``` c++
```c++
prometheus::simpleapi::METRIC_metric_t metric1 { "metric1", "first simple metric without any tag" };
prometheus::simpleapi::METRIC_metric_t metric2 { "metric2", "second simple metric without any tag" };
```
where ```METRIC``` can be ```counter```, ```gauge```, ```summary```, ```histogram``` or ```benchmark```.
where `METRIC` can be `counter`, `gauge`, `summary`, `histogram` or `benchmark`.
If you want to access an existing metric again elsewhere in the code, you can do this:
``` c++
```c++
prometheus::simpleapi::METRIC_metric_t metric2_yet_another_link { "metric2", "" };
```
this works because when adding a metric, it checks whether there is already a metric with the same name and, if there is one, a link to it is returned.
You can create a family of metrics (metrics with tags) as follows:
``` c++
```c++
prometheus::simpleapi::METRIC_family_t family { "metric_family", "metric family" };
prometheus::simpleapi::METRIC_metric_t metric1 { family.Add({{"name", "metric1"}}) };
prometheus::simpleapi::METRIC_metric_t metric2 { family.Add({{"name", "metric2"}}) };
```
where METRIC can be ```counter```, ```gauge```, ```summary```, ```histogram``` or ```benchmark```.
where METRIC can be `counter`, `gauge`, `summary`, `histogram` or `benchmark`.
Next, you can do the following things with metrics:
``` c++
```c++
metric++; // for increment it (only for counter and gauge metrics)
metric += value; // for add value to metric (only for gauge metric)
metric -= value; // for sub value from metric (only for gauge metric)
metric -= value; // for sub value from metric (only for gauge metric)
metric = value; // save current value (only gauge metrics)
metric.start(); // start calculate time (only for benchmark metric)
metric.stop(); // stop calculate time (only for benchmark metric)
```
You can change the settings of save (or send) metrics data as follows:
``` c++
```c++
prometheus::simpleapi::saver.set_delay(period_in_seconds); // change the period of saving (or sending) metrics data in seconds (5 seconds by default)
prometheus::simpleapi::saver.set_out_file(filename); // change the name of the output file (metrics.prom by default)
prometheus::simpleapi::saver.set_server_url(url); // change the name of prometheus server (unset by default)
@ -77,7 +88,7 @@ prometheus::simpleapi::saver.set_server_url(url); // change the name of
### Simple API complex example 1 (examples/simpleapi_example.cpp):
``` c++
```c++
#include <prometheus/simpleapi.h>
void main() {
@ -120,7 +131,7 @@ simple_counter_2 8
### Simple API complex example 2 (examples/simpleapi_use_in_class_example.cpp):
``` c++
```c++
#include <prometheus/simpleapi.h>
using namespace prometheus::simpleapi;
@ -198,4 +209,3 @@ simple_benchmark_family{benchmark="2"} 1.48e-05
# TYPE simple_benchmark counter
simple_benchmark 6.0503248
```

View file

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

View file

@ -25,7 +25,18 @@ namespace prometheus {
///
/// The class is thread-safe. No concurrent call to any API of this type causes
/// a data race.
template <typename Value_ = uint64_t>
#include <stdint.h>
#if UINTPTR_MAX == 0xffFFffFF
// 32-bit platform
template <typename Value_ = uint32_t>
#elif UINTPTR_MAX == 0xffFFffFFffFFffFF
// 64-bit platform
template <typename Value_ = uint64_t>
#else
#error Unknown platform - does not look either like 32-bit or 64-bit
#endif
class Counter : public Metric {
std::atomic<Value_> value{ 0 };

View file

@ -23,7 +23,17 @@ namespace prometheus {
///
/// The class is thread-safe. No concurrent call to any API of this type causes
/// a data race.
#include <stdint.h>
#if UINTPTR_MAX == 0xffFFffFF
// 32-bit
template <typename Value_ = uint32_t>
#elif UINTPTR_MAX == 0xffFFffFFffFFffFF
// 64-bit
template <typename Value_ = uint64_t>
#else
#error Unknown platform - does not look either like 32-bit or 64-bit
#endif
class Gauge : public Metric {
std::atomic<Value_> value { 0 };

View file

@ -15,6 +15,17 @@
#include <memory>
#include <functional>
#include <stdexcept>
#include <stdint.h>
#if UINTPTR_MAX == 0xffFFffFF
// 32-bit
typedef uint32_t metric_size;
#elif UINTPTR_MAX == 0xffFFffFFffFFffFF
// 64-bit
typedef uint64_t metric_size;
#else
#error Unknown platform - does not look either like 32-bit or 64-bit
#endif
namespace prometheus {
namespace simpleapi {
@ -46,7 +57,7 @@ namespace prometheus {
public:
using Metric = Counter<uint64_t>;
using Metric = Counter<metric_size>;
using Family = Metric::Family;
private:
@ -82,7 +93,7 @@ namespace prometheus {
public:
using Metric = Gauge<int64_t>;
using Metric = Gauge<metric_size>;
using Family = Metric::Family;
private:

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

@ -16,8 +16,13 @@ DESTDIR?=
EXTRA_DEPS?=
include objects.mk
ONE_OBJS+=osdep/LinuxEthernetTap.o
ONE_OBJS+=osdep/LinuxNetLink.o
ifeq ($(ZT_EXTOSDEP),1)
ONE_OBJS+=osdep/ExtOsdep.o
override DEFS += -DZT_EXTOSDEP
else
ONE_OBJS+=osdep/LinuxEthernetTap.o
ONE_OBJS+=osdep/LinuxNetLink.o
endif
# for central controller buildsk
TIMESTAMP=$(shell date +"%Y%m%d%H%M")
@ -275,6 +280,10 @@ ifeq ($(CC_MACH),loongarch64)
override DEFS+=-DZT_NO_TYPE_PUNNING
endif
ifeq ($(ZT_EXTOSDEP), 1)
ZT_SSO_SUPPORTED=0
endif
# Fail if system architecture could not be determined
ifeq ($(ZT_ARCHITECTURE),999)
ERR=$(error FATAL: architecture could not be determined from $(CC) -dumpmachine: $(CC_MACH))
@ -339,8 +348,12 @@ ifeq ($(ZT_ARCHITECTURE),3)
override CXXFLAGS+=-march=armv5t -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm
ZT_USE_ARM32_NEON_ASM_CRYPTO=0
else
override CFLAGS+=-mfloat-abi=hard -march=armv6zk -marm -mfpu=vfp -mno-unaligned-access -mtp=cp15 -mcpu=arm1176jzf-s
override CXXFLAGS+=-mfloat-abi=hard -march=armv6zk -marm -mfpu=vfp -fexceptions -mno-unaligned-access -mtp=cp15 -mcpu=arm1176jzf-s
ifeq ($(ZT_EXTOSDEP), 0)
override CFLAGS+=-mfloat-abi=hard -march=armv6zk -marm -mfpu=vfp -mno-unaligned-access -mtp=cp15 -mcpu=arm1176jzf-s
override CXXFLAGS+=-mfloat-abi=hard -march=armv6zk -marm -mfpu=vfp -fexceptions -mno-unaligned-access -mtp=cp15 -mcpu=arm1176jzf-s
else
override DEFS+=-DZT_NO_PEER_METRICS
endif
ZT_USE_ARM32_NEON_ASM_CRYPTO=0
endif
endif

View file

@ -194,6 +194,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 \
@ -42,7 +43,6 @@ ONE_OBJS=\
osdep/EthernetTap.o \
osdep/ManagedRoute.o \
osdep/Http.o \
osdep/OSUtils.o \
service/SoftwareUpdater.o \
service/OneService.o

31
one.cpp
View file

@ -57,6 +57,7 @@
#include <sys/socket.h>
#include <ifaddrs.h>
#include <sys/ioctl.h>
#include "osdep/ExtOsdep.hpp"
#ifndef ZT_NO_CAPABILITIES
#include <linux/capability.h>
#include <linux/securebits.h>
@ -2110,6 +2111,17 @@ int main(int argc,char **argv)
signal(SIGQUIT,&_sighandlerQuit);
signal(SIGINT,&_sighandlerQuit);
#ifdef ZT_EXTOSDEP
int extosdepFd1 = -1;
int extosdepFd2 = -1;
for(int i=1;i<argc;++i) {
if (argv[i][0] != '-' || argv[i][1] != 'x') continue;
if (sscanf(argv[i] + 2, "%d,%d", &extosdepFd1, &extosdepFd2) == 2) break;
fprintf(stderr, "bad extosdepFd\n");
return 1;
}
#endif // ZT_EXTOSDEP
/* Ensure that there are no inherited file descriptors open from a previous
* incarnation. This is a hack to ensure that GitHub issue #61 or variants
* of it do not return, and should not do anything otherwise bad. */
@ -2117,8 +2129,12 @@ int main(int argc,char **argv)
int mfd = STDIN_FILENO;
if (STDOUT_FILENO > mfd) mfd = STDOUT_FILENO;
if (STDERR_FILENO > mfd) mfd = STDERR_FILENO;
for(int f=mfd+1;f<1024;++f)
for(int f=mfd+1;f<1024;++f) {
#ifdef ZT_EXTOSDEP
if (f == extosdepFd1 || f == extosdepFd2) continue;
#endif // ZT_EXTOSDEP
::close(f);
}
}
bool runAsDaemon = false;
@ -2224,7 +2240,9 @@ int main(int argc,char **argv)
return 0;
} break;
#endif // __WINDOWS__
#ifdef ZT_EXTOSDEP
case 'x': break;
#endif
case 'h':
case '?':
default:
@ -2354,6 +2372,15 @@ int main(int argc,char **argv)
}
#endif // __UNIX_LIKE__
#ifdef ZT_EXTOSDEP
if (extosdepFd1 < 0) {
fprintf(stderr, "no extosdepFd specified\n");
OSUtils::rm(pidPath.c_str());
return 1;
}
ExtOsdep::init(extosdepFd1, extosdepFd2);
#endif
_OneServiceRunner thr(argv[0],homeDir,port);
thr.threadMain();
//Thread::join(Thread::start(&thr));

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

@ -53,6 +53,7 @@
#include "../node/Utils.hpp"
#include "OSUtils.hpp"
#include "Phy.hpp"
#include "../osdep/ExtOsdep.hpp"
#include <algorithm>
#include <atomic>
@ -136,6 +137,25 @@ class Binder {
bool interfacesEnumerated = true;
if (explicitBind.empty()) {
#ifdef ZT_EXTOSDEP
std::map<InetAddress,std::string> addrs;
interfacesEnumerated = ExtOsdep::getBindAddrs(addrs);
for (auto &a : addrs) {
auto ip = a.first;
switch(ip.ipScope()) {
default: break;
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
case InetAddress::IP_SCOPE_GLOBAL:
case InetAddress::IP_SCOPE_SHARED:
case InetAddress::IP_SCOPE_PRIVATE:
for(int x=0;x<(int)portCount;++x) {
ip.setPort(ports[x]);
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,a.second));
}
break;
}
}
#else // ZT_EXTOSDEP
#ifdef __WINDOWS__
char aabuf[32768];
@ -386,6 +406,8 @@ class Binder {
#endif
#endif
#endif // ZT_EXTOSDEP
}
else {
for (std::vector<InetAddress>::const_iterator i(explicitBind.begin()); i != explicitBind.end(); ++i) {

View file

@ -32,6 +32,7 @@
#endif // __APPLE__
#ifdef __LINUX__
#include "ExtOsdep.hpp"
#include "LinuxEthernetTap.hpp"
#endif // __LINUX__
@ -94,7 +95,11 @@ std::shared_ptr<EthernetTap> EthernetTap::newInstance(
#endif // __APPLE__
#ifdef __LINUX__
#ifdef ZT_EXTOSDEP
return std::shared_ptr<EthernetTap>(new ExtOsdepTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
#else
return std::shared_ptr<EthernetTap>(new LinuxEthernetTap(homePath,concurrency,pinning,mac,mtu,metric,nwid,friendlyName,handler,arg));
#endif // ZT_EXTOSDEP
#endif // __LINUX__
#ifdef __WINDOWS__
@ -140,7 +145,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?

628
osdep/ExtOsdep.cpp Normal file
View file

@ -0,0 +1,628 @@
/*
* 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 "ExtOsdep.hpp"
#include "../node/AtomicCounter.hpp"
#include <fcntl.h>
#include <iostream>
#include <list>
#include <sys/times.h>
#include <unistd.h>
#define ZT_TAP_BUF_SIZE 16384
namespace ZeroTier {
static int eodFd = -1;
static Mutex eodMutex;
static int eodMgmtFd = -1;
struct EodRoute {
InetAddress target;
InetAddress via;
InetAddress src;
std::string ifname;
};
static std::list<EodRoute> allRoutes;
template <typename T> static void __eodSend(const T& t)
{
write(eodFd, &t, sizeof(t));
}
static void strncpyx(char* dest, const char* src, size_t n)
{
strncpy(dest, src, n);
if (n > 1) {
dest[n - 1] = 0;
}
}
static int __eodWait(unsigned char msg, unsigned char* d, unsigned l, unsigned maxl = 0, int* recvfd = nullptr)
{
if (! maxl) {
maxl = l;
}
auto start = times(NULL);
while (1) {
msghdr mh;
iovec iov;
struct {
size_t cmsg_len;
int cmsg_level;
int cmsg_type;
int fd;
} __attribute__((packed)) cmsg;
memset(&mh, 0, sizeof(mh));
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
if (recvfd) {
mh.msg_control = &cmsg;
mh.msg_controllen = sizeof(cmsg);
}
iov.iov_base = d;
iov.iov_len = maxl;
int r = recvmsg(eodFd, &mh, MSG_TRUNC | MSG_CMSG_CLOEXEC);
if (r > 0) {
if (recvfd && mh.msg_controllen >= sizeof(cmsg) && cmsg.cmsg_len == sizeof(cmsg) && cmsg.cmsg_level == SOL_SOCKET && cmsg.cmsg_type == SCM_RIGHTS) {
*recvfd = cmsg.fd;
fprintf(stderr, "eodWait: received fd %d\n", *recvfd);
}
if (d[0] != msg) {
fprintf(stderr, "eodWait: wrong msg, expected %u got %u\n", msg, d[0]);
return -1;
}
if ((unsigned)r < l || (unsigned)r > maxl) {
fprintf(stderr, "eodWait: wrong len, expected %u got %d\n", l, r);
return -1;
}
return r;
}
if (times(NULL) - start > 500) {
fprintf(stderr, "eodWait: timeout\n");
return -1;
}
usleep(100000);
}
}
template <typename T> static bool __eodWait(unsigned msg, T& t)
{
return __eodWait(msg, (unsigned char*)&t, sizeof(T)) == (int)sizeof(T);
}
template <typename M, typename R> static bool __eodXchg(const M& m, unsigned rm, R& r)
{
__eodSend(m);
return __eodWait(rm, r);
}
template <typename M, typename R> static bool eodXchg(const M& m, unsigned rm, R& r)
{
Mutex::Lock l(eodMutex);
return __eodXchg(m, rm, r);
}
void ExtOsdep::init(int fd1, int fd2)
{
eodFd = fd1;
eodMgmtFd = fd2;
fcntl(eodMgmtFd, F_SETFL, O_NONBLOCK);
}
void ExtOsdep::started(int* f, void** cp)
{
*f = eodMgmtFd;
*cp = (void*)eodMgmtFd;
unsigned char msg = ZT_EOD_MSG_STARTED;
Mutex::Lock l(eodMutex);
__eodSend(msg);
}
static std::string mgmtrd;
static std::string mgmtwr;
bool ExtOsdep::mgmtWritable(void* cookie)
{
if (cookie != (void*)eodMgmtFd) {
return false;
}
if (mgmtwr.size() == 0) {
return true;
}
auto sz = write(eodMgmtFd, mgmtwr.data(), mgmtwr.size());
if (sz <= 0) {
return false;
}
mgmtwr.erase(mgmtwr.begin(), mgmtwr.begin() + sz);
return mgmtwr.empty();
}
bool ExtOsdep::mgmtRecv(void* cookie, void* data, unsigned long len, std::function<unsigned(unsigned, const std::string&, const std::string&, std::string&)> cb)
{
if (cookie != (void*)eodMgmtFd) {
return false;
}
mgmtrd.append((char*)data, len);
while (1) {
auto req = (zt_eod_mgmt_req*)mgmtrd.data();
if (mgmtrd.size() < sizeof(*req)) {
break;
}
unsigned reqsz = sizeof(*req) + req->pathlen + req->datalen;
if (mgmtrd.size() < reqsz) {
break;
}
std::string resp;
char* p = (char*)req->data;
zt_eod_mgmt_reply rep;
rep.scode = cb(req->method, std::string(p, p + req->pathlen), std::string(p + req->pathlen, p + req->pathlen + req->datalen), resp);
rep.datalen = resp.size();
mgmtrd.erase(mgmtrd.begin(), mgmtrd.begin() + reqsz);
mgmtwr.append((char*)&rep, sizeof(rep));
mgmtwr.append(resp);
auto sz = write(eodMgmtFd, mgmtwr.data(), mgmtwr.size());
if (sz > 0) {
mgmtwr.erase(mgmtwr.begin(), mgmtwr.begin() + sz);
}
}
return ! mgmtwr.empty();
}
void ExtOsdep::routeAddDel(bool add, const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifname)
{
Mutex::Lock l(eodMutex);
std::string ifn;
if (ifname) {
ifn = ifname;
}
if (add) {
for (auto x = allRoutes.begin(); x != allRoutes.end(); ++x) {
if (x->target == target && x->via == via && x->src == src && x->ifname == ifn) {
return;
}
}
allRoutes.push_back({ target, via, src, ifn });
}
else {
bool found = false;
for (auto x = allRoutes.begin(); x != allRoutes.end(); ++x) {
if (x->target == target && x->via == via && x->src == src && x->ifname == ifn) {
allRoutes.erase(x);
found = true;
break;
}
}
if (! found) {
return;
}
}
zt_eod_msg_route req;
memset(&req, 0, sizeof(req));
req.cmd = add ? ZT_EOD_MSG_ADDROUTE : ZT_EOD_MSG_DELROUTE;
req.afi = target.isV4() ? 1 : 2;
req.dstlen = target.netmaskBits();
memcpy(req.dst, target.rawIpData(), target.isV4() ? 4 : 16);
if (ifname) {
strncpyx(req.dev, ifname, sizeof(req.dev));
}
if (via) {
memcpy(req.gw, via.rawIpData(), target.isV4() ? 4 : 16);
}
if (src) {
memcpy(req.src, src.rawIpData(), target.isV4() ? 4 : 16);
}
unsigned char resp;
__eodXchg(req, add ? ZT_EOD_MSG_ADDROUTERESP : ZT_EOD_MSG_DELROUTERESP, resp);
}
bool ExtOsdep::getBindAddrs(std::map<InetAddress, std::string>& ret)
{
Mutex::Lock l(eodMutex);
unsigned char req = ZT_EOD_MSG_GETBINDADDRS;
__eodSend(req);
zt_eod_msg_getbindaddrsresp* resp;
unsigned char buf[ZT_EOD_MAXMSGSIZE];
int r = __eodWait(ZT_EOD_MSG_GETBINDADDRSRESP, (unsigned char*)buf, sizeof(*resp), sizeof(buf));
if (r < (int)sizeof(*resp)) {
return false;
}
int c = (r - (int)sizeof(*resp)) / sizeof(resp->addrs[0]);
resp = (zt_eod_msg_getbindaddrsresp*)buf;
for (int i = 0; i < c; ++i) {
ret[InetAddress(resp->addrs[i].data, resp->addrs[i].afi == 1 ? 4 : 16, resp->addrs[i].len)] = resp->addrs[i].ifname;
}
return resp->result;
}
ExtOsdepTap::ExtOsdepTap(
const char* homePath,
const MAC& mac,
unsigned int mtu,
unsigned int metric,
uint64_t nwid,
const char* friendlyName,
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
void* arg)
: _handler(handler)
, _arg(arg)
, _nwid(nwid)
, _mac(mac)
, _homePath(homePath)
, _mtu(mtu)
, _fd(0)
, _enabled(true)
, _run(true)
{
zt_eod_msg_addtap req;
req.cmd = ZT_EOD_MSG_ADDTAP;
req.nwid = nwid;
req.mtu = mtu;
req.metric = metric;
strncpyx(req.fname, friendlyName, sizeof(req.fname));
mac.copyTo(req.mac, 6);
zt_eod_msg_addtapresp resp;
Mutex::Lock l(eodMutex);
__eodSend(req);
_fd = -1;
if (__eodWait(ZT_EOD_MSG_ADDTAPRESP, (unsigned char*)&resp, sizeof(resp), sizeof(resp), &_fd) != sizeof(resp)) {
throw std::runtime_error(std::string("could not create TAP"));
}
_dev = resp.name;
if (_dev.empty() || _fd < 0) {
throw std::runtime_error(std::string("could not create TAP"));
}
fcntl(_fd, F_SETFL, O_NONBLOCK);
(void)::pipe(_shutdownSignalPipe);
for (unsigned int t = 0; t < 2; ++t) {
_tapReaderThread[t] = std::thread([this, t] {
fd_set readfds, nullfds;
int n, nfds, r;
void* buf = nullptr;
std::vector<void*> buffers;
if (! _run) {
return;
}
FD_ZERO(&readfds);
FD_ZERO(&nullfds);
nfds = (int)std::max(_shutdownSignalPipe[0], _fd) + 1;
r = 0;
for (;;) {
FD_SET(_shutdownSignalPipe[0], &readfds);
FD_SET(_fd, &readfds);
select(nfds, &readfds, &nullfds, &nullfds, (struct timeval*)0);
if (FD_ISSET(_shutdownSignalPipe[0], &readfds)) { // writes to shutdown pipe terminate thread
break;
}
if (FD_ISSET(_fd, &readfds)) {
for (;;) { // read until there are no more packets, then return to outer select() loop
if (! buf) {
// To reduce use of the mutex, we keep a local buffer vector and
// swap (which is a pointer swap) with the global one when it's
// empty. This retrieves a batch of buffers to use.
if (buffers.empty()) {
std::lock_guard<std::mutex> l(_buffers_l);
buffers.swap(_buffers);
}
if (buffers.empty()) {
buf = malloc(ZT_TAP_BUF_SIZE);
if (! buf) {
break;
}
}
else {
buf = buffers.back();
buffers.pop_back();
}
}
n = (int)::read(_fd, reinterpret_cast<uint8_t*>(buf) + r, ZT_TAP_BUF_SIZE - r);
if (n > 0) {
// Some tap drivers like to send the ethernet frame and the
// payload in two chunks, so handle that by accumulating
// data until we have at least a frame.
r += n;
if (r > 14) {
if (r > ((int)_mtu + 14)) { // sanity check for weird TAP behavior on some platforms
r = _mtu + 14;
}
if (_enabled && _tapqsize.load() < 1000) {
++_tapqsize;
_tapq.post(std::pair<void*, int>(buf, r));
buf = nullptr;
}
r = 0;
}
}
else {
r = 0;
break;
}
}
}
}
});
}
_tapProcessorThread = std::thread([this] {
MAC to, from;
std::pair<void*, int> qi;
while (_tapq.get(qi)) {
--_tapqsize;
uint8_t* const b = reinterpret_cast<uint8_t*>(qi.first);
if (b) {
to.setTo(b, 6);
from.setTo(b + 6, 6);
unsigned int etherType = Utils::ntoh(((const uint16_t*)b)[6]);
_handler(_arg, nullptr, _nwid, from, to, etherType, 0, (const void*)(b + 14), (unsigned int)(qi.second - 14));
{
std::lock_guard<std::mutex> l(_buffers_l);
if (_buffers.size() < 128) {
_buffers.push_back(qi.first);
}
else {
free(qi.first);
}
}
}
else {
break;
}
}
});
}
ExtOsdepTap::~ExtOsdepTap()
{
_run = false;
(void)::write(_shutdownSignalPipe[1], "\0", 1); // causes reader thread(s) to exit
_tapq.post(std::pair<void*, int>(nullptr, 0)); // causes processor thread to exit
_tapReaderThread[0].join();
_tapReaderThread[1].join();
_tapProcessorThread.join();
::close(_fd);
::close(_shutdownSignalPipe[0]);
::close(_shutdownSignalPipe[1]);
for (std::vector<void*>::iterator i(_buffers.begin()); i != _buffers.end(); ++i) {
free(*i);
}
std::vector<std::pair<void*, int> > dv(_tapq.drain());
for (std::vector<std::pair<void*, int> >::iterator i(dv.begin()); i != dv.end(); ++i) {
if (i->first) {
free(i->first);
}
}
zt_eod_msg_deltap req;
req.cmd = ZT_EOD_MSG_DELTAP;
strcpy(req.name, _dev.c_str());
unsigned char resp;
eodXchg(req, ZT_EOD_MSG_DELTAPRESP, resp);
}
void ExtOsdepTap::setEnabled(bool en)
{
_enabled = en;
}
bool ExtOsdepTap::enabled() const
{
return _enabled;
}
void ExtOsdepTap::doRemoveIp(const InetAddress& ip)
{
zt_eod_msg_ip req;
req.cmd = ZT_EOD_MSG_DELIP;
strcpy(req.name, _dev.c_str());
req.afi = ip.isV4() ? 1 : 2;
req.len = ip.netmaskBits();
memcpy(req.data, ip.rawIpData(), ip.isV4() ? 4 : 16);
unsigned char resp;
__eodXchg(req, ZT_EOD_MSG_DELIPRESP, resp);
}
bool ExtOsdepTap::addIp(const InetAddress& ip)
{
Mutex::Lock l(eodMutex);
for (auto i = allIps.begin(); i != allIps.end(); ++i) {
if (*i == ip) {
return true;
}
if (i->ipsEqual(ip)) {
doRemoveIp(*i);
}
}
zt_eod_msg_ip req;
req.cmd = ZT_EOD_MSG_ADDIP;
strcpy(req.name, _dev.c_str());
req.afi = ip.isV4() ? 1 : 2;
req.len = ip.netmaskBits();
memcpy(req.data, ip.rawIpData(), ip.isV4() ? 4 : 16);
unsigned char resp;
__eodXchg(req, ZT_EOD_MSG_ADDIPRESP, resp);
allIps.push_back(ip);
return true;
}
bool ExtOsdepTap::addIps(std::vector<InetAddress> ips)
{
return false;
}
bool ExtOsdepTap::removeIp(const InetAddress& ip)
{
Mutex::Lock l(eodMutex);
for (auto i = allIps.begin(); i != allIps.end(); ++i) {
if (*i == ip) {
doRemoveIp(*i);
return true;
}
}
return false;
}
std::vector<InetAddress> ExtOsdepTap::ips() const
{
std::vector<InetAddress> ret;
Mutex::Lock l(eodMutex);
zt_eod_msg_getips req;
req.cmd = ZT_EOD_MSG_GETIPS;
strcpy(req.name, _dev.c_str());
__eodSend(req);
zt_eod_msg_getipsresp* resp;
unsigned char buf[ZT_EOD_MAXMSGSIZE];
int r = __eodWait(ZT_EOD_MSG_GETIPSRESP, (unsigned char*)buf, sizeof(*resp), sizeof(buf));
if (r < (int)sizeof(*resp)) {
return ret;
}
int c = (r - (int)sizeof(*resp)) / sizeof(resp->addrs[0]);
resp = (zt_eod_msg_getipsresp*)buf;
for (int i = 0; i < c; ++i) {
ret.push_back(InetAddress(resp->addrs[i].data, resp->addrs[i].afi == 1 ? 4 : 16, resp->addrs[i].len));
}
return ret;
}
void ExtOsdepTap::put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len)
{
char putBuf[ZT_MAX_MTU + 64];
if ((_fd > 0) && (len <= _mtu) && (_enabled)) {
to.copyTo(putBuf, 6);
from.copyTo(putBuf + 6, 6);
*((uint16_t*)(putBuf + 12)) = htons((uint16_t)etherType);
memcpy(putBuf + 14, data, len);
len += 14;
(void)::write(_fd, putBuf, len);
}
}
std::string ExtOsdepTap::deviceName() const
{
return _dev;
}
void ExtOsdepTap::setFriendlyName(const char* friendlyName)
{
}
void ExtOsdepTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed)
{
char *ptr, *ptr2;
unsigned char mac[6];
std::vector<MulticastGroup> newGroups;
int fd = ::open("/proc/net/dev_mcast", O_RDONLY);
if (fd > 0) {
char buf[131072];
int n = (int)::read(fd, buf, sizeof(buf));
if ((n > 0) && (n < (int)sizeof(buf))) {
buf[n] = (char)0;
for (char* l = strtok_r(buf, "\r\n", &ptr); (l); l = strtok_r((char*)0, "\r\n", &ptr)) {
int fno = 0;
char* devname = (char*)0;
char* mcastmac = (char*)0;
for (char* f = strtok_r(l, " \t", &ptr2); (f); f = strtok_r((char*)0, " \t", &ptr2)) {
if (fno == 1) {
devname = f;
}
else if (fno == 4) {
mcastmac = f;
}
++fno;
}
if ((devname) && (! strcmp(devname, _dev.c_str())) && (mcastmac) && (Utils::unhex(mcastmac, mac, 6) == 6)) {
newGroups.push_back(MulticastGroup(MAC(mac, 6), 0));
}
}
}
::close(fd);
}
std::vector<InetAddress> allIps(ips());
for (std::vector<InetAddress>::iterator ip(allIps.begin()); ip != allIps.end(); ++ip) {
newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip));
}
std::sort(newGroups.begin(), newGroups.end());
newGroups.erase(std::unique(newGroups.begin(), newGroups.end()), newGroups.end());
for (std::vector<MulticastGroup>::iterator m(newGroups.begin()); m != newGroups.end(); ++m) {
if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m)) {
added.push_back(*m);
}
}
for (std::vector<MulticastGroup>::iterator m(_multicastGroups.begin()); m != _multicastGroups.end(); ++m) {
if (! std::binary_search(newGroups.begin(), newGroups.end(), *m)) {
removed.push_back(*m);
}
}
_multicastGroups.swap(newGroups);
}
void ExtOsdepTap::setMtu(unsigned int mtu)
{
if (mtu == _mtu) {
return;
}
_mtu = mtu;
zt_eod_msg_setmtu req;
req.cmd = ZT_EOD_MSG_SETMTU;
strcpy(req.name, _dev.c_str());
req.mtu = mtu;
unsigned char resp;
eodXchg(req, ZT_EOD_MSG_SETMTURESP, resp);
}
} // namespace ZeroTier

215
osdep/ExtOsdep.hpp Normal file
View file

@ -0,0 +1,215 @@
/*
* 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.
*/
/****/
#ifndef ZT_EXTOSDEP_HPP
#define ZT_EXTOSDEP_HPP
#ifdef ZT_EXTOSDEP
#include <stdint.h>
#define ZT_EOD_MAXMSGSIZE (64 * 1024)
#define ZT_EOD_MSG_STARTED 1 // no data
#define ZT_EOD_MSG_ADDTAP 2
#define ZT_EOD_MSG_ADDTAPRESP 3
#define ZT_EOD_MSG_DELTAP 4
#define ZT_EOD_MSG_DELTAPRESP 5 // no data
#define ZT_EOD_MSG_SETMTU 6
#define ZT_EOD_MSG_SETMTURESP 7
#define ZT_EOD_MSG_ADDIP 8
#define ZT_EOD_MSG_ADDIPRESP 9
#define ZT_EOD_MSG_DELIP 10
#define ZT_EOD_MSG_DELIPRESP 11
#define ZT_EOD_MSG_GETIPS 12
#define ZT_EOD_MSG_GETIPSRESP 13
#define ZT_EOD_MSG_GETBINDADDRS 14
#define ZT_EOD_MSG_GETBINDADDRSRESP 15
#define ZT_EOD_MSG_ADDROUTE 16
#define ZT_EOD_MSG_ADDROUTERESP 17
#define ZT_EOD_MSG_DELROUTE 18
#define ZT_EOD_MSG_DELROUTERESP 19
struct zt_eod_msg_addtap {
unsigned char cmd;
uint64_t nwid;
uint32_t mtu;
uint32_t metric;
char fname[128];
unsigned char mac[6];
} __attribute__((packed));
struct zt_eod_msg_addtapresp {
unsigned char cmd;
char name[16];
} __attribute__((packed));
struct zt_eod_msg_deltap {
unsigned char cmd;
char name[16];
} __attribute__((packed));
struct zt_eod_msg_setmtu {
unsigned char cmd;
char name[16];
unsigned mtu;
} __attribute__((packed));
struct zt_eod_msg_ip {
unsigned char cmd;
char name[16];
unsigned char afi; // 1 ip, 2 ip6
unsigned char len; // bits in mask
unsigned char data[16];
} __attribute__((packed));
struct zt_eod_msg_getips {
unsigned char cmd;
char name[16];
} __attribute__((packed));
struct zt_eod_msg_getipsresp {
unsigned char cmd;
struct addr {
unsigned char afi;
unsigned char len;
unsigned char data[16];
} __attribute__((packed)) addrs[0];
} __attribute__((packed));
#define ZT_EOD_GETIPSRESP_MAXADDRS ((ZT_EOD_MAXMSGSIZE - sizeof(zt_eod_msg_getipsresp)) / sizeof(zt_eod_msg_getipsresp::addr))
struct zt_eod_msg_getbindaddrsresp {
unsigned char cmd;
unsigned char result;
struct addr {
unsigned char afi;
unsigned char len;
unsigned char data[16];
char ifname[16];
} __attribute__((packed)) addrs[0];
} __attribute__((packed));
#define ZT_EOD_GETBINDADDRSRESP_MAXADDRS ((ZT_EOD_MAXMSGSIZE - sizeof(zt_eod_msg_getbindaddrsresp)) / sizeof(zt_eod_msg_getbindaddrsresp::addr))
struct zt_eod_msg_route {
unsigned char cmd;
unsigned char afi; // 1 ip, 2 ip6
unsigned char dstlen;
unsigned char dst[16];
unsigned char gw[16];
char dev[16];
unsigned char src[16];
} __attribute__((packed));
struct zt_eod_mgmt_req {
uint32_t method;
uint32_t pathlen;
uint32_t datalen;
unsigned char data[0];
} __attribute__((packed));
struct zt_eod_mgmt_reply {
uint32_t scode;
uint32_t datalen;
unsigned char data[0];
} __attribute__((packed));
#ifndef ZT_EXTOSDEP_IFACEONLY
#include "../node/AtomicCounter.hpp"
#include "../node/Hashtable.hpp"
#include "../node/InetAddress.hpp"
#include "../node/MAC.hpp"
#include "../node/Mutex.hpp"
#include "BlockingQueue.hpp"
#include "EthernetTap.hpp"
#include "Thread.hpp"
#include <atomic>
#include <functional>
#include <mutex>
#include <string>
#include <thread>
namespace ZeroTier {
class ExtOsdep {
public:
static void init(int, int);
static void started(int*, void**);
static void routeAddDel(bool, const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifaceName);
static bool getBindAddrs(std::map<InetAddress, std::string>&);
static bool mgmtRecv(void* cookie, void* data, unsigned long len, std::function<unsigned(unsigned, const std::string&, const std::string&, std::string&)>);
static bool mgmtWritable(void*);
};
class ExtOsdepTap : public EthernetTap {
public:
ExtOsdepTap(
const char* homePath,
const MAC& mac,
unsigned int mtu,
unsigned int metric,
uint64_t nwid,
const char* friendlyName,
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
void* arg);
virtual ~ExtOsdepTap();
virtual void setEnabled(bool en);
virtual bool enabled() const;
virtual bool addIp(const InetAddress& ip);
virtual bool addIps(std::vector<InetAddress> ips);
virtual bool removeIp(const InetAddress& ip);
virtual std::vector<InetAddress> ips() const;
virtual void put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len);
virtual std::string deviceName() const;
virtual void setFriendlyName(const char* friendlyName);
virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed);
virtual void setMtu(unsigned int mtu);
virtual void setDns(const char* domain, const std::vector<InetAddress>& servers)
{
}
private:
void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);
void* _arg;
uint64_t _nwid;
MAC _mac;
std::string _homePath;
std::string _dev;
std::vector<MulticastGroup> _multicastGroups;
unsigned int _mtu;
int _fd;
int _shutdownSignalPipe[2];
std::atomic_bool _enabled;
std::atomic_bool _run;
std::thread _tapReaderThread[2];
std::thread _tapProcessorThread;
std::mutex _buffers_l;
std::vector<void*> _buffers;
BlockingQueue<std::pair<void*, int> > _tapq;
AtomicCounter _tapqsize;
std::vector<InetAddress> allIps;
void doRemoveIp(const InetAddress&);
};
} // namespace ZeroTier
#endif // ZT_EXTOSDEP_IFACEONLY
#endif // ZT_EXTOSDEP
#endif

View file

@ -51,6 +51,7 @@
#include "ManagedRoute.hpp"
#ifdef __LINUX__
#include "ExtOsdep.hpp"
#include "LinuxNetLink.hpp"
#endif
@ -550,6 +551,10 @@ bool ManagedRoute::sync()
#ifdef __LINUX__ // ----------------------------------------------------------
#ifdef ZT_EXTOSDEP
_applied[_target] = false;
ExtOsdep::routeAddDel(true, _target, _via, _src, _device);
#else
if ((leftt)&&(!LinuxNetLink::getInstance().routeIsSet(leftt,_via,_src,_device))) {
_applied[leftt] = false; // boolean unused
LinuxNetLink::getInstance().addRoute(leftt, _via, _src, _device);
@ -558,6 +563,7 @@ bool ManagedRoute::sync()
_applied[rightt] = false; // boolean unused
LinuxNetLink::getInstance().addRoute(rightt, _via, _src, _device);
}
#endif // ZT_EXTOSDEP
#endif // __LINUX__ ----------------------------------------------------------
@ -609,7 +615,11 @@ void ManagedRoute::remove()
#ifdef __LINUX__ // ----------------------------------------------------------
//_routeCmd("del",r->first,_via,(_via) ? (const char *)0 : _device);
#ifdef ZT_EXTOSDEP
ExtOsdep::routeAddDel(false, r->first,_via,_src,(_via) ? (const char *)0 : _device);
#else
LinuxNetLink::getInstance().delRoute(r->first,_via,_src,(_via) ? (const char *)0 : _device);
#endif // ZT_EXTOSDEP
#endif // __LINUX__ ----------------------------------------------------------
#ifdef __WINDOWS__ // --------------------------------------------------------

1036
rustybits/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -55,6 +55,7 @@
#include "../osdep/Binder.hpp"
#include "../osdep/ManagedRoute.hpp"
#include "../osdep/BlockingQueue.hpp"
#include "../osdep/ExtOsdep.hpp"
#include "OneService.hpp"
#include "SoftwareUpdater.hpp"
@ -1125,6 +1126,15 @@ public:
}
#endif
#ifdef ZT_EXTOSDEP
{
int mgmtfd;
void *mgmtcookie;
ExtOsdep::started(&mgmtfd, &mgmtcookie);
_phy.wrapSocket(mgmtfd, mgmtcookie);
}
#endif
// Delete legacy iddb.d if present (cleanup)
OSUtils::rmDashRf((_homePath + ZT_PATH_SEPARATOR_S "iddb.d").c_str());
@ -2165,7 +2175,6 @@ public:
auto statusGet = [&, setContent](const httplib::Request &req, httplib::Response &res) {
ZT_NodeStatus status;
_node->status(&status);
auto out = json::object();
char tmp[256] = {};
@ -2335,7 +2344,9 @@ public:
_controller->configureHTTPControlPlane(_controlPlane, _controlPlaneV6, setContent);
}
#ifndef ZT_EXTOSDEP
_controlPlane.set_pre_routing_handler(authCheck);
#endif // ZT_EXTOSDEP
_controlPlaneV6.set_pre_routing_handler(authCheck);
#if ZT_DEBUG==1
@ -2351,6 +2362,7 @@ public:
exit(-1);
}
#ifndef ZT_EXTOSDEP
bool v4controlPlaneBound = false;
_controlPlane.set_address_family(AF_INET);
if(_controlPlane.bind_to_port("0.0.0.0", _primaryPort)) {
@ -2391,6 +2403,7 @@ public:
fprintf(stderr, "ERROR: Could not bind control plane. Exiting...\n");
exit(-1);
}
#endif // ZT_EXTOSDEP
}
// Must be called after _localConfig is read or modified
@ -2599,6 +2612,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);
@ -3161,8 +3175,52 @@ public:
inline void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) {}
inline void phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN) {}
inline void phyOnUnixClose(PhySocket *sock,void **uptr) {}
inline void phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
inline void phyOnUnixWritable(PhySocket *sock,void **uptr) {}
inline void phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) {
#ifdef ZT_EXTOSDEP
if (ExtOsdep::mgmtRecv(*uptr, data, len, [&](unsigned method, const std::string &path, const std::string &data, std::string &resp) {
// fprintf(stderr, "mgmtRecv: %u %s %s\n", method, path.c_str(), data.c_str());
httplib::Request req;
httplib::Response res;
req.path = "/" + path;
if (method == 1) req.method = "GET";
else if (method == 3) req.method = "POST";
else if (method == 0) req.method = "DELETE";
struct S : public httplib::Stream {
const char *ptr;
unsigned size;
S(const std::string &s) : ptr(s.c_str()), size(s.size()) {}
virtual bool is_readable() const { return true; }
virtual bool is_writable() const { return true; }
virtual ssize_t read(char *p, size_t sz) {
// fprintf(stderr, "S::read %d\n", (int)size);
if (sz > (size_t)size) sz = size;
memcpy(p, ptr, sz);
size -= (unsigned)sz;
ptr += sz;
return (ssize_t)sz;
}
virtual ssize_t write(const char *ptr, size_t size) {
// fprintf(stderr, "S::write %d\n", (int)size);
return size;
}
virtual void get_remote_ip_and_port(std::string &ip, int &port) const {}
virtual void get_local_ip_and_port(std::string &ip, int &port) const {};
virtual socket_t socket() const { return 0; }
};
S s(data);
bool x = _controlPlane.routing(req, res, s);
// fprintf(stderr, "mgmtRecv: done, x %d status %u body %s\n", x, res.status, res.body.c_str());
resp = res.body;
return res.status;
})) _phy.setNotifyWritable(sock,true);
#endif
}
inline void phyOnUnixWritable(PhySocket *sock,void **uptr) {
#ifdef ZT_EXTOSDEP
if (ExtOsdep::mgmtWritable(*uptr)) _phy.setNotifyWritable(sock,false);
#endif
}
inline int nodeVirtualNetworkConfigFunction(uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwc)
{

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