diff --git a/.clangd b/.clangd index cd9c5e1db..b4145667f 100644 --- a/.clangd +++ b/.clangd @@ -4,6 +4,8 @@ CompileFlags: - "-I../ext" - "-I../ext/prometheus-cpp-lite-1.0/core/include" - "-I../ext/prometheus-cpp-lite-1.0/simpleapi/include" + - "-I../ext/opentelemetry-cpp-1.21.0/api/include" - "-I./ext" - "-I./ext/prometheus-cpp-lite-1.0/core/include" - "-I./ext/prometheus-cpp-lite-1.0/simpleapi/include" + - "-I./ext/opentelemetry-cpp-1.21.0/api/include" diff --git a/.gitignore b/.gitignore index ec162c2f3..d52abee96 100755 --- a/.gitignore +++ b/.gitignore @@ -6,16 +6,19 @@ /zerotier /nltest -# IDE stuff +# IDE and dev tool stuff /.idea /.nova /compile_commands.json +/.claude +/.aider # OS-created garbage files from various platforms .DS_Store .Apple* Thumbs.db @eaDir +lost+found ._* # Windows build droppings @@ -58,6 +61,9 @@ zt1-src.tar.gz /MacEthernetTapAgent # Miscellaneous temporaries, build files, etc. +ext/installfiles/windows/*.back*.aip +tcp-proxy/tcp-proxy +rustybits/target *.log *.opensdf *.user @@ -101,7 +107,6 @@ windows/ZeroTierOne/Debug/ /ext/installfiles/windows/chocolatey/zerotier-one/*.nupkg # Miscellaneous mac/Xcode droppings -.DS_Store .Trashes *.swp *~.nib @@ -126,19 +131,14 @@ workspace2/ zeroidc/target/ tcp-proxy/target -#snapcraft specifics +# Snapcraft Linux build stuff /parts/ /stage/ /prime/ - *.snap - .snapcraft __pycache__ *.pyc *_source.tar.bz2 snap/.snapcraft -tcp-proxy/tcp-proxy -rustybits/target -ext/installfiles/windows/*.back*.aip build/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index fb6fe52b1..c705c2853 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,7 +91,7 @@ add_subdirectory(ext) add_subdirectory(node) add_subdirectory(osdep) add_subdirectory(service) -add_subdirectory(controller) +add_subdirectory(nonfree) set(LINKED_LIBRARIES prometheus-cpp-lite diff --git a/COPYING b/COPYING deleted file mode 100644 index 7f0801e20..000000000 --- a/COPYING +++ /dev/null @@ -1,12 +0,0 @@ -ZeroTier One, an endpoint server for the ZeroTier virtual network layer. -Copyright © 2011–2019 ZeroTier, Inc. - -ZeroTier is released under the terms of the BUSL version 1.1. See the -file LICENSE.txt for details. - -.. - Local variables: - coding: utf-8 - mode: text - End: - vim: fileencoding=utf-8 filetype=text : diff --git a/LICENSE-MPL.txt b/LICENSE-MPL.txt new file mode 100644 index 000000000..a612ad981 --- /dev/null +++ b/LICENSE-MPL.txt @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/LICENSE.txt b/LICENSE.txt index 06a3fad64..2c64b1820 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,149 +1,5 @@ ------------------------------------------------------------------------------ +See LICENSE-MPL.txt for all code in node/, osdep/. service/, and everywhere else except ext/ and nonfree/. -Business Source License 1.1 +See nonfree/LICENSE.md for all non-free ("source available") portions of this repository. -License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. -"Business Source License" is a trademark of MariaDB Corporation Ab. - ------------------------------------------------------------------------------ - -Parameters - -Licensor: ZeroTier, Inc. -Licensed Work: ZeroTier Network Virtualization Engine 1.4.4 - The Licensed Work is (c)2019 ZeroTier, Inc. -Additional Use Grant: You may make use of the Licensed Work, provided you - do not use it in any of the following ways: - - * Sell hosted ZeroTier services as a "SaaS" Product - - (1) Operate or sell access to ZeroTier root servers, - network controllers, or authorization key or certificate - generation components of the Licensed Work as a - for-profit service, regardless of whether the use of - these components is sold alone or is bundled with other - services. Note that this does not apply to the use of - ZeroTier behind the scenes to operate a service not - related to ZeroTier network administration. - - * Create Non-Open-Source Commercial Derivative Works - - (2) Link or directly include the Licensed Work in a - commercial or for-profit application or other product - not distributed under an Open Source Initiative (OSI) - compliant license. See: https://opensource.org/licenses - - (3) Remove the name, logo, copyright, or other branding - material from the Licensed Work to create a "rebranded" - or "white labeled" version to distribute as part of - any commercial or for-profit product or service. - - * Certain Government Uses - - (4) Use or deploy the Licensed Work in a government - setting in support of any active government function - or operation with the exception of the following: - physical or mental health care, family and social - services, social welfare, senior care, child care, and - the care of persons with disabilities. - -Change Date: 2026-01-01 - -Change License: Apache License version 2.0 as published by the Apache - Software Foundation - https://www.apache.org/licenses/ - -Alternative Licensing - -If you would like to use the Licensed Work in any way that conflicts with -the stipulations of the Additional Use Grant, contact ZeroTier, Inc. to -obtain an alternative commercial license. - -Visit us on the web at: https://www.zerotier.com/ - -Notice - -The Business Source License (this document, or the "License") is not an Open -Source license. However, the Licensed Work will eventually be made available -under an Open Source License, as stated in this License. - -For more information on the use of the Business Source License for ZeroTier -products, please visit our pricing page which contains license details and -and license FAQ: https://zerotier.com/pricing - -For more information on the use of the Business Source License generally, -please visit the Adopting and Developing Business Source License FAQ at -https://mariadb.com/bsl-faq-adopting. - ------------------------------------------------------------------------------ - -Business Source License 1.1 - -Terms - -The Licensor hereby grants you the right to copy, modify, create derivative -works, redistribute, and make non-production use of the Licensed Work. The -Licensor may make an Additional Use Grant, above, permitting limited -production use. - -Effective on the Change Date, or the fourth anniversary of the first publicly -available distribution of a specific version of the Licensed Work under this -License, whichever comes first, the Licensor hereby grants you rights under -the terms of the Change License, and the rights granted in the paragraph -above terminate. - -If your use of the Licensed Work does not comply with the requirements -currently in effect as described in this License, you must purchase a -commercial license from the Licensor, its affiliated entities, or authorized -resellers, or you must refrain from using the Licensed Work. - -All copies of the original and modified Licensed Work, and derivative works -of the Licensed Work, are subject to this License. This License applies -separately for each version of the Licensed Work and the Change Date may vary -for each version of the Licensed Work released by Licensor. - -You must conspicuously display this License on each original or modified copy -of the Licensed Work. If you receive the Licensed Work in original or -modified form from a third party, the terms and conditions set forth in this -License apply to your use of that work. - -Any use of the Licensed Work in violation of this License will automatically -terminate your rights under this License for the current and all other -versions of the Licensed Work. - -This License does not grant you any right in any trademark or logo of -Licensor or its affiliates (provided that you may use a trademark or logo of -Licensor as expressly required by this License). - -TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON -AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, -EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND -TITLE. - ------------------------------------------------------------------------------ - -MariaDB hereby grants you permission to use this License’s text to license -your works, and to refer to it using the trademark "Business Source License", -as long as you comply with the Covenants of Licensor below. - -Covenants of Licensor - -In consideration of the right to use this License’s text and the "Business -Source License" name and trademark, Licensor covenants to MariaDB, and to all -other recipients of the licensed work to be provided by Licensor: - -1. To specify as the Change License the GPL Version 2.0 or any later version, - or a license that is compatible with GPL Version 2.0 or a later version, - where "compatible" means that software provided under the Change License can - be included in a program with software provided under GPL Version 2.0 or a - later version. Licensor may specify additional Change Licenses without - limitation. - -2. To either: (a) specify an additional grant of rights to use that does not - impose any additional restriction on the right granted in this License, as - the Additional Use Grant; or (b) insert the text "None". - -3. To specify a Change Date. - -4. Not to modify this License in any other way. +Code in ext/ is external code included for build convenience or backward compatibility and retains its original license. diff --git a/Makefile b/Makefile index f77767fb8..51a9914bb 100644 --- a/Makefile +++ b/Makefile @@ -33,4 +33,4 @@ drone: drone sign zerotier/ZeroTierOne --save clang-format: - find node osdep service tcp-proxy controller -iname '*.cpp' -o -iname '*.hpp' | xargs clang-format -i + find node osdep service tcp-proxy nonfree/controller -iname '*.cpp' -o -iname '*.hpp' | xargs clang-format -i diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index e6582207e..ecec6b984 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,14 +1,42 @@ ZeroTier Release Notes ====== -# 2024-10-23 -- Version 1.14.2 +## 2025-08-21 -- Version 1.16.0 + + * License Changes + * The core (`node/` and `include/`) and the service (`service/` and `osdep/`) are now under the Mozilla Public License (MPL). + * The network controller (`controller/`) is now under a commercial source-available license. + * Use `make ZT_NONFREE=1` to build non-MPL components. + * Building with `ZT_NONFREE=1` changes the license of the resulting executable to a proprietary commercial license vs. MPL. + * Default binary builds no longer contain the controller. + * Network-Specific Relays (preview / beta) + * It is now possible to designate one or more nodes as network-specific relays to be used in preference to roots for relayed traffic between members of a network. These nodes need not necessarily be members of the network. + * "Moons" are now considered even more extra *deprecated* and should not be used in new deployments. + * We will announce support for network-specific relays once we have worked with some users to test and performed more internal validation. + * HELLO packet encryption is now available by enabling the `encryptedHelloEnabled` settting in `local.conf`. + * HELLO packets contain no data, only public keys and very basic meta-data like protocol version information. + * Most users won't care about this, but if you require this for e.g. compliance reasons you can enable. This adds a small amount of CPU and bandwidth overhead to the HELLO sign-on process. + * Small Fixes + * Code has been reformatted using `clang-format` with a `.clang-format` definition in the repo. Typing `make clang-format` executes this against all main core and service C++ files. + * Bridges are no longer counted toward multicast limits. + * A flow designation issue in bridged traffic under multipath scenarios has been fixed. + * Library version updates for OIDC and other features. + * Antiquated and unused software update code removed for precautionary reasons. + * Compiler warnings removed through removing use of deprecated functions on some platforms. + * Other minor bug fixes. + +---- + +# 1.14 + +## 2024-10-23 -- Version 1.14.2 * Fix for missing entitlement on macOS Sequoia. * Fix for a problem correctly parsing local.conf to enable low bandwidth mode. * Increment versions of some dependent libraries. * Other fixes. -# 2024-09-12 -- Version 1.14.1 +## 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 @@ -24,7 +52,7 @@ ZeroTier Release Notes 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 +## 2024-05-02 -- Version 1.14.0 * Linux I/O performance improvements under heavy load * Improvements to multipath @@ -33,18 +61,22 @@ ZeroTier Release Notes * Controller API enhancements: node names and other node meta-data * Other bug fixes -# 2023-09-12 -- Version 1.12.2 +---- + +# 1.12 and Older + +## 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 +## 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 +## 2023-08-23 -- Version 1.12.0 * Experimental Windows ARM64 support * Fix numerous sleep/wake issues on macOS and other platforms @@ -54,17 +86,17 @@ ZeroTier Release Notes * Numerous macOS DNS fixes * 10-30% speed improvement on Linux -# 2023-03-23 -- Version 1.10.6 +## 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 +## 2023-03-10 -- Version 1.10.5 * Fix for high CPU usage bug on Windows -# 2023-03-07 -- Version 1.10.4 +## 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 @@ -73,11 +105,10 @@ ZeroTier Release Notes 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 +## 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. @@ -89,7 +120,7 @@ ZeroTier Release Notes * Fix bug that prevented setting of custom TCP relay address. * Build script improvements and bug fixes. -# 2022-11-01 -- Version 1.10.2 +## 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. @@ -100,12 +131,12 @@ ZeroTier Release Notes 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 +## 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 +## 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. @@ -114,11 +145,11 @@ Note that releases are coming few and far between because most of our dev effort * 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 +## 2022-05-10 -- Version 1.8.10 * Fixed a bug preventing SSO sign-on on Windows. -# 2022-04-25 -- Version 1.8.9 +## 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. @@ -127,26 +158,26 @@ Note that releases are coming few and far between because most of our dev effort * 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 +## 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 +## 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 +## 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 +## 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. @@ -154,7 +185,7 @@ Note that releases are coming few and far between because most of our dev effort * 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 +## 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. @@ -162,7 +193,7 @@ Note that releases are coming few and far between because most of our dev effort * 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 +## 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. @@ -170,14 +201,14 @@ Note that releases are coming few and far between because most of our dev effort * 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 +## 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 +## 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. @@ -187,7 +218,7 @@ Note that releases are coming few and far between because most of our dev effort * 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) +## 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. @@ -198,32 +229,32 @@ Note that releases are coming few and far between because most of our dev effort * 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 +## 2021-09-21 -- Version 1.6.6 * Backport COM hash check mitigation against network member impersonation. -# 2021-04-13 -- Version 1.6.5 +## 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 +## 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 +## 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 +## 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 +## 2020-11-24 -- Version 1.6.1 This release fixes some minor bugs and other issues in 1.6.0. @@ -233,7 +264,7 @@ This release fixes some minor bugs and other issues in 1.6.0. * 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 +## 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. @@ -274,7 +305,7 @@ Known issues that are not yet fixed in this beta: We're trying to fix all these issues before the 1.6.0 release. Stay tuned. -# 2019-08-30 -- Version 1.4.6 +## 2019-08-30 -- Version 1.4.6 * Update default root list to latest * ARM32 platform build and flag fixes @@ -283,19 +314,19 @@ We're trying to fix all these issues before the 1.6.0 release. Stay tuned. * Windows service now looks for service command line arguments * Fixed a bug that could cause excessive queued multicasts -# 2019-08-23 -- Version 1.4.4 +## 2019-08-23 -- Version 1.4.4 * Change license from GPL3 to BSL 1.1, see LICENSE.txt * Fix an issue with the "ipauth" rule and auto-generated unforgeable IPv6 addresses * Fix socket/bind errors setting IPs and routes on Linux -# 2019-08-12 -- Version 1.4.2 +## 2019-08-12 -- Version 1.4.2 * Fix high CPU use bug on some platforms * Fix issues with PostgreSQL controller DB (only affects Central) * Restore backward compatibility with MacOS versions prior to 10.13 -# 2019-07-29 -- Version 1.4.0 +## 2019-07-29 -- Version 1.4.0 ### Major Changes @@ -313,20 +344,20 @@ We're trying to fix all these issues before the 1.6.0 release. Stay tuned. * Fixed numerous other small issues and bugs such as ARM alignment issues causing crashes on some devices. * Windows now sets the adapter name such that it is consistent in both the Windows UI and command line utilities. -# 2018-07-27 -- Version 1.2.12 +## 2018-07-27 -- Version 1.2.12 * Fixed a bug that caused exits to take a long time on Mac due to huge numbers of redundant attempts to delete managed routes. * Fixed a socket limit problem on Windows that caused the ZeroTier service to run out of sockets, causing the UI and CLI to be unable to access the API. * Fixed a threading bug in the ZeroTier Core, albeit one that never manifested on the regular ZeroTier One service/client. * Fixed a bug that could cause the service to crash if an authorized local client accessed an invalid URL via the control API. (Not exploitable since you needed admin access anyway.) -# 2018-05-08 -- Version 1.2.10 +## 2018-05-08 -- Version 1.2.10 * Fix bug loading `moons.d/` files for federated root operation. * Fix compile problem with ZT_DEBUG on some versions of `clang` * Fix slow network startup bug related to loading of `networks.d/` cache files -# 2018-04-27 -- Version 1.2.8 +## 2018-04-27 -- Version 1.2.8 * Linux version once again builds with PIE (position independent executable) flags * Fixed bug in zerotier-idtool file sign and verify @@ -334,7 +365,7 @@ We're trying to fix all these issues before the 1.6.0 release. Stay tuned. * Merged alpha NetBSD support (mostly untested, so YMMV) * Merged several minor typo and one-liner bug fixes -# 2018-04-17 -- Version 1.2.6 +## 2018-04-17 -- Version 1.2.6 * Features and Core Improvements * Path selection has been overhauled to improve path stability, simplify code, and prepare for multi-path and trunking in the next major release. @@ -369,7 +400,7 @@ We're trying to fix all these issues before the 1.6.0 release. Stay tuned. * Multicast now works on Android in most cases! Android apps can send and receive multicast and subscribe to multicast group IPs. Note that in some cases the app must bind to the specific correct interface for this to work. * IPv6 can be disabled in UI for cases where it causes problems. -# 2017-04-20 -- Version 1.2.4 +## 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. @@ -379,128 +410,12 @@ We're trying to fix all these issues before the 1.6.0 release. Stay tuned. * Fixed an issue causing build problems on some MIPS architecture systems. * Fixed Windows forgetting routes on sleep/wake or in some other circumstances. (GitHub issue #465) -# 2017-03-17 -- Version 1.2.2 +## 2017-03-17 -- Version 1.2.2 * A bug causing unreliable multicast propagation (GitHub issue #461). * A crash in ARM binaries due to a build chain and flags problem. * A bug in the network controller preventing members from being listed (GitHub issue #460). -# 2017-03-14 -- Version 1.2.0 +## 2017-03-14 -- Version 1.2.0 Version 1.2.0 is a major milestone release representing almost nine months of work. It includes our rules engine for distributed network packet filtering and security monitoring, federated roots, and many other architectural and UI improvements and bug fixes. - -## New Features in 1.2.0 - -### The ZeroTier Rules Engine - -The largest new feature in 1.2.0, and the product of many months of work, is our advanced network rules engine. With this release we achieve traffic control, security monitoring, and micro-segmentation capability on par with many enterprise SDN solutions designed for use in advanced data centers and corporate networks. - -Rules allow you to filter packets on your network and vector traffic to security observers. Security observation can be performed in-band using REDIRECT or out of band using TEE. - -Tags and capabilities provide advanced methods for implementing fine grained permission structures and micro-segmentation schemes without bloating the size and complexity of your rules table. - -See the [rules engine announcement blog post](https://www.zerotier.com/blog/?p=927) for an in-depth discussion of theory and implementation. The [manual](https://www.zerotier.com/manual.shtml) contains detailed information on rule, tag, and capability use, and the `rule-compiler/` subfolder of the ZeroTier source tree contains a JavaScript function to compile rules in our human-readable rule definition language into rules suitable for import into a network controller. (ZeroTier Central uses this same script to compile rules on [my.zerotier.com](https://my.zerotier.com/).) - -### Root Server Federation - -It's now possible to create your own root servers and add them to the root server pool on your nodes. This is done by creating what's called a "moon," which is a signed enumeration of root servers and their stable points on the network. Refer to the [manual](https://www.zerotier.com/manual.shtml) for instructions. - -Federated roots achieve a number of things: - - * You can deploy your own infrastructure to reduce dependency on ours. - * You can deploy roots *inside your LAN* to ensure that network connectivity inside your facility still works if the Internet goes down. This is the first step toward making ZeroTier viable as an in-house SDN solution. - * Roots can be deployed inside national boundaries for countries with data residency laws or "great firewalls." (As of 1.2.0 there is still no way to force all traffic to use these roots, but that will be easy to do in a later version.) - * Last but not least this makes ZeroTier somewhat less centralized by eliminating any hard dependency on ZeroTier, Inc.'s infrastructure. - -Our roots will of course remain and continue to provide zero-configuration instant-on deployment, a secure global authority for identities, and free traffic relaying for those who can't establish peer to peer connections. - -### Local Configuration - -An element of our design philosophy is "features are bugs." This isn't an absolute dogma but more of a guiding principle. We try as hard as we can to avoid adding features, especially "knobs" that must be tweaked by a user. - -As of 1.2.0 we've decided that certain knobs are unavoidable, and so there is now a `local.conf` file that can be used to configure them. See the ZeroTier One documentation for these. They include: - - * Blacklisting interfaces you want to make sure ZeroTier doesn't use for network traffic, such as VPNs, slow links, or backplanes designated for only certain kinds of traffic. - * Turning uPnP/NAT-PMP on or off. - * Configuring software updates on Windows and Mac platforms. - * Defining trusted paths (the old trusted paths file is now deprecated) - * Setting the ZeroTier main port so it doesn't have to be changed on the command line, which is very inconvenient in many cases. - -### Improved In-Band Software Updates - -A good software update system for Windows and Mac clients has been a missing feature in previous versions. It does exist but we've been shy about using it so far due to its fragility in some environments. - -We've greatly improved this mechanism in 1.2.0. Not only does it now do a better job of actually invoking the update, but it also transfers updates in-band using the ZeroTier protocol. This means it can work in environments that do not allows http/https traffic or that force it through proxies. There's also now an update channel setting: `beta` or `release` (the default). - -Software updates are authenticated three ways: - - 1. ZeroTier's own signing key is used to sign all updates and this signature is checked prior to installation. ZeroTier, Inc.'s signatures are performed on an air-gapped machine. - - 2. Updates for Mac and Windows are signed using Apple and Microsoft (DigiCert EV) keys and will not install unless these signatures are also valid. - - 3. The new in-band update mechanism also authenticates the source of the update via ZeroTier's built-in security features. This provides transport security, while 1 and 2 provide security of the update at rest. - -Updates are now configurable via `local.conf`. There are three options: `disable`, `download`, and `apply`. The third (apply) is the default for official builds on Windows and Mac, making updates happen silently and automatically as they do for popular browsers like Chrome and Firefox. Updates are disabled by default on Linux and other Unix-type systems as these are typically updated through package managers. - -### Path Link Quality Awareness - -Version 1.2.0 is now aware of the link quality of direct paths with other 1.2.0 nodes. This information isn't used yet but is visible through the JSON API. (Quality always shows as 100% with pre-1.2.0 nodes.) Quality is measured passively with no additional overhead using a counter based packet loss detection algorithm. - -This information is visible from the command line via `listpeers`: - - 200 listpeers XXXXXXXXXX 199.XXX.XXX.XXX/9993;10574;15250;1.00 48 1.2.0 LEAF - 200 listpeers XXXXXXXXXX 195.XXX.XXX.XXX/45584;467;7608;0.44 290 1.2.0 LEAF - -The first peer's path is at 100% (1.00), while the second peer's path is suffering quite a bit of packet loss (0.44). - -Link quality awareness is a precursor to intelligent multi-path and QoS support, which will in future versions bring us to feature parity with SD-WAN products like Cisco iWAN. - -### Security Improvements - -Version 1.2.0 adds anti-DOS (denial of service) rate limits and other hardening for improved resiliency against a number of denial of service attack scenarios. - -It also adds a mechanism for instantaneous credential revocation. This can be used to revoke certificates of membership instantly to kick a node off a network (for private networks) and also to revoke capabilities and tags. The new controller sends revocations by default when a peer is de-authorized. - -Revocations propagate using a "rumor mill" peer to peer algorithm. This means that a controller need only successfully send a revocation to at least one member of a network with connections to other active members. At this point the revocation will flood through the network peer to peer very quickly. This helps make revocations more robust in the face of poor connectivity with the controller or attempts to incapacitate the controller with denial of service attacks, as well as making revocations faster on huge networks. - -### Windows and Macintosh UI Improvements (ZeroTier One) - -The Mac has a whole new UI built natively in Objective-C. It provides a pulldown similar in appearance and operation to the Mac WiFi task bar menu. - -The Windows UI has also been improved and now provides a task bar icon that can be right-clicked to manage networks. Both now expose managed route and IP permissions, allowing nodes to easily opt in to full tunnel operation if you have a router configured on your network. - -### Ad-Hoc Networks - -A special kind of public network called an ad-hoc network may be accessed by joining a network ID with the format: - - ffSSSSEEEE000000 - | | | | - | | | Reserved for future use, must be 0 - | | End of port range (hex) - | Start of port range (hex) - Reserved ZeroTier address prefix indicating a controller-less network - -Ad-hoc networks are public (no access control) networks that have no network controller. Instead their configuration and other credentials are generated locally. Ad-hoc networks permit only IPv6 UDP and TCP unicast traffic (no multicast or broadcast) using 6plane format NDP-emulated IPv6 addresses. In addition an ad-hoc network ID encodes an IP port range. UDP packets and TCP SYN (connection open) packets are only allowed to destination ports within the encoded range. - -For example `ff00160016000000` is an ad-hoc network allowing only SSH, while `ff0000ffff000000` is an ad-hoc network allowing any UDP or TCP port. - -Keep in mind that these networks are public and anyone in the entire world can join them. Care must be taken to avoid exposing vulnerable services or sharing unwanted files or other resources. - -### Network Controller (Partial) Rewrite - -The network controller has been largely rewritten to use a simple in-filesystem JSON data store in place of SQLite, and it is now included by default in all Windows, Mac, Linux, and BSD builds. This means any desktop or server node running ZeroTier One can now be a controller with no recompilation needed. - -If you have data in an old SQLite3 controller we've included a NodeJS script in `controller/migrate-sqlite` to migrate data to the new format. If you don't migrate, members will start getting `NOT_FOUND` when they attempt to query for updates. - -## Major Bug Fixes in 1.2.0 - - * **The Windows HyperV 100% CPU bug is FINALLY DEAD**: This long-running problem turns out to have been an issue with Windows itself, but one we were triggering by placing invalid data into the Windows registry. Microsoft is aware of the issue but we've also fixed the triggering problem on our side. ZeroTier should now co-exist quite well with HyperV and should now be able to be bridged with a HyperV virtual switch. - * **Segmentation faults on musl-libc based Linux systems**: Alpine Linux and some embedded Linux systems that use musl libc (a minimal libc) experienced segmentation faults. These were due to a smaller default stack size. A work-around that sets the stack size for new threads has been added. - * **Windows firewall blocks local JSON API**: On some Windows systems the firewall likes to block 127.0.0.1:9993 for mysterious reasons. This is now fixed in the installer via the addition of another firewall exemption rule. - * **UI crash on embedded Windows due to missing fonts**: The MSI installer now ships fonts and will install them if they are not present, so this should be fixed. - -## Other Improvements in 1.2.0 - - * **Improved dead path detection**: ZeroTier is now more aggressive about expiring paths that do not seem to be active. If a path seems marginal it is re-confirmed before re-use. - * **Minor performance improvements**: We've reduced unnecessary memcpy's and made a few other performance improvements in the core. - * **Linux static binaries**: For our official packages (the ones in the download.zerotier.com apt and yum repositories) we now build Linux binaries with static linking. Hopefully this will stop all the bug reports relating to library inconsistencies, as well as allowing our deb packages to run on a wider variety of Debian-based distributions. (There are far too many of these to support officially!) The overhead for this is very small, especially since we built our static versions against musl-libc. Distribution maintainers are of course free to build dynamically linked versions for inclusion into distributions; this only affects our official binaries. diff --git a/SECURITY.md b/SECURITY.md index c539ed6a2..ceecc3b5d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,6 +1,6 @@ # Security -ZeroTier takes the security of our software products and services seriously, which +ZeroTier takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organization. ## Supported Versions @@ -9,8 +9,9 @@ The following versions of ZeroTier One receive security updates | Version | Supported | | -------- | ------------------ | +| 1.16.x | :white_check_mark: | | 1.14.x | :white_check_mark: | -| 1.12.x | :white_check_mark: | +| 1.12.x | :x: | | < 1.12.0 | :x: | ## Reporting a Vulnerability @@ -20,7 +21,7 @@ The following versions of ZeroTier One receive security updates 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 +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.) diff --git a/attic/world/README.md b/attic/world/README.md deleted file mode 100644 index dda4920ae..000000000 --- a/attic/world/README.md +++ /dev/null @@ -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'. - diff --git a/attic/world/build.sh b/attic/world/build.sh deleted file mode 100755 index f3bcfabc9..000000000 --- a/attic/world/build.sh +++ /dev/null @@ -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 diff --git a/attic/world/mkworld.cpp b/attic/world/mkworld.cpp deleted file mode 100644 index ed2c499a0..000000000 --- a/attic/world/mkworld.cpp +++ /dev/null @@ -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 . - */ - -/* - * 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 -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace ZeroTier; - -int main(int argc,char **argv) -{ - std::string previous,current; - if ((!OSUtils::readFile("previous.c25519",previous))||(!OSUtils::readFile("current.c25519",current))) { - ECC::Pair np(ECC::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; - } - ECC::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); - ECC::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 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 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 0) - fprintf(stdout,","); - fprintf(stdout,"0x%.2x",(unsigned int)d[i]); - } - fprintf(stdout,"};" ZT_EOL_S); - - return 0; -} diff --git a/attic/world/world.bin b/attic/world/world.bin deleted file mode 100644 index 88049ccdc..000000000 Binary files a/attic/world/world.bin and /dev/null differ diff --git a/attic/world/world.c b/attic/world/world.c deleted file mode 100644 index ecf30e6f0..000000000 --- a/attic/world/world.c +++ /dev/null @@ -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}; diff --git a/controller/LFDB.cpp b/controller/LFDB.cpp deleted file mode 100644 index 35532a7f5..000000000 --- a/controller/LFDB.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#include "LFDB.hpp" - -#ifdef CMAKE_BUILD -#include "httplib.h" -#else -#include "../ext/cpp-httplib/httplib.h" -#endif -#include "../osdep/OSUtils.hpp" - -#include -#include -#include -#include - -namespace ZeroTier { - -LFDB::LFDB(const Identity& myId, const char* path, const char* lfOwnerPrivate, const char* lfOwnerPublic, const char* lfNodeHost, int lfNodePort, bool storeOnlineState) - : DB() - , _myId(myId) - , _lfOwnerPrivate((lfOwnerPrivate) ? lfOwnerPrivate : "") - , _lfOwnerPublic((lfOwnerPublic) ? lfOwnerPublic : "") - , _lfNodeHost((lfNodeHost) ? lfNodeHost : "127.0.0.1") - , _lfNodePort(((lfNodePort > 0) && (lfNodePort < 65536)) ? lfNodePort : 9980) - , _running(true) - , _ready(false) - , _storeOnlineState(storeOnlineState) -{ - _syncThread = std::thread([this]() { - char controllerAddress[24]; - const uint64_t controllerAddressInt = _myId.address().toInt(); - _myId.address().toString(controllerAddress); - std::string networksSelectorName("com.zerotier.controller.lfdb:"); - networksSelectorName.append(controllerAddress); - networksSelectorName.append("/network"); - - // LF record masking key is the first 32 bytes of SHA512(controller private key) in hex, - // hiding record values from anything but the controller or someone who has its key. - uint8_t sha512pk[64]; - _myId.sha512PrivateKey(sha512pk); - char maskingKey[128]; - Utils::hex(sha512pk, 32, maskingKey); - - httplib::Client htcli(_lfNodeHost.c_str(), _lfNodePort); - int64_t timeRangeStart = 0; - while (_running.load()) { - { - std::lock_guard sl(_state_l); - for (auto ns = _state.begin(); ns != _state.end(); ++ns) { - if (ns->second.dirty) { - nlohmann::json network; - if (get(ns->first, network)) { - nlohmann::json newrec, selector0; - selector0["Name"] = networksSelectorName; - selector0["Ordinal"] = ns->first; - newrec["Selectors"].push_back(selector0); - newrec["Value"] = network.dump(); - newrec["OwnerPrivate"] = _lfOwnerPrivate; - newrec["MaskingKey"] = maskingKey; - newrec["PulseIfUnchanged"] = true; - try { - auto resp = htcli.Post("/makerecord", newrec.dump(), "application/json"); - if (resp) { - if (resp->status == 200) { - ns->second.dirty = false; - // printf("SET network %.16llx %s\n",ns->first,resp->body.c_str()); - } - else { - fprintf(stderr, "ERROR: LFDB: %d from node (create/update network): %s" ZT_EOL_S, resp->status, resp->body.c_str()); - } - } - else { - fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S); - } - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update network): %s" ZT_EOL_S, e.what()); - } - catch (...) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update network): unknown exception" ZT_EOL_S); - } - } - } - - for (auto ms = ns->second.members.begin(); ms != ns->second.members.end(); ++ms) { - if ((_storeOnlineState) && (ms->second.lastOnlineDirty) && (ms->second.lastOnlineAddress)) { - nlohmann::json newrec, selector0, selector1, selectors, ip; - char tmp[1024], tmp2[128]; - OSUtils::ztsnprintf(tmp, sizeof(tmp), "com.zerotier.controller.lfdb:%s/network/%.16llx/online", controllerAddress, (unsigned long long)ns->first); - ms->second.lastOnlineAddress.toIpString(tmp2); - selector0["Name"] = tmp; - selector0["Ordinal"] = ms->first; - selector1["Name"] = tmp2; - selector1["Ordinal"] = 0; - selectors.push_back(selector0); - selectors.push_back(selector1); - newrec["Selectors"] = selectors; - const uint8_t* const rawip = (const uint8_t*)ms->second.lastOnlineAddress.rawIpData(); - switch (ms->second.lastOnlineAddress.ss_family) { - case AF_INET: - for (int j = 0; j < 4; ++j) - ip.push_back((unsigned int)rawip[j]); - break; - case AF_INET6: - for (int j = 0; j < 16; ++j) - ip.push_back((unsigned int)rawip[j]); - break; - default: - ip = tmp2; // should never happen since only IP transport is currently supported - break; - } - newrec["Value"] = ip; - newrec["OwnerPrivate"] = _lfOwnerPrivate; - newrec["MaskingKey"] = maskingKey; - newrec["Timestamp"] = ms->second.lastOnlineTime; - newrec["PulseIfUnchanged"] = true; - try { - auto resp = htcli.Post("/makerecord", newrec.dump(), "application/json"); - if (resp) { - if (resp->status == 200) { - ms->second.lastOnlineDirty = false; - // printf("SET member online %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); - } - else { - fprintf(stderr, "ERROR: LFDB: %d from node (create/update member online status): %s" ZT_EOL_S, resp->status, resp->body.c_str()); - } - } - else { - fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S); - } - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member online status): %s" ZT_EOL_S, e.what()); - } - catch (...) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member online status): unknown exception" ZT_EOL_S); - } - } - - if (ms->second.dirty) { - nlohmann::json network, member; - if (get(ns->first, network, ms->first, member)) { - nlohmann::json newrec, selector0, selector1, selectors; - selector0["Name"] = networksSelectorName; - selector0["Ordinal"] = ns->first; - selector1["Name"] = "member"; - selector1["Ordinal"] = ms->first; - selectors.push_back(selector0); - selectors.push_back(selector1); - newrec["Selectors"] = selectors; - newrec["Value"] = member.dump(); - newrec["OwnerPrivate"] = _lfOwnerPrivate; - newrec["MaskingKey"] = maskingKey; - newrec["PulseIfUnchanged"] = true; - try { - auto resp = htcli.Post("/makerecord", newrec.dump(), "application/json"); - if (resp) { - if (resp->status == 200) { - ms->second.dirty = false; - // printf("SET member %.16llx %.10llx %s\n",ns->first,ms->first,resp->body.c_str()); - } - else { - fprintf(stderr, "ERROR: LFDB: %d from node (create/update member): %s" ZT_EOL_S, resp->status, resp->body.c_str()); - } - } - else { - fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S); - } - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member): %s" ZT_EOL_S, e.what()); - } - catch (...) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (create/update member): unknown exception" ZT_EOL_S); - } - } - } - } - } - } - - try { - std::ostringstream query; - query << "{" - "\"Ranges\":[{" - "\"Name\":\"" - << networksSelectorName - << "\"," - "\"Range\":[0,18446744073709551615]" - "}]," - "\"TimeRange\":[" - << timeRangeStart - << ",9223372036854775807]," - "\"MaskingKey\":\"" - << maskingKey - << "\"," - "\"Owners\":[\"" - << _lfOwnerPublic - << "\"]" - "}"; - auto resp = htcli.Post("/query", query.str(), "application/json"); - if (resp) { - if (resp->status == 200) { - nlohmann::json results(OSUtils::jsonParse(resp->body)); - if ((results.is_array()) && (! results.empty())) { - for (std::size_t ri = 0; ri < results.size(); ++ri) { - nlohmann::json& rset = results[ri]; - if ((rset.is_array()) && (! rset.empty())) { - nlohmann::json& result = rset[0]; - if (result.is_object()) { - nlohmann::json& record = result["Record"]; - if (record.is_object()) { - const std::string recordValue = result["Value"]; - // printf("GET network %s\n",recordValue.c_str()); - nlohmann::json network(OSUtils::jsonParse(recordValue)); - if (network.is_object()) { - const std::string idstr = network["id"]; - const uint64_t id = Utils::hexStrToU64(idstr.c_str()); - if ((id >> 24) == controllerAddressInt) { // sanity check - - nlohmann::json oldNetwork; - if ((timeRangeStart > 0) && (get(id, oldNetwork))) { - const uint64_t revision = network["revision"]; - const uint64_t prevRevision = oldNetwork["revision"]; - if (prevRevision < revision) { - _networkChanged(oldNetwork, network, timeRangeStart > 0); - } - } - else { - nlohmann::json nullJson; - _networkChanged(nullJson, network, timeRangeStart > 0); - } - } - } - } - } - } - } - } - } - else { - fprintf(stderr, "ERROR: LFDB: %d from node (check for network updates): %s" ZT_EOL_S, resp->status, resp->body.c_str()); - } - } - else { - fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S); - } - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for network updates): %s" ZT_EOL_S, e.what()); - } - catch (...) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for network updates): unknown exception" ZT_EOL_S); - } - - try { - std::ostringstream query; - query << "{" - "\"Ranges\":[{" - "\"Name\":\"" - << networksSelectorName - << "\"," - "\"Range\":[0,18446744073709551615]" - "},{" - "\"Name\":\"member\"," - "\"Range\":[0,18446744073709551615]" - "}]," - "\"TimeRange\":[" - << timeRangeStart - << ",9223372036854775807]," - "\"MaskingKey\":\"" - << maskingKey - << "\"," - "\"Owners\":[\"" - << _lfOwnerPublic - << "\"]" - "}"; - auto resp = htcli.Post("/query", query.str(), "application/json"); - if (resp) { - if (resp->status == 200) { - nlohmann::json results(OSUtils::jsonParse(resp->body)); - if ((results.is_array()) && (! results.empty())) { - for (std::size_t ri = 0; ri < results.size(); ++ri) { - nlohmann::json& rset = results[ri]; - if ((rset.is_array()) && (! rset.empty())) { - nlohmann::json& result = rset[0]; - if (result.is_object()) { - nlohmann::json& record = result["Record"]; - if (record.is_object()) { - const std::string recordValue = result["Value"]; - // printf("GET member %s\n",recordValue.c_str()); - nlohmann::json member(OSUtils::jsonParse(recordValue)); - if (member.is_object()) { - const std::string nwidstr = member["nwid"]; - const std::string idstr = member["id"]; - const uint64_t nwid = Utils::hexStrToU64(nwidstr.c_str()); - const uint64_t id = Utils::hexStrToU64(idstr.c_str()); - if ((id) && ((nwid >> 24) == controllerAddressInt)) { // sanity check - - nlohmann::json network, oldMember; - if ((timeRangeStart > 0) && (get(nwid, network, id, oldMember))) { - const uint64_t revision = member["revision"]; - const uint64_t prevRevision = oldMember["revision"]; - if (prevRevision < revision) - _memberChanged(oldMember, member, timeRangeStart > 0); - } - else if (hasNetwork(nwid)) { - nlohmann::json nullJson; - _memberChanged(nullJson, member, timeRangeStart > 0); - } - } - } - } - } - } - } - } - } - else { - fprintf(stderr, "ERROR: LFDB: %d from node (check for member updates): %s" ZT_EOL_S, resp->status, resp->body.c_str()); - } - } - else { - fprintf(stderr, "ERROR: LFDB: node is offline" ZT_EOL_S); - } - } - catch (std::exception& e) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for member updates): %s" ZT_EOL_S, e.what()); - } - catch (...) { - fprintf(stderr, "ERROR: LFDB: unexpected exception querying node (check for member updates): unknown exception" ZT_EOL_S); - } - - timeRangeStart = time(nullptr) - 120; // start next query 2m before now to avoid losing updates - _ready.store(true); - - for (int k = 0; k < 4; ++k) { // 2s delay between queries for remotely modified networks or members - if (! _running.load()) - return; - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } - } - }); -} - -LFDB::~LFDB() -{ - _running.store(false); - _syncThread.join(); -} - -bool LFDB::waitForReady() -{ - while (! _ready.load()) { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } - return true; -} - -bool LFDB::isReady() -{ - return (_ready.load()); -} - -bool LFDB::save(nlohmann::json& record, bool notifyListeners) -{ - bool modified = false; - const std::string objtype = record["objtype"]; - if (objtype == "network") { - const uint64_t nwid = OSUtils::jsonIntHex(record["id"], 0ULL); - if (nwid) { - nlohmann::json old; - get(nwid, old); - if ((! old.is_object()) || (! _compareRecords(old, record))) { - record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL; - _networkChanged(old, record, notifyListeners); - { - std::lock_guard l(_state_l); - _state[nwid].dirty = true; - } - modified = true; - } - } - } - else if (objtype == "member") { - const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"], 0ULL); - const uint64_t id = OSUtils::jsonIntHex(record["id"], 0ULL); - if ((id) && (nwid)) { - nlohmann::json network, old; - get(nwid, network, id, old); - if ((! old.is_object()) || (! _compareRecords(old, record))) { - record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL; - _memberChanged(old, record, notifyListeners); - { - std::lock_guard l(_state_l); - _state[nwid].members[id].dirty = true; - } - modified = true; - } - } - } - return modified; -} - -void LFDB::eraseNetwork(const uint64_t networkId) -{ - // TODO -} - -void LFDB::eraseMember(const uint64_t networkId, const uint64_t memberId) -{ - // TODO -} - -void LFDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch) -{ - std::lock_guard l(_state_l); - auto nw = _state.find(networkId); - if (nw != _state.end()) { - auto m = nw->second.members.find(memberId); - if (m != nw->second.members.end()) { - m->second.lastOnlineTime = OSUtils::now(); - if (physicalAddress) - m->second.lastOnlineAddress = physicalAddress; - m->second.lastOnlineDirty = true; - } - } -} - -void LFDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) -{ - this->nodeIsOnline(networkId, memberId, physicalAddress, "unknown/unknown"); -} - -} // namespace ZeroTier diff --git a/controller/LFDB.hpp b/controller/LFDB.hpp deleted file mode 100644 index 3632e483f..000000000 --- a/controller/LFDB.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#ifndef ZT_CONTROLLER_LFDB_HPP -#define ZT_CONTROLLER_LFDB_HPP - -#include "DB.hpp" - -#include -#include -#include -#include - -namespace ZeroTier { - -/** - * DB implementation for controller that stores data in LF - */ -class LFDB : public DB { - public: - /** - * @param myId This controller's identity - * @param path Base path for ZeroTier node itself - * @param lfOwnerPrivate LF owner private in PEM format - * @param lfOwnerPublic LF owner public in @base62 format - * @param lfNodeHost LF node host - * @param lfNodePort LF node http (not https) port - * @param storeOnlineState If true, store online/offline state and IP info in LF (a lot of data, only for private networks!) - */ - LFDB(const Identity& myId, const char* path, const char* lfOwnerPrivate, const char* lfOwnerPublic, const char* lfNodeHost, int lfNodePort, bool storeOnlineState); - virtual ~LFDB(); - - virtual bool waitForReady(); - virtual bool isReady(); - virtual bool save(nlohmann::json& record, bool notifyListeners); - virtual void eraseNetwork(const uint64_t networkId); - virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch); - - protected: - const Identity _myId; - - std::string _lfOwnerPrivate, _lfOwnerPublic; - std::string _lfNodeHost; - int _lfNodePort; - - struct _MemberState { - _MemberState() : lastOnlineAddress(), lastOnlineTime(0), dirty(false), lastOnlineDirty(false) - { - } - InetAddress lastOnlineAddress; - int64_t lastOnlineTime; - bool dirty; - bool lastOnlineDirty; - }; - struct _NetworkState { - _NetworkState() : members(), dirty(false) - { - } - std::unordered_map members; - bool dirty; - }; - std::unordered_map _state; - std::mutex _state_l; - - std::atomic_bool _running; - std::atomic_bool _ready; - std::thread _syncThread; - bool _storeOnlineState; -}; - -} // namespace ZeroTier - -#endif diff --git a/debian/changelog b/debian/changelog index fdc85f860..01ef8cf65 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +zerotier-one (1.16.0) unstable; urgency=medium + + * See RELEASE-NOTES.md for release notes. + + -- Adam Ierymenko Thu, 21 Aug 2025 01:00:00 -0700 + zerotier-one (1.14.2) unstable; urgency=medium * See RELEASE-NOTES.md for release notes. diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj index 70cedf9f9..56ae6ea28 100755 --- a/ext/installfiles/mac/ZeroTier One.pkgproj +++ b/ext/installfiles/mac/ZeroTier One.pkgproj @@ -1,14 +1,15 @@ - - + + PACKAGES MUST-CLOSE-APPLICATION-ITEMS - + MUST-CLOSE-APPLICATIONS - + PACKAGE_FILES DEFAULT_INSTALL_LOCATION @@ -22,7 +23,7 @@ CHILDREN - + GID 80 PATH @@ -38,7 +39,7 @@ BUNDLE_CAN_DOWNGRADE - + BUNDLE_POSTINSTALL_PATH PATH_TYPE @@ -50,7 +51,7 @@ 0 CHILDREN - + GID 80 PATH @@ -92,7 +93,7 @@ CHILDREN - + GID 0 PATH @@ -108,7 +109,7 @@ CHILDREN - + GID 0 PATH @@ -124,7 +125,7 @@ CHILDREN - + GID 80 PATH @@ -140,7 +141,7 @@ CHILDREN - + GID 0 PATH @@ -156,7 +157,7 @@ CHILDREN - + GID 0 PATH @@ -214,7 +215,7 @@ CHILDREN - + GID 0 PATH @@ -230,7 +231,7 @@ CHILDREN - + GID 0 PATH @@ -246,7 +247,7 @@ CHILDREN - + GID 0 PATH @@ -262,7 +263,7 @@ CHILDREN - + GID 0 PATH @@ -278,7 +279,7 @@ CHILDREN - + GID 0 PATH @@ -294,7 +295,7 @@ CHILDREN - + GID 0 PATH @@ -310,7 +311,7 @@ CHILDREN - + GID 0 PATH @@ -329,7 +330,7 @@ CHILDREN - + GID 0 PATH @@ -359,7 +360,7 @@ CHILDREN - + GID 0 PATH @@ -375,7 +376,7 @@ CHILDREN - + GID 0 PATH @@ -391,7 +392,7 @@ CHILDREN - + GID 80 PATH @@ -407,7 +408,7 @@ CHILDREN - + GID 0 PATH @@ -423,7 +424,7 @@ CHILDREN - + GID 0 PATH @@ -439,7 +440,7 @@ CHILDREN - + GID 0 PATH @@ -455,7 +456,7 @@ CHILDREN - + GID 0 PATH @@ -471,7 +472,7 @@ CHILDREN - + GID 0 PATH @@ -487,7 +488,7 @@ CHILDREN - + GID 0 PATH @@ -503,7 +504,7 @@ CHILDREN - + GID 0 PATH @@ -519,7 +520,7 @@ CHILDREN - + GID 0 PATH @@ -555,7 +556,7 @@ CHILDREN - + GID 0 PATH @@ -602,7 +603,7 @@ CHILDREN - + GID 0 PATH @@ -647,13 +648,13 @@ PAYLOAD_TYPE 0 PRESERVE_EXTENDED_ATTRIBUTES - + SHOW_INVISIBLE - + SPLIT_FORKS - + TREAT_MISSING_FILES_AS_WARNING - + VERSION 5 @@ -674,7 +675,7 @@ 1 RESOURCES - + PACKAGE_SETTINGS @@ -683,7 +684,7 @@ CONCLUSION_ACTION 0 FOLLOW_SYMBOLIC_LINKS - + IDENTIFIER com.zerotier.pkg.ZeroTierOne LOCATION @@ -691,17 +692,17 @@ NAME ZeroTier One OVERWRITE_PERMISSIONS - + PAYLOAD_SIZE -1 REFERENCE_PATH - + RELOCATABLE - + USE_HFS+_COMPRESSION - + VERSION - 1.14.2 + 1.16.0 TYPE 0 @@ -753,12 +754,12 @@ APPAREANCES DARK_AQUA - + LIGHT_AQUA - + SHARED_SETTINGS_FOR_ALL_APPAREANCES - + INSTALLATION TYPE @@ -770,20 +771,20 @@ CHILDREN - + DESCRIPTION - + OPTIONS HIDDEN - + STATE 1 PACKAGE_UUID 1B6AFC3A-9EA5-4401-83D4-37F06CD13CD6 TITLE - + TYPE 0 UUID @@ -791,7 +792,7 @@ REMOVED - + MODE @@ -859,24 +860,24 @@ INTRODUCTION LOCALIZATIONS - + LICENSE LOCALIZATIONS - + MODE 0 README LOCALIZATIONS - + TITLE LOCALIZATIONS - + PROJECT_REQUIREMENTS @@ -900,17 +901,17 @@ IDENTIFIER fr.whitebox.Packages.requirement.os MESSAGE - + NAME Operating System STATE - + RESOURCES - + ROOT_VOLUME_ONLY - + PROJECT_SETTINGS @@ -937,7 +938,7 @@ REGULAR_EXPRESSION - + STRING .DS_Store TYPE @@ -945,20 +946,20 @@ PROTECTED - + PROXY_NAME Remove .DS_Store files PROXY_TOOLTIP Remove ".DS_Store" files created by the Finder. STATE - + PATTERNS_ARRAY REGULAR_EXPRESSION - + STRING .pbdevelopment TYPE @@ -966,20 +967,21 @@ PROTECTED - + PROXY_NAME Remove .pbdevelopment files PROXY_TOOLTIP - Remove ".pbdevelopment" files created by ProjectBuilder or Xcode. + Remove ".pbdevelopment" files created by ProjectBuilder or Xcode. STATE - + PATTERNS_ARRAY REGULAR_EXPRESSION - + STRING CVS TYPE @@ -987,7 +989,7 @@ REGULAR_EXPRESSION - + STRING .cvsignore TYPE @@ -995,7 +997,7 @@ REGULAR_EXPRESSION - + STRING .cvspass TYPE @@ -1003,7 +1005,7 @@ REGULAR_EXPRESSION - + STRING .svn TYPE @@ -1011,7 +1013,7 @@ REGULAR_EXPRESSION - + STRING .git TYPE @@ -1019,7 +1021,7 @@ REGULAR_EXPRESSION - + STRING .gitignore TYPE @@ -1027,20 +1029,21 @@ PROTECTED - + PROXY_NAME Remove SCM metadata PROXY_TOOLTIP - Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems. + Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems. STATE - + PATTERNS_ARRAY REGULAR_EXPRESSION - + STRING classes.nib TYPE @@ -1048,7 +1051,7 @@ REGULAR_EXPRESSION - + STRING designable.db TYPE @@ -1056,7 +1059,7 @@ REGULAR_EXPRESSION - + STRING info.nib TYPE @@ -1064,20 +1067,21 @@ PROTECTED - + PROXY_NAME Optimize nib files PROXY_TOOLTIP - Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles. + Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles. STATE - + PATTERNS_ARRAY REGULAR_EXPRESSION - + STRING Resources Disabled TYPE @@ -1085,31 +1089,31 @@ PROTECTED - + PROXY_NAME Remove Resources Disabled folders PROXY_TOOLTIP Remove "Resources Disabled" folders. STATE - + SEPARATOR - + NAME ZeroTier One PAYLOAD_ONLY - + TREAT_MISSING_PRESENTATION_DOCUMENTS_AS_WARNING - + SHARED_GLOBAL_DATA IC_REQUIREMENT_JAVASCRIPT_SHARED_SOURCE_CODE - + TYPE 0 diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 3066eb788..5eb6c639c 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -1,5 +1,5 @@ - + @@ -21,10 +21,10 @@ - + - + @@ -62,7 +62,7 @@ - + @@ -515,10 +515,10 @@ - + - + diff --git a/include/ZeroTierDebug.h b/include/ZeroTierDebug.h index 2e9cc2c5a..22ac0cdd5 100644 --- a/include/ZeroTierDebug.h +++ b/include/ZeroTierDebug.h @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ /** * @file @@ -29,20 +24,20 @@ #include #define ZT_MSG_INFO true -#define ZT_COLOR true +#define ZT_COLOR true // Debug output colors #if defined(__APPLE__) #include "TargetConditionals.h" #endif #if defined(ZT_COLOR) && ! defined(_WIN32) && ! defined(__ANDROID__) && ! defined(TARGET_OS_IPHONE) && ! defined(TARGET_IPHONE_SIMULATOR) && ! defined(__APP_FRAMEWORK__) -#define ZT_RED "\x1B[31m" -#define ZT_GRN "\x1B[32m" -#define ZT_YEL "\x1B[33m" -#define ZT_BLU "\x1B[34m" -#define ZT_MAG "\x1B[35m" -#define ZT_CYN "\x1B[36m" -#define ZT_WHT "\x1B[37m" +#define ZT_RED "\x1B[31m" +#define ZT_GRN "\x1B[32m" +#define ZT_YEL "\x1B[33m" +#define ZT_BLU "\x1B[34m" +#define ZT_MAG "\x1B[35m" +#define ZT_CYN "\x1B[36m" +#define ZT_WHT "\x1B[37m" #define ZT_RESET "\x1B[0m" #else #define ZT_RED @@ -90,7 +85,7 @@ #else #define DEBUG_INFO(fmt, args...) #endif -#else // blank +#else // blank #if defined(_WIN32) #define DEBUG_INFO(...) #else @@ -98,4 +93,4 @@ #endif #endif -#endif // _H +#endif // _H diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 8aa701a8f..1f09c99c7 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ /* * This defines the external C API for ZeroTier's core network virtualization @@ -293,74 +288,74 @@ extern "C" { #define ZT_RULE_PACKET_CHARACTERISTICS_TCP_FIN 0x0000000000000001ULL // Fields in remote trace dictionaries -#define ZT_REMOTE_TRACE_FIELD__EVENT "event" -#define ZT_REMOTE_TRACE_FIELD__NODE_ID "nodeId" -#define ZT_REMOTE_TRACE_FIELD__PACKET_ID "packetId" -#define ZT_REMOTE_TRACE_FIELD__PACKET_VERB "packetVerb" -#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_ID "packetTrustedPathId" +#define ZT_REMOTE_TRACE_FIELD__EVENT "event" +#define ZT_REMOTE_TRACE_FIELD__NODE_ID "nodeId" +#define ZT_REMOTE_TRACE_FIELD__PACKET_ID "packetId" +#define ZT_REMOTE_TRACE_FIELD__PACKET_VERB "packetVerb" +#define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_ID "packetTrustedPathId" #define ZT_REMOTE_TRACE_FIELD__PACKET_TRUSTED_PATH_APPROVED "packetTrustedPathApproved" -#define ZT_REMOTE_TRACE_FIELD__PACKET_HOPS "packetHops" -#define ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR "remoteZtAddr" -#define ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR "remotePhyAddr" -#define ZT_REMOTE_TRACE_FIELD__LOCAL_ZTADDR "localZtAddr" -#define ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR "localPhyAddr" -#define ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET "localSocket" -#define ZT_REMOTE_TRACE_FIELD__IP_SCOPE "phyAddrIpScope" -#define ZT_REMOTE_TRACE_FIELD__NETWORK_ID "networkId" -#define ZT_REMOTE_TRACE_FIELD__SOURCE_ZTADDR "sourceZtAddr" -#define ZT_REMOTE_TRACE_FIELD__DEST_ZTADDR "destZtAddr" -#define ZT_REMOTE_TRACE_FIELD__SOURCE_MAC "sourceMac" -#define ZT_REMOTE_TRACE_FIELD__DEST_MAC "destMac" -#define ZT_REMOTE_TRACE_FIELD__ETHERTYPE "etherType" -#define ZT_REMOTE_TRACE_FIELD__VLAN_ID "vlanId" -#define ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH "frameLength" -#define ZT_REMOTE_TRACE_FIELD__FRAME_DATA "frameData" -#define ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_NOTEE "filterNoTee" -#define ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_INBOUND "filterInbound" -#define ZT_REMOTE_TRACE_FIELD__FILTER_RESULT "filterResult" -#define ZT_REMOTE_TRACE_FIELD__FILTER_BASE_RULE_LOG "filterBaseRuleLog" -#define ZT_REMOTE_TRACE_FIELD__FILTER_CAP_RULE_LOG "filterCapRuleLog" -#define ZT_REMOTE_TRACE_FIELD__FILTER_CAP_ID "filterMatchingCapId" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE "credType" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID "credId" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP "credTs" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO "credInfo" -#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO "credIssuedTo" +#define ZT_REMOTE_TRACE_FIELD__PACKET_HOPS "packetHops" +#define ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR "remoteZtAddr" +#define ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR "remotePhyAddr" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_ZTADDR "localZtAddr" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR "localPhyAddr" +#define ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET "localSocket" +#define ZT_REMOTE_TRACE_FIELD__IP_SCOPE "phyAddrIpScope" +#define ZT_REMOTE_TRACE_FIELD__NETWORK_ID "networkId" +#define ZT_REMOTE_TRACE_FIELD__SOURCE_ZTADDR "sourceZtAddr" +#define ZT_REMOTE_TRACE_FIELD__DEST_ZTADDR "destZtAddr" +#define ZT_REMOTE_TRACE_FIELD__SOURCE_MAC "sourceMac" +#define ZT_REMOTE_TRACE_FIELD__DEST_MAC "destMac" +#define ZT_REMOTE_TRACE_FIELD__ETHERTYPE "etherType" +#define ZT_REMOTE_TRACE_FIELD__VLAN_ID "vlanId" +#define ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH "frameLength" +#define ZT_REMOTE_TRACE_FIELD__FRAME_DATA "frameData" +#define ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_NOTEE "filterNoTee" +#define ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_INBOUND "filterInbound" +#define ZT_REMOTE_TRACE_FIELD__FILTER_RESULT "filterResult" +#define ZT_REMOTE_TRACE_FIELD__FILTER_BASE_RULE_LOG "filterBaseRuleLog" +#define ZT_REMOTE_TRACE_FIELD__FILTER_CAP_RULE_LOG "filterCapRuleLog" +#define ZT_REMOTE_TRACE_FIELD__FILTER_CAP_ID "filterMatchingCapId" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE "credType" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID "credId" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP "credTs" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO "credInfo" +#define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO "credIssuedTo" #define ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET "credRevocationTarget" -#define ZT_REMOTE_TRACE_FIELD__REASON "reason" -#define ZT_REMOTE_TRACE_FIELD__NETWORK_CONTROLLER_ID "networkControllerId" +#define ZT_REMOTE_TRACE_FIELD__REASON "reason" +#define ZT_REMOTE_TRACE_FIELD__NETWORK_CONTROLLER_ID "networkControllerId" // Event types in remote traces -#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE 0x1000 -#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH 0x1001 -#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH 0x1002 -#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED 0x1003 -#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE 0x1004 -#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID 0x1005 -#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO 0x1006 +#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE 0x1000 +#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH 0x1001 +#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH 0x1002 +#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED 0x1003 +#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE 0x1004 +#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID 0x1005 +#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO 0x1006 #define ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED 0x2000 #define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED 0x2001 #define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED 0x2002 -#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED 0x2003 -#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED 0x2004 -#define ZT_REMOTE_TRACE_EVENT__NETWORK_CONFIG_REQUEST_SENT 0x2005 -#define ZT_REMOTE_TRACE_EVENT__NETWORK_FILTER_TRACE 0x2006 +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED 0x2003 +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED 0x2004 +#define ZT_REMOTE_TRACE_EVENT__NETWORK_CONFIG_REQUEST_SENT 0x2005 +#define ZT_REMOTE_TRACE_EVENT__NETWORK_FILTER_TRACE 0x2006 // Event types in remote traces in hex string form -#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE_S "1000" -#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S "1001" -#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S "1002" -#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S "1003" -#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE_S "1004" -#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S "1005" -#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO_S "1006" +#define ZT_REMOTE_TRACE_EVENT__RESETTING_PATHS_IN_SCOPE_S "1000" +#define ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S "1001" +#define ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S "1002" +#define ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S "1003" +#define ZT_REMOTE_TRACE_EVENT__PACKET_MAC_FAILURE_S "1004" +#define ZT_REMOTE_TRACE_EVENT__PACKET_INVALID_S "1005" +#define ZT_REMOTE_TRACE_EVENT__DROPPED_HELLO_S "1006" #define ZT_REMOTE_TRACE_EVENT__OUTGOING_NETWORK_FRAME_DROPPED_S "2000" #define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_ACCESS_DENIED_S "2001" #define ZT_REMOTE_TRACE_EVENT__INCOMING_NETWORK_FRAME_DROPPED_S "2002" -#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S "2003" -#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S "2004" -#define ZT_REMOTE_TRACE_EVENT__NETWORK_CONFIG_REQUEST_SENT_S "2005" -#define ZT_REMOTE_TRACE_EVENT__NETWORK_FILTER_TRACE_S "2006" +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_REJECTED_S "2003" +#define ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S "2004" +#define ZT_REMOTE_TRACE_EVENT__NETWORK_CONFIG_REQUEST_SENT_S "2005" +#define ZT_REMOTE_TRACE_EVENT__NETWORK_FILTER_TRACE_S "2006" /****************************************************************************/ /* Structures and other types */ @@ -375,49 +370,49 @@ extern "C" { * problem. */ enum ZT_ResultCode { - /** - * Operation completed normally - */ - ZT_RESULT_OK = 0, + /** + * Operation completed normally + */ + ZT_RESULT_OK = 0, - /** - * Call produced no error but no action was taken - */ - ZT_RESULT_OK_IGNORED = 1, + /** + * Call produced no error but no action was taken + */ + ZT_RESULT_OK_IGNORED = 1, - // Fatal errors (>=100, <1000) + // Fatal errors (>=100, <1000) - /** - * Ran out of memory - */ - ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY = 100, + /** + * Ran out of memory + */ + ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY = 100, - /** - * Data store is not writable or has failed - */ - ZT_RESULT_FATAL_ERROR_DATA_STORE_FAILED = 101, + /** + * Data store is not writable or has failed + */ + ZT_RESULT_FATAL_ERROR_DATA_STORE_FAILED = 101, - /** - * Internal error (e.g. unexpected exception indicating bug or build problem) - */ - ZT_RESULT_FATAL_ERROR_INTERNAL = 102, + /** + * Internal error (e.g. unexpected exception indicating bug or build problem) + */ + ZT_RESULT_FATAL_ERROR_INTERNAL = 102, - // Non-fatal errors (>1000) + // Non-fatal errors (>1000) - /** - * Network ID not valid - */ - ZT_RESULT_ERROR_NETWORK_NOT_FOUND = 1000, + /** + * Network ID not valid + */ + ZT_RESULT_ERROR_NETWORK_NOT_FOUND = 1000, - /** - * The requested operation is not supported on this version or build - */ - ZT_RESULT_ERROR_UNSUPPORTED_OPERATION = 1001, + /** + * The requested operation is not supported on this version or build + */ + ZT_RESULT_ERROR_UNSUPPORTED_OPERATION = 1001, - /** - * The requested operation was given a bad parameter or was called in an invalid state - */ - ZT_RESULT_ERROR_BAD_PARAMETER = 1002 + /** + * The requested operation was given a bad parameter or was called in an invalid state + */ + ZT_RESULT_ERROR_BAD_PARAMETER = 1002 }; /** @@ -430,133 +425,133 @@ enum ZT_ResultCode { * Status codes sent to status update callback when things happen */ enum ZT_Event { - /** - * Node has been initialized - * - * This is the first event generated, and is always sent. It may occur - * before Node's constructor returns. - * - * Meta-data: none - */ - ZT_EVENT_UP = 0, + /** + * Node has been initialized + * + * This is the first event generated, and is always sent. It may occur + * before Node's constructor returns. + * + * Meta-data: none + */ + ZT_EVENT_UP = 0, - /** - * Node is offline -- network does not seem to be reachable by any available strategy - * - * Meta-data: none - */ - ZT_EVENT_OFFLINE = 1, + /** + * Node is offline -- network does not seem to be reachable by any available strategy + * + * Meta-data: none + */ + ZT_EVENT_OFFLINE = 1, - /** - * Node is online -- at least one upstream node appears reachable - * - * Meta-data: none - */ - ZT_EVENT_ONLINE = 2, + /** + * Node is online -- at least one upstream node appears reachable + * + * Meta-data: none + */ + ZT_EVENT_ONLINE = 2, - /** - * Node is shutting down - * - * This is generated within Node's destructor when it is being shut down. - * It's done for convenience, since cleaning up other state in the event - * handler may appear more idiomatic. - * - * Meta-data: none - */ - ZT_EVENT_DOWN = 3, + /** + * Node is shutting down + * + * This is generated within Node's destructor when it is being shut down. + * It's done for convenience, since cleaning up other state in the event + * handler may appear more idiomatic. + * + * Meta-data: none + */ + ZT_EVENT_DOWN = 3, - /** - * Your identity has collided with another node's ZeroTier address - * - * This happens if two different public keys both hash (via the algorithm - * in Identity::generate()) to the same 40-bit ZeroTier address. - * - * This is something you should "never" see, where "never" is defined as - * once per 2^39 new node initializations / identity creations. If you do - * see it, you're going to see it very soon after a node is first - * initialized. - * - * This is reported as an event rather than a return code since it's - * detected asynchronously via error messages from authoritative nodes. - * - * If this occurs, you must shut down and delete the node, delete the - * identity.secret record/file from the data store, and restart to generate - * a new identity. If you don't do this, you will not be able to communicate - * with other nodes. - * - * We'd automate this process, but we don't think silently deleting - * private keys or changing our address without telling the calling code - * is good form. It violates the principle of least surprise. - * - * You can technically get away with not handling this, but we recommend - * doing so in a mature reliable application. Besides, handling this - * condition is a good way to make sure it never arises. It's like how - * umbrellas prevent rain and smoke detectors prevent fires. They do, right? - * - * Meta-data: none - */ - ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION = 4, + /** + * Your identity has collided with another node's ZeroTier address + * + * This happens if two different public keys both hash (via the algorithm + * in Identity::generate()) to the same 40-bit ZeroTier address. + * + * This is something you should "never" see, where "never" is defined as + * once per 2^39 new node initializations / identity creations. If you do + * see it, you're going to see it very soon after a node is first + * initialized. + * + * This is reported as an event rather than a return code since it's + * detected asynchronously via error messages from authoritative nodes. + * + * If this occurs, you must shut down and delete the node, delete the + * identity.secret record/file from the data store, and restart to generate + * a new identity. If you don't do this, you will not be able to communicate + * with other nodes. + * + * We'd automate this process, but we don't think silently deleting + * private keys or changing our address without telling the calling code + * is good form. It violates the principle of least surprise. + * + * You can technically get away with not handling this, but we recommend + * doing so in a mature reliable application. Besides, handling this + * condition is a good way to make sure it never arises. It's like how + * umbrellas prevent rain and smoke detectors prevent fires. They do, right? + * + * Meta-data: none + */ + ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION = 4, - /** - * Trace (debugging) message - * - * These events are only generated if this is a TRACE-enabled build. - * - * Meta-data: C string, TRACE message - */ - ZT_EVENT_TRACE = 5, + /** + * Trace (debugging) message + * + * These events are only generated if this is a TRACE-enabled build. + * + * Meta-data: C string, TRACE message + */ + ZT_EVENT_TRACE = 5, - /** - * VERB_USER_MESSAGE received - * - * These are generated when a VERB_USER_MESSAGE packet is received via - * ZeroTier VL1. - * - * Meta-data: ZT_UserMessage structure - */ - ZT_EVENT_USER_MESSAGE = 6, + /** + * VERB_USER_MESSAGE received + * + * These are generated when a VERB_USER_MESSAGE packet is received via + * ZeroTier VL1. + * + * Meta-data: ZT_UserMessage structure + */ + ZT_EVENT_USER_MESSAGE = 6, - /** - * Remote trace received - * - * These are generated when a VERB_REMOTE_TRACE is received. Note - * that any node can fling one of these at us. It is your responsibility - * to filter and determine if it's worth paying attention to. If it's - * not just drop it. Most nodes that are not active controllers ignore - * these, and controllers only save them if they pertain to networks - * with remote tracing enabled. - * - * Meta-data: ZT_RemoteTrace structure - */ - ZT_EVENT_REMOTE_TRACE = 7 + /** + * Remote trace received + * + * These are generated when a VERB_REMOTE_TRACE is received. Note + * that any node can fling one of these at us. It is your responsibility + * to filter and determine if it's worth paying attention to. If it's + * not just drop it. Most nodes that are not active controllers ignore + * these, and controllers only save them if they pertain to networks + * with remote tracing enabled. + * + * Meta-data: ZT_RemoteTrace structure + */ + ZT_EVENT_REMOTE_TRACE = 7 }; /** * Payload of REMOTE_TRACE event */ typedef struct { - /** - * ZeroTier address of sender - */ - uint64_t origin; + /** + * ZeroTier address of sender + */ + uint64_t origin; - /** - * Null-terminated Dictionary containing key/value pairs sent by origin - * - * This *should* be a dictionary, but the implementation only checks - * that it is a valid non-empty C-style null-terminated string. Be very - * careful to use a well-tested parser to parse this as it represents - * data received from a potentially un-trusted peer on the network. - * Invalid payloads should be dropped. - * - * The contents of data[] may be modified. - */ - char* data; + /** + * Null-terminated Dictionary containing key/value pairs sent by origin + * + * This *should* be a dictionary, but the implementation only checks + * that it is a valid non-empty C-style null-terminated string. Be very + * careful to use a well-tested parser to parse this as it represents + * data received from a potentially un-trusted peer on the network. + * Invalid payloads should be dropped. + * + * The contents of data[] may be modified. + */ + char* data; - /** - * Length of dict[] in bytes, including terminating null - */ - unsigned int len; + /** + * Length of dict[] in bytes, including terminating null + */ + unsigned int len; } ZT_RemoteTrace; /** @@ -570,54 +565,54 @@ typedef struct { * gapped.) */ typedef struct { - /** - * ZeroTier address of sender (least significant 40 bits) - */ - uint64_t origin; + /** + * ZeroTier address of sender (least significant 40 bits) + */ + uint64_t origin; - /** - * User message type ID - */ - uint64_t typeId; + /** + * User message type ID + */ + uint64_t typeId; - /** - * User message data (not including type ID) - */ - const void* data; + /** + * User message data (not including type ID) + */ + const void* data; - /** - * Length of data in bytes - */ - unsigned int length; + /** + * Length of data in bytes + */ + unsigned int length; } ZT_UserMessage; /** * Current node status */ typedef struct { - /** - * 40-bit ZeroTier address of this node - */ - uint64_t address; + /** + * 40-bit ZeroTier address of this node + */ + uint64_t address; - /** - * Public identity in string-serialized form (safe to send to others) - * - * This pointer will remain valid as long as the node exists. - */ - const char* publicIdentity; + /** + * Public identity in string-serialized form (safe to send to others) + * + * This pointer will remain valid as long as the node exists. + */ + const char* publicIdentity; - /** - * Full identity including secret key in string-serialized form - * - * This pointer will remain valid as long as the node exists. - */ - const char* secretIdentity; + /** + * Full identity including secret key in string-serialized form + * + * This pointer will remain valid as long as the node exists. + */ + const char* secretIdentity; - /** - * True if some kind of connectivity appears available - */ - int online; + /** + * True if some kind of connectivity appears available + */ + int online; } ZT_NodeStatus; /** @@ -626,70 +621,70 @@ typedef struct { * This structure is subject to change between versions. */ typedef struct { - /** - * Number of each protocol verb (possible verbs 0..31) received - */ - uint64_t inVerbCounts[32]; + /** + * Number of each protocol verb (possible verbs 0..31) received + */ + uint64_t inVerbCounts[32]; - /** - * Number of bytes for each protocol verb received - */ - uint64_t inVerbBytes[32]; + /** + * Number of bytes for each protocol verb received + */ + uint64_t inVerbBytes[32]; } ZT_NodeStatistics; /** * Virtual network status codes */ enum ZT_VirtualNetworkStatus { - /** - * Waiting for network configuration (also means revision == 0) - */ - ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION = 0, + /** + * Waiting for network configuration (also means revision == 0) + */ + ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION = 0, - /** - * Configuration received and we are authorized - */ - ZT_NETWORK_STATUS_OK = 1, + /** + * Configuration received and we are authorized + */ + ZT_NETWORK_STATUS_OK = 1, - /** - * Netconf master told us 'nope' - */ - ZT_NETWORK_STATUS_ACCESS_DENIED = 2, + /** + * Netconf master told us 'nope' + */ + ZT_NETWORK_STATUS_ACCESS_DENIED = 2, - /** - * Netconf master exists, but this virtual network does not - */ - ZT_NETWORK_STATUS_NOT_FOUND = 3, + /** + * Netconf master exists, but this virtual network does not + */ + ZT_NETWORK_STATUS_NOT_FOUND = 3, - /** - * Initialization of network failed or other internal error - */ - ZT_NETWORK_STATUS_PORT_ERROR = 4, + /** + * Initialization of network failed or other internal error + */ + ZT_NETWORK_STATUS_PORT_ERROR = 4, - /** - * ZeroTier core version too old - */ - ZT_NETWORK_STATUS_CLIENT_TOO_OLD = 5, + /** + * ZeroTier core version too old + */ + ZT_NETWORK_STATUS_CLIENT_TOO_OLD = 5, - /** - * External authentication is required (e.g. SSO) - */ - ZT_NETWORK_STATUS_AUTHENTICATION_REQUIRED = 6 + /** + * External authentication is required (e.g. SSO) + */ + ZT_NETWORK_STATUS_AUTHENTICATION_REQUIRED = 6 }; /** * Virtual network type codes */ enum ZT_VirtualNetworkType { - /** - * Private networks are authorized via certificates of membership - */ - ZT_NETWORK_TYPE_PRIVATE = 0, + /** + * Private networks are authorized via certificates of membership + */ + ZT_NETWORK_TYPE_PRIVATE = 0, - /** - * Public networks have no access control -- they'll always be AUTHORIZED - */ - ZT_NETWORK_TYPE_PUBLIC = 1 + /** + * Public networks have no access control -- they'll always be AUTHORIZED + */ + ZT_NETWORK_TYPE_PUBLIC = 1 }; /** @@ -702,83 +697,83 @@ enum ZT_VirtualNetworkType { * An ACTION with no MATCHes is always taken. */ enum ZT_VirtualNetworkRuleType { - // 0 to 15 reserved for actions + // 0 to 15 reserved for actions - /** - * Drop frame - */ - ZT_NETWORK_RULE_ACTION_DROP = 0, + /** + * Drop frame + */ + ZT_NETWORK_RULE_ACTION_DROP = 0, - /** - * Accept and pass frame - */ - ZT_NETWORK_RULE_ACTION_ACCEPT = 1, + /** + * Accept and pass frame + */ + ZT_NETWORK_RULE_ACTION_ACCEPT = 1, - /** - * Forward a copy of this frame to an observer (by ZT address) - */ - ZT_NETWORK_RULE_ACTION_TEE = 2, + /** + * Forward a copy of this frame to an observer (by ZT address) + */ + ZT_NETWORK_RULE_ACTION_TEE = 2, - /** - * Exactly like TEE but mandates ACKs from observer - */ - ZT_NETWORK_RULE_ACTION_WATCH = 3, + /** + * Exactly like TEE but mandates ACKs from observer + */ + ZT_NETWORK_RULE_ACTION_WATCH = 3, - /** - * Drop and redirect this frame to another node (by ZT address) - */ - ZT_NETWORK_RULE_ACTION_REDIRECT = 4, + /** + * Drop and redirect this frame to another node (by ZT address) + */ + ZT_NETWORK_RULE_ACTION_REDIRECT = 4, - /** - * Stop evaluating rule set (drops unless there are capabilities, etc.) - */ - ZT_NETWORK_RULE_ACTION_BREAK = 5, + /** + * Stop evaluating rule set (drops unless there are capabilities, etc.) + */ + ZT_NETWORK_RULE_ACTION_BREAK = 5, - /** - * Place a matching frame in the specified QoS bucket - */ - ZT_NETWORK_RULE_ACTION_PRIORITY = 6, + /** + * Place a matching frame in the specified QoS bucket + */ + ZT_NETWORK_RULE_ACTION_PRIORITY = 6, - /** - * Maximum ID for an ACTION, anything higher is a MATCH - */ - ZT_NETWORK_RULE_ACTION__MAX_ID = 15, + /** + * Maximum ID for an ACTION, anything higher is a MATCH + */ + ZT_NETWORK_RULE_ACTION__MAX_ID = 15, - // 16 to 63 reserved for match criteria + // 16 to 63 reserved for match criteria - ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS = 24, - ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS = 25, - ZT_NETWORK_RULE_MATCH_VLAN_ID = 26, - ZT_NETWORK_RULE_MATCH_VLAN_PCP = 27, - ZT_NETWORK_RULE_MATCH_VLAN_DEI = 28, - ZT_NETWORK_RULE_MATCH_MAC_SOURCE = 29, - ZT_NETWORK_RULE_MATCH_MAC_DEST = 30, - ZT_NETWORK_RULE_MATCH_IPV4_SOURCE = 31, - ZT_NETWORK_RULE_MATCH_IPV4_DEST = 32, - ZT_NETWORK_RULE_MATCH_IPV6_SOURCE = 33, - ZT_NETWORK_RULE_MATCH_IPV6_DEST = 34, - ZT_NETWORK_RULE_MATCH_IP_TOS = 35, - ZT_NETWORK_RULE_MATCH_IP_PROTOCOL = 36, - ZT_NETWORK_RULE_MATCH_ETHERTYPE = 37, - ZT_NETWORK_RULE_MATCH_ICMP = 38, - ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE = 39, - ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE = 40, - ZT_NETWORK_RULE_MATCH_CHARACTERISTICS = 41, - ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE = 42, - ZT_NETWORK_RULE_MATCH_RANDOM = 43, - ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE = 44, - ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND = 45, - ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 46, - ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 47, - ZT_NETWORK_RULE_MATCH_TAGS_EQUAL = 48, - ZT_NETWORK_RULE_MATCH_TAG_SENDER = 49, - ZT_NETWORK_RULE_MATCH_TAG_RECEIVER = 50, - ZT_NETWORK_RULE_MATCH_INTEGER_RANGE = 51, + ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS = 24, + ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS = 25, + ZT_NETWORK_RULE_MATCH_VLAN_ID = 26, + ZT_NETWORK_RULE_MATCH_VLAN_PCP = 27, + ZT_NETWORK_RULE_MATCH_VLAN_DEI = 28, + ZT_NETWORK_RULE_MATCH_MAC_SOURCE = 29, + ZT_NETWORK_RULE_MATCH_MAC_DEST = 30, + ZT_NETWORK_RULE_MATCH_IPV4_SOURCE = 31, + ZT_NETWORK_RULE_MATCH_IPV4_DEST = 32, + ZT_NETWORK_RULE_MATCH_IPV6_SOURCE = 33, + ZT_NETWORK_RULE_MATCH_IPV6_DEST = 34, + ZT_NETWORK_RULE_MATCH_IP_TOS = 35, + ZT_NETWORK_RULE_MATCH_IP_PROTOCOL = 36, + ZT_NETWORK_RULE_MATCH_ETHERTYPE = 37, + ZT_NETWORK_RULE_MATCH_ICMP = 38, + ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE = 39, + ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE = 40, + ZT_NETWORK_RULE_MATCH_CHARACTERISTICS = 41, + ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE = 42, + ZT_NETWORK_RULE_MATCH_RANDOM = 43, + ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE = 44, + ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND = 45, + ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR = 46, + ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR = 47, + ZT_NETWORK_RULE_MATCH_TAGS_EQUAL = 48, + ZT_NETWORK_RULE_MATCH_TAG_SENDER = 49, + ZT_NETWORK_RULE_MATCH_TAG_RECEIVER = 50, + ZT_NETWORK_RULE_MATCH_INTEGER_RANGE = 51, - /** - * Maximum ID allowed for a MATCH entry in the rules table - */ - ZT_NETWORK_RULE_MATCH__MAX_ID = 63 + /** + * Maximum ID allowed for a MATCH entry in the rules table + */ + ZT_NETWORK_RULE_MATCH__MAX_ID = 63 }; /** @@ -793,229 +788,229 @@ enum ZT_VirtualNetworkRuleType { * a wide table, yet still fast and simple to access in code. */ typedef struct { - /** - * Type and flags - * - * Bits are: NOTTTTTT - * - * N - If true, sense of match is inverted (no effect on actions) - * O - If true, result is ORed with previous instead of ANDed (no effect on actions) - * T - Rule or action type - * - * AND with 0x3f to get type, 0x80 to get NOT bit, and 0x40 to get OR bit. - */ - uint8_t t; + /** + * Type and flags + * + * Bits are: NOTTTTTT + * + * N - If true, sense of match is inverted (no effect on actions) + * O - If true, result is ORed with previous instead of ANDed (no effect on actions) + * T - Rule or action type + * + * AND with 0x3f to get type, 0x80 to get NOT bit, and 0x40 to get OR bit. + */ + uint8_t t; - /** - * Union containing the value of this rule -- which field is used depends on 't' - */ - union { - /** - * IPv6 address in big-endian / network byte order and netmask bits - */ - struct { - uint8_t ip[16]; - uint8_t mask; - } ipv6; + /** + * Union containing the value of this rule -- which field is used depends on 't' + */ + union { + /** + * IPv6 address in big-endian / network byte order and netmask bits + */ + struct { + uint8_t ip[16]; + uint8_t mask; + } ipv6; - /** - * IPv4 address in big-endian / network byte order - */ - struct { - uint32_t ip; - uint8_t mask; - } ipv4; + /** + * IPv4 address in big-endian / network byte order + */ + struct { + uint32_t ip; + uint8_t mask; + } ipv4; - /** - * Integer range match in packet payload - * - * This allows matching of ranges of integers up to 64 bits wide where - * the range is +/- INT32_MAX. It's packed this way so it fits in 16 - * bytes and doesn't enlarge the overall size of this union. - */ - struct { - uint64_t start; // integer range start - uint32_t end; // end of integer range (relative to start, inclusive, 0 for equality w/start) - uint16_t idx; // index in packet of integer - uint8_t format; // bits in integer (range 1-64, ((format&63)+1)) and endianness (MSB 1 for little, 0 for big) - } intRange; + /** + * Integer range match in packet payload + * + * This allows matching of ranges of integers up to 64 bits wide where + * the range is +/- INT32_MAX. It's packed this way so it fits in 16 + * bytes and doesn't enlarge the overall size of this union. + */ + struct { + uint64_t start; // integer range start + uint32_t end; // end of integer range (relative to start, inclusive, 0 for equality w/start) + uint16_t idx; // index in packet of integer + uint8_t format; // bits in integer (range 1-64, ((format&63)+1)) and endianness (MSB 1 for little, 0 for big) + } intRange; - /** - * Packet characteristic flags being matched - */ - uint64_t characteristics; + /** + * Packet characteristic flags being matched + */ + uint64_t characteristics; - /** - * IP port range -- start-end inclusive -- host byte order - */ - uint16_t port[2]; + /** + * IP port range -- start-end inclusive -- host byte order + */ + uint16_t port[2]; - /** - * 40-bit ZeroTier address (in least significant bits, host byte order) - */ - uint64_t zt; + /** + * 40-bit ZeroTier address (in least significant bits, host byte order) + */ + uint64_t zt; - /** - * 0 = never, UINT32_MAX = always - */ - uint32_t randomProbability; + /** + * 0 = never, UINT32_MAX = always + */ + uint32_t randomProbability; - /** - * 48-bit Ethernet MAC address in big-endian order - */ - uint8_t mac[6]; + /** + * 48-bit Ethernet MAC address in big-endian order + */ + uint8_t mac[6]; - /** - * VLAN ID in host byte order - */ - uint16_t vlanId; + /** + * VLAN ID in host byte order + */ + uint16_t vlanId; - /** - * VLAN PCP (least significant 3 bits) - */ - uint8_t vlanPcp; + /** + * VLAN PCP (least significant 3 bits) + */ + uint8_t vlanPcp; - /** - * VLAN DEI (single bit / boolean) - */ - uint8_t vlanDei; + /** + * VLAN DEI (single bit / boolean) + */ + uint8_t vlanDei; - /** - * Ethernet type in host byte order - */ - uint16_t etherType; + /** + * Ethernet type in host byte order + */ + uint16_t etherType; - /** - * IP protocol - */ - uint8_t ipProtocol; + /** + * IP protocol + */ + uint8_t ipProtocol; - /** - * IP type of service a.k.a. DSCP field - */ - struct { - uint8_t mask; - uint8_t value[2]; - } ipTos; + /** + * IP type of service a.k.a. DSCP field + */ + struct { + uint8_t mask; + uint8_t value[2]; + } ipTos; - /** - * Ethernet packet size in host byte order (start-end, inclusive) - */ - uint16_t frameSize[2]; + /** + * Ethernet packet size in host byte order (start-end, inclusive) + */ + uint16_t frameSize[2]; - /** - * ICMP type and code - */ - struct { - uint8_t type; // ICMP type, always matched - uint8_t code; // ICMP code if matched - uint8_t flags; // flag 0x01 means also match code, otherwise only match type - } icmp; + /** + * ICMP type and code + */ + struct { + uint8_t type; // ICMP type, always matched + uint8_t code; // ICMP code if matched + uint8_t flags; // flag 0x01 means also match code, otherwise only match type + } icmp; - /** - * For tag-related rules - */ - struct { - uint32_t id; - uint32_t value; - } tag; + /** + * For tag-related rules + */ + struct { + uint32_t id; + uint32_t value; + } tag; - /** - * Destinations for TEE and REDIRECT - */ - struct { - uint64_t address; - uint32_t flags; - uint16_t length; - } fwd; + /** + * Destinations for TEE and REDIRECT + */ + struct { + uint64_t address; + uint32_t flags; + uint16_t length; + } fwd; - /** - * Quality of Service (QoS) bucket we want a frame to be placed in - */ - uint8_t qosBucket; - } v; + /** + * Quality of Service (QoS) bucket we want a frame to be placed in + */ + uint8_t qosBucket; + } v; } ZT_VirtualNetworkRule; /** * A route to be pushed on a virtual network */ typedef struct { - /** - * Target network / netmask bits (in port field) or NULL or 0.0.0.0/0 for default - */ - struct sockaddr_storage target; + /** + * Target network / netmask bits (in port field) or NULL or 0.0.0.0/0 for default + */ + struct sockaddr_storage target; - /** - * Gateway IP address (port ignored) or NULL (family == 0) for LAN-local (no gateway) - */ - struct sockaddr_storage via; + /** + * Gateway IP address (port ignored) or NULL (family == 0) for LAN-local (no gateway) + */ + struct sockaddr_storage via; - /** - * Route flags - */ - uint16_t flags; + /** + * Route flags + */ + uint16_t flags; - /** - * Route metric (not currently used) - */ - uint16_t metric; + /** + * Route metric (not currently used) + */ + uint16_t metric; } ZT_VirtualNetworkRoute; /** * DNS configuration to be pushed on a virtual network */ typedef struct { - char domain[128]; - struct sockaddr_storage server_addr[ZT_MAX_DNS_SERVERS]; + char domain[128]; + struct sockaddr_storage server_addr[ZT_MAX_DNS_SERVERS]; } ZT_VirtualNetworkDNS; /** * An Ethernet multicast group */ typedef struct { - /** - * MAC address (least significant 48 bits) - */ - uint64_t mac; + /** + * MAC address (least significant 48 bits) + */ + uint64_t mac; - /** - * Additional distinguishing information (usually zero) - */ - unsigned long adi; + /** + * Additional distinguishing information (usually zero) + */ + unsigned long adi; } ZT_MulticastGroup; /** * Virtual network configuration update type */ enum ZT_VirtualNetworkConfigOperation { - /** - * Network is coming up (either for the first time or after service restart) - */ - ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP = 1, + /** + * Network is coming up (either for the first time or after service restart) + */ + ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP = 1, - /** - * Network configuration has been updated - */ - ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE = 2, + /** + * Network configuration has been updated + */ + ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE = 2, - /** - * Network is going down (not permanently) - */ - ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN = 3, + /** + * Network is going down (not permanently) + */ + ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN = 3, - /** - * Network is going down permanently (leave/delete) - */ - ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY = 4 + /** + * Network is going down permanently (leave/delete) + */ + ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY = 4 }; /** * What trust hierarchy role does this peer have? */ enum ZT_PeerRole { - ZT_PEER_ROLE_LEAF = 0, // ordinary node - ZT_PEER_ROLE_MOON = 1, // moon root - ZT_PEER_ROLE_PLANET = 2 // planetary root + ZT_PEER_ROLE_LEAF = 0, // ordinary node + ZT_PEER_ROLE_MOON = 1, // moon root + ZT_PEER_ROLE_PLANET = 2 // planetary root }; /** @@ -1027,478 +1022,478 @@ enum ZT_Vendor { ZT_VENDOR_UNSPECIFIED = 0, ZT_VENDOR_ZEROTIER = 1 }; * Platform type */ enum ZT_Platform { - ZT_PLATFORM_UNSPECIFIED = 0, - ZT_PLATFORM_LINUX = 1, - ZT_PLATFORM_WINDOWS = 2, - ZT_PLATFORM_MACOS = 3, - ZT_PLATFORM_ANDROID = 4, - ZT_PLATFORM_IOS = 5, - ZT_PLATFORM_SOLARIS_SMARTOS = 6, - ZT_PLATFORM_FREEBSD = 7, - ZT_PLATFORM_NETBSD = 8, - ZT_PLATFORM_OPENBSD = 9, - ZT_PLATFORM_RISCOS = 10, - ZT_PLATFORM_VXWORKS = 11, - ZT_PLATFORM_FREERTOS = 12, - ZT_PLATFORM_SYSBIOS = 13, - ZT_PLATFORM_HURD = 14, - ZT_PLATFORM_WEB = 15 + ZT_PLATFORM_UNSPECIFIED = 0, + ZT_PLATFORM_LINUX = 1, + ZT_PLATFORM_WINDOWS = 2, + ZT_PLATFORM_MACOS = 3, + ZT_PLATFORM_ANDROID = 4, + ZT_PLATFORM_IOS = 5, + ZT_PLATFORM_SOLARIS_SMARTOS = 6, + ZT_PLATFORM_FREEBSD = 7, + ZT_PLATFORM_NETBSD = 8, + ZT_PLATFORM_OPENBSD = 9, + ZT_PLATFORM_RISCOS = 10, + ZT_PLATFORM_VXWORKS = 11, + ZT_PLATFORM_FREERTOS = 12, + ZT_PLATFORM_SYSBIOS = 13, + ZT_PLATFORM_HURD = 14, + ZT_PLATFORM_WEB = 15 }; /** * Architecture type */ enum ZT_Architecture { - ZT_ARCHITECTURE_UNSPECIFIED = 0, - ZT_ARCHITECTURE_X86 = 1, - ZT_ARCHITECTURE_X64 = 2, - ZT_ARCHITECTURE_ARM32 = 3, - ZT_ARCHITECTURE_ARM64 = 4, - ZT_ARCHITECTURE_MIPS32 = 5, - ZT_ARCHITECTURE_MIPS64 = 6, - ZT_ARCHITECTURE_POWER32 = 7, - ZT_ARCHITECTURE_POWER64 = 8, - ZT_ARCHITECTURE_OPENRISC32 = 9, - ZT_ARCHITECTURE_OPENRISC64 = 10, - ZT_ARCHITECTURE_SPARC32 = 11, - ZT_ARCHITECTURE_SPARC64 = 12, - ZT_ARCHITECTURE_DOTNET_CLR = 13, - ZT_ARCHITECTURE_JAVA_JVM = 14, - ZT_ARCHITECTURE_WEB = 15, - ZT_ARCHITECTURE_S390X = 16, - ZT_ARCHITECTURE_LOONGARCH64 = 17 + ZT_ARCHITECTURE_UNSPECIFIED = 0, + ZT_ARCHITECTURE_X86 = 1, + ZT_ARCHITECTURE_X64 = 2, + ZT_ARCHITECTURE_ARM32 = 3, + ZT_ARCHITECTURE_ARM64 = 4, + ZT_ARCHITECTURE_MIPS32 = 5, + ZT_ARCHITECTURE_MIPS64 = 6, + ZT_ARCHITECTURE_POWER32 = 7, + ZT_ARCHITECTURE_POWER64 = 8, + ZT_ARCHITECTURE_OPENRISC32 = 9, + ZT_ARCHITECTURE_OPENRISC64 = 10, + ZT_ARCHITECTURE_SPARC32 = 11, + ZT_ARCHITECTURE_SPARC64 = 12, + ZT_ARCHITECTURE_DOTNET_CLR = 13, + ZT_ARCHITECTURE_JAVA_JVM = 14, + ZT_ARCHITECTURE_WEB = 15, + ZT_ARCHITECTURE_S390X = 16, + ZT_ARCHITECTURE_LOONGARCH64 = 17 }; /** * Virtual network configuration */ typedef struct { - /** - * 64-bit ZeroTier network ID - */ - uint64_t nwid; + /** + * 64-bit ZeroTier network ID + */ + uint64_t nwid; - /** - * Ethernet MAC (48 bits) that should be assigned to port - */ - uint64_t mac; + /** + * Ethernet MAC (48 bits) that should be assigned to port + */ + uint64_t mac; - /** - * Network name (from network configuration master) - */ - char name[ZT_MAX_NETWORK_SHORT_NAME_LENGTH + 1]; + /** + * Network name (from network configuration master) + */ + char name[ZT_MAX_NETWORK_SHORT_NAME_LENGTH + 1]; - /** - * Network configuration request status - */ - enum ZT_VirtualNetworkStatus status; + /** + * Network configuration request status + */ + enum ZT_VirtualNetworkStatus status; - /** - * Network type - */ - enum ZT_VirtualNetworkType type; + /** + * Network type + */ + enum ZT_VirtualNetworkType type; - /** - * Maximum interface MTU - */ - unsigned int mtu; + /** + * Maximum interface MTU + */ + unsigned int mtu; - /** - * If nonzero, the network this port belongs to indicates DHCP availability - * - * This is a suggestion. The underlying implementation is free to ignore it - * for security or other reasons. This is simply a netconf parameter that - * means 'DHCP is available on this network.' - */ - int dhcp; + /** + * If nonzero, the network this port belongs to indicates DHCP availability + * + * This is a suggestion. The underlying implementation is free to ignore it + * for security or other reasons. This is simply a netconf parameter that + * means 'DHCP is available on this network.' + */ + int dhcp; - /** - * If nonzero, this port is allowed to bridge to other networks - * - * This is informational. If this is false (0), bridged packets will simply - * be dropped and bridging won't work. - */ - int bridge; + /** + * If nonzero, this port is allowed to bridge to other networks + * + * This is informational. If this is false (0), bridged packets will simply + * be dropped and bridging won't work. + */ + int bridge; - /** - * If nonzero, this network supports and allows broadcast (ff:ff:ff:ff:ff:ff) traffic - */ - int broadcastEnabled; + /** + * If nonzero, this network supports and allows broadcast (ff:ff:ff:ff:ff:ff) traffic + */ + int broadcastEnabled; - /** - * If the network is in PORT_ERROR state, this is the (negative) error code most recently reported - */ - int portError; + /** + * If the network is in PORT_ERROR state, this is the (negative) error code most recently reported + */ + int portError; - /** - * Revision number as reported by controller or 0 if still waiting for config - */ - unsigned long netconfRevision; + /** + * Revision number as reported by controller or 0 if still waiting for config + */ + unsigned long netconfRevision; - /** - * Number of assigned addresses - */ - unsigned int assignedAddressCount; + /** + * Number of assigned addresses + */ + unsigned int assignedAddressCount; - /** - * ZeroTier-assigned addresses (in sockaddr_storage structures) - * - * For IP, the port number of the sockaddr_XX structure contains the number - * of bits in the address netmask. Only the IP address and port are used. - * Other fields like interface number can be ignored. - * - * This is only used for ZeroTier-managed address assignments sent by the - * virtual network's configuration master. - */ - struct sockaddr_storage assignedAddresses[ZT_MAX_ZT_ASSIGNED_ADDRESSES]; + /** + * ZeroTier-assigned addresses (in sockaddr_storage structures) + * + * For IP, the port number of the sockaddr_XX structure contains the number + * of bits in the address netmask. Only the IP address and port are used. + * Other fields like interface number can be ignored. + * + * This is only used for ZeroTier-managed address assignments sent by the + * virtual network's configuration master. + */ + struct sockaddr_storage assignedAddresses[ZT_MAX_ZT_ASSIGNED_ADDRESSES]; - /** - * Number of ZT-pushed routes - */ - unsigned int routeCount; + /** + * Number of ZT-pushed routes + */ + unsigned int routeCount; - /** - * Routes (excluding those implied by assigned addresses and their masks) - */ - ZT_VirtualNetworkRoute routes[ZT_MAX_NETWORK_ROUTES]; + /** + * Routes (excluding those implied by assigned addresses and their masks) + */ + ZT_VirtualNetworkRoute routes[ZT_MAX_NETWORK_ROUTES]; - /** - * Number of multicast groups subscribed - */ - unsigned int multicastSubscriptionCount; + /** + * Number of multicast groups subscribed + */ + unsigned int multicastSubscriptionCount; - /** - * Multicast groups to which this network's device is subscribed - */ - struct { - uint64_t mac; /* MAC in lower 48 bits */ - uint32_t adi; /* Additional distinguishing information, usually zero except for IPv4 ARP groups */ - } multicastSubscriptions[ZT_MAX_MULTICAST_SUBSCRIPTIONS]; + /** + * Multicast groups to which this network's device is subscribed + */ + struct { + uint64_t mac; /* MAC in lower 48 bits */ + uint32_t adi; /* Additional distinguishing information, usually zero except for IPv4 ARP groups */ + } multicastSubscriptions[ZT_MAX_MULTICAST_SUBSCRIPTIONS]; - /** - * Network specific DNS configuration - */ - ZT_VirtualNetworkDNS dns; + /** + * Network specific DNS configuration + */ + ZT_VirtualNetworkDNS dns; - /** - * sso enabled - */ - bool ssoEnabled; + /** + * sso enabled + */ + bool ssoEnabled; - /** - * SSO version - */ - uint64_t ssoVersion; + /** + * SSO version + */ + uint64_t ssoVersion; - /** - * If the status us AUTHENTICATION_REQUIRED, this may contain a URL for authentication. - */ - char authenticationURL[2048]; + /** + * If the status us AUTHENTICATION_REQUIRED, this may contain a URL for authentication. + */ + char authenticationURL[2048]; - /** - * Time that current authentication expires. only valid if ssoEnabled is true - */ - uint64_t authenticationExpiryTime; + /** + * Time that current authentication expires. only valid if ssoEnabled is true + */ + uint64_t authenticationExpiryTime; - /** - * OIDC issuer URL. - */ - char issuerURL[2048]; + /** + * OIDC issuer URL. + */ + char issuerURL[2048]; - /** - * central base URL. - */ - char centralAuthURL[2048]; + /** + * central base URL. + */ + char centralAuthURL[2048]; - /** - * sso nonce - */ - char ssoNonce[128]; + /** + * sso nonce + */ + char ssoNonce[128]; - /** - * sso state - */ - char ssoState[256]; + /** + * sso state + */ + char ssoState[256]; - /** - * oidc client id - */ - char ssoClientID[256]; + /** + * oidc client id + */ + char ssoClientID[256]; - /** - * sso provider - **/ - char ssoProvider[64]; + /** + * sso provider + **/ + char ssoProvider[64]; } ZT_VirtualNetworkConfig; /** * A list of networks */ typedef struct { - ZT_VirtualNetworkConfig* networks; - unsigned long networkCount; + ZT_VirtualNetworkConfig* networks; + unsigned long networkCount; } ZT_VirtualNetworkList; /** * Physical path configuration */ typedef struct { - /** - * If non-zero set this physical network path to be trusted to disable encryption and authentication - */ - uint64_t trustedPathId; + /** + * If non-zero set this physical network path to be trusted to disable encryption and authentication + */ + uint64_t trustedPathId; - /** - * Physical path MTU from ZT_MIN_PHYSMTU and ZT_MAX_PHYSMTU or <= 0 to use default - */ - int mtu; + /** + * Physical path MTU from ZT_MIN_PHYSMTU and ZT_MAX_PHYSMTU or <= 0 to use default + */ + int mtu; } ZT_PhysicalPathConfiguration; /** * Physical network path to a peer */ typedef struct { - /** - * Address of endpoint - */ - struct sockaddr_storage address; + /** + * Address of endpoint + */ + struct sockaddr_storage address; - /** - * Time of last send in milliseconds or 0 for never - */ - uint64_t lastSend; + /** + * Time of last send in milliseconds or 0 for never + */ + uint64_t lastSend; - /** - * Time of last receive in milliseconds or 0 for never - */ - uint64_t lastReceive; + /** + * Time of last receive in milliseconds or 0 for never + */ + uint64_t lastReceive; - /** - * Is this a trusted path? If so this will be its nonzero ID. - */ - uint64_t trustedPathId; + /** + * Is this a trusted path? If so this will be its nonzero ID. + */ + uint64_t trustedPathId; - /** - * Mean latency - */ - float latencyMean; + /** + * Mean latency + */ + float latencyMean; - /** - * Maximum observed latency - */ - float latencyMax; + /** + * Maximum observed latency + */ + float latencyMax; - /** - * Variance of latency - */ - float latencyVariance; + /** + * Variance of latency + */ + float latencyVariance; - /** - * Packet loss ratio - */ - float packetLossRatio; + /** + * Packet loss ratio + */ + float packetLossRatio; - /** - * Packet error ratio - */ - float packetErrorRatio; + /** + * Packet error ratio + */ + float packetErrorRatio; - /** - * Number of flows assigned to this path - */ - uint16_t assignedFlowCount; + /** + * Number of flows assigned to this path + */ + uint16_t assignedFlowCount; - /** - * Address scope - */ - uint8_t scope; + /** + * Address scope + */ + uint8_t scope; - /** - * Relative quality value - */ - float relativeQuality; + /** + * Relative quality value + */ + float relativeQuality; - /** - * Name of physical interface this path resides on - */ - char ifname[ZT_MAX_PHYSIFNAME]; + /** + * Name of physical interface this path resides on + */ + char ifname[ZT_MAX_PHYSIFNAME]; - /** - * Pointer to PhySocket object for this path - */ - uint64_t localSocket; + /** + * Pointer to PhySocket object for this path + */ + uint64_t localSocket; - /** - * Local port corresponding to this path's localSocket - */ - uint16_t localPort; + /** + * Local port corresponding to this path's localSocket + */ + uint16_t localPort; - /** - * Is path expired? - */ - int expired; + /** + * Is path expired? + */ + int expired; - /** - * Whether this path is currently included in the bond - */ - uint8_t bonded; + /** + * Whether this path is currently included in the bond + */ + uint8_t bonded; - /** - * Whether this path is currently eligible to be used in a bond - */ - uint8_t eligible; + /** + * Whether this path is currently eligible to be used in a bond + */ + uint8_t eligible; - /** - * The capacity of this link (as given to bonding layer) - */ - uint32_t linkSpeed; + /** + * The capacity of this link (as given to bonding layer) + */ + uint32_t linkSpeed; - /** - * Is path preferred? - */ - int preferred; + /** + * Is path preferred? + */ + int preferred; } ZT_PeerPhysicalPath; /** * Peer status result buffer */ typedef struct { - /** - * ZeroTier address (40 bits) - */ - uint64_t address; + /** + * ZeroTier address (40 bits) + */ + uint64_t address; - /** - * Remote major version or -1 if not known - */ - int versionMajor; + /** + * Remote major version or -1 if not known + */ + int versionMajor; - /** - * Remote minor version or -1 if not known - */ - int versionMinor; + /** + * Remote minor version or -1 if not known + */ + int versionMinor; - /** - * Remote revision or -1 if not known - */ - int versionRev; + /** + * Remote revision or -1 if not known + */ + int versionRev; - /** - * Last measured latency in milliseconds or -1 if unknown - */ - int latency; + /** + * Last measured latency in milliseconds or -1 if unknown + */ + int latency; - /** - * What trust hierarchy role does this device have? - */ - enum ZT_PeerRole role; + /** + * What trust hierarchy role does this device have? + */ + enum ZT_PeerRole role; - /** - * Whether a multi-link bond has formed - */ - bool isBonded; + /** + * Whether a multi-link bond has formed + */ + bool isBonded; - /** - * The bonding policy used to bond to this peer - */ - int bondingPolicy; + /** + * The bonding policy used to bond to this peer + */ + int bondingPolicy; - /** - * The number of links that comprise the bond to this peer that are considered alive - */ - int numAliveLinks; + /** + * The number of links that comprise the bond to this peer that are considered alive + */ + int numAliveLinks; - /** - * The number of links that comprise the bond to this peer - */ - int numTotalLinks; + /** + * The number of links that comprise the bond to this peer + */ + int numTotalLinks; - /** - * The user-specified bond template name - */ - char customBondName[32]; + /** + * The user-specified bond template name + */ + char customBondName[32]; - /** - * Number of paths (size of paths[]) - */ - unsigned int pathCount; + /** + * Number of paths (size of paths[]) + */ + unsigned int pathCount; - /** - * Known network paths to peer - */ - ZT_PeerPhysicalPath paths[ZT_MAX_PEER_NETWORK_PATHS]; + /** + * Known network paths to peer + */ + ZT_PeerPhysicalPath paths[ZT_MAX_PEER_NETWORK_PATHS]; } ZT_Peer; /** * List of peers */ typedef struct { - ZT_Peer* peers; - unsigned long peerCount; + ZT_Peer* peers; + unsigned long peerCount; } ZT_PeerList; /** * ZeroTier core state objects */ enum ZT_StateObjectType { - /** - * Null object -- ignored - */ - ZT_STATE_OBJECT_NULL = 0, + /** + * Null object -- ignored + */ + ZT_STATE_OBJECT_NULL = 0, - /** - * Public address and public key - * - * Object ID: this node's address if known, or 0 if unknown (first query) - * Canonical path: /identity.public - * Persistence: required - */ - ZT_STATE_OBJECT_IDENTITY_PUBLIC = 1, + /** + * Public address and public key + * + * Object ID: this node's address if known, or 0 if unknown (first query) + * Canonical path: /identity.public + * Persistence: required + */ + ZT_STATE_OBJECT_IDENTITY_PUBLIC = 1, - /** - * Full identity with secret key - * - * Object ID: this node's address if known, or 0 if unknown (first query) - * Canonical path: /identity.secret - * Persistence: required, should be stored with restricted permissions e.g. mode 0600 on *nix - */ - ZT_STATE_OBJECT_IDENTITY_SECRET = 2, + /** + * Full identity with secret key + * + * Object ID: this node's address if known, or 0 if unknown (first query) + * Canonical path: /identity.secret + * Persistence: required, should be stored with restricted permissions e.g. mode 0600 on *nix + */ + ZT_STATE_OBJECT_IDENTITY_SECRET = 2, - /** - * The planet (there is only one per... well... planet!) - * - * Object ID: world ID of planet, or 0 if unknown (first query) - * Canonical path: /planet - * Persistence: recommended - */ - ZT_STATE_OBJECT_PLANET = 3, + /** + * The planet (there is only one per... well... planet!) + * + * Object ID: world ID of planet, or 0 if unknown (first query) + * Canonical path: /planet + * Persistence: recommended + */ + ZT_STATE_OBJECT_PLANET = 3, - /** - * A moon (federated root set) - * - * Object ID: world ID of moon - * Canonical path: /moons.d/.moon (16-digit hex ID) - * Persistence: required if moon memberships should persist - */ - ZT_STATE_OBJECT_MOON = 4, + /** + * A moon (federated root set) + * + * Object ID: world ID of moon + * Canonical path: /moons.d/.moon (16-digit hex ID) + * Persistence: required if moon memberships should persist + */ + ZT_STATE_OBJECT_MOON = 4, - /** - * Peer and related state - * - * Object ID: peer address - * Canonical path: /peers.d/ (10-digit address - * Persistence: optional, can be cleared at any time - */ - ZT_STATE_OBJECT_PEER = 5, + /** + * Peer and related state + * + * Object ID: peer address + * Canonical path: /peers.d/ (10-digit address + * Persistence: optional, can be cleared at any time + */ + ZT_STATE_OBJECT_PEER = 5, - /** - * Network configuration - * - * Object ID: peer address - * Canonical path: /networks.d/.conf (16-digit hex ID) - * Persistence: required if network memberships should persist - */ - ZT_STATE_OBJECT_NETWORK_CONFIG = 6 + /** + * Network configuration + * + * Object ID: peer address + * Canonical path: /networks.d/.conf (16-digit hex ID) + * Persistence: required if network memberships should persist + */ + ZT_STATE_OBJECT_NETWORK_CONFIG = 6 }; /** @@ -1532,13 +1527,13 @@ typedef void ZT_Node; * PORT_ERROR state. */ typedef int (*ZT_VirtualNetworkConfigFunction)( - ZT_Node*, /* Node */ - void*, /* User ptr */ - void*, /* Thread ptr */ - uint64_t, /* Network ID */ - void**, /* Modifiable network user PTR */ - enum ZT_VirtualNetworkConfigOperation, /* Config operation */ - const ZT_VirtualNetworkConfig*); /* Network configuration */ + ZT_Node*, /* Node */ + void*, /* User ptr */ + void*, /* Thread ptr */ + uint64_t, /* Network ID */ + void**, /* Modifiable network user PTR */ + enum ZT_VirtualNetworkConfigOperation, /* Config operation */ + const ZT_VirtualNetworkConfig*); /* Network configuration */ /** * Function to send a frame out to a virtual network port @@ -1548,17 +1543,17 @@ typedef int (*ZT_VirtualNetworkConfigFunction)( * (9) frame length. */ typedef void (*ZT_VirtualNetworkFrameFunction)( - ZT_Node*, /* Node */ - void*, /* User ptr */ - void*, /* Thread ptr */ - uint64_t, /* Network ID */ - void**, /* Modifiable network user PTR */ - uint64_t, /* Source MAC */ - uint64_t, /* Destination MAC */ - unsigned int, /* Ethernet type */ - unsigned int, /* VLAN ID (0 for none) */ - const void*, /* Frame data */ - unsigned int); /* Frame length */ + ZT_Node*, /* Node */ + void*, /* User ptr */ + void*, /* Thread ptr */ + uint64_t, /* Network ID */ + void**, /* Modifiable network user PTR */ + uint64_t, /* Source MAC */ + uint64_t, /* Destination MAC */ + unsigned int, /* Ethernet type */ + unsigned int, /* VLAN ID (0 for none) */ + const void*, /* Frame data */ + unsigned int); /* Frame length */ /** * Callback for events @@ -1570,11 +1565,11 @@ typedef void (*ZT_VirtualNetworkFrameFunction)( * in the definition of ZT_Event. */ typedef void (*ZT_EventCallback)( - ZT_Node*, /* Node */ - void*, /* User ptr */ - void*, /* Thread ptr */ - enum ZT_Event, /* Event type */ - const void*); /* Event payload (if applicable) */ + ZT_Node*, /* Node */ + void*, /* User ptr */ + void*, /* Thread ptr */ + enum ZT_Event, /* Event type */ + const void*); /* Event payload (if applicable) */ /** * Callback for storing and/or publishing state information @@ -1586,13 +1581,13 @@ typedef void (*ZT_EventCallback)( * deleted. */ typedef void (*ZT_StatePutFunction)( - ZT_Node*, /* Node */ - void*, /* User ptr */ - void*, /* Thread ptr */ - enum ZT_StateObjectType, /* State object type */ - const uint64_t[2], /* State object ID (if applicable) */ - const void*, /* State object data */ - int); /* Length of data or -1 to delete */ + ZT_Node*, /* Node */ + void*, /* User ptr */ + void*, /* Thread ptr */ + enum ZT_StateObjectType, /* State object type */ + const uint64_t[2], /* State object ID (if applicable) */ + const void*, /* State object data */ + int); /* Length of data or -1 to delete */ /** * Callback for retrieving stored state information @@ -1602,13 +1597,13 @@ typedef void (*ZT_StatePutFunction)( * small to store it. */ typedef int (*ZT_StateGetFunction)( - ZT_Node*, /* Node */ - void*, /* User ptr */ - void*, /* Thread ptr */ - enum ZT_StateObjectType, /* State object type */ - const uint64_t[2], /* State object ID (if applicable) */ - void*, /* Buffer to store state object data */ - unsigned int); /* Length of data buffer in bytes */ + ZT_Node*, /* Node */ + void*, /* User ptr */ + void*, /* Thread ptr */ + enum ZT_StateObjectType, /* State object type */ + const uint64_t[2], /* State object ID (if applicable) */ + void*, /* Buffer to store state object data */ + unsigned int); /* Length of data buffer in bytes */ /** * Function to send a ZeroTier packet out over the physical wire (L2/L3) @@ -1635,14 +1630,14 @@ typedef int (*ZT_StateGetFunction)( * delivery. It only means that the packet appears to have been sent. */ typedef int (*ZT_WirePacketSendFunction)( - ZT_Node*, /* Node */ - void*, /* User ptr */ - void*, /* Thread ptr */ - int64_t, /* Local socket */ - const struct sockaddr_storage*, /* Remote address */ - const void*, /* Packet data */ - unsigned int, /* Packet length */ - unsigned int); /* TTL or 0 to use default */ + ZT_Node*, /* Node */ + void*, /* User ptr */ + void*, /* Thread ptr */ + int64_t, /* Local socket */ + const struct sockaddr_storage*, /* Remote address */ + const void*, /* Packet data */ + unsigned int, /* Packet length */ + unsigned int); /* TTL or 0 to use default */ /** * Function to check whether a path should be used for ZeroTier traffic @@ -1666,12 +1661,12 @@ typedef int (*ZT_WirePacketSendFunction)( * interface (recursion). */ typedef int (*ZT_PathCheckFunction)( - ZT_Node*, /* Node */ - void*, /* User ptr */ - void*, /* Thread ptr */ - uint64_t, /* ZeroTier address */ - int64_t, /* Local socket or -1 if unknown */ - const struct sockaddr_storage*); /* Remote address */ + ZT_Node*, /* Node */ + void*, /* User ptr */ + void*, /* Thread ptr */ + uint64_t, /* ZeroTier address */ + int64_t, /* Local socket or -1 if unknown */ + const struct sockaddr_storage*); /* Remote address */ /** * Function to get physical addresses for ZeroTier peers @@ -1689,12 +1684,12 @@ typedef int (*ZT_PathCheckFunction)( * with an address. */ typedef int (*ZT_PathLookupFunction)( - ZT_Node*, /* Node */ - void*, /* User ptr */ - void*, /* Thread ptr */ - uint64_t, /* ZeroTier address (40 bits) */ - int, /* Desired ss_family or -1 for any */ - struct sockaddr_storage*); /* Result buffer */ + ZT_Node*, /* Node */ + void*, /* User ptr */ + void*, /* Thread ptr */ + uint64_t, /* ZeroTier address (40 bits) */ + int, /* Desired ss_family or -1 for any */ + struct sockaddr_storage*); /* Result buffer */ /****************************************************************************/ /* C Node API */ @@ -1704,50 +1699,77 @@ typedef int (*ZT_PathLookupFunction)( * Structure for configuring ZeroTier core callback functions */ struct ZT_Node_Callbacks { - /** - * Struct version -- must currently be 0 - */ - long version; + /** + * Struct version -- must currently be 0 + */ + long version; - /** - * REQUIRED: Function to store and/or replicate state objects - */ - ZT_StatePutFunction statePutFunction; + /** + * REQUIRED: Function to store and/or replicate state objects + */ + ZT_StatePutFunction statePutFunction; - /** - * REQUIRED: Function to retrieve state objects from an object store - */ - ZT_StateGetFunction stateGetFunction; + /** + * REQUIRED: Function to retrieve state objects from an object store + */ + ZT_StateGetFunction stateGetFunction; - /** - * REQUIRED: Function to send packets over the physical wire - */ - ZT_WirePacketSendFunction wirePacketSendFunction; + /** + * REQUIRED: Function to send packets over the physical wire + */ + ZT_WirePacketSendFunction wirePacketSendFunction; - /** - * REQUIRED: Function to inject frames into a virtual network's TAP - */ - ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction; + /** + * REQUIRED: Function to inject frames into a virtual network's TAP + */ + ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction; - /** - * REQUIRED: Function to be called when virtual networks are configured or changed - */ - ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction; + /** + * REQUIRED: Function to be called when virtual networks are configured or changed + */ + ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction; - /** - * REQUIRED: Function to be called to notify external code of important events - */ - ZT_EventCallback eventCallback; + /** + * REQUIRED: Function to be called to notify external code of important events + */ + ZT_EventCallback eventCallback; - /** - * OPTIONAL: Function to check whether a given physical path should be used - */ - ZT_PathCheckFunction pathCheckFunction; + /** + * OPTIONAL: Function to check whether a given physical path should be used + */ + ZT_PathCheckFunction pathCheckFunction; - /** - * OPTIONAL: Function to get hints to physical paths to ZeroTier addresses - */ - ZT_PathLookupFunction pathLookupFunction; + /** + * OPTIONAL: Function to get hints to physical paths to ZeroTier addresses + */ + ZT_PathLookupFunction pathLookupFunction; +}; + +/** + * Node configuration options + */ +struct ZT_Node_Config { + /** + * If non-zero enable encrypted HELLO packets. + * + * This attaches an ephemeral key to HELLO packets and encrypts them. It + * increases CPU usage slightly, which can matter at scale for nodes that + * handle huge numbers of clients like controllers. HELLO packets only + * contain keys and a small amount of meta-data like node version, never + * user data or information about things like network membership, so the + * security impact of this is negligable. ZT1 does not and never has + * guaranteed meta-data privacy, only data privacy. Enable only if you + * need it for compliance reasons. + */ + int enableEncryptedHello; + + /** + * If non-zero enable low bandwidth mode. + * + * This reduces keepalive and path sensing traffic, which can slow fail- + * over but reduces idle bandwidth. Enable in low bandwidth environments. + */ + int lowBandwidthMode; }; /** @@ -1759,13 +1781,14 @@ struct ZT_Node_Callbacks { * to a few seconds depending on your CPU speed. * * @param node Result: pointer is set to new node instance on success + * @param config Node-wide configuration options set on startup * @param uptr User pointer to pass to functions/callbacks * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param callbacks Callback function configuration * @param now Current clock in milliseconds * @return OK (0) or error code if a fatal error condition has occurred */ -ZT_SDK_API enum ZT_ResultCode ZT_Node_new(ZT_Node** node, void* uptr, void* tptr, const struct ZT_Node_Callbacks* callbacks, int64_t now); +ZT_SDK_API enum ZT_ResultCode ZT_Node_new(ZT_Node** node, const struct ZT_Node_Config* config, void* uptr, void* tptr, const struct ZT_Node_Callbacks* callbacks, int64_t now); /** * Delete a node and free all resources it consumes @@ -1810,17 +1833,17 @@ ZT_Node_processWirePacket(ZT_Node* node, void* tptr, int64_t now, int64_t localS * @return OK (0) or error code if a fatal error condition has occurred */ ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( - ZT_Node* node, - void* tptr, - int64_t now, - uint64_t nwid, - uint64_t sourceMac, - uint64_t destMac, - unsigned int etherType, - unsigned int vlanId, - const void* frameData, - unsigned int frameLength, - volatile int64_t* nextBackgroundTaskDeadline); + ZT_Node* node, + void* tptr, + int64_t now, + uint64_t nwid, + uint64_t sourceMac, + uint64_t destMac, + unsigned int etherType, + unsigned int vlanId, + const void* frameData, + unsigned int frameLength, + volatile int64_t* nextBackgroundTaskDeadline); /** * Perform periodic background operations diff --git a/make-bsd.mk b/make-bsd.mk index ce0b4dde1..cf4c22c8b 100644 --- a/make-bsd.mk +++ b/make-bsd.mk @@ -1,12 +1,21 @@ # 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=-isystem ext -Iext/prometheus-cpp-lite-1.0/core/include -Iext/prometheus-cpp-lite-1.0/simpleapi/include -Iext/opentelemetry-cpp-api-only/include DEFS= LIBS= include objects.mk ONE_OBJS+=osdep/BSDEthernetTap.o ext/http-parser/http_parser.o +ifeq ($(ZT_CONTROLLER),1) + ZT_NONFREE=1 +endif +ifeq ($(ZT_NONFREE),1) + include objects-nonfree.mk + ONE_OBJS+=$(CONTROLLER_OBJS) + override DEFS += -DZT_NONFREE_CONTROLLER +endif + 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. @@ -181,7 +190,7 @@ selftest: $(CORE_OBJS) $(ONE_OBJS) selftest.o zerotier-selftest: selftest clean: - rm -rf *.a *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o build-* zerotier-one zerotier-idtool zerotier-selftest zerotier-cli $(ONE_OBJS) $(CORE_OBJS) + rm -rf *.a *.o node/*.o nonfree/controller/*.o osdep/*.o service/*.o ext/http-parser/*.o build-* zerotier-one zerotier-idtool zerotier-selftest zerotier-cli $(ONE_OBJS) $(CORE_OBJS) debug: FORCE $(MAKE) -j ZT_DEBUG=1 diff --git a/make-linux.mk b/make-linux.mk index eab6dee5e..ff94cdd81 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -17,6 +17,16 @@ EXTRA_DEPS?= ZT_CARGO_FLAGS?= include objects.mk + +ifeq ($(ZT_CONTROLLER),1) + ZT_NONFREE=1 +endif +ifeq ($(ZT_NONFREE),1) + include objects-nonfree.mk + ONE_OBJS+=$(CONTROLLER_OBJS) + override DEFS += -DZT_NONFREE_CONTROLLER +endif + ifeq ($(ZT_EXTOSDEP),1) ONE_OBJS+=osdep/ExtOsdep.o override DEFS += -DZT_EXTOSDEP @@ -57,7 +67,7 @@ ifeq ($(ZT_RULES_ENGINE_DEBUGGING),1) endif ifeq ($(ZT_DEBUG_TRACE),1) - DEFS+=-DZT_DEBUG_TRACE + override DEFS+=-DZT_DEBUG_TRACE endif # Build with address sanitization library for advanced debugging (clang) @@ -94,10 +104,6 @@ ifeq ($(ZT_SYNOLOGY), 1) ZT_EMBEDDED=1 endif -ifeq ($(ZT_DISABLE_COMPRESSION), 1) - override DEFS+=-DZT_DISABLE_COMPRESSION -endif - ifeq ($(ZT_TRACE),1) override DEFS+=-DZT_TRACE endif @@ -115,7 +121,7 @@ ifeq ($(ZT_VAULT_SUPPORT),1) override LDLIBS+=-lcurl endif -# Determine system build architecture from compiler target +# Determine system build architecture from compiler target. This is hairy due to "ARM wrestling." CC_MACH=$(shell $(CC) -dumpmachine | cut -d '-' -f 1) ZT_ARCHITECTURE=999 ifeq ($(CC_MACH),x86_64) @@ -441,7 +447,7 @@ endif ext/${OTEL_INSTALL_DIR}/include/opentelemetry/version.h: otel 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 ext/opentelemetry-cpp-${OTEL_VERSION}/localinstall ext/opentelemetry-cpp-${OTEL_VERSION}/build + rm -rf *.a *.so *.o node/*.o nonfree/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 ext/opentelemetry-cpp-${OTEL_VERSION}/localinstall ext/opentelemetry-cpp-${OTEL_VERSION}/build distclean: clean diff --git a/make-mac.mk b/make-mac.mk index 280211b02..d16616fa3 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -5,7 +5,7 @@ TOPDIR=$(shell pwd) INCLUDES=-I$(shell pwd)/rustybits/target -isystem $(TOPDIR)/ext -I$(TOPDIR)/ext/prometheus-cpp-lite-1.0/core/include -I$(TOPDIR)/ext-prometheus-cpp-lite-1.0/3rdparty/http-client-lite/include -I$(TOPDIR)/ext/prometheus-cpp-lite-1.0/simpleapi/include DEFS= LIBS= -ARCH_FLAGS=-arch x86_64 -arch arm64 +ARCH_FLAGS=-arch x86_64 -arch arm64 CODESIGN=echo PRODUCTSIGN=echo @@ -33,9 +33,7 @@ LIBS+=-framework CoreServices -framework SystemConfiguration -framework CoreFoun EXTRA_CARGO_FLAGS?= -# 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 @@ -44,23 +42,21 @@ ifeq ($(ZT_OFFICIAL_RELEASE),1) NOTARIZE=xcrun notarytool NOTARIZE_APPLE_ID="adam.ierymenko@gmail.com" NOTARIZE_TEAM_ID="8ZD9JUCZ4V" -else - DEFS+=-DZT_SOFTWARE_UPDATE_DEFAULT="\"download\"" endif # Use fast ASM Salsa20/12 for x64 processors -DEFS+=-DZT_USE_X64_ASM_SALSA2012 +override DEFS+=-DZT_USE_X64_ASM_SALSA2012 CORE_OBJS+=ext/x64-salsa2012-asm/salsa2012.o CXXFLAGS=$(CFLAGS) -std=c++17 -stdlib=libc++ # Build miniupnpc and nat-pmp as included libraries -- extra defs are required for these sources -DEFS+=-DMACOSX -DZT_SSO_SUPPORTED -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 +override DEFS+=-DMACOSX -DZT_SSO_SUPPORTED -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 ifeq ($(ZT_CONTROLLER),1) MACOS_VERSION_MIN=10.15 override CXXFLAGS=$(CFLAGS) -std=c++17 -stdlib=libc++ LIBS+=-L/opt/homebrew/lib -L/usr/local/opt/libpqxx/lib -L/usr/local/opt/libpq/lib -L/usr/local/opt/openssl/lib/ -lpqxx -lpq -lssl -lcrypto -lgssapi_krb5 ext/redis-plus-plus-1.1.1/install/macos/lib/libredis++.a ext/hiredis-0.14.1/lib/macos/libhiredis.a rustybits/target/librustybits.a - DEFS+=-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER_USE_REDIS -DZT_CONTROLLER + override DEFS+=-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER_USE_REDIS -DZT_CONTROLLER INCLUDES+=-I/opt/homebrew/include -I/opt/homebrew/opt/libpq/include -I/usr/local/opt/libpq/include -I/usr/local/opt/libpqxx/include -Iext/hiredis-0.14.1/include/ -Iext/redis-plus-plus-1.1.1/install/macos/include/sw/ -Irustybits/target/ EXTRA_CARGO_FLAGS+=-F ztcontroller else @@ -69,10 +65,10 @@ endif # Build with address sanitization library for advanced debugging (clang) ifeq ($(ZT_SANITIZE),1) - DEFS+=-fsanitize=address -DASAN_OPTIONS=symbolize=1 + override DEFS+=-fsanitize=address -DASAN_OPTIONS=symbolize=1 endif ifeq ($(ZT_DEBUG_TRACE),1) - DEFS+=-DZT_DEBUG_TRACE + override DEFS+=-DZT_DEBUG_TRACE endif # Debug mode -- dump trace output, build binary with -g ifeq ($(ZT_DEBUG),1) @@ -93,22 +89,22 @@ else endif ifeq ($(ZT_TRACE),1) - DEFS+=-DZT_TRACE + override DEFS+=-DZT_TRACE endif ifeq ($(ZT_DEBUG),1) - DEFS+=-DZT_DEBUG + override DEFS+=-DZT_DEBUG endif ifeq ($(ZT_VAULT_SUPPORT),1) - DEFS+=-DZT_VAULT_SUPPORT=1 + override DEFS+=-DZT_VAULT_SUPPORT=1 LIBS+=-lcurl endif OTEL_VERSION=1.21.0 ifeq (${ZT_OTEL},1) OTEL_INSTALL_DIR=ext/opentelemetry-cpp-${OTEL_VERSION}/localinstall - DEFS+=-DZT_OTEL + override DEFS+=-DZT_OTEL INCLUDES+=-I${OTEL_INSTALL_DIR}/include LIBS+=-L${OTEL_INSTALL_DIR}/lib -lopentelemetry_exporter_in_memory_metric -lopentelemetry_exporter_in_memory -lopentelemetry_exporter_ostream_logs -lopentelemetry_exporter_ostream_metrics -lopentelemetry_exporter_ostream_span -lopentelemetry_trace -lopentelemetry_common -lopentelemetry_resources -lopentelemetry_logs -lopentelemetry_metrics -lopentelemetry_version else @@ -126,7 +122,7 @@ mac-agent: FORCE $(CODESIGN) -f --options=runtime -s $(CODESIGN_APP_CERT) MacEthernetTapAgent osdep/MacDNSHelper.o: osdep/MacDNSHelper.mm - $(CXX) $(CXXFLAGS) -c osdep/MacDNSHelper.mm -o osdep/MacDNSHelper.o + $(CXX) $(CXXFLAGS) -c osdep/MacDNSHelper.mm -o osdep/MacDNSHelper.o ifeq ($(ZT_CONTROLLER),1) one: otel rustybits $(CORE_OBJS) $(ONE_OBJS) one.o mac-agent @@ -163,10 +159,6 @@ libzerotiercore.a: $(CORE_OBJS) core: libzerotiercore.a -#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) rustybits/target/librustybits.a $(STRIP) zerotier-selftest @@ -183,8 +175,8 @@ mac-dist-pkg: FORCE 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 + #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) submit --apple-id "adam.ierymenko@gmail.com" --team-id "8ZD9JUCZ4V" --wait "ZeroTier One.pkg" echo '*** When Apple notifies that the app is notarized, run: xcrun stapler staple "ZeroTier One.pkg"' @@ -214,13 +206,13 @@ central-controller-docker: _buildx FORCE centralv2-controller-docker: _buildx FORCE docker buildx build --platform linux/amd64,linux/arm64 --no-cache -t us-central1-docker.pkg.dev/zerotier-d648c7/central-v2/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=`git name-rev --name-only HEAD` . --push - @echo Image: us-central1-docker.pkg.dev/zerotier-d648c7/central-v2/ztcentral-controller:${TIMESTAMP} + @echo Image: us-central1-docker.pkg.dev/zerotier-d648c7/central-v2/ztcentral-controller:${TIMESTAMP} docker-release: _buildx docker buildx build --platform linux/386,linux/amd64,linux/arm/v7,linux/arm64,linux/mips64le,linux/ppc64le,linux/s390x -t zerotier/zerotier:${RELEASE_DOCKER_TAG} -t zerotier/zerotier:latest --build-arg VERSION=${RELEASE_VERSION} -f Dockerfile.release . --push - + clean: - rm -rf MacEthernetTapAgent *.dSYM build-* *.a *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o $(CORE_OBJS) $(ONE_OBJS) zerotier-one zerotier-idtool zerotier-selftest zerotier-cli zerotier doc/node_modules zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_* rustybits/target/ ext/opentelemetry-cpp-${OTEL_VERSION}/localinstall ext/opentelemetry-cpp-${OTEL_VERSION}/build + rm -rf MacEthernetTapAgent *.dSYM build-* *.a *.pkg *.dmg *.o node/*.o nonfree/controller/*.o service/*.o osdep/*.o ext/http-parser/*.o $(CORE_OBJS) $(ONE_OBJS) zerotier-one zerotier-idtool zerotier-selftest zerotier-cli zerotier doc/node_modules zt1_update_$(ZT_BUILD_PLATFORM)_$(ZT_BUILD_ARCHITECTURE)_* rustybits/target/ ext/opentelemetry-cpp-${OTEL_VERSION}/localinstall ext/opentelemetry-cpp-${OTEL_VERSION}/build ifeq (${ZT_OTEL},1) otel: diff --git a/make-netbsd.mk b/make-netbsd.mk index f2490038b..6ee32ccd9 100644 --- a/make-netbsd.mk +++ b/make-netbsd.mk @@ -1,13 +1,22 @@ CC=gcc CXX=g++ -INCLUDES= +INCLUDES=-Iext/opentelemetry-cpp-api-only/include DEFS= LIBS= include objects.mk OBJS+=osdep/NetBSDEthernetTap.o ext/lz4/lz4.o ext/json-parser/json.o ext/http-parser/http_parser.o +ifeq ($(ZT_CONTROLLER),1) + ZT_NONFREE=1 +endif +ifeq ($(ZT_NONFREE),1) + include objects-nonfree.mk + ONE_OBJS+=$(CONTROLLER_OBJS) + override DEFS += -DZT_NONFREE_CONTROLLER +endif + # "make official" is a shortcut for this ifeq ($(ZT_OFFICIAL_RELEASE),1) DEFS+=-DZT_OFFICIAL_RELEASE @@ -53,7 +62,7 @@ selftest: $(OBJS) selftest.o # ./buildinstaller.sh clean: - rm -rf *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o build-* zerotier-one zerotier-idtool zerotier-selftest zerotier-cli ZeroTierOneInstaller-* + rm -rf *.o node/*.o nonfree/controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o build-* zerotier-one zerotier-idtool zerotier-selftest zerotier-cli ZeroTierOneInstaller-* debug: FORCE make -j 4 ZT_DEBUG=1 diff --git a/node/AES.cpp b/node/AES.cpp index 1ba6aeeb7..6bc308836 100644 --- a/node/AES.cpp +++ b/node/AES.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "AES.hpp" diff --git a/node/AES.hpp b/node/AES.hpp index cb4ca23f5..230915211 100644 --- a/node/AES.hpp +++ b/node/AES.hpp @@ -1,21 +1,15 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_AES_HPP #define ZT_AES_HPP #include "Constants.hpp" -#include "SHA512.hpp" #include "Utils.hpp" // Uncomment to disable all hardware acceleration (usually for testing) diff --git a/node/AES_aesni.cpp b/node/AES_aesni.cpp index e4509425a..1eecbfae8 100644 --- a/node/AES_aesni.cpp +++ b/node/AES_aesni.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "AES.hpp" #include "Constants.hpp" diff --git a/node/AES_armcrypto.cpp b/node/AES_armcrypto.cpp index a1be0b003..8e1cce30a 100644 --- a/node/AES_armcrypto.cpp +++ b/node/AES_armcrypto.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "AES.hpp" #include "Constants.hpp" diff --git a/node/Address.hpp b/node/Address.hpp index 182ccb7bb..6c376747c 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_ADDRESS_HPP #define ZT_ADDRESS_HPP @@ -21,8 +16,6 @@ #include #include #include -#include -#include namespace ZeroTier { diff --git a/node/AtomicCounter.hpp b/node/AtomicCounter.hpp index 1e75d6e9f..b70b3dd98 100644 --- a/node/AtomicCounter.hpp +++ b/node/AtomicCounter.hpp @@ -1,21 +1,14 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_ATOMICCOUNTER_HPP #define ZT_ATOMICCOUNTER_HPP -#include "Constants.hpp" - #ifndef __GNUC__ #include #endif diff --git a/node/Bond.cpp b/node/Bond.cpp index 647633342..8f9130462 100644 --- a/node/Bond.cpp +++ b/node/Bond.cpp @@ -1,23 +1,19 @@ -/* - * Copyright (c)2013-2021 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Bond.hpp" +#include "Constants.hpp" +#include "Node.hpp" #include "Switch.hpp" #include // for PRId64, etc. macros #include -#include #include // FIXME: remove this suppression and actually fix warnings @@ -899,7 +895,7 @@ void Bond::sendQOS_MEASUREMENT(void* tPtr, int pathIdx, int64_t localSocket, con RR->node->putPacket(tPtr, localSocket, atAddress, outp.data(), outp.size()); } else { - RR->sw->send(tPtr, outp, false); + RR->sw->send(tPtr, outp, false, 0, ZT_QOS_NO_FLOW); } Metrics::pkt_qos_out++; _paths[pathIdx].packetsReceivedSinceLastQoS = 0; diff --git a/node/Bond.hpp b/node/Bond.hpp index f7d1f05a2..5c7396d2c 100644 --- a/node/Bond.hpp +++ b/node/Bond.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2021 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_BOND_HPP #define ZT_BOND_HPP @@ -23,7 +18,6 @@ #include #include -#include #include /** diff --git a/node/Buffer.hpp b/node/Buffer.hpp index ae013c790..2cb6b5428 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_BUFFER_HPP #define ZT_BUFFER_HPP @@ -18,11 +13,8 @@ #include "Utils.hpp" #include -#include #include #include -#include -#include #if defined(__GNUC__) && (! defined(ZT_NO_TYPE_PUNNING)) #define ZT_VAR_MAY_ALIAS __attribute__((__may_alias__)) diff --git a/node/Capability.cpp b/node/Capability.cpp index b7ee3f9f7..7929df21f 100644 --- a/node/Capability.cpp +++ b/node/Capability.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Capability.hpp" diff --git a/node/Capability.hpp b/node/Capability.hpp index b22380c5d..e1541e809 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_CAPABILITY_HPP #define ZT_CAPABILITY_HPP @@ -21,7 +16,6 @@ #include "Credential.hpp" #include "ECC.hpp" #include "Identity.hpp" -#include "Utils.hpp" #include #include diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index 5a00c8eab..60e15397c 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "CertificateOfMembership.hpp" diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index c5a3c6a7a..25187a083 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_CERTIFICATEOFMEMBERSHIP_HPP #define ZT_CERTIFICATEOFMEMBERSHIP_HPP diff --git a/node/CertificateOfOwnership.cpp b/node/CertificateOfOwnership.cpp index 5a1cbf343..cd115a510 100644 --- a/node/CertificateOfOwnership.cpp +++ b/node/CertificateOfOwnership.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "CertificateOfOwnership.hpp" diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index 3e2f5b926..1b7b9bc3d 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_CERTIFICATEOFOWNERSHIP_HPP #define ZT_CERTIFICATEOFOWNERSHIP_HPP diff --git a/node/Constants.hpp b/node/Constants.hpp index 66621ec49..6baf8c7fe 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_CONSTANTS_HPP #define ZT_CONSTANTS_HPP diff --git a/node/Credential.hpp b/node/Credential.hpp index 3f290cadf..3065627e4 100644 --- a/node/Credential.hpp +++ b/node/Credential.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_CREDENTIAL_HPP #define ZT_CREDENTIAL_HPP diff --git a/node/DNS.hpp b/node/DNS.hpp index 79e422e8f..a6f5ea22c 100644 --- a/node/DNS.hpp +++ b/node/DNS.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_DNS_HPP #define ZT_DNS_HPP diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 1c6b52620..941227ebf 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_DICTIONARY_HPP #define ZT_DICTIONARY_HPP diff --git a/node/ECC.hpp b/node/ECC.hpp index 68f6d5ea8..1fc61adbe 100644 --- a/node/ECC.hpp +++ b/node/ECC.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ /* * This file defines the elliptic curve crypto used for ZeroTier V1. The normal diff --git a/node/Hashtable.hpp b/node/Hashtable.hpp index 5073f6029..f921c2949 100644 --- a/node/Hashtable.hpp +++ b/node/Hashtable.hpp @@ -1,23 +1,16 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_HASHTABLE_HPP #define ZT_HASHTABLE_HPP #include "Constants.hpp" -#include -#include #include #include #include diff --git a/node/Identity.cpp b/node/Identity.cpp index 1e6d4212d..86f005280 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Identity.hpp" diff --git a/node/Identity.hpp b/node/Identity.hpp index 0f82d4916..7016aee86 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_IDENTITY_HPP #define ZT_IDENTITY_HPP diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 8cf210437..cf55537a5 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "IncomingPacket.hpp" @@ -27,8 +22,6 @@ #include "Peer.hpp" #include "Revocation.hpp" #include "RuntimeEnvironment.hpp" -#include "SHA512.hpp" -#include "Salsa20.hpp" #include "SelfAwareness.hpp" #include "Switch.hpp" #include "Tag.hpp" diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index ebca8f220..d75a2928d 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_INCOMINGPACKET_HPP #define ZT_INCOMINGPACKET_HPP diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 17e297d6c..81a49e69e 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "InetAddress.hpp" @@ -19,7 +14,6 @@ #include #include #include -#include namespace ZeroTier { diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 4e0b89438..fbbe25dee 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_INETADDRESS_HPP #define ZT_INETADDRESS_HPP diff --git a/node/MAC.hpp b/node/MAC.hpp index 9cf8454da..f116dc7f6 100644 --- a/node/MAC.hpp +++ b/node/MAC.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_MAC_HPP #define ZT_MAC_HPP diff --git a/node/Membership.cpp b/node/Membership.cpp index f09755ffe..296a682b0 100644 --- a/node/Membership.cpp +++ b/node/Membership.cpp @@ -1,18 +1,14 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Membership.hpp" +#include "Constants.hpp" #include "Node.hpp" #include "Packet.hpp" #include "Peer.hpp" @@ -93,7 +89,7 @@ void Membership::pushCredentials(const RuntimeEnvironment* RR, void* tPtr, const outp.setAt(cooCountAt, (uint16_t)thisPacketCooCount); outp.compress(); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, nconf.networkId, ZT_QOS_NO_FLOW); Metrics::pkt_network_credentials_out++; } diff --git a/node/Membership.hpp b/node/Membership.hpp index 962fb55db..b66d8c959 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_MEMBERSHIP_HPP #define ZT_MEMBERSHIP_HPP diff --git a/node/Metrics.cpp b/node/Metrics.cpp index 11232cb0e..dd49d86bd 100644 --- a/node/Metrics.cpp +++ b/node/Metrics.cpp @@ -1,13 +1,9 @@ -/* - * Copyright (c)2013-2023 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ // clang-format off diff --git a/node/Metrics.hpp b/node/Metrics.hpp index 8c2c4290d..f4d4e20f9 100644 --- a/node/Metrics.hpp +++ b/node/Metrics.hpp @@ -1,14 +1,11 @@ -/* - * Copyright (c)2013-2023 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ + #ifndef METRICS_H_ #define METRICS_H_ diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp index 53905aa42..6e8cbc486 100644 --- a/node/MulticastGroup.hpp +++ b/node/MulticastGroup.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_MULTICASTGROUP_HPP #define ZT_MULTICASTGROUP_HPP diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 0d5fd7ce4..5a4d82a83 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Multicaster.hpp" @@ -186,9 +181,7 @@ void Multicaster::send(void* tPtr, int64_t now, const SharedPtr& networ outp.append((uint32_t)mg.adi()); outp.append((uint16_t)etherType); outp.append(data, len); - if (! network->config().disableCompression()) { - outp.compress(); - } + outp.compress(); outp.armor(bestMulticastReplicator->key(), true, false, bestMulticastReplicator->aesKeysIfSupported(), bestMulticastReplicator->identity()); Metrics::pkt_multicast_frame_out++; bestMulticastReplicatorPath->send(RR, tPtr, outp.data(), outp.size(), now); @@ -232,7 +225,7 @@ void Multicaster::send(void* tPtr, int64_t now, const SharedPtr& networ RR, now, network->id(), - network->config().disableCompression(), + false, limit, 1, // we'll still gather a little from peers to keep multicast list fresh src, @@ -272,7 +265,7 @@ void Multicaster::send(void* tPtr, int64_t now, const SharedPtr& networ Address explicitGatherPeers[16]; unsigned int numExplicitGatherPeers = 0; - SharedPtr bestRoot(RR->topology->getUpstreamPeer()); + SharedPtr bestRoot(RR->topology->getUpstreamPeer(network->id())); if (bestRoot) { explicitGatherPeers[numExplicitGatherPeers++] = bestRoot->address(); } @@ -300,16 +293,6 @@ void Multicaster::send(void* tPtr, int64_t now, const SharedPtr& networ } } - std::vector
anchors(network->config().anchors()); - for (std::vector
::const_iterator a(anchors.begin()); a != anchors.end(); ++a) { - if (*a != RR->identity.address()) { - explicitGatherPeers[numExplicitGatherPeers++] = *a; - if (numExplicitGatherPeers == 16) { - break; - } - } - } - for (unsigned int k = 0; k < numExplicitGatherPeers; ++k) { const CertificateOfMembership* com = (network) ? ((network->config().com) ? &(network->config().com) : (const CertificateOfMembership*)0) : (const CertificateOfMembership*)0; Packet outp(explicitGatherPeers[k], RR->identity.address(), Packet::VERB_MULTICAST_GATHER); @@ -322,7 +305,7 @@ void Multicaster::send(void* tPtr, int64_t now, const SharedPtr& networ com->serialize(outp); } RR->node->expectReplyTo(outp.packetId()); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, network->id(), ZT_QOS_NO_FLOW); Metrics::pkt_multicast_gather_out++; } } @@ -330,7 +313,7 @@ void Multicaster::send(void* tPtr, int64_t now, const SharedPtr& networ gs.txQueue.push_back(OutboundMulticast()); OutboundMulticast& out = gs.txQueue.back(); - out.init(RR, now, network->id(), network->config().disableCompression(), limit, gatherLimit, src, mg, etherType, data, len); + out.init(RR, now, network->id(), false, limit, gatherLimit, src, mg, etherType, data, len); if (origin) { out.logAsSent(origin); diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 0cb6e8f8e..0cf11c8cc 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_MULTICASTER_HPP #define ZT_MULTICASTER_HPP diff --git a/node/Mutex.hpp b/node/Mutex.hpp index d708b4571..cdcd759ec 100644 --- a/node/Mutex.hpp +++ b/node/Mutex.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_MUTEX_HPP #define ZT_MUTEX_HPP @@ -19,7 +14,6 @@ #ifdef __UNIX_LIKE__ #include -#include #include namespace ZeroTier { diff --git a/node/Network.cpp b/node/Network.cpp index 4b5cdd02d..425941f00 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Network.hpp" @@ -31,7 +26,6 @@ #include "Trace.hpp" #include -#include #include #include #include @@ -807,8 +801,7 @@ bool Network::filterOutgoingPacket( macSource.appendTo(outp); outp.append((uint16_t)etherType); outp.append(frameData, ccLength2); - outp.compress(); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, _id, ZT_QOS_NO_FLOW); } break; @@ -845,8 +838,7 @@ bool Network::filterOutgoingPacket( macSource.appendTo(outp); outp.append((uint16_t)etherType); outp.append(frameData, ccLength); - outp.compress(); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, _id, ZT_QOS_NO_FLOW); } if ((ztDest != ztFinalDest) && (ztFinalDest)) { @@ -857,8 +849,7 @@ bool Network::filterOutgoingPacket( macSource.appendTo(outp); outp.append((uint16_t)etherType); outp.append(frameData, frameLen); - outp.compress(); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, _id, ZT_QOS_NO_FLOW); if (_config.remoteTraceTarget) { RR->t->networkFilter( @@ -984,8 +975,7 @@ int Network::filterIncomingPacket( macSource.appendTo(outp); outp.append((uint16_t)etherType); outp.append(frameData, ccLength2); - outp.compress(); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, _id, ZT_QOS_NO_FLOW); } break; } @@ -1017,8 +1007,7 @@ int Network::filterIncomingPacket( macSource.appendTo(outp); outp.append((uint16_t)etherType); outp.append(frameData, ccLength); - outp.compress(); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, _id, ZT_QOS_NO_FLOW); } if ((ztDest != ztFinalDest) && (ztFinalDest)) { @@ -1029,8 +1018,7 @@ int Network::filterIncomingPacket( macSource.appendTo(outp); outp.append((uint16_t)etherType); outp.append(frameData, frameLen); - outp.compress(); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, _id, ZT_QOS_NO_FLOW); if (_config.remoteTraceTarget) { RR->t->networkFilter(tPtr, *this, rrl, (c) ? &crrl : (Trace::RuleResultLog*)0, c, sourcePeer->address(), ztDest, macSource, macDest, frameData, frameLen, etherType, vlanId, false, true, 0); @@ -1160,7 +1148,7 @@ uint64_t Network::handleConfigChunk(void* tPtr, const uint64_t packetId, const A if ((*a != source) && (*a != controller())) { Packet outp(*a, RR->identity.address(), Packet::VERB_NETWORK_CONFIG); outp.append(reinterpret_cast(chunk.data()) + start, chunk.size() - start); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, _id, ZT_QOS_NO_FLOW); } } } @@ -1471,7 +1459,7 @@ void Network::requestConfiguration(void* tPtr) } outp.compress(); RR->node->expectReplyTo(outp.packetId()); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, _id, ZT_QOS_NO_FLOW); } bool Network::gate(void* tPtr, const SharedPtr& peer) @@ -1628,7 +1616,7 @@ Membership::AddCredentialResult Network::addCredential(void* tPtr, const Address outp.append((uint16_t)1); // one revocation! rev.serialize(outp); outp.append((uint16_t)0); // no certificates of ownership - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, _id, ZT_QOS_NO_FLOW); } } } @@ -1758,19 +1746,17 @@ void Network::_sendUpdatesToMembers(void* tPtr, const MulticastGroup* const newM std::sort(alwaysAnnounceTo.begin(), alwaysAnnounceTo.end()); for (std::vector
::const_iterator a(alwaysAnnounceTo.begin()); a != alwaysAnnounceTo.end(); ++a) { - /* // push COM to non-members so they can do multicast request auth - if ( (_config.com) && (!_memberships.contains(*a)) && (*a != RR->identity.address()) ) { - Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS); + if ((_config.com) && (! _memberships.contains(*a)) && (*a != RR->identity.address())) { + Packet outp(*a, RR->identity.address(), Packet::VERB_NETWORK_CREDENTIALS); _config.com.serialize(outp); outp.append((uint8_t)0x00); - outp.append((uint16_t)0); // no capabilities - outp.append((uint16_t)0); // no tags - outp.append((uint16_t)0); // no revocations - outp.append((uint16_t)0); // no certificates of ownership - RR->sw->send(tPtr,outp,true); + outp.append((uint16_t)0); // no capabilities + outp.append((uint16_t)0); // no tags + outp.append((uint16_t)0); // no revocations + outp.append((uint16_t)0); // no certificates of ownership + RR->sw->send(tPtr, outp, true, _id, ZT_QOS_NO_FLOW); } - */ _announceMulticastGroupsTo(tPtr, *a, groups); } } @@ -1798,7 +1784,7 @@ void Network::_announceMulticastGroupsTo(void* tPtr, const Address& peer, const for (std::vector::const_iterator mg(allMulticastGroups.begin()); mg != allMulticastGroups.end(); ++mg) { if ((outp->size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) { outp->compress(); - RR->sw->send(tPtr, *outp, true); + RR->sw->send(tPtr, *outp, true, _id, ZT_QOS_NO_FLOW); outp->reset(peer, RR->identity.address(), Packet::VERB_MULTICAST_LIKE); } @@ -1810,7 +1796,7 @@ void Network::_announceMulticastGroupsTo(void* tPtr, const Address& peer, const if (outp->size() > ZT_PROTO_MIN_PACKET_LENGTH) { outp->compress(); - RR->sw->send(tPtr, *outp, true); + RR->sw->send(tPtr, *outp, true, _id, ZT_QOS_NO_FLOW); } delete outp; diff --git a/node/Network.hpp b/node/Network.hpp index a622786c6..4e417fe87 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_NETWORK_HPP #define ZT_NETWORK_HPP diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index a51fe1b29..7660f953b 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -1,23 +1,68 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "NetworkConfig.hpp" +#include "DNS.hpp" + #include #include namespace ZeroTier { +NetworkConfig::NetworkConfig() + : networkId(0) + , timestamp(0) + , credentialTimeMaxDelta(0) + , revision(0) + , issuedTo() + , remoteTraceTarget() + , flags(0) + , remoteTraceLevel(Trace::LEVEL_NORMAL) + , mtu(0) + , multicastLimit(0) + , specialistCount(0) + , routeCount(0) + , staticIpCount(0) + , ruleCount(0) + , capabilityCount(0) + , tagCount(0) + , certificateOfOwnershipCount(0) + , capabilities() + , tags() + , certificatesOfOwnership() + , type(ZT_NETWORK_TYPE_PRIVATE) + , dnsCount(0) + , ssoEnabled(false) + , authenticationURL() + , authenticationExpiryTime(0) + , issuerURL() + , centralAuthURL() + , ssoNonce() + , ssoState() + , ssoClientID() +{ + name[0] = 0; + memset(specialists, 0, sizeof(uint64_t) * ZT_MAX_NETWORK_SPECIALISTS); + memset(routes, 0, sizeof(ZT_VirtualNetworkRoute) * ZT_MAX_NETWORK_ROUTES); + memset(staticIps, 0, sizeof(InetAddress) * ZT_MAX_ZT_ASSIGNED_ADDRESSES); + memset(rules, 0, sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES); + memset(&dns, 0, sizeof(ZT_VirtualNetworkDNS)); + memset(authenticationURL, 0, sizeof(authenticationURL)); + memset(issuerURL, 0, sizeof(issuerURL)); + memset(centralAuthURL, 0, sizeof(centralAuthURL)); + memset(ssoNonce, 0, sizeof(ssoNonce)); + memset(ssoState, 0, sizeof(ssoState)); + memset(ssoClientID, 0, sizeof(ssoClientID)); + strncpy(ssoProvider, "default", sizeof(ssoProvider)); + ssoProvider[sizeof(ssoProvider) - 1] = 0; +} + bool NetworkConfig::toDictionary(Dictionary& d, bool includeLegacy) const { Buffer* tmp = new Buffer(); diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 30598cf2f..cba9b1232 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -1,41 +1,27 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_NETWORKCONFIG_HPP #define ZT_NETWORKCONFIG_HPP #include "../include/ZeroTierOne.h" #include "Address.hpp" -#include "Buffer.hpp" #include "Capability.hpp" #include "CertificateOfMembership.hpp" #include "CertificateOfOwnership.hpp" -#include "Constants.hpp" -#include "DNS.hpp" #include "Dictionary.hpp" #include "Hashtable.hpp" -#include "Identity.hpp" #include "InetAddress.hpp" -#include "MulticastGroup.hpp" #include "Tag.hpp" #include "Trace.hpp" -#include "Utils.hpp" -#include -#include #include #include -#include #include /** @@ -69,7 +55,7 @@ #define ZT_NETWORKCONFIG_FLAG_RULES_RESULT_OF_UNSUPPORTED_MATCH 0x0000000000000008ULL /** - * Flag: disable frame compression + * Flag: disable frame compression (unused, now always disabled) */ #define ZT_NETWORKCONFIG_FLAG_DISABLE_COMPRESSION 0x0000000000000010ULL @@ -78,16 +64,18 @@ */ #define ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE 0x0000020000000000ULL -/** - * Anchors are stable devices on this network that can act like roots when none are up - */ -#define ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR 0x0000040000000000ULL - /** * Designated multicast replicators replicate multicast in place of sender-side replication + * + * This is currently not really used. */ #define ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR 0x0000080000000000ULL +/** + * Designated per-network relays + */ +#define ZT_NETWORKCONFIG_SPECIALIST_TYPE_NETWORK_RELAY 0x0000100000000000ULL + namespace ZeroTier { // Dictionary capacity needed for max size network config @@ -250,51 +238,15 @@ namespace ZeroTier { */ class NetworkConfig { public: - NetworkConfig() - : networkId(0) - , timestamp(0) - , credentialTimeMaxDelta(0) - , revision(0) - , issuedTo() - , remoteTraceTarget() - , flags(0) - , remoteTraceLevel(Trace::LEVEL_NORMAL) - , mtu(0) - , multicastLimit(0) - , specialistCount(0) - , routeCount(0) - , staticIpCount(0) - , ruleCount(0) - , capabilityCount(0) - , tagCount(0) - , certificateOfOwnershipCount(0) - , capabilities() - , tags() - , certificatesOfOwnership() - , type(ZT_NETWORK_TYPE_PRIVATE) - , dnsCount(0) - , ssoEnabled(false) - , authenticationURL() - , authenticationExpiryTime(0) - , issuerURL() - , centralAuthURL() - , ssoNonce() - , ssoState() - , ssoClientID() + NetworkConfig(); + + inline bool operator==(const NetworkConfig& nc) const { - name[0] = 0; - memset(specialists, 0, sizeof(uint64_t) * ZT_MAX_NETWORK_SPECIALISTS); - memset(routes, 0, sizeof(ZT_VirtualNetworkRoute) * ZT_MAX_NETWORK_ROUTES); - memset(staticIps, 0, sizeof(InetAddress) * ZT_MAX_ZT_ASSIGNED_ADDRESSES); - memset(rules, 0, sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES); - memset(&dns, 0, sizeof(ZT_VirtualNetworkDNS)); - memset(authenticationURL, 0, sizeof(authenticationURL)); - memset(issuerURL, 0, sizeof(issuerURL)); - memset(centralAuthURL, 0, sizeof(centralAuthURL)); - memset(ssoNonce, 0, sizeof(ssoNonce)); - memset(ssoState, 0, sizeof(ssoState)); - memset(ssoClientID, 0, sizeof(ssoClientID)); - strncpy(ssoProvider, "default", sizeof(ssoProvider)); + return (memcmp(this, &nc, sizeof(NetworkConfig)) == 0); + } + inline bool operator!=(const NetworkConfig& nc) const + { + return (! (*this == nc)); } /** @@ -330,22 +282,6 @@ class NetworkConfig { return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION) != 0); } - /** - * @return True if frames should not be compressed - */ - inline bool disableCompression() const - { -#ifndef ZT_DISABLE_COMPRESSION - return ((this->flags & ZT_NETWORKCONFIG_FLAG_DISABLE_COMPRESSION) != 0); -#else - /* Compression is disabled for libzt builds since it causes non-obvious chaotic - interference with lwIP's TCP congestion algorithm. Compression is also disabled - for some NAS builds due to the usage of low-performance processors in certain - older and budget models. */ - return false; -#endif - } - /** * @return Network type is public (no access control) */ @@ -397,17 +333,6 @@ class NetworkConfig { return false; } - inline std::vector
anchors() const - { - std::vector
r; - for (unsigned int i = 0; i < specialistCount; ++i) { - if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR) != 0) { - r.push_back(Address(specialists[i])); - } - } - return r; - } - inline std::vector
multicastReplicators() const { std::vector
r; @@ -444,7 +369,7 @@ class NetworkConfig { { std::vector
r; for (unsigned int i = 0; i < specialistCount; ++i) { - if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) { + if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_NETWORK_RELAY | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) { r.push_back(Address(specialists[i])); } } @@ -455,7 +380,7 @@ class NetworkConfig { { unsigned int c = 0; for (unsigned int i = 0; i < specialistCount; ++i) { - if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) { + if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_NETWORK_RELAY | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) { ac[c++] = specialists[i]; } } @@ -465,7 +390,7 @@ class NetworkConfig { inline void alwaysContactAddresses(Hashtable >& a) const { for (unsigned int i = 0; i < specialistCount; ++i) { - if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) { + if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_NETWORK_RELAY | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) { a[Address(specialists[i])]; } } @@ -489,14 +414,6 @@ class NetworkConfig { { return (networkId != 0); } - inline bool operator==(const NetworkConfig& nc) const - { - return (memcmp(this, &nc, sizeof(NetworkConfig)) == 0); - } - inline bool operator!=(const NetworkConfig& nc) const - { - return (! (*this == nc)); - } /** * Add a specialist or mask flags if already present diff --git a/node/NetworkController.hpp b/node/NetworkController.hpp index 2b2f237de..6891e770c 100644 --- a/node/NetworkController.hpp +++ b/node/NetworkController.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_NETWORKCONFIGMASTER_HPP #define ZT_NETWORKCONFIGMASTER_HPP diff --git a/node/Node.cpp b/node/Node.cpp index ed4b71605..f704ff09a 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -1,21 +1,15 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Node.hpp" #include "../version.h" #include "Address.hpp" -#include "Buffer.hpp" #include "Constants.hpp" #include "ECC.hpp" #include "Identity.hpp" @@ -49,7 +43,7 @@ namespace ZeroTier { /* Public Node interface (C++, exposed via CAPI bindings) */ /****************************************************************************/ -Node::Node(void* uptr, void* tptr, const struct ZT_Node_Callbacks* callbacks, int64_t now) +Node::Node(void* uptr, void* tptr, const struct ZT_Node_Config* config, const struct ZT_Node_Callbacks* callbacks, int64_t now) : _RR(this) , RR(&_RR) , _uPtr(uptr) @@ -65,6 +59,7 @@ Node::Node(void* uptr, void* tptr, const struct ZT_Node_Callbacks* callbacks, in throw ZT_EXCEPTION_INVALID_ARGUMENT; } memcpy(&_cb, callbacks, sizeof(ZT_Node_Callbacks)); + memcpy(&_config, config, sizeof(ZT_Node_Config)); // Initialize non-cryptographic PRNG from a good random source Utils::getSecureRandom((void*)_prngState, sizeof(_prngState)); @@ -184,6 +179,7 @@ Node::~Node() Mutex::Lock _l(_networks_m); _networks.clear(); // destroy all networks before shutdown } + // Explicitly call destructors then free memory for all other objects. if (RR->sa) { RR->sa->~SelfAwareness(); } @@ -251,7 +247,7 @@ class _PingPeersThatNeedPing { , _tPtr(tPtr) , _alwaysContact(alwaysContact) , _now(now) - , _bestCurrentUpstream(RR->topology->getUpstreamPeer()) + , _bestCurrentUpstream(RR->topology->getUpstreamPeer(0)) { } @@ -340,9 +336,9 @@ ZT_ResultCode Node::processBackgroundTasks(void* tptr, int64_t now, volatile int try { _lastPingCheck = now; - // Get designated VL1 upstreams + // Get designated VL1 upstreams (roots) Hashtable > alwaysContact; - RR->topology->getUpstreamsToContact(alwaysContact); + RR->topology->getRootsToContact(alwaysContact); // Uncomment to dump stats /* @@ -699,7 +695,7 @@ int Node::sendUserMessage(void* tptr, uint64_t dest, uint64_t typeId, const void outp.append(typeId); outp.append(data, len); outp.compress(); - RR->sw->send(tptr, outp, true); + RR->sw->send(tptr, outp, true, 0, ZT_QOS_NO_FLOW); return 1; } } @@ -825,7 +821,7 @@ void Node::ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address& outp.append(sig.data, ZT_ECC_SIGNATURE_LEN); outp.compress(); - RR->sw->send((void*)0, outp, true); + RR->sw->send((void*)0, outp, true, nwid, ZT_QOS_NO_FLOW); chunkIndex += chunkLen; } } @@ -855,7 +851,7 @@ void Node::ncSendRevocation(const Address& destination, const Revocation& rev) outp.append((uint16_t)1); rev.serialize(outp); outp.append((uint16_t)0); - RR->sw->send((void*)0, outp, true); + RR->sw->send((void*)0, outp, true, rev.networkId(), ZT_QOS_NO_FLOW); } } @@ -911,7 +907,7 @@ void Node::ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address& d outp.append(errorData, errorDataSize); } - RR->sw->send((void*)0, outp, true); + RR->sw->send((void*)0, outp, true, nwid, ZT_QOS_NO_FLOW); } // else we can't send an ERROR() in response to nothing, so discard } @@ -923,11 +919,11 @@ void Node::ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address& d extern "C" { -enum ZT_ResultCode ZT_Node_new(ZT_Node** node, void* uptr, void* tptr, const struct ZT_Node_Callbacks* callbacks, int64_t now) +enum ZT_ResultCode ZT_Node_new(ZT_Node** node, const struct ZT_Node_Config* config, void* uptr, void* tptr, const struct ZT_Node_Callbacks* callbacks, int64_t now) { *node = (ZT_Node*)0; try { - *node = reinterpret_cast(new ZeroTier::Node(uptr, tptr, callbacks, now)); + *node = reinterpret_cast(new ZeroTier::Node(uptr, tptr, config, callbacks, now)); return ZT_RESULT_OK; } catch (std::bad_alloc& exc) { diff --git a/node/Node.hpp b/node/Node.hpp index 2f1075337..8ea09f551 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_NODE_HPP #define ZT_NODE_HPP @@ -25,13 +20,10 @@ #include "NetworkController.hpp" #include "Path.hpp" #include "RuntimeEnvironment.hpp" -#include "Salsa20.hpp" #include "SelfAwareness.hpp" -#include #include #include -#include #include // Bit mask for "expecting reply" hash @@ -49,7 +41,7 @@ class World; */ class Node : public NetworkController::Sender { public: - Node(void* uptr, void* tptr, const struct ZT_Node_Callbacks* callbacks, int64_t now); + Node(void* uptr, void* tptr, const struct ZT_Node_Config* config, const struct ZT_Node_Callbacks* callbacks, int64_t now); virtual ~Node(); // Get rid of alignment warnings on 32-bit Windows and possibly improve performance @@ -290,12 +282,22 @@ class Node : public NetworkController::Sender { inline void setLowBandwidthMode(bool isEnabled) { - _lowBandwidthMode = isEnabled; + _config.lowBandwidthMode = (int)isEnabled; + } + + inline void setEncryptedHelloEnabled(bool isEnabled) + { + _config.enableEncryptedHello = (int)isEnabled; } inline bool lowBandwidthModeEnabled() { - return _lowBandwidthMode; + return _config.lowBandwidthMode != 0; + } + + inline bool encryptedHelloEnabled() + { + return _config.enableEncryptedHello != 0; } void initMultithreading(unsigned int concurrency, bool cpuPinningEnabled); @@ -305,6 +307,7 @@ class Node : public NetworkController::Sender { RuntimeEnvironment* RR; void* _uPtr; // _uptr (lower case) is reserved in Visual Studio :P ZT_Node_Callbacks _cb; + ZT_Node_Config _config; // For tracking packet IDs to filter out OK/ERROR replies to packets we did not send uint8_t _expectingRepliesToBucketPtr[ZT_EXPECTING_REPLIES_BUCKET_MASK1 + 1]; diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index 702a0333e..1978e6e19 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -1,22 +1,16 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "OutboundMulticast.hpp" #include "Constants.hpp" #include "Network.hpp" #include "Node.hpp" -#include "Peer.hpp" #include "RuntimeEnvironment.hpp" #include "Switch.hpp" #include "Topology.hpp" @@ -87,7 +81,7 @@ void OutboundMulticast::sendOnly(const RuntimeEnvironment* RR, void* tPtr, const _packet.setDestination(toAddr); RR->node->expectReplyTo(_packet.packetId()); _tmp = _packet; - RR->sw->send(tPtr, _tmp, true); + RR->sw->send(tPtr, _tmp, true, _nwid, ZT_QOS_NO_FLOW); } } diff --git a/node/OutboundMulticast.hpp b/node/OutboundMulticast.hpp index 542151e2a..f09139269 100644 --- a/node/OutboundMulticast.hpp +++ b/node/OutboundMulticast.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_OUTBOUNDMULTICAST_HPP #define ZT_OUTBOUNDMULTICAST_HPP diff --git a/node/Packet.cpp b/node/Packet.cpp index 88af76105..14bede3a8 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Packet.hpp" diff --git a/node/Packet.hpp b/node/Packet.hpp index 804618476..f6b8fdbdc 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_N_PACKET_HPP #define ZT_N_PACKET_HPP diff --git a/node/PacketMultiplexer.cpp b/node/PacketMultiplexer.cpp index f6f3dc847..673b9a3c1 100644 --- a/node/PacketMultiplexer.cpp +++ b/node/PacketMultiplexer.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2021 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "PacketMultiplexer.hpp" @@ -119,4 +114,4 @@ void PacketMultiplexer::setUpPostDecodeReceiveThreads(unsigned int concurrency, } } -} // namespace ZeroTier \ No newline at end of file +} // namespace ZeroTier diff --git a/node/PacketMultiplexer.hpp b/node/PacketMultiplexer.hpp index 4753180ed..cd8093fe6 100644 --- a/node/PacketMultiplexer.hpp +++ b/node/PacketMultiplexer.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2021 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_PACKET_MULTIPLEXER_HPP #define ZT_PACKET_MULTIPLEXER_HPP @@ -62,4 +57,4 @@ class PacketMultiplexer { } // namespace ZeroTier -#endif // ZT_PACKET_MULTIPLEXER_HPP \ No newline at end of file +#endif // ZT_PACKET_MULTIPLEXER_HPP diff --git a/node/Path.cpp b/node/Path.cpp index 875f05b4a..1525d9e8f 100644 --- a/node/Path.cpp +++ b/node/Path.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Path.hpp" diff --git a/node/Path.hpp b/node/Path.hpp index 2639173ee..ee4c383bc 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_PATH_HPP #define ZT_PATH_HPP diff --git a/node/Peer.cpp b/node/Peer.cpp index 68ed4d64e..65199badb 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Peer.hpp" @@ -19,8 +14,8 @@ #include "InetAddress.hpp" #include "Metrics.hpp" #include "Network.hpp" +#include "Node.hpp" #include "Packet.hpp" -#include "RingBuffer.hpp" #include "SelfAwareness.hpp" #include "Switch.hpp" #include "Trace.hpp" @@ -464,13 +459,13 @@ void Peer::sendHELLO(void* tPtr, const int64_t localSocket, const InetAddress& a Metrics::pkt_hello_out++; if (atAddress) { - outp.armor(_key, false, true, nullptr, _id); + outp.armor(_key, false, RR->node->encryptedHelloEnabled(), nullptr, _id); RR->node->expectReplyTo(outp.packetId()); RR->node->putPacket(tPtr, RR->node->lowBandwidthModeEnabled() ? localSocket : -1, atAddress, outp.data(), outp.size()); } else { RR->node->expectReplyTo(outp.packetId()); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, 0, ZT_QOS_NO_FLOW); } } diff --git a/node/Peer.hpp b/node/Peer.hpp index 62524dee1..8bd36bd3d 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_PEER_HPP #define ZT_PEER_HPP @@ -20,12 +15,10 @@ #include "AtomicCounter.hpp" #include "Bond.hpp" #include "Constants.hpp" -#include "Hashtable.hpp" #include "Identity.hpp" #include "InetAddress.hpp" #include "Metrics.hpp" #include "Mutex.hpp" -#include "Node.hpp" #include "Packet.hpp" #include "Path.hpp" #include "RuntimeEnvironment.hpp" diff --git a/node/Poly1305.hpp b/node/Poly1305.hpp index e5c3a8547..7ffbdd710 100644 --- a/node/Poly1305.hpp +++ b/node/Poly1305.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_POLY1305_HPP #define ZT_POLY1305_HPP diff --git a/node/Revocation.cpp b/node/Revocation.cpp index 6da98f269..968ad6030 100644 --- a/node/Revocation.cpp +++ b/node/Revocation.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Revocation.hpp" diff --git a/node/Revocation.hpp b/node/Revocation.hpp index b6edccf57..3337aabce 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_REVOCATION_HPP #define ZT_REVOCATION_HPP diff --git a/node/RingBuffer.hpp b/node/RingBuffer.hpp index f99562894..32474aaa4 100644 --- a/node/RingBuffer.hpp +++ b/node/RingBuffer.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_RINGBUFFER_H #define ZT_RINGBUFFER_H diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index f55955ee8..8fca47300 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_RUNTIMEENVIRONMENT_HPP #define ZT_RUNTIMEENVIRONMENT_HPP diff --git a/node/SHA512.hpp b/node/SHA512.hpp index 3849856ef..abd525ec5 100644 --- a/node/SHA512.hpp +++ b/node/SHA512.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_SHA512_HPP #define ZT_SHA512_HPP diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index c73dd4b05..098eb941c 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "SelfAwareness.hpp" diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index 527537003..1ee64df2a 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_SELFAWARENESS_HPP #define ZT_SELFAWARENESS_HPP diff --git a/node/SharedPtr.hpp b/node/SharedPtr.hpp index ef720cab8..f4e936a4b 100644 --- a/node/SharedPtr.hpp +++ b/node/SharedPtr.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_SHAREDPTR_HPP #define ZT_SHAREDPTR_HPP diff --git a/node/Switch.cpp b/node/Switch.cpp index 6b0e2b081..efa6c0ba2 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -1,20 +1,14 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Switch.hpp" #include "../include/ZeroTierOne.h" -#include "../version.h" #include "Constants.hpp" #include "InetAddress.hpp" #include "Metrics.hpp" @@ -27,14 +21,12 @@ #include "Trace.hpp" #include -#include #include #include -#include namespace ZeroTier { -Switch::Switch(const RuntimeEnvironment* renv) : RR(renv), _lastBeaconResponse(0), _lastCheckedQueues(0), _lastUniteAttempt(8) // only really used on root servers and upstreams, and it'll grow there just fine +Switch::Switch(const RuntimeEnvironment* renv) : RR(renv), _lastBeaconResponse(0), _lastCheckedQueues(0), _lastUniteAttempt(8) { } @@ -86,6 +78,7 @@ void Switch::onRemotePacket(void* tPtr, const int64_t localSocket, const InetAdd const Address destination(fragment.destination()); if (destination != RR->identity.address()) { + // RELAY: fragment is for a different node, so maybe send it there if we should relay. if ((! RR->topology->amUpstream()) && (! path->trustEstablished(now))) { return; } @@ -98,7 +91,7 @@ void Switch::onRemotePacket(void* tPtr, const int64_t localSocket, const InetAdd SharedPtr relayTo = RR->topology->getPeer(tPtr, destination); if ((! relayTo) || (! relayTo->sendDirect(tPtr, fragment.data(), fragment.size(), now, false))) { // Don't know peer or no direct path -- so relay via someone upstream - relayTo = RR->topology->getUpstreamPeer(); + relayTo = RR->topology->getUpstreamPeer(0); if (relayTo) { relayTo->sendDirect(tPtr, fragment.data(), fragment.size(), now, true); } @@ -106,7 +99,8 @@ void Switch::onRemotePacket(void* tPtr, const int64_t localSocket, const InetAdd } } else { - // Fragment looks like ours + // RECEIVE: fragment appears to be ours (this is validated in cryptographic auth after assembly) + const uint64_t fragmentPacketId = fragment.packetId(); const unsigned int fragmentNumber = fragment.fragmentNumber(); const unsigned int totalFragments = fragment.totalFragments(); @@ -167,6 +161,8 @@ void Switch::onRemotePacket(void* tPtr, const int64_t localSocket, const InetAdd } if (destination != RR->identity.address()) { + // RELAY: packet head is for a different node, so maybe send it there if we should relay. + if ((! RR->topology->amUpstream()) && (! path->trustEstablished(now)) && (source != RR->identity.address())) { return; } @@ -185,7 +181,7 @@ void Switch::onRemotePacket(void* tPtr, const int64_t localSocket, const InetAdd } } else { - relayTo = RR->topology->getUpstreamPeer(); + relayTo = RR->topology->getUpstreamPeer(0); if ((relayTo) && (relayTo->address() != source)) { if (relayTo->sendDirect(tPtr, packet.data(), packet.size(), now, true)) { const SharedPtr sourcePeer(RR->topology->getPeer(tPtr, source)); @@ -198,7 +194,7 @@ void Switch::onRemotePacket(void* tPtr, const int64_t localSocket, const InetAdd } } else if ((reinterpret_cast(data)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_FRAGMENTED) != 0) { - // Packet is the head of a fragmented packet series + // RECEIVE: packet head appears to be ours (this is validated in cryptographic auth after assembly) const uint64_t packetId = ((((uint64_t)reinterpret_cast(data)[0]) << 56) | (((uint64_t)reinterpret_cast(data)[1]) << 48) | (((uint64_t)reinterpret_cast(data)[2]) << 40) @@ -243,7 +239,8 @@ void Switch::onRemotePacket(void* tPtr, const int64_t localSocket, const InetAdd } // else this is a duplicate head, ignore } else { - // Packet is unfragmented, so just process it + // RECEIVE: unfragmented packet appears to be ours (this is validated in cryptographic auth after assembly) + IncomingPacket packet(data, len, path, now); if (! packet.tryDecode(RR, tPtr, flowId)) { RXQueueEntry* const rq = _nextRXQueueEntry(); @@ -550,10 +547,7 @@ void Switch::onLocalEthernet(void* tPtr, const SharedPtr& network, cons outp.append(network->id()); outp.append((uint16_t)etherType); outp.append(data, len); - // 1.4.8: disable compression for unicast as it almost never helps - // if (!network->config().disableCompression()) - // outp.compress(); - aqm_enqueue(tPtr, network, outp, true, qosBucket, flowId); + aqm_enqueue(tPtr, network, outp, true, qosBucket, network->id(), flowId); } else { Packet outp(toZT, RR->identity.address(), Packet::VERB_EXT_FRAME); @@ -563,10 +557,7 @@ void Switch::onLocalEthernet(void* tPtr, const SharedPtr& network, cons from.appendTo(outp); outp.append((uint16_t)etherType); outp.append(data, len); - // 1.4.8: disable compression for unicast as it almost never helps - // if (!network->config().disableCompression()) - // outp.compress(); - aqm_enqueue(tPtr, network, outp, true, qosBucket, flowId); + aqm_enqueue(tPtr, network, outp, true, qosBucket, network->id(), flowId); } } else { @@ -627,10 +618,7 @@ void Switch::onLocalEthernet(void* tPtr, const SharedPtr& network, cons from.appendTo(outp); outp.append((uint16_t)etherType); outp.append(data, len); - // 1.4.8: disable compression for unicast as it almost never helps - // if (!network->config().disableCompression()) - // outp.compress(); - aqm_enqueue(tPtr, network, outp, true, qosBucket, flowId); + aqm_enqueue(tPtr, network, outp, true, qosBucket, network->id(), flowId); } else { RR->t->outgoingNetworkFrameDropped(tPtr, network, from, to, etherType, vlanId, len, "filter blocked (bridge replication)"); @@ -639,10 +627,10 @@ void Switch::onLocalEthernet(void* tPtr, const SharedPtr& network, cons } } -void Switch::aqm_enqueue(void* tPtr, const SharedPtr& network, Packet& packet, bool encrypt, int qosBucket, int32_t flowId) +void Switch::aqm_enqueue(void* tPtr, const SharedPtr& network, Packet& packet, const bool encrypt, const int qosBucket, const uint64_t nwid, const int32_t flowId) { if (! network->qosEnabled()) { - send(tPtr, packet, encrypt, flowId); + send(tPtr, packet, encrypt, nwid, flowId); return; } NetworkQoSControlBlock* nqcb = _netQueueControlBlock[network->id()]; @@ -657,7 +645,7 @@ void Switch::aqm_enqueue(void* tPtr, const SharedPtr& network, Packet& } // Don't apply QoS scheduling to ZT protocol traffic if (packet.verb() != Packet::VERB_FRAME && packet.verb() != Packet::VERB_EXT_FRAME) { - send(tPtr, packet, encrypt, flowId); + send(tPtr, packet, encrypt, nwid, flowId); } _aqm_m.lock(); @@ -665,7 +653,7 @@ void Switch::aqm_enqueue(void* tPtr, const SharedPtr& network, Packet& // Enqueue packet and move queue to appropriate list const Address dest(packet.destination()); - TXQueueEntry* txEntry = new TXQueueEntry(dest, RR->node->now(), packet, encrypt, flowId); + TXQueueEntry* txEntry = new TXQueueEntry(dest, nwid, RR->node->now(), packet, encrypt, flowId); ManagedQueue* selectedQueue = nullptr; for (size_t i = 0; i < ZT_AQM_NUM_BUCKETS; i++) { @@ -845,7 +833,7 @@ void Switch::aqm_dequeue(void* tPtr) queueAtFrontOfList->byteCredit -= len; // Send the packet! queueAtFrontOfList->q.pop_front(); - send(tPtr, entryToEmit->packet, entryToEmit->encrypt, entryToEmit->flowId); + send(tPtr, entryToEmit->packet, entryToEmit->encrypt, entryToEmit->nwid, entryToEmit->flowId); (*nqcb).second->_currEnqueuedPackets--; } if (queueAtFrontOfList) { @@ -878,7 +866,7 @@ void Switch::aqm_dequeue(void* tPtr) queueAtFrontOfList->byteLength -= len; queueAtFrontOfList->byteCredit -= len; queueAtFrontOfList->q.pop_front(); - send(tPtr, entryToEmit->packet, entryToEmit->encrypt, entryToEmit->flowId); + send(tPtr, entryToEmit->packet, entryToEmit->encrypt, entryToEmit->nwid, entryToEmit->flowId); (*nqcb).second->_currEnqueuedPackets--; } if (queueAtFrontOfList) { @@ -902,20 +890,20 @@ void Switch::removeNetworkQoSControlBlock(uint64_t nwid) } } -void Switch::send(void* tPtr, Packet& packet, bool encrypt, int32_t flowId) +void Switch::send(void* tPtr, Packet& packet, const bool encrypt, const uint64_t nwid, const int32_t flowId) { const Address dest(packet.destination()); if (dest == RR->identity.address()) { return; } _recordOutgoingPacketMetrics(packet); - if (! _trySend(tPtr, packet, encrypt, flowId)) { + if (! _trySend(tPtr, packet, encrypt, nwid, flowId)) { { Mutex::Lock _l(_txQueue_m); if (_txQueue.size() >= ZT_TX_QUEUE_SIZE) { _txQueue.pop_front(); } - _txQueue.push_back(TXQueueEntry(dest, RR->node->now(), packet, encrypt, flowId)); + _txQueue.push_back(TXQueueEntry(dest, nwid, RR->node->now(), packet, encrypt, flowId)); } if (! RR->topology->getPeer(tPtr, dest)) { requestWhois(tPtr, RR->node->now(), dest); @@ -940,12 +928,12 @@ void Switch::requestWhois(void* tPtr, const int64_t now, const Address& addr) } } - const SharedPtr upstream(RR->topology->getUpstreamPeer()); + const SharedPtr upstream(RR->topology->getUpstreamPeer(0)); if (upstream) { int32_t flowId = ZT_QOS_NO_FLOW; Packet outp(upstream->address(), RR->identity.address(), Packet::VERB_WHOIS); addr.appendTo(outp); - send(tPtr, outp, true, flowId); + send(tPtr, outp, true, 0, flowId); } } @@ -971,7 +959,7 @@ void Switch::doAnythingWaitingForPeer(void* tPtr, const SharedPtr& peer) Mutex::Lock _l(_txQueue_m); for (std::list::iterator txi(_txQueue.begin()); txi != _txQueue.end();) { if (txi->dest == peer->address()) { - if (_trySend(tPtr, txi->packet, txi->encrypt, txi->flowId)) { + if (_trySend(tPtr, txi->packet, txi->encrypt, txi->nwid, txi->flowId)) { _txQueue.erase(txi++); } else { @@ -998,7 +986,7 @@ unsigned long Switch::doTimerTasks(void* tPtr, int64_t now) Mutex::Lock _l(_txQueue_m); for (std::list::iterator txi(_txQueue.begin()); txi != _txQueue.end();) { - if (_trySend(tPtr, txi->packet, txi->encrypt, txi->flowId)) { + if (_trySend(tPtr, txi->packet, txi->encrypt, 0, txi->flowId)) { _txQueue.erase(txi++); } else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) { @@ -1070,7 +1058,7 @@ bool Switch::_shouldUnite(const int64_t now, const Address& source, const Addres return false; } -bool Switch::_trySend(void* tPtr, Packet& packet, bool encrypt, int32_t flowId) +bool Switch::_trySend(void* tPtr, Packet& packet, bool encrypt, const uint64_t nwid, const int32_t flowId) { SharedPtr viaPath; const int64_t now = RR->node->now(); @@ -1079,7 +1067,7 @@ bool Switch::_trySend(void* tPtr, Packet& packet, bool encrypt, int32_t flowId) const SharedPtr peer(RR->topology->getPeer(tPtr, destination)); if (peer) { if ((peer->bondingPolicy() == ZT_BOND_POLICY_BROADCAST) && (packet.verb() == Packet::VERB_FRAME || packet.verb() == Packet::VERB_EXT_FRAME)) { - const SharedPtr relay(RR->topology->getUpstreamPeer()); + const SharedPtr relay(RR->topology->getUpstreamPeer(nwid)); Mutex::Lock _l(peer->_paths_m); for (int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) { if (peer->_paths[i].p && peer->_paths[i].p->alive(now)) { @@ -1093,7 +1081,7 @@ bool Switch::_trySend(void* tPtr, Packet& packet, bool encrypt, int32_t flowId) viaPath = peer->getAppropriatePath(now, false, flowId); if (! viaPath) { peer->tryMemorizedPath(tPtr, now); // periodically attempt memorized or statically defined paths, if any are known - const SharedPtr relay(RR->topology->getUpstreamPeer()); + const SharedPtr relay(RR->topology->getUpstreamPeer(nwid)); if ((! relay) || (! (viaPath = relay->getAppropriatePath(now, false, flowId)))) { if (! (viaPath = peer->getAppropriatePath(now, true, flowId))) { return false; diff --git a/node/Switch.hpp b/node/Switch.hpp index cf8270d43..7c287f45e 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_N_SWITCH_HPP #define ZT_N_SWITCH_HPP @@ -24,11 +19,9 @@ #include "Packet.hpp" #include "SharedPtr.hpp" #include "Topology.hpp" -#include "Utils.hpp" #include #include -#include #include /* Ethernet frame types that might be relevant to us */ @@ -124,7 +117,7 @@ class Switch { * @param encrypt Encrypt packet payload? (always true except for HELLO) * @param qosBucket Which bucket the rule-system determined this packet should fall into */ - void aqm_enqueue(void* tPtr, const SharedPtr& network, Packet& packet, bool encrypt, int qosBucket, int32_t flowId = ZT_QOS_NO_FLOW); + void aqm_enqueue(void* tPtr, const SharedPtr& network, Packet& packet, const bool encrypt, const int qosBucket, const uint64_t nwid, const int32_t flowId /* = ZT_QOS_NO_FLOW*/); /** * Performs a single AQM cycle and dequeues and transmits all eligible packets on all networks @@ -169,8 +162,9 @@ class Switch { * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param packet Packet to send (buffer may be modified) * @param encrypt Encrypt packet payload? (always true except for HELLO) + * @param nwid Network ID to which this packet is related or 0 if none */ - void send(void* tPtr, Packet& packet, bool encrypt, int32_t flowId = ZT_QOS_NO_FLOW); + void send(void* tPtr, Packet& packet, const bool encrypt, const uint64_t nwid, const int32_t flowId /* = ZT_QOS_NO_FLOW*/); /** * Request WHOIS on a given address @@ -205,7 +199,7 @@ class Switch { private: bool _shouldUnite(const int64_t now, const Address& source, const Address& destination); - bool _trySend(void* tPtr, Packet& packet, bool encrypt, int32_t flowId = ZT_QOS_NO_FLOW); // packet is modified if return is true + bool _trySend(void* tPtr, Packet& packet, bool encrypt, const uint64_t nwid, const int32_t flowId /* = ZT_QOS_NO_FLOW*/); void _sendViaSpecificPath(void* tPtr, SharedPtr peer, SharedPtr viaPath, uint16_t userSpecifiedMtu, int64_t now, Packet& packet, bool encrypt, int32_t flowId); void _recordOutgoingPacketMetrics(const Packet& p); @@ -260,11 +254,12 @@ class Switch { TXQueueEntry() { } - TXQueueEntry(Address d, uint64_t ct, const Packet& p, bool enc, int32_t fid) : dest(d), creationTime(ct), packet(p), encrypt(enc), flowId(fid) + TXQueueEntry(Address d, uint64_t nwid, uint64_t ct, const Packet& p, bool enc, int32_t fid) : dest(d), nwid(nwid), creationTime(ct), packet(p), encrypt(enc), flowId(fid) { } Address dest; + uint64_t nwid; uint64_t creationTime; Packet packet; // unencrypted/unMAC'd packet -- this is done at send time bool encrypt; diff --git a/node/Tag.cpp b/node/Tag.cpp index a1ce0c0ed..7d483343e 100644 --- a/node/Tag.cpp +++ b/node/Tag.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Tag.hpp" diff --git a/node/Tag.hpp b/node/Tag.hpp index 0243264af..3273ba03e 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_TAG_HPP #define ZT_TAG_HPP diff --git a/node/Topology.cpp b/node/Topology.cpp index fc7e4ad1b..6959ac858 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -1,25 +1,19 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Topology.hpp" #include "Buffer.hpp" -#include "Constants.hpp" #include "Network.hpp" -#include "NetworkConfig.hpp" #include "Node.hpp" #include "RuntimeEnvironment.hpp" #include "Switch.hpp" +#include "Trace.hpp" namespace ZeroTier { @@ -146,30 +140,42 @@ Identity Topology::getIdentity(void* tPtr, const Address& zta) return Identity(); } -SharedPtr Topology::getUpstreamPeer() +SharedPtr Topology::getUpstreamPeer(const uint64_t nwid) { const int64_t now = RR->node->now(); unsigned int bestq = ~((unsigned int)0); const SharedPtr* best = (const SharedPtr*)0; - Mutex::Lock _l2(_peers_m); - Mutex::Lock _l1(_upstreams_m); + /* + // If this is related to a network, check for a network specific relay. + if (nwid) { + SharedPtr network = RR->node->network(nwid); + if (network) { + // + } + } + */ - for (std::vector
::const_iterator a(_upstreamAddresses.begin()); a != _upstreamAddresses.end(); ++a) { - const SharedPtr* p = _peers.get(*a); - if (p) { - const unsigned int q = (*p)->relayQuality(now); - if (q <= bestq) { - bestq = q; - best = p; + // If this is unrelated to a network OR there is no network-specific relay, send via a root. + { + Mutex::Lock _l2(_peers_m); + Mutex::Lock _l1(_upstreams_m); + for (std::vector
::const_iterator a(_upstreamAddresses.begin()); a != _upstreamAddresses.end(); ++a) { + const SharedPtr* p = _peers.get(*a); + if (p) { + const unsigned int q = (*p)->relayQuality(now); + if (q <= bestq) { + bestq = q; + best = p; + } } } + if (best) { + return *best; + } } - if (! best) { - return SharedPtr(); - } - return *best; + return SharedPtr(); } bool Topology::isUpstream(const Identity& id) const @@ -245,6 +251,38 @@ bool Topology::isProhibitedEndpoint(const Address& ztaddr, const InetAddress& ip return false; } +void Topology::getRootsToContact(Hashtable >& eps) const +{ + Mutex::Lock _l(_upstreams_m); + + for (std::vector::const_iterator i(_planet.roots().begin()); i != _planet.roots().end(); ++i) { + if (i->identity != RR->identity) { + std::vector& ips = eps[i->identity.address()]; + for (std::vector::const_iterator j(i->stableEndpoints.begin()); j != i->stableEndpoints.end(); ++j) { + if (std::find(ips.begin(), ips.end(), *j) == ips.end()) { + ips.push_back(*j); + } + } + } + } + + for (std::vector::const_iterator m(_moons.begin()); m != _moons.end(); ++m) { + for (std::vector::const_iterator i(m->roots().begin()); i != m->roots().end(); ++i) { + if (i->identity != RR->identity) { + std::vector& ips = eps[i->identity.address()]; + for (std::vector::const_iterator j(i->stableEndpoints.begin()); j != i->stableEndpoints.end(); ++j) { + if (std::find(ips.begin(), ips.end(), *j) == ips.end()) { + ips.push_back(*j); + } + } + } + } + } + for (std::vector >::const_iterator m(_moonSeeds.begin()); m != _moonSeeds.end(); ++m) { + eps[m->second]; + } +} + bool Topology::addWorld(void* tPtr, const World& newWorld, bool alwaysAcceptNew) { if ((newWorld.type() != World::TYPE_PLANET) && (newWorld.type() != World::TYPE_MOON)) { diff --git a/node/Topology.hpp b/node/Topology.hpp index 746cb30ce..527e27356 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -1,22 +1,16 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_TOPOLOGY_HPP #define ZT_TOPOLOGY_HPP #include "../include/ZeroTierOne.h" #include "Address.hpp" -#include "Constants.hpp" #include "Hashtable.hpp" #include "Identity.hpp" #include "InetAddress.hpp" @@ -26,9 +20,7 @@ #include "World.hpp" #include -#include #include -#include #include #include @@ -112,9 +104,10 @@ class Topology { /** * Get the current best upstream peer * + * @param nwid Network ID or 0 if this is to send something unrelated to a specific network * @return Upstream or NULL if none available */ - SharedPtr getUpstreamPeer(); + SharedPtr getUpstreamPeer(const uint64_t nwid); /** * @param id Identity to check @@ -155,35 +148,7 @@ class Topology { * * @param eps Hash table to fill with addresses and their stable endpoints */ - inline void getUpstreamsToContact(Hashtable >& eps) const - { - Mutex::Lock _l(_upstreams_m); - for (std::vector::const_iterator i(_planet.roots().begin()); i != _planet.roots().end(); ++i) { - if (i->identity != RR->identity) { - std::vector& ips = eps[i->identity.address()]; - for (std::vector::const_iterator j(i->stableEndpoints.begin()); j != i->stableEndpoints.end(); ++j) { - if (std::find(ips.begin(), ips.end(), *j) == ips.end()) { - ips.push_back(*j); - } - } - } - } - for (std::vector::const_iterator m(_moons.begin()); m != _moons.end(); ++m) { - for (std::vector::const_iterator i(m->roots().begin()); i != m->roots().end(); ++i) { - if (i->identity != RR->identity) { - std::vector& ips = eps[i->identity.address()]; - for (std::vector::const_iterator j(i->stableEndpoints.begin()); j != i->stableEndpoints.end(); ++j) { - if (std::find(ips.begin(), ips.end(), *j) == ips.end()) { - ips.push_back(*j); - } - } - } - } - } - for (std::vector >::const_iterator m(_moonSeeds.begin()); m != _moonSeeds.end(); ++m) { - eps[m->second]; - } - } + void getRootsToContact(Hashtable >& eps) const; /** * @return Vector of active upstream addresses (including roots) diff --git a/node/Trace.cpp b/node/Trace.cpp index 982047093..8fc4394e6 100644 --- a/node/Trace.cpp +++ b/node/Trace.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ // #define ZT_TRACE @@ -19,13 +14,13 @@ #include "Capability.hpp" #include "CertificateOfMembership.hpp" #include "CertificateOfOwnership.hpp" +#include "Constants.hpp" #include "Dictionary.hpp" #include "Node.hpp" #include "Revocation.hpp" #include "RuntimeEnvironment.hpp" #include "Switch.hpp" #include "Tag.hpp" -#include "Utils.hpp" #include #include @@ -632,7 +627,7 @@ void Trace::_send(void* const tPtr, const Dictionary& Packet outp(dest, RR->identity.address(), Packet::VERB_REMOTE_TRACE); outp.appendCString(d.data()); outp.compress(); - RR->sw->send(tPtr, outp, true); + RR->sw->send(tPtr, outp, true, 0, ZT_QOS_NO_FLOW); } void Trace::_spamToAllNetworks(void* const tPtr, const Dictionary& d, const Level level) diff --git a/node/Trace.hpp b/node/Trace.hpp index 991974c50..5a77c3798 100644 --- a/node/Trace.hpp +++ b/node/Trace.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_TRACE_HPP #define ZT_TRACE_HPP diff --git a/node/Utils.cpp b/node/Utils.cpp index ad838a7fb..705b6bd46 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Constants.hpp" diff --git a/node/Utils.hpp b/node/Utils.hpp index 76241ab56..157e10a3a 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_UTILS_HPP #define ZT_UTILS_HPP diff --git a/node/World.hpp b/node/World.hpp index 6806a01b9..bf148972c 100644 --- a/node/World.hpp +++ b/node/World.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_WORLD_HPP #define ZT_WORLD_HPP diff --git a/nonfree/CMakeLists.txt b/nonfree/CMakeLists.txt new file mode 100644 index 000000000..82d587d7c --- /dev/null +++ b/nonfree/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.13) + +add_subdirectory(controller) \ No newline at end of file diff --git a/nonfree/LICENSE.md b/nonfree/LICENSE.md new file mode 100644 index 000000000..3faedadbf --- /dev/null +++ b/nonfree/LICENSE.md @@ -0,0 +1,103 @@ +# ZeroTier SOURCE-AVAILABLE LICENSE +Version 1.0 +Copyright (c) 2025 ZeroTier, Inc. + +## DEFINITIONS + +"Software" means ZeroTier and all associated documentation, source code, object code, and any derivatives thereof. + +"Non-Commercial Use" means use of the Software solely for: +- Personal, non-commercial purposes, in a non-commercial environment +- Educational or academic research purposes (for students, not for organizational use) +- Evaluation purposes for a period not exceeding 30 days + +"Commercial Use" includes, but is not limited to: +- Any use of the Software by or for the benefit of a for-profit company +- Any use of the Software by or for the benefit of a government or military entity +- Any use of the Software by or for the benefit of a non-profit organization, or registered charity +- Use in a production, staging, or development environment for business purposes + +- Offering paid or unpaid services powered by the Software +- Incorporation of the Software into any paid or unpaid product, platform, distribution or service + +## LICENSE STRUCTURE + +This software distribution includes components governed by different license terms: + +- The "ZeroTier Agent" component is licensed under the Mozilla Public License 2.0 (MPL-2.0). See the LICENSE-MPL.txt file in project root for details. +- The "Controller" and other related components, located in the “nonfree” source directory, are licensed under this Source-Available License for Non-Commercial Use. Use of any of these components for Commercial Use requires a separate commercial license agreement with ZeroTier, Inc. + +## GRANT OF LICENSE + +### Non-Commercial License Grant +Permission is hereby granted, free of charge, to any person obtaining a copy of this Software, to use, copy, modify, and distribute the Software for Non-Commercial Use only, subject to the following conditions: +1. The above copyright notice and this license shall be included in all copies, modified versions and redistributions, in whole or in part of the Software. +2. The Software may not be used for Commercial Use without obtaining a separate commercial license. +3. Any modifications to the Software must be clearly noted in both the source code and documentation as such and must not be misrepresented as the original Software. +4. If you distribute the Software or any derivative works, you must retain all copyright, trademark, attribution notices, and this license text. + +### Commercial License Requirement + +ANY COMMERCIAL USE OF THIS SOFTWARE REQUIRES A SEPARATE COMMERCIAL LICENSE. + +To obtain a commercial license, please contact: +sales@zerotier.com +https://www.zerotier.com/ + +## RESTRICTIONS +You may NOT: +- Use the Software for Commercial Use without a commercial license +- Remove or alter any proprietary notices, copyright or trademark statements, headers, metadata, logos, branding or other identifying information in the Software +- Use the trademarks, service marks, trade names, logos, or other brand identifiers of the copyright holder in a manner likely to cause confusion about the source, sponsorship, or endorsement of the Software without prior written permission +- Imply endorsement by the copyright holder, directly or indirectly, without written permission + +## RESERVATION OF RIGHTS + +All rights not expressly granted herein are reserved by the copyright holder. No rights or licenses are granted by implication, estoppel, or otherwise. + +## NO PATENT LICENSE + +This License does not grant any rights under any patent owned or controlled by the copyright holder. To inquire about patent licensing, please contact: legal@zerotier.com + +## CONTRIBUTIONS + +If you contribute any code, bug fixes, or enhancements to the Software, you grant the copyright holder a perpetual, worldwide, royalty-free license to use, modify, reproduce, sublicense, and distribute such contributions for any purpose, including Commercial Use. + +## DISCLAIMER +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +## COMPLIANCE AND VERIFICATION + +To ensure compliance with this License, you agree to provide, upon request, reasonable documentation demonstrating that your use of the Software qualifies as Non-Commercial Use. Failure to provide such documentation within 30 days may result in termination of this License. + +## TERMINATION + +This license automatically terminates if you: +- Use the Software for Commercial Use without obtaining a commercial license +- Fail to comply with any of the terms and conditions stated herein +- Initiate legal action against the copyright holder related to the Software +Upon termination, you must cease all use of the Software and destroy all copies in your possession. + +## GOVERNING LAW +This License shall be governed by the laws of California, USA, without regard to conflict of law principles. + +## ENFORCEMENT + +The copyright holder reserves the right to enforce this License through legal or equitable remedies, including injunctive relief, in the event of a violation of its terms. + +## ENTIRE AGREEMENT +This License constitutes the entire agreement between the parties concerning the use of the Software for Non-Commercial Use and supersedes all prior or contemporaneous agreements regarding such use. + +--- +## NOTICE TO USERS + +This Software is source-available, but it is not “open source” as defined by the Open Source Initiative. + +The "ZeroTier Agent" component is licensed under the Mozilla Public License 2.0 (MPL-2.0). +The "Controller" and related components, located in the “nonfree” source directory, are licensed under this Source-Available License. + +Commercial use, as defined above, requires a paid commercial license. + +For inquiries, please contact: +sales@zerotier.com +Or visit: https://www.zerotier.com/ diff --git a/controller/BigTableStatusWriter.cpp b/nonfree/controller/BigTableStatusWriter.cpp similarity index 100% rename from controller/BigTableStatusWriter.cpp rename to nonfree/controller/BigTableStatusWriter.cpp diff --git a/controller/BigTableStatusWriter.hpp b/nonfree/controller/BigTableStatusWriter.hpp similarity index 100% rename from controller/BigTableStatusWriter.hpp rename to nonfree/controller/BigTableStatusWriter.hpp diff --git a/controller/CMakeLists.txt b/nonfree/controller/CMakeLists.txt similarity index 98% rename from controller/CMakeLists.txt rename to nonfree/controller/CMakeLists.txt index 670858caa..57560ce20 100644 --- a/controller/CMakeLists.txt +++ b/nonfree/controller/CMakeLists.txt @@ -11,8 +11,6 @@ set(SRC_FILES EmbeddedNetworkController.hpp FileDB.cpp FileDB.hpp - LFDB.cpp - LFDB.hpp CtlUtil.cpp CtlUtil.hpp ) diff --git a/controller/CV1.cpp b/nonfree/controller/CV1.cpp similarity index 99% rename from controller/CV1.cpp rename to nonfree/controller/CV1.cpp index e739561bb..dd45360cb 100644 --- a/controller/CV1.cpp +++ b/nonfree/controller/CV1.cpp @@ -1,23 +1,14 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #include "CV1.hpp" #ifdef ZT_CONTROLLER_USE_LIBPQ -#include "../node/Constants.hpp" -#include "../node/SHA512.hpp" -#include "../version.h" +#include "../../node/Constants.hpp" +#include "../../node/SHA512.hpp" +#include "../../version.h" #include "CtlUtil.hpp" #include "EmbeddedNetworkController.hpp" #include "Redis.hpp" diff --git a/controller/CV1.hpp b/nonfree/controller/CV1.hpp similarity index 82% rename from controller/CV1.hpp rename to nonfree/controller/CV1.hpp index e65cdb2af..2552be358 100644 --- a/controller/CV1.hpp +++ b/nonfree/controller/CV1.hpp @@ -1,15 +1,6 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #include "DB.hpp" @@ -20,7 +11,7 @@ #define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4 -#include "../node/Metrics.hpp" +#include "../../node/Metrics.hpp" #include "ConnectionPool.hpp" #include "PostgreSQL.hpp" @@ -56,7 +47,11 @@ class CV1 : public DB { virtual void eraseNetwork(const uint64_t networkId); virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); - virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch); + virtual void nodeIsOnline( + const uint64_t networkId, + const uint64_t memberId, + const InetAddress& physicalAddress, + const char* osArch); virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL); virtual bool ready() @@ -98,7 +93,10 @@ class CV1 : public DB { void onlineNotificationThread(); void onlineNotification_Postgres(); void onlineNotification_Redis(); - uint64_t _doRedisUpdate(sw::redis::Transaction& tx, std::string& controllerId, std::unordered_map, NodeOnlineRecord, _PairHasher>& lastOnline); + uint64_t _doRedisUpdate( + sw::redis::Transaction& tx, + std::string& controllerId, + std::unordered_map, NodeOnlineRecord, _PairHasher>& lastOnline); void configureSmee(); void notifyNewMember(const std::string& networkID, const std::string& memberID); diff --git a/controller/CV2.cpp b/nonfree/controller/CV2.cpp similarity index 98% rename from controller/CV2.cpp rename to nonfree/controller/CV2.cpp index 9be950f1d..01631ab4e 100644 --- a/controller/CV2.cpp +++ b/nonfree/controller/CV2.cpp @@ -1,23 +1,14 @@ -/* - * Copyright (c)2025 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ - -#include "CV2.hpp" #ifdef ZT_CONTROLLER_USE_LIBPQ -#include "../node/Constants.hpp" -#include "../node/SHA512.hpp" -#include "../version.h" +#include "CV2.hpp" + +#include "../../node/Constants.hpp" +#include "../../node/SHA512.hpp" +#include "../../version.h" #include "CtlUtil.hpp" #include "EmbeddedNetworkController.hpp" #include "opentelemetry/trace/provider.h" @@ -1246,4 +1237,4 @@ void CV2::onlineNotificationThread() exit(6); } } -#endif // ZT_CONTROLLER_USE_LIBPQ \ No newline at end of file +#endif // ZT_CONTROLLER_USE_LIBPQ diff --git a/controller/CV2.hpp b/nonfree/controller/CV2.hpp similarity index 86% rename from controller/CV2.hpp rename to nonfree/controller/CV2.hpp index 12c3ed440..5257ed037 100644 --- a/controller/CV2.hpp +++ b/nonfree/controller/CV2.hpp @@ -1,15 +1,6 @@ -/* - * Copyright (c)2025 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #include "DB.hpp" @@ -20,7 +11,7 @@ #define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4 -#include "../node/Metrics.hpp" +#include "../../node/Metrics.hpp" #include "ConnectionPool.hpp" #include "PostgreSQL.hpp" @@ -29,7 +20,6 @@ #include namespace ZeroTier { - class CV2 : public DB { friend class MemberNotificationReceiver; friend class NetworkNotificationReceiver; @@ -107,4 +97,4 @@ class CV2 : public DB { } // namespace ZeroTier #endif // ZT_CONTROLLER_CV2_HPP -#endif // ZT_CONTROLLER_USE_LIBPQ \ No newline at end of file +#endif // ZT_CONTROLLER_USE_LIBPQ diff --git a/controller/CentralDB.cpp b/nonfree/controller/CentralDB.cpp similarity index 99% rename from controller/CentralDB.cpp rename to nonfree/controller/CentralDB.cpp index 80cfa6982..846565e0f 100644 --- a/controller/CentralDB.cpp +++ b/nonfree/controller/CentralDB.cpp @@ -15,9 +15,9 @@ #ifdef ZT_CONTROLLER_USE_LIBPQ -#include "../node/Constants.hpp" -#include "../node/SHA512.hpp" -#include "../version.h" +#include "../../node/Constants.hpp" +#include "../../node/SHA512.hpp" +#include "../../version.h" #include "BigTableStatusWriter.hpp" #include "CtlUtil.hpp" #include "EmbeddedNetworkController.hpp" diff --git a/controller/CentralDB.hpp b/nonfree/controller/CentralDB.hpp similarity index 98% rename from controller/CentralDB.hpp rename to nonfree/controller/CentralDB.hpp index 6a3755952..e130c6344 100644 --- a/controller/CentralDB.hpp +++ b/nonfree/controller/CentralDB.hpp @@ -5,7 +5,7 @@ #define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4 -#include "../node/Metrics.hpp" +#include "../../node/Metrics.hpp" #include "ConnectionPool.hpp" #include "DB.hpp" #include "NotificationListener.hpp" diff --git a/controller/ConnectionPool.hpp b/nonfree/controller/ConnectionPool.hpp similarity index 92% rename from controller/ConnectionPool.hpp rename to nonfree/controller/ConnectionPool.hpp index 75690fab4..2588ae3a9 100644 --- a/controller/ConnectionPool.hpp +++ b/nonfree/controller/ConnectionPool.hpp @@ -1,15 +1,6 @@ -/* - * 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. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #ifndef ZT_CONNECTION_POOL_H_ #define ZT_CONNECTION_POOL_H_ @@ -18,7 +9,7 @@ #define _DEBUG(x) #endif -#include "../node/Metrics.hpp" +#include "../../node/Metrics.hpp" #include "opentelemetry/trace/provider.h" #include @@ -26,7 +17,6 @@ #include #include #include -#include namespace ZeroTier { diff --git a/controller/CtlUtil.cpp b/nonfree/controller/CtlUtil.cpp similarity index 94% rename from controller/CtlUtil.cpp rename to nonfree/controller/CtlUtil.cpp index e1e82f7a3..51a5535cf 100644 --- a/controller/CtlUtil.cpp +++ b/nonfree/controller/CtlUtil.cpp @@ -1,3 +1,7 @@ +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ + */ + #include "CtlUtil.hpp" #ifdef ZT_CONTROLLER_USE_LIBPQ @@ -61,4 +65,4 @@ std::string url_encode(const std::string& value) } // namespace ZeroTier -#endif \ No newline at end of file +#endif diff --git a/controller/CtlUtil.hpp b/nonfree/controller/CtlUtil.hpp similarity index 75% rename from controller/CtlUtil.hpp rename to nonfree/controller/CtlUtil.hpp index 0ba665af3..5347f9a4d 100644 --- a/controller/CtlUtil.hpp +++ b/nonfree/controller/CtlUtil.hpp @@ -1,3 +1,7 @@ +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ + */ + #ifndef ZT_CTLUTIL_HPP #define ZT_CTLUTIL_HPP @@ -13,4 +17,4 @@ std::vector split(std::string str, char delim); std::string url_encode(const std::string& value); } // namespace ZeroTier -#endif // namespace ZeroTier \ No newline at end of file +#endif // namespace ZeroTier diff --git a/controller/DB.cpp b/nonfree/controller/DB.cpp similarity index 97% rename from controller/DB.cpp rename to nonfree/controller/DB.cpp index 4cce312ed..e71fe6eee 100644 --- a/controller/DB.cpp +++ b/nonfree/controller/DB.cpp @@ -1,19 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #include "DB.hpp" -#include "../node/Metrics.hpp" +#include "../../node/Metrics.hpp" #include "EmbeddedNetworkController.hpp" #include "opentelemetry/trace/provider.h" diff --git a/controller/DB.hpp b/nonfree/controller/DB.hpp similarity index 91% rename from controller/DB.hpp rename to nonfree/controller/DB.hpp index 7ebff84ef..0eb4b6f2b 100644 --- a/controller/DB.hpp +++ b/nonfree/controller/DB.hpp @@ -1,26 +1,17 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #ifndef ZT_CONTROLLER_DB_HPP #define ZT_CONTROLLER_DB_HPP // #define ZT_CONTROLLER_USE_LIBPQ -#include "../node/Constants.hpp" -#include "../node/Identity.hpp" -#include "../node/InetAddress.hpp" -#include "../osdep/BlockingQueue.hpp" -#include "../osdep/OSUtils.hpp" +#include "../../node/Constants.hpp" +#include "../../node/Identity.hpp" +#include "../../node/InetAddress.hpp" +#include "../../osdep/BlockingQueue.hpp" +#include "../../osdep/OSUtils.hpp" #include #include diff --git a/controller/DBMirrorSet.cpp b/nonfree/controller/DBMirrorSet.cpp similarity index 97% rename from controller/DBMirrorSet.cpp rename to nonfree/controller/DBMirrorSet.cpp index f8c6f0366..404c494c5 100644 --- a/controller/DBMirrorSet.cpp +++ b/nonfree/controller/DBMirrorSet.cpp @@ -1,15 +1,6 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #include "DBMirrorSet.hpp" diff --git a/controller/DBMirrorSet.hpp b/nonfree/controller/DBMirrorSet.hpp similarity index 85% rename from controller/DBMirrorSet.hpp rename to nonfree/controller/DBMirrorSet.hpp index 50230c545..c839e440e 100644 --- a/controller/DBMirrorSet.hpp +++ b/nonfree/controller/DBMirrorSet.hpp @@ -1,15 +1,6 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #ifndef ZT_DBMIRRORSET_HPP #define ZT_DBMIRRORSET_HPP diff --git a/controller/EmbeddedNetworkController.cpp b/nonfree/controller/EmbeddedNetworkController.cpp similarity index 90% rename from controller/EmbeddedNetworkController.cpp rename to nonfree/controller/EmbeddedNetworkController.cpp index b7ba04299..c29feb620 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/nonfree/controller/EmbeddedNetworkController.cpp @@ -1,39 +1,25 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #include #include #include #include #include -#include #ifndef _WIN32 #include #endif -#include "../include/ZeroTierOne.h" -#include "../version.h" +#include "../../include/ZeroTierOne.h" #include "EmbeddedNetworkController.hpp" #include "FileDB.hpp" -#include "LFDB.hpp" #include #include -#include #include #include #include -#include #include #include #include @@ -42,11 +28,10 @@ #include "CV2.hpp" #endif -#include "../node/CertificateOfMembership.hpp" -#include "../node/Dictionary.hpp" -#include "../node/MAC.hpp" -#include "../node/NetworkConfig.hpp" -#include "../node/Node.hpp" +#include "../../node/CertificateOfMembership.hpp" +#include "../../node/Dictionary.hpp" +#include "../../node/NetworkConfig.hpp" +#include "../../node/Node.hpp" #include "opentelemetry/trace/provider.h" using json = nlohmann::json; @@ -131,29 +116,17 @@ static json _renderRule(ZT_VirtualNetworkRule& rule) case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: r["type"] = "MATCH_MAC_SOURCE"; OSUtils::ztsnprintf( - tmp, - sizeof(tmp), - "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", - (unsigned int)rule.v.mac[0], - (unsigned int)rule.v.mac[1], - (unsigned int)rule.v.mac[2], - (unsigned int)rule.v.mac[3], - (unsigned int)rule.v.mac[4], - (unsigned int)rule.v.mac[5]); + tmp, sizeof(tmp), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (unsigned int)rule.v.mac[0], + (unsigned int)rule.v.mac[1], (unsigned int)rule.v.mac[2], (unsigned int)rule.v.mac[3], + (unsigned int)rule.v.mac[4], (unsigned int)rule.v.mac[5]); r["mac"] = tmp; break; case ZT_NETWORK_RULE_MATCH_MAC_DEST: r["type"] = "MATCH_MAC_DEST"; OSUtils::ztsnprintf( - tmp, - sizeof(tmp), - "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", - (unsigned int)rule.v.mac[0], - (unsigned int)rule.v.mac[1], - (unsigned int)rule.v.mac[2], - (unsigned int)rule.v.mac[3], - (unsigned int)rule.v.mac[4], - (unsigned int)rule.v.mac[5]); + tmp, sizeof(tmp), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (unsigned int)rule.v.mac[0], + (unsigned int)rule.v.mac[1], (unsigned int)rule.v.mac[2], (unsigned int)rule.v.mac[3], + (unsigned int)rule.v.mac[4], (unsigned int)rule.v.mac[5]); r["mac"] = tmp; break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: @@ -533,7 +506,12 @@ static bool _parseRule(json& r, ZT_VirtualNetworkRule& rule) } // anonymous namespace -EmbeddedNetworkController::EmbeddedNetworkController(Node* node, const char* ztPath, const char* dbPath, int listenPort, RedisConfig* rc) +EmbeddedNetworkController::EmbeddedNetworkController( + Node* node, + const char* ztPath, + const char* dbPath, + int listenPort, + RedisConfig* rc) : _startTime(OSUtils::now()) , _listenPort(listenPort) , _node(node) @@ -626,47 +604,23 @@ void EmbeddedNetworkController::init(const Identity& signingId, Sender* sender) } #endif - std::string lfJSON; - OSUtils::readFile((_ztPath + ZT_PATH_SEPARATOR_S "local.conf").c_str(), lfJSON); - if (lfJSON.length() > 0) { - nlohmann::json lfConfig(OSUtils::jsonParse(lfJSON)); - nlohmann::json& settings = lfConfig["settings"]; - if (settings.is_object()) { - nlohmann::json& controllerDb = settings["controllerDb"]; - if (controllerDb.is_object()) { - std::string type = controllerDb["type"]; - if (type == "lf") { - std::string lfOwner = controllerDb["owner"]; - std::string lfHost = controllerDb["host"]; - int lfPort = controllerDb["port"]; - bool storeOnlineState = controllerDb["storeOnlineState"]; - if ((lfOwner.length()) && (lfHost.length()) && (lfPort > 0) && (lfPort < 65536)) { - std::size_t pubHdrLoc = lfOwner.find("Public: "); - if ((pubHdrLoc > 0) && ((pubHdrLoc + 8) < lfOwner.length())) { - std::string lfOwnerPublic = lfOwner.substr(pubHdrLoc + 8); - std::size_t pubHdrEnd = lfOwnerPublic.find_first_of("\n\r\t "); - if (pubHdrEnd != std::string::npos) { - lfOwnerPublic = lfOwnerPublic.substr(0, pubHdrEnd); - _db.addDB(std::shared_ptr(new LFDB(_signingId, _path.c_str(), lfOwner.c_str(), lfOwnerPublic.c_str(), lfHost.c_str(), lfPort, storeOnlineState))); - } - } - } - } - } - } - } - _db.waitForReady(); } -void EmbeddedNetworkController::request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary& metaData) +void EmbeddedNetworkController::request( + uint64_t nwid, + const InetAddress& fromAddr, + uint64_t requestPacketId, + const Identity& identity, + const Dictionary& metaData) { auto provider = opentelemetry::trace::Provider::GetTracerProvider(); auto tracer = provider->GetTracer("embedded_controller"); auto span = tracer->StartSpan("embedded_controller::request"); auto scope = tracer->WithActiveSpan(span); - if (((! _signingId) || (! _signingId.hasPrivate())) || (_signingId.address().toInt() != (nwid >> 24)) || (! _sender)) + if (((! _signingId) || (! _signingId.hasPrivate())) || (_signingId.address().toInt() != (nwid >> 24)) + || (! _sender)) return; _startThreads(); @@ -715,7 +669,9 @@ std::string EmbeddedNetworkController::networkUpdateFromPostData(uint64_t networ if (b.count("multicastLimit")) network["multicastLimit"] = OSUtils::jsonInt(b["multicastLimit"], 32ULL); if (b.count("mtu")) - network["mtu"] = std::max(std::min((unsigned int)OSUtils::jsonInt(b["mtu"], ZT_DEFAULT_MTU), (unsigned int)ZT_MAX_MTU), (unsigned int)ZT_MIN_MTU); + network["mtu"] = std::max( + std::min((unsigned int)OSUtils::jsonInt(b["mtu"], ZT_DEFAULT_MTU), (unsigned int)ZT_MAX_MTU), + (unsigned int)ZT_MIN_MTU); if (b.count("remoteTraceTarget")) { const std::string rtt(OSUtils::jsonString(b["remoteTraceTarget"], "")); @@ -780,6 +736,26 @@ std::string EmbeddedNetworkController::networkUpdateFromPostData(uint64_t networ network["v6AssignMode"] = nv6m; } + if (b.count("relays")) { + json nrelays = json::array(); + char rtmp[64]; + json& relays = b["relays"]; + if (relays.is_array()) { + for (unsigned long i = 0; i < relays.size(); ++i) { + json& relay = relays[i]; + if (relay.is_string()) { + nrelays.push_back( + Address(Utils::hexStrToU64(OSUtils::jsonString(relay, "0").c_str()) & 0xffffffffffULL) + .toString(rtmp)); + } + } + } + if (nrelays.size() > 0) + network["relays"] = nrelays; + else + network.erase("relays"); + } + if (b.count("routes")) { json& rts = b["routes"]; if (rts.is_array()) { @@ -972,7 +948,10 @@ std::string EmbeddedNetworkController::networkUpdateFromPostData(uint64_t networ return network.dump(); } -void EmbeddedNetworkController::configureHTTPControlPlane(httplib::Server& s, httplib::Server& sv6, const std::function setContent) +void EmbeddedNetworkController::configureHTTPControlPlane( + httplib::Server& s, + httplib::Server& sv6, + const std::function setContent) { // Control plane Endpoints std::string controllerPath = "/controller"; @@ -993,12 +972,9 @@ void EmbeddedNetworkController::configureHTTPControlPlane(httplib::Server& s, ht char tmp[4096]; const bool dbOk = _db.isReady(); OSUtils::ztsnprintf( - tmp, - sizeof(tmp), + tmp, sizeof(tmp), "{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu,\n\t\"databaseReady\": %s\n}\n", - ZT_NETCONF_CONTROLLER_API_VERSION, - (unsigned long long)OSUtils::now(), - dbOk ? "true" : "false"); + ZT_NETCONF_CONTROLLER_API_VERSION, (unsigned long long)OSUtils::now(), dbOk ? "true" : "false"); if (! dbOk) { res.status = 503; @@ -1388,7 +1364,8 @@ void EmbeddedNetworkController::configureHTTPControlPlane(httplib::Server& s, ht for (unsigned long i = 0; i < tags.size(); ++i) { json& tag = tags[i]; if ((tag.is_array()) && (tag.size() == 2)) - mtags[OSUtils::jsonInt(tag[0], 0ULL) & 0xffffffffULL] = OSUtils::jsonInt(tag[1], 0ULL) & 0xffffffffULL; + mtags[OSUtils::jsonInt(tag[0], 0ULL) & 0xffffffffULL] = + OSUtils::jsonInt(tag[1], 0ULL) & 0xffffffffULL; } json mtagsa = json::array(); for (std::map::iterator t(mtags.begin()); t != mtags.end(); ++t) { @@ -1518,7 +1495,9 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace& rt) } const int64_t now = OSUtils::now(); - OSUtils::ztsnprintf(id, sizeof(id), "%.10llx-%.16llx-%.10llx-%.4x", _signingId.address().toInt(), now, rt.origin, (unsigned int)(idCounter++ & 0xffff)); + OSUtils::ztsnprintf( + id, sizeof(id), "%.10llx-%.16llx-%.10llx-%.4x", _signingId.address().toInt(), now, rt.origin, + (unsigned int)(idCounter++ & 0xffff)); d["id"] = id; d["objtype"] = "trace"; d["ts"] = now; @@ -1546,7 +1525,11 @@ void EmbeddedNetworkController::onNetworkUpdate(const void* db, uint64_t network } } -void EmbeddedNetworkController::onNetworkMemberUpdate(const void* db, uint64_t networkId, uint64_t memberId, const nlohmann::json& member) +void EmbeddedNetworkController::onNetworkMemberUpdate( + const void* db, + uint64_t networkId, + uint64_t memberId, + const nlohmann::json& member) { auto provider = opentelemetry::trace::Provider::GetTracerProvider(); auto tracer = provider->GetTracer("embedded_controller"); @@ -1572,7 +1555,9 @@ void EmbeddedNetworkController::onNetworkMemberDeauthorize(const void* db, uint6 auto scope = tracer->WithActiveSpan(span); const int64_t now = OSUtils::now(); - Revocation rev((uint32_t)_node->prng(), networkId, 0, now, ZT_REVOCATION_FLAG_FAST_PROPAGATE, Address(memberId), Revocation::CREDENTIAL_TYPE_COM); + Revocation rev( + (uint32_t)_node->prng(), networkId, 0, now, ZT_REVOCATION_FLAG_FAST_PROPAGATE, Address(memberId), + Revocation::CREDENTIAL_TYPE_COM); rev.sign(_signingId); { std::lock_guard l(_memberStatus_l); @@ -1583,7 +1568,12 @@ void EmbeddedNetworkController::onNetworkMemberDeauthorize(const void* db, uint6 } } -void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary& metaData) +void EmbeddedNetworkController::_request( + uint64_t nwid, + const InetAddress& fromAddr, + uint64_t requestPacketId, + const Identity& identity, + const Dictionary& metaData) { auto provider = opentelemetry::trace::Provider::GetTracerProvider(); auto tracer = provider->GetTracer("embedded_controller"); @@ -1606,7 +1596,8 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA DB::NetworkSummaryInfo ns; json network, member; - if (((! _signingId) || (! _signingId.hasPrivate())) || (_signingId.address().toInt() != (nwid >> 24)) || (! _sender)) { + if (((! _signingId) || (! _signingId.hasPrivate())) || (_signingId.address().toInt() != (nwid >> 24)) + || (! _sender)) { return; } @@ -1635,7 +1626,8 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA Utils::hex(nwid, nwids); _db.get(nwid, network, identity.address().toInt(), member, ns); if ((! network.is_object()) || (network.empty())) { - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_OBJECT_NOT_FOUND, nullptr, 0); + _sender->ncSendError( + nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_OBJECT_NOT_FOUND, nullptr, 0); #ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK b3.stop(); #endif @@ -1662,7 +1654,9 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA // known member. try { if (Identity(haveIdStr.c_str()) != identity) { - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, 0); + _sender->ncSendError( + nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, + 0); #ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK b4.stop(); #endif @@ -1670,7 +1664,8 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA } } catch (...) { - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, 0); + _sender->ncSendError( + nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, 0); #ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK b4.stop(); #endif @@ -1767,7 +1762,9 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA Dictionary<4096> authInfo; authInfo.add(ZT_AUTHINFO_DICT_KEY_VERSION, (uint64_t)0ULL); authInfo.add(ZT_AUTHINFO_DICT_KEY_AUTHENTICATION_URL, info.authenticationURL.c_str()); - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED, authInfo.data(), authInfo.sizeBytes()); + _sender->ncSendError( + nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED, + authInfo.data(), authInfo.sizeBytes()); } else if (info.version == 1) { Dictionary<8192> authInfo; @@ -1778,7 +1775,9 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA authInfo.add(ZT_AUTHINFO_DICT_KEY_STATE, info.ssoState.c_str()); authInfo.add(ZT_AUTHINFO_DICT_KEY_CLIENT_ID, info.ssoClientID.c_str()); authInfo.add(ZT_AUTHINFO_DICT_KEY_SSO_PROVIDER, info.ssoProvider.c_str()); - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED, authInfo.data(), authInfo.sizeBytes()); + _sender->ncSendError( + nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED, + authInfo.data(), authInfo.sizeBytes()); } DB::cleanMember(member); _db.save(member, true); @@ -1831,7 +1830,8 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA // If they are not authorized, STOP! DB::cleanMember(member); _db.save(member, true); - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, 0); + _sender->ncSendError( + nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, 0); #ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK b7.stop(); #endif @@ -1857,7 +1857,9 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA if (network.contains("certificateTimeoutWindowSize")) { credentialtmd = (int64_t)network["certificateTimeoutWindowSize"]; } - credentialtmd = std::max(std::min(credentialtmd, ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA), ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MIN_MAX_DELTA); + credentialtmd = std::max( + std::min(credentialtmd, ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA), + ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MIN_MAX_DELTA); std::unique_ptr nc(new NetworkConfig()); @@ -1870,7 +1872,9 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA if (OSUtils::jsonBool(network["enableBroadcast"], true)) nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST; Utils::scopy(nc->name, sizeof(nc->name), OSUtils::jsonString(network["name"], "").c_str()); - nc->mtu = std::max(std::min((unsigned int)OSUtils::jsonInt(network["mtu"], ZT_DEFAULT_MTU), (unsigned int)ZT_MAX_MTU), (unsigned int)ZT_MIN_MTU); + nc->mtu = std::max( + std::min((unsigned int)OSUtils::jsonInt(network["mtu"], ZT_DEFAULT_MTU), (unsigned int)ZT_MAX_MTU), + (unsigned int)ZT_MIN_MTU); nc->multicastLimit = (unsigned int)OSUtils::jsonInt(network["multicastLimit"], 32ULL); nc->ssoEnabled = networkSSOEnabled; // OSUtils::jsonBool(network["ssoEnabled"], false); @@ -1931,6 +1935,7 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA json& v6AssignMode = network["v6AssignMode"]; json& ipAssignmentPools = network["ipAssignmentPools"]; json& routes = network["routes"]; + json& relays = network["relays"]; json& rules = network["rules"]; json& capabilities = network["capabilities"]; json& tags = network["tags"]; @@ -1938,7 +1943,8 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA json& memberTags = member["tags"]; json& dns = network["dns"]; - // fprintf(stderr, "IP Assignment Pools for Network %s: %s\n", nwids, OSUtils::jsonDump(ipAssignmentPools, 2).c_str()); + // fprintf(stderr, "IP Assignment Pools for Network %s: %s\n", nwids, OSUtils::jsonDump(ipAssignmentPools, + // 2).c_str()); if (metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV, 0) <= 0) { // Old versions with no rules engine support get an allow everything rule. @@ -2011,7 +2017,8 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA for (unsigned long i = 0; i < memberTags.size(); ++i) { json& t = memberTags[i]; if ((t.is_array()) && (t.size() == 2)) - memberTagsById[(uint32_t)(OSUtils::jsonInt(t[0], 0ULL) & 0xffffffffULL)] = (uint32_t)(OSUtils::jsonInt(t[1], 0ULL) & 0xffffffffULL); + memberTagsById[(uint32_t)(OSUtils::jsonInt(t[0], 0ULL) & 0xffffffffULL)] = + (uint32_t)(OSUtils::jsonInt(t[1], 0ULL) & 0xffffffffULL); } } if (tags.is_array()) { // check network tags array for defaults that are not present in member tags @@ -2062,6 +2069,15 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA } } + if (relays.is_array()) { + for (unsigned long i = 0; i < relays.size(); ++i) { + Address relay(Address(Utils::hexStrToU64(OSUtils::jsonString(relays[i], "0").c_str()) & 0xffffffffffULL)); + if (! relay.isReserved()) { + nc->addSpecialist(relay, ZT_NETWORKCONFIG_SPECIALIST_TYPE_NETWORK_RELAY); + } + } + } + const bool noAutoAssignIps = OSUtils::jsonBool(member["noAutoAssignIps"], false); if ((v6AssignMode.is_object()) && (! noAutoAssignIps)) { @@ -2087,7 +2103,8 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA int routedNetmaskBits = -1; for (unsigned int rk = 0; rk < nc->routeCount; ++rk) { if (reinterpret_cast(&(nc->routes[rk].target))->containsAddress(ip)) { - const int nb = (int)(reinterpret_cast(&(nc->routes[rk].target))->netmaskBits()); + const int nb = + (int)(reinterpret_cast(&(nc->routes[rk].target))->netmaskBits()); if (nb > routedNetmaskBits) routedNetmaskBits = nb; } @@ -2110,7 +2127,8 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA ipAssignments = json::array(); } - if ((ipAssignmentPools.is_array()) && ((v6AssignMode.is_object()) && (OSUtils::jsonBool(v6AssignMode["zt"], false))) && (! haveManagedIpv6AutoAssignment) && (! noAutoAssignIps)) { + if ((ipAssignmentPools.is_array()) && ((v6AssignMode.is_object()) && (OSUtils::jsonBool(v6AssignMode["zt"], false))) + && (! haveManagedIpv6AutoAssignment) && (! noAutoAssignIps)) { for (unsigned long p = 0; ((p < ipAssignmentPools.size()) && (! haveManagedIpv6AutoAssignment)); ++p) { json& pool = ipAssignmentPools[p]; if (pool.is_object()) { @@ -2134,7 +2152,8 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA xx[1] = Utils::hton(x[1] + identity.address().toInt()); } else { - // Otherwise pick random addresses -- this technically doesn't explore the whole range if the lower 64 bit range is >= 1 but that won't matter since that would be huge anyway + // Otherwise pick random addresses -- this technically doesn't explore the whole range if + // the lower 64 bit range is >= 1 but that won't matter since that would be huge anyway Utils::getSecureRandom((void*)xx, 16); if ((e[0] > s[0])) xx[0] %= (e[0] - s[0]); @@ -2153,12 +2172,16 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA // Check if this IP is within a local-to-Ethernet routed network int routedNetmaskBits = 0; for (unsigned int rk = 0; rk < nc->routeCount; ++rk) { - if ((! nc->routes[rk].via.ss_family) && (nc->routes[rk].target.ss_family == AF_INET6) && (reinterpret_cast(&(nc->routes[rk].target))->containsAddress(ip6))) - routedNetmaskBits = reinterpret_cast(&(nc->routes[rk].target))->netmaskBits(); + if ((! nc->routes[rk].via.ss_family) && (nc->routes[rk].target.ss_family == AF_INET6) + && (reinterpret_cast(&(nc->routes[rk].target)) + ->containsAddress(ip6))) + routedNetmaskBits = + reinterpret_cast(&(nc->routes[rk].target))->netmaskBits(); } // If it's routed, then try to claim and assign it and if successful end loop - if ((routedNetmaskBits > 0) && (! std::binary_search(ns.allocatedIps.begin(), ns.allocatedIps.end(), ip6))) { + if ((routedNetmaskBits > 0) + && (! std::binary_search(ns.allocatedIps.begin(), ns.allocatedIps.end(), ip6))) { char tmpip[64]; const std::string ipStr(ip6.toIpString(tmpip)); if (std::find(ipAssignments.begin(), ipAssignments.end(), ipStr) == ipAssignments.end()) { @@ -2177,15 +2200,18 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA } } - if ((ipAssignmentPools.is_array()) && ((v4AssignMode.is_object()) && (OSUtils::jsonBool(v4AssignMode["zt"], false))) && (! haveManagedIpv4AutoAssignment) && (! noAutoAssignIps)) { + if ((ipAssignmentPools.is_array()) && ((v4AssignMode.is_object()) && (OSUtils::jsonBool(v4AssignMode["zt"], false))) + && (! haveManagedIpv4AutoAssignment) && (! noAutoAssignIps)) { for (unsigned long p = 0; ((p < ipAssignmentPools.size()) && (! haveManagedIpv4AutoAssignment)); ++p) { json& pool = ipAssignmentPools[p]; if (pool.is_object()) { InetAddress ipRangeStartIA(OSUtils::jsonString(pool["ipRangeStart"], "").c_str()); InetAddress ipRangeEndIA(OSUtils::jsonString(pool["ipRangeEnd"], "").c_str()); if ((ipRangeStartIA.ss_family == AF_INET) && (ipRangeEndIA.ss_family == AF_INET)) { - uint32_t ipRangeStart = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeStartIA)->sin_addr.s_addr)); - uint32_t ipRangeEnd = Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeEndIA)->sin_addr.s_addr)); + uint32_t ipRangeStart = Utils::ntoh( + (uint32_t)(reinterpret_cast(&ipRangeStartIA)->sin_addr.s_addr)); + uint32_t ipRangeEnd = + Utils::ntoh((uint32_t)(reinterpret_cast(&ipRangeEndIA)->sin_addr.s_addr)); if ((ipRangeEnd < ipRangeStart) || (ipRangeStart == 0)) continue; @@ -2194,7 +2220,8 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA // Start with the LSB of the member's address uint32_t ipTrialCounter = (uint32_t)(identity.address().toInt() & 0xffffffff); - for (uint32_t k = ipRangeStart, trialCount = 0; ((k <= ipRangeEnd) && (trialCount < 1000)); ++k, ++trialCount) { + for (uint32_t k = ipRangeStart, trialCount = 0; ((k <= ipRangeEnd) && (trialCount < 1000)); + ++k, ++trialCount) { uint32_t ip = (ipRangeLen > 0) ? (ipRangeStart + (ipTrialCounter % ipRangeLen)) : ipRangeStart; ++ipTrialCounter; if ((ip & 0x000000ff) == 0x000000ff) { @@ -2205,8 +2232,12 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA int routedNetmaskBits = -1; for (unsigned int rk = 0; rk < nc->routeCount; ++rk) { if (nc->routes[rk].target.ss_family == AF_INET) { - uint32_t targetIp = Utils::ntoh((uint32_t)(reinterpret_cast(&(nc->routes[rk].target))->sin_addr.s_addr)); - int targetBits = Utils::ntoh((uint16_t)(reinterpret_cast(&(nc->routes[rk].target))->sin_port)); + uint32_t targetIp = Utils::ntoh( + (uint32_t)(reinterpret_cast(&(nc->routes[rk].target)) + ->sin_addr.s_addr)); + int targetBits = Utils::ntoh( + (uint16_t)(reinterpret_cast(&(nc->routes[rk].target)) + ->sin_port)); if ((ip & (0xffffffff << (32 - targetBits))) == targetIp) { routedNetmaskBits = targetBits; break; @@ -2216,14 +2247,16 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA // If it's routed, then try to claim and assign it and if successful end loop const InetAddress ip4(Utils::hton(ip), 0); - if ((routedNetmaskBits > 0) && (! std::binary_search(ns.allocatedIps.begin(), ns.allocatedIps.end(), ip4))) { + if ((routedNetmaskBits > 0) + && (! std::binary_search(ns.allocatedIps.begin(), ns.allocatedIps.end(), ip4))) { char tmpip[64]; const std::string ipStr(ip4.toIpString(tmpip)); if (std::find(ipAssignments.begin(), ipAssignments.end(), ipStr) == ipAssignments.end()) { ipAssignments.push_back(ipStr); member["ipAssignments"] = ipAssignments; if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) { - struct sockaddr_in* const v4ip = reinterpret_cast(&(nc->staticIps[nc->staticIpCount++])); + struct sockaddr_in* const v4ip = + reinterpret_cast(&(nc->staticIps[nc->staticIpCount++])); v4ip->sin_family = AF_INET; v4ip->sin_port = Utils::hton((uint16_t)routedNetmaskBits); v4ip->sin_addr.s_addr = Utils::hton(ip); @@ -2277,7 +2310,8 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA nc->com = com; } else { - _sender->ncSendError(nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR, nullptr, 0); + _sender->ncSendError( + nwid, requestPacketId, identity.address(), NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR, nullptr, 0); #ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK b9.stop(); #endif @@ -2301,7 +2335,9 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA c11++; b11.start(); #endif - _sender->ncSendConfig(nwid, requestPacketId, identity.address(), *(nc.get()), metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION, 0) < 6); + _sender->ncSendConfig( + nwid, requestPacketId, identity.address(), *(nc.get()), + metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION, 0) < 6); #ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK b11.stop(); #endif @@ -2335,10 +2371,14 @@ void EmbeddedNetworkController::_startThreads() _request(qe->nwid, qe->fromAddr, qe->requestPacketId, qe->identity, qe->metaData); } catch (std::exception& e) { - fprintf(stderr, "ERROR: exception in controller request handling thread: %s" ZT_EOL_S, e.what()); + fprintf( + stderr, "ERROR: exception in controller request handling thread: %s" ZT_EOL_S, + e.what()); } catch (...) { - fprintf(stderr, "ERROR: exception in controller request handling thread: unknown exception" ZT_EOL_S); + fprintf( + stderr, + "ERROR: exception in controller request handling thread: unknown exception" ZT_EOL_S); } delete qe; qe = nullptr; @@ -2371,7 +2411,8 @@ void EmbeddedNetworkController::_ssoExpiryThread() network.clear(); member.clear(); if (_db.get(s->second.networkId, network, s->second.nodeId, member)) { - int64_t authenticationExpiryTime = (int64_t)OSUtils::jsonInt(member["authenticationExpiryTime"], 0); + int64_t authenticationExpiryTime = + (int64_t)OSUtils::jsonInt(member["authenticationExpiryTime"], 0); if (authenticationExpiryTime <= now) { expired.push_back(s->second); } diff --git a/controller/EmbeddedNetworkController.hpp b/nonfree/controller/EmbeddedNetworkController.hpp similarity index 78% rename from controller/EmbeddedNetworkController.hpp rename to nonfree/controller/EmbeddedNetworkController.hpp index 61fcba839..3886c6391 100644 --- a/controller/EmbeddedNetworkController.hpp +++ b/nonfree/controller/EmbeddedNetworkController.hpp @@ -1,38 +1,22 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #ifndef ZT_SQLITENETWORKCONTROLLER_HPP #define ZT_SQLITENETWORKCONTROLLER_HPP -#include "../node/Address.hpp" -#include "../node/Constants.hpp" -#include "../node/InetAddress.hpp" -#include "../node/NetworkController.hpp" -#include "../node/Utils.hpp" -#include "../osdep/BlockingQueue.hpp" -#include "../osdep/OSUtils.hpp" -#include "../osdep/Thread.hpp" +#include "../../node/Constants.hpp" +#include "../../node/InetAddress.hpp" +#include "../../node/NetworkController.hpp" +#include "../../osdep/BlockingQueue.hpp" #include "DB.hpp" #include "DBMirrorSet.hpp" -#include #ifdef CMAKE_BUILD #include #else #include #endif -#include -#include #include #include #include @@ -61,18 +45,32 @@ class EmbeddedNetworkController void setSSORedirectURL(const std::string& url); - virtual void request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary& metaData); + virtual void request( + uint64_t nwid, + const InetAddress& fromAddr, + uint64_t requestPacketId, + const Identity& identity, + const Dictionary& metaData); - void configureHTTPControlPlane(httplib::Server& s, httplib::Server& sV6, const std::function); + void configureHTTPControlPlane( + httplib::Server& s, + httplib::Server& sV6, + const std::function); void handleRemoteTrace(const ZT_RemoteTrace& rt); 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); + 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); private: - void _request(uint64_t nwid, const InetAddress& fromAddr, uint64_t requestPacketId, const Identity& identity, const Dictionary& metaData); + void _request( + uint64_t nwid, + const InetAddress& fromAddr, + uint64_t requestPacketId, + const Identity& identity, + const Dictionary& metaData); void _startThreads(); void _ssoExpiryThread(); diff --git a/controller/FileDB.cpp b/nonfree/controller/FileDB.cpp similarity index 78% rename from controller/FileDB.cpp rename to nonfree/controller/FileDB.cpp index 6472022e2..906d39706 100644 --- a/controller/FileDB.cpp +++ b/nonfree/controller/FileDB.cpp @@ -1,24 +1,20 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #include "FileDB.hpp" -#include "../node/Metrics.hpp" +#include "../../node/Metrics.hpp" #include "opentelemetry/trace/provider.h" namespace ZeroTier { -FileDB::FileDB(const char* path) : DB(), _path(path), _networksPath(_path + ZT_PATH_SEPARATOR_S + "network"), _tracePath(_path + ZT_PATH_SEPARATOR_S + "trace"), _running(true) +FileDB::FileDB(const char* path) + : DB() + , _path(path) + , _networksPath(_path + ZT_PATH_SEPARATOR_S + "network") + , _tracePath(_path + ZT_PATH_SEPARATOR_S + "trace") + , _running(true) { auto provider = opentelemetry::trace::Provider::GetTracerProvider(); auto tracer = provider->GetTracer("filedb"); @@ -46,7 +42,8 @@ FileDB::FileDB(const char* path) : DB(), _path(path), _networksPath(_path + ZT_P std::vector members(OSUtils::listDirectory(membersPath.c_str(), false)); for (auto m = members.begin(); m != members.end(); ++m) { buf.clear(); - if ((m->length() == 15) && (OSUtils::readFile((membersPath + ZT_PATH_SEPARATOR_S + *m).c_str(), buf))) { + if ((m->length() == 15) + && (OSUtils::readFile((membersPath + ZT_PATH_SEPARATOR_S + *m).c_str(), buf))) { try { nlohmann::json member(OSUtils::jsonParse(buf)); const std::string addrs = member["id"]; @@ -110,7 +107,8 @@ bool FileDB::save(nlohmann::json& record, bool notifyListeners) get(nwid, old); 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); + OSUtils::ztsnprintf( + p1, sizeof(p1), "%s" ZT_PATH_SEPARATOR_S "%.16llx.json", _networksPath.c_str(), nwid); if (! OSUtils::writeFile(p1, OSUtils::jsonDump(record, -1))) { fprintf(stderr, "WARNING: controller unable to write to path: %s" ZT_EOL_S, p1); } @@ -130,10 +128,15 @@ bool FileDB::save(nlohmann::json& record, bool notifyListeners) get(nwid, network, id, old); if ((! old.is_object()) || (! _compareRecords(old, record))) { record["revision"] = OSUtils::jsonInt(record["revision"], 0ULL) + 1ULL; - OSUtils::ztsnprintf(pb, sizeof(pb), "%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member", _networksPath.c_str(), (unsigned long long)nwid); - OSUtils::ztsnprintf(p1, sizeof(p1), "%s" ZT_PATH_SEPARATOR_S "%.10llx.json", pb, (unsigned long long)id); + OSUtils::ztsnprintf( + pb, sizeof(pb), "%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member", + _networksPath.c_str(), (unsigned long long)nwid); + OSUtils::ztsnprintf( + p1, sizeof(p1), "%s" ZT_PATH_SEPARATOR_S "%.10llx.json", pb, (unsigned long long)id); if (! OSUtils::writeFile(p1, OSUtils::jsonDump(record, -1))) { - OSUtils::ztsnprintf(p2, sizeof(p2), "%s" ZT_PATH_SEPARATOR_S "%.16llx", _networksPath.c_str(), (unsigned long long)nwid); + 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))) { @@ -163,7 +166,8 @@ 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", _networksPath.c_str(), (unsigned long long)networkId); OSUtils::rmDashRf(p); _networkChanged(network, nullJson, true); std::lock_guard l(this->_online_l); @@ -180,14 +184,21 @@ void FileDB::eraseMember(const uint64_t networkId, const uint64_t memberId) nlohmann::json network, member, nullJson; get(networkId, network, 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::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); _memberChanged(member, nullJson, true); std::lock_guard l(this->_online_l); this->_online[networkId].erase(memberId); } -void FileDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch) +void FileDB::nodeIsOnline( + const uint64_t networkId, + const uint64_t memberId, + const InetAddress& physicalAddress, + const char* osArch) { auto provider = opentelemetry::trace::Provider::GetTracerProvider(); auto tracer = provider->GetTracer("filedb"); diff --git a/controller/FileDB.hpp b/nonfree/controller/FileDB.hpp similarity index 72% rename from controller/FileDB.hpp rename to nonfree/controller/FileDB.hpp index e10753223..f5b62ad89 100644 --- a/controller/FileDB.hpp +++ b/nonfree/controller/FileDB.hpp @@ -1,15 +1,6 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #ifndef ZT_CONTROLLER_FILEDB_HPP #define ZT_CONTROLLER_FILEDB_HPP diff --git a/controller/NotificationListener.hpp b/nonfree/controller/NotificationListener.hpp similarity index 100% rename from controller/NotificationListener.hpp rename to nonfree/controller/NotificationListener.hpp diff --git a/controller/PostgreSQL.cpp b/nonfree/controller/PostgreSQL.cpp similarity index 98% rename from controller/PostgreSQL.cpp rename to nonfree/controller/PostgreSQL.cpp index 9f6d80bd8..eb1d46124 100644 --- a/controller/PostgreSQL.cpp +++ b/nonfree/controller/PostgreSQL.cpp @@ -1,3 +1,7 @@ +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ + */ + #ifdef ZT_CONTROLLER_USE_LIBPQ #include "PostgreSQL.hpp" @@ -166,4 +170,4 @@ void PostgresNetworkListener::onNotification(const std::string& payload) } // namespace ZeroTier -#endif \ No newline at end of file +#endif diff --git a/controller/PostgreSQL.hpp b/nonfree/controller/PostgreSQL.hpp similarity index 94% rename from controller/PostgreSQL.hpp rename to nonfree/controller/PostgreSQL.hpp index fd1fd951d..46409e1b3 100644 --- a/controller/PostgreSQL.hpp +++ b/nonfree/controller/PostgreSQL.hpp @@ -1,15 +1,6 @@ -/* - * Copyright (c)2025 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ */ -/****/ #ifdef ZT_CONTROLLER_USE_LIBPQ @@ -269,4 +260,4 @@ class PostgresNetworkListener : public NotificationListener { #endif // ZT_CONTROLLER_POSTGRESQL_HPP -#endif // ZT_CONTROLLER_USE_LIBPQ \ No newline at end of file +#endif // ZT_CONTROLLER_USE_LIBPQ diff --git a/controller/PostgresStatusWriter.cpp b/nonfree/controller/PostgresStatusWriter.cpp similarity index 97% rename from controller/PostgresStatusWriter.cpp rename to nonfree/controller/PostgresStatusWriter.cpp index 3e5902845..5e59e73f5 100644 --- a/controller/PostgresStatusWriter.cpp +++ b/nonfree/controller/PostgresStatusWriter.cpp @@ -1,6 +1,6 @@ #include "PostgresStatusWriter.hpp" -#include "../node/Metrics.hpp" +#include "../../node/Metrics.hpp" #include #include diff --git a/controller/PostgresStatusWriter.hpp b/nonfree/controller/PostgresStatusWriter.hpp similarity index 100% rename from controller/PostgresStatusWriter.hpp rename to nonfree/controller/PostgresStatusWriter.hpp diff --git a/controller/PubSubListener.cpp b/nonfree/controller/PubSubListener.cpp similarity index 100% rename from controller/PubSubListener.cpp rename to nonfree/controller/PubSubListener.cpp diff --git a/controller/PubSubListener.hpp b/nonfree/controller/PubSubListener.hpp similarity index 100% rename from controller/PubSubListener.hpp rename to nonfree/controller/PubSubListener.hpp diff --git a/controller/README.md b/nonfree/controller/README.md similarity index 100% rename from controller/README.md rename to nonfree/controller/README.md diff --git a/controller/README_CENTRAL_CONTROLLER.md b/nonfree/controller/README_CENTRAL_CONTROLLER.md similarity index 100% rename from controller/README_CENTRAL_CONTROLLER.md rename to nonfree/controller/README_CENTRAL_CONTROLLER.md diff --git a/controller/Redis.hpp b/nonfree/controller/Redis.hpp similarity index 77% rename from controller/Redis.hpp rename to nonfree/controller/Redis.hpp index c6845d517..cc02cb97d 100644 --- a/controller/Redis.hpp +++ b/nonfree/controller/Redis.hpp @@ -1,3 +1,7 @@ +/* (c) ZeroTier, Inc. + * See LICENSE.txt in nonfree/ + */ + #ifndef ZT_CONTROLLER_REDIS_HPP #define ZT_CONTROLLER_REDIS_HPP @@ -12,4 +16,4 @@ struct RedisConfig { }; } // namespace ZeroTier -#endif \ No newline at end of file +#endif diff --git a/controller/RedisListener.cpp b/nonfree/controller/RedisListener.cpp similarity index 86% rename from controller/RedisListener.cpp rename to nonfree/controller/RedisListener.cpp index 7668d083a..f01bfa678 100644 --- a/controller/RedisListener.cpp +++ b/nonfree/controller/RedisListener.cpp @@ -2,7 +2,7 @@ #include "RedisListener.hpp" -#include "../node/Metrics.hpp" +#include "../../node/Metrics.hpp" #include "nlohmann/json.hpp" #include "opentelemetry/trace/provider.h" @@ -16,11 +16,19 @@ using Attrs = std::vector >; using Item = std::pair; using ItemStream = std::vector; -RedisListener::RedisListener(std::string controller_id, std::shared_ptr redis) : _controller_id(controller_id), _redis(redis), _is_cluster(false), _run(false) +RedisListener::RedisListener(std::string controller_id, std::shared_ptr redis) + : _controller_id(controller_id) + , _redis(redis) + , _is_cluster(false) + , _run(false) { } -RedisListener::RedisListener(std::string controller_id, std::shared_ptr cluster) : _controller_id(controller_id), _cluster(cluster), _is_cluster(true), _run(false) +RedisListener::RedisListener(std::string controller_id, std::shared_ptr cluster) + : _controller_id(controller_id) + , _cluster(cluster) + , _is_cluster(true) + , _run(false) { } @@ -32,12 +40,19 @@ RedisListener::~RedisListener() } } -RedisNetworkListener::RedisNetworkListener(std::string controller_id, std::shared_ptr redis, DB* db) : RedisListener(controller_id, redis), _db(db) +RedisNetworkListener::RedisNetworkListener(std::string controller_id, std::shared_ptr redis, DB* db) + : RedisListener(controller_id, redis) + , _db(db) { // Additional initialization for network listener if needed } -RedisNetworkListener::RedisNetworkListener(std::string controller_id, std::shared_ptr cluster, DB* db) : RedisListener(controller_id, cluster), _db(db) +RedisNetworkListener::RedisNetworkListener( + std::string controller_id, + std::shared_ptr cluster, + DB* db) + : RedisListener(controller_id, cluster) + , _db(db) { // Additional initialization for network listener if needed } @@ -121,12 +136,19 @@ void RedisNetworkListener::onNotification(const std::string& payload) // Handle notifications if needed } -RedisMemberListener::RedisMemberListener(std::string controller_id, std::shared_ptr redis, DB* db) : RedisListener(controller_id, redis), _db(db) +RedisMemberListener::RedisMemberListener(std::string controller_id, std::shared_ptr redis, DB* db) + : RedisListener(controller_id, redis) + , _db(db) { // Additional initialization for member listener if needed } -RedisMemberListener::RedisMemberListener(std::string controller_id, std::shared_ptr cluster, DB* db) : RedisListener(controller_id, cluster), _db(db) +RedisMemberListener::RedisMemberListener( + std::string controller_id, + std::shared_ptr cluster, + DB* db) + : RedisListener(controller_id, cluster) + , _db(db) { // Additional initialization for member listener if needed } diff --git a/controller/RedisListener.hpp b/nonfree/controller/RedisListener.hpp similarity index 100% rename from controller/RedisListener.hpp rename to nonfree/controller/RedisListener.hpp diff --git a/controller/RedisStatusWriter.cpp b/nonfree/controller/RedisStatusWriter.cpp similarity index 97% rename from controller/RedisStatusWriter.cpp rename to nonfree/controller/RedisStatusWriter.cpp index c222d26a2..9ad04eb24 100644 --- a/controller/RedisStatusWriter.cpp +++ b/nonfree/controller/RedisStatusWriter.cpp @@ -1,7 +1,7 @@ #include "RedisStatusWriter.hpp" -#include "../node/Metrics.hpp" -#include "../osdep/OSUtils.hpp" +#include "../../node/Metrics.hpp" +#include "../../osdep/OSUtils.hpp" #include #include diff --git a/controller/RedisStatusWriter.hpp b/nonfree/controller/RedisStatusWriter.hpp similarity index 100% rename from controller/RedisStatusWriter.hpp rename to nonfree/controller/RedisStatusWriter.hpp diff --git a/controller/StatusWriter.cpp b/nonfree/controller/StatusWriter.cpp similarity index 100% rename from controller/StatusWriter.cpp rename to nonfree/controller/StatusWriter.cpp diff --git a/controller/StatusWriter.hpp b/nonfree/controller/StatusWriter.hpp similarity index 95% rename from controller/StatusWriter.hpp rename to nonfree/controller/StatusWriter.hpp index 37b2dd06e..29e7f350d 100644 --- a/controller/StatusWriter.hpp +++ b/nonfree/controller/StatusWriter.hpp @@ -1,7 +1,7 @@ #ifndef STATUS_WRITER_HPP #define STATUS_WRITER_HPP -#include "../node/InetAddress.hpp" +#include "../../node/InetAddress.hpp" #include diff --git a/controller/protobuf/member.proto b/nonfree/controller/protobuf/member.proto similarity index 100% rename from controller/protobuf/member.proto rename to nonfree/controller/protobuf/member.proto diff --git a/controller/protobuf/member_status.proto b/nonfree/controller/protobuf/member_status.proto similarity index 100% rename from controller/protobuf/member_status.proto rename to nonfree/controller/protobuf/member_status.proto diff --git a/controller/protobuf/network.proto b/nonfree/controller/protobuf/network.proto similarity index 100% rename from controller/protobuf/network.proto rename to nonfree/controller/protobuf/network.proto diff --git a/objects-nonfree.mk b/objects-nonfree.mk new file mode 100644 index 000000000..cd25cce11 --- /dev/null +++ b/objects-nonfree.mk @@ -0,0 +1,8 @@ +CONTROLLER_OBJS=\ + nonfree/controller/EmbeddedNetworkController.o \ + nonfree/controller/DBMirrorSet.o \ + nonfree/controller/DB.o \ + nonfree/controller/FileDB.o \ + nonfree/controller/CtlUtil.o \ + nonfree/controller/CV1.o \ + nonfree/controller/CV2.o diff --git a/objects.mk b/objects.mk index 2e20a759b..1913bef00 100644 --- a/objects.mk +++ b/objects.mk @@ -34,21 +34,7 @@ CORE_OBJS=\ osdep/OSUtils.o ONE_OBJS=\ - controller/EmbeddedNetworkController.o \ - controller/DBMirrorSet.o \ - controller/DB.o \ - controller/FileDB.o \ - controller/LFDB.o \ - controller/CtlUtil.o \ - controller/CV1.o \ - controller/CV2.o \ - controller/CentralDB.o \ - controller/PubSubListener.o \ - controller/RedisListener.o \ - controller/PostgreSQL.o \ osdep/EthernetTap.o \ osdep/ManagedRoute.o \ osdep/Http.o \ - service/SoftwareUpdater.o \ service/OneService.o - diff --git a/one.cpp b/one.cpp index e5c9042ab..a84e8d65d 100644 --- a/one.cpp +++ b/one.cpp @@ -1,29 +1,24 @@ -/* - * Copyright (c)2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef _GNU_SOURCE #define _GNU_SOURCE #include "node/ECC.hpp" #endif +#include "node/Constants.hpp" + +#include +#include #include #include #include -#include #include -#include - -#include "node/Constants.hpp" #ifdef __WINDOWS__ // clang-format off @@ -43,24 +38,25 @@ #include "windows/ZeroTierOne/ZeroTierOneService.h" // clang-format on #else -#include -#include -#include -#include -#include -#include #include +#include +#include #include -#ifdef __LINUX__ -#include -#include -#include -#include +#include #include -#include -#include -#include +#include +#include +#ifdef __LINUX__ #include "osdep/ExtOsdep.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include #ifndef ZT_NO_CAPABILITIES #include #include @@ -68,102 +64,101 @@ #endif #endif -#include -#include -#include -#include -#include - -#include "version.h" #include "include/ZeroTierOne.h" - -#include "node/Identity.hpp" -#include "node/CertificateOfMembership.hpp" -#include "node/Utils.hpp" -#include "node/NetworkController.hpp" -#include "node/Buffer.hpp" -#include "node/World.hpp" - -#include "osdep/OSUtils.hpp" -#include "osdep/Http.hpp" -#include "osdep/Thread.hpp" - #include "node/Bond.hpp" - +#include "node/Buffer.hpp" +#include "node/CertificateOfMembership.hpp" +#include "node/Identity.hpp" +#include "node/NetworkController.hpp" +#include "node/Utils.hpp" +#include "node/World.hpp" +#include "osdep/Http.hpp" +#include "osdep/OSUtils.hpp" +#include "osdep/Thread.hpp" #include "service/OneService.hpp" +#include "version.h" +#include +#include #include +#include +#include +#include #ifdef __APPLE__ -#include #include -#include -#include +#include #include +#include +#include #endif #define ZT_PID_PATH "zerotier-one.pid" using namespace ZeroTier; -static OneService *volatile zt1Service = (OneService *)0; +static OneService* volatile zt1Service = (OneService*)0; -#define PROGRAM_NAME "ZeroTier One" -#define COPYRIGHT_NOTICE "Copyright (c) 2020 ZeroTier, Inc." -#define LICENSE_GRANT "Licensed under the ZeroTier BSL 1.1 (see LICENSE.txt)" +#define PROGRAM_NAME "ZeroTier One" +#define COPYRIGHT_NOTICE "Copyright (c) ZeroTier, Inc." + +#ifdef ZT_NONFREE_CONTROLLER +#define LICENSE_GRANT "Licensed under a non-commercial source-available license (nonfree/LICENSE.md)." +#else +#define LICENSE_GRANT "Licensed under Mozilla Public License v2.0 (LICENSE-MPL.txt)." +#endif /****************************************************************************/ /* zerotier-cli personality */ /****************************************************************************/ -// This is getting deprecated soon in favor of the stuff in cli/ - -static void cliPrintHelp(const char *pn,FILE *out) +static void cliPrintHelp(const char* pn, FILE* out) { - fprintf(out, + fprintf( + out, "%s version %d.%d.%d build %d (platform %d arch %d)" ZT_EOL_S, PROGRAM_NAME, - ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION, ZEROTIER_ONE_VERSION_BUILD, - ZT_BUILD_PLATFORM, ZT_BUILD_ARCHITECTURE); - fprintf(out, - COPYRIGHT_NOTICE ZT_EOL_S - LICENSE_GRANT ZT_EOL_S); - fprintf(out,"Usage: %s [-switches] []" ZT_EOL_S"" ZT_EOL_S,pn); - fprintf(out,"Available switches:" ZT_EOL_S); - fprintf(out," -h - Display this help" ZT_EOL_S); - fprintf(out," -v - Show version" ZT_EOL_S); - fprintf(out," -j - Display full raw JSON output" ZT_EOL_S); - fprintf(out," -D - ZeroTier home path for parameter auto-detect" ZT_EOL_S); - fprintf(out," -p - HTTP port (default: auto)" ZT_EOL_S); - fprintf(out," -T - Authentication token (default: auto)" ZT_EOL_S); - fprintf(out,ZT_EOL_S"Available commands:" ZT_EOL_S); - fprintf(out," info - Display status info" ZT_EOL_S); - fprintf(out," listpeers - List all peers" ZT_EOL_S); - fprintf(out," peers - List all peers (prettier)" ZT_EOL_S); - fprintf(out," listnetworks - List all networks" ZT_EOL_S); - fprintf(out," join - Join a network" ZT_EOL_S); - fprintf(out," leave - Leave a network" ZT_EOL_S); - fprintf(out," set - Set a network setting" ZT_EOL_S); - fprintf(out," get - Get a network setting" ZT_EOL_S); - fprintf(out," listmoons - List moons (federated root sets)" ZT_EOL_S); - fprintf(out," orbit - Join a moon via any member root" ZT_EOL_S); - fprintf(out," deorbit - Leave a moon" ZT_EOL_S); - fprintf(out," dump - Debug settings dump for support" ZT_EOL_S); - fprintf(out,ZT_EOL_S"Available settings:" ZT_EOL_S); - fprintf(out," Settings to use with [get/set] may include property names from " ZT_EOL_S); - fprintf(out," the JSON output of \"zerotier-cli -j listnetworks\". Additionally, " ZT_EOL_S); - fprintf(out," (ip, ip4, ip6, ip6plane, and ip6prefix can be used). For instance:" ZT_EOL_S); - fprintf(out," zerotier-cli get ip6plane will return the 6PLANE address" ZT_EOL_S); - fprintf(out," assigned to this node." ZT_EOL_S); + ZEROTIER_ONE_VERSION_MAJOR, + ZEROTIER_ONE_VERSION_MINOR, + ZEROTIER_ONE_VERSION_REVISION, + ZEROTIER_ONE_VERSION_BUILD, + ZT_BUILD_PLATFORM, + ZT_BUILD_ARCHITECTURE); + fprintf(out, COPYRIGHT_NOTICE ZT_EOL_S LICENSE_GRANT ZT_EOL_S); + fprintf(out, ZT_EOL_S "Usage: %s [-switches] []" ZT_EOL_S "" ZT_EOL_S, pn); + fprintf(out, "Available switches:" ZT_EOL_S); + fprintf(out, " -h - Display this help" ZT_EOL_S); + fprintf(out, " -v - Show version" ZT_EOL_S); + fprintf(out, " -j - Display full raw JSON output" ZT_EOL_S); + fprintf(out, " -D - ZeroTier home path for parameter auto-detect" ZT_EOL_S); + fprintf(out, " -p - HTTP port (default: auto)" ZT_EOL_S); + fprintf(out, " -T - Authentication token (default: auto)" ZT_EOL_S); + fprintf(out, ZT_EOL_S "Available commands:" ZT_EOL_S); + fprintf(out, " info - Display status info" ZT_EOL_S); + fprintf(out, " listpeers - List all peers" ZT_EOL_S); + fprintf(out, " peers - List all peers (prettier)" ZT_EOL_S); + fprintf(out, " listnetworks - List all networks" ZT_EOL_S); + fprintf(out, " join - Join a network" ZT_EOL_S); + fprintf(out, " leave - Leave a network" ZT_EOL_S); + fprintf(out, " set - Set a network setting" ZT_EOL_S); + fprintf(out, " get - Get a network setting" ZT_EOL_S); + fprintf(out, " dump - Debug settings dump for support" ZT_EOL_S); + fprintf(out, ZT_EOL_S "Available settings:" ZT_EOL_S); + fprintf(out, " Settings to use with [get/set] may include property names from " ZT_EOL_S); + fprintf(out, " the JSON output of \"zerotier-cli -j listnetworks\". Additionally, " ZT_EOL_S); + fprintf(out, " (ip, ip4, ip6, ip6plane, and ip6prefix can be used). For instance:" ZT_EOL_S); + fprintf(out, " zerotier-cli get ip6plane will return the 6PLANE address" ZT_EOL_S); + fprintf(out, " assigned to this node." ZT_EOL_S); } -static std::string cliFixJsonCRs(const std::string &s) +static std::string cliFixJsonCRs(const std::string& s) { std::string r; - for(std::string::const_iterator c(s.begin());c!=s.end();++c) { + for (std::string::const_iterator c(s.begin()); c != s.end(); ++c) { if (*c == '\n') r.append(ZT_EOL_S); - else r.push_back(*c); + else + r.push_back(*c); } return r; } @@ -171,27 +166,26 @@ static std::string cliFixJsonCRs(const std::string &s) #ifdef __WINDOWS__ static int cli(int argc, _TCHAR* argv[]) #else -static int cli(int argc,char **argv) +static int cli(int argc, char** argv) #endif { unsigned int port = 0; - std::string homeDir,command,arg1,arg2,arg3,arg4,authToken; + std::string homeDir, command, arg1, arg2, arg3, arg4, authToken; std::string ip("127.0.0.1"); bool json = false; - for(int i=1;i 0xffff)||(port == 0)) { - cliPrintHelp(argv[0],stdout); + if ((port > 0xffff) || (port == 0)) { + cliPrintHelp(argv[0], stdout); return 1; } break; @@ -208,8 +202,9 @@ static int cli(int argc,char **argv) case 'D': if (argv[i][2]) { homeDir = argv[i] + 2; - } else { - cliPrintHelp(argv[0],stdout); + } + else { + cliPrintHelp(argv[0], stdout); return 1; } break; @@ -217,8 +212,9 @@ static int cli(int argc,char **argv) case 'H': if (argv[i][2]) { ip = argv[i] + 2; - } else { - cliPrintHelp(argv[0],stdout); + } + else { + cliPrintHelp(argv[0], stdout); return 1; } break; @@ -226,72 +222,75 @@ static int cli(int argc,char **argv) case 'T': if (argv[i][2]) { authToken = argv[i] + 2; - } else { - cliPrintHelp(argv[0],stdout); + } + else { + cliPrintHelp(argv[0], stdout); return 1; } break; case 'v': if (argv[i][2]) { - cliPrintHelp(argv[0],stdout); + cliPrintHelp(argv[0], stdout); return 1; } - printf("%d.%d.%d" ZT_EOL_S,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); + printf("%d.%d.%d" ZT_EOL_S, ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION); return 0; case 'h': case '?': default: - cliPrintHelp(argv[0],stdout); + cliPrintHelp(argv[0], stdout); return 0; } - } else { + } + else { if (arg1.length()) arg2 = argv[i]; else if (command.length()) arg1 = argv[i]; - else command = argv[i]; + else + command = argv[i]; } } - if (!homeDir.length()) + if (! homeDir.length()) homeDir = OneService::platformDefaultHomePath(); // TODO: cleanup this logic - if ((!port)||(!authToken.length())) { - if (!homeDir.length()) { - fprintf(stderr,"%s: missing port or authentication token and no home directory specified to auto-detect" ZT_EOL_S,argv[0]); + if ((! port) || (! authToken.length())) { + if (! homeDir.length()) { + fprintf(stderr, "%s: missing port or authentication token and no home directory specified to auto-detect" ZT_EOL_S, argv[0]); return 2; } - if (!port) { + if (! port) { std::string portStr; - OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "zerotier-one.port").c_str(),portStr); + OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "zerotier-one.port").c_str(), portStr); port = Utils::strToUInt(portStr.c_str()); - if ((port == 0)||(port > 0xffff)) { - fprintf(stderr,"%s: missing port and zerotier-one.port not found in %s" ZT_EOL_S,argv[0],homeDir.c_str()); + if ((port == 0) || (port > 0xffff)) { + fprintf(stderr, "%s: missing port and zerotier-one.port not found in %s" ZT_EOL_S, argv[0], homeDir.c_str()); return 2; } } - if (!authToken.length()) { - OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "authtoken.secret").c_str(),authToken); + if (! authToken.length()) { + OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "authtoken.secret").c_str(), authToken); #ifdef __UNIX_LIKE__ - if (!authToken.length()) { - const char *hd = getenv("HOME"); + if (! authToken.length()) { + const char* hd = getenv("HOME"); if (hd) { char p[4096]; #ifdef __APPLE__ - OSUtils::ztsnprintf(p,sizeof(p),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",hd); + OSUtils::ztsnprintf(p, sizeof(p), "%s/Library/Application Support/ZeroTier/One/authtoken.secret", hd); #else - OSUtils::ztsnprintf(p,sizeof(p),"%s/.zeroTierOneAuthToken",hd); + OSUtils::ztsnprintf(p, sizeof(p), "%s/.zeroTierOneAuthToken", hd); #endif - OSUtils::readFile(p,authToken); + OSUtils::readFile(p, authToken); } } #endif - if (!authToken.length()) { - fprintf(stderr,"%s: authtoken.secret not found or readable in %s (try again as root)" ZT_EOL_S,argv[0],homeDir.c_str()); + if (! authToken.length()) { + fprintf(stderr, "%s: authtoken.secret not found or readable in %s (try again as root)" ZT_EOL_S, argv[0], homeDir.c_str()); return 2; } } @@ -300,34 +299,29 @@ static int cli(int argc,char **argv) InetAddress addr; { char addrtmp[256]; - OSUtils::ztsnprintf(addrtmp,sizeof(addrtmp),"%s/%u",ip.c_str(),port); + OSUtils::ztsnprintf(addrtmp, sizeof(addrtmp), "%s/%u", ip.c_str(), port); addr = InetAddress(addrtmp); } - std::map requestHeaders; - std::map responseHeaders; + std::map requestHeaders; + std::map responseHeaders; std::string responseBody; requestHeaders["X-ZT1-Auth"] = authToken; - if ((command.length() > 0)&&(command[0] == '/')) { - unsigned int scode = Http::GET( - 1024 * 1024 * 16, - 60000, - (const struct sockaddr *)&addr, - command.c_str(), - requestHeaders, - responseHeaders, - responseBody); + if ((command.length() > 0) && (command[0] == '/')) { + unsigned int scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, command.c_str(), requestHeaders, responseHeaders, responseBody); if (scode == 200) { printf("%s", cliFixJsonCRs(responseBody).c_str()); return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } - } else if ((command == "info")||(command == "status")) { - const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/status",requestHeaders,responseHeaders,responseBody); + } + else if ((command == "info") || (command == "status")) { + const unsigned int scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, "/status", requestHeaders, responseHeaders, responseBody); if (scode == 0) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); @@ -337,32 +331,34 @@ static int cli(int argc,char **argv) nlohmann::json j; try { j = OSUtils::jsonParse(responseBody); - } catch (std::exception &exc) { - printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what()); + } + catch (std::exception& exc) { + printf("%u %s invalid JSON response (%s)" ZT_EOL_S, scode, command.c_str(), exc.what()); return 1; - } catch ( ... ) { - printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str()); + } + catch (...) { + printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S, scode, command.c_str()); return 1; } if (scode == 200) { if (json) { - printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str()); - } else { + printf("%s" ZT_EOL_S, OSUtils::jsonDump(j).c_str()); + } + else { if (j.is_object()) { - printf("200 info %s %s %s" ZT_EOL_S, - OSUtils::jsonString(j["address"],"-").c_str(), - OSUtils::jsonString(j["version"],"-").c_str(), - ((j["tcpFallbackActive"]) ? "TUNNELED" : ((j["online"]) ? "ONLINE" : "OFFLINE"))); + printf("200 info %s %s %s" ZT_EOL_S, OSUtils::jsonString(j["address"], "-").c_str(), OSUtils::jsonString(j["version"], "-").c_str(), ((j["tcpFallbackActive"]) ? "TUNNELED" : ((j["online"]) ? "ONLINE" : "OFFLINE"))); } } return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } - } else if (command == "listpeers") { - const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/peer",requestHeaders,responseHeaders,responseBody); + } + else if (command == "listpeers") { + const unsigned int scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, "/peer", requestHeaders, responseHeaders, responseBody); if (scode == 0) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); @@ -372,66 +368,68 @@ static int cli(int argc,char **argv) nlohmann::json j; try { j = OSUtils::jsonParse(responseBody); - } catch (std::exception &exc) { - printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what()); + } + catch (std::exception& exc) { + printf("%u %s invalid JSON response (%s)" ZT_EOL_S, scode, command.c_str(), exc.what()); return 1; - } catch ( ... ) { - printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str()); + } + catch (...) { + printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S, scode, command.c_str()); return 1; } if (scode == 200) { if (json) { - printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str()); - } else { + printf("%s" ZT_EOL_S, OSUtils::jsonDump(j).c_str()); + } + else { printf("200 listpeers " ZT_EOL_S); if (j.is_array()) { - for(unsigned long k=0;k= 0) { - OSUtils::ztsnprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev); - } else { + OSUtils::ztsnprintf(ver, sizeof(ver), "%lld.%lld.%lld", vmaj, vmin, vrev); + } + else { ver[0] = '-'; ver[1] = (char)0; } - printf("200 listpeers %s %s %d %s %s" ZT_EOL_S, - OSUtils::jsonString(p["address"],"-").c_str(), - bestPath.c_str(), - (int)OSUtils::jsonInt(p["latency"],0), - ver, - OSUtils::jsonString(p["role"],"-").c_str()); + printf("200 listpeers %s %s %d %s %s" ZT_EOL_S, OSUtils::jsonString(p["address"], "-").c_str(), bestPath.c_str(), (int)OSUtils::jsonInt(p["latency"], 0), ver, OSUtils::jsonString(p["role"], "-").c_str()); } } } return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } - } else if (command == "peers") { - const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/peer",requestHeaders,responseHeaders,responseBody); + } + else if (command == "peers") { + const unsigned int scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, "/peer", requestHeaders, responseHeaders, responseBody); if (scode == 0) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); @@ -441,38 +439,41 @@ static int cli(int argc,char **argv) nlohmann::json j; try { j = OSUtils::jsonParse(responseBody); - } catch (std::exception &exc) { - printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what()); + } + catch (std::exception& exc) { + printf("%u %s invalid JSON response (%s)" ZT_EOL_S, scode, command.c_str(), exc.what()); return 1; - } catch ( ... ) { - printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str()); + } + catch (...) { + printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S, scode, command.c_str()); return 1; } if (scode == 200) { if (json) { - printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str()); - } else { + printf("%s" ZT_EOL_S, OSUtils::jsonDump(j).c_str()); + } + else { bool anyTunneled = false; printf("200 peers\n " ZT_EOL_S); if (j.is_array()) { - for(unsigned long k=0;k= 0) { - OSUtils::ztsnprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev); - } else { + OSUtils::ztsnprintf(ver, sizeof(ver), "%lld.%lld.%lld", vmaj, vmin, vrev); + } + else { ver[0] = '-'; ver[1] = (char)0; } - printf("%s %-6s %-6s %5d %s" ZT_EOL_S, - OSUtils::jsonString(p["address"],"-").c_str(), - ver, - OSUtils::jsonString(p["role"],"-").c_str(), - (int)OSUtils::jsonInt(p["latency"],0), - bestPath.c_str()); + printf("%s %-6s %-6s %5d %s" ZT_EOL_S, OSUtils::jsonString(p["address"], "-").c_str(), ver, OSUtils::jsonString(p["role"], "-").c_str(), (int)OSUtils::jsonInt(p["latency"], 0), bestPath.c_str()); } } if (anyTunneled) { @@ -509,11 +506,13 @@ static int cli(int argc,char **argv) } } return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } - } else if (command == "bond") { + } + else if (command == "bond") { /* zerotier-cli bond */ if (arg1.empty()) { printf("(bond) command is missing required arguments" ZT_EOL_S); @@ -521,7 +520,7 @@ static int cli(int argc,char **argv) } /* zerotier-cli bond list */ if (arg1 == "list") { - const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/peer",requestHeaders,responseHeaders,responseBody); + const unsigned int scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, "/peer", requestHeaders, responseHeaders, responseBody); if (scode == 0) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); return 1; @@ -529,22 +528,25 @@ static int cli(int argc,char **argv) nlohmann::json j; try { j = OSUtils::jsonParse(responseBody); - } catch (std::exception &exc) { - printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what()); + } + catch (std::exception& exc) { + printf("%u %s invalid JSON response (%s)" ZT_EOL_S, scode, command.c_str(), exc.what()); return 1; - } catch ( ... ) { - printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str()); + } + catch (...) { + printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S, scode, command.c_str()); return 1; } if (scode == 200) { if (json) { - printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str()); - } else { + printf("%s" ZT_EOL_S, OSUtils::jsonDump(j).c_str()); + } + else { bool bFoundBond = false; printf(" " ZT_EOL_S); if (j.is_array()) { - for(unsigned long k=0;k= ZT_BOND_POLICY_NONE && bondingPolicyCode <= ZT_BOND_POLICY_BALANCE_AWARE) { policyStr = Bond::getPolicyStrByCode(bondingPolicyCode); } - printf("%10s %32s %d/%d" ZT_EOL_S, - OSUtils::jsonString(p ["address"],"-").c_str(), - policyStr.c_str(), - numAliveLinks, - numTotalLinks); + printf("%10s %32s %d/%d" ZT_EOL_S, OSUtils::jsonString(p["address"], "-").c_str(), policyStr.c_str(), numAliveLinks, numTotalLinks); } } } - if (!bFoundBond) { + if (! bFoundBond) { printf(" NONE\t\t\t\tNONE\t NONE NONE" ZT_EOL_S); } } return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } } @@ -581,20 +580,12 @@ static int cli(int argc,char **argv) arg3 = argv[6]; arg4 = argv[7]; } - unsigned int scode = Http::POST( - 1024 * 1024 * 16, - 60000, - (const struct sockaddr *)&addr, - (std::string("/bond/") + arg1 + "/" + arg2 + "/" + arg3 + "/" + arg4).c_str(), - requestHeaders, - "{}", - 2, - responseHeaders, - responseBody); + unsigned int scode = Http::POST(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, (std::string("/bond/") + arg1 + "/" + arg2 + "/" + arg3 + "/" + arg4).c_str(), requestHeaders, "{}", 2, responseHeaders, responseBody); if (scode == 200) { printf("200 setmtu OK" ZT_EOL_S); return 0; - } else { + } + else { printf("%d Failed to set MTU: %s" ZT_EOL_S, scode, responseBody.c_str()); return 1; } @@ -604,37 +595,25 @@ static int cli(int argc,char **argv) if (arg2 == "rotate") { /* zerotier-cli bond rotate */ requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = "2"; - unsigned int scode = Http::POST( - 1024 * 1024 * 16, - 60000, - (const struct sockaddr *)&addr, - (std::string("/bond/") + arg2 + "/" + arg1).c_str(), - requestHeaders, - "{}", - 2, - responseHeaders, - responseBody); + unsigned int scode = Http::POST(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, (std::string("/bond/") + arg2 + "/" + arg1).c_str(), requestHeaders, "{}", 2, responseHeaders, responseBody); if (scode == 200) { if (json) { - printf("%s",cliFixJsonCRs(responseBody).c_str()); - } else { + printf("%s", cliFixJsonCRs(responseBody).c_str()); + } + else { printf("200 rotate OK" ZT_EOL_S); } return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } return 0; } if (arg2 == "show") { - //fprintf(stderr, "zerotier-cli bond show\n"); - const unsigned int scode = Http::GET( - 1024 * 1024 * 16,60000, - (const struct sockaddr *)&addr,(std::string("/bond/") + arg2 + "/" + arg1).c_str(), - requestHeaders, - responseHeaders, - responseBody); + // fprintf(stderr, "zerotier-cli bond show\n"); + const unsigned int scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, (std::string("/bond/") + arg2 + "/" + arg1).c_str(), requestHeaders, responseHeaders, responseBody); if (scode == 0) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); return 1; @@ -642,53 +621,59 @@ static int cli(int argc,char **argv) nlohmann::json j; try { j = OSUtils::jsonParse(responseBody); - } catch (std::exception &exc) { - printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what()); + } + catch (std::exception& exc) { + printf("%u %s invalid JSON response (%s)" ZT_EOL_S, scode, command.c_str(), exc.what()); return 1; - } catch ( ... ) { - printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str()); + } + catch (...) { + printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S, scode, command.c_str()); return 1; } if (scode == 200) { if (json) { - printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str()); - } else { - int numAliveLinks = OSUtils::jsonInt(j["numAliveLinks"],0); - int numTotalLinks = OSUtils::jsonInt(j["numTotalLinks"],0); + printf("%s" ZT_EOL_S, OSUtils::jsonDump(j).c_str()); + } + else { + int numAliveLinks = OSUtils::jsonInt(j["numAliveLinks"], 0); + int numTotalLinks = OSUtils::jsonInt(j["numTotalLinks"], 0); printf("Peer : %s\n", arg1.c_str()); - printf("Bond : %s\n", OSUtils::jsonString(j["bondingPolicyStr"],"-").c_str()); - printf("Link Select Method : %d\n", (int)OSUtils::jsonInt(j["linkSelectMethod"],0)); + printf("Bond : %s\n", OSUtils::jsonString(j["bondingPolicyStr"], "-").c_str()); + printf("Link Select Method : %d\n", (int)OSUtils::jsonInt(j["linkSelectMethod"], 0)); printf("Links : %d/%d\n", numAliveLinks, numTotalLinks); - printf("Failover Interval (ms) : %d\n", (int)OSUtils::jsonInt(j["failoverInterval"],0)); - printf("Up Delay (ms) : %d\n", (int)OSUtils::jsonInt(j["upDelay"],0)); - printf("Down Delay (ms) : %d\n", (int)OSUtils::jsonInt(j["downDelay"],0)); - printf("Packets Per Link : %d\n", (int)OSUtils::jsonInt(j["packetsPerLink"],0)); - nlohmann::json &p = j["paths"]; + printf("Failover Interval (ms) : %d\n", (int)OSUtils::jsonInt(j["failoverInterval"], 0)); + printf("Up Delay (ms) : %d\n", (int)OSUtils::jsonInt(j["upDelay"], 0)); + printf("Down Delay (ms) : %d\n", (int)OSUtils::jsonInt(j["downDelay"], 0)); + printf("Packets Per Link : %d\n", (int)OSUtils::jsonInt(j["packetsPerLink"], 0)); + nlohmann::json& p = j["paths"]; if (p.is_array()) { printf("\nidx" - " interface" - " " - "path socket local port\n"); - for(int i=0; i<120; i++) { printf("-"); } + " interface" + " " + "path socket local port\n"); + for (int i = 0; i < 120; i++) { + printf("-"); + } printf("\n"); - for (int i=0; i " ZT_EOL_S); if (j.is_array()) { - for(unsigned long k=0;k= ZT_BOND_POLICY_NONE && bondingPolicyCode <= ZT_BOND_POLICY_BALANCE_AWARE) { policyStr = Bond::getPolicyStrByCode(bondingPolicyCode); } - printf("%10s %32s %d/%d" ZT_EOL_S, - OSUtils::jsonString(p["address"],"-").c_str(), - policyStr.c_str(), - numAliveLinks, - numTotalLinks); + printf("%10s %32s %d/%d" ZT_EOL_S, OSUtils::jsonString(p["address"], "-").c_str(), policyStr.c_str(), numAliveLinks, numTotalLinks); } } } - if (!bFoundBond) { + if (! bFoundBond) { printf(" NONE\t\t\t\tNONE\t NONE NONE" ZT_EOL_S); } } return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } - } else if (command == "listnetworks") { - const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/network",requestHeaders,responseHeaders,responseBody); + } + else if (command == "listnetworks") { + const unsigned int scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, "/network", requestHeaders, responseHeaders, responseBody); if (scode == 0) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); @@ -780,49 +768,56 @@ static int cli(int argc,char **argv) nlohmann::json j; try { j = OSUtils::jsonParse(responseBody); - } catch (std::exception &exc) { - printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what()); + } + catch (std::exception& exc) { + printf("%u %s invalid JSON response (%s)" ZT_EOL_S, scode, command.c_str(), exc.what()); return 1; - } catch ( ... ) { - printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str()); + } + catch (...) { + printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S, scode, command.c_str()); return 1; } if (scode == 200) { if (json) { - printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str()); - } else { + printf("%s" ZT_EOL_S, OSUtils::jsonDump(j).c_str()); + } + else { printf("200 listnetworks " ZT_EOL_S); if (j.is_array()) { - for(unsigned long i=0;i 0) aa.push_back(','); + if (aa.length() > 0) + aa.push_back(','); aa.append(addr.get()); } } } - if (aa.length() == 0) aa = "-"; - const std::string status = OSUtils::jsonString(n["status"],"-"); - printf("200 listnetworks %s %s %s %s %s %s %s" ZT_EOL_S, - OSUtils::jsonString(n["nwid"],"-").c_str(), - OSUtils::jsonString(n["name"],"-").c_str(), - OSUtils::jsonString(n["mac"],"-").c_str(), + if (aa.length() == 0) + aa = "-"; + const std::string status = OSUtils::jsonString(n["status"], "-"); + printf( + "200 listnetworks %s %s %s %s %s %s %s" ZT_EOL_S, + OSUtils::jsonString(n["nwid"], "-").c_str(), + OSUtils::jsonString(n["name"], "-").c_str(), + OSUtils::jsonString(n["mac"], "-").c_str(), status.c_str(), - OSUtils::jsonString(n["type"],"-").c_str(), - OSUtils::jsonString(n["portDeviceName"],"-").c_str(), + OSUtils::jsonString(n["type"], "-").c_str(), + OSUtils::jsonString(n["portDeviceName"], "-").c_str(), aa.c_str()); if (OSUtils::jsonBool(n["ssoEnabled"], false)) { uint64_t authenticationExpiryTime = n["authenticationExpiryTime"]; if (status == "AUTHENTICATION_REQUIRED") { printf(" AUTH EXPIRED, URL: %s" ZT_EOL_S, OSUtils::jsonString(n["authenticationURL"], "(null)").c_str()); - } else if (status == "OK") { + } + else if (status == "OK") { int64_t expiresIn = ((int64_t)authenticationExpiryTime - OSUtils::now()) / 1000LL; if (expiresIn >= 0) { printf(" AUTH OK, expires in: %lld seconds" ZT_EOL_S, expiresIn); @@ -834,64 +829,56 @@ static int cli(int argc,char **argv) } } return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } - } else if (command == "join") { + } + else if (command == "join") { if (arg1.length() != 16) { printf("invalid network id" ZT_EOL_S); return 2; } requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = "2"; - unsigned int scode = Http::POST( - 1024 * 1024 * 16, - 60000, - (const struct sockaddr *)&addr, - (std::string("/network/") + arg1).c_str(), - requestHeaders, - "{}", - 2, - responseHeaders, - responseBody); + unsigned int scode = Http::POST(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, (std::string("/network/") + arg1).c_str(), requestHeaders, "{}", 2, responseHeaders, responseBody); if (scode == 200) { if (json) { - printf("%s",cliFixJsonCRs(responseBody).c_str()); - } else { + printf("%s", cliFixJsonCRs(responseBody).c_str()); + } + else { printf("200 join OK" ZT_EOL_S); } return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } - } else if (command == "leave") { + } + else if (command == "leave") { if (arg1.length() != 16) { printf("invalid network id" ZT_EOL_S); return 2; } - unsigned int scode = Http::DEL( - 1024 * 1024 * 16, - 60000, - (const struct sockaddr *)&addr, - (std::string("/network/") + arg1).c_str(), - requestHeaders, - responseHeaders, - responseBody); + unsigned int scode = Http::DEL(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, (std::string("/network/") + arg1).c_str(), requestHeaders, responseHeaders, responseBody); if (scode == 200) { if (json) { - printf("%s",cliFixJsonCRs(responseBody).c_str()); - } else { + printf("%s", cliFixJsonCRs(responseBody).c_str()); + } + else { printf("200 leave OK" ZT_EOL_S); } return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } - } else if (command == "listmoons") { - const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/moon",requestHeaders,responseHeaders,responseBody); + } + else if (command == "listmoons") { + const unsigned int scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, "/moon", requestHeaders, responseHeaders, responseBody); if (scode == 0) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); @@ -901,121 +888,106 @@ static int cli(int argc,char **argv) nlohmann::json j; try { j = OSUtils::jsonParse(responseBody); - } catch (std::exception &exc) { - printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what()); + } + catch (std::exception& exc) { + printf("%u %s invalid JSON response (%s)" ZT_EOL_S, scode, command.c_str(), exc.what()); return 1; - } catch ( ... ) { - printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str()); + } + catch (...) { + printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S, scode, command.c_str()); return 1; } if (scode == 200) { - printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str()); + printf("%s" ZT_EOL_S, OSUtils::jsonDump(j).c_str()); return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } - } else if (command == "orbit") { + } + else if (command == "orbit") { const uint64_t worldId = Utils::hexStrToU64(arg1.c_str()); const uint64_t seed = Utils::hexStrToU64(arg2.c_str()); - if ((worldId)&&(seed)) { + if ((worldId) && (seed)) { char jsons[1024]; - OSUtils::ztsnprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str()); + OSUtils::ztsnprintf(jsons, sizeof(jsons), "{\"seed\":\"%s\"}", arg2.c_str()); char cl[128]; - OSUtils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); + OSUtils::ztsnprintf(cl, sizeof(cl), "%u", (unsigned int)strlen(jsons)); requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = cl; - unsigned int scode = Http::POST( - 1024 * 1024 * 16, - 60000, - (const struct sockaddr *)&addr, - (std::string("/moon/") + arg1).c_str(), - requestHeaders, - jsons, - (unsigned long)strlen(jsons), - responseHeaders, - responseBody); + unsigned int scode = Http::POST(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, (std::string("/moon/") + arg1).c_str(), requestHeaders, jsons, (unsigned long)strlen(jsons), responseHeaders, responseBody); if (scode == 200) { printf("200 orbit OK" ZT_EOL_S); return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } } - } else if (command == "deorbit") { - unsigned int scode = Http::DEL( - 1024 * 1024 * 16, - 60000, - (const struct sockaddr *)&addr, - (std::string("/moon/") + arg1).c_str(), - requestHeaders, - responseHeaders, - responseBody); + } + else if (command == "deorbit") { + unsigned int scode = Http::DEL(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, (std::string("/moon/") + arg1).c_str(), requestHeaders, responseHeaders, responseBody); if (scode == 200) { if (json) { - printf("%s",cliFixJsonCRs(responseBody).c_str()); - } else { + printf("%s", cliFixJsonCRs(responseBody).c_str()); + } + else { printf("200 deorbit OK" ZT_EOL_S); } return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } - } else if (command == "set") { + } + else if (command == "set") { if (arg1.length() != 16) { - fprintf(stderr,"invalid format: must be a 16-digit (network) ID\n"); + fprintf(stderr, "invalid format: must be a 16-digit (network) ID\n"); return 2; } - if (!arg2.length()) { - fprintf(stderr,"invalid format: include a property name to set\n"); + if (! arg2.length()) { + fprintf(stderr, "invalid format: include a property name to set\n"); return 2; } std::size_t eqidx = arg2.find('='); if (eqidx != std::string::npos) { - if ((arg2.substr(0,eqidx) == "allowManaged")||(arg2.substr(0,eqidx) == "allowGlobal")||(arg2.substr(0,eqidx) == "allowDefault")||(arg2.substr(0,eqidx) == "allowDNS")) { + if ((arg2.substr(0, eqidx) == "allowManaged") || (arg2.substr(0, eqidx) == "allowGlobal") || (arg2.substr(0, eqidx) == "allowDefault") || (arg2.substr(0, eqidx) == "allowDNS")) { char jsons[1024]; - OSUtils::ztsnprintf(jsons,sizeof(jsons),"{\"%s\":%s}", - arg2.substr(0,eqidx).c_str(), - (((arg2.substr(eqidx,2) == "=t")||(arg2.substr(eqidx,2) == "=1")) ? "true" : "false")); + OSUtils::ztsnprintf(jsons, sizeof(jsons), "{\"%s\":%s}", arg2.substr(0, eqidx).c_str(), (((arg2.substr(eqidx, 2) == "=t") || (arg2.substr(eqidx, 2) == "=1")) ? "true" : "false")); char cl[128]; - OSUtils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons)); + OSUtils::ztsnprintf(cl, sizeof(cl), "%u", (unsigned int)strlen(jsons)); requestHeaders["Content-Type"] = "application/json"; requestHeaders["Content-Length"] = cl; - unsigned int scode = Http::POST( - 1024 * 1024 * 16, - 60000, - (const struct sockaddr *)&addr, - (std::string("/network/") + arg1).c_str(), - requestHeaders, - jsons, - (unsigned long)strlen(jsons), - responseHeaders, - responseBody); + unsigned int scode = Http::POST(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, (std::string("/network/") + arg1).c_str(), requestHeaders, jsons, (unsigned long)strlen(jsons), responseHeaders, responseBody); if (scode == 200) { - printf("%s",cliFixJsonCRs(responseBody).c_str()); + printf("%s", cliFixJsonCRs(responseBody).c_str()); return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } } - } else { - cliPrintHelp(argv[0],stderr); + } + else { + cliPrintHelp(argv[0], stderr); return 2; } - } else if (command == "get") { + } + else if (command == "get") { if (arg1.length() != 16) { - fprintf(stderr,"invalid format: must be a 16-digit (network) ID\n"); + fprintf(stderr, "invalid format: must be a 16-digit (network) ID\n"); return 2; } - if (!arg2.length()) { - fprintf(stderr,"invalid format: include a property name to get\n"); + if (! arg2.length()) { + fprintf(stderr, "invalid format: include a property name to get\n"); return 2; } - const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/network",requestHeaders,responseHeaders,responseBody); + const unsigned int scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, "/network", requestHeaders, responseHeaders, responseBody); if (scode == 0) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); return 1; @@ -1023,83 +995,87 @@ static int cli(int argc,char **argv) nlohmann::json j; try { j = OSUtils::jsonParse(responseBody); - } catch (std::exception &exc) { - printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what()); + } + catch (std::exception& exc) { + printf("%u %s invalid JSON response (%s)" ZT_EOL_S, scode, command.c_str(), exc.what()); return 1; - } catch ( ... ) { - printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str()); + } + catch (...) { + printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S, scode, command.c_str()); return 1; } bool bNetworkFound = false; if (j.is_array()) { - for(unsigned long i=0;i().find('.') != std::string::npos) - || ((arg2.find("ip6") == 0) && addr.get().find(":") != std::string::npos) - || (arg2 == "ip") - ) { + for (int k = 0; k < std::min(ZT_MAX_ZT_ASSIGNED_ADDRESSES, (int)assignedAddresses.size()); ++k) { + nlohmann::json& addr = assignedAddresses[k]; + if ((arg2 == "ip4" && addr.get().find('.') != std::string::npos) || ((arg2.find("ip6") == 0) && addr.get().find(":") != std::string::npos) || (arg2 == "ip")) { matchingIdxs[addressCountOfType++] = k; } } - for (int k=0; k().find("fc") == 0) { - aa.append(addr.get().substr(0,addr.get().find('/'))); - if (k < addressCountOfType-1) aa.append("\n"); + aa.append(addr.get().substr(0, addr.get().find('/'))); + if (k < addressCountOfType - 1) + aa.append("\n"); } } if (arg2 == "ip6prefix") { if (addr.get().find("fc") == 0) { - aa.append(addr.get().substr(0,addr.get().find('/')).substr(0,24)); - if (k < addressCountOfType-1) aa.append("\n"); + aa.append(addr.get().substr(0, addr.get().find('/')).substr(0, 24)); + if (k < addressCountOfType - 1) + aa.append("\n"); } } } else { - aa.append(addr.get().substr(0,addr.get().find('/'))); - if (k < addressCountOfType-1) aa.append("\n"); + aa.append(addr.get().substr(0, addr.get().find('/'))); + if (k < addressCountOfType - 1) + aa.append("\n"); } } } - printf("%s\n",aa.c_str()); + printf("%s\n", aa.c_str()); } } } } - if (!bNetworkFound) { - fprintf(stderr,"unknown network ID, check that you are a member of the network\n"); + if (! bNetworkFound) { + fprintf(stderr, "unknown network ID, check that you are a member of the network\n"); } if (scode == 200) { return 0; - } else { - printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); + } + else { + printf("%u %s %s" ZT_EOL_S, scode, command.c_str(), responseBody.c_str()); return 1; } - } else if (command == "dump") { + } + else if (command == "dump") { std::stringstream dump; dump << "platform: "; #ifdef __APPLE__ @@ -1111,12 +1087,11 @@ static int cli(int argc,char **argv) #else dump << "other unix based OS" << ZT_EOL_S; #endif - dump << "zerotier version: " << ZEROTIER_ONE_VERSION_MAJOR << "." - << ZEROTIER_ONE_VERSION_MINOR << "." << ZEROTIER_ONE_VERSION_REVISION << ZT_EOL_S << ZT_EOL_S; + dump << "zerotier version: " << ZEROTIER_ONE_VERSION_MAJOR << "." << ZEROTIER_ONE_VERSION_MINOR << "." << ZEROTIER_ONE_VERSION_REVISION << ZT_EOL_S << ZT_EOL_S; // grab status dump << "status" << ZT_EOL_S << "------" << ZT_EOL_S; - unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/status",requestHeaders,responseHeaders,responseBody); + unsigned int scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, "/status", requestHeaders, responseHeaders, responseBody); if (scode != 200) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); return 1; @@ -1128,7 +1103,7 @@ static int cli(int argc,char **argv) // grab network list dump << ZT_EOL_S << "networks" << ZT_EOL_S << "--------" << ZT_EOL_S; - scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/network",requestHeaders,responseHeaders,responseBody); + scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, "/network", requestHeaders, responseHeaders, responseBody); if (scode != 200) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); return 1; @@ -1140,7 +1115,7 @@ static int cli(int argc,char **argv) // list peers dump << ZT_EOL_S << "peers" << ZT_EOL_S << "-----" << ZT_EOL_S; - scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/peer",requestHeaders,responseHeaders,responseBody); + scode = Http::GET(1024 * 1024 * 16, 60000, (const struct sockaddr*)&addr, "/peer", requestHeaders, responseHeaders, responseBody); if (scode != 200) { printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str()); return 1; @@ -1166,13 +1141,13 @@ static int cli(int argc,char **argv) #ifdef __APPLE__ CFArrayRef interfaces = SCNetworkInterfaceCopyAll(); CFIndex size = CFArrayGetCount(interfaces); - for(CFIndex i = 0; i < size; ++i) { + for (CFIndex i = 0; i < size; ++i) { SCNetworkInterfaceRef iface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(interfaces, i); dump << "Interface " << i << ZT_EOL_S << "-----------" << ZT_EOL_S; CFStringRef tmp = SCNetworkInterfaceGetBSDName(iface); char stringBuffer[512] = {}; - CFStringGetCString(tmp,stringBuffer, sizeof(stringBuffer), kCFStringEncodingUTF8); + CFStringGetCString(tmp, stringBuffer, sizeof(stringBuffer), kCFStringEncodingUTF8); dump << "Name: " << stringBuffer << ZT_EOL_S; std::string ifName(stringBuffer); int mtuCur, mtuMin, mtuMax; @@ -1187,17 +1162,19 @@ static int cli(int argc,char **argv) dump << "Addresses:" << ZT_EOL_S; struct ifaddrs *ifap, *ifa; - void *addr; + void* addr; getifaddrs(&ifap); for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (strcmp(ifName.c_str(), ifa->ifa_name) == 0) { if (ifa->ifa_addr->sa_family == AF_INET) { - struct sockaddr_in *ipv4 = (struct sockaddr_in*)ifa->ifa_addr; + struct sockaddr_in* ipv4 = (struct sockaddr_in*)ifa->ifa_addr; addr = &ipv4->sin_addr; - } else if (ifa->ifa_addr->sa_family == AF_INET6) { - struct sockaddr_in6 *ipv6 = (struct sockaddr_in6*)ifa->ifa_addr; + } + else if (ifa->ifa_addr->sa_family == AF_INET6) { + struct sockaddr_in6* ipv6 = (struct sockaddr_in6*)ifa->ifa_addr; addr = &ipv6->sin6_addr; - } else { + } + else { continue; } inet_ntop(ifa->ifa_addr->sa_family, addr, stringBuffer, sizeof(stringBuffer)); @@ -1208,23 +1185,21 @@ static int cli(int argc,char **argv) dump << ZT_EOL_S; } - FSRef fsref; UInt8 path[PATH_MAX]; - if (FSFindFolder(kUserDomain, kDesktopFolderType, kDontCreateFolder, &fsref) == noErr && - FSRefMakePath(&fsref, path, sizeof(path)) == noErr) { - - } else if (getenv("SUDO_USER")) { - sprintf((char*)path, "/Users/%s/Desktop", getenv("SUDO_USER")); - } else { + if (FSFindFolder(kUserDomain, kDesktopFolderType, kDontCreateFolder, &fsref) == noErr && FSRefMakePath(&fsref, path, sizeof(path)) == noErr) {} + else if (getenv("SUDO_USER")) { + snprintf((char*)path, sizeof(path), "/Users/%s/Desktop", getenv("SUDO_USER")); + } + else { fprintf(stdout, "%s", dump.str().c_str()); return 0; } - sprintf((char*)path, "%s%szerotier_dump.txt", (char*)path, ZT_PATH_SEPARATOR_S); + snprintf((char*)path, sizeof(path), "%s%szerotier_dump.txt", (char*)path, ZT_PATH_SEPARATOR_S); fprintf(stdout, "Writing dump to: %s\n", path); - int fd = open((char*)path, O_CREAT|O_RDWR,0664); + int fd = open((char*)path, O_CREAT | O_RDWR, 0664); if (fd == -1) { fprintf(stderr, "Error creating file.\n"); return 1; @@ -1258,7 +1233,10 @@ static int cli(int argc,char **argv) dump << "MTU: " << curAddr->Mtu << ZT_EOL_S; dump << "MAC: "; char macBuffer[64] = {}; - sprintf(macBuffer, "%02x:%02x:%02x:%02x:%02x:%02x", + snprintf( + macBuffer, + sizeof(macBuffer), + "%02x:%02x:%02x:%02x:%02x:%02x", curAddr->PhysicalAddress[0], curAddr->PhysicalAddress[1], curAddr->PhysicalAddress[2], @@ -1275,13 +1253,7 @@ static int cli(int argc,char **argv) char buf[128] = {}; DWORD bufLen = 128; LPSOCKADDR a = pUnicast->Address.lpSockaddr; - WSAAddressToStringA( - pUnicast->Address.lpSockaddr, - pUnicast->Address.iSockaddrLength, - NULL, - buf, - &bufLen - ); + WSAAddressToStringA(pUnicast->Address.lpSockaddr, pUnicast->Address.iSockaddrLength, NULL, buf, &bufLen); dump << buf << ZT_EOL_S; pUnicast = pUnicast->Next; } @@ -1298,29 +1270,15 @@ static int cli(int argc,char **argv) char path[MAX_PATH + 1] = {}; if (SHGetFolderPathA(NULL, CSIDL_DESKTOP, NULL, 0, path) == S_OK) { - sprintf(path, "%s%szerotier_dump.txt", path, ZT_PATH_SEPARATOR_S); + snprintf(path, sizeof(path), "%s%szerotier_dump.txt", path, ZT_PATH_SEPARATOR_S); fprintf(stdout, "Writing dump to: %s\n", path); - HANDLE file = CreateFileA( - path, - GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL - ); + HANDLE file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (file == INVALID_HANDLE_VALUE) { fprintf(stdout, "%s", dump.str().c_str()); return 0; } - BOOL err = WriteFile( - file, - dump.str().c_str(), - dump.str().size(), - NULL, - NULL - ); + BOOL err = WriteFile(file, dump.str().c_str(), dump.str().size(), NULL, NULL); if (err = FALSE) { fprintf(stderr, "Error writing file"); return 1; @@ -1342,13 +1300,13 @@ static int cli(int argc,char **argv) ifc.ifc_buf = buf; ioctl(sock, SIOCGIFCONF, &ifc); - struct ifreq *it = ifc.ifc_req; - const struct ifreq * const end = it + (ifc.ifc_len / sizeof(struct ifreq)); + struct ifreq* it = ifc.ifc_req; + const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq)); int count = 0; - for(; it != end; ++it) { + for (; it != end; ++it) { strcpy(ifr.ifr_name, it->ifr_name); - if(ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) { - if (!(ifr.ifr_flags & IFF_LOOPBACK)) { // skip loopback + if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) { + if (! (ifr.ifr_flags & IFF_LOOPBACK)) { // skip loopback dump << "Interface " << count++ << ZT_EOL_S << "-----------" << ZT_EOL_S; dump << "Name: " << ifr.ifr_name << ZT_EOL_S; if (ioctl(sock, SIOCGIFMTU, &ifr) == 0) { @@ -1358,29 +1316,25 @@ static int cli(int argc,char **argv) unsigned char mac_addr[6]; memcpy(mac_addr, ifr.ifr_hwaddr.sa_data, 6); char macStr[18]; - sprintf(macStr, "%02x:%02x:%02x:%02x:%02x:%02x", - mac_addr[0], - mac_addr[1], - mac_addr[2], - mac_addr[3], - mac_addr[4], - mac_addr[5]); + snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); dump << "MAC: " << macStr << ZT_EOL_S; } dump << "Addresses: " << ZT_EOL_S; struct ifaddrs *ifap, *ifa; - void *addr; + void* addr; getifaddrs(&ifap); - for(ifa = ifap; ifa; ifa = ifa->ifa_next) { - if(strcmp(ifr.ifr_name, ifa->ifa_name) == 0 && ifa->ifa_addr != NULL) { - if(ifa->ifa_addr->sa_family == AF_INET) { - struct sockaddr_in *ipv4 = (struct sockaddr_in*)ifa->ifa_addr; + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (strcmp(ifr.ifr_name, ifa->ifa_name) == 0 && ifa->ifa_addr != NULL) { + if (ifa->ifa_addr->sa_family == AF_INET) { + struct sockaddr_in* ipv4 = (struct sockaddr_in*)ifa->ifa_addr; addr = &ipv4->sin_addr; - } else if (ifa->ifa_addr->sa_family == AF_INET6) { - struct sockaddr_in6 *ipv6 = (struct sockaddr_in6*)ifa->ifa_addr; + } + else if (ifa->ifa_addr->sa_family == AF_INET6) { + struct sockaddr_in6* ipv6 = (struct sockaddr_in6*)ifa->ifa_addr; addr = &ipv6->sin6_addr; - } else { + } + else { continue; } inet_ntop(ifa->ifa_addr->sa_family, addr, stringBuffer, sizeof(stringBuffer)); @@ -1393,9 +1347,9 @@ static int cli(int argc,char **argv) close(sock); char cwd[16384]; getcwd(cwd, sizeof(cwd)); - sprintf(cwd, "%s%szerotier_dump.txt", cwd, ZT_PATH_SEPARATOR_S); + snprintf(cwd, sizeof(cwd), "%s%szerotier_dump.txt", cwd, ZT_PATH_SEPARATOR_S); fprintf(stdout, "Writing dump to: %s\n", cwd); - int fd = open(cwd, O_CREAT|O_RDWR,0664); + int fd = open(cwd, O_CREAT | O_RDWR, 0664); if (fd == -1) { fprintf(stderr, "Error creating file.\n"); return 1; @@ -1403,13 +1357,13 @@ static int cli(int argc,char **argv) write(fd, dump.str().c_str(), dump.str().size()); close(fd); #else - fprintf(stderr, "%s", dump.str().c_str()); + fprintf(stderr, "%s", dump.str().c_str()); #endif // fprintf(stderr, "%s\n", dump.str().c_str()); - - } else { - cliPrintHelp(argv[0],stderr); + } + else { + cliPrintHelp(argv[0], stderr); return 0; } @@ -1420,34 +1374,30 @@ static int cli(int argc,char **argv) /* zerotier-idtool personality */ /****************************************************************************/ -static void idtoolPrintHelp(FILE *out,const char *pn) +static void idtoolPrintHelp(FILE* out, const char* pn) { - fprintf(out, - "%s version %d.%d.%d" ZT_EOL_S, - PROGRAM_NAME, - ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION); - fprintf(out, - COPYRIGHT_NOTICE ZT_EOL_S - LICENSE_GRANT ZT_EOL_S); - fprintf(out,"Usage: %s []" ZT_EOL_S"" ZT_EOL_S"Commands:" ZT_EOL_S,pn); - fprintf(out," generate [] [] []" ZT_EOL_S); - fprintf(out," validate " ZT_EOL_S); - fprintf(out," getpublic " ZT_EOL_S); - fprintf(out," sign " ZT_EOL_S); - fprintf(out," verify " ZT_EOL_S); - fprintf(out," initmoon " ZT_EOL_S); - fprintf(out," genmoon " ZT_EOL_S); + fprintf(out, "%s version %d.%d.%d" ZT_EOL_S, PROGRAM_NAME, ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION); + fprintf(out, COPYRIGHT_NOTICE ZT_EOL_S LICENSE_GRANT ZT_EOL_S); + fprintf(out, "Usage: %s []" ZT_EOL_S "" ZT_EOL_S "Commands:" ZT_EOL_S, pn); + fprintf(out, " generate [] [] []" ZT_EOL_S); + fprintf(out, " validate " ZT_EOL_S); + fprintf(out, " getpublic " ZT_EOL_S); + fprintf(out, " sign " ZT_EOL_S); + fprintf(out, " verify " ZT_EOL_S); + fprintf(out, " initmoon " ZT_EOL_S); + fprintf(out, " genmoon " ZT_EOL_S); } -static Identity getIdFromArg(char *arg) +static Identity getIdFromArg(char* arg) { Identity id; - if ((strlen(arg) > 32)&&(arg[10] == ':')) { // identity is a literal on the command line + if ((strlen(arg) > 32) && (arg[10] == ':')) { // identity is a literal on the command line if (id.fromString(arg)) return id; - } else { // identity is to be read from a file + } + else { // identity is to be read from a file std::string idser; - if (OSUtils::readFile(arg,idser)) { + if (OSUtils::readFile(arg, idser)) { if (id.fromString(idser.c_str())) return id; } @@ -1458,15 +1408,15 @@ static Identity getIdFromArg(char *arg) #ifdef __WINDOWS__ static int idtool(int argc, _TCHAR* argv[]) #else -static int idtool(int argc,char **argv) +static int idtool(int argc, char** argv) #endif { if (argc < 2) { - idtoolPrintHelp(stdout,argv[0]); + idtoolPrintHelp(stdout, argv[0]); return 1; } - if (!strcmp(argv[1],"generate")) { + if (! strcmp(argv[1], "generate")) { uint64_t vanity = 0; int vanityBits = 0; if (argc >= 5) { @@ -1477,132 +1427,150 @@ static int idtool(int argc,char **argv) } Identity id; - for(;;) { + for (;;) { id.generate(); if ((id.address().toInt() >> (40 - vanityBits)) == vanity) { if (vanityBits > 0) { - fprintf(stderr,"vanity address: found %.10llx !\n",(unsigned long long)id.address().toInt()); + fprintf(stderr, "vanity address: found %.10llx !\n", (unsigned long long)id.address().toInt()); } break; - } else { - fprintf(stderr,"vanity address: tried %.10llx looking for first %d bits of %.10llx\n",(unsigned long long)id.address().toInt(),vanityBits,(unsigned long long)(vanity << (40 - vanityBits))); + } + else { + fprintf(stderr, "vanity address: tried %.10llx looking for first %d bits of %.10llx\n", (unsigned long long)id.address().toInt(), vanityBits, (unsigned long long)(vanity << (40 - vanityBits))); } } char idtmp[1024]; - std::string idser = id.toString(true,idtmp); + std::string idser = id.toString(true, idtmp); if (argc >= 3) { - if (!OSUtils::writeFile(argv[2],idser)) { - fprintf(stderr,"Error writing to %s" ZT_EOL_S,argv[2]); + if (! OSUtils::writeFile(argv[2], idser)) { + fprintf(stderr, "Error writing to %s" ZT_EOL_S, argv[2]); return 1; - } else printf("%s written" ZT_EOL_S,argv[2]); - if (argc >= 4) { - idser = id.toString(false,idtmp); - if (!OSUtils::writeFile(argv[3],idser)) { - fprintf(stderr,"Error writing to %s" ZT_EOL_S,argv[3]); - return 1; - } else printf("%s written" ZT_EOL_S,argv[3]); } - } else printf("%s",idser.c_str()); - } else if (!strcmp(argv[1],"validate")) { + else + printf("%s written" ZT_EOL_S, argv[2]); + if (argc >= 4) { + idser = id.toString(false, idtmp); + if (! OSUtils::writeFile(argv[3], idser)) { + fprintf(stderr, "Error writing to %s" ZT_EOL_S, argv[3]); + return 1; + } + else + printf("%s written" ZT_EOL_S, argv[3]); + } + } + else + printf("%s", idser.c_str()); + } + else if (! strcmp(argv[1], "validate")) { if (argc < 3) { - idtoolPrintHelp(stdout,argv[0]); + idtoolPrintHelp(stdout, argv[0]); return 1; } Identity id = getIdFromArg(argv[2]); - if (!id) { - fprintf(stderr,"Identity argument invalid or file unreadable: %s" ZT_EOL_S,argv[2]); + if (! id) { + fprintf(stderr, "Identity argument invalid or file unreadable: %s" ZT_EOL_S, argv[2]); return 1; } - if (!id.locallyValidate()) { - fprintf(stderr,"%s FAILED validation." ZT_EOL_S,argv[2]); + if (! id.locallyValidate()) { + fprintf(stderr, "%s FAILED validation." ZT_EOL_S, argv[2]); return 1; - } else printf("%s is a valid identity" ZT_EOL_S,argv[2]); - } else if (!strcmp(argv[1],"getpublic")) { + } + else + printf("%s is a valid identity" ZT_EOL_S, argv[2]); + } + else if (! strcmp(argv[1], "getpublic")) { if (argc < 3) { - idtoolPrintHelp(stdout,argv[0]); + idtoolPrintHelp(stdout, argv[0]); return 1; } Identity id = getIdFromArg(argv[2]); - if (!id) { - fprintf(stderr,"Identity argument invalid or file unreadable: %s" ZT_EOL_S,argv[2]); + if (! id) { + fprintf(stderr, "Identity argument invalid or file unreadable: %s" ZT_EOL_S, argv[2]); return 1; } char idtmp[1024]; - printf("%s",id.toString(false,idtmp)); - } else if (!strcmp(argv[1],"sign")) { + printf("%s", id.toString(false, idtmp)); + } + else if (! strcmp(argv[1], "sign")) { if (argc < 4) { - idtoolPrintHelp(stdout,argv[0]); + idtoolPrintHelp(stdout, argv[0]); return 1; } Identity id = getIdFromArg(argv[2]); - if (!id) { - fprintf(stderr,"Identity argument invalid or file unreadable: %s" ZT_EOL_S,argv[2]); + if (! id) { + fprintf(stderr, "Identity argument invalid or file unreadable: %s" ZT_EOL_S, argv[2]); return 1; } - if (!id.hasPrivate()) { - fprintf(stderr,"%s does not contain a private key (must use private to sign)" ZT_EOL_S,argv[2]); + if (! id.hasPrivate()) { + fprintf(stderr, "%s does not contain a private key (must use private to sign)" ZT_EOL_S, argv[2]); return 1; } std::string inf; - if (!OSUtils::readFile(argv[3],inf)) { - fprintf(stderr,"%s is not readable" ZT_EOL_S,argv[3]); + if (! OSUtils::readFile(argv[3], inf)) { + fprintf(stderr, "%s is not readable" ZT_EOL_S, argv[3]); return 1; } - ECC::Signature signature = id.sign(inf.data(),(unsigned int)inf.length()); + ECC::Signature signature = id.sign(inf.data(), (unsigned int)inf.length()); char hexbuf[1024]; - printf("%s",Utils::hex(signature.data,ZT_ECC_SIGNATURE_LEN,hexbuf)); - } else if (!strcmp(argv[1],"verify")) { + printf("%s", Utils::hex(signature.data, ZT_ECC_SIGNATURE_LEN, hexbuf)); + } + else if (! strcmp(argv[1], "verify")) { if (argc < 5) { - idtoolPrintHelp(stdout,argv[0]); + idtoolPrintHelp(stdout, argv[0]); return 1; } Identity id = getIdFromArg(argv[2]); - if (!id) { - fprintf(stderr,"Identity argument invalid or file unreadable: %s" ZT_EOL_S,argv[2]); + if (! id) { + fprintf(stderr, "Identity argument invalid or file unreadable: %s" ZT_EOL_S, argv[2]); return 1; } std::string inf; - if (!OSUtils::readFile(argv[3],inf)) { - fprintf(stderr,"%s is not readable" ZT_EOL_S,argv[3]); + if (! OSUtils::readFile(argv[3], inf)) { + fprintf(stderr, "%s is not readable" ZT_EOL_S, argv[3]); return 1; } char buf[4096]; - std::string signature(buf,Utils::unhex(argv[4],buf,(unsigned int)sizeof(buf))); - if ((signature.length() > ZT_ADDRESS_LENGTH)&&(id.verify(inf.data(),(unsigned int)inf.length(),signature.data(),(unsigned int)signature.length()))) { - printf("%s signature valid" ZT_EOL_S,argv[3]); - } else { + std::string signature(buf, Utils::unhex(argv[4], buf, (unsigned int)sizeof(buf))); + if ((signature.length() > ZT_ADDRESS_LENGTH) && (id.verify(inf.data(), (unsigned int)inf.length(), signature.data(), (unsigned int)signature.length()))) { + printf("%s signature valid" ZT_EOL_S, argv[3]); + } + else { signature.clear(); - if (OSUtils::readFile(argv[4],signature)) { - signature.assign(buf,Utils::unhex(signature.c_str(),buf,(unsigned int)sizeof(buf))); - if ((signature.length() > ZT_ADDRESS_LENGTH)&&(id.verify(inf.data(),(unsigned int)inf.length(),signature.data(),(unsigned int)signature.length()))) { - printf("%s signature valid" ZT_EOL_S,argv[3]); - } else { - fprintf(stderr,"%s signature check FAILED" ZT_EOL_S,argv[3]); + if (OSUtils::readFile(argv[4], signature)) { + signature.assign(buf, Utils::unhex(signature.c_str(), buf, (unsigned int)sizeof(buf))); + if ((signature.length() > ZT_ADDRESS_LENGTH) && (id.verify(inf.data(), (unsigned int)inf.length(), signature.data(), (unsigned int)signature.length()))) { + printf("%s signature valid" ZT_EOL_S, argv[3]); + } + else { + fprintf(stderr, "%s signature check FAILED" ZT_EOL_S, argv[3]); return 1; } - } else { - fprintf(stderr,"%s signature check FAILED" ZT_EOL_S,argv[3]); + } + else { + fprintf(stderr, "%s signature check FAILED" ZT_EOL_S, argv[3]); return 1; } } - } else if (!strcmp(argv[1],"initmoon")) { + } + else if (! strcmp(argv[1], "initmoon")) { if (argc < 3) { - idtoolPrintHelp(stdout,argv[0]); - } else { + idtoolPrintHelp(stdout, argv[0]); + } + else { const Identity id = getIdFromArg(argv[2]); - if (!id) { - fprintf(stderr,"%s is not a valid identity" ZT_EOL_S,argv[2]); + if (! id) { + fprintf(stderr, "%s is not a valid identity" ZT_EOL_S, argv[2]); return 1; } @@ -1612,80 +1580,85 @@ static int idtool(int argc,char **argv) nlohmann::json mj; mj["objtype"] = "world"; mj["worldType"] = "moon"; - mj["updatesMustBeSignedBy"] = mj["signingKey"] = Utils::hex(kp.pub.data,ZT_ECC_PUBLIC_KEY_SET_LEN,idtmp); - mj["signingKey_SECRET"] = Utils::hex(kp.priv.data,ZT_ECC_PRIVATE_KEY_SET_LEN,idtmp); + mj["updatesMustBeSignedBy"] = mj["signingKey"] = Utils::hex(kp.pub.data, ZT_ECC_PUBLIC_KEY_SET_LEN, idtmp); + mj["signingKey_SECRET"] = Utils::hex(kp.priv.data, ZT_ECC_PRIVATE_KEY_SET_LEN, idtmp); mj["id"] = id.address().toString(idtmp); nlohmann::json seedj; - seedj["identity"] = id.toString(false,idtmp); + seedj["identity"] = id.toString(false, idtmp); seedj["stableEndpoints"] = nlohmann::json::array(); (mj["roots"] = nlohmann::json::array()).push_back(seedj); std::string mjd(OSUtils::jsonDump(mj)); - printf("%s" ZT_EOL_S,mjd.c_str()); + printf("%s" ZT_EOL_S, mjd.c_str()); } - } else if (!strcmp(argv[1],"genmoon")) { + } + else if (! strcmp(argv[1], "genmoon")) { if (argc < 3) { - idtoolPrintHelp(stdout,argv[0]); - } else { + idtoolPrintHelp(stdout, argv[0]); + } + else { std::string buf; - if (!OSUtils::readFile(argv[2],buf)) { - fprintf(stderr,"cannot read %s" ZT_EOL_S,argv[2]); + if (! OSUtils::readFile(argv[2], buf)) { + fprintf(stderr, "cannot read %s" ZT_EOL_S, argv[2]); return 1; } nlohmann::json mj(OSUtils::jsonParse(buf)); - const uint64_t id = Utils::hexStrToU64(OSUtils::jsonString(mj["id"],"0").c_str()); - if (!id) { - fprintf(stderr,"ID in %s is invalid" ZT_EOL_S,argv[2]); + const uint64_t id = Utils::hexStrToU64(OSUtils::jsonString(mj["id"], "0").c_str()); + if (! id) { + fprintf(stderr, "ID in %s is invalid" ZT_EOL_S, argv[2]); return 1; } World::Type t; if (mj["worldType"] == "moon") { t = World::TYPE_MOON; - } else if (mj["worldType"] == "planet") { + } + else if (mj["worldType"] == "planet") { t = World::TYPE_PLANET; - } else { - fprintf(stderr,"invalid worldType" ZT_EOL_S); + } + else { + fprintf(stderr, "invalid worldType" ZT_EOL_S); return 1; } ECC::Pair signingKey; ECC::Public updatesMustBeSignedBy; - Utils::unhex(OSUtils::jsonString(mj["signingKey"],"").c_str(),signingKey.pub.data,ZT_ECC_PUBLIC_KEY_SET_LEN); - Utils::unhex(OSUtils::jsonString(mj["signingKey_SECRET"],"").c_str(),signingKey.priv.data,ZT_ECC_PRIVATE_KEY_SET_LEN); - Utils::unhex(OSUtils::jsonString(mj["updatesMustBeSignedBy"],"").c_str(),updatesMustBeSignedBy.data,ZT_ECC_PUBLIC_KEY_SET_LEN); + Utils::unhex(OSUtils::jsonString(mj["signingKey"], "").c_str(), signingKey.pub.data, ZT_ECC_PUBLIC_KEY_SET_LEN); + Utils::unhex(OSUtils::jsonString(mj["signingKey_SECRET"], "").c_str(), signingKey.priv.data, ZT_ECC_PRIVATE_KEY_SET_LEN); + Utils::unhex(OSUtils::jsonString(mj["updatesMustBeSignedBy"], "").c_str(), updatesMustBeSignedBy.data, ZT_ECC_PUBLIC_KEY_SET_LEN); std::vector roots; - nlohmann::json &rootsj = mj["roots"]; + nlohmann::json& rootsj = mj["roots"]; if (rootsj.is_array()) { - for(unsigned long i=0;i<(unsigned long)rootsj.size();++i) { - nlohmann::json &r = rootsj[i]; + for (unsigned long i = 0; i < (unsigned long)rootsj.size(); ++i) { + nlohmann::json& r = rootsj[i]; if (r.is_object()) { roots.push_back(World::Root()); - roots.back().identity = Identity(OSUtils::jsonString(r["identity"],"").c_str()); - nlohmann::json &stableEndpointsj = r["stableEndpoints"]; + roots.back().identity = Identity(OSUtils::jsonString(r["identity"], "").c_str()); + nlohmann::json& stableEndpointsj = r["stableEndpoints"]; if (stableEndpointsj.is_array()) { - for(unsigned long k=0;k<(unsigned long)stableEndpointsj.size();++k) - roots.back().stableEndpoints.push_back(InetAddress(OSUtils::jsonString(stableEndpointsj[k],"").c_str())); - std::sort(roots.back().stableEndpoints.begin(),roots.back().stableEndpoints.end()); + for (unsigned long k = 0; k < (unsigned long)stableEndpointsj.size(); ++k) + roots.back().stableEndpoints.push_back(InetAddress(OSUtils::jsonString(stableEndpointsj[k], "").c_str())); + std::sort(roots.back().stableEndpoints.begin(), roots.back().stableEndpoints.end()); } } } } - std::sort(roots.begin(),roots.end()); + std::sort(roots.begin(), roots.end()); const int64_t now = OSUtils::now(); - World w(World::make(t,id,now,updatesMustBeSignedBy,roots,signingKey)); + World w(World::make(t, id, now, updatesMustBeSignedBy, roots, signingKey)); Buffer wbuf; w.serialize(wbuf); char fn[128]; - OSUtils::ztsnprintf(fn,sizeof(fn),"%.16llx.moon",w.id()); - OSUtils::writeFile(fn,wbuf.data(),wbuf.size()); - printf("wrote %s (signed world with timestamp %llu)" ZT_EOL_S,fn,(unsigned long long)now); + OSUtils::ztsnprintf(fn, sizeof(fn), "%.16llx.moon", w.id()); + OSUtils::writeFile(fn, wbuf.data(), wbuf.size()); + printf("wrote %s (signed world with timestamp %llu)" ZT_EOL_S, fn, (unsigned long long)now); } - } else { - idtoolPrintHelp(stdout,argv[0]); + } + else { + idtoolPrintHelp(stdout, argv[0]); return 1; } @@ -1706,24 +1679,25 @@ static void _sighandlerReallyQuit(int sig) } static void _sighandlerQuit(int sig) { - alarm(5); // force exit after 5s - OneService *s = zt1Service; + alarm(5); // force exit after 5s + OneService* s = zt1Service; if (s) s->terminate(); - else exit(0); + else + exit(0); } #endif // Drop privileges on Linux, if supported by libc etc. and "zerotier-one" user exists on system -#if defined(__LINUX__) && !defined(ZT_NO_CAPABILITIES) +#if defined(__LINUX__) && ! defined(ZT_NO_CAPABILITIES) #ifndef PR_CAP_AMBIENT -#define PR_CAP_AMBIENT 47 -#define PR_CAP_AMBIENT_IS_SET 1 -#define PR_CAP_AMBIENT_RAISE 2 -#define PR_CAP_AMBIENT_LOWER 3 +#define PR_CAP_AMBIENT 47 +#define PR_CAP_AMBIENT_IS_SET 1 +#define PR_CAP_AMBIENT_RAISE 2 +#define PR_CAP_AMBIENT_LOWER 3 #define PR_CAP_AMBIENT_CLEAR_ALL 4 #endif -#define ZT_LINUX_USER "zerotier-one" +#define ZT_LINUX_USER "zerotier-one" #define ZT_HAVE_DROP_PRIVILEGES 1 namespace { @@ -1738,78 +1712,81 @@ struct cap_data_struct { __u32 permitted; __u32 inheritable; }; -static inline int _zt_capset(cap_header_struct* hdrp, cap_data_struct* datap) { return syscall(SYS_capset, hdrp, datap); } +static inline int _zt_capset(cap_header_struct* hdrp, cap_data_struct* datap) +{ + return syscall(SYS_capset, hdrp, datap); +} -static void _notDropping(const char *procName,const std::string &homeDir) +static void _notDropping(const char* procName, const std::string& homeDir) { struct stat buf; - if (lstat(homeDir.c_str(),&buf) < 0) { + if (lstat(homeDir.c_str(), &buf) < 0) { if (buf.st_uid != 0 || buf.st_gid != 0) { - fprintf(stderr, "%s: FATAL: failed to drop privileges and can't run as root since privileges were previously dropped (home directory not owned by root)" ZT_EOL_S,procName); + fprintf(stderr, "%s: FATAL: failed to drop privileges and can't run as root since privileges were previously dropped (home directory not owned by root)" ZT_EOL_S, procName); exit(1); } } - fprintf(stderr, "%s: WARNING: failed to drop privileges (kernel may not support required prctl features), running as root" ZT_EOL_S,procName); + fprintf(stderr, "%s: WARNING: failed to drop privileges (kernel may not support required prctl features), running as root" ZT_EOL_S, procName); } static int _setCapabilities(int flags) { - cap_header_struct capheader = {_LINUX_CAPABILITY_VERSION_1, 0}; + cap_header_struct capheader = { _LINUX_CAPABILITY_VERSION_1, 0 }; cap_data_struct capdata; capdata.inheritable = capdata.permitted = capdata.effective = flags; return _zt_capset(&capheader, &capdata); } -static void _recursiveChown(const char *path,uid_t uid,gid_t gid) +static void _recursiveChown(const char* path, uid_t uid, gid_t gid) { struct dirent de; - struct dirent *dptr; - lchown(path,uid,gid); - DIR *d = opendir(path); - if (!d) + struct dirent* dptr; + lchown(path, uid, gid); + DIR* d = opendir(path); + if (! d) return; - dptr = (struct dirent *)0; - for(;;) { - if (readdir_r(d,&de,&dptr) != 0) + dptr = (struct dirent*)0; + for (;;) { + if (readdir_r(d, &de, &dptr) != 0) break; - if (!dptr) + if (! dptr) break; - if ((strcmp(dptr->d_name,".") != 0)&&(strcmp(dptr->d_name,"..") != 0)&&(strlen(dptr->d_name) > 0)) { + if ((strcmp(dptr->d_name, ".") != 0) && (strcmp(dptr->d_name, "..") != 0) && (strlen(dptr->d_name) > 0)) { std::string p(path); p.push_back(ZT_PATH_SEPARATOR); p.append(dptr->d_name); - _recursiveChown(p.c_str(),uid,gid); // will just fail and return on regular files + _recursiveChown(p.c_str(), uid, gid); // will just fail and return on regular files } } closedir(d); } -static void dropPrivileges(const char *procName,const std::string &homeDir) +static void dropPrivileges(const char* procName, const std::string& homeDir) { if (getuid() != 0) return; // dropPrivileges switches to zerotier-one user while retaining CAP_NET_ADMIN // and CAP_NET_RAW capabilities. - struct passwd *targetUser = getpwnam(ZT_LINUX_USER); - if (!targetUser) + struct passwd* targetUser = getpwnam(ZT_LINUX_USER); + if (! targetUser) return; if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_RAW, 0, 0) < 0) { // Kernel has no support for ambient capabilities. - _notDropping(procName,homeDir); + _notDropping(procName, homeDir); return; } if (prctl(PR_SET_SECUREBITS, SECBIT_KEEP_CAPS | SECBIT_NOROOT) < 0) { - _notDropping(procName,homeDir); + _notDropping(procName, homeDir); return; } // Change ownership of our home directory if everything looks good (does nothing if already chown'd) - _recursiveChown(homeDir.c_str(),targetUser->pw_uid,targetUser->pw_gid); + _recursiveChown(homeDir.c_str(), targetUser->pw_uid, targetUser->pw_gid); if (_setCapabilities((1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID) | (1 << CAP_SETGID) | (1 << CAP_NET_BIND_SERVICE)) < 0) { - _notDropping(procName,homeDir); + _notDropping(procName, homeDir); return; } @@ -1818,7 +1795,7 @@ static void dropPrivileges(const char *procName,const std::string &homeDir) // Disable ptracing. Otherwise there is a small window when previous // compromised ZeroTier process could ptrace us, when we still have CAP_SETUID. // (this is mitigated anyway on most distros by ptrace_scope=1) - fprintf(stderr,"%s: FATAL: prctl(PR_SET_DUMPABLE) failed while attempting to relinquish root permissions" ZT_EOL_S,procName); + fprintf(stderr, "%s: FATAL: prctl(PR_SET_DUMPABLE) failed while attempting to relinquish root permissions" ZT_EOL_S, procName); exit(1); } @@ -1833,27 +1810,27 @@ static void dropPrivileges(const char *procName,const std::string &homeDir) } if (_setCapabilities((1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE)) < 0) { - fprintf(stderr,"%s: FATAL: unable to drop capabilities after relinquishing root" ZT_EOL_S,procName); + fprintf(stderr, "%s: FATAL: unable to drop capabilities after relinquishing root" ZT_EOL_S, procName); exit(1); } if (prctl(PR_SET_DUMPABLE, oldDumpable) < 0) { - fprintf(stderr,"%s: FATAL: prctl(PR_SET_DUMPABLE) failed while attempting to relinquish root permissions" ZT_EOL_S,procName); + fprintf(stderr, "%s: FATAL: prctl(PR_SET_DUMPABLE) failed while attempting to relinquish root permissions" ZT_EOL_S, procName); exit(1); } if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_ADMIN, 0, 0) < 0) { - fprintf(stderr,"%s: FATAL: prctl(PR_CAP_AMBIENT,PR_CAP_AMBIENT_RAISE,CAP_NET_ADMIN) failed while attempting to relinquish root permissions" ZT_EOL_S,procName); + fprintf(stderr, "%s: FATAL: prctl(PR_CAP_AMBIENT,PR_CAP_AMBIENT_RAISE,CAP_NET_ADMIN) failed while attempting to relinquish root permissions" ZT_EOL_S, procName); exit(1); } if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_RAW, 0, 0) < 0) { - fprintf(stderr,"%s: FATAL: prctl(PR_CAP_AMBIENT,PR_CAP_AMBIENT_RAISE,CAP_NET_RAW) failed while attempting to relinquish root permissions" ZT_EOL_S,procName); + fprintf(stderr, "%s: FATAL: prctl(PR_CAP_AMBIENT,PR_CAP_AMBIENT_RAISE,CAP_NET_RAW) failed while attempting to relinquish root permissions" ZT_EOL_S, procName); exit(1); } } -} // anonymous namespace -#endif // __LINUX__ +} // anonymous namespace +#endif // __LINUX__ /****************************************************************************/ /* Windows helper functions and signal handlers */ @@ -1863,12 +1840,12 @@ static void dropPrivileges(const char *procName,const std::string &homeDir) // Console signal handler routine to allow CTRL+C to work, mostly for testing static BOOL WINAPI _winConsoleCtrlHandler(DWORD dwCtrlType) { - switch(dwCtrlType) { + switch (dwCtrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: case CTRL_CLOSE_EVENT: case CTRL_SHUTDOWN_EVENT: - OneService *s = zt1Service; + OneService* s = zt1Service; if (s) s->terminate(); return TRUE; @@ -1880,34 +1857,64 @@ static BOOL WINAPI _winConsoleCtrlHandler(DWORD dwCtrlType) static void _winPokeAHole() { char myPath[MAX_PATH]; - DWORD ps = GetModuleFileNameA(NULL,myPath,sizeof(myPath)); - if ((ps > 0)&&(ps < (DWORD)sizeof(myPath))) { + DWORD ps = GetModuleFileNameA(NULL, myPath, sizeof(myPath)); + if ((ps > 0) && (ps < (DWORD)sizeof(myPath))) { STARTUPINFOA startupInfo; PROCESS_INFORMATION processInfo; startupInfo.cb = sizeof(startupInfo); - memset(&startupInfo,0,sizeof(STARTUPINFOA)); - memset(&processInfo,0,sizeof(PROCESS_INFORMATION)); - if (CreateProcessA(NULL,(LPSTR)(std::string("C:\\Windows\\System32\\netsh.exe advfirewall firewall delete rule name=\"ZeroTier One\" program=\"") + myPath + "\"").c_str(),NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&startupInfo,&processInfo)) { - WaitForSingleObject(processInfo.hProcess,INFINITE); + memset(&startupInfo, 0, sizeof(STARTUPINFOA)); + memset(&processInfo, 0, sizeof(PROCESS_INFORMATION)); + if (CreateProcessA( + NULL, + (LPSTR)(std::string("C:\\Windows\\System32\\netsh.exe advfirewall firewall delete rule name=\"ZeroTier One\" program=\"") + myPath + "\"").c_str(), + NULL, + NULL, + FALSE, + CREATE_NO_WINDOW, + NULL, + NULL, + &startupInfo, + &processInfo)) { + WaitForSingleObject(processInfo.hProcess, INFINITE); CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); } startupInfo.cb = sizeof(startupInfo); - memset(&startupInfo,0,sizeof(STARTUPINFOA)); - memset(&processInfo,0,sizeof(PROCESS_INFORMATION)); - if (CreateProcessA(NULL,(LPSTR)(std::string("C:\\Windows\\System32\\netsh.exe advfirewall firewall add rule name=\"ZeroTier One\" dir=in action=allow program=\"") + myPath + "\" enable=yes").c_str(),NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&startupInfo,&processInfo)) { - WaitForSingleObject(processInfo.hProcess,INFINITE); + memset(&startupInfo, 0, sizeof(STARTUPINFOA)); + memset(&processInfo, 0, sizeof(PROCESS_INFORMATION)); + if (CreateProcessA( + NULL, + (LPSTR)(std::string("C:\\Windows\\System32\\netsh.exe advfirewall firewall add rule name=\"ZeroTier One\" dir=in action=allow program=\"") + myPath + "\" enable=yes").c_str(), + NULL, + NULL, + FALSE, + CREATE_NO_WINDOW, + NULL, + NULL, + &startupInfo, + &processInfo)) { + WaitForSingleObject(processInfo.hProcess, INFINITE); CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); } startupInfo.cb = sizeof(startupInfo); - memset(&startupInfo,0,sizeof(STARTUPINFOA)); - memset(&processInfo,0,sizeof(PROCESS_INFORMATION)); - if (CreateProcessA(NULL,(LPSTR)(std::string("C:\\Windows\\System32\\netsh.exe advfirewall firewall add rule name=\"ZeroTier One\" dir=out action=allow program=\"") + myPath + "\" enable=yes").c_str(),NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&startupInfo,&processInfo)) { - WaitForSingleObject(processInfo.hProcess,INFINITE); + memset(&startupInfo, 0, sizeof(STARTUPINFOA)); + memset(&processInfo, 0, sizeof(PROCESS_INFORMATION)); + if (CreateProcessA( + NULL, + (LPSTR)(std::string("C:\\Windows\\System32\\netsh.exe advfirewall firewall add rule name=\"ZeroTier One\" dir=out action=allow program=\"") + myPath + "\" enable=yes").c_str(), + NULL, + NULL, + FALSE, + CREATE_NO_WINDOW, + NULL, + NULL, + &startupInfo, + &processInfo)) { + WaitForSingleObject(processInfo.hProcess, INFINITE); CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); } @@ -1917,236 +1924,234 @@ static void _winPokeAHole() // Returns true if this is running as the local administrator static BOOL IsCurrentUserLocalAdministrator(void) { - BOOL fReturn = FALSE; - DWORD dwStatus; - DWORD dwAccessMask; - DWORD dwAccessDesired; - DWORD dwACLSize; - DWORD dwStructureSize = sizeof(PRIVILEGE_SET); - PACL pACL = NULL; - PSID psidAdmin = NULL; + BOOL fReturn = FALSE; + DWORD dwStatus; + DWORD dwAccessMask; + DWORD dwAccessDesired; + DWORD dwACLSize; + DWORD dwStructureSize = sizeof(PRIVILEGE_SET); + PACL pACL = NULL; + PSID psidAdmin = NULL; - HANDLE hToken = NULL; + HANDLE hToken = NULL; HANDLE hImpersonationToken = NULL; - PRIVILEGE_SET ps; + PRIVILEGE_SET ps; GENERIC_MAPPING GenericMapping; - PSECURITY_DESCRIPTOR psdAdmin = NULL; + PSECURITY_DESCRIPTOR psdAdmin = NULL; SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY; - const DWORD ACCESS_READ = 1; + const DWORD ACCESS_READ = 1; const DWORD ACCESS_WRITE = 2; - __try - { - if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY,TRUE,&hToken)) - { + __try { + if (! OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE | TOKEN_QUERY, TRUE, &hToken)) { if (GetLastError() != ERROR_NO_TOKEN) __leave; - if (!OpenProcessToken(GetCurrentProcess(),TOKEN_DUPLICATE|TOKEN_QUERY, &hToken)) + if (! OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY, &hToken)) __leave; } - if (!DuplicateToken (hToken, SecurityImpersonation,&hImpersonationToken)) + if (! DuplicateToken(hToken, SecurityImpersonation, &hImpersonationToken)) __leave; - if (!AllocateAndInitializeSid(&SystemSidAuthority, 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, &psidAdmin)) + if (! AllocateAndInitializeSid(&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin)) __leave; psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (psdAdmin == NULL) __leave; - if (!InitializeSecurityDescriptor(psdAdmin,SECURITY_DESCRIPTOR_REVISION)) + if (! InitializeSecurityDescriptor(psdAdmin, SECURITY_DESCRIPTOR_REVISION)) __leave; dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidAdmin) - sizeof(DWORD); pACL = (PACL)LocalAlloc(LPTR, dwACLSize); if (pACL == NULL) __leave; - if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2)) + if (! InitializeAcl(pACL, dwACLSize, ACL_REVISION2)) __leave; - dwAccessMask= ACCESS_READ | ACCESS_WRITE; - if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin)) + dwAccessMask = ACCESS_READ | ACCESS_WRITE; + if (! AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin)) __leave; - if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE)) + if (! SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE)) __leave; SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE); SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE); - if (!IsValidSecurityDescriptor(psdAdmin)) + if (! IsValidSecurityDescriptor(psdAdmin)) __leave; dwAccessDesired = ACCESS_READ; - GenericMapping.GenericRead = ACCESS_READ; - GenericMapping.GenericWrite = ACCESS_WRITE; + GenericMapping.GenericRead = ACCESS_READ; + GenericMapping.GenericWrite = ACCESS_WRITE; GenericMapping.GenericExecute = 0; - GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE; + GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE; - if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired, - &GenericMapping, &ps, &dwStructureSize, &dwStatus, - &fReturn)) - { + if (! AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired, &GenericMapping, &ps, &dwStructureSize, &dwStatus, &fReturn)) { fReturn = FALSE; __leave; } } - __finally - { + __finally { // Clean up. - if (pACL) LocalFree(pACL); - if (psdAdmin) LocalFree(psdAdmin); - if (psidAdmin) FreeSid(psidAdmin); - if (hImpersonationToken) CloseHandle (hImpersonationToken); - if (hToken) CloseHandle (hToken); + if (pACL) + LocalFree(pACL); + if (psdAdmin) + LocalFree(psdAdmin); + if (psidAdmin) + FreeSid(psidAdmin); + if (hImpersonationToken) + CloseHandle(hImpersonationToken); + if (hToken) + CloseHandle(hToken); } return fReturn; } -#endif // __WINDOWS__ +#endif // __WINDOWS__ /****************************************************************************/ /* main() and friends */ /****************************************************************************/ -static void printHelp(const char *cn,FILE *out) +static void printHelp(const char* cn, FILE* out) { - fprintf(out, - "%s version %d.%d.%d" ZT_EOL_S, - PROGRAM_NAME, - ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION); - fprintf(out, - COPYRIGHT_NOTICE ZT_EOL_S - LICENSE_GRANT ZT_EOL_S); - fprintf(out,"Usage: %s [-switches] [home directory]" ZT_EOL_S"" ZT_EOL_S,cn); - fprintf(out,"Available switches:" ZT_EOL_S); - fprintf(out," -h - Display this help" ZT_EOL_S); - fprintf(out," -v - Show version" ZT_EOL_S); - fprintf(out," -U - Skip privilege check and do not attempt to drop privileges" ZT_EOL_S); - fprintf(out," -p - Port for UDP and TCP/HTTP (default: 9993, 0 for random)" ZT_EOL_S); + fprintf(out, "%s version %d.%d.%d" ZT_EOL_S, PROGRAM_NAME, ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION); + fprintf(out, COPYRIGHT_NOTICE ZT_EOL_S LICENSE_GRANT ZT_EOL_S); + fprintf(out, ZT_EOL_S "Usage: %s [-switches] [home directory]" ZT_EOL_S "" ZT_EOL_S, cn); + fprintf(out, "Available switches:" ZT_EOL_S); + fprintf(out, " -h - Display this help" ZT_EOL_S); + fprintf(out, " -v - Show version" ZT_EOL_S); + fprintf(out, " -U - Skip privilege check and do not attempt to drop privileges" ZT_EOL_S); + fprintf(out, " -p - Port for UDP and TCP/HTTP (default: 9993, 0 for random)" ZT_EOL_S); #ifdef __UNIX_LIKE__ - fprintf(out," -d - Fork and run as daemon (Unix-ish OSes)" ZT_EOL_S); -#endif // __UNIX_LIKE__ + fprintf(out, " -d - Fork and run as daemon (Unix-ish OSes)" ZT_EOL_S); +#endif // __UNIX_LIKE__ #ifdef __WINDOWS__ - fprintf(out," -C - Run from command line instead of as service (Windows)" ZT_EOL_S); - fprintf(out," -I - Install Windows service (Windows)" ZT_EOL_S); - fprintf(out," -R - Uninstall Windows service (Windows)" ZT_EOL_S); - fprintf(out," -D - Remove all instances of Windows tap device (Windows)" ZT_EOL_S); -#endif // __WINDOWS__ + fprintf(out, " -C - Run from command line instead of as service (Windows)" ZT_EOL_S); + fprintf(out, " -I - Install Windows service (Windows)" ZT_EOL_S); + fprintf(out, " -R - Uninstall Windows service (Windows)" ZT_EOL_S); + fprintf(out, " -D - Remove all instances of Windows tap device (Windows)" ZT_EOL_S); +#endif // __WINDOWS__ - fprintf(out," -i - Generate and manage identities (zerotier-idtool)" ZT_EOL_S); - fprintf(out," -q - Query API (zerotier-cli)" ZT_EOL_S); + fprintf(out, " -i - Generate and manage identities (zerotier-idtool)" ZT_EOL_S); + fprintf(out, " -q - Query API (zerotier-cli)" ZT_EOL_S); } -class _OneServiceRunner -{ -public: - _OneServiceRunner(const char *pn,const std::string &hd,unsigned int p) : progname(pn),returnValue(0),port(p),homeDir(hd) {} - void threadMain() - throw() +class _OneServiceRunner { + public: + _OneServiceRunner(const char* pn, const std::string& hd, unsigned int p) : progname(pn), returnValue(0), port(p), homeDir(hd) + { + } + void threadMain() throw() { try { - for(;;) { - zt1Service = OneService::newInstance(homeDir.c_str(),port); - switch(zt1Service->run()) { - case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done + for (;;) { + zt1Service = OneService::newInstance(homeDir.c_str(), port); + switch (zt1Service->run()) { + case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done case OneService::ONE_NORMAL_TERMINATION: break; case OneService::ONE_UNRECOVERABLE_ERROR: - fprintf(stderr,"%s: fatal error: %s" ZT_EOL_S,progname,zt1Service->fatalErrorMessage().c_str()); + fprintf(stderr, "%s: fatal error: %s" ZT_EOL_S, progname, zt1Service->fatalErrorMessage().c_str()); returnValue = 1; break; case OneService::ONE_IDENTITY_COLLISION: { delete zt1Service; - zt1Service = (OneService *)0; + zt1Service = (OneService*)0; std::string oldid; - OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid); + OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(), oldid); if (oldid.length()) { - OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid); + OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(), oldid); OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str()); OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str()); } - } continue; // restart! + } + continue; // restart! } - break; // terminate loop -- normally we don't keep restarting + break; // terminate loop -- normally we don't keep restarting } delete zt1Service; - zt1Service = (OneService *)0; - } catch ( ... ) { - fprintf(stderr,"%s: unexpected exception starting main OneService instance" ZT_EOL_S,progname); + zt1Service = (OneService*)0; + } + catch (...) { + fprintf(stderr, "%s: unexpected exception starting main OneService instance" ZT_EOL_S, progname); returnValue = 1; } } - const char *progname; + const char* progname; unsigned int returnValue; unsigned int port; - const std::string &homeDir; + const std::string& homeDir; }; #ifdef __WINDOWS__ int __cdecl _tmain(int argc, _TCHAR* argv[]) #else -int main(int argc,char **argv) +int main(int argc, char** argv) #endif { -#if defined(__LINUX__) && ( (!defined(__GLIBC__)) || ((__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 18)) ) +#if defined(__LINUX__) && ((! defined(__GLIBC__)) || ((__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 18))) // This corrects for systems with abnormally small defaults (musl) and also // shrinks the stack on systems with large defaults to save a bit of memory. pthread_attr_t tattr; pthread_attr_init(&tattr); - pthread_attr_setstacksize(&tattr,1048576); + pthread_attr_setstacksize(&tattr, 1048576); pthread_setattr_default_np(&tattr); pthread_attr_destroy(&tattr); #endif #ifdef __UNIX_LIKE__ - signal(SIGHUP,&_sighandlerHup); - signal(SIGPIPE,SIG_IGN); - signal(SIGIO,SIG_IGN); - signal(SIGUSR1,SIG_IGN); - signal(SIGUSR2,SIG_IGN); - signal(SIGALRM,&_sighandlerReallyQuit); - signal(SIGINT,&_sighandlerQuit); - signal(SIGTERM,&_sighandlerQuit); - signal(SIGQUIT,&_sighandlerQuit); - signal(SIGINT,&_sighandlerQuit); + signal(SIGHUP, &_sighandlerHup); + signal(SIGPIPE, SIG_IGN); + signal(SIGIO, SIG_IGN); + signal(SIGUSR1, SIG_IGN); + signal(SIGUSR2, SIG_IGN); + signal(SIGALRM, &_sighandlerReallyQuit); + signal(SIGINT, &_sighandlerQuit); + signal(SIGTERM, &_sighandlerQuit); + signal(SIGQUIT, &_sighandlerQuit); + signal(SIGINT, &_sighandlerQuit); #ifdef ZT_EXTOSDEP int extosdepFd1 = -1; int extosdepFd2 = -1; - for(int i=1;i mfd) mfd = STDOUT_FILENO; - if (STDERR_FILENO > mfd) mfd = STDERR_FILENO; - for(int f=mfd+1;f<1024;++f) { + if (STDOUT_FILENO > mfd) + mfd = STDOUT_FILENO; + if (STDERR_FILENO > mfd) + mfd = STDERR_FILENO; + for (int f = mfd + 1; f < 1024; ++f) { #ifdef ZT_EXTOSDEP - if (f == extosdepFd1 || f == extosdepFd2) continue; -#endif // ZT_EXTOSDEP + if (f == extosdepFd1 || f == extosdepFd2) + continue; +#endif // ZT_EXTOSDEP ::close(f); } } bool runAsDaemon = false; -#endif // __UNIX_LIKE__ +#endif // __UNIX_LIKE__ #ifdef __WINDOWS__ { WSADATA wsaData; - WSAStartup(MAKEWORD(2,2),&wsaData); + WSAStartup(MAKEWORD(2, 2), &wsaData); } #ifdef ZT_WIN_RUN_IN_CONSOLE @@ -2154,130 +2159,137 @@ int main(int argc,char **argv) #else bool winRunFromCommandLine = false; #endif -#endif // __WINDOWS__ +#endif // __WINDOWS__ - if ((strstr(argv[0],"zerotier-idtool"))||(strstr(argv[0],"ZEROTIER-IDTOOL"))) - return idtool(argc,argv); - if ((strstr(argv[0],"zerotier-cli"))||(strstr(argv[0],"ZEROTIER-CLI"))) - return cli(argc,argv); + if ((strstr(argv[0], "zerotier-idtool")) || (strstr(argv[0], "ZEROTIER-IDTOOL"))) + return idtool(argc, argv); + if ((strstr(argv[0], "zerotier-cli")) || (strstr(argv[0], "ZEROTIER-CLI"))) + return cli(argc, argv); std::string homeDir; unsigned int port = ZT_DEFAULT_PORT; bool skipRootCheck = false; - for(int i=1;i 0xffff) { - printHelp(argv[0],stdout); + printHelp(argv[0], stdout); return 1; } break; #ifdef __UNIX_LIKE__ - case 'd': // Run in background as daemon + case 'd': // Run in background as daemon runAsDaemon = true; break; -#endif // __UNIX_LIKE__ +#endif // __UNIX_LIKE__ case 'U': skipRootCheck = true; break; - case 'v': // Display version - printf("%d.%d.%d" ZT_EOL_S,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); + case 'v': // Display version + printf("%d.%d.%d" ZT_EOL_S, ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION); return 0; - case 'i': // Invoke idtool personality + case 'i': // Invoke idtool personality if (argv[i][2]) { - printHelp(argv[0],stdout); + printHelp(argv[0], stdout); return 0; - } else return idtool(argc-1,argv+1); + } + else + return idtool(argc - 1, argv + 1); - case 'q': // Invoke cli personality + case 'q': // Invoke cli personality if (argv[i][2]) { - printHelp(argv[0],stdout); + printHelp(argv[0], stdout); return 0; - } else return cli(argc,argv); + } + else + return cli(argc, argv); #ifdef __WINDOWS__ - case 'C': // Run from command line instead of as Windows service + case 'C': // Run from command line instead of as Windows service winRunFromCommandLine = true; break; - case 'I': { // Install this binary as a Windows service - if (IsCurrentUserLocalAdministrator() != TRUE) { - fprintf(stderr,"%s: must be run as a local administrator." ZT_EOL_S,argv[0]); - return 1; - } - std::string ret(InstallService(ZT_SERVICE_NAME,ZT_SERVICE_DISPLAY_NAME,ZT_SERVICE_START_TYPE,ZT_SERVICE_DEPENDENCIES,ZT_SERVICE_ACCOUNT,ZT_SERVICE_PASSWORD)); - if (ret.length()) { - fprintf(stderr,"%s: unable to install service: %s" ZT_EOL_S,argv[0],ret.c_str()); - return 3; - } - return 0; - } break; + case 'I': { // Install this binary as a Windows service + if (IsCurrentUserLocalAdministrator() != TRUE) { + fprintf(stderr, "%s: must be run as a local administrator." ZT_EOL_S, argv[0]); + return 1; + } + std::string ret(InstallService(ZT_SERVICE_NAME, ZT_SERVICE_DISPLAY_NAME, ZT_SERVICE_START_TYPE, ZT_SERVICE_DEPENDENCIES, ZT_SERVICE_ACCOUNT, ZT_SERVICE_PASSWORD)); + if (ret.length()) { + fprintf(stderr, "%s: unable to install service: %s" ZT_EOL_S, argv[0], ret.c_str()); + return 3; + } + return 0; + } break; - case 'R': { // Uninstall this binary as Windows service - if (IsCurrentUserLocalAdministrator() != TRUE) { - fprintf(stderr,"%s: must be run as a local administrator." ZT_EOL_S,argv[0]); - return 1; - } - std::string ret(UninstallService(ZT_SERVICE_NAME)); - if (ret.length()) { - fprintf(stderr,"%s: unable to uninstall service: %s" ZT_EOL_S,argv[0],ret.c_str()); - return 3; - } - return 0; - } break; + case 'R': { // Uninstall this binary as Windows service + if (IsCurrentUserLocalAdministrator() != TRUE) { + fprintf(stderr, "%s: must be run as a local administrator." ZT_EOL_S, argv[0]); + return 1; + } + std::string ret(UninstallService(ZT_SERVICE_NAME)); + if (ret.length()) { + fprintf(stderr, "%s: unable to uninstall service: %s" ZT_EOL_S, argv[0], ret.c_str()); + return 3; + } + return 0; + } break; case 'D': { - std::string err = WindowsEthernetTap::destroyAllPersistentTapDevices(); - if (err.length() > 0) { - fprintf(stderr,"%s: unable to uninstall one or more persistent tap devices: %s" ZT_EOL_S,argv[0],err.c_str()); - return 3; - } - return 0; - } break; -#endif // __WINDOWS__ + std::string err = WindowsEthernetTap::destroyAllPersistentTapDevices(); + if (err.length() > 0) { + fprintf(stderr, "%s: unable to uninstall one or more persistent tap devices: %s" ZT_EOL_S, argv[0], err.c_str()); + return 3; + } + return 0; + } break; +#endif // __WINDOWS__ #ifdef ZT_EXTOSDEP - case 'x': break; + case 'x': + break; #endif case 'h': case '?': default: - printHelp(argv[0],stdout); + printHelp(argv[0], stdout); return 0; } - } else { + } + else { if (homeDir.length()) { - printHelp(argv[0],stdout); + printHelp(argv[0], stdout); return 0; - } else { + } + else { homeDir = argv[i]; } } } - if (!homeDir.length()) + if (! homeDir.length()) homeDir = OneService::platformDefaultHomePath(); - if (!homeDir.length()) { - fprintf(stderr,"%s: no home path specified and no platform default available" ZT_EOL_S,argv[0]); + if (! homeDir.length()) { + fprintf(stderr, "%s: no home path specified and no platform default available" ZT_EOL_S, argv[0]); return 1; - } else { - std::vector hpsp(OSUtils::split(homeDir.c_str(),ZT_PATH_SEPARATOR_S,"","")); + } + else { + std::vector hpsp(OSUtils::split(homeDir.c_str(), ZT_PATH_SEPARATOR_S, "", "")); std::string ptmp; if (homeDir[0] == ZT_PATH_SEPARATOR) ptmp.push_back(ZT_PATH_SEPARATOR); - for(std::vector::iterator pi(hpsp.begin());pi!=hpsp.end();++pi) { + for (std::vector::iterator pi(hpsp.begin()); pi != hpsp.end(); ++pi) { if (ptmp.length() > 0) ptmp.push_back(ZT_PATH_SEPARATOR); ptmp.append(*pi); - if ((*pi != ".")&&(*pi != "..")) { - if (!OSUtils::mkdir(ptmp)) + if ((*pi != ".") && (*pi != "..")) { + if (! OSUtils::mkdir(ptmp)) throw std::runtime_error("home path does not exist, and could not create. Please verify local system permissions."); } } @@ -2305,28 +2317,29 @@ int main(int argc,char **argv) } // This can be removed once the new controller code has been around for many versions - if (OSUtils::fileExists((homeDir + ZT_PATH_SEPARATOR_S + "controller.db").c_str(),true)) { - fprintf(stderr,"%s: FATAL: an old controller.db exists in %s -- see instructions in controller/README.md for how to migrate!" ZT_EOL_S,argv[0],homeDir.c_str()); + if (OSUtils::fileExists((homeDir + ZT_PATH_SEPARATOR_S + "controller.db").c_str(), true)) { + fprintf(stderr, "%s: FATAL: an old controller.db exists in %s -- see instructions in controller/README.md for how to migrate!" ZT_EOL_S, argv[0], homeDir.c_str()); return 1; } #ifdef __UNIX_LIKE__ #ifndef ZT_ONE_NO_ROOT_CHECK - if ((!skipRootCheck)&&(getuid() != 0)) { - fprintf(stderr,"%s: must be run as root (uid 0)" ZT_EOL_S,argv[0]); + if ((! skipRootCheck) && (getuid() != 0)) { + fprintf(stderr, "%s: must be run as root (uid 0)" ZT_EOL_S, argv[0]); return 1; } -#endif // !ZT_ONE_NO_ROOT_CHECK +#endif // !ZT_ONE_NO_ROOT_CHECK if (runAsDaemon) { long p = (long)fork(); if (p < 0) { - fprintf(stderr,"%s: could not fork" ZT_EOL_S,argv[0]); + fprintf(stderr, "%s: could not fork" ZT_EOL_S, argv[0]); return 1; - } else if (p > 0) - return 0; // forked - // else p == 0, so we are daemonized + } + else if (p > 0) + return 0; // forked + // else p == 0, so we are daemonized } -#endif // __UNIX_LIKE__ +#endif // __UNIX_LIKE__ #ifdef __WINDOWS__ // Uninstall legacy tap devices. New devices will automatically be installed and configured @@ -2336,44 +2349,47 @@ int main(int argc,char **argv) if (winRunFromCommandLine) { // Running in "interactive" mode (mostly for debugging) if (IsCurrentUserLocalAdministrator() != TRUE) { - if (!skipRootCheck) { - fprintf(stderr,"%s: must be run as a local administrator." ZT_EOL_S,argv[0]); + if (! skipRootCheck) { + fprintf(stderr, "%s: must be run as a local administrator." ZT_EOL_S, argv[0]); return 1; } - } else { + } + else { _winPokeAHole(); } - SetConsoleCtrlHandler(&_winConsoleCtrlHandler,TRUE); + SetConsoleCtrlHandler(&_winConsoleCtrlHandler, TRUE); // continues on to ordinary command line execution code below... - } else { + } + else { // Running from service manager _winPokeAHole(); ZeroTierOneService zt1WindowsService; if (CServiceBase::Run(zt1WindowsService) == TRUE) { return 0; - } else { - fprintf(stderr,"%s: unable to start service (try -h for help)" ZT_EOL_S,argv[0]); + } + else { + fprintf(stderr, "%s: unable to start service (try -h for help)" ZT_EOL_S, argv[0]); return 1; } } -#endif // __WINDOWS__ +#endif // __WINDOWS__ #ifdef __UNIX_LIKE__ #ifdef ZT_HAVE_DROP_PRIVILEGES - if (!skipRootCheck) - dropPrivileges(argv[0],homeDir); + if (! skipRootCheck) + dropPrivileges(argv[0], homeDir); #endif std::string pidPath(homeDir + ZT_PATH_SEPARATOR_S + ZT_PID_PATH); { // Write .pid file to home folder - FILE *pf = fopen(pidPath.c_str(),"w"); + FILE* pf = fopen(pidPath.c_str(), "w"); if (pf) { - fprintf(pf,"%ld",(long)getpid()); + fprintf(pf, "%ld", (long)getpid()); fclose(pf); } } -#endif // __UNIX_LIKE__ +#endif // __UNIX_LIKE__ #ifdef ZT_EXTOSDEP if (extosdepFd1 < 0) { @@ -2384,9 +2400,9 @@ int main(int argc,char **argv) ExtOsdep::init(extosdepFd1, extosdepFd2); #endif - _OneServiceRunner thr(argv[0],homeDir,port); + _OneServiceRunner thr(argv[0], homeDir, port); thr.threadMain(); - //Thread::join(Thread::start(&thr)); + // Thread::join(Thread::start(&thr)); #ifdef __UNIX_LIKE__ OSUtils::rm(pidPath.c_str()); diff --git a/osdep/Arp.cpp b/osdep/Arp.cpp index 8b307eb58..a54b79a17 100644 --- a/osdep/Arp.cpp +++ b/osdep/Arp.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Arp.hpp" diff --git a/osdep/Arp.hpp b/osdep/Arp.hpp index 51257ef5e..01bcf7ad5 100644 --- a/osdep/Arp.hpp +++ b/osdep/Arp.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_ARP_HPP #define ZT_ARP_HPP diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp index e1e0d42e5..36e70ca7c 100644 --- a/osdep/BSDEthernetTap.cpp +++ b/osdep/BSDEthernetTap.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "BSDEthernetTap.hpp" diff --git a/osdep/BSDEthernetTap.hpp b/osdep/BSDEthernetTap.hpp index 1f382ba7e..190f3a0b4 100644 --- a/osdep/BSDEthernetTap.hpp +++ b/osdep/BSDEthernetTap.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_BSDETHERNETTAP_HPP #define ZT_BSDETHERNETTAP_HPP diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index 6bb6a0890..7034d950a 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_BINDER_HPP #define ZT_BINDER_HPP @@ -470,6 +465,7 @@ class Binder { if (_bindingCount < ZT_BINDER_MAX_BINDINGS) { _bindings[_bindingCount].udpSock = udps; _bindings[_bindingCount].address = ii->first; + memset(_bindings[_bindingCount].ifname, 0x0, sizeof(_bindings[_bindingCount].ifname)); memcpy(_bindings[_bindingCount].ifname, (char*)ii->second.c_str(), (int)ii->second.length()); ++_bindingCount; } diff --git a/osdep/BlockingQueue.hpp b/osdep/BlockingQueue.hpp index f377aa0bf..785e5bcaf 100644 --- a/osdep/BlockingQueue.hpp +++ b/osdep/BlockingQueue.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_BLOCKINGQUEUE_HPP #define ZT_BLOCKINGQUEUE_HPP diff --git a/osdep/EthernetTap.cpp b/osdep/EthernetTap.cpp index 128ce0cfe..1d35e01dc 100644 --- a/osdep/EthernetTap.cpp +++ b/osdep/EthernetTap.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "EthernetTap.hpp" @@ -20,9 +15,9 @@ #ifdef ZT_SDK -#include "../controller/EmbeddedNetworkController.hpp" #include "../include/VirtualTap.hpp" #include "../node/Node.hpp" +#include "../nonfree/controller/EmbeddedNetworkController.hpp" #else diff --git a/osdep/EthernetTap.hpp b/osdep/EthernetTap.hpp index aaabfeb60..d213e088d 100644 --- a/osdep/EthernetTap.hpp +++ b/osdep/EthernetTap.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_ETHERNETTAP_HPP #define ZT_ETHERNETTAP_HPP diff --git a/osdep/ExtOsdep.cpp b/osdep/ExtOsdep.cpp index 7bd0001e8..7af42e4f5 100644 --- a/osdep/ExtOsdep.cpp +++ b/osdep/ExtOsdep.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "ExtOsdep.hpp" diff --git a/osdep/ExtOsdep.hpp b/osdep/ExtOsdep.hpp index f16893ced..d7028902c 100644 --- a/osdep/ExtOsdep.hpp +++ b/osdep/ExtOsdep.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_EXTOSDEP_HPP #define ZT_EXTOSDEP_HPP diff --git a/osdep/Http.cpp b/osdep/Http.cpp index 4b7879e82..c3e07e915 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "Http.hpp" diff --git a/osdep/Http.hpp b/osdep/Http.hpp index 2e4783226..da21d03a0 100644 --- a/osdep/Http.hpp +++ b/osdep/Http.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_HTTP_HPP #define ZT_HTTP_HPP diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 5fe37216d..efaa72959 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wrestrict" diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index fe8079360..c5e593c00 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_LINUXETHERNETTAP_HPP #define ZT_LINUXETHERNETTAP_HPP diff --git a/osdep/LinuxNetLink.cpp b/osdep/LinuxNetLink.cpp index 5e7ee5a1d..02c38c09a 100644 --- a/osdep/LinuxNetLink.cpp +++ b/osdep/LinuxNetLink.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "../node/Constants.hpp" diff --git a/osdep/LinuxNetLink.hpp b/osdep/LinuxNetLink.hpp index 6f99130ae..b5a9c38f6 100644 --- a/osdep/LinuxNetLink.hpp +++ b/osdep/LinuxNetLink.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_LINUX_NETLINK_HPP #define ZT_LINUX_NETLINK_HPP @@ -160,4 +155,4 @@ class LinuxNetLink { #endif -#endif // ZT_LINUX_NETLINK_HPPS \ No newline at end of file +#endif // ZT_LINUX_NETLINK_HPPS diff --git a/osdep/MacDNSHelper.hpp b/osdep/MacDNSHelper.hpp index 69ea58d3b..fc457eafd 100644 --- a/osdep/MacDNSHelper.hpp +++ b/osdep/MacDNSHelper.hpp @@ -1,3 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ + */ + #ifndef MAC_DNS_HELPER #define MAC_DNS_HELPER diff --git a/osdep/MacDNSHelper.mm b/osdep/MacDNSHelper.mm index 5e170e172..973e51c45 100644 --- a/osdep/MacDNSHelper.mm +++ b/osdep/MacDNSHelper.mm @@ -1,3 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ + */ + #include "MacDNSHelper.hpp" #include @@ -45,7 +53,7 @@ void MacDNSHelper::setDNS(uint64_t nwid, const char *domain, const std::vectorifa_name; args[2] = "destroy"; args[3] = (char*)0; - const pid_t pid = vfork(); + const pid_t pid = fork(); if (pid == 0) { execv(args[0], const_cast(args)); _exit(-1); @@ -260,7 +255,7 @@ MacEthernetTap::~MacEthernetTap() args[1] = _dev.c_str(); args[2] = "destroy"; args[3] = (char*)0; - pid0 = vfork(); + pid0 = fork(); if (pid0 == 0) { execv(args[0], const_cast(args)); _exit(-1); @@ -271,7 +266,7 @@ MacEthernetTap::~MacEthernetTap() args[1] = tmp; // args[2] = "destroy"; // args[3] = (char *)0; - pid1 = vfork(); + pid1 = fork(); if (pid1 == 0) { execv(args[0], const_cast(args)); _exit(-1); diff --git a/osdep/MacEthernetTap.hpp b/osdep/MacEthernetTap.hpp index ac774360c..fb3831f28 100644 --- a/osdep/MacEthernetTap.hpp +++ b/osdep/MacEthernetTap.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_OSXETHERNETTAP_HPP #define ZT_OSXETHERNETTAP_HPP diff --git a/osdep/MacEthernetTapAgent.c b/osdep/MacEthernetTapAgent.c index e74c66940..91248f268 100644 --- a/osdep/MacEthernetTapAgent.c +++ b/osdep/MacEthernetTapAgent.c @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ /* * This creates a pair of feth devices with the lower numbered device diff --git a/osdep/MacEthernetTapAgent.h b/osdep/MacEthernetTapAgent.h index da6e34195..79fdfd07f 100644 --- a/osdep/MacEthernetTapAgent.h +++ b/osdep/MacEthernetTapAgent.h @@ -1,27 +1,22 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_MACETHERNETTAPAGENT_H #define ZT_MACETHERNETTAPAGENT_H -#define ZT_MACETHERNETTAPAGENT_EXIT_CODE_SUCCESS 0 -#define ZT_MACETHERNETTAPAGENT_EXIT_CODE_INVALID_REQUEST -1 +#define ZT_MACETHERNETTAPAGENT_EXIT_CODE_SUCCESS 0 +#define ZT_MACETHERNETTAPAGENT_EXIT_CODE_INVALID_REQUEST -1 #define ZT_MACETHERNETTAPAGENT_EXIT_CODE_UNABLE_TO_CREATE -2 -#define ZT_MACETHERNETTAPAGENT_EXIT_CODE_READ_ERROR -3 +#define ZT_MACETHERNETTAPAGENT_EXIT_CODE_READ_ERROR -3 -#define ZT_MACETHERNETTAPAGENT_STDIN_CMD_PACKET 0 +#define ZT_MACETHERNETTAPAGENT_STDIN_CMD_PACKET 0 #define ZT_MACETHERNETTAPAGENT_STDIN_CMD_IFCONFIG 1 -#define ZT_MACETHERNETTAPAGENT_STDIN_CMD_EXIT 2 +#define ZT_MACETHERNETTAPAGENT_STDIN_CMD_EXIT 2 #define ZT_MACETHERNETTAPAGENT_DEFAULT_SYSTEM_PATH "/Library/Application Support/ZeroTier/One/MacEthernetTapAgent" diff --git a/osdep/MacKextEthernetTap.cpp b/osdep/MacKextEthernetTap.cpp index b7fa97947..707858fd9 100644 --- a/osdep/MacKextEthernetTap.cpp +++ b/osdep/MacKextEthernetTap.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "MacDNSHelper.hpp" @@ -459,7 +454,7 @@ MacKextEthernetTap::~MacKextEthernetTap() globalTapsRunning = 0; // sanity check -- should not be possible char tmp[16384]; - sprintf(tmp, "%s/%s", _homePath.c_str(), "tap.kext"); + snprintf(tmp, sizeof(tmp), "%s/%s", _homePath.c_str(), "tap.kext"); long kextpid = (long)fork(); if (kextpid == 0) { OSUtils::redirectUnixOutputs("/dev/null", (const char*)0); diff --git a/osdep/MacKextEthernetTap.hpp b/osdep/MacKextEthernetTap.hpp index aac51c32f..f759d50e9 100644 --- a/osdep/MacKextEthernetTap.hpp +++ b/osdep/MacKextEthernetTap.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_MacKextEthernetTap_HPP #define ZT_MacKextEthernetTap_HPP diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index 9d0245565..6a605b856 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "../node/Constants.hpp" #include "../osdep/OSUtils.hpp" diff --git a/osdep/ManagedRoute.hpp b/osdep/ManagedRoute.hpp index e30be8263..3b4e8464e 100644 --- a/osdep/ManagedRoute.hpp +++ b/osdep/ManagedRoute.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_MANAGEDROUTE_HPP #define ZT_MANAGEDROUTE_HPP diff --git a/osdep/NeighborDiscovery.cpp b/osdep/NeighborDiscovery.cpp index dd2114a3d..ea0b89dc9 100644 --- a/osdep/NeighborDiscovery.cpp +++ b/osdep/NeighborDiscovery.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "NeighborDiscovery.hpp" diff --git a/osdep/NeighborDiscovery.hpp b/osdep/NeighborDiscovery.hpp index fe5d790b0..1d82bb9de 100644 --- a/osdep/NeighborDiscovery.hpp +++ b/osdep/NeighborDiscovery.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_NEIGHBORDISCOVERY_HPP #define ZT_NEIGHBORDISCOVERY_HPP diff --git a/osdep/NetBSDEthernetTap.cpp b/osdep/NetBSDEthernetTap.cpp index 0508246b0..666a387f6 100644 --- a/osdep/NetBSDEthernetTap.cpp +++ b/osdep/NetBSDEthernetTap.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "NetBSDEthernetTap.hpp" diff --git a/osdep/NetBSDEthernetTap.hpp b/osdep/NetBSDEthernetTap.hpp index b505cb504..2502eaa0d 100644 --- a/osdep/NetBSDEthernetTap.hpp +++ b/osdep/NetBSDEthernetTap.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_NetBSDEthernetTap_HPP #define ZT_NetBSDEthernetTap_HPP diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 41d144f1b..2fee8f194 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "../node/Constants.hpp" #include "../node/Utils.hpp" diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index c105612f7..b122a0c94 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_OSUTILS_HPP #define ZT_OSUTILS_HPP diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index 5b1a5fed9..11cbe4c05 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_PHY_HPP #define ZT_PHY_HPP diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp index 1b5af9fd9..3585c330a 100644 --- a/osdep/PortMapper.cpp +++ b/osdep/PortMapper.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifdef ZT_USE_MINIUPNPC diff --git a/osdep/PortMapper.hpp b/osdep/PortMapper.hpp index e65064772..34931244e 100644 --- a/osdep/PortMapper.hpp +++ b/osdep/PortMapper.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifdef ZT_USE_MINIUPNPC diff --git a/osdep/Thread.hpp b/osdep/Thread.hpp index abebd4374..46c08f481 100644 --- a/osdep/Thread.hpp +++ b/osdep/Thread.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_THREAD_HPP #define ZT_THREAD_HPP diff --git a/osdep/WinDNSHelper.cpp b/osdep/WinDNSHelper.cpp index 88b39e56d..bde52d20b 100644 --- a/osdep/WinDNSHelper.cpp +++ b/osdep/WinDNSHelper.cpp @@ -1,3 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ + */ + #include "WinDNSHelper.hpp" #include @@ -304,4 +312,4 @@ void WinDNSHelper::removeDNS(uint64_t nwid) } } -} // namespace ZeroTier \ No newline at end of file +} // namespace ZeroTier diff --git a/osdep/WinDNSHelper.hpp b/osdep/WinDNSHelper.hpp index 8a9916da1..14ca8171e 100644 --- a/osdep/WinDNSHelper.hpp +++ b/osdep/WinDNSHelper.hpp @@ -1,3 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ + */ + #ifndef WIN_DNS_HELPER_H_ #define WIN_DNS_HELPER_H_ @@ -19,4 +27,4 @@ class WinDNSHelper { } // namespace ZeroTier -#endif \ No newline at end of file +#endif diff --git a/osdep/WinFWHelper.cpp b/osdep/WinFWHelper.cpp index 5f657d60b..e52e5ad43 100644 --- a/osdep/WinFWHelper.cpp +++ b/osdep/WinFWHelper.cpp @@ -1,3 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ + */ + #include "WinFWHelper.hpp" namespace ZeroTier { @@ -154,4 +162,4 @@ void WinFWHelper::_run(std::string cmd) } } -} // namespace ZeroTier \ No newline at end of file +} // namespace ZeroTier diff --git a/osdep/WinFWHelper.hpp b/osdep/WinFWHelper.hpp index 43c41e47e..2e8e8ef79 100644 --- a/osdep/WinFWHelper.hpp +++ b/osdep/WinFWHelper.hpp @@ -1,3 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ + */ + #ifndef WIN_FW_HELPER_H_ #define WIN_FW_HELPER_H_ @@ -27,4 +35,4 @@ class WinFWHelper { } // namespace ZeroTier -#endif \ No newline at end of file +#endif diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index 3043868ae..546af9d54 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "WindowsEthernetTap.hpp" diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index fded64bc1..293457f96 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/osdep/WindowsEthernetTap.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_WINDOWSETHERNETTAP_HPP #define ZT_WINDOWSETHERNETTAP_HPP diff --git a/rule-compiler/rule-compiler.js b/rule-compiler/rule-compiler.js index 81bd5e06c..937fb958c 100644 --- a/rule-compiler/rule-compiler.js +++ b/rule-compiler/rule-compiler.js @@ -1,917 +1,1154 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ -'use strict'; +"use strict"; // Names for bits in characteristics -- 0==LSB, 63==MSB const CHARACTERISTIC_BITS = { - 'inbound': 63, - 'multicast': 62, - 'broadcast': 61, - 'ipauth': 60, - 'macauth': 59, - 'tcp_fin': 0, - 'tcp_syn': 1, - 'tcp_rst': 2, - 'tcp_psh': 3, - 'tcp_ack': 4, - 'tcp_urg': 5, - 'tcp_ece': 6, - 'tcp_cwr': 7, - 'tcp_ns': 8, - 'tcp_rs2': 9, - 'tcp_rs1': 10, - 'tcp_rs0': 11 + inbound: 63, + multicast: 62, + broadcast: 61, + ipauth: 60, + macauth: 59, + tcp_fin: 0, + tcp_syn: 1, + tcp_rst: 2, + tcp_psh: 3, + tcp_ack: 4, + tcp_urg: 5, + tcp_ece: 6, + tcp_cwr: 7, + tcp_ns: 8, + tcp_rs2: 9, + tcp_rs1: 10, + tcp_rs0: 11, }; // Shorthand names for common ethernet types const ETHERTYPES = { - 'ipv4': 0x0800, - 'arp': 0x0806, - 'wol': 0x0842, - 'rarp': 0x8035, - 'ipv6': 0x86dd, - 'atalk': 0x809b, - 'aarp': 0x80f3, - 'ipx_a': 0x8137, - 'ipx_b': 0x8138 + ipv4: 0x0800, + arp: 0x0806, + wol: 0x0842, + rarp: 0x8035, + ipv6: 0x86dd, + atalk: 0x809b, + aarp: 0x80f3, + ipx_a: 0x8137, + ipx_b: 0x8138, }; // Shorthand names for common IP protocols const IP_PROTOCOLS = { - 'icmp': 0x01, - 'icmp4': 0x01, - 'icmpv4': 0x01, - 'igmp': 0x02, - 'ipip': 0x04, - 'tcp': 0x06, - 'egp': 0x08, - 'igp': 0x09, - 'udp': 0x11, - 'rdp': 0x1b, - 'esp': 0x32, - 'ah': 0x33, - 'icmp6': 0x3a, - 'icmpv6': 0x3a, - 'l2tp': 0x73, - 'sctp': 0x84, - 'udplite': 0x88 + icmp: 0x01, + icmp4: 0x01, + icmpv4: 0x01, + igmp: 0x02, + ipip: 0x04, + tcp: 0x06, + egp: 0x08, + igp: 0x09, + udp: 0x11, + rdp: 0x1b, + esp: 0x32, + ah: 0x33, + icmp6: 0x3a, + icmpv6: 0x3a, + l2tp: 0x73, + sctp: 0x84, + udplite: 0x88, }; // Keywords that open new blocks that must be terminated by a semicolon const OPEN_BLOCK_KEYWORDS = { - 'macro': true, - 'tag': true, - 'cap': true, - 'drop': true, - 'accept': true, - 'tee': true, - 'watch': true, - 'redirect': true, - 'break': true, - 'priority': true + macro: true, + tag: true, + cap: true, + drop: true, + accept: true, + tee: true, + watch: true, + redirect: true, + break: true, + priority: true, }; // Reserved words that can't be used as tag, capability, or rule set names const RESERVED_WORDS = { - 'macro': true, - 'tag': true, - 'cap': true, - 'default': true, + macro: true, + tag: true, + cap: true, + default: true, - 'drop': true, - 'accept': true, - 'tee': true, - 'watch': true, - 'redirect': true, - 'break': true, - 'priority': true, + drop: true, + accept: true, + tee: true, + watch: true, + redirect: true, + break: true, + priority: true, - 'ztsrc': true, - 'ztdest': true, - 'vlan': true, - 'vlanpcp': true, - 'vlandei': true, - 'ethertype': true, - 'macsrc': true, - 'macdest': true, - 'ipsrc': true, - 'ipdest': true, - 'iptos': true, - 'ipprotocol': true, - 'icmp': true, - 'sport': true, - 'dport': true, - 'chr': true, - 'framesize': true, - 'random': true, - 'tand': true, - 'tor': true, - 'txor': true, - 'tdiff': true, - 'teq': true, - 'tseq': true, - 'treq': true, + ztsrc: true, + ztdest: true, + vlan: true, + vlanpcp: true, + vlandei: true, + ethertype: true, + macsrc: true, + macdest: true, + ipsrc: true, + ipdest: true, + iptos: true, + ipprotocol: true, + icmp: true, + sport: true, + dport: true, + chr: true, + framesize: true, + random: true, + tand: true, + tor: true, + txor: true, + tdiff: true, + teq: true, + tseq: true, + treq: true, - 'type': true, - 'enum': true, - 'class': true, - 'define': true, - 'import': true, - 'include': true, - 'log': true, - 'not': true, - 'xor': true, - 'or': true, - 'and': true, - 'set': true, - 'var': true, - 'let': true + type: true, + enum: true, + class: true, + define: true, + import: true, + include: true, + log: true, + not: true, + xor: true, + or: true, + and: true, + set: true, + var: true, + let: true, }; const KEYWORD_TO_API_MAP = { - 'drop': 'ACTION_DROP', - 'accept': 'ACTION_ACCEPT', - 'tee': 'ACTION_TEE', - 'watch': 'ACTION_WATCH', - 'redirect': 'ACTION_REDIRECT', - 'break': 'ACTION_BREAK', - 'priority': 'ACTION_PRIORITY', + drop: "ACTION_DROP", + accept: "ACTION_ACCEPT", + tee: "ACTION_TEE", + watch: "ACTION_WATCH", + redirect: "ACTION_REDIRECT", + break: "ACTION_BREAK", + priority: "ACTION_PRIORITY", - 'ztsrc': 'MATCH_SOURCE_ZEROTIER_ADDRESS', - 'ztdest': 'MATCH_DEST_ZEROTIER_ADDRESS', - 'vlan': 'MATCH_VLAN_ID', - 'vlanpcp': 'MATCH_VLAN_PCP', - 'vlandei': 'MATCH_VLAN_DEI', - 'ethertype': 'MATCH_ETHERTYPE', - 'macsrc': 'MATCH_MAC_SOURCE', - 'macdest': 'MATCH_MAC_DEST', - //'ipsrc': '', // special handling since we programmatically differentiate between V4 and V6 - //'ipdest': '', // special handling - 'iptos': 'MATCH_IP_TOS', - 'ipprotocol': 'MATCH_IP_PROTOCOL', - 'icmp': 'MATCH_ICMP', - 'sport': 'MATCH_IP_SOURCE_PORT_RANGE', - 'dport': 'MATCH_IP_DEST_PORT_RANGE', - 'chr': 'MATCH_CHARACTERISTICS', - 'framesize': 'MATCH_FRAME_SIZE_RANGE', - 'random': 'MATCH_RANDOM', - 'tand': 'MATCH_TAGS_BITWISE_AND', - 'tor': 'MATCH_TAGS_BITWISE_OR', - 'txor': 'MATCH_TAGS_BITWISE_XOR', - 'tdiff': 'MATCH_TAGS_DIFFERENCE', - 'teq': 'MATCH_TAGS_EQUAL', - 'tseq': 'MATCH_TAG_SENDER', - 'treq': 'MATCH_TAG_RECEIVER' + ztsrc: "MATCH_SOURCE_ZEROTIER_ADDRESS", + ztdest: "MATCH_DEST_ZEROTIER_ADDRESS", + vlan: "MATCH_VLAN_ID", + vlanpcp: "MATCH_VLAN_PCP", + vlandei: "MATCH_VLAN_DEI", + ethertype: "MATCH_ETHERTYPE", + macsrc: "MATCH_MAC_SOURCE", + macdest: "MATCH_MAC_DEST", + //'ipsrc': '', // special handling since we programmatically differentiate between V4 and V6 + //'ipdest': '', // special handling + iptos: "MATCH_IP_TOS", + ipprotocol: "MATCH_IP_PROTOCOL", + icmp: "MATCH_ICMP", + sport: "MATCH_IP_SOURCE_PORT_RANGE", + dport: "MATCH_IP_DEST_PORT_RANGE", + chr: "MATCH_CHARACTERISTICS", + framesize: "MATCH_FRAME_SIZE_RANGE", + random: "MATCH_RANDOM", + tand: "MATCH_TAGS_BITWISE_AND", + tor: "MATCH_TAGS_BITWISE_OR", + txor: "MATCH_TAGS_BITWISE_XOR", + tdiff: "MATCH_TAGS_DIFFERENCE", + teq: "MATCH_TAGS_EQUAL", + tseq: "MATCH_TAG_SENDER", + treq: "MATCH_TAG_RECEIVER", }; // Number of args for each match const MATCH_ARG_COUNTS = { - 'ztsrc': 1, - 'ztdest': 1, - 'vlan': 1, - 'vlanpcp': 1, - 'vlandei': 1, - 'ethertype': 1, - 'macsrc': 1, - 'macdest': 1, - 'ipsrc': 1, - 'ipdest': 1, - 'iptos': 2, - 'ipprotocol': 1, - 'icmp': 2, - 'sport': 1, - 'dport': 1, - 'chr': 1, - 'framesize': 1, - 'random': 1, - 'tand': 2, - 'tor': 2, - 'txor': 2, - 'tdiff': 2, - 'teq': 2, - 'tseq': 2, - 'treq': 2 + ztsrc: 1, + ztdest: 1, + vlan: 1, + vlanpcp: 1, + vlandei: 1, + ethertype: 1, + macsrc: 1, + macdest: 1, + ipsrc: 1, + ipdest: 1, + iptos: 2, + ipprotocol: 1, + icmp: 2, + sport: 1, + dport: 1, + chr: 1, + framesize: 1, + random: 1, + tand: 2, + tor: 2, + txor: 2, + tdiff: 2, + teq: 2, + tseq: 2, + treq: 2, }; // Regex of all alphanumeric characters in Unicode -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]'); +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; - if ("0123456789".indexOf(n.charAt(0)) >= 0) return false; - for (let i = 0; i < n.length; ++i) { - let c = n.charAt(i); - if ((c !== '_') && (!INTL_ALPHANUM_REGEX.test(c))) return false; - } - return true; + 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) { + let c = n.charAt(i); + if (c !== "_" && !INTL_ALPHANUM_REGEX.test(c)) return false; + } + return true; } // Regexes for checking the basic syntactic validity of IP addresses -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])'); +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) { - try { - 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); - } catch (e) { - return -1; - } + try { + 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; + } catch (e) { + return -1; + } } function _cleanMac(m) { - m = m.toLowerCase(); - var m2 = ''; - let charcount = 0; - 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)) { - m2 += ':'; - charcount = 0; - } - } - } - return m2; + m = m.toLowerCase(); + var m2 = ""; + let charcount = 0; + 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) { + m2 += ":"; + charcount = 0; + } + } + } + return m2; } function _cleanHex(m) { - m = m.toLowerCase(); - var m2 = ''; - for (let i = 0; i < m.length; ++i) { - let c = m.charAt(i); - if ("0123456789abcdef".indexOf(c) >= 0) - m2 += c; - } - return m2; + m = m.toLowerCase(); + var m2 = ""; + for (let i = 0; i < m.length; ++i) { + let c = m.charAt(i); + if ("0123456789abcdef".indexOf(c) >= 0) m2 += c; + } + return m2; } function _renderMatches(mtree, rules, macros, caps, tags, params) { - let not = false; - let or = false; - 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 - continue; - } else if (match === 'not') { - not = true; - } else if (match === 'or') { - or = true; - } else { - 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) { - if (++k >= mtree.length) - 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 (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]]); - } else { - args.push(mtree[k]); - } - } + let not = false; + let or = false; + 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 + continue; + } else if (match === "not") { + not = true; + } else if (match === "or") { + or = true; + } else { + 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) { + if (++k >= mtree.length) + 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 (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]]); + } else { + args.push(mtree[k]); + } + } - 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.']; - rules.push({ - 'type': KEYWORD_TO_API_MAP[match], - 'not': not, - 'or': or, - 'zt': zt - }); - } break; + 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."]; + rules.push({ + type: KEYWORD_TO_API_MAP[match], + not: not, + or: or, + zt: zt, + }); + } + break; - case 'vlan': - case 'vlanpcp': - case 'vlandei': - case 'ethertype': - case 'ipprotocol': { - let num = null; - switch (match) { - case 'ethertype': num = ETHERTYPES[args[0][0]]; break; - case 'ipprotocol': num = IP_PROTOCOLS[args[0][0]]; break; - } - 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.']; - let r = { - 'type': KEYWORD_TO_API_MAP[match], - 'not': not, - 'or': or - }; - switch (match) { - case 'vlan': r['vlanId'] = num; break; - case 'vlanpcp': r['vlanPcp'] = num; break; - case 'vlandei': r['vlanDei'] = num; break; - case 'ethertype': r['etherType'] = num; break; - case 'ipprotocol': r['ipProtocol'] = num; break; - } - rules.push(r); - } break; + case "vlan": + case "vlanpcp": + case "vlandei": + case "ethertype": + case "ipprotocol": + { + let num = null; + switch (match) { + case "ethertype": + num = ETHERTYPES[args[0][0]]; + break; + case "ipprotocol": + num = IP_PROTOCOLS[args[0][0]]; + break; + } + 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."]; + let r = { + type: KEYWORD_TO_API_MAP[match], + not: not, + or: or, + }; + switch (match) { + case "vlan": + r["vlanId"] = num; + break; + case "vlanpcp": + r["vlanPcp"] = num; + break; + case "vlandei": + r["vlanDei"] = num; + break; + case "ethertype": + r["etherType"] = num; + break; + case "ipprotocol": + r["ipProtocol"] = num; + break; + } + rules.push(r); + } + break; - case 'random': { - let num = parseFloat(args[0][0]) || 0.0; - if (num < 0.0) num = 0.0; - if (num > 1.0) num = 1.0; - rules.push({ - 'type': KEYWORD_TO_API_MAP[match], - 'not': not, - 'or': or, - 'probability': Math.floor(4294967295 * num) - }); - } break; + case "random": + { + let num = parseFloat(args[0][0]) || 0.0; + if (num < 0.0) num = 0.0; + if (num > 1.0) num = 1.0; + rules.push({ + type: KEYWORD_TO_API_MAP[match], + not: not, + or: or, + probability: Math.floor(4294967295 * num), + }); + } + break; - case 'macsrc': - case 'macdest': { - let mac = _cleanMac(args[0][0]); - if (mac.length !== 17) - return [args[0][1], args[0][2], 'Invalid MAC address.']; - rules.push({ - 'type': KEYWORD_TO_API_MAP[match], - 'not': not, - 'or': or, - 'mac': mac - }); - } break; + case "macsrc": + case "macdest": + { + let mac = _cleanMac(args[0][0]); + if (mac.length !== 17) + return [args[0][1], args[0][2], "Invalid MAC address."]; + rules.push({ + type: KEYWORD_TO_API_MAP[match], + not: not, + or: or, + mac: mac, + }); + } + break; - case 'ipsrc': - case 'ipdest': { - 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); - if (IPV6_REGEX.test(ipOnly)) { - rules.push({ - 'type': ((match === 'ipsrc') ? 'MATCH_IPV6_SOURCE' : 'MATCH_IPV6_DEST'), - 'not': not, - 'or': or, - 'ip': ip - }); - } else if (IPV4_REGEX.test(ipOnly)) { - rules.push({ - 'type': ((match === 'ipsrc') ? 'MATCH_IPV4_SOURCE' : 'MATCH_IPV4_DEST'), - 'not': not, - 'or': or, - 'ip': ip - }); - } else { - return [args[0][1], args[0][2], 'Invalid IP address (not valid IPv4 or IPv6).']; - } - } break; + case "ipsrc": + case "ipdest": + { + 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); + if (IPV6_REGEX.test(ipOnly)) { + rules.push({ + type: + match === "ipsrc" ? "MATCH_IPV6_SOURCE" : "MATCH_IPV6_DEST", + not: not, + or: or, + ip: ip, + }); + } else if (IPV4_REGEX.test(ipOnly)) { + rules.push({ + type: + match === "ipsrc" ? "MATCH_IPV4_SOURCE" : "MATCH_IPV4_DEST", + not: not, + or: or, + ip: ip, + }); + } else { + 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.']; - 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).']; - rules.push({ - 'type': 'MATCH_ICMP', - 'not': not, - 'or': or, - 'icmpType': icmpType, - 'icmpCode': ((icmpCode < 0) ? null : icmpCode) - }); - } 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."]; + 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).", + ]; + rules.push({ + type: "MATCH_ICMP", + not: not, + or: or, + icmpType: icmpType, + icmpCode: icmpCode < 0 ? null : icmpCode, + }); + } + break; - case 'sport': - case 'dport': - case 'framesize': { - let arg = args[0][0]; - let fn = null; - let tn = null; - if (arg.indexOf('-') > 0) { - let asplit = arg.split('-'); - if (asplit.length !== 2) { - return [args[0][1], args[0][2], 'Invalid numeric range.']; - } else { - fn = _parseNum(asplit[0]); - tn = _parseNum(asplit[1]); - } - } else { - 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.']; - rules.push({ - 'type': KEYWORD_TO_API_MAP[match], - 'not': not, - 'or': or, - 'start': fn, - 'end': tn - }); - } break; + case "sport": + case "dport": + case "framesize": + { + let arg = args[0][0]; + let fn = null; + let tn = null; + if (arg.indexOf("-") > 0) { + let asplit = arg.split("-"); + if (asplit.length !== 2) { + return [args[0][1], args[0][2], "Invalid numeric range."]; + } else { + fn = _parseNum(asplit[0]); + tn = _parseNum(asplit[1]); + } + } else { + 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."]; + rules.push({ + type: KEYWORD_TO_API_MAP[match], + not: not, + or: or, + start: fn, + end: tn, + }); + } + break; - 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.']; - 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.']; - } else { - fn = _parseNum(asplit[0]); - tn = _parseNum(asplit[1]); - } - } else { - 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.']; - rules.push({ - 'type': 'MATCH_IP_TOS', - 'not': not, - 'or': or, - 'mask': mask, - 'start': fn, - 'end': tn - }); - } break; + 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."]; + 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."]; + } else { + fn = _parseNum(asplit[0]); + tn = _parseNum(asplit[1]); + } + } else { + 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."]; + rules.push({ + type: "MATCH_IP_TOS", + not: not, + or: or, + mask: mask, + start: fn, + end: tn, + }); + } + break; - case 'chr': { - let chrb = args[0][0].split(/[,]+/); - let maskhi = 0; - let masklo = 0; - 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 >= 32) - maskhi |= Math.abs(1 << (bit - 32)); - else masklo |= Math.abs(1 << bit); - } - } - maskhi = Math.abs(maskhi).toString(16); - while (maskhi.length < 8) maskhi = '0' + maskhi; - masklo = Math.abs(masklo).toString(16); - while (masklo.length < 8) masklo = '0' + masklo; - rules.push({ - 'type': 'MATCH_CHARACTERISTICS', - 'not': not, - 'or': or, - 'mask': (maskhi + masklo) - }); - } break; + case "chr": + { + let chrb = args[0][0].split(/[,]+/); + let maskhi = 0; + let masklo = 0; + 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 >= 32) maskhi |= Math.abs(1 << (bit - 32)); + else masklo |= Math.abs(1 << bit); + } + } + maskhi = Math.abs(maskhi).toString(16); + while (maskhi.length < 8) maskhi = "0" + maskhi; + masklo = Math.abs(masklo).toString(16); + while (masklo.length < 8) masklo = "0" + masklo; + rules.push({ + type: "MATCH_CHARACTERISTICS", + not: not, + or: or, + mask: maskhi + masklo, + }); + } + break; - case 'tand': - case 'tor': - case 'txor': - case 'tdiff': - case 'teq': - case 'tseq': - case 'treq': { - let tag = tags[args[0][0]]; - let tagId = -1; - let tagValue = -1; - if (tag) { - tagId = tag.id; - tagValue = args[1][0]; - if (tagValue in tag.flags) - tagValue = tag.flags[tagValue]; - else if (tagValue in tag.enums) - tagValue = tag.enums[tagValue]; - else tagValue = _parseNum(tagValue); - } else { - 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.']; - rules.push({ - 'type': KEYWORD_TO_API_MAP[match], - 'not': not, - 'or': or, - 'id': tagId, - 'value': tagValue - }); - } break; - } + case "tand": + case "tor": + case "txor": + case "tdiff": + case "teq": + case "tseq": + case "treq": + { + let tag = tags[args[0][0]]; + let tagId = -1; + let tagValue = -1; + if (tag) { + tagId = tag.id; + tagValue = args[1][0]; + if (tagValue in tag.flags) tagValue = tag.flags[tagValue]; + else if (tagValue in tag.enums) tagValue = tag.enums[tagValue]; + else tagValue = _parseNum(tagValue); + } else { + 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.", + ]; + rules.push({ + type: KEYWORD_TO_API_MAP[match], + not: not, + or: or, + id: tagId, + value: tagValue, + }); + } + break; + } - not = false; - or = false; - } - } - return null; + not = false; + or = false; + } + } + return null; } 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.']; - let macroName = rtree[k + 1][0]; - ++k; + 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.", + ]; + let macroName = rtree[k + 1][0]; + ++k; - let macroParamArray = []; - let parenIdx = macroName.indexOf('('); - if (parenIdx > 0) { - let pns = macroName.substr(parenIdx + 1).split(/[,)]+/); - for (let k = 0; k < pns.length; ++k) { - if (pns[k].length > 0) - macroParamArray.push(pns[k]); - } - macroName = macroName.substr(0, parenIdx); - } + let macroParamArray = []; + let parenIdx = macroName.indexOf("("); + if (parenIdx > 0) { + let pns = macroName.substr(parenIdx + 1).split(/[,)]+/); + for (let k = 0; k < pns.length; ++k) { + if (pns[k].length > 0) macroParamArray.push(pns[k]); + } + macroName = macroName.substr(0, parenIdx); + } - let macro = macros[macroName]; - if (!macro) - return [rtree[k][1], rtree[k][2], 'Macro name not found.']; - let macroParams = {}; - 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.']; - macroParams[param] = macroParamArray[pidx]; - } + let macro = macros[macroName]; + if (!macro) return [rtree[k][1], rtree[k][2], "Macro name not found."]; + let macroParams = {}; + 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.", + ]; + macroParams[param] = macroParamArray[pidx]; + } - 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]))) { - let mtree = rtree[k + 1]; ++k; - 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)) { - 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.']; - 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 (err !== null) - return err; - rules.push({ - 'type': KEYWORD_TO_API_MAP[action], - 'address': target, - '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).']; - } - } else if (action === 'redirect') { - 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 (err !== null) - return err; - rules.push({ - 'type': KEYWORD_TO_API_MAP[action], - 'address': target - }); - } else { - 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.']; - } - } + 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])) { + let mtree = rtree[k + 1]; + ++k; + 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 + ) { + 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.", + ]; + 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 (err !== null) return err; + rules.push({ + type: KEYWORD_TO_API_MAP[action], + address: target, + 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).", + ]; + } + } else if (action === "redirect") { + 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 (err !== null) return err; + rules.push({ + type: KEYWORD_TO_API_MAP[action], + address: target, + }); + } else { + 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 null; + return null; } function compile(src, rules, caps, tags) { - try { - if (typeof src !== 'string') - return [0, 0, '"src" parameter must be a string.']; + try { + if (typeof src !== "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. + // 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 skipRestOfLine = false; - 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')) { - skipRestOfLine = false; - ++lineNo; - lineIdx = 0; - } - } else { - switch (ch) { - case '\n': - ++lineNo; - lineIdx = 0; - case '\r': - case '\t': - case ' ': - if (curr[0].length > 0) { - let endOfBlock = false; - if (curr[0].charAt(curr[0].length - 1) === ';') { - endOfBlock = true; - curr[0] = curr[0].substr(0, curr[0].length - 1); - } + var blockStack = [[]]; + var curr = ["", -1, -1]; + var skipRestOfLine = false; + 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") { + skipRestOfLine = false; + ++lineNo; + lineIdx = 0; + } + } else { + switch (ch) { + case "\n": + ++lineNo; + lineIdx = 0; + case "\r": + case "\t": + case " ": + if (curr[0].length > 0) { + let endOfBlock = false; + if (curr[0].charAt(curr[0].length - 1) === ";") { + endOfBlock = true; + 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)) { - blockStack[blockStack.length - 2].push(blockStack[blockStack.length - 1]); - blockStack.pop(); - } else if (curr[0] in OPEN_BLOCK_KEYWORDS) { - blockStack.push([]); - } + if (curr[0].length > 0) { + blockStack[blockStack.length - 1].push(curr); + } + 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]; - } - break; - default: - if (curr[0].length === 0) { - if (ch === '#') { - skipRestOfLine = true; - continue; - } else { - curr[1] = lineNo; - curr[2] = lineIdx; - } - } - curr[0] += ch; - break; - } - } - } + curr = ["", -1, -1]; + } + break; + default: + if (curr[0].length === 0) { + if (ch === "#") { + skipRestOfLine = true; + continue; + } else { + curr[1] = lineNo; + curr[2] = lineIdx; + } + } + curr[0] += ch; + break; + } + } + } - if (curr[0].length > 0) { - if (curr[0].charAt(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)) { - blockStack[blockStack.length - 2].push(blockStack[blockStack.length - 1]); - blockStack.pop(); - } - var parsed = blockStack[0]; + if (curr[0].length > 0) { + if (curr[0].charAt(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 + ) { + blockStack[blockStack.length - 2].push(blockStack[blockStack.length - 1]); + blockStack.pop(); + } + var parsed = blockStack[0]; - // Pass 2: parse tree into capabilities, tags, rule sets, and document-level rules. + // Pass 2: parse tree into capabilities, tags, rule sets, and document-level rules. - let baseRuleTree = []; - let macros = {}; - 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 + let baseRuleTree = []; + let macros = {}; + 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.']; - let macro = parsed[++i]; - let macroName = macro[0][0].toLowerCase(); + 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(); - let params = {}; - let parenIdx = macroName.indexOf('('); - if (parenIdx > 0) { - let pns = macroName.substr(parenIdx + 1).split(/[,)]+/); - for (let k = 0; k < pns.length; ++k) { - if (pns[k].length > 0) - params[pns[k]] = k; - } - macroName = macroName.substr(0, parenIdx); - } + let params = {}; + let parenIdx = macroName.indexOf("("); + if (parenIdx > 0) { + let pns = macroName.substr(parenIdx + 1).split(/[,)]+/); + for (let k = 0; k < pns.length; ++k) { + if (pns[k].length > 0) params[pns[k]] = k; + } + macroName = macroName.substr(0, parenIdx); + } - if (!_isValidName(macroName)) - 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.']; + if (!_isValidName(macroName)) + 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."]; - if (macroName in macros) - return [macro[0][1], macro[0][2], 'Multiple definition of macro name.']; + if (macroName in macros) + return [ + macro[0][1], + macro[0][2], + "Multiple definition of macro name.", + ]; - macros[macroName] = { - params: params, - rules: macro.slice(1) - }; - } else if (keyword === 'tag') { - // Define tags + macros[macroName] = { + params: params, + rules: macro.slice(1), + }; + } 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.']; - let tag = parsed[++i]; - let tagName = tag[0][0].toLowerCase(); + 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.']; - if (tagName in RESERVED_WORDS) - return [tag[0][1], tag[0][2], 'Tag name is a reserved word.']; + if (!_isValidName(tagName)) + 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."]; - if (tagName in tags) - return [tag[0][1], tag[0][2], 'Multiple definition of tag name.']; + if (tagName in tags) + 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) { - let tkeyword = tag[k][0].toLowerCase(); - if (tkeyword === 'id') { - if (id >= 0) - 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.']; - id = _parseNum(tag[++k][0]); - 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.']; - if ((k + 1) >= tag.length) - 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.']; - ++k; - let bits = tag[k][0].split(/[,]+/); - let mask = 0; - 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.']; - mask |= (1 << b); - } - } - let flagName = tag[++k][0].toLowerCase(); - if (!_isValidName(flagName)) - 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.']; - 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.']; - ++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.']; - let enumName = tag[++k][0].toLowerCase(); - if (!_isValidName(enumName)) - 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.']; - enums[enumName] = value; - } else { - 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.']; + let flags = {}; + let enums = {}; + let id = -1; + let dfl = null; + 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."]; + if (k + 1 >= tag.length) + 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."]; + } else if (tkeyword === "default") { + if (dfl !== null) + 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."]; + 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.", + ]; + ++k; + let bits = tag[k][0].split(/[,]+/); + let mask = 0; + 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.", + ]; + mask |= 1 << b; + } + } + let flagName = tag[++k][0].toLowerCase(); + if (!_isValidName(flagName)) + 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.", + ]; + 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."]; + ++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.", + ]; + let enumName = tag[++k][0].toLowerCase(); + if (!_isValidName(enumName)) + 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.", + ]; + enums[enumName] = value; + } else { + 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.", + ]; - if (typeof dfl === 'string') { - let dfl2 = enums[dfl]; - if (typeof dfl2 === 'number') { - dfl = dfl2; - } else { - dfl2 = flags[dfl]; - if (typeof dfl2 === 'number') { - dfl = dfl2; - } else { - dfl = Math.abs(parseInt(dfl) || 0) & 0xffffffff; - } - } - } else if (typeof dfl === 'number') { - dfl = Math.abs(dfl) & 0xffffffff; - } + if (typeof dfl === "string") { + let dfl2 = enums[dfl]; + if (typeof dfl2 === "number") { + dfl = dfl2; + } else { + dfl2 = flags[dfl]; + if (typeof dfl2 === "number") { + dfl = dfl2; + } else { + dfl = Math.abs(parseInt(dfl) || 0) & 0xffffffff; + } + } + } else if (typeof dfl === "number") { + dfl = Math.abs(dfl) & 0xffffffff; + } - tags[tagName] = { - 'id': id, - 'default': dfl, - 'enums': enums, - 'flags': flags - }; - } else if (keyword === 'cap') { - // Define capabilities + tags[tagName] = { + id: id, + default: dfl, + enums: enums, + flags: flags, + }; + } 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.']; - let cap = parsed[++i]; - let capName = cap[0][0].toLowerCase(); + 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.']; - if (capName in RESERVED_WORDS) - return [cap[0][1], cap[0][2], 'Capability name is a reserved word.']; + if (!_isValidName(capName)) + 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."]; - if (capName in caps) - return [cap[0][1], cap[0][2], 'Multiple definition of capability name.']; + if (capName in caps) + 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) { - 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.']; - if ((k + 1) >= cap.length) - 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 (caps[cn].id === id) - return [cap[k - 1][1], cap[k - 1][2], 'Duplicate capability ID.']; - } - } else if (dn === 'default') { - dfl = true; - } else { - capRules.push(cap[k]); - } - } - if (id < 0) - return [cap[0][1], cap[0][2], 'Capability definition is missing a numeric ID.']; + let capRules = []; + let id = -1; + let dfl = false; + 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.", + ]; + if (k + 1 >= cap.length) + 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 (caps[cn].id === id) + return [ + cap[k - 1][1], + cap[k - 1][2], + "Duplicate capability ID.", + ]; + } + } else if (dn === "default") { + dfl = true; + } else { + capRules.push(cap[k]); + } + } + if (id < 0) + return [ + cap[0][1], + cap[0][2], + "Capability definition is missing a numeric ID.", + ]; - caps[capName] = { - 'id': id, - 'default': dfl, - 'rules': capRules - }; - } else { - baseRuleTree.push(parsed[i]); - } - } + caps[capName] = { + id: id, + default: dfl, + rules: capRules, + }; + } else { + baseRuleTree.push(parsed[i]); + } + } - // Pass 3: render low-level ZeroTier rules arrays for capabilities and base. + // Pass 3: render low-level ZeroTier rules arrays for capabilities and base. - for (let capName in caps) { - let r = []; - let err = _renderActions(caps[capName].rules, r, macros, caps, tags, {}); - if (err !== null) - return err; - caps[capName].rules = r; - } + for (let capName in caps) { + let r = []; + 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, {}); - if (err !== null) - return err; + 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 null; + } catch (e) { + console.log(e.stack); + return [0, 0, "Unexpected exception: " + e.toString()]; + } } exports.compile = compile; diff --git a/rustybits/Cargo.lock b/rustybits/Cargo.lock index a4da1e15e..2590fff4a 100644 --- a/rustybits/Cargo.lock +++ b/rustybits/Cargo.lock @@ -99,15 +99,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", @@ -235,9 +235,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" [[package]] name = "block-buffer" @@ -263,7 +263,7 @@ dependencies = [ "home", "http 1.3.1", "http-body-util", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-named-pipe", "hyper-rustls", "hyper-util", @@ -279,7 +279,7 @@ dependencies = [ "serde_json", "serde_repr", "serde_urlencoded", - "thiserror 2.0.12", + "thiserror 2.0.16", "tokio", "tokio-util", "tower-service", @@ -337,18 +337,18 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.29" +version = "1.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" dependencies = [ "shlex", ] [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "chrono" @@ -487,9 +487,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.2.0" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373b7c5dbd637569a2cca66e8d66b8c446a1e7bf064ea321d265d7b3dfe7c97e" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", @@ -676,9 +676,9 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "dyn-clone" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "ecdsa" @@ -841,9 +841,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.3.0" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" @@ -892,9 +892,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -1022,6 +1022,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "gethostname" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55" +dependencies = [ + "rustix", + "windows-targets 0.52.6", +] + [[package]] name = "getrandom" version = "0.2.16" @@ -1072,7 +1082,7 @@ dependencies = [ "parking_lot", "portable-atomic", "quanta", - "rand 0.9.1", + "rand 0.9.2", "smallvec", "spinning_top", "web-time", @@ -1110,9 +1120,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", @@ -1141,9 +1151,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", @@ -1274,7 +1284,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -1283,20 +1293,22 @@ dependencies = [ [[package]] name = "hyper" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", - "h2 0.4.11", + "futures-core", + "h2 0.4.12", "http 1.3.1", "http-body 1.0.1", "httparse", "httpdate", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", @@ -1309,7 +1321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" dependencies = [ "hex", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-util", "pin-project-lite", "tokio", @@ -1324,7 +1336,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ "http 1.3.1", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-util", "rustls", "rustls-pki-types", @@ -1339,7 +1351,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.6.0", + "hyper 1.7.0", "hyper-util", "pin-project-lite", "tokio", @@ -1361,9 +1373,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ "bytes", "futures-channel", @@ -1371,10 +1383,10 @@ dependencies = [ "futures-util", "http 1.3.1", "http-body 1.0.1", - "hyper 1.6.0", + "hyper 1.7.0", "libc", "pin-project-lite", - "socket2", + "socket2 0.6.0", "tokio", "tower-service", "tracing", @@ -1388,7 +1400,7 @@ checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7" dependencies = [ "hex", "http-body-util", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-util", "pin-project-lite", "tokio", @@ -1513,9 +1525,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -1550,7 +1562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.15.5", "serde", ] @@ -1565,20 +1577,20 @@ dependencies = [ [[package]] name = "inventory" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83" +checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" dependencies = [ "rustversion", ] [[package]] name = "io-uring" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "cfg-if", "libc", ] @@ -1654,9 +1666,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.174" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libm" @@ -1670,9 +1682,9 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "libc", - "redox_syscall 0.5.13", + "redox_syscall 0.5.17", ] [[package]] @@ -1709,7 +1721,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" dependencies = [ - "hashbrown 0.15.4", + "hashbrown 0.15.5", ] [[package]] @@ -1971,7 +1983,7 @@ version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "cfg-if", "foreign-types", "libc", @@ -2019,7 +2031,7 @@ dependencies = [ "futures-sink", "js-sys", "pin-project-lite", - "thiserror 2.0.12", + "thiserror 2.0.16", "tracing", ] @@ -2080,7 +2092,7 @@ checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.13", + "redox_syscall 0.5.17", "smallvec", "windows-targets 0.52.6", ] @@ -2121,9 +2133,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "petgraph" @@ -2270,9 +2282,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.35" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", "syn", @@ -2289,9 +2301,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -2489,9 +2501,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -2541,7 +2553,7 @@ version = "11.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", ] [[package]] @@ -2555,11 +2567,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", ] [[package]] @@ -2723,9 +2735,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc_version" @@ -2739,7 +2751,7 @@ dependencies = [ [[package]] name = "rustfsm" version = "0.1.0" -source = "git+https://github.com/temporalio/sdk-core?branch=master#49a0af54ff88b13c5b906a74df8f283601c2b962" +source = "git+https://github.com/temporalio/sdk-core?branch=master#199880d2f5673895e6437bc39a031243c7b7861c" dependencies = [ "rustfsm_procmacro", "rustfsm_trait", @@ -2748,7 +2760,7 @@ dependencies = [ [[package]] name = "rustfsm_procmacro" version = "0.1.0" -source = "git+https://github.com/temporalio/sdk-core?branch=master#49a0af54ff88b13c5b906a74df8f283601c2b962" +source = "git+https://github.com/temporalio/sdk-core?branch=master#199880d2f5673895e6437bc39a031243c7b7861c" dependencies = [ "derive_more", "proc-macro2", @@ -2760,26 +2772,26 @@ dependencies = [ [[package]] name = "rustfsm_trait" version = "0.1.0" -source = "git+https://github.com/temporalio/sdk-core?branch=master#49a0af54ff88b13c5b906a74df8f283601c2b962" +source = "git+https://github.com/temporalio/sdk-core?branch=master#199880d2f5673895e6437bc39a031243c7b7861c" [[package]] name = "rustix" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "rustls" -version = "0.23.29" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "log", "once_cell", @@ -2799,7 +2811,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.2.0", + "security-framework 3.3.0", ] [[package]] @@ -2842,9 +2854,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rustybits" @@ -2937,7 +2949,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -2946,11 +2958,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -3005,9 +3017,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "itoa", "memchr", @@ -3126,9 +3138,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.5" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] @@ -3151,9 +3163,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "slotmap" @@ -3180,6 +3192,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "spin" version = "0.9.8" @@ -3248,9 +3270,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.104" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -3316,21 +3338,21 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "temporal-client" version = "0.1.0" -source = "git+https://github.com/temporalio/sdk-core?branch=master#49a0af54ff88b13c5b906a74df8f283601c2b962" +source = "git+https://github.com/temporalio/sdk-core?branch=master#199880d2f5673895e6437bc39a031243c7b7861c" dependencies = [ "anyhow", "async-trait", @@ -3343,14 +3365,14 @@ dependencies = [ "futures-util", "http 1.3.1", "http-body-util", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-util", "opentelemetry", "parking_lot", "slotmap", "temporal-sdk-core-api", "temporal-sdk-core-protos", - "thiserror 2.0.12", + "thiserror 2.0.16", "tokio", "tonic", "tower", @@ -3362,7 +3384,7 @@ dependencies = [ [[package]] name = "temporal-sdk" version = "0.1.0-alpha.1" -source = "git+https://github.com/temporalio/sdk-core?branch=master#49a0af54ff88b13c5b906a74df8f283601c2b962" +source = "git+https://github.com/temporalio/sdk-core?branch=master#199880d2f5673895e6437bc39a031243c7b7861c" dependencies = [ "anyhow", "async-trait", @@ -3384,7 +3406,7 @@ dependencies = [ [[package]] name = "temporal-sdk-core" version = "0.1.0" -source = "git+https://github.com/temporalio/sdk-core?branch=master#49a0af54ff88b13c5b906a74df8f283601c2b962" +source = "git+https://github.com/temporalio/sdk-core?branch=master#199880d2f5673895e6437bc39a031243c7b7861c" dependencies = [ "anyhow", "async-trait", @@ -3398,6 +3420,7 @@ dependencies = [ "enum_dispatch", "futures-channel", "futures-util", + "gethostname", "governor", "itertools 0.14.0", "lru", @@ -3407,7 +3430,7 @@ dependencies = [ "pin-project", "prost 0.13.5", "prost-wkt-types", - "rand 0.9.1", + "rand 0.9.2", "ringbuf", "rustfsm", "serde", @@ -3418,7 +3441,7 @@ dependencies = [ "temporal-client", "temporal-sdk-core-api", "temporal-sdk-core-protos", - "thiserror 2.0.12", + "thiserror 2.0.16", "tokio", "tokio-stream", "tokio-util", @@ -3432,7 +3455,7 @@ dependencies = [ [[package]] name = "temporal-sdk-core-api" version = "0.1.0" -source = "git+https://github.com/temporalio/sdk-core?branch=master#49a0af54ff88b13c5b906a74df8f283601c2b962" +source = "git+https://github.com/temporalio/sdk-core?branch=master#199880d2f5673895e6437bc39a031243c7b7861c" dependencies = [ "async-trait", "derive_builder", @@ -3441,7 +3464,7 @@ dependencies = [ "prost 0.13.5", "serde_json", "temporal-sdk-core-protos", - "thiserror 2.0.12", + "thiserror 2.0.16", "tonic", "tracing", "tracing-core", @@ -3451,7 +3474,7 @@ dependencies = [ [[package]] name = "temporal-sdk-core-protos" version = "0.1.0" -source = "git+https://github.com/temporalio/sdk-core?branch=master#49a0af54ff88b13c5b906a74df8f283601c2b962" +source = "git+https://github.com/temporalio/sdk-core?branch=master#199880d2f5673895e6437bc39a031243c7b7861c" dependencies = [ "anyhow", "base64 0.22.1", @@ -3461,10 +3484,10 @@ dependencies = [ "prost-wkt", "prost-wkt-build", "prost-wkt-types", - "rand 0.9.1", + "rand 0.9.2", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.16", "tonic", "tonic-build", "uuid", @@ -3497,7 +3520,7 @@ dependencies = [ "serde", "serde_json", "serde_with", - "thiserror 2.0.12", + "thiserror 2.0.16", "tokio", "tokio-stream", "tokio-tar", @@ -3525,11 +3548,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.16", ] [[package]] @@ -3545,9 +3568,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ "proc-macro2", "quote", @@ -3606,9 +3629,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.46.1" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", @@ -3619,9 +3642,9 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "slab", - "socket2", + "socket2 0.6.0", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3683,9 +3706,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.15" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", @@ -3745,18 +3768,18 @@ dependencies = [ "axum", "base64 0.22.1", "bytes", - "h2 0.4.11", + "h2 0.4.12", "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", "prost 0.13.5", "rustls-native-certs", - "socket2", + "socket2 0.5.10", "tokio", "tokio-rustls", "tokio-stream", @@ -3946,9 +3969,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" dependencies = [ "getrandom 0.3.3", "js-sys", @@ -4255,7 +4278,7 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.2", + "windows-targets 0.53.3", ] [[package]] @@ -4291,10 +4314,11 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.2" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ + "windows-link", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -4468,7 +4492,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.2", ] [[package]] @@ -4571,9 +4595,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" dependencies = [ "yoke", "zerofrom", diff --git a/rustybits/src/ext.rs b/rustybits/src/ext.rs index bf6dcea91..32687bcaf 100644 --- a/rustybits/src/ext.rs +++ b/rustybits/src/ext.rs @@ -1,13 +1,9 @@ -/* - * Copyright (c)2021 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ use std::ffi::{CStr, CString}; diff --git a/rustybits/src/smeeclient/mod.rs b/rustybits/src/smeeclient/mod.rs index ddd2cc1f7..203444b60 100644 --- a/rustybits/src/smeeclient/mod.rs +++ b/rustybits/src/smeeclient/mod.rs @@ -1,13 +1,9 @@ -/* - * Copyright (c)2023 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ use serde::{Deserialize, Serialize}; use std::str::FromStr; diff --git a/rustybits/src/zeroidc/error.rs b/rustybits/src/zeroidc/error.rs index 4495254d1..2dfa79c52 100644 --- a/rustybits/src/zeroidc/error.rs +++ b/rustybits/src/zeroidc/error.rs @@ -1,13 +1,9 @@ -/* - * Copyright (c)2022 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ use thiserror::Error; diff --git a/rustybits/src/zeroidc/mod.rs b/rustybits/src/zeroidc/mod.rs index a494a2df6..973c9babb 100644 --- a/rustybits/src/zeroidc/mod.rs +++ b/rustybits/src/zeroidc/mod.rs @@ -1,13 +1,9 @@ -/* - * Copyright (c)2021 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ #![allow( diff --git a/selftest.cpp b/selftest.cpp index 1c5f7c1a1..60e26dc06 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include "node/Buffer.hpp" #include "node/CertificateOfMembership.hpp" @@ -61,1173 +56,1173 @@ using namespace ZeroTier; ////////////////////////////////////////////////////////////////////////////// #define KNOWN_GOOD_IDENTITY \ - "8e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:" \ - "bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e" + "8e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:" \ + "bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e" #define KNOWN_BAD_IDENTITY \ - "9e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:" \ - "bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e" + "9e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:" \ + "bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e" static const unsigned char s20TV0Key[32] = { 0x0f, 0x62, 0xb5, 0x08, 0x5b, 0xae, 0x01, 0x54, 0xa7, 0xfa, 0x4d, 0xa0, 0xf3, 0x46, 0x99, 0xec, 0x3f, 0x92, 0xe5, 0x38, 0x8b, 0xde, 0x31, 0x84, 0xd7, 0x2a, 0x7d, 0xd0, 0x23, 0x76, 0xc9, 0x1c }; static const unsigned char s20TV0Iv[8] = { 0x28, 0x8f, 0xf6, 0x5d, 0xc4, 0x2b, 0x92, 0xf9 }; static const unsigned char s20TV0Ks[64] = { 0x5e, 0x5e, 0x71, 0xf9, 0x01, 0x99, 0x34, 0x03, 0x04, 0xab, 0xb2, 0x2a, 0x37, 0xb6, 0x62, 0x5b, 0xf8, 0x83, 0xfb, 0x89, 0xce, 0x3b, 0x21, 0xf5, 0x4a, 0x10, 0xb8, 0x10, 0x66, 0xef, 0x87, 0xda, - 0x30, 0xb7, 0x76, 0x99, 0xaa, 0x73, 0x79, 0xda, 0x59, 0x5c, 0x77, 0xdd, 0x59, 0x54, 0x2d, 0xa2, 0x08, 0xe5, 0x95, 0x4f, 0x89, 0xe4, 0x0e, 0xb7, 0xaa, 0x80, 0xa8, 0x4a, 0x61, 0x76, 0x66, 0x3f }; + 0x30, 0xb7, 0x76, 0x99, 0xaa, 0x73, 0x79, 0xda, 0x59, 0x5c, 0x77, 0xdd, 0x59, 0x54, 0x2d, 0xa2, 0x08, 0xe5, 0x95, 0x4f, 0x89, 0xe4, 0x0e, 0xb7, 0xaa, 0x80, 0xa8, 0x4a, 0x61, 0x76, 0x66, 0x3f }; static const unsigned char s2012TV0Key[32] = { 0x0f, 0x62, 0xb5, 0x08, 0x5b, 0xae, 0x01, 0x54, 0xa7, 0xfa, 0x4d, 0xa0, 0xf3, 0x46, 0x99, 0xec, 0x3f, 0x92, 0xe5, 0x38, 0x8b, 0xde, 0x31, 0x84, 0xd7, 0x2a, 0x7d, 0xd0, 0x23, 0x76, 0xc9, 0x1c }; static const unsigned char s2012TV0Iv[8] = { 0x28, 0x8f, 0xf6, 0x5d, 0xc4, 0x2b, 0x92, 0xf9 }; static const unsigned char s2012TV0Ks[64] = { 0x99, 0xDB, 0x33, 0xAD, 0x11, 0xCE, 0x0C, 0xCB, 0x3B, 0xFD, 0xBF, 0x8D, 0x0C, 0x18, 0x16, 0x04, 0x52, 0xD0, 0x14, 0xCD, 0xE9, 0x89, 0xB4, 0xC4, 0x11, 0xA5, 0x59, 0xFF, 0x7C, 0x20, 0xA1, 0x69, - 0xE6, 0xDC, 0x99, 0x09, 0xD8, 0x16, 0xBE, 0xCE, 0xDC, 0x40, 0x63, 0xCE, 0x07, 0xCE, 0xA8, 0x28, 0xF4, 0x4B, 0xF9, 0xB6, 0xC9, 0xA0, 0xA0, 0xB2, 0x00, 0xE1, 0xB5, 0x2A, 0xF4, 0x18, 0x59, 0xC5 }; + 0xE6, 0xDC, 0x99, 0x09, 0xD8, 0x16, 0xBE, 0xCE, 0xDC, 0x40, 0x63, 0xCE, 0x07, 0xCE, 0xA8, 0x28, 0xF4, 0x4B, 0xF9, 0xB6, 0xC9, 0xA0, 0xA0, 0xB2, 0x00, 0xE1, 0xB5, 0x2A, 0xF4, 0x18, 0x59, 0xC5 }; static const unsigned char poly1305TV0Input[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const unsigned char poly1305TV0Key[32] = { - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x33, 0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35 + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x33, 0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35 }; static const unsigned char poly1305TV0Tag[16] = { 0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07 }; static const unsigned char poly1305TV1Input[12] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21 }; static const unsigned char poly1305TV1Key[32] = { - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x33, 0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35 + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x33, 0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35 }; static const unsigned char poly1305TV1Tag[16] = { 0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0 }; static const char* sha512TV0Input = "supercalifragilisticexpealidocious"; static const unsigned char sha512TV0Digest[64] = { 0x18, 0x2a, 0x85, 0x59, 0x69, 0xe5, 0xd3, 0xe6, 0xcb, 0xf6, 0x05, 0x24, 0xad, 0xf2, 0x88, 0xd1, 0xbb, 0xf2, 0x52, 0x92, 0x81, 0x24, - 0x31, 0xf6, 0xd2, 0x52, 0xf1, 0xdb, 0xc1, 0xcb, 0x44, 0xdf, 0x21, 0x57, 0x3d, 0xe1, 0xb0, 0x6b, 0x68, 0x75, 0x95, 0x9f, 0x3b, 0x6f, - 0x87, 0xb1, 0x13, 0x81, 0xd0, 0xbc, 0x79, 0x2c, 0x43, 0x3a, 0x13, 0x55, 0x3c, 0xe0, 0x84, 0xc2, 0x92, 0x55, 0x31, 0x1c }; + 0x31, 0xf6, 0xd2, 0x52, 0xf1, 0xdb, 0xc1, 0xcb, 0x44, 0xdf, 0x21, 0x57, 0x3d, 0xe1, 0xb0, 0x6b, 0x68, 0x75, 0x95, 0x9f, 0x3b, 0x6f, + 0x87, 0xb1, 0x13, 0x81, 0xd0, 0xbc, 0x79, 0x2c, 0x43, 0x3a, 0x13, 0x55, 0x3c, 0xe0, 0x84, 0xc2, 0x92, 0x55, 0x31, 0x1c }; struct C25519TestVector { - unsigned char pub1[64]; - unsigned char priv1[64]; - unsigned char pub2[64]; - unsigned char priv2[64]; - unsigned char agreement[64]; - unsigned char agreementSignedBy1[96]; - unsigned char agreementSignedBy2[96]; + unsigned char pub1[64]; + unsigned char priv1[64]; + unsigned char pub2[64]; + unsigned char priv2[64]; + unsigned char agreement[64]; + unsigned char agreementSignedBy1[96]; + unsigned char agreementSignedBy2[96]; }; #define ZT_NUM_C25519_TEST_VECTORS 32 static const C25519TestVector C25519_TEST_VECTORS[ZT_NUM_C25519_TEST_VECTORS] = { - { { 0xa1, 0xfc, 0x7a, 0xb4, 0x6d, 0xdf, 0x7d, 0xcf, 0xe7, 0xec, 0x75, 0xe5, 0xfa, 0xdd, 0x11, 0xcb, 0xcc, 0x37, 0xf8, 0x84, 0x5d, 0x1c, 0x92, 0x4e, 0x09, 0x89, 0x65, 0xfc, 0xd8, 0xe9, 0x5a, 0x30, - 0xda, 0xe4, 0x86, 0xa3, 0x35, 0xb4, 0x19, 0x0c, 0xbc, 0x7b, 0xcb, 0x3e, 0xb9, 0x4c, 0xbd, 0x16, 0xe8, 0x3d, 0x13, 0x2b, 0xc9, 0xc3, 0x39, 0xea, 0xf1, 0x42, 0xe7, 0x6f, 0x69, 0x78, 0x9a, 0xb7 }, - { 0xe5, 0xf3, 0x7b, 0xd4, 0x0e, 0xc9, 0xdc, 0x77, 0x50, 0x86, 0xdc, 0xf4, 0x2e, 0xbc, 0xdb, 0x27, 0xf0, 0x73, 0xd4, 0x58, 0x73, 0xc4, 0x4b, 0x71, 0x8b, 0x3c, 0xc5, 0x4f, 0xa8, 0x7c, 0xa4, 0x84, - 0xd9, 0x96, 0x23, 0x73, 0xb4, 0x03, 0x16, 0xbf, 0x1e, 0xa1, 0x2d, 0xd8, 0xc4, 0x8a, 0xe7, 0x82, 0x10, 0xda, 0xc9, 0xe5, 0x45, 0x9b, 0x01, 0xdc, 0x73, 0xa6, 0xc9, 0x17, 0xa8, 0x15, 0x31, 0x6d }, - { 0x3e, 0x49, 0xa4, 0x0e, 0x3a, 0xaf, 0xa3, 0x07, 0x3d, 0xf7, 0x2a, 0xec, 0x43, 0xb1, 0xd4, 0x09, 0x1a, 0xcb, 0x8e, 0x92, 0xf9, 0x65, 0x95, 0x04, 0x6d, 0x2d, 0x9b, 0x34, 0xa3, 0xbf, 0x51, 0x00, - 0xe2, 0xee, 0x23, 0xf5, 0x28, 0x0a, 0xa9, 0xb1, 0x57, 0x0b, 0x96, 0x56, 0x62, 0xba, 0x12, 0x94, 0xaf, 0xc6, 0x5f, 0xb5, 0x61, 0x43, 0x0f, 0xde, 0x0b, 0xab, 0xfa, 0x4f, 0xfe, 0xc5, 0xe7, 0x18 }, - { 0x00, 0x4d, 0x41, 0x8d, 0xe4, 0x69, 0x23, 0xae, 0x98, 0xc4, 0x3e, 0x77, 0x0f, 0x1d, 0x94, 0x5d, 0x29, 0x3e, 0x94, 0x5a, 0x38, 0x39, 0x20, 0x0f, 0xd3, 0x6f, 0x76, 0xa2, 0x29, 0x02, 0x03, 0xcb, - 0x0b, 0x7f, 0x4f, 0x1a, 0x29, 0x51, 0x13, 0x33, 0x7c, 0x99, 0xb3, 0x81, 0x82, 0x39, 0x44, 0x05, 0x97, 0xfb, 0x0d, 0xf2, 0x93, 0xa2, 0x40, 0x94, 0xf4, 0xff, 0x5d, 0x09, 0x61, 0xe4, 0x5f, 0x76 }, - { 0xab, 0xce, 0xd2, 0x24, 0xe8, 0x93, 0xb0, 0xe7, 0x72, 0x14, 0xdc, 0xbb, 0x7d, 0x0f, 0xd8, 0x94, 0x16, 0x9e, 0xb5, 0x7f, 0xd7, 0x19, 0x5f, 0x3e, 0x2d, 0x45, 0xd5, 0xf7, 0x90, 0x0b, 0x3e, 0x05, - 0x18, 0x2e, 0x2b, 0xf4, 0xfa, 0xd4, 0xec, 0x62, 0x4a, 0x4f, 0x48, 0x50, 0xaf, 0x1c, 0xe8, 0x9f, 0x1a, 0xe1, 0x3d, 0x70, 0x49, 0x00, 0xa7, 0xe3, 0x5b, 0x1e, 0xa1, 0x9b, 0x68, 0x1e, 0xa1, 0x73 }, - { 0xed, 0xb6, 0xd0, 0xf0, 0x06, 0x6e, 0x33, 0x9c, 0x86, 0xfb, 0xe8, 0xc3, 0x6c, 0x8d, 0xde, 0xdd, 0xa6, 0xa0, 0x2d, 0xb9, 0x07, 0x29, 0xa3, 0x13, 0xbb, 0xa4, 0xba, 0xec, 0x48, 0xc8, 0xf4, 0x56, - 0x82, 0x79, 0xe2, 0xb1, 0xd3, 0x3d, 0x83, 0x9f, 0x10, 0xe8, 0x52, 0xe6, 0x8b, 0x1c, 0x33, 0x9e, 0x2b, 0xd2, 0xdb, 0x62, 0x1c, 0x56, 0xfd, 0x50, 0x40, 0x77, 0x81, 0xab, 0x21, 0x67, 0x3e, 0x09, - 0x4f, 0xf2, 0x51, 0xac, 0x7d, 0xe7, 0xd1, 0x5d, 0x4b, 0xe2, 0x08, 0xc6, 0x3f, 0x6a, 0x4d, 0xc8, 0x5d, 0x74, 0xf6, 0x3b, 0xec, 0x8e, 0xc6, 0x0c, 0x32, 0x27, 0x2f, 0x9c, 0x09, 0x48, 0x59, 0x10 }, - { 0x23, 0x0f, 0xa3, 0xe2, 0x69, 0xce, 0xb9, 0xb9, 0xd1, 0x1c, 0x4e, 0xab, 0x63, 0xc9, 0x2e, 0x1e, 0x7e, 0xa2, 0xa2, 0xa0, 0x49, 0x2e, 0x78, 0xe4, 0x8a, 0x02, 0x3b, 0xa7, 0xab, 0x1f, 0xd4, 0xce, - 0x05, 0xe2, 0x80, 0x09, 0x09, 0x3c, 0x61, 0xc7, 0x10, 0x3a, 0x9c, 0xf4, 0x95, 0xac, 0x89, 0x6f, 0x23, 0xb3, 0x09, 0xe2, 0x24, 0x3f, 0xf6, 0x96, 0x02, 0x36, 0x41, 0x16, 0x32, 0xe1, 0x66, 0x05, - 0x4f, 0xf2, 0x51, 0xac, 0x7d, 0xe7, 0xd1, 0x5d, 0x4b, 0xe2, 0x08, 0xc6, 0x3f, 0x6a, 0x4d, 0xc8, 0x5d, 0x74, 0xf6, 0x3b, 0xec, 0x8e, 0xc6, 0x0c, 0x32, 0x27, 0x2f, 0x9c, 0x09, 0x48, 0x59, 0x10 } }, - { { 0xfd, 0x81, 0x14, 0xf1, 0x67, 0x07, 0x44, 0xbb, 0x93, 0x84, 0xa2, 0xdc, 0x36, 0xdc, 0xcc, 0xb3, 0x9e, 0x82, 0xd4, 0x8b, 0x42, 0x56, 0xfb, 0xf2, 0x6e, 0x83, 0x3b, 0x16, 0x2c, 0x29, 0xfb, 0x39, - 0x29, 0x48, 0x85, 0xe3, 0xe3, 0xf7, 0xe7, 0x80, 0x49, 0xd3, 0x01, 0x30, 0x5a, 0x2c, 0x3f, 0x4c, 0xea, 0x13, 0xeb, 0xda, 0xf4, 0x56, 0x75, 0x8d, 0x50, 0x1e, 0x19, 0x2d, 0x29, 0x2b, 0xfb, 0xdb }, - { 0x85, 0x34, 0x4d, 0xf7, 0x39, 0xbf, 0x98, 0x79, 0x8c, 0x98, 0xeb, 0x8d, 0x61, 0x27, 0xec, 0x87, 0x56, 0xcd, 0xd0, 0xa6, 0x55, 0x77, 0xee, 0xf0, 0x20, 0xd0, 0x59, 0x39, 0x95, 0xab, 0x29, 0x82, - 0x8e, 0x61, 0xf8, 0xad, 0xed, 0xb6, 0x27, 0xc3, 0xd8, 0x16, 0xce, 0x67, 0x78, 0xe2, 0x04, 0x4b, 0x0c, 0x2d, 0x2f, 0xc3, 0x24, 0x72, 0xbc, 0x53, 0xbd, 0xfe, 0x39, 0x23, 0xd4, 0xaf, 0x27, 0x84 }, - { 0x11, 0xbe, 0x5f, 0x5a, 0x73, 0xe7, 0x42, 0xef, 0xff, 0x3c, 0x47, 0x6a, 0x0e, 0x6b, 0x9e, 0x96, 0x21, 0xa3, 0xdf, 0x49, 0xe9, 0x3f, 0x40, 0xfc, 0xab, 0xb3, 0x66, 0xd3, 0x3d, 0xfa, 0x02, 0x29, - 0xf3, 0x43, 0x45, 0x3c, 0x70, 0xa3, 0x5d, 0x39, 0xf7, 0xc0, 0x6a, 0xcd, 0xfa, 0x1d, 0xbe, 0x3b, 0x91, 0x41, 0xe4, 0xb0, 0x60, 0xc0, 0x22, 0xf7, 0x2c, 0x11, 0x2b, 0x1c, 0x5f, 0x24, 0xef, 0x53 }, - { 0xfd, 0x3f, 0x09, 0x06, 0xc9, 0x39, 0x8d, 0x48, 0xfa, 0x6b, 0xc9, 0x80, 0xbf, 0xf6, 0xd6, 0x76, 0xb3, 0x62, 0x70, 0x88, 0x4f, 0xde, 0xde, 0xb9, 0xb4, 0xf0, 0xce, 0xf3, 0x74, 0x0d, 0xea, 0x00, - 0x9e, 0x9c, 0x29, 0xe1, 0xa2, 0x1b, 0xbd, 0xb5, 0x83, 0xcc, 0x12, 0xd8, 0x48, 0x08, 0x5b, 0xe5, 0xd6, 0xf9, 0x11, 0x5c, 0xe0, 0xd9, 0xc3, 0x3c, 0x26, 0xbd, 0x69, 0x9f, 0x5c, 0x6f, 0x0c, 0x6f }, - { 0xca, 0xd4, 0x76, 0x32, 0x8b, 0xbe, 0x0c, 0x65, 0x75, 0x43, 0x73, 0xc2, 0xf2, 0xfd, 0x7f, 0xeb, 0xe4, 0x62, 0xc5, 0x0d, 0x0f, 0xf9, 0x01, 0xc8, 0xb9, 0xfa, 0xca, 0xb4, 0x12, 0x1c, 0xb4, 0xac, - 0x0e, 0x5f, 0x18, 0xfc, 0x0c, 0x7f, 0x2a, 0x55, 0xc5, 0xfd, 0x4d, 0x83, 0xb2, 0x02, 0x31, 0x6a, 0x3f, 0x14, 0xee, 0x9d, 0x11, 0xa8, 0x06, 0xad, 0xeb, 0x93, 0x19, 0x79, 0xb1, 0xf2, 0x78, 0x05 }, - { 0x85, 0xe6, 0xe2, 0xf2, 0x96, 0xe7, 0xa2, 0x8b, 0x7e, 0x36, 0xbd, 0x7b, 0xf4, 0x28, 0x6a, 0xd7, 0xbc, 0x2a, 0x6a, 0x59, 0xfd, 0xc0, 0xc8, 0x3d, 0x50, 0x0f, 0x0c, 0x2b, 0x12, 0x3a, 0x75, 0xc7, - 0x56, 0xbb, 0x7f, 0x7d, 0x4e, 0xd4, 0x03, 0xb8, 0x7b, 0xde, 0xde, 0x99, 0x65, 0x9e, 0xc4, 0xa6, 0x6e, 0xfe, 0x00, 0x88, 0xeb, 0x9d, 0xa4, 0xa9, 0x9d, 0x37, 0xc9, 0x4a, 0xcf, 0x69, 0xc4, 0x01, - 0xba, 0xa8, 0xce, 0xeb, 0x72, 0xcb, 0x64, 0x8b, 0x9f, 0xc1, 0x1f, 0x9a, 0x9e, 0x99, 0xcc, 0x39, 0xec, 0xd9, 0xbb, 0xd9, 0xce, 0xc2, 0x74, 0x6f, 0xd0, 0x2a, 0xb9, 0xc6, 0xe3, 0xf5, 0xe7, 0xf4 }, - { 0xb1, 0x39, 0x50, 0xb1, 0x1a, 0x08, 0x42, 0x2b, 0xdd, 0x6d, 0x20, 0x9f, 0x0f, 0x37, 0xba, 0x69, 0x97, 0x21, 0x30, 0x7a, 0x71, 0x2f, 0xce, 0x98, 0x09, 0x04, 0xa2, 0x98, 0x6a, 0xed, 0x02, 0x1d, - 0x5d, 0x30, 0x8f, 0x03, 0x47, 0x6b, 0x89, 0xfd, 0xf7, 0x1a, 0xca, 0x46, 0x6f, 0x51, 0x69, 0x9a, 0x2b, 0x18, 0x77, 0xe4, 0xad, 0x0d, 0x7a, 0x66, 0xd2, 0x2c, 0x28, 0xa0, 0xd3, 0x0a, 0x99, 0x0d, - 0xba, 0xa8, 0xce, 0xeb, 0x72, 0xcb, 0x64, 0x8b, 0x9f, 0xc1, 0x1f, 0x9a, 0x9e, 0x99, 0xcc, 0x39, 0xec, 0xd9, 0xbb, 0xd9, 0xce, 0xc2, 0x74, 0x6f, 0xd0, 0x2a, 0xb9, 0xc6, 0xe3, 0xf5, 0xe7, 0xf4 } }, - { { 0x02, 0x3a, 0x7e, 0x0c, 0x6d, 0x96, 0x3c, 0x5d, 0x44, 0x56, 0x5d, 0xc1, 0x49, 0x94, 0x35, 0x12, 0x9d, 0xff, 0x8a, 0x5d, 0x91, 0x74, 0xa8, 0x15, 0xee, 0x5d, 0x1e, 0x72, 0xbe, 0x86, 0x15, 0x68, - 0xe7, 0x36, 0xa2, 0x4a, 0xb8, 0xa2, 0xa4, 0x4c, 0xd8, 0x95, 0xe3, 0xc7, 0xbb, 0x32, 0x21, 0x90, 0x64, 0x52, 0x32, 0xeb, 0x26, 0xd3, 0x4f, 0xf0, 0x8e, 0x27, 0x40, 0xea, 0xed, 0xdb, 0xf5, 0xc4 }, - { 0x76, 0x99, 0x64, 0x70, 0xf4, 0x50, 0xc8, 0xcc, 0x4a, 0x5a, 0xa5, 0x0f, 0xeb, 0x2d, 0xc7, 0x0e, 0x73, 0xd0, 0x65, 0x7d, 0xc3, 0xce, 0x73, 0x03, 0x20, 0x2f, 0xad, 0x65, 0xfd, 0x12, 0xe4, 0x7f, - 0xfd, 0x45, 0x3a, 0x6e, 0xc5, 0x9a, 0x06, 0x67, 0x0e, 0xa6, 0x7b, 0x21, 0x49, 0x2d, 0x01, 0x1b, 0x8e, 0x03, 0x6e, 0x10, 0x08, 0x0c, 0x68, 0xd9, 0x60, 0x47, 0xa4, 0xe2, 0x52, 0xfd, 0x3c, 0xf4 }, - { 0xa3, 0xe2, 0x5f, 0x16, 0x39, 0x78, 0x96, 0xf7, 0x47, 0x6f, 0x93, 0x5d, 0x27, 0x7b, 0x58, 0xe0, 0xc5, 0xdb, 0x71, 0x7d, 0xa9, 0x6f, 0xf8, 0x8b, 0x69, 0xdd, 0x50, 0xea, 0x91, 0x0d, 0x66, 0x77, - 0xaf, 0x8f, 0xd5, 0x9f, 0x8a, 0x26, 0x69, 0x4c, 0x64, 0x37, 0x62, 0x81, 0x6f, 0x05, 0x9a, 0x08, 0x0d, 0xe1, 0x69, 0x24, 0x77, 0x3f, 0x50, 0xb2, 0x49, 0x4d, 0x93, 0xef, 0x2e, 0x87, 0xff, 0xde }, - { 0xb3, 0x32, 0xe2, 0x67, 0x79, 0x32, 0x5f, 0x64, 0x47, 0x49, 0x1c, 0xd3, 0x8f, 0x95, 0x44, 0xfd, 0x4c, 0x7e, 0xbf, 0x6b, 0xb7, 0xaf, 0x2c, 0xdd, 0x8f, 0xa5, 0xd8, 0x2f, 0xbf, 0xa0, 0x8a, 0x6b, - 0x58, 0x25, 0xc9, 0x12, 0x23, 0x6f, 0xe6, 0x05, 0xa8, 0xd0, 0x68, 0x6e, 0x0c, 0xee, 0x70, 0xe4, 0xa3, 0x86, 0x51, 0x04, 0x6d, 0xca, 0xd5, 0xed, 0xcf, 0x74, 0x1d, 0x60, 0x9e, 0x86, 0x2d, 0x05 }, - { 0x91, 0xf4, 0x5f, 0x4a, 0xcb, 0xd8, 0xfd, 0x5f, 0xb9, 0x3d, 0x04, 0xb8, 0xec, 0x35, 0x85, 0x4f, 0x58, 0x20, 0xd1, 0x1f, 0x47, 0xc4, 0xf4, 0xcb, 0x21, 0x4e, 0x9a, 0xf1, 0x6e, 0xbf, 0xe3, 0xd3, - 0x62, 0xe3, 0x82, 0xf6, 0xba, 0xa8, 0xdf, 0x92, 0xe2, 0x3c, 0xe5, 0xf0, 0x16, 0x8a, 0xeb, 0xa4, 0xbb, 0xc7, 0x81, 0xaf, 0x15, 0x19, 0x87, 0x5f, 0xb7, 0xe0, 0x4c, 0x12, 0xff, 0x2c, 0xa9, 0xc8 }, - { 0xaf, 0x85, 0xe0, 0x36, 0x43, 0xdf, 0x41, 0x17, 0xda, 0xde, 0x5e, 0xb6, 0x33, 0xd0, 0xce, 0x62, 0x70, 0x5f, 0x85, 0x24, 0x6c, 0x3e, 0x1b, 0xe1, 0x52, 0xc1, 0x9b, 0x1c, 0xcd, 0x61, 0x80, 0x9c, - 0xa0, 0xe8, 0x18, 0xee, 0x40, 0x91, 0x93, 0x82, 0xdb, 0x33, 0x44, 0xff, 0xd4, 0xf6, 0x6f, 0x5d, 0xf0, 0x0e, 0x92, 0x92, 0x81, 0x55, 0x46, 0x06, 0xac, 0x58, 0x81, 0x3b, 0x04, 0xc7, 0xf7, 0x0d, - 0xd2, 0x0c, 0x08, 0x6d, 0x46, 0xdb, 0x43, 0x28, 0x31, 0xd8, 0xcd, 0x87, 0x50, 0xbb, 0xd3, 0x07, 0xf5, 0x72, 0x0b, 0x15, 0x7c, 0x16, 0xab, 0x03, 0xd9, 0x4b, 0x07, 0x38, 0x97, 0xe8, 0xd6, 0xb5 }, - { 0x93, 0xff, 0x6d, 0xc3, 0x62, 0xf7, 0xcc, 0x20, 0x95, 0xc2, 0x2f, 0x7d, 0x1d, 0x9b, 0xd1, 0x63, 0xfc, 0x61, 0x47, 0xb3, 0x22, 0x0f, 0xca, 0xb0, 0x16, 0xcf, 0x29, 0x53, 0x46, 0x97, 0xb1, 0x36, - 0x46, 0xac, 0x48, 0x13, 0x92, 0xe4, 0x46, 0x68, 0xcf, 0x09, 0x4e, 0xfa, 0x59, 0x45, 0x24, 0x08, 0xdb, 0xb4, 0x6f, 0x20, 0x55, 0x12, 0xd9, 0x75, 0x9d, 0x8e, 0x0b, 0xf8, 0x63, 0xe0, 0xf9, 0x01, - 0xd2, 0x0c, 0x08, 0x6d, 0x46, 0xdb, 0x43, 0x28, 0x31, 0xd8, 0xcd, 0x87, 0x50, 0xbb, 0xd3, 0x07, 0xf5, 0x72, 0x0b, 0x15, 0x7c, 0x16, 0xab, 0x03, 0xd9, 0x4b, 0x07, 0x38, 0x97, 0xe8, 0xd6, 0xb5 } }, - { { 0x14, 0x35, 0xa6, 0x7d, 0xc1, 0xb5, 0x71, 0xca, 0x42, 0x50, 0x90, 0xa7, 0x72, 0x85, 0xbe, 0x78, 0x7a, 0x5f, 0x83, 0x1e, 0xbe, 0xef, 0x6a, 0xbe, 0x48, 0xc5, 0x68, 0x14, 0x0c, 0xf7, 0x44, 0x5c, - 0x2e, 0xfd, 0x1b, 0xcc, 0xee, 0x09, 0x23, 0x82, 0x31, 0xad, 0xaf, 0x4b, 0x73, 0x9c, 0xf2, 0x88, 0x3c, 0xf3, 0xb5, 0x43, 0x8b, 0x53, 0xf9, 0xac, 0x17, 0x86, 0x1c, 0xc2, 0x53, 0x43, 0xec, 0x03 }, - { 0x7b, 0x36, 0x6c, 0xcc, 0xb5, 0xb2, 0x23, 0x3d, 0x7c, 0xe5, 0xe7, 0xcf, 0x06, 0xe2, 0x32, 0x0b, 0xc5, 0x3b, 0x7f, 0x86, 0x40, 0xfc, 0xaf, 0xba, 0x94, 0xe0, 0x88, 0x58, 0x5b, 0xac, 0xe8, 0xc3, - 0xe8, 0xc3, 0xdf, 0xc4, 0x45, 0x29, 0xe8, 0xf0, 0x1c, 0x10, 0x0d, 0x50, 0x81, 0x29, 0x30, 0xa8, 0x27, 0xb5, 0x3e, 0xb8, 0x25, 0xf1, 0x17, 0x30, 0xc6, 0x05, 0xe3, 0x3e, 0x45, 0x38, 0xa8, 0x3c }, - { 0xce, 0xd9, 0x45, 0x28, 0xb0, 0xce, 0xa5, 0x47, 0xa8, 0x29, 0x32, 0x76, 0x99, 0x73, 0x8d, 0x74, 0xf9, 0xed, 0x0a, 0xd0, 0xf1, 0xd8, 0x7e, 0x44, 0x63, 0x9e, 0x9a, 0xcf, 0x7c, 0x35, 0x8a, 0x29, - 0xbb, 0x71, 0x66, 0x8d, 0xa7, 0xfc, 0x05, 0x3d, 0xd4, 0x4b, 0x65, 0x20, 0xf5, 0xa4, 0x64, 0xd8, 0x9d, 0x16, 0x80, 0x9c, 0xb2, 0x3c, 0x3e, 0xd4, 0x9d, 0x09, 0x88, 0x8e, 0xbb, 0x58, 0xf8, 0x77 }, - { 0xe1, 0x29, 0xb3, 0x16, 0xe6, 0xa0, 0xdb, 0x64, 0x08, 0x36, 0xdc, 0x33, 0xad, 0x8b, 0x30, 0x26, 0x17, 0x56, 0xd7, 0x34, 0x17, 0xd1, 0xdd, 0x23, 0x38, 0x58, 0x25, 0x01, 0x42, 0x5a, 0x9d, 0x18, - 0x3e, 0xac, 0x31, 0xfa, 0x43, 0x28, 0xc4, 0x65, 0xfb, 0x30, 0x2f, 0x8c, 0x16, 0x52, 0x32, 0x1b, 0x19, 0xb7, 0x31, 0xf6, 0x67, 0xa7, 0xd8, 0xed, 0x9a, 0xa3, 0x95, 0x01, 0xd7, 0xb9, 0xe7, 0xcc }, - { 0x81, 0x2d, 0x11, 0xa9, 0x11, 0xf1, 0x22, 0xe2, 0x67, 0x70, 0xc4, 0xba, 0x34, 0xa1, 0x75, 0x8c, 0xf6, 0x0c, 0x63, 0xe7, 0x01, 0x3c, 0x64, 0x6c, 0xe8, 0xd0, 0xf8, 0x8e, 0x88, 0xdf, 0x5c, 0x61, - 0x68, 0x5d, 0x1f, 0xeb, 0x83, 0x1f, 0x40, 0xb8, 0xa8, 0x56, 0x57, 0x26, 0x81, 0x2c, 0xa3, 0x0e, 0x48, 0x4c, 0x45, 0x4d, 0x0d, 0x3d, 0x6e, 0x99, 0x52, 0xbd, 0x0b, 0xd8, 0x05, 0xc5, 0xf9, 0x61 }, - { 0x92, 0x45, 0xbe, 0xe6, 0xb4, 0x7a, 0xfa, 0x28, 0xd4, 0x5b, 0x6b, 0x17, 0xc6, 0x13, 0x61, 0x5d, 0x5f, 0xd7, 0x90, 0xbb, 0x89, 0x35, 0x7a, 0x02, 0x50, 0x57, 0x56, 0x5f, 0x19, 0xb5, 0xb6, 0xc5, - 0x77, 0x1e, 0x1b, 0xc0, 0xd7, 0x7a, 0x29, 0xbd, 0xe7, 0x24, 0x01, 0x2d, 0x37, 0xc0, 0x38, 0x6f, 0xc8, 0x35, 0xa1, 0x1b, 0xe0, 0xea, 0x16, 0xad, 0xbc, 0xdc, 0xd4, 0x8d, 0x4e, 0x71, 0xdb, 0x05, - 0x9e, 0xb5, 0x53, 0x6b, 0x5c, 0xf1, 0x7d, 0x15, 0x8b, 0xd7, 0xc7, 0x8b, 0x89, 0x9d, 0xfd, 0x28, 0x7c, 0xa1, 0x31, 0xe2, 0xf0, 0x2c, 0x3a, 0x8d, 0x0e, 0x23, 0x85, 0x4e, 0xf0, 0xd1, 0xc0, 0x83 }, - { 0x7b, 0x88, 0xeb, 0x45, 0x1c, 0x7f, 0xfd, 0xbe, 0xba, 0xac, 0x53, 0x28, 0x59, 0xe8, 0xad, 0x28, 0xf1, 0x97, 0x2d, 0x6c, 0x31, 0xa6, 0xae, 0x47, 0x10, 0x69, 0x68, 0x55, 0xa6, 0x9c, 0x03, 0x62, - 0xb7, 0x2f, 0x31, 0x46, 0x2a, 0x2b, 0x98, 0xdd, 0xe9, 0xf9, 0xfe, 0x77, 0x71, 0x41, 0x54, 0xf8, 0x59, 0x02, 0x7a, 0xe3, 0x45, 0x67, 0xb6, 0xf7, 0x94, 0x31, 0x3e, 0x62, 0x62, 0x2a, 0xf9, 0x0a, - 0x9e, 0xb5, 0x53, 0x6b, 0x5c, 0xf1, 0x7d, 0x15, 0x8b, 0xd7, 0xc7, 0x8b, 0x89, 0x9d, 0xfd, 0x28, 0x7c, 0xa1, 0x31, 0xe2, 0xf0, 0x2c, 0x3a, 0x8d, 0x0e, 0x23, 0x85, 0x4e, 0xf0, 0xd1, 0xc0, 0x83 } }, - { { 0x27, 0x4d, 0x84, 0x08, 0x95, 0x84, 0xc8, 0xeb, 0x1c, 0x9a, 0x0f, 0xca, 0x09, 0x6f, 0x48, 0x8b, 0x2b, 0x06, 0xa0, 0xae, 0xf2, 0xe3, 0x8a, 0xfe, 0xd7, 0x52, 0x4b, 0xf2, 0xc6, 0x7c, 0xc1, 0x55, - 0x87, 0x2e, 0x5a, 0xb4, 0xc2, 0x43, 0x0a, 0x0d, 0xd0, 0x00, 0xa8, 0xe1, 0x46, 0x68, 0x79, 0xd8, 0x8c, 0x01, 0x36, 0xb7, 0x5a, 0x61, 0x04, 0xe9, 0x7e, 0xbb, 0xc9, 0xee, 0xaa, 0x12, 0x13, 0xda }, - { 0x78, 0x66, 0xd0, 0xa2, 0x50, 0x82, 0x8d, 0xb0, 0xa0, 0x20, 0xac, 0xa4, 0xb6, 0xa0, 0x31, 0xf7, 0x7d, 0x93, 0x37, 0x67, 0xbb, 0x60, 0xa2, 0x1e, 0x36, 0xce, 0x3d, 0x48, 0x1d, 0x79, 0x99, 0xa5, - 0x19, 0xd8, 0x89, 0x1b, 0xcb, 0x14, 0x87, 0xb7, 0x62, 0xfd, 0xd2, 0xef, 0xbb, 0x13, 0x41, 0x4d, 0xf1, 0x77, 0x5c, 0x7f, 0x6c, 0x3b, 0x94, 0x7d, 0xb4, 0xba, 0x87, 0x3e, 0xc8, 0xe1, 0x3c, 0x0a }, - { 0xd9, 0x9e, 0x14, 0x89, 0xd6, 0xf8, 0x49, 0xa2, 0xe2, 0x19, 0xfe, 0x94, 0xaa, 0xf7, 0x35, 0xf9, 0x4a, 0xf8, 0xf3, 0x18, 0x68, 0x96, 0x47, 0xc6, 0x23, 0x7c, 0xb0, 0x53, 0xcb, 0xd8, 0x90, 0x31, - 0xb7, 0x50, 0x0e, 0x06, 0xc3, 0x84, 0x75, 0xf1, 0xac, 0x16, 0x4d, 0xc1, 0xbe, 0xf1, 0x80, 0x33, 0x47, 0x56, 0x6f, 0x33, 0x94, 0x5c, 0x81, 0x03, 0x4c, 0x2f, 0x6d, 0xac, 0x73, 0xba, 0x91, 0x3c }, - { 0x2f, 0xa9, 0xb6, 0xe8, 0x73, 0xe2, 0xef, 0x6d, 0x6d, 0xd7, 0x2e, 0xa0, 0x51, 0x61, 0x24, 0x81, 0x8c, 0xa8, 0x47, 0x40, 0xe1, 0xc7, 0x75, 0x79, 0xc8, 0xec, 0xb2, 0x23, 0x41, 0xad, 0x61, 0x3b, - 0xea, 0x8a, 0xdf, 0x63, 0xed, 0xe1, 0x8e, 0x50, 0x70, 0x6e, 0x86, 0xed, 0xb0, 0xba, 0x27, 0x48, 0x8e, 0xb9, 0x63, 0x39, 0x78, 0x58, 0x4f, 0x1e, 0xbc, 0x45, 0xf3, 0xf2, 0x3a, 0x73, 0x9b, 0x8c }, - { 0xad, 0x42, 0xc5, 0x84, 0xca, 0xe1, 0xe1, 0x23, 0x2a, 0x73, 0x15, 0x3c, 0x9a, 0xfe, 0x85, 0x8d, 0xa3, 0x2c, 0xcf, 0x46, 0x8d, 0x7f, 0x1c, 0x61, 0xd7, 0x0e, 0xb1, 0xa6, 0xb4, 0xae, 0xab, 0x63, - 0xc4, 0x0e, 0xf2, 0xa0, 0x5d, 0xa6, 0xf3, 0x5d, 0x35, 0x41, 0xea, 0x03, 0x91, 0xb1, 0x3a, 0x07, 0xe6, 0xed, 0x6c, 0x8c, 0xcb, 0x75, 0x27, 0xf1, 0x26, 0x58, 0xf0, 0x62, 0x57, 0xe4, 0x33, 0x00 }, - { 0x1f, 0xed, 0x53, 0xc6, 0xef, 0x38, 0x26, 0xa4, 0x18, 0x88, 0x8f, 0x5c, 0x49, 0x1c, 0x15, 0x7d, 0x77, 0x90, 0x06, 0x39, 0xe0, 0x7c, 0x25, 0xed, 0x79, 0x05, 0x66, 0xe0, 0x5e, 0x94, 0xe3, 0x46, - 0x6f, 0x96, 0xd8, 0xc1, 0x11, 0xa4, 0x11, 0x6f, 0x78, 0x42, 0x8e, 0x89, 0xc7, 0xc3, 0xed, 0xd2, 0x9e, 0x68, 0x47, 0x79, 0x89, 0x23, 0x70, 0x14, 0x21, 0x60, 0x2d, 0xfe, 0x37, 0x4b, 0xc8, 0x0a, - 0x16, 0x73, 0x7c, 0xc4, 0x55, 0x3f, 0x25, 0x04, 0x08, 0x75, 0x74, 0x68, 0xbc, 0xe4, 0x3a, 0xae, 0x4c, 0x0e, 0xd2, 0x85, 0xa1, 0xbc, 0x81, 0xc0, 0xc9, 0xfe, 0x9a, 0x44, 0x7b, 0x83, 0xdf, 0xc7 }, - { 0x27, 0x77, 0x97, 0x84, 0x0f, 0x2d, 0x8d, 0x33, 0xb8, 0x4e, 0xdb, 0x8b, 0xea, 0x58, 0x52, 0x88, 0x95, 0x88, 0x55, 0x5f, 0xb8, 0xc4, 0xc9, 0xd6, 0x1f, 0x1e, 0xee, 0x60, 0xb5, 0xeb, 0x78, 0x72, - 0xb5, 0xe5, 0x22, 0x2b, 0x7f, 0x5e, 0xc7, 0x9b, 0x29, 0x55, 0x8e, 0x2a, 0xfc, 0x65, 0x55, 0x4a, 0x02, 0xad, 0x64, 0x06, 0xd4, 0x25, 0xe1, 0x96, 0x6f, 0xee, 0x96, 0xcd, 0x29, 0xc6, 0x64, 0x00, - 0x16, 0x73, 0x7c, 0xc4, 0x55, 0x3f, 0x25, 0x04, 0x08, 0x75, 0x74, 0x68, 0xbc, 0xe4, 0x3a, 0xae, 0x4c, 0x0e, 0xd2, 0x85, 0xa1, 0xbc, 0x81, 0xc0, 0xc9, 0xfe, 0x9a, 0x44, 0x7b, 0x83, 0xdf, 0xc7 } }, - { { 0x5e, 0xc5, 0x5b, 0x9c, 0xdb, 0x14, 0x05, 0x18, 0x6b, 0xe2, 0x1d, 0x16, 0x77, 0x22, 0x0e, 0xd2, 0xe4, 0x57, 0x82, 0x6e, 0x5b, 0xc5, 0x6a, 0xb9, 0x34, 0x20, 0xdb, 0x72, 0xe2, 0xe1, 0xeb, 0x1b, - 0x34, 0x00, 0x04, 0xbf, 0x83, 0xf6, 0x4f, 0x12, 0x45, 0x08, 0xf0, 0x95, 0x2a, 0xdc, 0x3a, 0x14, 0xb3, 0x29, 0x0b, 0x99, 0xcd, 0x73, 0x31, 0xbd, 0x04, 0xbb, 0x49, 0x1c, 0xde, 0xcf, 0x09, 0x9e }, - { 0x15, 0x80, 0x3e, 0x2a, 0xfb, 0xc0, 0x8d, 0x62, 0x19, 0x27, 0x83, 0x04, 0xcc, 0xf5, 0xd1, 0xbb, 0x40, 0x41, 0xbe, 0x93, 0x59, 0x6e, 0x27, 0x6d, 0x95, 0x24, 0x0a, 0x07, 0x27, 0x86, 0x10, 0x75, - 0xf7, 0x0a, 0x11, 0xfc, 0x53, 0xd0, 0x4c, 0x15, 0xf8, 0x6e, 0x22, 0x3f, 0xeb, 0x12, 0x97, 0x8a, 0x3d, 0x69, 0xd8, 0x96, 0xc9, 0x53, 0x10, 0x9c, 0x02, 0x95, 0xe4, 0xd3, 0x1a, 0xd5, 0x43, 0x82 }, - { 0x40, 0x09, 0x2c, 0x17, 0x7e, 0xba, 0xce, 0x1f, 0xfc, 0xc1, 0x8e, 0xc3, 0x1c, 0xa2, 0x34, 0x52, 0x78, 0x16, 0x23, 0x71, 0x82, 0x40, 0xf8, 0x6d, 0x67, 0x65, 0x67, 0x50, 0x53, 0xd9, 0xc8, 0x5e, - 0x7e, 0x8a, 0x98, 0xa3, 0xc6, 0x2a, 0x4d, 0x27, 0xf3, 0xb9, 0xbb, 0xae, 0x43, 0x29, 0x6e, 0x02, 0x1c, 0xe9, 0x01, 0xd6, 0xcd, 0xd8, 0x91, 0x44, 0x95, 0x2b, 0x9e, 0xa5, 0x4f, 0xd0, 0x00, 0xb9 }, - { 0x3a, 0xe8, 0x3d, 0xb3, 0x32, 0xdc, 0xc2, 0xc8, 0xe3, 0x36, 0x2f, 0xc9, 0x30, 0x3a, 0xc0, 0x76, 0x56, 0xd3, 0x0b, 0x06, 0xbe, 0x8f, 0xe7, 0xf1, 0x66, 0x61, 0x25, 0x42, 0x28, 0xdc, 0x08, 0x81, - 0x84, 0x3a, 0x57, 0x96, 0x27, 0xa6, 0xcf, 0xd6, 0x8f, 0x35, 0xa2, 0xc3, 0x76, 0x86, 0x4f, 0xcf, 0x5f, 0xa1, 0x85, 0x28, 0x4f, 0x4a, 0x3a, 0xbb, 0x5c, 0x25, 0x4b, 0xcc, 0x46, 0xfe, 0xf2, 0x04 }, - { 0x62, 0xc8, 0xa2, 0x0a, 0x59, 0xb8, 0x97, 0xd2, 0x68, 0x94, 0x00, 0x3b, 0x01, 0xac, 0x91, 0x6e, 0x97, 0x8e, 0x08, 0xe3, 0xfe, 0x9f, 0x9e, 0x9f, 0x4b, 0xcc, 0x5d, 0x1d, 0xb9, 0xbf, 0x07, 0x83, - 0xfe, 0x51, 0x2a, 0xdf, 0x79, 0x2e, 0x07, 0xc9, 0x98, 0x9b, 0xbe, 0xb6, 0xe4, 0x0a, 0x20, 0x44, 0x86, 0xea, 0xb1, 0x61, 0x58, 0x11, 0x32, 0x8e, 0x7b, 0xb9, 0x67, 0x2d, 0xf0, 0x78, 0xb2, 0x93 }, - { 0x1a, 0x65, 0xb3, 0x6f, 0xa2, 0x45, 0x29, 0x53, 0xd7, 0x23, 0x4d, 0xff, 0x8e, 0xe9, 0xb9, 0xef, 0x16, 0xa0, 0xdd, 0x48, 0xdf, 0x70, 0xd2, 0xe1, 0x56, 0xca, 0xd1, 0xd0, 0x4a, 0x9d, 0x63, 0x92, - 0x2b, 0xfd, 0x7b, 0x87, 0x39, 0x3c, 0x12, 0xc7, 0xe5, 0x91, 0x31, 0x95, 0x78, 0xc4, 0x58, 0x95, 0x89, 0x6e, 0x2c, 0x90, 0xb4, 0x0b, 0xb2, 0xfe, 0x52, 0xc0, 0x86, 0xc4, 0x2e, 0x56, 0x97, 0x0c, - 0x20, 0xf2, 0xbc, 0x6a, 0x9b, 0x89, 0xfb, 0xe9, 0x85, 0x95, 0xd6, 0x22, 0x5e, 0x4d, 0x6d, 0x83, 0x9d, 0xf4, 0xbe, 0x66, 0x05, 0x32, 0xb6, 0xe2, 0xf1, 0x96, 0x42, 0xa4, 0xc8, 0x8c, 0x1b, 0xec }, - { 0x43, 0x85, 0xff, 0xb9, 0xcf, 0x04, 0x83, 0x40, 0x70, 0x3a, 0x9c, 0x48, 0xb4, 0xc2, 0x99, 0x3b, 0xa0, 0x39, 0xf1, 0x39, 0x58, 0x7f, 0xd2, 0x49, 0x94, 0x3c, 0xc3, 0xe1, 0xb6, 0x56, 0x38, 0x55, - 0x6f, 0xb5, 0x1a, 0x90, 0xa2, 0x04, 0x2f, 0x19, 0xf8, 0xb1, 0x65, 0x5a, 0xad, 0xcd, 0x1c, 0x56, 0x42, 0x38, 0xc2, 0x52, 0x09, 0xd6, 0x41, 0x98, 0x5d, 0x5f, 0xa5, 0xe7, 0xc2, 0x55, 0xa1, 0x09, - 0x20, 0xf2, 0xbc, 0x6a, 0x9b, 0x89, 0xfb, 0xe9, 0x85, 0x95, 0xd6, 0x22, 0x5e, 0x4d, 0x6d, 0x83, 0x9d, 0xf4, 0xbe, 0x66, 0x05, 0x32, 0xb6, 0xe2, 0xf1, 0x96, 0x42, 0xa4, 0xc8, 0x8c, 0x1b, 0xec } }, - { { 0xf2, 0x4a, 0x96, 0x57, 0xc3, 0x2f, 0xe6, 0x9f, 0xed, 0x7f, 0xcc, 0xe9, 0xea, 0xbe, 0xd2, 0x23, 0x4e, 0x47, 0x13, 0xd9, 0x53, 0x19, 0x31, 0x14, 0x0a, 0xd3, 0x9b, 0x95, 0xa7, 0x9c, 0x88, 0x5e, - 0x08, 0xb2, 0x16, 0xda, 0x45, 0x61, 0x1d, 0x6b, 0xdf, 0xb1, 0x14, 0x0c, 0x66, 0xfd, 0x3a, 0xbe, 0x25, 0xdc, 0xfd, 0xcd, 0xcc, 0x5e, 0x28, 0x77, 0x5a, 0xa9, 0x8b, 0x84, 0x77, 0x26, 0x9d, 0xa6 }, - { 0xea, 0xde, 0x4d, 0xab, 0x09, 0x02, 0xbf, 0x90, 0xf8, 0xae, 0x8b, 0x50, 0x01, 0xb2, 0x9d, 0x7c, 0x0a, 0x3b, 0x60, 0xda, 0x34, 0xa9, 0xbb, 0x4d, 0xa5, 0x53, 0x18, 0x65, 0xec, 0xaa, 0xc9, 0x29, - 0xb2, 0xf7, 0x74, 0x14, 0x63, 0x5f, 0x88, 0xcf, 0x4e, 0x70, 0x1b, 0x11, 0x64, 0x73, 0x15, 0x6b, 0x5a, 0x8c, 0xb8, 0x4e, 0x0f, 0x83, 0xae, 0x4b, 0x5c, 0x52, 0x1c, 0x6a, 0x0f, 0x54, 0x77, 0xc8 }, - { 0xae, 0xff, 0x55, 0xbf, 0x78, 0xb5, 0xde, 0x33, 0xeb, 0x87, 0xea, 0x13, 0x7d, 0x36, 0x22, 0x06, 0x32, 0xc4, 0x7e, 0xca, 0x65, 0x37, 0xcc, 0x83, 0x0e, 0xda, 0x54, 0xb3, 0xd2, 0xe6, 0xe7, 0x7f, - 0xe1, 0x90, 0x11, 0x25, 0x16, 0x83, 0x25, 0x43, 0xb4, 0x38, 0x06, 0xbb, 0x6c, 0x62, 0x7d, 0x84, 0x1f, 0xf3, 0x7b, 0xeb, 0xae, 0x50, 0xd8, 0xfb, 0xb9, 0xf2, 0xf9, 0xc3, 0x6f, 0x59, 0xb7, 0xb0 }, - { 0x95, 0x15, 0x83, 0x19, 0x56, 0x9c, 0x11, 0xd8, 0x31, 0x87, 0x1d, 0xe3, 0x3f, 0x07, 0x89, 0xb2, 0xcb, 0x81, 0xf0, 0xeb, 0x0b, 0x1e, 0x74, 0x08, 0xa2, 0x4a, 0x0e, 0x82, 0xc6, 0x45, 0x8c, 0x32, - 0xb4, 0x8f, 0xfd, 0x76, 0xeb, 0x5e, 0xc7, 0x62, 0xdc, 0xcb, 0xee, 0xad, 0xcf, 0xcf, 0xea, 0x33, 0x9d, 0xb0, 0x02, 0x64, 0x66, 0x77, 0x14, 0x97, 0x0c, 0x6e, 0x79, 0xe8, 0x58, 0x32, 0x0f, 0xe6 }, - { 0xcb, 0x2f, 0xaf, 0x53, 0xd8, 0x41, 0x48, 0x41, 0x6f, 0x36, 0x78, 0x80, 0x83, 0x5c, 0x0d, 0x4c, 0x1b, 0xf4, 0x39, 0xe0, 0x34, 0x4f, 0xc2, 0xb2, 0x4e, 0xf0, 0xac, 0xc2, 0xf8, 0x15, 0x7a, 0x81, - 0x9f, 0x46, 0x2b, 0xe3, 0xb9, 0x39, 0x05, 0x89, 0xa2, 0xda, 0x1a, 0x63, 0x51, 0xb4, 0x78, 0x0f, 0xfe, 0x2f, 0x9d, 0xce, 0x99, 0x38, 0xa9, 0x7e, 0xcb, 0x80, 0x57, 0x9f, 0xa2, 0x28, 0x0f, 0x6a }, - { 0x1b, 0xec, 0x67, 0x50, 0xd1, 0x28, 0x65, 0x55, 0xb8, 0xde, 0x3b, 0x2e, 0x1e, 0x33, 0xd8, 0x1b, 0xba, 0x2e, 0x78, 0x6a, 0xb8, 0x0b, 0x8c, 0xa0, 0x55, 0x34, 0x25, 0x90, 0x9a, 0xe2, 0xf5, 0xaa, - 0x95, 0x0c, 0x6f, 0x2a, 0xb0, 0x92, 0x1d, 0x48, 0x5b, 0x56, 0x8c, 0x82, 0x8f, 0xa7, 0x15, 0x75, 0x26, 0x61, 0x85, 0xc8, 0x7d, 0xda, 0xf5, 0x2a, 0xf3, 0x3c, 0x34, 0xc1, 0x20, 0x67, 0xbb, 0x04, - 0xec, 0x7c, 0xe2, 0xcb, 0x31, 0xcf, 0x23, 0xda, 0x5d, 0x8a, 0x05, 0x00, 0x9b, 0x23, 0x34, 0xd0, 0xed, 0x56, 0x10, 0x0a, 0x90, 0x6b, 0x73, 0x26, 0x6b, 0xf0, 0xd7, 0xbc, 0xd8, 0xc7, 0x89, 0xc8 }, - { 0x90, 0x43, 0x54, 0x87, 0x44, 0x00, 0x07, 0xca, 0xa8, 0x2b, 0xec, 0x55, 0xa0, 0xd2, 0x8c, 0x07, 0x03, 0xaa, 0x61, 0x1a, 0x7d, 0x0f, 0x90, 0x13, 0x67, 0x99, 0x46, 0x20, 0xcd, 0x70, 0xcb, 0xa7, - 0x96, 0xdf, 0x0c, 0x13, 0xc4, 0x41, 0x11, 0xd6, 0xc3, 0x33, 0x02, 0x96, 0x4f, 0x1d, 0xbd, 0x06, 0xa9, 0xa1, 0x31, 0x0a, 0xc3, 0xdf, 0x6d, 0x52, 0x6c, 0xc6, 0xbe, 0xc5, 0xb6, 0x2a, 0xb1, 0x0f, - 0xec, 0x7c, 0xe2, 0xcb, 0x31, 0xcf, 0x23, 0xda, 0x5d, 0x8a, 0x05, 0x00, 0x9b, 0x23, 0x34, 0xd0, 0xed, 0x56, 0x10, 0x0a, 0x90, 0x6b, 0x73, 0x26, 0x6b, 0xf0, 0xd7, 0xbc, 0xd8, 0xc7, 0x89, 0xc8 } }, - { { 0x4f, 0x3a, 0xdd, 0x0f, 0xcf, 0x7f, 0x27, 0xda, 0x27, 0xc4, 0xa6, 0x2b, 0x6b, 0xd1, 0x9f, 0x59, 0x73, 0x5f, 0xd4, 0xb7, 0xf0, 0x86, 0x16, 0xc9, 0xdd, 0xa6, 0xf9, 0x9b, 0x17, 0xb2, 0xb9, 0x71, - 0xe7, 0x4c, 0xa1, 0x17, 0x79, 0xe0, 0xcc, 0xae, 0x10, 0xec, 0x28, 0x3a, 0x09, 0xf2, 0x8b, 0x34, 0x9c, 0xac, 0x16, 0x2a, 0xa9, 0x21, 0xe8, 0xa7, 0x18, 0xc0, 0xc4, 0x9f, 0x30, 0xa0, 0x25, 0x62 }, - { 0x23, 0x4c, 0xd4, 0xae, 0x52, 0x30, 0xf6, 0x64, 0xb9, 0xe1, 0x47, 0xca, 0xf8, 0xf3, 0x3a, 0x6b, 0x8b, 0xf3, 0x29, 0xe2, 0x9b, 0x5d, 0xbb, 0x0a, 0x60, 0x52, 0x03, 0x40, 0x53, 0x5c, 0x9e, 0x35, - 0x03, 0xd4, 0xec, 0xd7, 0x67, 0xf4, 0x92, 0xd2, 0x98, 0x96, 0xf2, 0xa7, 0xf4, 0x25, 0x6a, 0x80, 0x9c, 0x75, 0xc6, 0xf2, 0x1f, 0x67, 0x11, 0x00, 0x0d, 0xda, 0x1e, 0xb2, 0x58, 0xa7, 0x8c, 0x39 }, - { 0x55, 0x1b, 0x80, 0xbb, 0xf3, 0xc5, 0x1a, 0x84, 0x34, 0xf5, 0x0a, 0x8a, 0x8a, 0xe1, 0x8c, 0xea, 0xa6, 0xfb, 0xd0, 0x26, 0xc9, 0xa2, 0x30, 0x37, 0x3e, 0xba, 0x98, 0xfe, 0x81, 0x8a, 0x52, 0x37, - 0x0b, 0x74, 0x4e, 0x3d, 0x26, 0x8f, 0x82, 0x4b, 0xc0, 0x6a, 0x01, 0x10, 0x91, 0x8f, 0x89, 0xb5, 0x62, 0x3f, 0x1e, 0x70, 0xcc, 0x25, 0x77, 0x39, 0x74, 0x88, 0xdd, 0xbc, 0xbe, 0x72, 0x08, 0x63 }, - { 0xe2, 0x9a, 0x46, 0xd2, 0x74, 0xdc, 0x0f, 0x8a, 0xa3, 0xbd, 0x20, 0xb7, 0xc7, 0xd9, 0x83, 0x4b, 0x58, 0xa6, 0xe3, 0xbd, 0xc5, 0x00, 0xb6, 0x18, 0x04, 0x25, 0x81, 0xbd, 0x99, 0xb3, 0xb1, 0x2a, - 0x7a, 0x68, 0x6d, 0xe1, 0x3e, 0x23, 0x8d, 0x29, 0x9e, 0x7a, 0x30, 0x56, 0x4c, 0x22, 0xb6, 0xf4, 0x7d, 0x7d, 0x4f, 0xfd, 0x76, 0xa5, 0x9d, 0x05, 0x41, 0x7c, 0x7a, 0x2d, 0x7b, 0xbe, 0xcf, 0x73 }, - { 0x7b, 0xae, 0x11, 0x86, 0x8a, 0x38, 0xbd, 0x56, 0x3c, 0xf3, 0x3c, 0x9c, 0x49, 0xa4, 0x68, 0x0f, 0x2b, 0xdf, 0xf2, 0xa1, 0xbc, 0xc2, 0xed, 0x08, 0x09, 0x96, 0xd0, 0x7e, 0x9b, 0xe3, 0x0a, 0x72, - 0x13, 0x03, 0xd4, 0x35, 0x0a, 0x94, 0x60, 0x09, 0x4a, 0xaa, 0xca, 0x35, 0x8e, 0xed, 0x12, 0xdd, 0x26, 0x8f, 0xf8, 0xa9, 0xa2, 0x8a, 0x7f, 0xac, 0xf3, 0x09, 0xc7, 0x22, 0xc5, 0x73, 0xec, 0xa0 }, - { 0xe9, 0xc5, 0x57, 0x0d, 0x85, 0xbf, 0x10, 0xe2, 0xd1, 0xf5, 0xd7, 0x22, 0xe9, 0x6a, 0x67, 0x8d, 0xd3, 0x9f, 0x1a, 0xef, 0x7f, 0xc0, 0x2b, 0xe1, 0xfd, 0x2c, 0xc2, 0x5f, 0x39, 0xf9, 0x34, 0xd0, - 0x87, 0x94, 0x41, 0x8a, 0x65, 0xa5, 0x20, 0x48, 0xa4, 0x20, 0x5f, 0x7a, 0xc7, 0x37, 0x00, 0x60, 0x59, 0x84, 0x2a, 0x1d, 0xff, 0x02, 0xc3, 0xe8, 0x20, 0xaa, 0x39, 0x13, 0xac, 0xf3, 0xd7, 0x05, - 0xbd, 0xef, 0x11, 0x66, 0x71, 0xb8, 0x9f, 0x1e, 0xe5, 0xee, 0x2e, 0x37, 0xfb, 0x34, 0xed, 0xc5, 0xa4, 0x40, 0x6e, 0x38, 0x31, 0x0a, 0x1c, 0xaf, 0x0d, 0xd3, 0x98, 0xac, 0x12, 0x40, 0xea, 0x9c }, - { 0xc6, 0xcd, 0x7a, 0xbd, 0x14, 0xdb, 0xe4, 0xed, 0xbf, 0x46, 0x70, 0x23, 0xbd, 0xdb, 0xc3, 0xce, 0x60, 0xd5, 0x6b, 0x17, 0x4c, 0x23, 0xfa, 0x78, 0x05, 0xcc, 0x18, 0xed, 0x42, 0x03, 0xa5, 0xb7, - 0xdf, 0x28, 0x0e, 0xd4, 0x5d, 0x31, 0xd8, 0xb9, 0xdc, 0xe9, 0xf6, 0x26, 0xc5, 0xe1, 0xb3, 0x80, 0x0d, 0x62, 0xaf, 0x2d, 0xbd, 0xd6, 0xe4, 0xbb, 0x16, 0x82, 0xc8, 0x13, 0x2a, 0x6f, 0xb9, 0x06, - 0xbd, 0xef, 0x11, 0x66, 0x71, 0xb8, 0x9f, 0x1e, 0xe5, 0xee, 0x2e, 0x37, 0xfb, 0x34, 0xed, 0xc5, 0xa4, 0x40, 0x6e, 0x38, 0x31, 0x0a, 0x1c, 0xaf, 0x0d, 0xd3, 0x98, 0xac, 0x12, 0x40, 0xea, 0x9c } }, - { { 0x6f, 0x46, 0xcd, 0x96, 0xc4, 0x13, 0xf4, 0x11, 0x62, 0x49, 0x8c, 0x5c, 0x78, 0x27, 0xef, 0xc8, 0xb9, 0xe2, 0x7d, 0xf1, 0x0d, 0x37, 0xf2, 0xfe, 0x85, 0x35, 0x82, 0x60, 0x23, 0xb6, 0x7b, 0x17, - 0xd2, 0x91, 0xef, 0x01, 0x9e, 0x99, 0x35, 0xab, 0xc7, 0xfb, 0xa1, 0xa3, 0x13, 0x44, 0x3f, 0x3c, 0x16, 0xcb, 0xd8, 0xf0, 0xbf, 0x9e, 0x65, 0x4d, 0x07, 0xe0, 0xfd, 0x8e, 0x32, 0x61, 0x95, 0xd5 }, - { 0xb7, 0x81, 0x16, 0x2f, 0xcb, 0xa4, 0x30, 0x4e, 0x6d, 0xf5, 0xf0, 0x3f, 0xfe, 0xd9, 0x81, 0x20, 0xa6, 0x0e, 0x2b, 0xa8, 0xc5, 0xed, 0x0d, 0x9a, 0x28, 0x9c, 0xe3, 0xa9, 0xb7, 0xbf, 0x87, 0x0f, - 0xa5, 0xf9, 0x33, 0xe7, 0xa6, 0x7f, 0x9b, 0xac, 0xb6, 0xcc, 0xaf, 0xfc, 0xa7, 0x4a, 0x4d, 0x36, 0x39, 0xa9, 0xb6, 0xf5, 0x09, 0xde, 0x8d, 0x37, 0x11, 0x07, 0xd1, 0x8a, 0xf5, 0x7b, 0x66, 0xe1 }, - { 0xcc, 0xe0, 0x07, 0x62, 0xbe, 0x10, 0x8c, 0x3a, 0xa2, 0x96, 0x5d, 0x11, 0xc7, 0xd5, 0x50, 0xc3, 0xbb, 0x55, 0x21, 0xc5, 0x40, 0x27, 0x7d, 0xdb, 0xad, 0xd2, 0x61, 0x2a, 0x42, 0x5f, 0x94, 0x23, - 0x77, 0x83, 0x3a, 0x99, 0xe8, 0xda, 0x79, 0x8c, 0x1e, 0xa8, 0x44, 0x04, 0xec, 0xf5, 0xd1, 0x55, 0x1e, 0x58, 0xf1, 0x6e, 0x4d, 0x27, 0xa4, 0x91, 0xec, 0x59, 0xc8, 0x17, 0x36, 0x58, 0x2a, 0x1f }, - { 0x6d, 0xf8, 0x73, 0xa3, 0x38, 0x61, 0x1d, 0x95, 0x09, 0xde, 0xe5, 0x26, 0x1b, 0x15, 0x16, 0xfb, 0xf5, 0x16, 0xa8, 0xf3, 0x9e, 0x3a, 0x6b, 0xb5, 0x8c, 0xee, 0xa8, 0x66, 0x79, 0xc3, 0x9e, 0xb4, - 0xe1, 0xc2, 0x85, 0x0e, 0x86, 0x10, 0x5a, 0x4e, 0x8b, 0x4c, 0x0a, 0x7a, 0xd8, 0x8a, 0x48, 0xf4, 0xa0, 0x79, 0x37, 0xe3, 0xa5, 0x90, 0x05, 0x5e, 0xbd, 0xa1, 0xf6, 0x09, 0x58, 0x9c, 0x6f, 0x09 }, - { 0x66, 0x47, 0x6d, 0x60, 0x06, 0x2d, 0x90, 0x8f, 0xae, 0x6c, 0x01, 0xe9, 0xb0, 0xf9, 0x6b, 0xa5, 0x4a, 0xe1, 0xdb, 0xd3, 0x64, 0x42, 0x37, 0x5c, 0x11, 0x40, 0x7a, 0xce, 0x4e, 0x83, 0xc3, 0x2c, - 0x2e, 0xd2, 0x67, 0x76, 0xfb, 0x8c, 0x5d, 0xab, 0xe8, 0xb8, 0xd6, 0x2b, 0xf8, 0x86, 0xff, 0x96, 0xf3, 0xa8, 0x0e, 0x2b, 0x1a, 0x68, 0xf5, 0xe4, 0xee, 0x49, 0xa6, 0x8c, 0x41, 0x1f, 0x97, 0xbf }, - { 0x81, 0x92, 0x4e, 0xc6, 0xab, 0x00, 0xdd, 0xf9, 0xf9, 0xb7, 0xe0, 0x0a, 0xa9, 0x3f, 0x0a, 0xf9, 0x32, 0x73, 0xf6, 0x22, 0xec, 0x95, 0xd9, 0x20, 0x8a, 0x3f, 0xeb, 0x0d, 0xc7, 0x79, 0x6f, 0xb3, - 0x85, 0xf4, 0xe1, 0x11, 0xe1, 0xcc, 0xaa, 0x1b, 0xfd, 0xf3, 0x43, 0xff, 0x66, 0x73, 0x0f, 0x09, 0xcc, 0xa4, 0x6c, 0xb8, 0x2a, 0x0f, 0x53, 0x58, 0x63, 0x32, 0x06, 0xd9, 0x6b, 0x1a, 0x14, 0x04, - 0x85, 0x3f, 0x2f, 0x2b, 0x05, 0xfb, 0xed, 0xe9, 0x08, 0x0d, 0x21, 0x49, 0xc9, 0x79, 0xdf, 0x6f, 0x77, 0x89, 0xd7, 0x74, 0x09, 0x57, 0x1a, 0xd2, 0xa7, 0x43, 0xbf, 0x08, 0x8e, 0x98, 0xbc, 0x2f }, - { 0xe3, 0xb1, 0xc4, 0x81, 0xe6, 0xec, 0x07, 0x58, 0xa4, 0xcb, 0x7e, 0xd5, 0xae, 0x9d, 0x43, 0xf1, 0xb7, 0xe2, 0x0a, 0x1f, 0xd5, 0xe8, 0x14, 0xba, 0x22, 0xff, 0xb7, 0x20, 0x76, 0x08, 0xdc, 0x9a, - 0x44, 0x4c, 0x1c, 0xcd, 0x38, 0x4d, 0xb5, 0xd8, 0xa9, 0x1b, 0x9d, 0xbb, 0x13, 0x5a, 0x6c, 0xe9, 0x5d, 0xa4, 0x42, 0x0e, 0xde, 0x9a, 0x47, 0x8a, 0x2a, 0x97, 0x42, 0x86, 0x87, 0x98, 0x3f, 0x04, - 0x85, 0x3f, 0x2f, 0x2b, 0x05, 0xfb, 0xed, 0xe9, 0x08, 0x0d, 0x21, 0x49, 0xc9, 0x79, 0xdf, 0x6f, 0x77, 0x89, 0xd7, 0x74, 0x09, 0x57, 0x1a, 0xd2, 0xa7, 0x43, 0xbf, 0x08, 0x8e, 0x98, 0xbc, 0x2f } }, - { { 0xff, 0xe3, 0x69, 0x7b, 0x62, 0x45, 0x40, 0x5f, 0x1c, 0x49, 0x65, 0xd6, 0xae, 0x24, 0x16, 0x84, 0xfa, 0x69, 0x6c, 0x1f, 0x6c, 0x65, 0xee, 0x52, 0xe9, 0x6c, 0x54, 0xc7, 0x31, 0x9b, 0xc2, 0x74, - 0x4f, 0xc0, 0x16, 0xb8, 0xf8, 0x75, 0x5f, 0x45, 0xb5, 0xf3, 0xa0, 0xd9, 0xbe, 0x25, 0x82, 0xbd, 0x3c, 0x03, 0xe0, 0x14, 0x15, 0x6a, 0xd5, 0x64, 0x08, 0x65, 0x13, 0x33, 0xc2, 0xab, 0xe0, 0x45 }, - { 0x6f, 0x5a, 0x90, 0x80, 0x25, 0x13, 0xc2, 0xa7, 0xfe, 0x1c, 0xa1, 0x07, 0x81, 0x4b, 0x09, 0xd3, 0xbd, 0xda, 0x55, 0xa8, 0xaa, 0x62, 0x19, 0x03, 0xe9, 0x9f, 0x77, 0xef, 0xff, 0xd4, 0x5e, 0x53, - 0xbc, 0x9d, 0x71, 0xb8, 0xc4, 0xc2, 0x85, 0xb9, 0xb4, 0x3d, 0x95, 0xb8, 0xfd, 0x44, 0xb7, 0xc8, 0x6f, 0x93, 0x15, 0x04, 0x16, 0x7e, 0x01, 0xf2, 0x09, 0x23, 0x96, 0x69, 0xe5, 0x65, 0x52, 0x34 }, - { 0xaf, 0xfe, 0x4f, 0x34, 0x4e, 0xfe, 0x51, 0xa5, 0xb2, 0xd8, 0x31, 0x74, 0x7b, 0xae, 0xfb, 0xb9, 0x33, 0xc1, 0xdc, 0x66, 0xe6, 0x95, 0x9e, 0xce, 0x77, 0x7d, 0x55, 0x3c, 0xa6, 0x6c, 0x09, 0x23, - 0x5a, 0x1a, 0x5e, 0x1a, 0x41, 0xd3, 0xad, 0x5f, 0x86, 0xd0, 0x14, 0xf5, 0xe0, 0xda, 0xf1, 0xce, 0x19, 0x90, 0x45, 0x0c, 0x4c, 0xb1, 0xd3, 0xc8, 0x4c, 0xdb, 0x7e, 0x49, 0xf5, 0xac, 0xde, 0xff }, - { 0x1b, 0x9b, 0x6b, 0x30, 0xd3, 0x19, 0x37, 0x83, 0xad, 0x05, 0xca, 0xba, 0x22, 0x85, 0x33, 0x7f, 0x55, 0x60, 0xe3, 0x14, 0x8c, 0x39, 0x87, 0xd1, 0x4c, 0x21, 0x27, 0xa0, 0xae, 0x4a, 0x56, 0x15, - 0x50, 0x6c, 0x99, 0xca, 0xff, 0xde, 0x10, 0xc6, 0x9f, 0x6c, 0x70, 0xd1, 0x66, 0xb4, 0x87, 0xd8, 0xfc, 0x46, 0xf2, 0xcf, 0x0c, 0xd8, 0xc3, 0x14, 0x5d, 0x27, 0xbd, 0xed, 0x32, 0x36, 0x7c, 0xed }, - { 0x64, 0x6b, 0x74, 0xc7, 0x60, 0x36, 0xc5, 0xe4, 0xb6, 0xde, 0x02, 0x1a, 0x09, 0xaf, 0x65, 0xb1, 0x94, 0xa3, 0xf4, 0x95, 0xf5, 0xb0, 0xef, 0x86, 0xb5, 0x13, 0x26, 0x0b, 0xe8, 0xc5, 0x5c, 0x77, - 0xf5, 0xe6, 0xb6, 0x10, 0x36, 0x87, 0xa3, 0xd2, 0x7c, 0x17, 0x2c, 0xb9, 0xb0, 0x90, 0x9e, 0x8c, 0x0a, 0x7d, 0x73, 0xb2, 0x29, 0xeb, 0xa7, 0x85, 0xd7, 0x04, 0x14, 0xf9, 0x77, 0xb7, 0xf4, 0x89 }, - { 0x7f, 0x1c, 0x5a, 0x57, 0x14, 0xf6, 0x30, 0x07, 0xf9, 0xfe, 0x42, 0x98, 0xcb, 0x3d, 0xac, 0x04, 0x30, 0x0d, 0xc6, 0xd0, 0x4f, 0x8a, 0xbc, 0xdd, 0x3e, 0xc3, 0xb7, 0x74, 0xc8, 0x3b, 0x1a, 0xcc, - 0x6a, 0x54, 0x9e, 0xb9, 0xbe, 0xf0, 0x7c, 0x35, 0x35, 0x1a, 0x50, 0x4c, 0xc2, 0x38, 0x41, 0x46, 0xc8, 0xc4, 0x81, 0x2b, 0x26, 0x56, 0x6f, 0x8a, 0x9f, 0x74, 0x87, 0xe0, 0x01, 0x82, 0xe2, 0x09, - 0xf3, 0x9a, 0xc5, 0x33, 0x5a, 0x7d, 0xb6, 0xbb, 0xff, 0x20, 0x4d, 0xc1, 0x99, 0x3d, 0xcc, 0x5a, 0xc7, 0xd1, 0xbe, 0x4c, 0xcf, 0xc8, 0x09, 0x79, 0x15, 0x5e, 0x0c, 0xc6, 0x26, 0x36, 0xe6, 0xd9 }, - { 0x4d, 0x2f, 0x08, 0x84, 0x32, 0xcf, 0xe0, 0x3b, 0xa8, 0x3e, 0xa5, 0xf8, 0x3a, 0xe8, 0xa9, 0x04, 0x5a, 0x74, 0x67, 0xcb, 0x41, 0x22, 0xc5, 0xc4, 0x9a, 0xa5, 0xc1, 0xa7, 0x94, 0x8b, 0xa5, 0x35, - 0x00, 0x00, 0x1a, 0xaf, 0xfb, 0xed, 0x40, 0xb8, 0x2b, 0x28, 0xf1, 0xb1, 0x02, 0xd3, 0x8b, 0xc0, 0x32, 0x4a, 0xa5, 0x0a, 0xa4, 0xc3, 0xbf, 0xb3, 0xf5, 0xb7, 0x65, 0x8e, 0x88, 0xdf, 0xd0, 0x0e, - 0xf3, 0x9a, 0xc5, 0x33, 0x5a, 0x7d, 0xb6, 0xbb, 0xff, 0x20, 0x4d, 0xc1, 0x99, 0x3d, 0xcc, 0x5a, 0xc7, 0xd1, 0xbe, 0x4c, 0xcf, 0xc8, 0x09, 0x79, 0x15, 0x5e, 0x0c, 0xc6, 0x26, 0x36, 0xe6, 0xd9 } }, - { { 0xc8, 0x8e, 0x1c, 0xea, 0x02, 0x6a, 0xfd, 0x88, 0x8b, 0xa9, 0x9d, 0xdd, 0xba, 0xea, 0x77, 0x30, 0x88, 0x1a, 0x93, 0x49, 0xda, 0x05, 0x18, 0xbb, 0x4a, 0x6a, 0x11, 0xc4, 0x48, 0x72, 0x77, 0x1f, - 0x6e, 0x2b, 0x9a, 0xe3, 0x27, 0xbe, 0xe1, 0x75, 0x32, 0x30, 0xa6, 0x12, 0x26, 0x44, 0xbf, 0xb2, 0xa5, 0x51, 0x0b, 0x48, 0x3a, 0xea, 0xc5, 0xd4, 0x24, 0x3f, 0x4e, 0xe8, 0xe5, 0xc3, 0xfb, 0xc2 }, - { 0xcb, 0x56, 0x3c, 0x00, 0x28, 0x15, 0x72, 0x16, 0x23, 0x4e, 0x2e, 0x2c, 0x8c, 0xe8, 0x7c, 0x44, 0x82, 0x2a, 0xe0, 0x57, 0xa3, 0x0a, 0xc4, 0x42, 0xb5, 0x07, 0xe1, 0x1b, 0x78, 0x8b, 0x3d, 0x4d, - 0xcb, 0xe4, 0x56, 0x72, 0x0b, 0x85, 0x52, 0xd8, 0x55, 0xe2, 0xcd, 0x38, 0xd2, 0x83, 0xb6, 0x05, 0xd2, 0x9f, 0x63, 0x9e, 0x7f, 0xca, 0xe5, 0x95, 0x36, 0x61, 0x9b, 0xca, 0x09, 0x27, 0x53, 0x82 }, - { 0x24, 0x67, 0x10, 0xd6, 0x8a, 0x1a, 0x8e, 0xb8, 0x53, 0xef, 0xb7, 0x67, 0x2a, 0xfd, 0xb8, 0xd6, 0xe3, 0xf7, 0x41, 0x95, 0x8c, 0x50, 0xca, 0x1d, 0x21, 0x21, 0x41, 0xd1, 0xef, 0x2d, 0x9b, 0x53, - 0xa9, 0x42, 0xcd, 0xda, 0x6d, 0x12, 0x1b, 0xbd, 0x0a, 0xe1, 0x4d, 0x95, 0xc6, 0xaa, 0x40, 0xfd, 0x98, 0xfb, 0x26, 0x21, 0x5e, 0xaf, 0x8e, 0x6b, 0xc9, 0x36, 0x2c, 0x66, 0x31, 0x24, 0x45, 0x87 }, - { 0x5e, 0xf9, 0x1d, 0x10, 0xb5, 0x79, 0x1f, 0x80, 0x85, 0x90, 0xc3, 0x7f, 0x2b, 0x73, 0xbf, 0x83, 0x0b, 0x5d, 0x46, 0xae, 0x79, 0xef, 0x09, 0x71, 0x29, 0xfb, 0x83, 0xde, 0x1f, 0xe2, 0xdb, 0x1b, - 0xa2, 0x22, 0xee, 0x50, 0x21, 0x9d, 0x9c, 0x35, 0x14, 0x48, 0x13, 0xa5, 0xd1, 0x68, 0xf4, 0x61, 0x1f, 0xd7, 0xe2, 0xd6, 0x42, 0x1c, 0xdc, 0x58, 0xec, 0x8b, 0x03, 0x6b, 0xdf, 0x64, 0x06, 0x30 }, - { 0xf9, 0xa6, 0x88, 0x74, 0x07, 0x19, 0x15, 0x38, 0xaf, 0xac, 0x07, 0x10, 0xe0, 0xd9, 0x22, 0xf3, 0x78, 0xb0, 0xbf, 0x60, 0xa3, 0x0f, 0xea, 0x0f, 0xa8, 0x64, 0xa9, 0xa3, 0x82, 0xe1, 0x4c, 0x29, - 0x36, 0x22, 0x6d, 0x43, 0x9c, 0xde, 0x22, 0xbf, 0xc6, 0x85, 0xf7, 0xe9, 0xe0, 0x79, 0x80, 0xfe, 0x9d, 0xd6, 0x24, 0xbd, 0x29, 0xa4, 0x8c, 0x35, 0x21, 0x87, 0x45, 0x7f, 0x88, 0xd9, 0x9a, 0x9d }, - { 0x49, 0x43, 0x19, 0x14, 0xcc, 0x4a, 0x11, 0x01, 0x05, 0xd1, 0x4e, 0x39, 0x6d, 0xb0, 0x22, 0x65, 0x32, 0x6e, 0x67, 0x04, 0x50, 0x85, 0x53, 0x42, 0x90, 0x2c, 0xc0, 0x63, 0x2f, 0xbd, 0x15, 0x90, - 0x1b, 0x3f, 0x03, 0x90, 0x16, 0x7f, 0x7b, 0x49, 0x74, 0xd0, 0x3d, 0x81, 0x80, 0x1e, 0x9e, 0x2e, 0xa9, 0x13, 0x6a, 0x10, 0x14, 0xc1, 0xfd, 0xf9, 0x25, 0x3a, 0x1d, 0x52, 0x93, 0x0a, 0x77, 0x03, - 0xa2, 0xdd, 0xce, 0x9f, 0x2a, 0x35, 0xc9, 0x93, 0x7c, 0xa2, 0x2c, 0xf6, 0x38, 0x73, 0xb3, 0xab, 0x7f, 0x55, 0xb6, 0x62, 0xa2, 0x8d, 0x6a, 0x3e, 0x88, 0x04, 0x9b, 0xa2, 0x19, 0x64, 0x55, 0x01 }, - { 0x22, 0x03, 0x49, 0x58, 0x76, 0x3c, 0x85, 0x45, 0x5e, 0x73, 0x78, 0x8f, 0x65, 0xc9, 0x50, 0xf8, 0xd7, 0x16, 0x92, 0xa4, 0xd1, 0x79, 0xce, 0xf3, 0x00, 0x34, 0x38, 0xb8, 0xcc, 0x96, 0x9f, 0xa6, - 0x87, 0x28, 0xcb, 0x19, 0x28, 0xad, 0x83, 0xb5, 0x09, 0x96, 0x54, 0xe8, 0x2a, 0xb9, 0x9b, 0xff, 0x60, 0x85, 0x31, 0x28, 0x62, 0x36, 0xd2, 0x0e, 0xad, 0x2a, 0xe1, 0x84, 0x80, 0xeb, 0x6f, 0x00, - 0xa2, 0xdd, 0xce, 0x9f, 0x2a, 0x35, 0xc9, 0x93, 0x7c, 0xa2, 0x2c, 0xf6, 0x38, 0x73, 0xb3, 0xab, 0x7f, 0x55, 0xb6, 0x62, 0xa2, 0x8d, 0x6a, 0x3e, 0x88, 0x04, 0x9b, 0xa2, 0x19, 0x64, 0x55, 0x01 } }, - { { 0xeb, 0x18, 0x95, 0x94, 0x5f, 0x15, 0x8c, 0xb8, 0x4d, 0x6e, 0x7d, 0xc0, 0x96, 0x6c, 0x52, 0xa2, 0x5f, 0x43, 0x67, 0xc2, 0x3a, 0x10, 0x5b, 0xf1, 0x8f, 0x21, 0x89, 0x06, 0x77, 0xe9, 0xab, 0x2e, - 0xcd, 0x17, 0x9c, 0x9a, 0xd7, 0x89, 0x7e, 0x53, 0x58, 0x60, 0x9b, 0xce, 0x90, 0xd9, 0x13, 0x2d, 0x78, 0xc4, 0x2c, 0x1c, 0x4c, 0xe8, 0x23, 0x70, 0xff, 0xa0, 0x42, 0x98, 0x25, 0x40, 0xd6, 0xd8 }, - { 0xb6, 0xfb, 0xdd, 0x5d, 0x35, 0xf2, 0x2b, 0x89, 0xda, 0x8e, 0x90, 0xee, 0x03, 0x4e, 0x75, 0xdb, 0x4c, 0x45, 0xc8, 0x00, 0xde, 0x06, 0x27, 0xde, 0x44, 0xb5, 0x5b, 0xc7, 0x56, 0xc3, 0xf5, 0xbb, - 0xee, 0xa6, 0x21, 0xd4, 0xd9, 0xb9, 0x24, 0x9c, 0x4c, 0xbc, 0x23, 0xe5, 0xeb, 0x05, 0xb6, 0xd0, 0xd0, 0xbf, 0x49, 0x95, 0x01, 0xb4, 0x97, 0xad, 0xb5, 0x71, 0x8d, 0x4b, 0x32, 0xd0, 0xdd, 0x1a }, - { 0xfd, 0x11, 0xd7, 0xe4, 0x46, 0xcd, 0xd8, 0x44, 0x89, 0x0a, 0xe7, 0x44, 0x59, 0xe9, 0xcf, 0x9f, 0xd6, 0xf1, 0x74, 0x56, 0x04, 0x78, 0xfa, 0x29, 0x46, 0x8a, 0x8d, 0x1b, 0xbe, 0x41, 0x92, 0x1c, - 0x8d, 0x74, 0x01, 0x1b, 0xc1, 0xf8, 0x26, 0xf4, 0xc2, 0x68, 0xc3, 0x23, 0x8c, 0x68, 0x7c, 0x0a, 0xad, 0xdd, 0x50, 0x10, 0xcf, 0xdb, 0x78, 0xc5, 0x79, 0x28, 0x37, 0x63, 0x92, 0x1a, 0x1d, 0xea }, - { 0xd2, 0x2a, 0xf0, 0x66, 0x15, 0x8b, 0xcb, 0x83, 0xcf, 0x34, 0xa1, 0x33, 0x6b, 0xd5, 0xa8, 0x98, 0x3b, 0xd7, 0x09, 0x0d, 0x70, 0xa5, 0x8a, 0xc0, 0x73, 0xcf, 0xde, 0x59, 0xd5, 0x13, 0x41, 0xd2, - 0x43, 0x8b, 0xb4, 0xc3, 0x5b, 0x6f, 0xf1, 0xed, 0x47, 0x76, 0xe6, 0x5e, 0xb8, 0x2a, 0x7e, 0x20, 0x91, 0xa0, 0x9d, 0xc1, 0xa2, 0x0a, 0x6d, 0x97, 0x7d, 0xeb, 0xe3, 0x64, 0x5f, 0x86, 0xff, 0x3e }, - { 0x45, 0xd8, 0xdc, 0xe4, 0x3a, 0x3a, 0x44, 0xdc, 0x7f, 0xa8, 0x92, 0x11, 0x1b, 0x4f, 0xfa, 0xcf, 0x21, 0xff, 0xfb, 0x20, 0xb0, 0x02, 0x6d, 0x0e, 0x1c, 0xde, 0xe8, 0x51, 0xd8, 0x2c, 0x72, 0x0e, - 0xbf, 0xf6, 0x9a, 0xd3, 0xd3, 0xfe, 0xfa, 0x98, 0x4e, 0xc2, 0xf0, 0x16, 0xda, 0x39, 0x93, 0xc4, 0xe0, 0x33, 0x9a, 0x43, 0xe8, 0x7a, 0xc5, 0x0f, 0x0b, 0xa4, 0x45, 0xf0, 0x5e, 0x7a, 0xa9, 0x42 }, - { 0xdb, 0x4e, 0x17, 0x76, 0x8b, 0x3c, 0x98, 0x7f, 0x58, 0x76, 0x97, 0xc9, 0x3f, 0x99, 0x01, 0x05, 0x42, 0x7e, 0xfd, 0x83, 0x99, 0xaa, 0x19, 0xb5, 0x72, 0x4c, 0x69, 0xed, 0x6e, 0x21, 0x79, 0x6e, - 0x3b, 0x71, 0xe5, 0xab, 0x23, 0x84, 0xe7, 0xfe, 0x58, 0x2b, 0x0d, 0x1e, 0x75, 0x7c, 0x29, 0xb3, 0x2d, 0x66, 0xc2, 0x45, 0x88, 0xac, 0x86, 0x29, 0xe4, 0xaa, 0x9e, 0x71, 0xa1, 0x88, 0xf9, 0x06, - 0xda, 0xa3, 0xdd, 0x7b, 0x6c, 0xd9, 0xc9, 0x73, 0xe9, 0x56, 0xd1, 0xee, 0x5b, 0xf9, 0xae, 0xc0, 0x29, 0xbe, 0x20, 0x6c, 0xc7, 0xf9, 0xc5, 0x2d, 0x6d, 0xad, 0x8f, 0x49, 0xf8, 0x17, 0xdb, 0x7a }, - { 0xb8, 0xb7, 0xec, 0xeb, 0x3e, 0x40, 0x77, 0x6c, 0xab, 0x10, 0xfe, 0x9f, 0xd1, 0x40, 0xfe, 0xd2, 0x88, 0x8e, 0xb0, 0x55, 0xae, 0x75, 0xb1, 0xcc, 0x9d, 0x6c, 0x11, 0x28, 0x95, 0x38, 0x9f, 0xb9, - 0x59, 0xe2, 0x29, 0xc3, 0xbc, 0x09, 0x16, 0x1f, 0x17, 0x9e, 0x15, 0x78, 0x09, 0x61, 0x07, 0x9e, 0xad, 0x67, 0x98, 0xa9, 0x24, 0xff, 0xf9, 0x4b, 0xa2, 0x76, 0x09, 0xa0, 0xd7, 0x1b, 0xed, 0x05, - 0xda, 0xa3, 0xdd, 0x7b, 0x6c, 0xd9, 0xc9, 0x73, 0xe9, 0x56, 0xd1, 0xee, 0x5b, 0xf9, 0xae, 0xc0, 0x29, 0xbe, 0x20, 0x6c, 0xc7, 0xf9, 0xc5, 0x2d, 0x6d, 0xad, 0x8f, 0x49, 0xf8, 0x17, 0xdb, 0x7a } }, - { { 0xc3, 0x92, 0x4d, 0x01, 0x9c, 0xea, 0x5a, 0x8d, 0xbd, 0x5c, 0x12, 0x58, 0x6d, 0x03, 0x26, 0xbf, 0xa4, 0xdd, 0xf7, 0x26, 0xa4, 0x0d, 0x22, 0xe0, 0xbd, 0xcc, 0x6f, 0x30, 0x9e, 0xf9, 0x4c, 0x1f, - 0x03, 0x52, 0xab, 0x38, 0xe9, 0x9c, 0x08, 0x9c, 0x09, 0xe5, 0x87, 0x5c, 0x24, 0x1a, 0xe2, 0x75, 0xcb, 0x18, 0x8a, 0x63, 0x50, 0xd1, 0x23, 0x45, 0x49, 0x93, 0x40, 0x2c, 0x09, 0xd4, 0xac, 0x39 }, - { 0xd4, 0xe7, 0xb7, 0x05, 0xfd, 0xd6, 0xf3, 0x57, 0xfb, 0xc2, 0x2f, 0x2c, 0x71, 0x80, 0xf5, 0xc3, 0xa6, 0x0a, 0x23, 0x9d, 0x1d, 0xa8, 0x68, 0x10, 0x8a, 0xfa, 0x68, 0x9d, 0x2b, 0xcf, 0x96, 0xa9, - 0xe6, 0x0e, 0x07, 0x32, 0x23, 0x09, 0x87, 0x16, 0xc5, 0xbb, 0x76, 0x22, 0xfc, 0xb4, 0x59, 0x6d, 0x67, 0xfd, 0x29, 0x51, 0x95, 0x4c, 0xe2, 0x8c, 0x18, 0xab, 0xda, 0x84, 0xc3, 0x62, 0x80, 0x14 }, - { 0xc9, 0xa1, 0xfe, 0xc3, 0x48, 0x0d, 0xee, 0x54, 0x44, 0xff, 0x9c, 0x46, 0x04, 0x0e, 0x74, 0xda, 0xa4, 0x6a, 0x56, 0x02, 0x5f, 0x76, 0x0e, 0xb5, 0xc1, 0xc9, 0xe9, 0xb2, 0x6e, 0x07, 0x49, 0x0c, - 0xf7, 0x4b, 0xee, 0xd6, 0x0a, 0xad, 0x94, 0x03, 0x58, 0x2d, 0x60, 0x95, 0xf8, 0x16, 0x7b, 0x49, 0x0b, 0x01, 0x66, 0x3e, 0x17, 0x01, 0xe5, 0x54, 0x7d, 0xd7, 0xbb, 0x10, 0xd1, 0xad, 0xad, 0x79 }, - { 0xb2, 0xd8, 0x10, 0x29, 0xeb, 0xb8, 0x4e, 0x2b, 0x39, 0x85, 0x5c, 0xb3, 0xdc, 0xf5, 0x87, 0xca, 0xca, 0x9c, 0x7a, 0x8c, 0x2b, 0x08, 0xe8, 0x25, 0xe2, 0xcf, 0x70, 0xe2, 0xe6, 0xfb, 0xdb, 0x0c, - 0xc3, 0x0d, 0x71, 0x11, 0x83, 0x65, 0xf2, 0x71, 0x08, 0x1b, 0x32, 0x6e, 0x6c, 0x51, 0x50, 0xf1, 0xf6, 0x4b, 0x54, 0x63, 0x16, 0x7f, 0xfd, 0x80, 0x05, 0x61, 0x63, 0xf1, 0x80, 0x6a, 0x0b, 0xfd }, - { 0xa7, 0x4b, 0x75, 0x38, 0x90, 0x64, 0x96, 0x7b, 0xda, 0x5e, 0x08, 0x9b, 0x80, 0xc4, 0x72, 0x3f, 0x73, 0xb2, 0xdb, 0xd3, 0x4a, 0xed, 0xa4, 0xdc, 0x5c, 0x79, 0xe5, 0x0f, 0x7a, 0xd3, 0x0c, 0xac, - 0xf9, 0x99, 0x5c, 0x1a, 0x0f, 0xb3, 0x1a, 0x0f, 0x5c, 0xc3, 0x9e, 0x1a, 0x2b, 0xfa, 0xc3, 0xf0, 0x40, 0xe5, 0x5f, 0x36, 0xd2, 0x98, 0x31, 0xa1, 0xaf, 0x18, 0x5f, 0xae, 0x92, 0xf3, 0x9e, 0xc0 }, - { 0xf9, 0xbf, 0x52, 0xe6, 0xd3, 0xe1, 0x5d, 0xd3, 0x30, 0xf3, 0xa1, 0x0c, 0xc8, 0x5a, 0x97, 0x55, 0xab, 0x67, 0x67, 0xd0, 0x00, 0x62, 0x7b, 0x80, 0x70, 0xbf, 0x24, 0xd0, 0x09, 0x8b, 0x07, 0x77, - 0xeb, 0x3e, 0xf0, 0x5d, 0xdf, 0x7b, 0xa9, 0x7d, 0xa4, 0x6a, 0x0d, 0xf1, 0xac, 0x83, 0x7d, 0x64, 0xb5, 0xf4, 0xc6, 0xc4, 0x12, 0x0c, 0x55, 0x9f, 0x67, 0xbb, 0xd5, 0xe3, 0xd3, 0xdb, 0x17, 0x0f, - 0x90, 0x2f, 0x8f, 0xc9, 0xfd, 0x4e, 0x6c, 0x8b, 0xe6, 0x99, 0xfa, 0xda, 0x8f, 0x1f, 0xe6, 0xc3, 0xeb, 0xd8, 0x14, 0x20, 0xcc, 0x3c, 0x1c, 0x23, 0x77, 0x28, 0x9b, 0x22, 0x9a, 0x5a, 0x0c, 0x43 }, - { 0xa2, 0x78, 0x37, 0xc9, 0x63, 0xe1, 0x31, 0x36, 0xc2, 0x58, 0xac, 0xca, 0xbb, 0xa2, 0x84, 0xaa, 0xb3, 0x82, 0xe2, 0x19, 0xb7, 0x14, 0x96, 0x27, 0x77, 0xfa, 0xa1, 0x02, 0xaa, 0xff, 0x55, 0x82, - 0xba, 0xc0, 0x38, 0x1a, 0x69, 0x35, 0x48, 0x87, 0xc2, 0xeb, 0x48, 0x08, 0xea, 0xc5, 0x6b, 0xfc, 0x84, 0x60, 0x4e, 0xce, 0xd7, 0xd2, 0x86, 0x8b, 0x76, 0xf3, 0x46, 0xe1, 0x87, 0x1f, 0xff, 0x09, - 0x90, 0x2f, 0x8f, 0xc9, 0xfd, 0x4e, 0x6c, 0x8b, 0xe6, 0x99, 0xfa, 0xda, 0x8f, 0x1f, 0xe6, 0xc3, 0xeb, 0xd8, 0x14, 0x20, 0xcc, 0x3c, 0x1c, 0x23, 0x77, 0x28, 0x9b, 0x22, 0x9a, 0x5a, 0x0c, 0x43 } }, - { { 0x0e, 0xa6, 0x0c, 0xef, 0x12, 0xd6, 0x7d, 0x71, 0xd4, 0x88, 0x73, 0x86, 0x9a, 0x88, 0x8f, 0x5b, 0xd1, 0xb6, 0x12, 0xc4, 0x93, 0x8b, 0x5f, 0xee, 0xdd, 0x9c, 0x2a, 0x7f, 0x4d, 0xfd, 0xba, 0x00, - 0x09, 0x45, 0x77, 0xd2, 0xcf, 0xcd, 0x3a, 0x6f, 0x27, 0x44, 0xe2, 0x55, 0x3e, 0x79, 0x88, 0x4d, 0x5f, 0x38, 0x34, 0xe8, 0xe7, 0xc6, 0x3a, 0xde, 0xef, 0x99, 0x15, 0xea, 0x88, 0x79, 0xd7, 0xca }, - { 0xa0, 0x9a, 0x0a, 0x3a, 0x42, 0x35, 0x54, 0x78, 0xb9, 0x82, 0x52, 0xb4, 0xc8, 0x5c, 0x4a, 0x03, 0xa1, 0xb9, 0x27, 0xcc, 0x99, 0xec, 0x03, 0xdf, 0xdd, 0x6e, 0xde, 0xef, 0x8f, 0x7f, 0xdc, 0x5a, - 0xc3, 0xcb, 0x0e, 0xa2, 0x7e, 0x93, 0xe6, 0xdd, 0xbd, 0xf1, 0x1b, 0x03, 0x29, 0x63, 0x72, 0x11, 0x72, 0x3d, 0x24, 0x6f, 0xdf, 0x8e, 0xed, 0xa4, 0xe2, 0x2a, 0x4c, 0x00, 0xe2, 0xc4, 0x55, 0x1b }, - { 0xb2, 0xf1, 0xff, 0xf6, 0x3a, 0x26, 0xe1, 0x74, 0x52, 0xba, 0xee, 0x28, 0xb6, 0x56, 0x90, 0x59, 0xde, 0x92, 0x5f, 0x84, 0xd1, 0x87, 0xe2, 0x64, 0xce, 0xdc, 0x94, 0x3c, 0xb4, 0xf8, 0x01, 0x0a, - 0x86, 0x2f, 0xfe, 0x79, 0x03, 0x72, 0xfc, 0x26, 0x21, 0xc3, 0x1e, 0xec, 0x63, 0x29, 0x64, 0xcb, 0x5f, 0xcc, 0xb6, 0x78, 0xf7, 0xc8, 0xd1, 0xf8, 0x5c, 0xc4, 0x4b, 0xc0, 0xc3, 0x75, 0x3e, 0x46 }, - { 0x03, 0x4b, 0xb9, 0xd1, 0x50, 0xa3, 0x79, 0xbe, 0x74, 0xa3, 0xb5, 0xd8, 0x28, 0x1b, 0x6d, 0x72, 0x68, 0x0a, 0x9b, 0x19, 0xc9, 0x13, 0xc4, 0x04, 0x94, 0x0a, 0xcb, 0x72, 0xff, 0x7d, 0xb6, 0x9a, - 0x1c, 0xfd, 0xe4, 0xa3, 0x75, 0x13, 0x57, 0x36, 0xfe, 0x4a, 0xf6, 0xbc, 0xca, 0xd9, 0x34, 0x9b, 0xef, 0x90, 0x02, 0xd9, 0xbd, 0xdd, 0x6f, 0x22, 0x54, 0x36, 0xb2, 0x3f, 0x22, 0x65, 0xef, 0xe7 }, - { 0x04, 0xd4, 0x43, 0xe8, 0x8c, 0xc4, 0xfb, 0xe5, 0x55, 0xd0, 0xa4, 0xea, 0x20, 0xf8, 0xe1, 0x8f, 0xc2, 0xbc, 0x1f, 0x55, 0xf1, 0x8d, 0xda, 0xc0, 0x85, 0xa4, 0xef, 0x36, 0x97, 0x22, 0x8b, 0x8e, - 0x77, 0x4c, 0x1a, 0xa4, 0xa0, 0x6f, 0xe1, 0xdc, 0x32, 0x47, 0xc4, 0x3a, 0xd8, 0x8a, 0xbd, 0x19, 0x30, 0x1c, 0x96, 0x7a, 0xb2, 0x23, 0x7c, 0x16, 0x03, 0xa7, 0x4f, 0xfd, 0xa6, 0x50, 0xd9, 0xf7 }, - { 0xdf, 0xc2, 0x59, 0xd2, 0xa9, 0x9b, 0x1e, 0xca, 0xf0, 0x39, 0x2f, 0xf8, 0xc2, 0xf3, 0x91, 0x55, 0x1b, 0xba, 0x81, 0x3a, 0x67, 0x1a, 0xd4, 0xf4, 0xb0, 0x9f, 0xb6, 0x18, 0x38, 0x65, 0x3e, 0x67, - 0xa0, 0x37, 0xc2, 0x9a, 0xc7, 0xee, 0x72, 0x8e, 0x13, 0x64, 0xd1, 0x0a, 0xda, 0xbd, 0x8d, 0xa4, 0x28, 0x55, 0x3a, 0x2c, 0x78, 0x41, 0xc6, 0xfc, 0x1c, 0x0f, 0xf8, 0xd7, 0x5f, 0xe6, 0xde, 0x0b, - 0xd5, 0xc0, 0xaa, 0x2c, 0x5c, 0xac, 0x46, 0xeb, 0xa4, 0x35, 0x2a, 0xab, 0x00, 0x2e, 0xc0, 0x8b, 0x42, 0x65, 0x2f, 0x2f, 0x13, 0x84, 0x60, 0x15, 0xa3, 0x69, 0xee, 0xab, 0x0e, 0x50, 0xbf, 0x5f }, - { 0xc1, 0xb0, 0xac, 0x4c, 0xfa, 0x62, 0x52, 0x22, 0xae, 0x8c, 0x94, 0x38, 0xd9, 0x6e, 0x10, 0x94, 0xe7, 0xaa, 0xc0, 0x92, 0x93, 0x06, 0x55, 0xf9, 0x2e, 0xd9, 0x10, 0x4d, 0xcb, 0x82, 0x19, 0x1f, - 0x27, 0x16, 0x81, 0xdd, 0xea, 0x7a, 0xa8, 0xce, 0x5a, 0xdd, 0x37, 0x77, 0x24, 0x57, 0xfb, 0x40, 0x3d, 0x1b, 0x48, 0x88, 0xda, 0xce, 0xe8, 0xd2, 0xed, 0xe0, 0x6e, 0x29, 0xeb, 0xdb, 0x95, 0x09, - 0xd5, 0xc0, 0xaa, 0x2c, 0x5c, 0xac, 0x46, 0xeb, 0xa4, 0x35, 0x2a, 0xab, 0x00, 0x2e, 0xc0, 0x8b, 0x42, 0x65, 0x2f, 0x2f, 0x13, 0x84, 0x60, 0x15, 0xa3, 0x69, 0xee, 0xab, 0x0e, 0x50, 0xbf, 0x5f } }, - { { 0x3a, 0x79, 0x39, 0x60, 0xe9, 0x93, 0xad, 0x78, 0xf9, 0x0b, 0x99, 0x64, 0x71, 0x76, 0xad, 0xdc, 0x63, 0xa3, 0x38, 0xbf, 0x0a, 0x36, 0x22, 0xcf, 0x4f, 0x84, 0x3e, 0x34, 0xaf, 0x0b, 0xd4, 0x5c, - 0xc0, 0xa4, 0x01, 0x7c, 0x07, 0xc3, 0xb4, 0xcb, 0xdb, 0x39, 0xdd, 0x39, 0xc7, 0x5c, 0xbd, 0xcf, 0x61, 0x8b, 0x72, 0x74, 0xd6, 0x85, 0xdc, 0x5c, 0x08, 0x93, 0x6d, 0xe6, 0xf1, 0xeb, 0xb9, 0x7c }, - { 0x71, 0x12, 0x20, 0xbb, 0x37, 0xa6, 0xd8, 0x71, 0xf7, 0x58, 0xaa, 0xbd, 0x30, 0xfb, 0xac, 0x94, 0x62, 0x45, 0xf0, 0x1a, 0xc3, 0x4a, 0x07, 0x78, 0x6d, 0x17, 0xf5, 0x8d, 0x69, 0x3d, 0x2e, 0x15, - 0x96, 0x48, 0x1a, 0xb0, 0x7e, 0xdd, 0xf5, 0x2d, 0xe1, 0x56, 0xfc, 0xe9, 0x26, 0x91, 0x51, 0xfe, 0x5e, 0x2a, 0xdc, 0x23, 0x89, 0x09, 0x14, 0xe6, 0x17, 0xa9, 0x14, 0x8c, 0x8c, 0xe8, 0xe3, 0x71 }, - { 0xe4, 0xd0, 0xa7, 0x5a, 0xce, 0x93, 0x1d, 0x55, 0xa2, 0x3d, 0xdd, 0x7e, 0x10, 0x66, 0x6d, 0xc6, 0x5c, 0x87, 0x9f, 0x7a, 0x52, 0x5e, 0x76, 0x3f, 0x09, 0x9e, 0xe5, 0x8e, 0x60, 0x39, 0x5e, 0x3c, - 0x28, 0x31, 0xa4, 0x12, 0x39, 0xfd, 0xba, 0xda, 0xc8, 0x59, 0xdd, 0x5b, 0x26, 0x78, 0x8f, 0x33, 0xd2, 0xc8, 0x22, 0x77, 0x49, 0xcf, 0x34, 0x61, 0xbe, 0x7a, 0xa6, 0x31, 0xbe, 0xe5, 0xab, 0xc2 }, - { 0x60, 0xf5, 0x52, 0xbd, 0xb1, 0x9e, 0x06, 0xa3, 0x94, 0xad, 0xe0, 0x82, 0x33, 0x7c, 0x41, 0x17, 0x5b, 0x8a, 0xbc, 0x7c, 0xce, 0xd1, 0x7e, 0xfd, 0x39, 0x17, 0xfd, 0x90, 0x5a, 0x53, 0x89, 0x27, - 0x9f, 0x27, 0x7a, 0x08, 0xb2, 0x66, 0xda, 0xb5, 0xbf, 0x3b, 0x80, 0xe2, 0x1a, 0x30, 0x80, 0x45, 0x13, 0xf3, 0x4b, 0x0c, 0x4a, 0xe9, 0x0a, 0x6e, 0xf2, 0x3e, 0xa3, 0x70, 0x3d, 0x89, 0xd3, 0xb2 }, - { 0x23, 0x41, 0x08, 0x8d, 0xa8, 0x0b, 0x6a, 0xe0, 0x65, 0xb1, 0x42, 0x50, 0x49, 0xdd, 0xd3, 0xe8, 0x89, 0x13, 0x7a, 0x04, 0xf0, 0xd6, 0x2f, 0x6e, 0x73, 0xcd, 0xdc, 0x10, 0xbb, 0x02, 0x6b, 0xa2, - 0x25, 0x58, 0xa3, 0x08, 0x37, 0x7c, 0x8b, 0x1f, 0x4a, 0x81, 0x38, 0x88, 0xbd, 0xf4, 0x4f, 0x24, 0xe8, 0xd6, 0x9f, 0x2f, 0x13, 0xeb, 0x79, 0x60, 0x80, 0x90, 0x52, 0x6b, 0x8e, 0xed, 0xcb, 0x77 }, - { 0x5b, 0x88, 0x63, 0xaf, 0xf9, 0xe2, 0x44, 0x23, 0xc8, 0x02, 0xe0, 0x22, 0x15, 0x3d, 0x2a, 0xb7, 0x40, 0x76, 0xe8, 0x95, 0xfd, 0xa9, 0xe3, 0x85, 0x94, 0xa3, 0xbb, 0xce, 0x61, 0x19, 0x0d, 0xe2, - 0x95, 0xdf, 0x81, 0x11, 0x53, 0x77, 0xcd, 0xf2, 0xd8, 0x4f, 0xbf, 0x19, 0x6a, 0x3d, 0x4b, 0xda, 0xa4, 0x56, 0xa4, 0xcd, 0x9d, 0x4f, 0x52, 0x53, 0x7d, 0xd8, 0xac, 0xe0, 0xfb, 0x9a, 0x71, 0x0c, - 0x59, 0xf9, 0x0b, 0x03, 0xf1, 0x7b, 0xaf, 0x33, 0xc3, 0xe5, 0x1e, 0x8d, 0x4f, 0xbe, 0x21, 0xed, 0x6b, 0x15, 0xdd, 0xd2, 0xeb, 0x7c, 0xe4, 0x59, 0x6c, 0xf9, 0x91, 0xc1, 0x3a, 0x3a, 0xb6, 0x2b }, - { 0x5e, 0x54, 0xe5, 0x1b, 0x3d, 0x2c, 0x00, 0x80, 0xdd, 0xe4, 0x10, 0x50, 0x98, 0xb6, 0x0e, 0x3a, 0xf7, 0xde, 0x67, 0x2c, 0x8e, 0x7b, 0xb4, 0x73, 0x0b, 0xc7, 0x12, 0xb0, 0x66, 0x6b, 0x3b, 0x99, - 0xd9, 0x33, 0x78, 0x5f, 0x45, 0xe5, 0xec, 0x15, 0x02, 0xfa, 0x8b, 0x86, 0xfd, 0xe0, 0xb7, 0x84, 0x72, 0xf2, 0x68, 0x5c, 0xd6, 0x2e, 0x37, 0xe9, 0x49, 0x32, 0x2f, 0xcd, 0xcd, 0x1e, 0x99, 0x0f, - 0x59, 0xf9, 0x0b, 0x03, 0xf1, 0x7b, 0xaf, 0x33, 0xc3, 0xe5, 0x1e, 0x8d, 0x4f, 0xbe, 0x21, 0xed, 0x6b, 0x15, 0xdd, 0xd2, 0xeb, 0x7c, 0xe4, 0x59, 0x6c, 0xf9, 0x91, 0xc1, 0x3a, 0x3a, 0xb6, 0x2b } }, - { { 0xfc, 0xb9, 0x4e, 0x4e, 0x11, 0xfe, 0xe1, 0xc5, 0xc7, 0x49, 0x54, 0xd2, 0x2f, 0x13, 0x34, 0x7c, 0x91, 0x7d, 0x98, 0x43, 0xe4, 0xb7, 0x48, 0xea, 0xe8, 0x26, 0xcb, 0x26, 0x1f, 0xe4, 0x99, 0x10, - 0xb9, 0x34, 0xc2, 0xac, 0xa3, 0x2c, 0xbd, 0x9e, 0x80, 0xd4, 0x12, 0x3b, 0xb3, 0xf0, 0x01, 0xae, 0x91, 0x9f, 0xba, 0x77, 0x32, 0x4d, 0x9d, 0xac, 0x1f, 0x8d, 0xad, 0xa7, 0x46, 0x44, 0x85, 0xfb }, - { 0x65, 0x05, 0x0b, 0xd2, 0x41, 0xd3, 0x58, 0x2a, 0x14, 0xbc, 0x7b, 0x15, 0x4a, 0x6a, 0x6a, 0x18, 0x71, 0x09, 0x25, 0x33, 0xac, 0x73, 0x53, 0xab, 0xd9, 0x0d, 0x8d, 0xdf, 0x95, 0x59, 0x7e, 0x02, - 0x4c, 0x03, 0x11, 0x5c, 0xdc, 0x80, 0x19, 0xd5, 0x13, 0x66, 0x7f, 0xf7, 0xd7, 0x23, 0x18, 0x40, 0x84, 0x16, 0x6b, 0x52, 0x82, 0x96, 0x05, 0x1b, 0xfa, 0xcb, 0x4b, 0x77, 0x00, 0x12, 0xa0, 0x28 }, - { 0x13, 0xe0, 0x16, 0x1e, 0x24, 0x24, 0xe9, 0xde, 0x9c, 0x86, 0xa9, 0xcf, 0x02, 0x96, 0xdf, 0x8c, 0x64, 0xcb, 0x3d, 0x7d, 0x8a, 0x2a, 0x73, 0x18, 0x20, 0xc8, 0xb0, 0xac, 0x10, 0xa0, 0x52, 0x0c, - 0x6c, 0x17, 0xd9, 0xbd, 0x3c, 0x3e, 0xe5, 0x0c, 0x4a, 0xdb, 0x59, 0xcc, 0x59, 0x15, 0x08, 0x1e, 0xfe, 0xaa, 0xe3, 0xd6, 0xa1, 0x37, 0xd6, 0xd5, 0x6d, 0x8e, 0xcd, 0x57, 0xa9, 0x81, 0xb3, 0x43 }, - { 0x46, 0x28, 0x2b, 0xa0, 0xe5, 0xe3, 0xf0, 0x72, 0xa7, 0xbc, 0x8d, 0xec, 0x45, 0x31, 0x6e, 0xdb, 0xb2, 0x4b, 0x20, 0xbf, 0x64, 0x74, 0x26, 0x70, 0x9b, 0xd6, 0xd3, 0x7f, 0x9f, 0xc1, 0x59, 0x03, - 0x2d, 0xda, 0x6f, 0xaa, 0x7c, 0x92, 0xc6, 0xe0, 0xe8, 0xaa, 0x1e, 0x26, 0xf0, 0x1e, 0xcc, 0xef, 0x6d, 0x87, 0x04, 0x3c, 0xed, 0x52, 0x15, 0xb3, 0x9f, 0x01, 0x4e, 0xe3, 0x3c, 0xb6, 0xbb, 0xac }, - { 0x86, 0x1a, 0x25, 0x8e, 0x41, 0x85, 0xf9, 0xba, 0x98, 0x15, 0xb1, 0xec, 0x50, 0xb4, 0xd0, 0xab, 0x55, 0x54, 0xbb, 0x3b, 0x61, 0xfc, 0x54, 0xf3, 0x09, 0xea, 0xaa, 0x6e, 0xbf, 0x03, 0xc3, 0x58, - 0x1d, 0x24, 0xb5, 0xd5, 0x45, 0x5a, 0x7a, 0x14, 0xc3, 0x6a, 0xa9, 0xd8, 0x6f, 0x41, 0xc3, 0xb4, 0x9a, 0x05, 0x71, 0xbc, 0x23, 0x67, 0xc2, 0xa8, 0xf5, 0x7b, 0x69, 0xa5, 0xe1, 0x7a, 0x35, 0x1d }, - { 0x3b, 0xf5, 0xa8, 0xc0, 0x2a, 0x7d, 0x85, 0x88, 0xd4, 0xf4, 0x26, 0xd3, 0xf4, 0xe3, 0x52, 0x35, 0x37, 0x06, 0x1e, 0x71, 0xc2, 0x3b, 0x7b, 0xeb, 0xf0, 0x07, 0x30, 0x6b, 0x37, 0x31, 0xb9, 0x27, - 0xd8, 0x0b, 0x17, 0xae, 0xff, 0xd4, 0x7c, 0x59, 0xd7, 0x2d, 0xea, 0xcb, 0x92, 0x2f, 0x93, 0xc7, 0xd7, 0xc3, 0xaf, 0x75, 0x73, 0x6a, 0x3f, 0x89, 0xe5, 0x13, 0x0c, 0x28, 0x47, 0xf4, 0xa4, 0x07, - 0xfb, 0xd9, 0x77, 0xb4, 0x1e, 0xb2, 0x70, 0xca, 0x85, 0x22, 0x58, 0xc6, 0x0b, 0x19, 0xc2, 0xa5, 0xba, 0xc3, 0xc9, 0xb6, 0x4a, 0xdb, 0x7d, 0x4d, 0x66, 0xde, 0xeb, 0x8c, 0x1a, 0x23, 0xb8, 0x4c }, - { 0x8c, 0x57, 0x0e, 0x9f, 0x0a, 0xb2, 0xf4, 0x07, 0xdd, 0x7b, 0x46, 0xf8, 0xa0, 0xb1, 0x33, 0x4c, 0x2b, 0x1e, 0x1a, 0xe0, 0x28, 0x17, 0x14, 0xba, 0x14, 0x06, 0x40, 0x1f, 0x30, 0x0a, 0x19, 0xcd, - 0xe7, 0xca, 0xfb, 0xdb, 0xb9, 0x76, 0xf8, 0x8a, 0x81, 0x3d, 0x03, 0x86, 0x7e, 0x66, 0x75, 0x1d, 0xec, 0xff, 0x6b, 0xa7, 0xea, 0x4c, 0x8c, 0x60, 0xd2, 0x1f, 0x72, 0x11, 0x4c, 0x5d, 0xeb, 0x01, - 0xfb, 0xd9, 0x77, 0xb4, 0x1e, 0xb2, 0x70, 0xca, 0x85, 0x22, 0x58, 0xc6, 0x0b, 0x19, 0xc2, 0xa5, 0xba, 0xc3, 0xc9, 0xb6, 0x4a, 0xdb, 0x7d, 0x4d, 0x66, 0xde, 0xeb, 0x8c, 0x1a, 0x23, 0xb8, 0x4c } }, - { { 0x05, 0x64, 0x16, 0x53, 0xbb, 0xb2, 0x6e, 0x81, 0xfc, 0xe6, 0xec, 0xc8, 0x0c, 0xc1, 0x75, 0x59, 0x23, 0xe2, 0x4b, 0xd8, 0x6a, 0x70, 0x34, 0x50, 0x37, 0xc6, 0xc2, 0xbd, 0x27, 0xfd, 0xad, 0x4c, - 0xee, 0xe4, 0xf7, 0xfc, 0x91, 0x05, 0x48, 0x3c, 0xd4, 0x09, 0x78, 0x00, 0xce, 0x15, 0x37, 0xdc, 0xe7, 0xce, 0x48, 0x09, 0x3e, 0x7f, 0x01, 0x9b, 0x03, 0xc8, 0x2f, 0x9b, 0xe6, 0x42, 0xe1, 0x71 }, - { 0x64, 0xbf, 0x63, 0x91, 0xe5, 0x3e, 0x90, 0x89, 0x96, 0xea, 0x59, 0x51, 0x60, 0x7b, 0x5f, 0xfe, 0x0f, 0x76, 0x86, 0x19, 0x45, 0x82, 0xd9, 0x5e, 0x1a, 0xd1, 0xf6, 0x04, 0xc6, 0xaa, 0x71, 0xda, - 0x80, 0xed, 0x75, 0x51, 0xc8, 0x9a, 0x27, 0x09, 0xc3, 0x50, 0xe4, 0x14, 0xa1, 0xc3, 0xf8, 0x3a, 0x6c, 0x84, 0xff, 0x87, 0xd5, 0xf0, 0xb0, 0x3c, 0x5a, 0x57, 0x14, 0x90, 0xc7, 0x31, 0xf8, 0x47 }, - { 0x88, 0x7d, 0xcc, 0x81, 0x2b, 0xbb, 0x7e, 0x96, 0xbe, 0x78, 0xe1, 0xb1, 0xf2, 0xed, 0x6f, 0xd8, 0xff, 0xbd, 0x7f, 0x8e, 0xe5, 0xeb, 0x7f, 0x7b, 0xca, 0xaf, 0x9b, 0x08, 0x1a, 0x77, 0x69, 0x1d, - 0xc2, 0xa4, 0x7c, 0x4d, 0xa6, 0x74, 0x8e, 0x33, 0x24, 0xff, 0x43, 0xe1, 0x8c, 0x59, 0xae, 0x5f, 0x95, 0xa4, 0x35, 0x9e, 0x61, 0xb8, 0xcc, 0x4c, 0x87, 0xb9, 0x76, 0x53, 0x20, 0xa3, 0xf3, 0xf5 }, - { 0x13, 0x2a, 0xcc, 0x07, 0xb1, 0x5f, 0xc7, 0xf1, 0x08, 0x0e, 0x7d, 0x7e, 0x26, 0x56, 0xd8, 0x16, 0x9c, 0xae, 0xac, 0xc4, 0xf5, 0x9c, 0x15, 0x67, 0xae, 0xc4, 0xcc, 0x3f, 0xc0, 0xaf, 0x53, 0x28, - 0x1f, 0x65, 0x14, 0xe5, 0x7f, 0x0c, 0xf5, 0x7a, 0xe3, 0x93, 0xc1, 0xa3, 0xd1, 0x4a, 0x09, 0x7d, 0x24, 0xab, 0x22, 0xc4, 0xc4, 0xce, 0x85, 0x37, 0x86, 0xa8, 0x9c, 0x39, 0x33, 0xba, 0x1b, 0x83 }, - { 0x6d, 0x3e, 0x92, 0x5a, 0xa8, 0xfa, 0xe6, 0x71, 0x98, 0xa8, 0x82, 0x38, 0xcc, 0xed, 0xd6, 0x92, 0x7e, 0x3e, 0xcb, 0xb2, 0x82, 0x92, 0x7a, 0x56, 0x9e, 0xd6, 0x29, 0x45, 0x42, 0x04, 0x76, 0x82, - 0xa5, 0xfc, 0xd9, 0x0c, 0x12, 0x4c, 0x98, 0x04, 0x2a, 0x3a, 0x98, 0x01, 0xb8, 0x62, 0xe8, 0xe6, 0x7c, 0x51, 0xe3, 0x7d, 0x97, 0xf5, 0x45, 0xb4, 0x13, 0xdf, 0x15, 0x68, 0xc3, 0x00, 0x75, 0x40 }, - { 0x7e, 0x89, 0x3d, 0x7c, 0x78, 0x36, 0x3c, 0x85, 0xda, 0xb6, 0x9b, 0x6d, 0xbc, 0x52, 0x7d, 0xc6, 0xaa, 0xfd, 0x90, 0x62, 0xe4, 0xc4, 0x1a, 0x5a, 0x2e, 0xa1, 0x57, 0xd7, 0xda, 0x57, 0xf4, 0x58, - 0xc5, 0x23, 0x61, 0x21, 0xe1, 0x93, 0xfa, 0x06, 0x22, 0xed, 0x41, 0x66, 0x24, 0x47, 0xb9, 0xed, 0xc8, 0x84, 0x25, 0x28, 0x39, 0xec, 0xfb, 0x29, 0xa1, 0xcd, 0xe1, 0x9d, 0x02, 0x48, 0x6f, 0x0a, - 0xe2, 0x9f, 0x98, 0xfd, 0x3d, 0x18, 0xa1, 0x24, 0x9c, 0xc6, 0x75, 0xb8, 0x99, 0x76, 0x2a, 0xa4, 0x9e, 0xb1, 0x97, 0x2d, 0x1c, 0x99, 0x65, 0x5f, 0x1f, 0xda, 0x14, 0x4f, 0x10, 0x49, 0xf1, 0x7a }, - { 0x2c, 0xec, 0x27, 0x63, 0xd2, 0x77, 0x14, 0x2d, 0x01, 0x18, 0x10, 0xe0, 0x23, 0x1b, 0xa2, 0x25, 0x61, 0xd4, 0x52, 0xd9, 0x90, 0xde, 0x97, 0x7e, 0xb8, 0xfa, 0x38, 0x25, 0xf2, 0x91, 0x07, 0x3e, - 0xc4, 0xa9, 0x3e, 0xb5, 0x67, 0x02, 0x28, 0x94, 0x5c, 0x34, 0xa1, 0x0a, 0x5c, 0x54, 0x53, 0xd9, 0xb4, 0xc4, 0x5a, 0x8e, 0x57, 0x18, 0xc3, 0x35, 0xea, 0x47, 0x75, 0xe0, 0x44, 0x01, 0x71, 0x09, - 0xe2, 0x9f, 0x98, 0xfd, 0x3d, 0x18, 0xa1, 0x24, 0x9c, 0xc6, 0x75, 0xb8, 0x99, 0x76, 0x2a, 0xa4, 0x9e, 0xb1, 0x97, 0x2d, 0x1c, 0x99, 0x65, 0x5f, 0x1f, 0xda, 0x14, 0x4f, 0x10, 0x49, 0xf1, 0x7a } }, - { { 0x41, 0x10, 0xd9, 0x7f, 0xb8, 0x83, 0x9e, 0x42, 0x43, 0x7a, 0xb0, 0x6d, 0xa6, 0xcf, 0xa5, 0x7a, 0x50, 0x93, 0x2d, 0x13, 0x94, 0x37, 0xa8, 0x92, 0x26, 0x1f, 0xad, 0xe0, 0x25, 0x19, 0x91, 0x62, - 0x28, 0xfb, 0x18, 0xbf, 0x89, 0xb0, 0x42, 0x80, 0x14, 0xcd, 0xd2, 0x72, 0x84, 0x1c, 0xfd, 0xe5, 0xc3, 0x71, 0x3c, 0x3f, 0x12, 0x5e, 0xdd, 0x53, 0x39, 0xf6, 0x4b, 0x9f, 0xb3, 0x5c, 0xe3, 0x15 }, - { 0xd0, 0xc7, 0x18, 0x4d, 0x68, 0x9f, 0xdd, 0xec, 0x81, 0xf8, 0xc6, 0x0e, 0x83, 0x43, 0x23, 0x3d, 0xfc, 0xf3, 0x66, 0x55, 0xa8, 0x65, 0x8b, 0xd7, 0x9b, 0x3c, 0x74, 0x23, 0xcd, 0xae, 0x60, 0xe7, - 0x61, 0xed, 0x2c, 0x7e, 0xe7, 0xa7, 0x63, 0x7d, 0x72, 0x47, 0x6a, 0x33, 0x1c, 0xaa, 0x81, 0xba, 0x6f, 0xd4, 0x00, 0xe7, 0xa9, 0x58, 0xb2, 0xad, 0xee, 0x3f, 0x9c, 0x70, 0xff, 0x2f, 0x13, 0x6f }, - { 0x56, 0x7b, 0x19, 0x66, 0x42, 0x9a, 0x99, 0x51, 0x23, 0x4f, 0xb6, 0xe7, 0xcf, 0x98, 0xff, 0x20, 0x5a, 0xc3, 0x0e, 0x36, 0xc9, 0xc6, 0x20, 0x25, 0x0c, 0x56, 0x98, 0xfb, 0xbd, 0xd6, 0x66, 0x4f, - 0x6f, 0x94, 0x85, 0x8a, 0x35, 0xf3, 0x50, 0xad, 0x87, 0xde, 0x95, 0x9e, 0xae, 0x2a, 0xd8, 0xdd, 0x78, 0x87, 0x96, 0x2b, 0xe0, 0x12, 0x95, 0xd9, 0x3b, 0xb2, 0x2a, 0x06, 0xe2, 0xf0, 0x06, 0xd4 }, - { 0x42, 0x24, 0xdd, 0x0a, 0xd1, 0x11, 0x31, 0x7e, 0x56, 0x45, 0xb0, 0x0e, 0x86, 0xc1, 0x5d, 0x8c, 0x03, 0x01, 0xb8, 0x33, 0x20, 0xbd, 0x08, 0x10, 0xe5, 0x70, 0x92, 0x2b, 0x5b, 0x86, 0xd3, 0x50, - 0x4c, 0x1e, 0xe3, 0xd1, 0x2a, 0x4e, 0x40, 0x02, 0x19, 0x0b, 0xf6, 0x91, 0xd9, 0x9e, 0xaa, 0x54, 0x7c, 0x3d, 0xba, 0xc5, 0x5a, 0x9e, 0xb2, 0xbb, 0x4e, 0x0d, 0x5b, 0xdd, 0x90, 0xc9, 0x7b, 0xc2 }, - { 0x54, 0x95, 0xd5, 0xdc, 0x7e, 0x7e, 0xec, 0xd4, 0x67, 0x08, 0xdc, 0x58, 0xa9, 0x80, 0x8a, 0x03, 0x6a, 0xf8, 0x40, 0xca, 0x0d, 0x5b, 0x6c, 0xe4, 0xc9, 0x71, 0xa5, 0xaf, 0x2a, 0xaa, 0xe8, 0x95, - 0x45, 0xe7, 0xe2, 0xc3, 0x47, 0x84, 0xc6, 0xbe, 0xe5, 0x65, 0xaf, 0xcd, 0x7c, 0x20, 0x5f, 0x8b, 0x19, 0x61, 0xe4, 0xc9, 0xc1, 0x86, 0xa5, 0x6f, 0x96, 0xf3, 0x9c, 0x13, 0x28, 0x1b, 0xcf, 0x07 }, - { 0xc4, 0x7f, 0xf2, 0x6f, 0xcc, 0x4a, 0xf8, 0xa4, 0x1f, 0x1d, 0x6e, 0x5e, 0x30, 0xb2, 0x99, 0x8f, 0x5d, 0x7c, 0x26, 0x1c, 0x52, 0x6f, 0xd0, 0x33, 0xa7, 0xf8, 0xca, 0x2a, 0xc3, 0x8c, 0xa8, 0xd1, - 0x50, 0x4f, 0xa7, 0xe8, 0xf2, 0x10, 0x4c, 0xcd, 0x8a, 0x31, 0x03, 0xc8, 0x93, 0x2c, 0xd7, 0xe4, 0x21, 0xdb, 0xa2, 0x62, 0x7b, 0x1f, 0x28, 0x14, 0x69, 0x7e, 0x87, 0xac, 0xf9, 0xb4, 0x97, 0x00, - 0x62, 0x86, 0x14, 0xd7, 0xe4, 0x65, 0xdd, 0x9e, 0x1c, 0x64, 0x5f, 0x3e, 0xef, 0xfe, 0xa6, 0x60, 0x68, 0x91, 0x94, 0x8a, 0x1c, 0x89, 0xae, 0xe4, 0xcf, 0x3a, 0xdd, 0xc0, 0xb4, 0x47, 0xe8, 0x8f }, - { 0x12, 0x80, 0x00, 0xda, 0xce, 0xc4, 0x80, 0x8f, 0xa9, 0xa1, 0x5d, 0x98, 0x7d, 0x2c, 0xb2, 0x9c, 0x71, 0xde, 0x62, 0x89, 0x6a, 0xe1, 0x92, 0xd7, 0x96, 0xdc, 0xcd, 0xc8, 0x08, 0x0e, 0x48, 0xbf, - 0x2a, 0x53, 0x72, 0x90, 0x31, 0x71, 0x49, 0x02, 0xda, 0x4e, 0x19, 0x05, 0x10, 0xcb, 0x41, 0x97, 0x44, 0xdc, 0x2d, 0x1e, 0x48, 0xe5, 0x0e, 0x41, 0x9d, 0x7d, 0x03, 0xa3, 0xe2, 0x65, 0xd4, 0x01, - 0x62, 0x86, 0x14, 0xd7, 0xe4, 0x65, 0xdd, 0x9e, 0x1c, 0x64, 0x5f, 0x3e, 0xef, 0xfe, 0xa6, 0x60, 0x68, 0x91, 0x94, 0x8a, 0x1c, 0x89, 0xae, 0xe4, 0xcf, 0x3a, 0xdd, 0xc0, 0xb4, 0x47, 0xe8, 0x8f } }, - { { 0x00, 0x4b, 0x0b, 0xf5, 0x1f, 0x07, 0x1e, 0x23, 0xe3, 0x93, 0x7b, 0x31, 0x41, 0x2a, 0x0a, 0x50, 0x35, 0xe2, 0xbb, 0xfe, 0x51, 0x77, 0x6c, 0xc9, 0xc5, 0x13, 0xb9, 0x87, 0x79, 0x65, 0x68, 0x20, - 0xcc, 0x09, 0x90, 0xa9, 0xe4, 0xef, 0x9f, 0x1a, 0xe1, 0x69, 0x76, 0x14, 0x82, 0x42, 0x88, 0x4b, 0xdc, 0xe0, 0x10, 0x22, 0xe2, 0xd6, 0x36, 0x7c, 0x0b, 0xd9, 0x08, 0xea, 0xfa, 0xe4, 0xfd, 0x45 }, - { 0x57, 0x5c, 0x1e, 0x20, 0xb4, 0xae, 0x9e, 0x9d, 0x04, 0xfb, 0x1a, 0xd7, 0x23, 0xd8, 0x8a, 0x6b, 0x1b, 0xb2, 0xef, 0xa9, 0x06, 0x38, 0xbb, 0x9b, 0x43, 0x2e, 0xf1, 0x81, 0x0b, 0x76, 0xec, 0x20, - 0x46, 0x1b, 0xc4, 0x71, 0x19, 0x3e, 0x79, 0xe8, 0xcf, 0xea, 0xdc, 0x4b, 0x3f, 0x0b, 0xeb, 0x05, 0x13, 0x1a, 0x2c, 0xfe, 0x16, 0xe9, 0xf0, 0xc4, 0x9c, 0x41, 0xab, 0x45, 0x1b, 0xba, 0x05, 0xec }, - { 0x06, 0x0b, 0x73, 0xec, 0x30, 0x74, 0x0d, 0x8d, 0x13, 0x4b, 0xef, 0xac, 0x3b, 0x05, 0xb6, 0xed, 0x2b, 0x05, 0xd1, 0xa7, 0x65, 0xb0, 0xcb, 0x69, 0x00, 0xeb, 0x47, 0xe3, 0x1c, 0x07, 0x8b, 0x15, - 0xbf, 0x69, 0xff, 0x27, 0xb4, 0xdb, 0x77, 0xaf, 0xe9, 0x9a, 0xfb, 0xb2, 0x28, 0xa4, 0xf9, 0x05, 0xe4, 0x3c, 0x66, 0x56, 0x00, 0x1a, 0x2c, 0x41, 0xf2, 0xe1, 0x11, 0x09, 0xfa, 0xe1, 0x50, 0x49 }, - { 0xbc, 0x4d, 0x6f, 0x75, 0x79, 0x77, 0x64, 0x6b, 0xec, 0xac, 0x1a, 0x26, 0x73, 0x9c, 0xf3, 0xf1, 0x4d, 0x79, 0xbe, 0x6f, 0x0c, 0x07, 0x22, 0xd1, 0xa1, 0x31, 0x75, 0xa8, 0x9c, 0xb6, 0x00, 0x63, - 0x0d, 0x40, 0x17, 0xec, 0x83, 0xda, 0x82, 0x2c, 0x3b, 0xfd, 0x90, 0xe3, 0xbc, 0xc2, 0x2c, 0xf5, 0x3e, 0x41, 0xe9, 0x98, 0x57, 0xa2, 0xb7, 0xce, 0x5f, 0x31, 0xbb, 0x0b, 0x05, 0x61, 0x0f, 0x55 }, - { 0xb7, 0xab, 0xb2, 0x84, 0xf1, 0x67, 0x24, 0x16, 0x61, 0xe9, 0x20, 0x33, 0x0b, 0xff, 0x22, 0x61, 0x70, 0xa0, 0x5d, 0xf6, 0xa8, 0x33, 0xc9, 0x30, 0x73, 0xe5, 0x89, 0x36, 0x59, 0xea, 0xa8, 0xe7, - 0x03, 0xf6, 0x14, 0xc1, 0x79, 0xb6, 0x42, 0xa5, 0xc8, 0x6c, 0xb8, 0x94, 0x29, 0x24, 0x00, 0x09, 0xb5, 0x54, 0x3f, 0xe1, 0x6b, 0xfb, 0x4d, 0x2d, 0xa9, 0x9a, 0x02, 0xa1, 0xa5, 0x09, 0xf4, 0xcb }, - { 0x92, 0xfa, 0x18, 0x84, 0x3e, 0xdb, 0xdf, 0x7d, 0x87, 0xd6, 0x2d, 0x07, 0x05, 0x2c, 0xba, 0xe4, 0x30, 0x76, 0xa2, 0xe8, 0x71, 0x3b, 0x1b, 0x93, 0x5b, 0xce, 0x2e, 0xec, 0x50, 0x6e, 0x4a, 0x0b, - 0x2d, 0xbe, 0xa3, 0x76, 0x92, 0xf8, 0xc8, 0x4a, 0x71, 0x66, 0xec, 0xfa, 0x36, 0xc5, 0xdb, 0xab, 0x99, 0x9c, 0xbf, 0x99, 0x07, 0xe8, 0xfe, 0xf4, 0x2f, 0x90, 0x16, 0x5d, 0xdc, 0xbe, 0xfa, 0x08, - 0x93, 0xde, 0x13, 0xf5, 0x32, 0x45, 0x9a, 0xde, 0xa2, 0x5d, 0xb9, 0xe0, 0x38, 0x4c, 0x6a, 0xcc, 0x13, 0x46, 0x27, 0x28, 0xbf, 0xf8, 0x7a, 0x9c, 0x2e, 0xde, 0x6f, 0xfe, 0xe1, 0x86, 0x41, 0x79 }, - { 0xa7, 0x32, 0x52, 0x76, 0x4f, 0x3e, 0x1b, 0xab, 0x82, 0x18, 0x14, 0xe7, 0x42, 0x32, 0xb8, 0xa4, 0x98, 0xde, 0xa4, 0xd7, 0xae, 0x42, 0x84, 0xda, 0x71, 0xf7, 0x78, 0x40, 0x56, 0x94, 0x64, 0x49, - 0x34, 0x37, 0xeb, 0xe3, 0x05, 0x4c, 0xb9, 0xbb, 0xce, 0xb2, 0x72, 0xc0, 0x75, 0x1c, 0xc4, 0xd5, 0x1e, 0x3a, 0xc1, 0x43, 0xda, 0xd1, 0x81, 0x82, 0xa9, 0xd5, 0x0e, 0x0a, 0x5e, 0xc2, 0xd7, 0x04, - 0x93, 0xde, 0x13, 0xf5, 0x32, 0x45, 0x9a, 0xde, 0xa2, 0x5d, 0xb9, 0xe0, 0x38, 0x4c, 0x6a, 0xcc, 0x13, 0x46, 0x27, 0x28, 0xbf, 0xf8, 0x7a, 0x9c, 0x2e, 0xde, 0x6f, 0xfe, 0xe1, 0x86, 0x41, 0x79 } }, - { { 0xa3, 0xdf, 0x4a, 0xfd, 0xe6, 0x74, 0xb8, 0xeb, 0xed, 0xe7, 0x7e, 0xd2, 0xae, 0xf8, 0x40, 0x80, 0x3a, 0x55, 0x58, 0x1d, 0x6b, 0xa4, 0x32, 0x6c, 0x15, 0xbb, 0x67, 0xdf, 0x9e, 0xb5, 0x70, 0x4b, - 0x7f, 0x4d, 0xfe, 0x34, 0x42, 0x0c, 0x4d, 0xe3, 0x97, 0x87, 0x6d, 0x08, 0xe8, 0x4d, 0x8a, 0xa9, 0xbc, 0xbf, 0x1b, 0xb7, 0x66, 0x32, 0xf4, 0x7f, 0x93, 0xca, 0xa4, 0xd2, 0x8f, 0x02, 0x7b, 0xfa }, - { 0xea, 0xac, 0xdf, 0x25, 0x39, 0xf3, 0x28, 0xb6, 0xbe, 0xa8, 0x4a, 0x32, 0x59, 0x4b, 0x4f, 0xb5, 0xd2, 0xf7, 0xf5, 0x75, 0x43, 0x8b, 0xb3, 0x6a, 0x98, 0x8c, 0x14, 0xc9, 0x3f, 0x7e, 0x5c, 0x05, - 0xf0, 0xeb, 0x1d, 0xc5, 0xe6, 0x1b, 0x5d, 0x7f, 0x38, 0x5d, 0x9a, 0xbe, 0xc8, 0x97, 0x09, 0x65, 0x62, 0x88, 0x99, 0xda, 0x95, 0x13, 0x93, 0xd9, 0xa3, 0x19, 0x0a, 0xa7, 0x4a, 0xb2, 0x81, 0xa4 }, - { 0x6e, 0x70, 0x65, 0xaa, 0x1b, 0x16, 0xcb, 0xc1, 0x59, 0x6b, 0xc9, 0x4d, 0xd1, 0x0a, 0x9d, 0x8c, 0x76, 0x70, 0x3c, 0xc1, 0xc1, 0x66, 0xa6, 0x9f, 0xfc, 0xca, 0xb0, 0x3f, 0x0e, 0xe9, 0xa9, 0x36, - 0x09, 0x4f, 0x94, 0xf3, 0x32, 0x25, 0x34, 0xf6, 0xe4, 0xf9, 0x0b, 0x0c, 0xe6, 0xe0, 0x6d, 0x9e, 0xa5, 0x52, 0x82, 0x9c, 0xd4, 0x43, 0xa4, 0xd1, 0xd1, 0x63, 0x20, 0xce, 0xbc, 0x4f, 0x43, 0xdc }, - { 0x35, 0xd6, 0xc1, 0x68, 0xa6, 0xd7, 0xd3, 0x36, 0x82, 0x2a, 0x0f, 0x29, 0x3e, 0xd6, 0x15, 0x29, 0x19, 0x73, 0x14, 0x78, 0x87, 0x86, 0xca, 0x9f, 0x6e, 0x17, 0xea, 0xaf, 0x24, 0x37, 0xd6, 0xb4, - 0xb0, 0xee, 0x84, 0x90, 0x2d, 0x18, 0xbd, 0x26, 0xc3, 0xd4, 0x39, 0x4f, 0x45, 0xfa, 0x2f, 0x70, 0xf2, 0xe2, 0x2a, 0x2a, 0x5c, 0x65, 0x15, 0xcb, 0xaf, 0x92, 0x9a, 0xfc, 0x06, 0xe0, 0x8a, 0x1b }, - { 0x5d, 0xfa, 0xc0, 0x2b, 0xc3, 0x94, 0x19, 0xb4, 0xd6, 0x13, 0xe3, 0xcf, 0x91, 0xad, 0x8c, 0xe1, 0x97, 0x46, 0xfe, 0xea, 0x74, 0xe0, 0x0c, 0x03, 0xf7, 0x2e, 0x51, 0xa7, 0xf2, 0xbc, 0xce, 0xe8, - 0x6b, 0xfd, 0x2f, 0x54, 0x52, 0x12, 0x00, 0x8d, 0x95, 0x91, 0xc3, 0xf6, 0x25, 0xf8, 0x65, 0x6a, 0x9c, 0x79, 0x6b, 0x71, 0xc0, 0x0c, 0x29, 0xfb, 0xe7, 0x14, 0x9f, 0x2f, 0x1a, 0x07, 0x53, 0x50 }, - { 0xe9, 0xd4, 0x46, 0x0b, 0x51, 0x3f, 0xf1, 0xbe, 0x0a, 0x23, 0xa5, 0x38, 0xa0, 0xe3, 0x70, 0x14, 0x63, 0xf0, 0x94, 0xbb, 0x1c, 0x4f, 0x23, 0x05, 0x1b, 0x62, 0x40, 0x9b, 0xf9, 0x52, 0x1b, 0x41, - 0x51, 0x57, 0x2a, 0x99, 0x73, 0xda, 0xe1, 0xcf, 0xc5, 0x4c, 0x65, 0x3a, 0xc2, 0x9d, 0x73, 0xda, 0xc9, 0x59, 0xf1, 0xdf, 0xab, 0x2b, 0x27, 0xe1, 0x59, 0x8b, 0xa7, 0x48, 0xf9, 0x36, 0xcb, 0x08, - 0xe3, 0x5e, 0x1d, 0xdd, 0xf9, 0x20, 0x4f, 0x64, 0xa9, 0x26, 0x74, 0x97, 0xf2, 0x2d, 0x31, 0xac, 0x8c, 0x20, 0x77, 0x09, 0xa9, 0x8f, 0xed, 0x23, 0x77, 0x7e, 0xd7, 0x34, 0x93, 0x84, 0xe7, 0xaa }, - { 0xaa, 0xf7, 0x64, 0xdf, 0x34, 0x59, 0x1c, 0x2c, 0xbc, 0x47, 0x08, 0x6a, 0x25, 0xbf, 0x9d, 0x48, 0x54, 0xcf, 0xa0, 0x6c, 0xfc, 0xd4, 0x10, 0x39, 0x9f, 0x64, 0x46, 0xce, 0xd9, 0x95, 0x28, 0x89, - 0xdf, 0x94, 0x5e, 0x74, 0x0b, 0x55, 0x46, 0x82, 0xd9, 0x3d, 0x82, 0x97, 0x7d, 0xd0, 0x3e, 0xd7, 0xf6, 0x6f, 0xaa, 0x97, 0x3e, 0xdf, 0xa7, 0xde, 0xe3, 0xc5, 0xaf, 0xd3, 0xa0, 0x5a, 0x30, 0x0d, - 0xe3, 0x5e, 0x1d, 0xdd, 0xf9, 0x20, 0x4f, 0x64, 0xa9, 0x26, 0x74, 0x97, 0xf2, 0x2d, 0x31, 0xac, 0x8c, 0x20, 0x77, 0x09, 0xa9, 0x8f, 0xed, 0x23, 0x77, 0x7e, 0xd7, 0x34, 0x93, 0x84, 0xe7, 0xaa } }, - { { 0x96, 0x4e, 0xf2, 0x1e, 0x3a, 0xe5, 0x77, 0xbf, 0xa7, 0x1c, 0x3d, 0x66, 0x08, 0x06, 0xca, 0x55, 0x43, 0x7a, 0x08, 0xf8, 0xff, 0x55, 0xb3, 0xbc, 0x9a, 0x83, 0x9a, 0x2e, 0xe6, 0x97, 0x14, 0x32, - 0x36, 0x57, 0x5c, 0xa4, 0x04, 0x78, 0xb1, 0x92, 0xf4, 0x23, 0x94, 0xe6, 0x2a, 0xef, 0xd4, 0xe7, 0xc4, 0x02, 0x9f, 0xa9, 0x79, 0x77, 0x61, 0x90, 0xd6, 0xdb, 0x6e, 0x28, 0x7e, 0xc0, 0x1d, 0x70 }, - { 0xc5, 0xd1, 0x5c, 0x34, 0x15, 0xa9, 0x1e, 0x42, 0x2a, 0x1b, 0x0d, 0xf0, 0x56, 0x83, 0x10, 0xc3, 0xc9, 0x21, 0xfd, 0x05, 0xfa, 0x51, 0x0e, 0x11, 0x28, 0xcc, 0x84, 0xac, 0x35, 0xb5, 0xd8, 0xc8, - 0x5c, 0x80, 0x11, 0x1f, 0x60, 0x1c, 0x72, 0x25, 0x82, 0x45, 0xb5, 0x4f, 0x66, 0x6b, 0x52, 0xb1, 0xf7, 0x28, 0x0f, 0x80, 0x76, 0x44, 0xdc, 0x15, 0x70, 0x39, 0xe9, 0xaf, 0xc7, 0x0a, 0xa0, 0x43 }, - { 0xff, 0x20, 0x5e, 0x3b, 0x75, 0xe9, 0x38, 0x7c, 0xa3, 0x5c, 0x8b, 0x1a, 0xec, 0x17, 0x8d, 0xf0, 0xef, 0xb3, 0x53, 0x9b, 0x16, 0xa9, 0x44, 0xf9, 0x34, 0x45, 0x13, 0x66, 0x80, 0x24, 0xdc, 0x22, - 0x0e, 0x51, 0x94, 0xed, 0xe6, 0x83, 0x36, 0x32, 0x63, 0x23, 0x1b, 0xf8, 0x78, 0xb4, 0x04, 0x7f, 0x5a, 0x50, 0x54, 0x12, 0x19, 0x04, 0x61, 0xdd, 0x25, 0xf0, 0x48, 0x29, 0x04, 0xc1, 0x44, 0xe2 }, - { 0x46, 0x32, 0x2d, 0xc7, 0xbc, 0x05, 0x2a, 0xd3, 0xb5, 0xce, 0x7d, 0x47, 0x5e, 0xfc, 0x90, 0x38, 0xef, 0xfa, 0x6f, 0x42, 0xf0, 0x66, 0x05, 0x89, 0x7c, 0x9a, 0xc1, 0xfd, 0xa2, 0xe8, 0xa7, 0x38, - 0x18, 0x6d, 0x7f, 0x9e, 0xfb, 0xbd, 0x06, 0x0c, 0x70, 0xd7, 0x29, 0x10, 0x88, 0x04, 0x9f, 0x24, 0x28, 0x9d, 0xc7, 0x84, 0xdf, 0xb6, 0xec, 0xb2, 0xc7, 0x1b, 0xd1, 0xc1, 0x9d, 0x56, 0xb0, 0x83 }, - { 0xda, 0xd7, 0x34, 0xee, 0x62, 0x13, 0x8f, 0x47, 0xad, 0xb4, 0x9c, 0x98, 0xe4, 0xc5, 0xb3, 0x29, 0x31, 0x11, 0x64, 0xad, 0xf5, 0x0b, 0x60, 0xe1, 0x0e, 0x18, 0x28, 0x30, 0x3c, 0xa2, 0xe3, 0x29, - 0x89, 0x0a, 0x7e, 0x18, 0xba, 0x30, 0x9e, 0x7d, 0x53, 0xf1, 0x82, 0xd5, 0x27, 0xe5, 0xf3, 0xab, 0x15, 0xcd, 0x62, 0x7e, 0xdf, 0xf0, 0x0e, 0x42, 0xfa, 0x6b, 0x7b, 0x54, 0xd2, 0x74, 0x19, 0x8f }, - { 0x29, 0x4d, 0x28, 0x80, 0x62, 0xb5, 0x77, 0xbb, 0x69, 0x70, 0xb0, 0xb7, 0x10, 0x2e, 0xed, 0xfc, 0x13, 0x34, 0x93, 0x7f, 0xd8, 0xfc, 0xb5, 0x7b, 0xfe, 0x34, 0x0a, 0xa3, 0x95, 0x5b, 0xb1, 0xa7, - 0xc6, 0xab, 0x82, 0x79, 0x25, 0x23, 0x94, 0x12, 0xa4, 0x34, 0xec, 0x23, 0xca, 0xcb, 0xd0, 0xa3, 0xf9, 0x31, 0x32, 0xce, 0x50, 0x31, 0x73, 0x23, 0x98, 0x94, 0xe3, 0x08, 0xd9, 0x1e, 0xc3, 0x0b, - 0x39, 0xe3, 0x3b, 0xf2, 0xe8, 0xb7, 0x26, 0x28, 0x9d, 0xb3, 0x12, 0x8d, 0x16, 0xca, 0x89, 0x26, 0xa9, 0x1c, 0xa3, 0x1f, 0x36, 0x10, 0x60, 0x6a, 0x29, 0x85, 0xe7, 0x2c, 0xee, 0xc1, 0xb6, 0xae }, - { 0x68, 0xed, 0x3c, 0x64, 0xe6, 0x87, 0xf0, 0x14, 0x64, 0xfc, 0x38, 0x3a, 0x0f, 0xd9, 0x7a, 0x5b, 0x52, 0x32, 0x10, 0xca, 0xc6, 0x83, 0x0b, 0xae, 0x17, 0x0e, 0xfe, 0x77, 0xe0, 0xe7, 0x83, 0xa1, - 0x2c, 0x78, 0x62, 0x9c, 0x79, 0x08, 0x2b, 0xd4, 0x85, 0x72, 0x27, 0x8d, 0x97, 0x78, 0x62, 0x33, 0x34, 0xeb, 0x5c, 0xde, 0x5d, 0xaa, 0x4d, 0xfa, 0xd1, 0x67, 0xa4, 0xea, 0x45, 0xad, 0xf9, 0x06, - 0x39, 0xe3, 0x3b, 0xf2, 0xe8, 0xb7, 0x26, 0x28, 0x9d, 0xb3, 0x12, 0x8d, 0x16, 0xca, 0x89, 0x26, 0xa9, 0x1c, 0xa3, 0x1f, 0x36, 0x10, 0x60, 0x6a, 0x29, 0x85, 0xe7, 0x2c, 0xee, 0xc1, 0xb6, 0xae } }, - { { 0xd9, 0x64, 0xb2, 0xe1, 0x9f, 0x0a, 0x35, 0xfc, 0x9f, 0xc3, 0xa5, 0x2a, 0xa3, 0x84, 0xb4, 0xf3, 0x23, 0xc4, 0xf3, 0x5a, 0x9d, 0xf8, 0x7f, 0x35, 0xa9, 0xf5, 0x5b, 0x68, 0xfc, 0x19, 0x69, 0x63, - 0x6a, 0x13, 0x19, 0x32, 0xcc, 0x9d, 0x0c, 0x3c, 0x7d, 0xdd, 0x85, 0x16, 0xa8, 0xd9, 0x2b, 0x75, 0x08, 0x4b, 0x9a, 0xa5, 0x6e, 0xf3, 0xe9, 0xeb, 0xed, 0x5d, 0x2e, 0xfd, 0x2e, 0x0c, 0x60, 0xa2 }, - { 0x0f, 0xf6, 0x8c, 0x3f, 0x6e, 0xee, 0x56, 0x4f, 0x43, 0x6f, 0x54, 0xbd, 0x7a, 0xe4, 0xbe, 0xa8, 0x77, 0x05, 0x99, 0xe7, 0x9e, 0x59, 0x22, 0x85, 0x9b, 0xc6, 0xe4, 0x2a, 0x61, 0x9c, 0x19, 0xb1, - 0x5a, 0xeb, 0x7a, 0xf8, 0x41, 0x4e, 0xe5, 0x2a, 0xd0, 0xf7, 0x44, 0xf0, 0x16, 0xea, 0x0c, 0x04, 0x19, 0x6c, 0xb6, 0x30, 0x3c, 0x6e, 0x2d, 0x79, 0x9a, 0x8f, 0x08, 0x90, 0x11, 0xf1, 0xc0, 0x4d }, - { 0x68, 0xe7, 0x1d, 0x40, 0xf1, 0x07, 0xc0, 0xc6, 0xb2, 0x87, 0x9c, 0xa2, 0x19, 0x43, 0x7a, 0xdf, 0x8a, 0x5a, 0x0f, 0xe2, 0x24, 0x97, 0xa0, 0x38, 0x79, 0x20, 0x38, 0xa9, 0x9c, 0x77, 0xc4, 0x37, - 0xa6, 0x02, 0xe0, 0x93, 0x47, 0xa4, 0x55, 0x21, 0xc2, 0x69, 0xbe, 0x09, 0x05, 0xaa, 0x87, 0x28, 0xf1, 0x95, 0x2f, 0xdb, 0xf0, 0xbf, 0xd2, 0x9e, 0x5e, 0x3a, 0xfa, 0xc6, 0x2f, 0x13, 0x09, 0xaf }, - { 0xe1, 0x9e, 0xc8, 0x4f, 0xc9, 0xdd, 0x61, 0x60, 0x94, 0xbc, 0xd3, 0xd6, 0xde, 0x11, 0x6e, 0xec, 0x84, 0xc4, 0xdd, 0xbe, 0x20, 0x46, 0x6c, 0xef, 0xf6, 0x9d, 0x37, 0x07, 0x53, 0x72, 0x57, 0xf9, - 0x02, 0xb5, 0x64, 0x1f, 0xe2, 0x56, 0xa4, 0x38, 0x6d, 0xa4, 0xed, 0x23, 0x9e, 0xa3, 0xf4, 0x4d, 0x77, 0x52, 0xdc, 0x8c, 0x51, 0xfc, 0x88, 0x18, 0xbc, 0x83, 0x2a, 0xac, 0xc1, 0x1d, 0x3d, 0x59 }, - { 0x08, 0x4f, 0x78, 0x21, 0xfd, 0x4b, 0x85, 0x86, 0x4e, 0x25, 0xdd, 0x47, 0x60, 0x7f, 0x7e, 0xc6, 0xd3, 0xa1, 0xab, 0x91, 0x3f, 0xeb, 0xf6, 0x40, 0x7e, 0x1b, 0xbd, 0x99, 0x9c, 0x7c, 0x2f, 0x4f, - 0xca, 0x68, 0xa5, 0xf6, 0x8c, 0x1e, 0xcb, 0xb8, 0x76, 0xe2, 0x87, 0x5b, 0x49, 0x68, 0x97, 0x2c, 0x21, 0x5c, 0x7c, 0x93, 0x79, 0x9a, 0x95, 0xa1, 0x3a, 0x49, 0xc9, 0x6d, 0x34, 0x6b, 0xa1, 0x98 }, - { 0xb9, 0x88, 0x25, 0x9a, 0x3b, 0x53, 0x56, 0xa1, 0x48, 0x0f, 0xf0, 0x92, 0xde, 0x4e, 0x3e, 0x3a, 0xcf, 0x02, 0xdc, 0x5c, 0xc2, 0xc3, 0x78, 0xad, 0x8a, 0x0c, 0x3c, 0xc7, 0xdd, 0xdd, 0x71, 0x6e, - 0x3f, 0xd9, 0x3a, 0x57, 0x2a, 0x19, 0xa5, 0x3b, 0x5c, 0x46, 0x7b, 0xc9, 0x0f, 0x16, 0xb3, 0x58, 0xa6, 0x85, 0xfa, 0x91, 0x2c, 0x9a, 0x9c, 0x12, 0xb6, 0xd6, 0x7d, 0x9a, 0xf0, 0x9d, 0xe9, 0x02, - 0xad, 0x12, 0x87, 0xda, 0x85, 0x58, 0x6b, 0xff, 0x68, 0x96, 0x05, 0x33, 0xba, 0x7f, 0x08, 0xf9, 0xa9, 0xa2, 0xa9, 0x46, 0x43, 0xe5, 0x03, 0x12, 0xe4, 0xbe, 0x74, 0xaa, 0x46, 0x4e, 0x51, 0xb3 }, - { 0x61, 0x70, 0x17, 0x50, 0x26, 0xfa, 0x51, 0x83, 0xe0, 0xca, 0xa9, 0xb1, 0xc3, 0xc4, 0x83, 0xa9, 0xb6, 0x43, 0x6b, 0x7a, 0x5b, 0xe4, 0x21, 0x5a, 0x6b, 0xd4, 0x34, 0xf8, 0xee, 0x95, 0x86, 0x2d, - 0x03, 0xbf, 0xca, 0xd0, 0xfa, 0x68, 0x53, 0xb2, 0x97, 0x50, 0xad, 0x89, 0x2f, 0x99, 0x63, 0x67, 0x18, 0x57, 0x1f, 0x57, 0x41, 0xbc, 0xb7, 0xc0, 0x18, 0xe7, 0xb6, 0xf3, 0x0f, 0xc4, 0x49, 0x0d, - 0xad, 0x12, 0x87, 0xda, 0x85, 0x58, 0x6b, 0xff, 0x68, 0x96, 0x05, 0x33, 0xba, 0x7f, 0x08, 0xf9, 0xa9, 0xa2, 0xa9, 0x46, 0x43, 0xe5, 0x03, 0x12, 0xe4, 0xbe, 0x74, 0xaa, 0x46, 0x4e, 0x51, 0xb3 } }, - { { 0xc5, 0xdf, 0x86, 0x8f, 0xf1, 0xa7, 0xad, 0x57, 0xfd, 0xb4, 0x53, 0xc3, 0x92, 0x1b, 0x9e, 0x2e, 0xdd, 0xc5, 0xa4, 0x3b, 0x72, 0xa6, 0x9b, 0x4a, 0x15, 0xca, 0x35, 0xed, 0x3c, 0x1a, 0x3b, 0x38, - 0x36, 0xd6, 0xf2, 0x03, 0xb6, 0x97, 0x1f, 0xcb, 0x40, 0x5d, 0x3c, 0x25, 0xfc, 0xe7, 0xff, 0xc6, 0xbe, 0x61, 0xe1, 0x98, 0x31, 0x13, 0xa9, 0xbe, 0x05, 0x86, 0xfe, 0x5c, 0xf6, 0xcc, 0xaa, 0xf5 }, - { 0xd2, 0x57, 0x19, 0x98, 0xf8, 0x74, 0x90, 0xb7, 0x69, 0x6e, 0xdd, 0x44, 0xf1, 0x8b, 0xb1, 0x9c, 0xfd, 0x5b, 0x6b, 0xc0, 0x45, 0xf2, 0x49, 0xa5, 0x4b, 0xff, 0x8b, 0x7f, 0x87, 0xe3, 0xf9, 0x71, - 0xab, 0xfa, 0xc8, 0x17, 0xed, 0xeb, 0x19, 0xc6, 0x3c, 0xee, 0x78, 0xba, 0x89, 0x97, 0x49, 0x85, 0x39, 0x68, 0x29, 0x88, 0x0b, 0x1c, 0xd1, 0x42, 0x8b, 0xe8, 0x1a, 0x3b, 0xeb, 0x4d, 0xef, 0x3b }, - { 0xea, 0xfb, 0xec, 0x27, 0xc3, 0x92, 0xc3, 0x68, 0x0d, 0x3c, 0x5b, 0x20, 0x20, 0x9c, 0x96, 0xa7, 0x39, 0xfa, 0x80, 0x91, 0xef, 0x86, 0x7d, 0xa8, 0x87, 0xf6, 0xef, 0x14, 0x01, 0x46, 0xf0, 0x68, - 0x0a, 0x8b, 0xae, 0x83, 0x91, 0x7e, 0xa0, 0x14, 0x14, 0xde, 0xf9, 0xa8, 0xfd, 0x67, 0x57, 0x17, 0x20, 0x46, 0x43, 0x49, 0x07, 0xf0, 0x3e, 0xc8, 0xbe, 0x66, 0xaf, 0x58, 0x3a, 0xbd, 0xd8, 0x00 }, - { 0x35, 0xf5, 0xc8, 0x2c, 0x0e, 0x4b, 0x56, 0xe0, 0xef, 0x08, 0x34, 0x38, 0x57, 0xe9, 0xde, 0xdb, 0x1d, 0xe1, 0x28, 0x05, 0x01, 0xed, 0x62, 0x3d, 0xa9, 0x6e, 0xea, 0x5b, 0x95, 0x09, 0xe0, 0x04, - 0x46, 0xff, 0xdc, 0x34, 0xf6, 0xf7, 0x63, 0xb1, 0x76, 0xb8, 0x3c, 0x03, 0xef, 0x36, 0x0f, 0x82, 0x1b, 0x5b, 0x6f, 0xe2, 0x86, 0xd9, 0x10, 0x01, 0xe6, 0x73, 0x75, 0x0d, 0x50, 0x30, 0x11, 0x68 }, - { 0x27, 0xb6, 0x3b, 0x78, 0x79, 0xf3, 0x22, 0x78, 0x8f, 0x0c, 0x14, 0x8b, 0x3f, 0x68, 0xc2, 0xab, 0x9f, 0x9f, 0x05, 0x70, 0x7e, 0xee, 0x4b, 0x1b, 0x6b, 0xfc, 0x04, 0x72, 0xca, 0xf1, 0x9a, 0xba, - 0xe3, 0x65, 0x9d, 0xdb, 0x01, 0x33, 0xc5, 0xdb, 0xf6, 0x87, 0xe4, 0x73, 0x5a, 0x0f, 0x94, 0xa9, 0x2e, 0xfe, 0x8f, 0x3e, 0xd1, 0x0a, 0x6d, 0xa1, 0x21, 0x2a, 0x92, 0x8c, 0x4b, 0x43, 0x13, 0x2f }, - { 0xa3, 0xa8, 0x3b, 0xb4, 0x4f, 0x8a, 0xac, 0xab, 0x8a, 0x4c, 0x39, 0x7e, 0xb8, 0x2f, 0xb1, 0x01, 0x2e, 0xbe, 0x0e, 0x7d, 0x28, 0x8a, 0x18, 0x4a, 0xda, 0x58, 0x1a, 0xfb, 0x95, 0x97, 0xf3, 0x63, - 0x58, 0xbe, 0x8c, 0x30, 0x13, 0x9b, 0xba, 0x9f, 0x4e, 0xac, 0x8d, 0x95, 0xf2, 0x07, 0xbb, 0x85, 0xa1, 0x41, 0x4c, 0x33, 0xe3, 0x58, 0x8e, 0x5c, 0xa1, 0x05, 0x45, 0xab, 0x5c, 0x0c, 0xe4, 0x02, - 0xc3, 0xa0, 0xa0, 0x72, 0xdb, 0x9a, 0x9d, 0xbf, 0x13, 0x29, 0x94, 0x70, 0x8b, 0xe4, 0xe8, 0xdb, 0x0e, 0x0b, 0xd0, 0xa0, 0x25, 0xad, 0x71, 0xa0, 0x27, 0x9c, 0x1d, 0x77, 0xb0, 0x98, 0xa8, 0x03 }, - { 0xe1, 0x84, 0xa5, 0xea, 0xa5, 0xd8, 0x1b, 0x29, 0xce, 0xd7, 0xa3, 0x72, 0xa7, 0xc9, 0xa5, 0xea, 0xf1, 0x02, 0xf3, 0x0c, 0xb0, 0x65, 0x12, 0xbc, 0xa4, 0xf2, 0x5d, 0x69, 0x00, 0xa4, 0x7f, 0x5a, - 0x52, 0x09, 0xb6, 0x7b, 0x30, 0xf2, 0x99, 0x03, 0x39, 0x9d, 0xee, 0x6f, 0xb5, 0xf7, 0x9e, 0x7a, 0x97, 0x8b, 0x81, 0x03, 0x8c, 0xdd, 0x35, 0xfc, 0x1f, 0x0a, 0xc6, 0xa4, 0x60, 0x7b, 0xc8, 0x0a, - 0xc3, 0xa0, 0xa0, 0x72, 0xdb, 0x9a, 0x9d, 0xbf, 0x13, 0x29, 0x94, 0x70, 0x8b, 0xe4, 0xe8, 0xdb, 0x0e, 0x0b, 0xd0, 0xa0, 0x25, 0xad, 0x71, 0xa0, 0x27, 0x9c, 0x1d, 0x77, 0xb0, 0x98, 0xa8, 0x03 } }, - { { 0x67, 0xe9, 0x62, 0x76, 0x3a, 0x90, 0x9b, 0x6b, 0x19, 0x1d, 0x65, 0xb2, 0x2a, 0x2f, 0xf7, 0x50, 0xaa, 0x54, 0xa5, 0xbb, 0x53, 0xb5, 0xf9, 0xee, 0x0c, 0x04, 0x3a, 0x3c, 0x29, 0x4b, 0x66, 0x3e, - 0x7b, 0xb6, 0xaa, 0xd2, 0x10, 0x89, 0xcc, 0x89, 0x2c, 0x47, 0xbe, 0x23, 0xd6, 0x52, 0x81, 0x5d, 0xc8, 0xbc, 0x49, 0xd6, 0x6a, 0xcd, 0x62, 0x99, 0x30, 0xff, 0x16, 0xa5, 0x50, 0x44, 0xd8, 0x7a }, - { 0xd6, 0xcd, 0xfe, 0xd4, 0x44, 0x4a, 0x9e, 0x90, 0x44, 0x73, 0x8a, 0xff, 0xbb, 0x82, 0x08, 0xb6, 0x7f, 0xf2, 0x87, 0xcb, 0xa5, 0x0b, 0x56, 0xd3, 0x9e, 0x91, 0xb8, 0x52, 0x6b, 0x25, 0xa6, 0x5d, - 0x50, 0xaf, 0x9b, 0xd5, 0xfb, 0x9f, 0x7e, 0x2d, 0x57, 0xdf, 0x30, 0x78, 0x8d, 0x1a, 0xc3, 0xac, 0x9c, 0x5a, 0xbf, 0xab, 0x5a, 0x0d, 0xc9, 0xb6, 0x4b, 0x18, 0xd4, 0xe7, 0x55, 0x40, 0xde, 0x7e }, - { 0xc2, 0xa9, 0x7e, 0x5c, 0x26, 0xf4, 0x7d, 0xce, 0x9e, 0x73, 0xae, 0x50, 0xde, 0xe7, 0xa6, 0xf9, 0x8b, 0x57, 0xf9, 0x7a, 0x4c, 0x38, 0x82, 0xf6, 0x30, 0x80, 0x12, 0xf7, 0xf6, 0x66, 0x80, 0x46, - 0x4d, 0x41, 0x53, 0x63, 0xd9, 0x65, 0x90, 0xe7, 0xee, 0x24, 0x07, 0xb0, 0x4f, 0xeb, 0x3e, 0x8e, 0x83, 0x21, 0xa3, 0x40, 0x03, 0xc0, 0x64, 0x52, 0xc6, 0xb2, 0x12, 0x9d, 0x8d, 0x86, 0xdd, 0x19 }, - { 0xe2, 0xd5, 0x49, 0x5e, 0x2a, 0x6e, 0x4e, 0xd9, 0x31, 0x26, 0x53, 0x13, 0x98, 0x5e, 0x2f, 0x23, 0xea, 0xa0, 0x30, 0xee, 0xef, 0x62, 0x2b, 0xdc, 0x93, 0x65, 0x90, 0xad, 0x9a, 0xf1, 0x74, 0x12, - 0xf5, 0x24, 0x33, 0xcc, 0xc3, 0xda, 0x42, 0x54, 0xa6, 0x6c, 0x86, 0x99, 0xb9, 0xb5, 0xf7, 0x07, 0x90, 0xd8, 0x85, 0x7f, 0x69, 0xfb, 0x19, 0x2a, 0x2c, 0xc0, 0x11, 0x81, 0x64, 0x37, 0x38, 0x07 }, - { 0xc7, 0xb3, 0xf5, 0xe4, 0x4b, 0x55, 0xcf, 0xd8, 0x2b, 0x72, 0xde, 0x62, 0xfc, 0x66, 0xea, 0x82, 0xee, 0x2e, 0xe5, 0x4f, 0x66, 0xba, 0x19, 0x63, 0x01, 0x0b, 0x2d, 0x89, 0xb4, 0xaa, 0x76, 0xb3, - 0x7e, 0xc5, 0xbe, 0xdd, 0x57, 0x90, 0x5e, 0xff, 0x5b, 0x9a, 0x71, 0xe1, 0x47, 0xf9, 0xec, 0xe5, 0xf0, 0x19, 0x89, 0x17, 0x65, 0x3e, 0x56, 0x4a, 0x98, 0xb2, 0x3c, 0x3b, 0xf0, 0x14, 0x13, 0x1b }, - { 0xc0, 0x72, 0x26, 0x96, 0x6b, 0xf5, 0x50, 0xa1, 0x65, 0xcd, 0xfe, 0x92, 0xa5, 0x5a, 0xb3, 0x56, 0x27, 0x5b, 0x2f, 0x4a, 0x8f, 0x67, 0xaa, 0xf4, 0xa1, 0x6e, 0x3c, 0x66, 0xcc, 0xb7, 0x71, 0x70, - 0xff, 0x70, 0x1f, 0x9e, 0x09, 0xae, 0x31, 0xcb, 0x2a, 0xd5, 0x8a, 0x38, 0xa9, 0xaf, 0xbc, 0x94, 0xa2, 0xa8, 0xe9, 0x77, 0x1c, 0xc3, 0xfa, 0xd1, 0x45, 0xd2, 0xe2, 0xff, 0x7d, 0xf2, 0x44, 0x00, - 0xa0, 0xc3, 0xc1, 0xdd, 0xa0, 0x4c, 0xfb, 0xed, 0x1a, 0xbd, 0x0c, 0x05, 0x3b, 0xa9, 0xc8, 0x98, 0xb0, 0x7d, 0x6a, 0x77, 0xcb, 0x08, 0x70, 0x64, 0x31, 0x9d, 0x9c, 0x7b, 0x40, 0x9e, 0xbb, 0xf4 }, - { 0xbc, 0x88, 0x9d, 0x36, 0xae, 0xbc, 0x92, 0x47, 0x63, 0x85, 0x41, 0xe3, 0x1e, 0x1c, 0x39, 0xf5, 0xd3, 0xc2, 0x0a, 0x7d, 0x18, 0x7a, 0x8f, 0xd3, 0x0c, 0x37, 0x50, 0x28, 0x35, 0x93, 0x77, 0x4b, - 0xcb, 0xba, 0x35, 0x4e, 0x94, 0x48, 0xe4, 0x0c, 0xa7, 0x36, 0x4f, 0x74, 0x2b, 0xf9, 0xb5, 0xb5, 0xeb, 0x91, 0x50, 0x3c, 0x67, 0x9b, 0x4d, 0x25, 0xd4, 0x0e, 0x0d, 0xb9, 0x5b, 0x77, 0xf3, 0x0e, - 0xa0, 0xc3, 0xc1, 0xdd, 0xa0, 0x4c, 0xfb, 0xed, 0x1a, 0xbd, 0x0c, 0x05, 0x3b, 0xa9, 0xc8, 0x98, 0xb0, 0x7d, 0x6a, 0x77, 0xcb, 0x08, 0x70, 0x64, 0x31, 0x9d, 0x9c, 0x7b, 0x40, 0x9e, 0xbb, 0xf4 } }, - { { 0x44, 0xdd, 0x62, 0x9e, 0x0f, 0xee, 0x20, 0x11, 0x37, 0xfc, 0xd0, 0x5c, 0xe4, 0xe1, 0x0a, 0xb8, 0xc2, 0xe0, 0x9c, 0x2c, 0x3e, 0x1b, 0x31, 0x1c, 0xdb, 0xa3, 0x84, 0x9a, 0xb7, 0x4e, 0x40, 0x74, - 0x21, 0xfd, 0xfc, 0x65, 0xbd, 0x38, 0x8a, 0x55, 0x6f, 0x1e, 0xc3, 0x14, 0xfc, 0x66, 0x04, 0x7b, 0xc4, 0x61, 0xb0, 0xcb, 0xfa, 0xdd, 0x50, 0x45, 0x4b, 0x2e, 0xf0, 0x6d, 0x0f, 0x26, 0x6d, 0xbf }, - { 0xe6, 0xbc, 0x35, 0x73, 0xb3, 0x11, 0x38, 0xc6, 0x31, 0x82, 0x96, 0x80, 0x1d, 0xa9, 0xd9, 0x17, 0x85, 0x4e, 0xad, 0x0f, 0x5c, 0xb7, 0xe8, 0x78, 0x62, 0x2f, 0x3c, 0x10, 0x0e, 0xdc, 0xf2, 0x7e, - 0xf5, 0x02, 0x6d, 0x1a, 0x50, 0xc2, 0x50, 0x7d, 0x0d, 0x14, 0x77, 0x77, 0xfc, 0xbe, 0x23, 0x02, 0x81, 0x0a, 0xdc, 0xa3, 0x16, 0xfd, 0xab, 0xb9, 0x7c, 0xb6, 0x7e, 0x8a, 0xde, 0x1f, 0x22, 0xeb }, - { 0xab, 0xf3, 0xea, 0x63, 0xc0, 0x25, 0xa2, 0xc7, 0x6a, 0xfe, 0x91, 0x4a, 0x0a, 0x91, 0xdd, 0x6d, 0x6f, 0x8c, 0xf9, 0xa8, 0x1c, 0x9f, 0xb5, 0xe5, 0xd2, 0xac, 0xe6, 0x51, 0x9a, 0xd3, 0x87, 0x17, - 0x82, 0x12, 0x0a, 0x58, 0x99, 0x7f, 0x81, 0x2d, 0x8d, 0x27, 0x2d, 0x1b, 0xb0, 0x02, 0x7e, 0x0d, 0xd6, 0x18, 0x89, 0x5e, 0x0c, 0x2b, 0x57, 0xa6, 0x56, 0x35, 0xff, 0x71, 0x4e, 0xb0, 0x49, 0x38 }, - { 0x36, 0xdf, 0x1d, 0x1c, 0xf6, 0xa7, 0x4d, 0x87, 0x7e, 0x2c, 0x3f, 0xb4, 0xda, 0xd7, 0x80, 0x71, 0x0b, 0xf3, 0x2a, 0x47, 0x20, 0xe6, 0x9a, 0x3d, 0x17, 0x9a, 0x97, 0xc9, 0x4e, 0x53, 0xa6, 0xe2, - 0x23, 0xea, 0x94, 0x4d, 0xf9, 0xeb, 0x2c, 0x03, 0x2c, 0x88, 0xa2, 0xe6, 0xc5, 0x94, 0xa5, 0x6f, 0xc3, 0x98, 0xa9, 0x8b, 0xa7, 0x41, 0x7d, 0xd3, 0x82, 0x01, 0x13, 0xb6, 0x0f, 0x39, 0x1e, 0xd2 }, - { 0x08, 0x28, 0xc3, 0x1c, 0xec, 0x21, 0x3a, 0xb4, 0x4c, 0xb1, 0xfa, 0xb9, 0x0c, 0xfe, 0xc2, 0x50, 0xc5, 0x99, 0x62, 0xa0, 0x11, 0x74, 0xcf, 0x05, 0x1e, 0x2b, 0xdf, 0x6d, 0x22, 0x8e, 0x6e, 0x55, - 0x19, 0x21, 0x9c, 0xa1, 0x98, 0x56, 0x45, 0x90, 0x40, 0x3a, 0x8e, 0xad, 0x76, 0x4d, 0xd3, 0x95, 0x27, 0x67, 0x4e, 0x02, 0x16, 0xc3, 0xfe, 0x5a, 0x79, 0x4e, 0x2d, 0x6f, 0xd0, 0xe4, 0x4f, 0x62 }, - { 0x40, 0x14, 0xe1, 0x88, 0x3d, 0xcc, 0x51, 0xcb, 0x98, 0x86, 0x06, 0x4d, 0xe4, 0x52, 0x71, 0xe2, 0x2e, 0x2b, 0x80, 0xfd, 0x81, 0x65, 0xaf, 0x93, 0x31, 0x87, 0xe0, 0xff, 0x31, 0xab, 0xff, 0x53, - 0x0e, 0x2d, 0xb1, 0x47, 0xe6, 0x44, 0xb7, 0x29, 0xab, 0x0f, 0x51, 0x3a, 0x53, 0x84, 0x36, 0x58, 0x8c, 0x5f, 0x7b, 0x65, 0x6a, 0xb7, 0x6f, 0xdc, 0xad, 0xc1, 0xa3, 0xe4, 0x21, 0xfc, 0x22, 0x0e, - 0xc1, 0x10, 0xd1, 0x7d, 0x9f, 0xd3, 0x1e, 0x33, 0xb4, 0xca, 0xb9, 0xff, 0xd8, 0x27, 0xb8, 0xca, 0xde, 0x49, 0x6f, 0xdc, 0xf0, 0xe8, 0x70, 0x36, 0xdb, 0x90, 0x00, 0x07, 0x9e, 0x77, 0x39, 0xfe }, - { 0xc9, 0x93, 0x4b, 0xe6, 0x47, 0x7e, 0x1d, 0x86, 0x15, 0x46, 0xe8, 0x27, 0xf5, 0x84, 0x67, 0x4e, 0x42, 0xe3, 0x2b, 0x8a, 0x4e, 0x90, 0x7b, 0x87, 0xcc, 0xdf, 0xaa, 0x04, 0x06, 0x05, 0xe6, 0x72, - 0xff, 0x6f, 0x44, 0x1b, 0x08, 0xad, 0x79, 0x3e, 0xb7, 0xdd, 0xd7, 0x2c, 0x73, 0xf0, 0xf0, 0xc4, 0x6e, 0xb7, 0x37, 0xe1, 0x02, 0xf5, 0x42, 0xe7, 0xef, 0xa1, 0xdd, 0x50, 0x9a, 0xc5, 0x8d, 0x00, - 0xc1, 0x10, 0xd1, 0x7d, 0x9f, 0xd3, 0x1e, 0x33, 0xb4, 0xca, 0xb9, 0xff, 0xd8, 0x27, 0xb8, 0xca, 0xde, 0x49, 0x6f, 0xdc, 0xf0, 0xe8, 0x70, 0x36, 0xdb, 0x90, 0x00, 0x07, 0x9e, 0x77, 0x39, 0xfe } }, - { { 0x3e, 0x0c, 0x21, 0xc4, 0x3d, 0x64, 0x61, 0xc1, 0x9d, 0xa1, 0x83, 0x10, 0x74, 0x1d, 0x56, 0x12, 0xaf, 0x29, 0x5c, 0x6c, 0x12, 0x48, 0x0a, 0xc7, 0xe5, 0x12, 0xb6, 0x42, 0x6b, 0x54, 0xf4, 0x42, - 0x0c, 0x43, 0x42, 0x2e, 0x78, 0xc2, 0xe7, 0x26, 0x09, 0x41, 0x4a, 0x2f, 0xa1, 0xb0, 0x1f, 0xcd, 0x63, 0x76, 0x1e, 0xa1, 0x6f, 0xf6, 0xe2, 0xc2, 0x08, 0x89, 0x0d, 0x28, 0xbf, 0x1b, 0x56, 0x5b }, - { 0x3e, 0x2e, 0xf2, 0xcc, 0x81, 0xca, 0xa7, 0x5d, 0x01, 0xd2, 0x82, 0xfd, 0x45, 0xee, 0xc0, 0xf5, 0x49, 0x3b, 0xe2, 0xa4, 0x2a, 0x4d, 0x5f, 0x40, 0x0d, 0xbc, 0xb9, 0x3d, 0x6e, 0xda, 0xe2, 0x86, - 0xe1, 0x23, 0x8b, 0x5f, 0x0d, 0xa2, 0x35, 0x15, 0x1d, 0x22, 0x23, 0xa5, 0x69, 0x56, 0x34, 0x78, 0xb3, 0xb3, 0x55, 0xef, 0x63, 0x8a, 0x17, 0x63, 0xda, 0xf0, 0x64, 0x99, 0x8a, 0x8a, 0xba, 0xd6 }, - { 0x68, 0x79, 0x36, 0xa7, 0x6b, 0xe3, 0x76, 0x1c, 0xe3, 0x38, 0x0b, 0xa3, 0x91, 0xb6, 0xb0, 0x82, 0x37, 0xfa, 0x52, 0x74, 0xf1, 0xb5, 0xd5, 0xd9, 0x07, 0x06, 0x9e, 0xda, 0x87, 0x6b, 0x0f, 0x24, - 0x4f, 0xbe, 0xc9, 0xff, 0x03, 0x41, 0xaf, 0x77, 0x68, 0xed, 0xe7, 0x71, 0xba, 0x2d, 0xde, 0x27, 0xa1, 0xbf, 0xa8, 0xa7, 0x30, 0x7c, 0xcb, 0x79, 0x72, 0x89, 0x1a, 0xdc, 0xc1, 0xe4, 0xb2, 0x9d }, - { 0x94, 0xa3, 0x11, 0xf4, 0x44, 0x80, 0xd0, 0xa3, 0x47, 0x93, 0x36, 0xe2, 0xbd, 0x04, 0xe4, 0x74, 0x3d, 0x00, 0x60, 0xad, 0xd0, 0x2d, 0x86, 0x66, 0xa1, 0x72, 0x1a, 0xb9, 0x1c, 0x14, 0xa2, 0x9b, - 0x4b, 0x04, 0x7d, 0x5b, 0xcd, 0xf8, 0x01, 0x33, 0xde, 0x34, 0x10, 0x29, 0xc4, 0x72, 0x56, 0xff, 0x11, 0xcd, 0xd8, 0x61, 0x2c, 0xb6, 0xb7, 0xf4, 0x24, 0x8b, 0x44, 0xb4, 0xe7, 0x34, 0x50, 0xb8 }, - { 0x72, 0xf6, 0xd4, 0xa3, 0x24, 0xf9, 0xef, 0xf4, 0x55, 0x8d, 0x3c, 0x07, 0xca, 0x10, 0xdd, 0x54, 0x87, 0x13, 0x32, 0x78, 0x5c, 0x64, 0x10, 0x08, 0x62, 0x7e, 0xf4, 0x34, 0x0f, 0x1c, 0xcd, 0xcc, - 0x3b, 0x42, 0xfe, 0x60, 0x41, 0x70, 0x2c, 0x6b, 0xd4, 0x6c, 0xf7, 0xb8, 0x24, 0xf6, 0xd7, 0x07, 0xb3, 0x46, 0xb0, 0x7d, 0x14, 0x24, 0x9b, 0x72, 0x79, 0xf4, 0x23, 0x2a, 0xec, 0x02, 0xe7, 0x69 }, - { 0xe5, 0xbe, 0x84, 0xc3, 0x92, 0x47, 0x15, 0xd3, 0xac, 0x06, 0x44, 0x72, 0x41, 0xeb, 0xb6, 0x5a, 0x17, 0x06, 0x90, 0xd9, 0x55, 0x3d, 0xe4, 0x87, 0x7d, 0x5a, 0x11, 0x9f, 0x02, 0x6d, 0xd3, 0x4e, - 0x71, 0xd1, 0x5e, 0x16, 0x9f, 0xb2, 0xc0, 0x7f, 0xcb, 0x78, 0x8b, 0x89, 0x11, 0xae, 0x43, 0xe8, 0x85, 0xb7, 0xf9, 0xc8, 0x48, 0x5a, 0xb2, 0x96, 0xaf, 0x8f, 0xab, 0x71, 0x84, 0x9d, 0x40, 0x09, - 0x30, 0xd4, 0x32, 0x6e, 0xa2, 0x77, 0x97, 0x71, 0x37, 0xce, 0x22, 0x6b, 0xca, 0xc9, 0x79, 0xef, 0xc0, 0xb2, 0xb4, 0x3d, 0x30, 0xbf, 0x77, 0xe9, 0xc3, 0x8d, 0xec, 0x15, 0x04, 0x08, 0xfa, 0x15 }, - { 0x4b, 0xf3, 0x7f, 0xb2, 0x78, 0x75, 0x45, 0xd4, 0xce, 0x5e, 0x3d, 0xaf, 0x92, 0x63, 0x3d, 0x90, 0xc0, 0xa7, 0x23, 0x62, 0x7f, 0x37, 0x58, 0x8d, 0x12, 0xe0, 0xb8, 0x6c, 0x46, 0x38, 0xaa, 0xf7, - 0xe1, 0x03, 0x9e, 0x1f, 0x31, 0xf9, 0x5a, 0xa4, 0x59, 0x0d, 0xec, 0xc5, 0x1f, 0x17, 0x88, 0x25, 0xcc, 0xed, 0x69, 0x2b, 0x91, 0x73, 0x6a, 0x3f, 0xcb, 0xe5, 0x9c, 0x1e, 0x26, 0x3e, 0xec, 0x0b, - 0x30, 0xd4, 0x32, 0x6e, 0xa2, 0x77, 0x97, 0x71, 0x37, 0xce, 0x22, 0x6b, 0xca, 0xc9, 0x79, 0xef, 0xc0, 0xb2, 0xb4, 0x3d, 0x30, 0xbf, 0x77, 0xe9, 0xc3, 0x8d, 0xec, 0x15, 0x04, 0x08, 0xfa, 0x15 } }, - { { 0xc5, 0x1d, 0xcd, 0x70, 0xb2, 0x9e, 0x53, 0x29, 0x05, 0x78, 0x83, 0x5d, 0x56, 0x30, 0x89, 0xee, 0x02, 0xd7, 0xac, 0x57, 0x0a, 0xd2, 0xa0, 0x9c, 0x96, 0x0c, 0xbf, 0xf2, 0x30, 0xbf, 0x1a, 0x2b, - 0xee, 0x0e, 0x9f, 0x1e, 0x1c, 0x65, 0x7d, 0xb5, 0x48, 0xad, 0x6f, 0x51, 0xa0, 0x91, 0x61, 0xe4, 0xe6, 0x83, 0x9f, 0x58, 0x7c, 0x76, 0x2b, 0x52, 0x94, 0x87, 0x3c, 0x8d, 0x36, 0x4c, 0x37, 0x3c }, - { 0x59, 0x3b, 0x0d, 0x38, 0xab, 0x93, 0xca, 0xfb, 0x67, 0x44, 0x30, 0x96, 0xec, 0xbd, 0x00, 0x1d, 0x93, 0xd0, 0xb3, 0x3d, 0x3c, 0xd4, 0x4e, 0x3d, 0xd8, 0x29, 0x93, 0xb2, 0xb3, 0x77, 0xfc, 0x57, - 0x31, 0x20, 0xe3, 0x90, 0x0d, 0xf4, 0x91, 0x2f, 0x8b, 0x43, 0xce, 0xfe, 0x99, 0x03, 0x03, 0xa2, 0x90, 0x8d, 0xcf, 0xa8, 0xc0, 0x21, 0x00, 0xca, 0xcc, 0xcb, 0x4b, 0x2f, 0xa5, 0x39, 0xa8, 0x0b }, - { 0xca, 0xf6, 0xf9, 0xbb, 0x53, 0xcb, 0x97, 0x76, 0xb6, 0x9c, 0x2c, 0x18, 0x21, 0x43, 0x13, 0x48, 0x13, 0xc9, 0x0e, 0xeb, 0x40, 0xea, 0xce, 0x1f, 0x3a, 0xe9, 0xd2, 0x9e, 0x29, 0xdb, 0xe2, 0x79, - 0xe2, 0x1a, 0x9f, 0x84, 0x9d, 0xe4, 0x55, 0x82, 0x17, 0xeb, 0x87, 0xf6, 0xc3, 0xef, 0xcd, 0x54, 0x14, 0xee, 0xc8, 0x5b, 0xd7, 0x67, 0x05, 0xe2, 0x34, 0xa2, 0x7e, 0x81, 0x83, 0x21, 0x7a, 0x02 }, - { 0xc5, 0x03, 0xd9, 0x75, 0xdf, 0x17, 0x15, 0xe3, 0x5b, 0x7b, 0x4f, 0x66, 0x9c, 0x15, 0x4e, 0x01, 0xdf, 0x3d, 0x16, 0xb6, 0x52, 0xcc, 0xcf, 0x28, 0x40, 0xdb, 0x20, 0xee, 0x8b, 0x69, 0xb1, 0x2b, - 0xc0, 0x6e, 0xe4, 0xd2, 0xf5, 0xd1, 0x49, 0x3f, 0xf3, 0x0a, 0x12, 0xcd, 0x13, 0xbd, 0x9d, 0x3d, 0x5b, 0x28, 0x5c, 0xb0, 0x0d, 0x0e, 0xb6, 0xed, 0xec, 0x65, 0xeb, 0x25, 0x28, 0x2e, 0x65, 0x2f }, - { 0xed, 0xa7, 0x05, 0xc1, 0xa6, 0x81, 0xf2, 0x7a, 0x69, 0x68, 0x17, 0x8e, 0xf7, 0xc9, 0x14, 0x80, 0x9f, 0x81, 0xfe, 0x16, 0xfd, 0x81, 0x93, 0xb4, 0x0b, 0x05, 0x5b, 0x4e, 0xef, 0x6e, 0x7a, 0x67, - 0x9d, 0x99, 0x4c, 0x17, 0xcd, 0x1c, 0x16, 0xfd, 0x31, 0x35, 0xd5, 0x3e, 0xa3, 0x00, 0xbf, 0xbe, 0xda, 0xd6, 0xe2, 0x37, 0x9b, 0x13, 0x1b, 0xca, 0x29, 0x90, 0x4b, 0xf2, 0x09, 0x57, 0x2f, 0xe9 }, - { 0xd7, 0xba, 0x23, 0xd3, 0xa0, 0x6e, 0x14, 0x6a, 0xf0, 0x77, 0xb7, 0xe6, 0xe3, 0xc9, 0x3b, 0x38, 0xbb, 0xe7, 0xbe, 0x54, 0x75, 0xf8, 0xb7, 0x42, 0x29, 0xe2, 0x83, 0xde, 0x20, 0x22, 0x41, 0xcf, - 0x5f, 0x6f, 0x80, 0x60, 0xf3, 0x44, 0x04, 0x21, 0xd5, 0x03, 0x68, 0x42, 0xde, 0x81, 0xea, 0xe8, 0x7e, 0x5b, 0x80, 0x0f, 0x1b, 0x2d, 0x06, 0xc7, 0xce, 0xe9, 0x46, 0xc7, 0xf7, 0xb3, 0xa2, 0x02, - 0x21, 0xb5, 0x4d, 0xc2, 0x36, 0xea, 0xe6, 0x7b, 0xb3, 0x61, 0xe6, 0x18, 0x40, 0x5b, 0xce, 0x5b, 0xc2, 0xee, 0xa5, 0xde, 0xe9, 0xe6, 0xe0, 0xa8, 0x58, 0x58, 0x03, 0x34, 0x26, 0x27, 0x65, 0x2a }, - { 0xfa, 0x43, 0xa6, 0xc4, 0x32, 0xa1, 0x2f, 0xb6, 0x37, 0x05, 0xf4, 0xa4, 0xa7, 0x36, 0xdd, 0x1c, 0x45, 0x10, 0x95, 0x83, 0x67, 0x89, 0x79, 0x18, 0x34, 0xad, 0xe7, 0x57, 0x7f, 0x0d, 0x48, 0x9b, - 0x14, 0xdf, 0x5f, 0xc8, 0xd7, 0x0f, 0x78, 0x47, 0x88, 0x20, 0xff, 0x7f, 0xb1, 0x21, 0x27, 0x14, 0x58, 0x32, 0x12, 0xfb, 0x97, 0xe0, 0x81, 0x0e, 0x92, 0xf4, 0x5c, 0x0e, 0x44, 0x48, 0x4e, 0x01, - 0x21, 0xb5, 0x4d, 0xc2, 0x36, 0xea, 0xe6, 0x7b, 0xb3, 0x61, 0xe6, 0x18, 0x40, 0x5b, 0xce, 0x5b, 0xc2, 0xee, 0xa5, 0xde, 0xe9, 0xe6, 0xe0, 0xa8, 0x58, 0x58, 0x03, 0x34, 0x26, 0x27, 0x65, 0x2a } }, - { { 0x1e, 0x89, 0x12, 0xe8, 0xab, 0xca, 0xeb, 0x96, 0x78, 0x43, 0x89, 0x79, 0x26, 0x61, 0x86, 0x2e, 0x37, 0xd7, 0x94, 0xb5, 0xb9, 0xf7, 0xc9, 0xe7, 0x04, 0x6c, 0x96, 0x1c, 0x54, 0x0d, 0xb0, 0x6c, - 0xd3, 0x68, 0x9b, 0x53, 0xa7, 0x56, 0x34, 0x1b, 0x65, 0xff, 0xf9, 0xee, 0xf1, 0xc6, 0xfd, 0x7e, 0xa8, 0x42, 0x59, 0x60, 0x06, 0x5f, 0xc2, 0x89, 0x8b, 0xfc, 0xf8, 0x6c, 0x9a, 0x0d, 0xb1, 0x36 }, - { 0x52, 0x3d, 0x83, 0x25, 0x0f, 0x57, 0x81, 0x76, 0x7b, 0x21, 0xf7, 0x96, 0xd6, 0x1f, 0xfe, 0xd7, 0x7c, 0xc1, 0x32, 0xb5, 0xbc, 0x05, 0x46, 0xdb, 0x6f, 0x25, 0xd8, 0x7a, 0x68, 0xe2, 0x01, 0x81, - 0xf8, 0x9a, 0xc5, 0x29, 0x78, 0x1c, 0x01, 0xc5, 0x4d, 0x61, 0x4e, 0x75, 0xdf, 0x9f, 0xc3, 0x22, 0x96, 0x7c, 0xf9, 0xa7, 0xed, 0x41, 0x6f, 0x64, 0xfd, 0xd4, 0x61, 0x58, 0x0d, 0x49, 0xc9, 0xa4 }, - { 0x4a, 0xf7, 0xda, 0xef, 0xe0, 0x3b, 0x33, 0x19, 0x79, 0x02, 0x7a, 0xbb, 0xd3, 0x53, 0xf4, 0x8c, 0x8a, 0x16, 0xfb, 0xbd, 0x35, 0xd9, 0x70, 0xb2, 0x0a, 0x06, 0x05, 0x14, 0xd0, 0x9e, 0xf6, 0x13, - 0x44, 0xbb, 0xb7, 0x93, 0x86, 0x1b, 0x3c, 0xb0, 0x54, 0xa7, 0x48, 0xc2, 0xa7, 0x10, 0xda, 0x65, 0xb2, 0xdb, 0x0f, 0x85, 0x23, 0x57, 0x77, 0x44, 0x23, 0x20, 0x6d, 0x2e, 0xde, 0x20, 0x01, 0xed }, - { 0x9c, 0xb8, 0x68, 0xeb, 0xbb, 0x8b, 0xaf, 0x81, 0x9c, 0x2f, 0x90, 0x4c, 0xc2, 0x62, 0x17, 0xfc, 0xf2, 0xa5, 0xab, 0x4c, 0x2e, 0x69, 0xcb, 0x82, 0x5f, 0x4c, 0x3c, 0x82, 0xcd, 0x6a, 0xcb, 0x15, - 0xa2, 0xfc, 0x50, 0x54, 0x5e, 0x2e, 0x83, 0x52, 0x48, 0x29, 0x51, 0xcc, 0x50, 0xaa, 0x27, 0xa3, 0xf3, 0x71, 0xdb, 0x2c, 0x1c, 0xa9, 0x8a, 0xa5, 0x95, 0xab, 0x3e, 0x6f, 0xcd, 0xba, 0x22, 0x7c }, - { 0xf7, 0x5d, 0xb5, 0x20, 0x65, 0xfe, 0xa9, 0xe7, 0x1f, 0x8e, 0xd6, 0xc0, 0xf2, 0x3f, 0x1b, 0x8c, 0x7a, 0x02, 0x54, 0xd8, 0xa7, 0x0e, 0x6f, 0x68, 0x94, 0x81, 0xff, 0x30, 0x0e, 0x6d, 0x1a, 0x96, - 0x1b, 0x86, 0x07, 0xaa, 0xbf, 0x37, 0xc5, 0x5e, 0x26, 0xa2, 0xdf, 0x0b, 0xd0, 0x7f, 0x94, 0x35, 0x30, 0xa4, 0x9e, 0x47, 0xaf, 0xad, 0x9c, 0xc9, 0x02, 0x21, 0x55, 0x94, 0x04, 0x13, 0xff, 0x64 }, - { 0x9c, 0x8d, 0x18, 0x63, 0x83, 0xad, 0x01, 0xcc, 0xbb, 0xe6, 0x00, 0xda, 0x15, 0xce, 0xc6, 0x6e, 0x7a, 0x37, 0x6a, 0x81, 0x44, 0xb3, 0xfc, 0xb7, 0xcd, 0x05, 0xee, 0x4a, 0x6f, 0x29, 0xe4, 0x79, - 0x63, 0x52, 0x7e, 0x14, 0xc9, 0x14, 0x77, 0xa8, 0x19, 0x94, 0x03, 0xc6, 0x51, 0x57, 0xf1, 0xcc, 0x11, 0x29, 0xde, 0x86, 0x08, 0xfe, 0x41, 0x02, 0x71, 0xb7, 0xbf, 0xd7, 0xe7, 0x83, 0x3e, 0x0c, - 0x9a, 0x59, 0x7e, 0xe8, 0x61, 0x36, 0x56, 0x9a, 0xbf, 0x64, 0xfd, 0xf3, 0xb7, 0xb9, 0x2f, 0x9e, 0x56, 0x1f, 0x57, 0x45, 0x2e, 0x19, 0x0f, 0x6f, 0x70, 0x01, 0xc2, 0x48, 0x05, 0x23, 0x9b, 0x2f }, - { 0xb5, 0x4e, 0xe7, 0xcc, 0x7b, 0x66, 0x7a, 0xf8, 0xec, 0xcd, 0x1b, 0x0c, 0x0f, 0xec, 0x04, 0x27, 0xa0, 0x61, 0xfd, 0x12, 0x2d, 0xab, 0xc9, 0xc5, 0x8e, 0xee, 0x36, 0xc2, 0xef, 0x67, 0xd5, 0x87, - 0x95, 0x6c, 0x12, 0xb7, 0x12, 0x81, 0x55, 0xe0, 0x7b, 0xdb, 0x8f, 0x67, 0xea, 0x04, 0x55, 0x91, 0x9b, 0x50, 0x65, 0x05, 0xc1, 0xf1, 0x0b, 0x04, 0x91, 0x66, 0x3c, 0x32, 0x53, 0x72, 0x01, 0x04, - 0x9a, 0x59, 0x7e, 0xe8, 0x61, 0x36, 0x56, 0x9a, 0xbf, 0x64, 0xfd, 0xf3, 0xb7, 0xb9, 0x2f, 0x9e, 0x56, 0x1f, 0x57, 0x45, 0x2e, 0x19, 0x0f, 0x6f, 0x70, 0x01, 0xc2, 0x48, 0x05, 0x23, 0x9b, 0x2f } }, - { { 0xc8, 0x37, 0x10, 0xdc, 0xdb, 0xfc, 0x51, 0x91, 0xae, 0x37, 0xa4, 0xe0, 0xcf, 0xbb, 0xdd, 0x92, 0x93, 0x5f, 0x6b, 0xd6, 0x81, 0xbf, 0x9b, 0x24, 0x5e, 0x0d, 0xf1, 0xe4, 0x04, 0x89, 0xd1, 0x1b, - 0xb2, 0x68, 0x56, 0x3a, 0xdc, 0x59, 0xd0, 0x8a, 0x93, 0x37, 0x5d, 0xa5, 0x40, 0x5e, 0xfe, 0xc9, 0x41, 0x0b, 0x8a, 0x50, 0xd2, 0xa0, 0x94, 0x86, 0xf7, 0x46, 0x3b, 0x7e, 0x1d, 0xea, 0x2b, 0xa8 }, - { 0x1b, 0xe2, 0xe6, 0x48, 0x86, 0xa8, 0x65, 0xfd, 0x2b, 0xae, 0xc7, 0x7d, 0x41, 0xee, 0xb2, 0x80, 0x33, 0x1c, 0x0a, 0xdc, 0x42, 0xea, 0x99, 0xd0, 0x1f, 0x6d, 0xc8, 0x80, 0x51, 0x70, 0xd4, 0x19, - 0xae, 0xfc, 0x66, 0x16, 0xa2, 0x53, 0x27, 0x19, 0x7a, 0xf2, 0x9a, 0x25, 0x0c, 0x39, 0x8c, 0xbf, 0xe7, 0xa3, 0x7a, 0xd6, 0xa3, 0x43, 0x62, 0xd2, 0x4a, 0xc2, 0xf1, 0x96, 0x7e, 0xe3, 0x83, 0x13 }, - { 0xf5, 0xb1, 0x2a, 0xc5, 0x4d, 0xcc, 0xdf, 0x56, 0xde, 0x92, 0x96, 0x46, 0x03, 0x11, 0xfc, 0xa0, 0xbc, 0xa2, 0x22, 0xf7, 0x25, 0x74, 0x2a, 0x1f, 0x27, 0x34, 0x18, 0xe8, 0x06, 0xa4, 0x77, 0x26, - 0x1a, 0x51, 0x5e, 0xfb, 0x77, 0xbc, 0x55, 0xb1, 0xf8, 0xa5, 0x19, 0x23, 0x00, 0x97, 0xf7, 0xbb, 0xe4, 0xcd, 0x41, 0x9e, 0xd9, 0x5e, 0x0c, 0x6b, 0x1b, 0x8a, 0xba, 0x52, 0x93, 0xbe, 0x2c, 0xf3 }, - { 0xb3, 0x02, 0xeb, 0x44, 0x3c, 0x05, 0xae, 0x9c, 0x94, 0xa9, 0x1f, 0x72, 0x41, 0xbc, 0x81, 0x66, 0x5f, 0x50, 0xc0, 0x57, 0xb4, 0x44, 0xf0, 0xe1, 0x2a, 0xa9, 0x88, 0x69, 0xa6, 0x1c, 0x05, 0x85, - 0xda, 0xc7, 0xb2, 0xe1, 0x8c, 0x2f, 0x7c, 0x49, 0x37, 0xa2, 0xf2, 0x56, 0xab, 0x12, 0x9f, 0x12, 0x4b, 0x1b, 0x73, 0x75, 0x3f, 0x30, 0x0f, 0x40, 0xf1, 0xf9, 0x1d, 0xa7, 0x2c, 0x98, 0x8c, 0x91 }, - { 0xcb, 0xd3, 0x39, 0x60, 0x56, 0xe3, 0xbd, 0x65, 0x86, 0x1a, 0x58, 0x40, 0xc0, 0xa4, 0xc4, 0x8b, 0xe5, 0xf7, 0x49, 0x0a, 0xf2, 0x09, 0x51, 0x32, 0x6e, 0x06, 0x5a, 0x27, 0x19, 0x78, 0x2e, 0x3a, - 0x04, 0xf9, 0x34, 0x80, 0x49, 0x39, 0x93, 0xcd, 0x89, 0x67, 0x7b, 0xc0, 0x8d, 0x9d, 0x8d, 0x4c, 0x83, 0x20, 0x80, 0xfc, 0x00, 0xf2, 0x8a, 0x8f, 0xa4, 0x4d, 0x8e, 0x8f, 0x58, 0x51, 0x5b, 0x71 }, - { 0x71, 0x3f, 0x90, 0x41, 0xb8, 0x74, 0xbc, 0x7a, 0x85, 0xf5, 0xab, 0xca, 0x7e, 0xf2, 0x70, 0x41, 0xbc, 0x36, 0xb5, 0xc3, 0x4e, 0xf1, 0x2b, 0x17, 0x35, 0x40, 0xdb, 0x3c, 0xdb, 0xd2, 0xec, 0x0b, - 0x99, 0xc1, 0x43, 0x17, 0xad, 0x38, 0x45, 0x2d, 0x07, 0x31, 0xd7, 0xb6, 0x95, 0x1c, 0x89, 0x25, 0xe4, 0x89, 0x97, 0xd3, 0xcf, 0x11, 0x2f, 0x63, 0x31, 0x51, 0xa2, 0x18, 0xfc, 0x12, 0x04, 0x0a, - 0xb0, 0x33, 0xce, 0x0b, 0x57, 0xc0, 0x8c, 0x58, 0x25, 0xf8, 0x9b, 0x50, 0x22, 0x1c, 0x5c, 0x7b, 0x02, 0xc7, 0xed, 0xfc, 0x98, 0x8b, 0xbd, 0xd2, 0x4e, 0xfc, 0x78, 0x91, 0x7f, 0x4c, 0x99, 0x24 }, - { 0xfc, 0x46, 0xe4, 0x85, 0x0c, 0x52, 0x14, 0xf8, 0x8a, 0xa4, 0x97, 0x17, 0x10, 0xb2, 0x93, 0xef, 0xa0, 0x66, 0x3c, 0xfd, 0x61, 0x42, 0x24, 0x30, 0x70, 0x4b, 0xfd, 0x0b, 0x86, 0xc8, 0x97, 0xd7, - 0x04, 0xc2, 0xa6, 0x61, 0x41, 0xaf, 0xcc, 0x1d, 0x52, 0xc9, 0xf3, 0xca, 0xe1, 0x90, 0x7c, 0xbd, 0xce, 0xaf, 0x30, 0xc4, 0xb4, 0x7d, 0x81, 0x7e, 0xbd, 0xe2, 0x09, 0x70, 0x1e, 0x6b, 0xb9, 0x03, - 0xb0, 0x33, 0xce, 0x0b, 0x57, 0xc0, 0x8c, 0x58, 0x25, 0xf8, 0x9b, 0x50, 0x22, 0x1c, 0x5c, 0x7b, 0x02, 0xc7, 0xed, 0xfc, 0x98, 0x8b, 0xbd, 0xd2, 0x4e, 0xfc, 0x78, 0x91, 0x7f, 0x4c, 0x99, 0x24 } }, - { { 0x5f, 0x01, 0x6d, 0xec, 0x82, 0x02, 0x96, 0x47, 0x74, 0xd9, 0x73, 0x2e, 0x2e, 0x17, 0x00, 0xb6, 0xe0, 0xa4, 0x13, 0x17, 0xae, 0x7f, 0x85, 0xcb, 0xff, 0xe7, 0x96, 0x99, 0xdb, 0x9f, 0xad, 0x21, - 0x60, 0xd9, 0x12, 0xdc, 0x41, 0x01, 0x33, 0x66, 0x4c, 0x24, 0x8b, 0x25, 0x17, 0xd7, 0x22, 0x14, 0x12, 0x4d, 0xad, 0x82, 0x9a, 0x85, 0x69, 0x5e, 0x35, 0x10, 0xe0, 0xd7, 0x1a, 0x82, 0x88, 0x14 }, - { 0xab, 0x5f, 0x2c, 0x7d, 0xa2, 0xe5, 0x67, 0x5f, 0xe4, 0x92, 0x03, 0x93, 0xd7, 0x13, 0xa1, 0xfa, 0x4a, 0xb7, 0x18, 0x4a, 0x8e, 0x8c, 0x78, 0x9a, 0x0c, 0x60, 0x02, 0xe8, 0x2d, 0x50, 0x05, 0x0f, - 0x92, 0xee, 0x9f, 0x81, 0xde, 0x6b, 0x20, 0xe4, 0x9b, 0x17, 0x2e, 0x99, 0x0f, 0x01, 0x31, 0xa7, 0xc5, 0xc4, 0x53, 0x70, 0xda, 0x03, 0xc6, 0xf7, 0x22, 0x87, 0x98, 0x87, 0x19, 0x36, 0xa6, 0x49 }, - { 0x93, 0xab, 0x22, 0xc4, 0x39, 0x6c, 0x97, 0x80, 0xd2, 0xe2, 0x36, 0xfa, 0x31, 0x74, 0x67, 0xcc, 0x50, 0x1b, 0x95, 0xbe, 0x77, 0xe0, 0xd1, 0x00, 0x74, 0x04, 0xe1, 0x4d, 0xca, 0x44, 0x35, 0x72, - 0x74, 0x69, 0x82, 0x23, 0x56, 0x9b, 0xcc, 0x34, 0x5a, 0xcb, 0xa2, 0xa3, 0x31, 0x12, 0x4a, 0x84, 0x4c, 0xe9, 0x37, 0x3a, 0x58, 0xf8, 0x79, 0x65, 0x4a, 0x66, 0x79, 0x82, 0xf4, 0x5d, 0x75, 0xc3 }, - { 0x2d, 0x5d, 0xac, 0x4f, 0xb5, 0x00, 0x68, 0x3b, 0x5f, 0x2e, 0xdd, 0xcb, 0x14, 0x4a, 0x7f, 0xad, 0x12, 0x45, 0x91, 0xd1, 0x84, 0xd8, 0x14, 0xff, 0xcb, 0x64, 0x43, 0x6d, 0x65, 0xe7, 0x19, 0x68, - 0x2b, 0x5e, 0x53, 0x05, 0x74, 0x66, 0xed, 0xac, 0x2f, 0x5a, 0x8f, 0x70, 0x96, 0xab, 0x29, 0xf3, 0x9a, 0x59, 0xa2, 0xe2, 0xef, 0xd3, 0xc9, 0xd7, 0x53, 0xf8, 0xf5, 0xa3, 0xd6, 0xf4, 0x34, 0xf8 }, - { 0x1d, 0x14, 0xf3, 0xfd, 0xb0, 0x66, 0x20, 0xff, 0xfc, 0x79, 0x47, 0xc7, 0x4c, 0xe9, 0x45, 0x67, 0xf5, 0x97, 0x14, 0xea, 0x7c, 0x63, 0xc5, 0x3f, 0x0b, 0x46, 0xe0, 0x88, 0xd6, 0x9b, 0x67, 0x71, - 0xba, 0xa6, 0x15, 0x28, 0x94, 0x54, 0x83, 0x68, 0x00, 0x3a, 0x33, 0xa6, 0x1a, 0x05, 0x6a, 0x68, 0x72, 0x98, 0x48, 0x71, 0xea, 0x5b, 0x47, 0xf5, 0x80, 0x46, 0xa9, 0x57, 0x84, 0xec, 0xad, 0xfc }, - { 0xa3, 0x1d, 0x87, 0xd3, 0x28, 0x62, 0xc6, 0xf7, 0xdb, 0xfb, 0xfa, 0xfc, 0xf3, 0x27, 0x5c, 0x31, 0xd3, 0x32, 0x26, 0x0e, 0x0f, 0x41, 0x49, 0xec, 0x05, 0x16, 0xf7, 0xa5, 0x63, 0xb3, 0xbc, 0xe5, - 0x0d, 0x1e, 0x6f, 0x97, 0x4f, 0x68, 0x40, 0xc0, 0xd4, 0x6c, 0x4f, 0x9e, 0x25, 0xd0, 0xab, 0x8d, 0x2a, 0xb9, 0x3e, 0x06, 0x4d, 0x9d, 0x3d, 0x2d, 0x79, 0x8d, 0x93, 0xdc, 0xfc, 0x6f, 0x0b, 0x04, - 0x48, 0x7c, 0x19, 0x5c, 0xa9, 0xc8, 0x44, 0xe5, 0xf6, 0x4f, 0x51, 0xd8, 0x72, 0x63, 0x41, 0xda, 0x62, 0xac, 0x78, 0x73, 0xb3, 0x3e, 0xc8, 0xb2, 0xf1, 0x3f, 0x89, 0xf2, 0x0e, 0x95, 0xdf, 0xed }, - { 0xfd, 0x69, 0xb1, 0x9a, 0xdb, 0xae, 0x95, 0x87, 0xe2, 0xc6, 0x8a, 0x97, 0x0c, 0xee, 0xc4, 0x22, 0x60, 0x4e, 0x96, 0xa9, 0x72, 0xb9, 0x6f, 0x86, 0x97, 0xa8, 0xdf, 0x83, 0xc5, 0x18, 0x18, 0x6e, - 0xc9, 0x43, 0x30, 0x7e, 0x5b, 0xcf, 0x37, 0x0f, 0xc1, 0xd7, 0xe5, 0xab, 0xb1, 0x31, 0xe0, 0x97, 0xc7, 0x53, 0xb7, 0xfd, 0xd7, 0xdf, 0x00, 0x43, 0x0e, 0x41, 0x62, 0x80, 0x0b, 0xe3, 0xe0, 0x06, - 0x48, 0x7c, 0x19, 0x5c, 0xa9, 0xc8, 0x44, 0xe5, 0xf6, 0x4f, 0x51, 0xd8, 0x72, 0x63, 0x41, 0xda, 0x62, 0xac, 0x78, 0x73, 0xb3, 0x3e, 0xc8, 0xb2, 0xf1, 0x3f, 0x89, 0xf2, 0x0e, 0x95, 0xdf, 0xed } }, - { { 0x98, 0x29, 0xf7, 0x57, 0xfd, 0xbd, 0x44, 0x3f, 0xd9, 0x90, 0x98, 0x19, 0x97, 0xf2, 0x60, 0x27, 0xfd, 0x08, 0xfc, 0x8a, 0xc6, 0xaf, 0x87, 0x22, 0x7f, 0x74, 0x4a, 0x80, 0xaf, 0x72, 0x00, 0x01, - 0x70, 0x9b, 0x47, 0x2a, 0xd2, 0x8e, 0x41, 0x0a, 0xea, 0x6a, 0xdf, 0xb7, 0x61, 0x54, 0x89, 0x5e, 0x01, 0x9f, 0x76, 0x64, 0x29, 0xee, 0x8d, 0x85, 0x20, 0xff, 0x30, 0x58, 0xc2, 0xa3, 0x2a, 0x56 }, - { 0xea, 0x69, 0x8e, 0x6b, 0x8e, 0xdd, 0x55, 0x22, 0x45, 0x61, 0xd4, 0x92, 0x66, 0x8e, 0x96, 0xaf, 0x7e, 0x40, 0x28, 0x72, 0xc4, 0x46, 0xe7, 0x88, 0xd4, 0x6c, 0x74, 0xb7, 0x48, 0x7f, 0xe8, 0xe1, - 0x5e, 0xa5, 0x85, 0x62, 0x8f, 0xd6, 0xfc, 0x27, 0x0a, 0xb2, 0x4b, 0x38, 0x94, 0x59, 0x52, 0x0d, 0x6a, 0x4d, 0xe5, 0x61, 0xce, 0x0d, 0x44, 0x03, 0xa6, 0x2a, 0xc2, 0xd4, 0xd4, 0xe2, 0x71, 0xe3 }, - { 0x40, 0xf0, 0x82, 0xf0, 0x8d, 0xaa, 0xad, 0xa9, 0x9f, 0x9b, 0x85, 0x02, 0xcf, 0x57, 0x15, 0x41, 0x13, 0x59, 0xf2, 0xba, 0xdd, 0xbf, 0x93, 0xe5, 0x40, 0x2e, 0xaf, 0xdd, 0x43, 0x52, 0xc8, 0x7f, - 0x40, 0xad, 0x91, 0x5b, 0x58, 0xd1, 0xa1, 0xe8, 0x6f, 0x77, 0xc3, 0x41, 0x35, 0x5e, 0xf7, 0x03, 0xba, 0xe4, 0xed, 0x2c, 0x28, 0x59, 0xd6, 0x48, 0xfe, 0x50, 0xcc, 0xf9, 0x80, 0xd1, 0x49, 0xd1 }, - { 0xd7, 0xa5, 0xd9, 0x13, 0xdf, 0x7d, 0xf6, 0xc6, 0x25, 0x0f, 0x52, 0xc2, 0x57, 0x61, 0x20, 0xf2, 0xf0, 0xdb, 0x47, 0x49, 0x56, 0xaf, 0x89, 0x11, 0xa7, 0x8d, 0x09, 0x3a, 0xfe, 0x45, 0x43, 0xef, - 0x9f, 0x0c, 0x42, 0xaf, 0xa8, 0xcc, 0x60, 0x48, 0xc0, 0x1c, 0x7c, 0xbe, 0x01, 0xe2, 0x88, 0xcc, 0x6c, 0x3e, 0x97, 0x91, 0xf3, 0xd9, 0xb2, 0xb2, 0x09, 0x7e, 0x35, 0xb1, 0x78, 0xb4, 0x03, 0xf6 }, - { 0x08, 0xc4, 0x1a, 0x3a, 0xc3, 0xe3, 0x26, 0xbd, 0x8d, 0xee, 0x5d, 0xf0, 0xba, 0xb6, 0x65, 0xff, 0x77, 0xc0, 0x99, 0xd1, 0xca, 0xdc, 0xf5, 0x4b, 0x50, 0x50, 0x0a, 0x9e, 0x13, 0x33, 0x76, 0x86, - 0x9b, 0x39, 0x79, 0x78, 0x73, 0x5c, 0x2f, 0x69, 0xa9, 0x9e, 0x0b, 0xeb, 0x11, 0x1e, 0x12, 0xaa, 0xc1, 0x09, 0x83, 0x0f, 0xca, 0xcb, 0x95, 0x10, 0xde, 0x85, 0xe3, 0x75, 0x62, 0x4a, 0xc2, 0x4c }, - { 0x68, 0x78, 0x6c, 0xce, 0x2f, 0x72, 0x80, 0xfe, 0x83, 0x88, 0x63, 0x37, 0xa7, 0xa1, 0x5a, 0x0b, 0x84, 0x8a, 0xda, 0x28, 0x84, 0xf1, 0x6a, 0x63, 0x24, 0x1c, 0x72, 0xda, 0x84, 0xee, 0x1d, 0xe0, - 0x77, 0xf0, 0xf6, 0xce, 0x7e, 0x79, 0x0a, 0x55, 0x03, 0x01, 0x13, 0x0f, 0xf7, 0x6b, 0x45, 0xe7, 0xcb, 0xfd, 0xb0, 0x37, 0x93, 0x4b, 0x40, 0x69, 0xe0, 0x77, 0x67, 0x72, 0x65, 0xee, 0x35, 0x08, - 0x00, 0xc0, 0x07, 0x10, 0xd8, 0x6e, 0x55, 0x83, 0x5a, 0xbc, 0xfa, 0x67, 0x80, 0x8f, 0xfa, 0x21, 0x3e, 0x56, 0x53, 0x5b, 0xbc, 0x9d, 0xff, 0x16, 0xd9, 0x57, 0xcf, 0x2b, 0x78, 0x06, 0x5a, 0x89 }, - { 0xdf, 0x32, 0x1a, 0x01, 0x84, 0xe5, 0xb8, 0x2c, 0x70, 0x6c, 0xeb, 0xd1, 0xf0, 0xb4, 0x9b, 0x32, 0xc8, 0xd0, 0x81, 0xc4, 0xea, 0xb2, 0x7c, 0x32, 0x1a, 0x02, 0x61, 0xf2, 0xd9, 0x4d, 0xe5, 0x85, - 0xad, 0xfc, 0xc6, 0x70, 0xee, 0x85, 0x77, 0x07, 0x9b, 0x5d, 0x5f, 0x88, 0xef, 0xb6, 0xd8, 0xdf, 0x2b, 0xa2, 0x4d, 0x90, 0x11, 0x2d, 0x38, 0x3f, 0xa8, 0x84, 0xf0, 0x76, 0xdd, 0x31, 0xd0, 0x09, - 0x00, 0xc0, 0x07, 0x10, 0xd8, 0x6e, 0x55, 0x83, 0x5a, 0xbc, 0xfa, 0x67, 0x80, 0x8f, 0xfa, 0x21, 0x3e, 0x56, 0x53, 0x5b, 0xbc, 0x9d, 0xff, 0x16, 0xd9, 0x57, 0xcf, 0x2b, 0x78, 0x06, 0x5a, 0x89 } }, - { { 0x25, 0x87, 0x1e, 0x6f, 0xe8, 0xd0, 0xde, 0x1d, 0xd5, 0xf2, 0xd3, 0x5b, 0xff, 0x9e, 0x67, 0x99, 0x60, 0xb4, 0x0e, 0xb7, 0x98, 0x1b, 0x2a, 0x3a, 0x9c, 0xec, 0xc1, 0xe1, 0x2e, 0x2b, 0xc0, 0x3e, - 0x3c, 0xfb, 0x64, 0x91, 0x72, 0xc6, 0x7e, 0x57, 0x47, 0x00, 0x97, 0xbf, 0x8e, 0x0e, 0xbf, 0xad, 0xd9, 0x28, 0x86, 0x7c, 0xfd, 0x41, 0x91, 0xae, 0x2d, 0xee, 0xc0, 0xb2, 0x32, 0x7d, 0x99, 0x7d }, - { 0x63, 0xc1, 0xf9, 0x61, 0x9c, 0x9e, 0x1a, 0xd7, 0xca, 0xa3, 0x71, 0xd6, 0x34, 0x3d, 0xa7, 0x08, 0x36, 0x0c, 0xec, 0x37, 0x35, 0x94, 0x1a, 0x45, 0xa9, 0xfa, 0xf2, 0xb5, 0x25, 0x92, 0xbf, 0xd1, - 0x1e, 0xca, 0xdd, 0x5a, 0x23, 0xad, 0x9e, 0x45, 0xc3, 0x66, 0xcb, 0x8f, 0xda, 0xa3, 0xd1, 0xe6, 0x27, 0x38, 0x11, 0x54, 0x67, 0x31, 0x03, 0x64, 0x35, 0xe0, 0x68, 0x0b, 0x93, 0xee, 0x81, 0x17 }, - { 0x8b, 0x01, 0xe9, 0x99, 0x54, 0x54, 0x73, 0x15, 0x0b, 0xac, 0x38, 0x7b, 0xe9, 0xe3, 0x17, 0x4f, 0x02, 0x3e, 0xe3, 0x8e, 0xda, 0x41, 0xa0, 0x9d, 0x10, 0xe0, 0xda, 0x11, 0xfe, 0xec, 0x2f, 0x42, - 0xe7, 0xc8, 0xb3, 0xde, 0x2f, 0x7b, 0xfd, 0xdf, 0x7c, 0x34, 0x3b, 0x5e, 0xac, 0x22, 0x8c, 0x99, 0x3d, 0xa1, 0xa9, 0xd9, 0x81, 0xb6, 0x51, 0xc8, 0xaf, 0x3e, 0x75, 0xed, 0x45, 0xcf, 0xf7, 0xb9 }, - { 0xaf, 0xe9, 0x9c, 0x16, 0x4a, 0x8f, 0x3b, 0x0f, 0xef, 0x71, 0x2f, 0xaa, 0x8d, 0x7d, 0xce, 0xed, 0xea, 0x31, 0x93, 0xaf, 0x2c, 0x75, 0xc6, 0xfa, 0xda, 0x3e, 0xa6, 0xea, 0x2a, 0x3e, 0x7b, 0x72, - 0xb6, 0xf8, 0xd7, 0x9a, 0x88, 0xcb, 0x0b, 0x81, 0x97, 0x24, 0x29, 0x3b, 0x11, 0x23, 0x69, 0xc2, 0xff, 0x98, 0x39, 0x25, 0x99, 0xae, 0xe1, 0x07, 0x3e, 0x97, 0xde, 0x10, 0x21, 0x23, 0x7a, 0x2d }, - { 0xbe, 0x2f, 0xb9, 0x4c, 0x41, 0x5a, 0x9a, 0xf6, 0xfb, 0xf8, 0x26, 0x9d, 0x81, 0x7f, 0x39, 0x91, 0xaf, 0x5b, 0xf1, 0xd7, 0x93, 0x0a, 0xdf, 0x18, 0x19, 0x4a, 0x80, 0x74, 0x14, 0x98, 0x2b, 0xf2, - 0x3b, 0x25, 0xc5, 0xe8, 0xfc, 0x07, 0x3f, 0x5d, 0xa1, 0x39, 0x27, 0x4e, 0x1c, 0xd2, 0x7a, 0xfe, 0x3e, 0x7b, 0x03, 0x35, 0x15, 0x9e, 0x35, 0x2b, 0xd0, 0xbe, 0x67, 0x48, 0x42, 0xdd, 0xa4, 0xdd }, - { 0xbd, 0xcd, 0xd7, 0xbf, 0xb1, 0x0a, 0xdb, 0x9f, 0x85, 0x42, 0xba, 0xf4, 0xc8, 0xff, 0xb0, 0xe1, 0x9a, 0x18, 0x6d, 0x1a, 0xe0, 0x37, 0xc1, 0xa2, 0xe1, 0x1c, 0x38, 0x55, 0x14, 0xbf, 0x64, 0x67, - 0x84, 0x47, 0xb6, 0x0a, 0xf6, 0x93, 0xf1, 0x10, 0xab, 0x09, 0xf0, 0x60, 0x84, 0xe2, 0x4e, 0x4b, 0x5e, 0xa2, 0xd2, 0xd1, 0x19, 0x22, 0xd7, 0xc4, 0x85, 0x13, 0x23, 0xa3, 0x6a, 0xb6, 0x75, 0x0f, - 0x43, 0xe6, 0xde, 0x7b, 0x67, 0x2a, 0x73, 0x77, 0x9e, 0xb4, 0x94, 0x6c, 0xc3, 0x9a, 0x67, 0x51, 0xcf, 0xe9, 0x47, 0x46, 0x0e, 0x3a, 0x12, 0x7d, 0x7c, 0x66, 0x73, 0x6c, 0xd5, 0x4a, 0x21, 0x4d }, - { 0x89, 0x7e, 0xd0, 0xbf, 0x2e, 0x9f, 0x0c, 0xff, 0x6e, 0x56, 0x25, 0x9b, 0x79, 0x99, 0x52, 0x27, 0xc2, 0x3a, 0xaa, 0xf0, 0x47, 0x6d, 0xed, 0x05, 0xa1, 0xeb, 0x9c, 0x92, 0x28, 0x7f, 0x1b, 0xc8, - 0x1c, 0x57, 0x76, 0xab, 0x05, 0xe3, 0xd3, 0xb7, 0xa3, 0xf5, 0xac, 0xa8, 0x21, 0x33, 0x7c, 0xb7, 0xe7, 0xc2, 0xd0, 0x25, 0x6f, 0xdf, 0x34, 0xd1, 0xb0, 0x34, 0x41, 0x46, 0x30, 0x9c, 0x76, 0x07, - 0x43, 0xe6, 0xde, 0x7b, 0x67, 0x2a, 0x73, 0x77, 0x9e, 0xb4, 0x94, 0x6c, 0xc3, 0x9a, 0x67, 0x51, 0xcf, 0xe9, 0x47, 0x46, 0x0e, 0x3a, 0x12, 0x7d, 0x7c, 0x66, 0x73, 0x6c, 0xd5, 0x4a, 0x21, 0x4d } } + { { 0xa1, 0xfc, 0x7a, 0xb4, 0x6d, 0xdf, 0x7d, 0xcf, 0xe7, 0xec, 0x75, 0xe5, 0xfa, 0xdd, 0x11, 0xcb, 0xcc, 0x37, 0xf8, 0x84, 0x5d, 0x1c, 0x92, 0x4e, 0x09, 0x89, 0x65, 0xfc, 0xd8, 0xe9, 0x5a, 0x30, + 0xda, 0xe4, 0x86, 0xa3, 0x35, 0xb4, 0x19, 0x0c, 0xbc, 0x7b, 0xcb, 0x3e, 0xb9, 0x4c, 0xbd, 0x16, 0xe8, 0x3d, 0x13, 0x2b, 0xc9, 0xc3, 0x39, 0xea, 0xf1, 0x42, 0xe7, 0x6f, 0x69, 0x78, 0x9a, 0xb7 }, + { 0xe5, 0xf3, 0x7b, 0xd4, 0x0e, 0xc9, 0xdc, 0x77, 0x50, 0x86, 0xdc, 0xf4, 0x2e, 0xbc, 0xdb, 0x27, 0xf0, 0x73, 0xd4, 0x58, 0x73, 0xc4, 0x4b, 0x71, 0x8b, 0x3c, 0xc5, 0x4f, 0xa8, 0x7c, 0xa4, 0x84, + 0xd9, 0x96, 0x23, 0x73, 0xb4, 0x03, 0x16, 0xbf, 0x1e, 0xa1, 0x2d, 0xd8, 0xc4, 0x8a, 0xe7, 0x82, 0x10, 0xda, 0xc9, 0xe5, 0x45, 0x9b, 0x01, 0xdc, 0x73, 0xa6, 0xc9, 0x17, 0xa8, 0x15, 0x31, 0x6d }, + { 0x3e, 0x49, 0xa4, 0x0e, 0x3a, 0xaf, 0xa3, 0x07, 0x3d, 0xf7, 0x2a, 0xec, 0x43, 0xb1, 0xd4, 0x09, 0x1a, 0xcb, 0x8e, 0x92, 0xf9, 0x65, 0x95, 0x04, 0x6d, 0x2d, 0x9b, 0x34, 0xa3, 0xbf, 0x51, 0x00, + 0xe2, 0xee, 0x23, 0xf5, 0x28, 0x0a, 0xa9, 0xb1, 0x57, 0x0b, 0x96, 0x56, 0x62, 0xba, 0x12, 0x94, 0xaf, 0xc6, 0x5f, 0xb5, 0x61, 0x43, 0x0f, 0xde, 0x0b, 0xab, 0xfa, 0x4f, 0xfe, 0xc5, 0xe7, 0x18 }, + { 0x00, 0x4d, 0x41, 0x8d, 0xe4, 0x69, 0x23, 0xae, 0x98, 0xc4, 0x3e, 0x77, 0x0f, 0x1d, 0x94, 0x5d, 0x29, 0x3e, 0x94, 0x5a, 0x38, 0x39, 0x20, 0x0f, 0xd3, 0x6f, 0x76, 0xa2, 0x29, 0x02, 0x03, 0xcb, + 0x0b, 0x7f, 0x4f, 0x1a, 0x29, 0x51, 0x13, 0x33, 0x7c, 0x99, 0xb3, 0x81, 0x82, 0x39, 0x44, 0x05, 0x97, 0xfb, 0x0d, 0xf2, 0x93, 0xa2, 0x40, 0x94, 0xf4, 0xff, 0x5d, 0x09, 0x61, 0xe4, 0x5f, 0x76 }, + { 0xab, 0xce, 0xd2, 0x24, 0xe8, 0x93, 0xb0, 0xe7, 0x72, 0x14, 0xdc, 0xbb, 0x7d, 0x0f, 0xd8, 0x94, 0x16, 0x9e, 0xb5, 0x7f, 0xd7, 0x19, 0x5f, 0x3e, 0x2d, 0x45, 0xd5, 0xf7, 0x90, 0x0b, 0x3e, 0x05, + 0x18, 0x2e, 0x2b, 0xf4, 0xfa, 0xd4, 0xec, 0x62, 0x4a, 0x4f, 0x48, 0x50, 0xaf, 0x1c, 0xe8, 0x9f, 0x1a, 0xe1, 0x3d, 0x70, 0x49, 0x00, 0xa7, 0xe3, 0x5b, 0x1e, 0xa1, 0x9b, 0x68, 0x1e, 0xa1, 0x73 }, + { 0xed, 0xb6, 0xd0, 0xf0, 0x06, 0x6e, 0x33, 0x9c, 0x86, 0xfb, 0xe8, 0xc3, 0x6c, 0x8d, 0xde, 0xdd, 0xa6, 0xa0, 0x2d, 0xb9, 0x07, 0x29, 0xa3, 0x13, 0xbb, 0xa4, 0xba, 0xec, 0x48, 0xc8, 0xf4, 0x56, + 0x82, 0x79, 0xe2, 0xb1, 0xd3, 0x3d, 0x83, 0x9f, 0x10, 0xe8, 0x52, 0xe6, 0x8b, 0x1c, 0x33, 0x9e, 0x2b, 0xd2, 0xdb, 0x62, 0x1c, 0x56, 0xfd, 0x50, 0x40, 0x77, 0x81, 0xab, 0x21, 0x67, 0x3e, 0x09, + 0x4f, 0xf2, 0x51, 0xac, 0x7d, 0xe7, 0xd1, 0x5d, 0x4b, 0xe2, 0x08, 0xc6, 0x3f, 0x6a, 0x4d, 0xc8, 0x5d, 0x74, 0xf6, 0x3b, 0xec, 0x8e, 0xc6, 0x0c, 0x32, 0x27, 0x2f, 0x9c, 0x09, 0x48, 0x59, 0x10 }, + { 0x23, 0x0f, 0xa3, 0xe2, 0x69, 0xce, 0xb9, 0xb9, 0xd1, 0x1c, 0x4e, 0xab, 0x63, 0xc9, 0x2e, 0x1e, 0x7e, 0xa2, 0xa2, 0xa0, 0x49, 0x2e, 0x78, 0xe4, 0x8a, 0x02, 0x3b, 0xa7, 0xab, 0x1f, 0xd4, 0xce, + 0x05, 0xe2, 0x80, 0x09, 0x09, 0x3c, 0x61, 0xc7, 0x10, 0x3a, 0x9c, 0xf4, 0x95, 0xac, 0x89, 0x6f, 0x23, 0xb3, 0x09, 0xe2, 0x24, 0x3f, 0xf6, 0x96, 0x02, 0x36, 0x41, 0x16, 0x32, 0xe1, 0x66, 0x05, + 0x4f, 0xf2, 0x51, 0xac, 0x7d, 0xe7, 0xd1, 0x5d, 0x4b, 0xe2, 0x08, 0xc6, 0x3f, 0x6a, 0x4d, 0xc8, 0x5d, 0x74, 0xf6, 0x3b, 0xec, 0x8e, 0xc6, 0x0c, 0x32, 0x27, 0x2f, 0x9c, 0x09, 0x48, 0x59, 0x10 } }, + { { 0xfd, 0x81, 0x14, 0xf1, 0x67, 0x07, 0x44, 0xbb, 0x93, 0x84, 0xa2, 0xdc, 0x36, 0xdc, 0xcc, 0xb3, 0x9e, 0x82, 0xd4, 0x8b, 0x42, 0x56, 0xfb, 0xf2, 0x6e, 0x83, 0x3b, 0x16, 0x2c, 0x29, 0xfb, 0x39, + 0x29, 0x48, 0x85, 0xe3, 0xe3, 0xf7, 0xe7, 0x80, 0x49, 0xd3, 0x01, 0x30, 0x5a, 0x2c, 0x3f, 0x4c, 0xea, 0x13, 0xeb, 0xda, 0xf4, 0x56, 0x75, 0x8d, 0x50, 0x1e, 0x19, 0x2d, 0x29, 0x2b, 0xfb, 0xdb }, + { 0x85, 0x34, 0x4d, 0xf7, 0x39, 0xbf, 0x98, 0x79, 0x8c, 0x98, 0xeb, 0x8d, 0x61, 0x27, 0xec, 0x87, 0x56, 0xcd, 0xd0, 0xa6, 0x55, 0x77, 0xee, 0xf0, 0x20, 0xd0, 0x59, 0x39, 0x95, 0xab, 0x29, 0x82, + 0x8e, 0x61, 0xf8, 0xad, 0xed, 0xb6, 0x27, 0xc3, 0xd8, 0x16, 0xce, 0x67, 0x78, 0xe2, 0x04, 0x4b, 0x0c, 0x2d, 0x2f, 0xc3, 0x24, 0x72, 0xbc, 0x53, 0xbd, 0xfe, 0x39, 0x23, 0xd4, 0xaf, 0x27, 0x84 }, + { 0x11, 0xbe, 0x5f, 0x5a, 0x73, 0xe7, 0x42, 0xef, 0xff, 0x3c, 0x47, 0x6a, 0x0e, 0x6b, 0x9e, 0x96, 0x21, 0xa3, 0xdf, 0x49, 0xe9, 0x3f, 0x40, 0xfc, 0xab, 0xb3, 0x66, 0xd3, 0x3d, 0xfa, 0x02, 0x29, + 0xf3, 0x43, 0x45, 0x3c, 0x70, 0xa3, 0x5d, 0x39, 0xf7, 0xc0, 0x6a, 0xcd, 0xfa, 0x1d, 0xbe, 0x3b, 0x91, 0x41, 0xe4, 0xb0, 0x60, 0xc0, 0x22, 0xf7, 0x2c, 0x11, 0x2b, 0x1c, 0x5f, 0x24, 0xef, 0x53 }, + { 0xfd, 0x3f, 0x09, 0x06, 0xc9, 0x39, 0x8d, 0x48, 0xfa, 0x6b, 0xc9, 0x80, 0xbf, 0xf6, 0xd6, 0x76, 0xb3, 0x62, 0x70, 0x88, 0x4f, 0xde, 0xde, 0xb9, 0xb4, 0xf0, 0xce, 0xf3, 0x74, 0x0d, 0xea, 0x00, + 0x9e, 0x9c, 0x29, 0xe1, 0xa2, 0x1b, 0xbd, 0xb5, 0x83, 0xcc, 0x12, 0xd8, 0x48, 0x08, 0x5b, 0xe5, 0xd6, 0xf9, 0x11, 0x5c, 0xe0, 0xd9, 0xc3, 0x3c, 0x26, 0xbd, 0x69, 0x9f, 0x5c, 0x6f, 0x0c, 0x6f }, + { 0xca, 0xd4, 0x76, 0x32, 0x8b, 0xbe, 0x0c, 0x65, 0x75, 0x43, 0x73, 0xc2, 0xf2, 0xfd, 0x7f, 0xeb, 0xe4, 0x62, 0xc5, 0x0d, 0x0f, 0xf9, 0x01, 0xc8, 0xb9, 0xfa, 0xca, 0xb4, 0x12, 0x1c, 0xb4, 0xac, + 0x0e, 0x5f, 0x18, 0xfc, 0x0c, 0x7f, 0x2a, 0x55, 0xc5, 0xfd, 0x4d, 0x83, 0xb2, 0x02, 0x31, 0x6a, 0x3f, 0x14, 0xee, 0x9d, 0x11, 0xa8, 0x06, 0xad, 0xeb, 0x93, 0x19, 0x79, 0xb1, 0xf2, 0x78, 0x05 }, + { 0x85, 0xe6, 0xe2, 0xf2, 0x96, 0xe7, 0xa2, 0x8b, 0x7e, 0x36, 0xbd, 0x7b, 0xf4, 0x28, 0x6a, 0xd7, 0xbc, 0x2a, 0x6a, 0x59, 0xfd, 0xc0, 0xc8, 0x3d, 0x50, 0x0f, 0x0c, 0x2b, 0x12, 0x3a, 0x75, 0xc7, + 0x56, 0xbb, 0x7f, 0x7d, 0x4e, 0xd4, 0x03, 0xb8, 0x7b, 0xde, 0xde, 0x99, 0x65, 0x9e, 0xc4, 0xa6, 0x6e, 0xfe, 0x00, 0x88, 0xeb, 0x9d, 0xa4, 0xa9, 0x9d, 0x37, 0xc9, 0x4a, 0xcf, 0x69, 0xc4, 0x01, + 0xba, 0xa8, 0xce, 0xeb, 0x72, 0xcb, 0x64, 0x8b, 0x9f, 0xc1, 0x1f, 0x9a, 0x9e, 0x99, 0xcc, 0x39, 0xec, 0xd9, 0xbb, 0xd9, 0xce, 0xc2, 0x74, 0x6f, 0xd0, 0x2a, 0xb9, 0xc6, 0xe3, 0xf5, 0xe7, 0xf4 }, + { 0xb1, 0x39, 0x50, 0xb1, 0x1a, 0x08, 0x42, 0x2b, 0xdd, 0x6d, 0x20, 0x9f, 0x0f, 0x37, 0xba, 0x69, 0x97, 0x21, 0x30, 0x7a, 0x71, 0x2f, 0xce, 0x98, 0x09, 0x04, 0xa2, 0x98, 0x6a, 0xed, 0x02, 0x1d, + 0x5d, 0x30, 0x8f, 0x03, 0x47, 0x6b, 0x89, 0xfd, 0xf7, 0x1a, 0xca, 0x46, 0x6f, 0x51, 0x69, 0x9a, 0x2b, 0x18, 0x77, 0xe4, 0xad, 0x0d, 0x7a, 0x66, 0xd2, 0x2c, 0x28, 0xa0, 0xd3, 0x0a, 0x99, 0x0d, + 0xba, 0xa8, 0xce, 0xeb, 0x72, 0xcb, 0x64, 0x8b, 0x9f, 0xc1, 0x1f, 0x9a, 0x9e, 0x99, 0xcc, 0x39, 0xec, 0xd9, 0xbb, 0xd9, 0xce, 0xc2, 0x74, 0x6f, 0xd0, 0x2a, 0xb9, 0xc6, 0xe3, 0xf5, 0xe7, 0xf4 } }, + { { 0x02, 0x3a, 0x7e, 0x0c, 0x6d, 0x96, 0x3c, 0x5d, 0x44, 0x56, 0x5d, 0xc1, 0x49, 0x94, 0x35, 0x12, 0x9d, 0xff, 0x8a, 0x5d, 0x91, 0x74, 0xa8, 0x15, 0xee, 0x5d, 0x1e, 0x72, 0xbe, 0x86, 0x15, 0x68, + 0xe7, 0x36, 0xa2, 0x4a, 0xb8, 0xa2, 0xa4, 0x4c, 0xd8, 0x95, 0xe3, 0xc7, 0xbb, 0x32, 0x21, 0x90, 0x64, 0x52, 0x32, 0xeb, 0x26, 0xd3, 0x4f, 0xf0, 0x8e, 0x27, 0x40, 0xea, 0xed, 0xdb, 0xf5, 0xc4 }, + { 0x76, 0x99, 0x64, 0x70, 0xf4, 0x50, 0xc8, 0xcc, 0x4a, 0x5a, 0xa5, 0x0f, 0xeb, 0x2d, 0xc7, 0x0e, 0x73, 0xd0, 0x65, 0x7d, 0xc3, 0xce, 0x73, 0x03, 0x20, 0x2f, 0xad, 0x65, 0xfd, 0x12, 0xe4, 0x7f, + 0xfd, 0x45, 0x3a, 0x6e, 0xc5, 0x9a, 0x06, 0x67, 0x0e, 0xa6, 0x7b, 0x21, 0x49, 0x2d, 0x01, 0x1b, 0x8e, 0x03, 0x6e, 0x10, 0x08, 0x0c, 0x68, 0xd9, 0x60, 0x47, 0xa4, 0xe2, 0x52, 0xfd, 0x3c, 0xf4 }, + { 0xa3, 0xe2, 0x5f, 0x16, 0x39, 0x78, 0x96, 0xf7, 0x47, 0x6f, 0x93, 0x5d, 0x27, 0x7b, 0x58, 0xe0, 0xc5, 0xdb, 0x71, 0x7d, 0xa9, 0x6f, 0xf8, 0x8b, 0x69, 0xdd, 0x50, 0xea, 0x91, 0x0d, 0x66, 0x77, + 0xaf, 0x8f, 0xd5, 0x9f, 0x8a, 0x26, 0x69, 0x4c, 0x64, 0x37, 0x62, 0x81, 0x6f, 0x05, 0x9a, 0x08, 0x0d, 0xe1, 0x69, 0x24, 0x77, 0x3f, 0x50, 0xb2, 0x49, 0x4d, 0x93, 0xef, 0x2e, 0x87, 0xff, 0xde }, + { 0xb3, 0x32, 0xe2, 0x67, 0x79, 0x32, 0x5f, 0x64, 0x47, 0x49, 0x1c, 0xd3, 0x8f, 0x95, 0x44, 0xfd, 0x4c, 0x7e, 0xbf, 0x6b, 0xb7, 0xaf, 0x2c, 0xdd, 0x8f, 0xa5, 0xd8, 0x2f, 0xbf, 0xa0, 0x8a, 0x6b, + 0x58, 0x25, 0xc9, 0x12, 0x23, 0x6f, 0xe6, 0x05, 0xa8, 0xd0, 0x68, 0x6e, 0x0c, 0xee, 0x70, 0xe4, 0xa3, 0x86, 0x51, 0x04, 0x6d, 0xca, 0xd5, 0xed, 0xcf, 0x74, 0x1d, 0x60, 0x9e, 0x86, 0x2d, 0x05 }, + { 0x91, 0xf4, 0x5f, 0x4a, 0xcb, 0xd8, 0xfd, 0x5f, 0xb9, 0x3d, 0x04, 0xb8, 0xec, 0x35, 0x85, 0x4f, 0x58, 0x20, 0xd1, 0x1f, 0x47, 0xc4, 0xf4, 0xcb, 0x21, 0x4e, 0x9a, 0xf1, 0x6e, 0xbf, 0xe3, 0xd3, + 0x62, 0xe3, 0x82, 0xf6, 0xba, 0xa8, 0xdf, 0x92, 0xe2, 0x3c, 0xe5, 0xf0, 0x16, 0x8a, 0xeb, 0xa4, 0xbb, 0xc7, 0x81, 0xaf, 0x15, 0x19, 0x87, 0x5f, 0xb7, 0xe0, 0x4c, 0x12, 0xff, 0x2c, 0xa9, 0xc8 }, + { 0xaf, 0x85, 0xe0, 0x36, 0x43, 0xdf, 0x41, 0x17, 0xda, 0xde, 0x5e, 0xb6, 0x33, 0xd0, 0xce, 0x62, 0x70, 0x5f, 0x85, 0x24, 0x6c, 0x3e, 0x1b, 0xe1, 0x52, 0xc1, 0x9b, 0x1c, 0xcd, 0x61, 0x80, 0x9c, + 0xa0, 0xe8, 0x18, 0xee, 0x40, 0x91, 0x93, 0x82, 0xdb, 0x33, 0x44, 0xff, 0xd4, 0xf6, 0x6f, 0x5d, 0xf0, 0x0e, 0x92, 0x92, 0x81, 0x55, 0x46, 0x06, 0xac, 0x58, 0x81, 0x3b, 0x04, 0xc7, 0xf7, 0x0d, + 0xd2, 0x0c, 0x08, 0x6d, 0x46, 0xdb, 0x43, 0x28, 0x31, 0xd8, 0xcd, 0x87, 0x50, 0xbb, 0xd3, 0x07, 0xf5, 0x72, 0x0b, 0x15, 0x7c, 0x16, 0xab, 0x03, 0xd9, 0x4b, 0x07, 0x38, 0x97, 0xe8, 0xd6, 0xb5 }, + { 0x93, 0xff, 0x6d, 0xc3, 0x62, 0xf7, 0xcc, 0x20, 0x95, 0xc2, 0x2f, 0x7d, 0x1d, 0x9b, 0xd1, 0x63, 0xfc, 0x61, 0x47, 0xb3, 0x22, 0x0f, 0xca, 0xb0, 0x16, 0xcf, 0x29, 0x53, 0x46, 0x97, 0xb1, 0x36, + 0x46, 0xac, 0x48, 0x13, 0x92, 0xe4, 0x46, 0x68, 0xcf, 0x09, 0x4e, 0xfa, 0x59, 0x45, 0x24, 0x08, 0xdb, 0xb4, 0x6f, 0x20, 0x55, 0x12, 0xd9, 0x75, 0x9d, 0x8e, 0x0b, 0xf8, 0x63, 0xe0, 0xf9, 0x01, + 0xd2, 0x0c, 0x08, 0x6d, 0x46, 0xdb, 0x43, 0x28, 0x31, 0xd8, 0xcd, 0x87, 0x50, 0xbb, 0xd3, 0x07, 0xf5, 0x72, 0x0b, 0x15, 0x7c, 0x16, 0xab, 0x03, 0xd9, 0x4b, 0x07, 0x38, 0x97, 0xe8, 0xd6, 0xb5 } }, + { { 0x14, 0x35, 0xa6, 0x7d, 0xc1, 0xb5, 0x71, 0xca, 0x42, 0x50, 0x90, 0xa7, 0x72, 0x85, 0xbe, 0x78, 0x7a, 0x5f, 0x83, 0x1e, 0xbe, 0xef, 0x6a, 0xbe, 0x48, 0xc5, 0x68, 0x14, 0x0c, 0xf7, 0x44, 0x5c, + 0x2e, 0xfd, 0x1b, 0xcc, 0xee, 0x09, 0x23, 0x82, 0x31, 0xad, 0xaf, 0x4b, 0x73, 0x9c, 0xf2, 0x88, 0x3c, 0xf3, 0xb5, 0x43, 0x8b, 0x53, 0xf9, 0xac, 0x17, 0x86, 0x1c, 0xc2, 0x53, 0x43, 0xec, 0x03 }, + { 0x7b, 0x36, 0x6c, 0xcc, 0xb5, 0xb2, 0x23, 0x3d, 0x7c, 0xe5, 0xe7, 0xcf, 0x06, 0xe2, 0x32, 0x0b, 0xc5, 0x3b, 0x7f, 0x86, 0x40, 0xfc, 0xaf, 0xba, 0x94, 0xe0, 0x88, 0x58, 0x5b, 0xac, 0xe8, 0xc3, + 0xe8, 0xc3, 0xdf, 0xc4, 0x45, 0x29, 0xe8, 0xf0, 0x1c, 0x10, 0x0d, 0x50, 0x81, 0x29, 0x30, 0xa8, 0x27, 0xb5, 0x3e, 0xb8, 0x25, 0xf1, 0x17, 0x30, 0xc6, 0x05, 0xe3, 0x3e, 0x45, 0x38, 0xa8, 0x3c }, + { 0xce, 0xd9, 0x45, 0x28, 0xb0, 0xce, 0xa5, 0x47, 0xa8, 0x29, 0x32, 0x76, 0x99, 0x73, 0x8d, 0x74, 0xf9, 0xed, 0x0a, 0xd0, 0xf1, 0xd8, 0x7e, 0x44, 0x63, 0x9e, 0x9a, 0xcf, 0x7c, 0x35, 0x8a, 0x29, + 0xbb, 0x71, 0x66, 0x8d, 0xa7, 0xfc, 0x05, 0x3d, 0xd4, 0x4b, 0x65, 0x20, 0xf5, 0xa4, 0x64, 0xd8, 0x9d, 0x16, 0x80, 0x9c, 0xb2, 0x3c, 0x3e, 0xd4, 0x9d, 0x09, 0x88, 0x8e, 0xbb, 0x58, 0xf8, 0x77 }, + { 0xe1, 0x29, 0xb3, 0x16, 0xe6, 0xa0, 0xdb, 0x64, 0x08, 0x36, 0xdc, 0x33, 0xad, 0x8b, 0x30, 0x26, 0x17, 0x56, 0xd7, 0x34, 0x17, 0xd1, 0xdd, 0x23, 0x38, 0x58, 0x25, 0x01, 0x42, 0x5a, 0x9d, 0x18, + 0x3e, 0xac, 0x31, 0xfa, 0x43, 0x28, 0xc4, 0x65, 0xfb, 0x30, 0x2f, 0x8c, 0x16, 0x52, 0x32, 0x1b, 0x19, 0xb7, 0x31, 0xf6, 0x67, 0xa7, 0xd8, 0xed, 0x9a, 0xa3, 0x95, 0x01, 0xd7, 0xb9, 0xe7, 0xcc }, + { 0x81, 0x2d, 0x11, 0xa9, 0x11, 0xf1, 0x22, 0xe2, 0x67, 0x70, 0xc4, 0xba, 0x34, 0xa1, 0x75, 0x8c, 0xf6, 0x0c, 0x63, 0xe7, 0x01, 0x3c, 0x64, 0x6c, 0xe8, 0xd0, 0xf8, 0x8e, 0x88, 0xdf, 0x5c, 0x61, + 0x68, 0x5d, 0x1f, 0xeb, 0x83, 0x1f, 0x40, 0xb8, 0xa8, 0x56, 0x57, 0x26, 0x81, 0x2c, 0xa3, 0x0e, 0x48, 0x4c, 0x45, 0x4d, 0x0d, 0x3d, 0x6e, 0x99, 0x52, 0xbd, 0x0b, 0xd8, 0x05, 0xc5, 0xf9, 0x61 }, + { 0x92, 0x45, 0xbe, 0xe6, 0xb4, 0x7a, 0xfa, 0x28, 0xd4, 0x5b, 0x6b, 0x17, 0xc6, 0x13, 0x61, 0x5d, 0x5f, 0xd7, 0x90, 0xbb, 0x89, 0x35, 0x7a, 0x02, 0x50, 0x57, 0x56, 0x5f, 0x19, 0xb5, 0xb6, 0xc5, + 0x77, 0x1e, 0x1b, 0xc0, 0xd7, 0x7a, 0x29, 0xbd, 0xe7, 0x24, 0x01, 0x2d, 0x37, 0xc0, 0x38, 0x6f, 0xc8, 0x35, 0xa1, 0x1b, 0xe0, 0xea, 0x16, 0xad, 0xbc, 0xdc, 0xd4, 0x8d, 0x4e, 0x71, 0xdb, 0x05, + 0x9e, 0xb5, 0x53, 0x6b, 0x5c, 0xf1, 0x7d, 0x15, 0x8b, 0xd7, 0xc7, 0x8b, 0x89, 0x9d, 0xfd, 0x28, 0x7c, 0xa1, 0x31, 0xe2, 0xf0, 0x2c, 0x3a, 0x8d, 0x0e, 0x23, 0x85, 0x4e, 0xf0, 0xd1, 0xc0, 0x83 }, + { 0x7b, 0x88, 0xeb, 0x45, 0x1c, 0x7f, 0xfd, 0xbe, 0xba, 0xac, 0x53, 0x28, 0x59, 0xe8, 0xad, 0x28, 0xf1, 0x97, 0x2d, 0x6c, 0x31, 0xa6, 0xae, 0x47, 0x10, 0x69, 0x68, 0x55, 0xa6, 0x9c, 0x03, 0x62, + 0xb7, 0x2f, 0x31, 0x46, 0x2a, 0x2b, 0x98, 0xdd, 0xe9, 0xf9, 0xfe, 0x77, 0x71, 0x41, 0x54, 0xf8, 0x59, 0x02, 0x7a, 0xe3, 0x45, 0x67, 0xb6, 0xf7, 0x94, 0x31, 0x3e, 0x62, 0x62, 0x2a, 0xf9, 0x0a, + 0x9e, 0xb5, 0x53, 0x6b, 0x5c, 0xf1, 0x7d, 0x15, 0x8b, 0xd7, 0xc7, 0x8b, 0x89, 0x9d, 0xfd, 0x28, 0x7c, 0xa1, 0x31, 0xe2, 0xf0, 0x2c, 0x3a, 0x8d, 0x0e, 0x23, 0x85, 0x4e, 0xf0, 0xd1, 0xc0, 0x83 } }, + { { 0x27, 0x4d, 0x84, 0x08, 0x95, 0x84, 0xc8, 0xeb, 0x1c, 0x9a, 0x0f, 0xca, 0x09, 0x6f, 0x48, 0x8b, 0x2b, 0x06, 0xa0, 0xae, 0xf2, 0xe3, 0x8a, 0xfe, 0xd7, 0x52, 0x4b, 0xf2, 0xc6, 0x7c, 0xc1, 0x55, + 0x87, 0x2e, 0x5a, 0xb4, 0xc2, 0x43, 0x0a, 0x0d, 0xd0, 0x00, 0xa8, 0xe1, 0x46, 0x68, 0x79, 0xd8, 0x8c, 0x01, 0x36, 0xb7, 0x5a, 0x61, 0x04, 0xe9, 0x7e, 0xbb, 0xc9, 0xee, 0xaa, 0x12, 0x13, 0xda }, + { 0x78, 0x66, 0xd0, 0xa2, 0x50, 0x82, 0x8d, 0xb0, 0xa0, 0x20, 0xac, 0xa4, 0xb6, 0xa0, 0x31, 0xf7, 0x7d, 0x93, 0x37, 0x67, 0xbb, 0x60, 0xa2, 0x1e, 0x36, 0xce, 0x3d, 0x48, 0x1d, 0x79, 0x99, 0xa5, + 0x19, 0xd8, 0x89, 0x1b, 0xcb, 0x14, 0x87, 0xb7, 0x62, 0xfd, 0xd2, 0xef, 0xbb, 0x13, 0x41, 0x4d, 0xf1, 0x77, 0x5c, 0x7f, 0x6c, 0x3b, 0x94, 0x7d, 0xb4, 0xba, 0x87, 0x3e, 0xc8, 0xe1, 0x3c, 0x0a }, + { 0xd9, 0x9e, 0x14, 0x89, 0xd6, 0xf8, 0x49, 0xa2, 0xe2, 0x19, 0xfe, 0x94, 0xaa, 0xf7, 0x35, 0xf9, 0x4a, 0xf8, 0xf3, 0x18, 0x68, 0x96, 0x47, 0xc6, 0x23, 0x7c, 0xb0, 0x53, 0xcb, 0xd8, 0x90, 0x31, + 0xb7, 0x50, 0x0e, 0x06, 0xc3, 0x84, 0x75, 0xf1, 0xac, 0x16, 0x4d, 0xc1, 0xbe, 0xf1, 0x80, 0x33, 0x47, 0x56, 0x6f, 0x33, 0x94, 0x5c, 0x81, 0x03, 0x4c, 0x2f, 0x6d, 0xac, 0x73, 0xba, 0x91, 0x3c }, + { 0x2f, 0xa9, 0xb6, 0xe8, 0x73, 0xe2, 0xef, 0x6d, 0x6d, 0xd7, 0x2e, 0xa0, 0x51, 0x61, 0x24, 0x81, 0x8c, 0xa8, 0x47, 0x40, 0xe1, 0xc7, 0x75, 0x79, 0xc8, 0xec, 0xb2, 0x23, 0x41, 0xad, 0x61, 0x3b, + 0xea, 0x8a, 0xdf, 0x63, 0xed, 0xe1, 0x8e, 0x50, 0x70, 0x6e, 0x86, 0xed, 0xb0, 0xba, 0x27, 0x48, 0x8e, 0xb9, 0x63, 0x39, 0x78, 0x58, 0x4f, 0x1e, 0xbc, 0x45, 0xf3, 0xf2, 0x3a, 0x73, 0x9b, 0x8c }, + { 0xad, 0x42, 0xc5, 0x84, 0xca, 0xe1, 0xe1, 0x23, 0x2a, 0x73, 0x15, 0x3c, 0x9a, 0xfe, 0x85, 0x8d, 0xa3, 0x2c, 0xcf, 0x46, 0x8d, 0x7f, 0x1c, 0x61, 0xd7, 0x0e, 0xb1, 0xa6, 0xb4, 0xae, 0xab, 0x63, + 0xc4, 0x0e, 0xf2, 0xa0, 0x5d, 0xa6, 0xf3, 0x5d, 0x35, 0x41, 0xea, 0x03, 0x91, 0xb1, 0x3a, 0x07, 0xe6, 0xed, 0x6c, 0x8c, 0xcb, 0x75, 0x27, 0xf1, 0x26, 0x58, 0xf0, 0x62, 0x57, 0xe4, 0x33, 0x00 }, + { 0x1f, 0xed, 0x53, 0xc6, 0xef, 0x38, 0x26, 0xa4, 0x18, 0x88, 0x8f, 0x5c, 0x49, 0x1c, 0x15, 0x7d, 0x77, 0x90, 0x06, 0x39, 0xe0, 0x7c, 0x25, 0xed, 0x79, 0x05, 0x66, 0xe0, 0x5e, 0x94, 0xe3, 0x46, + 0x6f, 0x96, 0xd8, 0xc1, 0x11, 0xa4, 0x11, 0x6f, 0x78, 0x42, 0x8e, 0x89, 0xc7, 0xc3, 0xed, 0xd2, 0x9e, 0x68, 0x47, 0x79, 0x89, 0x23, 0x70, 0x14, 0x21, 0x60, 0x2d, 0xfe, 0x37, 0x4b, 0xc8, 0x0a, + 0x16, 0x73, 0x7c, 0xc4, 0x55, 0x3f, 0x25, 0x04, 0x08, 0x75, 0x74, 0x68, 0xbc, 0xe4, 0x3a, 0xae, 0x4c, 0x0e, 0xd2, 0x85, 0xa1, 0xbc, 0x81, 0xc0, 0xc9, 0xfe, 0x9a, 0x44, 0x7b, 0x83, 0xdf, 0xc7 }, + { 0x27, 0x77, 0x97, 0x84, 0x0f, 0x2d, 0x8d, 0x33, 0xb8, 0x4e, 0xdb, 0x8b, 0xea, 0x58, 0x52, 0x88, 0x95, 0x88, 0x55, 0x5f, 0xb8, 0xc4, 0xc9, 0xd6, 0x1f, 0x1e, 0xee, 0x60, 0xb5, 0xeb, 0x78, 0x72, + 0xb5, 0xe5, 0x22, 0x2b, 0x7f, 0x5e, 0xc7, 0x9b, 0x29, 0x55, 0x8e, 0x2a, 0xfc, 0x65, 0x55, 0x4a, 0x02, 0xad, 0x64, 0x06, 0xd4, 0x25, 0xe1, 0x96, 0x6f, 0xee, 0x96, 0xcd, 0x29, 0xc6, 0x64, 0x00, + 0x16, 0x73, 0x7c, 0xc4, 0x55, 0x3f, 0x25, 0x04, 0x08, 0x75, 0x74, 0x68, 0xbc, 0xe4, 0x3a, 0xae, 0x4c, 0x0e, 0xd2, 0x85, 0xa1, 0xbc, 0x81, 0xc0, 0xc9, 0xfe, 0x9a, 0x44, 0x7b, 0x83, 0xdf, 0xc7 } }, + { { 0x5e, 0xc5, 0x5b, 0x9c, 0xdb, 0x14, 0x05, 0x18, 0x6b, 0xe2, 0x1d, 0x16, 0x77, 0x22, 0x0e, 0xd2, 0xe4, 0x57, 0x82, 0x6e, 0x5b, 0xc5, 0x6a, 0xb9, 0x34, 0x20, 0xdb, 0x72, 0xe2, 0xe1, 0xeb, 0x1b, + 0x34, 0x00, 0x04, 0xbf, 0x83, 0xf6, 0x4f, 0x12, 0x45, 0x08, 0xf0, 0x95, 0x2a, 0xdc, 0x3a, 0x14, 0xb3, 0x29, 0x0b, 0x99, 0xcd, 0x73, 0x31, 0xbd, 0x04, 0xbb, 0x49, 0x1c, 0xde, 0xcf, 0x09, 0x9e }, + { 0x15, 0x80, 0x3e, 0x2a, 0xfb, 0xc0, 0x8d, 0x62, 0x19, 0x27, 0x83, 0x04, 0xcc, 0xf5, 0xd1, 0xbb, 0x40, 0x41, 0xbe, 0x93, 0x59, 0x6e, 0x27, 0x6d, 0x95, 0x24, 0x0a, 0x07, 0x27, 0x86, 0x10, 0x75, + 0xf7, 0x0a, 0x11, 0xfc, 0x53, 0xd0, 0x4c, 0x15, 0xf8, 0x6e, 0x22, 0x3f, 0xeb, 0x12, 0x97, 0x8a, 0x3d, 0x69, 0xd8, 0x96, 0xc9, 0x53, 0x10, 0x9c, 0x02, 0x95, 0xe4, 0xd3, 0x1a, 0xd5, 0x43, 0x82 }, + { 0x40, 0x09, 0x2c, 0x17, 0x7e, 0xba, 0xce, 0x1f, 0xfc, 0xc1, 0x8e, 0xc3, 0x1c, 0xa2, 0x34, 0x52, 0x78, 0x16, 0x23, 0x71, 0x82, 0x40, 0xf8, 0x6d, 0x67, 0x65, 0x67, 0x50, 0x53, 0xd9, 0xc8, 0x5e, + 0x7e, 0x8a, 0x98, 0xa3, 0xc6, 0x2a, 0x4d, 0x27, 0xf3, 0xb9, 0xbb, 0xae, 0x43, 0x29, 0x6e, 0x02, 0x1c, 0xe9, 0x01, 0xd6, 0xcd, 0xd8, 0x91, 0x44, 0x95, 0x2b, 0x9e, 0xa5, 0x4f, 0xd0, 0x00, 0xb9 }, + { 0x3a, 0xe8, 0x3d, 0xb3, 0x32, 0xdc, 0xc2, 0xc8, 0xe3, 0x36, 0x2f, 0xc9, 0x30, 0x3a, 0xc0, 0x76, 0x56, 0xd3, 0x0b, 0x06, 0xbe, 0x8f, 0xe7, 0xf1, 0x66, 0x61, 0x25, 0x42, 0x28, 0xdc, 0x08, 0x81, + 0x84, 0x3a, 0x57, 0x96, 0x27, 0xa6, 0xcf, 0xd6, 0x8f, 0x35, 0xa2, 0xc3, 0x76, 0x86, 0x4f, 0xcf, 0x5f, 0xa1, 0x85, 0x28, 0x4f, 0x4a, 0x3a, 0xbb, 0x5c, 0x25, 0x4b, 0xcc, 0x46, 0xfe, 0xf2, 0x04 }, + { 0x62, 0xc8, 0xa2, 0x0a, 0x59, 0xb8, 0x97, 0xd2, 0x68, 0x94, 0x00, 0x3b, 0x01, 0xac, 0x91, 0x6e, 0x97, 0x8e, 0x08, 0xe3, 0xfe, 0x9f, 0x9e, 0x9f, 0x4b, 0xcc, 0x5d, 0x1d, 0xb9, 0xbf, 0x07, 0x83, + 0xfe, 0x51, 0x2a, 0xdf, 0x79, 0x2e, 0x07, 0xc9, 0x98, 0x9b, 0xbe, 0xb6, 0xe4, 0x0a, 0x20, 0x44, 0x86, 0xea, 0xb1, 0x61, 0x58, 0x11, 0x32, 0x8e, 0x7b, 0xb9, 0x67, 0x2d, 0xf0, 0x78, 0xb2, 0x93 }, + { 0x1a, 0x65, 0xb3, 0x6f, 0xa2, 0x45, 0x29, 0x53, 0xd7, 0x23, 0x4d, 0xff, 0x8e, 0xe9, 0xb9, 0xef, 0x16, 0xa0, 0xdd, 0x48, 0xdf, 0x70, 0xd2, 0xe1, 0x56, 0xca, 0xd1, 0xd0, 0x4a, 0x9d, 0x63, 0x92, + 0x2b, 0xfd, 0x7b, 0x87, 0x39, 0x3c, 0x12, 0xc7, 0xe5, 0x91, 0x31, 0x95, 0x78, 0xc4, 0x58, 0x95, 0x89, 0x6e, 0x2c, 0x90, 0xb4, 0x0b, 0xb2, 0xfe, 0x52, 0xc0, 0x86, 0xc4, 0x2e, 0x56, 0x97, 0x0c, + 0x20, 0xf2, 0xbc, 0x6a, 0x9b, 0x89, 0xfb, 0xe9, 0x85, 0x95, 0xd6, 0x22, 0x5e, 0x4d, 0x6d, 0x83, 0x9d, 0xf4, 0xbe, 0x66, 0x05, 0x32, 0xb6, 0xe2, 0xf1, 0x96, 0x42, 0xa4, 0xc8, 0x8c, 0x1b, 0xec }, + { 0x43, 0x85, 0xff, 0xb9, 0xcf, 0x04, 0x83, 0x40, 0x70, 0x3a, 0x9c, 0x48, 0xb4, 0xc2, 0x99, 0x3b, 0xa0, 0x39, 0xf1, 0x39, 0x58, 0x7f, 0xd2, 0x49, 0x94, 0x3c, 0xc3, 0xe1, 0xb6, 0x56, 0x38, 0x55, + 0x6f, 0xb5, 0x1a, 0x90, 0xa2, 0x04, 0x2f, 0x19, 0xf8, 0xb1, 0x65, 0x5a, 0xad, 0xcd, 0x1c, 0x56, 0x42, 0x38, 0xc2, 0x52, 0x09, 0xd6, 0x41, 0x98, 0x5d, 0x5f, 0xa5, 0xe7, 0xc2, 0x55, 0xa1, 0x09, + 0x20, 0xf2, 0xbc, 0x6a, 0x9b, 0x89, 0xfb, 0xe9, 0x85, 0x95, 0xd6, 0x22, 0x5e, 0x4d, 0x6d, 0x83, 0x9d, 0xf4, 0xbe, 0x66, 0x05, 0x32, 0xb6, 0xe2, 0xf1, 0x96, 0x42, 0xa4, 0xc8, 0x8c, 0x1b, 0xec } }, + { { 0xf2, 0x4a, 0x96, 0x57, 0xc3, 0x2f, 0xe6, 0x9f, 0xed, 0x7f, 0xcc, 0xe9, 0xea, 0xbe, 0xd2, 0x23, 0x4e, 0x47, 0x13, 0xd9, 0x53, 0x19, 0x31, 0x14, 0x0a, 0xd3, 0x9b, 0x95, 0xa7, 0x9c, 0x88, 0x5e, + 0x08, 0xb2, 0x16, 0xda, 0x45, 0x61, 0x1d, 0x6b, 0xdf, 0xb1, 0x14, 0x0c, 0x66, 0xfd, 0x3a, 0xbe, 0x25, 0xdc, 0xfd, 0xcd, 0xcc, 0x5e, 0x28, 0x77, 0x5a, 0xa9, 0x8b, 0x84, 0x77, 0x26, 0x9d, 0xa6 }, + { 0xea, 0xde, 0x4d, 0xab, 0x09, 0x02, 0xbf, 0x90, 0xf8, 0xae, 0x8b, 0x50, 0x01, 0xb2, 0x9d, 0x7c, 0x0a, 0x3b, 0x60, 0xda, 0x34, 0xa9, 0xbb, 0x4d, 0xa5, 0x53, 0x18, 0x65, 0xec, 0xaa, 0xc9, 0x29, + 0xb2, 0xf7, 0x74, 0x14, 0x63, 0x5f, 0x88, 0xcf, 0x4e, 0x70, 0x1b, 0x11, 0x64, 0x73, 0x15, 0x6b, 0x5a, 0x8c, 0xb8, 0x4e, 0x0f, 0x83, 0xae, 0x4b, 0x5c, 0x52, 0x1c, 0x6a, 0x0f, 0x54, 0x77, 0xc8 }, + { 0xae, 0xff, 0x55, 0xbf, 0x78, 0xb5, 0xde, 0x33, 0xeb, 0x87, 0xea, 0x13, 0x7d, 0x36, 0x22, 0x06, 0x32, 0xc4, 0x7e, 0xca, 0x65, 0x37, 0xcc, 0x83, 0x0e, 0xda, 0x54, 0xb3, 0xd2, 0xe6, 0xe7, 0x7f, + 0xe1, 0x90, 0x11, 0x25, 0x16, 0x83, 0x25, 0x43, 0xb4, 0x38, 0x06, 0xbb, 0x6c, 0x62, 0x7d, 0x84, 0x1f, 0xf3, 0x7b, 0xeb, 0xae, 0x50, 0xd8, 0xfb, 0xb9, 0xf2, 0xf9, 0xc3, 0x6f, 0x59, 0xb7, 0xb0 }, + { 0x95, 0x15, 0x83, 0x19, 0x56, 0x9c, 0x11, 0xd8, 0x31, 0x87, 0x1d, 0xe3, 0x3f, 0x07, 0x89, 0xb2, 0xcb, 0x81, 0xf0, 0xeb, 0x0b, 0x1e, 0x74, 0x08, 0xa2, 0x4a, 0x0e, 0x82, 0xc6, 0x45, 0x8c, 0x32, + 0xb4, 0x8f, 0xfd, 0x76, 0xeb, 0x5e, 0xc7, 0x62, 0xdc, 0xcb, 0xee, 0xad, 0xcf, 0xcf, 0xea, 0x33, 0x9d, 0xb0, 0x02, 0x64, 0x66, 0x77, 0x14, 0x97, 0x0c, 0x6e, 0x79, 0xe8, 0x58, 0x32, 0x0f, 0xe6 }, + { 0xcb, 0x2f, 0xaf, 0x53, 0xd8, 0x41, 0x48, 0x41, 0x6f, 0x36, 0x78, 0x80, 0x83, 0x5c, 0x0d, 0x4c, 0x1b, 0xf4, 0x39, 0xe0, 0x34, 0x4f, 0xc2, 0xb2, 0x4e, 0xf0, 0xac, 0xc2, 0xf8, 0x15, 0x7a, 0x81, + 0x9f, 0x46, 0x2b, 0xe3, 0xb9, 0x39, 0x05, 0x89, 0xa2, 0xda, 0x1a, 0x63, 0x51, 0xb4, 0x78, 0x0f, 0xfe, 0x2f, 0x9d, 0xce, 0x99, 0x38, 0xa9, 0x7e, 0xcb, 0x80, 0x57, 0x9f, 0xa2, 0x28, 0x0f, 0x6a }, + { 0x1b, 0xec, 0x67, 0x50, 0xd1, 0x28, 0x65, 0x55, 0xb8, 0xde, 0x3b, 0x2e, 0x1e, 0x33, 0xd8, 0x1b, 0xba, 0x2e, 0x78, 0x6a, 0xb8, 0x0b, 0x8c, 0xa0, 0x55, 0x34, 0x25, 0x90, 0x9a, 0xe2, 0xf5, 0xaa, + 0x95, 0x0c, 0x6f, 0x2a, 0xb0, 0x92, 0x1d, 0x48, 0x5b, 0x56, 0x8c, 0x82, 0x8f, 0xa7, 0x15, 0x75, 0x26, 0x61, 0x85, 0xc8, 0x7d, 0xda, 0xf5, 0x2a, 0xf3, 0x3c, 0x34, 0xc1, 0x20, 0x67, 0xbb, 0x04, + 0xec, 0x7c, 0xe2, 0xcb, 0x31, 0xcf, 0x23, 0xda, 0x5d, 0x8a, 0x05, 0x00, 0x9b, 0x23, 0x34, 0xd0, 0xed, 0x56, 0x10, 0x0a, 0x90, 0x6b, 0x73, 0x26, 0x6b, 0xf0, 0xd7, 0xbc, 0xd8, 0xc7, 0x89, 0xc8 }, + { 0x90, 0x43, 0x54, 0x87, 0x44, 0x00, 0x07, 0xca, 0xa8, 0x2b, 0xec, 0x55, 0xa0, 0xd2, 0x8c, 0x07, 0x03, 0xaa, 0x61, 0x1a, 0x7d, 0x0f, 0x90, 0x13, 0x67, 0x99, 0x46, 0x20, 0xcd, 0x70, 0xcb, 0xa7, + 0x96, 0xdf, 0x0c, 0x13, 0xc4, 0x41, 0x11, 0xd6, 0xc3, 0x33, 0x02, 0x96, 0x4f, 0x1d, 0xbd, 0x06, 0xa9, 0xa1, 0x31, 0x0a, 0xc3, 0xdf, 0x6d, 0x52, 0x6c, 0xc6, 0xbe, 0xc5, 0xb6, 0x2a, 0xb1, 0x0f, + 0xec, 0x7c, 0xe2, 0xcb, 0x31, 0xcf, 0x23, 0xda, 0x5d, 0x8a, 0x05, 0x00, 0x9b, 0x23, 0x34, 0xd0, 0xed, 0x56, 0x10, 0x0a, 0x90, 0x6b, 0x73, 0x26, 0x6b, 0xf0, 0xd7, 0xbc, 0xd8, 0xc7, 0x89, 0xc8 } }, + { { 0x4f, 0x3a, 0xdd, 0x0f, 0xcf, 0x7f, 0x27, 0xda, 0x27, 0xc4, 0xa6, 0x2b, 0x6b, 0xd1, 0x9f, 0x59, 0x73, 0x5f, 0xd4, 0xb7, 0xf0, 0x86, 0x16, 0xc9, 0xdd, 0xa6, 0xf9, 0x9b, 0x17, 0xb2, 0xb9, 0x71, + 0xe7, 0x4c, 0xa1, 0x17, 0x79, 0xe0, 0xcc, 0xae, 0x10, 0xec, 0x28, 0x3a, 0x09, 0xf2, 0x8b, 0x34, 0x9c, 0xac, 0x16, 0x2a, 0xa9, 0x21, 0xe8, 0xa7, 0x18, 0xc0, 0xc4, 0x9f, 0x30, 0xa0, 0x25, 0x62 }, + { 0x23, 0x4c, 0xd4, 0xae, 0x52, 0x30, 0xf6, 0x64, 0xb9, 0xe1, 0x47, 0xca, 0xf8, 0xf3, 0x3a, 0x6b, 0x8b, 0xf3, 0x29, 0xe2, 0x9b, 0x5d, 0xbb, 0x0a, 0x60, 0x52, 0x03, 0x40, 0x53, 0x5c, 0x9e, 0x35, + 0x03, 0xd4, 0xec, 0xd7, 0x67, 0xf4, 0x92, 0xd2, 0x98, 0x96, 0xf2, 0xa7, 0xf4, 0x25, 0x6a, 0x80, 0x9c, 0x75, 0xc6, 0xf2, 0x1f, 0x67, 0x11, 0x00, 0x0d, 0xda, 0x1e, 0xb2, 0x58, 0xa7, 0x8c, 0x39 }, + { 0x55, 0x1b, 0x80, 0xbb, 0xf3, 0xc5, 0x1a, 0x84, 0x34, 0xf5, 0x0a, 0x8a, 0x8a, 0xe1, 0x8c, 0xea, 0xa6, 0xfb, 0xd0, 0x26, 0xc9, 0xa2, 0x30, 0x37, 0x3e, 0xba, 0x98, 0xfe, 0x81, 0x8a, 0x52, 0x37, + 0x0b, 0x74, 0x4e, 0x3d, 0x26, 0x8f, 0x82, 0x4b, 0xc0, 0x6a, 0x01, 0x10, 0x91, 0x8f, 0x89, 0xb5, 0x62, 0x3f, 0x1e, 0x70, 0xcc, 0x25, 0x77, 0x39, 0x74, 0x88, 0xdd, 0xbc, 0xbe, 0x72, 0x08, 0x63 }, + { 0xe2, 0x9a, 0x46, 0xd2, 0x74, 0xdc, 0x0f, 0x8a, 0xa3, 0xbd, 0x20, 0xb7, 0xc7, 0xd9, 0x83, 0x4b, 0x58, 0xa6, 0xe3, 0xbd, 0xc5, 0x00, 0xb6, 0x18, 0x04, 0x25, 0x81, 0xbd, 0x99, 0xb3, 0xb1, 0x2a, + 0x7a, 0x68, 0x6d, 0xe1, 0x3e, 0x23, 0x8d, 0x29, 0x9e, 0x7a, 0x30, 0x56, 0x4c, 0x22, 0xb6, 0xf4, 0x7d, 0x7d, 0x4f, 0xfd, 0x76, 0xa5, 0x9d, 0x05, 0x41, 0x7c, 0x7a, 0x2d, 0x7b, 0xbe, 0xcf, 0x73 }, + { 0x7b, 0xae, 0x11, 0x86, 0x8a, 0x38, 0xbd, 0x56, 0x3c, 0xf3, 0x3c, 0x9c, 0x49, 0xa4, 0x68, 0x0f, 0x2b, 0xdf, 0xf2, 0xa1, 0xbc, 0xc2, 0xed, 0x08, 0x09, 0x96, 0xd0, 0x7e, 0x9b, 0xe3, 0x0a, 0x72, + 0x13, 0x03, 0xd4, 0x35, 0x0a, 0x94, 0x60, 0x09, 0x4a, 0xaa, 0xca, 0x35, 0x8e, 0xed, 0x12, 0xdd, 0x26, 0x8f, 0xf8, 0xa9, 0xa2, 0x8a, 0x7f, 0xac, 0xf3, 0x09, 0xc7, 0x22, 0xc5, 0x73, 0xec, 0xa0 }, + { 0xe9, 0xc5, 0x57, 0x0d, 0x85, 0xbf, 0x10, 0xe2, 0xd1, 0xf5, 0xd7, 0x22, 0xe9, 0x6a, 0x67, 0x8d, 0xd3, 0x9f, 0x1a, 0xef, 0x7f, 0xc0, 0x2b, 0xe1, 0xfd, 0x2c, 0xc2, 0x5f, 0x39, 0xf9, 0x34, 0xd0, + 0x87, 0x94, 0x41, 0x8a, 0x65, 0xa5, 0x20, 0x48, 0xa4, 0x20, 0x5f, 0x7a, 0xc7, 0x37, 0x00, 0x60, 0x59, 0x84, 0x2a, 0x1d, 0xff, 0x02, 0xc3, 0xe8, 0x20, 0xaa, 0x39, 0x13, 0xac, 0xf3, 0xd7, 0x05, + 0xbd, 0xef, 0x11, 0x66, 0x71, 0xb8, 0x9f, 0x1e, 0xe5, 0xee, 0x2e, 0x37, 0xfb, 0x34, 0xed, 0xc5, 0xa4, 0x40, 0x6e, 0x38, 0x31, 0x0a, 0x1c, 0xaf, 0x0d, 0xd3, 0x98, 0xac, 0x12, 0x40, 0xea, 0x9c }, + { 0xc6, 0xcd, 0x7a, 0xbd, 0x14, 0xdb, 0xe4, 0xed, 0xbf, 0x46, 0x70, 0x23, 0xbd, 0xdb, 0xc3, 0xce, 0x60, 0xd5, 0x6b, 0x17, 0x4c, 0x23, 0xfa, 0x78, 0x05, 0xcc, 0x18, 0xed, 0x42, 0x03, 0xa5, 0xb7, + 0xdf, 0x28, 0x0e, 0xd4, 0x5d, 0x31, 0xd8, 0xb9, 0xdc, 0xe9, 0xf6, 0x26, 0xc5, 0xe1, 0xb3, 0x80, 0x0d, 0x62, 0xaf, 0x2d, 0xbd, 0xd6, 0xe4, 0xbb, 0x16, 0x82, 0xc8, 0x13, 0x2a, 0x6f, 0xb9, 0x06, + 0xbd, 0xef, 0x11, 0x66, 0x71, 0xb8, 0x9f, 0x1e, 0xe5, 0xee, 0x2e, 0x37, 0xfb, 0x34, 0xed, 0xc5, 0xa4, 0x40, 0x6e, 0x38, 0x31, 0x0a, 0x1c, 0xaf, 0x0d, 0xd3, 0x98, 0xac, 0x12, 0x40, 0xea, 0x9c } }, + { { 0x6f, 0x46, 0xcd, 0x96, 0xc4, 0x13, 0xf4, 0x11, 0x62, 0x49, 0x8c, 0x5c, 0x78, 0x27, 0xef, 0xc8, 0xb9, 0xe2, 0x7d, 0xf1, 0x0d, 0x37, 0xf2, 0xfe, 0x85, 0x35, 0x82, 0x60, 0x23, 0xb6, 0x7b, 0x17, + 0xd2, 0x91, 0xef, 0x01, 0x9e, 0x99, 0x35, 0xab, 0xc7, 0xfb, 0xa1, 0xa3, 0x13, 0x44, 0x3f, 0x3c, 0x16, 0xcb, 0xd8, 0xf0, 0xbf, 0x9e, 0x65, 0x4d, 0x07, 0xe0, 0xfd, 0x8e, 0x32, 0x61, 0x95, 0xd5 }, + { 0xb7, 0x81, 0x16, 0x2f, 0xcb, 0xa4, 0x30, 0x4e, 0x6d, 0xf5, 0xf0, 0x3f, 0xfe, 0xd9, 0x81, 0x20, 0xa6, 0x0e, 0x2b, 0xa8, 0xc5, 0xed, 0x0d, 0x9a, 0x28, 0x9c, 0xe3, 0xa9, 0xb7, 0xbf, 0x87, 0x0f, + 0xa5, 0xf9, 0x33, 0xe7, 0xa6, 0x7f, 0x9b, 0xac, 0xb6, 0xcc, 0xaf, 0xfc, 0xa7, 0x4a, 0x4d, 0x36, 0x39, 0xa9, 0xb6, 0xf5, 0x09, 0xde, 0x8d, 0x37, 0x11, 0x07, 0xd1, 0x8a, 0xf5, 0x7b, 0x66, 0xe1 }, + { 0xcc, 0xe0, 0x07, 0x62, 0xbe, 0x10, 0x8c, 0x3a, 0xa2, 0x96, 0x5d, 0x11, 0xc7, 0xd5, 0x50, 0xc3, 0xbb, 0x55, 0x21, 0xc5, 0x40, 0x27, 0x7d, 0xdb, 0xad, 0xd2, 0x61, 0x2a, 0x42, 0x5f, 0x94, 0x23, + 0x77, 0x83, 0x3a, 0x99, 0xe8, 0xda, 0x79, 0x8c, 0x1e, 0xa8, 0x44, 0x04, 0xec, 0xf5, 0xd1, 0x55, 0x1e, 0x58, 0xf1, 0x6e, 0x4d, 0x27, 0xa4, 0x91, 0xec, 0x59, 0xc8, 0x17, 0x36, 0x58, 0x2a, 0x1f }, + { 0x6d, 0xf8, 0x73, 0xa3, 0x38, 0x61, 0x1d, 0x95, 0x09, 0xde, 0xe5, 0x26, 0x1b, 0x15, 0x16, 0xfb, 0xf5, 0x16, 0xa8, 0xf3, 0x9e, 0x3a, 0x6b, 0xb5, 0x8c, 0xee, 0xa8, 0x66, 0x79, 0xc3, 0x9e, 0xb4, + 0xe1, 0xc2, 0x85, 0x0e, 0x86, 0x10, 0x5a, 0x4e, 0x8b, 0x4c, 0x0a, 0x7a, 0xd8, 0x8a, 0x48, 0xf4, 0xa0, 0x79, 0x37, 0xe3, 0xa5, 0x90, 0x05, 0x5e, 0xbd, 0xa1, 0xf6, 0x09, 0x58, 0x9c, 0x6f, 0x09 }, + { 0x66, 0x47, 0x6d, 0x60, 0x06, 0x2d, 0x90, 0x8f, 0xae, 0x6c, 0x01, 0xe9, 0xb0, 0xf9, 0x6b, 0xa5, 0x4a, 0xe1, 0xdb, 0xd3, 0x64, 0x42, 0x37, 0x5c, 0x11, 0x40, 0x7a, 0xce, 0x4e, 0x83, 0xc3, 0x2c, + 0x2e, 0xd2, 0x67, 0x76, 0xfb, 0x8c, 0x5d, 0xab, 0xe8, 0xb8, 0xd6, 0x2b, 0xf8, 0x86, 0xff, 0x96, 0xf3, 0xa8, 0x0e, 0x2b, 0x1a, 0x68, 0xf5, 0xe4, 0xee, 0x49, 0xa6, 0x8c, 0x41, 0x1f, 0x97, 0xbf }, + { 0x81, 0x92, 0x4e, 0xc6, 0xab, 0x00, 0xdd, 0xf9, 0xf9, 0xb7, 0xe0, 0x0a, 0xa9, 0x3f, 0x0a, 0xf9, 0x32, 0x73, 0xf6, 0x22, 0xec, 0x95, 0xd9, 0x20, 0x8a, 0x3f, 0xeb, 0x0d, 0xc7, 0x79, 0x6f, 0xb3, + 0x85, 0xf4, 0xe1, 0x11, 0xe1, 0xcc, 0xaa, 0x1b, 0xfd, 0xf3, 0x43, 0xff, 0x66, 0x73, 0x0f, 0x09, 0xcc, 0xa4, 0x6c, 0xb8, 0x2a, 0x0f, 0x53, 0x58, 0x63, 0x32, 0x06, 0xd9, 0x6b, 0x1a, 0x14, 0x04, + 0x85, 0x3f, 0x2f, 0x2b, 0x05, 0xfb, 0xed, 0xe9, 0x08, 0x0d, 0x21, 0x49, 0xc9, 0x79, 0xdf, 0x6f, 0x77, 0x89, 0xd7, 0x74, 0x09, 0x57, 0x1a, 0xd2, 0xa7, 0x43, 0xbf, 0x08, 0x8e, 0x98, 0xbc, 0x2f }, + { 0xe3, 0xb1, 0xc4, 0x81, 0xe6, 0xec, 0x07, 0x58, 0xa4, 0xcb, 0x7e, 0xd5, 0xae, 0x9d, 0x43, 0xf1, 0xb7, 0xe2, 0x0a, 0x1f, 0xd5, 0xe8, 0x14, 0xba, 0x22, 0xff, 0xb7, 0x20, 0x76, 0x08, 0xdc, 0x9a, + 0x44, 0x4c, 0x1c, 0xcd, 0x38, 0x4d, 0xb5, 0xd8, 0xa9, 0x1b, 0x9d, 0xbb, 0x13, 0x5a, 0x6c, 0xe9, 0x5d, 0xa4, 0x42, 0x0e, 0xde, 0x9a, 0x47, 0x8a, 0x2a, 0x97, 0x42, 0x86, 0x87, 0x98, 0x3f, 0x04, + 0x85, 0x3f, 0x2f, 0x2b, 0x05, 0xfb, 0xed, 0xe9, 0x08, 0x0d, 0x21, 0x49, 0xc9, 0x79, 0xdf, 0x6f, 0x77, 0x89, 0xd7, 0x74, 0x09, 0x57, 0x1a, 0xd2, 0xa7, 0x43, 0xbf, 0x08, 0x8e, 0x98, 0xbc, 0x2f } }, + { { 0xff, 0xe3, 0x69, 0x7b, 0x62, 0x45, 0x40, 0x5f, 0x1c, 0x49, 0x65, 0xd6, 0xae, 0x24, 0x16, 0x84, 0xfa, 0x69, 0x6c, 0x1f, 0x6c, 0x65, 0xee, 0x52, 0xe9, 0x6c, 0x54, 0xc7, 0x31, 0x9b, 0xc2, 0x74, + 0x4f, 0xc0, 0x16, 0xb8, 0xf8, 0x75, 0x5f, 0x45, 0xb5, 0xf3, 0xa0, 0xd9, 0xbe, 0x25, 0x82, 0xbd, 0x3c, 0x03, 0xe0, 0x14, 0x15, 0x6a, 0xd5, 0x64, 0x08, 0x65, 0x13, 0x33, 0xc2, 0xab, 0xe0, 0x45 }, + { 0x6f, 0x5a, 0x90, 0x80, 0x25, 0x13, 0xc2, 0xa7, 0xfe, 0x1c, 0xa1, 0x07, 0x81, 0x4b, 0x09, 0xd3, 0xbd, 0xda, 0x55, 0xa8, 0xaa, 0x62, 0x19, 0x03, 0xe9, 0x9f, 0x77, 0xef, 0xff, 0xd4, 0x5e, 0x53, + 0xbc, 0x9d, 0x71, 0xb8, 0xc4, 0xc2, 0x85, 0xb9, 0xb4, 0x3d, 0x95, 0xb8, 0xfd, 0x44, 0xb7, 0xc8, 0x6f, 0x93, 0x15, 0x04, 0x16, 0x7e, 0x01, 0xf2, 0x09, 0x23, 0x96, 0x69, 0xe5, 0x65, 0x52, 0x34 }, + { 0xaf, 0xfe, 0x4f, 0x34, 0x4e, 0xfe, 0x51, 0xa5, 0xb2, 0xd8, 0x31, 0x74, 0x7b, 0xae, 0xfb, 0xb9, 0x33, 0xc1, 0xdc, 0x66, 0xe6, 0x95, 0x9e, 0xce, 0x77, 0x7d, 0x55, 0x3c, 0xa6, 0x6c, 0x09, 0x23, + 0x5a, 0x1a, 0x5e, 0x1a, 0x41, 0xd3, 0xad, 0x5f, 0x86, 0xd0, 0x14, 0xf5, 0xe0, 0xda, 0xf1, 0xce, 0x19, 0x90, 0x45, 0x0c, 0x4c, 0xb1, 0xd3, 0xc8, 0x4c, 0xdb, 0x7e, 0x49, 0xf5, 0xac, 0xde, 0xff }, + { 0x1b, 0x9b, 0x6b, 0x30, 0xd3, 0x19, 0x37, 0x83, 0xad, 0x05, 0xca, 0xba, 0x22, 0x85, 0x33, 0x7f, 0x55, 0x60, 0xe3, 0x14, 0x8c, 0x39, 0x87, 0xd1, 0x4c, 0x21, 0x27, 0xa0, 0xae, 0x4a, 0x56, 0x15, + 0x50, 0x6c, 0x99, 0xca, 0xff, 0xde, 0x10, 0xc6, 0x9f, 0x6c, 0x70, 0xd1, 0x66, 0xb4, 0x87, 0xd8, 0xfc, 0x46, 0xf2, 0xcf, 0x0c, 0xd8, 0xc3, 0x14, 0x5d, 0x27, 0xbd, 0xed, 0x32, 0x36, 0x7c, 0xed }, + { 0x64, 0x6b, 0x74, 0xc7, 0x60, 0x36, 0xc5, 0xe4, 0xb6, 0xde, 0x02, 0x1a, 0x09, 0xaf, 0x65, 0xb1, 0x94, 0xa3, 0xf4, 0x95, 0xf5, 0xb0, 0xef, 0x86, 0xb5, 0x13, 0x26, 0x0b, 0xe8, 0xc5, 0x5c, 0x77, + 0xf5, 0xe6, 0xb6, 0x10, 0x36, 0x87, 0xa3, 0xd2, 0x7c, 0x17, 0x2c, 0xb9, 0xb0, 0x90, 0x9e, 0x8c, 0x0a, 0x7d, 0x73, 0xb2, 0x29, 0xeb, 0xa7, 0x85, 0xd7, 0x04, 0x14, 0xf9, 0x77, 0xb7, 0xf4, 0x89 }, + { 0x7f, 0x1c, 0x5a, 0x57, 0x14, 0xf6, 0x30, 0x07, 0xf9, 0xfe, 0x42, 0x98, 0xcb, 0x3d, 0xac, 0x04, 0x30, 0x0d, 0xc6, 0xd0, 0x4f, 0x8a, 0xbc, 0xdd, 0x3e, 0xc3, 0xb7, 0x74, 0xc8, 0x3b, 0x1a, 0xcc, + 0x6a, 0x54, 0x9e, 0xb9, 0xbe, 0xf0, 0x7c, 0x35, 0x35, 0x1a, 0x50, 0x4c, 0xc2, 0x38, 0x41, 0x46, 0xc8, 0xc4, 0x81, 0x2b, 0x26, 0x56, 0x6f, 0x8a, 0x9f, 0x74, 0x87, 0xe0, 0x01, 0x82, 0xe2, 0x09, + 0xf3, 0x9a, 0xc5, 0x33, 0x5a, 0x7d, 0xb6, 0xbb, 0xff, 0x20, 0x4d, 0xc1, 0x99, 0x3d, 0xcc, 0x5a, 0xc7, 0xd1, 0xbe, 0x4c, 0xcf, 0xc8, 0x09, 0x79, 0x15, 0x5e, 0x0c, 0xc6, 0x26, 0x36, 0xe6, 0xd9 }, + { 0x4d, 0x2f, 0x08, 0x84, 0x32, 0xcf, 0xe0, 0x3b, 0xa8, 0x3e, 0xa5, 0xf8, 0x3a, 0xe8, 0xa9, 0x04, 0x5a, 0x74, 0x67, 0xcb, 0x41, 0x22, 0xc5, 0xc4, 0x9a, 0xa5, 0xc1, 0xa7, 0x94, 0x8b, 0xa5, 0x35, + 0x00, 0x00, 0x1a, 0xaf, 0xfb, 0xed, 0x40, 0xb8, 0x2b, 0x28, 0xf1, 0xb1, 0x02, 0xd3, 0x8b, 0xc0, 0x32, 0x4a, 0xa5, 0x0a, 0xa4, 0xc3, 0xbf, 0xb3, 0xf5, 0xb7, 0x65, 0x8e, 0x88, 0xdf, 0xd0, 0x0e, + 0xf3, 0x9a, 0xc5, 0x33, 0x5a, 0x7d, 0xb6, 0xbb, 0xff, 0x20, 0x4d, 0xc1, 0x99, 0x3d, 0xcc, 0x5a, 0xc7, 0xd1, 0xbe, 0x4c, 0xcf, 0xc8, 0x09, 0x79, 0x15, 0x5e, 0x0c, 0xc6, 0x26, 0x36, 0xe6, 0xd9 } }, + { { 0xc8, 0x8e, 0x1c, 0xea, 0x02, 0x6a, 0xfd, 0x88, 0x8b, 0xa9, 0x9d, 0xdd, 0xba, 0xea, 0x77, 0x30, 0x88, 0x1a, 0x93, 0x49, 0xda, 0x05, 0x18, 0xbb, 0x4a, 0x6a, 0x11, 0xc4, 0x48, 0x72, 0x77, 0x1f, + 0x6e, 0x2b, 0x9a, 0xe3, 0x27, 0xbe, 0xe1, 0x75, 0x32, 0x30, 0xa6, 0x12, 0x26, 0x44, 0xbf, 0xb2, 0xa5, 0x51, 0x0b, 0x48, 0x3a, 0xea, 0xc5, 0xd4, 0x24, 0x3f, 0x4e, 0xe8, 0xe5, 0xc3, 0xfb, 0xc2 }, + { 0xcb, 0x56, 0x3c, 0x00, 0x28, 0x15, 0x72, 0x16, 0x23, 0x4e, 0x2e, 0x2c, 0x8c, 0xe8, 0x7c, 0x44, 0x82, 0x2a, 0xe0, 0x57, 0xa3, 0x0a, 0xc4, 0x42, 0xb5, 0x07, 0xe1, 0x1b, 0x78, 0x8b, 0x3d, 0x4d, + 0xcb, 0xe4, 0x56, 0x72, 0x0b, 0x85, 0x52, 0xd8, 0x55, 0xe2, 0xcd, 0x38, 0xd2, 0x83, 0xb6, 0x05, 0xd2, 0x9f, 0x63, 0x9e, 0x7f, 0xca, 0xe5, 0x95, 0x36, 0x61, 0x9b, 0xca, 0x09, 0x27, 0x53, 0x82 }, + { 0x24, 0x67, 0x10, 0xd6, 0x8a, 0x1a, 0x8e, 0xb8, 0x53, 0xef, 0xb7, 0x67, 0x2a, 0xfd, 0xb8, 0xd6, 0xe3, 0xf7, 0x41, 0x95, 0x8c, 0x50, 0xca, 0x1d, 0x21, 0x21, 0x41, 0xd1, 0xef, 0x2d, 0x9b, 0x53, + 0xa9, 0x42, 0xcd, 0xda, 0x6d, 0x12, 0x1b, 0xbd, 0x0a, 0xe1, 0x4d, 0x95, 0xc6, 0xaa, 0x40, 0xfd, 0x98, 0xfb, 0x26, 0x21, 0x5e, 0xaf, 0x8e, 0x6b, 0xc9, 0x36, 0x2c, 0x66, 0x31, 0x24, 0x45, 0x87 }, + { 0x5e, 0xf9, 0x1d, 0x10, 0xb5, 0x79, 0x1f, 0x80, 0x85, 0x90, 0xc3, 0x7f, 0x2b, 0x73, 0xbf, 0x83, 0x0b, 0x5d, 0x46, 0xae, 0x79, 0xef, 0x09, 0x71, 0x29, 0xfb, 0x83, 0xde, 0x1f, 0xe2, 0xdb, 0x1b, + 0xa2, 0x22, 0xee, 0x50, 0x21, 0x9d, 0x9c, 0x35, 0x14, 0x48, 0x13, 0xa5, 0xd1, 0x68, 0xf4, 0x61, 0x1f, 0xd7, 0xe2, 0xd6, 0x42, 0x1c, 0xdc, 0x58, 0xec, 0x8b, 0x03, 0x6b, 0xdf, 0x64, 0x06, 0x30 }, + { 0xf9, 0xa6, 0x88, 0x74, 0x07, 0x19, 0x15, 0x38, 0xaf, 0xac, 0x07, 0x10, 0xe0, 0xd9, 0x22, 0xf3, 0x78, 0xb0, 0xbf, 0x60, 0xa3, 0x0f, 0xea, 0x0f, 0xa8, 0x64, 0xa9, 0xa3, 0x82, 0xe1, 0x4c, 0x29, + 0x36, 0x22, 0x6d, 0x43, 0x9c, 0xde, 0x22, 0xbf, 0xc6, 0x85, 0xf7, 0xe9, 0xe0, 0x79, 0x80, 0xfe, 0x9d, 0xd6, 0x24, 0xbd, 0x29, 0xa4, 0x8c, 0x35, 0x21, 0x87, 0x45, 0x7f, 0x88, 0xd9, 0x9a, 0x9d }, + { 0x49, 0x43, 0x19, 0x14, 0xcc, 0x4a, 0x11, 0x01, 0x05, 0xd1, 0x4e, 0x39, 0x6d, 0xb0, 0x22, 0x65, 0x32, 0x6e, 0x67, 0x04, 0x50, 0x85, 0x53, 0x42, 0x90, 0x2c, 0xc0, 0x63, 0x2f, 0xbd, 0x15, 0x90, + 0x1b, 0x3f, 0x03, 0x90, 0x16, 0x7f, 0x7b, 0x49, 0x74, 0xd0, 0x3d, 0x81, 0x80, 0x1e, 0x9e, 0x2e, 0xa9, 0x13, 0x6a, 0x10, 0x14, 0xc1, 0xfd, 0xf9, 0x25, 0x3a, 0x1d, 0x52, 0x93, 0x0a, 0x77, 0x03, + 0xa2, 0xdd, 0xce, 0x9f, 0x2a, 0x35, 0xc9, 0x93, 0x7c, 0xa2, 0x2c, 0xf6, 0x38, 0x73, 0xb3, 0xab, 0x7f, 0x55, 0xb6, 0x62, 0xa2, 0x8d, 0x6a, 0x3e, 0x88, 0x04, 0x9b, 0xa2, 0x19, 0x64, 0x55, 0x01 }, + { 0x22, 0x03, 0x49, 0x58, 0x76, 0x3c, 0x85, 0x45, 0x5e, 0x73, 0x78, 0x8f, 0x65, 0xc9, 0x50, 0xf8, 0xd7, 0x16, 0x92, 0xa4, 0xd1, 0x79, 0xce, 0xf3, 0x00, 0x34, 0x38, 0xb8, 0xcc, 0x96, 0x9f, 0xa6, + 0x87, 0x28, 0xcb, 0x19, 0x28, 0xad, 0x83, 0xb5, 0x09, 0x96, 0x54, 0xe8, 0x2a, 0xb9, 0x9b, 0xff, 0x60, 0x85, 0x31, 0x28, 0x62, 0x36, 0xd2, 0x0e, 0xad, 0x2a, 0xe1, 0x84, 0x80, 0xeb, 0x6f, 0x00, + 0xa2, 0xdd, 0xce, 0x9f, 0x2a, 0x35, 0xc9, 0x93, 0x7c, 0xa2, 0x2c, 0xf6, 0x38, 0x73, 0xb3, 0xab, 0x7f, 0x55, 0xb6, 0x62, 0xa2, 0x8d, 0x6a, 0x3e, 0x88, 0x04, 0x9b, 0xa2, 0x19, 0x64, 0x55, 0x01 } }, + { { 0xeb, 0x18, 0x95, 0x94, 0x5f, 0x15, 0x8c, 0xb8, 0x4d, 0x6e, 0x7d, 0xc0, 0x96, 0x6c, 0x52, 0xa2, 0x5f, 0x43, 0x67, 0xc2, 0x3a, 0x10, 0x5b, 0xf1, 0x8f, 0x21, 0x89, 0x06, 0x77, 0xe9, 0xab, 0x2e, + 0xcd, 0x17, 0x9c, 0x9a, 0xd7, 0x89, 0x7e, 0x53, 0x58, 0x60, 0x9b, 0xce, 0x90, 0xd9, 0x13, 0x2d, 0x78, 0xc4, 0x2c, 0x1c, 0x4c, 0xe8, 0x23, 0x70, 0xff, 0xa0, 0x42, 0x98, 0x25, 0x40, 0xd6, 0xd8 }, + { 0xb6, 0xfb, 0xdd, 0x5d, 0x35, 0xf2, 0x2b, 0x89, 0xda, 0x8e, 0x90, 0xee, 0x03, 0x4e, 0x75, 0xdb, 0x4c, 0x45, 0xc8, 0x00, 0xde, 0x06, 0x27, 0xde, 0x44, 0xb5, 0x5b, 0xc7, 0x56, 0xc3, 0xf5, 0xbb, + 0xee, 0xa6, 0x21, 0xd4, 0xd9, 0xb9, 0x24, 0x9c, 0x4c, 0xbc, 0x23, 0xe5, 0xeb, 0x05, 0xb6, 0xd0, 0xd0, 0xbf, 0x49, 0x95, 0x01, 0xb4, 0x97, 0xad, 0xb5, 0x71, 0x8d, 0x4b, 0x32, 0xd0, 0xdd, 0x1a }, + { 0xfd, 0x11, 0xd7, 0xe4, 0x46, 0xcd, 0xd8, 0x44, 0x89, 0x0a, 0xe7, 0x44, 0x59, 0xe9, 0xcf, 0x9f, 0xd6, 0xf1, 0x74, 0x56, 0x04, 0x78, 0xfa, 0x29, 0x46, 0x8a, 0x8d, 0x1b, 0xbe, 0x41, 0x92, 0x1c, + 0x8d, 0x74, 0x01, 0x1b, 0xc1, 0xf8, 0x26, 0xf4, 0xc2, 0x68, 0xc3, 0x23, 0x8c, 0x68, 0x7c, 0x0a, 0xad, 0xdd, 0x50, 0x10, 0xcf, 0xdb, 0x78, 0xc5, 0x79, 0x28, 0x37, 0x63, 0x92, 0x1a, 0x1d, 0xea }, + { 0xd2, 0x2a, 0xf0, 0x66, 0x15, 0x8b, 0xcb, 0x83, 0xcf, 0x34, 0xa1, 0x33, 0x6b, 0xd5, 0xa8, 0x98, 0x3b, 0xd7, 0x09, 0x0d, 0x70, 0xa5, 0x8a, 0xc0, 0x73, 0xcf, 0xde, 0x59, 0xd5, 0x13, 0x41, 0xd2, + 0x43, 0x8b, 0xb4, 0xc3, 0x5b, 0x6f, 0xf1, 0xed, 0x47, 0x76, 0xe6, 0x5e, 0xb8, 0x2a, 0x7e, 0x20, 0x91, 0xa0, 0x9d, 0xc1, 0xa2, 0x0a, 0x6d, 0x97, 0x7d, 0xeb, 0xe3, 0x64, 0x5f, 0x86, 0xff, 0x3e }, + { 0x45, 0xd8, 0xdc, 0xe4, 0x3a, 0x3a, 0x44, 0xdc, 0x7f, 0xa8, 0x92, 0x11, 0x1b, 0x4f, 0xfa, 0xcf, 0x21, 0xff, 0xfb, 0x20, 0xb0, 0x02, 0x6d, 0x0e, 0x1c, 0xde, 0xe8, 0x51, 0xd8, 0x2c, 0x72, 0x0e, + 0xbf, 0xf6, 0x9a, 0xd3, 0xd3, 0xfe, 0xfa, 0x98, 0x4e, 0xc2, 0xf0, 0x16, 0xda, 0x39, 0x93, 0xc4, 0xe0, 0x33, 0x9a, 0x43, 0xe8, 0x7a, 0xc5, 0x0f, 0x0b, 0xa4, 0x45, 0xf0, 0x5e, 0x7a, 0xa9, 0x42 }, + { 0xdb, 0x4e, 0x17, 0x76, 0x8b, 0x3c, 0x98, 0x7f, 0x58, 0x76, 0x97, 0xc9, 0x3f, 0x99, 0x01, 0x05, 0x42, 0x7e, 0xfd, 0x83, 0x99, 0xaa, 0x19, 0xb5, 0x72, 0x4c, 0x69, 0xed, 0x6e, 0x21, 0x79, 0x6e, + 0x3b, 0x71, 0xe5, 0xab, 0x23, 0x84, 0xe7, 0xfe, 0x58, 0x2b, 0x0d, 0x1e, 0x75, 0x7c, 0x29, 0xb3, 0x2d, 0x66, 0xc2, 0x45, 0x88, 0xac, 0x86, 0x29, 0xe4, 0xaa, 0x9e, 0x71, 0xa1, 0x88, 0xf9, 0x06, + 0xda, 0xa3, 0xdd, 0x7b, 0x6c, 0xd9, 0xc9, 0x73, 0xe9, 0x56, 0xd1, 0xee, 0x5b, 0xf9, 0xae, 0xc0, 0x29, 0xbe, 0x20, 0x6c, 0xc7, 0xf9, 0xc5, 0x2d, 0x6d, 0xad, 0x8f, 0x49, 0xf8, 0x17, 0xdb, 0x7a }, + { 0xb8, 0xb7, 0xec, 0xeb, 0x3e, 0x40, 0x77, 0x6c, 0xab, 0x10, 0xfe, 0x9f, 0xd1, 0x40, 0xfe, 0xd2, 0x88, 0x8e, 0xb0, 0x55, 0xae, 0x75, 0xb1, 0xcc, 0x9d, 0x6c, 0x11, 0x28, 0x95, 0x38, 0x9f, 0xb9, + 0x59, 0xe2, 0x29, 0xc3, 0xbc, 0x09, 0x16, 0x1f, 0x17, 0x9e, 0x15, 0x78, 0x09, 0x61, 0x07, 0x9e, 0xad, 0x67, 0x98, 0xa9, 0x24, 0xff, 0xf9, 0x4b, 0xa2, 0x76, 0x09, 0xa0, 0xd7, 0x1b, 0xed, 0x05, + 0xda, 0xa3, 0xdd, 0x7b, 0x6c, 0xd9, 0xc9, 0x73, 0xe9, 0x56, 0xd1, 0xee, 0x5b, 0xf9, 0xae, 0xc0, 0x29, 0xbe, 0x20, 0x6c, 0xc7, 0xf9, 0xc5, 0x2d, 0x6d, 0xad, 0x8f, 0x49, 0xf8, 0x17, 0xdb, 0x7a } }, + { { 0xc3, 0x92, 0x4d, 0x01, 0x9c, 0xea, 0x5a, 0x8d, 0xbd, 0x5c, 0x12, 0x58, 0x6d, 0x03, 0x26, 0xbf, 0xa4, 0xdd, 0xf7, 0x26, 0xa4, 0x0d, 0x22, 0xe0, 0xbd, 0xcc, 0x6f, 0x30, 0x9e, 0xf9, 0x4c, 0x1f, + 0x03, 0x52, 0xab, 0x38, 0xe9, 0x9c, 0x08, 0x9c, 0x09, 0xe5, 0x87, 0x5c, 0x24, 0x1a, 0xe2, 0x75, 0xcb, 0x18, 0x8a, 0x63, 0x50, 0xd1, 0x23, 0x45, 0x49, 0x93, 0x40, 0x2c, 0x09, 0xd4, 0xac, 0x39 }, + { 0xd4, 0xe7, 0xb7, 0x05, 0xfd, 0xd6, 0xf3, 0x57, 0xfb, 0xc2, 0x2f, 0x2c, 0x71, 0x80, 0xf5, 0xc3, 0xa6, 0x0a, 0x23, 0x9d, 0x1d, 0xa8, 0x68, 0x10, 0x8a, 0xfa, 0x68, 0x9d, 0x2b, 0xcf, 0x96, 0xa9, + 0xe6, 0x0e, 0x07, 0x32, 0x23, 0x09, 0x87, 0x16, 0xc5, 0xbb, 0x76, 0x22, 0xfc, 0xb4, 0x59, 0x6d, 0x67, 0xfd, 0x29, 0x51, 0x95, 0x4c, 0xe2, 0x8c, 0x18, 0xab, 0xda, 0x84, 0xc3, 0x62, 0x80, 0x14 }, + { 0xc9, 0xa1, 0xfe, 0xc3, 0x48, 0x0d, 0xee, 0x54, 0x44, 0xff, 0x9c, 0x46, 0x04, 0x0e, 0x74, 0xda, 0xa4, 0x6a, 0x56, 0x02, 0x5f, 0x76, 0x0e, 0xb5, 0xc1, 0xc9, 0xe9, 0xb2, 0x6e, 0x07, 0x49, 0x0c, + 0xf7, 0x4b, 0xee, 0xd6, 0x0a, 0xad, 0x94, 0x03, 0x58, 0x2d, 0x60, 0x95, 0xf8, 0x16, 0x7b, 0x49, 0x0b, 0x01, 0x66, 0x3e, 0x17, 0x01, 0xe5, 0x54, 0x7d, 0xd7, 0xbb, 0x10, 0xd1, 0xad, 0xad, 0x79 }, + { 0xb2, 0xd8, 0x10, 0x29, 0xeb, 0xb8, 0x4e, 0x2b, 0x39, 0x85, 0x5c, 0xb3, 0xdc, 0xf5, 0x87, 0xca, 0xca, 0x9c, 0x7a, 0x8c, 0x2b, 0x08, 0xe8, 0x25, 0xe2, 0xcf, 0x70, 0xe2, 0xe6, 0xfb, 0xdb, 0x0c, + 0xc3, 0x0d, 0x71, 0x11, 0x83, 0x65, 0xf2, 0x71, 0x08, 0x1b, 0x32, 0x6e, 0x6c, 0x51, 0x50, 0xf1, 0xf6, 0x4b, 0x54, 0x63, 0x16, 0x7f, 0xfd, 0x80, 0x05, 0x61, 0x63, 0xf1, 0x80, 0x6a, 0x0b, 0xfd }, + { 0xa7, 0x4b, 0x75, 0x38, 0x90, 0x64, 0x96, 0x7b, 0xda, 0x5e, 0x08, 0x9b, 0x80, 0xc4, 0x72, 0x3f, 0x73, 0xb2, 0xdb, 0xd3, 0x4a, 0xed, 0xa4, 0xdc, 0x5c, 0x79, 0xe5, 0x0f, 0x7a, 0xd3, 0x0c, 0xac, + 0xf9, 0x99, 0x5c, 0x1a, 0x0f, 0xb3, 0x1a, 0x0f, 0x5c, 0xc3, 0x9e, 0x1a, 0x2b, 0xfa, 0xc3, 0xf0, 0x40, 0xe5, 0x5f, 0x36, 0xd2, 0x98, 0x31, 0xa1, 0xaf, 0x18, 0x5f, 0xae, 0x92, 0xf3, 0x9e, 0xc0 }, + { 0xf9, 0xbf, 0x52, 0xe6, 0xd3, 0xe1, 0x5d, 0xd3, 0x30, 0xf3, 0xa1, 0x0c, 0xc8, 0x5a, 0x97, 0x55, 0xab, 0x67, 0x67, 0xd0, 0x00, 0x62, 0x7b, 0x80, 0x70, 0xbf, 0x24, 0xd0, 0x09, 0x8b, 0x07, 0x77, + 0xeb, 0x3e, 0xf0, 0x5d, 0xdf, 0x7b, 0xa9, 0x7d, 0xa4, 0x6a, 0x0d, 0xf1, 0xac, 0x83, 0x7d, 0x64, 0xb5, 0xf4, 0xc6, 0xc4, 0x12, 0x0c, 0x55, 0x9f, 0x67, 0xbb, 0xd5, 0xe3, 0xd3, 0xdb, 0x17, 0x0f, + 0x90, 0x2f, 0x8f, 0xc9, 0xfd, 0x4e, 0x6c, 0x8b, 0xe6, 0x99, 0xfa, 0xda, 0x8f, 0x1f, 0xe6, 0xc3, 0xeb, 0xd8, 0x14, 0x20, 0xcc, 0x3c, 0x1c, 0x23, 0x77, 0x28, 0x9b, 0x22, 0x9a, 0x5a, 0x0c, 0x43 }, + { 0xa2, 0x78, 0x37, 0xc9, 0x63, 0xe1, 0x31, 0x36, 0xc2, 0x58, 0xac, 0xca, 0xbb, 0xa2, 0x84, 0xaa, 0xb3, 0x82, 0xe2, 0x19, 0xb7, 0x14, 0x96, 0x27, 0x77, 0xfa, 0xa1, 0x02, 0xaa, 0xff, 0x55, 0x82, + 0xba, 0xc0, 0x38, 0x1a, 0x69, 0x35, 0x48, 0x87, 0xc2, 0xeb, 0x48, 0x08, 0xea, 0xc5, 0x6b, 0xfc, 0x84, 0x60, 0x4e, 0xce, 0xd7, 0xd2, 0x86, 0x8b, 0x76, 0xf3, 0x46, 0xe1, 0x87, 0x1f, 0xff, 0x09, + 0x90, 0x2f, 0x8f, 0xc9, 0xfd, 0x4e, 0x6c, 0x8b, 0xe6, 0x99, 0xfa, 0xda, 0x8f, 0x1f, 0xe6, 0xc3, 0xeb, 0xd8, 0x14, 0x20, 0xcc, 0x3c, 0x1c, 0x23, 0x77, 0x28, 0x9b, 0x22, 0x9a, 0x5a, 0x0c, 0x43 } }, + { { 0x0e, 0xa6, 0x0c, 0xef, 0x12, 0xd6, 0x7d, 0x71, 0xd4, 0x88, 0x73, 0x86, 0x9a, 0x88, 0x8f, 0x5b, 0xd1, 0xb6, 0x12, 0xc4, 0x93, 0x8b, 0x5f, 0xee, 0xdd, 0x9c, 0x2a, 0x7f, 0x4d, 0xfd, 0xba, 0x00, + 0x09, 0x45, 0x77, 0xd2, 0xcf, 0xcd, 0x3a, 0x6f, 0x27, 0x44, 0xe2, 0x55, 0x3e, 0x79, 0x88, 0x4d, 0x5f, 0x38, 0x34, 0xe8, 0xe7, 0xc6, 0x3a, 0xde, 0xef, 0x99, 0x15, 0xea, 0x88, 0x79, 0xd7, 0xca }, + { 0xa0, 0x9a, 0x0a, 0x3a, 0x42, 0x35, 0x54, 0x78, 0xb9, 0x82, 0x52, 0xb4, 0xc8, 0x5c, 0x4a, 0x03, 0xa1, 0xb9, 0x27, 0xcc, 0x99, 0xec, 0x03, 0xdf, 0xdd, 0x6e, 0xde, 0xef, 0x8f, 0x7f, 0xdc, 0x5a, + 0xc3, 0xcb, 0x0e, 0xa2, 0x7e, 0x93, 0xe6, 0xdd, 0xbd, 0xf1, 0x1b, 0x03, 0x29, 0x63, 0x72, 0x11, 0x72, 0x3d, 0x24, 0x6f, 0xdf, 0x8e, 0xed, 0xa4, 0xe2, 0x2a, 0x4c, 0x00, 0xe2, 0xc4, 0x55, 0x1b }, + { 0xb2, 0xf1, 0xff, 0xf6, 0x3a, 0x26, 0xe1, 0x74, 0x52, 0xba, 0xee, 0x28, 0xb6, 0x56, 0x90, 0x59, 0xde, 0x92, 0x5f, 0x84, 0xd1, 0x87, 0xe2, 0x64, 0xce, 0xdc, 0x94, 0x3c, 0xb4, 0xf8, 0x01, 0x0a, + 0x86, 0x2f, 0xfe, 0x79, 0x03, 0x72, 0xfc, 0x26, 0x21, 0xc3, 0x1e, 0xec, 0x63, 0x29, 0x64, 0xcb, 0x5f, 0xcc, 0xb6, 0x78, 0xf7, 0xc8, 0xd1, 0xf8, 0x5c, 0xc4, 0x4b, 0xc0, 0xc3, 0x75, 0x3e, 0x46 }, + { 0x03, 0x4b, 0xb9, 0xd1, 0x50, 0xa3, 0x79, 0xbe, 0x74, 0xa3, 0xb5, 0xd8, 0x28, 0x1b, 0x6d, 0x72, 0x68, 0x0a, 0x9b, 0x19, 0xc9, 0x13, 0xc4, 0x04, 0x94, 0x0a, 0xcb, 0x72, 0xff, 0x7d, 0xb6, 0x9a, + 0x1c, 0xfd, 0xe4, 0xa3, 0x75, 0x13, 0x57, 0x36, 0xfe, 0x4a, 0xf6, 0xbc, 0xca, 0xd9, 0x34, 0x9b, 0xef, 0x90, 0x02, 0xd9, 0xbd, 0xdd, 0x6f, 0x22, 0x54, 0x36, 0xb2, 0x3f, 0x22, 0x65, 0xef, 0xe7 }, + { 0x04, 0xd4, 0x43, 0xe8, 0x8c, 0xc4, 0xfb, 0xe5, 0x55, 0xd0, 0xa4, 0xea, 0x20, 0xf8, 0xe1, 0x8f, 0xc2, 0xbc, 0x1f, 0x55, 0xf1, 0x8d, 0xda, 0xc0, 0x85, 0xa4, 0xef, 0x36, 0x97, 0x22, 0x8b, 0x8e, + 0x77, 0x4c, 0x1a, 0xa4, 0xa0, 0x6f, 0xe1, 0xdc, 0x32, 0x47, 0xc4, 0x3a, 0xd8, 0x8a, 0xbd, 0x19, 0x30, 0x1c, 0x96, 0x7a, 0xb2, 0x23, 0x7c, 0x16, 0x03, 0xa7, 0x4f, 0xfd, 0xa6, 0x50, 0xd9, 0xf7 }, + { 0xdf, 0xc2, 0x59, 0xd2, 0xa9, 0x9b, 0x1e, 0xca, 0xf0, 0x39, 0x2f, 0xf8, 0xc2, 0xf3, 0x91, 0x55, 0x1b, 0xba, 0x81, 0x3a, 0x67, 0x1a, 0xd4, 0xf4, 0xb0, 0x9f, 0xb6, 0x18, 0x38, 0x65, 0x3e, 0x67, + 0xa0, 0x37, 0xc2, 0x9a, 0xc7, 0xee, 0x72, 0x8e, 0x13, 0x64, 0xd1, 0x0a, 0xda, 0xbd, 0x8d, 0xa4, 0x28, 0x55, 0x3a, 0x2c, 0x78, 0x41, 0xc6, 0xfc, 0x1c, 0x0f, 0xf8, 0xd7, 0x5f, 0xe6, 0xde, 0x0b, + 0xd5, 0xc0, 0xaa, 0x2c, 0x5c, 0xac, 0x46, 0xeb, 0xa4, 0x35, 0x2a, 0xab, 0x00, 0x2e, 0xc0, 0x8b, 0x42, 0x65, 0x2f, 0x2f, 0x13, 0x84, 0x60, 0x15, 0xa3, 0x69, 0xee, 0xab, 0x0e, 0x50, 0xbf, 0x5f }, + { 0xc1, 0xb0, 0xac, 0x4c, 0xfa, 0x62, 0x52, 0x22, 0xae, 0x8c, 0x94, 0x38, 0xd9, 0x6e, 0x10, 0x94, 0xe7, 0xaa, 0xc0, 0x92, 0x93, 0x06, 0x55, 0xf9, 0x2e, 0xd9, 0x10, 0x4d, 0xcb, 0x82, 0x19, 0x1f, + 0x27, 0x16, 0x81, 0xdd, 0xea, 0x7a, 0xa8, 0xce, 0x5a, 0xdd, 0x37, 0x77, 0x24, 0x57, 0xfb, 0x40, 0x3d, 0x1b, 0x48, 0x88, 0xda, 0xce, 0xe8, 0xd2, 0xed, 0xe0, 0x6e, 0x29, 0xeb, 0xdb, 0x95, 0x09, + 0xd5, 0xc0, 0xaa, 0x2c, 0x5c, 0xac, 0x46, 0xeb, 0xa4, 0x35, 0x2a, 0xab, 0x00, 0x2e, 0xc0, 0x8b, 0x42, 0x65, 0x2f, 0x2f, 0x13, 0x84, 0x60, 0x15, 0xa3, 0x69, 0xee, 0xab, 0x0e, 0x50, 0xbf, 0x5f } }, + { { 0x3a, 0x79, 0x39, 0x60, 0xe9, 0x93, 0xad, 0x78, 0xf9, 0x0b, 0x99, 0x64, 0x71, 0x76, 0xad, 0xdc, 0x63, 0xa3, 0x38, 0xbf, 0x0a, 0x36, 0x22, 0xcf, 0x4f, 0x84, 0x3e, 0x34, 0xaf, 0x0b, 0xd4, 0x5c, + 0xc0, 0xa4, 0x01, 0x7c, 0x07, 0xc3, 0xb4, 0xcb, 0xdb, 0x39, 0xdd, 0x39, 0xc7, 0x5c, 0xbd, 0xcf, 0x61, 0x8b, 0x72, 0x74, 0xd6, 0x85, 0xdc, 0x5c, 0x08, 0x93, 0x6d, 0xe6, 0xf1, 0xeb, 0xb9, 0x7c }, + { 0x71, 0x12, 0x20, 0xbb, 0x37, 0xa6, 0xd8, 0x71, 0xf7, 0x58, 0xaa, 0xbd, 0x30, 0xfb, 0xac, 0x94, 0x62, 0x45, 0xf0, 0x1a, 0xc3, 0x4a, 0x07, 0x78, 0x6d, 0x17, 0xf5, 0x8d, 0x69, 0x3d, 0x2e, 0x15, + 0x96, 0x48, 0x1a, 0xb0, 0x7e, 0xdd, 0xf5, 0x2d, 0xe1, 0x56, 0xfc, 0xe9, 0x26, 0x91, 0x51, 0xfe, 0x5e, 0x2a, 0xdc, 0x23, 0x89, 0x09, 0x14, 0xe6, 0x17, 0xa9, 0x14, 0x8c, 0x8c, 0xe8, 0xe3, 0x71 }, + { 0xe4, 0xd0, 0xa7, 0x5a, 0xce, 0x93, 0x1d, 0x55, 0xa2, 0x3d, 0xdd, 0x7e, 0x10, 0x66, 0x6d, 0xc6, 0x5c, 0x87, 0x9f, 0x7a, 0x52, 0x5e, 0x76, 0x3f, 0x09, 0x9e, 0xe5, 0x8e, 0x60, 0x39, 0x5e, 0x3c, + 0x28, 0x31, 0xa4, 0x12, 0x39, 0xfd, 0xba, 0xda, 0xc8, 0x59, 0xdd, 0x5b, 0x26, 0x78, 0x8f, 0x33, 0xd2, 0xc8, 0x22, 0x77, 0x49, 0xcf, 0x34, 0x61, 0xbe, 0x7a, 0xa6, 0x31, 0xbe, 0xe5, 0xab, 0xc2 }, + { 0x60, 0xf5, 0x52, 0xbd, 0xb1, 0x9e, 0x06, 0xa3, 0x94, 0xad, 0xe0, 0x82, 0x33, 0x7c, 0x41, 0x17, 0x5b, 0x8a, 0xbc, 0x7c, 0xce, 0xd1, 0x7e, 0xfd, 0x39, 0x17, 0xfd, 0x90, 0x5a, 0x53, 0x89, 0x27, + 0x9f, 0x27, 0x7a, 0x08, 0xb2, 0x66, 0xda, 0xb5, 0xbf, 0x3b, 0x80, 0xe2, 0x1a, 0x30, 0x80, 0x45, 0x13, 0xf3, 0x4b, 0x0c, 0x4a, 0xe9, 0x0a, 0x6e, 0xf2, 0x3e, 0xa3, 0x70, 0x3d, 0x89, 0xd3, 0xb2 }, + { 0x23, 0x41, 0x08, 0x8d, 0xa8, 0x0b, 0x6a, 0xe0, 0x65, 0xb1, 0x42, 0x50, 0x49, 0xdd, 0xd3, 0xe8, 0x89, 0x13, 0x7a, 0x04, 0xf0, 0xd6, 0x2f, 0x6e, 0x73, 0xcd, 0xdc, 0x10, 0xbb, 0x02, 0x6b, 0xa2, + 0x25, 0x58, 0xa3, 0x08, 0x37, 0x7c, 0x8b, 0x1f, 0x4a, 0x81, 0x38, 0x88, 0xbd, 0xf4, 0x4f, 0x24, 0xe8, 0xd6, 0x9f, 0x2f, 0x13, 0xeb, 0x79, 0x60, 0x80, 0x90, 0x52, 0x6b, 0x8e, 0xed, 0xcb, 0x77 }, + { 0x5b, 0x88, 0x63, 0xaf, 0xf9, 0xe2, 0x44, 0x23, 0xc8, 0x02, 0xe0, 0x22, 0x15, 0x3d, 0x2a, 0xb7, 0x40, 0x76, 0xe8, 0x95, 0xfd, 0xa9, 0xe3, 0x85, 0x94, 0xa3, 0xbb, 0xce, 0x61, 0x19, 0x0d, 0xe2, + 0x95, 0xdf, 0x81, 0x11, 0x53, 0x77, 0xcd, 0xf2, 0xd8, 0x4f, 0xbf, 0x19, 0x6a, 0x3d, 0x4b, 0xda, 0xa4, 0x56, 0xa4, 0xcd, 0x9d, 0x4f, 0x52, 0x53, 0x7d, 0xd8, 0xac, 0xe0, 0xfb, 0x9a, 0x71, 0x0c, + 0x59, 0xf9, 0x0b, 0x03, 0xf1, 0x7b, 0xaf, 0x33, 0xc3, 0xe5, 0x1e, 0x8d, 0x4f, 0xbe, 0x21, 0xed, 0x6b, 0x15, 0xdd, 0xd2, 0xeb, 0x7c, 0xe4, 0x59, 0x6c, 0xf9, 0x91, 0xc1, 0x3a, 0x3a, 0xb6, 0x2b }, + { 0x5e, 0x54, 0xe5, 0x1b, 0x3d, 0x2c, 0x00, 0x80, 0xdd, 0xe4, 0x10, 0x50, 0x98, 0xb6, 0x0e, 0x3a, 0xf7, 0xde, 0x67, 0x2c, 0x8e, 0x7b, 0xb4, 0x73, 0x0b, 0xc7, 0x12, 0xb0, 0x66, 0x6b, 0x3b, 0x99, + 0xd9, 0x33, 0x78, 0x5f, 0x45, 0xe5, 0xec, 0x15, 0x02, 0xfa, 0x8b, 0x86, 0xfd, 0xe0, 0xb7, 0x84, 0x72, 0xf2, 0x68, 0x5c, 0xd6, 0x2e, 0x37, 0xe9, 0x49, 0x32, 0x2f, 0xcd, 0xcd, 0x1e, 0x99, 0x0f, + 0x59, 0xf9, 0x0b, 0x03, 0xf1, 0x7b, 0xaf, 0x33, 0xc3, 0xe5, 0x1e, 0x8d, 0x4f, 0xbe, 0x21, 0xed, 0x6b, 0x15, 0xdd, 0xd2, 0xeb, 0x7c, 0xe4, 0x59, 0x6c, 0xf9, 0x91, 0xc1, 0x3a, 0x3a, 0xb6, 0x2b } }, + { { 0xfc, 0xb9, 0x4e, 0x4e, 0x11, 0xfe, 0xe1, 0xc5, 0xc7, 0x49, 0x54, 0xd2, 0x2f, 0x13, 0x34, 0x7c, 0x91, 0x7d, 0x98, 0x43, 0xe4, 0xb7, 0x48, 0xea, 0xe8, 0x26, 0xcb, 0x26, 0x1f, 0xe4, 0x99, 0x10, + 0xb9, 0x34, 0xc2, 0xac, 0xa3, 0x2c, 0xbd, 0x9e, 0x80, 0xd4, 0x12, 0x3b, 0xb3, 0xf0, 0x01, 0xae, 0x91, 0x9f, 0xba, 0x77, 0x32, 0x4d, 0x9d, 0xac, 0x1f, 0x8d, 0xad, 0xa7, 0x46, 0x44, 0x85, 0xfb }, + { 0x65, 0x05, 0x0b, 0xd2, 0x41, 0xd3, 0x58, 0x2a, 0x14, 0xbc, 0x7b, 0x15, 0x4a, 0x6a, 0x6a, 0x18, 0x71, 0x09, 0x25, 0x33, 0xac, 0x73, 0x53, 0xab, 0xd9, 0x0d, 0x8d, 0xdf, 0x95, 0x59, 0x7e, 0x02, + 0x4c, 0x03, 0x11, 0x5c, 0xdc, 0x80, 0x19, 0xd5, 0x13, 0x66, 0x7f, 0xf7, 0xd7, 0x23, 0x18, 0x40, 0x84, 0x16, 0x6b, 0x52, 0x82, 0x96, 0x05, 0x1b, 0xfa, 0xcb, 0x4b, 0x77, 0x00, 0x12, 0xa0, 0x28 }, + { 0x13, 0xe0, 0x16, 0x1e, 0x24, 0x24, 0xe9, 0xde, 0x9c, 0x86, 0xa9, 0xcf, 0x02, 0x96, 0xdf, 0x8c, 0x64, 0xcb, 0x3d, 0x7d, 0x8a, 0x2a, 0x73, 0x18, 0x20, 0xc8, 0xb0, 0xac, 0x10, 0xa0, 0x52, 0x0c, + 0x6c, 0x17, 0xd9, 0xbd, 0x3c, 0x3e, 0xe5, 0x0c, 0x4a, 0xdb, 0x59, 0xcc, 0x59, 0x15, 0x08, 0x1e, 0xfe, 0xaa, 0xe3, 0xd6, 0xa1, 0x37, 0xd6, 0xd5, 0x6d, 0x8e, 0xcd, 0x57, 0xa9, 0x81, 0xb3, 0x43 }, + { 0x46, 0x28, 0x2b, 0xa0, 0xe5, 0xe3, 0xf0, 0x72, 0xa7, 0xbc, 0x8d, 0xec, 0x45, 0x31, 0x6e, 0xdb, 0xb2, 0x4b, 0x20, 0xbf, 0x64, 0x74, 0x26, 0x70, 0x9b, 0xd6, 0xd3, 0x7f, 0x9f, 0xc1, 0x59, 0x03, + 0x2d, 0xda, 0x6f, 0xaa, 0x7c, 0x92, 0xc6, 0xe0, 0xe8, 0xaa, 0x1e, 0x26, 0xf0, 0x1e, 0xcc, 0xef, 0x6d, 0x87, 0x04, 0x3c, 0xed, 0x52, 0x15, 0xb3, 0x9f, 0x01, 0x4e, 0xe3, 0x3c, 0xb6, 0xbb, 0xac }, + { 0x86, 0x1a, 0x25, 0x8e, 0x41, 0x85, 0xf9, 0xba, 0x98, 0x15, 0xb1, 0xec, 0x50, 0xb4, 0xd0, 0xab, 0x55, 0x54, 0xbb, 0x3b, 0x61, 0xfc, 0x54, 0xf3, 0x09, 0xea, 0xaa, 0x6e, 0xbf, 0x03, 0xc3, 0x58, + 0x1d, 0x24, 0xb5, 0xd5, 0x45, 0x5a, 0x7a, 0x14, 0xc3, 0x6a, 0xa9, 0xd8, 0x6f, 0x41, 0xc3, 0xb4, 0x9a, 0x05, 0x71, 0xbc, 0x23, 0x67, 0xc2, 0xa8, 0xf5, 0x7b, 0x69, 0xa5, 0xe1, 0x7a, 0x35, 0x1d }, + { 0x3b, 0xf5, 0xa8, 0xc0, 0x2a, 0x7d, 0x85, 0x88, 0xd4, 0xf4, 0x26, 0xd3, 0xf4, 0xe3, 0x52, 0x35, 0x37, 0x06, 0x1e, 0x71, 0xc2, 0x3b, 0x7b, 0xeb, 0xf0, 0x07, 0x30, 0x6b, 0x37, 0x31, 0xb9, 0x27, + 0xd8, 0x0b, 0x17, 0xae, 0xff, 0xd4, 0x7c, 0x59, 0xd7, 0x2d, 0xea, 0xcb, 0x92, 0x2f, 0x93, 0xc7, 0xd7, 0xc3, 0xaf, 0x75, 0x73, 0x6a, 0x3f, 0x89, 0xe5, 0x13, 0x0c, 0x28, 0x47, 0xf4, 0xa4, 0x07, + 0xfb, 0xd9, 0x77, 0xb4, 0x1e, 0xb2, 0x70, 0xca, 0x85, 0x22, 0x58, 0xc6, 0x0b, 0x19, 0xc2, 0xa5, 0xba, 0xc3, 0xc9, 0xb6, 0x4a, 0xdb, 0x7d, 0x4d, 0x66, 0xde, 0xeb, 0x8c, 0x1a, 0x23, 0xb8, 0x4c }, + { 0x8c, 0x57, 0x0e, 0x9f, 0x0a, 0xb2, 0xf4, 0x07, 0xdd, 0x7b, 0x46, 0xf8, 0xa0, 0xb1, 0x33, 0x4c, 0x2b, 0x1e, 0x1a, 0xe0, 0x28, 0x17, 0x14, 0xba, 0x14, 0x06, 0x40, 0x1f, 0x30, 0x0a, 0x19, 0xcd, + 0xe7, 0xca, 0xfb, 0xdb, 0xb9, 0x76, 0xf8, 0x8a, 0x81, 0x3d, 0x03, 0x86, 0x7e, 0x66, 0x75, 0x1d, 0xec, 0xff, 0x6b, 0xa7, 0xea, 0x4c, 0x8c, 0x60, 0xd2, 0x1f, 0x72, 0x11, 0x4c, 0x5d, 0xeb, 0x01, + 0xfb, 0xd9, 0x77, 0xb4, 0x1e, 0xb2, 0x70, 0xca, 0x85, 0x22, 0x58, 0xc6, 0x0b, 0x19, 0xc2, 0xa5, 0xba, 0xc3, 0xc9, 0xb6, 0x4a, 0xdb, 0x7d, 0x4d, 0x66, 0xde, 0xeb, 0x8c, 0x1a, 0x23, 0xb8, 0x4c } }, + { { 0x05, 0x64, 0x16, 0x53, 0xbb, 0xb2, 0x6e, 0x81, 0xfc, 0xe6, 0xec, 0xc8, 0x0c, 0xc1, 0x75, 0x59, 0x23, 0xe2, 0x4b, 0xd8, 0x6a, 0x70, 0x34, 0x50, 0x37, 0xc6, 0xc2, 0xbd, 0x27, 0xfd, 0xad, 0x4c, + 0xee, 0xe4, 0xf7, 0xfc, 0x91, 0x05, 0x48, 0x3c, 0xd4, 0x09, 0x78, 0x00, 0xce, 0x15, 0x37, 0xdc, 0xe7, 0xce, 0x48, 0x09, 0x3e, 0x7f, 0x01, 0x9b, 0x03, 0xc8, 0x2f, 0x9b, 0xe6, 0x42, 0xe1, 0x71 }, + { 0x64, 0xbf, 0x63, 0x91, 0xe5, 0x3e, 0x90, 0x89, 0x96, 0xea, 0x59, 0x51, 0x60, 0x7b, 0x5f, 0xfe, 0x0f, 0x76, 0x86, 0x19, 0x45, 0x82, 0xd9, 0x5e, 0x1a, 0xd1, 0xf6, 0x04, 0xc6, 0xaa, 0x71, 0xda, + 0x80, 0xed, 0x75, 0x51, 0xc8, 0x9a, 0x27, 0x09, 0xc3, 0x50, 0xe4, 0x14, 0xa1, 0xc3, 0xf8, 0x3a, 0x6c, 0x84, 0xff, 0x87, 0xd5, 0xf0, 0xb0, 0x3c, 0x5a, 0x57, 0x14, 0x90, 0xc7, 0x31, 0xf8, 0x47 }, + { 0x88, 0x7d, 0xcc, 0x81, 0x2b, 0xbb, 0x7e, 0x96, 0xbe, 0x78, 0xe1, 0xb1, 0xf2, 0xed, 0x6f, 0xd8, 0xff, 0xbd, 0x7f, 0x8e, 0xe5, 0xeb, 0x7f, 0x7b, 0xca, 0xaf, 0x9b, 0x08, 0x1a, 0x77, 0x69, 0x1d, + 0xc2, 0xa4, 0x7c, 0x4d, 0xa6, 0x74, 0x8e, 0x33, 0x24, 0xff, 0x43, 0xe1, 0x8c, 0x59, 0xae, 0x5f, 0x95, 0xa4, 0x35, 0x9e, 0x61, 0xb8, 0xcc, 0x4c, 0x87, 0xb9, 0x76, 0x53, 0x20, 0xa3, 0xf3, 0xf5 }, + { 0x13, 0x2a, 0xcc, 0x07, 0xb1, 0x5f, 0xc7, 0xf1, 0x08, 0x0e, 0x7d, 0x7e, 0x26, 0x56, 0xd8, 0x16, 0x9c, 0xae, 0xac, 0xc4, 0xf5, 0x9c, 0x15, 0x67, 0xae, 0xc4, 0xcc, 0x3f, 0xc0, 0xaf, 0x53, 0x28, + 0x1f, 0x65, 0x14, 0xe5, 0x7f, 0x0c, 0xf5, 0x7a, 0xe3, 0x93, 0xc1, 0xa3, 0xd1, 0x4a, 0x09, 0x7d, 0x24, 0xab, 0x22, 0xc4, 0xc4, 0xce, 0x85, 0x37, 0x86, 0xa8, 0x9c, 0x39, 0x33, 0xba, 0x1b, 0x83 }, + { 0x6d, 0x3e, 0x92, 0x5a, 0xa8, 0xfa, 0xe6, 0x71, 0x98, 0xa8, 0x82, 0x38, 0xcc, 0xed, 0xd6, 0x92, 0x7e, 0x3e, 0xcb, 0xb2, 0x82, 0x92, 0x7a, 0x56, 0x9e, 0xd6, 0x29, 0x45, 0x42, 0x04, 0x76, 0x82, + 0xa5, 0xfc, 0xd9, 0x0c, 0x12, 0x4c, 0x98, 0x04, 0x2a, 0x3a, 0x98, 0x01, 0xb8, 0x62, 0xe8, 0xe6, 0x7c, 0x51, 0xe3, 0x7d, 0x97, 0xf5, 0x45, 0xb4, 0x13, 0xdf, 0x15, 0x68, 0xc3, 0x00, 0x75, 0x40 }, + { 0x7e, 0x89, 0x3d, 0x7c, 0x78, 0x36, 0x3c, 0x85, 0xda, 0xb6, 0x9b, 0x6d, 0xbc, 0x52, 0x7d, 0xc6, 0xaa, 0xfd, 0x90, 0x62, 0xe4, 0xc4, 0x1a, 0x5a, 0x2e, 0xa1, 0x57, 0xd7, 0xda, 0x57, 0xf4, 0x58, + 0xc5, 0x23, 0x61, 0x21, 0xe1, 0x93, 0xfa, 0x06, 0x22, 0xed, 0x41, 0x66, 0x24, 0x47, 0xb9, 0xed, 0xc8, 0x84, 0x25, 0x28, 0x39, 0xec, 0xfb, 0x29, 0xa1, 0xcd, 0xe1, 0x9d, 0x02, 0x48, 0x6f, 0x0a, + 0xe2, 0x9f, 0x98, 0xfd, 0x3d, 0x18, 0xa1, 0x24, 0x9c, 0xc6, 0x75, 0xb8, 0x99, 0x76, 0x2a, 0xa4, 0x9e, 0xb1, 0x97, 0x2d, 0x1c, 0x99, 0x65, 0x5f, 0x1f, 0xda, 0x14, 0x4f, 0x10, 0x49, 0xf1, 0x7a }, + { 0x2c, 0xec, 0x27, 0x63, 0xd2, 0x77, 0x14, 0x2d, 0x01, 0x18, 0x10, 0xe0, 0x23, 0x1b, 0xa2, 0x25, 0x61, 0xd4, 0x52, 0xd9, 0x90, 0xde, 0x97, 0x7e, 0xb8, 0xfa, 0x38, 0x25, 0xf2, 0x91, 0x07, 0x3e, + 0xc4, 0xa9, 0x3e, 0xb5, 0x67, 0x02, 0x28, 0x94, 0x5c, 0x34, 0xa1, 0x0a, 0x5c, 0x54, 0x53, 0xd9, 0xb4, 0xc4, 0x5a, 0x8e, 0x57, 0x18, 0xc3, 0x35, 0xea, 0x47, 0x75, 0xe0, 0x44, 0x01, 0x71, 0x09, + 0xe2, 0x9f, 0x98, 0xfd, 0x3d, 0x18, 0xa1, 0x24, 0x9c, 0xc6, 0x75, 0xb8, 0x99, 0x76, 0x2a, 0xa4, 0x9e, 0xb1, 0x97, 0x2d, 0x1c, 0x99, 0x65, 0x5f, 0x1f, 0xda, 0x14, 0x4f, 0x10, 0x49, 0xf1, 0x7a } }, + { { 0x41, 0x10, 0xd9, 0x7f, 0xb8, 0x83, 0x9e, 0x42, 0x43, 0x7a, 0xb0, 0x6d, 0xa6, 0xcf, 0xa5, 0x7a, 0x50, 0x93, 0x2d, 0x13, 0x94, 0x37, 0xa8, 0x92, 0x26, 0x1f, 0xad, 0xe0, 0x25, 0x19, 0x91, 0x62, + 0x28, 0xfb, 0x18, 0xbf, 0x89, 0xb0, 0x42, 0x80, 0x14, 0xcd, 0xd2, 0x72, 0x84, 0x1c, 0xfd, 0xe5, 0xc3, 0x71, 0x3c, 0x3f, 0x12, 0x5e, 0xdd, 0x53, 0x39, 0xf6, 0x4b, 0x9f, 0xb3, 0x5c, 0xe3, 0x15 }, + { 0xd0, 0xc7, 0x18, 0x4d, 0x68, 0x9f, 0xdd, 0xec, 0x81, 0xf8, 0xc6, 0x0e, 0x83, 0x43, 0x23, 0x3d, 0xfc, 0xf3, 0x66, 0x55, 0xa8, 0x65, 0x8b, 0xd7, 0x9b, 0x3c, 0x74, 0x23, 0xcd, 0xae, 0x60, 0xe7, + 0x61, 0xed, 0x2c, 0x7e, 0xe7, 0xa7, 0x63, 0x7d, 0x72, 0x47, 0x6a, 0x33, 0x1c, 0xaa, 0x81, 0xba, 0x6f, 0xd4, 0x00, 0xe7, 0xa9, 0x58, 0xb2, 0xad, 0xee, 0x3f, 0x9c, 0x70, 0xff, 0x2f, 0x13, 0x6f }, + { 0x56, 0x7b, 0x19, 0x66, 0x42, 0x9a, 0x99, 0x51, 0x23, 0x4f, 0xb6, 0xe7, 0xcf, 0x98, 0xff, 0x20, 0x5a, 0xc3, 0x0e, 0x36, 0xc9, 0xc6, 0x20, 0x25, 0x0c, 0x56, 0x98, 0xfb, 0xbd, 0xd6, 0x66, 0x4f, + 0x6f, 0x94, 0x85, 0x8a, 0x35, 0xf3, 0x50, 0xad, 0x87, 0xde, 0x95, 0x9e, 0xae, 0x2a, 0xd8, 0xdd, 0x78, 0x87, 0x96, 0x2b, 0xe0, 0x12, 0x95, 0xd9, 0x3b, 0xb2, 0x2a, 0x06, 0xe2, 0xf0, 0x06, 0xd4 }, + { 0x42, 0x24, 0xdd, 0x0a, 0xd1, 0x11, 0x31, 0x7e, 0x56, 0x45, 0xb0, 0x0e, 0x86, 0xc1, 0x5d, 0x8c, 0x03, 0x01, 0xb8, 0x33, 0x20, 0xbd, 0x08, 0x10, 0xe5, 0x70, 0x92, 0x2b, 0x5b, 0x86, 0xd3, 0x50, + 0x4c, 0x1e, 0xe3, 0xd1, 0x2a, 0x4e, 0x40, 0x02, 0x19, 0x0b, 0xf6, 0x91, 0xd9, 0x9e, 0xaa, 0x54, 0x7c, 0x3d, 0xba, 0xc5, 0x5a, 0x9e, 0xb2, 0xbb, 0x4e, 0x0d, 0x5b, 0xdd, 0x90, 0xc9, 0x7b, 0xc2 }, + { 0x54, 0x95, 0xd5, 0xdc, 0x7e, 0x7e, 0xec, 0xd4, 0x67, 0x08, 0xdc, 0x58, 0xa9, 0x80, 0x8a, 0x03, 0x6a, 0xf8, 0x40, 0xca, 0x0d, 0x5b, 0x6c, 0xe4, 0xc9, 0x71, 0xa5, 0xaf, 0x2a, 0xaa, 0xe8, 0x95, + 0x45, 0xe7, 0xe2, 0xc3, 0x47, 0x84, 0xc6, 0xbe, 0xe5, 0x65, 0xaf, 0xcd, 0x7c, 0x20, 0x5f, 0x8b, 0x19, 0x61, 0xe4, 0xc9, 0xc1, 0x86, 0xa5, 0x6f, 0x96, 0xf3, 0x9c, 0x13, 0x28, 0x1b, 0xcf, 0x07 }, + { 0xc4, 0x7f, 0xf2, 0x6f, 0xcc, 0x4a, 0xf8, 0xa4, 0x1f, 0x1d, 0x6e, 0x5e, 0x30, 0xb2, 0x99, 0x8f, 0x5d, 0x7c, 0x26, 0x1c, 0x52, 0x6f, 0xd0, 0x33, 0xa7, 0xf8, 0xca, 0x2a, 0xc3, 0x8c, 0xa8, 0xd1, + 0x50, 0x4f, 0xa7, 0xe8, 0xf2, 0x10, 0x4c, 0xcd, 0x8a, 0x31, 0x03, 0xc8, 0x93, 0x2c, 0xd7, 0xe4, 0x21, 0xdb, 0xa2, 0x62, 0x7b, 0x1f, 0x28, 0x14, 0x69, 0x7e, 0x87, 0xac, 0xf9, 0xb4, 0x97, 0x00, + 0x62, 0x86, 0x14, 0xd7, 0xe4, 0x65, 0xdd, 0x9e, 0x1c, 0x64, 0x5f, 0x3e, 0xef, 0xfe, 0xa6, 0x60, 0x68, 0x91, 0x94, 0x8a, 0x1c, 0x89, 0xae, 0xe4, 0xcf, 0x3a, 0xdd, 0xc0, 0xb4, 0x47, 0xe8, 0x8f }, + { 0x12, 0x80, 0x00, 0xda, 0xce, 0xc4, 0x80, 0x8f, 0xa9, 0xa1, 0x5d, 0x98, 0x7d, 0x2c, 0xb2, 0x9c, 0x71, 0xde, 0x62, 0x89, 0x6a, 0xe1, 0x92, 0xd7, 0x96, 0xdc, 0xcd, 0xc8, 0x08, 0x0e, 0x48, 0xbf, + 0x2a, 0x53, 0x72, 0x90, 0x31, 0x71, 0x49, 0x02, 0xda, 0x4e, 0x19, 0x05, 0x10, 0xcb, 0x41, 0x97, 0x44, 0xdc, 0x2d, 0x1e, 0x48, 0xe5, 0x0e, 0x41, 0x9d, 0x7d, 0x03, 0xa3, 0xe2, 0x65, 0xd4, 0x01, + 0x62, 0x86, 0x14, 0xd7, 0xe4, 0x65, 0xdd, 0x9e, 0x1c, 0x64, 0x5f, 0x3e, 0xef, 0xfe, 0xa6, 0x60, 0x68, 0x91, 0x94, 0x8a, 0x1c, 0x89, 0xae, 0xe4, 0xcf, 0x3a, 0xdd, 0xc0, 0xb4, 0x47, 0xe8, 0x8f } }, + { { 0x00, 0x4b, 0x0b, 0xf5, 0x1f, 0x07, 0x1e, 0x23, 0xe3, 0x93, 0x7b, 0x31, 0x41, 0x2a, 0x0a, 0x50, 0x35, 0xe2, 0xbb, 0xfe, 0x51, 0x77, 0x6c, 0xc9, 0xc5, 0x13, 0xb9, 0x87, 0x79, 0x65, 0x68, 0x20, + 0xcc, 0x09, 0x90, 0xa9, 0xe4, 0xef, 0x9f, 0x1a, 0xe1, 0x69, 0x76, 0x14, 0x82, 0x42, 0x88, 0x4b, 0xdc, 0xe0, 0x10, 0x22, 0xe2, 0xd6, 0x36, 0x7c, 0x0b, 0xd9, 0x08, 0xea, 0xfa, 0xe4, 0xfd, 0x45 }, + { 0x57, 0x5c, 0x1e, 0x20, 0xb4, 0xae, 0x9e, 0x9d, 0x04, 0xfb, 0x1a, 0xd7, 0x23, 0xd8, 0x8a, 0x6b, 0x1b, 0xb2, 0xef, 0xa9, 0x06, 0x38, 0xbb, 0x9b, 0x43, 0x2e, 0xf1, 0x81, 0x0b, 0x76, 0xec, 0x20, + 0x46, 0x1b, 0xc4, 0x71, 0x19, 0x3e, 0x79, 0xe8, 0xcf, 0xea, 0xdc, 0x4b, 0x3f, 0x0b, 0xeb, 0x05, 0x13, 0x1a, 0x2c, 0xfe, 0x16, 0xe9, 0xf0, 0xc4, 0x9c, 0x41, 0xab, 0x45, 0x1b, 0xba, 0x05, 0xec }, + { 0x06, 0x0b, 0x73, 0xec, 0x30, 0x74, 0x0d, 0x8d, 0x13, 0x4b, 0xef, 0xac, 0x3b, 0x05, 0xb6, 0xed, 0x2b, 0x05, 0xd1, 0xa7, 0x65, 0xb0, 0xcb, 0x69, 0x00, 0xeb, 0x47, 0xe3, 0x1c, 0x07, 0x8b, 0x15, + 0xbf, 0x69, 0xff, 0x27, 0xb4, 0xdb, 0x77, 0xaf, 0xe9, 0x9a, 0xfb, 0xb2, 0x28, 0xa4, 0xf9, 0x05, 0xe4, 0x3c, 0x66, 0x56, 0x00, 0x1a, 0x2c, 0x41, 0xf2, 0xe1, 0x11, 0x09, 0xfa, 0xe1, 0x50, 0x49 }, + { 0xbc, 0x4d, 0x6f, 0x75, 0x79, 0x77, 0x64, 0x6b, 0xec, 0xac, 0x1a, 0x26, 0x73, 0x9c, 0xf3, 0xf1, 0x4d, 0x79, 0xbe, 0x6f, 0x0c, 0x07, 0x22, 0xd1, 0xa1, 0x31, 0x75, 0xa8, 0x9c, 0xb6, 0x00, 0x63, + 0x0d, 0x40, 0x17, 0xec, 0x83, 0xda, 0x82, 0x2c, 0x3b, 0xfd, 0x90, 0xe3, 0xbc, 0xc2, 0x2c, 0xf5, 0x3e, 0x41, 0xe9, 0x98, 0x57, 0xa2, 0xb7, 0xce, 0x5f, 0x31, 0xbb, 0x0b, 0x05, 0x61, 0x0f, 0x55 }, + { 0xb7, 0xab, 0xb2, 0x84, 0xf1, 0x67, 0x24, 0x16, 0x61, 0xe9, 0x20, 0x33, 0x0b, 0xff, 0x22, 0x61, 0x70, 0xa0, 0x5d, 0xf6, 0xa8, 0x33, 0xc9, 0x30, 0x73, 0xe5, 0x89, 0x36, 0x59, 0xea, 0xa8, 0xe7, + 0x03, 0xf6, 0x14, 0xc1, 0x79, 0xb6, 0x42, 0xa5, 0xc8, 0x6c, 0xb8, 0x94, 0x29, 0x24, 0x00, 0x09, 0xb5, 0x54, 0x3f, 0xe1, 0x6b, 0xfb, 0x4d, 0x2d, 0xa9, 0x9a, 0x02, 0xa1, 0xa5, 0x09, 0xf4, 0xcb }, + { 0x92, 0xfa, 0x18, 0x84, 0x3e, 0xdb, 0xdf, 0x7d, 0x87, 0xd6, 0x2d, 0x07, 0x05, 0x2c, 0xba, 0xe4, 0x30, 0x76, 0xa2, 0xe8, 0x71, 0x3b, 0x1b, 0x93, 0x5b, 0xce, 0x2e, 0xec, 0x50, 0x6e, 0x4a, 0x0b, + 0x2d, 0xbe, 0xa3, 0x76, 0x92, 0xf8, 0xc8, 0x4a, 0x71, 0x66, 0xec, 0xfa, 0x36, 0xc5, 0xdb, 0xab, 0x99, 0x9c, 0xbf, 0x99, 0x07, 0xe8, 0xfe, 0xf4, 0x2f, 0x90, 0x16, 0x5d, 0xdc, 0xbe, 0xfa, 0x08, + 0x93, 0xde, 0x13, 0xf5, 0x32, 0x45, 0x9a, 0xde, 0xa2, 0x5d, 0xb9, 0xe0, 0x38, 0x4c, 0x6a, 0xcc, 0x13, 0x46, 0x27, 0x28, 0xbf, 0xf8, 0x7a, 0x9c, 0x2e, 0xde, 0x6f, 0xfe, 0xe1, 0x86, 0x41, 0x79 }, + { 0xa7, 0x32, 0x52, 0x76, 0x4f, 0x3e, 0x1b, 0xab, 0x82, 0x18, 0x14, 0xe7, 0x42, 0x32, 0xb8, 0xa4, 0x98, 0xde, 0xa4, 0xd7, 0xae, 0x42, 0x84, 0xda, 0x71, 0xf7, 0x78, 0x40, 0x56, 0x94, 0x64, 0x49, + 0x34, 0x37, 0xeb, 0xe3, 0x05, 0x4c, 0xb9, 0xbb, 0xce, 0xb2, 0x72, 0xc0, 0x75, 0x1c, 0xc4, 0xd5, 0x1e, 0x3a, 0xc1, 0x43, 0xda, 0xd1, 0x81, 0x82, 0xa9, 0xd5, 0x0e, 0x0a, 0x5e, 0xc2, 0xd7, 0x04, + 0x93, 0xde, 0x13, 0xf5, 0x32, 0x45, 0x9a, 0xde, 0xa2, 0x5d, 0xb9, 0xe0, 0x38, 0x4c, 0x6a, 0xcc, 0x13, 0x46, 0x27, 0x28, 0xbf, 0xf8, 0x7a, 0x9c, 0x2e, 0xde, 0x6f, 0xfe, 0xe1, 0x86, 0x41, 0x79 } }, + { { 0xa3, 0xdf, 0x4a, 0xfd, 0xe6, 0x74, 0xb8, 0xeb, 0xed, 0xe7, 0x7e, 0xd2, 0xae, 0xf8, 0x40, 0x80, 0x3a, 0x55, 0x58, 0x1d, 0x6b, 0xa4, 0x32, 0x6c, 0x15, 0xbb, 0x67, 0xdf, 0x9e, 0xb5, 0x70, 0x4b, + 0x7f, 0x4d, 0xfe, 0x34, 0x42, 0x0c, 0x4d, 0xe3, 0x97, 0x87, 0x6d, 0x08, 0xe8, 0x4d, 0x8a, 0xa9, 0xbc, 0xbf, 0x1b, 0xb7, 0x66, 0x32, 0xf4, 0x7f, 0x93, 0xca, 0xa4, 0xd2, 0x8f, 0x02, 0x7b, 0xfa }, + { 0xea, 0xac, 0xdf, 0x25, 0x39, 0xf3, 0x28, 0xb6, 0xbe, 0xa8, 0x4a, 0x32, 0x59, 0x4b, 0x4f, 0xb5, 0xd2, 0xf7, 0xf5, 0x75, 0x43, 0x8b, 0xb3, 0x6a, 0x98, 0x8c, 0x14, 0xc9, 0x3f, 0x7e, 0x5c, 0x05, + 0xf0, 0xeb, 0x1d, 0xc5, 0xe6, 0x1b, 0x5d, 0x7f, 0x38, 0x5d, 0x9a, 0xbe, 0xc8, 0x97, 0x09, 0x65, 0x62, 0x88, 0x99, 0xda, 0x95, 0x13, 0x93, 0xd9, 0xa3, 0x19, 0x0a, 0xa7, 0x4a, 0xb2, 0x81, 0xa4 }, + { 0x6e, 0x70, 0x65, 0xaa, 0x1b, 0x16, 0xcb, 0xc1, 0x59, 0x6b, 0xc9, 0x4d, 0xd1, 0x0a, 0x9d, 0x8c, 0x76, 0x70, 0x3c, 0xc1, 0xc1, 0x66, 0xa6, 0x9f, 0xfc, 0xca, 0xb0, 0x3f, 0x0e, 0xe9, 0xa9, 0x36, + 0x09, 0x4f, 0x94, 0xf3, 0x32, 0x25, 0x34, 0xf6, 0xe4, 0xf9, 0x0b, 0x0c, 0xe6, 0xe0, 0x6d, 0x9e, 0xa5, 0x52, 0x82, 0x9c, 0xd4, 0x43, 0xa4, 0xd1, 0xd1, 0x63, 0x20, 0xce, 0xbc, 0x4f, 0x43, 0xdc }, + { 0x35, 0xd6, 0xc1, 0x68, 0xa6, 0xd7, 0xd3, 0x36, 0x82, 0x2a, 0x0f, 0x29, 0x3e, 0xd6, 0x15, 0x29, 0x19, 0x73, 0x14, 0x78, 0x87, 0x86, 0xca, 0x9f, 0x6e, 0x17, 0xea, 0xaf, 0x24, 0x37, 0xd6, 0xb4, + 0xb0, 0xee, 0x84, 0x90, 0x2d, 0x18, 0xbd, 0x26, 0xc3, 0xd4, 0x39, 0x4f, 0x45, 0xfa, 0x2f, 0x70, 0xf2, 0xe2, 0x2a, 0x2a, 0x5c, 0x65, 0x15, 0xcb, 0xaf, 0x92, 0x9a, 0xfc, 0x06, 0xe0, 0x8a, 0x1b }, + { 0x5d, 0xfa, 0xc0, 0x2b, 0xc3, 0x94, 0x19, 0xb4, 0xd6, 0x13, 0xe3, 0xcf, 0x91, 0xad, 0x8c, 0xe1, 0x97, 0x46, 0xfe, 0xea, 0x74, 0xe0, 0x0c, 0x03, 0xf7, 0x2e, 0x51, 0xa7, 0xf2, 0xbc, 0xce, 0xe8, + 0x6b, 0xfd, 0x2f, 0x54, 0x52, 0x12, 0x00, 0x8d, 0x95, 0x91, 0xc3, 0xf6, 0x25, 0xf8, 0x65, 0x6a, 0x9c, 0x79, 0x6b, 0x71, 0xc0, 0x0c, 0x29, 0xfb, 0xe7, 0x14, 0x9f, 0x2f, 0x1a, 0x07, 0x53, 0x50 }, + { 0xe9, 0xd4, 0x46, 0x0b, 0x51, 0x3f, 0xf1, 0xbe, 0x0a, 0x23, 0xa5, 0x38, 0xa0, 0xe3, 0x70, 0x14, 0x63, 0xf0, 0x94, 0xbb, 0x1c, 0x4f, 0x23, 0x05, 0x1b, 0x62, 0x40, 0x9b, 0xf9, 0x52, 0x1b, 0x41, + 0x51, 0x57, 0x2a, 0x99, 0x73, 0xda, 0xe1, 0xcf, 0xc5, 0x4c, 0x65, 0x3a, 0xc2, 0x9d, 0x73, 0xda, 0xc9, 0x59, 0xf1, 0xdf, 0xab, 0x2b, 0x27, 0xe1, 0x59, 0x8b, 0xa7, 0x48, 0xf9, 0x36, 0xcb, 0x08, + 0xe3, 0x5e, 0x1d, 0xdd, 0xf9, 0x20, 0x4f, 0x64, 0xa9, 0x26, 0x74, 0x97, 0xf2, 0x2d, 0x31, 0xac, 0x8c, 0x20, 0x77, 0x09, 0xa9, 0x8f, 0xed, 0x23, 0x77, 0x7e, 0xd7, 0x34, 0x93, 0x84, 0xe7, 0xaa }, + { 0xaa, 0xf7, 0x64, 0xdf, 0x34, 0x59, 0x1c, 0x2c, 0xbc, 0x47, 0x08, 0x6a, 0x25, 0xbf, 0x9d, 0x48, 0x54, 0xcf, 0xa0, 0x6c, 0xfc, 0xd4, 0x10, 0x39, 0x9f, 0x64, 0x46, 0xce, 0xd9, 0x95, 0x28, 0x89, + 0xdf, 0x94, 0x5e, 0x74, 0x0b, 0x55, 0x46, 0x82, 0xd9, 0x3d, 0x82, 0x97, 0x7d, 0xd0, 0x3e, 0xd7, 0xf6, 0x6f, 0xaa, 0x97, 0x3e, 0xdf, 0xa7, 0xde, 0xe3, 0xc5, 0xaf, 0xd3, 0xa0, 0x5a, 0x30, 0x0d, + 0xe3, 0x5e, 0x1d, 0xdd, 0xf9, 0x20, 0x4f, 0x64, 0xa9, 0x26, 0x74, 0x97, 0xf2, 0x2d, 0x31, 0xac, 0x8c, 0x20, 0x77, 0x09, 0xa9, 0x8f, 0xed, 0x23, 0x77, 0x7e, 0xd7, 0x34, 0x93, 0x84, 0xe7, 0xaa } }, + { { 0x96, 0x4e, 0xf2, 0x1e, 0x3a, 0xe5, 0x77, 0xbf, 0xa7, 0x1c, 0x3d, 0x66, 0x08, 0x06, 0xca, 0x55, 0x43, 0x7a, 0x08, 0xf8, 0xff, 0x55, 0xb3, 0xbc, 0x9a, 0x83, 0x9a, 0x2e, 0xe6, 0x97, 0x14, 0x32, + 0x36, 0x57, 0x5c, 0xa4, 0x04, 0x78, 0xb1, 0x92, 0xf4, 0x23, 0x94, 0xe6, 0x2a, 0xef, 0xd4, 0xe7, 0xc4, 0x02, 0x9f, 0xa9, 0x79, 0x77, 0x61, 0x90, 0xd6, 0xdb, 0x6e, 0x28, 0x7e, 0xc0, 0x1d, 0x70 }, + { 0xc5, 0xd1, 0x5c, 0x34, 0x15, 0xa9, 0x1e, 0x42, 0x2a, 0x1b, 0x0d, 0xf0, 0x56, 0x83, 0x10, 0xc3, 0xc9, 0x21, 0xfd, 0x05, 0xfa, 0x51, 0x0e, 0x11, 0x28, 0xcc, 0x84, 0xac, 0x35, 0xb5, 0xd8, 0xc8, + 0x5c, 0x80, 0x11, 0x1f, 0x60, 0x1c, 0x72, 0x25, 0x82, 0x45, 0xb5, 0x4f, 0x66, 0x6b, 0x52, 0xb1, 0xf7, 0x28, 0x0f, 0x80, 0x76, 0x44, 0xdc, 0x15, 0x70, 0x39, 0xe9, 0xaf, 0xc7, 0x0a, 0xa0, 0x43 }, + { 0xff, 0x20, 0x5e, 0x3b, 0x75, 0xe9, 0x38, 0x7c, 0xa3, 0x5c, 0x8b, 0x1a, 0xec, 0x17, 0x8d, 0xf0, 0xef, 0xb3, 0x53, 0x9b, 0x16, 0xa9, 0x44, 0xf9, 0x34, 0x45, 0x13, 0x66, 0x80, 0x24, 0xdc, 0x22, + 0x0e, 0x51, 0x94, 0xed, 0xe6, 0x83, 0x36, 0x32, 0x63, 0x23, 0x1b, 0xf8, 0x78, 0xb4, 0x04, 0x7f, 0x5a, 0x50, 0x54, 0x12, 0x19, 0x04, 0x61, 0xdd, 0x25, 0xf0, 0x48, 0x29, 0x04, 0xc1, 0x44, 0xe2 }, + { 0x46, 0x32, 0x2d, 0xc7, 0xbc, 0x05, 0x2a, 0xd3, 0xb5, 0xce, 0x7d, 0x47, 0x5e, 0xfc, 0x90, 0x38, 0xef, 0xfa, 0x6f, 0x42, 0xf0, 0x66, 0x05, 0x89, 0x7c, 0x9a, 0xc1, 0xfd, 0xa2, 0xe8, 0xa7, 0x38, + 0x18, 0x6d, 0x7f, 0x9e, 0xfb, 0xbd, 0x06, 0x0c, 0x70, 0xd7, 0x29, 0x10, 0x88, 0x04, 0x9f, 0x24, 0x28, 0x9d, 0xc7, 0x84, 0xdf, 0xb6, 0xec, 0xb2, 0xc7, 0x1b, 0xd1, 0xc1, 0x9d, 0x56, 0xb0, 0x83 }, + { 0xda, 0xd7, 0x34, 0xee, 0x62, 0x13, 0x8f, 0x47, 0xad, 0xb4, 0x9c, 0x98, 0xe4, 0xc5, 0xb3, 0x29, 0x31, 0x11, 0x64, 0xad, 0xf5, 0x0b, 0x60, 0xe1, 0x0e, 0x18, 0x28, 0x30, 0x3c, 0xa2, 0xe3, 0x29, + 0x89, 0x0a, 0x7e, 0x18, 0xba, 0x30, 0x9e, 0x7d, 0x53, 0xf1, 0x82, 0xd5, 0x27, 0xe5, 0xf3, 0xab, 0x15, 0xcd, 0x62, 0x7e, 0xdf, 0xf0, 0x0e, 0x42, 0xfa, 0x6b, 0x7b, 0x54, 0xd2, 0x74, 0x19, 0x8f }, + { 0x29, 0x4d, 0x28, 0x80, 0x62, 0xb5, 0x77, 0xbb, 0x69, 0x70, 0xb0, 0xb7, 0x10, 0x2e, 0xed, 0xfc, 0x13, 0x34, 0x93, 0x7f, 0xd8, 0xfc, 0xb5, 0x7b, 0xfe, 0x34, 0x0a, 0xa3, 0x95, 0x5b, 0xb1, 0xa7, + 0xc6, 0xab, 0x82, 0x79, 0x25, 0x23, 0x94, 0x12, 0xa4, 0x34, 0xec, 0x23, 0xca, 0xcb, 0xd0, 0xa3, 0xf9, 0x31, 0x32, 0xce, 0x50, 0x31, 0x73, 0x23, 0x98, 0x94, 0xe3, 0x08, 0xd9, 0x1e, 0xc3, 0x0b, + 0x39, 0xe3, 0x3b, 0xf2, 0xe8, 0xb7, 0x26, 0x28, 0x9d, 0xb3, 0x12, 0x8d, 0x16, 0xca, 0x89, 0x26, 0xa9, 0x1c, 0xa3, 0x1f, 0x36, 0x10, 0x60, 0x6a, 0x29, 0x85, 0xe7, 0x2c, 0xee, 0xc1, 0xb6, 0xae }, + { 0x68, 0xed, 0x3c, 0x64, 0xe6, 0x87, 0xf0, 0x14, 0x64, 0xfc, 0x38, 0x3a, 0x0f, 0xd9, 0x7a, 0x5b, 0x52, 0x32, 0x10, 0xca, 0xc6, 0x83, 0x0b, 0xae, 0x17, 0x0e, 0xfe, 0x77, 0xe0, 0xe7, 0x83, 0xa1, + 0x2c, 0x78, 0x62, 0x9c, 0x79, 0x08, 0x2b, 0xd4, 0x85, 0x72, 0x27, 0x8d, 0x97, 0x78, 0x62, 0x33, 0x34, 0xeb, 0x5c, 0xde, 0x5d, 0xaa, 0x4d, 0xfa, 0xd1, 0x67, 0xa4, 0xea, 0x45, 0xad, 0xf9, 0x06, + 0x39, 0xe3, 0x3b, 0xf2, 0xe8, 0xb7, 0x26, 0x28, 0x9d, 0xb3, 0x12, 0x8d, 0x16, 0xca, 0x89, 0x26, 0xa9, 0x1c, 0xa3, 0x1f, 0x36, 0x10, 0x60, 0x6a, 0x29, 0x85, 0xe7, 0x2c, 0xee, 0xc1, 0xb6, 0xae } }, + { { 0xd9, 0x64, 0xb2, 0xe1, 0x9f, 0x0a, 0x35, 0xfc, 0x9f, 0xc3, 0xa5, 0x2a, 0xa3, 0x84, 0xb4, 0xf3, 0x23, 0xc4, 0xf3, 0x5a, 0x9d, 0xf8, 0x7f, 0x35, 0xa9, 0xf5, 0x5b, 0x68, 0xfc, 0x19, 0x69, 0x63, + 0x6a, 0x13, 0x19, 0x32, 0xcc, 0x9d, 0x0c, 0x3c, 0x7d, 0xdd, 0x85, 0x16, 0xa8, 0xd9, 0x2b, 0x75, 0x08, 0x4b, 0x9a, 0xa5, 0x6e, 0xf3, 0xe9, 0xeb, 0xed, 0x5d, 0x2e, 0xfd, 0x2e, 0x0c, 0x60, 0xa2 }, + { 0x0f, 0xf6, 0x8c, 0x3f, 0x6e, 0xee, 0x56, 0x4f, 0x43, 0x6f, 0x54, 0xbd, 0x7a, 0xe4, 0xbe, 0xa8, 0x77, 0x05, 0x99, 0xe7, 0x9e, 0x59, 0x22, 0x85, 0x9b, 0xc6, 0xe4, 0x2a, 0x61, 0x9c, 0x19, 0xb1, + 0x5a, 0xeb, 0x7a, 0xf8, 0x41, 0x4e, 0xe5, 0x2a, 0xd0, 0xf7, 0x44, 0xf0, 0x16, 0xea, 0x0c, 0x04, 0x19, 0x6c, 0xb6, 0x30, 0x3c, 0x6e, 0x2d, 0x79, 0x9a, 0x8f, 0x08, 0x90, 0x11, 0xf1, 0xc0, 0x4d }, + { 0x68, 0xe7, 0x1d, 0x40, 0xf1, 0x07, 0xc0, 0xc6, 0xb2, 0x87, 0x9c, 0xa2, 0x19, 0x43, 0x7a, 0xdf, 0x8a, 0x5a, 0x0f, 0xe2, 0x24, 0x97, 0xa0, 0x38, 0x79, 0x20, 0x38, 0xa9, 0x9c, 0x77, 0xc4, 0x37, + 0xa6, 0x02, 0xe0, 0x93, 0x47, 0xa4, 0x55, 0x21, 0xc2, 0x69, 0xbe, 0x09, 0x05, 0xaa, 0x87, 0x28, 0xf1, 0x95, 0x2f, 0xdb, 0xf0, 0xbf, 0xd2, 0x9e, 0x5e, 0x3a, 0xfa, 0xc6, 0x2f, 0x13, 0x09, 0xaf }, + { 0xe1, 0x9e, 0xc8, 0x4f, 0xc9, 0xdd, 0x61, 0x60, 0x94, 0xbc, 0xd3, 0xd6, 0xde, 0x11, 0x6e, 0xec, 0x84, 0xc4, 0xdd, 0xbe, 0x20, 0x46, 0x6c, 0xef, 0xf6, 0x9d, 0x37, 0x07, 0x53, 0x72, 0x57, 0xf9, + 0x02, 0xb5, 0x64, 0x1f, 0xe2, 0x56, 0xa4, 0x38, 0x6d, 0xa4, 0xed, 0x23, 0x9e, 0xa3, 0xf4, 0x4d, 0x77, 0x52, 0xdc, 0x8c, 0x51, 0xfc, 0x88, 0x18, 0xbc, 0x83, 0x2a, 0xac, 0xc1, 0x1d, 0x3d, 0x59 }, + { 0x08, 0x4f, 0x78, 0x21, 0xfd, 0x4b, 0x85, 0x86, 0x4e, 0x25, 0xdd, 0x47, 0x60, 0x7f, 0x7e, 0xc6, 0xd3, 0xa1, 0xab, 0x91, 0x3f, 0xeb, 0xf6, 0x40, 0x7e, 0x1b, 0xbd, 0x99, 0x9c, 0x7c, 0x2f, 0x4f, + 0xca, 0x68, 0xa5, 0xf6, 0x8c, 0x1e, 0xcb, 0xb8, 0x76, 0xe2, 0x87, 0x5b, 0x49, 0x68, 0x97, 0x2c, 0x21, 0x5c, 0x7c, 0x93, 0x79, 0x9a, 0x95, 0xa1, 0x3a, 0x49, 0xc9, 0x6d, 0x34, 0x6b, 0xa1, 0x98 }, + { 0xb9, 0x88, 0x25, 0x9a, 0x3b, 0x53, 0x56, 0xa1, 0x48, 0x0f, 0xf0, 0x92, 0xde, 0x4e, 0x3e, 0x3a, 0xcf, 0x02, 0xdc, 0x5c, 0xc2, 0xc3, 0x78, 0xad, 0x8a, 0x0c, 0x3c, 0xc7, 0xdd, 0xdd, 0x71, 0x6e, + 0x3f, 0xd9, 0x3a, 0x57, 0x2a, 0x19, 0xa5, 0x3b, 0x5c, 0x46, 0x7b, 0xc9, 0x0f, 0x16, 0xb3, 0x58, 0xa6, 0x85, 0xfa, 0x91, 0x2c, 0x9a, 0x9c, 0x12, 0xb6, 0xd6, 0x7d, 0x9a, 0xf0, 0x9d, 0xe9, 0x02, + 0xad, 0x12, 0x87, 0xda, 0x85, 0x58, 0x6b, 0xff, 0x68, 0x96, 0x05, 0x33, 0xba, 0x7f, 0x08, 0xf9, 0xa9, 0xa2, 0xa9, 0x46, 0x43, 0xe5, 0x03, 0x12, 0xe4, 0xbe, 0x74, 0xaa, 0x46, 0x4e, 0x51, 0xb3 }, + { 0x61, 0x70, 0x17, 0x50, 0x26, 0xfa, 0x51, 0x83, 0xe0, 0xca, 0xa9, 0xb1, 0xc3, 0xc4, 0x83, 0xa9, 0xb6, 0x43, 0x6b, 0x7a, 0x5b, 0xe4, 0x21, 0x5a, 0x6b, 0xd4, 0x34, 0xf8, 0xee, 0x95, 0x86, 0x2d, + 0x03, 0xbf, 0xca, 0xd0, 0xfa, 0x68, 0x53, 0xb2, 0x97, 0x50, 0xad, 0x89, 0x2f, 0x99, 0x63, 0x67, 0x18, 0x57, 0x1f, 0x57, 0x41, 0xbc, 0xb7, 0xc0, 0x18, 0xe7, 0xb6, 0xf3, 0x0f, 0xc4, 0x49, 0x0d, + 0xad, 0x12, 0x87, 0xda, 0x85, 0x58, 0x6b, 0xff, 0x68, 0x96, 0x05, 0x33, 0xba, 0x7f, 0x08, 0xf9, 0xa9, 0xa2, 0xa9, 0x46, 0x43, 0xe5, 0x03, 0x12, 0xe4, 0xbe, 0x74, 0xaa, 0x46, 0x4e, 0x51, 0xb3 } }, + { { 0xc5, 0xdf, 0x86, 0x8f, 0xf1, 0xa7, 0xad, 0x57, 0xfd, 0xb4, 0x53, 0xc3, 0x92, 0x1b, 0x9e, 0x2e, 0xdd, 0xc5, 0xa4, 0x3b, 0x72, 0xa6, 0x9b, 0x4a, 0x15, 0xca, 0x35, 0xed, 0x3c, 0x1a, 0x3b, 0x38, + 0x36, 0xd6, 0xf2, 0x03, 0xb6, 0x97, 0x1f, 0xcb, 0x40, 0x5d, 0x3c, 0x25, 0xfc, 0xe7, 0xff, 0xc6, 0xbe, 0x61, 0xe1, 0x98, 0x31, 0x13, 0xa9, 0xbe, 0x05, 0x86, 0xfe, 0x5c, 0xf6, 0xcc, 0xaa, 0xf5 }, + { 0xd2, 0x57, 0x19, 0x98, 0xf8, 0x74, 0x90, 0xb7, 0x69, 0x6e, 0xdd, 0x44, 0xf1, 0x8b, 0xb1, 0x9c, 0xfd, 0x5b, 0x6b, 0xc0, 0x45, 0xf2, 0x49, 0xa5, 0x4b, 0xff, 0x8b, 0x7f, 0x87, 0xe3, 0xf9, 0x71, + 0xab, 0xfa, 0xc8, 0x17, 0xed, 0xeb, 0x19, 0xc6, 0x3c, 0xee, 0x78, 0xba, 0x89, 0x97, 0x49, 0x85, 0x39, 0x68, 0x29, 0x88, 0x0b, 0x1c, 0xd1, 0x42, 0x8b, 0xe8, 0x1a, 0x3b, 0xeb, 0x4d, 0xef, 0x3b }, + { 0xea, 0xfb, 0xec, 0x27, 0xc3, 0x92, 0xc3, 0x68, 0x0d, 0x3c, 0x5b, 0x20, 0x20, 0x9c, 0x96, 0xa7, 0x39, 0xfa, 0x80, 0x91, 0xef, 0x86, 0x7d, 0xa8, 0x87, 0xf6, 0xef, 0x14, 0x01, 0x46, 0xf0, 0x68, + 0x0a, 0x8b, 0xae, 0x83, 0x91, 0x7e, 0xa0, 0x14, 0x14, 0xde, 0xf9, 0xa8, 0xfd, 0x67, 0x57, 0x17, 0x20, 0x46, 0x43, 0x49, 0x07, 0xf0, 0x3e, 0xc8, 0xbe, 0x66, 0xaf, 0x58, 0x3a, 0xbd, 0xd8, 0x00 }, + { 0x35, 0xf5, 0xc8, 0x2c, 0x0e, 0x4b, 0x56, 0xe0, 0xef, 0x08, 0x34, 0x38, 0x57, 0xe9, 0xde, 0xdb, 0x1d, 0xe1, 0x28, 0x05, 0x01, 0xed, 0x62, 0x3d, 0xa9, 0x6e, 0xea, 0x5b, 0x95, 0x09, 0xe0, 0x04, + 0x46, 0xff, 0xdc, 0x34, 0xf6, 0xf7, 0x63, 0xb1, 0x76, 0xb8, 0x3c, 0x03, 0xef, 0x36, 0x0f, 0x82, 0x1b, 0x5b, 0x6f, 0xe2, 0x86, 0xd9, 0x10, 0x01, 0xe6, 0x73, 0x75, 0x0d, 0x50, 0x30, 0x11, 0x68 }, + { 0x27, 0xb6, 0x3b, 0x78, 0x79, 0xf3, 0x22, 0x78, 0x8f, 0x0c, 0x14, 0x8b, 0x3f, 0x68, 0xc2, 0xab, 0x9f, 0x9f, 0x05, 0x70, 0x7e, 0xee, 0x4b, 0x1b, 0x6b, 0xfc, 0x04, 0x72, 0xca, 0xf1, 0x9a, 0xba, + 0xe3, 0x65, 0x9d, 0xdb, 0x01, 0x33, 0xc5, 0xdb, 0xf6, 0x87, 0xe4, 0x73, 0x5a, 0x0f, 0x94, 0xa9, 0x2e, 0xfe, 0x8f, 0x3e, 0xd1, 0x0a, 0x6d, 0xa1, 0x21, 0x2a, 0x92, 0x8c, 0x4b, 0x43, 0x13, 0x2f }, + { 0xa3, 0xa8, 0x3b, 0xb4, 0x4f, 0x8a, 0xac, 0xab, 0x8a, 0x4c, 0x39, 0x7e, 0xb8, 0x2f, 0xb1, 0x01, 0x2e, 0xbe, 0x0e, 0x7d, 0x28, 0x8a, 0x18, 0x4a, 0xda, 0x58, 0x1a, 0xfb, 0x95, 0x97, 0xf3, 0x63, + 0x58, 0xbe, 0x8c, 0x30, 0x13, 0x9b, 0xba, 0x9f, 0x4e, 0xac, 0x8d, 0x95, 0xf2, 0x07, 0xbb, 0x85, 0xa1, 0x41, 0x4c, 0x33, 0xe3, 0x58, 0x8e, 0x5c, 0xa1, 0x05, 0x45, 0xab, 0x5c, 0x0c, 0xe4, 0x02, + 0xc3, 0xa0, 0xa0, 0x72, 0xdb, 0x9a, 0x9d, 0xbf, 0x13, 0x29, 0x94, 0x70, 0x8b, 0xe4, 0xe8, 0xdb, 0x0e, 0x0b, 0xd0, 0xa0, 0x25, 0xad, 0x71, 0xa0, 0x27, 0x9c, 0x1d, 0x77, 0xb0, 0x98, 0xa8, 0x03 }, + { 0xe1, 0x84, 0xa5, 0xea, 0xa5, 0xd8, 0x1b, 0x29, 0xce, 0xd7, 0xa3, 0x72, 0xa7, 0xc9, 0xa5, 0xea, 0xf1, 0x02, 0xf3, 0x0c, 0xb0, 0x65, 0x12, 0xbc, 0xa4, 0xf2, 0x5d, 0x69, 0x00, 0xa4, 0x7f, 0x5a, + 0x52, 0x09, 0xb6, 0x7b, 0x30, 0xf2, 0x99, 0x03, 0x39, 0x9d, 0xee, 0x6f, 0xb5, 0xf7, 0x9e, 0x7a, 0x97, 0x8b, 0x81, 0x03, 0x8c, 0xdd, 0x35, 0xfc, 0x1f, 0x0a, 0xc6, 0xa4, 0x60, 0x7b, 0xc8, 0x0a, + 0xc3, 0xa0, 0xa0, 0x72, 0xdb, 0x9a, 0x9d, 0xbf, 0x13, 0x29, 0x94, 0x70, 0x8b, 0xe4, 0xe8, 0xdb, 0x0e, 0x0b, 0xd0, 0xa0, 0x25, 0xad, 0x71, 0xa0, 0x27, 0x9c, 0x1d, 0x77, 0xb0, 0x98, 0xa8, 0x03 } }, + { { 0x67, 0xe9, 0x62, 0x76, 0x3a, 0x90, 0x9b, 0x6b, 0x19, 0x1d, 0x65, 0xb2, 0x2a, 0x2f, 0xf7, 0x50, 0xaa, 0x54, 0xa5, 0xbb, 0x53, 0xb5, 0xf9, 0xee, 0x0c, 0x04, 0x3a, 0x3c, 0x29, 0x4b, 0x66, 0x3e, + 0x7b, 0xb6, 0xaa, 0xd2, 0x10, 0x89, 0xcc, 0x89, 0x2c, 0x47, 0xbe, 0x23, 0xd6, 0x52, 0x81, 0x5d, 0xc8, 0xbc, 0x49, 0xd6, 0x6a, 0xcd, 0x62, 0x99, 0x30, 0xff, 0x16, 0xa5, 0x50, 0x44, 0xd8, 0x7a }, + { 0xd6, 0xcd, 0xfe, 0xd4, 0x44, 0x4a, 0x9e, 0x90, 0x44, 0x73, 0x8a, 0xff, 0xbb, 0x82, 0x08, 0xb6, 0x7f, 0xf2, 0x87, 0xcb, 0xa5, 0x0b, 0x56, 0xd3, 0x9e, 0x91, 0xb8, 0x52, 0x6b, 0x25, 0xa6, 0x5d, + 0x50, 0xaf, 0x9b, 0xd5, 0xfb, 0x9f, 0x7e, 0x2d, 0x57, 0xdf, 0x30, 0x78, 0x8d, 0x1a, 0xc3, 0xac, 0x9c, 0x5a, 0xbf, 0xab, 0x5a, 0x0d, 0xc9, 0xb6, 0x4b, 0x18, 0xd4, 0xe7, 0x55, 0x40, 0xde, 0x7e }, + { 0xc2, 0xa9, 0x7e, 0x5c, 0x26, 0xf4, 0x7d, 0xce, 0x9e, 0x73, 0xae, 0x50, 0xde, 0xe7, 0xa6, 0xf9, 0x8b, 0x57, 0xf9, 0x7a, 0x4c, 0x38, 0x82, 0xf6, 0x30, 0x80, 0x12, 0xf7, 0xf6, 0x66, 0x80, 0x46, + 0x4d, 0x41, 0x53, 0x63, 0xd9, 0x65, 0x90, 0xe7, 0xee, 0x24, 0x07, 0xb0, 0x4f, 0xeb, 0x3e, 0x8e, 0x83, 0x21, 0xa3, 0x40, 0x03, 0xc0, 0x64, 0x52, 0xc6, 0xb2, 0x12, 0x9d, 0x8d, 0x86, 0xdd, 0x19 }, + { 0xe2, 0xd5, 0x49, 0x5e, 0x2a, 0x6e, 0x4e, 0xd9, 0x31, 0x26, 0x53, 0x13, 0x98, 0x5e, 0x2f, 0x23, 0xea, 0xa0, 0x30, 0xee, 0xef, 0x62, 0x2b, 0xdc, 0x93, 0x65, 0x90, 0xad, 0x9a, 0xf1, 0x74, 0x12, + 0xf5, 0x24, 0x33, 0xcc, 0xc3, 0xda, 0x42, 0x54, 0xa6, 0x6c, 0x86, 0x99, 0xb9, 0xb5, 0xf7, 0x07, 0x90, 0xd8, 0x85, 0x7f, 0x69, 0xfb, 0x19, 0x2a, 0x2c, 0xc0, 0x11, 0x81, 0x64, 0x37, 0x38, 0x07 }, + { 0xc7, 0xb3, 0xf5, 0xe4, 0x4b, 0x55, 0xcf, 0xd8, 0x2b, 0x72, 0xde, 0x62, 0xfc, 0x66, 0xea, 0x82, 0xee, 0x2e, 0xe5, 0x4f, 0x66, 0xba, 0x19, 0x63, 0x01, 0x0b, 0x2d, 0x89, 0xb4, 0xaa, 0x76, 0xb3, + 0x7e, 0xc5, 0xbe, 0xdd, 0x57, 0x90, 0x5e, 0xff, 0x5b, 0x9a, 0x71, 0xe1, 0x47, 0xf9, 0xec, 0xe5, 0xf0, 0x19, 0x89, 0x17, 0x65, 0x3e, 0x56, 0x4a, 0x98, 0xb2, 0x3c, 0x3b, 0xf0, 0x14, 0x13, 0x1b }, + { 0xc0, 0x72, 0x26, 0x96, 0x6b, 0xf5, 0x50, 0xa1, 0x65, 0xcd, 0xfe, 0x92, 0xa5, 0x5a, 0xb3, 0x56, 0x27, 0x5b, 0x2f, 0x4a, 0x8f, 0x67, 0xaa, 0xf4, 0xa1, 0x6e, 0x3c, 0x66, 0xcc, 0xb7, 0x71, 0x70, + 0xff, 0x70, 0x1f, 0x9e, 0x09, 0xae, 0x31, 0xcb, 0x2a, 0xd5, 0x8a, 0x38, 0xa9, 0xaf, 0xbc, 0x94, 0xa2, 0xa8, 0xe9, 0x77, 0x1c, 0xc3, 0xfa, 0xd1, 0x45, 0xd2, 0xe2, 0xff, 0x7d, 0xf2, 0x44, 0x00, + 0xa0, 0xc3, 0xc1, 0xdd, 0xa0, 0x4c, 0xfb, 0xed, 0x1a, 0xbd, 0x0c, 0x05, 0x3b, 0xa9, 0xc8, 0x98, 0xb0, 0x7d, 0x6a, 0x77, 0xcb, 0x08, 0x70, 0x64, 0x31, 0x9d, 0x9c, 0x7b, 0x40, 0x9e, 0xbb, 0xf4 }, + { 0xbc, 0x88, 0x9d, 0x36, 0xae, 0xbc, 0x92, 0x47, 0x63, 0x85, 0x41, 0xe3, 0x1e, 0x1c, 0x39, 0xf5, 0xd3, 0xc2, 0x0a, 0x7d, 0x18, 0x7a, 0x8f, 0xd3, 0x0c, 0x37, 0x50, 0x28, 0x35, 0x93, 0x77, 0x4b, + 0xcb, 0xba, 0x35, 0x4e, 0x94, 0x48, 0xe4, 0x0c, 0xa7, 0x36, 0x4f, 0x74, 0x2b, 0xf9, 0xb5, 0xb5, 0xeb, 0x91, 0x50, 0x3c, 0x67, 0x9b, 0x4d, 0x25, 0xd4, 0x0e, 0x0d, 0xb9, 0x5b, 0x77, 0xf3, 0x0e, + 0xa0, 0xc3, 0xc1, 0xdd, 0xa0, 0x4c, 0xfb, 0xed, 0x1a, 0xbd, 0x0c, 0x05, 0x3b, 0xa9, 0xc8, 0x98, 0xb0, 0x7d, 0x6a, 0x77, 0xcb, 0x08, 0x70, 0x64, 0x31, 0x9d, 0x9c, 0x7b, 0x40, 0x9e, 0xbb, 0xf4 } }, + { { 0x44, 0xdd, 0x62, 0x9e, 0x0f, 0xee, 0x20, 0x11, 0x37, 0xfc, 0xd0, 0x5c, 0xe4, 0xe1, 0x0a, 0xb8, 0xc2, 0xe0, 0x9c, 0x2c, 0x3e, 0x1b, 0x31, 0x1c, 0xdb, 0xa3, 0x84, 0x9a, 0xb7, 0x4e, 0x40, 0x74, + 0x21, 0xfd, 0xfc, 0x65, 0xbd, 0x38, 0x8a, 0x55, 0x6f, 0x1e, 0xc3, 0x14, 0xfc, 0x66, 0x04, 0x7b, 0xc4, 0x61, 0xb0, 0xcb, 0xfa, 0xdd, 0x50, 0x45, 0x4b, 0x2e, 0xf0, 0x6d, 0x0f, 0x26, 0x6d, 0xbf }, + { 0xe6, 0xbc, 0x35, 0x73, 0xb3, 0x11, 0x38, 0xc6, 0x31, 0x82, 0x96, 0x80, 0x1d, 0xa9, 0xd9, 0x17, 0x85, 0x4e, 0xad, 0x0f, 0x5c, 0xb7, 0xe8, 0x78, 0x62, 0x2f, 0x3c, 0x10, 0x0e, 0xdc, 0xf2, 0x7e, + 0xf5, 0x02, 0x6d, 0x1a, 0x50, 0xc2, 0x50, 0x7d, 0x0d, 0x14, 0x77, 0x77, 0xfc, 0xbe, 0x23, 0x02, 0x81, 0x0a, 0xdc, 0xa3, 0x16, 0xfd, 0xab, 0xb9, 0x7c, 0xb6, 0x7e, 0x8a, 0xde, 0x1f, 0x22, 0xeb }, + { 0xab, 0xf3, 0xea, 0x63, 0xc0, 0x25, 0xa2, 0xc7, 0x6a, 0xfe, 0x91, 0x4a, 0x0a, 0x91, 0xdd, 0x6d, 0x6f, 0x8c, 0xf9, 0xa8, 0x1c, 0x9f, 0xb5, 0xe5, 0xd2, 0xac, 0xe6, 0x51, 0x9a, 0xd3, 0x87, 0x17, + 0x82, 0x12, 0x0a, 0x58, 0x99, 0x7f, 0x81, 0x2d, 0x8d, 0x27, 0x2d, 0x1b, 0xb0, 0x02, 0x7e, 0x0d, 0xd6, 0x18, 0x89, 0x5e, 0x0c, 0x2b, 0x57, 0xa6, 0x56, 0x35, 0xff, 0x71, 0x4e, 0xb0, 0x49, 0x38 }, + { 0x36, 0xdf, 0x1d, 0x1c, 0xf6, 0xa7, 0x4d, 0x87, 0x7e, 0x2c, 0x3f, 0xb4, 0xda, 0xd7, 0x80, 0x71, 0x0b, 0xf3, 0x2a, 0x47, 0x20, 0xe6, 0x9a, 0x3d, 0x17, 0x9a, 0x97, 0xc9, 0x4e, 0x53, 0xa6, 0xe2, + 0x23, 0xea, 0x94, 0x4d, 0xf9, 0xeb, 0x2c, 0x03, 0x2c, 0x88, 0xa2, 0xe6, 0xc5, 0x94, 0xa5, 0x6f, 0xc3, 0x98, 0xa9, 0x8b, 0xa7, 0x41, 0x7d, 0xd3, 0x82, 0x01, 0x13, 0xb6, 0x0f, 0x39, 0x1e, 0xd2 }, + { 0x08, 0x28, 0xc3, 0x1c, 0xec, 0x21, 0x3a, 0xb4, 0x4c, 0xb1, 0xfa, 0xb9, 0x0c, 0xfe, 0xc2, 0x50, 0xc5, 0x99, 0x62, 0xa0, 0x11, 0x74, 0xcf, 0x05, 0x1e, 0x2b, 0xdf, 0x6d, 0x22, 0x8e, 0x6e, 0x55, + 0x19, 0x21, 0x9c, 0xa1, 0x98, 0x56, 0x45, 0x90, 0x40, 0x3a, 0x8e, 0xad, 0x76, 0x4d, 0xd3, 0x95, 0x27, 0x67, 0x4e, 0x02, 0x16, 0xc3, 0xfe, 0x5a, 0x79, 0x4e, 0x2d, 0x6f, 0xd0, 0xe4, 0x4f, 0x62 }, + { 0x40, 0x14, 0xe1, 0x88, 0x3d, 0xcc, 0x51, 0xcb, 0x98, 0x86, 0x06, 0x4d, 0xe4, 0x52, 0x71, 0xe2, 0x2e, 0x2b, 0x80, 0xfd, 0x81, 0x65, 0xaf, 0x93, 0x31, 0x87, 0xe0, 0xff, 0x31, 0xab, 0xff, 0x53, + 0x0e, 0x2d, 0xb1, 0x47, 0xe6, 0x44, 0xb7, 0x29, 0xab, 0x0f, 0x51, 0x3a, 0x53, 0x84, 0x36, 0x58, 0x8c, 0x5f, 0x7b, 0x65, 0x6a, 0xb7, 0x6f, 0xdc, 0xad, 0xc1, 0xa3, 0xe4, 0x21, 0xfc, 0x22, 0x0e, + 0xc1, 0x10, 0xd1, 0x7d, 0x9f, 0xd3, 0x1e, 0x33, 0xb4, 0xca, 0xb9, 0xff, 0xd8, 0x27, 0xb8, 0xca, 0xde, 0x49, 0x6f, 0xdc, 0xf0, 0xe8, 0x70, 0x36, 0xdb, 0x90, 0x00, 0x07, 0x9e, 0x77, 0x39, 0xfe }, + { 0xc9, 0x93, 0x4b, 0xe6, 0x47, 0x7e, 0x1d, 0x86, 0x15, 0x46, 0xe8, 0x27, 0xf5, 0x84, 0x67, 0x4e, 0x42, 0xe3, 0x2b, 0x8a, 0x4e, 0x90, 0x7b, 0x87, 0xcc, 0xdf, 0xaa, 0x04, 0x06, 0x05, 0xe6, 0x72, + 0xff, 0x6f, 0x44, 0x1b, 0x08, 0xad, 0x79, 0x3e, 0xb7, 0xdd, 0xd7, 0x2c, 0x73, 0xf0, 0xf0, 0xc4, 0x6e, 0xb7, 0x37, 0xe1, 0x02, 0xf5, 0x42, 0xe7, 0xef, 0xa1, 0xdd, 0x50, 0x9a, 0xc5, 0x8d, 0x00, + 0xc1, 0x10, 0xd1, 0x7d, 0x9f, 0xd3, 0x1e, 0x33, 0xb4, 0xca, 0xb9, 0xff, 0xd8, 0x27, 0xb8, 0xca, 0xde, 0x49, 0x6f, 0xdc, 0xf0, 0xe8, 0x70, 0x36, 0xdb, 0x90, 0x00, 0x07, 0x9e, 0x77, 0x39, 0xfe } }, + { { 0x3e, 0x0c, 0x21, 0xc4, 0x3d, 0x64, 0x61, 0xc1, 0x9d, 0xa1, 0x83, 0x10, 0x74, 0x1d, 0x56, 0x12, 0xaf, 0x29, 0x5c, 0x6c, 0x12, 0x48, 0x0a, 0xc7, 0xe5, 0x12, 0xb6, 0x42, 0x6b, 0x54, 0xf4, 0x42, + 0x0c, 0x43, 0x42, 0x2e, 0x78, 0xc2, 0xe7, 0x26, 0x09, 0x41, 0x4a, 0x2f, 0xa1, 0xb0, 0x1f, 0xcd, 0x63, 0x76, 0x1e, 0xa1, 0x6f, 0xf6, 0xe2, 0xc2, 0x08, 0x89, 0x0d, 0x28, 0xbf, 0x1b, 0x56, 0x5b }, + { 0x3e, 0x2e, 0xf2, 0xcc, 0x81, 0xca, 0xa7, 0x5d, 0x01, 0xd2, 0x82, 0xfd, 0x45, 0xee, 0xc0, 0xf5, 0x49, 0x3b, 0xe2, 0xa4, 0x2a, 0x4d, 0x5f, 0x40, 0x0d, 0xbc, 0xb9, 0x3d, 0x6e, 0xda, 0xe2, 0x86, + 0xe1, 0x23, 0x8b, 0x5f, 0x0d, 0xa2, 0x35, 0x15, 0x1d, 0x22, 0x23, 0xa5, 0x69, 0x56, 0x34, 0x78, 0xb3, 0xb3, 0x55, 0xef, 0x63, 0x8a, 0x17, 0x63, 0xda, 0xf0, 0x64, 0x99, 0x8a, 0x8a, 0xba, 0xd6 }, + { 0x68, 0x79, 0x36, 0xa7, 0x6b, 0xe3, 0x76, 0x1c, 0xe3, 0x38, 0x0b, 0xa3, 0x91, 0xb6, 0xb0, 0x82, 0x37, 0xfa, 0x52, 0x74, 0xf1, 0xb5, 0xd5, 0xd9, 0x07, 0x06, 0x9e, 0xda, 0x87, 0x6b, 0x0f, 0x24, + 0x4f, 0xbe, 0xc9, 0xff, 0x03, 0x41, 0xaf, 0x77, 0x68, 0xed, 0xe7, 0x71, 0xba, 0x2d, 0xde, 0x27, 0xa1, 0xbf, 0xa8, 0xa7, 0x30, 0x7c, 0xcb, 0x79, 0x72, 0x89, 0x1a, 0xdc, 0xc1, 0xe4, 0xb2, 0x9d }, + { 0x94, 0xa3, 0x11, 0xf4, 0x44, 0x80, 0xd0, 0xa3, 0x47, 0x93, 0x36, 0xe2, 0xbd, 0x04, 0xe4, 0x74, 0x3d, 0x00, 0x60, 0xad, 0xd0, 0x2d, 0x86, 0x66, 0xa1, 0x72, 0x1a, 0xb9, 0x1c, 0x14, 0xa2, 0x9b, + 0x4b, 0x04, 0x7d, 0x5b, 0xcd, 0xf8, 0x01, 0x33, 0xde, 0x34, 0x10, 0x29, 0xc4, 0x72, 0x56, 0xff, 0x11, 0xcd, 0xd8, 0x61, 0x2c, 0xb6, 0xb7, 0xf4, 0x24, 0x8b, 0x44, 0xb4, 0xe7, 0x34, 0x50, 0xb8 }, + { 0x72, 0xf6, 0xd4, 0xa3, 0x24, 0xf9, 0xef, 0xf4, 0x55, 0x8d, 0x3c, 0x07, 0xca, 0x10, 0xdd, 0x54, 0x87, 0x13, 0x32, 0x78, 0x5c, 0x64, 0x10, 0x08, 0x62, 0x7e, 0xf4, 0x34, 0x0f, 0x1c, 0xcd, 0xcc, + 0x3b, 0x42, 0xfe, 0x60, 0x41, 0x70, 0x2c, 0x6b, 0xd4, 0x6c, 0xf7, 0xb8, 0x24, 0xf6, 0xd7, 0x07, 0xb3, 0x46, 0xb0, 0x7d, 0x14, 0x24, 0x9b, 0x72, 0x79, 0xf4, 0x23, 0x2a, 0xec, 0x02, 0xe7, 0x69 }, + { 0xe5, 0xbe, 0x84, 0xc3, 0x92, 0x47, 0x15, 0xd3, 0xac, 0x06, 0x44, 0x72, 0x41, 0xeb, 0xb6, 0x5a, 0x17, 0x06, 0x90, 0xd9, 0x55, 0x3d, 0xe4, 0x87, 0x7d, 0x5a, 0x11, 0x9f, 0x02, 0x6d, 0xd3, 0x4e, + 0x71, 0xd1, 0x5e, 0x16, 0x9f, 0xb2, 0xc0, 0x7f, 0xcb, 0x78, 0x8b, 0x89, 0x11, 0xae, 0x43, 0xe8, 0x85, 0xb7, 0xf9, 0xc8, 0x48, 0x5a, 0xb2, 0x96, 0xaf, 0x8f, 0xab, 0x71, 0x84, 0x9d, 0x40, 0x09, + 0x30, 0xd4, 0x32, 0x6e, 0xa2, 0x77, 0x97, 0x71, 0x37, 0xce, 0x22, 0x6b, 0xca, 0xc9, 0x79, 0xef, 0xc0, 0xb2, 0xb4, 0x3d, 0x30, 0xbf, 0x77, 0xe9, 0xc3, 0x8d, 0xec, 0x15, 0x04, 0x08, 0xfa, 0x15 }, + { 0x4b, 0xf3, 0x7f, 0xb2, 0x78, 0x75, 0x45, 0xd4, 0xce, 0x5e, 0x3d, 0xaf, 0x92, 0x63, 0x3d, 0x90, 0xc0, 0xa7, 0x23, 0x62, 0x7f, 0x37, 0x58, 0x8d, 0x12, 0xe0, 0xb8, 0x6c, 0x46, 0x38, 0xaa, 0xf7, + 0xe1, 0x03, 0x9e, 0x1f, 0x31, 0xf9, 0x5a, 0xa4, 0x59, 0x0d, 0xec, 0xc5, 0x1f, 0x17, 0x88, 0x25, 0xcc, 0xed, 0x69, 0x2b, 0x91, 0x73, 0x6a, 0x3f, 0xcb, 0xe5, 0x9c, 0x1e, 0x26, 0x3e, 0xec, 0x0b, + 0x30, 0xd4, 0x32, 0x6e, 0xa2, 0x77, 0x97, 0x71, 0x37, 0xce, 0x22, 0x6b, 0xca, 0xc9, 0x79, 0xef, 0xc0, 0xb2, 0xb4, 0x3d, 0x30, 0xbf, 0x77, 0xe9, 0xc3, 0x8d, 0xec, 0x15, 0x04, 0x08, 0xfa, 0x15 } }, + { { 0xc5, 0x1d, 0xcd, 0x70, 0xb2, 0x9e, 0x53, 0x29, 0x05, 0x78, 0x83, 0x5d, 0x56, 0x30, 0x89, 0xee, 0x02, 0xd7, 0xac, 0x57, 0x0a, 0xd2, 0xa0, 0x9c, 0x96, 0x0c, 0xbf, 0xf2, 0x30, 0xbf, 0x1a, 0x2b, + 0xee, 0x0e, 0x9f, 0x1e, 0x1c, 0x65, 0x7d, 0xb5, 0x48, 0xad, 0x6f, 0x51, 0xa0, 0x91, 0x61, 0xe4, 0xe6, 0x83, 0x9f, 0x58, 0x7c, 0x76, 0x2b, 0x52, 0x94, 0x87, 0x3c, 0x8d, 0x36, 0x4c, 0x37, 0x3c }, + { 0x59, 0x3b, 0x0d, 0x38, 0xab, 0x93, 0xca, 0xfb, 0x67, 0x44, 0x30, 0x96, 0xec, 0xbd, 0x00, 0x1d, 0x93, 0xd0, 0xb3, 0x3d, 0x3c, 0xd4, 0x4e, 0x3d, 0xd8, 0x29, 0x93, 0xb2, 0xb3, 0x77, 0xfc, 0x57, + 0x31, 0x20, 0xe3, 0x90, 0x0d, 0xf4, 0x91, 0x2f, 0x8b, 0x43, 0xce, 0xfe, 0x99, 0x03, 0x03, 0xa2, 0x90, 0x8d, 0xcf, 0xa8, 0xc0, 0x21, 0x00, 0xca, 0xcc, 0xcb, 0x4b, 0x2f, 0xa5, 0x39, 0xa8, 0x0b }, + { 0xca, 0xf6, 0xf9, 0xbb, 0x53, 0xcb, 0x97, 0x76, 0xb6, 0x9c, 0x2c, 0x18, 0x21, 0x43, 0x13, 0x48, 0x13, 0xc9, 0x0e, 0xeb, 0x40, 0xea, 0xce, 0x1f, 0x3a, 0xe9, 0xd2, 0x9e, 0x29, 0xdb, 0xe2, 0x79, + 0xe2, 0x1a, 0x9f, 0x84, 0x9d, 0xe4, 0x55, 0x82, 0x17, 0xeb, 0x87, 0xf6, 0xc3, 0xef, 0xcd, 0x54, 0x14, 0xee, 0xc8, 0x5b, 0xd7, 0x67, 0x05, 0xe2, 0x34, 0xa2, 0x7e, 0x81, 0x83, 0x21, 0x7a, 0x02 }, + { 0xc5, 0x03, 0xd9, 0x75, 0xdf, 0x17, 0x15, 0xe3, 0x5b, 0x7b, 0x4f, 0x66, 0x9c, 0x15, 0x4e, 0x01, 0xdf, 0x3d, 0x16, 0xb6, 0x52, 0xcc, 0xcf, 0x28, 0x40, 0xdb, 0x20, 0xee, 0x8b, 0x69, 0xb1, 0x2b, + 0xc0, 0x6e, 0xe4, 0xd2, 0xf5, 0xd1, 0x49, 0x3f, 0xf3, 0x0a, 0x12, 0xcd, 0x13, 0xbd, 0x9d, 0x3d, 0x5b, 0x28, 0x5c, 0xb0, 0x0d, 0x0e, 0xb6, 0xed, 0xec, 0x65, 0xeb, 0x25, 0x28, 0x2e, 0x65, 0x2f }, + { 0xed, 0xa7, 0x05, 0xc1, 0xa6, 0x81, 0xf2, 0x7a, 0x69, 0x68, 0x17, 0x8e, 0xf7, 0xc9, 0x14, 0x80, 0x9f, 0x81, 0xfe, 0x16, 0xfd, 0x81, 0x93, 0xb4, 0x0b, 0x05, 0x5b, 0x4e, 0xef, 0x6e, 0x7a, 0x67, + 0x9d, 0x99, 0x4c, 0x17, 0xcd, 0x1c, 0x16, 0xfd, 0x31, 0x35, 0xd5, 0x3e, 0xa3, 0x00, 0xbf, 0xbe, 0xda, 0xd6, 0xe2, 0x37, 0x9b, 0x13, 0x1b, 0xca, 0x29, 0x90, 0x4b, 0xf2, 0x09, 0x57, 0x2f, 0xe9 }, + { 0xd7, 0xba, 0x23, 0xd3, 0xa0, 0x6e, 0x14, 0x6a, 0xf0, 0x77, 0xb7, 0xe6, 0xe3, 0xc9, 0x3b, 0x38, 0xbb, 0xe7, 0xbe, 0x54, 0x75, 0xf8, 0xb7, 0x42, 0x29, 0xe2, 0x83, 0xde, 0x20, 0x22, 0x41, 0xcf, + 0x5f, 0x6f, 0x80, 0x60, 0xf3, 0x44, 0x04, 0x21, 0xd5, 0x03, 0x68, 0x42, 0xde, 0x81, 0xea, 0xe8, 0x7e, 0x5b, 0x80, 0x0f, 0x1b, 0x2d, 0x06, 0xc7, 0xce, 0xe9, 0x46, 0xc7, 0xf7, 0xb3, 0xa2, 0x02, + 0x21, 0xb5, 0x4d, 0xc2, 0x36, 0xea, 0xe6, 0x7b, 0xb3, 0x61, 0xe6, 0x18, 0x40, 0x5b, 0xce, 0x5b, 0xc2, 0xee, 0xa5, 0xde, 0xe9, 0xe6, 0xe0, 0xa8, 0x58, 0x58, 0x03, 0x34, 0x26, 0x27, 0x65, 0x2a }, + { 0xfa, 0x43, 0xa6, 0xc4, 0x32, 0xa1, 0x2f, 0xb6, 0x37, 0x05, 0xf4, 0xa4, 0xa7, 0x36, 0xdd, 0x1c, 0x45, 0x10, 0x95, 0x83, 0x67, 0x89, 0x79, 0x18, 0x34, 0xad, 0xe7, 0x57, 0x7f, 0x0d, 0x48, 0x9b, + 0x14, 0xdf, 0x5f, 0xc8, 0xd7, 0x0f, 0x78, 0x47, 0x88, 0x20, 0xff, 0x7f, 0xb1, 0x21, 0x27, 0x14, 0x58, 0x32, 0x12, 0xfb, 0x97, 0xe0, 0x81, 0x0e, 0x92, 0xf4, 0x5c, 0x0e, 0x44, 0x48, 0x4e, 0x01, + 0x21, 0xb5, 0x4d, 0xc2, 0x36, 0xea, 0xe6, 0x7b, 0xb3, 0x61, 0xe6, 0x18, 0x40, 0x5b, 0xce, 0x5b, 0xc2, 0xee, 0xa5, 0xde, 0xe9, 0xe6, 0xe0, 0xa8, 0x58, 0x58, 0x03, 0x34, 0x26, 0x27, 0x65, 0x2a } }, + { { 0x1e, 0x89, 0x12, 0xe8, 0xab, 0xca, 0xeb, 0x96, 0x78, 0x43, 0x89, 0x79, 0x26, 0x61, 0x86, 0x2e, 0x37, 0xd7, 0x94, 0xb5, 0xb9, 0xf7, 0xc9, 0xe7, 0x04, 0x6c, 0x96, 0x1c, 0x54, 0x0d, 0xb0, 0x6c, + 0xd3, 0x68, 0x9b, 0x53, 0xa7, 0x56, 0x34, 0x1b, 0x65, 0xff, 0xf9, 0xee, 0xf1, 0xc6, 0xfd, 0x7e, 0xa8, 0x42, 0x59, 0x60, 0x06, 0x5f, 0xc2, 0x89, 0x8b, 0xfc, 0xf8, 0x6c, 0x9a, 0x0d, 0xb1, 0x36 }, + { 0x52, 0x3d, 0x83, 0x25, 0x0f, 0x57, 0x81, 0x76, 0x7b, 0x21, 0xf7, 0x96, 0xd6, 0x1f, 0xfe, 0xd7, 0x7c, 0xc1, 0x32, 0xb5, 0xbc, 0x05, 0x46, 0xdb, 0x6f, 0x25, 0xd8, 0x7a, 0x68, 0xe2, 0x01, 0x81, + 0xf8, 0x9a, 0xc5, 0x29, 0x78, 0x1c, 0x01, 0xc5, 0x4d, 0x61, 0x4e, 0x75, 0xdf, 0x9f, 0xc3, 0x22, 0x96, 0x7c, 0xf9, 0xa7, 0xed, 0x41, 0x6f, 0x64, 0xfd, 0xd4, 0x61, 0x58, 0x0d, 0x49, 0xc9, 0xa4 }, + { 0x4a, 0xf7, 0xda, 0xef, 0xe0, 0x3b, 0x33, 0x19, 0x79, 0x02, 0x7a, 0xbb, 0xd3, 0x53, 0xf4, 0x8c, 0x8a, 0x16, 0xfb, 0xbd, 0x35, 0xd9, 0x70, 0xb2, 0x0a, 0x06, 0x05, 0x14, 0xd0, 0x9e, 0xf6, 0x13, + 0x44, 0xbb, 0xb7, 0x93, 0x86, 0x1b, 0x3c, 0xb0, 0x54, 0xa7, 0x48, 0xc2, 0xa7, 0x10, 0xda, 0x65, 0xb2, 0xdb, 0x0f, 0x85, 0x23, 0x57, 0x77, 0x44, 0x23, 0x20, 0x6d, 0x2e, 0xde, 0x20, 0x01, 0xed }, + { 0x9c, 0xb8, 0x68, 0xeb, 0xbb, 0x8b, 0xaf, 0x81, 0x9c, 0x2f, 0x90, 0x4c, 0xc2, 0x62, 0x17, 0xfc, 0xf2, 0xa5, 0xab, 0x4c, 0x2e, 0x69, 0xcb, 0x82, 0x5f, 0x4c, 0x3c, 0x82, 0xcd, 0x6a, 0xcb, 0x15, + 0xa2, 0xfc, 0x50, 0x54, 0x5e, 0x2e, 0x83, 0x52, 0x48, 0x29, 0x51, 0xcc, 0x50, 0xaa, 0x27, 0xa3, 0xf3, 0x71, 0xdb, 0x2c, 0x1c, 0xa9, 0x8a, 0xa5, 0x95, 0xab, 0x3e, 0x6f, 0xcd, 0xba, 0x22, 0x7c }, + { 0xf7, 0x5d, 0xb5, 0x20, 0x65, 0xfe, 0xa9, 0xe7, 0x1f, 0x8e, 0xd6, 0xc0, 0xf2, 0x3f, 0x1b, 0x8c, 0x7a, 0x02, 0x54, 0xd8, 0xa7, 0x0e, 0x6f, 0x68, 0x94, 0x81, 0xff, 0x30, 0x0e, 0x6d, 0x1a, 0x96, + 0x1b, 0x86, 0x07, 0xaa, 0xbf, 0x37, 0xc5, 0x5e, 0x26, 0xa2, 0xdf, 0x0b, 0xd0, 0x7f, 0x94, 0x35, 0x30, 0xa4, 0x9e, 0x47, 0xaf, 0xad, 0x9c, 0xc9, 0x02, 0x21, 0x55, 0x94, 0x04, 0x13, 0xff, 0x64 }, + { 0x9c, 0x8d, 0x18, 0x63, 0x83, 0xad, 0x01, 0xcc, 0xbb, 0xe6, 0x00, 0xda, 0x15, 0xce, 0xc6, 0x6e, 0x7a, 0x37, 0x6a, 0x81, 0x44, 0xb3, 0xfc, 0xb7, 0xcd, 0x05, 0xee, 0x4a, 0x6f, 0x29, 0xe4, 0x79, + 0x63, 0x52, 0x7e, 0x14, 0xc9, 0x14, 0x77, 0xa8, 0x19, 0x94, 0x03, 0xc6, 0x51, 0x57, 0xf1, 0xcc, 0x11, 0x29, 0xde, 0x86, 0x08, 0xfe, 0x41, 0x02, 0x71, 0xb7, 0xbf, 0xd7, 0xe7, 0x83, 0x3e, 0x0c, + 0x9a, 0x59, 0x7e, 0xe8, 0x61, 0x36, 0x56, 0x9a, 0xbf, 0x64, 0xfd, 0xf3, 0xb7, 0xb9, 0x2f, 0x9e, 0x56, 0x1f, 0x57, 0x45, 0x2e, 0x19, 0x0f, 0x6f, 0x70, 0x01, 0xc2, 0x48, 0x05, 0x23, 0x9b, 0x2f }, + { 0xb5, 0x4e, 0xe7, 0xcc, 0x7b, 0x66, 0x7a, 0xf8, 0xec, 0xcd, 0x1b, 0x0c, 0x0f, 0xec, 0x04, 0x27, 0xa0, 0x61, 0xfd, 0x12, 0x2d, 0xab, 0xc9, 0xc5, 0x8e, 0xee, 0x36, 0xc2, 0xef, 0x67, 0xd5, 0x87, + 0x95, 0x6c, 0x12, 0xb7, 0x12, 0x81, 0x55, 0xe0, 0x7b, 0xdb, 0x8f, 0x67, 0xea, 0x04, 0x55, 0x91, 0x9b, 0x50, 0x65, 0x05, 0xc1, 0xf1, 0x0b, 0x04, 0x91, 0x66, 0x3c, 0x32, 0x53, 0x72, 0x01, 0x04, + 0x9a, 0x59, 0x7e, 0xe8, 0x61, 0x36, 0x56, 0x9a, 0xbf, 0x64, 0xfd, 0xf3, 0xb7, 0xb9, 0x2f, 0x9e, 0x56, 0x1f, 0x57, 0x45, 0x2e, 0x19, 0x0f, 0x6f, 0x70, 0x01, 0xc2, 0x48, 0x05, 0x23, 0x9b, 0x2f } }, + { { 0xc8, 0x37, 0x10, 0xdc, 0xdb, 0xfc, 0x51, 0x91, 0xae, 0x37, 0xa4, 0xe0, 0xcf, 0xbb, 0xdd, 0x92, 0x93, 0x5f, 0x6b, 0xd6, 0x81, 0xbf, 0x9b, 0x24, 0x5e, 0x0d, 0xf1, 0xe4, 0x04, 0x89, 0xd1, 0x1b, + 0xb2, 0x68, 0x56, 0x3a, 0xdc, 0x59, 0xd0, 0x8a, 0x93, 0x37, 0x5d, 0xa5, 0x40, 0x5e, 0xfe, 0xc9, 0x41, 0x0b, 0x8a, 0x50, 0xd2, 0xa0, 0x94, 0x86, 0xf7, 0x46, 0x3b, 0x7e, 0x1d, 0xea, 0x2b, 0xa8 }, + { 0x1b, 0xe2, 0xe6, 0x48, 0x86, 0xa8, 0x65, 0xfd, 0x2b, 0xae, 0xc7, 0x7d, 0x41, 0xee, 0xb2, 0x80, 0x33, 0x1c, 0x0a, 0xdc, 0x42, 0xea, 0x99, 0xd0, 0x1f, 0x6d, 0xc8, 0x80, 0x51, 0x70, 0xd4, 0x19, + 0xae, 0xfc, 0x66, 0x16, 0xa2, 0x53, 0x27, 0x19, 0x7a, 0xf2, 0x9a, 0x25, 0x0c, 0x39, 0x8c, 0xbf, 0xe7, 0xa3, 0x7a, 0xd6, 0xa3, 0x43, 0x62, 0xd2, 0x4a, 0xc2, 0xf1, 0x96, 0x7e, 0xe3, 0x83, 0x13 }, + { 0xf5, 0xb1, 0x2a, 0xc5, 0x4d, 0xcc, 0xdf, 0x56, 0xde, 0x92, 0x96, 0x46, 0x03, 0x11, 0xfc, 0xa0, 0xbc, 0xa2, 0x22, 0xf7, 0x25, 0x74, 0x2a, 0x1f, 0x27, 0x34, 0x18, 0xe8, 0x06, 0xa4, 0x77, 0x26, + 0x1a, 0x51, 0x5e, 0xfb, 0x77, 0xbc, 0x55, 0xb1, 0xf8, 0xa5, 0x19, 0x23, 0x00, 0x97, 0xf7, 0xbb, 0xe4, 0xcd, 0x41, 0x9e, 0xd9, 0x5e, 0x0c, 0x6b, 0x1b, 0x8a, 0xba, 0x52, 0x93, 0xbe, 0x2c, 0xf3 }, + { 0xb3, 0x02, 0xeb, 0x44, 0x3c, 0x05, 0xae, 0x9c, 0x94, 0xa9, 0x1f, 0x72, 0x41, 0xbc, 0x81, 0x66, 0x5f, 0x50, 0xc0, 0x57, 0xb4, 0x44, 0xf0, 0xe1, 0x2a, 0xa9, 0x88, 0x69, 0xa6, 0x1c, 0x05, 0x85, + 0xda, 0xc7, 0xb2, 0xe1, 0x8c, 0x2f, 0x7c, 0x49, 0x37, 0xa2, 0xf2, 0x56, 0xab, 0x12, 0x9f, 0x12, 0x4b, 0x1b, 0x73, 0x75, 0x3f, 0x30, 0x0f, 0x40, 0xf1, 0xf9, 0x1d, 0xa7, 0x2c, 0x98, 0x8c, 0x91 }, + { 0xcb, 0xd3, 0x39, 0x60, 0x56, 0xe3, 0xbd, 0x65, 0x86, 0x1a, 0x58, 0x40, 0xc0, 0xa4, 0xc4, 0x8b, 0xe5, 0xf7, 0x49, 0x0a, 0xf2, 0x09, 0x51, 0x32, 0x6e, 0x06, 0x5a, 0x27, 0x19, 0x78, 0x2e, 0x3a, + 0x04, 0xf9, 0x34, 0x80, 0x49, 0x39, 0x93, 0xcd, 0x89, 0x67, 0x7b, 0xc0, 0x8d, 0x9d, 0x8d, 0x4c, 0x83, 0x20, 0x80, 0xfc, 0x00, 0xf2, 0x8a, 0x8f, 0xa4, 0x4d, 0x8e, 0x8f, 0x58, 0x51, 0x5b, 0x71 }, + { 0x71, 0x3f, 0x90, 0x41, 0xb8, 0x74, 0xbc, 0x7a, 0x85, 0xf5, 0xab, 0xca, 0x7e, 0xf2, 0x70, 0x41, 0xbc, 0x36, 0xb5, 0xc3, 0x4e, 0xf1, 0x2b, 0x17, 0x35, 0x40, 0xdb, 0x3c, 0xdb, 0xd2, 0xec, 0x0b, + 0x99, 0xc1, 0x43, 0x17, 0xad, 0x38, 0x45, 0x2d, 0x07, 0x31, 0xd7, 0xb6, 0x95, 0x1c, 0x89, 0x25, 0xe4, 0x89, 0x97, 0xd3, 0xcf, 0x11, 0x2f, 0x63, 0x31, 0x51, 0xa2, 0x18, 0xfc, 0x12, 0x04, 0x0a, + 0xb0, 0x33, 0xce, 0x0b, 0x57, 0xc0, 0x8c, 0x58, 0x25, 0xf8, 0x9b, 0x50, 0x22, 0x1c, 0x5c, 0x7b, 0x02, 0xc7, 0xed, 0xfc, 0x98, 0x8b, 0xbd, 0xd2, 0x4e, 0xfc, 0x78, 0x91, 0x7f, 0x4c, 0x99, 0x24 }, + { 0xfc, 0x46, 0xe4, 0x85, 0x0c, 0x52, 0x14, 0xf8, 0x8a, 0xa4, 0x97, 0x17, 0x10, 0xb2, 0x93, 0xef, 0xa0, 0x66, 0x3c, 0xfd, 0x61, 0x42, 0x24, 0x30, 0x70, 0x4b, 0xfd, 0x0b, 0x86, 0xc8, 0x97, 0xd7, + 0x04, 0xc2, 0xa6, 0x61, 0x41, 0xaf, 0xcc, 0x1d, 0x52, 0xc9, 0xf3, 0xca, 0xe1, 0x90, 0x7c, 0xbd, 0xce, 0xaf, 0x30, 0xc4, 0xb4, 0x7d, 0x81, 0x7e, 0xbd, 0xe2, 0x09, 0x70, 0x1e, 0x6b, 0xb9, 0x03, + 0xb0, 0x33, 0xce, 0x0b, 0x57, 0xc0, 0x8c, 0x58, 0x25, 0xf8, 0x9b, 0x50, 0x22, 0x1c, 0x5c, 0x7b, 0x02, 0xc7, 0xed, 0xfc, 0x98, 0x8b, 0xbd, 0xd2, 0x4e, 0xfc, 0x78, 0x91, 0x7f, 0x4c, 0x99, 0x24 } }, + { { 0x5f, 0x01, 0x6d, 0xec, 0x82, 0x02, 0x96, 0x47, 0x74, 0xd9, 0x73, 0x2e, 0x2e, 0x17, 0x00, 0xb6, 0xe0, 0xa4, 0x13, 0x17, 0xae, 0x7f, 0x85, 0xcb, 0xff, 0xe7, 0x96, 0x99, 0xdb, 0x9f, 0xad, 0x21, + 0x60, 0xd9, 0x12, 0xdc, 0x41, 0x01, 0x33, 0x66, 0x4c, 0x24, 0x8b, 0x25, 0x17, 0xd7, 0x22, 0x14, 0x12, 0x4d, 0xad, 0x82, 0x9a, 0x85, 0x69, 0x5e, 0x35, 0x10, 0xe0, 0xd7, 0x1a, 0x82, 0x88, 0x14 }, + { 0xab, 0x5f, 0x2c, 0x7d, 0xa2, 0xe5, 0x67, 0x5f, 0xe4, 0x92, 0x03, 0x93, 0xd7, 0x13, 0xa1, 0xfa, 0x4a, 0xb7, 0x18, 0x4a, 0x8e, 0x8c, 0x78, 0x9a, 0x0c, 0x60, 0x02, 0xe8, 0x2d, 0x50, 0x05, 0x0f, + 0x92, 0xee, 0x9f, 0x81, 0xde, 0x6b, 0x20, 0xe4, 0x9b, 0x17, 0x2e, 0x99, 0x0f, 0x01, 0x31, 0xa7, 0xc5, 0xc4, 0x53, 0x70, 0xda, 0x03, 0xc6, 0xf7, 0x22, 0x87, 0x98, 0x87, 0x19, 0x36, 0xa6, 0x49 }, + { 0x93, 0xab, 0x22, 0xc4, 0x39, 0x6c, 0x97, 0x80, 0xd2, 0xe2, 0x36, 0xfa, 0x31, 0x74, 0x67, 0xcc, 0x50, 0x1b, 0x95, 0xbe, 0x77, 0xe0, 0xd1, 0x00, 0x74, 0x04, 0xe1, 0x4d, 0xca, 0x44, 0x35, 0x72, + 0x74, 0x69, 0x82, 0x23, 0x56, 0x9b, 0xcc, 0x34, 0x5a, 0xcb, 0xa2, 0xa3, 0x31, 0x12, 0x4a, 0x84, 0x4c, 0xe9, 0x37, 0x3a, 0x58, 0xf8, 0x79, 0x65, 0x4a, 0x66, 0x79, 0x82, 0xf4, 0x5d, 0x75, 0xc3 }, + { 0x2d, 0x5d, 0xac, 0x4f, 0xb5, 0x00, 0x68, 0x3b, 0x5f, 0x2e, 0xdd, 0xcb, 0x14, 0x4a, 0x7f, 0xad, 0x12, 0x45, 0x91, 0xd1, 0x84, 0xd8, 0x14, 0xff, 0xcb, 0x64, 0x43, 0x6d, 0x65, 0xe7, 0x19, 0x68, + 0x2b, 0x5e, 0x53, 0x05, 0x74, 0x66, 0xed, 0xac, 0x2f, 0x5a, 0x8f, 0x70, 0x96, 0xab, 0x29, 0xf3, 0x9a, 0x59, 0xa2, 0xe2, 0xef, 0xd3, 0xc9, 0xd7, 0x53, 0xf8, 0xf5, 0xa3, 0xd6, 0xf4, 0x34, 0xf8 }, + { 0x1d, 0x14, 0xf3, 0xfd, 0xb0, 0x66, 0x20, 0xff, 0xfc, 0x79, 0x47, 0xc7, 0x4c, 0xe9, 0x45, 0x67, 0xf5, 0x97, 0x14, 0xea, 0x7c, 0x63, 0xc5, 0x3f, 0x0b, 0x46, 0xe0, 0x88, 0xd6, 0x9b, 0x67, 0x71, + 0xba, 0xa6, 0x15, 0x28, 0x94, 0x54, 0x83, 0x68, 0x00, 0x3a, 0x33, 0xa6, 0x1a, 0x05, 0x6a, 0x68, 0x72, 0x98, 0x48, 0x71, 0xea, 0x5b, 0x47, 0xf5, 0x80, 0x46, 0xa9, 0x57, 0x84, 0xec, 0xad, 0xfc }, + { 0xa3, 0x1d, 0x87, 0xd3, 0x28, 0x62, 0xc6, 0xf7, 0xdb, 0xfb, 0xfa, 0xfc, 0xf3, 0x27, 0x5c, 0x31, 0xd3, 0x32, 0x26, 0x0e, 0x0f, 0x41, 0x49, 0xec, 0x05, 0x16, 0xf7, 0xa5, 0x63, 0xb3, 0xbc, 0xe5, + 0x0d, 0x1e, 0x6f, 0x97, 0x4f, 0x68, 0x40, 0xc0, 0xd4, 0x6c, 0x4f, 0x9e, 0x25, 0xd0, 0xab, 0x8d, 0x2a, 0xb9, 0x3e, 0x06, 0x4d, 0x9d, 0x3d, 0x2d, 0x79, 0x8d, 0x93, 0xdc, 0xfc, 0x6f, 0x0b, 0x04, + 0x48, 0x7c, 0x19, 0x5c, 0xa9, 0xc8, 0x44, 0xe5, 0xf6, 0x4f, 0x51, 0xd8, 0x72, 0x63, 0x41, 0xda, 0x62, 0xac, 0x78, 0x73, 0xb3, 0x3e, 0xc8, 0xb2, 0xf1, 0x3f, 0x89, 0xf2, 0x0e, 0x95, 0xdf, 0xed }, + { 0xfd, 0x69, 0xb1, 0x9a, 0xdb, 0xae, 0x95, 0x87, 0xe2, 0xc6, 0x8a, 0x97, 0x0c, 0xee, 0xc4, 0x22, 0x60, 0x4e, 0x96, 0xa9, 0x72, 0xb9, 0x6f, 0x86, 0x97, 0xa8, 0xdf, 0x83, 0xc5, 0x18, 0x18, 0x6e, + 0xc9, 0x43, 0x30, 0x7e, 0x5b, 0xcf, 0x37, 0x0f, 0xc1, 0xd7, 0xe5, 0xab, 0xb1, 0x31, 0xe0, 0x97, 0xc7, 0x53, 0xb7, 0xfd, 0xd7, 0xdf, 0x00, 0x43, 0x0e, 0x41, 0x62, 0x80, 0x0b, 0xe3, 0xe0, 0x06, + 0x48, 0x7c, 0x19, 0x5c, 0xa9, 0xc8, 0x44, 0xe5, 0xf6, 0x4f, 0x51, 0xd8, 0x72, 0x63, 0x41, 0xda, 0x62, 0xac, 0x78, 0x73, 0xb3, 0x3e, 0xc8, 0xb2, 0xf1, 0x3f, 0x89, 0xf2, 0x0e, 0x95, 0xdf, 0xed } }, + { { 0x98, 0x29, 0xf7, 0x57, 0xfd, 0xbd, 0x44, 0x3f, 0xd9, 0x90, 0x98, 0x19, 0x97, 0xf2, 0x60, 0x27, 0xfd, 0x08, 0xfc, 0x8a, 0xc6, 0xaf, 0x87, 0x22, 0x7f, 0x74, 0x4a, 0x80, 0xaf, 0x72, 0x00, 0x01, + 0x70, 0x9b, 0x47, 0x2a, 0xd2, 0x8e, 0x41, 0x0a, 0xea, 0x6a, 0xdf, 0xb7, 0x61, 0x54, 0x89, 0x5e, 0x01, 0x9f, 0x76, 0x64, 0x29, 0xee, 0x8d, 0x85, 0x20, 0xff, 0x30, 0x58, 0xc2, 0xa3, 0x2a, 0x56 }, + { 0xea, 0x69, 0x8e, 0x6b, 0x8e, 0xdd, 0x55, 0x22, 0x45, 0x61, 0xd4, 0x92, 0x66, 0x8e, 0x96, 0xaf, 0x7e, 0x40, 0x28, 0x72, 0xc4, 0x46, 0xe7, 0x88, 0xd4, 0x6c, 0x74, 0xb7, 0x48, 0x7f, 0xe8, 0xe1, + 0x5e, 0xa5, 0x85, 0x62, 0x8f, 0xd6, 0xfc, 0x27, 0x0a, 0xb2, 0x4b, 0x38, 0x94, 0x59, 0x52, 0x0d, 0x6a, 0x4d, 0xe5, 0x61, 0xce, 0x0d, 0x44, 0x03, 0xa6, 0x2a, 0xc2, 0xd4, 0xd4, 0xe2, 0x71, 0xe3 }, + { 0x40, 0xf0, 0x82, 0xf0, 0x8d, 0xaa, 0xad, 0xa9, 0x9f, 0x9b, 0x85, 0x02, 0xcf, 0x57, 0x15, 0x41, 0x13, 0x59, 0xf2, 0xba, 0xdd, 0xbf, 0x93, 0xe5, 0x40, 0x2e, 0xaf, 0xdd, 0x43, 0x52, 0xc8, 0x7f, + 0x40, 0xad, 0x91, 0x5b, 0x58, 0xd1, 0xa1, 0xe8, 0x6f, 0x77, 0xc3, 0x41, 0x35, 0x5e, 0xf7, 0x03, 0xba, 0xe4, 0xed, 0x2c, 0x28, 0x59, 0xd6, 0x48, 0xfe, 0x50, 0xcc, 0xf9, 0x80, 0xd1, 0x49, 0xd1 }, + { 0xd7, 0xa5, 0xd9, 0x13, 0xdf, 0x7d, 0xf6, 0xc6, 0x25, 0x0f, 0x52, 0xc2, 0x57, 0x61, 0x20, 0xf2, 0xf0, 0xdb, 0x47, 0x49, 0x56, 0xaf, 0x89, 0x11, 0xa7, 0x8d, 0x09, 0x3a, 0xfe, 0x45, 0x43, 0xef, + 0x9f, 0x0c, 0x42, 0xaf, 0xa8, 0xcc, 0x60, 0x48, 0xc0, 0x1c, 0x7c, 0xbe, 0x01, 0xe2, 0x88, 0xcc, 0x6c, 0x3e, 0x97, 0x91, 0xf3, 0xd9, 0xb2, 0xb2, 0x09, 0x7e, 0x35, 0xb1, 0x78, 0xb4, 0x03, 0xf6 }, + { 0x08, 0xc4, 0x1a, 0x3a, 0xc3, 0xe3, 0x26, 0xbd, 0x8d, 0xee, 0x5d, 0xf0, 0xba, 0xb6, 0x65, 0xff, 0x77, 0xc0, 0x99, 0xd1, 0xca, 0xdc, 0xf5, 0x4b, 0x50, 0x50, 0x0a, 0x9e, 0x13, 0x33, 0x76, 0x86, + 0x9b, 0x39, 0x79, 0x78, 0x73, 0x5c, 0x2f, 0x69, 0xa9, 0x9e, 0x0b, 0xeb, 0x11, 0x1e, 0x12, 0xaa, 0xc1, 0x09, 0x83, 0x0f, 0xca, 0xcb, 0x95, 0x10, 0xde, 0x85, 0xe3, 0x75, 0x62, 0x4a, 0xc2, 0x4c }, + { 0x68, 0x78, 0x6c, 0xce, 0x2f, 0x72, 0x80, 0xfe, 0x83, 0x88, 0x63, 0x37, 0xa7, 0xa1, 0x5a, 0x0b, 0x84, 0x8a, 0xda, 0x28, 0x84, 0xf1, 0x6a, 0x63, 0x24, 0x1c, 0x72, 0xda, 0x84, 0xee, 0x1d, 0xe0, + 0x77, 0xf0, 0xf6, 0xce, 0x7e, 0x79, 0x0a, 0x55, 0x03, 0x01, 0x13, 0x0f, 0xf7, 0x6b, 0x45, 0xe7, 0xcb, 0xfd, 0xb0, 0x37, 0x93, 0x4b, 0x40, 0x69, 0xe0, 0x77, 0x67, 0x72, 0x65, 0xee, 0x35, 0x08, + 0x00, 0xc0, 0x07, 0x10, 0xd8, 0x6e, 0x55, 0x83, 0x5a, 0xbc, 0xfa, 0x67, 0x80, 0x8f, 0xfa, 0x21, 0x3e, 0x56, 0x53, 0x5b, 0xbc, 0x9d, 0xff, 0x16, 0xd9, 0x57, 0xcf, 0x2b, 0x78, 0x06, 0x5a, 0x89 }, + { 0xdf, 0x32, 0x1a, 0x01, 0x84, 0xe5, 0xb8, 0x2c, 0x70, 0x6c, 0xeb, 0xd1, 0xf0, 0xb4, 0x9b, 0x32, 0xc8, 0xd0, 0x81, 0xc4, 0xea, 0xb2, 0x7c, 0x32, 0x1a, 0x02, 0x61, 0xf2, 0xd9, 0x4d, 0xe5, 0x85, + 0xad, 0xfc, 0xc6, 0x70, 0xee, 0x85, 0x77, 0x07, 0x9b, 0x5d, 0x5f, 0x88, 0xef, 0xb6, 0xd8, 0xdf, 0x2b, 0xa2, 0x4d, 0x90, 0x11, 0x2d, 0x38, 0x3f, 0xa8, 0x84, 0xf0, 0x76, 0xdd, 0x31, 0xd0, 0x09, + 0x00, 0xc0, 0x07, 0x10, 0xd8, 0x6e, 0x55, 0x83, 0x5a, 0xbc, 0xfa, 0x67, 0x80, 0x8f, 0xfa, 0x21, 0x3e, 0x56, 0x53, 0x5b, 0xbc, 0x9d, 0xff, 0x16, 0xd9, 0x57, 0xcf, 0x2b, 0x78, 0x06, 0x5a, 0x89 } }, + { { 0x25, 0x87, 0x1e, 0x6f, 0xe8, 0xd0, 0xde, 0x1d, 0xd5, 0xf2, 0xd3, 0x5b, 0xff, 0x9e, 0x67, 0x99, 0x60, 0xb4, 0x0e, 0xb7, 0x98, 0x1b, 0x2a, 0x3a, 0x9c, 0xec, 0xc1, 0xe1, 0x2e, 0x2b, 0xc0, 0x3e, + 0x3c, 0xfb, 0x64, 0x91, 0x72, 0xc6, 0x7e, 0x57, 0x47, 0x00, 0x97, 0xbf, 0x8e, 0x0e, 0xbf, 0xad, 0xd9, 0x28, 0x86, 0x7c, 0xfd, 0x41, 0x91, 0xae, 0x2d, 0xee, 0xc0, 0xb2, 0x32, 0x7d, 0x99, 0x7d }, + { 0x63, 0xc1, 0xf9, 0x61, 0x9c, 0x9e, 0x1a, 0xd7, 0xca, 0xa3, 0x71, 0xd6, 0x34, 0x3d, 0xa7, 0x08, 0x36, 0x0c, 0xec, 0x37, 0x35, 0x94, 0x1a, 0x45, 0xa9, 0xfa, 0xf2, 0xb5, 0x25, 0x92, 0xbf, 0xd1, + 0x1e, 0xca, 0xdd, 0x5a, 0x23, 0xad, 0x9e, 0x45, 0xc3, 0x66, 0xcb, 0x8f, 0xda, 0xa3, 0xd1, 0xe6, 0x27, 0x38, 0x11, 0x54, 0x67, 0x31, 0x03, 0x64, 0x35, 0xe0, 0x68, 0x0b, 0x93, 0xee, 0x81, 0x17 }, + { 0x8b, 0x01, 0xe9, 0x99, 0x54, 0x54, 0x73, 0x15, 0x0b, 0xac, 0x38, 0x7b, 0xe9, 0xe3, 0x17, 0x4f, 0x02, 0x3e, 0xe3, 0x8e, 0xda, 0x41, 0xa0, 0x9d, 0x10, 0xe0, 0xda, 0x11, 0xfe, 0xec, 0x2f, 0x42, + 0xe7, 0xc8, 0xb3, 0xde, 0x2f, 0x7b, 0xfd, 0xdf, 0x7c, 0x34, 0x3b, 0x5e, 0xac, 0x22, 0x8c, 0x99, 0x3d, 0xa1, 0xa9, 0xd9, 0x81, 0xb6, 0x51, 0xc8, 0xaf, 0x3e, 0x75, 0xed, 0x45, 0xcf, 0xf7, 0xb9 }, + { 0xaf, 0xe9, 0x9c, 0x16, 0x4a, 0x8f, 0x3b, 0x0f, 0xef, 0x71, 0x2f, 0xaa, 0x8d, 0x7d, 0xce, 0xed, 0xea, 0x31, 0x93, 0xaf, 0x2c, 0x75, 0xc6, 0xfa, 0xda, 0x3e, 0xa6, 0xea, 0x2a, 0x3e, 0x7b, 0x72, + 0xb6, 0xf8, 0xd7, 0x9a, 0x88, 0xcb, 0x0b, 0x81, 0x97, 0x24, 0x29, 0x3b, 0x11, 0x23, 0x69, 0xc2, 0xff, 0x98, 0x39, 0x25, 0x99, 0xae, 0xe1, 0x07, 0x3e, 0x97, 0xde, 0x10, 0x21, 0x23, 0x7a, 0x2d }, + { 0xbe, 0x2f, 0xb9, 0x4c, 0x41, 0x5a, 0x9a, 0xf6, 0xfb, 0xf8, 0x26, 0x9d, 0x81, 0x7f, 0x39, 0x91, 0xaf, 0x5b, 0xf1, 0xd7, 0x93, 0x0a, 0xdf, 0x18, 0x19, 0x4a, 0x80, 0x74, 0x14, 0x98, 0x2b, 0xf2, + 0x3b, 0x25, 0xc5, 0xe8, 0xfc, 0x07, 0x3f, 0x5d, 0xa1, 0x39, 0x27, 0x4e, 0x1c, 0xd2, 0x7a, 0xfe, 0x3e, 0x7b, 0x03, 0x35, 0x15, 0x9e, 0x35, 0x2b, 0xd0, 0xbe, 0x67, 0x48, 0x42, 0xdd, 0xa4, 0xdd }, + { 0xbd, 0xcd, 0xd7, 0xbf, 0xb1, 0x0a, 0xdb, 0x9f, 0x85, 0x42, 0xba, 0xf4, 0xc8, 0xff, 0xb0, 0xe1, 0x9a, 0x18, 0x6d, 0x1a, 0xe0, 0x37, 0xc1, 0xa2, 0xe1, 0x1c, 0x38, 0x55, 0x14, 0xbf, 0x64, 0x67, + 0x84, 0x47, 0xb6, 0x0a, 0xf6, 0x93, 0xf1, 0x10, 0xab, 0x09, 0xf0, 0x60, 0x84, 0xe2, 0x4e, 0x4b, 0x5e, 0xa2, 0xd2, 0xd1, 0x19, 0x22, 0xd7, 0xc4, 0x85, 0x13, 0x23, 0xa3, 0x6a, 0xb6, 0x75, 0x0f, + 0x43, 0xe6, 0xde, 0x7b, 0x67, 0x2a, 0x73, 0x77, 0x9e, 0xb4, 0x94, 0x6c, 0xc3, 0x9a, 0x67, 0x51, 0xcf, 0xe9, 0x47, 0x46, 0x0e, 0x3a, 0x12, 0x7d, 0x7c, 0x66, 0x73, 0x6c, 0xd5, 0x4a, 0x21, 0x4d }, + { 0x89, 0x7e, 0xd0, 0xbf, 0x2e, 0x9f, 0x0c, 0xff, 0x6e, 0x56, 0x25, 0x9b, 0x79, 0x99, 0x52, 0x27, 0xc2, 0x3a, 0xaa, 0xf0, 0x47, 0x6d, 0xed, 0x05, 0xa1, 0xeb, 0x9c, 0x92, 0x28, 0x7f, 0x1b, 0xc8, + 0x1c, 0x57, 0x76, 0xab, 0x05, 0xe3, 0xd3, 0xb7, 0xa3, 0xf5, 0xac, 0xa8, 0x21, 0x33, 0x7c, 0xb7, 0xe7, 0xc2, 0xd0, 0x25, 0x6f, 0xdf, 0x34, 0xd1, 0xb0, 0x34, 0x41, 0x46, 0x30, 0x9c, 0x76, 0x07, + 0x43, 0xe6, 0xde, 0x7b, 0x67, 0x2a, 0x73, 0x77, 0x9e, 0xb4, 0x94, 0x6c, 0xc3, 0x9a, 0x67, 0x51, 0xcf, 0xe9, 0x47, 0x46, 0x0e, 0x3a, 0x12, 0x7d, 0x7c, 0x66, 0x73, 0x6c, 0xd5, 0x4a, 0x21, 0x4d } } }; ////////////////////////////////////////////////////////////////////////////// static int testCrypto() { - static unsigned char buf1[16384]; - static unsigned char buf2[sizeof(buf1)], buf3[sizeof(buf1)]; - static char hexbuf[1024]; + static unsigned char buf1[16384]; + static unsigned char buf2[sizeof(buf1)], buf3[sizeof(buf1)]; + static char hexbuf[1024]; - for (int i = 0; i < 3; ++i) { - Utils::getSecureRandom(buf1, 64); - std::cout << "[crypto] getSecureRandom: " << Utils::hex(buf1, 64, hexbuf) << std::endl; - } + for (int i = 0; i < 3; ++i) { + Utils::getSecureRandom(buf1, 64); + std::cout << "[crypto] getSecureRandom: " << Utils::hex(buf1, 64, hexbuf) << std::endl; + } - std::cout << "[crypto] Testing Salsa20... "; - std::cout.flush(); - for (unsigned int i = 0; i < 4; ++i) { - for (unsigned int k = 0; k < sizeof(buf1); ++k) - buf1[k] = (unsigned char)rand(); - memset(buf2, 0, sizeof(buf2)); - memset(buf3, 0, sizeof(buf3)); - Salsa20 s20; - s20.init("12345678123456781234567812345678", "12345678"); - s20.crypt20(buf1, buf2, sizeof(buf1)); - s20.init("12345678123456781234567812345678", "12345678"); - s20.crypt20(buf2, buf3, sizeof(buf2)); - if (memcmp(buf1, buf3, sizeof(buf1))) { - std::cout << "FAIL (encrypt/decrypt test)" << std::endl; - return -1; - } - } - Salsa20 s20(s20TV0Key, s20TV0Iv); - memset(buf1, 0, sizeof(buf1)); - memset(buf2, 0, sizeof(buf2)); - s20.crypt20(buf1, buf2, 64); - if (memcmp(buf2, s20TV0Ks, 64)) { - std::cout << "FAIL (test vector 0)" << std::endl; - return -1; - } - s20.init(s2012TV0Key, s2012TV0Iv); - memset(buf1, 0, sizeof(buf1)); - memset(buf2, 0, sizeof(buf2)); - s20.crypt12(buf1, buf2, 64); - if (memcmp(buf2, s2012TV0Ks, 64)) { - std::cout << "FAIL (test vector 1)" << std::endl; - return -1; - } - std::cout << "PASS" << std::endl; + std::cout << "[crypto] Testing Salsa20... "; + std::cout.flush(); + for (unsigned int i = 0; i < 4; ++i) { + for (unsigned int k = 0; k < sizeof(buf1); ++k) + buf1[k] = (unsigned char)rand(); + memset(buf2, 0, sizeof(buf2)); + memset(buf3, 0, sizeof(buf3)); + Salsa20 s20; + s20.init("12345678123456781234567812345678", "12345678"); + s20.crypt20(buf1, buf2, sizeof(buf1)); + s20.init("12345678123456781234567812345678", "12345678"); + s20.crypt20(buf2, buf3, sizeof(buf2)); + if (memcmp(buf1, buf3, sizeof(buf1))) { + std::cout << "FAIL (encrypt/decrypt test)" << std::endl; + return -1; + } + } + Salsa20 s20(s20TV0Key, s20TV0Iv); + memset(buf1, 0, sizeof(buf1)); + memset(buf2, 0, sizeof(buf2)); + s20.crypt20(buf1, buf2, 64); + if (memcmp(buf2, s20TV0Ks, 64)) { + std::cout << "FAIL (test vector 0)" << std::endl; + return -1; + } + s20.init(s2012TV0Key, s2012TV0Iv); + memset(buf1, 0, sizeof(buf1)); + memset(buf2, 0, sizeof(buf2)); + s20.crypt12(buf1, buf2, 64); + if (memcmp(buf2, s2012TV0Ks, 64)) { + std::cout << "FAIL (test vector 1)" << std::endl; + return -1; + } + std::cout << "PASS" << std::endl; #ifdef ZT_SALSA20_SSE - std::cout << "[crypto] Salsa20 SSE: ENABLED" << std::endl; + std::cout << "[crypto] Salsa20 SSE: ENABLED" << std::endl; #else - std::cout << "[crypto] Salsa20 SSE: DISABLED" << std::endl; + std::cout << "[crypto] Salsa20 SSE: DISABLED" << std::endl; #endif - std::cout << "[crypto] Benchmarking Salsa20/12... "; - std::cout.flush(); - { - unsigned char* bb = (unsigned char*)::malloc(1234567); - for (unsigned int i = 0; i < 1234567; ++i) - bb[i] = (unsigned char)i; - Salsa20 s20(s20TV0Key, s20TV0Iv); - long double bytes = 0.0; - uint64_t start = OSUtils::now(); - for (unsigned int i = 0; i < 200; ++i) { - s20.crypt12(bb, bb, 1234567); - bytes += 1234567.0; - } - uint64_t end = OSUtils::now(); - SHA512(buf1, bb, 1234567); - std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1, 16, hexbuf) << ')' << std::endl; - ::free((void*)bb); - } + std::cout << "[crypto] Benchmarking Salsa20/12... "; + std::cout.flush(); + { + unsigned char* bb = (unsigned char*)::malloc(1234567); + for (unsigned int i = 0; i < 1234567; ++i) + bb[i] = (unsigned char)i; + Salsa20 s20(s20TV0Key, s20TV0Iv); + long double bytes = 0.0; + uint64_t start = OSUtils::now(); + for (unsigned int i = 0; i < 200; ++i) { + s20.crypt12(bb, bb, 1234567); + bytes += 1234567.0; + } + uint64_t end = OSUtils::now(); + SHA512(buf1, bb, 1234567); + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1, 16, hexbuf) << ')' << std::endl; + ::free((void*)bb); + } #if defined(ZT_USE_X64_ASM_SALSA2012) && defined(ZT_ARCH_X64) - std::cout << "[crypto] Benchmarking Salsa20/12 fast x64 ASM... "; - std::cout.flush(); - { - unsigned char* bb = (unsigned char*)::malloc(1234567); - double bytes = 0.0; - uint64_t start = OSUtils::now(); - for (unsigned int i = 0; i < 200; ++i) { - zt_salsa2012_amd64_xmm6(bb, 1234567, s20TV0Iv, s20TV0Key); - bytes += 1234567.0; - } - uint64_t end = OSUtils::now(); - std::cout << ((bytes / 1048576.0) / ((double)(end - start) / 1024.0)) << " MiB/second" << std::endl; - ::free((void*)bb); - } + std::cout << "[crypto] Benchmarking Salsa20/12 fast x64 ASM... "; + std::cout.flush(); + { + unsigned char* bb = (unsigned char*)::malloc(1234567); + double bytes = 0.0; + uint64_t start = OSUtils::now(); + for (unsigned int i = 0; i < 200; ++i) { + zt_salsa2012_amd64_xmm6(bb, 1234567, s20TV0Iv, s20TV0Key); + bytes += 1234567.0; + } + uint64_t end = OSUtils::now(); + std::cout << ((bytes / 1048576.0) / ((double)(end - start) / 1024.0)) << " MiB/second" << std::endl; + ::free((void*)bb); + } #endif #ifdef ZT_USE_ARM32_NEON_ASM_SALSA2012 - if (zt_arm_has_neon()) { - std::cout << "[crypto] Benchmarking Salsa20/12 fast arm32/neon ASM... "; - std::cout.flush(); - { - unsigned char* bb = (unsigned char*)::malloc(1234567); - double bytes = 0.0; - uint64_t start = OSUtils::now(); - for (unsigned int i = 0; i < 200; ++i) { - zt_salsa2012_armneon3_xor(bb, (const unsigned char*)0, 1234567, s20TV0Iv, s20TV0Key); - bytes += 1234567.0; - } - uint64_t end = OSUtils::now(); - std::cout << ((bytes / 1048576.0) / ((double)(end - start) / 1024.0)) << " MiB/second" << std::endl; - ::free((void*)bb); - } - } + if (zt_arm_has_neon()) { + std::cout << "[crypto] Benchmarking Salsa20/12 fast arm32/neon ASM... "; + std::cout.flush(); + { + unsigned char* bb = (unsigned char*)::malloc(1234567); + double bytes = 0.0; + uint64_t start = OSUtils::now(); + for (unsigned int i = 0; i < 200; ++i) { + zt_salsa2012_armneon3_xor(bb, (const unsigned char*)0, 1234567, s20TV0Iv, s20TV0Key); + bytes += 1234567.0; + } + uint64_t end = OSUtils::now(); + std::cout << ((bytes / 1048576.0) / ((double)(end - start) / 1024.0)) << " MiB/second" << std::endl; + ::free((void*)bb); + } + } #endif - std::cout << "[crypto] Benchmarking Salsa20/20... "; - std::cout.flush(); - { - unsigned char* bb = (unsigned char*)::malloc(1234567); - for (unsigned int i = 0; i < 1234567; ++i) - bb[i] = (unsigned char)i; - Salsa20 s20(s20TV0Key, s20TV0Iv); - long double bytes = 0.0; - uint64_t start = OSUtils::now(); - for (unsigned int i = 0; i < 200; ++i) { - s20.crypt20(bb, bb, 1234567); - bytes += 1234567.0; - } - uint64_t end = OSUtils::now(); - SHA512(buf1, bb, 1234567); - std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1, 16, hexbuf) << ')' << std::endl; - ::free((void*)bb); - } + std::cout << "[crypto] Benchmarking Salsa20/20... "; + std::cout.flush(); + { + unsigned char* bb = (unsigned char*)::malloc(1234567); + for (unsigned int i = 0; i < 1234567; ++i) + bb[i] = (unsigned char)i; + Salsa20 s20(s20TV0Key, s20TV0Iv); + long double bytes = 0.0; + uint64_t start = OSUtils::now(); + for (unsigned int i = 0; i < 200; ++i) { + s20.crypt20(bb, bb, 1234567); + bytes += 1234567.0; + } + uint64_t end = OSUtils::now(); + SHA512(buf1, bb, 1234567); + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1, 16, hexbuf) << ')' << std::endl; + ::free((void*)bb); + } - /* - { - AES k0,k1; - k0.init("00000000000000000000000000000000"); - k1.init("11111111111111111111111111111111"); - uint8_t test_pt[65536]; - uint8_t test_ct[65536]; - uint8_t test_aad[65536]; - uint8_t ct_hash[48]; - char hex_tmp[128]; - for(unsigned int i=0;i<65536;++i) { - test_pt[i] = (uint8_t)i; - test_aad[i] = (uint8_t)i; - } - AES::GMACSIVEncryptor enc(k0,k1); - for(unsigned int test_length=0;test_length<65536;test_length+=777) { - memset(test_ct, 0, test_length); - enc.init((uint64_t)test_length, test_ct); - enc.aad(test_aad, test_length); - enc.update1(test_pt, test_length); - enc.finish1(); - enc.update2(test_pt, test_length); - const void *tag = enc.finish2(); - SHA384(ct_hash, test_ct, test_length); - std::cout << "(" << test_length << ", \"" << Utils::hex(ct_hash, 48, hex_tmp) << "\", \"" << Utils::hex(tag, 16, hex_tmp) << "\")," <= 5000) - break; - } - std::cout << (((double)bytes / 1048576.0) / ((double)(end - start) / 1024.0)) << " MiB/second" << std::endl; - } + std::cout << "[crypto] Benchmarking AES-GMAC-SIV... "; + std::cout.flush(); + { + uint64_t end, start = OSUtils::now(); + uint64_t bytes = 0; + AES k0, k1; + k0.init(buf1); + k1.init(buf2); + AES::GMACSIVEncryptor enc(k0, k1); + for (;;) { + for (unsigned int i = 0; i < 10000; ++i) { + enc.init(i, buf2); + enc.update1(buf1, sizeof(buf1)); + enc.finish1(); + enc.update2(buf1, sizeof(buf1)); + enc.finish2(); + buf1[0] = buf2[0]; + bytes += sizeof(buf1); + } + end = OSUtils::now(); + if ((end - start) >= 5000) + break; + } + std::cout << (((double)bytes / 1048576.0) / ((double)(end - start) / 1024.0)) << " MiB/second" << std::endl; + } - std::cout << "[crypto] Testing SHA-512... "; - std::cout.flush(); - SHA512(buf1, sha512TV0Input, (unsigned int)strlen(sha512TV0Input)); - if (memcmp(buf1, sha512TV0Digest, 64)) { - std::cout << "FAIL" << std::endl; - return -1; - } - std::cout << "PASS" << std::endl; + std::cout << "[crypto] Testing SHA-512... "; + std::cout.flush(); + SHA512(buf1, sha512TV0Input, (unsigned int)strlen(sha512TV0Input)); + if (memcmp(buf1, sha512TV0Digest, 64)) { + std::cout << "FAIL" << std::endl; + return -1; + } + std::cout << "PASS" << std::endl; - std::cout << "[crypto] Testing Poly1305... "; - std::cout.flush(); - Poly1305::compute(buf1, poly1305TV0Input, sizeof(poly1305TV0Input), poly1305TV0Key); - if (memcmp(buf1, poly1305TV0Tag, 16)) { - std::cout << "FAIL (1)" << std::endl; - return -1; - } - Poly1305::compute(buf1, poly1305TV1Input, sizeof(poly1305TV1Input), poly1305TV1Key); - if (memcmp(buf1, poly1305TV1Tag, 16)) { - std::cout << "FAIL (2)" << std::endl; - return -1; - } - std::cout << "PASS" << std::endl; + std::cout << "[crypto] Testing Poly1305... "; + std::cout.flush(); + Poly1305::compute(buf1, poly1305TV0Input, sizeof(poly1305TV0Input), poly1305TV0Key); + if (memcmp(buf1, poly1305TV0Tag, 16)) { + std::cout << "FAIL (1)" << std::endl; + return -1; + } + Poly1305::compute(buf1, poly1305TV1Input, sizeof(poly1305TV1Input), poly1305TV1Key); + if (memcmp(buf1, poly1305TV1Tag, 16)) { + std::cout << "FAIL (2)" << std::endl; + return -1; + } + std::cout << "PASS" << std::endl; - std::cout << "[crypto] Benchmarking Poly1305... "; - std::cout.flush(); - { - unsigned char* bb = (unsigned char*)::malloc(1234567); - for (unsigned int i = 0; i < 1234567; ++i) - bb[i] = (unsigned char)i; - long double bytes = 0.0; - uint64_t start = OSUtils::now(); - for (unsigned int i = 0; i < 200; ++i) { - Poly1305::compute(buf1, bb, 1234567, poly1305TV0Key); - bytes += 1234567.0; - } - uint64_t end = OSUtils::now(); - std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1000.0)) << " MiB/second" << std::endl; - ::free((void*)bb); - } + std::cout << "[crypto] Benchmarking Poly1305... "; + std::cout.flush(); + { + unsigned char* bb = (unsigned char*)::malloc(1234567); + for (unsigned int i = 0; i < 1234567; ++i) + bb[i] = (unsigned char)i; + long double bytes = 0.0; + uint64_t start = OSUtils::now(); + for (unsigned int i = 0; i < 200; ++i) { + Poly1305::compute(buf1, bb, 1234567, poly1305TV0Key); + bytes += 1234567.0; + } + uint64_t end = OSUtils::now(); + std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1000.0)) << " MiB/second" << std::endl; + ::free((void*)bb); + } - /* - for(unsigned int d=8;d<=10;++d) { - for(int k=0;k<8;++k) { - std::cout << "[crypto] computeSalsa2012Sha512ProofOfWork(" << d << ",\"foobarbaz\",9) == "; std::cout.flush(); - unsigned char result[16]; - uint64_t start = OSUtils::now(); - IncomingPacket::computeSalsa2012Sha512ProofOfWork(d,"foobarbaz",9,result); - uint64_t end = OSUtils::now(); - std::cout << Utils::hex(result,16) << " -- valid: " << IncomingPacket::testSalsa2012Sha512ProofOfWorkResult(d,"foobarbaz",9,result) << ", " << (end - start) << "ms" << std::endl; - } - } - */ + /* + for(unsigned int d=8;d<=10;++d) { + for(int k=0;k<8;++k) { + std::cout << "[crypto] computeSalsa2012Sha512ProofOfWork(" << d << ",\"foobarbaz\",9) == "; std::cout.flush(); + unsigned char result[16]; + uint64_t start = OSUtils::now(); + IncomingPacket::computeSalsa2012Sha512ProofOfWork(d,"foobarbaz",9,result); + uint64_t end = OSUtils::now(); + std::cout << Utils::hex(result,16) << " -- valid: " << IncomingPacket::testSalsa2012Sha512ProofOfWorkResult(d,"foobarbaz",9,result) << ", " << (end - start) << "ms" << std::endl; + } + } + */ - std::cout << "[crypto] Testing C25519 and Ed25519 against test vectors... "; - std::cout.flush(); - for (int k = 0; k < ZT_NUM_C25519_TEST_VECTORS; ++k) { - ECC::Pair p1, p2; - memcpy(p1.pub.data, C25519_TEST_VECTORS[k].pub1, ZT_ECC_PUBLIC_KEY_SET_LEN); - memcpy(p1.priv.data, C25519_TEST_VECTORS[k].priv1, ZT_ECC_PRIVATE_KEY_SET_LEN); - memcpy(p2.pub.data, C25519_TEST_VECTORS[k].pub2, ZT_ECC_PUBLIC_KEY_SET_LEN); - memcpy(p2.priv.data, C25519_TEST_VECTORS[k].priv2, ZT_ECC_PRIVATE_KEY_SET_LEN); - ECC::agree(p1, p2.pub, buf1, 64); - ECC::agree(p2, p1.pub, buf2, 64); - if (memcmp(buf1, buf2, 64)) { - std::cout << "FAIL (1)" << std::endl; - return -1; - } - if (memcmp(buf1, C25519_TEST_VECTORS[k].agreement, 64)) { - std::cout << "FAIL (2)" << std::endl; - return -1; - } - ECC::Signature sig1 = ECC::sign(p1, buf1, 64); - if (memcmp(sig1.data, C25519_TEST_VECTORS[k].agreementSignedBy1, 64)) { - std::cout << "FAIL (3)" << std::endl; - return -1; - } - ECC::Signature sig2 = ECC::sign(p2, buf1, 64); - if (memcmp(sig2.data, C25519_TEST_VECTORS[k].agreementSignedBy2, 64)) { - std::cout << "FAIL (4)" << std::endl; - return -1; - } - } - std::cout << "PASS" << std::endl; + std::cout << "[crypto] Testing C25519 and Ed25519 against test vectors... "; + std::cout.flush(); + for (int k = 0; k < ZT_NUM_C25519_TEST_VECTORS; ++k) { + ECC::Pair p1, p2; + memcpy(p1.pub.data, C25519_TEST_VECTORS[k].pub1, ZT_ECC_PUBLIC_KEY_SET_LEN); + memcpy(p1.priv.data, C25519_TEST_VECTORS[k].priv1, ZT_ECC_PRIVATE_KEY_SET_LEN); + memcpy(p2.pub.data, C25519_TEST_VECTORS[k].pub2, ZT_ECC_PUBLIC_KEY_SET_LEN); + memcpy(p2.priv.data, C25519_TEST_VECTORS[k].priv2, ZT_ECC_PRIVATE_KEY_SET_LEN); + ECC::agree(p1, p2.pub, buf1, 64); + ECC::agree(p2, p1.pub, buf2, 64); + if (memcmp(buf1, buf2, 64)) { + std::cout << "FAIL (1)" << std::endl; + return -1; + } + if (memcmp(buf1, C25519_TEST_VECTORS[k].agreement, 64)) { + std::cout << "FAIL (2)" << std::endl; + return -1; + } + ECC::Signature sig1 = ECC::sign(p1, buf1, 64); + if (memcmp(sig1.data, C25519_TEST_VECTORS[k].agreementSignedBy1, 64)) { + std::cout << "FAIL (3)" << std::endl; + return -1; + } + ECC::Signature sig2 = ECC::sign(p2, buf1, 64); + if (memcmp(sig2.data, C25519_TEST_VECTORS[k].agreementSignedBy2, 64)) { + std::cout << "FAIL (4)" << std::endl; + return -1; + } + } + std::cout << "PASS" << std::endl; - std::cout << "[crypto] Testing C25519 ECC key agreement... "; - std::cout.flush(); - for (unsigned int i = 0; i < 100; ++i) { - memset(buf1, 64, sizeof(buf1)); - memset(buf2, 64, sizeof(buf2)); - memset(buf3, 64, sizeof(buf3)); - ECC::Pair p1 = ECC::generate(); - ECC::Pair p2 = ECC::generate(); - ECC::Pair p3 = ECC::generate(); - ECC::agree(p1, p2.pub, buf1, 64); - ECC::agree(p2, p1.pub, buf2, 64); - ECC::agree(p3, p1.pub, buf3, 64); - // p1<>p2 should equal p2<>p1 - if (memcmp(buf1, buf2, 64)) { - std::cout << "FAIL (1)" << std::endl; - return -1; - } - // p2<>p1 should not equal p3<>p1 - if (! memcmp(buf2, buf3, 64)) { - std::cout << "FAIL (2)" << std::endl; - return -1; - } - } - std::cout << "PASS" << std::endl; + std::cout << "[crypto] Testing C25519 ECC key agreement... "; + std::cout.flush(); + for (unsigned int i = 0; i < 100; ++i) { + memset(buf1, 64, sizeof(buf1)); + memset(buf2, 64, sizeof(buf2)); + memset(buf3, 64, sizeof(buf3)); + ECC::Pair p1 = ECC::generate(); + ECC::Pair p2 = ECC::generate(); + ECC::Pair p3 = ECC::generate(); + ECC::agree(p1, p2.pub, buf1, 64); + ECC::agree(p2, p1.pub, buf2, 64); + ECC::agree(p3, p1.pub, buf3, 64); + // p1<>p2 should equal p2<>p1 + if (memcmp(buf1, buf2, 64)) { + std::cout << "FAIL (1)" << std::endl; + return -1; + } + // p2<>p1 should not equal p3<>p1 + if (! memcmp(buf2, buf3, 64)) { + std::cout << "FAIL (2)" << std::endl; + return -1; + } + } + std::cout << "PASS" << std::endl; - std::cout << "[crypto] Benchmarking C25519 ECC key agreement... "; - std::cout.flush(); - ECC::Pair bp[8]; - for (int k = 0; k < 8; ++k) - bp[k] = ECC::generate(); - uint64_t st = OSUtils::now(); - for (unsigned int k = 0; k < 50; ++k) { - ECC::agree(bp[~k & 7], bp[k & 7].pub, buf1, 64); - } - uint64_t et = OSUtils::now(); - std::cout << ((double)(et - st) / 50.0) << "ms per agreement." << std::endl; + std::cout << "[crypto] Benchmarking C25519 ECC key agreement... "; + std::cout.flush(); + ECC::Pair bp[8]; + for (int k = 0; k < 8; ++k) + bp[k] = ECC::generate(); + uint64_t st = OSUtils::now(); + for (unsigned int k = 0; k < 50; ++k) { + ECC::agree(bp[~k & 7], bp[k & 7].pub, buf1, 64); + } + uint64_t et = OSUtils::now(); + std::cout << ((double)(et - st) / 50.0) << "ms per agreement." << std::endl; - std::cout << "[crypto] Testing Ed25519 ECC signatures... "; - std::cout.flush(); - ECC::Pair didntSign = ECC::generate(); - for (unsigned int i = 0; i < 10; ++i) { - ECC::Pair p1 = ECC::generate(); - for (unsigned int k = 0; k < sizeof(buf1); ++k) - buf1[k] = (unsigned char)rand(); - ECC::Signature sig = ECC::sign(p1, buf1, sizeof(buf1)); - if (! ECC::verify(p1.pub, buf1, sizeof(buf1), sig)) { - std::cout << "FAIL (1)" << std::endl; - return -1; - } - ++buf1[17]; - if (ECC::verify(p1.pub, buf1, sizeof(buf1), sig)) { - std::cout << "FAIL (2)" << std::endl; - return -1; - } - --buf1[17]; - if (! ECC::verify(p1.pub, buf1, sizeof(buf1), sig)) { - std::cout << "FAIL (3)" << std::endl; - return -1; - } - if (ECC::verify(didntSign.pub, buf1, sizeof(buf1), sig)) { - std::cout << "FAIL (2)" << std::endl; - return -1; - } - for (unsigned int k = 0; k < 64; ++k) { - ECC::Signature sig2(sig); - sig2.data[rand() % ZT_ECC_SIGNATURE_LEN] ^= (unsigned char)(1 << (rand() & 7)); - if (ECC::verify(p1.pub, buf1, sizeof(buf1), sig2)) { - std::cout << "FAIL (5)" << std::endl; - return -1; - } - } - } - std::cout << "PASS" << std::endl; + std::cout << "[crypto] Testing Ed25519 ECC signatures... "; + std::cout.flush(); + ECC::Pair didntSign = ECC::generate(); + for (unsigned int i = 0; i < 10; ++i) { + ECC::Pair p1 = ECC::generate(); + for (unsigned int k = 0; k < sizeof(buf1); ++k) + buf1[k] = (unsigned char)rand(); + ECC::Signature sig = ECC::sign(p1, buf1, sizeof(buf1)); + if (! ECC::verify(p1.pub, buf1, sizeof(buf1), sig)) { + std::cout << "FAIL (1)" << std::endl; + return -1; + } + ++buf1[17]; + if (ECC::verify(p1.pub, buf1, sizeof(buf1), sig)) { + std::cout << "FAIL (2)" << std::endl; + return -1; + } + --buf1[17]; + if (! ECC::verify(p1.pub, buf1, sizeof(buf1), sig)) { + std::cout << "FAIL (3)" << std::endl; + return -1; + } + if (ECC::verify(didntSign.pub, buf1, sizeof(buf1), sig)) { + std::cout << "FAIL (2)" << std::endl; + return -1; + } + for (unsigned int k = 0; k < 64; ++k) { + ECC::Signature sig2(sig); + sig2.data[rand() % ZT_ECC_SIGNATURE_LEN] ^= (unsigned char)(1 << (rand() & 7)); + if (ECC::verify(p1.pub, buf1, sizeof(buf1), sig2)) { + std::cout << "FAIL (5)" << std::endl; + return -1; + } + } + } + std::cout << "PASS" << std::endl; - std::cout << "[crypto] Benchmarking Ed25519 ECC signatures... "; - std::cout.flush(); - st = OSUtils::now(); - for (int k = 0; k < 1000; ++k) { - ECC::Signature sig; - ECC::sign(didntSign.priv, didntSign.pub, buf1, sizeof(buf1), sig.data); - } - et = OSUtils::now(); - std::cout << ((double)(et - st) / 50.0) << "ms per signature." << std::endl; + std::cout << "[crypto] Benchmarking Ed25519 ECC signatures... "; + std::cout.flush(); + st = OSUtils::now(); + for (int k = 0; k < 1000; ++k) { + ECC::Signature sig; + ECC::sign(didntSign.priv, didntSign.pub, buf1, sizeof(buf1), sig.data); + } + et = OSUtils::now(); + std::cout << ((double)(et - st) / 50.0) << "ms per signature." << std::endl; - return 0; + return 0; } static int testIdentity() { - Identity id; - Buffer<512> buf; - char buf2[1024]; + Identity id; + Buffer<512> buf; + char buf2[1024]; - std::cout << "[identity] Validate known-good identity... "; - std::cout.flush(); - if (! id.fromString(KNOWN_GOOD_IDENTITY)) { - std::cout << "FAIL (1)" << std::endl; - return -1; - } - const uint64_t vst = OSUtils::now(); - for (int k = 0; k < 10; ++k) { - if (! id.locallyValidate()) { - std::cout << "FAIL (2)" << std::endl; - return -1; - } - } - const uint64_t vet = OSUtils::now(); - std::cout << "PASS (" << ((double)(vet - vst) / 10.0) << "ms per validation)" << std::endl; + std::cout << "[identity] Validate known-good identity... "; + std::cout.flush(); + if (! id.fromString(KNOWN_GOOD_IDENTITY)) { + std::cout << "FAIL (1)" << std::endl; + return -1; + } + const uint64_t vst = OSUtils::now(); + for (int k = 0; k < 10; ++k) { + if (! id.locallyValidate()) { + std::cout << "FAIL (2)" << std::endl; + return -1; + } + } + const uint64_t vet = OSUtils::now(); + std::cout << "PASS (" << ((double)(vet - vst) / 10.0) << "ms per validation)" << std::endl; - std::cout << "[identity] Validate known-bad identity... "; - std::cout.flush(); - if (! id.fromString(KNOWN_BAD_IDENTITY)) { - std::cout << "FAIL (1)" << std::endl; - return -1; - } - if (id.locallyValidate()) { - std::cout << "FAIL (2)" << std::endl; - return -1; - } - std::cout << "PASS (i.e. it failed)" << std::endl; + std::cout << "[identity] Validate known-bad identity... "; + std::cout.flush(); + if (! id.fromString(KNOWN_BAD_IDENTITY)) { + std::cout << "FAIL (1)" << std::endl; + return -1; + } + if (id.locallyValidate()) { + std::cout << "FAIL (2)" << std::endl; + return -1; + } + std::cout << "PASS (i.e. it failed)" << std::endl; - for (unsigned int k = 0; k < 4; ++k) { - std::cout << "[identity] Generate identity... "; - std::cout.flush(); - uint64_t genstart = OSUtils::now(); - id.generate(); - uint64_t genend = OSUtils::now(); - std::cout << "(took " << (genend - genstart) << "ms): " << id.toString(true, buf2) << std::endl; - std::cout << "[identity] Locally validate identity: "; - if (id.locallyValidate()) { - std::cout << "PASS" << std::endl; - } - else { - std::cout << "FAIL" << std::endl; - return -1; - } - } + for (unsigned int k = 0; k < 4; ++k) { + std::cout << "[identity] Generate identity... "; + std::cout.flush(); + uint64_t genstart = OSUtils::now(); + id.generate(); + uint64_t genend = OSUtils::now(); + std::cout << "(took " << (genend - genstart) << "ms): " << id.toString(true, buf2) << std::endl; + std::cout << "[identity] Locally validate identity: "; + if (id.locallyValidate()) { + std::cout << "PASS" << std::endl; + } + else { + std::cout << "FAIL" << std::endl; + return -1; + } + } - { - Identity id2; - buf.clear(); - id.serialize(buf, true); - id2.deserialize(buf); - std::cout << "[identity] Serialize and deserialize (w/private): "; - if ((id == id2) && (id2.locallyValidate())) { - std::cout << "PASS" << std::endl; - } - else { - std::cout << "FAIL" << std::endl; - return -1; - } - } + { + Identity id2; + buf.clear(); + id.serialize(buf, true); + id2.deserialize(buf); + std::cout << "[identity] Serialize and deserialize (w/private): "; + if ((id == id2) && (id2.locallyValidate())) { + std::cout << "PASS" << std::endl; + } + else { + std::cout << "FAIL" << std::endl; + return -1; + } + } - { - Identity id2; - buf.clear(); - id.serialize(buf, false); - id2.deserialize(buf); - std::cout << "[identity] Serialize and deserialize (no private): "; - if ((id == id2) && (id2.locallyValidate())) { - std::cout << "PASS" << std::endl; - } - else { - std::cout << "FAIL" << std::endl; - return -1; - } - } + { + Identity id2; + buf.clear(); + id.serialize(buf, false); + id2.deserialize(buf); + std::cout << "[identity] Serialize and deserialize (no private): "; + if ((id == id2) && (id2.locallyValidate())) { + std::cout << "PASS" << std::endl; + } + else { + std::cout << "FAIL" << std::endl; + return -1; + } + } - { - Identity id2; - id2.fromString(id.toString(true, buf2)); - std::cout << "[identity] Serialize and deserialize (ASCII w/private): "; - if ((id == id2) && (id2.locallyValidate())) { - std::cout << "PASS" << std::endl; - } - else { - std::cout << "FAIL" << std::endl; - return -1; - } - } + { + Identity id2; + id2.fromString(id.toString(true, buf2)); + std::cout << "[identity] Serialize and deserialize (ASCII w/private): "; + if ((id == id2) && (id2.locallyValidate())) { + std::cout << "PASS" << std::endl; + } + else { + std::cout << "FAIL" << std::endl; + return -1; + } + } - { - Identity id2; - id2.fromString(id.toString(false, buf2)); - std::cout << "[identity] Serialize and deserialize (ASCII no private): "; - if ((id == id2) && (id2.locallyValidate())) { - std::cout << "PASS" << std::endl; - } - else { - std::cout << "FAIL" << std::endl; - return -1; - } - } + { + Identity id2; + id2.fromString(id.toString(false, buf2)); + std::cout << "[identity] Serialize and deserialize (ASCII no private): "; + if ((id == id2) && (id2.locallyValidate())) { + std::cout << "PASS" << std::endl; + } + else { + std::cout << "FAIL" << std::endl; + return -1; + } + } - return 0; + return 0; } static int testCertificate() { - char buf[4096]; + char buf[4096]; - Identity authority; - std::cout << "[certificate] Generating identity to act as authority... "; - std::cout.flush(); - authority.generate(); - std::cout << authority.address().toString(buf) << std::endl; + Identity authority; + std::cout << "[certificate] Generating identity to act as authority... "; + std::cout.flush(); + authority.generate(); + std::cout << authority.address().toString(buf) << std::endl; - Identity idA, idB; - std::cout << "[certificate] Generating identities A and B... "; - std::cout.flush(); - idA.generate(); - idB.generate(); - std::cout << idA.address().toString(buf) << ", " << idB.address().toString(buf) << std::endl; + Identity idA, idB; + std::cout << "[certificate] Generating identities A and B... "; + std::cout.flush(); + idA.generate(); + idB.generate(); + std::cout << idA.address().toString(buf) << ", " << idB.address().toString(buf) << std::endl; - std::cout << "[certificate] Generating certificates A and B..."; - CertificateOfMembership cA(10000, 100, 1, idA); - CertificateOfMembership cB(10099, 100, 1, idB); - std::cout << std::endl; + std::cout << "[certificate] Generating certificates A and B..."; + CertificateOfMembership cA(10000, 100, 1, idA); + CertificateOfMembership cB(10099, 100, 1, idB); + std::cout << std::endl; - std::cout << "[certificate] Signing certificates A and B with authority..."; - cA.sign(authority); - cB.sign(authority); - std::cout << std::endl; + std::cout << "[certificate] Signing certificates A and B with authority..."; + cA.sign(authority); + cB.sign(authority); + std::cout << std::endl; - // std::cout << "[certificate] A: " << cA.toString() << std::endl; - // std::cout << "[certificate] B: " << cB.toString() << std::endl; + // std::cout << "[certificate] A: " << cA.toString() << std::endl; + // std::cout << "[certificate] B: " << cB.toString() << std::endl; - std::cout << "[certificate] A agrees with B and B with A... "; - if (cA.agreesWith(cB, idB)) - std::cout << "yes, "; - else { - std::cout << "FAIL" << std::endl; - return -1; - } - if (cB.agreesWith(cA, idA)) - std::cout << "yes." << std::endl; - else { - std::cout << "FAIL" << std::endl; - return -1; - } + std::cout << "[certificate] A agrees with B and B with A... "; + if (cA.agreesWith(cB, idB)) + std::cout << "yes, "; + else { + std::cout << "FAIL" << std::endl; + return -1; + } + if (cB.agreesWith(cA, idA)) + std::cout << "yes." << std::endl; + else { + std::cout << "FAIL" << std::endl; + return -1; + } - std::cout << "[certificate] Generating two certificates that should not agree..."; - cA = CertificateOfMembership(10000, 100, 1, idA); - cB = CertificateOfMembership(10101, 100, 1, idB); - std::cout << std::endl; + std::cout << "[certificate] Generating two certificates that should not agree..."; + cA = CertificateOfMembership(10000, 100, 1, idA); + cB = CertificateOfMembership(10101, 100, 1, idB); + std::cout << std::endl; - std::cout << "[certificate] A agrees with B and B with A... "; - if (! cA.agreesWith(cB, idB)) - std::cout << "no, "; - else { - std::cout << "FAIL" << std::endl; - return -1; - } - if (! cB.agreesWith(cA, idA)) - std::cout << "no." << std::endl; - else { - std::cout << "FAIL" << std::endl; - return -1; - } + std::cout << "[certificate] A agrees with B and B with A... "; + if (! cA.agreesWith(cB, idB)) + std::cout << "no, "; + else { + std::cout << "FAIL" << std::endl; + return -1; + } + if (! cB.agreesWith(cA, idA)) + std::cout << "no." << std::endl; + else { + std::cout << "FAIL" << std::endl; + return -1; + } - return 0; + return 0; } static int testPacket() { - unsigned char salsaKey[32]; - Packet a, b; + unsigned char salsaKey[32]; + Packet a, b; - a.burn(); - b.burn(); + a.burn(); + b.burn(); - for (unsigned int i = 0; i < 32; ++i) - salsaKey[i] = (unsigned char)rand(); + for (unsigned int i = 0; i < 32; ++i) + salsaKey[i] = (unsigned char)rand(); - std::cout << "[packet] Testing Packet encoder/decoder... "; + std::cout << "[packet] Testing Packet encoder/decoder... "; - a.reset(Address(), Address(), Packet::VERB_HELLO); - for (int i = 0; i < 32; ++i) - a.append("supercalifragilisticexpealidocious", (unsigned int)strlen("supercalifragilisticexpealidocious")); + a.reset(Address(), Address(), Packet::VERB_HELLO); + for (int i = 0; i < 32; ++i) + a.append("supercalifragilisticexpealidocious", (unsigned int)strlen("supercalifragilisticexpealidocious")); - b = a; - if (a != b) { - std::cout << "FAIL (assign)" << std::endl; - return -1; - } + b = a; + if (a != b) { + std::cout << "FAIL (assign)" << std::endl; + return -1; + } - a.compress(); - unsigned int complen = a.size(); - a.uncompress(); + a.compress(); + unsigned int complen = a.size(); + a.uncompress(); - std::cout << "(compressed: " << complen << ", decompressed: " << a.size() << ") "; - if (a != b) { - std::cout << "FAIL (compression)" << std::endl; - return -1; - } + std::cout << "(compressed: " << complen << ", decompressed: " << a.size() << ") "; + if (a != b) { + std::cout << "FAIL (compression)" << std::endl; + return -1; + } - /* - a.armor(salsaKey, true, false, nullptr); - if (! a.dearmor(salsaKey, nullptr)) { - std::cout << "FAIL (encrypt-decrypt/verify)" << std::endl; - return -1; - } - */ + /* + a.armor(salsaKey, true, false, nullptr); + if (! a.dearmor(salsaKey, nullptr)) { + std::cout << "FAIL (encrypt-decrypt/verify)" << std::endl; + return -1; + } + */ - std::cout << "PASS" << std::endl; - return 0; + std::cout << "PASS" << std::endl; + return 0; } static int testOther() { - char buf[1024]; - char buf2[4096]; - char buf3[1024]; + char buf[1024]; + char buf2[4096]; + char buf3[1024]; - std::cout << "[other] Testing hex/unhex... "; - std::cout.flush(); - Utils::getSecureRandom(buf, (unsigned int)sizeof(buf)); - Utils::hex(buf, (unsigned int)sizeof(buf), buf2); - Utils::unhex(buf2, buf3, (unsigned int)sizeof(buf3)); - if (memcmp(buf, buf3, sizeof(buf)) == 0) { - std::cout << "PASS" << std::endl; - } - else { - std::cout << "FAIL!" << std::endl; - buf2[78] = 0; - std::cout << buf2 << std::endl; - Utils::hex(buf3, (unsigned int)sizeof(buf3), buf2); - buf2[78] = 0; - std::cout << buf2 << std::endl; - return -1; - } + std::cout << "[other] Testing hex/unhex... "; + std::cout.flush(); + Utils::getSecureRandom(buf, (unsigned int)sizeof(buf)); + Utils::hex(buf, (unsigned int)sizeof(buf), buf2); + Utils::unhex(buf2, buf3, (unsigned int)sizeof(buf3)); + if (memcmp(buf, buf3, sizeof(buf)) == 0) { + std::cout << "PASS" << std::endl; + } + else { + std::cout << "FAIL!" << std::endl; + buf2[78] = 0; + std::cout << buf2 << std::endl; + Utils::hex(buf3, (unsigned int)sizeof(buf3), buf2); + buf2[78] = 0; + std::cout << buf2 << std::endl; + return -1; + } - std::cout << "[other] Testing InetAddress encode/decode..."; - std::cout.flush(); - std::cout << " " << InetAddress("127.0.0.1/9993").toString(buf); - std::cout << " " << InetAddress("feed:dead:babe:dead:beef:f00d:1234:5678/12345").toString(buf); - std::cout << " " << InetAddress("0/9993").toString(buf); - std::cout << " " << InetAddress("").toString(buf); - std::cout << std::endl; + std::cout << "[other] Testing InetAddress encode/decode..."; + std::cout.flush(); + std::cout << " " << InetAddress("127.0.0.1/9993").toString(buf); + std::cout << " " << InetAddress("feed:dead:babe:dead:beef:f00d:1234:5678/12345").toString(buf); + std::cout << " " << InetAddress("0/9993").toString(buf); + std::cout << " " << InetAddress("").toString(buf); + std::cout << std::endl; #if 0 std::cout << "[other] Testing Hashtable... "; std::cout.flush(); @@ -1395,69 +1390,69 @@ static int testOther() std::cout << "PASS" << std::endl; #endif - std::cout << "[other] Testing/fuzzing Dictionary... "; - std::cout.flush(); - for (int k = 0; k < 1000; ++k) { - Dictionary<8194>* test = new Dictionary<8194>(); - char key[32][16]; - char value[32][128]; - memset(key, 0, sizeof(key)); - memset(value, 0, sizeof(value)); - for (unsigned int q = 0; q < 32; ++q) { - Utils::hex((uint32_t)((rand() % 1000) + (q * 1000)), key[q]); - int r = rand() % 128; - for (int x = 0; x < r; ++x) - value[q][x] = ("0123456789\0\t\r\n= ")[rand() % 16]; - value[q][r] = (char)0; - test->add(key[q], value[q], r); - } - for (unsigned int q = 0; q < 1024; ++q) { - int r = rand() % 32; - char tmp[128]; - if (test->get(key[r], tmp, sizeof(tmp)) >= 0) { - if (strcmp(value[r], tmp)) { - std::cout << "FAILED (invalid value '" << value[r] << "' != '" << tmp << "')!" << std::endl; - return -1; - } - } - else { - std::cout << "FAILED (can't find key '" << key[r] << "')!" << std::endl; - return -1; - } - } - delete test; - } - int foo = 0; - volatile int* volatile bar = &foo; // force compiler not to optimize out test.get() below - for (int k = 0; k < 200; ++k) { - int r = rand() % 8194; - unsigned char* tmp = new unsigned char[8194]; - for (int q = 0; q < r; ++q) - tmp[q] = (unsigned char)((rand() % 254) + 1); // don't put nulls since those will always just terminate scan - tmp[r] = (r % 32) ? (char)(rand() & 0xff) : (char)0; // every 32nd iteration don't terminate the string maybe... - Dictionary<8194>* test = new Dictionary<8194>((const char*)tmp); - for (unsigned int q = 0; q < 100; ++q) { - char tmp[128]; - for (unsigned int x = 0; x < 128; ++x) - tmp[x] = (char)(rand() & 0xff); - tmp[127] = (char)0; - char value[8194]; - *bar += test->get(tmp, value, sizeof(value)); - } - delete test; - delete[] tmp; - } - std::cout << "PASS (junk value to prevent optimization-out of test: " << foo << ")" << std::endl; + std::cout << "[other] Testing/fuzzing Dictionary... "; + std::cout.flush(); + for (int k = 0; k < 1000; ++k) { + Dictionary<8194>* test = new Dictionary<8194>(); + char key[32][16]; + char value[32][128]; + memset(key, 0, sizeof(key)); + memset(value, 0, sizeof(value)); + for (unsigned int q = 0; q < 32; ++q) { + Utils::hex((uint32_t)((rand() % 1000) + (q * 1000)), key[q]); + int r = rand() % 128; + for (int x = 0; x < r; ++x) + value[q][x] = ("0123456789\0\t\r\n= ")[rand() % 16]; + value[q][r] = (char)0; + test->add(key[q], value[q], r); + } + for (unsigned int q = 0; q < 1024; ++q) { + int r = rand() % 32; + char tmp[128]; + if (test->get(key[r], tmp, sizeof(tmp)) >= 0) { + if (strcmp(value[r], tmp)) { + std::cout << "FAILED (invalid value '" << value[r] << "' != '" << tmp << "')!" << std::endl; + return -1; + } + } + else { + std::cout << "FAILED (can't find key '" << key[r] << "')!" << std::endl; + return -1; + } + } + delete test; + } + int foo = 0; + volatile int* volatile bar = &foo; // force compiler not to optimize out test.get() below + for (int k = 0; k < 200; ++k) { + int r = rand() % 8194; + unsigned char* tmp = new unsigned char[8194]; + for (int q = 0; q < r; ++q) + tmp[q] = (unsigned char)((rand() % 254) + 1); // don't put nulls since those will always just terminate scan + tmp[r] = (r % 32) ? (char)(rand() & 0xff) : (char)0; // every 32nd iteration don't terminate the string maybe... + Dictionary<8194>* test = new Dictionary<8194>((const char*)tmp); + for (unsigned int q = 0; q < 100; ++q) { + char tmp[128]; + for (unsigned int x = 0; x < 128; ++x) + tmp[x] = (char)(rand() & 0xff); + tmp[127] = (char)0; + char value[8194]; + *bar += test->get(tmp, value, sizeof(value)); + } + delete test; + delete[] tmp; + } + std::cout << "PASS (junk value to prevent optimization-out of test: " << foo << ")" << std::endl; - return 0; + return 0; } -#define ZT_TEST_PHY_NUM_UDP_PACKETS 10000 -#define ZT_TEST_PHY_UDP_PACKET_SIZE 1000 -#define ZT_TEST_PHY_NUM_VALID_TCP_CONNECTS 10 +#define ZT_TEST_PHY_NUM_UDP_PACKETS 10000 +#define ZT_TEST_PHY_UDP_PACKET_SIZE 1000 +#define ZT_TEST_PHY_NUM_VALID_TCP_CONNECTS 10 #define ZT_TEST_PHY_NUM_INVALID_TCP_CONNECTS 2 -#define ZT_TEST_PHY_TCP_MESSAGE_SIZE 1000000 -#define ZT_TEST_PHY_TIMEOUT_MS 20000 +#define ZT_TEST_PHY_TCP_MESSAGE_SIZE 1000000 +#define ZT_TEST_PHY_TIMEOUT_MS 20000 static unsigned long phyTestUdpPacketCount = 0; static unsigned long phyTestTcpByteCount = 0; static unsigned long phyTestTcpConnectSuccessCount = 0; @@ -1466,153 +1461,153 @@ static unsigned long phyTestTcpAcceptCount = 0; struct TestPhyHandlers; static Phy* testPhyInstance = (Phy*)0; struct TestPhyHandlers { - inline void phyOnDatagram(PhySocket* sock, void** uptr, const struct sockaddr* localAddr, const struct sockaddr* from, void* data, unsigned long len) - { - ++phyTestUdpPacketCount; - } + inline void phyOnDatagram(PhySocket* sock, void** uptr, const struct sockaddr* localAddr, const struct sockaddr* from, void* data, unsigned long len) + { + ++phyTestUdpPacketCount; + } - inline void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success) - { - if (success) { - ++phyTestTcpConnectSuccessCount; - } - else { - ++phyTestTcpConnectFailCount; - } - } + inline void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success) + { + if (success) { + ++phyTestTcpConnectSuccessCount; + } + else { + ++phyTestTcpConnectFailCount; + } + } - inline void phyOnTcpAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN, const struct sockaddr* from) - { - ++phyTestTcpAcceptCount; - *uptrN = new std::string(ZT_TEST_PHY_TCP_MESSAGE_SIZE, (char)0xff); - testPhyInstance->setNotifyWritable(sockN, true); - } + inline void phyOnTcpAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN, const struct sockaddr* from) + { + ++phyTestTcpAcceptCount; + *uptrN = new std::string(ZT_TEST_PHY_TCP_MESSAGE_SIZE, (char)0xff); + testPhyInstance->setNotifyWritable(sockN, true); + } - inline void phyOnTcpClose(PhySocket* sock, void** uptr) - { - delete (std::string*)*uptr; // delete testMessage if any - } + inline void phyOnTcpClose(PhySocket* sock, void** uptr) + { + delete (std::string*)*uptr; // delete testMessage if any + } - inline void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len) - { - phyTestTcpByteCount += len; - } + inline void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len) + { + phyTestTcpByteCount += len; + } - inline void phyOnTcpWritable(PhySocket* sock, void** uptr) - { - std::string* testMessage = (std::string*)*uptr; - if ((testMessage) && (testMessage->length() > 0)) { - long sent = testPhyInstance->streamSend(sock, (const void*)testMessage->data(), (unsigned long)testMessage->length(), true); - if (sent > 0) - testMessage->erase(0, sent); - } - if ((! testMessage) || (! testMessage->length())) { - testPhyInstance->close(sock, true); - } - } + inline void phyOnTcpWritable(PhySocket* sock, void** uptr) + { + std::string* testMessage = (std::string*)*uptr; + if ((testMessage) && (testMessage->length() > 0)) { + long sent = testPhyInstance->streamSend(sock, (const void*)testMessage->data(), (unsigned long)testMessage->length(), true); + if (sent > 0) + testMessage->erase(0, sent); + } + if ((! testMessage) || (! testMessage->length())) { + testPhyInstance->close(sock, true); + } + } #ifdef __UNIX_LIKE__ - inline void phyOnUnixAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN) - { - } - inline void phyOnUnixClose(PhySocket* sock, void** uptr) - { - } - inline void phyOnUnixData(PhySocket* sock, void** uptr, void* data, unsigned long len) - { - } - inline void phyOnUnixWritable(PhySocket* sock, void** uptr) - { - } -#endif // __UNIX_LIKE__ + inline void phyOnUnixAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN) + { + } + inline void phyOnUnixClose(PhySocket* sock, void** uptr) + { + } + inline void phyOnUnixData(PhySocket* sock, void** uptr, void* data, unsigned long len) + { + } + inline void phyOnUnixWritable(PhySocket* sock, void** uptr) + { + } +#endif // __UNIX_LIKE__ - inline void phyOnFileDescriptorActivity(PhySocket* sock, void** uptr, bool readable, bool writable) - { - } + inline void phyOnFileDescriptorActivity(PhySocket* sock, void** uptr, bool readable, bool writable) + { + } }; static int testPhy() { - char udpTestPayload[ZT_TEST_PHY_UDP_PACKET_SIZE]; - memset(udpTestPayload, 0xff, sizeof(udpTestPayload)); + char udpTestPayload[ZT_TEST_PHY_UDP_PACKET_SIZE]; + memset(udpTestPayload, 0xff, sizeof(udpTestPayload)); - struct sockaddr_in bindaddr; - memset(&bindaddr, 0, sizeof(bindaddr)); - bindaddr.sin_family = AF_INET; - bindaddr.sin_port = Utils::hton((uint16_t)60002); - bindaddr.sin_addr.s_addr = Utils::hton((uint32_t)0x7f000001); - struct sockaddr_in invalidAddr; - memset(&bindaddr, 0, sizeof(bindaddr)); - bindaddr.sin_family = AF_INET; - bindaddr.sin_port = Utils::hton((uint16_t)60004); - bindaddr.sin_addr.s_addr = Utils::hton((uint32_t)0x7f000001); + struct sockaddr_in bindaddr; + memset(&bindaddr, 0, sizeof(bindaddr)); + bindaddr.sin_family = AF_INET; + bindaddr.sin_port = Utils::hton((uint16_t)60002); + bindaddr.sin_addr.s_addr = Utils::hton((uint32_t)0x7f000001); + struct sockaddr_in invalidAddr; + memset(&bindaddr, 0, sizeof(bindaddr)); + bindaddr.sin_family = AF_INET; + bindaddr.sin_port = Utils::hton((uint16_t)60004); + bindaddr.sin_addr.s_addr = Utils::hton((uint32_t)0x7f000001); - std::cout << "[phy] Creating phy endpoint..." << std::endl; - TestPhyHandlers testPhyHandlers; - testPhyInstance = new Phy(&testPhyHandlers, false, true); + std::cout << "[phy] Creating phy endpoint..." << std::endl; + TestPhyHandlers testPhyHandlers; + testPhyInstance = new Phy(&testPhyHandlers, false, true); - std::cout << "[phy] Binding UDP listen socket to 127.0.0.1/60002... "; - PhySocket* udpListenSock = testPhyInstance->udpBind((const struct sockaddr*)&bindaddr); - if (! udpListenSock) { - std::cout << "FAILED." << std::endl; - return -1; - } - std::cout << "OK" << std::endl; + std::cout << "[phy] Binding UDP listen socket to 127.0.0.1/60002... "; + PhySocket* udpListenSock = testPhyInstance->udpBind((const struct sockaddr*)&bindaddr); + if (! udpListenSock) { + std::cout << "FAILED." << std::endl; + return -1; + } + std::cout << "OK" << std::endl; - std::cout << "[phy] Binding TCP listen socket to 127.0.0.1/60002... "; - PhySocket* tcpListenSock = testPhyInstance->tcpListen((const struct sockaddr*)&bindaddr); - if (! tcpListenSock) { - std::cout << "FAILED." << std::endl; - return -1; - } - std::cout << "OK" << std::endl; + std::cout << "[phy] Binding TCP listen socket to 127.0.0.1/60002... "; + PhySocket* tcpListenSock = testPhyInstance->tcpListen((const struct sockaddr*)&bindaddr); + if (! tcpListenSock) { + std::cout << "FAILED." << std::endl; + return -1; + } + std::cout << "OK" << std::endl; - unsigned long phyTestUdpPacketsSent = 0; - unsigned long phyTestTcpValidConnectionsAttempted = 0; - unsigned long phyTestTcpInvalidConnectionsAttempted = 0; + unsigned long phyTestUdpPacketsSent = 0; + unsigned long phyTestTcpValidConnectionsAttempted = 0; + unsigned long phyTestTcpInvalidConnectionsAttempted = 0; - std::cout << "[phy] Testing UDP send/receive... "; - std::cout.flush(); - uint64_t timeoutAt = OSUtils::now() + ZT_TEST_PHY_TIMEOUT_MS; - while ((OSUtils::now() < timeoutAt) && (phyTestUdpPacketCount < ZT_TEST_PHY_NUM_UDP_PACKETS)) { - if (phyTestUdpPacketsSent < ZT_TEST_PHY_NUM_UDP_PACKETS) { - if (! testPhyInstance->udpSend(udpListenSock, (const struct sockaddr*)&bindaddr, udpTestPayload, sizeof(udpTestPayload))) { - std::cout << "FAILED." << std::endl; - return -1; - } - else - ++phyTestUdpPacketsSent; - } - testPhyInstance->poll(100); - } - std::cout << "got " << phyTestUdpPacketCount << " packets, OK" << std::endl; + std::cout << "[phy] Testing UDP send/receive... "; + std::cout.flush(); + uint64_t timeoutAt = OSUtils::now() + ZT_TEST_PHY_TIMEOUT_MS; + while ((OSUtils::now() < timeoutAt) && (phyTestUdpPacketCount < ZT_TEST_PHY_NUM_UDP_PACKETS)) { + if (phyTestUdpPacketsSent < ZT_TEST_PHY_NUM_UDP_PACKETS) { + if (! testPhyInstance->udpSend(udpListenSock, (const struct sockaddr*)&bindaddr, udpTestPayload, sizeof(udpTestPayload))) { + std::cout << "FAILED." << std::endl; + return -1; + } + else + ++phyTestUdpPacketsSent; + } + testPhyInstance->poll(100); + } + std::cout << "got " << phyTestUdpPacketCount << " packets, OK" << std::endl; - std::cout << "[phy] Testing TCP... "; - std::cout.flush(); - timeoutAt = OSUtils::now() + ZT_TEST_PHY_TIMEOUT_MS; - while ((OSUtils::now() < timeoutAt) && (phyTestTcpByteCount < (ZT_TEST_PHY_NUM_VALID_TCP_CONNECTS * ZT_TEST_PHY_TCP_MESSAGE_SIZE))) { - if (phyTestTcpValidConnectionsAttempted < ZT_TEST_PHY_NUM_VALID_TCP_CONNECTS) { - ++phyTestTcpValidConnectionsAttempted; - bool connected = false; - if (! testPhyInstance->tcpConnect((const struct sockaddr*)&bindaddr, connected, (void*)0, true)) - ++phyTestTcpConnectFailCount; - } - if (phyTestTcpInvalidConnectionsAttempted < ZT_TEST_PHY_NUM_INVALID_TCP_CONNECTS) { - ++phyTestTcpInvalidConnectionsAttempted; - bool connected = false; - if (! testPhyInstance->tcpConnect((const struct sockaddr*)&invalidAddr, connected, (void*)0, true)) - ++phyTestTcpConnectFailCount; - } - testPhyInstance->poll(100); - } - if (phyTestTcpByteCount < (ZT_TEST_PHY_NUM_VALID_TCP_CONNECTS * ZT_TEST_PHY_TCP_MESSAGE_SIZE)) { - std::cout << "got " << phyTestTcpConnectSuccessCount << " connect successes, " << phyTestTcpConnectFailCount << " failures, and " << phyTestTcpByteCount << " bytes, FAILED." << std::endl; - return -1; - } - else { - std::cout << "got " << phyTestTcpConnectSuccessCount << " connect successes, " << phyTestTcpConnectFailCount << " failures, and " << phyTestTcpByteCount << " bytes, OK" << std::endl; - } + std::cout << "[phy] Testing TCP... "; + std::cout.flush(); + timeoutAt = OSUtils::now() + ZT_TEST_PHY_TIMEOUT_MS; + while ((OSUtils::now() < timeoutAt) && (phyTestTcpByteCount < (ZT_TEST_PHY_NUM_VALID_TCP_CONNECTS * ZT_TEST_PHY_TCP_MESSAGE_SIZE))) { + if (phyTestTcpValidConnectionsAttempted < ZT_TEST_PHY_NUM_VALID_TCP_CONNECTS) { + ++phyTestTcpValidConnectionsAttempted; + bool connected = false; + if (! testPhyInstance->tcpConnect((const struct sockaddr*)&bindaddr, connected, (void*)0, true)) + ++phyTestTcpConnectFailCount; + } + if (phyTestTcpInvalidConnectionsAttempted < ZT_TEST_PHY_NUM_INVALID_TCP_CONNECTS) { + ++phyTestTcpInvalidConnectionsAttempted; + bool connected = false; + if (! testPhyInstance->tcpConnect((const struct sockaddr*)&invalidAddr, connected, (void*)0, true)) + ++phyTestTcpConnectFailCount; + } + testPhyInstance->poll(100); + } + if (phyTestTcpByteCount < (ZT_TEST_PHY_NUM_VALID_TCP_CONNECTS * ZT_TEST_PHY_TCP_MESSAGE_SIZE)) { + std::cout << "got " << phyTestTcpConnectSuccessCount << " connect successes, " << phyTestTcpConnectFailCount << " failures, and " << phyTestTcpByteCount << " bytes, FAILED." << std::endl; + return -1; + } + else { + std::cout << "got " << phyTestTcpConnectSuccessCount << " connect successes, " << phyTestTcpConnectFailCount << " failures, and " << phyTestTcpByteCount << " bytes, OK" << std::endl; + } - return 0; + return 0; } #ifdef __WINDOWS__ @@ -1621,77 +1616,77 @@ int __cdecl _tmain(int argc, _TCHAR* argv[]) int main(int argc, char** argv) #endif { - int r = 0; + int r = 0; #ifdef __WINDOWS__ - WSADATA wsaData; - WSAStartup(MAKEWORD(2, 2), &wsaData); + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); #endif - // Code to generate the C25519 test vectors -- did this once and then - // put these up top so that we can ensure that every platform produces - // the same result. - /* - for(int k=0;k<32;++k) { - ECC::Pair p1 = ECC::generate(); - ECC::Pair p2 = ECC::generate(); - unsigned char agg[64]; - ECC::agree(p1,p2.pub,agg,64); - ECC::Signature sig1 = ECC::sign(p1,agg,64); - ECC::Signature sig2 = ECC::sign(p2,agg,64); - printf("{{"); - for(int i=0;i<64;++i) - printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)p1.pub.data[i]); - printf("},{"); - for(int i=0;i<64;++i) - printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)p1.priv.data[i]); - printf("},{"); - for(int i=0;i<64;++i) - printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)p2.pub.data[i]); - printf("},{"); - for(int i=0;i<64;++i) - printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)p2.priv.data[i]); - printf("},{"); - for(int i=0;i<64;++i) - printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)agg[i]); - printf("},{"); - for(int i=0;i<96;++i) - printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)sig1.data[i]); - printf("},{"); - for(int i=0;i<96;++i) - printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)sig2.data[i]); - printf("}}\n"); - } - exit(0); - */ + // Code to generate the C25519 test vectors -- did this once and then + // put these up top so that we can ensure that every platform produces + // the same result. + /* + for(int k=0;k<32;++k) { + ECC::Pair p1 = ECC::generate(); + ECC::Pair p2 = ECC::generate(); + unsigned char agg[64]; + ECC::agree(p1,p2.pub,agg,64); + ECC::Signature sig1 = ECC::sign(p1,agg,64); + ECC::Signature sig2 = ECC::sign(p2,agg,64); + printf("{{"); + for(int i=0;i<64;++i) + printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)p1.pub.data[i]); + printf("},{"); + for(int i=0;i<64;++i) + printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)p1.priv.data[i]); + printf("},{"); + for(int i=0;i<64;++i) + printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)p2.pub.data[i]); + printf("},{"); + for(int i=0;i<64;++i) + printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)p2.priv.data[i]); + printf("},{"); + for(int i=0;i<64;++i) + printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)agg[i]); + printf("},{"); + for(int i=0;i<96;++i) + printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)sig1.data[i]); + printf("},{"); + for(int i=0;i<96;++i) + printf("%s0x%.2x",((i > 0) ? "," : ""),(unsigned int)sig2.data[i]); + printf("}}\n"); + } + exit(0); + */ - std::cout << "[info] sizeof(void *) == " << sizeof(void*) << std::endl; - std::cout << "[info] OSUtils::now() == " << OSUtils::now() << std::endl; - std::cout << "[info] hardware concurrency == " << std::thread::hardware_concurrency() << std::endl; - std::cout << "[info] sizeof(NetworkConfig) == " << sizeof(ZeroTier::NetworkConfig) << std::endl; + std::cout << "[info] sizeof(void *) == " << sizeof(void*) << std::endl; + std::cout << "[info] OSUtils::now() == " << OSUtils::now() << std::endl; + std::cout << "[info] hardware concurrency == " << std::thread::hardware_concurrency() << std::endl; + std::cout << "[info] sizeof(NetworkConfig) == " << sizeof(ZeroTier::NetworkConfig) << std::endl; - srand((unsigned int)time(0)); + srand((unsigned int)time(0)); - ///* - r |= testOther(); - r |= testCrypto(); - r |= testPacket(); - r |= testIdentity(); - r |= testCertificate(); - r |= testPhy(); - //*/ + ///* + r |= testOther(); + r |= testCrypto(); + r |= testPacket(); + r |= testIdentity(); + r |= testCertificate(); + r |= testPhy(); + //*/ - if (r) - std::cout << std::endl << "SOMETHING FAILED!" << std::endl; + if (r) + std::cout << std::endl << "SOMETHING FAILED!" << std::endl; - /* + /* #ifdef ZT_USE_MINIUPNPC - std::cout << std::endl; - std::cout << "[portmapper] Starting port mapper and waiting forever... use CTRL+C to exit. (enable ZT_PORTMAPPER_TRACE in PortMapper.cpp for output)" << std::endl; - PortMapper mapper(12345,"ZeroTier/__selftest"); - Thread::sleep(0xffffffff); + std::cout << std::endl; + std::cout << "[portmapper] Starting port mapper and waiting forever... use CTRL+C to exit. (enable ZT_PORTMAPPER_TRACE in PortMapper.cpp for output)" << std::endl; + PortMapper mapper(12345,"ZeroTier/__selftest"); + Thread::sleep(0xffffffff); #endif - */ + */ - return r; + return r; } diff --git a/service/OneService.cpp b/service/OneService.cpp index a535a4895..aea790194 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1,22 +1,14 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #include -#include #include -#include #include -#include #include #include #include @@ -38,24 +30,17 @@ #include "../node/MAC.hpp" #include "../node/Mutex.hpp" #include "../node/Node.hpp" -#include "../node/PacketMultiplexer.hpp" #include "../node/Peer.hpp" -#include "../node/Poly1305.hpp" -#include "../node/SHA512.hpp" -#include "../node/Salsa20.hpp" #include "../node/Utils.hpp" #include "../node/World.hpp" #include "../osdep/Binder.hpp" #include "../osdep/BlockingQueue.hpp" -#include "../osdep/ExtOsdep.hpp" -#include "../osdep/Http.hpp" #include "../osdep/ManagedRoute.hpp" #include "../osdep/OSUtils.hpp" #include "../osdep/Phy.hpp" #include "../osdep/PortMapper.hpp" #include "../version.h" #include "OneService.hpp" -#include "SoftwareUpdater.hpp" #ifdef CMAKE_BUILD #include @@ -90,8 +75,8 @@ namespace sdkmetrics = opentelemetry::v1::sdk::metrics; namespace sdklogs = opentelemetry::v1::sdk::logs; namespace sdkresource = opentelemetry::v1::sdk::resource; #else -#include "opentelemetry/logs/logger.h" -#include "opentelemetry/metrics/provider.h" +// #include "opentelemetry/logs/logger.h" +// #include "opentelemetry/metrics/provider.h" #include "opentelemetry/trace/provider.h" #endif @@ -142,11 +127,9 @@ extern "C" { using json = nlohmann::json; -#include "../controller/EmbeddedNetworkController.hpp" -#ifdef ZT_CONTROLLER_USE_LIBPQ -#include "../controller/PostgreSQL.hpp" -#include "../controller/Redis.hpp" -#endif +#include "../nonfree/controller/EmbeddedNetworkController.hpp" +#include "../nonfree/controller/PostgreSQL.hpp" +#include "../nonfree/controller/Redis.hpp" #include "../osdep/EthernetTap.hpp" #ifdef __WINDOWS__ #include "../osdep/WindowsEthernetTap.hpp" @@ -290,7 +273,8 @@ std::string http_log(const httplib::Request& req, const httplib::Response& res) std::string query; for (auto it = req.params.begin(); it != req.params.end(); ++it) { const auto& x = *it; - snprintf(buf, sizeof(buf), "%c%s=%s", (it == req.params.begin()) ? '?' : '&', x.first.c_str(), x.second.c_str()); + snprintf( + buf, sizeof(buf), "%c%s=%s", (it == req.params.begin()) ? '?' : '&', x.first.c_str(), x.second.c_str()); query += buf; } snprintf(buf, sizeof(buf), "%s\n", query.c_str()); @@ -439,7 +423,8 @@ class NetworkState { assert(_config.centralAuthURL != nullptr); assert(_config.ssoProvider != nullptr); - _idc = rustybits::zeroidc_new(_config.issuerURL, _config.ssoClientID, _config.centralAuthURL, _config.ssoProvider, _webPort); + _idc = rustybits::zeroidc_new( + _config.issuerURL, _config.ssoClientID, _config.centralAuthURL, _config.ssoProvider, _webPort); if (_idc == nullptr) { fprintf(stderr, "idc is null\n"); @@ -526,9 +511,15 @@ namespace { static const InetAddress NULL_INET_ADDR; // Fake TLS hello for TCP tunnel outgoing connections (TUNNELED mode) -static const char ZT_TCP_TUNNEL_HELLO[9] = { - 0x17, 0x03, 0x03, 0x00, 0x04, (char)ZEROTIER_ONE_VERSION_MAJOR, (char)ZEROTIER_ONE_VERSION_MINOR, (char)((ZEROTIER_ONE_VERSION_REVISION >> 8) & 0xff), (char)(ZEROTIER_ONE_VERSION_REVISION & 0xff) -}; +static const char ZT_TCP_TUNNEL_HELLO[9] = { 0x17, + 0x03, + 0x03, + 0x00, + 0x04, + (char)ZEROTIER_ONE_VERSION_MAJOR, + (char)ZEROTIER_ONE_VERSION_MINOR, + (char)((ZEROTIER_ONE_VERSION_REVISION >> 8) & 0xff), + (char)(ZEROTIER_ONE_VERSION_REVISION & 0xff) }; static std::string _trimString(const std::string& s) { @@ -592,14 +583,9 @@ static void _networkToJson(nlohmann::json& nj, NetworkState& ns) nj["id"] = tmp; nj["nwid"] = tmp; OSUtils::ztsnprintf( - tmp, - sizeof(tmp), - "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", - (unsigned int)((ns.config().mac >> 40) & 0xff), - (unsigned int)((ns.config().mac >> 32) & 0xff), - (unsigned int)((ns.config().mac >> 24) & 0xff), - (unsigned int)((ns.config().mac >> 16) & 0xff), - (unsigned int)((ns.config().mac >> 8) & 0xff), + tmp, sizeof(tmp), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (unsigned int)((ns.config().mac >> 40) & 0xff), + (unsigned int)((ns.config().mac >> 32) & 0xff), (unsigned int)((ns.config().mac >> 24) & 0xff), + (unsigned int)((ns.config().mac >> 16) & 0xff), (unsigned int)((ns.config().mac >> 8) & 0xff), (unsigned int)(ns.config().mac & 0xff)); nj["mac"] = tmp; nj["name"] = ns.config().name; @@ -766,15 +752,76 @@ static void _moonToJson(nlohmann::json& mj, const World& world) class OneServiceImpl; -static int SnodeVirtualNetworkConfigFunction(ZT_Node* node, void* uptr, void* tptr, uint64_t nwid, void** nuptr, enum ZT_VirtualNetworkConfigOperation op, const ZT_VirtualNetworkConfig* nwconf); +static int SnodeVirtualNetworkConfigFunction( + ZT_Node* node, + void* uptr, + void* tptr, + uint64_t nwid, + void** nuptr, + enum ZT_VirtualNetworkConfigOperation op, + const ZT_VirtualNetworkConfig* nwconf); static void SnodeEventCallback(ZT_Node* node, void* uptr, void* tptr, enum ZT_Event event, const void* metaData); -static void SnodeStatePutFunction(ZT_Node* node, void* uptr, void* tptr, enum ZT_StateObjectType type, const uint64_t id[2], const void* data, int len); -static int SnodeStateGetFunction(ZT_Node* node, void* uptr, void* tptr, enum ZT_StateObjectType type, const uint64_t id[2], void* data, unsigned int maxlen); -static int SnodeWirePacketSendFunction(ZT_Node* node, void* uptr, void* tptr, int64_t localSocket, const struct sockaddr_storage* addr, const void* data, unsigned int len, unsigned int ttl); -static void SnodeVirtualNetworkFrameFunction(ZT_Node* node, void* uptr, void* tptr, uint64_t nwid, void** nuptr, uint64_t sourceMac, uint64_t destMac, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len); -static int SnodePathCheckFunction(ZT_Node* node, void* uptr, void* tptr, uint64_t ztaddr, int64_t localSocket, const struct sockaddr_storage* remoteAddr); -static int SnodePathLookupFunction(ZT_Node* node, void* uptr, void* tptr, uint64_t ztaddr, int family, struct sockaddr_storage* result); -static void StapFrameHandler(void* uptr, void* tptr, uint64_t nwid, const MAC& from, const MAC& to, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len); +static void SnodeStatePutFunction( + ZT_Node* node, + void* uptr, + void* tptr, + enum ZT_StateObjectType type, + const uint64_t id[2], + const void* data, + int len); +static int SnodeStateGetFunction( + ZT_Node* node, + void* uptr, + void* tptr, + enum ZT_StateObjectType type, + const uint64_t id[2], + void* data, + unsigned int maxlen); +static int SnodeWirePacketSendFunction( + ZT_Node* node, + void* uptr, + void* tptr, + int64_t localSocket, + const struct sockaddr_storage* addr, + const void* data, + unsigned int len, + unsigned int ttl); +static void SnodeVirtualNetworkFrameFunction( + ZT_Node* node, + void* uptr, + void* tptr, + uint64_t nwid, + void** nuptr, + uint64_t sourceMac, + uint64_t destMac, + unsigned int etherType, + unsigned int vlanId, + const void* data, + unsigned int len); +static int SnodePathCheckFunction( + ZT_Node* node, + void* uptr, + void* tptr, + uint64_t ztaddr, + int64_t localSocket, + const struct sockaddr_storage* remoteAddr); +static int SnodePathLookupFunction( + ZT_Node* node, + void* uptr, + void* tptr, + uint64_t ztaddr, + int family, + struct sockaddr_storage* result); +static void StapFrameHandler( + void* uptr, + void* tptr, + uint64_t nwid, + const MAC& from, + const MAC& to, + unsigned int etherType, + unsigned int vlanId, + const void* data, + unsigned int len); static int ShttpOnMessageBegin(http_parser* parser); static int ShttpOnUrl(http_parser* parser, const char* ptr, size_t length); @@ -790,9 +837,15 @@ static int ShttpOnBody(http_parser* parser, const char* ptr, size_t length); static int ShttpOnMessageComplete(http_parser* parser); #if (HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 1) -static const struct http_parser_settings HTTP_PARSER_SETTINGS = { ShttpOnMessageBegin, ShttpOnUrl, ShttpOnStatus, ShttpOnHeaderField, ShttpOnValue, ShttpOnHeadersComplete, ShttpOnBody, ShttpOnMessageComplete }; +static const struct http_parser_settings HTTP_PARSER_SETTINGS = { ShttpOnMessageBegin, ShttpOnUrl, + ShttpOnStatus, ShttpOnHeaderField, + ShttpOnValue, ShttpOnHeadersComplete, + ShttpOnBody, ShttpOnMessageComplete }; #else -static const struct http_parser_settings HTTP_PARSER_SETTINGS = { ShttpOnMessageBegin, ShttpOnUrl, ShttpOnHeaderField, ShttpOnValue, ShttpOnHeadersComplete, ShttpOnBody, ShttpOnMessageComplete }; +static const struct http_parser_settings HTTP_PARSER_SETTINGS = { ShttpOnMessageBegin, ShttpOnUrl, + ShttpOnHeaderField, ShttpOnValue, + ShttpOnHeadersComplete, ShttpOnBody, + ShttpOnMessageComplete }; #endif /** @@ -847,7 +900,6 @@ class OneServiceImpl : public OneService { EmbeddedNetworkController* _controller; Phy _phy; Node* _node; - SoftwareUpdater* _updater; bool _updateAutoApply; httplib::Server _controlPlane; @@ -967,7 +1019,6 @@ class OneServiceImpl : public OneService { , _controller((EmbeddedNetworkController*)0) , _phy(this, false, true) , _node((Node*)0) - , _updater((SoftwareUpdater*)0) , _updateAutoApply(false) , _controlPlane() , _controlPlaneV6() @@ -1072,28 +1123,39 @@ class OneServiceImpl : public OneService { void initTracing() { if (! _exporterEndpoint.empty() && _exporterSampleRate > 0.0) { - fprintf(stderr, "OpenTelemetry tracing enabled with endpoint %s and sample rate %.2f\n", _exporterEndpoint.c_str(), _exporterSampleRate); + fprintf( + stderr, "OpenTelemetry tracing enabled with endpoint %s and sample rate %.2f\n", + _exporterEndpoint.c_str(), _exporterSampleRate); // Set up OpenTelemetry exporter and tracer provider opentelemetry::v1::exporter::otlp::OtlpGrpcExporterOptions opts; opts.endpoint = _exporterEndpoint + "/v1/traces"; - auto exporter = std::unique_ptr(new opentelemetry::exporter::otlp::OtlpGrpcExporter(opts)); + auto exporter = std::unique_ptr( + new opentelemetry::exporter::otlp::OtlpGrpcExporter(opts)); sdktrace::BatchSpanProcessorOptions batch_options {}; batch_options.schedule_delay_millis = std::chrono::milliseconds(5000); // 5 seconds - auto processor = std::unique_ptr(new sdktrace::BatchSpanProcessor(std::move(exporter), batch_options)); + auto processor = std::unique_ptr( + new sdktrace::BatchSpanProcessor(std::move(exporter), batch_options)); auto processors = std::vector >(); processors.push_back(std::move(processor)); char buf[256]; auto versionString = std::stringstream(); - versionString << ZEROTIER_ONE_VERSION_MAJOR << "." << ZEROTIER_ONE_VERSION_MINOR << "." << ZEROTIER_ONE_VERSION_REVISION; - auto resource_attributes = sdkresource::ResourceAttributes { { "service.version", versionString.str() }, { "service.node_id", _node->identity().address().toString(buf) }, { "service.namespace", "com.zerotier.zerotier-one" } }; + versionString << ZEROTIER_ONE_VERSION_MAJOR << "." << ZEROTIER_ONE_VERSION_MINOR << "." + << ZEROTIER_ONE_VERSION_REVISION; + auto resource_attributes = + sdkresource::ResourceAttributes { { "service.version", versionString.str() }, + { "service.node_id", _node->identity().address().toString(buf) }, + { "service.namespace", "com.zerotier.zerotier-one" } }; auto resource = sdkresource::Resource::Create(resource_attributes); - auto sampler = std::unique_ptr(new sdktrace::TraceIdRatioBasedSampler(_exporterSampleRate)); - auto tracer_context = std::make_unique(std::move(processors), resource, std::move(sampler)); - _traceProvider = opentelemetry::nostd::shared_ptr(new sdktrace::TracerProvider(std::move(tracer_context))); + auto sampler = + std::unique_ptr(new sdktrace::TraceIdRatioBasedSampler(_exporterSampleRate)); + auto tracer_context = + std::make_unique(std::move(processors), resource, std::move(sampler)); + _traceProvider = opentelemetry::nostd::shared_ptr( + new sdktrace::TracerProvider(std::move(tracer_context))); sdktrace::Provider::SetTracerProvider(_traceProvider); } } @@ -1104,10 +1166,12 @@ class OneServiceImpl : public OneService { // Set up OpenTelemetry metrics exporter // opentelemetry::exporter::otlp::OtlpGrpcExporterOptions opts; // opts.endpoint = _exporterEndpoint + "/v1/metrics"; - // auto exporter = std::unique_ptr(new opentelemetry::exporter::otlp::OtlpGrpcExporter(opts)); - // auto processor = std::unique_ptr(new sdkmetrics::PeriodicExportingMetricReader(std::move(exporter))); - // auto meter_provider = opentelemetry::v1::nostd::shared_ptr(new sdkmetrics::MeterProvider(std::move(processor))); - // sdkmetrics::Provider::SetMeterProvider(meter_provider); + // auto exporter = std::unique_ptr(new + // opentelemetry::exporter::otlp::OtlpGrpcExporter(opts)); auto processor = + // std::unique_ptr(new + // sdkmetrics::PeriodicExportingMetricReader(std::move(exporter))); auto meter_provider = + // opentelemetry::v1::nostd::shared_ptr(new + // sdkmetrics::MeterProvider(std::move(processor))); sdkmetrics::Provider::SetMeterProvider(meter_provider); } } @@ -1117,9 +1181,12 @@ class OneServiceImpl : public OneService { // Set up OpenTelemetry logging exporter // opentelemetry::exporter::otlp::OtlpGrpcExporterOptions opts; // opts.endpoint = _exporterEndpoint + "/v1/logs"; - // auto exporter = std::unique_ptr(new opentelemetry::exporter::otlp::OtlpGrpcExporter(opts)); - // auto processor = std::unique_ptr(new opentelemetry::v1::sdk::logs::SimpleLogRecordProcessor(std::move(exporter))); - // auto logger_provider = opentelemetry::nostd::shared_ptr(new opentelemetry::v1::sdk::logs::LoggerProvider(std::move(processor))); + // auto exporter = std::unique_ptr(new + // opentelemetry::exporter::otlp::OtlpGrpcExporter(opts)); auto processor = + // std::unique_ptr(new + // opentelemetry::v1::sdk::logs::SimpleLogRecordProcessor(std::move(exporter))); auto logger_provider = + // opentelemetry::nostd::shared_ptr(new + // opentelemetry::v1::sdk::logs::LoggerProvider(std::move(processor))); // opentelemetry::logs::Provider::SetLoggerProvider(logger_provider); } } @@ -1139,7 +1206,8 @@ class OneServiceImpl : public OneService { if (! OSUtils::writeFile(authTokenPath.c_str(), _authToken)) { Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = "authtoken.secret could not be written (try running with -U to prevent dropping of privileges)"; + _fatalErrorMessage = "authtoken.secret could not be written (try running with -U to prevent " + "dropping of privileges)"; return _termReason; } else { @@ -1160,7 +1228,8 @@ class OneServiceImpl : public OneService { if (! OSUtils::writeFile(metricsTokenPath.c_str(), _metricsToken)) { Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = "metricstoken.secret could not be written (try running with -U to prevent dropping of privileges)"; + _fatalErrorMessage = "metricstoken.secret could not be written (try running with -U to prevent " + "dropping of privileges)"; return _termReason; } else { @@ -1181,7 +1250,11 @@ class OneServiceImpl : public OneService { cb.eventCallback = SnodeEventCallback; cb.pathCheckFunction = SnodePathCheckFunction; cb.pathLookupFunction = SnodePathLookupFunction; - _node = new Node(this, (void*)0, &cb, OSUtils::now()); + // These settings can get set later when local.conf is checked. + struct ZT_Node_Config config; + config.enableEncryptedHello = 0; + config.lowBandwidthMode = 0; + _node = new Node(this, (void*)0, &config, &cb, OSUtils::now()); } // local.conf @@ -1216,7 +1289,8 @@ class OneServiceImpl : public OneService { if (_ports[0] == 0) { Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; - _fatalErrorMessage = std::string("cannot bind to local control interface port ") + std::to_string(_configuredPort); + _fatalErrorMessage = + std::string("cannot bind to local control interface port ") + std::to_string(_configuredPort); return _termReason; } @@ -1258,7 +1332,8 @@ class OneServiceImpl : public OneService { if (_ports[2]) { char uniqueName[64]; - OSUtils::ztsnprintf(uniqueName, sizeof(uniqueName), "ZeroTier/%.10llx@%u", _node->address(), _ports[2]); + OSUtils::ztsnprintf( + uniqueName, sizeof(uniqueName), "ZeroTier/%.10llx@%u", _node->address(), _ports[2]); _portMapper = new PortMapper(_ports[2], uniqueName); } } @@ -1277,17 +1352,21 @@ class OneServiceImpl : public OneService { OSUtils::rmDashRf((_homePath + ZT_PATH_SEPARATOR_S "iddb.d").c_str()); // Network controller is now enabled by default for desktop and server - _controller = new EmbeddedNetworkController(_node, _homePath.c_str(), _controllerDbPath.c_str(), _ports[0], _rc); +#ifdef ZT_NONFREE_CONTROLLER + _controller = + new EmbeddedNetworkController(_node, _homePath.c_str(), _controllerDbPath.c_str(), _ports[0], _rc); if (! _ssoRedirectURL.empty()) { _controller->setSSORedirectURL(_ssoRedirectURL); } _node->setNetconfMaster((void*)_controller); +#endif startHTTPControlPlane(); // Join existing networks in networks.d { - std::vector networksDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "networks.d").c_str())); + std::vector networksDotD( + OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "networks.d").c_str())); for (std::vector::iterator f(networksDotD.begin()); f != networksDotD.end(); ++f) { std::size_t dot = f->find_last_of('.'); if ((dot == 16) && (f->substr(16) == ".conf")) @@ -1297,7 +1376,8 @@ class OneServiceImpl : public OneService { // Orbit existing moons in moons.d { - std::vector moonsDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "moons.d").c_str())); + std::vector moonsDotD( + OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "moons.d").c_str())); for (std::vector::iterator f(moonsDotD.begin()); f != moonsDotD.end(); ++f) { std::size_t dot = f->find_last_of('.'); if ((dot == 16) && (f->substr(16) == ".moon")) @@ -1311,7 +1391,6 @@ class OneServiceImpl : public OneService { _lastRestart = clockShouldBe; int64_t lastTapMulticastGroupCheck = 0; int64_t lastBindRefresh = 0; - int64_t lastUpdateCheck = clockShouldBe; int64_t lastCleanedPeersDb = 0; int64_t lastLocalConfFileCheck = OSUtils::now(); int64_t lastOnline = lastLocalConfFileCheck; @@ -1338,13 +1417,6 @@ class OneServiceImpl : public OneService { restarted = true; } - // Check for updates (if enabled) - if ((_updater) && ((now - lastUpdateCheck) > 10000)) { - lastUpdateCheck = now; - if (_updater->check(now) && _updateAutoApply) - _updater->apply(); - } - // Reload local.conf if anything changed recently if ((now - lastLocalConfFileCheck) >= ZT_LOCAL_CONF_FILE_CHECK_INTERVAL) { lastLocalConfFileCheck = now; @@ -1358,8 +1430,11 @@ class OneServiceImpl : public OneService { } } - // Refresh bindings in case device's interfaces have changed, and also sync routes to update any shadow routes (e.g. shadow default) - if (((now - lastBindRefresh) >= (_node->bondController()->inUse() ? ZT_BINDER_REFRESH_PERIOD / 4 : ZT_BINDER_REFRESH_PERIOD)) || restarted) { + // Refresh bindings in case device's interfaces have changed, and also sync routes to update any shadow + // routes (e.g. shadow default) + if (((now - lastBindRefresh) + >= (_node->bondController()->inUse() ? ZT_BINDER_REFRESH_PERIOD / 4 : ZT_BINDER_REFRESH_PERIOD)) + || restarted) { // If secondary port is not configured to a constant value and we've been offline for a while, // bind a new secondary port. This is a workaround for a "coma" issue caused by buggy NATs that stop // working on one port after a while. @@ -1395,7 +1470,8 @@ class OneServiceImpl : public OneService { #ifdef ZT_USE_MINIUPNPC if (_portMapper) { std::vector mappedAddresses(_portMapper->get()); - for (std::vector::const_iterator ext(mappedAddresses.begin()); ext != mappedAddresses.end(); ++ext) + for (std::vector::const_iterator ext(mappedAddresses.begin()); + ext != mappedAddresses.end(); ++ext) _node->addLocalInterfaceAddress(reinterpret_cast(&(*ext))); } #endif @@ -1421,28 +1497,42 @@ class OneServiceImpl : public OneService { } // Close TCP fallback tunnel if we have direct UDP - if (! _forceTcpRelay && (_tcpFallbackTunnel) && ((now - _lastDirectReceiveFromGlobal) < (ZT_TCP_FALLBACK_AFTER / 2))) { + if (! _forceTcpRelay && (_tcpFallbackTunnel) + && ((now - _lastDirectReceiveFromGlobal) < (ZT_TCP_FALLBACK_AFTER / 2))) { _phy.close(_tcpFallbackTunnel->sock); } // Sync multicast group memberships if ((now - lastTapMulticastGroupCheck) >= ZT_TAP_CHECK_MULTICAST_INTERVAL) { lastTapMulticastGroupCheck = now; - std::vector, std::vector > > > mgChanges; + std::vector< + std::pair, std::vector > > > + mgChanges; { Mutex::Lock _l(_nets_m); mgChanges.reserve(_nets.size() + 1); for (std::map::const_iterator n(_nets.begin()); n != _nets.end(); ++n) { if (n->second.tap()) { - mgChanges.push_back(std::pair, std::vector > >(n->first, std::pair, std::vector >())); - n->second.tap()->scanMulticastGroups(mgChanges.back().second.first, mgChanges.back().second.second); + mgChanges.push_back( + std::pair< + uint64_t, + std::pair, std::vector > >( + n->first, + std::pair, std::vector >())); + n->second.tap()->scanMulticastGroups( + mgChanges.back().second.first, mgChanges.back().second.second); } } } - for (std::vector, std::vector > > >::iterator c(mgChanges.begin()); c != mgChanges.end(); ++c) { - for (std::vector::iterator m(c->second.first.begin()); m != c->second.first.end(); ++m) + for (std::vector, std::vector > > >:: + iterator c(mgChanges.begin()); + c != mgChanges.end(); ++c) { + for (std::vector::iterator m(c->second.first.begin()); + m != c->second.first.end(); ++m) _node->multicastSubscribe((void*)0, c->first, m->mac().toInt(), m->adi()); - for (std::vector::iterator m(c->second.second.begin()); m != c->second.second.end(); ++m) + for (std::vector::iterator m(c->second.second.begin()); + m != c->second.second.end(); ++m) _node->multicastUnsubscribe(c->first, m->mac().toInt(), m->adi()); } } @@ -1450,7 +1540,9 @@ class OneServiceImpl : public OneService { // Clean peers.d periodically if ((now - lastCleanedPeersDb) >= 3600000) { lastCleanedPeersDb = now; - OSUtils::cleanDirectory((_homePath + ZT_PATH_SEPARATOR_S "peers.d").c_str(), now - 2592000000LL); // delete older than 30 days + OSUtils::cleanDirectory( + (_homePath + ZT_PATH_SEPARATOR_S "peers.d").c_str(), + now - 2592000000LL); // delete older than 30 days } const unsigned long delay = (dl > now) ? (unsigned long)(dl - now) : 500; @@ -1484,7 +1576,9 @@ class OneServiceImpl : public OneService { break; } case ZT_EXCEPTION_INVALID_IDENTITY: { - _fatalErrorMessage = "invalid identity loaded from disk. Please remove identity.public and identity.secret from " + _homePath + " and try again"; + _fatalErrorMessage = + "invalid identity loaded from disk. Please remove identity.public and identity.secret from " + + _homePath + " and try again"; break; } case ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE: { @@ -1528,8 +1622,6 @@ class OneServiceImpl : public OneService { _nets.clear(); } - delete _updater; - _updater = (SoftwareUpdater*)0; delete _node; _node = (Node*)0; @@ -1544,14 +1636,17 @@ class OneServiceImpl : public OneService { // LEGACY: support old "trustedpaths" flat file FILE* trustpaths = fopen((_homePath + ZT_PATH_SEPARATOR_S "trustedpaths").c_str(), "r"); if (trustpaths) { - fprintf(stderr, "WARNING: 'trustedpaths' flat file format is deprecated in favor of path definitions in local.conf" ZT_EOL_S); + fprintf( + stderr, "WARNING: 'trustedpaths' flat file format is deprecated in favor of path definitions in " + "local.conf" ZT_EOL_S); char buf[1024]; while (fgets(buf, sizeof(buf), trustpaths)) { int fno = 0; char* saveptr = (char*)0; uint64_t trustedPathId = 0; InetAddress trustedPathNetwork; - for (char* f = Utils::stok(buf, "=\r\n \t", &saveptr); (f); f = Utils::stok((char*)0, "=\r\n \t", &saveptr)) { + for (char* f = Utils::stok(buf, "=\r\n \t", &saveptr); (f); + f = Utils::stok((char*)0, "=\r\n \t", &saveptr)) { if (fno == 0) { trustedPathId = Utils::hexStrToU64(f); } @@ -1562,7 +1657,9 @@ class OneServiceImpl : public OneService { break; ++fno; } - if ((trustedPathId != 0) && ((trustedPathNetwork.ss_family == AF_INET) || (trustedPathNetwork.ss_family == AF_INET6)) && (trustedPathNetwork.netmaskBits() > 0)) { + if ((trustedPathId != 0) + && ((trustedPathNetwork.ss_family == AF_INET) || (trustedPathNetwork.ss_family == AF_INET6)) + && (trustedPathNetwork.netmaskBits() > 0)) { ppc[trustedPathNetwork].trustedPathId = trustedPathId; ppc[trustedPathNetwork].mtu = 0; // use default } @@ -1578,7 +1675,8 @@ class OneServiceImpl : public OneService { try { _localConfig = OSUtils::jsonParse(lcbuf); if (! _localConfig.is_object()) { - fprintf(stderr, "ERROR: unable to parse local.conf (root element is not a JSON object)" ZT_EOL_S); + fprintf( + stderr, "ERROR: unable to parse local.conf (root element is not a JSON object)" ZT_EOL_S); exit(1); } } @@ -1637,14 +1735,20 @@ class OneServiceImpl : public OneService { _exporterEndpoint = OSUtils::jsonString(otel["exporterEndpoint"], ""); _exporterSampleRate = OSUtils::jsonDouble(otel["exporterSampleRate"], 1.0f); if (_exporterEndpoint.empty()) { - fprintf(stderr, "WARNING: OpenTelemetry exporter endpoint is not set. Traces will not be exported." ZT_EOL_S); + fprintf( + stderr, + "WARNING: OpenTelemetry exporter endpoint is not set. Traces will not be exported." ZT_EOL_S); } if (_exporterSampleRate <= 0.0) { - fprintf(stderr, "WARNING: OpenTelemetry exporter sample rate is not set or invalid. Traces will not be exported." ZT_EOL_S); + fprintf( + stderr, "WARNING: OpenTelemetry exporter sample rate is not set or invalid. Traces will not be " + "exported." ZT_EOL_S); } } else { - fprintf(stderr, "WARNING: OpenTelemetry exporter settings are not set. Traces will not be exported." ZT_EOL_S); + fprintf( + stderr, + "WARNING: OpenTelemetry exporter settings are not set. Traces will not be exported." ZT_EOL_S); } #else fprintf(stderr, "WARNING: OpenTelemetry support is not enabled. Traces will not be exported." ZT_EOL_S); @@ -1667,7 +1771,8 @@ class OneServiceImpl : public OneService { // Set trusted paths if there are any if (! ppc.empty()) { for (std::map::iterator i(ppc.begin()); i != ppc.end(); ++i) - _node->setPhysicalPathConfiguration(reinterpret_cast(&(i->first)), &(i->second)); + _node->setPhysicalPathConfiguration( + reinterpret_cast(&(i->first)), &(i->second)); } } @@ -1738,7 +1843,8 @@ class OneServiceImpl : public OneService { virtual bool setNetworkSettings(const uint64_t nwid, const NetworkSettings& settings) { char nlcpath[4096]; - OSUtils::ztsnprintf(nlcpath, sizeof(nlcpath), "%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf", _networksPath.c_str(), nwid); + OSUtils::ztsnprintf( + nlcpath, sizeof(nlcpath), "%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf", _networksPath.c_str(), nwid); FILE* out = fopen(nlcpath, "w"); if (out) { fprintf(out, "allowManaged=%d\n", (int)settings.allowManaged); @@ -1797,20 +1903,27 @@ class OneServiceImpl : public OneService { if (_enableWebServer) { static std::string appUiPath = "/app"; static char appUiDir[16384]; - sprintf(appUiDir, "%s%s", _homePath.c_str(), appUiPath.c_str()); + snprintf(appUiDir, sizeof(appUiDir), "%s%s", _homePath.c_str(), appUiPath.c_str()); auto ret = _controlPlane.set_mount_point(appUiPath, appUiDir); _controlPlaneV6.set_mount_point(appUiPath, appUiDir); if (! ret) { - fprintf(stderr, "Mounting app directory failed. Creating it. Path: %s - Dir: %s\n", appUiPath.c_str(), appUiDir); + fprintf( + stderr, "Mounting app directory failed. Creating it. Path: %s - Dir: %s\n", appUiPath.c_str(), + appUiDir); if (! OSUtils::mkdir(appUiDir)) { - fprintf(stderr, "Could not create app directory either. Path: %s - Dir: %s\n", appUiPath.c_str(), appUiDir); + fprintf( + stderr, "Could not create app directory either. Path: %s - Dir: %s\n", appUiPath.c_str(), + appUiDir); } else { ret = _controlPlane.set_mount_point(appUiPath, appUiDir); _controlPlaneV6.set_mount_point(appUiPath, appUiDir); if (! ret) { - fprintf(stderr, "Really could not create and mount directory. Path: %s - Dir: %s\nWeb apps won't work.\n", appUiPath.c_str(), appUiDir); + fprintf( + stderr, + "Really could not create and mount directory. Path: %s - Dir: %s\nWeb apps won't work.\n", + appUiPath.c_str(), appUiDir); } } } @@ -1824,7 +1937,9 @@ class OneServiceImpl : public OneService { if (match.matched) { // fallback char indexHtmlPath[16384]; - sprintf(indexHtmlPath, "%s/%s/%s", appUiDir, match.str().c_str(), "index.html"); + snprintf( + indexHtmlPath, sizeof(indexHtmlPath), "%s/%s/%s", appUiDir, match.str().c_str(), + "index.html"); // fprintf(stderr, "fallback path %s\n", indexHtmlPath); std::string indexHtml; @@ -1848,7 +1963,9 @@ class OneServiceImpl : public OneService { // add .html std::string htmlFile; char htmlPath[16384]; - sprintf(htmlPath, "%s%s%s", appUiDir, (req.path).substr(appUiPath.length()).c_str(), ".html"); + snprintf( + htmlPath, sizeof(htmlPath), "%s%s%s", appUiDir, (req.path).substr(appUiPath.length()).c_str(), + ".html"); // fprintf(stderr, "path: %s\n", htmlPath); if (OSUtils::readFile(htmlPath, htmlFile)) { res.set_content(htmlFile.c_str(), "text/html"); @@ -2074,7 +2191,10 @@ class OneServiceImpl : public OneService { res.status = 400; return; } - res.status = _node->bondController()->setAllMtuByTuple(mtu, req.matches[2].str().c_str(), req.matches[3].str().c_str()) ? 200 : 400; + res.status = _node->bondController()->setAllMtuByTuple( + mtu, req.matches[2].str().c_str(), req.matches[3].str().c_str()) + ? 200 + : 400; if (res.status == 400) { setContent(req, res, "Unable to find specified link"); return; @@ -2148,7 +2268,9 @@ class OneServiceImpl : public OneService { out["versionMinor"] = ZEROTIER_ONE_VERSION_MINOR; out["versionRev"] = ZEROTIER_ONE_VERSION_REVISION; out["versionBuild"] = ZEROTIER_ONE_VERSION_BUILD; - OSUtils::ztsnprintf(tmp, sizeof(tmp), "%d.%d.%d", ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION); + OSUtils::ztsnprintf( + tmp, sizeof(tmp), "%d.%d.%d", ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, + ZEROTIER_ONE_VERSION_REVISION); out["version"] = tmp; out["clock"] = OSUtils::now(); @@ -2461,7 +2583,9 @@ class OneServiceImpl : public OneService { out["versionMinor"] = ZEROTIER_ONE_VERSION_MINOR; out["versionRev"] = ZEROTIER_ONE_VERSION_REVISION; out["versionBuild"] = ZEROTIER_ONE_VERSION_BUILD; - OSUtils::ztsnprintf(tmp, sizeof(tmp), "%d.%d.%d", ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION); + OSUtils::ztsnprintf( + tmp, sizeof(tmp), "%d.%d.%d", ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, + ZEROTIER_ONE_VERSION_REVISION); out["version"] = tmp; out["clock"] = OSUtils::now(); @@ -2470,7 +2594,8 @@ class OneServiceImpl : public OneService { out["config"] = _localConfig; } json& settings = out["config"]["settings"]; - settings["allowTcpFallbackRelay"] = OSUtils::jsonBool(settings["allowTcpFallbackRelay"], _allowTcpFallbackRelay); + settings["allowTcpFallbackRelay"] = + OSUtils::jsonBool(settings["allowTcpFallbackRelay"], _allowTcpFallbackRelay); settings["forceTcpRelay"] = OSUtils::jsonBool(settings["forceTcpRelay"], _forceTcpRelay); settings["primaryPort"] = OSUtils::jsonInt(settings["primaryPort"], (uint64_t)_primaryPort) & 0xffff; settings["secondaryPort"] = OSUtils::jsonInt(settings["secondaryPort"], (uint64_t)_ports[1]) & 0xffff; @@ -2499,10 +2624,6 @@ class OneServiceImpl : public OneService { settings["portMappingEnabled"] = OSUtils::jsonBool(settings["portMappingEnabled"], true); #else settings["portMappingEnabled"] = false; // not supported in build -#endif -#ifndef ZT_SDK - settings["softwareUpdate"] = OSUtils::jsonString(settings["softwareUpdate"], ZT_SOFTWARE_UPDATE_DEFAULT); - settings["softwareUpdateChannel"] = OSUtils::jsonString(settings["softwareUpdateChannel"], ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL); #endif const World planet(_node->planet()); out["planetWorldId"] = planet.id(); @@ -2605,32 +2726,35 @@ class OneServiceImpl : public OneService { _controlPlane.Get(metricsPath, metricsGet); _controlPlaneV6.Get(metricsPath, metricsGet); - auto exceptionHandler = [&, setContent](const httplib::Request& req, httplib::Response& res, std::exception_ptr ep) { - auto provider = opentelemetry::trace::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer("http_control_plane"); - auto span = tracer->StartSpan("http_control_plane::exceptionHandler"); - auto scope = tracer->WithActiveSpan(span); + auto exceptionHandler = + [&, setContent](const httplib::Request& req, httplib::Response& res, std::exception_ptr ep) { + auto provider = opentelemetry::trace::Provider::GetTracerProvider(); + auto tracer = provider->GetTracer("http_control_plane"); + auto span = tracer->StartSpan("http_control_plane::exceptionHandler"); + auto scope = tracer->WithActiveSpan(span); - char buf[1024]; - auto fmt = "{\"error\": %d, \"description\": \"%s\"}"; - try { - std::rethrow_exception(ep); - } - catch (std::exception& e) { - snprintf(buf, sizeof(buf), fmt, 500, e.what()); - } - catch (...) { - snprintf(buf, sizeof(buf), fmt, 500, "Unknown Exception"); - } - setContent(req, res, buf); - res.status = 500; - }; + char buf[1024]; + auto fmt = "{\"error\": %d, \"description\": \"%s\"}"; + try { + std::rethrow_exception(ep); + } + catch (std::exception& e) { + snprintf(buf, sizeof(buf), fmt, 500, e.what()); + } + catch (...) { + snprintf(buf, sizeof(buf), fmt, 500, "Unknown Exception"); + } + setContent(req, res, buf); + res.status = 500; + }; _controlPlane.set_exception_handler(exceptionHandler); _controlPlaneV6.set_exception_handler(exceptionHandler); +#ifdef ZT_NONFREE_CONTROLLER if (_controller) { _controller->configureHTTPControlPlane(_controlPlane, _controlPlaneV6, setContent); } +#endif #ifndef ZT_EXTOSDEP _controlPlane.set_pre_routing_handler(authCheck); @@ -2638,8 +2762,12 @@ class OneServiceImpl : public OneService { _controlPlaneV6.set_pre_routing_handler(authCheck); #if ZT_DEBUG == 1 - _controlPlane.set_logger([](const httplib::Request& req, const httplib::Response& res) { fprintf(stderr, "%s", http_log(req, res).c_str()); }); - _controlPlaneV6.set_logger([](const httplib::Request& req, const httplib::Response& res) { fprintf(stderr, "%s", http_log(req, res).c_str()); }); + _controlPlane.set_logger([](const httplib::Request& req, const httplib::Response& res) { + fprintf(stderr, "%s", http_log(req, res).c_str()); + }); + _controlPlaneV6.set_logger([](const httplib::Request& req, const httplib::Response& res) { + fprintf(stderr, "%s", http_log(req, res).c_str()); + }); #endif if (_primaryPort == 0) { fprintf(stderr, "unable to determine local control port"); @@ -2779,24 +2907,34 @@ class OneServiceImpl : public OneService { std::string defaultBondingPolicyStr(OSUtils::jsonString(settings["defaultBondingPolicy"], "")); int defaultBondingPolicy = _node->bondController()->getPolicyCodeByStr(defaultBondingPolicyStr); _node->bondController()->setBondingLayerDefaultPolicy(defaultBondingPolicy); - _node->bondController()->setBondingLayerDefaultPolicyStr(defaultBondingPolicyStr); // Used if custom policy + _node->bondController()->setBondingLayerDefaultPolicyStr( + defaultBondingPolicyStr); // Used if custom policy // Custom Policies json& customBondingPolicies = settings["policies"]; - for (json::iterator policyItr = customBondingPolicies.begin(); policyItr != customBondingPolicies.end(); ++policyItr) { + for (json::iterator policyItr = customBondingPolicies.begin(); policyItr != customBondingPolicies.end(); + ++policyItr) { // Custom Policy std::string customPolicyStr(policyItr.key()); json& customPolicy = policyItr.value(); std::string basePolicyStr(OSUtils::jsonString(customPolicy["basePolicy"], "")); if (basePolicyStr.empty()) { - fprintf(stderr, "error: no base policy was specified for custom policy (%s)\n", customPolicyStr.c_str()); + fprintf( + stderr, "error: no base policy was specified for custom policy (%s)\n", + customPolicyStr.c_str()); } int basePolicyCode = _node->bondController()->getPolicyCodeByStr(basePolicyStr); if (basePolicyCode == ZT_BOND_POLICY_NONE) { - fprintf(stderr, "error: custom policy (%s) is invalid, unknown base policy (%s).\n", customPolicyStr.c_str(), basePolicyStr.c_str()); + fprintf( + stderr, "error: custom policy (%s) is invalid, unknown base policy (%s).\n", + customPolicyStr.c_str(), basePolicyStr.c_str()); continue; } if (_node->bondController()->getPolicyCodeByStr(customPolicyStr) != ZT_BOND_POLICY_NONE) { - fprintf(stderr, "error: custom policy (%s) will be ignored, cannot use standard policy names for custom policies.\n", customPolicyStr.c_str()); + fprintf( + stderr, + "error: custom policy (%s) will be ignored, cannot use standard policy names for custom " + "policies.\n", + customPolicyStr.c_str()); continue; } // New bond, used as a copy template for new instances @@ -2819,7 +2957,8 @@ class OneServiceImpl : public OneService { // Bond-specific properties newTemplateBond->setUpDelay(OSUtils::jsonInt(customPolicy["upDelay"], -1)); newTemplateBond->setDownDelay(OSUtils::jsonInt(customPolicy["downDelay"], -1)); - newTemplateBond->setFailoverInterval(OSUtils::jsonInt(customPolicy["failoverInterval"], ZT_BOND_FAILOVER_DEFAULT_INTERVAL)); + newTemplateBond->setFailoverInterval( + OSUtils::jsonInt(customPolicy["failoverInterval"], ZT_BOND_FAILOVER_DEFAULT_INTERVAL)); newTemplateBond->setPacketsPerLink(OSUtils::jsonInt(customPolicy["packetsPerLink"], -1)); // Policy-Specific link set @@ -2851,7 +2990,9 @@ class OneServiceImpl : public OneService { failoverToStr = ""; enabled = false; } - _node->bondController()->addCustomLink(customPolicyStr, new Link(linkNameStr, ipvPref, mtu, capacity, enabled, linkMode, failoverToStr)); + _node->bondController()->addCustomLink( + customPolicyStr, + new Link(linkNameStr, ipvPref, mtu, capacity, enabled, linkMode, failoverToStr)); } // Check for new field name first, fall back to legacy field name for backward compatibility std::string linkSelectMethodStr; @@ -2861,7 +3002,11 @@ class OneServiceImpl : public OneService { else { linkSelectMethodStr = OSUtils::jsonString(customPolicy["activeReselect"], "always"); if (customPolicy.contains("activeReselect")) { - fprintf(stderr, "warning: 'activeReselect' is deprecated, please use 'linkSelectMethod' instead in policy '%s'\n", customPolicyStr.c_str()); + fprintf( + stderr, + "warning: 'activeReselect' is deprecated, please use 'linkSelectMethod' instead in policy " + "'%s'\n", + customPolicyStr.c_str()); } } @@ -2878,10 +3023,13 @@ class OneServiceImpl : public OneService { newTemplateBond->setLinkSelectMethod(ZT_BOND_RESELECTION_POLICY_OPTIMIZE); } if (newTemplateBond->getLinkSelectMethod() < 0 || newTemplateBond->getLinkSelectMethod() > 3) { - fprintf(stderr, "warning: invalid value (%s) for linkSelectMethod, assuming mode: always\n", linkSelectMethodStr.c_str()); + fprintf( + stderr, "warning: invalid value (%s) for linkSelectMethod, assuming mode: always\n", + linkSelectMethodStr.c_str()); } if (! _node->bondController()->addCustomPolicy(newTemplateBond)) { - fprintf(stderr, "error: a custom policy of this name (%s) already exists.\n", customPolicyStr.c_str()); + fprintf( + stderr, "error: a custom policy of this name (%s) already exists.\n", customPolicyStr.c_str()); } } // Peer-specific bonding @@ -2891,7 +3039,9 @@ class OneServiceImpl : public OneService { } // Check settings if (defaultBondingPolicyStr.length() && ! defaultBondingPolicy && ! _node->bondController()->inUse()) { - fprintf(stderr, "error: unknown policy (%s) specified by defaultBondingPolicy, bond disabled.\n", defaultBondingPolicyStr.c_str()); + fprintf( + stderr, "error: unknown policy (%s) specified by defaultBondingPolicy, bond disabled.\n", + defaultBondingPolicyStr.c_str()); } } @@ -2901,21 +3051,26 @@ class OneServiceImpl : public OneService { if (_forceTcpRelayTmp && _bondInUse) { fprintf(stderr, "Warning: forceTcpRelay cannot be used with multipath. Disabling forceTcpRelay\n"); } - _allowTcpFallbackRelay = (OSUtils::jsonBool(settings["allowTcpFallbackRelay"], true) && ! _node->bondController()->inUse()); + _allowTcpFallbackRelay = + (OSUtils::jsonBool(settings["allowTcpFallbackRelay"], true) && ! _node->bondController()->inUse()); _forceTcpRelay = (_forceTcpRelayTmp && ! _node->bondController()->inUse()); _enableWebServer = (OSUtils::jsonBool(settings["enableWebServer"], false)); #ifdef ZT_TCP_FALLBACK_RELAY - _fallbackRelayAddress = InetAddress(OSUtils::jsonString(settings["tcpFallbackRelay"], ZT_TCP_FALLBACK_RELAY).c_str()); + _fallbackRelayAddress = + InetAddress(OSUtils::jsonString(settings["tcpFallbackRelay"], ZT_TCP_FALLBACK_RELAY).c_str()); #endif _primaryPort = (unsigned int)OSUtils::jsonInt(settings["primaryPort"], (uint64_t)_primaryPort) & 0xffff; _allowSecondaryPort = OSUtils::jsonBool(settings["allowSecondaryPort"], true); _secondaryPort = (unsigned int)OSUtils::jsonInt(settings["secondaryPort"], 0); _tertiaryPort = (unsigned int)OSUtils::jsonInt(settings["tertiaryPort"], 0); if (_secondaryPort != 0 || _tertiaryPort != 0) { - fprintf(stderr, "WARNING: using manually-specified secondary and/or tertiary ports. This can cause NAT issues." ZT_EOL_S); + fprintf( + stderr, "WARNING: using manually-specified secondary and/or tertiary ports. This can cause NAT " + "issues." ZT_EOL_S); } _portMappingEnabled = OSUtils::jsonBool(settings["portMappingEnabled"], true); + _node->setEncryptedHelloEnabled(OSUtils::jsonBool(settings["encryptedHelloEnabled"], false)); _node->setLowBandwidthMode(OSUtils::jsonBool(settings["lowBandwidthMode"], false)); #if defined(__LINUX__) || defined(__FreeBSD__) _multicoreEnabled = OSUtils::jsonBool(settings["multicoreEnabled"], false); @@ -2925,7 +3080,10 @@ class OneServiceImpl : public OneService { unsigned int maxConcurrency = std::thread::hardware_concurrency(); if (_concurrency <= 1 || _concurrency >= maxConcurrency) { unsigned int conservativeDefault = (std::thread::hardware_concurrency() >= 4 ? 2 : 1); - fprintf(stderr, "Concurrency level provided (%d) is invalid, assigning conservative default value of (%d)\n", _concurrency, conservativeDefault); + fprintf( + stderr, + "Concurrency level provided (%d) is invalid, assigning conservative default value of (%d)\n", + _concurrency, conservativeDefault); _concurrency = conservativeDefault; } setUpMultithreading(); @@ -2941,23 +3099,6 @@ class OneServiceImpl : public OneService { _cpuPinningEnabled = false; #endif -#ifndef ZT_SDK - const std::string up(OSUtils::jsonString(settings["softwareUpdate"], ZT_SOFTWARE_UPDATE_DEFAULT)); - const bool udist = OSUtils::jsonBool(settings["softwareUpdateDist"], false); - if (((up == "apply") || (up == "download")) || (udist)) { - if (! _updater) - _updater = new SoftwareUpdater(*_node, _homePath); - _updateAutoApply = (up == "apply"); - _updater->setUpdateDistribution(udist); - _updater->setChannel(OSUtils::jsonString(settings["softwareUpdateChannel"], ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL)); - } - else { - delete _updater; - _updater = (SoftwareUpdater*)0; - _updateAutoApply = false; - } -#endif - json& ignoreIfs = settings["interfacePrefixBlacklist"]; if (ignoreIfs.is_array()) { for (unsigned long i = 0; i < ignoreIfs.size(); ++i) { @@ -3099,7 +3240,8 @@ class OneServiceImpl : public OneService { #ifdef __APPLE__ // We can't add multiple addresses to an interface on macOs unless we futz with the netmask. // see `man ifconfig`, alias section - // "If the address is on the same subnet as the first network address for this interface, a non-conflicting netmask must be given. Usually 0xffffffff is most appropriate." + // "If the address is on the same subnet as the first network address for this interface, a + // non-conflicting netmask must be given. Usually 0xffffffff is most appropriate." auto same_subnet = [ip](InetAddress i) { return ip->network() == i.network(); }; #endif @@ -3107,7 +3249,9 @@ class OneServiceImpl : public OneService { if (std::find(n.managedIps().begin(), n.managedIps().end(), *ip) == n.managedIps().end()) { #ifdef __APPLE__ // if same subnet as a previously added address - if (std::find_if(n.managedIps().begin(), n.managedIps().end(), same_subnet) != n.managedIps().end() || std::find_if(newManagedIps2.begin(), newManagedIps2.end(), same_subnet) != newManagedIps2.end()) { + if (std::find_if(n.managedIps().begin(), n.managedIps().end(), same_subnet) != n.managedIps().end() + || std::find_if(newManagedIps2.begin(), newManagedIps2.end(), same_subnet) + != newManagedIps2.end()) { if (ip->isV4()) { ip->setPort(32); } @@ -3132,11 +3276,13 @@ class OneServiceImpl : public OneService { } #ifdef __APPLE__ - if (! MacDNSHelper::addIps6(n.config().nwid, n.config().mac, n.tap()->deviceName().c_str(), newManagedIps)) { + if (! MacDNSHelper::addIps6( + n.config().nwid, n.config().mac, n.tap()->deviceName().c_str(), newManagedIps)) { fprintf(stderr, "ERROR: unable to add v6 addresses to system configuration" ZT_EOL_S); } - if (! MacDNSHelper::addIps4(n.config().nwid, n.config().mac, n.tap()->deviceName().c_str(), newManagedIps)) { + if (! MacDNSHelper::addIps4( + n.config().nwid, n.config().mac, n.tap()->deviceName().c_str(), newManagedIps)) { fprintf(stderr, "ERROR: unable to add v4 addresses to system configuration" ZT_EOL_S); } #endif @@ -3147,7 +3293,9 @@ class OneServiceImpl : public OneService { // Get tap device name (use LUID in hex on Windows) and IP addresses. #if defined(__WINDOWS__) && ! defined(ZT_SDK) char tapdevbuf[64]; - OSUtils::ztsnprintf(tapdevbuf, sizeof(tapdevbuf), "%.16llx", (unsigned long long)((WindowsEthernetTap*)(n.tap().get()))->luid().Value); + OSUtils::ztsnprintf( + tapdevbuf, sizeof(tapdevbuf), "%.16llx", + (unsigned long long)((WindowsEthernetTap*)(n.tap().get()))->luid().Value); std::string tapdev(tapdevbuf); #else std::string tapdev(n.tap()->deviceName()); @@ -3165,7 +3313,8 @@ class OneServiceImpl : public OneService { // Make sure we are allowed to set this managed route, and that 'via' is not our IP. The latter // avoids setting routes via the router on the router. - if ((! checkIfManagedIsAllowed(n, *target)) || ((via->ss_family == target->ss_family) && (matchIpOnly(myIps, *via)))) + if ((! checkIfManagedIsAllowed(n, *target)) + || ((via->ss_family == target->ss_family) && (matchIpOnly(myIps, *via)))) continue; // Find an IP on the interface that can be a source IP, abort if no IPs assigned. @@ -3173,7 +3322,8 @@ class OneServiceImpl : public OneService { unsigned int mostMatchingPrefixBits = 0; for (std::set::const_iterator i(myIps.begin()); i != myIps.end(); ++i) { const unsigned int matchingPrefixBits = i->matchingPrefixBits(*target); - if (matchingPrefixBits >= mostMatchingPrefixBits && ((target->isV4() && i->isV4()) || (target->isV6() && i->isV6()))) { + if (matchingPrefixBits >= mostMatchingPrefixBits + && ((target->isV4() && i->isV4()) || (target->isV6() && i->isV6()))) { mostMatchingPrefixBits = matchingPrefixBits; src = &(*i); } @@ -3204,7 +3354,8 @@ class OneServiceImpl : public OneService { #endif } - for (std::map >::iterator r(n.managedRoutes().begin()); r != n.managedRoutes().end();) { + for (std::map >::iterator r(n.managedRoutes().begin()); + r != n.managedRoutes().end();) { if (haveRouteTargets.find(r->first) == haveRouteTargets.end()) n.managedRoutes().erase(r++); else @@ -3214,11 +3365,13 @@ class OneServiceImpl : public OneService { // Sync device-local managed routes first, then indirect results. That way // we don't get destination unreachable for routes that are via things // that do not yet have routes in the system. - for (std::map >::iterator r(n.managedRoutes().begin()); r != n.managedRoutes().end(); ++r) { + for (std::map >::iterator r(n.managedRoutes().begin()); + r != n.managedRoutes().end(); ++r) { if (! r->second->via()) r->second->sync(); } - for (std::map >::iterator r(n.managedRoutes().begin()); r != n.managedRoutes().end(); ++r) { + for (std::map >::iterator r(n.managedRoutes().begin()); + r != n.managedRoutes().end(); ++r) { if (r->second->via() && (! r->second->target().isDefaultRoute() || _node->online())) { r->second->sync(); } @@ -3252,7 +3405,13 @@ class OneServiceImpl : public OneService { // Handlers for Node and Phy<> callbacks // ========================================================================= - inline void phyOnDatagram(PhySocket* sock, void** uptr, const struct sockaddr* localAddr, const struct sockaddr* from, void* data, unsigned long len) + inline void phyOnDatagram( + PhySocket* sock, + void** uptr, + const struct sockaddr* localAddr, + const struct sockaddr* from, + void* data, + unsigned long len) { if (_forceTcpRelay) { return; @@ -3262,7 +3421,9 @@ class OneServiceImpl : public OneService { if ((len >= 16) && (reinterpret_cast(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) { _lastDirectReceiveFromGlobal = now; } - const ZT_ResultCode rc = _node->processWirePacket(nullptr, now, reinterpret_cast(sock), reinterpret_cast(from), data, len, &_nextBackgroundTaskDeadline); + const ZT_ResultCode rc = _node->processWirePacket( + nullptr, now, reinterpret_cast(sock), reinterpret_cast(from), data, + len, &_nextBackgroundTaskDeadline); if (ZT_ResultCode_isFatal(rc)) { char tmp[256]; OSUtils::ztsnprintf(tmp, sizeof(tmp), "fatal error code from processWirePacket: %d", (int)rc); @@ -3298,7 +3459,8 @@ class OneServiceImpl : public OneService { } } - inline void phyOnTcpAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN, const struct sockaddr* from) + inline void + phyOnTcpAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN, const struct sockaddr* from) { if (! from) { _phy.close(sockN, false); @@ -3306,7 +3468,8 @@ class OneServiceImpl : public OneService { } else { #ifdef ZT_SDK - // Immediately close new local connections. The intention is to prevent the backplane from being accessed when operating as libzt + // Immediately close new local connections. The intention is to prevent the backplane from being accessed + // when operating as libzt if (! allowHttpBackplaneManagement && ((InetAddress*)from)->ipScope() == InetAddress::IP_SCOPE_LOOPBACK) { _phy.close(sockN, false); return; @@ -3340,7 +3503,8 @@ class OneServiceImpl : public OneService { } { Mutex::Lock _l(_tcpConnections_m); - _tcpConnections.erase(std::remove(_tcpConnections.begin(), _tcpConnections.end(), tc), _tcpConnections.end()); + _tcpConnections.erase( + std::remove(_tcpConnections.begin(), _tcpConnections.end(), tc), _tcpConnections.end()); } delete tc; } @@ -3369,7 +3533,8 @@ class OneServiceImpl : public OneService { tc->readq.append((const char*)data, len); while (tc->readq.length() >= 5) { const char* data = tc->readq.data(); - const unsigned long mlen = (((((unsigned long)data[3]) & 0xff) << 8) | (((unsigned long)data[4]) & 0xff)); + const unsigned long mlen = + (((((unsigned long)data[3]) & 0xff) << 8) | (((unsigned long)data[4]) & 0xff)); if (tc->readq.length() >= (mlen + 5)) { InetAddress from; @@ -3383,7 +3548,10 @@ class OneServiceImpl : public OneService { switch (data[0]) { case 4: // IPv4 if (plen >= 7) { - from.set((const void*)(data + 1), 4, ((((unsigned int)data[5]) & 0xff) << 8) | (((unsigned int)data[6]) & 0xff)); + from.set( + (const void*)(data + 1), 4, + ((((unsigned int)data[5]) & 0xff) << 8) + | (((unsigned int)data[6]) & 0xff)); data += 7; // type + 4 byte IP + 2 byte port plen -= 7; } @@ -3394,7 +3562,10 @@ class OneServiceImpl : public OneService { break; case 6: // IPv6 if (plen >= 19) { - from.set((const void*)(data + 1), 16, ((((unsigned int)data[17]) & 0xff) << 8) | (((unsigned int)data[18]) & 0xff)); + from.set( + (const void*)(data + 1), 16, + ((((unsigned int)data[17]) & 0xff) << 8) + | (((unsigned int)data[18]) & 0xff)); data += 19; // type + 16 byte IP + 2 byte port plen -= 19; } @@ -3414,10 +3585,13 @@ class OneServiceImpl : public OneService { if (from) { InetAddress fakeTcpLocalInterfaceAddress((uint32_t)0xffffffff, 0xffff); - const ZT_ResultCode rc = _node->processWirePacket((void*)0, OSUtils::now(), -1, reinterpret_cast(&from), data, plen, &_nextBackgroundTaskDeadline); + const ZT_ResultCode rc = _node->processWirePacket( + (void*)0, OSUtils::now(), -1, reinterpret_cast(&from), + data, plen, &_nextBackgroundTaskDeadline); if (ZT_ResultCode_isFatal(rc)) { char tmp[256]; - OSUtils::ztsnprintf(tmp, sizeof(tmp), "fatal error code from processWirePacket: %d", (int)rc); + OSUtils::ztsnprintf( + tmp, sizeof(tmp), "fatal error code from processWirePacket: %d", (int)rc); Mutex::Lock _l(_termReason_m); _termReason = ONE_UNRECOVERABLE_ERROR; _fatalErrorMessage = tmp; @@ -3486,62 +3660,64 @@ class OneServiceImpl : public OneService { inline void phyOnUnixData(PhySocket* sock, void** uptr, void* data, unsigned long len) { #ifdef ZT_EXTOSDEP - if (ExtOsdep::mgmtRecv(*uptr, data, len, [&](unsigned method, const std::string& path, const std::string& data, std::string& resp) { - // fprintf(stderr, "mgmtRecv: %u %s %s\n", method, path.c_str(), data.c_str()); - httplib::Request req; - httplib::Response res; - req.path = "/" + path; - if (method == 1) - req.method = "GET"; - else if (method == 3) - req.method = "POST"; - else if (method == 0) - req.method = "DELETE"; - struct S : public httplib::Stream { - const char* ptr; - unsigned size; - S(const std::string& s) : ptr(s.c_str()), size(s.size()) - { - } - virtual bool is_readable() const - { - return true; - } - virtual bool is_writable() const - { - return true; - } - virtual ssize_t read(char* p, size_t sz) - { - // fprintf(stderr, "S::read %d\n", (int)size); - if (sz > (size_t)size) - sz = size; - memcpy(p, ptr, sz); - size -= (unsigned)sz; - ptr += sz; - return (ssize_t)sz; - } - virtual ssize_t write(const char* ptr, size_t size) - { - // fprintf(stderr, "S::write %d\n", (int)size); - return size; - } - virtual void get_remote_ip_and_port(std::string& ip, int& port) const - { - } - virtual void get_local_ip_and_port(std::string& ip, int& port) const {}; - virtual socket_t socket() const - { - return 0; - } - }; - S s(data); + if (ExtOsdep::mgmtRecv( + *uptr, data, len, + [&](unsigned method, const std::string& path, const std::string& data, std::string& resp) { + // fprintf(stderr, "mgmtRecv: %u %s %s\n", method, path.c_str(), data.c_str()); + httplib::Request req; + httplib::Response res; + req.path = "/" + path; + if (method == 1) + req.method = "GET"; + else if (method == 3) + req.method = "POST"; + else if (method == 0) + req.method = "DELETE"; + struct S : public httplib::Stream { + const char* ptr; + unsigned size; + S(const std::string& s) : ptr(s.c_str()), size(s.size()) + { + } + virtual bool is_readable() const + { + return true; + } + virtual bool is_writable() const + { + return true; + } + virtual ssize_t read(char* p, size_t sz) + { + // fprintf(stderr, "S::read %d\n", (int)size); + if (sz > (size_t)size) + sz = size; + memcpy(p, ptr, sz); + size -= (unsigned)sz; + ptr += sz; + return (ssize_t)sz; + } + virtual ssize_t write(const char* ptr, size_t size) + { + // fprintf(stderr, "S::write %d\n", (int)size); + return size; + } + virtual void get_remote_ip_and_port(std::string& ip, int& port) const + { + } + virtual void get_local_ip_and_port(std::string& ip, int& port) const {}; + virtual socket_t socket() const + { + return 0; + } + }; + S s(data); - bool x = _controlPlane.routing(req, res, s); - // fprintf(stderr, "mgmtRecv: done, x %d status %u body %s\n", x, res.status, res.body.c_str()); - resp = res.body; - return res.status; - })) + bool x = _controlPlane.routing(req, res, s); + // fprintf(stderr, "mgmtRecv: done, x %d status %u body %s\n", x, res.status, res.body.c_str()); + resp = res.body; + return res.status; + })) _phy.setNotifyWritable(sock, true); #endif } @@ -3553,7 +3729,11 @@ class OneServiceImpl : public OneService { #endif } - inline int nodeVirtualNetworkConfigFunction(uint64_t nwid, void** nuptr, enum ZT_VirtualNetworkConfigOperation op, const ZT_VirtualNetworkConfig* nwc) + inline int nodeVirtualNetworkConfigFunction( + uint64_t nwid, + void** nuptr, + enum ZT_VirtualNetworkConfigOperation op, + const ZT_VirtualNetworkConfig* nwc) { Mutex::Lock _l(_nets_m); NetworkState& n = _nets[nwid]; @@ -3566,11 +3746,17 @@ class OneServiceImpl : public OneService { char friendlyName[128]; OSUtils::ztsnprintf(friendlyName, sizeof(friendlyName), "ZeroTier One [%.16llx]", nwid); - n.setTap(EthernetTap::newInstance(nullptr, _concurrency, _cpuPinningEnabled, _homePath.c_str(), MAC(nwc->mac), nwc->mtu, (unsigned int)ZT_IF_METRIC, nwid, friendlyName, StapFrameHandler, (void*)this)); + n.setTap( + EthernetTap::newInstance( + nullptr, _concurrency, _cpuPinningEnabled, _homePath.c_str(), MAC(nwc->mac), nwc->mtu, + (unsigned int)ZT_IF_METRIC, nwid, friendlyName, StapFrameHandler, (void*)this)); *nuptr = (void*)&n; char nlcpath[256]; - OSUtils::ztsnprintf(nlcpath, sizeof(nlcpath), "%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf", _homePath.c_str(), nwid); + OSUtils::ztsnprintf( + nlcpath, sizeof(nlcpath), + "%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf", + _homePath.c_str(), nwid); std::string nlcbuf; if (OSUtils::readFile(nlcpath, nlcbuf)) { Dictionary<4096> nc; @@ -3592,7 +3778,8 @@ class OneServiceImpl : public OneService { size_t pos = 0; while (true) { size_t nextPos = addresses.find(',', pos); - std::string address = addresses.substr(pos, (nextPos == std::string::npos ? addresses.size() : nextPos) - pos); + std::string address = addresses.substr( + pos, (nextPos == std::string::npos ? addresses.size() : nextPos) - pos); n.addToAllowManagedWhiteList(InetAddress(address.c_str())); if (nextPos == std::string::npos) break; @@ -3637,7 +3824,8 @@ class OneServiceImpl : public OneService { // without WindowsEthernetTap::isInitialized() returning true, the won't actually // be online yet and setting managed routes on it will fail. const int MAX_SLEEP_COUNT = 500; - for (int i = 0; ! ((WindowsEthernetTap*)(n.tap().get()))->isInitialized() && i < MAX_SLEEP_COUNT; i++) { + for (int i = 0; ! ((WindowsEthernetTap*)(n.tap().get()))->isInitialized() && i < MAX_SLEEP_COUNT; + i++) { Sleep(10); } #endif @@ -3667,7 +3855,10 @@ class OneServiceImpl : public OneService { #endif if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY) { char nlcpath[256]; - OSUtils::ztsnprintf(nlcpath, sizeof(nlcpath), "%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf", _homePath.c_str(), nwid); + OSUtils::ztsnprintf( + nlcpath, sizeof(nlcpath), + "%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf", + _homePath.c_str(), nwid); OSUtils::rm(nlcpath); } } @@ -3696,17 +3887,12 @@ class OneServiceImpl : public OneService { } } break; - case ZT_EVENT_USER_MESSAGE: { - const ZT_UserMessage* um = reinterpret_cast(metaData); - if ((um->typeId == ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE) && (_updater)) { - _updater->handleSoftwareUpdateUserMessage(um->origin, um->data, um->length); - } - } break; - case ZT_EVENT_REMOTE_TRACE: { +#ifdef ZT_NONFREE_CONTROLLER const ZT_RemoteTrace* rt = reinterpret_cast(metaData); if ((rt) && (rt->len > 0) && (rt->len <= ZT_MAX_REMOTE_TRACE_SIZE) && (rt->data)) _controller->handleRemoteTrace(*rt); +#endif } default: @@ -3814,15 +4000,18 @@ class OneServiceImpl : public OneService { break; case ZT_STATE_OBJECT_MOON: OSUtils::ztsnprintf(dirname, sizeof(dirname), "%s" ZT_PATH_SEPARATOR_S "moons.d", _homePath.c_str()); - OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.16llx.moon", dirname, (unsigned long long)id[0]); + OSUtils::ztsnprintf( + p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.16llx.moon", dirname, (unsigned long long)id[0]); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: OSUtils::ztsnprintf(dirname, sizeof(dirname), "%s" ZT_PATH_SEPARATOR_S "networks.d", _homePath.c_str()); - OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.16llx.conf", dirname, (unsigned long long)id[0]); + OSUtils::ztsnprintf( + p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.16llx.conf", dirname, (unsigned long long)id[0]); break; case ZT_STATE_OBJECT_PEER: OSUtils::ztsnprintf(dirname, sizeof(dirname), "%s" ZT_PATH_SEPARATOR_S "peers.d", _homePath.c_str()); - OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.10llx.peer", dirname, (unsigned long long)id[0]); + OSUtils::ztsnprintf( + p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "%.10llx.peer", dirname, (unsigned long long)id[0]); break; default: return; @@ -3966,13 +4155,19 @@ class OneServiceImpl : public OneService { OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "planet", _homePath.c_str()); break; case ZT_STATE_OBJECT_MOON: - OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "moons.d" ZT_PATH_SEPARATOR_S "%.16llx.moon", _homePath.c_str(), (unsigned long long)id[0]); + OSUtils::ztsnprintf( + p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "moons.d" ZT_PATH_SEPARATOR_S "%.16llx.moon", + _homePath.c_str(), (unsigned long long)id[0]); break; case ZT_STATE_OBJECT_NETWORK_CONFIG: - OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.conf", _homePath.c_str(), (unsigned long long)id[0]); + OSUtils::ztsnprintf( + p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.conf", + _homePath.c_str(), (unsigned long long)id[0]); break; case ZT_STATE_OBJECT_PEER: - OSUtils::ztsnprintf(p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "peers.d" ZT_PATH_SEPARATOR_S "%.10llx.peer", _homePath.c_str(), (unsigned long long)id[0]); + OSUtils::ztsnprintf( + p, sizeof(p), "%s" ZT_PATH_SEPARATOR_S "peers.d" ZT_PATH_SEPARATOR_S "%.10llx.peer", + _homePath.c_str(), (unsigned long long)id[0]); break; default: return -1; @@ -3998,18 +4193,26 @@ class OneServiceImpl : public OneService { return -1; } - inline int nodeWirePacketSendFunction(const int64_t localSocket, const struct sockaddr_storage* addr, const void* data, unsigned int len, unsigned int ttl) + inline int nodeWirePacketSendFunction( + const int64_t localSocket, + const struct sockaddr_storage* addr, + const void* data, + unsigned int len, + unsigned int ttl) { #ifdef ZT_TCP_FALLBACK_RELAY if (_allowTcpFallbackRelay) { if (addr->ss_family == AF_INET) { // TCP fallback tunnel support, currently IPv4 only - if ((len >= 16) && (reinterpret_cast(addr)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) { + if ((len >= 16) + && (reinterpret_cast(addr)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) { // Engage TCP tunnel fallback if we haven't received anything valid from a global // IP address in ZT_TCP_FALLBACK_AFTER milliseconds. If we do start getting // valid direct traffic we'll stop using it and close the socket after a while. const int64_t now = OSUtils::now(); - if (_forceTcpRelay || (((now - _lastDirectReceiveFromGlobal) > ZT_TCP_FALLBACK_AFTER) && ((now - _lastRestart) > ZT_TCP_FALLBACK_AFTER))) { + if (_forceTcpRelay + || (((now - _lastDirectReceiveFromGlobal) > ZT_TCP_FALLBACK_AFTER) + && ((now - _lastRestart) > ZT_TCP_FALLBACK_AFTER))) { if (_tcpFallbackTunnel) { bool flushNow = false; { @@ -4026,8 +4229,14 @@ class OneServiceImpl : public OneService { _tcpFallbackTunnel->writeq.push_back((char)((mlen >> 8) & 0xff)); _tcpFallbackTunnel->writeq.push_back((char)(mlen & 0xff)); _tcpFallbackTunnel->writeq.push_back((char)4); // IPv4 - _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_addr.s_addr))), 4); - _tcpFallbackTunnel->writeq.append(reinterpret_cast(reinterpret_cast(&(reinterpret_cast(addr)->sin_port))), 2); + _tcpFallbackTunnel->writeq.append( + reinterpret_cast(reinterpret_cast( + &(reinterpret_cast(addr)->sin_addr.s_addr))), + 4); + _tcpFallbackTunnel->writeq.append( + reinterpret_cast(reinterpret_cast( + &(reinterpret_cast(addr)->sin_port))), + 2); _tcpFallbackTunnel->writeq.append((const char*)data, len); } } @@ -4036,7 +4245,10 @@ class OneServiceImpl : public OneService { phyOnTcpWritable(_tcpFallbackTunnel->sock, &tmpptr); } } - else if (_forceTcpRelay || (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER) && ((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INTERVAL / 2)))) { + else if ( + _forceTcpRelay + || (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER) + && ((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INTERVAL / 2)))) { const InetAddress addr(_fallbackRelayAddress); TcpConnection* tc = new TcpConnection(); { @@ -4050,7 +4262,8 @@ class OneServiceImpl : public OneService { tc->sock = (PhySocket*)0; // set in connect handler tc->messageSize = 0; bool connected = false; - _phy.tcpConnect(reinterpret_cast(&addr), connected, (void*)tc, true); + _phy.tcpConnect( + reinterpret_cast(&addr), connected, (void*)tc, true); } } _lastSendToGlobalV4 = now; @@ -4066,7 +4279,8 @@ class OneServiceImpl : public OneService { // Even when relaying we still send via UDP. This way if UDP starts // working we can instantly "fail forward" to it and stop using TCP // proxy fallback, which is slow. - if ((localSocket != -1) && (localSocket != 0) && (_binder.isUdpSocketValid((PhySocket*)((uintptr_t)localSocket)))) { + if ((localSocket != -1) && (localSocket != 0) + && (_binder.isUdpSocketValid((PhySocket*)((uintptr_t)localSocket)))) { if ((ttl) && (addr->ss_family == AF_INET)) { _phy.setIp4UdpTtl((PhySocket*)((uintptr_t)localSocket), ttl); } @@ -4081,7 +4295,15 @@ class OneServiceImpl : public OneService { } } - inline void nodeVirtualNetworkFrameFunction(uint64_t nwid, void** nuptr, uint64_t sourceMac, uint64_t destMac, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len) + inline void nodeVirtualNetworkFrameFunction( + uint64_t nwid, + void** nuptr, + uint64_t sourceMac, + uint64_t destMac, + unsigned int etherType, + unsigned int vlanId, + const void* data, + unsigned int len) { NetworkState* n = reinterpret_cast(*nuptr); if ((! n) || (! n->tap())) { @@ -4090,7 +4312,8 @@ class OneServiceImpl : public OneService { n->tap()->put(MAC(sourceMac), MAC(destMac), etherType, data, len); } - inline int nodePathCheckFunction(uint64_t ztaddr, const int64_t localSocket, const struct sockaddr_storage* remoteAddr) + inline int + nodePathCheckFunction(uint64_t ztaddr, const int64_t localSocket, const struct sockaddr_storage* remoteAddr) { // Make sure we're not trying to do ZeroTier-over-ZeroTier { @@ -4114,7 +4337,8 @@ class OneServiceImpl : public OneService { * revisit if we see recursion problems. */ // Check blacklists - const Hashtable >* blh = (const Hashtable >*)0; + const Hashtable >* blh = + (const Hashtable >*)0; const std::vector* gbl = (const std::vector*)0; if (remoteAddr->ss_family == AF_INET) { blh = &_v4Blacklists; @@ -4145,7 +4369,8 @@ class OneServiceImpl : public OneService { inline int nodePathLookupFunction(uint64_t ztaddr, int family, struct sockaddr_storage* result) { - const Hashtable >* lh = (const Hashtable >*)0; + const Hashtable >* lh = + (const Hashtable >*)0; if (family < 0) lh = (_node->prng() & 1) ? &_v4Hints : &_v6Hints; else if (family == AF_INET) @@ -4163,9 +4388,18 @@ class OneServiceImpl : public OneService { return 0; } - inline void tapFrameHandler(uint64_t nwid, const MAC& from, const MAC& to, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len) + inline void tapFrameHandler( + uint64_t nwid, + const MAC& from, + const MAC& to, + unsigned int etherType, + unsigned int vlanId, + const void* data, + unsigned int len) { - _node->processVirtualNetworkFrame((void*)0, OSUtils::now(), nwid, from.toInt(), to.toInt(), etherType, vlanId, data, len, &_nextBackgroundTaskDeadline); + _node->processVirtualNetworkFrame( + (void*)0, OSUtils::now(), nwid, from.toInt(), to.toInt(), etherType, vlanId, data, len, + &_nextBackgroundTaskDeadline); } inline void onHttpResponseFromClient(TcpConnection* tc) @@ -4210,7 +4444,8 @@ class OneServiceImpl : public OneService { { Mutex::Lock _l(_localConfig_m); - for (std::vector::const_iterator p(_interfacePrefixBlacklist.begin()); p != _interfacePrefixBlacklist.end(); ++p) { + for (std::vector::const_iterator p(_interfacePrefixBlacklist.begin()); + p != _interfacePrefixBlacklist.end(); ++p) { if (! strncmp(p->c_str(), ifname, p->length())) return false; } @@ -4306,7 +4541,14 @@ class OneServiceImpl : public OneService { } }; -static int SnodeVirtualNetworkConfigFunction(ZT_Node* node, void* uptr, void* tptr, uint64_t nwid, void** nuptr, enum ZT_VirtualNetworkConfigOperation op, const ZT_VirtualNetworkConfig* nwconf) +static int SnodeVirtualNetworkConfigFunction( + ZT_Node* node, + void* uptr, + void* tptr, + uint64_t nwid, + void** nuptr, + enum ZT_VirtualNetworkConfigOperation op, + const ZT_VirtualNetworkConfig* nwconf) { return reinterpret_cast(uptr)->nodeVirtualNetworkConfigFunction(nwid, nuptr, op, nwconf); } @@ -4314,31 +4556,86 @@ static void SnodeEventCallback(ZT_Node* node, void* uptr, void* tptr, enum ZT_Ev { reinterpret_cast(uptr)->nodeEventCallback(event, metaData); } -static void SnodeStatePutFunction(ZT_Node* node, void* uptr, void* tptr, enum ZT_StateObjectType type, const uint64_t id[2], const void* data, int len) +static void SnodeStatePutFunction( + ZT_Node* node, + void* uptr, + void* tptr, + enum ZT_StateObjectType type, + const uint64_t id[2], + const void* data, + int len) { reinterpret_cast(uptr)->nodeStatePutFunction(type, id, data, len); } -static int SnodeStateGetFunction(ZT_Node* node, void* uptr, void* tptr, enum ZT_StateObjectType type, const uint64_t id[2], void* data, unsigned int maxlen) +static int SnodeStateGetFunction( + ZT_Node* node, + void* uptr, + void* tptr, + enum ZT_StateObjectType type, + const uint64_t id[2], + void* data, + unsigned int maxlen) { return reinterpret_cast(uptr)->nodeStateGetFunction(type, id, data, maxlen); } -static int SnodeWirePacketSendFunction(ZT_Node* node, void* uptr, void* tptr, int64_t localSocket, const struct sockaddr_storage* addr, const void* data, unsigned int len, unsigned int ttl) +static int SnodeWirePacketSendFunction( + ZT_Node* node, + void* uptr, + void* tptr, + int64_t localSocket, + const struct sockaddr_storage* addr, + const void* data, + unsigned int len, + unsigned int ttl) { return reinterpret_cast(uptr)->nodeWirePacketSendFunction(localSocket, addr, data, len, ttl); } -static void SnodeVirtualNetworkFrameFunction(ZT_Node* node, void* uptr, void* tptr, uint64_t nwid, void** nuptr, uint64_t sourceMac, uint64_t destMac, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len) +static void SnodeVirtualNetworkFrameFunction( + ZT_Node* node, + void* uptr, + void* tptr, + uint64_t nwid, + void** nuptr, + uint64_t sourceMac, + uint64_t destMac, + unsigned int etherType, + unsigned int vlanId, + const void* data, + unsigned int len) { - reinterpret_cast(uptr)->nodeVirtualNetworkFrameFunction(nwid, nuptr, sourceMac, destMac, etherType, vlanId, data, len); + reinterpret_cast(uptr)->nodeVirtualNetworkFrameFunction( + nwid, nuptr, sourceMac, destMac, etherType, vlanId, data, len); } -static int SnodePathCheckFunction(ZT_Node* node, void* uptr, void* tptr, uint64_t ztaddr, int64_t localSocket, const struct sockaddr_storage* remoteAddr) +static int SnodePathCheckFunction( + ZT_Node* node, + void* uptr, + void* tptr, + uint64_t ztaddr, + int64_t localSocket, + const struct sockaddr_storage* remoteAddr) { return reinterpret_cast(uptr)->nodePathCheckFunction(ztaddr, localSocket, remoteAddr); } -static int SnodePathLookupFunction(ZT_Node* node, void* uptr, void* tptr, uint64_t ztaddr, int family, struct sockaddr_storage* result) +static int SnodePathLookupFunction( + ZT_Node* node, + void* uptr, + void* tptr, + uint64_t ztaddr, + int family, + struct sockaddr_storage* result) { return reinterpret_cast(uptr)->nodePathLookupFunction(ztaddr, family, result); } -static void StapFrameHandler(void* uptr, void* tptr, uint64_t nwid, const MAC& from, const MAC& to, unsigned int etherType, unsigned int vlanId, const void* data, unsigned int len) +static void StapFrameHandler( + void* uptr, + void* tptr, + uint64_t nwid, + const MAC& from, + const MAC& to, + unsigned int etherType, + unsigned int vlanId, + const void* data, + unsigned int len) { reinterpret_cast(uptr)->tapFrameHandler(nwid, from, to, etherType, vlanId, data, len); } diff --git a/service/OneService.hpp b/service/OneService.hpp index f63c70b26..f4ab72996 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef ZT_ONESERVICE_HPP #define ZT_ONESERVICE_HPP diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp deleted file mode 100644 index 978370f68..000000000 --- a/service/SoftwareUpdater.cpp +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#include "../node/Constants.hpp" -#include "../version.h" - -#include -#include -#include -#include - -#ifdef __WINDOWS__ -#include -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#endif - -#include "../node/Buffer.hpp" -#include "../node/Node.hpp" -#include "../node/SHA512.hpp" -#include "../node/Utils.hpp" -#include "../osdep/OSUtils.hpp" -#include "SoftwareUpdater.hpp" - -namespace ZeroTier { - -static int _compareVersion(unsigned int maj1, unsigned int min1, unsigned int rev1, unsigned int b1, unsigned int maj2, unsigned int min2, unsigned int rev2, unsigned int b2) -{ - if (maj1 > maj2) { - return 1; - } - else if (maj1 < maj2) { - return -1; - } - else { - if (min1 > min2) { - return 1; - } - else if (min1 < min2) { - return -1; - } - else { - if (rev1 > rev2) { - return 1; - } - else if (rev1 < rev2) { - return -1; - } - else { - if (b1 > b2) { - return 1; - } - else if (b1 < b2) { - return -1; - } - else { - return 0; - } - } - } - } -} - -SoftwareUpdater::SoftwareUpdater(Node& node, const std::string& homePath) : _node(node), _lastCheckTime(0), _homePath(homePath), _channel(ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL), _distLog((FILE*)0), _latestValid(false), _downloadLength(0) -{ - OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME).c_str()); -} - -SoftwareUpdater::~SoftwareUpdater() -{ - if (_distLog) - fclose(_distLog); -} - -void SoftwareUpdater::setUpdateDistribution(bool distribute) -{ - _dist.clear(); - if (distribute) { - _distLog = fopen((_homePath + ZT_PATH_SEPARATOR_S "update-dist.log").c_str(), "a"); - - const std::string udd(_homePath + ZT_PATH_SEPARATOR_S "update-dist.d"); - const std::vector ud(OSUtils::listDirectory(udd.c_str())); - for (std::vector::const_iterator u(ud.begin()); u != ud.end(); ++u) { - // Each update has a companion .json file describing it. Other files are ignored. - if ((u->length() > 5) && (u->substr(u->length() - 5, 5) == ".json")) { - std::string buf; - if (OSUtils::readFile((udd + ZT_PATH_SEPARATOR_S + *u).c_str(), buf)) { - try { - _D d; - d.meta = OSUtils::jsonParse(buf); // throws on invalid JSON - - // If update meta is called e.g. foo.exe.json, then foo.exe is the update itself - const std::string binPath(udd + ZT_PATH_SEPARATOR_S + u->substr(0, u->length() - 5)); - const std::string metaHash(OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH])); - if ((metaHash.length() == 64) && (OSUtils::readFile(binPath.c_str(), d.bin))) { - std::array sha512; - SHA512(sha512.data(), d.bin.data(), (unsigned int)d.bin.length()); - if (! memcmp(sha512.data(), metaHash.data(), 64)) { // double check that hash in JSON is correct - d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIZE] = d.bin.length(); // override with correct value -- setting this in meta json is optional - std::array shakey; - memcpy(shakey.data(), sha512.data(), 16); - _dist[shakey] = d; - if (_distLog) { - fprintf(_distLog, ".......... INIT: DISTRIBUTING %s (%u bytes)" ZT_EOL_S, binPath.c_str(), (unsigned int)d.bin.length()); - fflush(_distLog); - } - } - } - } - catch (...) { - } // ignore bad meta JSON, etc. - } - } - } - } - else { - if (_distLog) { - fclose(_distLog); - _distLog = (FILE*)0; - } - } -} - -void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin, const void* data, unsigned int len) -{ - if (! len) - return; - const MessageVerb v = (MessageVerb) reinterpret_cast(data)[0]; - try { - switch (v) { - case VERB_GET_LATEST: - case VERB_LATEST: { - nlohmann::json req = OSUtils::jsonParse(std::string(reinterpret_cast(data) + 1, len - 1)); // throws on invalid JSON - if (req.is_object()) { - const unsigned int rvMaj = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR], 0); - const unsigned int rvMin = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR], 0); - const unsigned int rvRev = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION], 0); - const unsigned int rvBld = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_VERSION_BUILD], 0); - const unsigned int rvPlatform = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_PLATFORM], 0); - const unsigned int rvArch = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE], 0); - const unsigned int rvVendor = (unsigned int)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_VENDOR], 0); - const std::string rvChannel(OSUtils::jsonString(req[ZT_SOFTWARE_UPDATE_JSON_CHANNEL], "")); - - if (v == VERB_GET_LATEST) { - if (! _dist.empty()) { - const nlohmann::json* latest = (const nlohmann::json*)0; - const std::string expectedSigner = OSUtils::jsonString(req[ZT_SOFTWARE_UPDATE_JSON_EXPECT_SIGNED_BY], ""); - unsigned int bestVMaj = rvMaj; - unsigned int bestVMin = rvMin; - unsigned int bestVRev = rvRev; - unsigned int bestVBld = rvBld; - for (std::map, _D>::const_iterator d(_dist.begin()); d != _dist.end(); ++d) { - // The arch field in update description .json files can be an array for e.g. multi-arch update files - const nlohmann::json& dvArch2 = d->second.meta[ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE]; - std::vector dvArch; - if (dvArch2.is_array()) { - for (unsigned long i = 0; i < dvArch2.size(); ++i) - dvArch.push_back((unsigned int)OSUtils::jsonInt(dvArch2[i], 0)); - } - else { - dvArch.push_back((unsigned int)OSUtils::jsonInt(dvArch2, 0)); - } - - if ((OSUtils::jsonInt(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_PLATFORM], 0) == rvPlatform) && (std::find(dvArch.begin(), dvArch.end(), rvArch) != dvArch.end()) - && (OSUtils::jsonInt(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_VENDOR], 0) == rvVendor) && (OSUtils::jsonString(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_CHANNEL], "") == rvChannel) - && (OSUtils::jsonString(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNED_BY], "") == expectedSigner)) { - const unsigned int dvMaj = (unsigned int)OSUtils::jsonInt(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR], 0); - const unsigned int dvMin = (unsigned int)OSUtils::jsonInt(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR], 0); - const unsigned int dvRev = (unsigned int)OSUtils::jsonInt(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION], 0); - const unsigned int dvBld = (unsigned int)OSUtils::jsonInt(d->second.meta[ZT_SOFTWARE_UPDATE_JSON_VERSION_BUILD], 0); - if (_compareVersion(dvMaj, dvMin, dvRev, dvBld, bestVMaj, bestVMin, bestVRev, bestVBld) > 0) { - latest = &(d->second.meta); - bestVMaj = dvMaj; - bestVMin = dvMin; - bestVRev = dvRev; - bestVBld = dvBld; - } - } - } - if (latest) { - std::string lj; - lj.push_back((char)VERB_LATEST); - lj.append(OSUtils::jsonDump(*latest)); - _node.sendUserMessage((void*)0, origin, ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE, lj.data(), (unsigned int)lj.length()); - if (_distLog) { - fprintf( - _distLog, - "%.10llx GET_LATEST %u.%u.%u_%u platform %u arch %u vendor %u channel %s -> LATEST %u.%u.%u_%u" ZT_EOL_S, - (unsigned long long)origin, - rvMaj, - rvMin, - rvRev, - rvBld, - rvPlatform, - rvArch, - rvVendor, - rvChannel.c_str(), - bestVMaj, - bestVMin, - bestVRev, - bestVBld); - fflush(_distLog); - } - } - } // else no reply, since we have nothing to distribute - } - else { // VERB_LATEST - - if ((origin == ZT_SOFTWARE_UPDATE_SERVICE) && (_compareVersion(rvMaj, rvMin, rvRev, rvBld, ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION, ZEROTIER_ONE_VERSION_BUILD) > 0) - && (OSUtils::jsonString(req[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNED_BY], "") == ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY)) { - const unsigned long len = (unsigned long)OSUtils::jsonInt(req[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIZE], 0); - const std::string hash = OSUtils::jsonBinFromHex(req[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH]); - if ((len <= ZT_SOFTWARE_UPDATE_MAX_SIZE) && (hash.length() >= 16)) { - if (_latestMeta != req) { - _latestMeta = req; - _latestValid = false; - OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME).c_str()); - _download = std::string(); - memcpy(_downloadHashPrefix.data(), hash.data(), 16); - _downloadLength = len; - } - - if ((_downloadLength > 0) && (_download.length() < _downloadLength)) { - Buffer<128> gd; - gd.append((uint8_t)VERB_GET_DATA); - gd.append(_downloadHashPrefix.data(), 16); - gd.append((uint32_t)_download.length()); - _node.sendUserMessage((void*)0, ZT_SOFTWARE_UPDATE_SERVICE, ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE, gd.data(), gd.size()); - } - } - } - } - } - } break; - - case VERB_GET_DATA: - if ((len >= 21) && (! _dist.empty())) { - unsigned long idx = (unsigned long)*(reinterpret_cast(data) + 17) << 24; - idx |= (unsigned long)*(reinterpret_cast(data) + 18) << 16; - idx |= (unsigned long)*(reinterpret_cast(data) + 19) << 8; - idx |= (unsigned long)*(reinterpret_cast(data) + 20); - std::array shakey; - memcpy(shakey.data(), reinterpret_cast(data) + 1, 16); - std::map, _D>::iterator d(_dist.find(shakey)); - if ((d != _dist.end()) && (idx < (unsigned long)d->second.bin.length())) { - Buffer buf; - buf.append((uint8_t)VERB_DATA); - buf.append(reinterpret_cast(data) + 1, 16); - buf.append((uint32_t)idx); - buf.append(d->second.bin.data() + idx, std::min((unsigned long)ZT_SOFTWARE_UPDATE_CHUNK_SIZE, (unsigned long)(d->second.bin.length() - idx))); - _node.sendUserMessage((void*)0, origin, ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE, buf.data(), buf.size()); - } - } - break; - - case VERB_DATA: - if ((len >= 21) && (_downloadLength > 0) && (! memcmp(_downloadHashPrefix.data(), reinterpret_cast(data) + 1, 16))) { - unsigned long idx = (unsigned long)*(reinterpret_cast(data) + 17) << 24; - idx |= (unsigned long)*(reinterpret_cast(data) + 18) << 16; - idx |= (unsigned long)*(reinterpret_cast(data) + 19) << 8; - idx |= (unsigned long)*(reinterpret_cast(data) + 20); - if (idx == (unsigned long)_download.length()) { - _download.append(reinterpret_cast(data) + 21, len - 21); - if (_download.length() < _downloadLength) { - Buffer<128> gd; - gd.append((uint8_t)VERB_GET_DATA); - gd.append(_downloadHashPrefix.data(), 16); - gd.append((uint32_t)_download.length()); - _node.sendUserMessage((void*)0, ZT_SOFTWARE_UPDATE_SERVICE, ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE, gd.data(), gd.size()); - } - } - } - break; - - default: - if (_distLog) { - fprintf(_distLog, "%.10llx WARNING: bad update message verb==%u length==%u (unrecognized verb)" ZT_EOL_S, (unsigned long long)origin, (unsigned int)v, len); - fflush(_distLog); - } - break; - } - } - catch (...) { - if (_distLog) { - fprintf(_distLog, "%.10llx WARNING: bad update message verb==%u length==%u (unexpected exception, likely invalid JSON)" ZT_EOL_S, (unsigned long long)origin, (unsigned int)v, len); - fflush(_distLog); - } - } -} - -bool SoftwareUpdater::check(const int64_t now) -{ - if ((now - _lastCheckTime) >= ZT_SOFTWARE_UPDATE_CHECK_PERIOD) { - _lastCheckTime = now; - char tmp[512]; - const unsigned int len = OSUtils::ztsnprintf( - tmp, - sizeof(tmp), - "%c{\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR "\":%d," - "\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR "\":%d," - "\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION "\":%d," - "\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_BUILD "\":%d," - "\"" ZT_SOFTWARE_UPDATE_JSON_EXPECT_SIGNED_BY "\":\"%s\"," - "\"" ZT_SOFTWARE_UPDATE_JSON_PLATFORM "\":%d," - "\"" ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE "\":%d," - "\"" ZT_SOFTWARE_UPDATE_JSON_VENDOR "\":%d," - "\"" ZT_SOFTWARE_UPDATE_JSON_CHANNEL "\":\"%s\"}", - (char)VERB_GET_LATEST, - ZEROTIER_ONE_VERSION_MAJOR, - ZEROTIER_ONE_VERSION_MINOR, - ZEROTIER_ONE_VERSION_REVISION, - ZEROTIER_ONE_VERSION_BUILD, - ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY, - ZT_BUILD_PLATFORM, - ZT_BUILD_ARCHITECTURE, - (int)ZT_VENDOR_ZEROTIER, - _channel.c_str()); - _node.sendUserMessage((void*)0, ZT_SOFTWARE_UPDATE_SERVICE, ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE, tmp, len); - } - - if (_latestValid) - return true; - - if (_downloadLength > 0) { - if (_download.length() >= _downloadLength) { - // This is the very important security validation part that makes sure - // this software update doesn't have cooties. - - const std::string binPath(_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME); - try { - // (1) Check the hash itself to make sure the image is basically okay - uint8_t sha512[64]; - SHA512(sha512, _download.data(), (unsigned int)_download.length()); - char hexbuf[(64 * 2) + 2]; - if (OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH], "") == Utils::hex(sha512, 64, hexbuf)) { - // (2) Check signature by signing authority - const std::string sig(OSUtils::jsonBinFromHex(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNATURE])); - if (Identity(ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY).verify(_download.data(), (unsigned int)_download.length(), sig.data(), (unsigned int)sig.length())) { - // (3) Try to save file, and if so we are good. - OSUtils::rm(binPath.c_str()); - if (OSUtils::writeFile(binPath.c_str(), _download)) { - OSUtils::lockDownFile(binPath.c_str(), false); - _latestValid = true; - _download = std::string(); - _downloadLength = 0; - return true; - } - } - } - } - catch (...) { - } // any exception equals verification failure - - // If we get here, checks failed. - OSUtils::rm(binPath.c_str()); - _latestMeta = nlohmann::json(); - _latestValid = false; - _download = std::string(); - _downloadLength = 0; - } - else { - Buffer<128> gd; - gd.append((uint8_t)VERB_GET_DATA); - gd.append(_downloadHashPrefix.data(), 16); - gd.append((uint32_t)_download.length()); - _node.sendUserMessage((void*)0, ZT_SOFTWARE_UPDATE_SERVICE, ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE, gd.data(), gd.size()); - } - } - - return false; -} - -void SoftwareUpdater::apply() -{ - std::string updatePath(_homePath + ZT_PATH_SEPARATOR_S ZT_SOFTWARE_UPDATE_BIN_FILENAME); - if ((_latestMeta.is_object()) && (_latestValid) && (OSUtils::fileExists(updatePath.c_str(), false))) { -#ifdef __WINDOWS__ - std::string cmdArgs(OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_EXEC_ARGS], "")); - if (cmdArgs.length() > 0) { - updatePath.push_back(' '); - updatePath.append(cmdArgs); - } - STARTUPINFOA si; - PROCESS_INFORMATION pi; - memset(&si, 0, sizeof(si)); - memset(&pi, 0, sizeof(pi)); - CreateProcessA(NULL, const_cast(updatePath.c_str()), NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi); - // Windows doesn't exit here -- updater will stop the service during update, etc. -- but we do want to stop multiple runs from happening - _latestMeta = nlohmann::json(); - _latestValid = false; -#else - char* argv[256]; - unsigned long ac = 0; - argv[ac++] = const_cast(updatePath.c_str()); - const std::vector argsSplit(OSUtils::split(OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_EXEC_ARGS], "").c_str(), " ", "\\", "\"")); - for (std::vector::const_iterator a(argsSplit.begin()); a != argsSplit.end(); ++a) { - argv[ac] = const_cast(a->c_str()); - if (++ac == 255) - break; - } - argv[ac] = (char*)0; - chmod(updatePath.c_str(), 0700); - - // Close all open file descriptors except stdout/stderr/etc. - int minMyFd = STDIN_FILENO; - if (STDOUT_FILENO > minMyFd) - minMyFd = STDOUT_FILENO; - if (STDERR_FILENO > minMyFd) - minMyFd = STDERR_FILENO; - ++minMyFd; -#ifdef _SC_OPEN_MAX - int maxMyFd = (int)sysconf(_SC_OPEN_MAX); - if (maxMyFd <= minMyFd) - maxMyFd = 65536; -#else - int maxMyFd = 65536; -#endif - while (minMyFd < maxMyFd) - close(minMyFd++); - - execv(updatePath.c_str(), argv); - fprintf(stderr, "FATAL: unable to execute software update binary at %s\n", updatePath.c_str()); - exit(1); -#endif - } -} - -} // namespace ZeroTier diff --git a/service/SoftwareUpdater.hpp b/service/SoftwareUpdater.hpp deleted file mode 100644 index 18539af44..000000000 --- a/service/SoftwareUpdater.hpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2026-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#ifndef ZT_SOFTWAREUPDATER_HPP -#define ZT_SOFTWAREUPDATER_HPP - -#include "../include/ZeroTierOne.h" -#include "../node/Identity.hpp" -#include "../node/Packet.hpp" - -#include -#include -#include -#include -#include -#include -#include - -/** - * VERB_USER_MESSAGE type ID for software update messages - */ -#define ZT_SOFTWARE_UPDATE_USER_MESSAGE_TYPE 100 - -/** - * ZeroTier address of node that provides software updates - */ -#define ZT_SOFTWARE_UPDATE_SERVICE 0xb1d366e81fULL - -/** - * ZeroTier identity that must be used to sign software updates - * - * df24360f3e - update-signing-key-0010 generated Fri Jan 13th, 2017 at 4:05pm PST - */ -#define ZT_SOFTWARE_UPDATE_SIGNING_AUTHORITY "df24360f3e:0:06072642959c8dfb68312904d74d90197c8a7692697caa1b3fd769eca714f4370fab462fcee6ebcb5fffb63bc5af81f28a2514b2cd68daabb42f7352c06f21db" - -/** - * Chunk size for in-band downloads (can be changed, designed to always fit in one UDP packet easily) - */ -#define ZT_SOFTWARE_UPDATE_CHUNK_SIZE (ZT_PROTO_MAX_PACKET_LENGTH - 128) - -/** - * Sanity limit for the size of an update binary image - */ -#define ZT_SOFTWARE_UPDATE_MAX_SIZE (1024 * 1024 * 256) - -/** - * How often (ms) do we check? - */ -#define ZT_SOFTWARE_UPDATE_CHECK_PERIOD (60 * 10 * 1000) - -/** - * Default update channel - */ -#define ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL "release" - -/** - * Filename for latest update's binary image - */ -#define ZT_SOFTWARE_UPDATE_BIN_FILENAME "latest-update.exe" - -#define ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR "vMajor" -#define ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR "vMinor" -#define ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION "vRev" -#define ZT_SOFTWARE_UPDATE_JSON_VERSION_BUILD "vBuild" -#define ZT_SOFTWARE_UPDATE_JSON_PLATFORM "platform" -#define ZT_SOFTWARE_UPDATE_JSON_ARCHITECTURE "arch" -#define ZT_SOFTWARE_UPDATE_JSON_VENDOR "vendor" -#define ZT_SOFTWARE_UPDATE_JSON_CHANNEL "channel" -#define ZT_SOFTWARE_UPDATE_JSON_EXPECT_SIGNED_BY "expectedSigner" -#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNED_BY "signer" -#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIGNATURE "signature" -#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH "hash" -#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIZE "size" -#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_EXEC_ARGS "execArgs" -#define ZT_SOFTWARE_UPDATE_JSON_UPDATE_URL "url" - -namespace ZeroTier { - -class Node; - -/** - * This class handles retrieving and executing updates, or serving them - */ -class SoftwareUpdater { - public: - /** - * Each message begins with an 8-bit message verb - */ - enum MessageVerb { - /** - * Payload: JSON containing current system platform, version, etc. - */ - VERB_GET_LATEST = 1, - - /** - * Payload: JSON describing latest update for this target. (No response is sent if there is none.) - */ - VERB_LATEST = 2, - - /** - * Payload: - * <[16] first 128 bits of hash of data object> - * <[4] 32-bit index of chunk to get> - */ - VERB_GET_DATA = 3, - - /** - * Payload: - * <[16] first 128 bits of hash of data object> - * <[4] 32-bit index of chunk> - * <[...] chunk data> - */ - VERB_DATA = 4 - }; - - SoftwareUpdater(Node& node, const std::string& homePath); - ~SoftwareUpdater(); - - /** - * Set whether or not we will distribute updates - * - * @param distribute If true, scan update-dist.d now and distribute updates found there -- if false, clear and stop distributing - */ - void setUpdateDistribution(bool distribute); - - /** - * Handle a software update user message - * - * @param origin ZeroTier address of message origin - * @param data Message payload - * @param len Length of message - */ - void handleSoftwareUpdateUserMessage(uint64_t origin, const void* data, unsigned int len); - - /** - * Check for updates and do other update-related housekeeping - * - * It should be called about every 10 seconds. - * - * @return True if we've downloaded and verified an update - */ - bool check(const int64_t now); - - /** - * @return Meta-data for downloaded update or NULL if none - */ - inline const nlohmann::json& pending() const - { - return _latestMeta; - } - - /** - * Apply any ready update now - * - * Depending on the platform this function may never return and may forcibly - * exit the process. It does nothing if no update is ready. - */ - void apply(); - - /** - * Set software update channel - * - * @param channel 'release', 'beta', etc. - */ - inline void setChannel(const std::string& channel) - { - _channel = channel; - } - - private: - Node& _node; - uint64_t _lastCheckTime; - std::string _homePath; - std::string _channel; - FILE* _distLog; - - // Offered software updates if we are an update host (we have update-dist.d and update hosting is enabled) - struct _D { - nlohmann::json meta; - std::string bin; - }; - std::map, _D> _dist; // key is first 16 bytes of hash - - nlohmann::json _latestMeta; - bool _latestValid; - - std::string _download; - std::array _downloadHashPrefix; - unsigned long _downloadLength; -}; - -} // namespace ZeroTier - -#endif diff --git a/tcp-proxy/tcp-proxy.cpp b/tcp-proxy/tcp-proxy.cpp index f763306d6..c6711cb4a 100644 --- a/tcp-proxy/tcp-proxy.cpp +++ b/tcp-proxy/tcp-proxy.cpp @@ -1,19 +1,9 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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 . + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ // HACK! Will eventually use epoll() or something in Phy<> instead of select(). diff --git a/version.h b/version.h index 9c417f5b7..3cfa04ffa 100644 --- a/version.h +++ b/version.h @@ -1,15 +1,10 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #ifndef _ZT_VERSION_H #define _ZT_VERSION_H @@ -22,12 +17,12 @@ /** * Minor version */ -#define ZEROTIER_ONE_VERSION_MINOR 15 +#define ZEROTIER_ONE_VERSION_MINOR 16 /** * Revision */ -#define ZEROTIER_ONE_VERSION_REVISION 2 +#define ZEROTIER_ONE_VERSION_REVISION 0 /** * Build version diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index cfd16407f..3c6f66e33 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -39,12 +39,6 @@ - - - - - - @@ -101,6 +95,14 @@ + + + + + + + + false false @@ -132,7 +134,6 @@ true - @@ -157,13 +158,6 @@ - - - - - - - @@ -228,6 +222,16 @@ + + + + + + + + + + @@ -240,7 +244,6 @@ - diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index 9f05b729a..8c30bf323 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -70,21 +70,27 @@ {409ec37e-ff36-4c13-b18d-52d6052e0ca2} - - {3cad34c8-c436-43ae-8323-57803637c832} - {ff20532b-d9a2-440d-a7b4-b49e26a9b2f8} {05d9cde8-03ae-4e37-b9f7-7417de98cbe9} - - {7dc22e9c-f869-41e7-b43d-f07f5b94f6fb} - {4dfde4c7-2950-40ee-92f2-05e0916d36c5} + + {87126f8c-5daf-46cb-9d94-36a6993fb058} + + + {d05823b2-51ff-4383-ba81-2e7c53a30c0b} + + + {0f51b1ae-6141-41b8-b7a1-ac700e78b13d} + + + {50dfe57d-a749-40c2-ac5a-30614e56c424} + @@ -231,12 +237,6 @@ Source Files\node - - Source Files\controller - - - Source Files\service - Source Files\node @@ -249,21 +249,6 @@ Source Files\node - - Source Files\controller - - - Source Files\controller - - - Source Files\controller - - - Source Files\controller - - - Source Files\controller - Source Files\osdep @@ -297,6 +282,30 @@ Source Files\node + + Source Files\nonfree\controller + + + Source Files\nonfree\controller + + + Source Files\nonfree\controller + + + Source Files\nonfree\controller + + + Source Files\nonfree\controller + + + Source Files\nonfree\controller + + + Source Files\nonfree\controller + + + Source Files\nonfree\controller + @@ -503,9 +512,6 @@ Header Files\osdep - - Header Files\service - Header Files\ext\json @@ -518,33 +524,15 @@ Header Files\ext\x64-salsa2012-asm - - Header Files\controller - Header Files\node - - Header Files\controller - - - Header Files\controller - Header Files\node - - Header Files\controller - - - Header Files\controller - Header Files\ext\cpp-httplib - - Header Files\controller - Header Files\osdep @@ -554,9 +542,6 @@ Header Files\node - - Header Files\controller - Header Files\osdep @@ -566,6 +551,36 @@ Header Files\node + + Header Files\nonfree\controller + + + Header Files\nonfree\controller + + + Header Files\nonfree\controller + + + Header Files\nonfree\controller + + + Header Files\nonfree\controller + + + Header Files\nonfree\controller + + + Header Files\nonfree\controller + + + Header Files\nonfree\controller + + + Header Files\nonfree\controller + + + Header Files\nonfree\controller + diff --git a/windows/ZeroTierOne/ZeroTierOneService.cpp b/windows/ZeroTierOne/ZeroTierOneService.cpp index 033a9d219..8af4eb878 100644 --- a/windows/ZeroTierOne/ZeroTierOneService.cpp +++ b/windows/ZeroTierOne/ZeroTierOneService.cpp @@ -1,50 +1,42 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #pragma region Includes #if defined(_WIN32) || defined(_WIN64) -#include -#include -#include -#include - #include "ZeroTierOneService.h" -#include "../../version.h" #include "../../include/ZeroTierOne.h" - #include "../../node/Constants.hpp" #include "../../node/Utils.hpp" #include "../../osdep/OSUtils.hpp" #include "../../service/OneService.hpp" +#include "../../version.h" -#pragma endregion // Includes +#include +#include +#include +#include + +#pragma endregion // Includes #ifdef ZT_DEBUG_SERVICE -FILE *SVCDBGfile = (FILE *)0; +FILE* SVCDBGfile = (FILE*)0; ZeroTier::Mutex SVCDBGfile_m; #endif -ZeroTierOneService::ZeroTierOneService() : - CServiceBase(ZT_SERVICE_NAME,TRUE,TRUE,FALSE), - _service((ZeroTier::OneService *)0) +ZeroTierOneService::ZeroTierOneService() : CServiceBase(ZT_SERVICE_NAME, TRUE, TRUE, FALSE), _service((ZeroTier::OneService*)0) { #ifdef ZT_DEBUG_SERVICE SVCDBGfile_m.lock(); - if (!SVCDBGfile) - SVCDBGfile = fopen(ZT_DEBUG_SERVICE,"a"); + if (! SVCDBGfile) + SVCDBGfile = fopen(ZT_DEBUG_SERVICE, "a"); SVCDBGfile_m.unlock(); #endif @@ -59,14 +51,13 @@ ZeroTierOneService::~ZeroTierOneService(void) SVCDBGfile_m.lock(); if (SVCDBGfile) { fclose(SVCDBGfile); - SVCDBGfile = (FILE *)0; + SVCDBGfile = (FILE*)0; } SVCDBGfile_m.unlock(); #endif } -void ZeroTierOneService::threadMain() - throw() +void ZeroTierOneService::threadMain() throw() { ZT_SVCDBG("ZeroTierOneService::threadMain()\r\n"); @@ -75,38 +66,41 @@ restart_node: { ZeroTier::Mutex::Lock _l(_lock); delete _service; - _service = (ZeroTier::OneService *)0; // in case newInstance() fails + _service = (ZeroTier::OneService*)0; // in case newInstance() fails _service = ZeroTier::OneService::newInstance(_path.c_str(), ZT_DEFAULT_PORT); } - switch(_service->run()) { + switch (_service->run()) { case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR: { std::string err("ZeroTier One encountered an unrecoverable error: "); err.append(_service->fatalErrorMessage()); err.append(" (restarting in 5 seconds)"); - WriteEventLogEntry(const_cast (err.c_str()),EVENTLOG_ERROR_TYPE); + WriteEventLogEntry(const_cast(err.c_str()), EVENTLOG_ERROR_TYPE); Sleep(5000); - } goto restart_node; + } + goto restart_node; case ZeroTier::OneService::ONE_IDENTITY_COLLISION: { std::string homeDir(ZeroTier::OneService::platformDefaultHomePath()); delete _service; - _service = (ZeroTier::OneService *)0; + _service = (ZeroTier::OneService*)0; std::string oldid; - ZeroTier::OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid); + ZeroTier::OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(), oldid); if (oldid.length()) { - ZeroTier::OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid); + ZeroTier::OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(), oldid); ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str()); ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str()); } - } goto restart_node; + } + goto restart_node; - default: // normal termination + default: // normal termination break; } - } catch ( ... ) { + } + catch (...) { // sanity check, shouldn't happen since Node::run() should catch all its own errors // could also happen if we're out of memory though! - WriteEventLogEntry("unexpected exception (out of memory?) (trying again in 5 seconds)",EVENTLOG_ERROR_TYPE); + WriteEventLogEntry("unexpected exception (out of memory?) (trying again in 5 seconds)", EVENTLOG_ERROR_TYPE); Sleep(5000); goto restart_node; } @@ -114,23 +108,25 @@ restart_node: { ZeroTier::Mutex::Lock _l(_lock); delete _service; - _service = (ZeroTier::OneService *)0; + _service = (ZeroTier::OneService*)0; } } -void ZeroTierOneService::OnStart(DWORD dwArgc, PSTR *lpszArgv) +void ZeroTierOneService::OnStart(DWORD dwArgc, PSTR* lpszArgv) { ZT_SVCDBG("ZeroTierOneService::OnStart()\r\n"); - if ((dwArgc > 1)&&(lpszArgv[1])&&(strlen(lpszArgv[1]) > 0)) { + if ((dwArgc > 1) && (lpszArgv[1]) && (strlen(lpszArgv[1]) > 0)) { this->_path = lpszArgv[1]; - } else { + } + else { this->_path = ZeroTier::OneService::platformDefaultHomePath(); } try { _thread = ZeroTier::Thread::start(this); - } catch ( ... ) { + } + catch (...) { throw (DWORD)ERROR_EXCEPTION_IN_SERVICE; } } @@ -140,7 +136,7 @@ void ZeroTierOneService::OnStop() ZT_SVCDBG("ZeroTierOneService::OnStop()\r\n"); _lock.lock(); - ZeroTier::OneService *s = _service; + ZeroTier::OneService* s = _service; _lock.unlock(); if (s) { diff --git a/windows/ZeroTierOne/ZeroTierOneService.h b/windows/ZeroTierOne/ZeroTierOneService.h index 8fe20996a..d6ccbeefe 100644 --- a/windows/ZeroTierOne/ZeroTierOneService.h +++ b/windows/ZeroTierOne/ZeroTierOneService.h @@ -1,69 +1,68 @@ -/* - * Copyright (c)2019 ZeroTier, Inc. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. * - * 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. + * (c) ZeroTier, Inc. + * https://www.zerotier.com/ */ -/****/ #pragma once #if defined(_WIN32) || defined(_WIN64) -#include - -#include "ServiceBase.h" - -#include - #include "../../node/Mutex.hpp" #include "../../osdep/Thread.hpp" #include "../../service/OneService.hpp" +#include "ServiceBase.h" + +#include +#include // Uncomment to make debugging Windows services suck slightly less hard. -//#define ZT_DEBUG_SERVICE "C:\\ZeroTierOneServiceDebugLog.txt" +// #define ZT_DEBUG_SERVICE "C:\\ZeroTierOneServiceDebugLog.txt" #ifdef ZT_DEBUG_SERVICE -extern FILE *SVCDBGfile; +extern FILE* SVCDBGfile; extern ZeroTier::Mutex SVCDBGfile_m; -#define ZT_SVCDBG(f,...) { SVCDBGfile_m.lock(); fprintf(SVCDBGfile,f,##__VA_ARGS__); fflush(SVCDBGfile); SVCDBGfile_m.unlock(); } +#define ZT_SVCDBG(f, ...) \ + { \ + SVCDBGfile_m.lock(); \ + fprintf(SVCDBGfile, f, ##__VA_ARGS__); \ + fflush(SVCDBGfile); \ + SVCDBGfile_m.unlock(); \ + } #else -#define ZT_SVCDBG(f,...) {} +#define ZT_SVCDBG(f, ...) \ + { \ + } #endif -#define ZT_SERVICE_NAME "ZeroTierOneService" +#define ZT_SERVICE_NAME "ZeroTierOneService" #define ZT_SERVICE_DISPLAY_NAME "ZeroTier One" -#define ZT_SERVICE_START_TYPE SERVICE_AUTO_START +#define ZT_SERVICE_START_TYPE SERVICE_AUTO_START #define ZT_SERVICE_DEPENDENCIES "" -//#define ZT_SERVICE_ACCOUNT "NT AUTHORITY\\LocalService" -#define ZT_SERVICE_ACCOUNT NULL +// #define ZT_SERVICE_ACCOUNT "NT AUTHORITY\\LocalService" +#define ZT_SERVICE_ACCOUNT NULL #define ZT_SERVICE_PASSWORD NULL -class ZeroTierOneService : public CServiceBase -{ -public: - ZeroTierOneService(); - virtual ~ZeroTierOneService(void); +class ZeroTierOneService : public CServiceBase { + public: + ZeroTierOneService(); + virtual ~ZeroTierOneService(void); /** * Thread main method; do not call elsewhere */ - void threadMain() - throw(); + void threadMain() throw(); -protected: - virtual void OnStart(DWORD dwArgc, PSTR *pszArgv); + protected: + virtual void OnStart(DWORD dwArgc, PSTR* pszArgv); virtual void OnStop(); virtual void OnShutdown(); -private: + private: std::string _path; - ZeroTier::OneService *volatile _service; + ZeroTier::OneService* volatile _service; ZeroTier::Mutex _lock; ZeroTier::Thread _thread; }; diff --git a/zerotier-one.spec b/zerotier-one.spec index 655068bf6..5d24c2366 100644 --- a/zerotier-one.spec +++ b/zerotier-one.spec @@ -1,9 +1,9 @@ Name: zerotier-one -Version: 1.14.2 +Version: 1.16.0 Release: 1%{?dist} Summary: ZeroTier network virtualization service -License: ZeroTier BUSL 1.1 +License: MPL 2.0 URL: https://www.zerotier.com # Fedora