Compare commits

..

356 commits
main ... root

Author SHA1 Message Date
Grant Limberg
b849e23536
Moved zerotier-root code to its own repo 2025-01-07 11:06:42 -08:00
Adam Ierymenko
0ab4e2f750 Roots now understand encrypted HELLO. 2024-09-26 19:47:57 -04:00
Adam Ierymenko
2316a45a45 clang-format root 2024-09-26 13:41:59 -04:00
Adam Ierymenko
0a6c22a9b8 . 2024-08-14 08:10:44 -04:00
Adam Ierymenko
8adf064a04 Yet another fix. 2021-09-21 12:36:00 -04:00
Adam Ierymenko
7fe00f4247 Another dumb RENDEZVOUS bug. 2021-09-21 12:13:47 -04:00
Adam Ierymenko
5eae02068d Fix bass ackwards addresses making RENDEZVOUS packets not make it, improve P2P. 2021-09-21 11:58:39 -04:00
Adam Ierymenko
5d429cedbb Send error. 2021-09-20 16:56:16 -04:00
Adam Ierymenko
3c85322067 Meh... fixed now. 2021-09-20 15:54:12 -04:00
Adam Ierymenko
9fb902bdf6 Pointer deref fix. 2021-09-20 15:43:27 -04:00
Adam Ierymenko
262cb7a4b5 Generate new peer if old was bad. 2021-09-20 15:12:56 -04:00
Adam Ierymenko
104fade420 Thinko. 2021-09-20 15:04:25 -04:00
Adam Ierymenko
bcf8c30ce0 Simplify validation logic too. 2021-09-20 14:56:49 -04:00
Adam Ierymenko
c2413fca4d Clean out a bunch of old code related to the possibility of multiple peers sharing virtual addresses. Does not seem to be currently exploitable but we are never going back to that idea, so this simplifies things. May also speed up the root. 2021-09-20 14:42:49 -04:00
Adam Ierymenko
5028aca372 Fix some identity verification stuff, performance improvements, build of root now requires libjemalloc. 2021-06-18 16:14:59 -04:00
Adam Ierymenko
311f9c5c2a A few minor changes: (1) bind sockets to peers so the same socket is always used to send as most recently received, (2) pick the most recently active IP (v4 or v6) if both exist, and (3) introduce expiry of V4 or V6 IPs in addition to the peer overall. 2021-05-26 19:37:48 -04:00
Adam Ierymenko
32ca1a09da Set version threshold correctly for v2 2020-08-27 10:00:11 -07:00
Adam Ierymenko
bba1324145 One more sanity check. 2020-01-21 11:04:18 -08:00
Adam Ierymenko
ff655292fb Allocate packet on heap, add extra sanity checks on packet size. 2020-01-21 10:58:41 -08:00
Grant Limberg
2558bd1b9b
include iomanip 2020-01-16 09:11:12 -08:00
Grant Limberg
95d0944b9f
add /metrics endpoint for exposing root metrics to Prometheus 2020-01-16 09:08:52 -08:00
Adam Ierymenko
68ac884d47
. 2019-10-02 14:30:46 -07:00
Adam Ierymenko
e2f3996843
Fix callbacks 2019-10-02 13:39:48 -07:00
Adam Ierymenko
57ade250af
. 2019-10-02 12:19:37 -07:00
Adam Ierymenko
c3e0f262d1
Regularize JSON stuff 2019-10-02 09:34:44 -07:00
Adam Ierymenko
b9911d0db7
More plumbing 2019-10-02 07:09:54 -07:00
Adam Ierymenko
d1b780c7be
addroot 2019-10-01 13:09:53 -07:00
Adam Ierymenko
1711cced3e
. 2019-09-30 20:31:48 -07:00
Adam Ierymenko
63e6693255
. 2019-09-30 20:10:53 -07:00
Adam Ierymenko
9b8d191bb1
Locator fix 2019-09-30 20:09:35 -07:00
Adam Ierymenko
6db2b8c66d
. 2019-09-30 20:03:03 -07:00
Adam Ierymenko
47a08ccbd4
Identity management plumbing to Go 2019-09-30 18:59:57 -07:00
Adam Ierymenko
7fc78129f4
A bunch of CLI work 2019-09-30 16:12:08 -07:00
Adam Ierymenko
c4504fd3ff
Vendor Go modules 2019-09-30 12:41:21 -07:00
Adam Ierymenko
e4799ff8c4
Bunch of small warnings and stylistic things... 2019-09-30 11:10:47 -07:00
Adam Ierymenko
f680924585
Build fixes 2019-09-30 09:48:44 -07:00
Adam Ierymenko
b0d222768a
Root admin stuff 2019-09-30 09:32:00 -07:00
Adam Ierymenko
4303c43db7
. 2019-09-27 14:55:46 -07:00
Adam Ierymenko
3b3e6d2bfc
Simplify root API 2019-09-26 13:35:56 -07:00
Adam Ierymenko
7061f13b24
. 2019-09-26 09:34:31 -07:00
Adam Ierymenko
5175636d36
. 2019-09-25 14:31:08 -07:00
Adam Ierymenko
570032484f
. 2019-09-25 14:16:55 -07:00
Adam Ierymenko
9c37fc1a5f
. 2019-09-25 13:32:46 -07:00
Adam Ierymenko
105023bd87
Build fix 2019-09-25 12:43:14 -07:00
Adam Ierymenko
8a9669f130
. 2019-09-25 12:36:49 -07:00
Adam Ierymenko
e5bd230fb0
. 2019-09-24 16:44:29 -07:00
Adam Ierymenko
e3d47e588a
. 2019-09-24 12:32:35 -07:00
Adam Ierymenko
f4a5abeed9
Go CLI work 2019-09-24 12:19:28 -07:00
Adam Ierymenko
a7e38d2b00
. 2019-09-23 16:58:55 -07:00
Adam Ierymenko
84ba396ed3
. 2019-09-23 16:47:13 -07:00
Adam Ierymenko
6683280a37
. 2019-09-23 16:46:58 -07:00
Adam Ierymenko
1edf680464
. 2019-09-23 16:46:31 -07:00
Adam Ierymenko
4df090469a
Clean out obsolete dependencies. 2019-09-23 16:42:23 -07:00
Adam Ierymenko
3c63f58532
Build fix. 2019-09-23 16:21:43 -07:00
Adam Ierymenko
64c8171e13
Port binding check. 2019-09-23 16:21:02 -07:00
Adam Ierymenko
b6175bd408
Gogogogogogogo 2019-09-23 15:18:52 -07:00
Adam Ierymenko
b44bd19c53
. 2019-09-22 22:33:11 -07:00
Adam Ierymenko
536bc59abb
. 2019-09-22 22:25:55 -07:00
Adam Ierymenko
70d5da1e2a
. 2019-09-22 19:25:40 -07:00
Adam Ierymenko
90d4d79828
Peers and paths 2019-09-22 17:41:15 -07:00
Adam Ierymenko
ccc9be2d4d
All that cgo crap compiles! 2019-09-22 00:06:07 -07:00
Adam Ierymenko
3341c4a670
Rooting around 2019-09-21 22:54:58 -07:00
Adam Ierymenko
bcb9df9cdf
Network config stuff in Go 2019-09-21 20:40:06 -07:00
Adam Ierymenko
2eef9d22e6
getting there... 2019-09-21 18:22:25 -07:00
Adam Ierymenko
5e35346f17
Gogog 2019-09-21 15:35:27 -07:00
Adam Ierymenko
bb53ee9567
Going once... going twice! 2019-09-21 15:04:00 -07:00
Adam Ierymenko
9934a856dd
More go 2019-09-21 12:54:45 -07:00
Adam Ierymenko
24904c5083
Go F yourself 2019-09-21 11:56:31 -07:00
Adam Ierymenko
6ce4663a31
GoGoGo 2019-09-21 00:19:20 -07:00
Adam Ierymenko
fbf74d3baa
Go! Go! https://www.youtube.com/watch?v=hyGYdqMfrQQ 2019-09-20 21:00:54 -07:00
Adam Ierymenko
b540181990
Go! Go! Go! - Moby 2019-09-20 20:34:31 -07:00
Adam Ierymenko
02a6b15e6b
Moar Go 2019-09-20 19:51:57 -07:00
Adam Ierymenko
b34aa10bf8
Go code! 2019-09-20 18:48:48 -07:00
Adam Ierymenko
e0ddbc2f28
Update build process, Go glue builds now. 2019-09-20 15:00:53 -07:00
Adam Ierymenko
ed2024285d
More Go boilerplate. 2019-09-20 14:11:15 -07:00
Adam Ierymenko
ae2120eb96
New service, work in progress 2019-09-20 09:09:05 -07:00
Adam Ierymenko
3ceb2257e5
Plumb through roots via API. 2019-09-19 09:47:12 -07:00
Adam Ierymenko
624efde7e4
Make sure threads dont exit on spurious return values from recvfrom unless we are really dying. 2019-09-16 20:41:23 -07:00
Adam Ierymenko
50009fef6f
Merge branch 'dev' into edge 2019-09-16 20:26:41 -07:00
Adam Ierymenko
dde937e197
cleanup 2019-09-16 19:58:21 -07:00
Adam Ierymenko
07a480b37a
Build fix. 2019-09-16 18:04:32 -07:00
Adam Ierymenko
9f5bccec30
Add a recv timeout to root 2019-09-16 18:03:17 -07:00
Adam Ierymenko
ade52bf81e
Fix RENDEZVOUS issue and possibly improve GeoIP resolution. 2019-09-16 17:04:13 -07:00
Adam Ierymenko
71c766a3b2
Build fix 2019-09-16 15:09:56 -07:00
Adam Ierymenko
eef66aee9a
build fix 2019-09-16 14:51:02 -07:00
Adam Ierymenko
e245eb1eb5
Trim some unnecessary locks from root, and cleanup elsewhere. 2019-09-16 14:48:27 -07:00
Adam Ierymenko
e08fc81397
More threading improvements in root, more DNS TXT and multicast work (in progress) 2019-09-16 10:33:59 -07:00
Adam Ierymenko
9f9032ae36
Cleanup and warning removal. 2019-09-13 16:24:02 -07:00
Adam Ierymenko
063a16fcd6
Ensure SSE is enabled for Salsa20 on x64 2019-09-13 11:16:21 -07:00
Adam Ierymenko
0db4151492
cleanup 2019-09-13 11:10:56 -07:00
Adam Ierymenko
e44d7a553f
The root technically does not need to do this, and its slow. 2019-09-13 10:29:11 -07:00
Adam Ierymenko
53a2de98de
Packet ID fix 2019-09-13 10:23:35 -07:00
Adam Ierymenko
2deaaeef28
Some root cleanup and more lock contention reduction. 2019-09-13 10:20:29 -07:00
Adam Ierymenko
1f9e16f63e
AES optimization rabbit hole 2019-09-13 09:37:09 -07:00
Adam Ierymenko
87fe69c27c
AES optimization rabbit hole 2019-09-13 09:35:49 -07:00
Adam Ierymenko
2d1eeda188
Cleanup, optimization 2019-09-12 14:32:37 -07:00
Adam Ierymenko
5c06d40358
cleanup 2019-09-12 10:37:26 -07:00
Adam Ierymenko
31e193756d
cleanup 2019-09-12 09:59:46 -07:00
Adam Ierymenko
5aa744db84
Simplification and further concurrency improvements. 2019-09-12 08:41:34 -07:00
Adam Ierymenko
0ad82dad80
Linux build fix 2019-09-12 08:25:26 -07:00
Adam Ierymenko
99c36ed2f2
Parallelization improvements 2019-09-12 08:20:38 -07:00
Adam Ierymenko
44878e583a
Bug fixes 2019-09-11 16:10:06 -07:00
Adam Ierymenko
0723a85ab3
Build fixes. 2019-09-11 15:52:18 -07:00
Adam Ierymenko
d8dae365f6
Cleanup, optimization, multicast stuff, and it now compiles again. 2019-09-11 15:34:55 -07:00
Adam Ierymenko
bccb86a401
More multicast work... 2019-09-10 16:20:28 -07:00
Adam Ierymenko
592e743349
Yet more multicast work. 2019-09-09 15:49:17 -07:00
Adam Ierymenko
fb6161e9ac
May as well make it a full self-signature. 2019-09-09 10:45:49 -07:00
Adam Ierymenko
787277d282
More multicast work, add a signature in identity for safety margin, cleanup. 2019-09-09 10:44:31 -07:00
Adam Ierymenko
540ee69773
A bunch of multicast work... in progress. 2019-09-07 19:15:21 -07:00
Adam Ierymenko
0d2c87fe4e
map fix 2019-09-06 08:54:27 -07:00
Adam Ierymenko
2460de9713
map fix 2019-09-06 08:50:36 -07:00
Adam Ierymenko
0d32f42d26
map fix 2019-09-06 08:47:32 -07:00
Adam Ierymenko
277497684e
Revert "map fix"
This reverts commit f4a83e516c.
2019-09-06 08:45:39 -07:00
Adam Ierymenko
f4a83e516c
map fix 2019-09-06 08:41:03 -07:00
Adam Ierymenko
d2eb1ed9a5
map fix 2019-09-06 08:27:03 -07:00
Adam Ierymenko
a3ec5846df
map fix 2019-09-06 08:18:11 -07:00
Adam Ierymenko
b6047899a8
map fix 2019-09-06 08:12:46 -07:00
Adam Ierymenko
3516070b6e
map fix 2019-09-06 08:11:20 -07:00
Adam Ierymenko
56ec87e00e
map fix 2019-09-06 08:03:59 -07:00
Adam Ierymenko
fe0b896665
map fix 2019-09-06 07:58:43 -07:00
Adam Ierymenko
e4721417e6
map fix 2019-09-06 07:55:36 -07:00
Adam Ierymenko
45f5b3b648
map fix 2019-09-06 07:40:32 -07:00
Adam Ierymenko
3123102211
root cleanup and add nifty geoip thing 2019-09-06 07:37:44 -07:00
Adam Ierymenko
c6141ffbc7
cleanup 2019-09-05 18:06:48 -07:00
Adam Ierymenko
c0e92d06a5
faster without const variable second-guessing of the compiler 2019-09-05 17:31:12 -07:00
Adam Ierymenko
274b2682d6
cleanup and docs 2019-09-05 15:09:20 -07:00
Adam Ierymenko
171d661b84
cleanup 2019-09-05 12:17:04 -07:00
Adam Ierymenko
5cea8da664
Optimization and naming cleanup 2019-09-05 12:03:11 -07:00
Adam Ierymenko
44dd52d08f
KBKDF 2019-09-05 11:39:16 -07:00
Adam Ierymenko
70648d006d
Merge branch 'dev' into edge 2019-09-05 11:06:27 -07:00
Adam Ierymenko
43e6a9e9ee
more fastitude 2019-09-05 09:54:30 -07:00
Adam Ierymenko
0599c1710b
Merge branch 'dev' into edge 2019-09-04 16:41:05 -07:00
Adam Ierymenko
abf218a9cd
cleanup 2019-09-04 16:38:55 -07:00
Adam Ierymenko
55f4f9aaeb
cleanup 2019-09-04 16:15:10 -07:00
Adam Ierymenko
82b7e1dbcb
HMAC fix 2019-09-04 15:22:15 -07:00
Adam Ierymenko
e8f8b0f8e5
cleanup 2019-09-04 14:40:36 -07:00
Adam Ierymenko
7566d4fbab
Merge dev 2019-09-04 14:38:35 -07:00
Adam Ierymenko
3a0d385119
Implement changes to AES-GMAC-CTR: four keys with one for each role/purpose instead of just two, and simpler CTR-IV calculation. 2019-09-04 14:37:38 -07:00
Adam Ierymenko
a465afa83d
Merge branch 'dev' into edge 2019-09-04 08:19:39 -07:00
Adam Ierymenko
185e90c40f
AES-GMAC-CTR tweaks, self test tweaks, debian typo fix. 2019-09-04 08:19:12 -07:00
Adam Ierymenko
e29c2d0260
Fix field headers 2019-09-03 15:59:34 -07:00
Adam Ierymenko
acf6425ae9
Formatting fix 2019-09-03 15:55:23 -07:00
Adam Ierymenko
5e8d49de0f
Stats, tweak P2P success rate stat. 2019-09-03 15:48:10 -07:00
Adam Ierymenko
1f9456a462
Estimate P2P Success Rate 2019-09-03 15:19:17 -07:00
Adam Ierymenko
a7d8285c3a
Don't require siblings field 2019-09-03 14:57:54 -07:00
Adam Ierymenko
5f1dc4b851
cleanup 2019-09-03 14:57:02 -07:00
Adam Ierymenko
b1c22949c5
Cleanup, add support for distributing a new planet file 2019-09-03 14:44:13 -07:00
Adam Ierymenko
29be175743
Make relay max hops configurable on roots 2019-09-03 13:17:12 -07:00
Adam Ierymenko
b6c5ba264b
One more fix for discarding hops exceeded packets. 2019-09-03 13:01:01 -07:00
Adam Ierymenko
8e7e3c2b11
Fix max hops. 2019-09-03 12:58:23 -07:00
Adam Ierymenko
0e7df129d8
Fix variable shadowing bug. 2019-09-03 12:51:32 -07:00
Adam Ierymenko
50709cbd21
Fix siblings in peers list, fix meter. 2019-09-03 12:44:09 -07:00
Adam Ierymenko
fd6e8d8c5c
Add instrumentation to root, add capability to forward to siblings if no path is known to a peer. 2019-09-03 12:21:57 -07:00
Adam Ierymenko
2e7496130c
Fix silly thinko in root that harms p2p establishment. 2019-08-30 21:17:34 -07:00
Adam Ierymenko
9666ab5797
Merge branch 'dev' into edge 2019-08-30 17:57:11 -07:00
Adam Ierymenko
4c08ac7873
Fix MULTICAST_GATHER reply problem in root 2019-08-30 17:34:05 -07:00
Adam Ierymenko
5435ec7545
Merge dev 2019-08-30 15:40:00 -07:00
Adam Ierymenko
8764d50179
Merge branch 'dev' of http://git.int.zerotier.com/zerotier/ZeroTierOne into edge 2019-08-30 15:16:21 -07:00
Adam Ierymenko
62cdb8dc94
cleanup 2019-08-30 12:47:19 -07:00
Adam Ierymenko
9918a1092f
JSON fix 2019-08-30 09:39:46 -07:00
Adam Ierymenko
7d89511fda
JSON fix 2019-08-30 09:38:18 -07:00
Adam Ierymenko
795b6d13d1
Simple status output on root of HTTP tree 2019-08-30 09:29:06 -07:00
Adam Ierymenko
8328b6f657
Lib fix 2019-08-30 09:10:11 -07:00
Adam Ierymenko
9994e591bd
More root work and CMake-ify root 2019-08-30 09:08:39 -07:00
Adam Ierymenko
b27a38e55e
Implement WHOIS 2019-08-29 14:27:41 -07:00
Adam Ierymenko
f6d747a5a0
Fix some more multicast stuff (minor) 2019-08-29 12:02:37 -07:00
Adam Ierymenko
b7da7574d1
Helps to decompress the packet 2019-08-29 11:40:31 -07:00
Adam Ierymenko
dbad9585cd
Fix parsing of MULTICAST_GATHER 2019-08-29 11:23:23 -07:00
Adam Ierymenko
2d7a97bb94
Fix V4/V6 forwarding issue in root 2019-08-29 10:58:47 -07:00
Adam Ierymenko
da19da0360
RENDEZVOUS works now 2019-08-29 08:00:54 -07:00
Adam Ierymenko
ee7361ee2e
crash fix 2019-08-29 07:25:16 -07:00
Adam Ierymenko
6e3e09bed4
Add RENDEZVOUS to high throughput root 2019-08-29 07:17:18 -07:00
Adam Ierymenko
86762d2b40
high throughput root is working! 2019-08-28 15:52:18 -07:00
Adam Ierymenko
ef12c5af99
. 2019-08-28 15:22:28 -07:00
Adam Ierymenko
933404b1dd
. 2019-08-28 15:20:34 -07:00
Adam Ierymenko
ccec49e444
. 2019-08-28 15:17:16 -07:00
Adam Ierymenko
e5f1bf81f7
. 2019-08-28 15:15:21 -07:00
Adam Ierymenko
0e627f4f68
. 2019-08-28 15:07:38 -07:00
Adam Ierymenko
d33f7d2bf5
. 2019-08-28 14:49:16 -07:00
Adam Ierymenko
e07a019615
. 2019-08-28 14:47:05 -07:00
Adam Ierymenko
34ca3012e6
. 2019-08-28 14:43:37 -07:00
Adam Ierymenko
62634ca2da
. 2019-08-28 14:39:31 -07:00
Adam Ierymenko
846c96e8d5
. 2019-08-28 14:36:29 -07:00
Adam Ierymenko
63775723c1
. 2019-08-28 14:28:07 -07:00
Adam Ierymenko
2f7d3e655a
. 2019-08-28 14:26:13 -07:00
Adam Ierymenko
b19634d7e4
. 2019-08-28 14:21:02 -07:00
Adam Ierymenko
a92967a7c1
. 2019-08-28 14:16:14 -07:00
Adam Ierymenko
8915b88de5
. 2019-08-28 14:06:45 -07:00
Adam Ierymenko
7bca81464b
. 2019-08-28 14:04:42 -07:00
Adam Ierymenko
b974ece24f
. 2019-08-28 13:59:23 -07:00
Adam Ierymenko
b1c8e6ad59
. 2019-08-28 13:51:13 -07:00
Adam Ierymenko
64f7185e3a
. 2019-08-28 13:44:15 -07:00
Adam Ierymenko
807cc9afc3
. 2019-08-28 13:40:49 -07:00
Adam Ierymenko
0adf306dd4
. 2019-08-28 13:38:52 -07:00
Adam Ierymenko
db0f602e86
. 2019-08-28 13:10:36 -07:00
Adam Ierymenko
17ec47f5c0
. 2019-08-28 13:09:14 -07:00
Adam Ierymenko
cf831d9cd3
. 2019-08-28 13:04:58 -07:00
Adam Ierymenko
5e3c633f74
root work 2019-08-28 11:59:13 -07:00
Adam Ierymenko
4e4b27b6ab
build fix 2019-08-28 11:54:09 -07:00
Adam Ierymenko
c0c9590904
High throughput root stuff 2019-08-28 11:49:45 -07:00
Adam Ierymenko
24c9577e39
cleanup 2019-08-28 11:28:51 -07:00
Adam Ierymenko
59ee0cfe88
Safety upgrades to code 2019-08-28 10:34:32 -07:00
Adam Ierymenko
1977b9b764
Use -flto on Mac for release 2019-08-28 07:45:49 -07:00
Adam Ierymenko
6f9d1fc14c
Merge branch 'dev' into edge 2019-08-28 07:43:36 -07:00
Adam Ierymenko
8ac59ae2be
cleanup 2019-08-28 07:40:13 -07:00
Adam Ierymenko
46db37e06c
Yield in ticket lock 2019-08-28 07:34:24 -07:00
Adam Ierymenko
9d1207b339
Merge branch 'dev' into edge 2019-08-28 07:31:33 -07:00
Adam Ierymenko
6e730cfad1
Cleanup, multicast fingerprint, benchmark asymmetric crypto 2019-08-28 07:31:17 -07:00
Adam Ierymenko
199b3345a0
cleanup 2019-08-27 14:42:49 -07:00
Adam Ierymenko
b7f504b8a4
cleanup 2019-08-27 14:40:01 -07:00
Adam Ierymenko
1b459b0560
cleanup 2019-08-27 14:31:04 -07:00
Adam Ierymenko
40803a4dc1
cleanup 2019-08-27 14:25:11 -07:00
Adam Ierymenko
6f22570648
Optimization and cleanup 2019-08-26 20:18:28 -07:00
Adam Ierymenko
8203547cfc
Warning removal. 2019-08-26 20:01:54 -07:00
Adam Ierymenko
dad160209e
Add -mmacosx-version-min=10.9 2019-08-26 19:54:24 -07:00
Adam Ierymenko
8faaaec710
Add check for PCLMUL instruction too. Virtually all CPUs with AES-NI have it but good to be sure. 2019-08-26 19:48:56 -07:00
Adam Ierymenko
012fba617d
Set SSE/AES-NI flags only on x86/x64 targets. 2019-08-26 19:40:22 -07:00
Adam Ierymenko
9ca495229b
Revert "optimization stuff"
This reverts commit e63f624d3a.
2019-08-26 19:03:09 -07:00
Adam Ierymenko
e63f624d3a
optimization stuff 2019-08-26 19:02:28 -07:00
Adam Ierymenko
e1dd413266
cleanup 2019-08-26 18:44:56 -07:00
Adam Ierymenko
b9ef09dd58
Optimization stuff 2019-08-26 18:15:32 -07:00
Adam Ierymenko
990333e7ec
cleanup, re-enable AES-NI check 2019-08-26 16:35:28 -07:00
Adam Ierymenko
ec9582f3f2
More test vectors, software mode GCM. 2019-08-26 16:24:42 -07:00
Adam Ierymenko
ea65386e15
Merge branch 'dev' into edge 2019-08-26 12:22:20 -07:00
Adam Ierymenko
a0fd4ad23f
Cleanup, Linux build fix. 2019-08-26 12:17:23 -07:00
Adam Ierymenko
b6d7a95028
Merge branch 'dev' into edge 2019-08-26 11:09:19 -07:00
Adam Ierymenko
1d8f3cee62
cleanup 2019-08-23 21:12:24 -07:00
Adam Ierymenko
5ba6e21967
cleanup 2019-08-23 20:34:09 -07:00
Adam Ierymenko
52f7f6e6cf
Fully implement the packet encryption/decryption algorithms. 2019-08-23 20:20:32 -07:00
Adam Ierymenko
9fd5ec673b
Get rid of complicated AES-GCM + scramble construct in favor of a simpler construct thanks to "Squeamish Ossifrage" on crypto.stackexchange.com 2019-08-23 18:41:21 -07:00
Adam Ierymenko
e905b3c963
cleanup 2019-08-23 17:22:23 -07:00
Adam Ierymenko
f12370c348
more opt 2019-08-23 12:40:08 -07:00
Adam Ierymenko
b727e2a67a
More opt stuff 2019-08-23 12:34:45 -07:00
Adam Ierymenko
8e87319925
Optimization stuff 2019-08-23 12:18:02 -07:00
Adam Ierymenko
1ab29b1ab0
Merge branch 'dev' into edge 2019-08-23 12:11:07 -07:00
Adam Ierymenko
52d55e34e6
Licenses, and use full strength AES-128 in scramble. 2019-08-23 12:03:13 -07:00
Adam Ierymenko
c79360f58b
Merge dev 2019-08-23 11:37:40 -07:00
Adam Ierymenko
8057c826bc
cleanup 2019-08-23 09:34:26 -07:00
Adam Ierymenko
6f6138c500
Merge relicensing change from dev 2019-08-23 09:27:13 -07:00
Adam Ierymenko
903a18db1d
work in progress 2019-08-23 08:41:22 -07:00
Adam Ierymenko
0731f3f1a9
wiring more stuff up, and simplification of timing loops 2019-08-23 07:04:20 -07:00
Adam Ierymenko
37047a39f9
More cleanup, and fix SHA384 built-in C code. 2019-08-22 14:52:47 -07:00
Adam Ierymenko
91d0cbe892
cleanup 2019-08-22 13:08:10 -07:00
Adam Ierymenko
b66431bc29
Work in progress... 2019-08-22 13:06:08 -07:00
Adam Ierymenko
0e18b14087
Merge branch 'dev' into edge 2019-08-21 14:58:26 -07:00
Adam Ierymenko
31bd413166
stub out new verbs 2019-08-21 14:57:57 -07:00
Adam Ierymenko
95a6fce2b4
Yet more cleanup, it builds again now. 2019-08-21 14:36:56 -07:00
Adam Ierymenko
0b5472f9fb
Tons and tons of cleanup and cruft removal 2019-08-21 14:24:45 -07:00
Adam Ierymenko
5280d28505
cleanup 2019-08-21 10:44:52 -07:00
Adam Ierymenko
67a9898a99
Bunch more work on DNS, cleanup, removal of obsolete cruft. 2019-08-21 09:27:45 -07:00
Adam Ierymenko
fe8815f80f
cleanup 2019-08-20 15:36:18 -07:00
Adam Ierymenko
3a21fdc304
Crypto work, packet work 2019-08-20 15:34:30 -07:00
Adam Ierymenko
83d723eb79
type 1 (P-384) identities 2019-08-20 13:32:23 -07:00
Adam Ierymenko
6e771607c0
cleanup 2019-08-19 20:35:16 -07:00
Adam Ierymenko
e73b220104
cleanup 2019-08-19 20:30:34 -07:00
Adam Ierymenko
5c1fc43610
cleanup 2019-08-19 20:29:24 -07:00
Adam Ierymenko
cfbd7e3bf5
Add stubs to easily build and include all of libnatpmp and miniupnpc in osdep/ 2019-08-19 20:28:44 -07:00
Adam Ierymenko
c8ca1cfa3c
Kill old inline software update, we will use https and secondary auth for new versions. 2019-08-19 19:24:23 -07:00
Adam Ierymenko
5cfbb0a423
Clean up dead stuff from OneService and fix build errors. 2019-08-19 19:21:33 -07:00
Adam Ierymenko
900ec143a8
. 2019-08-19 16:45:29 -07:00
Adam Ierymenko
7bda3d0f74
put sse4.1 back 2019-08-19 15:49:13 -07:00
Adam Ierymenko
7650786fb5
cleanup, Locator fix and self-test 2019-08-19 15:43:15 -07:00
Adam Ierymenko
ca60d08621
cleanup, scrambler functions 2019-08-19 12:49:33 -07:00
Adam Ierymenko
b34218c8c2
auto-set -j option in makefile, and split out cmake setup rule 2019-08-19 10:06:39 -07:00
Adam Ierymenko
b14a59629c
cleanup 2019-08-19 06:58:42 -07:00
Adam Ierymenko
0914bf8cf0
Some ARM NEON code (not finished) 2019-08-16 19:22:03 -07:00
Adam Ierymenko
7bdca83de3
Add decrypt 2019-08-16 18:40:22 -07:00
Adam Ierymenko
846f03504e
Add DNS TXT resolver (need one for Windows) 2019-08-16 16:49:30 -07:00
Adam Ierymenko
01e8fd0b07
The newer C ed25519 is the same speed as the old ASM, so drop it to simplify. 2019-08-16 14:42:38 -07:00
Adam Ierymenko
7f301c44b7
more cleanup 2019-08-16 14:26:45 -07:00
Adam Ierymenko
51a25fdec9
Remove ASM Salsa20 since it will not be the default in 2.x any more... reduce build complexity. 2019-08-16 14:26:25 -07:00
Grant Limberg
2b681c37ac Consolidate common compiler flags 2019-08-16 11:42:43 -07:00
Grant Limberg
cb4ebfdbd2 Dragging adam into CMake kicking and screaming :) 2019-08-16 10:45:14 -07:00
Grant Limberg
206c85222c Fix Constants.hpp inclusion of version.h 2019-08-16 09:52:13 -07:00
ZeroTier
18071e038e Fix MacEthernetTapAgent & Cmake integration 2019-08-16 09:44:31 -07:00
Grant Limberg
39f7ce15ad mac compiler flags 2019-08-15 17:40:21 -07:00
Grant Limberg
e39b42bbd3 fixing some CMake stuff on Linux 2019-08-15 17:29:33 -07:00
Adam Ierymenko
607d8f72e8
cruftectomy 2019-08-15 15:43:35 -07:00
Adam Ierymenko
c483f75fb4
cleanup 2019-08-15 15:32:16 -07:00
Adam Ierymenko
81f0175251
cleanup 2019-08-15 14:14:49 -07:00
Adam Ierymenko
f753519729
A bit more optimization 2019-08-15 14:07:52 -07:00
Adam Ierymenko
f39693f97e
cleanup 2019-08-15 13:52:23 -07:00
Adam Ierymenko
f83ae0e39e
Add self-test for AES and AES-GCM using public test vectors. 2019-08-15 13:47:43 -07:00
Adam Ierymenko
521d371b5d
A bunch more refactoring to rip out obsolete stuff related to old root system and general cleanup. 2019-08-15 10:49:50 -07:00
Adam Ierymenko
b23d551d00
cleanup 2019-08-14 16:05:09 -07:00
Adam Ierymenko
1b20cc6075
More optimization and cleanup 2019-08-14 15:59:45 -07:00
Adam Ierymenko
2043e12ac2
. 2019-08-14 15:50:25 -07:00
Adam Ierymenko
9461bc948f
. 2019-08-14 15:28:10 -07:00
Adam Ierymenko
9740ab8bd6
more cleanup 2019-08-14 15:17:06 -07:00
Adam Ierymenko
6947a6b1d4
more cleanup 2019-08-14 15:12:49 -07:00
Adam Ierymenko
4da8036222
More refactor 2019-08-14 15:00:18 -07:00
Adam Ierymenko
e6b4006c70
Refactoring to eliminate duplicated code 2019-08-14 14:55:37 -07:00
Adam Ierymenko
8f5f7f1baa
More work in progress 2019-08-14 12:48:45 -07:00
Adam Ierymenko
573d3eea87
Merge branch 'dev' into edge 2019-08-14 10:53:03 -07:00
Adam Ierymenko
eb84eec0f4
Merge branch 'dev' into edge 2019-08-14 10:48:07 -07:00
Adam Ierymenko
d7a31088ba
Cleanup, warning removal, cppcheck informed cleanup. 2019-08-14 10:35:57 -07:00
Adam Ierymenko
a028e04ab9
Merge branch 'dev' into edge 2019-08-13 15:51:19 -07:00
Adam Ierymenko
a0520536df
. 2019-08-13 08:49:25 -07:00
Adam Ierymenko
af137fd5d3
Merge branch 'edge' of http://git.int.zerotier.com/zerotier/ZeroTierOne into edge 2019-08-12 15:37:55 -07:00
Adam Ierymenko
f7bc9f01c9
More AES stuff 2019-08-12 15:37:50 -07:00
Grant Limberg
e4ce1ffd85 Windows detection of AES-NI 2019-08-12 15:28:42 -07:00
Grant Limberg
2384b49156 set cmake windows build target to Windows 7 2019-08-12 15:28:30 -07:00
Adam Ierymenko
f5e71f64ed
Merge branch 'edge' of http://git.int.zerotier.com/zerotier/ZeroTierOne into edge 2019-08-12 13:27:07 -07:00
Adam Ierymenko
927ef22cf8
Merge branch 'dev' into edge 2019-08-12 13:27:00 -07:00
Grant Limberg
b6eaec1278 run selftest 2019-08-12 13:26:34 -07:00
Grant Limberg
c7d1eb71da build & run selftest as part of jenkins 2019-08-12 13:25:14 -07:00
Grant Limberg
7d41d267a3 silencing warnings for code paths that will never be hit 2019-08-12 13:18:21 -07:00
Grant Limberg
0ead65ad2d change this 2019-08-12 13:11:43 -07:00
Grant Limberg
8c5481a3d5 Merge branch 'edge' of http://git.int.zerotier.com/zerotier/ZeroTierOne into edge 2019-08-12 12:58:20 -07:00
Grant Limberg
741258051e this should work better 2019-08-12 12:58:10 -07:00
Adam Ierymenko
0f4fc8635b
Merge branch 'edge' of http://git.int.zerotier.com/zerotier/ZeroTierOne into edge 2019-08-12 12:51:38 -07:00
Adam Ierymenko
d02d3f72fe
AES-GCM code 2019-08-12 12:51:32 -07:00
Grant Limberg
710b69fc75 kill build dir before jenkins build 2019-08-12 12:44:47 -07:00
Grant Limberg
4fae382ffd Auto-generate version.h 2019-08-12 12:43:51 -07:00
Grant Limberg
68b94a3188 CMake for edge branch 2019-08-12 12:35:07 -07:00
Grant Limberg
8e04f83232 Merge branch 'edge' into cmake 2019-08-12 12:24:25 -07:00
Grant Limberg
cc9fd9f8ce Merge branch 'dev' into cmake 2019-08-12 12:23:36 -07:00
Adam Ierymenko
1e8fcf1344
Add AES to build 2019-08-09 13:42:40 -05:00
Adam Ierymenko
809c8305b1
AES code 2019-08-09 10:54:08 -05:00
Adam Ierymenko
652c7e8f37
Locator work 2019-08-08 23:23:16 -05:00
Adam Ierymenko
beebca98fe
Merge branch 'dev' into edge 2019-08-08 19:42:16 -05:00
Adam Ierymenko
ce67abc32f
Merge branch 'dev' into edge 2019-08-08 18:49:03 -05:00
Adam Ierymenko
52cc482521
Merge branch 'dev' into edge 2019-08-08 15:59:58 -05:00
Adam Ierymenko
5eacad444d
workinprogress 2019-08-08 15:03:52 -05:00
Adam Ierymenko
e8155cbbeb
Merge dev 2019-08-08 13:05:28 -05:00
Adam Ierymenko
663376e385
cleanup 2019-08-08 08:42:27 -05:00
Adam Ierymenko
3c590994db
Finish up ECC384 identity generation. 2019-08-07 23:50:47 -05:00
Adam Ierymenko
14c8564893
Merge branch 'dev' into edge 2019-08-07 22:35:27 -05:00
Adam Ierymenko
91a37f8868
Add base64 code (unpadded standard alphabet) 2019-08-07 22:35:17 -05:00
Adam Ierymenko
1a2ff884b3
Merge branch 'dev' into edge 2019-08-07 19:08:35 -05:00
Adam Ierymenko
0298719be0
Use SHA384 with ECC384 to match FIPS / Suite B recommendation. 2019-08-07 17:06:03 -05:00
Adam Ierymenko
d0746da5e2
Add SHA384 support, more cleanup 2019-08-07 16:41:58 -05:00
Adam Ierymenko
5b1cf33b1b
Merge branch 'dev' into edge 2019-08-07 11:31:32 -05:00
Adam Ierymenko
54a1bbd016
. 2019-08-07 11:20:12 -05:00
Adam Ierymenko
455cd5551b
. 2019-08-06 17:06:39 -05:00
Adam Ierymenko
b3e1783658
. 2019-08-06 16:46:13 -05:00
Adam Ierymenko
906c83af83
Merge branch 'dev' into edge 2019-08-06 15:47:54 -05:00
Adam Ierymenko
f9900cc6fb
Merge dev to edge 2019-08-06 14:13:07 -05:00
ZeroTier
8e20187d8c set OS X deployment target to 10.9 2019-08-01 15:58:32 -07:00
ZeroTier
28dac7ff0e build MacEthernetTapAgent 2019-08-01 15:41:50 -07:00
Grant Limberg
e385b3d377 Merge branch 'dev' into cmake 2019-08-01 15:16:31 -07:00
Grant Limberg
7e5c68c553 update jenkins to use cmake for builds 2019-08-01 15:13:06 -07:00
Grant Limberg
39ad7bc741 update cmake to add LFDB and force C++11 2019-08-01 14:36:35 -07:00
Grant Limberg
c2f9aab068 Merge branch 'master' into cmake 2019-08-01 13:49:30 -07:00
Adam Ierymenko
7e105343e2 WIP 2019-07-17 16:53:33 -05:00
Adam Ierymenko
fe2215df00 TON of refactoring, moon/planet is DEAD, ECC P-384 is integrated (but not enabled), and multicast work and cleanup. Whew. 2019-07-17 10:52:08 -05:00
Adam Ierymenko
640bbaabbf Safer value 2019-07-16 17:28:42 -05:00
Adam Ierymenko
da2965cb4e P-384 test vectors 2019-07-16 17:25:25 -05:00
Adam Ierymenko
94ba242c33 Nist P-384 guts and glory 2019-07-16 16:09:14 -05:00
Adam Ierymenko
debd5a5c5e Add capability for P2P multicast propagation, and some cleanup. 2019-07-16 13:33:11 -05:00
Adam Ierymenko
98bbb84a63 Merge branch 'dev' into edge 2019-07-15 19:40:52 -05:00
Adam Ierymenko
9d908a11ed Some new stuff, may not live forever... 2019-07-15 13:57:42 -05:00
Grant Limberg
4d599e2f9f Linux build with CMake 2019-06-21 15:16:20 -07:00
Grant Limberg
d3b33e5512 Can now build the Windows UI via CMake as well 2019-06-21 12:54:53 -07:00
Grant Limberg
c8487cc395 no message 2019-06-20 16:15:19 -07:00
Grant Limberg
0b3b5f6174 Beginning CMake configuration for ZT
Only tested on Windows so far
2019-06-20 16:13:52 -07:00
1921 changed files with 78997 additions and 399055 deletions

View file

@ -57,7 +57,7 @@ SpacesInCStyleCastParentheses: 'false'
SpacesInContainerLiterals: 'true'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
UseTab: 'Always'
UseTab: 'Never'
---
Language: Cpp

View file

@ -1,2 +0,0 @@
.git/
workspace/

View file

@ -1,256 +0,0 @@
//
// tweakables
//
local registry = "084037375216.dkr.ecr.us-east-2.amazonaws.com";
local build_channel = "zerotier-builds";
local release_channel = "zerotier-releases";
local targets = [
{ "os": "linux", distro: "redhat", "name": "el9", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag", "custom" ] },
{ "os": "linux", distro: "redhat", "name": "el8", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag" ] },
{ "os": "linux", distro: "redhat", "name": "el7", "isas": [ "386", "amd64", "ppc64le"], "events": [ "tag" ] },
{ "os": "linux", distro: "amazon", "name": "amzn2", "isas": [ "amd64", "arm64" ], "events": [ "tag" ] },
{ "os": "linux", distro: "amazon", "name": "amzn2022", "isas": [ "amd64", "arm64" ], "events": [ "tag" ] },
{ "os": "linux", distro: "fedora", "name": "fc38", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag" ] },
{ "os": "linux", distro: "fedora", "name": "fc37", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag" ] },
{ "os": "linux", distro: "fedora", "name": "fc36", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag" ] },
{ "os": "linux", distro: "ubuntu", "name": "jammy", "isas": [ "armv7", "amd64", "arm64", "ppc64le", "s390x", "riscv64" ], "events": [ "tag" ] },
{ "os": "linux", distro: "ubuntu", "name": "focal", "isas": [ "armv7", "amd64", "arm64", "ppc64le", "s390x", "riscv64" ], "events": [ "tag" ] },
{ "os": "linux", distro: "ubuntu", "name": "bionic", "isas": [ "386", "armv7", "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag" ] },
{ "os": "linux", distro: "ubuntu", "name": "xenial", "isas": [ "386", "armv7", "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag" ] },
{ "os": "linux", distro: "ubuntu", "name": "trusty", "isas": [ "386", "armv7", "amd64", "arm64" ], "events": [ "tag" ] },
{ "os": "linux", distro: "debian", "name": "bookworm", "isas": [ "386", "armv7", "amd64", "arm64", "mips64le", "ppc64le", "s390x" ], "events": [ "tag"] },
{ "os": "linux", distro: "debian", "name": "bullseye", "isas": [ "386", "armv7", "amd64", "arm64", "mips64le", "ppc64le", "s390x" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "debian", "name": "buster", "isas": [ "386", "armv7", "amd64", "arm64" ], "events": [ "tag" ] },
{ "os": "linux", distro: "debian", "name": "stretch", "isas": [ "386", "armv7", "amd64", "arm64" ], "events": [ "tag" ] },
{ "os": "linux", distro: "debian", "name": "jessie", "isas": [ "386", "armv7", "amd64" ], "events": [ "tag" ] },
// { "os": "windows", distro: "windows", "name": "windows", "isas": [ "amd64" ], "events": [ "push", "tag", "custom" ] },
// { "os": "darwin", distro: "darwin", "name": "darwin", "isas": [ "amd64" ], "events": [ "push", "tag", "custom" ] },
];
local less_targets = [
{ "os": "linux", distro: "redhat", "name": "el9", "isas": [ "amd64", "arm64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "redhat", "name": "el8", "isas": [ "amd64", "arm64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "ubuntu", "name": "jammy", "isas": [ "armv7", "amd64", "arm64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "ubuntu", "name": "focal", "isas": [ "armv7", "amd64", "arm64" ], "events": [ "push", "tag", "custom" ] },
];
local native_targets = [
{ "os": "linux", distro: "debian", "name": "bullseye", "isas": [ "386", "armv7", "amd64", "arm64" ], "events": [ "push", "tag", "custom" ] },
];
local master_targets = [
//
// copypasta from here
//
{ "os": "linux", distro: "redhat", "name": "el9", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "redhat", "name": "el8", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "redhat", "name": "el7", "isas": [ "386", "amd64", "ppc64le"], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "amazon", "name": "amzn2", "isas": [ "amd64", "arm64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "amazon", "name": "amzn2022", "isas": [ "amd64", "arm64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "fedora", "name": "fc38", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "fedora", "name": "fc37", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "fedora", "name": "fc36", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "ubuntu", "name": "jammy", "isas": [ "armv7", "amd64", "arm64", "ppc64le", "s390x", "riscv64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "ubuntu", "name": "focal", "isas": [ "armv7", "amd64", "arm64", "ppc64le", "s390x", "riscv64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "ubuntu", "name": "bionic", "isas": [ "386", "armv7", "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "ubuntu", "name": "xenial", "isas": [ "386", "armv7", "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "ubuntu", "name": "trusty", "isas": [ "386", "armv7", "amd64", "arm64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "debian", "name": "sid", "isas": [ "386", "armv7", "amd64", "arm64", "mips64le", "ppc64le", "s390x", "riscv64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "debian", "name": "bookworm", "isas": [ "386", "armv7", "amd64", "arm64", "mips64le", "ppc64le", "s390x" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "debian", "name": "bullseye", "isas": [ "386", "armv7", "amd64", "arm64", "mips64le", "ppc64le", "s390x" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "debian", "name": "buster", "isas": [ "386", "armv7", "amd64", "arm64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "debian", "name": "stretch", "isas": [ "386", "armv7", "amd64", "arm64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "linux", distro: "debian", "name": "jessie", "isas": [ "386", "armv7", "amd64" ], "events": [ "push", "tag", "custom" ] },
{ "os": "windows", distro: "windows", "name": "win2k22", "isas": [ "amd64" ], "events": [ "push", "tag", "custom" ] }
];
//
// functions
//
local pipeline_type(os) = if os == "darwin" then "exec" else "docker";
local builder_image(os) = if os == "linux" then registry + "/honda-builder" else registry + "/windows-builder";
local tester_image(os) = if os == "linux" then registry + "/honda-builder" else registry + "/windows-tester";
local build_step_volumes(os) = if os == "linux" then [ { name: "zerotier-builds", path: "/zerotier-builds" } ] else [];
local release_step_volumes(os) = if os == "linux" then [ { name: "zerotier-releases", path: "/zerotier-releases" } ] else [];
local host_volumes(os) = if os == "linux" then [
{ name: "zerotier-builds", host: { path: "/zerotier-builds" } },
{ name: "zerotier-releases", host: { path: "/zerotier-releases" } },
] else [];
local index_image(distro) =
if distro == "debian" || distro == "ubuntu" then
registry + "/apt-builder"
else if distro == "redhat" || distro == "fedora" || distro == "amazon" then
registry + "/dnf-builder"
else if distro == "windows" then
registry + "/msi-builder"
;
local copy_commands(os, distro, name, isa, version) =
if os == "linux" then [
std.join(" ", [ "./ci/scripts/publish.sh", name, distro, isa, version, "${DRONE_BUILD_EVENT}" ])
]
else if os == "windows" then [
"C:\\scripts\\fix-ec2-metadata.ps1",
"Get-ChildItem windows",
// "aws s3 cp windows\\bytey-SetupFiles\\bytey.msi s3://zerotier-builds/windows/" + version + "/bytey.msi",
] else if os == "darwin" then [
"echo hello"
]
;
local index_commands(os, channel, distro, name, isas) =
if os == "linux" then
[ "/usr/local/bin/index " + channel + " " + distro + " " + name + " " + std.join(" ", isas) ]
else if os == "windows" then
[ "Get-ChildItem -Recurse windows" ]
;
local build_commands(os, distro, name, isa, version) =
if os == "linux" then
[ std.join(" ", [ "./ci/scripts/build.sh", name, distro, isa, version, "${DRONE_BUILD_EVENT}" ]) ]
else
if os == "windows" then
[ "windows/build.ps1", "windows/package.ps1" ]
else
if os == "darwin" then
[ "whoami" ]
;
local test_commands(os, distro, name, isa, version) =
if os == "linux" then
[ std.join(" ", [ "./ci/scripts/test.sh", name, distro, isa, version, "${DRONE_BUILD_EVENT}" ]) ]
else
if os == "windows" then
[ "windows/testpackage.ps1 " + version ]
;
//
// render
//
local Build(os, distro, name, isa, events) = {
"kind": "pipeline",
"type": pipeline_type(os),
"name": std.join(" ", [ name, isa, "build" ]),
"pull": "always",
"clone": { "depth": 1, [ if os == "darwin" then "disable" ]: true },
"steps": [
{
"name": "build",
"image": builder_image(os),
"commands": build_commands(os, distro, name, isa, "100.0.0+${DRONE_COMMIT_SHA:0:8}"),
"when": { "event": [ "push" ]},
},
{
"name": "release",
"image": builder_image(os),
"commands": build_commands(os, distro, name, isa, "${DRONE_TAG}"),
"when": { "event": [ "tag" ]},
},
{
"name": "copy build",
"image": builder_image(os),
"commands": copy_commands(os, distro, name, isa, "100.0.0+${DRONE_COMMIT_SHA:0:8}"),
"volumes": build_step_volumes(os),
"when": { "event": [ "push" ]},
},
{
"name": "copy relase",
"image": builder_image(os),
"commands": copy_commands(os, distro, name, isa, "${DRONE_TAG}"),
"volumes": release_step_volumes(os),
"when": { "event": [ "tag" ]},
},
],
"volumes": host_volumes(os),
"platform": { "os": os, [ if isa == "arm64" || isa == "armv7" then "arch" ]: "arm64" },
"trigger": { "event": events }
};
local Test(os, distro, name, isa, events) = {
"kind": "pipeline",
"type": pipeline_type(os),
"name": std.join(" ", [ name, isa, "test"]),
"pull": "always",
"clone": { "depth": 1 },
"steps": [
{
"name": "test build",
"image": tester_image(os),
"volumes": build_step_volumes(os),
"commands": test_commands(os, distro, name, isa, "100.0.0+${DRONE_COMMIT_SHA:0:8}"),
"when": { "event": [ "push" ]},
},
{
"name": "test release",
"image": tester_image(os),
"volumes": release_step_volumes(os),
"commands": test_commands(os, distro, name, isa, "${DRONE_TAG}"),
"when": { "event": [ "tag" ]},
},
],
"volumes": host_volumes(os),
"platform": { "os": os, [ if isa == "arm64" || isa == "armv7" then "arch" ]: "arm64" },
"depends_on": [ std.join(" ", [ name, "index" ]) ],
"trigger": { "event": events }
};
local Index(p) = {
"kind": "pipeline",
"type": pipeline_type(p.os),
"name": std.join(" ", [ p.name, "index" ]),
"pull": "always",
"clone": { "depth": 1 },
"steps": [
{
"name": "index build",
"image": index_image(p.distro),
"commands": index_commands(p.os, "zerotier-builds", p.distro, p.name, p.isas),
"volumes": build_step_volumes(p.os),
"environment":{ "GPG_PRIVATE_KEY": { from_secret: "gpg-private-key" }},
"when": { "event": [ "push" ]},
},
{
"name": "index release",
"image": index_image(p.distro),
"commands": index_commands(p.os, "zerotier-releases", p.distro, p.name, p.isas),
"volumes": release_step_volumes(p.os),
"environment":{ "GPG_PRIVATE_KEY": { from_secret: "gpg-private-key" }},
"when": { "event": [ "tag" ]},
},
],
"volumes": host_volumes(p.os),
"platform": { "os": p.os },
depends_on: std.flattenArrays([ [ std.join(" ", [ p.name, isa, "build" ]) ] for isa in p.isas ]),
"trigger": { "event": p.events }
};
//
// print
//
std.flattenArrays([
[
Build(p.os, p.distro, p.name, isa, p.events)
for isa in p.isas
] +
[
Index(p)
]
for p in native_targets
]) +
std.flattenArrays([
[
Test(p.os, p.distro, p.name, isa, p.events)
for isa in p.isas
]
for p in native_targets
])

View file

@ -1,465 +0,0 @@
---
clone:
depth: 1
kind: pipeline
name: bullseye 386 build
platform:
os: linux
pull: always
steps:
- commands:
- ./ci/scripts/build.sh bullseye debian 386 100.0.0+${DRONE_COMMIT_SHA:0:8} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: build
when:
event:
- push
- commands:
- ./ci/scripts/build.sh bullseye debian 386 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: release
when:
event:
- tag
- commands:
- ./ci/scripts/publish.sh bullseye debian 386 100.0.0+${DRONE_COMMIT_SHA:0:8} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: copy build
volumes:
- name: zerotier-builds
path: /zerotier-builds
when:
event:
- push
- commands:
- ./ci/scripts/publish.sh bullseye debian 386 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: copy relase
volumes:
- name: zerotier-releases
path: /zerotier-releases
when:
event:
- tag
trigger:
event:
- push
- tag
- custom
type: docker
volumes:
- host:
path: /zerotier-builds
name: zerotier-builds
- host:
path: /zerotier-releases
name: zerotier-releases
---
clone:
depth: 1
kind: pipeline
name: bullseye armv7 build
platform:
arch: arm64
os: linux
pull: always
steps:
- commands:
- ./ci/scripts/build.sh bullseye debian armv7 100.0.0+${DRONE_COMMIT_SHA:0:8} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: build
when:
event:
- push
- commands:
- ./ci/scripts/build.sh bullseye debian armv7 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: release
when:
event:
- tag
- commands:
- ./ci/scripts/publish.sh bullseye debian armv7 100.0.0+${DRONE_COMMIT_SHA:0:8}
${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: copy build
volumes:
- name: zerotier-builds
path: /zerotier-builds
when:
event:
- push
- commands:
- ./ci/scripts/publish.sh bullseye debian armv7 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: copy relase
volumes:
- name: zerotier-releases
path: /zerotier-releases
when:
event:
- tag
trigger:
event:
- push
- tag
- custom
type: docker
volumes:
- host:
path: /zerotier-builds
name: zerotier-builds
- host:
path: /zerotier-releases
name: zerotier-releases
---
clone:
depth: 1
kind: pipeline
name: bullseye amd64 build
platform:
os: linux
pull: always
steps:
- commands:
- ./ci/scripts/build.sh bullseye debian amd64 100.0.0+${DRONE_COMMIT_SHA:0:8} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: build
when:
event:
- push
- commands:
- ./ci/scripts/build.sh bullseye debian amd64 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: release
when:
event:
- tag
- commands:
- ./ci/scripts/publish.sh bullseye debian amd64 100.0.0+${DRONE_COMMIT_SHA:0:8}
${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: copy build
volumes:
- name: zerotier-builds
path: /zerotier-builds
when:
event:
- push
- commands:
- ./ci/scripts/publish.sh bullseye debian amd64 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: copy relase
volumes:
- name: zerotier-releases
path: /zerotier-releases
when:
event:
- tag
trigger:
event:
- push
- tag
- custom
type: docker
volumes:
- host:
path: /zerotier-builds
name: zerotier-builds
- host:
path: /zerotier-releases
name: zerotier-releases
---
clone:
depth: 1
kind: pipeline
name: bullseye arm64 build
platform:
arch: arm64
os: linux
pull: always
steps:
- commands:
- ./ci/scripts/build.sh bullseye debian arm64 100.0.0+${DRONE_COMMIT_SHA:0:8} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: build
when:
event:
- push
- commands:
- ./ci/scripts/build.sh bullseye debian arm64 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: release
when:
event:
- tag
- commands:
- ./ci/scripts/publish.sh bullseye debian arm64 100.0.0+${DRONE_COMMIT_SHA:0:8}
${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: copy build
volumes:
- name: zerotier-builds
path: /zerotier-builds
when:
event:
- push
- commands:
- ./ci/scripts/publish.sh bullseye debian arm64 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: copy relase
volumes:
- name: zerotier-releases
path: /zerotier-releases
when:
event:
- tag
trigger:
event:
- push
- tag
- custom
type: docker
volumes:
- host:
path: /zerotier-builds
name: zerotier-builds
- host:
path: /zerotier-releases
name: zerotier-releases
---
clone:
depth: 1
depends_on:
- bullseye 386 build
- bullseye armv7 build
- bullseye amd64 build
- bullseye arm64 build
kind: pipeline
name: bullseye index
platform:
os: linux
pull: always
steps:
- commands:
- /usr/local/bin/index zerotier-builds debian bullseye 386 armv7 amd64 arm64
environment:
GPG_PRIVATE_KEY:
from_secret: gpg-private-key
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/apt-builder
name: index build
volumes:
- name: zerotier-builds
path: /zerotier-builds
when:
event:
- push
- commands:
- /usr/local/bin/index zerotier-releases debian bullseye 386 armv7 amd64 arm64
environment:
GPG_PRIVATE_KEY:
from_secret: gpg-private-key
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/apt-builder
name: index release
volumes:
- name: zerotier-releases
path: /zerotier-releases
when:
event:
- tag
trigger:
event:
- push
- tag
- custom
type: docker
volumes:
- host:
path: /zerotier-builds
name: zerotier-builds
- host:
path: /zerotier-releases
name: zerotier-releases
---
clone:
depth: 1
depends_on:
- bullseye index
kind: pipeline
name: bullseye 386 test
platform:
os: linux
pull: always
steps:
- commands:
- ./ci/scripts/test.sh bullseye debian 386 100.0.0+${DRONE_COMMIT_SHA:0:8} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: test build
volumes:
- name: zerotier-builds
path: /zerotier-builds
when:
event:
- push
- commands:
- ./ci/scripts/test.sh bullseye debian 386 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: test release
volumes:
- name: zerotier-releases
path: /zerotier-releases
when:
event:
- tag
trigger:
event:
- push
- tag
- custom
type: docker
volumes:
- host:
path: /zerotier-builds
name: zerotier-builds
- host:
path: /zerotier-releases
name: zerotier-releases
---
clone:
depth: 1
depends_on:
- bullseye index
kind: pipeline
name: bullseye armv7 test
platform:
arch: arm64
os: linux
pull: always
steps:
- commands:
- ./ci/scripts/test.sh bullseye debian armv7 100.0.0+${DRONE_COMMIT_SHA:0:8} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: test build
volumes:
- name: zerotier-builds
path: /zerotier-builds
when:
event:
- push
- commands:
- ./ci/scripts/test.sh bullseye debian armv7 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: test release
volumes:
- name: zerotier-releases
path: /zerotier-releases
when:
event:
- tag
trigger:
event:
- push
- tag
- custom
type: docker
volumes:
- host:
path: /zerotier-builds
name: zerotier-builds
- host:
path: /zerotier-releases
name: zerotier-releases
---
clone:
depth: 1
depends_on:
- bullseye index
kind: pipeline
name: bullseye amd64 test
platform:
os: linux
pull: always
steps:
- commands:
- ./ci/scripts/test.sh bullseye debian amd64 100.0.0+${DRONE_COMMIT_SHA:0:8} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: test build
volumes:
- name: zerotier-builds
path: /zerotier-builds
when:
event:
- push
- commands:
- ./ci/scripts/test.sh bullseye debian amd64 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: test release
volumes:
- name: zerotier-releases
path: /zerotier-releases
when:
event:
- tag
trigger:
event:
- push
- tag
- custom
type: docker
volumes:
- host:
path: /zerotier-builds
name: zerotier-builds
- host:
path: /zerotier-releases
name: zerotier-releases
---
clone:
depth: 1
depends_on:
- bullseye index
kind: pipeline
name: bullseye arm64 test
platform:
arch: arm64
os: linux
pull: always
steps:
- commands:
- ./ci/scripts/test.sh bullseye debian arm64 100.0.0+${DRONE_COMMIT_SHA:0:8} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: test build
volumes:
- name: zerotier-builds
path: /zerotier-builds
when:
event:
- push
- commands:
- ./ci/scripts/test.sh bullseye debian arm64 ${DRONE_TAG} ${DRONE_BUILD_EVENT}
image: 084037375216.dkr.ecr.us-east-2.amazonaws.com/honda-builder
name: test release
volumes:
- name: zerotier-releases
path: /zerotier-releases
when:
event:
- tag
trigger:
event:
- push
- tag
- custom
type: docker
volumes:
- host:
path: /zerotier-builds
name: zerotier-builds
- host:
path: /zerotier-releases
name: zerotier-releases
---
kind: signature
hmac: 887a3ef78d3fe8f0149911e1e4876401dd7dd313b36eb893e791fa42f45d7768
...

4
.gitattributes vendored
View file

@ -1,4 +0,0 @@
ext/bin/tap-windows-ndis6/x64/zttap300.inf eol=crlf
ext/bin/tap-windows-ndis6/x64.old/zttap300.inf eol=crlf
ext/bin/tap-windows-ndis6/x86/zttap300.inf eol=crlf
windows/TapDriver6/zttap300.inf eol=crlf

46
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,46 @@
---
name: Bug report
about: Create a report to help us improve
---
**Alternative, faster ways to get help**
If you have just started using ZeroTier, here are some places to get help:
- my.zerotier.com has a _Community_ tab. It's a live chat with other users and the developers.
- [ZeroTier Knowledge Base](https://zerotier.atlassian.net/wiki/spaces/SD/overview)
- www.zerotier.com has a Contact Us button
- email contact@zerotier.com
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Create a Network '...'
2. Install zerotier-one '....'
3. '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots or console output to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. Mac, Linux, Windows, BSD]
- OS/Distribution Version
- ZeroTier Version [e.g. 1.2.4]
- Hardware [e.g. raspberry pi 3]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Version [e.g. 1.2.4]
**Additional context**
Add any other context about the problem here.
- ZeroTier Network Configuration
- Router Config
- Firewall Config (try turning the firewall off)
- General Network Environment: [ e.g Home, University Campus, Corporate LAN ]

View file

@ -1,31 +0,0 @@
---
name: Bugs and Issues
about: Create a report to help us improve
title: ''
labels: NEEDS TRIAGE
assignees: ''
---
# Before filing a Bug Report
_Using these will ensure you get quicker support, and make this space available for code-related issues. Thank you!_
- [Docs Site](https://docs.zerotier.com/zerotier/troubleshooting) => Troubleshooting, quickstarts, and more advanced topics.
- [Discuss Forum](https://discuss.zerotier.com/) => Our discussion forum for users and support to mutually resolve issues & suggest ideas.
- [Reddit](https://www.reddit.com/r/zerotier/) => Our subreddit, which we monitor regularly and is fairly active.
- [Knowledge Base](https://zerotier.atlassian.net/wiki/spaces/SD/overview) => Older wiki.
If you are having a connection issue, it's much easier to diagnose through the discussion forum or the ticket system.
# If you still want to file a Bug Report
## Please let us know
- What you expect to be happening.
- What is actually happening?
- Any steps to reproduce the error.
- Any relevant console output or screenshots.
- What operating system and ZeroTier version. Please try the latest ZeroTier release.

View file

@ -1,13 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[Feature Request] "
labels: suggestion
assignees: ''
---
If there is something you'd like to have added to ZeroTier, to go to https://discuss.zerotier.com/c/feature-requests/ instead. Issues there can be voted on and discussed in-depth.
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
Thank you!
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View file

@ -1,15 +0,0 @@
---
name: Game Connection Issue
about: Game issues are better served by forum posts
title: Please go to our Discuss or Reddit for game-related issues. Thanks!
labels: wontfix
assignees: ''
---
Are you having trouble connecting to a game on your virtual network after installing ZeroTier?
- [ ] Yes
- [ ] No
If you answered yes, then it is very likely that your question would be better answered on our [Community Forums](https://discuss.zerotier.com) or [Reddit](https://www.reddit.com/r/zerotier/) community; we monitor both regularly. We also have extensive documentation on our [Knowledge Base](https://zerotier.atlassian.net/wiki/spaces/SD/overview). Thank you!

View file

@ -1,123 +0,0 @@
on: [ push ]
jobs:
build_ubuntu:
runs-on: ubuntu-latest
steps:
- name: gitconfig
run: |
git config --global core.autocrlf input
# git config --global core.eol lf
- name: checkout
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: x86_64-unknown-linux-gnu
components: rustfmt, clippy
- name: Set up cargo cache
uses: Swatinem/rust-cache@v2
continue-on-error: false
with:
key: ${{ runner.os }}-cargo-${{ hashFiles('rustybits//Cargo.lock') }}
shared-key: ${{ runner.os }}-cargo-
workspaces: |
rustybits/
- name: make
run: make
- name: selftest
run: |
make selftest
./zerotier-selftest
- name: 'Tar files' # keeps permissions (execute)
run: tar -cvf zerotier-one.tar zerotier-one
- name: Archive production artifacts
uses: actions/upload-artifact@v4
with:
name: zerotier-one-ubuntu-x64
path: zerotier-one.tar
retention-days: 7
build_macos:
runs-on: macos-latest
steps:
- name: gitconfig
run: |
git config --global core.autocrlf input
# git config --global core.eol lf
- name: checkout
uses: actions/checkout@v4
- name: Install Rust aarch64
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
target: aarch64-apple-darwin
components: rustfmt, clippy
- name: Install Rust x86_64
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
target: x86_64-apple-darwin
components: rustfmt, clippy
- name: Set up cargo cache
uses: Swatinem/rust-cache@v2
continue-on-error: false
with:
key: ${{ runner.os }}-cargo-${{ hashFiles('rustybits//Cargo.lock') }}
shared-key: ${{ runner.os }}-cargo-
workspaces: |
rustybits/
- name: make
run: make
- name: selftest
run: |
make selftest
./zerotier-selftest
- name: 'Tar files' # keeps permissions (execute)
run: tar -cvf zerotier-one.tar zerotier-one
- name: Archive production artifacts
uses: actions/upload-artifact@v4
with:
name: zerotier-one-mac
path: zerotier-one.tar
retention-days: 7
build_windows:
runs-on: windows-latest
steps:
- name: gitconfig
run: |
git config --global core.autocrlf true
# git config --global core.eol lf
- name: checkout
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
target: aarch64-apple-darwin
components: rustfmt, clippy
- name: Set up cargo cache
uses: Swatinem/rust-cache@v2
continue-on-error: false
with:
key: ${{ runner.os }}-cargo-${{ hashFiles('rustybits//Cargo.lock') }}
shared-key: ${{ runner.os }}-cargo-
workspaces: |
rustybits/
- name: setup msbuild
uses: microsoft/setup-msbuild@v2
- name: msbuild
run: |
msbuild windows\ZeroTierOne.sln /m /p:Configuration=Release /property:Platform=x64 /t:ZeroTierOne
- name: Archive production artifacts
uses: actions/upload-artifact@v4
with:
name: zerotier-one-windows
path: windows/Build
retention-days: 7

View file

@ -1,497 +0,0 @@
#!/bin/bash
# This test script joins Earth and pokes some stuff
TEST_NETWORK=8056c2e21c000001
RUN_LENGTH=30
TEST_FINISHED=false
ZTO_VER=$(git describe --tags $(git rev-list --tags --max-count=1))
ZTO_COMMIT=$(git rev-parse HEAD)
ZTO_COMMIT_SHORT=$(git rev-parse --short HEAD)
TEST_DIR_PREFIX="$ZTO_VER-$ZTO_COMMIT_SHORT-test-results"
TEST_OK=0
TEST_FAIL=1
echo "Performing test on: $ZTO_VER-$ZTO_COMMIT_SHORT"
TEST_FILEPATH_PREFIX="$TEST_DIR_PREFIX/$ZTO_COMMIT_SHORT"
mkdir $TEST_DIR_PREFIX
# How long we will wait for ZT to come online before considering it a failure
MAX_WAIT_SECS=30
ZT_PORT_NODE_1=9996
ZT_PORT_NODE_2=9997
################################################################################
# Multi-node connectivity and performance test #
################################################################################
test() {
echo -e "\nPerforming pre-flight checks"
check_exit_on_invalid_identity
echo -e "\nRunning test for $RUN_LENGTH seconds"
export NS1="ip netns exec ns1"
export NS2="ip netns exec ns2"
export ZT1="$NS1 ./zerotier-cli -p9996 -D$(pwd)/node1"
# Specify custom port on one node to ensure that feature works
export ZT2="$NS2 ./zerotier-cli -p9997 -D$(pwd)/node2"
echo -e "\nSetting up network namespaces..."
echo "Setting up ns1"
ip netns add ns1
$NS1 ip link set dev lo up
ip link add veth0 type veth peer name veth1
ip link set veth1 netns ns1
ip addr add 192.168.0.1/24 dev veth0
ip link set dev veth0 up
$NS1 ip addr add 192.168.0.2/24 dev veth1
$NS1 ip link set dev veth1 up
# Add default route
$NS1 ip route add default via 192.168.0.1
iptables -t nat -A POSTROUTING -s 192.168.0.0/255.255.255.0 \
-o eth0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o veth0 -j ACCEPT
iptables -A FORWARD -o eth0 -i veth0 -j ACCEPT
echo "Setting up ns2"
ip netns add ns2
$NS2 ip link set dev lo up
ip link add veth2 type veth peer name veth3
ip link set veth3 netns ns2
ip addr add 192.168.1.1/24 dev veth2
ip link set dev veth2 up
$NS2 ip addr add 192.168.1.2/24 dev veth3
$NS2 ip link set dev veth3 up
$NS2 ip route add default via 192.168.1.1
iptables -t nat -A POSTROUTING -s 192.168.1.0/255.255.255.0 \
-o eth0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o veth2 -j ACCEPT
iptables -A FORWARD -o eth0 -i veth2 -j ACCEPT
# Allow forwarding
sysctl -w net.ipv4.ip_forward=1
################################################################################
# Memory Leak Check #
################################################################################
export FILENAME_MEMORY_LOG="$TEST_FILEPATH_PREFIX-memory.log"
echo -e "\nStarting a ZeroTier instance in each namespace..."
export time_test_start=$(date +%s)
# Spam the CLI as ZeroTier is starting
spam_cli 100
echo "Starting memory leak check"
$NS1 sudo valgrind --demangle=yes --exit-on-first-error=yes \
--error-exitcode=1 \
--xml=yes \
--xml-file=$FILENAME_MEMORY_LOG \
--leak-check=full \
./zerotier-one node1 -p$ZT_PORT_NODE_1 -U >>node_1.log 2>&1 &
# Second instance, not run in memory profiler
# Don't set up internet access until _after_ zerotier is running
# This has been a source of stuckness in the past.
$NS2 ip addr del 192.168.1.2/24 dev veth3
$NS2 sudo ./zerotier-one node2 -U -p$ZT_PORT_NODE_2 >>node_2.log 2>&1 &
sleep 10; # New HTTP control plane is a bit sluggish, so we delay here
check_bind_to_correct_ports $ZT_PORT_NODE_1
check_bind_to_correct_ports $ZT_PORT_NODE_2
$NS2 ip addr add 192.168.1.2/24 dev veth3
$NS2 ip route add default via 192.168.1.1
echo -e "\nPing from host to namespaces"
ping -c 3 192.168.0.1
ping -c 3 192.168.1.1
echo -e "\nPing from namespace to host"
$NS1 ping -c 3 192.168.0.1
$NS1 ping -c 3 192.168.0.1
$NS2 ping -c 3 192.168.0.2
$NS2 ping -c 3 192.168.0.2
echo -e "\nPing from ns1 to ns2"
$NS1 ping -c 3 192.168.0.1
echo -e "\nPing from ns2 to ns1"
$NS2 ping -c 3 192.168.0.1
################################################################################
# Online Check #
################################################################################
echo "Waiting for ZeroTier to come online before attempting test..."
node1_online=false
node2_online=false
both_instances_online=false
time_zt_node1_start=$(date +%s)
time_zt_node2_start=$(date +%s)
for ((s = 0; s <= $MAX_WAIT_SECS; s++)); do
node1_online="$($ZT1 -j info | jq '.online' 2>/dev/null)"
node2_online="$($ZT2 -j info | jq '.online' 2>/dev/null)"
echo "Checking for online status: try #$s, node1:$node1_online, node2:$node2_online"
if [[ "$node2_online" == "true" && "$node1_online" == "true" ]]; then
export both_instances_online=true
export time_to_both_nodes_online=$(date +%s)
break
fi
sleep 1
done
echo -e "\n\nContents of ZeroTier home paths:"
ls -lga node1
tree node1
ls -lga node2
tree node2
echo -e "\n\nRunning ZeroTier processes:"
echo -e "\nNode 1:\n"
$NS1 ps aux | grep zerotier-one
echo -e "\nNode 2:\n"
$NS2 ps aux | grep zerotier-one
echo -e "\n\nStatus of each instance:"
echo -e "\n\nNode 1:\n"
$ZT1 status
echo -e "\n\nNode 2:\n"
$ZT2 status
if [[ "$both_instances_online" != "true" ]]; then
exit_test_and_generate_report $TEST_FAIL "one or more nodes failed to come online"
fi
echo -e "\nJoining networks"
$ZT1 join $TEST_NETWORK
$ZT2 join $TEST_NETWORK
sleep 10
node1_ip4=$($ZT1 get $TEST_NETWORK ip4)
node2_ip4=$($ZT2 get $TEST_NETWORK ip4)
echo "node1_ip4=$node1_ip4"
echo "node2_ip4=$node2_ip4"
echo -e "\nPinging each node"
PING12_FILENAME="$TEST_FILEPATH_PREFIX-ping-1-to-2.txt"
PING21_FILENAME="$TEST_FILEPATH_PREFIX-ping-2-to-1.txt"
$NS1 ping -c 16 $node2_ip4 >$PING12_FILENAME
$NS2 ping -c 16 $node1_ip4 >$PING21_FILENAME
ping_loss_percent_1_to_2=$(cat $PING12_FILENAME |
grep "packet loss" | awk '{print $6}' | sed 's/%//')
ping_loss_percent_2_to_1=$(cat $PING21_FILENAME |
grep "packet loss" | awk '{print $6}' | sed 's/%//')
# Normalize loss value
export ping_loss_percent_1_to_2=$(echo "scale=2; $ping_loss_percent_1_to_2/100.0" | bc)
export ping_loss_percent_2_to_1=$(echo "scale=2; $ping_loss_percent_2_to_1/100.0" | bc)
################################################################################
# CLI Check #
################################################################################
echo "Testing basic CLI functionality..."
spam_cli 10
$ZT1 join $TEST_NETWORK
$ZT1 -h
$ZT1 -v
$ZT1 status
$ZT1 info
$ZT1 listnetworks
$ZT1 peers
$ZT1 listpeers
$ZT1 -j status
$ZT1 -j info
$ZT1 -j listnetworks
$ZT1 -j peers
$ZT1 -j listpeers
$ZT1 dump
$ZT1 get $TEST_NETWORK allowDNS
$ZT1 get $TEST_NETWORK allowDefault
$ZT1 get $TEST_NETWORK allowGlobal
$ZT1 get $TEST_NETWORK allowManaged
$ZT1 get $TEST_NETWORK bridge
$ZT1 get $TEST_NETWORK broadcastEnabled
$ZT1 get $TEST_NETWORK dhcp
$ZT1 get $TEST_NETWORK id
$ZT1 get $TEST_NETWORK mac
$ZT1 get $TEST_NETWORK mtu
$ZT1 get $TEST_NETWORK name
$ZT1 get $TEST_NETWORK netconfRevision
$ZT1 get $TEST_NETWORK nwid
$ZT1 get $TEST_NETWORK portDeviceName
$ZT1 get $TEST_NETWORK portError
$ZT1 get $TEST_NETWORK status
$ZT1 get $TEST_NETWORK type
# Test an invalid command
$ZT1 get $TEST_NETWORK derpderp
# TODO: Validate JSON
# Performance Test
export FILENAME_PERF_JSON="$TEST_FILEPATH_PREFIX-iperf.json"
echo -e "\nBeginning performance test:"
echo -e "\nStarting server:"
echo "$NS1 iperf3 -s &"
sleep 1
echo -e "\nStarting client:"
sleep 1
echo "$NS2 iperf3 --json -c $node1_ip4 > $FILENAME_PERF_JSON"
cat $FILENAME_PERF_JSON
# Let ZeroTier idle long enough for various timers
echo -e "\nIdling ZeroTier for $RUN_LENGTH seconds..."
sleep $RUN_LENGTH
echo -e "\nLeaving networks"
$ZT1 leave $TEST_NETWORK
$ZT2 leave $TEST_NETWORK
sleep 5
exit_test_and_generate_report $TEST_OK "completed test"
}
################################################################################
# Generate report #
################################################################################
exit_test_and_generate_report() {
echo -e "\nStopping memory check..."
sudo pkill -15 -f valgrind
sleep 10
time_test_end=$(date +%s)
echo "Exiting test with reason: $2 ($1)"
# Collect ZeroTier dump files
echo -e "\nCollecting ZeroTier dump files"
node1_id=$($ZT1 -j status | jq -r .address)
node2_id=$($ZT2 -j status | jq -r .address)
$ZT1 dump
mv zerotier_dump.txt "$TEST_FILEPATH_PREFIX-node-dump-$node1_id.txt"
$ZT2 dump
mv zerotier_dump.txt "$TEST_FILEPATH_PREFIX-node-dump-$node2_id.txt"
# Copy ZeroTier stdout/stderr logs
cp node_1.log "$TEST_FILEPATH_PREFIX-node-log-$node1_id.txt"
cp node_2.log "$TEST_FILEPATH_PREFIX-node-log-$node2_id.txt"
# Generate report
cat $FILENAME_MEMORY_LOG
DEFINITELY_LOST=$(xmlstarlet sel -t -v '/valgrindoutput/error/xwhat' \
$FILENAME_MEMORY_LOG | grep "definitely" | awk '{print $1;}')
POSSIBLY_LOST=$(xmlstarlet sel -t -v '/valgrindoutput/error/xwhat' \
$FILENAME_MEMORY_LOG | grep "possibly" | awk '{print $1;}')
# Generate coverage report artifact and summary
FILENAME_COVERAGE_JSON="$TEST_FILEPATH_PREFIX-coverage.json"
FILENAME_COVERAGE_HTML="$TEST_FILEPATH_PREFIX-coverage.html"
echo -e "\nGenerating coverage test report..."
gcovr -r . --exclude ext --json-summary $FILENAME_COVERAGE_JSON \
--html >$FILENAME_COVERAGE_HTML
cat $FILENAME_COVERAGE_JSON
COVERAGE_LINE_COVERED=$(cat $FILENAME_COVERAGE_JSON | jq .line_covered)
COVERAGE_LINE_TOTAL=$(cat $FILENAME_COVERAGE_JSON | jq .line_total)
COVERAGE_LINE_PERCENT=$(cat $FILENAME_COVERAGE_JSON | jq .line_percent)
COVERAGE_LINE_COVERED="${COVERAGE_LINE_COVERED:-0}"
COVERAGE_LINE_TOTAL="${COVERAGE_LINE_TOTAL:-0}"
COVERAGE_LINE_PERCENT="${COVERAGE_LINE_PERCENT:-0}"
# Default values
DEFINITELY_LOST="${DEFINITELY_LOST:-0}"
POSSIBLY_LOST="${POSSIBLY_LOST:-0}"
ping_loss_percent_1_to_2="${ping_loss_percent_1_to_2:-100.0}"
ping_loss_percent_2_to_1="${ping_loss_percent_2_to_1:-100.0}"
time_to_both_nodes_online="${time_to_both_nodes_online:--1}"
# Summarize and emit json for trend reporting
FILENAME_SUMMARY="$TEST_FILEPATH_PREFIX-summary.json"
time_length_test=$((time_test_end - time_test_start))
if [[ $time_to_both_nodes_online != -1 ]];
then
time_to_both_nodes_online=$((time_to_both_nodes_online - time_test_start))
fi
#time_length_zt_join=$((time_zt_join_end-time_zt_join_start))
#time_length_zt_leave=$((time_zt_leave_end-time_zt_leave_start))
#time_length_zt_can_still_ping=$((time_zt_can_still_ping-time_zt_leave_start))
summary=$(
cat <<EOF
{
"version":"$ZTO_VER",
"commit":"$ZTO_COMMIT",
"arch_m":"$(uname -m)",
"arch_a":"$(uname -a)",
"binary_size":"$(stat -c %s zerotier-one)",
"time_length_test":$time_length_test,
"time_to_both_nodes_online":$time_to_both_nodes_online,
"num_possible_bytes_lost": $POSSIBLY_LOST,
"num_definite_bytes_lost": $DEFINITELY_LOST,
"num_bad_formattings": $POSSIBLY_LOST,
"coverage_lines_covered": $COVERAGE_LINE_COVERED,
"coverage_lines_total": $COVERAGE_LINE_TOTAL,
"coverage_lines_percent": $COVERAGE_LINE_PERCENT,
"ping_loss_percent_1_to_2": $ping_loss_percent_1_to_2,
"ping_loss_percent_2_to_1": $ping_loss_percent_2_to_1,
"test_exit_code": $1,
"test_exit_reason":"$2"
}
EOF
)
echo $summary >$FILENAME_SUMMARY
cat $FILENAME_SUMMARY
exit 0
}
################################################################################
# CLI Check #
################################################################################
spam_cli() {
echo "Spamming CLI..."
# Rapidly spam the CLI with joins/leaves
MAX_TRIES="${1:-10}"
for ((s = 0; s <= MAX_TRIES; s++)); do
$ZT1 status
$ZT2 status
sleep 0.1
done
SPAM_TRIES=128
for ((s = 0; s <= SPAM_TRIES; s++)); do
$ZT1 join $TEST_NETWORK
done
for ((s = 0; s <= SPAM_TRIES; s++)); do
$ZT1 leave $TEST_NETWORK
done
for ((s = 0; s <= SPAM_TRIES; s++)); do
$ZT1 leave $TEST_NETWORK
$ZT1 join $TEST_NETWORK
done
}
################################################################################
# Check for proper exit on load of invalid identity #
################################################################################
check_exit_on_invalid_identity() {
echo "Checking ZeroTier exits on invalid identity..."
mkdir -p $(pwd)/exit_test
ZT1="sudo ./zerotier-one -p9999 $(pwd)/exit_test"
echo "asdfasdfasdfasdf" > $(pwd)/exit_test/identity.secret
echo "asdfasdfasdfasdf" > $(pwd)/exit_test/authtoken.secret
echo "Launch ZeroTier with an invalid identity"
$ZT1 &
my_pid=$!
echo "Waiting 5 seconds"
sleep 5
# check if process is running
kill -0 $my_pid
if [ $? -eq 0 ]; then
exit_test_and_generate_report $TEST_FAIL "Exit test FAILED: Process still running after being fed an invalid identity"
fi
}
################################################################################
# Check that we're binding to the primary port for TCP/TCP6/UDP #
################################################################################
check_bind_to_correct_ports() {
PORT_NUMBER=$1
echo "Checking bound ports:"
sudo netstat -anp | grep "$PORT_NUMBER" | grep "zerotier"
if [[ $(sudo netstat -anp | grep "$PORT_NUMBER" | grep "zerotier" | grep "tcp") ]];
then
:
else
exit_test_and_generate_report $TEST_FAIL "ZeroTier did not bind to tcp/$1"
fi
if [[ $(sudo netstat -anp | grep "$PORT_NUMBER" | grep "zerotier" | grep "tcp6") ]];
then
:
else
exit_test_and_generate_report $TEST_FAIL "ZeroTier did not bind to tcp6/$1"
fi
if [[ $(sudo netstat -anp | grep "$PORT_NUMBER" | grep "zerotier" | grep "udp") ]];
then
:
else
exit_test_and_generate_report $TEST_FAIL "ZeroTier did not bind to udp/$1"
fi
}
test "$@"

View file

@ -1,24 +0,0 @@
#!/bin/bash
################################################################################
# Set exit code depending on tool reports #
################################################################################
DEFINITELY_LOST=$(cat *test-results/*summary.json | jq .num_definite_bytes_lost)
EXIT_CODE=$(cat *test-results/*summary.json | jq .exit_code)
EXIT_REASON=$(cat *test-results/*summary.json | jq .exit_reason)
cat *test-results/*summary.json
echo -e "\nBytes of memory definitely lost: $DEFINITELY_LOST"
if [[ "$DEFINITELY_LOST" -gt 0 ]]; then
exit 1
fi
# Catch-all for other non-zero exit codes
if [[ "$EXIT_CODE" -gt 0 ]]; then
echo "Test failed: $EXIT_REASON"
exit 1
fi

View file

@ -1,56 +0,0 @@
on:
push:
workflow_dispatch:
jobs:
build_ubuntu:
runs-on: ubuntu-latest
steps:
- name: gitconfig
run: |
git config --global core.autocrlf input
- name: checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: x86_64-unknown-linux-gnu
override: true
components: rustfmt, clippy
- name: Set up cargo cache
uses: Swatinem/rust-cache@v2
continue-on-error: false
with:
key: ${{ runner.os }}-cargo-${{ hashFiles('zeroidc//Cargo.lock') }}
shared-key: ${{ runner.os }}-cargo-
workspaces: |
zeroidc/
- name: validate-1m-linux
env:
CC: 'gcc'
CXX: 'g++'
BRANCH: ${{ github.ref_name }}
run: |
sudo apt install -y valgrind xmlstarlet gcovr iperf3 tree
make one ZT_COVERAGE=1 ZT_TRACE=1
sudo chmod +x ./.github/workflows/validate-linux.sh
sudo ./.github/workflows/validate-linux.sh
- name: Archive test results
uses: actions/upload-artifact@v3
with:
name: ${{github.sha}}-test-results
path: "*test-results*"
- name: final-report
run: |
sudo chmod +x ./.github/workflows/validate-report.sh
sudo ./.github/workflows/validate-report.sh

151
.gitignore vendored Executable file → Normal file
View file

@ -1,24 +1,56 @@
# Main binaries created in *nix builds
/zerotier-one
/zerotier-idtool
/zerotier-cli
/zerotier-selftest
/zerotier
/nltest
# IDE stuff
/.idea
/.nova
/compile_commands.json
# OS-created garbage files from various platforms
build/
/version.h
.DS_Store
.Trashes
*.swp
._*
*~
*~.nib
.Apple*
Thumbs.db
@eaDir
._*
DerivedData/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
*.xccheckout
xcuserdata/
.vscode
__pycache__
attic/world/*.c25519
attic/world/mkworld
*.log
*.opensdf
*.user
*.cache
*.obj
*.tlog
*.pid
*.pkg
*.o
*.o-*
*.core
*.deb
*.rpm
*.autosave
*.tmp
.depend
node_modules
debian/files
debian/zerotier-one
debian/zerotier-one*.debhelper
debian/*.log
debian/zerotier-one.substvars
root/identity.*
root/config.*
/ext/installfiles/windows/chocolatey/zerotier-one/*.nupkg
/go/zerotier
# Windows build droppings
/windows/ZeroTierOne.sdf
/windows/ZeroTierOne.v11.suo
/windows/x64
@ -35,8 +67,10 @@ Thumbs.db
/windows/WebUIWrapper/obj
/windows/lib
/ext/installfiles/windows/ZeroTier One-SetupFiles
/ext/installfiles/windows/Prerequisites
/ext/installfiles/windows/*-cache
/ZeroTier One.msi
/*.msi
/windows/.vs
*.vcxproj.backup
/windows/TapDriver6/Win7Debug
/windows/TapDriver6/win7Release
@ -45,48 +79,7 @@ Thumbs.db
enc_temp_folder
/windows/copyutil/bin
/windows/copyutil/obj
.vs/
# *nix/Mac build droppings
/build-*
/ZeroTierOneInstaller-*
/examples/docker/zerotier-one
/examples/docker/test-*.env
/world/mkworld
/world/*.c25519
zt1-src.tar.gz
/MacEthernetTapAgent
# Miscellaneous temporaries, build files, etc.
*.log
*.opensdf
*.user
*.cache
*.tlog
*.pid
*.pkg
*.o
/*.a
*.dylib
*.so
*.so.*
*.o-*
*.core
*.deb
*.rpm
*.autosave
*.tmp
.depend
node_modules
zt1_update_*
debian/files
debian/zerotier-one
debian/zerotier-one*.debhelper
debian/*.log
debian/zerotier-one.substvars
root-watcher/config.json
# Java/Android/JNI build droppings
java/obj/
java/libs/
java/bin/
@ -98,45 +91,3 @@ java/build_win32/
windows/WinUI/obj/
windows/WinUI/bin/
windows/ZeroTierOne/Debug/
/ext/installfiles/windows/chocolatey/zerotier-one/*.nupkg
# Miscellaneous mac/Xcode droppings
.DS_Store
.Trashes
*.swp
*~.nib
DerivedData/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
*.xccheckout
xcuserdata/
.vscode
__pycache__
*~
attic/world/*.c25519
attic/world/mkworld
workspace/
workspace2/
zeroidc/target/
tcp-proxy/target
#snapcraft specifics
/parts/
/stage/
/prime/
*.snap
.snapcraft
__pycache__
*.pyc
*_source.tar.bz2
snap/.snapcraft
tcp-proxy/tcp-proxy
rustybits/target

3
.idea/.gitignore generated vendored Normal file
View file

@ -0,0 +1,3 @@
# Default ignored files
/workspace.xml

9
.idea/ZeroTierOne.iml generated Normal file
View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View file

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

11
.idea/dictionaries/api.xml generated Normal file
View file

@ -0,0 +1,11 @@
<component name="ProjectDictionaryState">
<dictionary name="api">
<words>
<w>apisocket</w>
<w>nwid</w>
<w>secrand</w>
<w>sockaddr</w>
<w>unmarshals</w>
</words>
</dictionary>
</component>

View file

@ -0,0 +1,10 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>

6
.idea/misc.xml generated Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/ZeroTierOne.iml" filepath="$PROJECT_DIR$/.idea/ZeroTierOne.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

29
.idea/watcherTasks.xml generated Normal file
View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions">
<TaskOptions isEnabled="true">
<option name="arguments" value="fmt $FilePath$" />
<option name="checkSyntaxErrors" value="true" />
<option name="description" />
<option name="exitCodeBehavior" value="ERROR" />
<option name="fileExtension" value="go" />
<option name="immediateSync" value="false" />
<option name="name" value="go fmt" />
<option name="output" value="$FilePath$" />
<option name="outputFilters">
<array />
</option>
<option name="outputFromStdout" value="false" />
<option name="program" value="$GoExecPath$" />
<option name="runOnExternalChanges" value="false" />
<option name="scopeName" value="Project Files" />
<option name="trackOnlyRoot" value="true" />
<option name="workingDir" value="$ProjectFileDir$" />
<envs>
<env name="GOROOT" value="$GOROOT$" />
<env name="GOPATH" value="$GOPATH$" />
<env name="PATH" value="$GoBinDirs$" />
</envs>
</TaskOptions>
</component>
</project>

14
.kick
View file

@ -1,14 +0,0 @@
kick
kick
kick
kick
kick
kick
kick
kick
kick
kick
kick
kick
kick
kick

View file

@ -36,12 +36,6 @@ ZeroTier includes the following third party code, either in ext/ or incorporated
* Home page: http://code.google.com/p/lz4/
* License grant: BSD 2-clause
* http-parser by Joyent, Inc. (many authors)
* Files: ext/http-parser/*
* Home page: https://github.com/joyent/http-parser/
* License grant: MIT/Expat
* C++11 json (nlohmann/json) by Niels Lohmann
* Files: ext/json/*
@ -62,12 +56,6 @@ ZeroTier includes the following third party code, either in ext/ or incorporated
* License grant: public domain
* ZeroTier Modifications: slight cryptographically-irrelevant modifications for inclusion into ZeroTier core
* MiniUPNPC and libnatpmp by Thomas Bernard
* Files: ext/libnatpmp/* ext/miniupnpc/*
* Home page: http://miniupnp.free.fr/
* License grant: BSD attribution no-endorsement
* cpp-httplib by yhirose
* Files: ext/cpp-httplib/*

View file

@ -1,12 +1,199 @@
# CMake build script for libzerotiercore.a
cmake_minimum_required (VERSION 3.10)
cmake_minimum_required (VERSION 2.8)
project (zerotiercore)
if(${CMAKE_VERSION} VERSION_LESS 3.15)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else()
cmake_policy(VERSION 3.15)
endif()
set (PROJ_DIR ${PROJECT_SOURCE_DIR})
set (ZT_DEFS -std=c++11)
if(WIN32)
# If building on Windows, set minimum target to Windows 7
set(CMAKE_SYSTEM_VERSION "7" CACHE STRING INTERNAL FORCE)
endif(WIN32)
file(GLOB core_src_glob ${PROJ_DIR}/node/*.cpp)
add_library(zerotiercore STATIC ${core_src_glob})
set(ZEROTIER_ONE_VERSION_MAJOR 2 CACHE INTERNAL "")
set(ZEROTIER_ONE_VERSION_MINOR 0 CACHE INTERNAL "")
set(ZEROTIER_ONE_VERSION_REVISION 0 CACHE INTERNAL "")
set(ZEROTIER_ONE_VERSION_BUILD 0 CACHE INTERNAL "")
target_compile_options(zerotiercore PRIVATE ${ZT_DEFS})
set(default_build_type "Release")
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
set(default_build_type "Debug")
endif()
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
option(BUILD_CENTRAL_CONTROLLER "Build ZeroTier Central Controller" OFF)
option(ZT_TRACE "Trace Messages" OFF)
option(ZT_DEBUG_TRACE "Debug Trace Messages" OFF)
if (BUILD_CENTRAL_CONTROLLER)
find_package(PostgreSQL REQUIRED)
set(ENABLE_SSL_SUPPORT OFF)
set(BUILD_SHARED_LIBS OFF)
set(BUILD_EXAMPLES OFF)
set(BUILD_TOOLS OFF)
set(BUILD_TESTS OFF)
set(BUILD_API_DOCS OFF)
add_subdirectory("ext/librabbitmq")
endif(BUILD_CENTRAL_CONTROLLER)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X Deployment Version")
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DZT_TRACE)
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
project(zerotier
DESCRIPTION "ZeroTier Network Hypervisor"
LANGUAGES CXX C)
if(WIN32)
add_definitions(-DNOMINMAX)
else(WIN32)
if(APPLE)
message("Setting macOS Compiler Flags ${CMAKE_BUILD_TYPE}")
add_compile_options(
-Wall
-Wno-deprecated
-mmacosx-version-min=10.9
$<$<CONFIG:Debug>:-g>
$<$<CONFIG:DEBUG>:-O0>
$<$<CONFIG:RELEASE>:-Ofast>
$<$<CONFIG:RELEASE>:-fPIE>
$<$<CONFIG:RELEASE>:-flto>
$<$<CONFIG:RELWITHDEBINFO>:-Ofast>
$<$<CONFIG:RELWITHDEBINFO>:-fPIE>
$<$<CONFIG:RELWITHDEBINFO>:-g>
)
add_link_options(
-mmacosx-version-min=10.9
$<$<CONFIG:RELEASE>:-flto>
)
elseif (
CMAKE_SYSTEM_NAME MATCHES "Linux" OR
CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR
CMAKE_SYSTEM_NAME MATCHES "OpenBSD" OR
CMAKE_SYSTEM_NAME MATCHES "NetBSD"
)
message("Setting Linux/BSD Compiler Flags (${CMAKE_BUILD_TYPE})")
add_compile_options(
-Wall
-Wno-deprecated
$<$<CONFIG:Debug>:-g>
$<$<CONFIG:DEBUG>:-O0>
$<$<CONFIG:RELEASE>:-O3>
$<$<CONFIG:RELEASE>:-fPIE>
$<$<CONFIG:RELWITHDEBINFO>:-O3>
$<$<CONFIG:RELWITHDEBINFO>:-fPIE>
$<$<CONFIG:RELWITHDEBINFO>:-g>
)
endif(APPLE)
endif(WIN32)
if (
CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR
CMAKE_SYSTEM_PROCESSOR MATCHES "amd64" OR
CMAKE_SYSTEM_PROCESSOR MATCHES "i386" OR
CMAKE_SYSTEM_PROCESSOR MATCHES "i486" OR
CMAKE_SYSTEM_PROCESSOR MATCHES "i586" OR
CMAKE_SYSTEM_PROCESSOR MATCHES "i686"
)
message("Adding SSE and AES-NI flags for processor ${CMAKE_SYSTEM_PROCESSOR}")
add_compile_options(
-maes
-mmmx
-mrdrnd
-mpclmul
-msse
-msse2
-msse3
-msse4.1
)
endif()
if(ZT_TRACE)
add_definitions(-DZT_TRACE)
endif()
if(ZT_DEBUG_TRACE)
add_definitions(-DZT_DEBUG_TRACE)
endif()
add_subdirectory(node)
add_subdirectory(controller)
add_subdirectory(osdep)
add_subdirectory(go/native)
#if(WIN32)
# add_subdirectory("windows/WinUI")
# add_subdirectory("windows/copyutil")
# add_definitions(-DNOMINMAX)
#endif(WIN32)
set(
zt_osdep
zt_core
zt_controller
zt_go_native
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/version.h.in
${CMAKE_CURRENT_BINARY_DIR}/version.h
)
#set(src
# one.cpp
# "ext/http-parser/http_parser.c"
#)
#set(headers
# "ext/http-parser/http_parser.h"
#)
if(WIN32)
set(libs ${libs} wsock32 ws2_32 rpcrt4 iphlpapi)
else(WIN32)
set(libs ${libs} pthread)
endif(WIN32)
#if(WIN32)
# set(libs ${libs} wsock32 ws2_32 rpcrt4 iphlpapi)
# set(src
# ${src}
# "windows/ZeroTierOne/ServiceBase.cpp"
# "windows/ZeroTierOne/ServiceInstaller.cpp"
# "windows/ZeroTierOne/ZeroTierOneService.cpp"
# "windows/ZeroTierOne/ZeroTierOne.rc"
# )
# set(headers
# ${headers}
# "windows/ZeroTierOne/ServiceBase.h"
# "windows/ZeroTierOne/ServiceInstaller.h"
# "windows/ZeroTierOne/ZeroTierOneService.h"
# )
#else(WIN32)
# set(libs ${libs} pthread resolv)
#endif(WIN32)
#if(BUILD_CENTRAL_CONTROLLER)
# set(libs ${libs} rabbitmq-static ${PostgreSQL_LIBRARIES})
#endif(BUILD_CENTRAL_CONTROLLER)
#add_executable(${PROJECT_NAME} ${src} ${headers})
#target_link_libraries(${PROJECT_NAME} ${libs})
#target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR})
add_executable(zerotier-selftest selftest.cpp)
target_link_libraries(zerotier-selftest ${libs} zt_core zt_osdep)
target_compile_features(zerotier-selftest PUBLIC cxx_std_11)

View file

@ -1,28 +0,0 @@
# vim: ft=dockerfile
FROM ubuntu:21.04 as stage
RUN apt-get update -qq && apt-get -qq install make clang
COPY . .
RUN /usr/bin/make
RUN echo $PWD
RUN cp zerotier-one /usr/sbin
FROM ubuntu:21.04
COPY --from=stage /zerotier-one /usr/sbin
RUN ln -sf /usr/sbin/zerotier-one /usr/sbin/zerotier-idtool
RUN ln -sf /usr/sbin/zerotier-one /usr/sbin/zerotier-cli
RUN echo "${VERSION}" > /etc/zerotier-version
RUN rm -rf /var/lib/zerotier-one
RUN apt-get -qq update
RUN apt-get -qq install iproute2 net-tools fping 2ping iputils-ping iputils-arping
COPY entrypoint.sh.release /entrypoint.sh
RUN chmod 755 /entrypoint.sh
CMD []
ENTRYPOINT ["/entrypoint.sh"]

View file

@ -1,23 +0,0 @@
# vim: ft=dockerfile
FROM debian:bullseye
ARG VERSION
RUN apt-get update -qq && apt-get install curl gpg -y
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
RUN apt-get update -qq && apt-get install zerotier-one=${VERSION} curl iproute2 net-tools iputils-ping openssl libssl1.1 -y
RUN rm -rf /var/lib/zerotier-one
COPY entrypoint.sh.release /entrypoint.sh
RUN chmod 755 /entrypoint.sh
HEALTHCHECK --interval=1s CMD bash /healthcheck.sh
CMD []
ENTRYPOINT ["/entrypoint.sh"]

90
Jenkinsfile vendored Normal file
View file

@ -0,0 +1,90 @@
#!/usr/bin/env groovy
node('master') {
checkout scm
def changelog = getChangeLog currentBuild
mattermostSend "Building ${env.JOB_NAME} #${env.BUILD_NUMBER} \n Change Log: \n ${changelog}"
}
parallel 'centos7': {
node('centos7') {
try {
checkout scm
stage('Build Centos 7') {
sh '''. /opt/rh/devtoolset-8/enable
rm -rf build/
mkdir build && cd build
cmake ..
make -j4
./zerotier-selftest
'''
}
}
catch (err) {
currentBuild.result = "FAILURE"
mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on Centos 7 (<${env.BUILD_URL}|Open>)"
throw err
}
}
// }, 'android-ndk': {
// node('android-ndk') {
// try {
// checkout scm
// stage('Build Android NDK') {
// sh "/android/android-ndk-r15b/ndk-build -C $WORKSPACE/java ZT1=${WORKSPACE}"
// }
// }
// catch (err) {
// currentBuild.result = "FAILURE"
// mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on Android NDK (<${env.BUILD_URL}|Open>)"
// throw err
// }
// }
// }, 'macOS': {
// node('macOS') {
// try {
// checkout scm
// stage('Build macOS') {
// sh 'make -f make-mac.mk'
// }
// stage('Build macOS UI') {
// sh 'cd macui && xcodebuild -target "ZeroTier One" -configuration Debug'
// }
// }
// catch (err) {
// currentBuild.result = "FAILURE"
// mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on macOS (<${env.BUILD_URL}|Open>)"
// throw err
// }
// }
// }, 'windows': {
// node('windows') {
// try {
// checkout scm
// stage('Build Windows') {
// bat '''CALL "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\vcvarsall.bat" amd64
// git clean -dfx
// msbuild windows\\ZeroTierOne.sln
// '''
// }
// }
// catch (err) {
// currentBuild.result = "FAILURE"
// mattermostSend color: '#ff0000', message: "${env.JOB_NAME} broken on Windows (<${env.BUILD_URL}|Open>)"
// throw err
// }
// }
}
mattermostSend color: "#00ff00", message: "${env.JOB_NAME} #${env.BUILD_NUMBER} Complete (<${env.BUILD_URL}|Show More...>)"

View file

@ -26,7 +26,7 @@ Additional Use Grant: You may make use of the Licensed Work, provided you
ZeroTier behind the scenes to operate a service not
related to ZeroTier network administration.
* Create Non-Open-Source Commercial Derivative Works
* Create Non-Open-Source Commercial Derviative Works
(2) Link or directly include the Licensed Work in a
commercial or for-profit application or other product
@ -47,7 +47,7 @@ Additional Use Grant: You may make use of the Licensed Work, provided you
services, social welfare, senior care, child care, and
the care of persons with disabilities.
Change Date: 2026-01-01
Change Date: 2023-01-01
Change License: Apache License version 2.0 as published by the Apache
Software Foundation

View file

@ -1,33 +1,20 @@
# Common makefile -- loads make rules for each platform
OSTYPE=$(shell uname -s)
BUILDDIR := build
ifeq ($(OSTYPE),Darwin)
include make-mac.mk
endif
.PHONY: all
ifeq ($(OSTYPE),Linux)
include make-linux.mk
endif
all: setup
cd ${BUILDDIR} && $(MAKE) -j$(shell getconf _NPROCESSORS_ONLN)
ifeq ($(OSTYPE),FreeBSD)
CC=clang
CXX=clang++
ZT_BUILD_PLATFORM=7
include make-bsd.mk
endif
ifeq ($(OSTYPE),OpenBSD)
CC=clang
CXX=clang++
ZT_BUILD_PLATFORM=9
include make-bsd.mk
endif
setup:
mkdir -p ${BUILDDIR} && cd ${BUILDDIR} && cmake .. -DCMAKE_BUILD_TYPE=Release
ifeq ($(OSTYPE),NetBSD)
include make-netbsd.mk
endif
debug:
mkdir -p ${BUILDDIR} && cd ${BUILDDIR} && cmake .. -DCMAKE_BUILD_TYPE=Debug && $(MAKE)
drone:
@echo "rendering .drone.yaml from .drone.jsonnet"
drone jsonnet --format --stream
drone sign zerotier/ZeroTierOne --save
clean:
rm -rf ${BUILDDIR}
distclean:
rm -rf ${BUILDDIR}

View file

@ -14,7 +14,7 @@ The version must be incremented in all of the following files:
/debian/changelog
/ext/installfiles/mac/ZeroTier One.pkgproj
/ext/installfiles/windows/ZeroTier One.aip
../DesktopUI/mac-app-template/ZeroTier.app/Contents/Info.plist
/windows/WinUI/AboutView.xaml
The final .AIP file can only be edited on Windows with [Advanced Installer Enterprise](http://www.advancedinstaller.com/). In addition to incrementing the version be sure that a new product code is generated. (The "upgrade code" GUID on the other hand must never change.)

View file

@ -1,72 +0,0 @@
# ZeroTier One in a container!
**NOTE:** _Most of this information pertains to the docker image only. For more information about ZeroTier, check out the repository_: [here](https://github.com/zerotier/ZeroTierOne) or the [commercial website](https://www.zerotier.com).
[ZeroTier](https://www.zerotier.com) is a smart programmable Ethernet switch for planet Earth. It allows all networked devices, VMs, containers, and applications to communicate as if they all reside in the same physical data center or cloud region.
This is accomplished by combining a cryptographically addressed and secure peer to peer network (termed VL1) with an Ethernet emulation layer somewhat similar to VXLAN (termed VL2). Our VL2 Ethernet virtualization layer includes advanced enterprise SDN features like fine grained access control rules for network micro-segmentation and security monitoring.
All ZeroTier traffic is encrypted end-to-end using secret keys that only you control. Most traffic flows peer to peer, though we offer free (but slow) relaying for users who cannot establish peer to peer connections.
The goals and design principles of ZeroTier are inspired by among other things the original [Google BeyondCorp](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43231.pdf) paper and the [Jericho Forum](https://en.wikipedia.org/wiki/Jericho_Forum) with its notion of "deperimeterization."
Visit [ZeroTier's site](https://www.zerotier.com/) for more information and [pre-built binary packages](https://www.zerotier.com/download/). Apps for Android and iOS are available for free in the Google Play and Apple app stores.
ZeroTier is licensed under the [BSL version 1.1](https://mariadb.com/bsl11/). See [LICENSE.txt](https://github.com/zerotier/ZeroTierOne/blob/master/LICENSE.txt) and the [ZeroTier pricing page](https://www.zerotier.com/pricing) for details. ZeroTier is free to use internally in businesses and academic institutions and for non-commercial purposes. Certain types of commercial use such as building closed-source apps and devices based on ZeroTier or offering ZeroTier network controllers and network management as a SaaS service require a commercial license.
A small amount of third party code is also included in ZeroTier and is not subject to our BSL license. See [AUTHORS.md](https://github.com/zerotier/ZeroTierOne/blob/master/AUTHORS.md) for a list of third party code, where it is included, and the licenses that apply to it. All of the third party code in ZeroTier is liberally licensed (MIT, BSD, Apache, public domain, etc.).
## Building the docker image
Due to the network being a substrate for most applications and not an application unto itself, it makes sense that many people would want to build their own image based on our formula.
The image is based on `debian:buster`.
The `Dockerfile.release` file contains build instructions for building the described image in the rest of the README. The build is multi-arch and multi-release capable.
These build arguments power the build:
- `PACKAGE_BASEURL`: The base URL of the package repository to fetch from. (default: `https://download.zerotier.com/debian/buster/pool/main/z/zerotier-one/`)
- `ARCH`: The architecture of the package, in debian format. Must match your image arch. (default: `amd64`)
- `VERSION`: **REQUIRED** the version of ZeroTier to fetch.
You can build this image like so:
```
docker build -f Dockerfile.release -t mybuild --build-arg VERSION=1.6.5 .
```
## Using the docker image
The `entrypoint.sh` in the docker image is a little different; zerotier will be spawned in the background and the "main process" is actually just a sleeping shell script. This allows `zerotier-one` to gracefully terminate in some situations largely unique to docker.
The `zerotier/zerotier` image requires the `CAP_NET_ADMIN` capability and the `/dev/net/tun` device must be forwarded to it.
To join a network, simply supply it on the command-line; you can supply multiple networks.
```
docker run --name myzerotier --rm --cap-add NET_ADMIN --device /dev/net/tun zerotier/zerotier:latest abcdefdeadbeef00
```
Once joining all the networks you have provided, it will sleep until terminated. Note that in ZeroTier, joining a network does not necessarily mean you have an IP or can do anything, really. You will want to probe the control socket:
```
docker exec myzerotier zerotier-cli listnetworks
```
To ensure you have a network available before trying to listen on it. Without pre-configuring the identity, this usually means going to the central admin panel and clicking the checkmark against your zerotier identity.
### Environment Variables
You can control a few settings including the identity used and the authtoken used to interact with the control socket (which you can forward and access through `localhost:9993`).
- `ZEROTIER_JOIN_NETWORKS`: additional way to set networks to join.
- `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.
### Tips
- Forwarding port `<dockerip>:9993` to somewhere outside is probably a good idea for highly trafficked services.
- Forwarding `localhost:9993` to a control network where you can drive it remotely might be a good idea, just be sure to set your authtoken properly through environment variables.
- Pre-generating your identities could be much simpler to do via our [terraform plugin](https://github.com/zerotier/terraform-provider-zerotier)

135
README.md
View file

@ -1,13 +1,11 @@
ZeroTier - Global Area Networking
======
*This document is written for a software developer audience. For information on using ZeroTier, see the: [Website](https://www.zerotier.com), [Documentation Site](https://docs.zerotier.com), and [Discussion Forum](https://discuss.zerotier.com).*
ZeroTier is a smart programmable Ethernet switch for planet Earth. It allows all networked devices, VMs, containers, and applications to communicate as if they all reside in the same physical data center or cloud region.
This is accomplished by combining a cryptographically addressed and secure peer to peer network (termed VL1) with an Ethernet emulation layer somewhat similar to VXLAN (termed VL2). Our VL2 Ethernet virtualization layer includes advanced enterprise SDN features like fine grained access control rules for network micro-segmentation and security monitoring.
All ZeroTier traffic is encrypted end-to-end using secret keys that only you control. Most traffic flows peer to peer, though we offer free (but slow) relaying for users who cannot establish peer to peer connections.
All ZeroTier traffic is encrypted end-to-end using secret keys that only you control. Most traffic flows peer to peer, though we offer free (but slow) relaying for users who cannot establish peer to peer connetions.
The goals and design principles of ZeroTier are inspired by among other things the original [Google BeyondCorp](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43231.pdf) paper and the [Jericho Forum](https://en.wikipedia.org/wiki/Jericho_Forum) with its notion of "deperimeterization."
@ -15,7 +13,7 @@ Visit [ZeroTier's site](https://www.zerotier.com/) for more information and [pre
ZeroTier is licensed under the [BSL version 1.1](https://mariadb.com/bsl11/). See [LICENSE.txt](LICENSE.txt) and the [ZeroTier pricing page](https://www.zerotier.com/pricing) for details. ZeroTier is free to use internally in businesses and academic institutions and for non-commercial purposes. Certain types of commercial use such as building closed-source apps and devices based on ZeroTier or offering ZeroTier network controllers and network management as a SaaS service require a commercial license.
A small amount of third party code is also included in ZeroTier and is not subject to our BSL license. See [AUTHORS.md](AUTHORS.md) for a list of third party code, where it is included, and the licenses that apply to it. All of the third party code in ZeroTier is liberally licensed (MIT, BSD, Apache, public domain, etc.).
A small amount of third party code is also included in ZeroTier and is not subject to our BSL license. See [AUTHORS.md] for a list of third party code, where it is included, and the licenses that apply to it. All of the third party code in ZeroTier is liberally licensed (MIT, BSD, Apache, public domain, etc.).
### Getting Started
@ -37,161 +35,74 @@ The base path contains the ZeroTier One service main entry point (`one.cpp`), se
- `ext/`: third party libraries, binaries that we ship for convenience on some platforms (Mac and Windows), and installation support files.
- `include/`: include files for the ZeroTier core.
- `java/`: a JNI wrapper used with our Android mobile app. (The whole Android app is not open source but may be made so in the future.)
- `macui/`: a Macintosh menu-bar app for controlling ZeroTier One, written in Objective C.
- `node/`: the ZeroTier virtual Ethernet switch core, which is designed to be entirely separate from the rest of the code and able to be built as a stand-alone OS-independent library. Note to developers: do not use C++11 features in here, since we want this to build on old embedded platforms that lack C++11 support. C++11 can be used elsewhere.
- `osdep/`: code to support and integrate with OSes, including platform-specific stuff only built for certain targets.
- `rule-compiler/`: JavaScript rules language compiler for defining network-level rules.
- `service/`: the ZeroTier One service, which wraps the ZeroTier core and provides VPN-like connectivity to virtual networks for desktops, laptops, servers, VMs, and containers.
- `windows/`: Visual Studio solution files, Windows service code, and the Windows task bar app UI.
- `zeroidc/`: OIDC implementation used by ZeroTier service to log into SSO-enabled networks. (This part is written in Rust, and more Rust will be appearing in this repository in the future.)
### Contributing
Please do pull requests off of the `dev` branch.
Releases are done by merging `dev` into `main` and then tagging and doing builds.
### Build and Platform Notes
To build on Mac and Linux just type `make`. On FreeBSD and OpenBSD `gmake` (GNU make) is required and can be installed from packages or ports. For Windows there is a Visual Studio solution in `windows/`.
To build on Mac and Linux just type `make`. On FreeBSD and OpenBSD `gmake` (GNU make) is required and can be installed from packages or ports. For Windows there is a Visual Studio solution in `windows/'.
- **Mac**
- Xcode command line tools for macOS 10.13 or newer are required.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
- Xcode command line tools for OSX 10.8 or newer are required.
- **Linux**
- The minimum compiler versions required are GCC/G++ 8.x or CLANG/CLANG++ 5.x.
- The minimum compiler versions required are GCC/G++ 4.9.3 or CLANG/CLANG++ 3.4.2. (Install `clang` on CentOS 7 as G++ is too old.)
- Linux makefiles automatically detect and prefer clang/clang++ if present as it produces smaller and slightly faster binaries in most cases. You can override by supplying CC and CXX variables on the make command line.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
- **Windows**
- Visual Studio 2022 on Windows 10 or newer.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
- Windows 7 or newer is supported. This *may* work on Vista but isn't officially supported there. It will not work on Windows XP.
- We build with Visual Studio 2017. Older versions may not work. Clang or MinGW will also probably work but may require some makefile hacking.
- **FreeBSD**
- GNU make is required. Type `gmake` to build.
- `binutils` is required. Type `pkg install binutils` to install.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
- **OpenBSD**
- There is a limit of four network memberships on OpenBSD as there are only four tap devices (`/dev/tap0` through `/dev/tap3`).
- GNU make is required. Type `gmake` to build.
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
Typing `make selftest` will build a *zerotier-selftest* binary which unit tests various internals and reports on a few aspects of the build environment. It's a good idea to try this on novel platforms or architectures.
### Running
Running *zerotier-one* with `-h` option will show help.
Running *zerotier-one* with -h will show help.
On Linux and BSD, if you built from source, you can start the service with:
On Linux and BSD you can start the service with:
sudo ./zerotier-one -d
On most distributions, macOS, and Windows, the installer will start the service and set it up to start on boot.
A home folder for your system will automatically be created.
The service is controlled via the JSON API, which by default is available at `127.0.0.1:9993`. It also listens on `0.0.0.0:9993` which is only usable if `allowManagementFrom` is properly configured in `local.conf`. We include a *zerotier-cli* command line utility to make API calls for standard things like joining and leaving networks. The *authtoken.secret* file in the home folder contains the secret token for accessing this API. See [service/README.md](service/README.md) for API documentation.
The service is controlled via the JSON API, which by default is available at 127.0.0.1 port 9993. We include a *zerotier-cli* command line utility to make API calls for standard things like joining and leaving networks. The *authtoken.secret* file in the home folder contains the secret token for accessing this API. See README.md in [service/](service/) for API documentation.
Here's where home folders live (by default) on each OS:
* **Linux**: `/var/lib/zerotier-one`
* **FreeBSD** / **OpenBSD**: `/var/db/zerotier-one`
* **Mac**: `/Library/Application Support/ZeroTier/One`
* **Windows**: `\ProgramData\ZeroTier\One` (That's the default. The base 'shared app data' folder might be different if Windows is installed with a non-standard drive letter assignment or layout.)
* **Windows**: `\ProgramData\ZeroTier\One` (That's for Windows 7. The base 'shared app data' folder might be different on different Windows versions.)
Running ZeroTier One on a Mac is the same, but OSX requires a kernel extension. We ship a signed binary build of the ZeroTier tap device driver, which can be installed on Mac with:
sudo make install-mac-tap
This will create the home folder for Mac, place *tap.kext* there, and set its modes correctly to enable ZeroTier One to manage it with *kextload* and *kextunload*.
### Basic Troubleshooting
For most users, it just works.
If you are running a local system firewall, we recommend adding a rules permitting zerotier. If you installed binaries for Windows this should be done automatically. Other platforms might require manual editing of local firewall rules depending on your configuration.
If you are running a local system firewall, we recommend adding a rule permitting UDP port 9993 inbound and outbound. If you installed binaries for Windows this should be done automatically. Other platforms might require manual editing of local firewall rules depending on your configuration.
See the [documentation site](https://docs.zerotier.com/zerotier/troubleshooting) for more information.
The Mac firewall can be found under "Security" in System Preferences. Linux has a variety of firewall configuration systems and tools. If you're using Ubuntu's *ufw*, you can do this:
The Mac firewall can be found under "Security" in System Preferences. Linux has a variety of firewall configuration systems and tools.
sudo ufw allow 9993/udp
On CentOS check `/etc/sysconfig/iptables` for IPTables rules. For other distributions consult your distribution's documentation. You'll also have to check the UIs or documentation for commercial third party firewall applications like Little Snitch (Mac), McAfee Firewall Enterprise (Windows), etc. if you are running any of those. Some corporate environments might have centrally managed firewall software, so you might also have to contact IT.
ZeroTier One peers will automatically locate each other and communicate directly over a local wired LAN *if UDP port 9993 inbound is open*. If that port is filtered, they won't be able to see each others' LAN announcement packets. If you're experiencing poor performance between devices on the same physical network, check their firewall settings. Without LAN auto-location peers must attempt "loopback" NAT traversal, which sometimes fails and in any case requires that every packet traverse your external router twice.
Users behind certain types of firewalls and "symmetric" NAT devices may not be able to connect to external peers directly at all. ZeroTier has limited support for port prediction and will *attempt* to traverse symmetric NATs, but this doesn't always work. If P2P connectivity fails you'll be bouncing UDP packets off our relay servers resulting in slower performance. Some NAT router(s) have a configurable NAT mode, and setting this to "full cone" will eliminate this problem. If you do this you may also see a magical improvement for things like VoIP phones, Skype, BitTorrent, WebRTC, certain games, etc., since all of these use NAT traversal techniques similar to ours.
Users behind certain types of firewalls and "symmetric" NAT devices may not able able to connect to external peers directly at all. ZeroTier has limited support for port prediction and will *attempt* to traverse symmetric NATs, but this doesn't always work. If P2P connectivity fails you'll be bouncing UDP packets off our relay servers resulting in slower performance. Some NAT router(s) have a configurable NAT mode, and setting this to "full cone" will eliminate this problem. If you do this you may also see a magical improvement for things like VoIP phones, Skype, BitTorrent, WebRTC, certain games, etc., since all of these use NAT traversal techniques similar to ours.
If a firewall between you and the Internet blocks ZeroTier's UDP traffic, you will fall back to last-resort TCP tunneling to rootservers over port 443 (https impersonation). This will work almost anywhere but is *very slow* compared to UDP or direct peer to peer connectivity.
Additional help can be found in our [knowledge base](https://zerotier.atlassian.net/wiki/spaces/SD/overview).
### Prometheus Metrics
Prometheus Metrics are available at the `/metrics` API endpoint. This endpoint is protected by an API key stored in `metricstoken.secret` to prevent unwanted information leakage. Information that could be gleaned from the metrics include joined networks and peers your instance is talking to.
Access control is via the ZeroTier control interface itself and `metricstoken.secret`. This can be sent as a bearer auth token, via the `X-ZT1-Auth` HTTP header field, or appended to the URL as `?auth=<token>`. You can see the current metrics via `cURL` with the following command:
// Linux
curl -H "X-ZT1-Auth: $(sudo cat /var/lib/zerotier-one/metricstoken.secret)" http://localhost:9993/metrics
// macOS
curl -H "X-ZT1-Auth: $(sudo cat /Library/Application\ Support/ZeroTier/One/metricstoken.secret)" http://localhost:9993/metrics
// Windows PowerShell (Admin)
Invoke-RestMethod -Headers @{'X-ZT1-Auth' = "$(Get-Content C:\ProgramData\ZeroTier\One\metricstoken.secret)"; } -Uri http://localhost:9993/metrics
To configure a scrape job in Prometheus on the machine ZeroTier is running on, add this to your Prometheus `scrape_config`:
- job_name: zerotier-one
honor_labels: true
scrape_interval: 15s
metrics_path: /metrics
static_configs:
- targets:
- 127.0.0.1:9993
labels:
group: zerotier-one
node_id: $YOUR_10_CHARACTER_NODE_ID
authorization:
credentials: $YOUR_METRICS_TOKEN_SECRET
If neither of these methods are desirable, it is probably possible to distribute metrics via [Prometheus Proxy](https://github.com/pambrose/prometheus-proxy) or some other tool. Note: We have not tested this internally, but will probably work with the correct configuration.
Metrics are also available on disk in ZeroTier's working directory:
// Linux
/var/lib/zerotier-one/metrics.prom
// macOS
/Library/Application\ Support/ZeroTier/One/metrics.prom
//Windows
C:\ProgramData\ZeroTier\One\metrics.prom
#### Available Metrics
| Metric Name | Labels | Metric Type | Description |
| --- | --- | --- | --- |
| zt_packet | packet_type, direction | Counter | ZeroTier packet type counts |
| zt_packet_error | error_type, direction | Counter | ZeroTier packet errors|
| zt_data | protocol, direction | Counter | number of bytes ZeroTier has transmitted or received |
| zt_num_networks | | Gauge | number of networks this instance is joined to |
| zt_network_multicast_groups_subscribed | network_id | Gauge | number of multicast groups networks are subscribed to |
| zt_network_packets | network_id, direction | Counter | number of incoming/outgoing packets per network |
| zt_peer_latency | node_id | Histogram | peer latency (ms) |
| zt_peer_path_count | node_id, status | Gauge | number of paths to peer |
| zt_peer_packets | node_id, direction | Counter | number of packets to/from a peer |
| zt_peer_packet_errors | node_id | Counter | number of incoming packet errors from a peer |
If there are other metrics you'd like to see tracked, ask us in an Issue or send us a Pull Request!
### HTTP / App server
There is a static http file server suitable for hosting Single Page Apps at http://localhost:9993/app/<app-path>
Use `zerotier-cli info -j` to find your zerotier-one service's homeDir
``` sh
cd $ZT_HOME
sudo mkdir -p app/app1
sudo mkdir -p app/appB
echo '<html><meta charset=utf-8><title>appA</title><body><h1>hello world A' | sudo tee app/appA/index.html
echo '<html><meta charset=utf-8><title>app2</title><body><h1>hello world 2' | sudo tee app/app2/index.html
curl -sL http://localhost:9993/app/appA http://localhost:9993/app/app2
```
Then visit [http://localhost:9993/app/app1/](http://localhost:9993/app/app1/) and [http://localhost:9993/app/appB/](http://localhost:9993/app/appB/)
Requests to paths don't exist return the app root index.html, as is customary for SPAs.
If you want, you can write some javascript that talks to the service or controller [api](https://docs.zerotier.com/service/v1).
Additional help [can be found in our knowledge base](https://zerotier.atlassian.net/wiki/spaces/SD/overview).

View file

@ -1,272 +1,6 @@
ZeroTier Release Notes
======
# 2024-09-12 -- Version 1.14.1
* Multithreaded packet I/O support! Currently this is just for Linux and must
be enabled in local.conf. It will likely make the largest difference on small
multi-core devices where CPU is a bottleneck and high throughput is desired.
It may be enabled by default in the future but we want it to be thoroughly
tested. It's a little harder than it seems at first glance due to the need
to keep packets in sequence and balance load.
* Several multipath bug fixes.
* Updated the versions on a number of libraries related to OIDC support and HTTP.
* MacOS .app now shows the correct version in its Info.plist manifest.
* Sanitize MAC addresses in JSON format rules parser.
* Some basic information about the platform (OS, CPU architecture) is now reported
to network controllers when networks are joined so it can be displayed to
network admins and in the future used in policy checking and inventory operations.
# 2024-05-02 -- Version 1.14.0
* Linux I/O performance improvements under heavy load
* Improvements to multipath
* Fix for port rebinding "coma" bug after periods offline (some laptop users)
* Fixed a rules engine quirk/ambiguity (GitHub Issue #2200)
* Controller API enhancements: node names and other node meta-data
* Other bug fixes
# 2023-09-12 -- Version 1.12.2
* More improvements to macOS full tunnel mode.
* Faster recovery after changes to physical network settings.
# 2023-08-25 -- Version 1.12.1
* Minor release to fix a port binding issue in Linux.
* Update Debian dependencies.
* No changes for other platforms.
# 2023-08-23 -- Version 1.12.0
* Experimental Windows ARM64 support
* Fix numerous sleep/wake issues on macOS and other platforms
* Faster recovery after changes to physical network settings
* Prometheus compatible metrics support!
* Fix full tunnel mode on recent macOS versions
* Numerous macOS DNS fixes
* 10-30% speed improvement on Linux
# 2023-03-23 -- Version 1.10.6
* Prevent binding temporary ipv6 addresses on macos (#1910)
* Prevent path-learning loops (#1914)
* Prevent infinite loop of UAC prompts in tray app
# 2023-03-10 -- Version 1.10.5
* Fix for high CPU usage bug on Windows
# 2023-03-07 -- Version 1.10.4
* SECURITY FIX (Windows): this version fixes a file permission problem on
Windows that could allow non-privileged users on a Windows system to read
privileged files in the ZeroTier service's working directory. This could
allow an unprivileged local Windows user to administrate the local ZeroTier
instance without appropriate local permissions. This issue is not remotely
exploitable unless a remote user can read arbitrary local files, and does
not impact other operating systems.
* Fix a bug in the handling of multiple IP address assignments to virtual
interfaces on macOS.
# 2023-02-15 -- Version 1.10.3
* Fix for duplicate paths in client. Could cause connectivity issues. Affects all platforms.
* Fix for Ethernet Tap MTU setting, would not properly apply on Linux.
* Fix default route bugs (macOS.)
* Enable Ping automatically for ZeroTier Adapters (Windows.)
* SSO updates and minor bugfixes.
* Add low-bandwidth mode.
* Add forceTcpRelay mode (optionally enabled.)
* Fix bug that prevented setting of custom TCP relay address.
* Build script improvements and bug fixes.
# 2022-11-01 -- Version 1.10.2
* Fix another SSO "stuck client" issue in zeroidc.
* Expose root-reported external IP/port information via the local JSON API for better diagnostics.
* Multipath: CLI output improvement for inspecting bonds
* Multipath: balance-aware mode
* Multipath: Custom policies
* Multipath: Link quality measurement improvements
Note that releases are coming few and far between because most of our dev effort is going into version 2.
# 2022-06-27 -- Version 1.10.1
* Fix an issue that could cause SSO clients to get "stuck" on stale auth URLs.
* A few other SSO related bug fixes.
# 2022-06-07 -- Version 1.10.0
* Fix formatting problem in `zerotier-cli` when using SSO networks.
* Fix a few other minor bugs in SSO signin to prepare for general availability.
* Remove requirement for webview in desktop UI and instead just make everything available via the tray pulldown/menu. Use [libui-ng](https://github.com/libui-ng/libui-ng) for minor prompt dialogs. Saves space and eliminates installation headaches on Windows.
* Fix SSO "spam" bug in desktop UI.
* Use system default browser for SSO login so all your plugins, MFA devices, password managers, etc. will work as you have them configured.
* Minor fix for bonding/multipath.
# 2022-05-10 -- Version 1.8.10
* Fixed a bug preventing SSO sign-on on Windows.
# 2022-04-25 -- Version 1.8.9
* Fixed a long-standing and strange bug that was causing sporadic "phantom" packet authentication failures. Not a security problem but could be behind sporadic reports of link failures under some conditions.
* Fixed a memory leak in SSO/OIDC support.
* Fixed SSO/OIDC display error on CLI.
* Fixed a bug causing nodes to sometimes fail to push certs to each other (primarily affects SSO/OIDC use cases).
* Fixed a deadlock bug on leaving SSO/OIDC managed networks.
* Added some new Linux distributions to the build subsystem.
# 2022-04-11 -- Version 1.8.8
* Fix a local privilege escalation bug in the Windows installer.
* Dependency fix for some Ubuntu versions.
* No changes for other platforms. Windows upgrade recommended, everyone else optional.
# 2022-03-30 -- Version 1.8.7
* Fix for dependency installations in Windows MSI package.
* Fix for desktop UI setup when run by a non-super-user.
* Bug fix in local OIDC / SSO support for auth0 and other providers.
* Other minor fixes for e.g. old Linux distributions.
# 2022-03-04 -- Version 1.8.6
* Fixed an issue that could cause the UI to be non-responsive if not joined to any networks.
* Fix dependency issues in Debian and RedHat packages for some distributions (Fedora, Mint).
* Bumped the peer cache serialization version to prevent "coma" issues on upgrade due to changes in path logic behaving badly with old values.
# 2022-02-22 -- Version 1.8.5
* Plumbing under the hood for endpoint device SSO support.
* Fix in LinuxEthernetTap to tap device support on very old (2.6) Linux kernels.
* Fix an issue that could cause self-hosted roots ("moons") to fail to assist peers in making direct links. (GitHub issue #1512)
* Merge a series of changes by Joseph Henry (of ZeroTier) that should fix some edge cases where ZeroTier would "forget" valid paths.
* Minor multipath improvements for automatic path negotiation.
# 2021-11-30 -- Version 1.8.4
* Fixed an ugly font problem on some older macOS versions.
* Fixed a bug that could cause the desktop tray app control panel to stop opening after a while on Windows.
* Fixed a possible double "release" in macOS tray app code that crashed on older macOS versions.
* Fixed installation on 32-bit Windows 10.
* Fixed a build flags issue that could cause ZeroTier to crash on older ARM32 CPUs.
# 2021-11-15 -- Version 1.8.3
* Remove problematic spinlock, which was only used on x86_64 anyway. Just use pthread always.
* Fix fd leak on MacOS that caused non-responsiveness after some time.
* Fix Debian install scripts to set /usr/sbin/nologin as shell on service user.
* Fix regression that could prevent managed routes from being deleted.
* DesktopUI: Remove NSDate:now() call, now works on MacOS 10.13 or newer!
# 2021-11-08 -- Version 1.8.2
* Fix multicast on linux.
* Fix a bug that could cause the tap adapter to have the wrong MAC on Linux.
* Update build flags to possibly support MacOS older than 10.14, but more work needs to be done. It may not work yet.
* Fix path variable setting on Windows.
# 2021-10-28 -- Version 1.8.1
* Fix numerous UI issues from 1.8.0 (never fully released).
* Remove support for REALLY ancient 1.1.6 or earlier network controllers.
* MacOS IPv6 no longer binds to temporary addresses as these can cause interruptions if they expire.
* Added additional hardening against address impersonation on networks (also in 1.6.6).
* Fix an issue that could cause clobbering of MacOS IP route settings on restart.
* NOTE: Windows 7 is no longer supported! Windows 7 users will have to use version 1.6.5 or earlier.
# 2021-09-15 -- Version 1.8.0 (preview release only)
* A *completely* rewritten desktop UI for Mac and Windows!
* Implement a workaround for one potential source of a "coma" bug, which can occur if buggy NATs/routers stop allowing the service to communicate on a given port. ZeroTier now reassigns a new secondary port if it's offline for a while unless a secondary port is manually specified in local.conf. Working around crummy buggy routers is an ongoing effort.
* Fix for MacOS MTU capping issue on feth devices
* Fix for mistakenly using v6 source addresses for v4 routes on some platforms
* Stop binding to temporary IPv6 addresses
* Set MAC address before bringing up Linux TAP link
* Check if DNS servers need to be applied on macOS
* Upgrade json.hpp dependency to version 3.10.2
# 2021-09-21 -- Version 1.6.6
* Backport COM hash check mitigation against network member impersonation.
# 2021-04-13 -- Version 1.6.5
* Fix a bug in potential network path filtering that could in some circumstances lead to "software laser" effects.
* Fix a printf overflow in zerotier-cli (not exploitable or a security risk)
* Windows now looks up the name of ZeroTier devices instead of relying on them having "ZeroTier" in them.
# 2021-02-15 -- Version 1.6.4
* The groundhog saw his shadow, which meant that the "connection coma" bug still wasn't gone. We think we found it this time.
# 2021-02-02 -- Version 1.6.3
* Likely fix for GitHub issue #1334, an issue that could cause ZeroTier to
go into a "coma" on some networks.
* Also groundhog day
# 2020-11-30 -- Version 1.6.2
* Fix an ARM hardware AES crypto issue (not an exploitable vulnerability).
* Fix a Linux network leave hang due to a mutex deadlock.
# 2020-11-24 -- Version 1.6.1
This release fixes some minor bugs and other issues in 1.6.0.
* Fixed a bug that caused IP addresses in the 203.0.0.0/8 block to be miscategorized as not being in global scope.
* Changed Linux builds to (hopefully) fix LXC and SELinux issues.
* Fixed unaligned memory access that caused crash on FreeBSD systems on the ARM architecture.
* Merged CLI options for controlling bonded devices into the beta multipath code.
* Updated Windows driver with Microsoft cross-signing to fix issues on some Windows systems.
# 2020-11-19 -- Version 1.6.0
Version 1.6.0 is a major release that incorporates back-ported features from the 2.0 branch, which is still under development. It also fixes a number of issues.
New features and improvements (including those listed under 1.5.0):
* **Apple Silicon** (MacOS ARM64) native support via universal binary. ZeroTier now requires the very latest Xcode to build.
* **Linux performance improvements** for up to 25% faster tun/tap I/O performance on multi-core systems.
* **Multipath support** with modes modeled after the Linux kernel's bonding driver. This includes active-passive and active-active modes with fast failover and load balancing. See section 2.1.5 of the manual.
* **DNS configuration** push from network controllers to end nodes, with locally configurable permissions for whether or not push is allowed.
* **AES-GMAC-SIV** encryption mode, which is both somewhat more secure and significantly faster than the old Salsa20/12-Poly1305 mode on hardware that supports AES acceleration. This includes virtually all X86-64 chips and most ARM64. This mode is based on AES-SIV and has been audited by Trail of Bits to ensure that it is equivalent security-wise.
Bug fixes:
* **Managed route assignment fixes** to eliminate missing routes on Linux and what we believe to be the source of sporadic high CPU usage on MacOS.
* **Hang on shutdown** issues should be fixed.
* **Sporadic multicast outages** should be fixed.
Known remaining issues:
* AES hardware acceleration is not yet supported on 32-bit ARM, PowerPC (32 or 64), or MIPS (32 or 64) systems. Currently supported are X86-64 and ARM64/AARCH64 with crypto extensions.
# 2020-10-05 -- Version 1.5.0 (actually 1.6.0-beta1)
Version 1.6.0 (1.5.0 is a beta!) is a significant release that incorporates a number of back-ported fixes and features from the ZeroTier 2.0 tree.
Major new features are:
* **Multipath support** with modes modeled after the Linux kernel's bonding driver. This includes active-passive and active-active modes with fast failover and load balancing. See section 2.1.5 of the manual.
* **DNS configuration** push from network controllers to end nodes, with locally configurable permissions for whether or not push is allowed.
* **AES-GMAC-SIV** encryption mode, which is both somewhat more secure and significantly faster than the old Salsa20/12-Poly1305 mode on hardware that supports AES acceleration. This includes virtually all X86-64 chips and most ARM64. This mode is based on AES-SIV and has been audited by Trail of Bits to ensure that it is equivalent security-wise.
Known issues that are not yet fixed in this beta:
* Some Mac users have reported periods of 100% CPU in kernel_task and connection instability after leaving networks that have been joined for a period of time, or needing to kill ZeroTier and restart it to finish leaving a network. This doesn't appear to affect all users and we haven't diagnosed the root cause yet.
* The service sometimes hangs on shutdown requiring a kill -9. This also does not affect all systems or users.
* AES hardware acceleration is not yet supported on 32-bit ARM, PowerPC (32 or 64), or MIPS (32 or 64) systems. Currently supported are X86-64 and ARM64/AARCH64 with crypto extensions.
* Some users have reported multicast/broadcast outages on networks lasting up to 30 seconds. Still investigating.
We're trying to fix all these issues before the 1.6.0 release. Stay tuned.
# 2019-08-30 -- Version 1.4.6
* Update default root list to latest
@ -365,7 +99,7 @@ We're trying to fix all these issues before the 1.6.0 release. Stay tuned.
# 2017-04-20 -- Version 1.2.4
* Managed routes are now only bifurcated for the default route. This is a change in behavior, though few people will probably notice. Bifurcating all managed routes was causing more trouble than it was worth for most users.
* Up to 2X crypto speedup on x86-64 (except Windows, which will take some porting) and 32-bit ARM platforms due to integration of fast assembly language implementations of Salsa20/12 from the [supercop](http://bench.cr.yp.to/supercop.html) code base. These were written by Daniel J. Bernstein and are in the public domain. My MacBook Pro (Core i5 2.8ghz) now does almost 1.5GiB/sec Salsa20/12 per core and a Raspberry Pi got a 2X boost. 64-bit ARM support and Windows support will take some work but should not be too hard.
* Up to 2X crypto speedup on x86-64 (except Windows, which will take some porting) and 32-bit ARM platforms due to integration of fast assembly language implementations of Salsa20/12 from the [supercop](http://bench.cr.yp.to/supercop.html) code base. These were written by Daniel J. Bernstein and are in the public domain. My Macbook Pro (Core i5 2.8ghz) now does almost 1.5GiB/sec Salsa20/12 per core and a Raspberry Pi got a 2X boost. 64-bit ARM support and Windows support will take some work but should not be too hard.
* Refactored code that manages credentials to greatly reduce memory use in most cases. This may also result in a small performance improvement.
* Reworked and simplified path selection and priority logic to fix path instability and dead path persistence edge cases. There have been some sporadic reports of persistent path instabilities and dead paths hanging around that take minutes to resolve. These have proven difficult to reproduce in house, but hopefully this will fix them. In any case it seems to speed up path establishment in our tests and it makes the code simpler and more readable.
* Eliminated some unused cruft from the code around path management and in the peer class.

View file

@ -1,93 +0,0 @@
# Security
ZeroTier takes the security of our software products and services seriously, which
includes all source code repositories managed through our GitHub organization.
## Supported Versions
The following versions of ZeroTier One receive security updates
| Version | Supported |
| -------- | ------------------ |
| 1.14.x | :white_check_mark: |
| 1.12.x | :white_check_mark: |
| < 1.12.0 | :x: |
## Reporting a Vulnerability
**Please do not report security issues through public GitHub issues**
Instead, please report vulnerabilities via email to security@zerotier.com. If possible,
please encrypt with our PGP key (see below).
Please include the following information, or as much as you can provide to help us
understand the nature and scope of the issue:
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
## Preferred Languages
We prefer all communications to be in English.
## security@zerotier.com PGP key
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGQGOVIBEACalXTnNqaiSOVLFEiqHpDMg8N/OI5D5850Xy1ZEvx3B3rz7cbn
k30ozHtJKbh+vqpyItE7DjyQAuF19gP5Q64Yh0Y+MmLHq60q/GwOwAYz7cI+UzA3
5x8YqcmTp32LAM1xJn+iMlMLBuAmJl4kULKmOXPlpqPiyTFs5saizvm7fgRmfgJJ
HpsnIrTkaDFJhAR+jvMJohVYwmhuydeI0DsHu7KGpG1ddcHDrUjOPNqXnnAPSPwx
llw4yfKlQb8GYErsv/G5QVyzd5+SxEuiI4MARRnrk8LlMQ33CR6pzIQ/Bk5AAmye
mHqfEAknkiOf++urYhRs9BL3Kz3MdV0cg92zr9EFOg0u56jxf5OnAiTOhGUUA0hn
dS7peVGl46R9Oy2JYIazNDGi+4NIsYDFXsnsss9xOQVygPyeQd71zFHfix0jct9w
j3o/kj7Egsnm9nc13354bYT6bbalqXiRWwGH1eAFpjueNWiVFwZS6NZUP3WeNDiY
BlPo1LodvolbXiJcTILTCyEkERJPCK2zoE2nTdVfvTLWsuehw1M6Yd2/q74TVYy/
RY+KjHkrChEBQ9PqXsXRHj6opKbT8JLfZkvU5k+3IiqqxOpB+QXFI/whj493CxWW
so7QAmzOCyJq8GDVPxzkwUac22YIkXdiOmb8i/HWq+kLY/HjQE259Gx6KwARAQAB
tClaZXJvVGllciBTZWN1cml0eSA8c2VjdXJpdHlAemVyb3RpZXIuY29tPokCTAQT
AQoANhYhBH1HQGb+4jzl6mnFqf09m6uqADkABQJkBjlSAhsDBAsJCAcEFQoJCAUW
AgMBAAIeAQIXgAAKCRD9PZurqgA5ACqPD/sFt6SG6Tu0HwTY2ofJtYsa2GBLL0pf
dYlX4cWSs1PVB5+m5Oj18y+GB2umA9GnsVtmvaSfp3XEngt2zNWX27uUsVfL35b2
/5TVVe8RjzOedqMN+lQWMvO+f/C1zmWYXjjpC+iGjgMMaRRrofkkn+7uL4N9y6gY
rcXtpACT1rYFC+i1AKnZfUO8Vr5ji7odq0f7bDkN/N38rB0kRRwEmO8wqdpQK6gK
nxf9vgJl5ggimDk5Xtz1sfd3y28bf5N4hdOCkXUbd10nUFY3wDNTM4VxozxTGJeG
imdcc19Wuw/1fGUZ5SIjgPanCdPLGYwSTr+M6Fuern9uTtlC1GOby3BUtmVGP6EU
1pSAJSRpmoBPHKKOYtSMwV8PCboXru9P1ab8y8STKM3SKyghUJrl17gdc0LaksZa
E54pJudGPIQMFRqZjMdV6jgMuaLTozjZ4mW8EThf4mkX4xDkO8l7cOn0225ZYJZC
lZKpdnwzk9owkJA80u4KBNJxTtB4ZAPzjBsD5hFzCZQTLNQp/psU3EjZsau28eXT
E/C1QjEQHgy4ohkgQlCm1H1+clKssCWcdmsVGXuS1u8gh4K6X9b0Z6LeCGRaQvH2
+DB8oTAdqp9nUZv9rP4pbo+sR4fF67CFLriVuxjedAiFkbM4uHMFcL4tc/X9+DRo
YN5X7oEkZvO507kCDQRkBjlSARAAz58UMF7K1qKyQjzKTcutaYZ5SaIGky9lCLZn
/2vjpFCoBogkxS/6IKQcwZk8b4S9QstaaQZDFEkxqNeKC0GiFTAMAb6SmYcK495h
EZnHl0NA5Nc2dBlZk5E/ENzTCz2bXaxCcVESc2z+xCzu07brbhGrqvliKiwOUzt9
JzqEsar6I95OutBcZvkFCs44/Uf9bS1qf1w4klE8w3vdMtGH23umrET4tFZ+sh6o
ZFtQx0u2eKjsRdn/RMtsxLNaJlcE1DdIAqBpQrcmuwMC8v5wUGfCGZjhClzmyQlq
akUkayir7UtbHbFT/mgO+YI77YGXWk5QrwPscqqT2l8KB/YMujNDmaWa/0KV1lIY
zr5s4dzVeiwqFLR9ANFIhzFwzf3JLi6XSx123Qix0TxZoYPZCHl7yoi9qi6qybz5
0Od2LSz3jbApeKYymZ+zjE+YV5y9DI6Wzy1j2M1FogNvTO9fMk+6dLt4HhTdSNvH
cKya462YCcy+tnZTkhmh+FTebbJlV6D4wG7skE5KCdBhjm53xLwp6XW9L6n2CrkL
W1IDBcCz0oPd1sMkXbO3wnxdXprV2XurCfsg/R2nszSNzvdJ8/xj3cr9hpoJ714R
qqyoEDRZ1Ss9kGL166o5MpN5qb/EewdkqGgWP7YFXbhsdHQiW7Z7dAqzjoaybD4O
nakkwyUAEQEAAYkCNgQYAQoAIBYhBH1HQGb+4jzl6mnFqf09m6uqADkABQJkBjlS
AhsMAAoJEP09m6uqADkAax0P/Rh8EZYRqW6dPYTl1YQusAK10rAcRNq3ekjofXGk
oXK1S7HWGoFgl5++5nfSfNgFJ5VLcgIM56wtIf49zFjWe5oC6fw8k+ghh4d2chMP
hdDILx6e0c30Iq1+EvovGR9hWa0wJ4cKTdzlwhY9ZC09q0ia+bl2mwpie1JQDR0c
zXCjt+PldLeeK9z1/XT0Q7KowYC+U18oR+KFm+EaRV4QT85JVequnIeGkmaHJrHB
lH4T5A5ib7y8edon1c0Zx3GsaxJUojkEJ0SX7ffVDu6ztUZfkHfCVpMW4VzUeGA/
m+CtFO9ciLRGZEkRa+zhIGoBvwEXU0GiwiF4nZ0F2C8UioeW0YIEV9zl3nXJctYE
ZKc2whSENQRTGgaYHVoVZhznt71LKWgFLshwBo81UCXVkzwAjMW1ActDnmPw5M7q
xR5Qp5G49Z1GmfSozazha0HVFPKNV5i3RlTzs4yLUnZyH0yC9IvtOefMHcLjG96L
N5miEV97gvJJjrn8rhRvpUwAWgmT/9IuYjBNQTtNN40arto5HxezR76WCjdKYxdL
p3dM1iiBDShHNm7LdyZlLFhTOMU0tNBxJJ7B09ar5gakeZjD+2aB1ODX9VuFtozL
onBjI2gIkry0UIkuznHfFw05lZAZAiqHEVgVi/WTk4C/bklDZNgE0lx+IWzEz2iS
L455
=lheL
-----END PGP PUBLIC KEY BLOCK-----
```

461
attic/Binder.hpp Normal file
View file

@ -0,0 +1,461 @@
/*
* 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: 2023-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_BINDER_HPP
#define ZT_BINDER_HPP
#include "../node/Constants.hpp"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __WINDOWS__
#include <WinSock2.h>
#include <Windows.h>
#include <ShlObj.h>
#include <netioapi.h>
#include <iphlpapi.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <ifaddrs.h>
#ifdef __LINUX__
#include <sys/ioctl.h>
#include <net/if.h>
#endif
#endif
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <map>
#include <set>
#include <atomic>
#include "../node/InetAddress.hpp"
#include "../node/Mutex.hpp"
#include "../node/Utils.hpp"
#include "Phy.hpp"
#include "OSUtils.hpp"
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__))
#define ZT_UDP_DESIRED_BUF_SIZE 1048576
#else
#define ZT_UDP_DESIRED_BUF_SIZE 131072
#endif
// Period between refreshes of bindings
#define ZT_BINDER_REFRESH_PERIOD 30000
// Max number of bindings
#define ZT_BINDER_MAX_BINDINGS 256
namespace ZeroTier {
/**
* Enumerates local devices and binds to all potential ZeroTier path endpoints
*
* This replaces binding to wildcard (0.0.0.0 and ::0) with explicit binding
* as part of the path to default gateway support. Under the hood it uses
* different queries on different OSes to enumerate devices, and also exposes
* device enumeration and endpoint IP data for use elsewhere.
*
* On OSes that do not support local port enumeration or where this is not
* meaningful, this degrades to binding to wildcard.
*/
class Binder
{
private:
struct _Binding
{
_Binding() : udpSock((PhySocket *)0),tcpListenSock((PhySocket *)0) {}
PhySocket *udpSock;
PhySocket *tcpListenSock;
InetAddress address;
};
public:
Binder() : _bindingCount(0) {}
/**
* Close all bound ports, should be called on shutdown
*
* @param phy Physical interface
*/
template<typename PHY_HANDLER_TYPE>
void closeAll(Phy<PHY_HANDLER_TYPE> &phy)
{
Mutex::Lock _l(_lock);
for(unsigned int b=0,c=_bindingCount;b<c;++b) {
phy.close(_bindings[b].udpSock,false);
phy.close(_bindings[b].tcpListenSock,false);
}
_bindingCount = 0;
}
/**
* Scan local devices and addresses and rebind TCP and UDP
*
* This should be called after wake from sleep, on detected network device
* changes, on startup, or periodically (e.g. every 30-60s).
*
* @param phy Physical interface
* @param ports Ports to bind on all interfaces
* @param portCount Number of ports
* @param explicitBind If present, override interface IP detection and bind to these (if possible)
* @param ifChecker Interface checker function to see if an interface should be used
* @tparam PHY_HANDLER_TYPE Type for Phy<> template
* @tparam INTERFACE_CHECKER Type for class containing shouldBindInterface() method
*/
template<typename PHY_HANDLER_TYPE,typename INTERFACE_CHECKER>
void refresh(Phy<PHY_HANDLER_TYPE> &phy,unsigned int *ports,unsigned int portCount,const std::vector<InetAddress> explicitBind,INTERFACE_CHECKER &ifChecker)
{
std::map<InetAddress,std::string> localIfAddrs;
PhySocket *udps,*tcps;
Mutex::Lock _l(_lock);
bool interfacesEnumerated = true;
if (explicitBind.empty()) {
#ifdef __WINDOWS__
char aabuf[32768];
ULONG aalen = sizeof(aabuf);
if (GetAdaptersAddresses(AF_UNSPEC,GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER,(void *)0,reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf),&aalen) == NO_ERROR) {
PIP_ADAPTER_ADDRESSES a = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf);
while (a) {
PIP_ADAPTER_UNICAST_ADDRESS ua = a->FirstUnicastAddress;
while (ua) {
InetAddress ip(ua->Address.lpSockaddr);
if (ifChecker.shouldBindInterface("",ip)) {
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,std::string()));
}
break;
}
}
ua = ua->Next;
}
a = a->Next;
}
}
else {
interfacesEnumerated = false;
}
#else // not __WINDOWS__
/* On Linux we use an alternative method if available since getifaddrs()
* gets very slow when there are lots of network namespaces. This won't
* work unless /proc/PID/net/if_inet6 exists and it may not on some
* embedded systems, so revert to getifaddrs() there. */
#ifdef __LINUX__
char fn[256],tmp[256];
std::set<std::string> ifnames;
const unsigned long pid = (unsigned long)getpid();
// Get all device names
OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid);
FILE *procf = fopen(fn,"r");
if (procf) {
while (fgets(tmp,sizeof(tmp),procf)) {
tmp[255] = 0;
char *saveptr = (char *)0;
for(char *f=Utils::stok(tmp," \t\r\n:|",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n:|",&saveptr)) {
if ((strcmp(f,"Inter-") != 0)&&(strcmp(f,"face") != 0)&&(f[0] != 0))
ifnames.insert(f);
break; // we only want the first field
}
}
fclose(procf);
}
else {
interfacesEnumerated = false;
}
// Get IPv6 addresses (and any device names we don't already know)
OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid);
procf = fopen(fn,"r");
if (procf) {
while (fgets(tmp,sizeof(tmp),procf)) {
tmp[255] = 0;
char *saveptr = (char *)0;
unsigned char ipbits[16];
memset(ipbits,0,sizeof(ipbits));
char *devname = (char *)0;
int n = 0;
for(char *f=Utils::stok(tmp," \t\r\n",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n",&saveptr)) {
switch(n++) {
case 0: // IP in hex
Utils::unhex(f,32,ipbits,16);
break;
case 5: // device name
devname = f;
break;
}
}
if (devname) {
ifnames.insert(devname);
InetAddress ip(ipbits,16,0);
if (ifChecker.shouldBindInterface(devname,ip)) {
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,std::string(devname)));
}
break;
}
}
}
}
fclose(procf);
}
// Get IPv4 addresses for each device
if (ifnames.size() > 0) {
const int controlfd = (int)socket(AF_INET,SOCK_DGRAM,0);
struct ifconf configuration;
configuration.ifc_len = 0;
configuration.ifc_buf = nullptr;
if (controlfd < 0) goto ip4_address_error;
if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error;
configuration.ifc_buf = (char*)malloc(configuration.ifc_len);
if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error;
for (int i=0; i < (int)(configuration.ifc_len / sizeof(ifreq)); i ++) {
struct ifreq& request = configuration.ifc_req[i];
struct sockaddr* addr = &request.ifr_ifru.ifru_addr;
if (addr->sa_family != AF_INET) continue;
std::string ifname = request.ifr_ifrn.ifrn_name;
// name can either be just interface name or interface name followed by ':' and arbitrary label
if (ifname.find(':') != std::string::npos)
ifname = ifname.substr(0, ifname.find(':'));
InetAddress ip(&(((struct sockaddr_in *)addr)->sin_addr),4,0);
if (ifChecker.shouldBindInterface(ifname.c_str(), ip)) {
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,ifname));
}
break;
}
}
}
ip4_address_error:
free(configuration.ifc_buf);
if (controlfd > 0) close(controlfd);
}
const bool gotViaProc = (localIfAddrs.size() > 0);
#else
const bool gotViaProc = false;
#endif
#if !defined(ZT_SDK) || !defined(__ANDROID__) // getifaddrs() freeifaddrs() not available on Android
if (!gotViaProc) {
struct ifaddrs *ifatbl = (struct ifaddrs *)0;
struct ifaddrs *ifa;
if ((getifaddrs(&ifatbl) == 0)&&(ifatbl)) {
ifa = ifatbl;
while (ifa) {
if ((ifa->ifa_name)&&(ifa->ifa_addr)) {
InetAddress ip = *(ifa->ifa_addr);
if (ifChecker.shouldBindInterface(ifa->ifa_name,ip)) {
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,std::string(ifa->ifa_name)));
}
break;
}
}
}
ifa = ifa->ifa_next;
}
freeifaddrs(ifatbl);
}
else {
interfacesEnumerated = false;
}
}
#endif
#endif
} else {
for(std::vector<InetAddress>::const_iterator i(explicitBind.begin());i!=explicitBind.end();++i)
localIfAddrs.insert(std::pair<InetAddress,std::string>(*i,std::string()));
}
// Default to binding to wildcard if we can't enumerate addresses
if (!interfacesEnumerated && localIfAddrs.empty()) {
for(int x=0;x<(int)portCount;++x) {
localIfAddrs.insert(std::pair<InetAddress,std::string>(InetAddress((uint32_t)0,ports[x]),std::string()));
localIfAddrs.insert(std::pair<InetAddress,std::string>(InetAddress((const void *)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",16,ports[x]),std::string()));
}
}
const unsigned int oldBindingCount = _bindingCount;
_bindingCount = 0;
// Save bindings that are still valid, close those that are not
for(unsigned int b=0;b<oldBindingCount;++b) {
if (localIfAddrs.find(_bindings[b].address) != localIfAddrs.end()) {
if (_bindingCount != b)
_bindings[(unsigned int)_bindingCount] = _bindings[b];
++_bindingCount;
} else {
PhySocket *const udps = _bindings[b].udpSock;
PhySocket *const tcps = _bindings[b].tcpListenSock;
_bindings[b].udpSock = (PhySocket *)0;
_bindings[b].tcpListenSock = (PhySocket *)0;
phy.close(udps,false);
phy.close(tcps,false);
}
}
// Create new bindings for those not already bound
for(std::map<InetAddress,std::string>::const_iterator ii(localIfAddrs.begin());ii!=localIfAddrs.end();++ii) {
unsigned int bi = 0;
while (bi != _bindingCount) {
if (_bindings[bi].address == ii->first)
break;
++bi;
}
if (bi == _bindingCount) {
udps = phy.udpBind(reinterpret_cast<const struct sockaddr *>(&(ii->first)),(void *)0,ZT_UDP_DESIRED_BUF_SIZE);
tcps = phy.tcpListen(reinterpret_cast<const struct sockaddr *>(&(ii->first)),(void *)0);
if ((udps)&&(tcps)) {
#ifdef __LINUX__
// Bind Linux sockets to their device so routes that we manage do not override physical routes (wish all platforms had this!)
if (ii->second.length() > 0) {
char tmp[256];
Utils::scopy(tmp,sizeof(tmp),ii->second.c_str());
int fd = (int)Phy<PHY_HANDLER_TYPE>::getDescriptor(udps);
if (fd >= 0)
setsockopt(fd,SOL_SOCKET,SO_BINDTODEVICE,tmp,strlen(tmp));
fd = (int)Phy<PHY_HANDLER_TYPE>::getDescriptor(tcps);
if (fd >= 0)
setsockopt(fd,SOL_SOCKET,SO_BINDTODEVICE,tmp,strlen(tmp));
}
#endif // __LINUX__
if (_bindingCount < ZT_BINDER_MAX_BINDINGS) {
_bindings[_bindingCount].udpSock = udps;
_bindings[_bindingCount].tcpListenSock = tcps;
_bindings[_bindingCount].address = ii->first;
phy.setIfName(udps,(char*)ii->second.c_str(),(int)ii->second.length());
++_bindingCount;
}
} else {
phy.close(udps,false);
phy.close(tcps,false);
}
}
}
}
/**
* @return All currently bound local interface addresses
*/
inline std::vector<InetAddress> allBoundLocalInterfaceAddresses() const
{
std::vector<InetAddress> aa;
Mutex::Lock _l(_lock);
for(unsigned int b=0,c=_bindingCount;b<c;++b)
aa.push_back(_bindings[b].address);
return aa;
}
/**
* Send from all bound UDP sockets
*/
template<typename PHY_HANDLER_TYPE>
inline bool udpSendAll(Phy<PHY_HANDLER_TYPE> &phy,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl)
{
bool r = false;
Mutex::Lock _l(_lock);
for(unsigned int b=0,c=_bindingCount;b<c;++b) {
if (ttl) phy.setIp4UdpTtl(_bindings[b].udpSock,ttl);
if (phy.udpSend(_bindings[b].udpSock,(const struct sockaddr *)addr,data,len)) r = true;
if (ttl) phy.setIp4UdpTtl(_bindings[b].udpSock,255);
}
return r;
}
/**
* @param addr Address to check
* @return True if this is a bound local interface address
*/
inline bool isBoundLocalInterfaceAddress(const InetAddress &addr) const
{
Mutex::Lock _l(_lock);
for(unsigned int b=0;b<_bindingCount;++b) {
if (_bindings[b].address == addr)
return true;
}
return false;
}
/**
* Quickly check that a UDP socket is valid
*
* @param udpSock UDP socket to check
* @return True if socket is currently bound/allocated
*/
inline bool isUdpSocketValid(PhySocket *const udpSock)
{
for(unsigned int b=0,c=_bindingCount;b<c;++b) {
if (_bindings[b].udpSock == udpSock)
return (b < _bindingCount); // double check atomic which may have changed
}
return false;
}
private:
_Binding _bindings[ZT_BINDER_MAX_BINDINGS];
std::atomic<unsigned int> _bindingCount;
Mutex _lock;
};
} // namespace ZeroTier
#endif

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -19,9 +19,9 @@
#include <stdexcept>
#if defined(_WIN32) || defined(_WIN64)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#else
#include <unistd.h>
#include <sys/time.h>

View file

@ -1,10 +1,10 @@
/*
* Copyright (c)2013-2020 ZeroTier, Inc.
* 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
* Change Date: 2023-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.
@ -23,9 +23,9 @@
#if defined(_WIN32) || defined(_WIN64)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#define ZT_PHY_SOCKFD_TYPE SOCKET
#define ZT_PHY_SOCKFD_NULL (INVALID_SOCKET)
@ -48,10 +48,9 @@
#include <sys/un.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include "../node/Metrics.hpp"
#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux)
#ifndef IPV6_DONTFRAG
#define IPV6_DONTFRAG 62
@ -142,12 +141,12 @@ private:
};
struct PhySocketImpl {
PhySocketImpl() {}
PhySocketImpl() { memset(ifname, 0, sizeof(ifname)); }
PhySocketType type;
ZT_PHY_SOCKFD_TYPE sock;
void *uptr; // user-settable pointer
uint16_t localPort;
ZT_PHY_SOCKADDR_STORAGE_TYPE saddr; // remote for TCP_OUT and TCP_IN, local for TCP_LISTEN, RAW, and UDP
char ifname[16];
};
std::list<PhySocketImpl> _socks;
@ -231,30 +230,76 @@ public:
* @param s Socket object
* @return Underlying OS-type (usually int or long) file descriptor associated with object
*/
static inline ZT_PHY_SOCKFD_TYPE getDescriptor(PhySocket* s) throw()
{
return reinterpret_cast<PhySocketImpl*>(s)->sock;
}
static inline ZT_PHY_SOCKFD_TYPE getDescriptor(PhySocket *s) throw() { return reinterpret_cast<PhySocketImpl *>(s)->sock; }
/**
* @param s Socket object
* @return Pointer to user object
*/
static inline void** getuptr(PhySocket* s) throw()
static inline void** getuptr(PhySocket *s) throw() { return &(reinterpret_cast<PhySocketImpl *>(s)->uptr); }
/**
* @param s Socket object
* @param nameBuf Buffer to store name of interface which this Socket object is bound to
* @param buflen Length of buffer to copy name into
*/
static inline void getIfName(PhySocket *s, char *nameBuf, int buflen)
{
return &(reinterpret_cast<PhySocketImpl*>(s)->uptr);
if (s) {
memcpy(nameBuf, reinterpret_cast<PhySocketImpl *>(s)->ifname, buflen);
}
}
/**
* Return the local port corresponding to this PhySocket
* @param s Socket object
* @param ifname Buffer containing name of interface that this Socket object is bound to
* @param len Length of name of interface
*/
static inline void setIfName(PhySocket *s, char *ifname, int len)
{
if (s) {
memcpy(&(reinterpret_cast<PhySocketImpl *>(s)->ifname), ifname, len);
}
}
/**
* Whether or not the socket object is in a closed state
*
* @param s Socket object
*
* @return Local port corresponding to this PhySocket
* @return true if socket is closed, false if otherwise
*/
static inline uint16_t getLocalPort(PhySocket* s) throw()
inline bool isClosed(PhySocket *s)
{
return reinterpret_cast<PhySocketImpl*>(s)->localPort;
PhySocketImpl *sws = (reinterpret_cast<PhySocketImpl *>(s));
return sws->type == ZT_PHY_SOCKET_CLOSED;
}
/**
* Get state of socket object
*
* @param s Socket object
* @return State of socket
*/
inline int getState(PhySocket *s)
{
PhySocketImpl *sws = (reinterpret_cast<PhySocketImpl *>(s));
return sws->type;
}
/**
* In the event that this socket is erased, we need a way to convey to the multipath logic
* that this path is no longer valid.
*
* @param s Socket object
* @return Whether the state of this socket is within an acceptable range of values
*/
inline bool isValidState(PhySocket *s)
{
if (s) {
PhySocketImpl *sws = (reinterpret_cast<PhySocketImpl *>(s));
return sws->type >= ZT_PHY_SOCKET_CLOSED && sws->type <= ZT_PHY_SOCKET_UNIX_LISTEN;
}
return false;
}
/**
@ -266,27 +311,21 @@ public:
inline void whack()
{
#if defined(_WIN32) || defined(_WIN64)
::send(_whackSendSocket, (const char*)this, 1, 0);
::send(_whackSendSocket,(const char *)this,1,0);
#else
(void)(::write(_whackSendSocket, (PhySocket*)this, 1));
(void)(::write(_whackSendSocket,(PhySocket *)this,1));
#endif
}
/**
* @return Number of open sockets
*/
inline unsigned long count() const throw()
{
return _socks.size();
}
inline unsigned long count() const throw() { return _socks.size(); }
/**
* @return Maximum number of sockets allowed
*/
inline unsigned long maxCount() const throw()
{
return ZT_PHY_MAX_SOCKETS;
}
inline unsigned long maxCount() const throw() { return ZT_PHY_MAX_SOCKETS; }
/**
* Wrap a raw file descriptor in a PhySocket structure
@ -353,14 +392,14 @@ public:
int tmpbs = bs;
if (setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char *)&tmpbs,sizeof(tmpbs)) == 0)
break;
bs -= 4096;
bs -= 16384;
}
bs = bufferSize;
while (bs >= 65536) {
int tmpbs = bs;
if (setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char *)&tmpbs,sizeof(tmpbs)) == 0)
break;
bs -= 4096;
bs -= 16384;
}
}
@ -430,11 +469,6 @@ public:
sws.type = ZT_PHY_SOCKET_UDP;
sws.sock = s;
sws.uptr = uptr;
#ifdef __UNIX_LIKE__
struct sockaddr_in *sin = (struct sockaddr_in *)localAddress;
sws.localPort = htons(sin->sin_port);
#endif
memset(&(sws.saddr),0,sizeof(struct sockaddr_storage));
memcpy(&(sws.saddr),localAddress,(localAddress->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
@ -471,33 +505,11 @@ public:
inline bool udpSend(PhySocket *sock,const struct sockaddr *remoteAddress,const void *data,unsigned long len)
{
PhySocketImpl &sws = *(reinterpret_cast<PhySocketImpl *>(sock));
bool sent = false;
#if defined(_WIN32) || defined(_WIN64)
sent = ((long)::sendto(
sws.sock,
reinterpret_cast<const char *>(data),
len,
0,
remoteAddress,
(remoteAddress->sa_family == AF_INET6) ?
sizeof(struct sockaddr_in6) :
sizeof(struct sockaddr_in)) == (long)len);
return ((long)::sendto(sws.sock,reinterpret_cast<const char *>(data),len,0,remoteAddress,(remoteAddress->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) == (long)len);
#else
sent = ((long)::sendto(
sws.sock,
data,
len,
0,
remoteAddress,
(remoteAddress->sa_family == AF_INET6) ?
sizeof(struct sockaddr_in6) :
sizeof(struct sockaddr_in)) == (long)len);
return ((long)::sendto(sws.sock,data,len,0,remoteAddress,(remoteAddress->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) == (long)len);
#endif
if (sent) {
Metrics::udp_send += len;
}
return sent;
}
#ifdef __UNIX_LIKE__
@ -1006,61 +1018,18 @@ public:
break;
case ZT_PHY_SOCKET_UDP:
if (FD_ISSET(s->sock, &rfds)) {
#if (defined(__linux__) || defined(linux) || defined(__linux)) && defined(MSG_WAITFORONE)
#define RECVMMSG_WINDOW_SIZE 128
#define RECVMMSG_BUF_SIZE 1500
iovec iovs[RECVMMSG_WINDOW_SIZE];
uint8_t bufs[RECVMMSG_WINDOW_SIZE][RECVMMSG_BUF_SIZE];
sockaddr_storage addrs[RECVMMSG_WINDOW_SIZE];
memset(addrs, 0, sizeof(addrs));
mmsghdr mm[RECVMMSG_WINDOW_SIZE];
memset(mm, 0, sizeof(mm));
for (int i = 0; i < RECVMMSG_WINDOW_SIZE; ++i) {
iovs[i].iov_base = (void*)bufs[i];
iovs[i].iov_len = RECVMMSG_BUF_SIZE;
mm[i].msg_hdr.msg_name = (void*)&(addrs[i]);
mm[i].msg_hdr.msg_iov = &(iovs[i]);
mm[i].msg_hdr.msg_iovlen = 1;
}
for (int k = 0; k < 1024; ++k) {
for (int i = 0; i < RECVMMSG_WINDOW_SIZE; ++i) {
mm[i].msg_hdr.msg_namelen = sizeof(sockaddr_storage);
mm[i].msg_len = 0;
}
int received_count = recvmmsg(s->sock, mm, RECVMMSG_WINDOW_SIZE, MSG_WAITFORONE, nullptr);
if (received_count > 0) {
for (int i = 0; i < received_count; ++i) {
long n = (long)mm[i].msg_len;
if (n > 0) {
try {
_handler->phyOnDatagram((PhySocket*)&(*s), &(s->uptr), (const struct sockaddr*)&(s->saddr), (const struct sockaddr*)&(addrs[i]), bufs[i], (unsigned long)n);
}
catch (...) {
}
}
}
}
else {
break;
}
}
#else
for (int k = 0; k < 1024; ++k) {
memset(&ss, 0, sizeof(ss));
if (FD_ISSET(s->sock,&rfds)) {
for(int k=0;k<1024;++k) {
memset(&ss,0,sizeof(ss));
socklen_t slen = sizeof(ss);
long n = (long)::recvfrom(s->sock, buf, sizeof(buf), 0, (struct sockaddr*)&ss, &slen);
long n = (long)::recvfrom(s->sock,buf,sizeof(buf),0,(struct sockaddr *)&ss,&slen);
if (n > 0) {
try {
_handler->phyOnDatagram((PhySocket*)&(*s), &(s->uptr), (const struct sockaddr*)&(s->saddr), (const struct sockaddr*)&ss, (void*)buf, (unsigned long)n);
}
catch (...) {
}
}
else if (n < 0)
_handler->phyOnDatagram((PhySocket *)&(*s),&(s->uptr),(const struct sockaddr *)&(s->saddr),(const struct sockaddr *)&ss,(void *)buf,(unsigned long)n);
} catch ( ... ) {}
} else if (n < 0)
break;
}
#endif
}
break;

View file

@ -0,0 +1,14 @@
#define ENABLE_STRNATPMPERR
#define _BSD_SOURCE
#define _DEFAULT_SOURCE
#define _XOPEN_SOURCE 600
#ifdef __APPLE__
#ifndef _DARWIN_C_SOURCE
#define _DARWIN_C_SOURCE
#endif
#endif
#include "../ext/libnatpmp/getgateway.c"
#include "../ext/libnatpmp/wingettimeofday.c"
#include "../ext/libnatpmp/natpmp.c"

View file

@ -0,0 +1,41 @@
#define MINIUPNP_STATICLIB
#define MINIUPNPC_SET_SOCKET_TIMEOUT
#define MINIUPNPC_GET_SRC_ADDR
#define _BSD_SOURCE
#define _DEFAULT_SOURCE
#define _XOPEN_SOURCE 600
#define MINIUPNPC_VERSION_STRING "2.0"
#define UPNP_VERSION_STRING "UPnP/1.1"
#ifdef __LINUX__
#define OS_STRING "Linux"
#endif
#ifdef __APPLE__
#define OS_STRING "Darwin"
#endif
#ifdef __WINDOWS__
#define OS_STRING "Windows"
#endif
#ifndef OS_STRING
#define OS_STRING "ZeroTier"
#endif
#ifdef __APPLE__
#ifndef _DARWIN_C_SOURCE
#define _DARWIN_C_SOURCE
#endif
#endif
#include "../ext/miniupnpc/connecthostport.c"
#include "../ext/miniupnpc/igd_desc_parse.c"
#include "../ext/miniupnpc/minisoap.c"
#include "../ext/miniupnpc/miniupnpc.c"
#include "../ext/miniupnpc/miniwget.c"
#include "../ext/miniupnpc/minixml.c"
#include "../ext/miniupnpc/portlistingparse.c"
#include "../ext/miniupnpc/receivedata.c"
#include "../ext/miniupnpc/upnpcommands.c"
#include "../ext/miniupnpc/upnpdev.c"
#include "../ext/miniupnpc/upnperrors.c"
#include "../ext/miniupnpc/upnpreplyparse.c"
#include "../ext/miniupnpc/minissdpc.c"

View file

@ -4,15 +4,13 @@
* 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
* Change Date: 2023-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.
*/
/****/
#ifdef ZT_USE_MINIUPNPC
// Uncomment to dump debug messages
//#define ZT_PORTMAPPER_TRACE 1
@ -47,9 +45,14 @@
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnpcommands.h>
#else
#ifdef __ANDROID__
#include "miniupnpc.h"
#include "upnpcommands.h"
#else
#include "../ext/miniupnpc/miniupnpc.h"
#include "../ext/miniupnpc/upnpcommands.h"
#endif
#endif
#ifdef ZT_USE_SYSTEM_NATPMP
#include <natpmp.h>
@ -79,7 +82,6 @@ public:
throw()
{
int mode = 0; // 0 == NAT-PMP, 1 == UPnP
int retrytime = 500;
#ifdef ZT_PORTMAPPER_TRACE
fprintf(stderr,"PortMapper: started for UDP port %d" ZT_EOL_S,localPort);
@ -87,26 +89,6 @@ public:
while (run) {
{
// use initnatpmp to check if we can bind a port at all
natpmp_t _natpmp;
int result = initnatpmp(&_natpmp,0,0);
if (result == NATPMP_ERR_CANNOTGETGATEWAY || result == NATPMP_ERR_SOCKETERROR) {
closenatpmp(&_natpmp);
#ifdef ZT_PORTMAPPER_TRACE
PM_TRACE("PortMapper: init failed %d. You might not have an internet connection yet. Trying again in %d" ZT_EOL_S, result, retrytime);
#endif
Thread::sleep(retrytime);
retrytime = retrytime * 2;
if (retrytime > ZT_PORTMAPPER_REFRESH_DELAY / 10) {
retrytime = ZT_PORTMAPPER_REFRESH_DELAY / 10;
}
continue;
} else {
closenatpmp(&_natpmp);
retrytime = 500;
}
}
// ---------------------------------------------------------------------
// NAT-PMP mode (preferred)
// ---------------------------------------------------------------------
@ -193,7 +175,6 @@ public:
#ifdef ZT_PORTMAPPER_TRACE
PM_TRACE("PortMapper: NAT-PMP: request failed, switching to UPnP mode" ZT_EOL_S);
#endif
continue;
}
}
// ---------------------------------------------------------------------
@ -229,8 +210,7 @@ public:
memset(&data,0,sizeof(data));
OSUtils::ztsnprintf(inport,sizeof(inport),"%d",localPort);
int foundValidIGD = 0;
if ((foundValidIGD = UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) {
if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) {
#ifdef ZT_PORTMAPPER_TRACE
PM_TRACE("PortMapper: UPnP: my LAN IP address: %s" ZT_EOL_S,lanaddr);
#endif
@ -305,11 +285,9 @@ public:
PM_TRACE("PortMapper: UPnP: UPNP_GetValidIGD failed, returning to NAT-PMP mode" ZT_EOL_S);
#endif
}
freeUPNPDevlist(devlist);
if(foundValidIGD) {
FreeUPNPUrls(&urls);
}
} else {
mode = 0;
#ifdef ZT_PORTMAPPER_TRACE
@ -354,5 +332,3 @@ std::vector<InetAddress> PortMapper::get() const
}
} // namespace ZeroTier
#endif // ZT_USE_MINIUPNPC

View file

@ -4,15 +4,13 @@
* 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
* Change Date: 2023-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.
*/
/****/
#ifdef ZT_USE_MINIUPNPC
#ifndef ZT_PORTMAPPER_HPP
#define ZT_PORTMAPPER_HPP
@ -26,7 +24,7 @@
/**
* How frequently should we refresh our UPNP/NAT-PnP/whatever state?
*/
#define ZT_PORTMAPPER_REFRESH_DELAY 300000
#define ZT_PORTMAPPER_REFRESH_DELAY 120000
namespace ZeroTier {
@ -62,5 +60,3 @@ private:
} // namespace ZeroTier
#endif
#endif // ZT_USE_MINIUPNPC

182
attic/Root.hpp Normal file
View file

@ -0,0 +1,182 @@
/*
* 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: 2023-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_ROOT_HPP
#define ZT_ROOT_HPP
#include "Constants.hpp"
#include "Str.hpp"
#include "ECC384.hpp"
#include "Locator.hpp"
#include "InetAddress.hpp"
#include "Utils.hpp"
#include "Identity.hpp"
#include "Mutex.hpp"
namespace ZeroTier {
/**
* A root entry pointing to a node capable of global identity lookup and indirect transit
*
* Root entries point to DNS records that contain TXT entries that decode to Locator objects
* pointing to actual root nodes. A default root identity and static addresses can also be
* provided as fallback if DNS is not available.
*
* Note that root identities can change if DNS returns a different result, but that DNS entries
* are authenticated using their own signature scheme. This allows a root DNS name to serve
* up different roots based on factors like location or relative load of different roots.
*
* It's also possible to create a root with no DNS and no DNS validator public key. This root
* will be a static entry pointing to a single root identity and set of physical addresses.
*/
class Root
{
public:
ZT_ALWAYS_INLINE Root() : _dnsPublicKeySize(0) {}
/**
* Create a new root entry
*
* @param dn DNS name
* @param dnspk DNS public key for record validation
* @param dnspksize Size of DNS public key (currently always the size of a NIST P-384 point compressed public key)
* @param dflId Default identity if DNS is not available
* @param dflAddrs Default IP addresses if DNS is not available
*/
template<typename S>
ZT_ALWAYS_INLINE Root(S dn,const uint8_t *const dnspk,const unsigned int dnspksize,const Identity &dflId,const std::vector<InetAddress> &dflAddrs) :
_defaultIdentity(dflId),
_defaultAddresses(dflAddrs),
_dnsName(dn),
_dnsPublicKeySize(dnspksize)
{
if (dnspksize != 0) {
if (dnspksize > sizeof(_dnsPublicKey))
throw ZT_EXCEPTION_INVALID_ARGUMENT;
memcpy(_dnsPublicKey,dnspk,dnspksize);
}
}
/**
* @return Current identity (either default or latest locator)
*/
ZT_ALWAYS_INLINE const Identity id() const
{
if (_lastFetchedLocator.id())
return _lastFetchedLocator.id();
return _defaultIdentity;
}
/**
* @param id Identity to check
* @return True if identity equals this root's current identity
*/
ZT_ALWAYS_INLINE bool is(const Identity &id) const
{
return ((_lastFetchedLocator.id()) ? (id == _lastFetchedLocator.id()) : (id == _defaultIdentity));
}
/**
* @return Current ZeroTier address (either default or latest locator)
*/
ZT_ALWAYS_INLINE const Address address() const
{
if (_lastFetchedLocator.id())
return _lastFetchedLocator.id().address();
return _defaultIdentity.address();
}
/**
* @return DNS name for this root or empty string if static entry with no DNS
*/
ZT_ALWAYS_INLINE const Str dnsName() const { return _dnsName; }
/**
* @return Latest locator or NIL locator object if none
*/
ZT_ALWAYS_INLINE Locator locator() const { return _lastFetchedLocator; }
/**
* @return Timestamp of latest retrieved locator or 0 if none
*/
ZT_ALWAYS_INLINE int64_t locatorTimestamp() const { return _lastFetchedLocator.timestamp(); }
/**
* Update locator, returning true if new locator is valid and newer than existing
*/
ZT_ALWAYS_INLINE bool updateLocator(const Locator &loc)
{
if (!loc.verify())
return false;
if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
_lastFetchedLocator = loc;
return true;
}
return false;
}
/**
* Update this root's locator from a series of TXT records
*/
template<typename I>
ZT_ALWAYS_INLINE bool updateLocatorFromTxt(I start,I end)
{
try {
if (_dnsPublicKeySize != ZT_ECC384_PUBLIC_KEY_SIZE)
return false;
Locator loc;
if (!loc.decodeTxtRecords(start,end,_dnsPublicKey)) // also does verify()
return false;
if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
_lastFetchedLocator = loc;
return true;
}
return false;
} catch ( ... ) {}
return false;
}
/**
* Pick a random physical IP for this root with the given address family
*
* @param addressFamily AF_INET or AF_INET6
* @return Address or InetAddress::NIL if no addresses exist for the given family
*/
ZT_ALWAYS_INLINE const InetAddress &pickPhysical(const int addressFamily) const
{
std::vector<const InetAddress *> pickList;
const std::vector<InetAddress> *const av = (_lastFetchedLocator) ? &(_lastFetchedLocator.phy()) : &_defaultAddresses;
for(std::vector<InetAddress>::const_iterator i(av->begin());i!=av->end();++i) {
if (addressFamily == (int)i->ss_family) {
pickList.push_back(&(*i));
}
}
if (pickList.size() == 1)
return *pickList[0];
else if (pickList.size() > 1)
return *pickList[(unsigned long)Utils::random() % (unsigned long)pickList.size()];
return InetAddress::NIL;
}
private:
Identity _defaultIdentity;
std::vector<InetAddress> _defaultAddresses;
Str _dnsName;
Locator _lastFetchedLocator;
unsigned int _dnsPublicKeySize;
uint8_t _dnsPublicKey[ZT_ECC384_PUBLIC_KEY_SIZE];
};
} // namespace ZeroTier
#endif

30
attic/listaddrinfo.go Normal file
View file

@ -0,0 +1,30 @@
package main
import (
"fmt"
"net"
)
func main() {
ifs, err := net.Interfaces()
if err != nil {
fmt.Printf("Error: %s\n", err.Error())
return
}
for _, i := range ifs {
fmt.Printf("name: %s\n", i.Name)
fmt.Printf("hwaddr: %s\n", i.HardwareAddr.String())
fmt.Printf("index: %d\n", i.Index)
fmt.Printf("addrs:\n")
addrs, _ := i.Addrs()
for _, a := range addrs {
fmt.Printf(" %s\n", a.String())
}
fmt.Printf("multicast:\n")
mc, _ := i.MulticastAddrs()
for _, m := range mc {
fmt.Printf(" %s\n", m.String())
}
fmt.Printf("\n")
}
}

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View file

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>

View file

@ -1,42 +1,19 @@
# This requires GNU make, which is typically "gmake" on BSD systems
INCLUDES=-isystem ext -Iext/prometheus-cpp-lite-1.0/core/include -Iext/prometheus-cpp-lite-1.0/simpleapi/include
INCLUDES=
DEFS=
LIBS=
include objects.mk
ONE_OBJS+=osdep/BSDEthernetTap.o ext/http-parser/http_parser.o
ifeq ($(OSTYPE),FreeBSD)
# Auto-detect miniupnpc and nat-pmp as well and use ports libs if present,
# otherwise build into binary as done on Mac and Windows.
INCLUDES+=-I/usr/local/include
LIBS+=-L/usr/local/lib
ONE_OBJS+=osdep/PortMapper.o
override DEFS+=-DZT_USE_MINIUPNPC
MINIUPNPC_IS_NEW_ENOUGH=$(shell grep -sqr '.*define.*MINIUPNPC_VERSION.*"2..*"' /usr/local/include/miniupnpc/miniupnpc.h && echo 1)
ifeq ($(MINIUPNPC_IS_NEW_ENOUGH),1)
LIBS+=-lminiupnpc
override DEFS+=-DZT_USE_SYSTEM_MINIUPNPC
else
override DEFS+=-DMINIUPNP_STATICLIB -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"FreeBSD/$(shell uname -r)\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
ONE_OBJS+=ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o
endif
ifeq ($(wildcard /usr/local/include/natpmp.h),)
ONE_OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o
else
LIBS+=-lnatpmp
override DEFS+=-DZT_USE_SYSTEM_NATPMP
endif
endif
# Build with address sanitization library for advanced debugging (clang)
ifeq ($(ZT_SANITIZE),1)
SANFLAGS+=-fsanitize=address -DASAN_OPTIONS=symbolize=1
endif
# "make debug" is a shortcut for this
ifeq ($(ZT_DEBUG),1)
CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)
CFLAGS+=-Wall -Werror -g -pthread $(INCLUDES) $(DEFS)
LDFLAGS+=
STRIP=echo
ZT_TRACE=1
@ -88,7 +65,7 @@ ifeq ($(CC_MACH),armhf)
endif
ifeq ($(CC_MACH),armv6)
ZT_ARCHITECTURE=3
override DEFS+=-DZT_NO_TYPE_PUNNING -DZT_NO_UNALIGNED_ACCESS
override DEFS+=-DZT_NO_TYPE_PUNNING
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
endif
ifeq ($(CC_MACH),armv6zk)
@ -103,16 +80,16 @@ ifeq ($(CC_MACH),armv6kz)
endif
ifeq ($(CC_MACH),armv7)
ZT_ARCHITECTURE=3
override DEFS+=-DZT_NO_TYPE_PUNNING -DZT_AES_NO_ACCEL -DZT_NO_UNALIGNED_ACCESS
override DEFS+=-DZT_NO_TYPE_PUNNING
ZT_USE_ARM32_NEON_ASM_SALSA2012=1
endif
ifeq ($(CC_MACH),arm64)
ZT_ARCHITECTURE=4
override DEFS+=-DZT_NO_TYPE_PUNNING -march=armv8-a+crypto
override DEFS+=-DZT_NO_TYPE_PUNNING
endif
ifeq ($(CC_MACH),aarch64)
ZT_ARCHITECTURE=4
override DEFS+=-DZT_NO_TYPE_PUNNING -march=armv8-a+crypto
override DEFS+=-DZT_NO_TYPE_PUNNING
endif
ifeq ($(CC_MACH),mipsel)
ZT_ARCHITECTURE=5
@ -133,7 +110,7 @@ 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))
ERR=$(error FATAL: architecture could not be determined from $(CC) -dumpmachine: $CC_MACH)
.PHONY: err
err: ; $(ERR)
endif
@ -147,12 +124,11 @@ ifeq ($(ZT_USE_ARM32_NEON_ASM_SALSA2012),1)
override DEFS+=-DZT_USE_ARM32_NEON_ASM_SALSA2012
override CORE_OBJS+=ext/arm32-neon-salsa2012-asm/salsa2012.o
override ASFLAGS+=-meabi=5
override LDFLAGS+=-Wl,-z,notext
endif
override DEFS+=-DZT_BUILD_PLATFORM=$(ZT_BUILD_PLATFORM) -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\""
CXXFLAGS+=$(CFLAGS) -std=c++17 #-D_GLIBCXX_USE_C99 -D_GLIBCXX_USE_C99_MATH -D_GLIBCXX_USE_C99_MATH_TR1
CXXFLAGS+=$(CFLAGS) -std=c++11 #-D_GLIBCXX_USE_C99 -D_GLIBCXX_USE_C99_MATH -D_GLIBCXX_USE_C99_MATH_TR1
all: one

View file

@ -9,17 +9,16 @@ ifeq ($(origin CXX),default)
CXX:=$(shell if [ -e /opt/rh/devtoolset-8/root/usr/bin/g++ ]; then echo /opt/rh/devtoolset-8/root/usr/bin/g++; else echo $(CXX); fi)
endif
INCLUDES?=-Irustybits/target -isystem ext -Iext/prometheus-cpp-lite-1.0/core/include -Iext-prometheus-cpp-lite-1.0/3rdparty/http-client-lite/include -Iext/prometheus-cpp-lite-1.0/simpleapi/include
INCLUDES?=
DEFS?=
LDLIBS?=
DESTDIR?=
EXTRA_DEPS?=
include objects.mk
ONE_OBJS+=osdep/LinuxEthernetTap.o
ONE_OBJS+=osdep/LinuxNetLink.o
# for central controller buildsk
# for central controller builds
TIMESTAMP=$(shell date +"%Y%m%d%H%M")
# Auto-detect miniupnpc and nat-pmp as well and use system libs if present,
@ -32,7 +31,7 @@ ifeq ($(MINIUPNPC_IS_NEW_ENOUGH),1)
override DEFS+=-DZT_USE_SYSTEM_MINIUPNPC
LDLIBS+=-lminiupnpc
else
override DEFS+=-DMINIUPNP_STATICLIB -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DOS_STRING="\"Linux\"" -DMINIUPNPC_VERSION_STRING="\"2.0\"" -DUPNP_VERSION_STRING="\"UPnP/1.1\"" -DENABLE_STRNATPMPERR
override DEFS+=-DMINIUPNP_STATICLIB -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DOS_STRING=\"Linux\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
ONE_OBJS+=ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o
endif
ifeq ($(wildcard /usr/include/natpmp.h),)
@ -46,47 +45,51 @@ endif
# Trying to use dynamically linked libhttp-parser causes tons of compatibility problems.
ONE_OBJS+=ext/http-parser/http_parser.o
# Build with address sanitization library for advanced debugging (clang)
ifeq ($(ZT_SANITIZE),1)
DEFS+=-fsanitize=address -DASAN_OPTIONS=symbolize=1
endif
ifeq ($(ZT_DEBUG_TRACE),1)
DEFS+=-DZT_DEBUG_TRACE
endif
ifeq ($(ZT_TRACE),1)
DEFS+=-DZT_TRACE
endif
ifeq ($(ZT_RULES_ENGINE_DEBUGGING),1)
override DEFS+=-DZT_RULES_ENGINE_DEBUGGING
endif
ifeq ($(ZT_DEBUG_TRACE),1)
DEFS+=-DZT_DEBUG_TRACE
endif
# Build with address sanitization library for advanced debugging (clang)
ifeq ($(ZT_SANITIZE),1)
override DEFS+=-fsanitize=address -DASAN_OPTIONS=symbolize=1
SANFLAGS+=-fsanitize=address -DASAN_OPTIONS=symbolize=1
endif
ifeq ($(ZT_DEBUG),1)
override CFLAGS+=-Wall -Wno-deprecated -g -O -pthread $(INCLUDES) $(DEFS)
override CXXFLAGS+=-Wall -Wno-deprecated -g -O -std=c++17 -pthread $(INCLUDES) $(DEFS)
override CFLAGS+=-Wall -Wno-deprecated -g -pthread $(INCLUDES) $(DEFS)
override CXXFLAGS+=-Wall -Wno-deprecated -g -std=c++11 -pthread $(INCLUDES) $(DEFS)
ZT_TRACE=1
ZT_CARGO_FLAGS=
STRIP?=echo
# The following line enables optimization for the crypto code, since
# C25519 in particular is almost UNUSABLE in -O0 even on a 3ghz box!
node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CXXFLAGS=-Wall -O2 -g -pthread $(INCLUDES) $(DEFS)
else
CFLAGS?=-O3 -fstack-protector
CFLAGS?=-O3 -fstack-protector -fPIE
override CFLAGS+=-Wall -Wno-deprecated -pthread $(INCLUDES) -DNDEBUG $(DEFS)
CXXFLAGS?=-O3 -fstack-protector
override CXXFLAGS+=-Wall -Wno-deprecated -std=c++17 -pthread $(INCLUDES) -DNDEBUG $(DEFS)
LDFLAGS?=-pie -Wl,-z,relro,-z,now
ZT_CARGO_FLAGS=--release
CXXFLAGS?=-O3 -fstack-protector -fPIE
override CXXFLAGS+=-Wall -Wno-deprecated -std=c++11 -pthread $(INCLUDES) -DNDEBUG $(DEFS)
LDFLAGS=-pie -Wl,-z,relro,-z,now
STRIP?=strip
STRIP+=--strip-all
endif
ifeq ($(ZT_QNAP), 1)
override DEFS+=-D__QNAP__
ZT_EMBEDDED=1
endif
ifeq ($(ZT_UBIQUITI), 1)
override DEFS+=-D__UBIQUITI__
ZT_EMBEDDED=1
endif
ifeq ($(ZT_SYNOLOGY), 1)
override CFLAGS+=-fPIC
override CXXFLAGS+=-fPIC
override DEFS+=-D__SYNOLOGY__
ZT_EMBEDDED=1
endif
ifeq ($(ZT_DISABLE_COMPRESSION), 1)
@ -97,10 +100,6 @@ ifeq ($(ZT_TRACE),1)
override DEFS+=-DZT_TRACE
endif
ifeq ($(ZT_DEBUG),1)
override DEFS+=-DZT_DEBUG
endif
ifeq ($(ZT_USE_TEST_TAP),1)
override DEFS+=-DZT_USE_TEST_TAP
endif
@ -110,6 +109,12 @@ ifeq ($(ZT_VAULT_SUPPORT),1)
override LDLIBS+=-lcurl
endif
# Uncomment for gprof profile build
#CFLAGS=-Wall -g -pg -pthread $(INCLUDES) $(DEFS)
#CXXFLAGS=-Wall -g -pg -pthread $(INCLUDES) $(DEFS)
#LDFLAGS=
#STRIP=echo
# Determine system build architecture from compiler target
CC_MACH=$(shell $(CC) -dumpmachine | cut -d '-' -f 1)
ZT_ARCHITECTURE=999
@ -117,23 +122,11 @@ ifeq ($(CC_MACH),x86_64)
ZT_ARCHITECTURE=2
ZT_USE_X64_ASM_SALSA=1
ZT_USE_X64_ASM_ED25519=1
override CFLAGS+=-msse -msse2
override CXXFLAGS+=-msse -msse2
ZT_SSO_SUPPORTED=1
ifeq ($(ZT_CONTROLLER),1)
EXT_ARCH=amd64
endif
endif
ifeq ($(CC_MACH),amd64)
ZT_ARCHITECTURE=2
ZT_USE_X64_ASM_SALSA=1
ZT_USE_X64_ASM_ED25519=1
override CFLAGS+=-msse -msse2
override CXXFLAGS+=-msse -msse2
ZT_SSO_SUPPORTED=1
ifeq ($(ZT_CONTROLLER),1)
EXT_ARCH=amd64
endif
endif
ifeq ($(CC_MACH),powerpc64le)
ZT_ARCHITECTURE=8
@ -150,27 +143,17 @@ endif
ifeq ($(CC_MACH),ppc64el)
ZT_ARCHITECTURE=8
endif
ifeq ($(CC_MACH),e2k)
ZT_ARCHITECTURE=2
endif
ifeq ($(CC_MACH),e2k64)
ZT_ARCHITECTURE=2
endif
ifeq ($(CC_MACH),i386)
ZT_ARCHITECTURE=1
ZT_SSO_SUPPORTED=1
endif
ifeq ($(CC_MACH),i486)
ZT_ARCHITECTURE=1
ZT_SSO_SUPPORTED=1
endif
ifeq ($(CC_MACH),i586)
ZT_ARCHITECTURE=1
ZT_SSO_SUPPORTED=1
endif
ifeq ($(CC_MACH),i686)
ZT_ARCHITECTURE=1
ZT_SSO_SUPPORTED=1
endif
ifeq ($(CC_MACH),arm)
ZT_ARCHITECTURE=3
@ -186,7 +169,6 @@ ifeq ($(CC_MACH),armhf)
ZT_ARCHITECTURE=3
override DEFS+=-DZT_NO_TYPE_PUNNING
ZT_USE_ARM32_NEON_ASM_CRYPTO=1
ZT_SSO_SUPPORTED=1
endif
ifeq ($(CC_MACH),armv6)
ZT_ARCHITECTURE=3
@ -208,11 +190,6 @@ ifeq ($(CC_MACH),armv6kz)
override DEFS+=-DZT_NO_TYPE_PUNNING
ZT_USE_ARM32_NEON_ASM_CRYPTO=1
endif
ifeq ($(CC_MACH),armv6k)
ZT_ARCHITECTURE=3
override DEFS+=-DZT_NO_TYPE_PUNNING
ZT_USE_ARM32_NEON_ASM_CRYPTO=1
endif
ifeq ($(CC_MACH),armv7)
ZT_ARCHITECTURE=3
override DEFS+=-DZT_NO_TYPE_PUNNING
@ -228,25 +205,13 @@ ifeq ($(CC_MACH),armv7hl)
override DEFS+=-DZT_NO_TYPE_PUNNING
ZT_USE_ARM32_NEON_ASM_CRYPTO=1
endif
ifeq ($(CC_MACH),armv7ve)
ZT_ARCHITECTURE=3
override DEFS+=-DZT_NO_TYPE_PUNNING
ZT_USE_ARM32_NEON_ASM_CRYPTO=1
endif
ifeq ($(CC_MACH),arm64)
ZT_ARCHITECTURE=4
ZT_SSO_SUPPORTED=1
ZT_USE_X64_ASM_ED25519=0
override DEFS+=-DZT_NO_TYPE_PUNNING -DZT_ARCH_ARM_HAS_NEON -march=armv8-a+crypto -mtune=generic -mstrict-align
override DEFS+=-DZT_NO_TYPE_PUNNING
endif
ifeq ($(CC_MACH),aarch64)
ZT_ARCHITECTURE=4
ZT_SSO_SUPPORTED=1
ZT_USE_X64_ASM_ED25519=0
override DEFS+=-DZT_NO_TYPE_PUNNING -DZT_ARCH_ARM_HAS_NEON -march=armv8-a+crypto -mtune=generic -mstrict-align
ifeq ($(ZT_CONTROLLER),1)
EXT_ARCH=arm64
endif
override DEFS+=-DZT_NO_TYPE_PUNNING
endif
ifeq ($(CC_MACH),mipsel)
ZT_ARCHITECTURE=5
@ -267,42 +232,14 @@ endif
ifeq ($(CC_MACH),s390x)
ZT_ARCHITECTURE=16
endif
ifeq ($(CC_MACH),riscv64)
ZT_ARCHITECTURE=0
endif
ifeq ($(CC_MACH),loongarch64)
ZT_ARCHITECTURE=17
override DEFS+=-DZT_NO_TYPE_PUNNING
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))
ERR=$(error FATAL: architecture could not be determined from $(CC) -dumpmachine: $CC_MACH)
.PHONY: err
err: ; $(ERR)
endif
# Flag for Intel 32-bit processors since some machine images are incorrectly marked as i386
ifeq ($(ZT_IA32),1)
override LDFLAGS+=-m32
override CFLAGS+=-m32
override CXXFLAGS+=-m32
# Prevent the use of X64 crypto
ZT_USE_X64_ASM_SALSA=0
ZT_USE_X64_ASM_ED25519=0
endif
ifeq ($(ZT_SSO_SUPPORTED), 1)
ifeq ($(ZT_EMBEDDED),)
override DEFS+=-DZT_SSO_SUPPORTED=1
ifeq ($(ZT_DEBUG),1)
LDLIBS+=rustybits/target/debug/libzeroidc.a -ldl -lssl -lcrypto
else
LDLIBS+=rustybits/target/release/libzeroidc.a -ldl -lssl -lcrypto
endif
endif
endif
# Disable software updates by default on Linux since that is normally done with package management
override DEFS+=-DZT_BUILD_PLATFORM=1 -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\""
@ -320,27 +257,15 @@ ifeq ($(ZT_OFFICIAL),1)
override LDFLAGS+=-Wl,--wrap=memcpy -static-libstdc++
endif
ifeq ($(ZT_CONTROLLER),1)
override CXXFLAGS+=-Wall -Wno-deprecated -std=c++17 -pthread $(INCLUDES) -DNDEBUG $(DEFS)
override LDLIBS+=-Lext/libpqxx-7.7.3/install/ubuntu22.04/$(EXT_ARCH)/lib -lpqxx -lpq ext/hiredis-1.0.2/lib/ubuntu22.04/$(EXT_ARCH)/libhiredis.a ext/redis-plus-plus-1.3.3/install/ubuntu22.04/$(EXT_ARCH)/lib/libredis++.a -lssl -lcrypto
override DEFS+=-DZT_CONTROLLER_USE_LIBPQ -DZT_NO_PEER_METRICS
override INCLUDES+=-I/usr/include/postgresql -Iext/libpqxx-7.7.3/install/ubuntu22.04/$(EXT_ARCH)/include -Iext/hiredis-1.0.2/include/ -Iext/redis-plus-plus-1.3.3/install/ubuntu22.04/$(EXT_ARCH)/include/sw/
ifeq ($(ZT_DEBUG),1)
override LDLIBS+=rustybits/target/debug/libsmeeclient.a
else
override LDLIBS+=rustybits/target/release/libsmeeclient.a
endif
endif
# ARM32 hell -- use conservative CFLAGS
ifeq ($(ZT_ARCHITECTURE),3)
ifeq ($(shell if [ -e /usr/bin/dpkg ]; then dpkg --print-architecture; fi),armel)
override CFLAGS+=-march=armv5t -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm
override CXXFLAGS+=-march=armv5t -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm
override CFLAGS+=-march=armv5 -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm
override CXXFLAGS+=-march=armv5 -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
override CFLAGS+=-march=armv5 -mno-unaligned-access -marm -fexceptions
override CXXFLAGS+=-march=armv5 -mno-unaligned-access -marm -fexceptions
ZT_USE_ARM32_NEON_ASM_CRYPTO=0
endif
endif
@ -359,25 +284,15 @@ ifeq ($(ZT_USE_ARM32_NEON_ASM_CRYPTO),1)
override CORE_OBJS+=ext/arm32-neon-salsa2012-asm/salsa2012.o
endif
# Position Independence
override CFLAGS+=-fPIC -fPIE
override CXXFLAGS+=-fPIC -fPIE
# Non-executable stack
override LDFLAGS+=-Wl,-z,noexecstack
.PHONY: all
all: one
.PHONY: one
one: zerotier-one zerotier-idtool zerotier-cli
from_builder: FORCE
ln -sf zerotier-one zerotier-idtool
ln -sf zerotier-one zerotier-cli
zerotier-one: $(CORE_OBJS) $(ONE_OBJS) one.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LDLIBS)
$(STRIP) zerotier-one
zerotier-idtool: zerotier-one
ln -sf zerotier-one zerotier-idtool
@ -385,10 +300,8 @@ zerotier-idtool: zerotier-one
zerotier-cli: zerotier-one
ln -sf zerotier-one zerotier-cli
$(ONE_OBJS): zeroidc smeeclient
libzerotiercore.a: FORCE
make CFLAGS="-O3 -fstack-protector -fPIC" CXXFLAGS="-O3 -std=c++17 -fstack-protector -fPIC" $(CORE_OBJS)
make CFLAGS="-O3 -fstack-protector -fPIC" CXXFLAGS="-O3 -std=c++11 -fstack-protector -fPIC" $(CORE_OBJS)
ar rcs libzerotiercore.a $(CORE_OBJS)
ranlib libzerotiercore.a
@ -396,6 +309,7 @@ core: libzerotiercore.a
selftest: $(CORE_OBJS) $(ONE_OBJS) selftest.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-selftest selftest.o $(CORE_OBJS) $(ONE_OBJS) $(LDLIBS)
$(STRIP) zerotier-selftest
zerotier-selftest: selftest
@ -405,52 +319,28 @@ manpages: FORCE
doc: manpages
clean: FORCE
rm -rf *.a *.so *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/miniupnpc/*.o ext/libnatpmp/*.o $(CORE_OBJS) $(ONE_OBJS) zerotier-one zerotier-idtool zerotier-cli zerotier-selftest build-* ZeroTierOneInstaller-* *.deb *.rpm .depend debian/files debian/zerotier-one*.debhelper debian/zerotier-one.substvars debian/*.log debian/zerotier-one doc/node_modules ext/misc/*.o debian/.debhelper debian/debhelper-build-stamp docker/zerotier-one rustybits/target
rm -rf *.a *.so *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/miniupnpc/*.o ext/libnatpmp/*.o $(CORE_OBJS) $(ONE_OBJS) zerotier-one zerotier-idtool zerotier-cli zerotier-selftest build-* ZeroTierOneInstaller-* *.deb *.rpm .depend debian/files debian/zerotier-one*.debhelper debian/zerotier-one.substvars debian/*.log debian/zerotier-one doc/node_modules ext/misc/*.o debian/.debhelper debian/debhelper-build-stamp docker/zerotier-one
distclean: clean
realclean: distclean
official: FORCE
make -j`nproc` ZT_OFFICIAL=1 all
make -j4 ZT_OFFICIAL=1 all
docker: FORCE
docker build --no-cache -f ext/installfiles/linux/zerotier-containerized/Dockerfile -t zerotier-containerized .
_buildx:
@echo "docker buildx create"
# docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
docker run --privileged --rm tonistiigi/binfmt --install all
@echo docker buildx create --name multiarch --driver docker-container --use
@echo docker buildx inspect --bootstrap
docker build -f ext/installfiles/linux/zerotier-containerized/Dockerfile -t zerotier-containerized .
central-controller: FORCE
make -j4 ZT_CONTROLLER=1 one
make -j4 LDLIBS="-L/usr/pgsql-10/lib/ -lpq -Lext/librabbitmq/centos_x64/lib/ -lrabbitmq" CXXFLAGS="-I/usr/pgsql-10/include -I./ext/librabbitmq/centos_x64/include -fPIC" DEFS="-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER" ZT_OFFICIAL=1 ZT_USE_X64_ASM_ED25519=1 one
central-controller-docker: _buildx FORCE
docker buildx build --platform linux/amd64,linux/arm64 --no-cache -t registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=`git name-rev --name-only HEAD` . --push
@echo Image: registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP}
central-controller-docker: central-controller
docker build -t docker.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile .
debug: FORCE
make ZT_DEBUG=1 one
make ZT_DEBUG=1 selftest
ifeq ($(ZT_SSO_SUPPORTED), 1)
ifeq ($(ZT_EMBEDDED),)
zeroidc: FORCE
export PATH=/${HOME}/.cargo/bin:$$PATH; cd rustybits && cargo build $(ZT_CARGO_FLAGS) -p zeroidc
endif
else
zeroidc:
endif
ifeq ($(ZT_CONTROLLER), 1)
smeeclient: FORCE
export PATH=/${HOME}/.cargo/bin:$$PATH; cd rustybits && cargo build $(ZT_CARGO_FLAGS) -p smeeclient
else
smeeclient:
endif
# Note: keep the symlinks in /var/lib/zerotier-one to the binaries since these
# provide backward compatibility with old releases where the binaries actually
# lived here. Folks got scripts.
@ -478,7 +368,6 @@ install: FORCE
rm -f $(DESTDIR)/usr/share/man/man1/zerotier-cli.1.gz
cat doc/zerotier-cli.1 | gzip -9 >$(DESTDIR)/usr/share/man/man1/zerotier-cli.1.gz
cat doc/zerotier-idtool.1 | gzip -9 >$(DESTDIR)/usr/share/man/man1/zerotier-idtool.1.gz
cp ext/installfiles/linux/zerotier-one.te $(DESTDIR)/var/lib/zerotier-one/zerotier-one.te
# Uninstall preserves identity.public and identity.secret since the user might
# want to save these. These are your ZeroTier address.
@ -500,29 +389,13 @@ uninstall: FORCE
# These are just for convenience for building Linux packages
echo_flags:
@echo "=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~"
@echo "echo_flags :: CC=$(CC)"
@echo "echo_flags :: CXX=$(CXX)"
@echo "echo_flags :: CFLAGS=$(CFLAGS)"
@echo "echo_flags :: CXXFLAGS=$(CXXFLAGS)"
@echo "echo_flags :: LDFLAGS=$(LDFLAGS)"
@echo "echo_flags :: RUSTFLAGS=$(RUSTFLAGS)"
@echo "=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~"
debian: echo_flags
@echo "building deb package"
debuild --no-lintian -I -i -us -uc -nc -b
# debuild --no-lintian -b -uc -us
# debian: FORCE
# debuild --no-lintian -I -i -us -uc -nc -b
debian: FORCE
debuild -I -i -us -uc -nc -b
debian-clean: FORCE
rm -rf debian/files debian/zerotier-one*.debhelper debian/zerotier-one.substvars debian/*.log debian/zerotier-one debian/.debhelper debian/debhelper-build-stamp
redhat:
@echo "building rpm package"
redhat: FORCE
rpmbuild --target `rpm -q bash --qf "%{arch}"` -ba zerotier-one.spec
# This installs the packages needed to build ZT locally on CentOS 7 and
@ -532,37 +405,4 @@ centos-7-setup: FORCE
yum install -y centos-release-scl
yum install -y devtoolset-8-gcc devtoolset-8-gcc-c++
snap-build-local: FORCE
snapcraft
snap-install: FORCE
snap install zerotier_`git describe --tags --abbrev=0`_${SNAP_ARCH}.snap --dangerous
snap-uninstall: FORCE
snap remove zerotier
snap-build-remote: FORCE
cd pkg && snapcraft remote-build --build-for=amd64,arm64,s390x,ppc64el,armhf,i386
snap-upload: ./pkg/*.snap
for file in $^ ; do \
snapcraft upload --release=beta,edge,candidate $${file} ; \
done
synology-pkg: FORCE
cd pkg/synology ; ./build.sh build
synology-docker: FORCE
cd pkg/synology/dsm7-docker/; ./build.sh build-and-push
munge_rpm:
@:$(call check_defined, VERSION)
@echo "Updating rpm spec to $(VERSION)"
ci/scripts/munge_rpm_spec.sh zerotier-one.spec $(VERSION) "Adam Ierymenko <adam.ierymenko@zerotier.com>" "see https://github.com/zerotier/ZeroTierOne for release notes"
munge_deb:
@:$(call check_defined, VERSION)
@echo "Updating debian/changelog to $(VERSION)"
ci/scripts/munge_debian_changelog.sh debian/changelog $(VERSION) "Adam Ierymenko <adam.ierymenko@zerotier.com>" "see https://github.com/zerotier/ZeroTierOne for release notes"
FORCE:

155
attic/make-mac.mk Normal file
View file

@ -0,0 +1,155 @@
CC=clang
CXX=clang++
INCLUDES=
DEFS=
LIBS=
ARCH_FLAGS=
CODESIGN=echo
PRODUCTSIGN=echo
CODESIGN_APP_CERT=
CODESIGN_INSTALLER_CERT=
NOTARIZE=echo
NOTARIZE_USER_ID=null
ZT_BUILD_PLATFORM=3
ZT_BUILD_ARCHITECTURE=2
ZT_VERSION_MAJOR=$(shell cat version.h | grep -F VERSION_MAJOR | cut -d ' ' -f 3)
ZT_VERSION_MINOR=$(shell cat version.h | grep -F VERSION_MINOR | cut -d ' ' -f 3)
ZT_VERSION_REV=$(shell cat version.h | grep -F VERSION_REVISION | cut -d ' ' -f 3)
ZT_VERSION_BUILD=$(shell cat version.h | grep -F VERSION_BUILD | cut -d ' ' -f 3)
DEFS+=-DZT_BUILD_PLATFORM=$(ZT_BUILD_PLATFORM) -DZT_BUILD_ARCHITECTURE=$(ZT_BUILD_ARCHITECTURE)
include objects.mk
ONE_OBJS+=osdep/MacEthernetTap.o osdep/MacKextEthernetTap.o ext/http-parser/http_parser.o
ifeq ($(ZT_CONTROLLER),1)
LIBS+=-lpq -lrabbitmq
DEFS+=-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER
endif
# Official releases are signed with our Apple cert and apply software updates by default
ifeq ($(ZT_OFFICIAL_RELEASE),1)
DEFS+=-DZT_SOFTWARE_UPDATE_DEFAULT="\"apply\""
ZT_USE_MINIUPNPC=1
CODESIGN=codesign
PRODUCTSIGN=productsign
CODESIGN_APP_CERT="Developer ID Application: ZeroTier, Inc (8ZD9JUCZ4V)"
CODESIGN_INSTALLER_CERT="Developer ID Installer: ZeroTier, Inc (8ZD9JUCZ4V)"
NOTARIZE=xcrun altool
NOTARIZE_USER_ID="adam.ierymenko@gmail.com"
else
DEFS+=-DZT_SOFTWARE_UPDATE_DEFAULT="\"download\""
endif
# Use fast ASM Salsa20/12 for x64 processors
DEFS+=-DZT_USE_X64_ASM_SALSA2012
CORE_OBJS+=ext/x64-salsa2012-asm/salsa2012.o
# Build miniupnpc and nat-pmp as included libraries -- extra defs are required for these sources
DEFS+=-DMACOSX -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
ONE_OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o
# Build with address sanitization library for advanced debugging (clang)
ifeq ($(ZT_SANITIZE),1)
DEFS+=-fsanitize=address -DASAN_OPTIONS=symbolize=1
endif
ifeq ($(ZT_DEBUG_TRACE),1)
DEFS+=-DZT_DEBUG_TRACE
endif
# Debug mode -- dump trace output, build binary with -g
ifeq ($(ZT_DEBUG),1)
ZT_TRACE=1
CFLAGS+=-Wall -g -maes -mpclmul $(INCLUDES) $(DEFS)
STRIP=echo
# The following line enables optimization for the crypto code, since
# C25519 in particular is almost UNUSABLE in heavy testing without it.
node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o node/AES.o: CFLAGS = -Wall -O2 -g -maes -mpclmul $(INCLUDES) $(DEFS)
else
CFLAGS?=-Ofast -fstack-protector-strong
CFLAGS+=$(ARCH_FLAGS) -Wall -flto -fPIE -maes -msse -msse2 -msse3 -mpclmul -mmacosx-version-min=10.9 -DNDEBUG -Wno-unused-private-field $(INCLUDES) $(DEFS)
STRIP=strip
endif
ifeq ($(ZT_TRACE),1)
DEFS+=-DZT_TRACE
endif
ifeq ($(ZT_VAULT_SUPPORT),1)
DEFS+=-DZT_VAULT_SUPPORT=1
LIBS+=-lcurl
endif
CXXFLAGS=$(CFLAGS) -std=c++11 -stdlib=libc++
all: one macui
ext/x64-salsa2012-asm/salsa2012.o:
$(CC) $(CFLAGS) -c ext/x64-salsa2012-asm/salsa2012.s -o ext/x64-salsa2012-asm/salsa2012.o
mac-agent: FORCE
$(CC) -Ofast -o MacEthernetTapAgent osdep/MacEthernetTapAgent.c
$(CODESIGN) -f -s $(CODESIGN_APP_CERT) MacEthernetTapAgent
one: $(CORE_OBJS) $(ONE_OBJS) one.o mac-agent
$(CXX) $(CXXFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LIBS)
$(STRIP) zerotier-one
ln -sf zerotier-one zerotier-idtool
ln -sf zerotier-one zerotier-cli
$(CODESIGN) -f -s $(CODESIGN_APP_CERT) zerotier-one
zerotier-one: one
central-controller:
make ZT_CONTROLLER=1 one
zerotier-idtool: one
zerotier-cli: one
libzerotiercore.a: $(CORE_OBJS)
ar rcs libzerotiercore.a $(CORE_OBJS)
ranlib libzerotiercore.a
core: libzerotiercore.a
macui: FORCE
cd macui && xcodebuild -target "ZeroTier One" -configuration Release
$(CODESIGN) -f -s $(CODESIGN_APP_CERT) "macui/build/Release/ZeroTier One.app"
#cli: FORCE
# $(CXX) $(CXXFLAGS) -o zerotier cli/zerotier.cpp osdep/OSUtils.cpp node/InetAddress.cpp node/Utils.cpp node/Salsa20.cpp node/Identity.cpp node/SHA512.cpp node/C25519.cpp -lcurl
# $(STRIP) zerotier
selftest: $(CORE_OBJS) $(ONE_OBJS) selftest.o
$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(CORE_OBJS) $(ONE_OBJS) $(LIBS)
$(STRIP) zerotier-selftest
zerotier-selftest: selftest
# Requires Packages: http://s.sudre.free.fr/Software/Packages/about.html
mac-dist-pkg: FORCE
packagesbuild "ext/installfiles/mac/ZeroTier One.pkgproj"
rm -f "ZeroTier One Signed.pkg"
$(PRODUCTSIGN) --sign $(CODESIGN_INSTALLER_CERT) "ZeroTier One.pkg" "ZeroTier One Signed.pkg"
if [ -f "ZeroTier One Signed.pkg" ]; then mv -f "ZeroTier One Signed.pkg" "ZeroTier One.pkg"; fi
rm -f zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_*
cat ext/installfiles/mac-update/updater.tmpl.sh "ZeroTier One.pkg" >zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_$(ZT_VERSION_MAJOR).$(ZT_VERSION_MINOR).$(ZT_VERSION_REV)_$(ZT_VERSION_BUILD).exe
$(NOTARIZE) -t osx -f "ZeroTier One.pkg" --primary-bundle-id --output-format xml --notarize-app -u $(NOTARIZE_USER_ID)
echo '*** When Apple notifies that the app is notarized, run: xcrun stapler staple "ZeroTier One.pkg"'
# For ZeroTier, Inc. to build official signed packages
official: FORCE
make clean
make ZT_OFFICIAL_RELEASE=1 -j 8 one
make ZT_OFFICIAL_RELEASE=1 macui
make ZT_OFFICIAL_RELEASE=1 mac-dist-pkg
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 macui/build zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_*
distclean: clean
realclean: clean
FORCE:

View file

@ -1,16 +1,12 @@
CORE_OBJS=\
node/AES.o \
node/AES_aesni.o \
node/AES_armcrypto.o \
node/C25519.o \
node/Capability.o \
node/CertificateOfMembership.o \
node/CertificateOfOwnership.o \
node/Credential.o \
node/ECC384.o \
node/Identity.o \
node/IncomingPacket.o \
node/InetAddress.o \
node/Membership.o \
node/Metrics.o \
node/Multicaster.o \
node/Network.o \
node/NetworkConfig.o \
@ -20,17 +16,12 @@ CORE_OBJS=\
node/Path.o \
node/Peer.o \
node/Poly1305.o \
node/Revocation.o \
node/Salsa20.o \
node/SelfAwareness.o \
node/SHA512.o \
node/Switch.o \
node/Tag.o \
node/Topology.o \
node/Trace.o \
node/Utils.o \
node/Bond.o \
node/PacketMultiplexer.o
node/Utils.o
ONE_OBJS=\
controller/EmbeddedNetworkController.o \
@ -39,6 +30,7 @@ ONE_OBJS=\
controller/FileDB.o \
controller/LFDB.o \
controller/PostgreSQL.o \
controller/RabbitMQ.o \
osdep/EthernetTap.o \
osdep/ManagedRoute.o \
osdep/Http.o \

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -208,12 +208,13 @@ const MATCH_ARG_COUNTS = {
const INTL_ALPHANUM_REGEX = new RegExp('[0-9A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]');
// Checks whether something is a valid capability, tag, or macro name
function _isValidName(n) {
if ((typeof n !== 'string') || (n.length === 0)) return false;
function _isValidName(n)
{
if ((typeof n !== 'string')||(n.length === 0)) return false;
if ("0123456789".indexOf(n.charAt(0)) >= 0) return false;
for (let i = 0; i < n.length; ++i) {
for(let i=0;i<n.length;++i) {
let c = n.charAt(i);
if ((c !== '_') && (!INTL_ALPHANUM_REGEX.test(c))) return false;
if ((c !== '_')&&(!INTL_ALPHANUM_REGEX.test(c))) return false;
}
return true;
}
@ -222,42 +223,45 @@ function _isValidName(n) {
const IPV6_REGEX = new RegExp('(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))');
const IPV4_REGEX = new RegExp('((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])');
function _parseNum(n) {
function _parseNum(n)
{
try {
if ((typeof n !== 'string') || (n.length === 0))
if ((typeof n !== 'string')||(n.length === 0))
return -1;
n = n.toLowerCase();
if ((n.length > 2) && (n.substr(0, 2) === '0x'))
n = parseInt(n.substr(2), 16);
else n = parseInt(n, 10);
return (((typeof n === 'number') && (n !== null) && (!isNaN(n))) ? n : -1);
if ((n.length > 2)&&(n.substr(0,2) === '0x'))
n = parseInt(n.substr(2),16);
else n = parseInt(n,10);
return (((typeof n === 'number')&&(n !== null)&&(!isNaN(n))) ? n : -1);
} catch (e) {
return -1;
}
}
function _cleanMac(m) {
function _cleanMac(m)
{
m = m.toLowerCase();
var m2 = '';
let charcount = 0;
for (let i = 0; ((i < m.length) && (m2.length < 17)); ++i) {
for(let i=0;((i<m.length)&&(m2.length<17));++i) {
let c = m.charAt(i);
if ("0123456789abcdef".indexOf(c) >= 0) {
m2 += c;
charcount++;
if ((m2.length > 0) && (m2.length !== 17) && (charcount >= 2)) {
if ((m2.length > 0)&&(m2.length !== 17)&&(charcount >= 2) ) {
m2 += ':';
charcount = 0;
charcount=0;
}
}
}
return m2;
}
function _cleanHex(m) {
function _cleanHex(m)
{
m = m.toLowerCase();
var m2 = '';
for (let i = 0; i < m.length; ++i) {
for(let i=0;i<m.length;++i) {
let c = m.charAt(i);
if ("0123456789abcdef".indexOf(c) >= 0)
m2 += c;
@ -265,12 +269,13 @@ function _cleanHex(m) {
return m2;
}
function _renderMatches(mtree, rules, macros, caps, tags, params) {
function _renderMatches(mtree,rules,macros,caps,tags,params)
{
let not = false;
let or = false;
for (let k = 0; k < mtree.length; ++k) {
for(let k=0;k<mtree.length;++k) {
let match = (typeof mtree[k][0] === 'string') ? mtree[k][0].toLowerCase() : '';
if ((match.length === 0) || (match === 'and')) { // AND is the default
if ((match.length === 0)||(match === 'and')) { // AND is the default
continue;
} else if (match === 'not') {
not = true;
@ -280,29 +285,29 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
let args = [];
let argCount = MATCH_ARG_COUNTS[match];
if (!argCount)
return [mtree[k][1], mtree[k][2], 'Unrecognized match type "' + match + '".'];
for (let i = 0; i < argCount; ++i) {
return [ mtree[k][1],mtree[k][2],'Unrecognized match type "'+match+'".' ];
for(let i=0;i<argCount;++i) {
if (++k >= mtree.length)
return [mtree[k - 1][1], mtree[k - 1][2], 'Missing argument(s) to match.'];
return [ mtree[k - 1][1],mtree[k - 1][2],'Missing argument(s) to match.' ];
let arg = mtree[k][0];
if ((typeof arg !== 'string') || (arg in RESERVED_WORDS) || (arg.length === 0))
return [mtree[k - 1][1], mtree[k - 1][2], 'Missing argument(s) to match (invalid argument or argument is reserved word).'];
if ((typeof arg !== 'string')||(arg in RESERVED_WORDS)||(arg.length === 0))
return [ mtree[k - 1][1],mtree[k - 1][2],'Missing argument(s) to match (invalid argument or argument is reserved word).' ];
if (arg.charAt(0) === '$') {
let tmp = params[arg];
if (typeof tmp === 'undefined')
return [mtree[k][1], mtree[k][2], 'Undefined variable name.'];
args.push([tmp, mtree[k][1], mtree[k][2]]);
return [ mtree[k][1],mtree[k][2],'Undefined variable name.' ];
args.push([ tmp,mtree[k][1],mtree[k][2] ]);
} else {
args.push(mtree[k]);
}
}
switch (match) {
switch(match) {
case 'ztsrc':
case 'ztdest': {
let zt = _cleanHex(args[0][0]);
if (zt.length !== 10)
return [args[0][1], args[0][2], 'Invalid ZeroTier address.'];
return [ args[0][1],args[0][2],'Invalid ZeroTier address.' ];
rules.push({
'type': KEYWORD_TO_API_MAP[match],
'not': not,
@ -323,14 +328,14 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
}
if (typeof num !== 'number')
num = _parseNum(args[0][0]);
if ((typeof num !== 'number') || (num < 0) || (num > 0xffffffff) || (num === null))
return [args[0][1], args[0][2], 'Invalid numeric value.'];
if ((typeof num !== 'number')||(num < 0)||(num > 0xffffffff)||(num === null))
return [ args[0][1],args[0][2],'Invalid numeric value.' ];
let r = {
'type': KEYWORD_TO_API_MAP[match],
'not': not,
'or': or
};
switch (match) {
switch(match) {
case 'vlan': r['vlanId'] = num; break;
case 'vlanpcp': r['vlanPcp'] = num; break;
case 'vlandei': r['vlanDei'] = num; break;
@ -341,7 +346,7 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
} break;
case 'random': {
let num = parseFloat(args[0][0]) || 0.0;
let num = parseFloat(args[0][0])||0.0;
if (num < 0.0) num = 0.0;
if (num > 1.0) num = 1.0;
rules.push({
@ -356,7 +361,7 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
case 'macdest': {
let mac = _cleanMac(args[0][0]);
if (mac.length !== 17)
return [args[0][1], args[0][2], 'Invalid MAC address.'];
return [ args[0][1],args[0][2],'Invalid MAC address.' ];
rules.push({
'type': KEYWORD_TO_API_MAP[match],
'not': not,
@ -370,8 +375,8 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
let ip = args[0][0];
let slashIdx = ip.indexOf('/');
if (slashIdx <= 0)
return [args[0][1], args[0][2], 'Missing /bits netmask length designation in IP.'];
let ipOnly = ip.substr(0, slashIdx);
return [ args[0][1],args[0][2],'Missing /bits netmask length designation in IP.' ];
let ipOnly = ip.substr(0,slashIdx);
if (IPV6_REGEX.test(ipOnly)) {
rules.push({
'type': ((match === 'ipsrc') ? 'MATCH_IPV6_SOURCE' : 'MATCH_IPV6_DEST'),
@ -387,17 +392,17 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
'ip': ip
});
} else {
return [args[0][1], args[0][2], 'Invalid IP address (not valid IPv4 or IPv6).'];
return [ args[0][1],args[0][2],'Invalid IP address (not valid IPv4 or IPv6).' ];
}
} break;
case 'icmp': {
let icmpType = _parseNum(args[0][0]);
if ((icmpType < 0) || (icmpType > 0xff))
return [args[0][1], args[0][2], 'Missing or invalid ICMP type.'];
if ((icmpType < 0)||(icmpType > 0xff))
return [ args[0][1],args[0][2],'Missing or invalid ICMP type.' ];
let icmpCode = _parseNum(args[1][0]); // -1 okay, indicates don't match code
if (icmpCode > 0xff)
return [args[1][1], args[1][2], 'Invalid ICMP code (use -1 for none).'];
return [ args[1][1],args[1][2],'Invalid ICMP code (use -1 for none).' ];
rules.push({
'type': 'MATCH_ICMP',
'not': not,
@ -416,7 +421,7 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
if (arg.indexOf('-') > 0) {
let asplit = arg.split('-');
if (asplit.length !== 2) {
return [args[0][1], args[0][2], 'Invalid numeric range.'];
return [ args[0][1],args[0][2],'Invalid numeric range.' ];
} else {
fn = _parseNum(asplit[0]);
tn = _parseNum(asplit[1]);
@ -425,8 +430,8 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
fn = _parseNum(arg);
tn = fn;
}
if ((fn < 0) || (fn > 0xffff) || (tn < 0) || (tn > 0xffff) || (tn < fn))
return [args[0][1], args[0][2], 'Invalid numeric range.'];
if ((fn < 0)||(fn > 0xffff)||(tn < 0)||(tn > 0xffff)||(tn < fn))
return [ args[0][1],args[0][2],'Invalid numeric range.' ];
rules.push({
'type': KEYWORD_TO_API_MAP[match],
'not': not,
@ -438,15 +443,15 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
case 'iptos': {
let mask = _parseNum(args[0][0]);
if ((typeof mask !== 'number') || (mask < 0) || (mask > 0xff) || (mask === null))
return [args[0][1], args[0][2], 'Invalid mask.'];
if ((typeof mask !== 'number')||(mask < 0)||(mask > 0xff)||(mask === null))
return [ args[0][1],args[0][2],'Invalid mask.' ];
let arg = args[1][0];
let fn = null;
let tn = null;
if (arg.indexOf('-') > 0) {
let asplit = arg.split('-');
if (asplit.length !== 2) {
return [args[1][1], args[1][2], 'Invalid value range.'];
return [ args[1][1],args[1][2],'Invalid value range.' ];
} else {
fn = _parseNum(asplit[0]);
tn = _parseNum(asplit[1]);
@ -455,8 +460,8 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
fn = _parseNum(arg);
tn = fn;
}
if ((fn < 0) || (fn > 0xff) || (tn < 0) || (tn > 0xff) || (tn < fn))
return [args[1][1], args[1][2], 'Invalid value range.'];
if ((fn < 0)||(fn > 0xff)||(tn < 0)||(tn > 0xff)||(tn < fn))
return [ args[1][1],args[1][2],'Invalid value range.' ];
rules.push({
'type': 'MATCH_IP_TOS',
'not': not,
@ -471,12 +476,12 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
let chrb = args[0][0].split(/[,]+/);
let maskhi = 0;
let masklo = 0;
for (let i = 0; i < chrb.length; ++i) {
for(let i=0;i<chrb.length;++i) {
if (chrb[i].length > 0) {
let tmp = CHARACTERISTIC_BITS[chrb[i]];
let bit = (typeof tmp === 'number') ? tmp : _parseNum(chrb[i]);
if ((bit < 0) || (bit > 63))
return [args[0][1], args[0][2], 'Invalid bit index (range 0-63) or unrecognized name.'];
if ((bit < 0)||(bit > 63))
return [ args[0][1],args[0][2],'Invalid bit index (range 0-63) or unrecognized name.' ];
if (bit >= 32)
maskhi |= Math.abs(1 << (bit - 32));
else masklo |= Math.abs(1 << bit);
@ -516,10 +521,10 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
tagId = _parseNum(args[0][0]);
tagValue = _parseNum(args[1][0]);
}
if ((tagId < 0) || (tagId > 0xffffffff))
return [args[0][1], args[0][2], 'Undefined tag name and invalid tag value.'];
if ((tagValue < 0) || (tagValue > 0xffffffff))
return [args[1][1], args[1][2], 'Invalid tag value or unrecognized flag/enum name.'];
if ((tagId < 0)||(tagId > 0xffffffff))
return [ args[0][1],args[0][2],'Undefined tag name and invalid tag value.' ];
if ((tagValue < 0)||(tagValue > 0xffffffff))
return [ args[1][1],args[1][2],'Invalid tag value or unrecognized flag/enum name.' ];
rules.push({
'type': KEYWORD_TO_API_MAP[match],
'not': not,
@ -537,14 +542,15 @@ function _renderMatches(mtree, rules, macros, caps, tags, params) {
return null;
}
function _renderActions(rtree, rules, macros, caps, tags, params) {
for (let k = 0; k < rtree.length; ++k) {
function _renderActions(rtree,rules,macros,caps,tags,params)
{
for(let k=0;k<rtree.length;++k) {
let action = (typeof rtree[k][0] === 'string') ? rtree[k][0].toLowerCase() : '';
if (action.length === 0) {
continue;
} else if (action === 'include') {
if ((k + 1) >= rtree.length)
return [rtree[k][1], rtree[k][2], 'Include directive is missing a macro name.'];
return [ rtree[k][1],rtree[k][2],'Include directive is missing a macro name.' ];
let macroName = rtree[k + 1][0];
++k;
@ -552,47 +558,47 @@ function _renderActions(rtree, rules, macros, caps, tags, params) {
let parenIdx = macroName.indexOf('(');
if (parenIdx > 0) {
let pns = macroName.substr(parenIdx + 1).split(/[,)]+/);
for (let k = 0; k < pns.length; ++k) {
for(let k=0;k<pns.length;++k) {
if (pns[k].length > 0)
macroParamArray.push(pns[k]);
}
macroName = macroName.substr(0, parenIdx);
macroName = macroName.substr(0,parenIdx);
}
let macro = macros[macroName];
if (!macro)
return [rtree[k][1], rtree[k][2], 'Macro name not found.'];
return [ rtree[k][1],rtree[k][2],'Macro name not found.' ];
let macroParams = {};
for (let param in macro.params) {
for(let param in macro.params) {
let pidx = macro.params[param];
if (pidx >= macroParamArray.length)
return [rtree[k][1], rtree[k][2], 'Missing one or more required macro parameter.'];
return [ rtree[k][1],rtree[k][2],'Missing one or more required macro parameter.' ];
macroParams[param] = macroParamArray[pidx];
}
let err = _renderActions(macro.rules, rules, macros, caps, tags, macroParams);
let err = _renderActions(macro.rules,rules,macros,caps,tags,macroParams);
if (err !== null)
return err;
} else if ((action === 'drop') || (action === 'accept') || (action === 'break')) { // actions without arguments
if (((k + 1) < rtree.length) && (Array.isArray(rtree[k + 1][0]))) {
} else if ((action === 'drop')||(action === 'accept')||(action === 'break')) { // actions without arguments
if (((k + 1) < rtree.length)&&(Array.isArray(rtree[k + 1][0]))) {
let mtree = rtree[k + 1]; ++k;
let err = _renderMatches(mtree, rules, macros, caps, tags, params);
let err = _renderMatches(mtree,rules,macros,caps,tags,params);
if (err !== null)
return err;
}
rules.push({
'type': KEYWORD_TO_API_MAP[action]
});
} else if ((action === 'tee') || (action === 'watch')) { // actions with arguments (ZeroTier address)
if (((k + 1) < rtree.length) && (Array.isArray(rtree[k + 1][0])) && (rtree[k + 1][0].length >= 2)) {
} else if ((action === 'tee')||(action === 'watch')) { // actions with arguments (ZeroTier address)
if (((k + 1) < rtree.length)&&(Array.isArray(rtree[k + 1][0]))&&(rtree[k + 1][0].length >= 2)) {
let mtree = rtree[k + 1]; ++k;
let maxLength = _parseNum(mtree[0][0]);
if ((maxLength < -1) || (maxLength > 0xffff))
return [mtree[0][1], mtree[1][2], 'Tee/watch max packet length to forward invalid or out of range.'];
if ((maxLength < -1)||(maxLength > 0xffff))
return [ mtree[0][1],mtree[1][2],'Tee/watch max packet length to forward invalid or out of range.' ];
let target = mtree[1][0];
if ((typeof target !== 'string') || (target.length !== 10))
return [mtree[1][1], mtree[1][2], 'Missing or invalid ZeroTier address target for tee/watch.'];
let err = _renderMatches(mtree.slice(2), rules, macros, caps, tags, params);
if ((typeof target !== 'string')||(target.length !== 10))
return [ mtree[1][1],mtree[1][2],'Missing or invalid ZeroTier address target for tee/watch.' ];
let err = _renderMatches(mtree.slice(2),rules,macros,caps,tags,params);
if (err !== null)
return err;
rules.push({
@ -601,15 +607,15 @@ function _renderActions(rtree, rules, macros, caps, tags, params) {
'length': maxLength
});
} else {
return [rtree[k][1], rtree[k][2], 'The tee and watch actions require two paremters (max length or 0 for all, target).'];
return [ rtree[k][1],rtree[k][2],'The tee and watch actions require two paremters (max length or 0 for all, target).' ];
}
} else if (action === 'redirect') {
if (((k + 1) < rtree.length) && (Array.isArray(rtree[k + 1][0])) && (rtree[k + 1][0].length >= 1)) {
if (((k + 1) < rtree.length)&&(Array.isArray(rtree[k + 1][0]))&&(rtree[k + 1][0].length >= 1)) {
let mtree = rtree[k + 1]; ++k;
let target = mtree[0][0];
if ((typeof target !== 'string') || (target.length !== 10))
return [mtree[0][1], mtree[0][2], 'Missing or invalid ZeroTier address target for redirect.'];
let err = _renderMatches(mtree.slice(1), rules, macros, caps, tags, params);
if ((typeof target !== 'string')||(target.length !== 10))
return [ mtree[0][1],mtree[0][2],'Missing or invalid ZeroTier address target for redirect.' ];
let err = _renderMatches(mtree.slice(1),rules,macros,caps,tags,params);
if (err !== null)
return err;
rules.push({
@ -617,38 +623,39 @@ function _renderActions(rtree, rules, macros, caps, tags, params) {
'address': target
});
} else {
return [rtree[k][1], rtree[k][2], 'The redirect action requires a target parameter.'];
return [ rtree[k][1],rtree[k][2],'The redirect action requires a target parameter.' ];
}
} else {
return [rtree[k][1], rtree[k][2], 'Unrecognized action or directive in rule set.'];
return [ rtree[k][1],rtree[k][2],'Unrecognized action or directive in rule set.' ];
}
}
return null;
}
function compile(src, rules, caps, tags) {
function compile(src,rules,caps,tags)
{
try {
if (typeof src !== 'string')
return [0, 0, '"src" parameter must be a string.'];
return [ 0,0,'"src" parameter must be a string.' ];
// Pass 1: parse source into a tree of arrays of elements. Each element is a 3-item
// tuple consisting of string, line number, and character index in line to enable
// informative error messages to be returned.
var blockStack = [[]];
var curr = ['', -1, -1];
var blockStack = [ [] ];
var curr = [ '',-1,-1 ];
var skipRestOfLine = false;
for (let idx = 0, lineNo = 1, lineIdx = 0; idx < src.length; ++idx, ++lineIdx) {
for(let idx=0,lineNo=1,lineIdx=0;idx<src.length;++idx,++lineIdx) {
let ch = src.charAt(idx);
if (skipRestOfLine) {
if ((ch === '\r') || (ch === '\n')) {
if ((ch === '\r')||(ch === '\n')) {
skipRestOfLine = false;
++lineNo;
lineIdx = 0;
}
} else {
switch (ch) {
switch(ch) {
case '\n':
++lineNo;
lineIdx = 0;
@ -659,20 +666,20 @@ function compile(src, rules, caps, tags) {
let endOfBlock = false;
if (curr[0].charAt(curr[0].length - 1) === ';') {
endOfBlock = true;
curr[0] = curr[0].substr(0, curr[0].length - 1);
curr[0] = curr[0].substr(0,curr[0].length - 1);
}
if (curr[0].length > 0) {
blockStack[blockStack.length - 1].push(curr);
}
if ((endOfBlock) && (blockStack.length > 1) && (blockStack[blockStack.length - 1].length > 0)) {
if ((endOfBlock)&&(blockStack.length > 1)&&(blockStack[blockStack.length - 1].length > 0)) {
blockStack[blockStack.length - 2].push(blockStack[blockStack.length - 1]);
blockStack.pop();
} else if (curr[0] in OPEN_BLOCK_KEYWORDS) {
blockStack.push([]);
}
curr = ['', -1, -1];
curr = [ '',-1,-1 ];
}
break;
default:
@ -693,11 +700,11 @@ function compile(src, rules, caps, tags) {
if (curr[0].length > 0) {
if (curr[0].charAt(curr[0].length - 1) === ';')
curr[0] = curr[0].substr(0, curr[0].length - 1);
curr[0] = curr[0].substr(0,curr[0].length - 1);
if (curr[0].length > 0)
blockStack[blockStack.length - 1].push(curr);
}
while ((blockStack.length > 1) && (blockStack[blockStack.length - 1].length > 0)) {
while ((blockStack.length > 1)&&(blockStack[blockStack.length - 1].length > 0)) {
blockStack[blockStack.length - 2].push(blockStack[blockStack.length - 1]);
blockStack.pop();
}
@ -707,13 +714,13 @@ function compile(src, rules, caps, tags) {
let baseRuleTree = [];
let macros = {};
for (let i = 0; i < parsed.length; ++i) {
for(let i=0;i<parsed.length;++i) {
let keyword = (typeof parsed[i][0] === 'string') ? parsed[i][0].toLowerCase() : null;
if (keyword === 'macro') {
// Define macros
if (((i + 1) >= parsed.length) || (!Array.isArray(parsed[i + 1])) || (parsed[i + 1].length < 1) || (!Array.isArray(parsed[i + 1][0])))
return [parsed[i][1], parsed[i][2], 'Macro definition is missing name.'];
if ( ((i + 1) >= parsed.length) || (!Array.isArray(parsed[i + 1])) || (parsed[i + 1].length < 1) || (!Array.isArray(parsed[i + 1][0])) )
return [ parsed[i][1],parsed[i][2],'Macro definition is missing name.' ];
let macro = parsed[++i];
let macroName = macro[0][0].toLowerCase();
@ -721,20 +728,20 @@ function compile(src, rules, caps, tags) {
let parenIdx = macroName.indexOf('(');
if (parenIdx > 0) {
let pns = macroName.substr(parenIdx + 1).split(/[,)]+/);
for (let k = 0; k < pns.length; ++k) {
for(let k=0;k<pns.length;++k) {
if (pns[k].length > 0)
params[pns[k]] = k;
}
macroName = macroName.substr(0, parenIdx);
macroName = macroName.substr(0,parenIdx);
}
if (!_isValidName(macroName))
return [macro[0][1], macro[0][2], 'Invalid macro name.'];
return [ macro[0][1],macro[0][2],'Invalid macro name.' ];
if (macroName in RESERVED_WORDS)
return [macro[0][1], macro[0][2], 'Macro name is a reserved word.'];
return [ macro[0][1],macro[0][2],'Macro name is a reserved word.' ];
if (macroName in macros)
return [macro[0][1], macro[0][2], 'Multiple definition of macro name.'];
return [ macro[0][1],macro[0][2],'Multiple definition of macro name.' ];
macros[macroName] = {
params: params,
@ -743,81 +750,81 @@ function compile(src, rules, caps, tags) {
} else if (keyword === 'tag') {
// Define tags
if (((i + 1) >= parsed.length) || (!Array.isArray(parsed[i + 1])) || (parsed[i + 1].length < 1) || (!Array.isArray(parsed[i + 1][0])))
return [parsed[i][1], parsed[i][2], 'Tag definition is missing name.'];
if ( ((i + 1) >= parsed.length) || (!Array.isArray(parsed[i + 1])) || (parsed[i + 1].length < 1) || (!Array.isArray(parsed[i + 1][0])) )
return [ parsed[i][1],parsed[i][2],'Tag definition is missing name.' ];
let tag = parsed[++i];
let tagName = tag[0][0].toLowerCase();
if (!_isValidName(tagName))
return [tag[0][1], tag[0][2], 'Invalid tag name.'];
return [ tag[0][1],tag[0][2],'Invalid tag name.' ];
if (tagName in RESERVED_WORDS)
return [tag[0][1], tag[0][2], 'Tag name is a reserved word.'];
return [ tag[0][1],tag[0][2],'Tag name is a reserved word.' ];
if (tagName in tags)
return [tag[0][1], tag[0][2], 'Multiple definition of tag name.'];
return [ tag[0][1],tag[0][2],'Multiple definition of tag name.' ];
let flags = {};
let enums = {};
let id = -1;
let dfl = null;
for (let k = 1; k < tag.length; ++k) {
for(let k=1;k<tag.length;++k) {
let tkeyword = tag[k][0].toLowerCase();
if (tkeyword === 'id') {
if (id >= 0)
return [tag[k][1], tag[k][2], 'Duplicate tag id definition.'];
return [ tag[k][1],tag[k][2],'Duplicate tag id definition.' ];
if ((k + 1) >= tag.length)
return [tag[k][1], tag[k][2], 'Missing numeric value for ID.'];
return [ tag[k][1],tag[k][2],'Missing numeric value for ID.' ];
id = _parseNum(tag[++k][0]);
if ((id < 0) || (id > 0xffffffff))
return [tag[k][1], tag[k][2], 'Invalid or out of range tag ID.'];
if ((id < 0)||(id > 0xffffffff))
return [ tag[k][1],tag[k][2],'Invalid or out of range tag ID.' ];
} else if (tkeyword === 'default') {
if (dfl !== null)
return [tag[k][1], tag[k][2], 'Duplicate tag default directive.'];
return [ tag[k][1],tag[k][2],'Duplicate tag default directive.' ];
if ((k + 1) >= tag.length)
return [tag[k][1], tag[k][2], 'Missing value for default.'];
return [ tag[k][1],tag[k][2],'Missing value for default.' ];
dfl = tag[++k][0];
} else if (tkeyword === 'flag') {
if ((k + 2) >= tag.length)
return [tag[k][1], tag[k][2], 'Missing tag flag name or bit index.'];
return [ tag[k][1],tag[k][2],'Missing tag flag name or bit index.' ];
++k;
let bits = tag[k][0].split(/[,]+/);
let mask = 0;
for (let j = 0; j < bits.length; ++j) {
for(let j=0;j<bits.length;++j) {
let b = bits[j].toLowerCase();
if (b in flags) {
mask |= flags[b];
} else {
b = _parseNum(b);
if ((b < 0) || (b > 31))
return [tag[k][1], tag[k][2], 'Bit index invalid, out of range, or references an undefined flag name.'];
if ((b < 0)||(b > 31))
return [ tag[k][1],tag[k][2],'Bit index invalid, out of range, or references an undefined flag name.' ];
mask |= (1 << b);
}
}
let flagName = tag[++k][0].toLowerCase();
if (!_isValidName(flagName))
return [tag[k][1], tag[k][2], 'Invalid or reserved flag name.'];
return [ tag[k][1],tag[k][2],'Invalid or reserved flag name.' ];
if (flagName in flags)
return [tag[k][1], tag[k][2], 'Duplicate flag name in tag definition.'];
return [ tag[k][1],tag[k][2],'Duplicate flag name in tag definition.' ];
flags[flagName] = mask;
} else if (tkeyword === 'enum') {
if ((k + 2) >= tag.length)
return [tag[k][1], tag[k][2], 'Missing tag enum name or value.'];
return [ tag[k][1],tag[k][2],'Missing tag enum name or value.' ];
++k;
let value = _parseNum(tag[k][0]);
if ((value < 0) || (value > 0xffffffff))
return [tag[k][1], tag[k][2], 'Tag enum value invalid or out of range.'];
if ((value < 0)||(value > 0xffffffff))
return [ tag[k][1],tag[k][2],'Tag enum value invalid or out of range.' ];
let enumName = tag[++k][0].toLowerCase();
if (!_isValidName(enumName))
return [tag[k][1], tag[k][2], 'Invalid or reserved tag enum name.'];
return [ tag[k][1],tag[k][2],'Invalid or reserved tag enum name.' ];
if (enumName in enums)
return [tag[k][1], tag[k][2], 'Duplicate enum name in tag definition.'];
return [ tag[k][1],tag[k][2],'Duplicate enum name in tag definition.' ];
enums[enumName] = value;
} else {
return [tag[k][1], tag[k][2], 'Unrecognized keyword in tag definition.'];
return [ tag[k][1],tag[k][2],'Unrecognized keyword in tag definition.' ];
}
}
if (id < 0)
return [tag[0][1], tag[0][2], 'Tag definition is missing a numeric ID.'];
return [ tag[0][1],tag[0][2],'Tag definition is missing a numeric ID.' ];
if (typeof dfl === 'string') {
let dfl2 = enums[dfl];
@ -828,7 +835,7 @@ function compile(src, rules, caps, tags) {
if (typeof dfl2 === 'number') {
dfl = dfl2;
} else {
dfl = Math.abs(parseInt(dfl) || 0) & 0xffffffff;
dfl = Math.abs(parseInt(dfl)||0) & 0xffffffff;
}
}
} else if (typeof dfl === 'number') {
@ -844,35 +851,35 @@ function compile(src, rules, caps, tags) {
} else if (keyword === 'cap') {
// Define capabilities
if (((i + 1) >= parsed.length) || (!Array.isArray(parsed[i + 1])) || (parsed[i + 1].length < 1) || (!Array.isArray(parsed[i + 1][0])))
return [parsed[i][1], parsed[i][2], 'Capability definition is missing name.'];
if ( ((i + 1) >= parsed.length) || (!Array.isArray(parsed[i + 1])) || (parsed[i + 1].length < 1) || (!Array.isArray(parsed[i + 1][0])) )
return [ parsed[i][1],parsed[i][2],'Capability definition is missing name.' ];
let cap = parsed[++i];
let capName = cap[0][0].toLowerCase();
if (!_isValidName(capName))
return [cap[0][1], cap[0][2], 'Invalid capability name.'];
return [ cap[0][1],cap[0][2],'Invalid capability name.' ];
if (capName in RESERVED_WORDS)
return [cap[0][1], cap[0][2], 'Capability name is a reserved word.'];
return [ cap[0][1],cap[0][2],'Capability name is a reserved word.' ];
if (capName in caps)
return [cap[0][1], cap[0][2], 'Multiple definition of capability name.'];
return [ cap[0][1],cap[0][2],'Multiple definition of capability name.' ];
let capRules = [];
let id = -1;
let dfl = false;
for (let k = 1; k < cap.length; ++k) {
for(let k=1;k<cap.length;++k) {
let dn = (typeof cap[k][0] === 'string') ? cap[k][0].toLowerCase() : null;
if (dn === 'id') {
if (id >= 0)
return [cap[k][1], cap[k][2], 'Duplicate id directive in capability definition.'];
return [ cap[k][1],cap[k][2],'Duplicate id directive in capability definition.' ];
if ((k + 1) >= cap.length)
return [cap[k][1], cap[k][2], 'Missing value for ID.'];
return [ cap[k][1],cap[k][2],'Missing value for ID.' ];
id = _parseNum(cap[++k][0]);
if ((id < 0) || (id > 0xffffffff))
return [cap[k - 1][1], cap[k - 1][2], 'Invalid or out of range capability ID.'];
for (let cn in caps) {
if ((id < 0)||(id > 0xffffffff))
return [ cap[k - 1][1],cap[k - 1][2],'Invalid or out of range capability ID.' ];
for(let cn in caps) {
if (caps[cn].id === id)
return [cap[k - 1][1], cap[k - 1][2], 'Duplicate capability ID.'];
return [ cap[k - 1][1],cap[k - 1][2],'Duplicate capability ID.' ];
}
} else if (dn === 'default') {
dfl = true;
@ -881,7 +888,7 @@ function compile(src, rules, caps, tags) {
}
}
if (id < 0)
return [cap[0][1], cap[0][2], 'Capability definition is missing a numeric ID.'];
return [ cap[0][1],cap[0][2],'Capability definition is missing a numeric ID.' ];
caps[capName] = {
'id': id,
@ -895,22 +902,22 @@ function compile(src, rules, caps, tags) {
// Pass 3: render low-level ZeroTier rules arrays for capabilities and base.
for (let capName in caps) {
for(let capName in caps) {
let r = [];
let err = _renderActions(caps[capName].rules, r, macros, caps, tags, {});
let err = _renderActions(caps[capName].rules,r,macros,caps,tags,{});
if (err !== null)
return err;
caps[capName].rules = r;
}
let err = _renderActions(baseRuleTree, rules, macros, caps, tags, {});
let err = _renderActions(baseRuleTree,rules,macros,caps,tags,{});
if (err !== null)
return err;
return null;
} catch (e) {
console.log(e.stack);
return [0, 0, 'Unexpected exception: ' + e.toString()];
return [ 0,0,'Unexpected exception: '+e.toString() ];
}
}

View file

@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 2.8)
project(zt_service)
if(WIN32)
add_definitions(-DNOMINMAX)
endif(WIN32)
set(src
OneService.cpp
)
set(headers
OneService.hpp
)
add_library(${PROJECT_NAME} STATIC ${src} ${headers})
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)

2253
attic/service/OneService.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -86,11 +86,6 @@ public:
* Allow overriding of system default routes for "full tunnel" operation?
*/
bool allowDefault;
/**
* Allow configuration of DNS for the network
*/
bool allowDNS;
};
/**

View file

@ -5,11 +5,7 @@ This is the actual implementation of ZeroTier One, a service providing connectiv
### Local Configuration File
A file called `local.conf` in the ZeroTier [home](https://github.com/zerotier/ZeroTierOne/blob/6faca86bb424d0b9643b6efa50571f73310d8276/README.md) folder contains configuration options that apply to the local node. (It does not exist unless you create it). It can be used to set up trusted paths, blacklist physical paths, set up physical path hints for certain nodes, and define trusted upstream devices (federated roots). In a large deployment it can be deployed using a tool like Puppet, Chef, SaltStack, etc. to set a uniform configuration across systems.
It's a JSON format file that can also be edited and rewritten by ZeroTier One itself, so ensure that proper JSON formatting is used. To validate your config, paste it into a website like [jsonlint.com](https://jsonlint.com), or use a tool like `jq`.
Check the output of `zerotier-cli info -j` to see if your configuration is being loaded.
A file called `local.conf` in the ZeroTier home folder contains configuration options that apply to the local node. (It does not exist unless you create it). It can be used to set up trusted paths, blacklist physical paths, set up physical path hints for certain nodes, and define trusted upstream devices (federated roots). In a large deployment it can be deployed using a tool like Puppet, Chef, SaltStack, etc. to set a uniform configuration across systems. It's a JSON format file that can also be edited and rewritten by ZeroTier One itself, so ensure that proper JSON formatting is used.
Settings available in `local.conf` (this is not valid JSON, and JSON does not allow comments):
@ -33,7 +29,6 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al
"secondaryPort": 1-65535, /* If set, override default random secondary port */
"tertiaryPort": 1-65535, /* If set, override default random tertiary port */
"portMappingEnabled": true|false, /* If true (the default), try to use uPnP or NAT-PMP to map ports */
"allowSecondaryPort": true|false /* false will also disable secondary port */
"softwareUpdate": "apply"|"download"|"disable", /* Automatically apply updates, just download, or disable built-in software updates */
"softwareUpdateChannel": "release"|"beta", /* Software update channel */
"softwareUpdateDist": true|false, /* If true, distribute software updates (only really useful to ZeroTier, Inc. itself, default is false) */
@ -143,7 +138,6 @@ Most network settings are not writable, as they are defined by the network contr
| allowManaged | boolean | Allow IP and route management | yes |
| allowGlobal | boolean | Allow IPs and routes that overlap with global IPs | yes |
| allowDefault | boolean | Allow overriding of system default route | yes |
| allowDNS | boolean | Allow configuration of DNS on network | yes |
Route objects:

View file

@ -1,12 +1,9 @@
DEL "ZeroTier One.msi"
DEL zt1_update*.exe
RMDIR /Q /S windows\Build
RMDIR /Q /S windows\x64
RMDIR /Q /S windows\ARM64
RMDIR /Q /S windows\Release
RMDIR /Q /S windows\copyutil\bin
RMDIR /Q /S windows\copyutil\obj
RMDIR /Q /S windows\WinUI\bin
RMDIR /Q /S windows\WinUI\obj
RMDIR /Q /S windows\ZeroTierOne\Release
RMDIR /Q /S windows\ZeroTierOne\x64
RMDIR /Q /S zeroidc\x64
RMDIR /Q /S zeroidc\target

View file

@ -1,7 +0,0 @@
World Definitions and Generator Code
======
This little bit of code is used to generate world updates. Ordinary users probably will never need this unless they want to test or experiment.
See mkworld.cpp for documentation. To build from this directory use 'source ./build.sh'.

View file

@ -1,3 +0,0 @@
#!/bin/bash
c++ -std=c++11 -I../.. -I../../ext -I.. -g -o mkworld ../../node/C25519.cpp ../../node/Salsa20.cpp ../../node/SHA512.cpp ../../node/Identity.cpp ../../node/Utils.cpp ../../node/InetAddress.cpp ../../osdep/OSUtils.cpp mkworld.cpp -lm

View file

@ -1,173 +0,0 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* This utility makes the World from the configuration specified below.
* It probably won't be much use to anyone outside ZeroTier, Inc. except
* for testing and experimentation purposes.
*
* If you want to make your own World you must edit this file.
*
* When run, it expects two files in the current directory:
*
* previous.c25519 - key pair to sign this world (key from previous world)
* current.c25519 - key pair whose public key should be embedded in this world
*
* If these files do not exist, they are both created with the same key pair
* and a self-signed initial World is born.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <string>
#include <vector>
#include <algorithm>
#include <node/Constants.hpp>
#include <node/World.hpp>
#include <node/C25519.hpp>
#include <node/Identity.hpp>
#include <node/InetAddress.hpp>
#include <osdep/OSUtils.hpp>
using namespace ZeroTier;
int main(int argc,char **argv)
{
std::string previous,current;
if ((!OSUtils::readFile("previous.c25519",previous))||(!OSUtils::readFile("current.c25519",current))) {
C25519::Pair np(C25519::generate());
previous = std::string();
previous.append((const char *)np.pub.data,ZT_C25519_PUBLIC_KEY_LEN);
previous.append((const char *)np.priv.data,ZT_C25519_PRIVATE_KEY_LEN);
current = previous;
OSUtils::writeFile("previous.c25519",previous);
OSUtils::writeFile("current.c25519",current);
fprintf(stderr,"INFO: created initial world keys: previous.c25519 and current.c25519 (both initially the same)" ZT_EOL_S);
}
if ((previous.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))||(current.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))) {
fprintf(stderr,"FATAL: previous.c25519 or current.c25519 empty or invalid" ZT_EOL_S);
return 1;
}
C25519::Pair previousKP;
memcpy(previousKP.pub.data,previous.data(),ZT_C25519_PUBLIC_KEY_LEN);
memcpy(previousKP.priv.data,previous.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN);
C25519::Pair currentKP;
memcpy(currentKP.pub.data,current.data(),ZT_C25519_PUBLIC_KEY_LEN);
memcpy(currentKP.priv.data,current.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN);
// =========================================================================
// EDIT BELOW HERE
std::vector<World::Root> roots;
const uint64_t id = ZT_WORLD_ID_EARTH;
const uint64_t ts = 1567191349589ULL; // August 30th, 2019
// Los Angeles
roots.push_back(World::Root());
roots.back().identity = Identity("3a46f1bf30:0:76e66fab33e28549a62ee2064d1843273c2c300ba45c3f20bef02dbad225723bb59a9bb4b13535730961aeecf5a163ace477cceb0727025b99ac14a5166a09a3");
roots.back().stableEndpoints.push_back(InetAddress("185.180.13.82/9993"));
roots.back().stableEndpoints.push_back(InetAddress("2a02:6ea0:c815::/9993"));
// Miami
roots.push_back(World::Root());
roots.back().identity = Identity("de8950a8b2:0:1b3ada8251b91b6b6fa6535b8c7e2460918f4f729abdec97d3c7f3796868fb02f0de0b0ee554b2d59fc3524743eebfcf5315e790ed6d92db5bd10c28c09b40ef");
roots.back().stableEndpoints.push_back(InetAddress("207.246.73.245/443"));
roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:9002:5cb:ec4:7aff:fe8f:69d9/443"));
// Tokyo
roots.push_back(World::Root());
roots.back().identity = Identity("34e0a5e174:0:93efb50934788f856d5cfb9ca5be88e85b40965586b75befac900df77352c145a1ba7007569d37c77bfe52c0999f3bdc67a47a4a6000b720a883ce47aa2fb7f8");
roots.back().stableEndpoints.push_back(InetAddress("147.75.92.2/443"));
roots.back().stableEndpoints.push_back(InetAddress("2604:1380:3000:7100::1/443"));
// Amsterdam
roots.push_back(World::Root());
roots.back().identity = Identity("992fcf1db7:0:206ed59350b31916f749a1f85dffb3a8787dcbf83b8c6e9448d4e3ea0e3369301be716c3609344a9d1533850fb4460c50af43322bcfc8e13d3301a1f1003ceb6");
roots.back().stableEndpoints.push_back(InetAddress("195.181.173.159/443"));
roots.back().stableEndpoints.push_back(InetAddress("2a02:6ea0:c024::/443"));
// Alice
//roots.push_back(World::Root());
//roots.back().identity = Identity("9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e");
//roots.back().stableEndpoints.push_back(InetAddress("188.166.94.177/9993")); // Amsterdam
//roots.back().stableEndpoints.push_back(InetAddress("2a03:b0c0:2:d0::7d:1/9993")); // Amsterdam
//roots.back().stableEndpoints.push_back(InetAddress("154.66.197.33/9993")); // Johannesburg
//roots.back().stableEndpoints.push_back(InetAddress("2c0f:f850:154:197::33/9993")); // Johannesburg
//roots.back().stableEndpoints.push_back(InetAddress("159.203.97.171/9993")); // New York
//roots.back().stableEndpoints.push_back(InetAddress("2604:a880:800:a1::54:6001/9993")); // New York
//roots.back().stableEndpoints.push_back(InetAddress("131.255.6.16/9993")); // Buenos Aires
//roots.back().stableEndpoints.push_back(InetAddress("2803:eb80:0:e::2/9993")); // Buenos Aires
//roots.back().stableEndpoints.push_back(InetAddress("107.170.197.14/9993")); // San Francisco
//roots.back().stableEndpoints.push_back(InetAddress("2604:a880:1:20::200:e001/9993")); // San Francisco
//roots.back().stableEndpoints.push_back(InetAddress("128.199.197.217/9993")); // Singapore
//roots.back().stableEndpoints.push_back(InetAddress("2400:6180:0:d0::b7:4001/9993")); // Singapore
// Bob
//roots.push_back(World::Root());
//roots.back().identity = Identity("8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c");
//roots.back().stableEndpoints.push_back(InetAddress("45.32.198.130/9993")); // Dallas
//roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:6400:81c3:5400:00ff:fe18:1d61/9993")); // Dallas
//roots.back().stableEndpoints.push_back(InetAddress("46.101.160.249/9993")); // Frankfurt
//roots.back().stableEndpoints.push_back(InetAddress("2a03:b0c0:3:d0::6a:3001/9993")); // Frankfurt
//roots.back().stableEndpoints.push_back(InetAddress("107.191.46.210/9993")); // Paris
//roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:6800:83a4::64/9993")); // Paris
//roots.back().stableEndpoints.push_back(InetAddress("45.32.246.179/9993")); // Sydney
//roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:5800:8bf8:5400:ff:fe15:b39a/9993")); // Sydney
//roots.back().stableEndpoints.push_back(InetAddress("45.32.248.87/9993")); // Tokyo
//roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:7000:9bc9:5400:00ff:fe15:c4f5/9993")); // Tokyo
//roots.back().stableEndpoints.push_back(InetAddress("159.203.2.154/9993")); // Toronto
//roots.back().stableEndpoints.push_back(InetAddress("2604:a880:cad:d0::26:7001/9993")); // Toronto
// END WORLD DEFINITION
// =========================================================================
fprintf(stderr,"INFO: generating and signing id==%llu ts==%llu" ZT_EOL_S,(unsigned long long)id,(unsigned long long)ts);
World nw = World::make(World::TYPE_PLANET,id,ts,currentKP.pub,roots,previousKP);
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> outtmp;
nw.serialize(outtmp,false);
World testw;
testw.deserialize(outtmp,0);
if (testw != nw) {
fprintf(stderr,"FATAL: serialization test failed!" ZT_EOL_S);
return 1;
}
OSUtils::writeFile("world.bin",std::string((const char *)outtmp.data(),outtmp.size()));
fprintf(stderr,"INFO: world.bin written with %u bytes of binary world data." ZT_EOL_S,outtmp.size());
fprintf(stdout,ZT_EOL_S);
fprintf(stdout,"#define ZT_DEFAULT_WORLD_LENGTH %u" ZT_EOL_S,outtmp.size());
fprintf(stdout,"static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {");
for(unsigned int i=0;i<outtmp.size();++i) {
const unsigned char *d = (const unsigned char *)outtmp.data();
if (i > 0)
fprintf(stdout,",");
fprintf(stdout,"0x%.2x",(unsigned int)d[i]);
}
fprintf(stdout,"};" ZT_EOL_S);
return 0;
}

Binary file not shown.

View file

@ -1,3 +0,0 @@
#define ZT_DEFAULT_WORLD_LENGTH 732
static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x6b,0xd4,0x16,0x08,0xc1,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x16,0x93,0xf4,0xe5,0xbd,0x20,0xda,0x10,0xad,0xc7,0x05,0xf4,0x99,0xfe,0x04,0x08,0x9b,0xe0,0x9e,0x77,0x1d,0x9f,0x47,0x16,0xaa,0x92,0x4f,0x10,0x16,0x3d,0xc7,0xec,0xd3,0x90,0x9e,0xd1,0x74,0xfc,0xb3,0xb5,0x07,0x9c,0x4d,0x95,0xc5,0x17,0x8b,0x3d,0x0b,0x60,0x76,0xe8,0x51,0xbb,0xb6,0x3d,0x74,0xb5,0x21,0x83,0x7b,0x95,0x1d,0x02,0x9b,0xcd,0xaf,0x5c,0x3e,0x96,0xdf,0x37,0x2c,0x56,0x6d,0xfa,0x75,0x0f,0xda,0x55,0x85,0x13,0xf4,0x76,0x1a,0x66,0x4d,0x3b,0x8d,0xcf,0x12,0xc9,0x34,0xb9,0x0d,0x61,0x03,0x3a,0x46,0xf1,0xbf,0x30,0x00,0x76,0xe6,0x6f,0xab,0x33,0xe2,0x85,0x49,0xa6,0x2e,0xe2,0x06,0x4d,0x18,0x43,0x27,0x3c,0x2c,0x30,0x0b,0xa4,0x5c,0x3f,0x20,0xbe,0xf0,0x2d,0xba,0xd2,0x25,0x72,0x3b,0xb5,0x9a,0x9b,0xb4,0xb1,0x35,0x35,0x73,0x09,0x61,0xae,0xec,0xf5,0xa1,0x63,0xac,0xe4,0x77,0xcc,0xeb,0x07,0x27,0x02,0x5b,0x99,0xac,0x14,0xa5,0x16,0x6a,0x09,0xa3,0x00,0x02,0x04,0xb9,0xb4,0x0d,0x52,0x27,0x09,0x06,0x2a,0x02,0x6e,0xa0,0xc8,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x09,0x9d,0x21,0x90,0x39,0xf3,0x00,0x01,0xf0,0x92,0x2a,0x98,0xe3,0xb3,0x4e,0xbc,0xbf,0xf3,0x33,0x26,0x9d,0xc2,0x65,0xd7,0xa0,0x20,0xaa,0xb6,0x9d,0x72,0xbe,0x4d,0x4a,0xcc,0x9c,0x8c,0x92,0x94,0x78,0x57,0x71,0x25,0x6c,0xd1,0xd9,0x42,0xa9,0x0d,0x1b,0xd1,0xd2,0xdc,0xa3,0xea,0x84,0xef,0x7d,0x85,0xaf,0xe6,0x61,0x1f,0xb4,0x3f,0xf0,0xb7,0x41,0x26,0xd9,0x0a,0x6e,0x00,0x0c,0x04,0xbc,0xa6,0x5e,0xb1,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x7d,0x00,0x01,0x27,0x09,0x04,0x9a,0x42,0xc5,0x21,0x27,0x09,0x06,0x2c,0x0f,0xf8,0x50,0x01,0x54,0x01,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x27,0x09,0x04,0x9f,0xcb,0x61,0xab,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x54,0x60,0x01,0x27,0x09,0x04,0x83,0xff,0x06,0x10,0x27,0x09,0x06,0x28,0x03,0xeb,0x80,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27,0x09,0x04,0x6b,0xaa,0xc5,0x0e,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x02,0x00,0xe0,0x01,0x27,0x09,0x04,0x80,0xc7,0xc5,0xd9,0x27,0x09,0x06,0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xb7,0x40,0x01,0x27,0x09,0x88,0x41,0x40,0x8a,0x2e,0x00,0xbb,0x1d,0x31,0xf2,0xc3,0x23,0xe2,0x64,0xe9,0xe6,0x41,0x72,0xc1,0xa7,0x4f,0x77,0x89,0x95,0x55,0xed,0x10,0x75,0x1c,0xd5,0x6e,0x86,0x40,0x5c,0xde,0x11,0x8d,0x02,0xdf,0xfe,0x55,0x5d,0x46,0x2c,0xcf,0x6a,0x85,0xb5,0x63,0x1c,0x12,0x35,0x0c,0x8d,0x5d,0xc4,0x09,0xba,0x10,0xb9,0x02,0x5d,0x0f,0x44,0x5c,0xf4,0x49,0xd9,0x2b,0x1c,0x00,0x0c,0x04,0x2d,0x20,0xc6,0x82,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x64,0x00,0x81,0xc3,0x54,0x00,0x00,0xff,0xfe,0x18,0x1d,0x61,0x27,0x09,0x04,0x2e,0x65,0xa0,0xf9,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x6a,0x30,0x01,0x27,0x09,0x04,0x6b,0xbf,0x2e,0xd2,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x68,0x00,0x83,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x27,0x09,0x04,0x2d,0x20,0xf6,0xb3,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x58,0x00,0x8b,0xf8,0x54,0x00,0x00,0xff,0xfe,0x15,0xb3,0x9a,0x27,0x09,0x04,0x2d,0x20,0xf8,0x57,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x70,0x00,0x9b,0xc9,0x54,0x00,0x00,0xff,0xfe,0x15,0xc4,0xf5,0x27,0x09,0x04,0x9f,0xcb,0x02,0x9a,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x26,0x70,0x01,0x27,0x09};

View file

@ -1,13 +0,0 @@
ARG ZT_NAME
FROM 084037375216.dkr.ecr.us-east-2.amazonaws.com/${ZT_NAME}-builder as builder
WORKDIR /work/build
COPY . .
RUN pwd
RUN ls -la .
RUN make clean
RUN make debian
RUN ls -ls /work
FROM scratch AS export
ARG ZT_NAME
COPY --from=builder /work/*.deb ./${ZT_NAME}/

View file

@ -1,36 +0,0 @@
ARG DOCKER_ARCH
FROM --platform=linux/${DOCKER_ARCH} alpine:edge AS builder
RUN apk update
RUN apk add curl
RUN apk add bash
RUN apk add file
RUN apk add rust
RUN apk add cargo
RUN apk add make
RUN apk add cmake
RUN apk add clang
RUN apk add openssl-dev
RUN apk add linux-headers
RUN apk add build-base
RUN apk add openssl-libs-static
COPY . .
RUN ZT_STATIC=1 make
RUN ls -la
ARG DOCKER_ARCH
FROM --platform=linux/${DOCKER_ARCH} centos:6 AS stage
WORKDIR /root/rpmbuild/BUILD
COPY . .
COPY --from=builder zerotier-* ./
RUN curl https://gist.githubusercontent.com/someara/b363002ba6e57b3c474dd027d4daef85/raw/4ac5534139752fc92fbe1a53599a390214f69615/el6%2520vault --output /etc/yum.repos.d/CentOS-Base.repo
RUN uname -a
RUN yum -y install make gcc rpm-build
RUN pwd
RUN ls -la
RUN make redhat
FROM scratch AS export
ARG ZT_NAME
COPY --from=stage /root/rpmbuild/RPMS/*/*.rpm ./${ZT_NAME}/

View file

@ -1,9 +0,0 @@
ARG ZT_NAME
FROM 084037375216.dkr.ecr.us-east-2.amazonaws.com/${ZT_NAME}-builder as builder
WORKDIR /root/rpmbuild/BUILD
COPY . .
RUN make redhat
FROM scratch AS export
ARG ZT_NAME
COPY --from=builder /root/rpmbuild/RPMS/*/*.rpm ./${ZT_NAME}/

View file

@ -1,13 +0,0 @@
ARG ZT_NAME
FROM 084037375216.dkr.ecr.us-east-2.amazonaws.com/${ZT_NAME}-tester
ARG BASEURL
ARG VERSION
ARG DEB_ARCH
ARG ZT_NAME
ARG DISTRO
RUN curl -s http://${BASEURL}/key.gpg -o /etc/apt/trusted.gpg.d/zerotier.gpg
RUN echo "deb [arch=${DEB_ARCH} signed-by=/etc/apt/trusted.gpg.d/zerotier.gpg] http://${BASEURL}/${DISTRO} ${ZT_NAME} main" > /etc/apt/sources.list.d/zerotier.list
RUN apt-get -qq update
RUN apt-get -qq install zerotier-one=${VERSION}
RUN ldd $(which zerotier-cli)

View file

@ -1,4 +0,0 @@
ARG DOCKER_ARCH
FROM --platform=linux/${DOCKER_ARCH} centos:6
RUN printf "[C6.10-base]\nname=CentOS-6.10 - Base\nbaseurl=http://vault.epel.cloud/6.10/os/\$basearch/\ngpgcheck=1\ngpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6\nenabled=1\nmetadata_expire=never\n" > /etc/yum.repos.d/CentOS-Base.repo
RUN yum -y install curl

View file

@ -1,17 +0,0 @@
ARG ZT_NAME
FROM 084037375216.dkr.ecr.us-east-2.amazonaws.com/${ZT_NAME}-tester
ARG BASEURL
ARG VERSION
ARG DEB_ARCH
ARG ZT_NAME
ARG DISTRO
ARG DNF_ARCH
RUN curl -s http://${BASEURL}/key.asc -o /etc/pki/rpm-gpg/RPM-GPG-KEY-zerotier
RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-zerotier
RUN rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n'
RUN printf "[zerotier]\nname=zerotier\nbaseurl=http://${BASEURL}/${DISTRO}/${ZT_NAME}/$basearch/\nenabled=1\ngpgcheck=1\ngpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-zerotier\n" > /etc/yum.repos.d/zerotier.repo
# RUN yum -v repolist
RUN setarch ${DNF_ARCH} yum -y install zerotier-one-${VERSION}
RUN file $(which zerotier-cli)
RUN ldd $(which zerotier-cli)

View file

@ -1,49 +0,0 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
ZT_NAME="$1" ; shift
DISTRO="$1" ; shift
ZT_ISA="$1" ; shift
VERSION="$1" ; shift
BUILD_EVENT="$1" ; shift
source "$(dirname $0)/lib.sh"
if [ -f "ci/Dockerfile-build.${ZT_NAME}" ]; then
DOCKERFILE="ci/Dockerfile-build.${ZT_NAME}"
else
DOCKERFILE="ci/Dockerfile-build.${PKGFMT}"
fi
echo "#~~~~~~~~~~~~~~~~~~~~"
echo "$0 variables:"
echo "nproc: $(nproc)"
echo "ZT_NAME: ${ZT_NAME}"
echo "DISTRO: ${DISTRO}"
echo "ZT_ISA: ${ZT_ISA}"
echo "VERSION: ${VERSION}"
echo "BUILD_EVENT: ${BUILD_EVENT}"
echo "DOCKER_ARCH: ${DOCKER_ARCH}"
echo "DNF_ARCH: ${DNF_ARCH}"
echo "RUST_TRIPLET: ${RUST_TRIPLET}"
echo "PKGFMT: ${PKGFMT}"
echo "PWD: ${PWD}"
echo "DOCKERFILE: ${DOCKERFILE}"
echo "#~~~~~~~~~~~~~~~~~~~~"
make munge_rpm zerotier-one.spec VERSION=${VERSION}
make munge_deb debian/changelog VERSION=${VERSION}
docker buildx build \
--no-cache=true \
--build-arg ZT_NAME="${ZT_NAME}" \
--build-arg RUST_TRIPLET="${RUST_TRIPLET}" \
--build-arg DOCKER_ARCH="${DOCKER_ARCH}" \
--build-arg DNF_ARCH="${DNF_ARCH}" \
--platform linux/${DOCKER_ARCH} \
-f ${DOCKERFILE} \
-t build \
. \
--output type=local,dest=. \
--target export

View file

@ -1,63 +0,0 @@
case $ZT_NAME in
el*|fc*|amzn*)
export PKGFMT=rpm
;;
*)
export PKGFMT=deb
esac
case $ZT_ISA in
386)
export DOCKER_ARCH=386
export DEB_ARCH=i386
export DNF_ARCH=i686
export RUST_TRIPLET=i686-unknown-linux-gnu
;;
amd64)
export DOCKER_ARCH=amd64
export DEB_ARCH=amd64
export DNF_ARCH=x86_64
export RUST_TRIPLET=x86_64-unknown-linux-gnu
;;
armv7)
export DOCKER_ARCH=arm/v7
export DNF_ARCH=armv7
export DEB_ARCH=armhf
export RUST_TRIPLET=armv7-unknown-linux-gnueabihf
;;
arm64)
export DOCKER_ARCH=arm64/v8
export DEB_ARCH=arm64
export DNF_ARCH=linux64
export RUST_TRIPLET=aarch64-unknown-linux-gnu
;;
riscv64)
export DOCKER_ARCH=riscv64
export DEB_ARCH=riscv64
export DNF_ARCH=riscv64
export RUST_TRIPLET=riscv64gc-unknown-linux-gnu
;;
ppc64le)
export DOCKER_ARCH=ppc64le
export DEB_ARCH=ppc64el
export DNF_ARCH=ppc64le
export RUST_TRIPLET=powerpc64le-unknown-linux-gnu
;;
mips64le)
export DOCKER_ARCH=mips64le
export DEB_ARCH=mips64le
export DNF_ARCH=mips64le
export RUST_TRIPLET=mips64el-unknown-linux-gnuabi64
;;
s390x)
export DOCKER_ARCH=s390x
export DEB_ARCH=s390x
export DNF_ARCH=s390x
export RUST_TRIPLET=s390x-unknown-linux-gnu
;;
*)
echo "ERROR: could not determine architecture settings. PLEASE FIX ME"
exit 1
;;
esac

View file

@ -1,37 +0,0 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
export FILE=$1
export VERSION=$2
export NAME=$3
export MESSAGE=$4
export DATE=$(date "+%a, %d %b %Y %T %z")
# export DATE=$(date "+%a %b %d %Y")
set +e
grep --version | grep BSD &> /dev/null
if [ $? == 0 ]; then BSDGREP=true ; else BSDGREP=false ; fi
set -e
# echo "#~~~~~~~~~~~~~~~~~~~~"
# echo "$0 variables:"
# echo "VERSION: ${VERSION}"
# echo "NAME: ${NAME}"
# echo "MESSAGE: ${MESSAGE}"
# echo "DATE: ${DATE}"
# echo "BSDGREP: ${BSDGREP}"
# echo "#~~~~~~~~~~~~~~~~~~~~"
# echo
if $BSDGREP ; then
sed -i '' s/^Version:.*/"Version: ${VERSION}"/ ${FILE}
else
sed -i s/^Version:.*/"Version: ${VERSION}"/ ${FILE}
fi
awk -v version=${VERSION} -v date=${DATE} -v name=${NAME} -v message=${MESSAGE} \
'BEGIN{print "zerotier-one (" version ") stable; urgency=medium\n\n * " message "\n\n -- " name " " date "\n" }{ print }' \
${FILE} > ${FILE}.new
mv ${FILE}.new ${FILE}

View file

@ -1,36 +0,0 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
export FILE=$1
export VERSION=$2
export NAME=$3
export MESSAGE=$4
export DATE=$(date "+%a %b %d %Y")
set +e
grep --version | grep BSD &> /dev/null
if [ $? == 0 ]; then BSDGREP=true ; else BSDGREP=false ; fi
set -e
# echo "#~~~~~~~~~~~~~~~~~~~~"
# echo "$0 variables:"
# echo "VERSION: ${VERSION}"
# echo "NAME: ${NAME}"
# echo "MESSAGE: ${MESSAGE}"
# echo "DATE: ${DATE}"
# echo "BSDGREP: ${BSDGREP}"
# echo "#~~~~~~~~~~~~~~~~~~~~"
# echo
if $BSDGREP ; then
sed -i '' s/^Version:.*/"Version: ${VERSION}"/ ${FILE}
else
sed -i s/^Version:.*/"Version: ${VERSION}"/ ${FILE}
fi
awk -v version=${VERSION} -v date=${DATE} -v name=${NAME} -v message=${MESSAGE} \
'FNR==NR{ if (/%changelog/) p=NR; next} 1; FNR==p{ print "* " date " " name " - " version "\n- " message "\n" }' \
${FILE} ${FILE} > ${FILE}.new
mv ${FILE}.new ${FILE}

View file

@ -1,38 +0,0 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
ZT_NAME="$1" ; shift
DISTRO="$1" ; shift
ZT_ISA="$1" ; shift
VERSION="$1" ; shift
BUILD_EVENT="$1" ; shift
source "$(dirname $0)/lib.sh"
if [ ${BUILD_EVENT} == "tag" ]; then
CHANNEL="zerotier-releases"
else
CHANNEL="zerotier-builds"
fi
function publish_rpm {
mkdir -p /${CHANNEL}/${DISTRO}
ls -la /${CHANNEL}
ls -la .
cp -a ${ZT_NAME} /${CHANNEL}/${DISTRO}
}
function publish_deb {
mkdir -p /${CHANNEL}/${DISTRO}/pool/dists/${ZT_NAME}/main
cp -a ${ZT_NAME}/* /${CHANNEL}/${DISTRO}/pool/dists/${ZT_NAME}/main
}
case ${PKGFMT} in
"rpm")
publish_rpm
;;
"deb")
publish_deb
esac

View file

@ -1,55 +0,0 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
ZT_NAME="$1" ; shift
DISTRO="$1" ; shift
ZT_ISA="$1" ; shift
VERSION="$1" ; shift
BUILD_EVENT="$1" ; shift
source "$(dirname $0)/lib.sh"
if [ -f "ci/Dockerfile-test.${ZT_NAME}" ]; then
DOCKERFILE="ci/Dockerfile-test.${ZT_NAME}"
else
DOCKERFILE="ci/Dockerfile-test.${PKGFMT}"
fi
if [ ${BUILD_EVENT} == "tag" ]; then
BASEURL="zerotier-releases.home.arpa"
else
BASEURL="zerotier-builds.home.arpa"
fi
echo "#~~~~~~~~~~~~~~~~~~~~"
echo "$0 variables:"
echo "nproc: $(nproc)"
echo "ZT_NAME: ${ZT_NAME}"
echo "DISTRO: ${DISTRO}"
echo "ZT_ISA: ${ZT_ISA}"
echo "VERSION: ${VERSION}"
echo "BUILD_EVENT: ${BUILD_EVENT}"
echo "DOCKER_ARCH: ${DOCKER_ARCH}"
echo "DNF_ARCH: ${DNF_ARCH}"
echo "RUST_TRIPLET: ${RUST_TRIPLET}"
echo "PKGFMT: ${PKGFMT}"
echo "PWD: ${PWD}"
echo "DOCKERFILE: ${DOCKERFILE}"
echo "#~~~~~~~~~~~~~~~~~~~~"
# docker pull -q --platform="linux/${DOCKER_ARCH}" 084037375216.dkr.ecr.us-east-2.amazonaws.com/${ZT_NAME}-tester
docker buildx build \
--build-arg BASEURL="${BASEURL}" \
--build-arg ZT_NAME="${ZT_NAME}" \
--build-arg DISTRO="${DISTRO}" \
--build-arg DEB_ARCH="${DEB_ARCH}" \
--build-arg DNF_ARCH="${DNF_ARCH}" \
--build-arg VERSION="${VERSION}" \
--build-arg DOCKER_ARCH="${DOCKER_ARCH}" \
--platform "linux/${DOCKER_ARCH}" \
--no-cache \
-f ${DOCKERFILE} \
-t test \
.

36
controller/CMakeLists.txt Normal file
View file

@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 2.8)
project(zt_controller)
if(WIN32)
add_definitions(-DNOMINMAX)
endif(WIN32)
set(ctl_src
DB.cpp
DBMirrorSet.cpp
EmbeddedNetworkController.cpp
FileDB.cpp
LFDB.cpp
RabbitMQ.cpp
)
set(ctl_hdr
DB.hpp
DBMirrorSet.hpp
EmbeddedNetworkController.hpp
FileDB.hpp
LFDB.hpp
RabbitMQ.hpp
)
if(BUILD_CENTRAL_CONTROLLER)
add_definitions(-DZT_CONTROLLER_USE_LIBPQ)
include_directories("../ext/librabbitmq/librabbitmq" ${PostgreSQL_INCLUDE_DIRS})
set(ctl_src ${ctl_src} PostgreSQL.cpp)
set(ctl_hdr ${ctl_hdr} PostgreSQL.hpp)
endif(BUILD_CENTRAL_CONTROLLER)
add_library(${PROJECT_NAME} STATIC ${ctl_src} ${ctl_hdr})
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)

View file

@ -1,175 +0,0 @@
/*
* Copyright (c)2021 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_CONNECTION_POOL_H_
#define ZT_CONNECTION_POOL_H_
#ifndef _DEBUG
#define _DEBUG(x)
#endif
#include "../node/Metrics.hpp"
#include <deque>
#include <set>
#include <memory>
#include <mutex>
#include <exception>
#include <string>
namespace ZeroTier {
struct ConnectionUnavailable : std::exception {
char const* what() const throw() {
return "Unable to allocate connection";
};
};
class Connection {
public:
virtual ~Connection() {};
};
class ConnectionFactory {
public:
virtual ~ConnectionFactory() {};
virtual std::shared_ptr<Connection> create()=0;
};
struct ConnectionPoolStats {
size_t pool_size;
size_t borrowed_size;
};
template<class T>
class ConnectionPool {
public:
ConnectionPool(size_t max_pool_size, size_t min_pool_size, std::shared_ptr<ConnectionFactory> factory)
: m_maxPoolSize(max_pool_size)
, m_minPoolSize(min_pool_size)
, m_factory(factory)
{
Metrics::max_pool_size += max_pool_size;
Metrics::min_pool_size += min_pool_size;
while(m_pool.size() < m_minPoolSize){
m_pool.push_back(m_factory->create());
Metrics::pool_avail++;
}
};
ConnectionPoolStats get_stats() {
std::unique_lock<std::mutex> lock(m_poolMutex);
ConnectionPoolStats stats;
stats.pool_size = m_pool.size();
stats.borrowed_size = m_borrowed.size();
return stats;
};
~ConnectionPool() {
};
/**
* Borrow
*
* Borrow a connection for temporary use
*
* When done, either (a) call unborrow() to return it, or (b) (if it's bad) just let it go out of scope. This will cause it to automatically be replaced.
* @retval a shared_ptr to the connection object
*/
std::shared_ptr<T> borrow() {
std::unique_lock<std::mutex> l(m_poolMutex);
while((m_pool.size() + m_borrowed.size()) < m_minPoolSize) {
std::shared_ptr<Connection> conn = m_factory->create();
m_pool.push_back(conn);
Metrics::pool_avail++;
}
if(m_pool.size()==0){
if ((m_pool.size() + m_borrowed.size()) < m_maxPoolSize) {
try {
std::shared_ptr<Connection> conn = m_factory->create();
m_borrowed.insert(conn);
Metrics::pool_in_use++;
return std::static_pointer_cast<T>(conn);
} catch (std::exception &e) {
Metrics::pool_errors++;
throw ConnectionUnavailable();
}
} else {
for(auto it = m_borrowed.begin(); it != m_borrowed.end(); ++it){
if((*it).unique()) {
// This connection has been abandoned! Destroy it and create a new connection
try {
// If we are able to create a new connection, return it
_DEBUG("Creating new connection to replace discarded connection");
std::shared_ptr<Connection> conn = m_factory->create();
m_borrowed.erase(it);
m_borrowed.insert(conn);
return std::static_pointer_cast<T>(conn);
} catch(std::exception& e) {
// Error creating a replacement connection
Metrics::pool_errors++;
throw ConnectionUnavailable();
}
}
}
// Nothing available
Metrics::pool_errors++;
throw ConnectionUnavailable();
}
}
// Take one off the front
std::shared_ptr<Connection> conn = m_pool.front();
m_pool.pop_front();
Metrics::pool_avail--;
// Add it to the borrowed list
m_borrowed.insert(conn);
Metrics::pool_in_use++;
return std::static_pointer_cast<T>(conn);
};
/**
* Unborrow a connection
*
* Only call this if you are returning a working connection. If the connection was bad, just let it go out of scope (so the connection manager can replace it).
* @param the connection
*/
void unborrow(std::shared_ptr<T> conn) {
// Lock
std::unique_lock<std::mutex> lock(m_poolMutex);
m_borrowed.erase(conn);
Metrics::pool_in_use--;
if ((m_pool.size() + m_borrowed.size()) < m_maxPoolSize) {
Metrics::pool_avail++;
m_pool.push_back(conn);
}
};
protected:
size_t m_maxPoolSize;
size_t m_minPoolSize;
std::shared_ptr<ConnectionFactory> m_factory;
std::deque<std::shared_ptr<Connection> > m_pool;
std::set<std::shared_ptr<Connection> > m_borrowed;
std::mutex m_poolMutex;
};
}
#endif

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -13,7 +13,6 @@
#include "DB.hpp"
#include "EmbeddedNetworkController.hpp"
#include "../node/Metrics.hpp"
#include <chrono>
#include <algorithm>
@ -49,18 +48,12 @@ void DB::initNetwork(nlohmann::json &network)
{ "type","ACTION_ACCEPT" }
}};
}
if (!network.count("dns")) network["dns"] = nlohmann::json::array();
if (!network.count("ssoEnabled")) network["ssoEnabled"] = false;
if (!network.count("clientId")) network["clientId"] = "";
if (!network.count("authorizationEndpoint")) network["authorizationEndpoint"] = "";
network["objtype"] = "network";
}
void DB::initMember(nlohmann::json &member)
{
if (!member.count("authorized")) member["authorized"] = false;
if (!member.count("ssoExempt")) member["ssoExempt"] = false;
if (!member.count("ipAssignments")) member["ipAssignments"] = nlohmann::json::array();
if (!member.count("activeBridge")) member["activeBridge"] = false;
if (!member.count("tags")) member["tags"] = nlohmann::json::array();
@ -72,7 +65,6 @@ void DB::initMember(nlohmann::json &member)
if (!member.count("lastAuthorizedTime")) member["lastAuthorizedTime"] = 0ULL;
if (!member.count("lastAuthorizedCredentialType")) member["lastAuthorizedCredentialType"] = nlohmann::json();
if (!member.count("lastAuthorizedCredential")) member["lastAuthorizedCredential"] = nlohmann::json();
if (!member.count("authenticationExpiryTime")) member["authenticationExpiryTime"] = 0LL;
if (!member.count("vMajor")) member["vMajor"] = -1;
if (!member.count("vMinor")) member["vMinor"] = -1;
if (!member.count("vRev")) member["vRev"] = -1;
@ -98,8 +90,6 @@ void DB::cleanMember(nlohmann::json &member)
member.erase("recentLog");
member.erase("lastModified");
member.erase("lastRequestMetaData");
member.erase("authenticationURL"); // computed
member.erase("authenticationClientID"); // computed
}
DB::DB() {}
@ -108,17 +98,16 @@ DB::~DB() {}
bool DB::get(const uint64_t networkId,nlohmann::json &network)
{
waitForReady();
Metrics::db_get_network++;
std::shared_ptr<_Network> nw;
{
std::shared_lock<std::shared_mutex> l(_networks_l);
std::lock_guard<std::mutex> l(_networks_l);
auto nwi = _networks.find(networkId);
if (nwi == _networks.end())
return false;
nw = nwi->second;
}
{
std::shared_lock<std::shared_mutex> l2(nw->lock);
std::lock_guard<std::mutex> l2(nw->lock);
network = nw->config;
}
return true;
@ -127,17 +116,16 @@ bool DB::get(const uint64_t networkId,nlohmann::json &network)
bool DB::get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member)
{
waitForReady();
Metrics::db_get_network_and_member++;
std::shared_ptr<_Network> nw;
{
std::shared_lock<std::shared_mutex> l(_networks_l);
std::lock_guard<std::mutex> l(_networks_l);
auto nwi = _networks.find(networkId);
if (nwi == _networks.end())
return false;
nw = nwi->second;
}
{
std::shared_lock<std::shared_mutex> l2(nw->lock);
std::lock_guard<std::mutex> l2(nw->lock);
network = nw->config;
auto m = nw->members.find(memberId);
if (m == nw->members.end())
@ -150,17 +138,16 @@ bool DB::get(const uint64_t networkId,nlohmann::json &network,const uint64_t mem
bool DB::get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member,NetworkSummaryInfo &info)
{
waitForReady();
Metrics::db_get_network_and_member_and_summary++;
std::shared_ptr<_Network> nw;
{
std::shared_lock<std::shared_mutex> l(_networks_l);
std::lock_guard<std::mutex> l(_networks_l);
auto nwi = _networks.find(networkId);
if (nwi == _networks.end())
return false;
nw = nwi->second;
}
{
std::shared_lock<std::shared_mutex> l2(nw->lock);
std::lock_guard<std::mutex> l2(nw->lock);
network = nw->config;
_fillSummaryInfo(nw,info);
auto m = nw->members.find(memberId);
@ -174,37 +161,33 @@ bool DB::get(const uint64_t networkId,nlohmann::json &network,const uint64_t mem
bool DB::get(const uint64_t networkId,nlohmann::json &network,std::vector<nlohmann::json> &members)
{
waitForReady();
Metrics::db_get_member_list++;
std::shared_ptr<_Network> nw;
{
std::shared_lock<std::shared_mutex> l(_networks_l);
std::lock_guard<std::mutex> l(_networks_l);
auto nwi = _networks.find(networkId);
if (nwi == _networks.end())
return false;
nw = nwi->second;
}
{
std::shared_lock<std::shared_mutex> l2(nw->lock);
std::lock_guard<std::mutex> l2(nw->lock);
network = nw->config;
for(auto m=nw->members.begin();m!=nw->members.end();++m) {
for(auto m=nw->members.begin();m!=nw->members.end();++m)
members.push_back(m->second);
}
}
return true;
}
void DB::networks(std::set<uint64_t> &networks)
{
waitForReady();
Metrics::db_get_network_list++;
std::shared_lock<std::shared_mutex> l(_networks_l);
std::lock_guard<std::mutex> l(_networks_l);
for(auto n=_networks.begin();n!=_networks.end();++n)
networks.insert(n->first);
}
void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool notifyListeners)
{
Metrics::db_member_change++;
uint64_t memberId = 0;
uint64_t networkId = 0;
bool isAuth = false;
@ -216,21 +199,18 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
networkId = OSUtils::jsonIntHex(old["nwid"],0ULL);
if ((memberId)&&(networkId)) {
{
std::unique_lock<std::shared_mutex> l(_networks_l);
std::lock_guard<std::mutex> l(_networks_l);
auto nw2 = _networks.find(networkId);
if (nw2 != _networks.end()) {
if (nw2 != _networks.end())
nw = nw2->second;
}
}
if (nw) {
std::unique_lock<std::shared_mutex> l(nw->lock);
if (OSUtils::jsonBool(old["activeBridge"],false)) {
std::lock_guard<std::mutex> l(nw->lock);
if (OSUtils::jsonBool(old["activeBridge"],false))
nw->activeBridgeMembers.erase(memberId);
}
wasAuth = OSUtils::jsonBool(old["authorized"],false);
if (wasAuth) {
if (wasAuth)
nw->authorizedMembers.erase(memberId);
}
json &ips = old["ipAssignments"];
if (ips.is_array()) {
for(unsigned long i=0;i<ips.size();++i) {
@ -253,7 +233,7 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
networkId = OSUtils::jsonIntHex(memberConfig["nwid"],0ULL);
if ((!memberId)||(!networkId))
return;
std::unique_lock<std::shared_mutex> l(_networks_l);
std::lock_guard<std::mutex> l(_networks_l);
std::shared_ptr<_Network> &nw2 = _networks[networkId];
if (!nw2)
nw2.reset(new _Network);
@ -261,18 +241,15 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
}
{
std::unique_lock<std::shared_mutex> l(nw->lock);
std::lock_guard<std::mutex> l(nw->lock);
nw->members[memberId] = memberConfig;
if (OSUtils::jsonBool(memberConfig["activeBridge"],false)) {
if (OSUtils::jsonBool(memberConfig["activeBridge"],false))
nw->activeBridgeMembers.insert(memberId);
}
isAuth = OSUtils::jsonBool(memberConfig["authorized"],false);
if (isAuth) {
Metrics::member_auths++;
if (isAuth)
nw->authorizedMembers.insert(memberId);
}
json &ips = memberConfig["ipAssignments"];
if (ips.is_array()) {
for(unsigned long i=0;i<ips.size();++i) {
@ -294,18 +271,18 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
}
if (notifyListeners) {
std::unique_lock<std::shared_mutex> ll(_changeListeners_l);
std::lock_guard<std::mutex> ll(_changeListeners_l);
for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) {
(*i)->onNetworkMemberUpdate(this,networkId,memberId,memberConfig);
}
}
} else if (memberId) {
if (nw) {
std::unique_lock<std::shared_mutex> l(nw->lock);
std::lock_guard<std::mutex> l(nw->lock);
nw->members.erase(memberId);
}
if (networkId) {
std::unique_lock<std::shared_mutex> l(_networks_l);
std::lock_guard<std::mutex> l(_networks_l);
auto er = _networkByMember.equal_range(memberId);
for(auto i=er.first;i!=er.second;++i) {
if (i->second == networkId) {
@ -316,26 +293,8 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
}
}
if (notifyListeners) {
if(networkId != 0 && memberId != 0 && old.is_object() && !memberConfig.is_object()) {
// member delete
Metrics::member_count--;
} else if (networkId != 0 && memberId != 0 && !old.is_object() && memberConfig.is_object()) {
// new member
Metrics::member_count++;
}
if (!wasAuth && isAuth) {
Metrics::member_auths++;
} else if (wasAuth && !isAuth) {
Metrics::member_deauths++;
} else {
Metrics::member_changes++;
}
}
if ((notifyListeners)&&((wasAuth)&&(!isAuth)&&(networkId)&&(memberId))) {
std::unique_lock<std::shared_mutex> ll(_changeListeners_l);
std::lock_guard<std::mutex> ll(_changeListeners_l);
for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) {
(*i)->onNetworkMemberDeauthorize(this,networkId,memberId);
}
@ -344,35 +303,24 @@ void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool no
void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool notifyListeners)
{
Metrics::db_network_change++;
if (notifyListeners) {
if (old.is_object() && old.contains("id") && networkConfig.is_object() && networkConfig.contains("id")) {
Metrics::network_changes++;
} else if (!old.is_object() && networkConfig.is_object() && networkConfig.contains("id")) {
Metrics::network_count++;
} else if (old.is_object() && old.contains("id") && !networkConfig.is_object()) {
Metrics::network_count--;
}
}
if (networkConfig.is_object()) {
const std::string ids = networkConfig["id"];
const uint64_t networkId = Utils::hexStrToU64(ids.c_str());
if (networkId) {
std::shared_ptr<_Network> nw;
{
std::unique_lock<std::shared_mutex> l(_networks_l);
std::lock_guard<std::mutex> l(_networks_l);
std::shared_ptr<_Network> &nw2 = _networks[networkId];
if (!nw2)
nw2.reset(new _Network);
nw = nw2;
}
{
std::unique_lock<std::shared_mutex> l2(nw->lock);
std::lock_guard<std::mutex> l2(nw->lock);
nw->config = networkConfig;
}
if (notifyListeners) {
std::unique_lock<std::shared_mutex> ll(_changeListeners_l);
std::lock_guard<std::mutex> ll(_changeListeners_l);
for(auto i=_changeListeners.begin();i!=_changeListeners.end();++i) {
(*i)->onNetworkUpdate(this,networkId,networkConfig);
}
@ -382,25 +330,7 @@ void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool
const std::string ids = old["id"];
const uint64_t networkId = Utils::hexStrToU64(ids.c_str());
if (networkId) {
try {
// deauth all members on the network
nlohmann::json network;
std::vector<nlohmann::json> members;
this->get(networkId, network, members);
for(auto i=members.begin();i!=members.end();++i) {
const std::string nodeID = (*i)["id"];
const uint64_t memberId = Utils::hexStrToU64(nodeID.c_str());
std::unique_lock<std::shared_mutex> ll(_changeListeners_l);
for(auto j=_changeListeners.begin();j!=_changeListeners.end();++j) {
(*j)->onNetworkMemberDeauthorize(this,networkId,memberId);
}
}
} catch (std::exception &e) {
std::cerr << "Error deauthorizing members on network delete: " << e.what() << std::endl;
}
// delete the network
std::unique_lock<std::shared_mutex> l(_networks_l);
std::lock_guard<std::mutex> l(_networks_l);
_networks.erase(networkId);
}
}

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -29,47 +29,14 @@
#include <unordered_set>
#include <vector>
#include <atomic>
#include <shared_mutex>
#include <mutex>
#include <set>
#include <map>
#include <nlohmann/json.hpp>
#include <prometheus/simpleapi.h>
#define ZT_MEMBER_AUTH_TIMEOUT_NOTIFY_BEFORE 25000
#include "../ext/json/json.hpp"
namespace ZeroTier
{
struct AuthInfo
{
public:
AuthInfo()
: enabled(false)
, version(0)
, authenticationURL()
, authenticationExpiryTime(0)
, issuerURL()
, centralAuthURL()
, ssoNonce()
, ssoState()
, ssoClientID()
, ssoProvider("default")
{}
bool enabled;
uint64_t version;
std::string authenticationURL;
uint64_t authenticationExpiryTime;
std::string issuerURL;
std::string centralAuthURL;
std::string ssoNonce;
std::string ssoState;
std::string ssoClientID;
std::string ssoProvider;
};
/**
* Base class with common infrastructure for all controller DB implementations
*/
@ -109,7 +76,7 @@ public:
inline bool hasNetwork(const uint64_t networkId) const
{
std::shared_lock<std::shared_mutex> l(_networks_l);
std::lock_guard<std::mutex> l(_networks_l);
return (_networks.find(networkId) != _networks.end());
}
@ -124,7 +91,7 @@ public:
inline void each(F f)
{
nlohmann::json nullJson;
std::unique_lock<std::shared_mutex> lck(_networks_l);
std::lock_guard<std::mutex> lck(_networks_l);
for(auto nw=_networks.begin();nw!=_networks.end();++nw) {
f(nw->first,nw->second->config,0,nullJson); // first provide network with 0 for member ID
for(auto m=nw->second->members.begin();m!=nw->second->members.end();++m) {
@ -134,15 +101,15 @@ public:
}
virtual bool save(nlohmann::json &record,bool notifyListeners) = 0;
virtual void eraseNetwork(const uint64_t networkId) = 0;
virtual void eraseMember(const uint64_t networkId,const uint64_t memberId) = 0;
virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) = 0;
virtual AuthInfo getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL) { return AuthInfo(); }
virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) = 0;
inline void addListener(DB::ChangeListener *const listener)
{
std::unique_lock<std::shared_mutex> l(_changeListeners_l);
std::lock_guard<std::mutex> l(_changeListeners_l);
_changeListeners.push_back(listener);
}
@ -178,18 +145,18 @@ protected:
std::unordered_set<uint64_t> authorizedMembers;
std::unordered_set<InetAddress,InetAddress::Hasher> allocatedIps;
int64_t mostRecentDeauthTime;
std::shared_mutex lock;
std::mutex lock;
};
virtual void _memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool notifyListeners);
virtual void _networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool notifyListeners);
void _memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool notifyListeners);
void _networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool notifyListeners);
void _fillSummaryInfo(const std::shared_ptr<_Network> &nw,NetworkSummaryInfo &info);
std::vector<DB::ChangeListener *> _changeListeners;
std::unordered_map< uint64_t,std::shared_ptr<_Network> > _networks;
std::unordered_multimap< uint64_t,uint64_t > _networkByMember;
mutable std::shared_mutex _changeListeners_l;
mutable std::shared_mutex _networks_l;
mutable std::mutex _changeListeners_l;
mutable std::mutex _networks_l;
};
} // namespace ZeroTier

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -15,12 +15,9 @@
namespace ZeroTier {
DBMirrorSet::DBMirrorSet(DB::ChangeListener *listener)
: _listener(listener)
, _running(true)
, _syncCheckerThread()
, _dbs()
, _dbs_l()
DBMirrorSet::DBMirrorSet(DB::ChangeListener *listener) :
_listener(listener),
_running(true)
{
_syncCheckerThread = std::thread([this]() {
for(;;) {
@ -32,7 +29,7 @@ DBMirrorSet::DBMirrorSet(DB::ChangeListener *listener)
std::vector< std::shared_ptr<DB> > dbs;
{
std::unique_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
if (_dbs.size() <= 1)
continue; // no need to do this if there's only one DB, so skip the iteration
dbs = _dbs;
@ -79,7 +76,7 @@ DBMirrorSet::~DBMirrorSet()
bool DBMirrorSet::hasNetwork(const uint64_t networkId) const
{
std::shared_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
if ((*d)->hasNetwork(networkId))
return true;
@ -89,7 +86,7 @@ bool DBMirrorSet::hasNetwork(const uint64_t networkId) const
bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network)
{
std::shared_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
if ((*d)->get(networkId,network)) {
return true;
@ -100,7 +97,7 @@ bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network)
bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member)
{
std::shared_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
if ((*d)->get(networkId,network,memberId,member))
return true;
@ -110,7 +107,7 @@ bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,const uin
bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,const uint64_t memberId,nlohmann::json &member,DB::NetworkSummaryInfo &info)
{
std::shared_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
if ((*d)->get(networkId,network,memberId,member,info))
return true;
@ -120,7 +117,7 @@ bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,const uin
bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,std::vector<nlohmann::json> &members)
{
std::shared_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
if ((*d)->get(networkId,network,members))
return true;
@ -128,21 +125,9 @@ bool DBMirrorSet::get(const uint64_t networkId,nlohmann::json &network,std::vect
return false;
}
AuthInfo DBMirrorSet::getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL)
{
std::shared_lock<std::shared_mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
AuthInfo info = (*d)->getSSOAuthInfo(member, redirectURL);
if (info.enabled) {
return info;
}
}
return AuthInfo();
}
void DBMirrorSet::networks(std::set<uint64_t> &networks)
{
std::shared_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
(*d)->networks(networks);
}
@ -151,7 +136,7 @@ void DBMirrorSet::networks(std::set<uint64_t> &networks)
bool DBMirrorSet::waitForReady()
{
bool r = false;
std::shared_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
r |= (*d)->waitForReady();
}
@ -160,7 +145,7 @@ bool DBMirrorSet::waitForReady()
bool DBMirrorSet::isReady()
{
std::shared_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
if (!(*d)->isReady())
return false;
@ -172,7 +157,7 @@ bool DBMirrorSet::save(nlohmann::json &record,bool notifyListeners)
{
std::vector< std::shared_ptr<DB> > dbs;
{
std::unique_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
dbs = _dbs;
}
if (notifyListeners) {
@ -192,7 +177,7 @@ bool DBMirrorSet::save(nlohmann::json &record,bool notifyListeners)
void DBMirrorSet::eraseNetwork(const uint64_t networkId)
{
std::unique_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
(*d)->eraseNetwork(networkId);
}
@ -200,7 +185,7 @@ void DBMirrorSet::eraseNetwork(const uint64_t networkId)
void DBMirrorSet::eraseMember(const uint64_t networkId,const uint64_t memberId)
{
std::unique_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
(*d)->eraseMember(networkId,memberId);
}
@ -208,7 +193,7 @@ void DBMirrorSet::eraseMember(const uint64_t networkId,const uint64_t memberId)
void DBMirrorSet::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress)
{
std::shared_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
(*d)->nodeIsOnline(networkId,memberId,physicalAddress);
}
@ -217,7 +202,7 @@ void DBMirrorSet::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,
void DBMirrorSet::onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network)
{
nlohmann::json record(network);
std::unique_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
if (d->get() != db) {
(*d)->save(record,false);
@ -229,7 +214,7 @@ void DBMirrorSet::onNetworkUpdate(const void *db,uint64_t networkId,const nlohma
void DBMirrorSet::onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member)
{
nlohmann::json record(member);
std::unique_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
if (d->get() != db) {
(*d)->save(record,false);

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -18,7 +18,7 @@
#include <vector>
#include <memory>
#include <shared_mutex>
#include <mutex>
#include <set>
#include <thread>
@ -51,12 +51,10 @@ public:
virtual void onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member);
virtual void onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId);
AuthInfo getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL);
inline void addDB(const std::shared_ptr<DB> &db)
{
db->addListener(this);
std::unique_lock<std::shared_mutex> l(_dbs_l);
std::lock_guard<std::mutex> l(_dbs_l);
_dbs.push_back(db);
}
@ -65,7 +63,7 @@ private:
std::atomic_bool _running;
std::thread _syncCheckerThread;
std::vector< std::shared_ptr< DB > > _dbs;
mutable std::shared_mutex _dbs_l;
mutable std::mutex _dbs_l;
};
} // namespace ZeroTier

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -35,9 +35,7 @@
#include "../osdep/Thread.hpp"
#include "../osdep/BlockingQueue.hpp"
#include <nlohmann/json.hpp>
#include <cpp-httplib/httplib.h>
#include "../ext/json/json.hpp"
#include "DB.hpp"
#include "DBMirrorSet.hpp"
@ -45,22 +43,22 @@
namespace ZeroTier {
class Node;
struct RedisConfig;
struct MQConfig;
class EmbeddedNetworkController : public NetworkController,public DB::ChangeListener
{
public:
/**
* @param node Parent node
* @param ztPath ZeroTier base path
* @param dbPath Database path (file path or database credentials)
*/
EmbeddedNetworkController(Node *node,const char *ztPath,const char *dbPath, int listenPort, RedisConfig *rc);
EmbeddedNetworkController(Node *node,const char *ztPath,const char *dbPath, int listenPort, MQConfig *mqc = NULL);
virtual ~EmbeddedNetworkController();
virtual void init(const Identity &signingId,Sender *sender);
void setSSORedirectURL(const std::string &url);
virtual void request(
uint64_t nwid,
const InetAddress &fromAddr,
@ -68,12 +66,21 @@ public:
const Identity &identity,
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
void configureHTTPControlPlane(
httplib::Server &s,
httplib::Server &sV6,
const std::function<void(const httplib::Request&, httplib::Response&, std::string)>);
void handleRemoteTrace(const ZT_RemoteTrace &rt);
unsigned int handleControlPlaneHttpGET(
const std::vector<std::string> &path,
const std::string &body,
std::string &responseBody,
std::string &responseContentType);
unsigned int handleControlPlaneHttpPOST(
const std::vector<std::string> &path,
const std::string &body,
std::string &responseBody,
std::string &responseContentType);
unsigned int handleControlPlaneHttpDELETE(
const std::vector<std::string> &path,
const std::string &body,
std::string &responseBody,
std::string &responseContentType);
virtual void onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network);
virtual void onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member);
@ -82,9 +89,6 @@ public:
private:
void _request(uint64_t nwid,const InetAddress &fromAddr,uint64_t requestPacketId,const Identity &identity,const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
void _startThreads();
void _ssoExpiryThread();
std::string networkUpdateFromPostData(uint64_t networkID, const std::string &body);
struct _RQEntry
{
@ -97,7 +101,6 @@ private:
RQENTRY_TYPE_REQUEST = 0
} type;
};
struct _MemberStatusKey
{
_MemberStatusKey() : networkId(0),nodeId(0) {}
@ -105,13 +108,11 @@ private:
uint64_t networkId;
uint64_t nodeId;
inline bool operator==(const _MemberStatusKey &k) const { return ((k.networkId == networkId)&&(k.nodeId == nodeId)); }
inline bool operator<(const _MemberStatusKey &k) const { return (k.networkId < networkId) || ((k.networkId == networkId)&&(k.nodeId < nodeId)); }
};
struct _MemberStatus
{
_MemberStatus() : lastRequestTime(0),authenticationExpiryTime(-1),vMajor(-1),vMinor(-1),vRev(-1),vProto(-1) {}
int64_t lastRequestTime;
int64_t authenticationExpiryTime;
_MemberStatus() : lastRequestTime(0),vMajor(-1),vMinor(-1),vRev(-1),vProto(-1) {}
uint64_t lastRequestTime;
int vMajor,vMinor,vRev,vProto;
Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> lastRequestMetaData;
Identity identity;
@ -143,39 +144,7 @@ private:
std::unordered_map< _MemberStatusKey,_MemberStatus,_MemberStatusHash > _memberStatus;
std::mutex _memberStatus_l;
std::set< std::pair<int64_t, _MemberStatusKey> > _expiringSoon;
std::mutex _expiringSoon_l;
RedisConfig *_rc;
std::string _ssoRedirectURL;
bool _ssoExpiryRunning;
std::thread _ssoExpiry;
#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK
prometheus::simpleapi::benchmark_family_t _member_status_lookup;
prometheus::simpleapi::counter_family_t _member_status_lookup_count;
prometheus::simpleapi::benchmark_family_t _node_is_online;
prometheus::simpleapi::counter_family_t _node_is_online_count;
prometheus::simpleapi::benchmark_family_t _get_and_init_member;
prometheus::simpleapi::counter_family_t _get_and_init_member_count;
prometheus::simpleapi::benchmark_family_t _have_identity;
prometheus::simpleapi::counter_family_t _have_identity_count;
prometheus::simpleapi::benchmark_family_t _determine_auth;
prometheus::simpleapi::counter_family_t _determine_auth_count;
prometheus::simpleapi::benchmark_family_t _sso_check;
prometheus::simpleapi::counter_family_t _sso_check_count;
prometheus::simpleapi::benchmark_family_t _auth_check;
prometheus::simpleapi::counter_family_t _auth_check_count;
prometheus::simpleapi::benchmark_family_t _json_schlep;
prometheus::simpleapi::counter_family_t _json_schlep_count;
prometheus::simpleapi::benchmark_family_t _issue_certificate;
prometheus::simpleapi::counter_family_t _issue_certificate_count;
prometheus::simpleapi::benchmark_family_t _save_member;
prometheus::simpleapi::counter_family_t _save_member_count;
prometheus::simpleapi::benchmark_family_t _send_netconf;
prometheus::simpleapi::counter_family_t _send_netconf_count;
#endif
MQConfig *_mqc;
};
} // namespace ZeroTier

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -13,8 +13,6 @@
#include "FileDB.hpp"
#include "../node/Metrics.hpp"
namespace ZeroTier
{
@ -22,13 +20,11 @@ FileDB::FileDB(const char *path) :
DB(),
_path(path),
_networksPath(_path + ZT_PATH_SEPARATOR_S + "network"),
_tracePath(_path + ZT_PATH_SEPARATOR_S + "trace"),
_running(true)
{
OSUtils::mkdir(_path.c_str());
OSUtils::lockDownFile(_path.c_str(),true);
OSUtils::mkdir(_networksPath.c_str());
OSUtils::mkdir(_tracePath.c_str());
std::vector<std::string> networks(OSUtils::listDirectory(_networksPath.c_str(),false));
std::string buf;
@ -41,7 +37,6 @@ FileDB::FileDB(const char *path) :
if (nwids.length() == 16) {
nlohmann::json nullJson;
_networkChanged(nullJson,network,false);
Metrics::network_count++;
std::string membersPath(_networksPath + ZT_PATH_SEPARATOR_S + nwids + ZT_PATH_SEPARATOR_S "member");
std::vector<std::string> members(OSUtils::listDirectory(membersPath.c_str(),false));
for(auto m=members.begin();m!=members.end();++m) {
@ -53,7 +48,6 @@ FileDB::FileDB(const char *path) :
if (addrs.length() == 10) {
nlohmann::json nullJson2;
_memberChanged(nullJson2,member,false);
Metrics::member_count++;
}
} catch ( ... ) {}
}
@ -92,9 +86,8 @@ bool FileDB::save(nlohmann::json &record,bool notifyListeners)
if ((!old.is_object())||(!_compareRecords(old,record))) {
record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid);
if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) {
if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1)))
fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1);
}
_networkChanged(old,record,notifyListeners);
modified = true;
}
@ -115,10 +108,9 @@ bool FileDB::save(nlohmann::json &record,bool notifyListeners)
OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.16llx",_networksPath.c_str(),(unsigned long long)nwid);
OSUtils::mkdir(p2);
OSUtils::mkdir(pb);
if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) {
if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1)))
fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1);
}
}
_memberChanged(old,record,notifyListeners);
modified = true;
}
@ -136,7 +128,7 @@ void FileDB::eraseNetwork(const uint64_t networkId)
char p[16384];
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),networkId);
OSUtils::rm(p);
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx",_networksPath.c_str(),(unsigned long long)networkId);
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)networkId);
OSUtils::rmDashRf(p);
_networkChanged(network,nullJson,true);
std::lock_guard<std::mutex> l(this->_online_l);
@ -146,7 +138,8 @@ void FileDB::eraseNetwork(const uint64_t networkId)
void FileDB::eraseMember(const uint64_t networkId,const uint64_t memberId)
{
nlohmann::json network,member,nullJson;
get(networkId,network,memberId,member);
get(networkId,network);
get(memberId,member);
char p[4096];
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member" ZT_PATH_SEPARATOR_S "%.10llx.json",_networksPath.c_str(),networkId,memberId);
OSUtils::rm(p);

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -35,7 +35,6 @@ public:
protected:
std::string _path;
std::string _networksPath;
std::string _tracePath;
std::thread _onlineUpdateThread;
std::map< uint64_t,std::map<uint64_t,std::map<int64_t,InetAddress> > > _online;
std::mutex _online_l;

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -48,7 +48,7 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons
char maskingKey [128];
Utils::hex(sha512pk,32,maskingKey);
httplib::Client htcli(_lfNodeHost.c_str(),_lfNodePort);
httplib::Client htcli(_lfNodeHost.c_str(),_lfNodePort,600);
int64_t timeRangeStart = 0;
while (_running.load()) {
{
@ -190,10 +190,10 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons
if (resp) {
if (resp->status == 200) {
nlohmann::json results(OSUtils::jsonParse(resp->body));
if ((results.is_array())&&(!results.empty())) {
if ((results.is_array())&&(results.size() > 0)) {
for(std::size_t ri=0;ri<results.size();++ri) {
nlohmann::json &rset = results[ri];
if ((rset.is_array())&&(!rset.empty())) {
if ((rset.is_array())&&(rset.size() > 0)) {
nlohmann::json &result = rset[0];
if (result.is_object()) {
@ -258,10 +258,10 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons
if (resp) {
if (resp->status == 200) {
nlohmann::json results(OSUtils::jsonParse(resp->body));
if ((results.is_array())&&(!results.empty())) {
if ((results.is_array())&&(results.size() > 0)) {
for(std::size_t ri=0;ri<results.size();++ri) {
nlohmann::json &rset = results[ri];
if ((rset.is_array())&&(!rset.empty())) {
if ((rset.is_array())&&(rset.size() > 0)) {
nlohmann::json &result = rset[0];
if (result.is_object()) {

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
* 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
* Change Date: 2023-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.
@ -20,92 +20,24 @@
#define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4
#include "ConnectionPool.hpp"
#include <pqxx/pqxx>
#include <memory>
#include <redis++/redis++.h>
#include "../node/Metrics.hpp"
extern "C" {
typedef struct pg_conn PGconn;
}
namespace smeeclient {
struct SmeeClient;
}
namespace ZeroTier {
struct RedisConfig;
class PostgresConnection : public Connection {
public:
virtual ~PostgresConnection() {
}
std::shared_ptr<pqxx::connection> c;
int a;
};
class PostgresConnFactory : public ConnectionFactory {
public:
PostgresConnFactory(std::string &connString)
: m_connString(connString)
{
}
virtual std::shared_ptr<Connection> create() {
Metrics::conn_counter++;
auto c = std::shared_ptr<PostgresConnection>(new PostgresConnection());
c->c = std::make_shared<pqxx::connection>(m_connString);
return std::static_pointer_cast<Connection>(c);
}
private:
std::string m_connString;
};
class PostgreSQL;
class MemberNotificationReceiver : public pqxx::notification_receiver {
public:
MemberNotificationReceiver(PostgreSQL *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;
};
class NetworkNotificationReceiver : public pqxx::notification_receiver {
public:
NetworkNotificationReceiver(PostgreSQL *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;
};
struct MQConfig;
/**
* 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.
* but be aware taht 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);
PostgreSQL(const Identity &myId, const char *path, int listenPort, MQConfig *mqc = NULL);
virtual ~PostgreSQL();
virtual bool waitForReady();
@ -114,49 +46,33 @@ public:
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 initializeNetworks(PGconn *conn);
void initializeMembers(PGconn *conn);
void heartbeat();
void membersDbWatcher();
void _membersWatcher_Postgres();
void _membersWatcher_Postgres(PGconn *conn);
void _membersWatcher_RabbitMQ();
void networksDbWatcher();
void _networksWatcher_Postgres();
void _membersWatcher_Redis();
void _networksWatcher_Redis();
void _networksWatcher_Postgres(PGconn *conn);
void _networksWatcher_RabbitMQ();
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;
PGconn * getPgConn( OverrideMode m = ALLOW_PGBOUNCER_OVERRIDE );
const Identity _myId;
const Address _myAddress;
@ -179,14 +95,8 @@ private:
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;
MQConfig *_mqc;
};
} // namespace ZeroTier

View file

@ -3,7 +3,7 @@ Network Controller Microservice
Every ZeroTier virtual network has a *network controller* responsible for admitting members to the network, issuing certificates, and issuing default configuration information.
This is our reference controller implementation and is almost the same as the one we use to power our own hosted services at [my.zerotier.com](https://my.zerotier.com/). The only difference is the database backend used.
This is our reference controller implementation and is the same one we use to power our own hosted services at [my.zerotier.com](https://my.zerotier.com/). As of ZeroTier One version 1.2.0 this code is included in normal builds for desktop, laptop, and server (Linux, etc.) targets.
Controller data is stored in JSON format under `controller.d` in the ZeroTier working directory. It can be copied, rsync'd, placed in `git`, etc. The files under `controller.d` should not be modified in place while the controller is running or data loss may result, and if they are edited directly take care not to save corrupt JSON since that can also lead to data loss when the controller is restarted. Going through the API is strongly preferred to directly modifying these files.
@ -19,6 +19,10 @@ Since ZeroTier nodes are mobile and do not need static IPs, implementing high av
ZeroTier network controllers can easily be run in Docker or other container systems. Since containers do not need to actually join networks, extra privilege options like "--device=/dev/net/tun --privileged" are not needed. You'll just need to map the local JSON API port of the running controller and allow it to access the Internet (over UDP/9993 at a minimum) so things can reach and query it.
### PostgreSQL Database Implementation
The default controller stores its data in the filesystem in `controller.d` under ZeroTier's home folder. There's an alternative implementation that stores data in PostgreSQL that can be built with `make central-controller`. Right now this is only guaranteed to build and run on Centos 7 Linux with PostgreSQL 10 installed via the [PostgreSQL Yum Repository](https://www.postgresql.org/download/linux/redhat/) and is designed for use with [ZeroTier Central](https://my.zerotier.com/). You're welcome to use it but we don't "officially" support it for end-user use and it could change at any time.
### Upgrading from Older (1.1.14 or earlier) Versions
Older versions of this code used a SQLite database instead of in-filesystem JSON. A migration utility called `migrate-sqlite` is included here and *must* be used to migrate this data to the new format. If the controller is started with an old `controller.db` in its working directory it will terminate after printing an error to *stderr*. This is done to prevent "surprises" for those running DIY controllers using the old code.
@ -39,17 +43,190 @@ While networks with any valid ID can be added to the controller's database, it w
The controller JSON API is *very* sensitive about types. Integers must be integers and strings strings, etc. Incorrect types may be ignored, set to default values, or set to undefined values.
Full documentation of the Controller API can be found on our [documentation site](https://docs.zerotier.com/service/v1#tag/controller)
#### `/controller`
### Prometheus Metrics
* Purpose: Check for controller function and return controller status
* Methods: GET
* Returns: { object }
Controller specific metrics are available from the `/metrics` endpoint.
| Field | Type | Description | Writable |
| ------------------ | ----------- | ------------------------------------------------- | -------- |
| controller | boolean | Always 'true' | no |
| apiVersion | integer | Controller API version, currently 3 | no |
| clock | integer | Current clock on controller, ms since epoch | no |
#### `/controller/network`
* Purpose: List all networks hosted by this controller
* Methods: GET
* Returns: [ string, ... ]
This returns an array of 16-digit hexadecimal network IDs.
#### `/controller/network/<network ID>`
* Purpose: Create, configure, and delete hosted networks
* Methods: GET, POST, DELETE
* Returns: { object }
By making queries to this path you can create, configure, and delete networks. DELETE is final, so don't do it unless you really mean it.
When POSTing new networks take care that their IDs are not in use, otherwise you may overwrite an existing one. To create a new network with a random unused ID, POST to `/controller/network/##########______`. The #'s are the controller's 10-digit ZeroTier address and they're followed by six underscores. Check the `nwid` field of the returned JSON object for your network's newly allocated ID. Subsequent POSTs to this network must refer to its actual path.
Example:
`curl -X POST --header "X-ZT1-Auth: secret" -d '{"name":"my network"}' http://localhost:9993/controller/network/305f406058______`
**Network object format:**
| Field | Type | Description | Writable |
| --------------------- | ------------- | ------------------------------------------------- | -------- |
| id | string | 16-digit network ID | no |
| nwid | string | 16-digit network ID (legacy) | no |
| objtype | string | Always "network" | no |
| name | string | A short name for this network | YES |
| creationTime | integer | Time network record was created (ms since epoch) | no |
| private | boolean | Is access control enabled? | YES |
| enableBroadcast | boolean | Ethernet ff:ff:ff:ff:ff:ff allowed? | YES |
| v4AssignMode | object | IPv4 management and assign options (see below) | YES |
| v6AssignMode | object | IPv6 management and assign options (see below) | YES |
| mtu | integer | Network MTU (default: 2800) | YES |
| multicastLimit | integer | Maximum recipients for a multicast packet | YES |
| revision | integer | Network config revision counter | no |
| routes | array[object] | Managed IPv4 and IPv6 routes; see below | YES |
| ipAssignmentPools | array[object] | IP auto-assign ranges; see below | YES |
| rules | array[object] | Traffic rules; see below | YES |
| capabilities | array[object] | Array of capability objects (see below) | YES |
| tags | array[object] | Array of tag objects (see below) | YES |
| remoteTraceTarget | string | 10-digit ZeroTier ID of remote trace target | YES |
| remoteTraceLevel | integer | Remote trace verbosity level | YES |
* Networks without rules won't carry any traffic. If you don't specify any on network creation an "accept anything" rule set will automatically be added.
* Managed IP address assignments and IP assignment pools that do not fall within a route configured in `routes` are ignored and won't be used or sent to members.
* The default for `private` is `true` and this is probably what you want. Turning `private` off means *anyone* can join your network with only its 16-digit network ID. It's also impossible to de-authorize a member as these networks don't issue or enforce certificates. Such "party line" networks are used for decentralized app backplanes, gaming, and testing but are otherwise not common.
* Changing the MTU can be disruptive and on some operating systems may require a leave/rejoin of the network or a restart of the ZeroTier service.
**Auto-Assign Modes:**
Auto assign modes (`v4AssignMode` and `v6AssignMode`) contain objects that map assignment modes to booleans.
For IPv4 the only valid setting is `zt` which, if true, causes IPv4 addresses to be auto-assigned from `ipAssignmentPools` to members that do not have an IPv4 assignment. Note that active bridges are exempt and will not get auto-assigned IPs since this can interfere with bridging. (You can still manually assign one if you want.)
IPv6 includes this option and two others: `6plane` and `rfc4193`. These assign private IPv6 addresses to each member based on a deterministic assignment scheme that allows members to emulate IPv6 NDP to skip multicast for better performance and scalability. The `rfc4193` mode gives every member a /128 on a /88 network, while `6plane` gives every member a /80 within a /40 network but uses NDP emulation to route *all* IPs under that /80 to its owner. The `6plane` mode is great for use cases like Docker since it allows every member to assign IPv6 addresses within its /80 that just work instantly and globally across the network.
**IP assignment pool object format:**
| Field | Type | Description |
| --------------------- | ------------- | ------------------------------------------------- |
| ipRangeStart | string | Starting IP address in range |
| ipRangeEnd | string | Ending IP address in range (inclusive) |
Pools are only used if auto-assignment is on for the given address type (IPv4 or IPv6) and if the entire range falls within a managed route.
IPv6 ranges work just like IPv4 ranges and look like this:
{
"ipRangeStart": "fd00:feed:feed:beef:0000:0000:0000:0000",
"ipRangeEnd": "fd00:feed:feed:beef:ffff:ffff:ffff:ffff"
}
(You can POST a shortened-form IPv6 address but the API will always report back un-shortened canonical form addresses.)
That defines a range within network `fd00:feed:feed:beef::/64` that contains up to 2^64 addresses. If an IPv6 range is large enough, the controller will assign addresses by placing each member's device ID into the address in a manner similar to the RFC4193 and 6PLANE modes. Otherwise it will assign addresses at random.
**Rule object format:**
Each rule is actually a sequence of zero or more `MATCH_` entries in the rule array followed by an `ACTION_` entry that describes what to do if all the preceding entries match. An `ACTION_` without any preceding `MATCH_` entries is always taken, so setting a single `ACTION_ACCEPT` rule yields a network that allows all traffic. If no rules are present the default action is `ACTION_DROP`.
Rules are evaluated in the order in which they appear in the array. There is currently a limit of 256 entries per network. Capabilities should be used if a larger and more complex rule set is needed since they allow rules to be grouped by purpose and only shipped to members that need them.
Each rule table entry has two common fields.
| Field | Type | Description |
| --------------------- | ------------- | ------------------------------------------------- |
| type | string | Entry type (all caps, case sensitive) |
| not | boolean | If true, MATCHes match if they don't match |
The following fields may or may not be present depending on rule type:
| Field | Type | Description |
| --------------------- | ------------- | ------------------------------------------------- |
| zt | string | 10-digit hex ZeroTier address |
| etherType | integer | Ethernet frame type |
| mac | string | Hex MAC address (with or without :'s) |
| ip | string | IPv4 or IPv6 address |
| ipTos | integer | IP type of service |
| ipProtocol | integer | IP protocol (e.g. TCP) |
| start | integer | Start of an integer range (e.g. port range) |
| end | integer | End of an integer range (inclusive) |
| id | integer | Tag ID |
| value | integer | Tag value or comparison value |
| mask | integer | Bit mask (for characteristics flags) |
The entry types and their additional fields are:
| Entry type | Description | Fields |
| ------------------------------- | ----------------------------------------------------------------- | -------------- |
| `ACTION_DROP` | Drop any packets matching this rule | (none) |
| `ACTION_ACCEPT` | Accept any packets matching this rule | (none) |
| `ACTION_TEE` | Send a copy of this packet to a node (rule parsing continues) | `zt` |
| `ACTION_REDIRECT` | Redirect this packet to another node | `zt` |
| `ACTION_DEBUG_LOG` | Output debug info on match (if built with rules engine debug) | (none) |
| `MATCH_SOURCE_ZEROTIER_ADDRESS` | Match VL1 ZeroTier address of packet sender. | `zt` |
| `MATCH_DEST_ZEROTIER_ADDRESS` | Match VL1 ZeroTier address of recipient | `zt` |
| `MATCH_ETHERTYPE` | Match Ethernet frame type | `etherType` |
| `MATCH_MAC_SOURCE` | Match source Ethernet MAC address | `mac` |
| `MATCH_MAC_DEST` | Match destination Ethernet MAC address | `mac` |
| `MATCH_IPV4_SOURCE` | Match source IPv4 address | `ip` |
| `MATCH_IPV4_DEST` | Match destination IPv4 address | `ip` |
| `MATCH_IPV6_SOURCE` | Match source IPv6 address | `ip` |
| `MATCH_IPV6_DEST` | Match destination IPv6 address | `ip` |
| `MATCH_IP_TOS` | Match IP TOS field | `ipTos` |
| `MATCH_IP_PROTOCOL` | Match IP protocol field | `ipProtocol` |
| `MATCH_IP_SOURCE_PORT_RANGE` | Match a source IP port range | `start`,`end` |
| `MATCH_IP_DEST_PORT_RANGE` | Match a destination IP port range | `start`,`end` |
| `MATCH_CHARACTERISTICS` | Match on characteristics flags | `mask`,`value` |
| `MATCH_FRAME_SIZE_RANGE` | Match a range of Ethernet frame sizes | `start`,`end` |
| `MATCH_TAGS_SAMENESS` | Match if both sides' tags differ by no more than value | `id`,`value` |
| `MATCH_TAGS_BITWISE_AND` | Match if both sides' tags AND to value | `id`,`value` |
| `MATCH_TAGS_BITWISE_OR` | Match if both sides' tags OR to value | `id`,`value` |
| `MATCH_TAGS_BITWISE_XOR` | Match if both sides' tags XOR to value | `id`,`value` |
Important notes about rules engine behavior:
* IPv4 and IPv6 IP address rules do not match for frames that are not IPv4 or IPv6 respectively.
* `ACTION_DEBUG_LOG` is a no-op on nodes not built with `ZT_RULES_ENGINE_DEBUGGING` enabled (see Network.cpp). If that is enabled nodes will dump a trace of rule evaluation results to *stdout* when this action is encountered but will otherwise keep evaluating rules. This is used for basic "smoke testing" of the rules engine.
* Multicast packets and packets destined for bridged devices treated a little differently. They are matched more than once. They are matched at the point of send with a NULL ZeroTier destination address, meaning that `MATCH_DEST_ZEROTIER_ADDRESS` is useless. That's because the true VL1 destination is not yet known. Then they are matched again for each true VL1 destination. On these later subsequent matches TEE actions are ignored and REDIRECT rules are interpreted as DROPs. This prevents multiple TEE or REDIRECT packets from being sent to third party devices.
* Rules in capabilities are always matched as if the current device is the sender (inbound == false). A capability specifies sender side rules that can be enforced on both sides.
#### `/controller/network/<network ID>/member`
* Purpose: Get a set of all members on this network
* Methods: GET
* Returns: { object }
This returns a JSON object containing all member IDs as keys and their `memberRevisionCounter` values as values.
#### `/controller/network/<network ID>/member/<address>`
* Purpose: Create, authorize, or remove a network member
* Methods: GET, POST, DELETE
* Returns: { object }
| Field | Type | Description | Writable |
| --------------------- | ------------- | ------------------------------------------------- | -------- |
| id | string | Member's 10-digit ZeroTier address | no |
| address | string | Member's 10-digit ZeroTier address | no |
| nwid | string | 16-digit network ID | no |
| authorized | boolean | Is member authorized? (for private networks) | YES |
| activeBridge | boolean | Member is able to bridge to other Ethernet nets | YES |
| identity | string | Member's public ZeroTier identity (if known) | no |
| ipAssignments | array[string] | Managed IP address assignments | YES |
| revision | integer | Member revision counter | no |
| vMajor | integer | Most recently known major version | no |
| vMinor | integer | Most recently known minor version | no |
| vRev | integer | Most recently known revision | no |
| vProto | integer | Most recently known protocl version | no |
Note that managed IP assignments are only used if they fall within a managed route. Otherwise they are ignored.
| Metric Name | Type | Description |
| --- | --- | --- |
| controller_network_count | Gauge | number of networks the controller is serving |
| controller_member_count | Gauge | number of network members the controller is serving |
| controller_network_change_count | Counter | number of times a network configuration is changed |
| controller_member_change_count | Counter | number of times a network member configuration is changed |
| controller_member_auth_count | Counter | number of network member auths |
| controller_member_deauth_count | Counter | number of network member deauths|

120
controller/RabbitMQ.cpp Normal file
View file

@ -0,0 +1,120 @@
/*
* 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: 2023-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 "RabbitMQ.hpp"
#ifdef ZT_CONTROLLER_USE_LIBPQ
#include <amqp.h>
#include <amqp_tcp_socket.h>
#include <stdexcept>
#include <cstring>
namespace ZeroTier
{
RabbitMQ::RabbitMQ(MQConfig *cfg, const char *queueName)
: _mqc(cfg)
, _qName(queueName)
, _socket(NULL)
, _status(0)
{
}
RabbitMQ::~RabbitMQ()
{
amqp_channel_close(_conn, _channel, AMQP_REPLY_SUCCESS);
amqp_connection_close(_conn, AMQP_REPLY_SUCCESS);
amqp_destroy_connection(_conn);
}
void RabbitMQ::init()
{
struct timeval tval;
memset(&tval, 0, sizeof(struct timeval));
tval.tv_sec = 5;
fprintf(stderr, "Initializing RabbitMQ %s\n", _qName);
_conn = amqp_new_connection();
_socket = amqp_tcp_socket_new(_conn);
if (!_socket) {
throw std::runtime_error("Can't create socket for RabbitMQ");
}
_status = amqp_socket_open_noblock(_socket, _mqc->host, _mqc->port, &tval);
if (_status) {
throw std::runtime_error("Can't connect to RabbitMQ");
}
amqp_rpc_reply_t r = amqp_login(_conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN,
_mqc->username, _mqc->password);
if (r.reply_type != AMQP_RESPONSE_NORMAL) {
throw std::runtime_error("RabbitMQ Login Error");
}
static int chan = 0;
{
Mutex::Lock l(_chan_m);
_channel = ++chan;
}
amqp_channel_open(_conn, _channel);
r = amqp_get_rpc_reply(_conn);
if(r.reply_type != AMQP_RESPONSE_NORMAL) {
throw std::runtime_error("Error opening communication channel");
}
_q = amqp_queue_declare(_conn, _channel, amqp_cstring_bytes(_qName), 0, 0, 0, 0, amqp_empty_table);
r = amqp_get_rpc_reply(_conn);
if (r.reply_type != AMQP_RESPONSE_NORMAL) {
throw std::runtime_error("Error declaring queue " + std::string(_qName));
}
amqp_basic_consume(_conn, _channel, amqp_cstring_bytes(_qName), amqp_empty_bytes, 0, 1, 0, amqp_empty_table);
r = amqp_get_rpc_reply(_conn);
if (r.reply_type != AMQP_RESPONSE_NORMAL) {
throw std::runtime_error("Error consuming queue " + std::string(_qName));
}
fprintf(stderr, "RabbitMQ Init OK %s\n", _qName);
}
std::string RabbitMQ::consume()
{
amqp_rpc_reply_t res;
amqp_envelope_t envelope;
amqp_maybe_release_buffers(_conn);
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
res = amqp_consume_message(_conn, &envelope, &timeout, 0);
if (res.reply_type != AMQP_RESPONSE_NORMAL) {
if (res.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION && res.library_error == AMQP_STATUS_TIMEOUT) {
// timeout waiting for message. Return empty string
return "";
} else {
throw std::runtime_error("Error getting message");
}
}
std::string msg(
(const char*)envelope.message.body.bytes,
envelope.message.body.len
);
amqp_destroy_envelope(&envelope);
return msg;
}
}
#endif // ZT_CONTROLLER_USE_LIBPQ

Some files were not shown because too many files have changed in this diff Show more