mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-03-12 04:36:29 -07:00
Merge branch 'edge' of http://git.int.zerotier.com/zerotier/ZeroTierOne into edge
This commit is contained in:
commit
8e1a88c2fb
.gitignore
.idea
.gitignoreZeroTierOne.iml
CMakeLists.txtcodeStyles
dictionaries
inspectionProfiles
misc.xmlmodules.xmlvcs.xmlwatcherTasks.xmlattic
Binder.hppHttp.cppHttp.hppPhy.hppPortMapper-libnatpmp.cPortMapper-miniupnpc.cPortMapper.cppPortMapper.hppRoot.hpplinux-old-glibc-compat.clistaddrinfo.goone.cpp
webview
controller
go
include
node
AES-aesni.cAES.cppAES.hppAddress.hppAtomicCounter.hppBuf.cppBuf.hppC25519.cppC25519.hppCMakeLists.txtCapability.hppCertificateOfMembership.hppCertificateOfOwnership.hppConstants.hppCredential.cppCredential.hppDictionary.hppECC384.cppEndpoint.hppHashtable.hppIdentity.cppIdentity.hppIncomingPacket.cppIncomingPacket.hppInetAddress.cppInetAddress.hppLocator.cpp
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,5 +1,9 @@
|
||||
build/
|
||||
/build
|
||||
/cmake-build-debug
|
||||
/cmake-build-release
|
||||
/version.h
|
||||
/.idea
|
||||
/go/.idea
|
||||
.DS_Store
|
||||
.Trashes
|
||||
*.swp
|
||||
|
3
.idea/.gitignore
generated
vendored
3
.idea/.gitignore
generated
vendored
@ -1,3 +0,0 @@
|
||||
|
||||
# Default ignored files
|
||||
/workspace.xml
|
9
.idea/ZeroTierOne.iml
generated
9
.idea/ZeroTierOne.iml
generated
@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="Go" enabled="true" />
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
5
.idea/codeStyles/codeStyleConfig.xml
generated
@ -1,5 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
11
.idea/dictionaries/api.xml
generated
11
.idea/dictionaries/api.xml
generated
@ -1,11 +0,0 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="api">
|
||||
<words>
|
||||
<w>apisocket</w>
|
||||
<w>nwid</w>
|
||||
<w>secrand</w>
|
||||
<w>sockaddr</w>
|
||||
<w>unmarshals</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
10
.idea/inspectionProfiles/Project_Default.xml
generated
10
.idea/inspectionProfiles/Project_Default.xml
generated
@ -1,10 +0,0 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
6
.idea/misc.xml
generated
6
.idea/misc.xml
generated
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
</project>
|
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/ZeroTierOne.iml" filepath="$PROJECT_DIR$/.idea/ZeroTierOne.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
29
.idea/watcherTasks.xml
generated
29
.idea/watcherTasks.xml
generated
@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectTasksOptions">
|
||||
<TaskOptions isEnabled="true">
|
||||
<option name="arguments" value="fmt $FilePath$" />
|
||||
<option name="checkSyntaxErrors" value="true" />
|
||||
<option name="description" />
|
||||
<option name="exitCodeBehavior" value="ERROR" />
|
||||
<option name="fileExtension" value="go" />
|
||||
<option name="immediateSync" value="false" />
|
||||
<option name="name" value="go fmt" />
|
||||
<option name="output" value="$FilePath$" />
|
||||
<option name="outputFilters">
|
||||
<array />
|
||||
</option>
|
||||
<option name="outputFromStdout" value="false" />
|
||||
<option name="program" value="$GoExecPath$" />
|
||||
<option name="runOnExternalChanges" value="false" />
|
||||
<option name="scopeName" value="Project Files" />
|
||||
<option name="trackOnlyRoot" value="true" />
|
||||
<option name="workingDir" value="$ProjectFileDir$" />
|
||||
<envs>
|
||||
<env name="GOROOT" value="$GOROOT$" />
|
||||
<env name="GOPATH" value="$GOPATH$" />
|
||||
<env name="PATH" value="$GoBinDirs$" />
|
||||
</envs>
|
||||
</TaskOptions>
|
||||
</component>
|
||||
</project>
|
@ -1,4 +1,5 @@
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
project(zerotier DESCRIPTION "ZeroTier Network Hypervisor" LANGUAGES CXX C)
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.15)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
@ -7,33 +8,32 @@ else()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# If building on Windows, set minimum target to Windows 7
|
||||
set(CMAKE_SYSTEM_VERSION "7" CACHE STRING INTERNAL FORCE)
|
||||
endif(WIN32)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X Deployment Version")
|
||||
|
||||
set(ZEROTIER_ONE_VERSION_MAJOR 2 CACHE INTERNAL "")
|
||||
set(ZEROTIER_ONE_VERSION_MINOR 0 CACHE INTERNAL "")
|
||||
set(ZEROTIER_ONE_VERSION_REVISION 0 CACHE INTERNAL "")
|
||||
set(ZEROTIER_ONE_VERSION_BUILD 0 CACHE INTERNAL "")
|
||||
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/version.h.in
|
||||
${CMAKE_BINARY_DIR}/version.h
|
||||
)
|
||||
|
||||
set(default_build_type "Release")
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
set(default_build_type "Debug")
|
||||
endif()
|
||||
#if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
# set(default_build_type "Debug")
|
||||
#endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
|
||||
STRING "Choose the type of build." FORCE)
|
||||
# Set the possible values of build type for cmake-gui
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
option(BUILD_CENTRAL_CONTROLLER "Build ZeroTier Central Controller" OFF)
|
||||
option(ZT_TRACE "Trace Messages" OFF)
|
||||
option(ZT_DEBUG_TRACE "Debug Trace Messages" OFF)
|
||||
|
||||
if (BUILD_CENTRAL_CONTROLLER)
|
||||
find_package(PostgreSQL REQUIRED)
|
||||
set(ENABLE_SSL_SUPPORT OFF)
|
||||
@ -45,25 +45,21 @@ if (BUILD_CENTRAL_CONTROLLER)
|
||||
add_subdirectory("ext/librabbitmq")
|
||||
endif(BUILD_CENTRAL_CONTROLLER)
|
||||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X Deployment Version")
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_definitions(-DZT_TRACE)
|
||||
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
|
||||
project(zerotier
|
||||
DESCRIPTION "ZeroTier Network Hypervisor"
|
||||
LANGUAGES CXX C)
|
||||
|
||||
if(WIN32)
|
||||
message("++ Setting Windows Compiler Flags ${CMAKE_BUILD_TYPE}")
|
||||
add_definitions(-DNOMINMAX)
|
||||
else(WIN32)
|
||||
if(APPLE)
|
||||
|
||||
message("Setting macOS Compiler Flags ${CMAKE_BUILD_TYPE}")
|
||||
message("++ Setting MacOS Compiler Flags ${CMAKE_BUILD_TYPE}")
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wno-deprecated
|
||||
-Wno-unused-function
|
||||
-mmacosx-version-min=10.9
|
||||
$<$<CONFIG:Debug>:-g>
|
||||
$<$<CONFIG:DEBUG>:-O0>
|
||||
@ -79,17 +75,13 @@ else(WIN32)
|
||||
$<$<CONFIG:RELEASE>:-flto>
|
||||
)
|
||||
|
||||
elseif (
|
||||
CMAKE_SYSTEM_NAME MATCHES "Linux" OR
|
||||
CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR
|
||||
CMAKE_SYSTEM_NAME MATCHES "OpenBSD" OR
|
||||
CMAKE_SYSTEM_NAME MATCHES "NetBSD"
|
||||
)
|
||||
else(APPLE)
|
||||
|
||||
message("Setting Linux/BSD Compiler Flags (${CMAKE_BUILD_TYPE})")
|
||||
message("++ Setting Linux/BSD/Posix Compiler Flags (${CMAKE_BUILD_TYPE})")
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wno-deprecated
|
||||
-Wno-unused-function
|
||||
$<$<CONFIG:Debug>:-g>
|
||||
$<$<CONFIG:DEBUG>:-O0>
|
||||
$<$<CONFIG:RELEASE>:-O3>
|
||||
@ -110,10 +102,9 @@ if (
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "i586" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "i686"
|
||||
)
|
||||
message("Adding SSE and AES-NI flags for processor ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
message("++ Adding SSE and AES-NI flags for processor ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
add_compile_options(
|
||||
-maes
|
||||
-mmmx
|
||||
-mrdrnd
|
||||
-mpclmul
|
||||
-msse
|
||||
@ -126,9 +117,6 @@ endif()
|
||||
if(ZT_TRACE)
|
||||
add_definitions(-DZT_TRACE)
|
||||
endif()
|
||||
if(ZT_DEBUG_TRACE)
|
||||
add_definitions(-DZT_DEBUG_TRACE)
|
||||
endif()
|
||||
|
||||
add_subdirectory(node)
|
||||
add_subdirectory(controller)
|
||||
@ -136,12 +124,6 @@ add_subdirectory(osdep)
|
||||
add_subdirectory(root)
|
||||
add_subdirectory(go/native)
|
||||
|
||||
#if(WIN32)
|
||||
# add_subdirectory("windows/WinUI")
|
||||
# add_subdirectory("windows/copyutil")
|
||||
# add_definitions(-DNOMINMAX)
|
||||
#endif(WIN32)
|
||||
|
||||
set(
|
||||
zt_osdep
|
||||
zt_core
|
||||
@ -149,25 +131,18 @@ set(
|
||||
zt_go_native
|
||||
)
|
||||
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/version.h.in
|
||||
${CMAKE_BINARY_DIR}/version.h
|
||||
)
|
||||
|
||||
#set(src
|
||||
# one.cpp
|
||||
# "ext/http-parser/http_parser.c"
|
||||
#)
|
||||
#set(headers
|
||||
# "ext/http-parser/http_parser.h"
|
||||
#)
|
||||
|
||||
if(WIN32)
|
||||
set(libs ${libs} wsock32 ws2_32 rpcrt4 iphlpapi)
|
||||
else(WIN32)
|
||||
set(libs ${libs} pthread)
|
||||
endif(WIN32)
|
||||
|
||||
#if(WIN32)
|
||||
# add_subdirectory("windows/WinUI")
|
||||
# add_subdirectory("windows/copyutil")
|
||||
# add_definitions(-DNOMINMAX)
|
||||
#endif(WIN32)
|
||||
|
||||
#if(WIN32)
|
||||
# set(libs ${libs} wsock32 ws2_32 rpcrt4 iphlpapi)
|
||||
# set(src
|
||||
@ -203,6 +178,6 @@ add_custom_command(
|
||||
)
|
||||
add_custom_target(build_zerotier ALL DEPENDS zerotier)
|
||||
|
||||
add_executable(zerotier-selftest selftest.cpp)
|
||||
target_link_libraries(zerotier-selftest ${libs} zt_core zt_osdep)
|
||||
target_compile_features(zerotier-selftest PUBLIC cxx_std_11)
|
||||
#add_executable(zerotier-selftest selftest.cpp)
|
||||
#target_link_libraries(zerotier-selftest ${libs} zt_core zt_osdep)
|
||||
#target_compile_features(zerotier-selftest PUBLIC cxx_std_11)
|
||||
|
461
attic/Binder.hpp
461
attic/Binder.hpp
@ -1,461 +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: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#ifndef ZT_BINDER_HPP
|
||||
#define ZT_BINDER_HPP
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#include <ShlObj.h>
|
||||
#include <netioapi.h>
|
||||
#include <iphlpapi.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <ifaddrs.h>
|
||||
#ifdef __LINUX__
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <atomic>
|
||||
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
|
||||
#include "Phy.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__))
|
||||
#define ZT_UDP_DESIRED_BUF_SIZE 1048576
|
||||
#else
|
||||
#define ZT_UDP_DESIRED_BUF_SIZE 131072
|
||||
#endif
|
||||
|
||||
// Period between refreshes of bindings
|
||||
#define ZT_BINDER_REFRESH_PERIOD 30000
|
||||
|
||||
// Max number of bindings
|
||||
#define ZT_BINDER_MAX_BINDINGS 256
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Enumerates local devices and binds to all potential ZeroTier path endpoints
|
||||
*
|
||||
* This replaces binding to wildcard (0.0.0.0 and ::0) with explicit binding
|
||||
* as part of the path to default gateway support. Under the hood it uses
|
||||
* different queries on different OSes to enumerate devices, and also exposes
|
||||
* device enumeration and endpoint IP data for use elsewhere.
|
||||
*
|
||||
* On OSes that do not support local port enumeration or where this is not
|
||||
* meaningful, this degrades to binding to wildcard.
|
||||
*/
|
||||
class Binder
|
||||
{
|
||||
private:
|
||||
struct _Binding
|
||||
{
|
||||
_Binding() : udpSock((PhySocket *)0),tcpListenSock((PhySocket *)0) {}
|
||||
PhySocket *udpSock;
|
||||
PhySocket *tcpListenSock;
|
||||
InetAddress address;
|
||||
};
|
||||
|
||||
public:
|
||||
Binder() : _bindingCount(0) {}
|
||||
|
||||
/**
|
||||
* Close all bound ports, should be called on shutdown
|
||||
*
|
||||
* @param phy Physical interface
|
||||
*/
|
||||
template<typename PHY_HANDLER_TYPE>
|
||||
void closeAll(Phy<PHY_HANDLER_TYPE> &phy)
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
for(unsigned int b=0,c=_bindingCount;b<c;++b) {
|
||||
phy.close(_bindings[b].udpSock,false);
|
||||
phy.close(_bindings[b].tcpListenSock,false);
|
||||
}
|
||||
_bindingCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan local devices and addresses and rebind TCP and UDP
|
||||
*
|
||||
* This should be called after wake from sleep, on detected network device
|
||||
* changes, on startup, or periodically (e.g. every 30-60s).
|
||||
*
|
||||
* @param phy Physical interface
|
||||
* @param ports Ports to bind on all interfaces
|
||||
* @param portCount Number of ports
|
||||
* @param explicitBind If present, override interface IP detection and bind to these (if possible)
|
||||
* @param ifChecker Interface checker function to see if an interface should be used
|
||||
* @tparam PHY_HANDLER_TYPE Type for Phy<> template
|
||||
* @tparam INTERFACE_CHECKER Type for class containing shouldBindInterface() method
|
||||
*/
|
||||
template<typename PHY_HANDLER_TYPE,typename INTERFACE_CHECKER>
|
||||
void refresh(Phy<PHY_HANDLER_TYPE> &phy,unsigned int *ports,unsigned int portCount,const std::vector<InetAddress> explicitBind,INTERFACE_CHECKER &ifChecker)
|
||||
{
|
||||
std::map<InetAddress,std::string> localIfAddrs;
|
||||
PhySocket *udps,*tcps;
|
||||
Mutex::Lock _l(_lock);
|
||||
bool interfacesEnumerated = true;
|
||||
|
||||
if (explicitBind.empty()) {
|
||||
#ifdef __WINDOWS__
|
||||
|
||||
char aabuf[32768];
|
||||
ULONG aalen = sizeof(aabuf);
|
||||
if (GetAdaptersAddresses(AF_UNSPEC,GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER,(void *)0,reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf),&aalen) == NO_ERROR) {
|
||||
PIP_ADAPTER_ADDRESSES a = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf);
|
||||
while (a) {
|
||||
PIP_ADAPTER_UNICAST_ADDRESS ua = a->FirstUnicastAddress;
|
||||
while (ua) {
|
||||
InetAddress ip(ua->Address.lpSockaddr);
|
||||
if (ifChecker.shouldBindInterface("",ip)) {
|
||||
switch(ip.ipScope()) {
|
||||
default: break;
|
||||
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
||||
case InetAddress::IP_SCOPE_GLOBAL:
|
||||
case InetAddress::IP_SCOPE_SHARED:
|
||||
case InetAddress::IP_SCOPE_PRIVATE:
|
||||
for(int x=0;x<(int)portCount;++x) {
|
||||
ip.setPort(ports[x]);
|
||||
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
ua = ua->Next;
|
||||
}
|
||||
a = a->Next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
interfacesEnumerated = false;
|
||||
}
|
||||
|
||||
#else // not __WINDOWS__
|
||||
|
||||
/* On Linux we use an alternative method if available since getifaddrs()
|
||||
* gets very slow when there are lots of network namespaces. This won't
|
||||
* work unless /proc/PID/net/if_inet6 exists and it may not on some
|
||||
* embedded systems, so revert to getifaddrs() there. */
|
||||
|
||||
#ifdef __LINUX__
|
||||
char fn[256],tmp[256];
|
||||
std::set<std::string> ifnames;
|
||||
const unsigned long pid = (unsigned long)getpid();
|
||||
|
||||
// Get all device names
|
||||
OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid);
|
||||
FILE *procf = fopen(fn,"r");
|
||||
if (procf) {
|
||||
while (fgets(tmp,sizeof(tmp),procf)) {
|
||||
tmp[255] = 0;
|
||||
char *saveptr = (char *)0;
|
||||
for(char *f=Utils::stok(tmp," \t\r\n:|",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n:|",&saveptr)) {
|
||||
if ((strcmp(f,"Inter-") != 0)&&(strcmp(f,"face") != 0)&&(f[0] != 0))
|
||||
ifnames.insert(f);
|
||||
break; // we only want the first field
|
||||
}
|
||||
}
|
||||
fclose(procf);
|
||||
}
|
||||
else {
|
||||
interfacesEnumerated = false;
|
||||
}
|
||||
|
||||
// Get IPv6 addresses (and any device names we don't already know)
|
||||
OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid);
|
||||
procf = fopen(fn,"r");
|
||||
if (procf) {
|
||||
while (fgets(tmp,sizeof(tmp),procf)) {
|
||||
tmp[255] = 0;
|
||||
char *saveptr = (char *)0;
|
||||
unsigned char ipbits[16];
|
||||
memset(ipbits,0,sizeof(ipbits));
|
||||
char *devname = (char *)0;
|
||||
int n = 0;
|
||||
for(char *f=Utils::stok(tmp," \t\r\n",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n",&saveptr)) {
|
||||
switch(n++) {
|
||||
case 0: // IP in hex
|
||||
Utils::unhex(f,32,ipbits,16);
|
||||
break;
|
||||
case 5: // device name
|
||||
devname = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (devname) {
|
||||
ifnames.insert(devname);
|
||||
InetAddress ip(ipbits,16,0);
|
||||
if (ifChecker.shouldBindInterface(devname,ip)) {
|
||||
switch(ip.ipScope()) {
|
||||
default: break;
|
||||
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
||||
case InetAddress::IP_SCOPE_GLOBAL:
|
||||
case InetAddress::IP_SCOPE_SHARED:
|
||||
case InetAddress::IP_SCOPE_PRIVATE:
|
||||
for(int x=0;x<(int)portCount;++x) {
|
||||
ip.setPort(ports[x]);
|
||||
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string(devname)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(procf);
|
||||
}
|
||||
|
||||
// Get IPv4 addresses for each device
|
||||
if (ifnames.size() > 0) {
|
||||
const int controlfd = (int)socket(AF_INET,SOCK_DGRAM,0);
|
||||
struct ifconf configuration;
|
||||
configuration.ifc_len = 0;
|
||||
configuration.ifc_buf = nullptr;
|
||||
|
||||
if (controlfd < 0) goto ip4_address_error;
|
||||
if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error;
|
||||
configuration.ifc_buf = (char*)malloc(configuration.ifc_len);
|
||||
if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error;
|
||||
|
||||
for (int i=0; i < (int)(configuration.ifc_len / sizeof(ifreq)); i ++) {
|
||||
struct ifreq& request = configuration.ifc_req[i];
|
||||
struct sockaddr* addr = &request.ifr_ifru.ifru_addr;
|
||||
if (addr->sa_family != AF_INET) continue;
|
||||
std::string ifname = request.ifr_ifrn.ifrn_name;
|
||||
// name can either be just interface name or interface name followed by ':' and arbitrary label
|
||||
if (ifname.find(':') != std::string::npos)
|
||||
ifname = ifname.substr(0, ifname.find(':'));
|
||||
|
||||
InetAddress ip(&(((struct sockaddr_in *)addr)->sin_addr),4,0);
|
||||
if (ifChecker.shouldBindInterface(ifname.c_str(), ip)) {
|
||||
switch(ip.ipScope()) {
|
||||
default: break;
|
||||
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
||||
case InetAddress::IP_SCOPE_GLOBAL:
|
||||
case InetAddress::IP_SCOPE_SHARED:
|
||||
case InetAddress::IP_SCOPE_PRIVATE:
|
||||
for(int x=0;x<(int)portCount;++x) {
|
||||
ip.setPort(ports[x]);
|
||||
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,ifname));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ip4_address_error:
|
||||
free(configuration.ifc_buf);
|
||||
if (controlfd > 0) close(controlfd);
|
||||
}
|
||||
|
||||
const bool gotViaProc = (localIfAddrs.size() > 0);
|
||||
#else
|
||||
const bool gotViaProc = false;
|
||||
#endif
|
||||
#if !defined(ZT_SDK) || !defined(__ANDROID__) // getifaddrs() freeifaddrs() not available on Android
|
||||
if (!gotViaProc) {
|
||||
struct ifaddrs *ifatbl = (struct ifaddrs *)0;
|
||||
struct ifaddrs *ifa;
|
||||
if ((getifaddrs(&ifatbl) == 0)&&(ifatbl)) {
|
||||
ifa = ifatbl;
|
||||
while (ifa) {
|
||||
if ((ifa->ifa_name)&&(ifa->ifa_addr)) {
|
||||
InetAddress ip = *(ifa->ifa_addr);
|
||||
if (ifChecker.shouldBindInterface(ifa->ifa_name,ip)) {
|
||||
switch(ip.ipScope()) {
|
||||
default: break;
|
||||
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
||||
case InetAddress::IP_SCOPE_GLOBAL:
|
||||
case InetAddress::IP_SCOPE_SHARED:
|
||||
case InetAddress::IP_SCOPE_PRIVATE:
|
||||
for(int x=0;x<(int)portCount;++x) {
|
||||
ip.setPort(ports[x]);
|
||||
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string(ifa->ifa_name)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ifa = ifa->ifa_next;
|
||||
}
|
||||
freeifaddrs(ifatbl);
|
||||
}
|
||||
else {
|
||||
interfacesEnumerated = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
} else {
|
||||
for(std::vector<InetAddress>::const_iterator i(explicitBind.begin());i!=explicitBind.end();++i)
|
||||
localIfAddrs.insert(std::pair<InetAddress,std::string>(*i,std::string()));
|
||||
}
|
||||
|
||||
// Default to binding to wildcard if we can't enumerate addresses
|
||||
if (!interfacesEnumerated && localIfAddrs.empty()) {
|
||||
for(int x=0;x<(int)portCount;++x) {
|
||||
localIfAddrs.insert(std::pair<InetAddress,std::string>(InetAddress((uint32_t)0,ports[x]),std::string()));
|
||||
localIfAddrs.insert(std::pair<InetAddress,std::string>(InetAddress((const void *)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",16,ports[x]),std::string()));
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned int oldBindingCount = _bindingCount;
|
||||
_bindingCount = 0;
|
||||
|
||||
// Save bindings that are still valid, close those that are not
|
||||
for(unsigned int b=0;b<oldBindingCount;++b) {
|
||||
if (localIfAddrs.find(_bindings[b].address) != localIfAddrs.end()) {
|
||||
if (_bindingCount != b)
|
||||
_bindings[(unsigned int)_bindingCount] = _bindings[b];
|
||||
++_bindingCount;
|
||||
} else {
|
||||
PhySocket *const udps = _bindings[b].udpSock;
|
||||
PhySocket *const tcps = _bindings[b].tcpListenSock;
|
||||
_bindings[b].udpSock = (PhySocket *)0;
|
||||
_bindings[b].tcpListenSock = (PhySocket *)0;
|
||||
phy.close(udps,false);
|
||||
phy.close(tcps,false);
|
||||
}
|
||||
}
|
||||
|
||||
// Create new bindings for those not already bound
|
||||
for(std::map<InetAddress,std::string>::const_iterator ii(localIfAddrs.begin());ii!=localIfAddrs.end();++ii) {
|
||||
unsigned int bi = 0;
|
||||
while (bi != _bindingCount) {
|
||||
if (_bindings[bi].address == ii->first)
|
||||
break;
|
||||
++bi;
|
||||
}
|
||||
if (bi == _bindingCount) {
|
||||
udps = phy.udpBind(reinterpret_cast<const struct sockaddr *>(&(ii->first)),(void *)0,ZT_UDP_DESIRED_BUF_SIZE);
|
||||
tcps = phy.tcpListen(reinterpret_cast<const struct sockaddr *>(&(ii->first)),(void *)0);
|
||||
if ((udps)&&(tcps)) {
|
||||
#ifdef __LINUX__
|
||||
// Bind Linux sockets to their device so routes that we manage do not override physical routes (wish all platforms had this!)
|
||||
if (ii->second.length() > 0) {
|
||||
char tmp[256];
|
||||
Utils::scopy(tmp,sizeof(tmp),ii->second.c_str());
|
||||
int fd = (int)Phy<PHY_HANDLER_TYPE>::getDescriptor(udps);
|
||||
if (fd >= 0)
|
||||
setsockopt(fd,SOL_SOCKET,SO_BINDTODEVICE,tmp,strlen(tmp));
|
||||
fd = (int)Phy<PHY_HANDLER_TYPE>::getDescriptor(tcps);
|
||||
if (fd >= 0)
|
||||
setsockopt(fd,SOL_SOCKET,SO_BINDTODEVICE,tmp,strlen(tmp));
|
||||
}
|
||||
#endif // __LINUX__
|
||||
if (_bindingCount < ZT_BINDER_MAX_BINDINGS) {
|
||||
_bindings[_bindingCount].udpSock = udps;
|
||||
_bindings[_bindingCount].tcpListenSock = tcps;
|
||||
_bindings[_bindingCount].address = ii->first;
|
||||
phy.setIfName(udps,(char*)ii->second.c_str(),(int)ii->second.length());
|
||||
++_bindingCount;
|
||||
}
|
||||
} else {
|
||||
phy.close(udps,false);
|
||||
phy.close(tcps,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return All currently bound local interface addresses
|
||||
*/
|
||||
inline std::vector<InetAddress> allBoundLocalInterfaceAddresses() const
|
||||
{
|
||||
std::vector<InetAddress> aa;
|
||||
Mutex::Lock _l(_lock);
|
||||
for(unsigned int b=0,c=_bindingCount;b<c;++b)
|
||||
aa.push_back(_bindings[b].address);
|
||||
return aa;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send from all bound UDP sockets
|
||||
*/
|
||||
template<typename PHY_HANDLER_TYPE>
|
||||
inline bool udpSendAll(Phy<PHY_HANDLER_TYPE> &phy,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl)
|
||||
{
|
||||
bool r = false;
|
||||
Mutex::Lock _l(_lock);
|
||||
for(unsigned int b=0,c=_bindingCount;b<c;++b) {
|
||||
if (ttl) phy.setIp4UdpTtl(_bindings[b].udpSock,ttl);
|
||||
if (phy.udpSend(_bindings[b].udpSock,(const struct sockaddr *)addr,data,len)) r = true;
|
||||
if (ttl) phy.setIp4UdpTtl(_bindings[b].udpSock,255);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param addr Address to check
|
||||
* @return True if this is a bound local interface address
|
||||
*/
|
||||
inline bool isBoundLocalInterfaceAddress(const InetAddress &addr) const
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
for(unsigned int b=0;b<_bindingCount;++b) {
|
||||
if (_bindings[b].address == addr)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quickly check that a UDP socket is valid
|
||||
*
|
||||
* @param udpSock UDP socket to check
|
||||
* @return True if socket is currently bound/allocated
|
||||
*/
|
||||
inline bool isUdpSocketValid(PhySocket *const udpSock)
|
||||
{
|
||||
for(unsigned int b=0,c=_bindingCount;b<c;++b) {
|
||||
if (_bindings[b].udpSock == udpSock)
|
||||
return (b < _bindingCount); // double check atomic which may have changed
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
_Binding _bindings[ZT_BINDER_MAX_BINDINGS];
|
||||
std::atomic<unsigned int> _bindingCount;
|
||||
Mutex _lock;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
287
attic/Http.cpp
287
attic/Http.cpp
@ -1,287 +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: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Http.hpp"
|
||||
#include "Phy.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
|
||||
#ifdef ZT_USE_SYSTEM_HTTP_PARSER
|
||||
#include <http_parser.h>
|
||||
#else
|
||||
#include "../ext/http-parser/http_parser.h"
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
namespace {
|
||||
|
||||
static int ShttpOnMessageBegin(http_parser *parser);
|
||||
static int ShttpOnUrl(http_parser *parser,const char *ptr,size_t length);
|
||||
#if (HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 2)
|
||||
static int ShttpOnStatus(http_parser *parser,const char *ptr,size_t length);
|
||||
#else
|
||||
static int ShttpOnStatus(http_parser *parser);
|
||||
#endif
|
||||
static int ShttpOnHeaderField(http_parser *parser,const char *ptr,size_t length);
|
||||
static int ShttpOnValue(http_parser *parser,const char *ptr,size_t length);
|
||||
static int ShttpOnHeadersComplete(http_parser *parser);
|
||||
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
|
||||
};
|
||||
#else
|
||||
static const struct http_parser_settings HTTP_PARSER_SETTINGS = {
|
||||
ShttpOnMessageBegin,
|
||||
ShttpOnUrl,
|
||||
ShttpOnHeaderField,
|
||||
ShttpOnValue,
|
||||
ShttpOnHeadersComplete,
|
||||
ShttpOnBody,
|
||||
ShttpOnMessageComplete
|
||||
};
|
||||
#endif
|
||||
|
||||
struct HttpPhyHandler
|
||||
{
|
||||
// not used
|
||||
inline void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) {}
|
||||
inline void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from) {}
|
||||
|
||||
inline void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success)
|
||||
{
|
||||
if (success) {
|
||||
phy->setNotifyWritable(sock,true);
|
||||
} else {
|
||||
*responseBody = "connection failed";
|
||||
error = true;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
inline void phyOnTcpClose(PhySocket *sock,void **uptr)
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
|
||||
inline void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len)
|
||||
{
|
||||
lastActivity = OSUtils::now();
|
||||
http_parser_execute(&parser,&HTTP_PARSER_SETTINGS,(const char *)data,len);
|
||||
if ((parser.upgrade)||(parser.http_errno != HPE_OK))
|
||||
phy->close(sock);
|
||||
}
|
||||
|
||||
inline void phyOnTcpWritable(PhySocket *sock,void **uptr)
|
||||
{
|
||||
if (writePtr < (unsigned long)writeBuf.length()) {
|
||||
long n = phy->streamSend(sock,writeBuf.data() + writePtr,(unsigned long)writeBuf.length() - writePtr,true);
|
||||
if (n > 0)
|
||||
writePtr += n;
|
||||
}
|
||||
if (writePtr >= (unsigned long)writeBuf.length())
|
||||
phy->setNotifyWritable(sock,false);
|
||||
}
|
||||
|
||||
inline void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) {}
|
||||
#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__
|
||||
|
||||
http_parser parser;
|
||||
std::string currentHeaderField;
|
||||
std::string currentHeaderValue;
|
||||
unsigned long messageSize;
|
||||
unsigned long writePtr;
|
||||
uint64_t lastActivity;
|
||||
std::string writeBuf;
|
||||
|
||||
unsigned long maxResponseSize;
|
||||
std::map<std::string,std::string> *responseHeaders;
|
||||
std::string *responseBody;
|
||||
bool error;
|
||||
bool done;
|
||||
|
||||
Phy<HttpPhyHandler *> *phy;
|
||||
PhySocket *sock;
|
||||
};
|
||||
|
||||
static int ShttpOnMessageBegin(http_parser *parser)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnUrl(http_parser *parser,const char *ptr,size_t length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#if (HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 2)
|
||||
static int ShttpOnStatus(http_parser *parser,const char *ptr,size_t length)
|
||||
#else
|
||||
static int ShttpOnStatus(http_parser *parser)
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
|
||||
hh->messageSize += (unsigned long)length;
|
||||
if (hh->messageSize > hh->maxResponseSize)
|
||||
return -1;
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnHeaderField(http_parser *parser,const char *ptr,size_t length)
|
||||
{
|
||||
HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
|
||||
hh->messageSize += (unsigned long)length;
|
||||
if (hh->messageSize > hh->maxResponseSize)
|
||||
return -1;
|
||||
if ((hh->currentHeaderField.length())&&(hh->currentHeaderValue.length())) {
|
||||
(*hh->responseHeaders)[hh->currentHeaderField] = hh->currentHeaderValue;
|
||||
hh->currentHeaderField = "";
|
||||
hh->currentHeaderValue = "";
|
||||
}
|
||||
for(size_t i=0;i<length;++i)
|
||||
hh->currentHeaderField.push_back(OSUtils::toLower(ptr[i]));
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnValue(http_parser *parser,const char *ptr,size_t length)
|
||||
{
|
||||
HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
|
||||
hh->messageSize += (unsigned long)length;
|
||||
if (hh->messageSize > hh->maxResponseSize)
|
||||
return -1;
|
||||
hh->currentHeaderValue.append(ptr,length);
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnHeadersComplete(http_parser *parser)
|
||||
{
|
||||
HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
|
||||
if ((hh->currentHeaderField.length())&&(hh->currentHeaderValue.length()))
|
||||
(*hh->responseHeaders)[hh->currentHeaderField] = hh->currentHeaderValue;
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnBody(http_parser *parser,const char *ptr,size_t length)
|
||||
{
|
||||
HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
|
||||
hh->messageSize += (unsigned long)length;
|
||||
if (hh->messageSize > hh->maxResponseSize)
|
||||
return -1;
|
||||
hh->responseBody->append(ptr,length);
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnMessageComplete(http_parser *parser)
|
||||
{
|
||||
HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
|
||||
hh->phy->close(hh->sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
unsigned int Http::_do(
|
||||
const char *method,
|
||||
unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
const void *requestBody,
|
||||
unsigned long requestBodyLength,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody)
|
||||
{
|
||||
try {
|
||||
responseHeaders.clear();
|
||||
responseBody = "";
|
||||
|
||||
HttpPhyHandler handler;
|
||||
|
||||
http_parser_init(&(handler.parser),HTTP_RESPONSE);
|
||||
handler.parser.data = (void *)&handler;
|
||||
handler.messageSize = 0;
|
||||
handler.writePtr = 0;
|
||||
handler.lastActivity = OSUtils::now();
|
||||
|
||||
try {
|
||||
char tmp[1024];
|
||||
OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path);
|
||||
handler.writeBuf.append(tmp);
|
||||
for(std::map<std::string,std::string>::const_iterator h(requestHeaders.begin());h!=requestHeaders.end();++h) {
|
||||
OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str());
|
||||
handler.writeBuf.append(tmp);
|
||||
}
|
||||
handler.writeBuf.append("\r\n");
|
||||
if ((requestBody)&&(requestBodyLength))
|
||||
handler.writeBuf.append((const char *)requestBody,requestBodyLength);
|
||||
} catch ( ... ) {
|
||||
responseBody = "request too large";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (maxResponseSize) {
|
||||
handler.maxResponseSize = maxResponseSize;
|
||||
} else {
|
||||
handler.maxResponseSize = 2147483647;
|
||||
}
|
||||
handler.responseHeaders = &responseHeaders;
|
||||
handler.responseBody = &responseBody;
|
||||
handler.error = false;
|
||||
handler.done = false;
|
||||
|
||||
Phy<HttpPhyHandler *> phy(&handler,true,true);
|
||||
|
||||
bool instantConnect = false;
|
||||
handler.phy = &phy;
|
||||
handler.sock = phy.tcpConnect((const struct sockaddr *)remoteAddress,instantConnect,(void *)0,true);
|
||||
if (!handler.sock) {
|
||||
responseBody = "connection failed (2)";
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!handler.done) {
|
||||
phy.poll(timeout / 2);
|
||||
if ((timeout)&&((unsigned long)(OSUtils::now() - handler.lastActivity) > timeout)) {
|
||||
phy.close(handler.sock);
|
||||
responseBody = "timed out";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ((handler.error) ? 0 : ((handler.parser.http_errno != HPE_OK) ? 0 : handler.parser.status_code));
|
||||
} catch (std::exception &exc) {
|
||||
responseBody = exc.what();
|
||||
return 0;
|
||||
} catch ( ... ) {
|
||||
responseBody = "unknown exception";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
182
attic/Http.hpp
182
attic/Http.hpp
@ -1,182 +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: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#ifndef ZT_HTTP_HPP
|
||||
#define ZT_HTTP_HPP
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Simple synchronous HTTP client used for updater and cli
|
||||
*/
|
||||
class Http
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Make HTTP GET request
|
||||
*
|
||||
* The caller must set all headers, including Host.
|
||||
*
|
||||
* @return HTTP status code or 0 on error (responseBody will contain error message)
|
||||
*/
|
||||
static inline unsigned int GET(
|
||||
unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody)
|
||||
{
|
||||
return _do(
|
||||
"GET",
|
||||
maxResponseSize,
|
||||
timeout,
|
||||
remoteAddress,
|
||||
path,
|
||||
requestHeaders,
|
||||
(const void *)0,
|
||||
0,
|
||||
responseHeaders,
|
||||
responseBody);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make HTTP DELETE request
|
||||
*
|
||||
* The caller must set all headers, including Host.
|
||||
*
|
||||
* @return HTTP status code or 0 on error (responseBody will contain error message)
|
||||
*/
|
||||
static inline unsigned int DEL(
|
||||
unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody)
|
||||
{
|
||||
return _do(
|
||||
"DELETE",
|
||||
maxResponseSize,
|
||||
timeout,
|
||||
remoteAddress,
|
||||
path,
|
||||
requestHeaders,
|
||||
(const void *)0,
|
||||
0,
|
||||
responseHeaders,
|
||||
responseBody);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make HTTP POST request
|
||||
*
|
||||
* It is the responsibility of the caller to set all headers. With POST, the
|
||||
* Content-Length and Content-Type headers must be set or the POST will not
|
||||
* work.
|
||||
*
|
||||
* @return HTTP status code or 0 on error (responseBody will contain error message)
|
||||
*/
|
||||
static inline unsigned int POST(
|
||||
unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
const void *postData,
|
||||
unsigned long postDataLength,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody)
|
||||
{
|
||||
return _do(
|
||||
"POST",
|
||||
maxResponseSize,
|
||||
timeout,
|
||||
remoteAddress,
|
||||
path,
|
||||
requestHeaders,
|
||||
postData,
|
||||
postDataLength,
|
||||
responseHeaders,
|
||||
responseBody);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make HTTP PUT request
|
||||
*
|
||||
* It is the responsibility of the caller to set all headers. With PUT, the
|
||||
* Content-Length and Content-Type headers must be set or the PUT will not
|
||||
* work.
|
||||
*
|
||||
* @return HTTP status code or 0 on error (responseBody will contain error message)
|
||||
*/
|
||||
static inline unsigned int PUT(
|
||||
unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
const void *postData,
|
||||
unsigned long postDataLength,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody)
|
||||
{
|
||||
return _do(
|
||||
"PUT",
|
||||
maxResponseSize,
|
||||
timeout,
|
||||
remoteAddress,
|
||||
path,
|
||||
requestHeaders,
|
||||
postData,
|
||||
postDataLength,
|
||||
responseHeaders,
|
||||
responseBody);
|
||||
}
|
||||
|
||||
private:
|
||||
static unsigned int _do(
|
||||
const char *method,
|
||||
unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
const void *requestBody,
|
||||
unsigned long requestBodyLength,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody);
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
1177
attic/Phy.hpp
1177
attic/Phy.hpp
File diff suppressed because it is too large
Load Diff
@ -1,14 +0,0 @@
|
||||
#define ENABLE_STRNATPMPERR
|
||||
#define _BSD_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _XOPEN_SOURCE 600
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifndef _DARWIN_C_SOURCE
|
||||
#define _DARWIN_C_SOURCE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../ext/libnatpmp/getgateway.c"
|
||||
#include "../ext/libnatpmp/wingettimeofday.c"
|
||||
#include "../ext/libnatpmp/natpmp.c"
|
@ -1,41 +0,0 @@
|
||||
#define MINIUPNP_STATICLIB
|
||||
#define MINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
#define MINIUPNPC_GET_SRC_ADDR
|
||||
#define _BSD_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _XOPEN_SOURCE 600
|
||||
#define MINIUPNPC_VERSION_STRING "2.0"
|
||||
#define UPNP_VERSION_STRING "UPnP/1.1"
|
||||
|
||||
#ifdef __LINUX__
|
||||
#define OS_STRING "Linux"
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
#define OS_STRING "Darwin"
|
||||
#endif
|
||||
#ifdef __WINDOWS__
|
||||
#define OS_STRING "Windows"
|
||||
#endif
|
||||
#ifndef OS_STRING
|
||||
#define OS_STRING "ZeroTier"
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifndef _DARWIN_C_SOURCE
|
||||
#define _DARWIN_C_SOURCE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../ext/miniupnpc/connecthostport.c"
|
||||
#include "../ext/miniupnpc/igd_desc_parse.c"
|
||||
#include "../ext/miniupnpc/minisoap.c"
|
||||
#include "../ext/miniupnpc/miniupnpc.c"
|
||||
#include "../ext/miniupnpc/miniwget.c"
|
||||
#include "../ext/miniupnpc/minixml.c"
|
||||
#include "../ext/miniupnpc/portlistingparse.c"
|
||||
#include "../ext/miniupnpc/receivedata.c"
|
||||
#include "../ext/miniupnpc/upnpcommands.c"
|
||||
#include "../ext/miniupnpc/upnpdev.c"
|
||||
#include "../ext/miniupnpc/upnperrors.c"
|
||||
#include "../ext/miniupnpc/upnpreplyparse.c"
|
||||
#include "../ext/miniupnpc/minissdpc.c"
|
@ -1,334 +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: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
// Uncomment to dump debug messages
|
||||
//#define ZT_PORTMAPPER_TRACE 1
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#define PM_TRACE(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "PortMapper", __VA_ARGS__))
|
||||
#else
|
||||
#define PM_TRACE(...) fprintf(stderr, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../node/Utils.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
#include "PortMapper.hpp"
|
||||
|
||||
// These must be defined to get rid of dynamic export stuff in libminiupnpc and libnatpmp
|
||||
#ifdef __WINDOWS__
|
||||
#ifndef MINIUPNP_STATICLIB
|
||||
#define MINIUPNP_STATICLIB
|
||||
#endif
|
||||
#ifndef STATICLIB
|
||||
#define STATICLIB
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ZT_USE_SYSTEM_MINIUPNPC
|
||||
#include <miniupnpc/miniupnpc.h>
|
||||
#include <miniupnpc/upnpcommands.h>
|
||||
#else
|
||||
#ifdef __ANDROID__
|
||||
#include "miniupnpc.h"
|
||||
#include "upnpcommands.h"
|
||||
#else
|
||||
#include "../ext/miniupnpc/miniupnpc.h"
|
||||
#include "../ext/miniupnpc/upnpcommands.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ZT_USE_SYSTEM_NATPMP
|
||||
#include <natpmp.h>
|
||||
#else
|
||||
#ifdef __ANDROID__
|
||||
#include "natpmp.h"
|
||||
#else
|
||||
#include "../ext/libnatpmp/natpmp.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class PortMapperImpl
|
||||
{
|
||||
public:
|
||||
PortMapperImpl(int localUdpPortToMap,const char *un) :
|
||||
run(true),
|
||||
localPort(localUdpPortToMap),
|
||||
uniqueName(un)
|
||||
{
|
||||
}
|
||||
|
||||
~PortMapperImpl() {}
|
||||
|
||||
void threadMain()
|
||||
throw()
|
||||
{
|
||||
int mode = 0; // 0 == NAT-PMP, 1 == UPnP
|
||||
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
fprintf(stderr,"PortMapper: started for UDP port %d" ZT_EOL_S,localPort);
|
||||
#endif
|
||||
|
||||
while (run) {
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// NAT-PMP mode (preferred)
|
||||
// ---------------------------------------------------------------------
|
||||
if (mode == 0) {
|
||||
natpmp_t natpmp;
|
||||
natpmpresp_t response;
|
||||
int r = 0;
|
||||
|
||||
bool natPmpSuccess = false;
|
||||
for(int tries=0;tries<60;++tries) {
|
||||
int tryPort = (int)localPort + tries;
|
||||
if (tryPort >= 65535)
|
||||
tryPort = (tryPort - 65535) + 1025;
|
||||
|
||||
memset(&natpmp,0,sizeof(natpmp));
|
||||
memset(&response,0,sizeof(response));
|
||||
|
||||
if (initnatpmp(&natpmp,0,0) != 0) {
|
||||
mode = 1;
|
||||
closenatpmp(&natpmp);
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: NAT-PMP: init failed, switching to UPnP mode" ZT_EOL_S);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
InetAddress publicAddress;
|
||||
sendpublicaddressrequest(&natpmp);
|
||||
int64_t myTimeout = OSUtils::now() + 5000;
|
||||
do {
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(natpmp.s, &fds);
|
||||
getnatpmprequesttimeout(&natpmp, &timeout);
|
||||
select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
|
||||
r = readnatpmpresponseorretry(&natpmp, &response);
|
||||
if (OSUtils::now() >= myTimeout)
|
||||
break;
|
||||
} while (r == NATPMP_TRYAGAIN);
|
||||
if (r == 0) {
|
||||
publicAddress = InetAddress((uint32_t)response.pnu.publicaddress.addr.s_addr,0);
|
||||
} else {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: NAT-PMP: request for external address failed, aborting..." ZT_EOL_S);
|
||||
#endif
|
||||
closenatpmp(&natpmp);
|
||||
break;
|
||||
}
|
||||
|
||||
sendnewportmappingrequest(&natpmp,NATPMP_PROTOCOL_UDP,localPort,tryPort,(ZT_PORTMAPPER_REFRESH_DELAY * 2) / 1000);
|
||||
myTimeout = OSUtils::now() + 10000;
|
||||
do {
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(natpmp.s, &fds);
|
||||
getnatpmprequesttimeout(&natpmp, &timeout);
|
||||
select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
|
||||
r = readnatpmpresponseorretry(&natpmp, &response);
|
||||
if (OSUtils::now() >= myTimeout)
|
||||
break;
|
||||
} while (r == NATPMP_TRYAGAIN);
|
||||
if (r == 0) {
|
||||
publicAddress.setPort(response.pnu.newportmapping.mappedpublicport);
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
char paddr[128];
|
||||
PM_TRACE("PortMapper: NAT-PMP: mapped %u to %s" ZT_EOL_S,(unsigned int)localPort,publicAddress.toString(paddr));
|
||||
#endif
|
||||
Mutex::Lock sl(surface_l);
|
||||
surface.clear();
|
||||
surface.push_back(publicAddress);
|
||||
natPmpSuccess = true;
|
||||
closenatpmp(&natpmp);
|
||||
break;
|
||||
} else {
|
||||
closenatpmp(&natpmp);
|
||||
// continue
|
||||
}
|
||||
}
|
||||
|
||||
if (!natPmpSuccess) {
|
||||
mode = 1;
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: NAT-PMP: request failed, switching to UPnP mode" ZT_EOL_S);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// UPnP mode
|
||||
// ---------------------------------------------------------------------
|
||||
if (mode == 1) {
|
||||
char lanaddr[4096];
|
||||
char externalip[4096]; // no range checking? so make these buffers larger than any UDP packet a uPnP server could send us as a precaution :P
|
||||
char inport[16];
|
||||
char outport[16];
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
|
||||
int upnpError = 0;
|
||||
UPNPDev *devlist = upnpDiscoverAll(5000,(const char *)0,(const char *)0,0,0,2,&upnpError);
|
||||
if (devlist) {
|
||||
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
{
|
||||
UPNPDev *dev = devlist;
|
||||
while (dev) {
|
||||
PM_TRACE("PortMapper: found UPnP device at URL '%s': %s" ZT_EOL_S,dev->descURL,dev->st);
|
||||
dev = dev->pNext;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(lanaddr,0,sizeof(lanaddr));
|
||||
memset(externalip,0,sizeof(externalip));
|
||||
memset(&urls,0,sizeof(urls));
|
||||
memset(&data,0,sizeof(data));
|
||||
OSUtils::ztsnprintf(inport,sizeof(inport),"%d",localPort);
|
||||
|
||||
if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: my LAN IP address: %s" ZT_EOL_S,lanaddr);
|
||||
#endif
|
||||
if ((UPNP_GetExternalIPAddress(urls.controlURL,data.first.servicetype,externalip) == UPNPCOMMAND_SUCCESS)&&(externalip[0])) {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: my external IP address: %s" ZT_EOL_S,externalip);
|
||||
#endif
|
||||
|
||||
for(int tries=0;tries<60;++tries) {
|
||||
int tryPort = (int)localPort + tries;
|
||||
if (tryPort >= 65535)
|
||||
tryPort = (tryPort - 65535) + 1025;
|
||||
OSUtils::ztsnprintf(outport,sizeof(outport),"%u",tryPort);
|
||||
|
||||
// First check and see if this port is already mapped to the
|
||||
// same unique name. If so, keep this mapping and don't try
|
||||
// to map again since this can break buggy routers. But don't
|
||||
// fail if this command fails since not all routers support it.
|
||||
{
|
||||
char haveIntClient[128]; // 128 == big enough for all these as per miniupnpc "documentation"
|
||||
char haveIntPort[128];
|
||||
char haveDesc[128];
|
||||
char haveEnabled[128];
|
||||
char haveLeaseDuration[128];
|
||||
memset(haveIntClient,0,sizeof(haveIntClient));
|
||||
memset(haveIntPort,0,sizeof(haveIntPort));
|
||||
memset(haveDesc,0,sizeof(haveDesc));
|
||||
memset(haveEnabled,0,sizeof(haveEnabled));
|
||||
memset(haveLeaseDuration,0,sizeof(haveLeaseDuration));
|
||||
if ((UPNP_GetSpecificPortMappingEntry(urls.controlURL,data.first.servicetype,outport,"UDP",(const char *)0,haveIntClient,haveIntPort,haveDesc,haveEnabled,haveLeaseDuration) == UPNPCOMMAND_SUCCESS)&&(uniqueName == haveDesc)) {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: reusing previously reserved external port: %s" ZT_EOL_S,outport);
|
||||
#endif
|
||||
Mutex::Lock sl(surface_l);
|
||||
surface.clear();
|
||||
InetAddress tmp(externalip);
|
||||
tmp.setPort(tryPort);
|
||||
surface.push_back(tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to map this port
|
||||
int mapResult = 0;
|
||||
if ((mapResult = UPNP_AddPortMapping(urls.controlURL,data.first.servicetype,outport,inport,lanaddr,uniqueName.c_str(),"UDP",(const char *)0,"0")) == UPNPCOMMAND_SUCCESS) {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: reserved external port: %s" ZT_EOL_S,outport);
|
||||
#endif
|
||||
Mutex::Lock sl(surface_l);
|
||||
surface.clear();
|
||||
InetAddress tmp(externalip);
|
||||
tmp.setPort(tryPort);
|
||||
surface.push_back(tmp);
|
||||
break;
|
||||
} else {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: UPNP_AddPortMapping(%s) failed: %d" ZT_EOL_S,outport,mapResult);
|
||||
#endif
|
||||
Thread::sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
mode = 0;
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: UPNP_GetExternalIPAddress failed, returning to NAT-PMP mode" ZT_EOL_S);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
mode = 0;
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: UPNP_GetValidIGD failed, returning to NAT-PMP mode" ZT_EOL_S);
|
||||
#endif
|
||||
}
|
||||
|
||||
freeUPNPDevlist(devlist);
|
||||
|
||||
} else {
|
||||
mode = 0;
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: upnpDiscover failed, returning to NAT-PMP mode: %d" ZT_EOL_S,upnpError);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("UPNPClient: rescanning in %d ms" ZT_EOL_S,ZT_PORTMAPPER_REFRESH_DELAY);
|
||||
#endif
|
||||
Thread::sleep(ZT_PORTMAPPER_REFRESH_DELAY);
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
volatile bool run;
|
||||
int localPort;
|
||||
std::string uniqueName;
|
||||
|
||||
Mutex surface_l;
|
||||
std::vector<InetAddress> surface;
|
||||
};
|
||||
|
||||
PortMapper::PortMapper(int localUdpPortToMap,const char *uniqueName)
|
||||
{
|
||||
_impl = new PortMapperImpl(localUdpPortToMap,uniqueName);
|
||||
Thread::start(_impl);
|
||||
}
|
||||
|
||||
PortMapper::~PortMapper()
|
||||
{
|
||||
_impl->run = false;
|
||||
}
|
||||
|
||||
std::vector<InetAddress> PortMapper::get() const
|
||||
{
|
||||
Mutex::Lock _l(_impl->surface_l);
|
||||
return _impl->surface;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
@ -1,62 +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: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#ifndef ZT_PORTMAPPER_HPP
|
||||
#define ZT_PORTMAPPER_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "Thread.hpp"
|
||||
|
||||
/**
|
||||
* How frequently should we refresh our UPNP/NAT-PnP/whatever state?
|
||||
*/
|
||||
#define ZT_PORTMAPPER_REFRESH_DELAY 120000
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class PortMapperImpl;
|
||||
|
||||
/**
|
||||
* UPnP/NAT-PnP port mapping "daemon"
|
||||
*/
|
||||
class PortMapper
|
||||
{
|
||||
friend class PortMapperImpl;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create and start port mapper service
|
||||
*
|
||||
* @param localUdpPortToMap Port we want visible to the outside world
|
||||
* @param name Unique name of this endpoint (based on ZeroTier address)
|
||||
*/
|
||||
PortMapper(int localUdpPortToMap,const char *uniqueName);
|
||||
|
||||
~PortMapper();
|
||||
|
||||
/**
|
||||
* @return All current external mappings for our port
|
||||
*/
|
||||
std::vector<InetAddress> get() const;
|
||||
|
||||
private:
|
||||
PortMapperImpl *_impl;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
182
attic/Root.hpp
182
attic/Root.hpp
@ -1,182 +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: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#ifndef ZT_ROOT_HPP
|
||||
#define ZT_ROOT_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Str.hpp"
|
||||
#include "ECC384.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* A root entry pointing to a node capable of global identity lookup and indirect transit
|
||||
*
|
||||
* Root entries point to DNS records that contain TXT entries that decode to Locator objects
|
||||
* pointing to actual root nodes. A default root identity and static addresses can also be
|
||||
* provided as fallback if DNS is not available.
|
||||
*
|
||||
* Note that root identities can change if DNS returns a different result, but that DNS entries
|
||||
* are authenticated using their own signature scheme. This allows a root DNS name to serve
|
||||
* up different roots based on factors like location or relative load of different roots.
|
||||
*
|
||||
* It's also possible to create a root with no DNS and no DNS validator public key. This root
|
||||
* will be a static entry pointing to a single root identity and set of physical addresses.
|
||||
*/
|
||||
class Root
|
||||
{
|
||||
public:
|
||||
ZT_ALWAYS_INLINE Root() : _dnsPublicKeySize(0) {}
|
||||
|
||||
/**
|
||||
* Create a new root entry
|
||||
*
|
||||
* @param dn DNS name
|
||||
* @param dnspk DNS public key for record validation
|
||||
* @param dnspksize Size of DNS public key (currently always the size of a NIST P-384 point compressed public key)
|
||||
* @param dflId Default identity if DNS is not available
|
||||
* @param dflAddrs Default IP addresses if DNS is not available
|
||||
*/
|
||||
template<typename S>
|
||||
ZT_ALWAYS_INLINE Root(S dn,const uint8_t *const dnspk,const unsigned int dnspksize,const Identity &dflId,const std::vector<InetAddress> &dflAddrs) :
|
||||
_defaultIdentity(dflId),
|
||||
_defaultAddresses(dflAddrs),
|
||||
_dnsName(dn),
|
||||
_dnsPublicKeySize(dnspksize)
|
||||
{
|
||||
if (dnspksize != 0) {
|
||||
if (dnspksize > sizeof(_dnsPublicKey))
|
||||
throw ZT_EXCEPTION_INVALID_ARGUMENT;
|
||||
memcpy(_dnsPublicKey,dnspk,dnspksize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current identity (either default or latest locator)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const Identity id() const
|
||||
{
|
||||
if (_lastFetchedLocator.id())
|
||||
return _lastFetchedLocator.id();
|
||||
return _defaultIdentity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id Identity to check
|
||||
* @return True if identity equals this root's current identity
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool is(const Identity &id) const
|
||||
{
|
||||
return ((_lastFetchedLocator.id()) ? (id == _lastFetchedLocator.id()) : (id == _defaultIdentity));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current ZeroTier address (either default or latest locator)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const Address address() const
|
||||
{
|
||||
if (_lastFetchedLocator.id())
|
||||
return _lastFetchedLocator.id().address();
|
||||
return _defaultIdentity.address();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DNS name for this root or empty string if static entry with no DNS
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const Str dnsName() const { return _dnsName; }
|
||||
|
||||
/**
|
||||
* @return Latest locator or NIL locator object if none
|
||||
*/
|
||||
ZT_ALWAYS_INLINE Locator locator() const { return _lastFetchedLocator; }
|
||||
|
||||
/**
|
||||
* @return Timestamp of latest retrieved locator or 0 if none
|
||||
*/
|
||||
ZT_ALWAYS_INLINE int64_t locatorTimestamp() const { return _lastFetchedLocator.timestamp(); }
|
||||
|
||||
/**
|
||||
* Update locator, returning true if new locator is valid and newer than existing
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool updateLocator(const Locator &loc)
|
||||
{
|
||||
if (!loc.verify())
|
||||
return false;
|
||||
if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
|
||||
_lastFetchedLocator = loc;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update this root's locator from a series of TXT records
|
||||
*/
|
||||
template<typename I>
|
||||
ZT_ALWAYS_INLINE bool updateLocatorFromTxt(I start,I end)
|
||||
{
|
||||
try {
|
||||
if (_dnsPublicKeySize != ZT_ECC384_PUBLIC_KEY_SIZE)
|
||||
return false;
|
||||
Locator loc;
|
||||
if (!loc.decodeTxtRecords(start,end,_dnsPublicKey)) // also does verify()
|
||||
return false;
|
||||
if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
|
||||
_lastFetchedLocator = loc;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch ( ... ) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a random physical IP for this root with the given address family
|
||||
*
|
||||
* @param addressFamily AF_INET or AF_INET6
|
||||
* @return Address or InetAddress::NIL if no addresses exist for the given family
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const InetAddress &pickPhysical(const int addressFamily) const
|
||||
{
|
||||
std::vector<const InetAddress *> pickList;
|
||||
const std::vector<InetAddress> *const av = (_lastFetchedLocator) ? &(_lastFetchedLocator.phy()) : &_defaultAddresses;
|
||||
for(std::vector<InetAddress>::const_iterator i(av->begin());i!=av->end();++i) {
|
||||
if (addressFamily == (int)i->ss_family) {
|
||||
pickList.push_back(&(*i));
|
||||
}
|
||||
}
|
||||
if (pickList.size() == 1)
|
||||
return *pickList[0];
|
||||
else if (pickList.size() > 1)
|
||||
return *pickList[(unsigned long)Utils::random() % (unsigned long)pickList.size()];
|
||||
return InetAddress::NIL;
|
||||
}
|
||||
|
||||
private:
|
||||
Identity _defaultIdentity;
|
||||
std::vector<InetAddress> _defaultAddresses;
|
||||
Str _dnsName;
|
||||
Locator _lastFetchedLocator;
|
||||
unsigned int _dnsPublicKeySize;
|
||||
uint8_t _dnsPublicKey[ZT_ECC384_PUBLIC_KEY_SIZE];
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
@ -1,18 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void *__wrap_memcpy(void *dest,const void *src,size_t n)
|
||||
{
|
||||
return memcpy(dest,src,n);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,30 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ifs, err := net.Interfaces()
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
for _, i := range ifs {
|
||||
fmt.Printf("name: %s\n", i.Name)
|
||||
fmt.Printf("hwaddr: %s\n", i.HardwareAddr.String())
|
||||
fmt.Printf("index: %d\n", i.Index)
|
||||
fmt.Printf("addrs:\n")
|
||||
addrs, _ := i.Addrs()
|
||||
for _, a := range addrs {
|
||||
fmt.Printf(" %s\n", a.String())
|
||||
}
|
||||
fmt.Printf("multicast:\n")
|
||||
mc, _ := i.MulticastAddrs()
|
||||
for _, m := range mc {
|
||||
fmt.Printf(" %s\n", m.String())
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
}
|
1542
attic/one.cpp
1542
attic/one.cpp
File diff suppressed because it is too large
Load Diff
111
attic/webview/.clang-format
Normal file
111
attic/webview/.clang-format
Normal file
@ -0,0 +1,111 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
...
|
||||
|
256
attic/webview/.clang-tidy
Normal file
256
attic/webview/.clang-tidy
Normal file
@ -0,0 +1,256 @@
|
||||
---
|
||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,*'
|
||||
HeaderFilterRegex: ''
|
||||
AnalyzeTemporaryDtors: false
|
||||
User: serge
|
||||
CheckOptions:
|
||||
- key: bugprone-argument-comment.StrictMode
|
||||
value: '0'
|
||||
- key: bugprone-assert-side-effect.AssertMacros
|
||||
value: assert
|
||||
- key: bugprone-assert-side-effect.CheckFunctionCalls
|
||||
value: '0'
|
||||
- key: bugprone-dangling-handle.HandleClasses
|
||||
value: 'std::basic_string_view;std::experimental::basic_string_view'
|
||||
- key: bugprone-string-constructor.LargeLengthThreshold
|
||||
value: '8388608'
|
||||
- key: bugprone-string-constructor.WarnOnLargeLength
|
||||
value: '1'
|
||||
- key: cert-dcl59-cpp.HeaderFileExtensions
|
||||
value: ',h,hh,hpp,hxx'
|
||||
- key: cert-err09-cpp.CheckThrowTemporaries
|
||||
value: '1'
|
||||
- key: cert-err61-cpp.CheckThrowTemporaries
|
||||
value: '1'
|
||||
- key: cert-oop11-cpp.IncludeStyle
|
||||
value: llvm
|
||||
- key: cppcoreguidelines-no-malloc.Allocations
|
||||
value: '::malloc;::calloc'
|
||||
- key: cppcoreguidelines-no-malloc.Deallocations
|
||||
value: '::free'
|
||||
- key: cppcoreguidelines-no-malloc.Reallocations
|
||||
value: '::realloc'
|
||||
- key: cppcoreguidelines-owning-memory.LegacyResourceConsumers
|
||||
value: '::free;::realloc;::freopen;::fclose'
|
||||
- key: cppcoreguidelines-owning-memory.LegacyResourceProducers
|
||||
value: '::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile'
|
||||
- key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader
|
||||
value: ''
|
||||
- key: cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle
|
||||
value: '0'
|
||||
- key: cppcoreguidelines-pro-type-member-init.IgnoreArrays
|
||||
value: '0'
|
||||
- key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions
|
||||
value: '0'
|
||||
- key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
|
||||
value: '0'
|
||||
- key: google-build-namespaces.HeaderFileExtensions
|
||||
value: ',h,hh,hpp,hxx'
|
||||
- key: google-global-names-in-headers.HeaderFileExtensions
|
||||
value: ',h,hh,hpp,hxx'
|
||||
- key: google-readability-braces-around-statements.ShortStatementLines
|
||||
value: '1'
|
||||
- key: google-readability-function-size.BranchThreshold
|
||||
value: '4294967295'
|
||||
- key: google-readability-function-size.LineThreshold
|
||||
value: '4294967295'
|
||||
- key: google-readability-function-size.NestingThreshold
|
||||
value: '4294967295'
|
||||
- key: google-readability-function-size.ParameterThreshold
|
||||
value: '4294967295'
|
||||
- key: google-readability-function-size.StatementThreshold
|
||||
value: '800'
|
||||
- key: google-readability-namespace-comments.ShortNamespaceLines
|
||||
value: '10'
|
||||
- key: google-readability-namespace-comments.SpacesBeforeComments
|
||||
value: '2'
|
||||
- key: google-runtime-int.SignedTypePrefix
|
||||
value: int
|
||||
- key: google-runtime-int.TypeSuffix
|
||||
value: ''
|
||||
- key: google-runtime-int.UnsignedTypePrefix
|
||||
value: uint
|
||||
- key: google-runtime-references.WhiteListTypes
|
||||
value: ''
|
||||
- key: hicpp-braces-around-statements.ShortStatementLines
|
||||
value: '0'
|
||||
- key: hicpp-function-size.BranchThreshold
|
||||
value: '4294967295'
|
||||
- key: hicpp-function-size.LineThreshold
|
||||
value: '4294967295'
|
||||
- key: hicpp-function-size.NestingThreshold
|
||||
value: '4294967295'
|
||||
- key: hicpp-function-size.ParameterThreshold
|
||||
value: '4294967295'
|
||||
- key: hicpp-function-size.StatementThreshold
|
||||
value: '800'
|
||||
- key: hicpp-member-init.IgnoreArrays
|
||||
value: '0'
|
||||
- key: hicpp-move-const-arg.CheckTriviallyCopyableMove
|
||||
value: '1'
|
||||
- key: hicpp-named-parameter.IgnoreFailedSplit
|
||||
value: '0'
|
||||
- key: hicpp-no-malloc.Allocations
|
||||
value: '::malloc;::calloc'
|
||||
- key: hicpp-no-malloc.Deallocations
|
||||
value: '::free'
|
||||
- key: hicpp-no-malloc.Reallocations
|
||||
value: '::realloc'
|
||||
- key: hicpp-special-member-functions.AllowMissingMoveFunctions
|
||||
value: '0'
|
||||
- key: hicpp-special-member-functions.AllowSoleDefaultDtor
|
||||
value: '0'
|
||||
- key: hicpp-use-auto.RemoveStars
|
||||
value: '0'
|
||||
- key: hicpp-use-emplace.ContainersWithPushBack
|
||||
value: '::std::vector;::std::list;::std::deque'
|
||||
- key: hicpp-use-emplace.SmartPointers
|
||||
value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr'
|
||||
- key: hicpp-use-emplace.TupleMakeFunctions
|
||||
value: '::std::make_pair;::std::make_tuple'
|
||||
- key: hicpp-use-emplace.TupleTypes
|
||||
value: '::std::pair;::std::tuple'
|
||||
- key: hicpp-use-equals-default.IgnoreMacros
|
||||
value: '1'
|
||||
- key: hicpp-use-noexcept.ReplacementString
|
||||
value: ''
|
||||
- key: hicpp-use-noexcept.UseNoexceptFalse
|
||||
value: '1'
|
||||
- key: hicpp-use-nullptr.NullMacros
|
||||
value: ''
|
||||
- key: llvm-namespace-comment.ShortNamespaceLines
|
||||
value: '1'
|
||||
- key: llvm-namespace-comment.SpacesBeforeComments
|
||||
value: '1'
|
||||
- key: misc-definitions-in-headers.HeaderFileExtensions
|
||||
value: ',h,hh,hpp,hxx'
|
||||
- key: misc-definitions-in-headers.UseHeaderFileExtension
|
||||
value: '1'
|
||||
- key: misc-misplaced-widening-cast.CheckImplicitCasts
|
||||
value: '0'
|
||||
- key: misc-sizeof-expression.WarnOnSizeOfCompareToConstant
|
||||
value: '1'
|
||||
- key: misc-sizeof-expression.WarnOnSizeOfConstant
|
||||
value: '1'
|
||||
- key: misc-sizeof-expression.WarnOnSizeOfThis
|
||||
value: '1'
|
||||
- key: misc-suspicious-enum-usage.StrictMode
|
||||
value: '0'
|
||||
- key: misc-suspicious-missing-comma.MaxConcatenatedTokens
|
||||
value: '5'
|
||||
- key: misc-suspicious-missing-comma.RatioThreshold
|
||||
value: '0.200000'
|
||||
- key: misc-suspicious-missing-comma.SizeThreshold
|
||||
value: '5'
|
||||
- key: misc-suspicious-string-compare.StringCompareLikeFunctions
|
||||
value: ''
|
||||
- key: misc-suspicious-string-compare.WarnOnImplicitComparison
|
||||
value: '1'
|
||||
- key: misc-suspicious-string-compare.WarnOnLogicalNotComparison
|
||||
value: '0'
|
||||
- key: misc-throw-by-value-catch-by-reference.CheckThrowTemporaries
|
||||
value: '1'
|
||||
- key: modernize-loop-convert.MaxCopySize
|
||||
value: '16'
|
||||
- key: modernize-loop-convert.MinConfidence
|
||||
value: reasonable
|
||||
- key: modernize-loop-convert.NamingStyle
|
||||
value: CamelCase
|
||||
- key: modernize-make-shared.IgnoreMacros
|
||||
value: '1'
|
||||
- key: modernize-make-shared.IncludeStyle
|
||||
value: '0'
|
||||
- key: modernize-make-shared.MakeSmartPtrFunction
|
||||
value: 'std::make_shared'
|
||||
- key: modernize-make-shared.MakeSmartPtrFunctionHeader
|
||||
value: memory
|
||||
- key: modernize-make-unique.IgnoreMacros
|
||||
value: '1'
|
||||
- key: modernize-make-unique.IncludeStyle
|
||||
value: '0'
|
||||
- key: modernize-make-unique.MakeSmartPtrFunction
|
||||
value: 'std::make_unique'
|
||||
- key: modernize-make-unique.MakeSmartPtrFunctionHeader
|
||||
value: memory
|
||||
- key: modernize-pass-by-value.IncludeStyle
|
||||
value: llvm
|
||||
- key: modernize-pass-by-value.ValuesOnly
|
||||
value: '0'
|
||||
- key: modernize-raw-string-literal.ReplaceShorterLiterals
|
||||
value: '0'
|
||||
- key: modernize-replace-auto-ptr.IncludeStyle
|
||||
value: llvm
|
||||
- key: modernize-replace-random-shuffle.IncludeStyle
|
||||
value: llvm
|
||||
- key: modernize-use-auto.RemoveStars
|
||||
value: '0'
|
||||
- key: modernize-use-default-member-init.IgnoreMacros
|
||||
value: '1'
|
||||
- key: modernize-use-default-member-init.UseAssignment
|
||||
value: '0'
|
||||
- key: modernize-use-emplace.ContainersWithPushBack
|
||||
value: '::std::vector;::std::list;::std::deque'
|
||||
- key: modernize-use-emplace.SmartPointers
|
||||
value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr'
|
||||
- key: modernize-use-emplace.TupleMakeFunctions
|
||||
value: '::std::make_pair;::std::make_tuple'
|
||||
- key: modernize-use-emplace.TupleTypes
|
||||
value: '::std::pair;::std::tuple'
|
||||
- key: modernize-use-equals-default.IgnoreMacros
|
||||
value: '1'
|
||||
- key: modernize-use-noexcept.ReplacementString
|
||||
value: ''
|
||||
- key: modernize-use-noexcept.UseNoexceptFalse
|
||||
value: '1'
|
||||
- key: modernize-use-nullptr.NullMacros
|
||||
value: 'NULL'
|
||||
- key: modernize-use-transparent-functors.SafeMode
|
||||
value: '0'
|
||||
- key: modernize-use-using.IgnoreMacros
|
||||
value: '1'
|
||||
- key: objc-forbidden-subclassing.ForbiddenSuperClassNames
|
||||
value: 'ABNewPersonViewController;ABPeoplePickerNavigationController;ABPersonViewController;ABUnknownPersonViewController;NSHashTable;NSMapTable;NSPointerArray;NSPointerFunctions;NSTimer;UIActionSheet;UIAlertView;UIImagePickerController;UITextInputMode;UIWebView'
|
||||
- key: objc-property-declaration.Acronyms
|
||||
value: 'ASCII;PDF;XML;HTML;URL;RTF;HTTP;TIFF;JPG;PNG;GIF;LZW;ROM;RGB;CMYK;MIDI;FTP'
|
||||
- key: performance-faster-string-find.StringLikeClasses
|
||||
value: 'std::basic_string'
|
||||
- key: performance-for-range-copy.WarnOnAllAutoCopies
|
||||
value: '0'
|
||||
- key: performance-inefficient-string-concatenation.StrictMode
|
||||
value: '0'
|
||||
- key: performance-inefficient-vector-operation.VectorLikeClasses
|
||||
value: '::std::vector'
|
||||
- key: performance-move-const-arg.CheckTriviallyCopyableMove
|
||||
value: '1'
|
||||
- key: performance-move-constructor-init.IncludeStyle
|
||||
value: llvm
|
||||
- key: performance-type-promotion-in-math-fn.IncludeStyle
|
||||
value: llvm
|
||||
- key: performance-unnecessary-value-param.IncludeStyle
|
||||
value: llvm
|
||||
- key: readability-braces-around-statements.ShortStatementLines
|
||||
value: '0'
|
||||
- key: readability-function-size.BranchThreshold
|
||||
value: '4294967295'
|
||||
- key: readability-function-size.LineThreshold
|
||||
value: '4294967295'
|
||||
- key: readability-function-size.NestingThreshold
|
||||
value: '4294967295'
|
||||
- key: readability-function-size.ParameterThreshold
|
||||
value: '4294967295'
|
||||
- key: readability-function-size.StatementThreshold
|
||||
value: '800'
|
||||
- key: readability-identifier-naming.IgnoreFailedSplit
|
||||
value: '0'
|
||||
- key: readability-implicit-bool-conversion.AllowIntegerConditions
|
||||
value: '0'
|
||||
- key: readability-implicit-bool-conversion.AllowPointerConditions
|
||||
value: '0'
|
||||
- key: readability-simplify-boolean-expr.ChainedConditionalAssignment
|
||||
value: '0'
|
||||
- key: readability-simplify-boolean-expr.ChainedConditionalReturn
|
||||
value: '0'
|
||||
- key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold
|
||||
value: '3'
|
||||
...
|
||||
|
1
attic/webview/.gitattributes
vendored
Normal file
1
attic/webview/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.h linguist-language=c
|
7
attic/webview/.gitignore
vendored
Normal file
7
attic/webview/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# Build atrifacts
|
||||
/build
|
||||
/examples/minimal-go/minimal-go
|
||||
/examples/minimal/minimal
|
||||
/examples/minimal/minimal.exe
|
||||
/examples/minimal/build
|
||||
/examples/timer-cxx/build
|
19
attic/webview/.travis.yml
Normal file
19
attic/webview/.travis.yml
Normal file
@ -0,0 +1,19 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.x
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
before_install:
|
||||
- sudo add-apt-repository ppa:webkit-team/ppa -y
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install libwebkit2gtk-4.0-dev -y
|
||||
env: WEBVIEW=gtk
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
env: WEBVIEW=cocoa
|
||||
|
||||
script:
|
||||
- make example
|
21
attic/webview/LICENSE
Normal file
21
attic/webview/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Serge Zaitsev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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.
|
28
attic/webview/Makefile
Normal file
28
attic/webview/Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
WEBVIEW_gtk_FLAGS = -DWEBVIEW_GTK -std=c++14 -Wall -Wextra -pedantic $(shell pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.0)
|
||||
WEBVIEW_cocoa_FLAGS = -DWEBVIEW_COCOA -std=c++14 -Wall -Wextra -pedantic -framework WebKit -mmacosx-version-min=10.11 -DOBJC_OLD_DISPATCH_PROTOTYPES
|
||||
WEBVIEW_mshtml_FLAGS := -DWEBVIEW_MSHTML -std=c++14 -luser32 -lole32 -loleaut32 -lcomctl32 -luuid -static
|
||||
WEBVIEW_edge_FLAGS := -DWEBVIEW_EDGE
|
||||
|
||||
all:
|
||||
@echo "make WEBVIEW=... test - build and run tests"
|
||||
@echo "make WEBVIEW=... lint - run clang-tidy checkers"
|
||||
@echo "make WEBVIEW=... fmt - run clang-format for all sources"
|
||||
|
||||
fmt: webview.h
|
||||
clang-format -i $^
|
||||
|
||||
check-env:
|
||||
ifndef WEBVIEW_$(WEBVIEW)_FLAGS
|
||||
$(error "Unknown WEBVIEW value, use WEBVIEW=gtk|cocoa|mshtml|edge")
|
||||
endif
|
||||
|
||||
lint: check-env
|
||||
clang-tidy example.cc -- $(WEBVIEW_$(WEBVIEW)_FLAGS)
|
||||
|
||||
example: check-env example.cc webview.h
|
||||
$(CXX) example.cc $(WEBVIEW_$(WEBVIEW)_FLAGS) -o example
|
||||
|
||||
test: check-env
|
||||
$(CXX) webview_test.cc $(WEBVIEW_$(WEBVIEW)_FLAGS) -o webview_test
|
||||
./webview_test
|
||||
rm webview_test
|
39
attic/webview/example.cc
Normal file
39
attic/webview/example.cc
Normal file
@ -0,0 +1,39 @@
|
||||
// +build ignore
|
||||
|
||||
#include "webview.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||
LPSTR lpCmdLine, int nCmdShow)
|
||||
#else
|
||||
int main()
|
||||
#endif
|
||||
{
|
||||
webview::webview w(true, nullptr);
|
||||
w.set_title("Example");
|
||||
w.set_size(480, 320, true);
|
||||
w.bind("noop", [](std::string s) -> std::string { printf("%s\n", s.c_str());return s; });
|
||||
w.bind("add", [](std::string s) -> std::string {
|
||||
auto a = std::stoi(webview::json_parse(s, "", 0));
|
||||
auto b = std::stoi(webview::json_parse(s, "", 1));
|
||||
return std::to_string(a + b);
|
||||
});
|
||||
w.navigate(R"(data:text/html,
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>hello</body>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
noop('hello').then(function(res) {
|
||||
console.log('noop res', res);
|
||||
});
|
||||
add(1, 2).then(function(res) {
|
||||
console.log('add res', res);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</html>
|
||||
)");
|
||||
w.run();
|
||||
return 0;
|
||||
}
|
15
attic/webview/example/example.go
Normal file
15
attic/webview/example/example.go
Normal file
@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/zserge/webview"
|
||||
)
|
||||
|
||||
func main() {
|
||||
w := webview.New(true)
|
||||
w.Navigate("https://github.com")
|
||||
w.SetTitle("Hello")
|
||||
w.Dispatch(func() {
|
||||
println("Hello dispatch")
|
||||
})
|
||||
w.Run()
|
||||
}
|
3
attic/webview/go.mod
Normal file
3
attic/webview/go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/zserge/webview
|
||||
|
||||
go 1.13
|
1
attic/webview/webview.cc
Normal file
1
attic/webview/webview.cc
Normal file
@ -0,0 +1 @@
|
||||
#include "webview.h"
|
138
attic/webview/webview.go
Normal file
138
attic/webview/webview.go
Normal file
@ -0,0 +1,138 @@
|
||||
package webview
|
||||
|
||||
/*
|
||||
#cgo linux openbsd freebsd CXXFLAGS: -DWEBVIEW_GTK -std=c++14
|
||||
#cgo linux openbsd freebsd pkg-config: gtk+-3.0 webkit2gtk-4.0
|
||||
|
||||
#cgo darwin CXXFLAGS: -DWEBVIEW_COCOA -std=c++14 -DOBJC_OLD_DISPATCH_PROTOTYPES
|
||||
#cgo darwin LDFLAGS: -framework WebKit
|
||||
|
||||
#cgo windows CXXFLAGS: -DWEBVIEW_MSHTML
|
||||
#cgo windows LDFLAGS: -lole32 -lcomctl32 -loleaut32 -luuid -lgdi32
|
||||
|
||||
#define WEBVIEW_HEADER
|
||||
#include "webview.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern void _webviewDispatchGoCallback(void *);
|
||||
static inline void _webview_dispatch_cb(webview_t w, void *arg) {
|
||||
_webviewDispatchGoCallback(arg);
|
||||
}
|
||||
static inline void CgoWebViewDispatch(webview_t w, uintptr_t arg) {
|
||||
webview_dispatch(w, _webview_dispatch_cb, (void *)arg);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"runtime"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Ensure that main.main is called from the main thread
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
type WebView interface {
|
||||
Run()
|
||||
Terminate()
|
||||
Dispatch(f func())
|
||||
Navigate(url string)
|
||||
SetTitle(title string)
|
||||
Window() unsafe.Pointer
|
||||
Init(js string)
|
||||
Eval(js string)
|
||||
Destroy()
|
||||
/*
|
||||
SetBounds(x, y, width, height int)
|
||||
Bounds() (x, y, width, height int)
|
||||
Bind(name string, v interface{})
|
||||
*/
|
||||
}
|
||||
|
||||
type webview struct {
|
||||
w C.webview_t
|
||||
}
|
||||
|
||||
var (
|
||||
m sync.Mutex
|
||||
index uintptr
|
||||
dispatch = map[uintptr]func(){}
|
||||
)
|
||||
|
||||
func boolToInt(b bool) C.int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func New(debug bool) WebView { return NewWindow(debug, nil) }
|
||||
|
||||
func NewWindow(debug bool, window unsafe.Pointer) WebView {
|
||||
w := &webview{}
|
||||
q
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *webview) Destroy() {
|
||||
C.webview_destroy(w.w)
|
||||
}
|
||||
|
||||
func (w *webview) Run() {
|
||||
C.webview_run(w.w)
|
||||
}
|
||||
|
||||
func (w *webview) Terminate() {
|
||||
C.webview_terminate(w.w)
|
||||
}
|
||||
|
||||
func (w *webview) Window() unsafe.Pointer {
|
||||
return C.webview_get_window(w.w)
|
||||
}
|
||||
|
||||
func (w *webview) Navigate(url string) {
|
||||
s := C.CString(url)
|
||||
defer C.free(unsafe.Pointer(s))
|
||||
C.webview_navigate(w.w, s)
|
||||
}
|
||||
|
||||
func (w *webview) SetTitle(title string) {
|
||||
s := C.CString(title)
|
||||
defer C.free(unsafe.Pointer(s))
|
||||
C.webview_set_title(w.w, s)
|
||||
}
|
||||
|
||||
func (w *webview) Init(js string) {
|
||||
s := C.CString(js)
|
||||
defer C.free(unsafe.Pointer(s))
|
||||
C.webview_init(w.w, s)
|
||||
}
|
||||
|
||||
func (w *webview) Eval(js string) {
|
||||
s := C.CString(js)
|
||||
defer C.free(unsafe.Pointer(s))
|
||||
C.webview_eval(w.w, s)
|
||||
}
|
||||
|
||||
func (w *webview) Dispatch(f func()) {
|
||||
m.Lock()
|
||||
for ; dispatch[index] != nil; index++ {
|
||||
}
|
||||
dispatch[index] = f
|
||||
m.Unlock()
|
||||
C.CgoWebViewDispatch(w.w, C.uintptr_t(index))
|
||||
}
|
||||
|
||||
//export _webviewDispatchGoCallback
|
||||
func _webviewDispatchGoCallback(index unsafe.Pointer) {
|
||||
var f func()
|
||||
m.Lock()
|
||||
f = dispatch[uintptr(index)]
|
||||
delete(dispatch, uintptr(index))
|
||||
m.Unlock()
|
||||
f()
|
||||
}
|
1248
attic/webview/webview.h
Normal file
1248
attic/webview/webview.h
Normal file
File diff suppressed because it is too large
Load Diff
38
attic/webview/webview_test.cc
Normal file
38
attic/webview/webview_test.cc
Normal file
@ -0,0 +1,38 @@
|
||||
// +build ignore
|
||||
|
||||
#include "webview.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
static void test_terminate() {
|
||||
webview::webview w(false, nullptr);
|
||||
w.dispatch([&]() { w.terminate(); });
|
||||
w.run();
|
||||
}
|
||||
|
||||
static void cb_assert_arg(webview_t w, void *arg) {
|
||||
assert(w != NULL);
|
||||
assert(memcmp(arg, "arg", 3) == 0);
|
||||
}
|
||||
static void cb_terminate(webview_t w, void *arg) {
|
||||
assert(arg == NULL);
|
||||
webview_terminate(w);
|
||||
}
|
||||
static void test_c_api() {
|
||||
webview_t w;
|
||||
w = webview_create(false, NULL);
|
||||
webview_set_bounds(w, 100, 100, 480, 320, 0);
|
||||
webview_set_title(w, "Test");
|
||||
webview_navigate(w, "https://github.com/zserge/webview");
|
||||
webview_dispatch(w, cb_assert_arg, (void *)"arg");
|
||||
webview_dispatch(w, cb_terminate, NULL);
|
||||
webview_run(w);
|
||||
webview_destroy(w);
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_terminate();
|
||||
test_c_api();
|
||||
return 0;
|
||||
}
|
@ -479,6 +479,7 @@ EmbeddedNetworkController::~EmbeddedNetworkController()
|
||||
void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender)
|
||||
{
|
||||
char tmp[64];
|
||||
|
||||
_signingId = signingId;
|
||||
_sender = sender;
|
||||
_signingIdAddressString = signingId.address().toString(tmp);
|
||||
@ -1445,6 +1446,7 @@ void EmbeddedNetworkController::_request(
|
||||
|
||||
const bool noAutoAssignIps = OSUtils::jsonBool(member["noAutoAssignIps"],false);
|
||||
|
||||
// Set IPv6 static IPs based on NDP emulated schemes if enabled.
|
||||
if ((v6AssignMode.is_object())&&(!noAutoAssignIps)) {
|
||||
if ((OSUtils::jsonBool(v6AssignMode["rfc4193"],false))&&(nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) {
|
||||
nc->staticIps[nc->staticIpCount++] = InetAddress::makeIpv6rfc4193(nwid,identity.address().toInt());
|
||||
|
@ -43,10 +43,10 @@ LFDB::LFDB(const Identity &myId,const char *path,const char *lfOwnerPrivate,cons
|
||||
|
||||
// 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);
|
||||
uint8_t sha384pk[48];
|
||||
_myId.hash(sha384pk,true);
|
||||
char maskingKey [128];
|
||||
Utils::hex(sha512pk,32,maskingKey);
|
||||
Utils::hex(sha384pk,32,maskingKey);
|
||||
|
||||
httplib::Client htcli(_lfNodeHost.c_str(),_lfNodePort,600);
|
||||
int64_t timeRangeStart = 0;
|
||||
|
@ -13,53 +13,6 @@
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
// AddRoot CLI command
|
||||
func AddRoot(basePath, authToken string, args []string) {
|
||||
if len(args) == 0 {
|
||||
Help()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
locData, err := ioutil.ReadFile(args[0])
|
||||
if err != nil {
|
||||
locData, err2 := base64.StdEncoding.DecodeString(strings.TrimSpace(args[0]))
|
||||
if err2 != nil || len(locData) == 0 {
|
||||
fmt.Printf("ERROR: unable to read locator: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
loc, err := zerotier.NewLocatorFromBytes(locData)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: invalid locator '%s' (tried as file and base64 literal): %s\n", args[0], err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var name string
|
||||
if len(args) > 1 {
|
||||
if len(args) > 2 {
|
||||
Help()
|
||||
os.Exit(1)
|
||||
}
|
||||
name = strings.TrimSpace(args[1])
|
||||
}
|
||||
|
||||
var result zerotier.Root
|
||||
apiPost(basePath, authToken, "/root/"+url.PathEscape(name), &zerotier.Root{
|
||||
Name: name,
|
||||
Locator: loc,
|
||||
}, &result)
|
||||
|
||||
fmt.Println(jsonDump(&result))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
@ -41,12 +41,8 @@ Commands:
|
||||
status Show ZeroTier service status and config
|
||||
peers Show VL1 peers
|
||||
roots Show configured VL1 root servers
|
||||
addroot <locator> [name] Add a VL1 root
|
||||
removeroot <name> Remove a VL1 root
|
||||
locator <command> [args] Locator management commands
|
||||
new <identity> <address> [...] Create and sign locator for identity
|
||||
newdnskey Create a secure DNS name and secret
|
||||
getdns <dns key> <locator> Create secure DNS TXT records
|
||||
addroot <identity> Add VL1 root server
|
||||
removeroot <identity|address> Remove VL1 root server
|
||||
identity <command> [args] Identity management commands
|
||||
new [c25519|p384] Create new identity (including secret)
|
||||
getpublic <identity> Extract only public part of identity
|
||||
|
@ -1,137 +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: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
func locatorNew(args []string) {
|
||||
if len(args) < 2 {
|
||||
Help()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
identity := readIdentity(args[0])
|
||||
if !identity.HasPrivate() {
|
||||
fmt.Println("FATAL: identity does not contain a secret key (required to sign locator)")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var virt []*zerotier.Identity
|
||||
var phys []*zerotier.InetAddress
|
||||
for i := 1; i < len(args); i++ {
|
||||
if strings.Contains(args[i], "/") {
|
||||
a := zerotier.NewInetAddressFromString(args[i])
|
||||
if a == nil {
|
||||
fmt.Printf("FATAL: IP/port address '%s' is not valid\n", args[i])
|
||||
os.Exit(1)
|
||||
}
|
||||
phys = append(phys, a)
|
||||
} else {
|
||||
a, err := zerotier.NewIdentityFromString(args[i])
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: identity (virtual address) '%s' is not valid: %s\n", args[i], err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
virt = append(virt, a)
|
||||
}
|
||||
}
|
||||
|
||||
loc, err := zerotier.NewLocator(identity, virt, phys)
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: internal error creating locator: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(jsonDump(loc))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func locatorNewDNSKey(args []string) {
|
||||
if len(args) != 0 {
|
||||
Help()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
sk, err := zerotier.NewLocatorDNSSigningKey()
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: error creating secure DNS signing key: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(jsonDump(sk))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func locatorGetDNS(args []string) {
|
||||
if len(args) < 2 {
|
||||
Help()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
keyData, err := ioutil.ReadFile(args[0])
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: unable to read secure DNS key file: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
var sk zerotier.LocatorDNSSigningKey
|
||||
err = json.Unmarshal(keyData, &sk)
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: DNS key file invalid: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
locData, err := ioutil.ReadFile(args[1])
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: unable to read locator: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
var loc zerotier.Locator
|
||||
err = json.Unmarshal(locData, &loc)
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: locator invalid: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
txt, err := loc.MakeTXTRecords(&sk)
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: error creating TXT records: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
for _, t := range txt {
|
||||
fmt.Println(t)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Locator CLI command
|
||||
func Locator(args []string) {
|
||||
if len(args) > 0 {
|
||||
switch args[0] {
|
||||
case "new":
|
||||
locatorNew(args[1:])
|
||||
case "newdnskey":
|
||||
locatorNewDNSKey(args[1:])
|
||||
case "getdns":
|
||||
locatorGetDNS(args[1:])
|
||||
}
|
||||
}
|
||||
Help()
|
||||
os.Exit(1)
|
||||
}
|
@ -13,51 +13,6 @@
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
// Roots CLI command
|
||||
func Roots(basePath, authToken string, args []string, jsonOutput bool) {
|
||||
var roots []zerotier.Root
|
||||
apiGet(basePath, authToken, "/root", &roots)
|
||||
|
||||
if jsonOutput {
|
||||
fmt.Println(jsonDump(roots))
|
||||
} else {
|
||||
fmt.Printf("%32s <address> <physical/virtual>\n", "<name>")
|
||||
for _, r := range roots {
|
||||
rn := r.Name
|
||||
if len(rn) > 32 {
|
||||
rn = rn[len(rn)-32:]
|
||||
}
|
||||
if r.Locator != nil {
|
||||
if len(r.Locator.Physical) == 0 && len(r.Locator.Virtual) == 0 {
|
||||
fmt.Printf("%32s %.10x -\n", rn, uint64(r.Locator.Identity.Address()))
|
||||
} else {
|
||||
fmt.Printf("%32s %.10x ", rn, uint64(r.Locator.Identity.Address()))
|
||||
for i, a := range r.Locator.Physical {
|
||||
if i > 0 {
|
||||
fmt.Print(",")
|
||||
}
|
||||
fmt.Print(a.String())
|
||||
}
|
||||
for i, a := range r.Locator.Virtual {
|
||||
if i > 0 || len(r.Locator.Physical) > 0 {
|
||||
fmt.Print(",")
|
||||
}
|
||||
fmt.Print(a.String())
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%32s - -\n", rn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
|
@ -127,8 +127,6 @@ func main() {
|
||||
case "removeroot":
|
||||
authTokenRequired(authToken)
|
||||
cli.RemoveRoot(basePath, authToken, cmdArgs)
|
||||
case "locator":
|
||||
cli.Locator(cmdArgs)
|
||||
case "identity":
|
||||
cli.Identity(cmdArgs)
|
||||
case "networks", "listnetworks":
|
||||
|
@ -5,4 +5,5 @@ go 1.13
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.4.14
|
||||
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95
|
||||
golang.org/x/sys v0.0.0-20200107162124-548cf772de50 // indirect
|
||||
)
|
||||
|
@ -13,3 +13,5 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259 h1:so6Hr/LodwSZ5UQDu/7PmQiDeS112WwtLvU3lpSPZTU=
|
||||
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200107162124-548cf772de50 h1:YvQ10rzcqWXLlJZ3XCUoO25savxmscf4+SC+ZqiCHhA=
|
||||
golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -13,35 +13,25 @@
|
||||
|
||||
#include "GoGlue.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cerrno>
|
||||
|
||||
#include "../../node/Constants.hpp"
|
||||
#include "../../node/InetAddress.hpp"
|
||||
#include "../../node/Node.hpp"
|
||||
#include "../../node/Utils.hpp"
|
||||
#include "../../node/MAC.hpp"
|
||||
#include "../../node/Address.hpp"
|
||||
#include "../../node/Locator.hpp"
|
||||
#include "../../osdep/OSUtils.hpp"
|
||||
#include "../../osdep/EthernetTap.hpp"
|
||||
#include "../../osdep/ManagedRoute.hpp"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#ifdef __BSD__
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
@ -56,7 +46,6 @@
|
||||
#include <mutex>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
@ -111,10 +100,9 @@ const char *ZT_PLATFORM_DEFAULT_HOMEPATH = defaultHomePath.c_str();
|
||||
|
||||
/* These functions are implemented in Go in pkg/ztnode/node-callbacks.go */
|
||||
extern "C" int goPathCheckFunc(void *,uint64_t,int,const void *,int);
|
||||
extern "C" int goPathLookupFunc(void *,uint64_t,int,int *,uint8_t [16],int *);
|
||||
extern "C" int goPathLookupFunc(void *,uint64_t,int,const ZT_Identity *,int *,uint8_t [16],int *);
|
||||
extern "C" void goStateObjectPutFunc(void *,int,const uint64_t [2],const void *,int);
|
||||
extern "C" int goStateObjectGetFunc(void *,int,const uint64_t [2],void *,unsigned int);
|
||||
extern "C" void goDNSResolverFunc(void *,const uint8_t *,int,const char *,uintptr_t);
|
||||
extern "C" void goVirtualNetworkConfigFunc(void *,ZT_GoTap *,uint64_t,int,const ZT_VirtualNetworkConfig *);
|
||||
extern "C" void goZtEvent(void *,int,const void *);
|
||||
extern "C" void goHandleTapAddedMulticastGroup(void *,ZT_GoTap *,uint64_t,uint64_t,uint32_t);
|
||||
@ -279,6 +267,7 @@ static int ZT_GoNode_PathLookupFunction(
|
||||
void *uptr,
|
||||
void *tptr,
|
||||
uint64_t ztAddress,
|
||||
const ZT_Identity *id,
|
||||
int desiredAddressFamily,
|
||||
struct sockaddr_storage *sa)
|
||||
{
|
||||
@ -289,6 +278,7 @@ static int ZT_GoNode_PathLookupFunction(
|
||||
reinterpret_cast<ZT_GoNode *>(uptr)->goUserPtr,
|
||||
ztAddress,
|
||||
desiredAddressFamily,
|
||||
id,
|
||||
&family,
|
||||
ip,
|
||||
&port
|
||||
@ -310,20 +300,6 @@ static int ZT_GoNode_PathLookupFunction(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ZT_GoNode_DNSResolver(
|
||||
ZT_Node *node,
|
||||
void *uptr,
|
||||
void *tptr,
|
||||
const enum ZT_DNSRecordType *types,
|
||||
unsigned int numTypes,
|
||||
const char *name,
|
||||
uintptr_t requestId)
|
||||
{
|
||||
uint8_t t[256];
|
||||
for(unsigned int i=0;(i<numTypes)&&(i<256);++i) t[i] = (uint8_t)types[i];
|
||||
goDNSResolverFunc(reinterpret_cast<ZT_GoNode *>(uptr)->goUserPtr,t,(int)numTypes,name,requestId);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath,uintptr_t userPtr)
|
||||
@ -336,7 +312,6 @@ extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath,uintptr_t userPtr)
|
||||
cb.virtualNetworkFrameFunction = &ZT_GoNode_VirtualNetworkFrameFunction;
|
||||
cb.virtualNetworkConfigFunction = &ZT_GoNode_VirtualNetworkConfigFunction;
|
||||
cb.eventCallback = &ZT_GoNode_EventCallback;
|
||||
cb.dnsResolver = &ZT_GoNode_DNSResolver;
|
||||
cb.pathCheckFunction = &ZT_GoNode_PathCheckFunction;
|
||||
cb.pathLookupFunction = &ZT_GoNode_PathLookupFunction;
|
||||
|
||||
@ -727,133 +702,3 @@ extern "C" int ZT_GoTap_removeRoute(ZT_GoTap *tap,int targetAf,const void *targe
|
||||
}
|
||||
return reinterpret_cast<EthernetTap *>(tap)->removeRoute(target,via,metric);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
extern "C" const char *ZT_GoIdentity_generate(int type)
|
||||
{
|
||||
Identity id;
|
||||
id.generate((Identity::Type)type);
|
||||
char *tmp = (char *)malloc(ZT_IDENTITY_STRING_BUFFER_LENGTH);
|
||||
if (tmp)
|
||||
id.toString(true,tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
extern "C" int ZT_GoIdentity_validate(const char *idStr)
|
||||
{
|
||||
Identity id;
|
||||
if (!id.fromString(idStr))
|
||||
return 0;
|
||||
if (!id.locallyValidate())
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" int ZT_GoIdentity_sign(const char *idStr,const void *data,unsigned int len,void *sigbuf,unsigned int sigbuflen)
|
||||
{
|
||||
Identity id;
|
||||
if (!id.fromString(idStr))
|
||||
return 0;
|
||||
return (int)id.sign(data,len,sigbuf,sigbuflen);
|
||||
}
|
||||
|
||||
extern "C" int ZT_GoIdentity_verify(const char *idStr,const void *data,unsigned int len,const void *sig,unsigned int siglen)
|
||||
{
|
||||
Identity id;
|
||||
if (!id.fromString(idStr))
|
||||
return 0;
|
||||
return id.verify(data,len,sig,siglen) ? 1 : 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
extern "C" int ZT_GoLocator_makeSecureDNSName(char *name,unsigned int nameBufSize,uint8_t *privateKey,unsigned int privateKeyBufSize)
|
||||
{
|
||||
if ((privateKeyBufSize < ZT_ECC384_PRIVATE_KEY_SIZE)||(nameBufSize < 256))
|
||||
return -1;
|
||||
uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE];
|
||||
ECC384GenerateKey(pub,privateKey);
|
||||
const Str n(Locator::makeSecureDnsName(pub));
|
||||
if (n.length() >= nameBufSize)
|
||||
return -1;
|
||||
Utils::scopy(name,nameBufSize,n.c_str());
|
||||
return ZT_ECC384_PRIVATE_KEY_SIZE;
|
||||
}
|
||||
|
||||
extern "C" int ZT_GoLocator_makeLocator(
|
||||
uint8_t *buf,
|
||||
unsigned int bufSize,
|
||||
int64_t ts,
|
||||
const char *id,
|
||||
const struct sockaddr_storage *physicalAddresses,
|
||||
unsigned int physicalAddressCount,
|
||||
const char **virtualAddresses,
|
||||
unsigned int virtualAddressCount)
|
||||
{
|
||||
Locator loc;
|
||||
for(unsigned int i=0;i<physicalAddressCount;++i) {
|
||||
loc.add(*reinterpret_cast<const InetAddress *>(physicalAddresses + i));
|
||||
}
|
||||
for(unsigned int i=0;i<virtualAddressCount;++i) {
|
||||
Identity id;
|
||||
if (!id.fromString(virtualAddresses[i]))
|
||||
return -1;
|
||||
loc.add(id);
|
||||
}
|
||||
Identity signingId;
|
||||
if (!signingId.fromString(id))
|
||||
return -1;
|
||||
if (!signingId.hasPrivate())
|
||||
return -1;
|
||||
if (!loc.finish(signingId,ts))
|
||||
return -1;
|
||||
Buffer<65536> *tmp = new Buffer<65536>();
|
||||
loc.serialize(*tmp);
|
||||
if (tmp->size() > bufSize) {
|
||||
delete tmp;
|
||||
return -1;
|
||||
}
|
||||
memcpy(buf,tmp->data(),tmp->size());
|
||||
int s = (int)tmp->size();
|
||||
delete tmp;
|
||||
return s;
|
||||
}
|
||||
|
||||
extern "C" int ZT_GoLocator_decodeLocator(const uint8_t *locatorBytes,unsigned int locatorSize,struct ZT_GoLocator_Info *info)
|
||||
{
|
||||
Locator loc;
|
||||
if (!loc.deserialize(locatorBytes,locatorSize))
|
||||
return -1;
|
||||
if (!loc.verify())
|
||||
return -2;
|
||||
loc.id().toString(false,info->id);
|
||||
info->phyCount = 0;
|
||||
info->virtCount = 0;
|
||||
for(auto p=loc.phy().begin();p!=loc.phy().end();++p)
|
||||
memcpy(&(info->phy[info->phyCount++]),&(*p),sizeof(struct sockaddr_storage));
|
||||
for(auto v=loc.virt().begin();v!=loc.virt().end();++v)
|
||||
v->toString(false,info->virt[info->virtCount++]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ZT_GoLocator_makeSignedTxtRecords(
|
||||
const uint8_t *locator,
|
||||
unsigned int locatorSize,
|
||||
const char *name,
|
||||
const uint8_t *privateKey,
|
||||
unsigned int privateKeySize,
|
||||
char results[256][256])
|
||||
{
|
||||
if (privateKeySize != ZT_ECC384_PRIVATE_KEY_SIZE)
|
||||
return -1;
|
||||
Locator loc;
|
||||
if (!loc.deserialize(locator,locatorSize))
|
||||
return -1;
|
||||
std::vector<Str> r(loc.makeTxtRecords(privateKey));
|
||||
if (r.size() > 256)
|
||||
return -1;
|
||||
for(unsigned long i=0;i<r.size();++i)
|
||||
Utils::scopy(results[i],256,r[i].c_str());
|
||||
return (int)r.size();
|
||||
}
|
||||
|
@ -14,14 +14,22 @@
|
||||
#ifndef ZT_GONODE_H
|
||||
#define ZT_GONODE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "../../include/ZeroTierCore.h"
|
||||
#include "../../node/Constants.hpp"
|
||||
|
||||
/****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* A pointer to an instance of EthernetTap */
|
||||
typedef void ZT_GoTap;
|
||||
@ -32,18 +40,8 @@ typedef void ZT_GoTap;
|
||||
struct ZT_GoNode_Impl;
|
||||
typedef struct ZT_GoNode_Impl ZT_GoNode;
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
extern const char *ZT_PLATFORM_DEFAULT_HOMEPATH;
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
ZT_GoNode *ZT_GoNode_new(const char *workingPath,uintptr_t userPtr);
|
||||
|
||||
void ZT_GoNode_delete(ZT_GoNode *gn);
|
||||
@ -60,8 +58,6 @@ ZT_GoTap *ZT_GoNode_join(ZT_GoNode *gn,uint64_t nwid);
|
||||
|
||||
void ZT_GoNode_leave(ZT_GoNode *gn,uint64_t nwid);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void ZT_GoTap_setEnabled(ZT_GoTap *tap,int enabled);
|
||||
|
||||
int ZT_GoTap_addIp(ZT_GoTap *tap,int af,const void *ip,int netmaskBits);
|
||||
@ -88,67 +84,6 @@ int ZT_GoTap_addRoute(ZT_GoTap *tap,int targetAf,const void *targetIp,int target
|
||||
|
||||
int ZT_GoTap_removeRoute(ZT_GoTap *tap,int targetAf,const void *targetIp,int targetNetmaskBits,int viaAf,const void *viaIp,unsigned int metric);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *ZT_GoIdentity_generate(int type);
|
||||
|
||||
int ZT_GoIdentity_validate(const char *idStr);
|
||||
|
||||
int ZT_GoIdentity_sign(const char *idStr,const void *data,unsigned int len,void *sigbuf,unsigned int sigbuflen);
|
||||
|
||||
int ZT_GoIdentity_verify(const char *idStr,const void *data,unsigned int len,const void *sig,unsigned int siglen);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
struct ZT_GoLocator_Info {
|
||||
char id[1024];
|
||||
unsigned int phyCount;
|
||||
unsigned int virtCount;
|
||||
struct sockaddr_storage phy[256];
|
||||
char virt[256][1024];
|
||||
};
|
||||
|
||||
/* Returns length of private key stored in private key buffer on success, -1 on fail */
|
||||
int ZT_GoLocator_makeSecureDNSName(char name[256],unsigned int nameBufSize,uint8_t *privateKey,unsigned int privateKeyBufSize);
|
||||
|
||||
/*
|
||||
* The id is the full identity described by the locator. It must include
|
||||
* its secret key to permit the locator to be signed.
|
||||
*
|
||||
* Physical addresses must be IPv4 or IPv6 IP/port pairs. Virtual addresses
|
||||
* must be full ZeroTier identities in string format.
|
||||
*
|
||||
* On success this returns the actual number of bytes stored in the buffer.
|
||||
* On failure -1 is returned.
|
||||
*/
|
||||
int ZT_GoLocator_makeLocator(
|
||||
uint8_t *buf,
|
||||
unsigned int bufSize,
|
||||
int64_t ts,
|
||||
const char *id,
|
||||
const struct sockaddr_storage *physicalAddresses,
|
||||
unsigned int physicalAddressCount,
|
||||
const char **virtualAddresses,
|
||||
unsigned int virtualAddressCount);
|
||||
|
||||
/* Returns >0 on success, fills info structure */
|
||||
int ZT_GoLocator_decodeLocator(const uint8_t *locatorBytes,unsigned int locatorSize,struct ZT_GoLocator_Info *info);
|
||||
|
||||
/*
|
||||
* The privateKey and privateKeySize are those created by makeSecureDNSName.
|
||||
* Results is filled and the number of lines of TXT are returned. The value
|
||||
* -1 is returned on error.
|
||||
*/
|
||||
int ZT_GoLocator_makeSignedTxtRecords(
|
||||
const uint8_t *locator,
|
||||
unsigned int locatorSize,
|
||||
const char *name,
|
||||
const uint8_t *privateKey,
|
||||
unsigned int privateKeySize,
|
||||
char results[256][256]);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -460,57 +460,14 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
||||
}
|
||||
apiSetStandardHeaders(out)
|
||||
|
||||
var queriedName string
|
||||
if len(req.URL.Path) > 6 {
|
||||
queriedName = req.URL.Path[6:]
|
||||
}
|
||||
//var queriedName string
|
||||
//if len(req.URL.Path) > 6 {
|
||||
// queriedName = req.URL.Path[6:]
|
||||
//}
|
||||
|
||||
if req.Method == http.MethodDelete {
|
||||
if len(queriedName) > 0 {
|
||||
roots := node.Roots()
|
||||
for _, r := range roots {
|
||||
if r.Name == queriedName {
|
||||
node.RemoveRoot(queriedName)
|
||||
_ = apiSendObj(out, req, http.StatusOK, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"root not found"})
|
||||
} else if req.Method == http.MethodPost || req.Method == http.MethodPut {
|
||||
if len(queriedName) == 0 {
|
||||
_ = apiSendObj(out, req, http.StatusBadRequest, &APIErr{"only individual roots can be added or modified with POST/PUT"})
|
||||
return
|
||||
}
|
||||
var r Root
|
||||
if apiReadObj(out, req, &r) == nil {
|
||||
if r.Name != queriedName {
|
||||
_ = apiSendObj(out, req, http.StatusBadRequest, &APIErr{"root name does not match name in path"})
|
||||
return
|
||||
}
|
||||
err := node.SetRoot(r.Name, r.Locator)
|
||||
if err != nil {
|
||||
_ = apiSendObj(out, req, http.StatusBadRequest, &APIErr{"set/update root failed: " + err.Error()})
|
||||
} else {
|
||||
roots := node.Roots()
|
||||
for _, r := range roots {
|
||||
if r.Name == queriedName {
|
||||
_ = apiSendObj(out, req, http.StatusOK, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"set/update root failed: root set but not subsequently found in list"})
|
||||
}
|
||||
}
|
||||
} else if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
roots := node.Roots()
|
||||
for _, r := range roots {
|
||||
if r.Name == queriedName {
|
||||
_ = apiSendObj(out, req, http.StatusOK, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"root not found"})
|
||||
} else {
|
||||
out.Header().Set("Allow", "GET, HEAD, PUT, POST, DELETE")
|
||||
_ = apiSendObj(out, req, http.StatusMethodNotAllowed, &APIErr{"unsupported method: " + req.Method})
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
package zerotier
|
||||
|
||||
//#cgo CFLAGS: -O3
|
||||
//#include "../../native/GoGlue.h"
|
||||
import "C"
|
||||
|
||||
@ -47,15 +46,26 @@ type Identity struct {
|
||||
privateKey []byte
|
||||
}
|
||||
|
||||
// NewIdentity generates a new identity of the selected type
|
||||
func NewIdentity(identityType int) (*Identity, error) {
|
||||
cIdStr := C.ZT_GoIdentity_generate(C.int(identityType))
|
||||
if uintptr(unsafe.Pointer(cIdStr)) == 0 {
|
||||
func newIdentityFromCIdentity(cid unsafe.Pointer) (*Identity, error) {
|
||||
if uintptr(cid) == 0 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
var idStrBuf [4096]byte
|
||||
idStr := C.ZT_Identity_toString(cid,(*C.char)(unsafe.Pointer(&idStrBuf[0])),4096,1)
|
||||
if uintptr(unsafe.Pointer(idStr)) == 0 {
|
||||
return nil, ErrInternal
|
||||
}
|
||||
id, err := NewIdentityFromString(C.GoString(cIdStr))
|
||||
C.free(unsafe.Pointer(cIdStr))
|
||||
return id, err
|
||||
return NewIdentityFromString(C.GoString(idStr))
|
||||
}
|
||||
|
||||
// NewIdentity generates a new identity of the selected type
|
||||
func NewIdentity(identityType int) (*Identity, error) {
|
||||
cid := C.ZT_Identity_new(C.enum_ZT_Identity_Type(identityType))
|
||||
if uintptr(unsafe.Pointer(cid)) == 0 {
|
||||
return nil, ErrInternal
|
||||
}
|
||||
defer C.ZT_Identity_delete(cid)
|
||||
return newIdentityFromCIdentity(cid)
|
||||
}
|
||||
|
||||
// NewIdentityFromString generates a new identity from its string representation.
|
||||
@ -159,23 +169,35 @@ func (id *Identity) String() string {
|
||||
func (id *Identity) LocallyValidate() bool {
|
||||
idCStr := C.CString(id.String())
|
||||
defer C.free(unsafe.Pointer(idCStr))
|
||||
return C.ZT_GoIdentity_validate(idCStr) != 0
|
||||
cid := C.ZT_Identity_fromString(idCStr)
|
||||
if uintptr(cid) == 0 {
|
||||
return false
|
||||
}
|
||||
defer C.ZT_Identity_delete(cid)
|
||||
return C.ZT_Identity_validate(cid) != 0
|
||||
}
|
||||
|
||||
// Sign signs a message with this identity
|
||||
func (id *Identity) Sign(msg []byte) ([]byte, error) {
|
||||
idCStr := C.CString(id.PrivateKeyString())
|
||||
var sigbuf [96]byte
|
||||
defer C.free(unsafe.Pointer(idCStr))
|
||||
cid := C.ZT_Identity_fromString(idCStr)
|
||||
if uintptr(cid) == 0 {
|
||||
return nil, ErrInvalidKey
|
||||
}
|
||||
defer C.ZT_Identity_delete(cid)
|
||||
|
||||
var dataP unsafe.Pointer
|
||||
if len(msg) > 0 {
|
||||
dataP = unsafe.Pointer(&msg[0])
|
||||
}
|
||||
siglen := C.ZT_GoIdentity_sign(idCStr, dataP, C.uint(len(msg)), unsafe.Pointer(&sigbuf[0]), C.uint(len(sigbuf)))
|
||||
C.free(unsafe.Pointer(idCStr))
|
||||
if siglen <= 0 {
|
||||
var sig [96]byte
|
||||
sigLen := C.ZT_Identity_sign(cid,dataP,C.uint(len(msg)),unsafe.Pointer(&sig[0]),96)
|
||||
if sigLen <= 0 {
|
||||
return nil, ErrInvalidKey
|
||||
}
|
||||
return sigbuf[0:int(siglen)], nil
|
||||
|
||||
return sig[0:uint(sigLen)], nil
|
||||
}
|
||||
|
||||
// Verify verifies a signature
|
||||
@ -183,13 +205,20 @@ func (id *Identity) Verify(msg, sig []byte) bool {
|
||||
if len(sig) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
idCStr := C.CString(id.String())
|
||||
defer C.free(unsafe.Pointer(idCStr))
|
||||
cid := C.ZT_Identity_fromString(idCStr)
|
||||
if uintptr(cid) == 0 {
|
||||
return false
|
||||
}
|
||||
defer C.ZT_Identity_delete(cid)
|
||||
|
||||
var dataP unsafe.Pointer
|
||||
if len(msg) > 0 {
|
||||
dataP = unsafe.Pointer(&msg[0])
|
||||
}
|
||||
return C.ZT_GoIdentity_verify(idCStr, dataP, C.uint(len(msg)), unsafe.Pointer(&sig[0]), C.uint(len(sig))) != 0
|
||||
return C.ZT_Identity_verify(cid,dataP,C.uint(len(msg)),unsafe.Pointer(&sig[0]),C.uint(len(sig))) != 0
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this Identity in its string format (private key is never included)
|
||||
|
@ -33,7 +33,7 @@ type LocalConfigPhysicalPathConfiguration struct {
|
||||
// LocalConfigVirtualAddressConfiguration contains settings for virtual addresses
|
||||
type LocalConfigVirtualAddressConfiguration struct {
|
||||
// Try is a list of IPs/ports to try for this peer in addition to anything learned from roots or direct path push
|
||||
Try []InetAddress `json:",omitempty"`
|
||||
Try []InetAddress `json:"try,omitempty"`
|
||||
}
|
||||
|
||||
// ExternalAddress is an externally visible address
|
||||
|
@ -1,191 +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: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package zerotier
|
||||
|
||||
//#cgo CFLAGS: -O3
|
||||
//#include "../../native/GoGlue.h"
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// LocatorDNSSigningKey is the public (as a secure DNS name) and private keys for entering locators into DNS
|
||||
type LocatorDNSSigningKey struct {
|
||||
SecureDNSName string `json:"secureDNSName"`
|
||||
PrivateKey []byte `json:"privateKey"`
|
||||
}
|
||||
|
||||
// NewLocatorDNSSigningKey creates a new signing key and secure DNS name for storing locators in DNS
|
||||
func NewLocatorDNSSigningKey() (*LocatorDNSSigningKey, error) {
|
||||
var nameBuf [256]C.char
|
||||
var keyBuf [64]byte
|
||||
keySize := int(C.ZT_GoLocator_makeSecureDNSName(&nameBuf[0], 256, (*C.uint8_t)(unsafe.Pointer(&keyBuf[0])), 128))
|
||||
if keySize <= 0 {
|
||||
return nil, ErrInternal
|
||||
}
|
||||
var sk LocatorDNSSigningKey
|
||||
sk.SecureDNSName = C.GoString(&nameBuf[0])
|
||||
sk.PrivateKey = keyBuf[0:keySize]
|
||||
return &sk, nil
|
||||
}
|
||||
|
||||
// Locator is a binary serialized record containing information about where a ZeroTier node is located on the network.
|
||||
// Note that for JSON objects only Bytes needs to be specified. When JSON is deserialized only this field is used
|
||||
// and the others are always reconstructed from it.
|
||||
type Locator struct {
|
||||
// Identity is the full identity of the node being located
|
||||
Identity *Identity `json:"identity"`
|
||||
|
||||
// Physical is a list of static physical network addresses for this node
|
||||
Physical []*InetAddress `json:"physical,omitempty"`
|
||||
|
||||
// Virtual is a list of ZeroTier nodes that can relay to this node
|
||||
Virtual []*Identity `json:"virtual,omitempty"`
|
||||
|
||||
// Bytes is the raw serialized Locator
|
||||
Bytes []byte `json:"bytes,omitempty"`
|
||||
}
|
||||
|
||||
// NewLocator creates a new locator with the given identity and addresses and the current time as timestamp.
|
||||
// The identity must include its secret key so that it can sign the final locator.
|
||||
func NewLocator(id *Identity, virtualAddresses []*Identity, physicalAddresses []*InetAddress) (*Locator, error) {
|
||||
if !id.HasPrivate() {
|
||||
return nil, ErrSecretKeyRequired
|
||||
}
|
||||
|
||||
idstr := id.PrivateKeyString()
|
||||
phy := make([]C.struct_sockaddr_storage, len(physicalAddresses))
|
||||
virt := make([]*C.char, len(virtualAddresses))
|
||||
idCstr := C.CString(idstr)
|
||||
|
||||
defer func() {
|
||||
C.free(unsafe.Pointer(idCstr))
|
||||
for _, v := range virt {
|
||||
if uintptr(unsafe.Pointer(v)) != 0 {
|
||||
C.free(unsafe.Pointer(v))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for i := 0; i < len(physicalAddresses); i++ {
|
||||
if !makeSockaddrStorage(physicalAddresses[i].IP, physicalAddresses[i].Port, &phy[i]) {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(virtualAddresses); i++ {
|
||||
idstr := virtualAddresses[i].String()
|
||||
virt[i] = C.CString(idstr)
|
||||
}
|
||||
|
||||
var buf [65536]byte
|
||||
var pPhy *C.struct_sockaddr_storage
|
||||
var pVirt **C.char
|
||||
if len(phy) > 0 {
|
||||
pPhy = &phy[0]
|
||||
}
|
||||
if len(virt) > 0 {
|
||||
pVirt = &virt[0]
|
||||
}
|
||||
locSize := C.ZT_GoLocator_makeLocator((*C.uint8_t)(unsafe.Pointer(&buf[0])), 65536, C.int64_t(TimeMs()), idCstr, pPhy, C.uint(len(phy)), pVirt, C.uint(len(virt)))
|
||||
if locSize <= 0 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
|
||||
r := make([]byte, int(locSize))
|
||||
copy(r[:], buf[0:int(locSize)])
|
||||
return &Locator{
|
||||
Identity: id,
|
||||
Physical: physicalAddresses,
|
||||
Virtual: virtualAddresses,
|
||||
Bytes: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewLocatorFromBytes decodes a locator from its serialized byte array form
|
||||
func NewLocatorFromBytes(b []byte) (*Locator, error) {
|
||||
if len(b) == 0 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
var info C.struct_ZT_GoLocator_Info
|
||||
res := C.ZT_GoLocator_decodeLocator((*C.uint8_t)(unsafe.Pointer(&b[0])), C.uint(len(b)), &info)
|
||||
if res == -2 {
|
||||
return nil, ErrInvalidSignature
|
||||
} else if res <= 0 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
|
||||
var loc Locator
|
||||
|
||||
var err error
|
||||
loc.Identity, err = NewIdentityFromString(C.GoString(&info.id[0]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < int(info.phyCount); i++ {
|
||||
ua := sockaddrStorageToUDPAddr(&info.phy[i])
|
||||
if ua != nil {
|
||||
loc.Physical = append(loc.Physical, &InetAddress{IP: ua.IP, Port: ua.Port})
|
||||
}
|
||||
}
|
||||
for i := 0; i < int(info.virtCount); i++ {
|
||||
id, err := NewIdentityFromString(C.GoString(&info.virt[i][0]))
|
||||
if err == nil {
|
||||
loc.Virtual = append(loc.Virtual, id)
|
||||
}
|
||||
}
|
||||
loc.Bytes = b
|
||||
|
||||
return &loc, nil
|
||||
}
|
||||
|
||||
// MakeTXTRecords creates secure DNS TXT records for this locator
|
||||
func (l *Locator) MakeTXTRecords(key *LocatorDNSSigningKey) ([]string, error) {
|
||||
if key == nil || len(l.Bytes) == 0 || len(key.PrivateKey) == 0 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
var results [256][256]C.char
|
||||
cName := C.CString(key.SecureDNSName)
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
count := int(C.ZT_GoLocator_makeSignedTxtRecords((*C.uint8_t)(&l.Bytes[0]), C.uint(len(l.Bytes)), cName, (*C.uint8_t)(&key.PrivateKey[0]), C.uint(len(key.PrivateKey)), &results[0]))
|
||||
if count > 0 {
|
||||
var t []string
|
||||
for i := 0; i < int(count); i++ {
|
||||
t = append(t, C.GoString(&results[i][0]))
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
return nil, ErrInternal
|
||||
}
|
||||
|
||||
type locatorForUnmarshal struct {
|
||||
Bytes []byte `json:"bytes,omitempty"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this Locator from a byte array in JSON.
|
||||
func (l *Locator) UnmarshalJSON(j []byte) error {
|
||||
var bytes locatorForUnmarshal
|
||||
err := json.Unmarshal(j, &bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmp, err := NewLocatorFromBytes(bytes.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*l = *tmp
|
||||
return nil
|
||||
}
|
@ -595,62 +595,6 @@ func (n *Node) Networks() []*Network {
|
||||
return nws
|
||||
}
|
||||
|
||||
// Roots retrieves a list of root servers on this node and their preferred and online status.
|
||||
func (n *Node) Roots() []*Root {
|
||||
var roots []*Root
|
||||
rl := C.ZT_Node_listRoots(unsafe.Pointer(n.zn), C.int64_t(TimeMs()))
|
||||
if rl != nil {
|
||||
for i := 0; i < int(rl.count); i++ {
|
||||
root := (*C.ZT_Root)(unsafe.Pointer(uintptr(unsafe.Pointer(rl)) + C.sizeof_ZT_RootList))
|
||||
loc, _ := NewLocatorFromBytes(C.GoBytes(root.locator, C.int(root.locatorSize)))
|
||||
if loc != nil {
|
||||
roots = append(roots, &Root{
|
||||
Name: C.GoString(root.name),
|
||||
Locator: loc,
|
||||
})
|
||||
}
|
||||
}
|
||||
C.ZT_Node_freeQueryResult(unsafe.Pointer(n.zn), unsafe.Pointer(rl))
|
||||
}
|
||||
return roots
|
||||
}
|
||||
|
||||
// SetRoot sets or updates a root.
|
||||
// Name can be a DNS name (preferably secure) for DNS fetched locators or can be
|
||||
// the empty string for static roots. If the name is empty then the locator must
|
||||
// be non-nil.
|
||||
func (n *Node) SetRoot(name string, locator *Locator) error {
|
||||
if len(name) == 0 {
|
||||
if locator == nil {
|
||||
return ErrInvalidParameter
|
||||
}
|
||||
name = locator.Identity.address.String()
|
||||
}
|
||||
var lb []byte
|
||||
if locator != nil {
|
||||
lb = locator.Bytes
|
||||
}
|
||||
var lbp unsafe.Pointer
|
||||
if len(lb) > 0 {
|
||||
lbp = unsafe.Pointer(&lb[0])
|
||||
}
|
||||
cn := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cn))
|
||||
if C.ZT_Node_setRoot(unsafe.Pointer(n.zn), cn, lbp, C.uint(len(lb))) != 0 {
|
||||
return ErrInternal
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveRoot removes a root.
|
||||
// For static roots the name should be the ZeroTier address.
|
||||
func (n *Node) RemoveRoot(name string) {
|
||||
cn := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cn))
|
||||
C.ZT_Node_removeRoot(unsafe.Pointer(n.zn), cn)
|
||||
return
|
||||
}
|
||||
|
||||
// Peers retrieves a list of current peers
|
||||
func (n *Node) Peers() []*Peer {
|
||||
var peers []*Peer
|
||||
@ -665,59 +609,21 @@ func (n *Node) Peers() []*Peer {
|
||||
p2.Role = int(p.role)
|
||||
|
||||
p2.Paths = make([]Path, 0, int(p.pathCount))
|
||||
usingAllocation := false
|
||||
for j := uintptr(0); j < uintptr(p.pathCount); j++ {
|
||||
pt := &p.paths[j]
|
||||
if pt.alive != 0 {
|
||||
a := sockaddrStorageToUDPAddr(&pt.address)
|
||||
if a != nil {
|
||||
alloc := float32(pt.allocation)
|
||||
if alloc > 0.0 {
|
||||
usingAllocation = true
|
||||
}
|
||||
p2.Paths = append(p2.Paths, Path{
|
||||
IP: a.IP,
|
||||
Port: a.Port,
|
||||
LastSend: int64(pt.lastSend),
|
||||
LastReceive: int64(pt.lastReceive),
|
||||
TrustedPathID: uint64(pt.trustedPathId),
|
||||
Latency: float32(pt.latency),
|
||||
PacketDelayVariance: float32(pt.packetDelayVariance),
|
||||
ThroughputDisturbCoeff: float32(pt.throughputDisturbCoeff),
|
||||
PacketErrorRatio: float32(pt.packetErrorRatio),
|
||||
PacketLossRatio: float32(pt.packetLossRatio),
|
||||
Stability: float32(pt.stability),
|
||||
Throughput: uint64(pt.throughput),
|
||||
MaxThroughput: uint64(pt.maxThroughput),
|
||||
Allocation: alloc,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if !usingAllocation { // if all allocations are zero fall back to single path mode that uses the preferred flag
|
||||
for i, j := 0, uintptr(0); j < uintptr(p.pathCount); j++ {
|
||||
pt := &p.paths[j]
|
||||
if pt.alive != 0 {
|
||||
if pt.preferred == 0 {
|
||||
p2.Paths[i].Allocation = 0.0
|
||||
} else {
|
||||
p2.Paths[i].Allocation = 1.0
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Slice(p2.Paths, func(a, b int) bool {
|
||||
pa := &p2.Paths[a]
|
||||
pb := &p2.Paths[b]
|
||||
if pb.Allocation < pa.Allocation { // invert order, put highest allocation paths first
|
||||
return true
|
||||
}
|
||||
if pa.Allocation == pb.Allocation {
|
||||
return pa.LastReceive < pb.LastReceive // then sort by most recent activity
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
p2.Clock = TimeMs()
|
||||
peers = append(peers, p2)
|
||||
@ -754,10 +660,10 @@ func (n *Node) pathCheck(ztAddress Address, af int, ip net.IP, port int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (n *Node) pathLookup(ztAddress Address) (net.IP, int) {
|
||||
func (n *Node) pathLookup(id *Identity) (net.IP, int) {
|
||||
n.localConfigLock.RLock()
|
||||
defer n.localConfigLock.RUnlock()
|
||||
virt := n.localConfig.Virtual[ztAddress]
|
||||
virt := n.localConfig.Virtual[id.address]
|
||||
if len(virt.Try) > 0 {
|
||||
idx := rand.Int() % len(virt.Try)
|
||||
return virt.Try[idx].IP, virt.Try[idx].Port
|
||||
@ -831,9 +737,6 @@ func (n *Node) handleTrace(traceMessage string) {
|
||||
func (n *Node) handleUserMessage(originAddress, messageTypeID uint64, data []byte) {
|
||||
}
|
||||
|
||||
func (n *Node) handleRemoteTrace(originAddress uint64, dictData []byte) {
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// These are callbacks called by the core and GoGlue stuff to talk to the
|
||||
@ -860,7 +763,7 @@ func goPathCheckFunc(gn unsafe.Pointer, ztAddress C.uint64_t, af C.int, ip unsaf
|
||||
}
|
||||
|
||||
//export goPathLookupFunc
|
||||
func goPathLookupFunc(gn unsafe.Pointer, ztAddress C.uint64_t, _ int, familyP, ipP, portP unsafe.Pointer) C.int {
|
||||
func goPathLookupFunc(gn unsafe.Pointer, ztAddress C.uint64_t, desiredFamily int, identity, familyP, ipP, portP unsafe.Pointer) C.int {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
@ -868,7 +771,11 @@ func goPathLookupFunc(gn unsafe.Pointer, ztAddress C.uint64_t, _ int, familyP, i
|
||||
return 0
|
||||
}
|
||||
|
||||
ip, port := node.pathLookup(Address(ztAddress))
|
||||
id, err := newIdentityFromCIdentity(identity)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
ip, port := node.pathLookup(id)
|
||||
if len(ip) > 0 && port > 0 && port <= 65535 {
|
||||
ip4 := ip.To4()
|
||||
if len(ip4) == 4 {
|
||||
@ -922,38 +829,6 @@ func goStateObjectGetFunc(gn unsafe.Pointer, objType C.int, id, data unsafe.Poin
|
||||
return -1
|
||||
}
|
||||
|
||||
//export goDNSResolverFunc
|
||||
func goDNSResolverFunc(gn unsafe.Pointer, dnsRecordTypes unsafe.Pointer, numDNSRecordTypes C.int, name unsafe.Pointer, requestID C.uintptr_t) {
|
||||
go func() {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
||||
recordTypes := C.GoBytes(dnsRecordTypes, numDNSRecordTypes)
|
||||
recordName := C.GoString((*C.char)(name))
|
||||
|
||||
recordNameCStrCopy := C.CString(recordName)
|
||||
for _, rt := range recordTypes {
|
||||
switch rt {
|
||||
case C.ZT_DNS_RECORD_TXT:
|
||||
recs, _ := net.LookupTXT(recordName)
|
||||
for _, rec := range recs {
|
||||
if len(rec) > 0 {
|
||||
rnCS := C.CString(rec)
|
||||
C.ZT_Node_processDNSResult(unsafe.Pointer(node.zn), nil, requestID, recordNameCStrCopy, C.ZT_DNS_RECORD_TXT, unsafe.Pointer(rnCS), C.uint(len(rec)), 0)
|
||||
C.free(unsafe.Pointer(rnCS))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
C.ZT_Node_processDNSResult(unsafe.Pointer(node.zn), nil, requestID, recordNameCStrCopy, C.ZT_DNS_RECORD__END_OF_RESULTS, nil, 0, 0)
|
||||
C.free(unsafe.Pointer(recordNameCStrCopy))
|
||||
}()
|
||||
}
|
||||
|
||||
//export goVirtualNetworkConfigFunc
|
||||
func goVirtualNetworkConfigFunc(gn, _ unsafe.Pointer, nwid C.uint64_t, op C.int, conf unsafe.Pointer) {
|
||||
go func() {
|
||||
@ -1032,9 +907,6 @@ func goZtEvent(gn unsafe.Pointer, eventType C.int, data unsafe.Pointer) {
|
||||
case C.ZT_EVENT_USER_MESSAGE:
|
||||
um := (*C.ZT_UserMessage)(data)
|
||||
node.handleUserMessage(uint64(um.origin), uint64(um.typeId), C.GoBytes(um.data, C.int(um.length)))
|
||||
case C.ZT_EVENT_REMOTE_TRACE:
|
||||
rt := (*C.ZT_RemoteTrace)(data)
|
||||
node.handleRemoteTrace(uint64(rt.origin), C.GoBytes(unsafe.Pointer(rt.data), C.int(rt.len)))
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
@ -22,13 +22,4 @@ type Path struct {
|
||||
LastSend int64 `json:"lastSend"`
|
||||
LastReceive int64 `json:"lastReceive"`
|
||||
TrustedPathID uint64 `json:"trustedPathID"`
|
||||
Latency float32 `json:"latency"`
|
||||
PacketDelayVariance float32 `json:"packetDelayVariance"`
|
||||
ThroughputDisturbCoeff float32 `json:"throughputDisturbCoeff"`
|
||||
PacketErrorRatio float32 `json:"packetErrorRatio"`
|
||||
PacketLossRatio float32 `json:"packetLossRatio"`
|
||||
Stability float32 `json:"stability"`
|
||||
Throughput uint64 `json:"throughput"`
|
||||
MaxThroughput uint64 `json:"maxThroughput"`
|
||||
Allocation float32 `json:"allocation"`
|
||||
}
|
||||
|
@ -1,20 +1,8 @@
|
||||
/*
|
||||
* Copyright (c)2019 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package zerotier
|
||||
|
||||
// Root describes a root server used to find and establish communication with other nodes.
|
||||
// Root is a root server with one or more permanent IPs.
|
||||
type Root struct {
|
||||
Name string `json:"name"`
|
||||
Locator *Locator `json:"locator,omitempty"`
|
||||
Identity Identity
|
||||
DNSName string
|
||||
PhysicalAddresses []InetAddress
|
||||
}
|
||||
|
13
go/vendor/golang.org/x/sys/windows/asm_windows_386.s
generated
vendored
13
go/vendor/golang.org/x/sys/windows/asm_windows_386.s
generated
vendored
@ -1,13 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//
|
||||
// System calls for 386, Windows are implemented in runtime/syscall_windows.goc
|
||||
//
|
||||
|
||||
TEXT ·getprocaddress(SB), 7, $0-16
|
||||
JMP syscall·getprocaddress(SB)
|
||||
|
||||
TEXT ·loadlibrary(SB), 7, $0-12
|
||||
JMP syscall·loadlibrary(SB)
|
13
go/vendor/golang.org/x/sys/windows/asm_windows_amd64.s
generated
vendored
13
go/vendor/golang.org/x/sys/windows/asm_windows_amd64.s
generated
vendored
@ -1,13 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//
|
||||
// System calls for amd64, Windows are implemented in runtime/syscall_windows.goc
|
||||
//
|
||||
|
||||
TEXT ·getprocaddress(SB), 7, $0-32
|
||||
JMP syscall·getprocaddress(SB)
|
||||
|
||||
TEXT ·loadlibrary(SB), 7, $0-24
|
||||
JMP syscall·loadlibrary(SB)
|
11
go/vendor/golang.org/x/sys/windows/asm_windows_arm.s
generated
vendored
11
go/vendor/golang.org/x/sys/windows/asm_windows_arm.s
generated
vendored
@ -1,11 +0,0 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·getprocaddress(SB),NOSPLIT,$0
|
||||
B syscall·getprocaddress(SB)
|
||||
|
||||
TEXT ·loadlibrary(SB),NOSPLIT,$0
|
||||
B syscall·loadlibrary(SB)
|
22
go/vendor/golang.org/x/sys/windows/dll_windows.go
generated
vendored
22
go/vendor/golang.org/x/sys/windows/dll_windows.go
generated
vendored
@ -11,6 +11,18 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// We need to use LoadLibrary and GetProcAddress from the Go runtime, because
|
||||
// the these symbols are loaded by the system linker and are required to
|
||||
// dynamically load additional symbols. Note that in the Go runtime, these
|
||||
// return syscall.Handle and syscall.Errno, but these are the same, in fact,
|
||||
// as windows.Handle and windows.Errno, and we intend to keep these the same.
|
||||
|
||||
//go:linkname syscall_loadlibrary syscall.loadlibrary
|
||||
func syscall_loadlibrary(filename *uint16) (handle Handle, err Errno)
|
||||
|
||||
//go:linkname syscall_getprocaddress syscall.getprocaddress
|
||||
func syscall_getprocaddress(handle Handle, procname *uint8) (proc uintptr, err Errno)
|
||||
|
||||
// DLLError describes reasons for DLL load failures.
|
||||
type DLLError struct {
|
||||
Err error
|
||||
@ -20,10 +32,6 @@ type DLLError struct {
|
||||
|
||||
func (e *DLLError) Error() string { return e.Msg }
|
||||
|
||||
// Implemented in runtime/syscall_windows.goc; we provide jumps to them in our assembly file.
|
||||
func loadlibrary(filename *uint16) (handle uintptr, err syscall.Errno)
|
||||
func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err syscall.Errno)
|
||||
|
||||
// A DLL implements access to a single DLL.
|
||||
type DLL struct {
|
||||
Name string
|
||||
@ -40,7 +48,7 @@ func LoadDLL(name string) (dll *DLL, err error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h, e := loadlibrary(namep)
|
||||
h, e := syscall_loadlibrary(namep)
|
||||
if e != 0 {
|
||||
return nil, &DLLError{
|
||||
Err: e,
|
||||
@ -50,7 +58,7 @@ func LoadDLL(name string) (dll *DLL, err error) {
|
||||
}
|
||||
d := &DLL{
|
||||
Name: name,
|
||||
Handle: Handle(h),
|
||||
Handle: h,
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
@ -71,7 +79,7 @@ func (d *DLL) FindProc(name string) (proc *Proc, err error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a, e := getprocaddress(uintptr(d.Handle), namep)
|
||||
a, e := syscall_getprocaddress(d.Handle, namep)
|
||||
if e != 0 {
|
||||
return nil, &DLLError{
|
||||
Err: e,
|
||||
|
7
go/vendor/golang.org/x/sys/windows/mkerrors.go → go/vendor/golang.org/x/sys/windows/empty.s
generated
vendored
7
go/vendor/golang.org/x/sys/windows/mkerrors.go → go/vendor/golang.org/x/sys/windows/empty.s
generated
vendored
@ -2,8 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build generate
|
||||
// +build !go1.12
|
||||
|
||||
package windows
|
||||
|
||||
//go:generate ./mkerrors.bash zerrors_windows.go
|
||||
// This file is here to allow bodyless functions with go:linkname for Go 1.11
|
||||
// and earlier (see https://golang.org/issue/23311).
|
5
go/vendor/golang.org/x/sys/windows/mkerrors.bash
generated
vendored
5
go/vendor/golang.org/x/sys/windows/mkerrors.bash
generated
vendored
@ -7,14 +7,13 @@
|
||||
set -e
|
||||
shopt -s nullglob
|
||||
|
||||
[[ $# -eq 1 ]] || { echo "Usage: $0 OUTPUT_FILE.go" >&2; exit 1; }
|
||||
winerror="$(printf '%s\n' "/mnt/c/Program Files (x86)/Windows Kits/"/*/Include/*/shared/winerror.h | sort -Vr | head -n 1)"
|
||||
[[ -n $winerror ]] || { echo "Unable to find winerror.h" >&2; exit 1; }
|
||||
|
||||
declare -A errors
|
||||
|
||||
{
|
||||
echo "// Code generated by 'go generate'; DO NOT EDIT."
|
||||
echo "// Code generated by 'mkerrors.bash'; DO NOT EDIT."
|
||||
echo
|
||||
echo "package windows"
|
||||
echo "import \"syscall\""
|
||||
@ -61,4 +60,4 @@ declare -A errors
|
||||
done < "$winerror"
|
||||
|
||||
echo ")"
|
||||
} | gofmt > "$1"
|
||||
} | gofmt > "zerrors_windows.go"
|
||||
|
27
go/vendor/golang.org/x/sys/windows/mkknownfolderids.bash
generated
vendored
Normal file
27
go/vendor/golang.org/x/sys/windows/mkknownfolderids.bash
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2019 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
set -e
|
||||
shopt -s nullglob
|
||||
|
||||
knownfolders="$(printf '%s\n' "/mnt/c/Program Files (x86)/Windows Kits/"/*/Include/*/um/KnownFolders.h | sort -Vr | head -n 1)"
|
||||
[[ -n $knownfolders ]] || { echo "Unable to find KnownFolders.h" >&2; exit 1; }
|
||||
|
||||
{
|
||||
echo "// Code generated by 'mkknownfolderids.bash'; DO NOT EDIT."
|
||||
echo
|
||||
echo "package windows"
|
||||
echo "type KNOWNFOLDERID GUID"
|
||||
echo "var ("
|
||||
while read -r line; do
|
||||
[[ $line =~ DEFINE_KNOWN_FOLDER\((FOLDERID_[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+),[\t\ ]*(0x[^,]+)\) ]] || continue
|
||||
printf "%s = &KNOWNFOLDERID{0x%08x, 0x%04x, 0x%04x, [8]byte{0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x}}\n" \
|
||||
"${BASH_REMATCH[1]}" $(( "${BASH_REMATCH[2]}" )) $(( "${BASH_REMATCH[3]}" )) $(( "${BASH_REMATCH[4]}" )) \
|
||||
$(( "${BASH_REMATCH[5]}" )) $(( "${BASH_REMATCH[6]}" )) $(( "${BASH_REMATCH[7]}" )) $(( "${BASH_REMATCH[8]}" )) \
|
||||
$(( "${BASH_REMATCH[9]}" )) $(( "${BASH_REMATCH[10]}" )) $(( "${BASH_REMATCH[11]}" )) $(( "${BASH_REMATCH[12]}" ))
|
||||
done < "$knownfolders"
|
||||
echo ")"
|
||||
} | gofmt > "zknownfolderids_windows.go"
|
2
go/vendor/golang.org/x/sys/windows/mksyscall.go
generated
vendored
2
go/vendor/golang.org/x/sys/windows/mksyscall.go
generated
vendored
@ -6,4 +6,4 @@
|
||||
|
||||
package windows
|
||||
|
||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go
|
||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go
|
||||
|
614
go/vendor/golang.org/x/sys/windows/security_windows.go
generated
vendored
614
go/vendor/golang.org/x/sys/windows/security_windows.go
generated
vendored
@ -9,14 +9,6 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
STANDARD_RIGHTS_REQUIRED = 0xf0000
|
||||
STANDARD_RIGHTS_READ = 0x20000
|
||||
STANDARD_RIGHTS_WRITE = 0x20000
|
||||
STANDARD_RIGHTS_EXECUTE = 0x20000
|
||||
STANDARD_RIGHTS_ALL = 0x1F0000
|
||||
)
|
||||
|
||||
const (
|
||||
NameUnknown = 0
|
||||
NameFullyQualifiedDN = 1
|
||||
@ -235,16 +227,15 @@ func LookupSID(system, account string) (sid *SID, domain string, accType uint32,
|
||||
}
|
||||
}
|
||||
|
||||
// String converts SID to a string format
|
||||
// suitable for display, storage, or transmission.
|
||||
func (sid *SID) String() (string, error) {
|
||||
// String converts SID to a string format suitable for display, storage, or transmission.
|
||||
func (sid *SID) String() string {
|
||||
var s *uint16
|
||||
e := ConvertSidToStringSid(sid, &s)
|
||||
if e != nil {
|
||||
return "", e
|
||||
return ""
|
||||
}
|
||||
defer LocalFree((Handle)(unsafe.Pointer(s)))
|
||||
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
|
||||
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:])
|
||||
}
|
||||
|
||||
// Len returns the length, in bytes, of a valid security identifier SID.
|
||||
@ -603,12 +594,22 @@ type Tokenprimarygroup struct {
|
||||
|
||||
type Tokengroups struct {
|
||||
GroupCount uint32
|
||||
Groups [1]SIDAndAttributes
|
||||
Groups [1]SIDAndAttributes // Use AllGroups() for iterating.
|
||||
}
|
||||
|
||||
// AllGroups returns a slice that can be used to iterate over the groups in g.
|
||||
func (g *Tokengroups) AllGroups() []SIDAndAttributes {
|
||||
return (*[(1 << 28) - 1]SIDAndAttributes)(unsafe.Pointer(&g.Groups[0]))[:g.GroupCount:g.GroupCount]
|
||||
}
|
||||
|
||||
type Tokenprivileges struct {
|
||||
PrivilegeCount uint32
|
||||
Privileges [1]LUIDAndAttributes
|
||||
Privileges [1]LUIDAndAttributes // Use AllPrivileges() for iterating.
|
||||
}
|
||||
|
||||
// AllPrivileges returns a slice that can be used to iterate over the privileges in p.
|
||||
func (p *Tokenprivileges) AllPrivileges() []LUIDAndAttributes {
|
||||
return (*[(1 << 27) - 1]LUIDAndAttributes)(unsafe.Pointer(&p.Privileges[0]))[:p.PrivilegeCount:p.PrivilegeCount]
|
||||
}
|
||||
|
||||
type Tokenmandatorylabel struct {
|
||||
@ -634,6 +635,8 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
|
||||
//sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
|
||||
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
|
||||
//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
|
||||
//sys getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetWindowsDirectoryW
|
||||
//sys getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemWindowsDirectoryW
|
||||
|
||||
// An access token contains the security information for a logon session.
|
||||
// The system creates an access token when a user logs on, and every
|
||||
@ -644,21 +647,16 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
|
||||
// system-related operations on the local computer.
|
||||
type Token Handle
|
||||
|
||||
// OpenCurrentProcessToken opens the access token
|
||||
// associated with current process. It is a real
|
||||
// token that needs to be closed, unlike
|
||||
// GetCurrentProcessToken.
|
||||
// OpenCurrentProcessToken opens an access token associated with current
|
||||
// process with TOKEN_QUERY access. It is a real token that needs to be closed.
|
||||
//
|
||||
// Deprecated: Explicitly call OpenProcessToken(CurrentProcess(), ...)
|
||||
// with the desired access instead, or use GetCurrentProcessToken for a
|
||||
// TOKEN_QUERY token.
|
||||
func OpenCurrentProcessToken() (Token, error) {
|
||||
p, e := GetCurrentProcess()
|
||||
if e != nil {
|
||||
return 0, e
|
||||
}
|
||||
var t Token
|
||||
e = OpenProcessToken(p, TOKEN_QUERY, &t)
|
||||
if e != nil {
|
||||
return 0, e
|
||||
}
|
||||
return t, nil
|
||||
var token Token
|
||||
err := OpenProcessToken(CurrentProcess(), TOKEN_QUERY, &token)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// GetCurrentProcessToken returns the access token associated with
|
||||
@ -775,8 +773,8 @@ func (token Token) GetLinkedToken() (Token, error) {
|
||||
return linkedToken, nil
|
||||
}
|
||||
|
||||
// GetSystemDirectory retrieves path to current location of the system
|
||||
// directory, which is typically, though not always, C:\Windows\System32.
|
||||
// GetSystemDirectory retrieves the path to current location of the system
|
||||
// directory, which is typically, though not always, `C:\Windows\System32`.
|
||||
func GetSystemDirectory() (string, error) {
|
||||
n := uint32(MAX_PATH)
|
||||
for {
|
||||
@ -792,6 +790,42 @@ func GetSystemDirectory() (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// GetWindowsDirectory retrieves the path to current location of the Windows
|
||||
// directory, which is typically, though not always, `C:\Windows`. This may
|
||||
// be a private user directory in the case that the application is running
|
||||
// under a terminal server.
|
||||
func GetWindowsDirectory() (string, error) {
|
||||
n := uint32(MAX_PATH)
|
||||
for {
|
||||
b := make([]uint16, n)
|
||||
l, e := getWindowsDirectory(&b[0], n)
|
||||
if e != nil {
|
||||
return "", e
|
||||
}
|
||||
if l <= n {
|
||||
return UTF16ToString(b[:l]), nil
|
||||
}
|
||||
n = l
|
||||
}
|
||||
}
|
||||
|
||||
// GetSystemWindowsDirectory retrieves the path to current location of the
|
||||
// Windows directory, which is typically, though not always, `C:\Windows`.
|
||||
func GetSystemWindowsDirectory() (string, error) {
|
||||
n := uint32(MAX_PATH)
|
||||
for {
|
||||
b := make([]uint16, n)
|
||||
l, e := getSystemWindowsDirectory(&b[0], n)
|
||||
if e != nil {
|
||||
return "", e
|
||||
}
|
||||
if l <= n {
|
||||
return UTF16ToString(b[:l]), nil
|
||||
}
|
||||
n = l
|
||||
}
|
||||
}
|
||||
|
||||
// IsMember reports whether the access token t is a member of the provided SID.
|
||||
func (t Token) IsMember(sid *SID) (bool, error) {
|
||||
var b int32
|
||||
@ -842,3 +876,521 @@ type WTS_SESSION_INFO struct {
|
||||
//sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken
|
||||
//sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
|
||||
//sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
|
||||
|
||||
type ACL struct {
|
||||
aclRevision byte
|
||||
sbz1 byte
|
||||
aclSize uint16
|
||||
aceCount uint16
|
||||
sbz2 uint16
|
||||
}
|
||||
|
||||
type SECURITY_DESCRIPTOR struct {
|
||||
revision byte
|
||||
sbz1 byte
|
||||
control SECURITY_DESCRIPTOR_CONTROL
|
||||
owner *SID
|
||||
group *SID
|
||||
sacl *ACL
|
||||
dacl *ACL
|
||||
}
|
||||
|
||||
type SecurityAttributes struct {
|
||||
Length uint32
|
||||
SecurityDescriptor *SECURITY_DESCRIPTOR
|
||||
InheritHandle uint32
|
||||
}
|
||||
|
||||
type SE_OBJECT_TYPE uint32
|
||||
|
||||
// Constants for type SE_OBJECT_TYPE
|
||||
const (
|
||||
SE_UNKNOWN_OBJECT_TYPE = 0
|
||||
SE_FILE_OBJECT = 1
|
||||
SE_SERVICE = 2
|
||||
SE_PRINTER = 3
|
||||
SE_REGISTRY_KEY = 4
|
||||
SE_LMSHARE = 5
|
||||
SE_KERNEL_OBJECT = 6
|
||||
SE_WINDOW_OBJECT = 7
|
||||
SE_DS_OBJECT = 8
|
||||
SE_DS_OBJECT_ALL = 9
|
||||
SE_PROVIDER_DEFINED_OBJECT = 10
|
||||
SE_WMIGUID_OBJECT = 11
|
||||
SE_REGISTRY_WOW64_32KEY = 12
|
||||
SE_REGISTRY_WOW64_64KEY = 13
|
||||
)
|
||||
|
||||
type SECURITY_INFORMATION uint32
|
||||
|
||||
// Constants for type SECURITY_INFORMATION
|
||||
const (
|
||||
OWNER_SECURITY_INFORMATION = 0x00000001
|
||||
GROUP_SECURITY_INFORMATION = 0x00000002
|
||||
DACL_SECURITY_INFORMATION = 0x00000004
|
||||
SACL_SECURITY_INFORMATION = 0x00000008
|
||||
LABEL_SECURITY_INFORMATION = 0x00000010
|
||||
ATTRIBUTE_SECURITY_INFORMATION = 0x00000020
|
||||
SCOPE_SECURITY_INFORMATION = 0x00000040
|
||||
BACKUP_SECURITY_INFORMATION = 0x00010000
|
||||
PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
|
||||
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000
|
||||
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000
|
||||
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000
|
||||
)
|
||||
|
||||
type SECURITY_DESCRIPTOR_CONTROL uint16
|
||||
|
||||
// Constants for type SECURITY_DESCRIPTOR_CONTROL
|
||||
const (
|
||||
SE_OWNER_DEFAULTED = 0x0001
|
||||
SE_GROUP_DEFAULTED = 0x0002
|
||||
SE_DACL_PRESENT = 0x0004
|
||||
SE_DACL_DEFAULTED = 0x0008
|
||||
SE_SACL_PRESENT = 0x0010
|
||||
SE_SACL_DEFAULTED = 0x0020
|
||||
SE_DACL_AUTO_INHERIT_REQ = 0x0100
|
||||
SE_SACL_AUTO_INHERIT_REQ = 0x0200
|
||||
SE_DACL_AUTO_INHERITED = 0x0400
|
||||
SE_SACL_AUTO_INHERITED = 0x0800
|
||||
SE_DACL_PROTECTED = 0x1000
|
||||
SE_SACL_PROTECTED = 0x2000
|
||||
SE_RM_CONTROL_VALID = 0x4000
|
||||
SE_SELF_RELATIVE = 0x8000
|
||||
)
|
||||
|
||||
type ACCESS_MASK uint32
|
||||
|
||||
// Constants for type ACCESS_MASK
|
||||
const (
|
||||
DELETE = 0x00010000
|
||||
READ_CONTROL = 0x00020000
|
||||
WRITE_DAC = 0x00040000
|
||||
WRITE_OWNER = 0x00080000
|
||||
SYNCHRONIZE = 0x00100000
|
||||
STANDARD_RIGHTS_REQUIRED = 0x000F0000
|
||||
STANDARD_RIGHTS_READ = READ_CONTROL
|
||||
STANDARD_RIGHTS_WRITE = READ_CONTROL
|
||||
STANDARD_RIGHTS_EXECUTE = READ_CONTROL
|
||||
STANDARD_RIGHTS_ALL = 0x001F0000
|
||||
SPECIFIC_RIGHTS_ALL = 0x0000FFFF
|
||||
ACCESS_SYSTEM_SECURITY = 0x01000000
|
||||
MAXIMUM_ALLOWED = 0x02000000
|
||||
GENERIC_READ = 0x80000000
|
||||
GENERIC_WRITE = 0x40000000
|
||||
GENERIC_EXECUTE = 0x20000000
|
||||
GENERIC_ALL = 0x10000000
|
||||
)
|
||||
|
||||
type ACCESS_MODE uint32
|
||||
|
||||
// Constants for type ACCESS_MODE
|
||||
const (
|
||||
NOT_USED_ACCESS = 0
|
||||
GRANT_ACCESS = 1
|
||||
SET_ACCESS = 2
|
||||
DENY_ACCESS = 3
|
||||
REVOKE_ACCESS = 4
|
||||
SET_AUDIT_SUCCESS = 5
|
||||
SET_AUDIT_FAILURE = 6
|
||||
)
|
||||
|
||||
// Constants for AceFlags and Inheritance fields
|
||||
const (
|
||||
NO_INHERITANCE = 0x0
|
||||
SUB_OBJECTS_ONLY_INHERIT = 0x1
|
||||
SUB_CONTAINERS_ONLY_INHERIT = 0x2
|
||||
SUB_CONTAINERS_AND_OBJECTS_INHERIT = 0x3
|
||||
INHERIT_NO_PROPAGATE = 0x4
|
||||
INHERIT_ONLY = 0x8
|
||||
INHERITED_ACCESS_ENTRY = 0x10
|
||||
INHERITED_PARENT = 0x10000000
|
||||
INHERITED_GRANDPARENT = 0x20000000
|
||||
OBJECT_INHERIT_ACE = 0x1
|
||||
CONTAINER_INHERIT_ACE = 0x2
|
||||
NO_PROPAGATE_INHERIT_ACE = 0x4
|
||||
INHERIT_ONLY_ACE = 0x8
|
||||
INHERITED_ACE = 0x10
|
||||
VALID_INHERIT_FLAGS = 0x1F
|
||||
)
|
||||
|
||||
type MULTIPLE_TRUSTEE_OPERATION uint32
|
||||
|
||||
// Constants for MULTIPLE_TRUSTEE_OPERATION
|
||||
const (
|
||||
NO_MULTIPLE_TRUSTEE = 0
|
||||
TRUSTEE_IS_IMPERSONATE = 1
|
||||
)
|
||||
|
||||
type TRUSTEE_FORM uint32
|
||||
|
||||
// Constants for TRUSTEE_FORM
|
||||
const (
|
||||
TRUSTEE_IS_SID = 0
|
||||
TRUSTEE_IS_NAME = 1
|
||||
TRUSTEE_BAD_FORM = 2
|
||||
TRUSTEE_IS_OBJECTS_AND_SID = 3
|
||||
TRUSTEE_IS_OBJECTS_AND_NAME = 4
|
||||
)
|
||||
|
||||
type TRUSTEE_TYPE uint32
|
||||
|
||||
// Constants for TRUSTEE_TYPE
|
||||
const (
|
||||
TRUSTEE_IS_UNKNOWN = 0
|
||||
TRUSTEE_IS_USER = 1
|
||||
TRUSTEE_IS_GROUP = 2
|
||||
TRUSTEE_IS_DOMAIN = 3
|
||||
TRUSTEE_IS_ALIAS = 4
|
||||
TRUSTEE_IS_WELL_KNOWN_GROUP = 5
|
||||
TRUSTEE_IS_DELETED = 6
|
||||
TRUSTEE_IS_INVALID = 7
|
||||
TRUSTEE_IS_COMPUTER = 8
|
||||
)
|
||||
|
||||
// Constants for ObjectsPresent field
|
||||
const (
|
||||
ACE_OBJECT_TYPE_PRESENT = 0x1
|
||||
ACE_INHERITED_OBJECT_TYPE_PRESENT = 0x2
|
||||
)
|
||||
|
||||
type EXPLICIT_ACCESS struct {
|
||||
AccessPermissions ACCESS_MASK
|
||||
AccessMode ACCESS_MODE
|
||||
Inheritance uint32
|
||||
Trustee TRUSTEE
|
||||
}
|
||||
|
||||
// This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions.
|
||||
type TrusteeValue uintptr
|
||||
|
||||
func TrusteeValueFromString(str string) TrusteeValue {
|
||||
return TrusteeValue(unsafe.Pointer(StringToUTF16Ptr(str)))
|
||||
}
|
||||
func TrusteeValueFromSID(sid *SID) TrusteeValue {
|
||||
return TrusteeValue(unsafe.Pointer(sid))
|
||||
}
|
||||
func TrusteeValueFromObjectsAndSid(objectsAndSid *OBJECTS_AND_SID) TrusteeValue {
|
||||
return TrusteeValue(unsafe.Pointer(objectsAndSid))
|
||||
}
|
||||
func TrusteeValueFromObjectsAndName(objectsAndName *OBJECTS_AND_NAME) TrusteeValue {
|
||||
return TrusteeValue(unsafe.Pointer(objectsAndName))
|
||||
}
|
||||
|
||||
type TRUSTEE struct {
|
||||
MultipleTrustee *TRUSTEE
|
||||
MultipleTrusteeOperation MULTIPLE_TRUSTEE_OPERATION
|
||||
TrusteeForm TRUSTEE_FORM
|
||||
TrusteeType TRUSTEE_TYPE
|
||||
TrusteeValue TrusteeValue
|
||||
}
|
||||
|
||||
type OBJECTS_AND_SID struct {
|
||||
ObjectsPresent uint32
|
||||
ObjectTypeGuid GUID
|
||||
InheritedObjectTypeGuid GUID
|
||||
Sid *SID
|
||||
}
|
||||
|
||||
type OBJECTS_AND_NAME struct {
|
||||
ObjectsPresent uint32
|
||||
ObjectType SE_OBJECT_TYPE
|
||||
ObjectTypeName *uint16
|
||||
InheritedObjectTypeName *uint16
|
||||
Name *uint16
|
||||
}
|
||||
|
||||
//sys getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetSecurityInfo
|
||||
//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) = advapi32.SetSecurityInfo
|
||||
//sys getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetNamedSecurityInfoW
|
||||
//sys SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW
|
||||
|
||||
//sys buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) = advapi32.BuildSecurityDescriptorW
|
||||
//sys initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor
|
||||
|
||||
//sys getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) = advapi32.GetSecurityDescriptorControl
|
||||
//sys getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorDacl
|
||||
//sys getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorSacl
|
||||
//sys getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorOwner
|
||||
//sys getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorGroup
|
||||
//sys getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) = advapi32.GetSecurityDescriptorLength
|
||||
//sys getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) [failretval!=0] = advapi32.GetSecurityDescriptorRMControl
|
||||
//sys isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) = advapi32.IsValidSecurityDescriptor
|
||||
|
||||
//sys setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) = advapi32.SetSecurityDescriptorControl
|
||||
//sys setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl
|
||||
//sys setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl
|
||||
//sys setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) = advapi32.SetSecurityDescriptorOwner
|
||||
//sys setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) = advapi32.SetSecurityDescriptorGroup
|
||||
//sys setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) = advapi32.SetSecurityDescriptorRMControl
|
||||
|
||||
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
|
||||
//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
|
||||
|
||||
//sys makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) = advapi32.MakeAbsoluteSD
|
||||
//sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD
|
||||
|
||||
//sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW
|
||||
|
||||
// Control returns the security descriptor control bits.
|
||||
func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) {
|
||||
err = getSecurityDescriptorControl(sd, &control, &revision)
|
||||
return
|
||||
}
|
||||
|
||||
// SetControl sets the security descriptor control bits.
|
||||
func (sd *SECURITY_DESCRIPTOR) SetControl(controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) error {
|
||||
return setSecurityDescriptorControl(sd, controlBitsOfInterest, controlBitsToSet)
|
||||
}
|
||||
|
||||
// RMControl returns the security descriptor resource manager control bits.
|
||||
func (sd *SECURITY_DESCRIPTOR) RMControl() (control uint8, err error) {
|
||||
err = getSecurityDescriptorRMControl(sd, &control)
|
||||
return
|
||||
}
|
||||
|
||||
// SetRMControl sets the security descriptor resource manager control bits.
|
||||
func (sd *SECURITY_DESCRIPTOR) SetRMControl(rmControl uint8) {
|
||||
setSecurityDescriptorRMControl(sd, &rmControl)
|
||||
}
|
||||
|
||||
// DACL returns the security descriptor DACL and whether it was defaulted. The dacl return value may be nil
|
||||
// if a DACL exists but is an "empty DACL", meaning fully permissive. If the DACL does not exist, err returns
|
||||
// ERROR_OBJECT_NOT_FOUND.
|
||||
func (sd *SECURITY_DESCRIPTOR) DACL() (dacl *ACL, defaulted bool, err error) {
|
||||
var present bool
|
||||
err = getSecurityDescriptorDacl(sd, &present, &dacl, &defaulted)
|
||||
if !present {
|
||||
err = ERROR_OBJECT_NOT_FOUND
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SetDACL sets the absolute security descriptor DACL.
|
||||
func (absoluteSD *SECURITY_DESCRIPTOR) SetDACL(dacl *ACL, present, defaulted bool) error {
|
||||
return setSecurityDescriptorDacl(absoluteSD, present, dacl, defaulted)
|
||||
}
|
||||
|
||||
// SACL returns the security descriptor SACL and whether it was defaulted. The sacl return value may be nil
|
||||
// if a SACL exists but is an "empty SACL", meaning fully permissive. If the SACL does not exist, err returns
|
||||
// ERROR_OBJECT_NOT_FOUND.
|
||||
func (sd *SECURITY_DESCRIPTOR) SACL() (sacl *ACL, defaulted bool, err error) {
|
||||
var present bool
|
||||
err = getSecurityDescriptorSacl(sd, &present, &sacl, &defaulted)
|
||||
if !present {
|
||||
err = ERROR_OBJECT_NOT_FOUND
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SetSACL sets the absolute security descriptor SACL.
|
||||
func (absoluteSD *SECURITY_DESCRIPTOR) SetSACL(sacl *ACL, present, defaulted bool) error {
|
||||
return setSecurityDescriptorSacl(absoluteSD, present, sacl, defaulted)
|
||||
}
|
||||
|
||||
// Owner returns the security descriptor owner and whether it was defaulted.
|
||||
func (sd *SECURITY_DESCRIPTOR) Owner() (owner *SID, defaulted bool, err error) {
|
||||
err = getSecurityDescriptorOwner(sd, &owner, &defaulted)
|
||||
return
|
||||
}
|
||||
|
||||
// SetOwner sets the absolute security descriptor owner.
|
||||
func (absoluteSD *SECURITY_DESCRIPTOR) SetOwner(owner *SID, defaulted bool) error {
|
||||
return setSecurityDescriptorOwner(absoluteSD, owner, defaulted)
|
||||
}
|
||||
|
||||
// Group returns the security descriptor group and whether it was defaulted.
|
||||
func (sd *SECURITY_DESCRIPTOR) Group() (group *SID, defaulted bool, err error) {
|
||||
err = getSecurityDescriptorGroup(sd, &group, &defaulted)
|
||||
return
|
||||
}
|
||||
|
||||
// SetGroup sets the absolute security descriptor owner.
|
||||
func (absoluteSD *SECURITY_DESCRIPTOR) SetGroup(group *SID, defaulted bool) error {
|
||||
return setSecurityDescriptorGroup(absoluteSD, group, defaulted)
|
||||
}
|
||||
|
||||
// Length returns the length of the security descriptor.
|
||||
func (sd *SECURITY_DESCRIPTOR) Length() uint32 {
|
||||
return getSecurityDescriptorLength(sd)
|
||||
}
|
||||
|
||||
// IsValid returns whether the security descriptor is valid.
|
||||
func (sd *SECURITY_DESCRIPTOR) IsValid() bool {
|
||||
return isValidSecurityDescriptor(sd)
|
||||
}
|
||||
|
||||
// String returns the SDDL form of the security descriptor, with a function signature that can be
|
||||
// used with %v formatting directives.
|
||||
func (sd *SECURITY_DESCRIPTOR) String() string {
|
||||
var sddl *uint16
|
||||
err := convertSecurityDescriptorToStringSecurityDescriptor(sd, 1, 0xff, &sddl, nil)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
defer LocalFree(Handle(unsafe.Pointer(sddl)))
|
||||
return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(sddl))[:])
|
||||
}
|
||||
|
||||
// ToAbsolute converts a self-relative security descriptor into an absolute one.
|
||||
func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
|
||||
control, _, err := selfRelativeSD.Control()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if control&SE_SELF_RELATIVE == 0 {
|
||||
err = ERROR_INVALID_PARAMETER
|
||||
return
|
||||
}
|
||||
var absoluteSDSize, daclSize, saclSize, ownerSize, groupSize uint32
|
||||
err = makeAbsoluteSD(selfRelativeSD, nil, &absoluteSDSize,
|
||||
nil, &daclSize, nil, &saclSize, nil, &ownerSize, nil, &groupSize)
|
||||
switch err {
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
case nil:
|
||||
// makeAbsoluteSD is expected to fail, but it succeeds.
|
||||
return nil, ERROR_INTERNAL_ERROR
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
if absoluteSDSize > 0 {
|
||||
absoluteSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, absoluteSDSize)[0]))
|
||||
}
|
||||
var (
|
||||
dacl *ACL
|
||||
sacl *ACL
|
||||
owner *SID
|
||||
group *SID
|
||||
)
|
||||
if daclSize > 0 {
|
||||
dacl = (*ACL)(unsafe.Pointer(&make([]byte, daclSize)[0]))
|
||||
}
|
||||
if saclSize > 0 {
|
||||
sacl = (*ACL)(unsafe.Pointer(&make([]byte, saclSize)[0]))
|
||||
}
|
||||
if ownerSize > 0 {
|
||||
owner = (*SID)(unsafe.Pointer(&make([]byte, ownerSize)[0]))
|
||||
}
|
||||
if groupSize > 0 {
|
||||
group = (*SID)(unsafe.Pointer(&make([]byte, groupSize)[0]))
|
||||
}
|
||||
err = makeAbsoluteSD(selfRelativeSD, absoluteSD, &absoluteSDSize,
|
||||
dacl, &daclSize, sacl, &saclSize, owner, &ownerSize, group, &groupSize)
|
||||
return
|
||||
}
|
||||
|
||||
// ToSelfRelative converts an absolute security descriptor into a self-relative one.
|
||||
func (absoluteSD *SECURITY_DESCRIPTOR) ToSelfRelative() (selfRelativeSD *SECURITY_DESCRIPTOR, err error) {
|
||||
control, _, err := absoluteSD.Control()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if control&SE_SELF_RELATIVE != 0 {
|
||||
err = ERROR_INVALID_PARAMETER
|
||||
return
|
||||
}
|
||||
var selfRelativeSDSize uint32
|
||||
err = makeSelfRelativeSD(absoluteSD, nil, &selfRelativeSDSize)
|
||||
switch err {
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
case nil:
|
||||
// makeSelfRelativeSD is expected to fail, but it succeeds.
|
||||
return nil, ERROR_INTERNAL_ERROR
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
if selfRelativeSDSize > 0 {
|
||||
selfRelativeSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, selfRelativeSDSize)[0]))
|
||||
}
|
||||
err = makeSelfRelativeSD(absoluteSD, selfRelativeSD, &selfRelativeSDSize)
|
||||
return
|
||||
}
|
||||
|
||||
func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor() *SECURITY_DESCRIPTOR {
|
||||
sdBytes := make([]byte, selfRelativeSD.Length())
|
||||
copy(sdBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(selfRelativeSD))[:len(sdBytes)])
|
||||
return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&sdBytes[0]))
|
||||
}
|
||||
|
||||
// SecurityDescriptorFromString converts an SDDL string describing a security descriptor into a
|
||||
// self-relative security descriptor object allocated on the Go heap.
|
||||
func SecurityDescriptorFromString(sddl string) (sd *SECURITY_DESCRIPTOR, err error) {
|
||||
var winHeapSD *SECURITY_DESCRIPTOR
|
||||
err = convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &winHeapSD, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
|
||||
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
|
||||
}
|
||||
|
||||
// GetSecurityInfo queries the security information for a given handle and returns the self-relative security
|
||||
// descriptor result on the Go heap.
|
||||
func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
|
||||
var winHeapSD *SECURITY_DESCRIPTOR
|
||||
err = getSecurityInfo(handle, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
|
||||
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
|
||||
}
|
||||
|
||||
// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security
|
||||
// descriptor result on the Go heap.
|
||||
func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
|
||||
var winHeapSD *SECURITY_DESCRIPTOR
|
||||
err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
|
||||
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
|
||||
}
|
||||
|
||||
// BuildSecurityDescriptor makes a new security descriptor using the input trustees, explicit access lists, and
|
||||
// prior security descriptor to be merged, any of which can be nil, returning the self-relative security descriptor
|
||||
// result on the Go heap.
|
||||
func BuildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, accessEntries []EXPLICIT_ACCESS, auditEntries []EXPLICIT_ACCESS, mergedSecurityDescriptor *SECURITY_DESCRIPTOR) (sd *SECURITY_DESCRIPTOR, err error) {
|
||||
var winHeapSD *SECURITY_DESCRIPTOR
|
||||
var winHeapSDSize uint32
|
||||
var firstAccessEntry *EXPLICIT_ACCESS
|
||||
if len(accessEntries) > 0 {
|
||||
firstAccessEntry = &accessEntries[0]
|
||||
}
|
||||
var firstAuditEntry *EXPLICIT_ACCESS
|
||||
if len(auditEntries) > 0 {
|
||||
firstAuditEntry = &auditEntries[0]
|
||||
}
|
||||
err = buildSecurityDescriptor(owner, group, uint32(len(accessEntries)), firstAccessEntry, uint32(len(auditEntries)), firstAuditEntry, mergedSecurityDescriptor, &winHeapSDSize, &winHeapSD)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
|
||||
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
|
||||
}
|
||||
|
||||
// NewSecurityDescriptor creates and initializes a new absolute security descriptor.
|
||||
func NewSecurityDescriptor() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
|
||||
absoluteSD = &SECURITY_DESCRIPTOR{}
|
||||
err = initializeSecurityDescriptor(absoluteSD, 1)
|
||||
return
|
||||
}
|
||||
|
||||
// ACLFromEntries returns a new ACL on the Go heap containing a list of explicit entries as well as those of another ACL.
|
||||
// Both explicitEntries and mergedACL are optional and can be nil.
|
||||
func ACLFromEntries(explicitEntries []EXPLICIT_ACCESS, mergedACL *ACL) (acl *ACL, err error) {
|
||||
var firstExplicitEntry *EXPLICIT_ACCESS
|
||||
if len(explicitEntries) > 0 {
|
||||
firstExplicitEntry = &explicitEntries[0]
|
||||
}
|
||||
var winHeapACL *ACL
|
||||
err = setEntriesInAcl(uint32(len(explicitEntries)), firstExplicitEntry, mergedACL, &winHeapACL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer LocalFree(Handle(unsafe.Pointer(winHeapACL)))
|
||||
aclBytes := make([]byte, winHeapACL.aclSize)
|
||||
copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes)])
|
||||
return (*ACL)(unsafe.Pointer(&aclBytes[0])), nil
|
||||
}
|
||||
|
11
go/vendor/golang.org/x/sys/windows/service.go
generated
vendored
11
go/vendor/golang.org/x/sys/windows/service.go
generated
vendored
@ -159,6 +159,10 @@ type SERVICE_DESCRIPTION struct {
|
||||
Description *uint16
|
||||
}
|
||||
|
||||
type SERVICE_DELAYED_AUTO_START_INFO struct {
|
||||
IsDelayedAutoStartUp uint32
|
||||
}
|
||||
|
||||
type SERVICE_STATUS_PROCESS struct {
|
||||
ServiceType uint32
|
||||
CurrentState uint32
|
||||
@ -200,12 +204,19 @@ type SC_ACTION struct {
|
||||
Delay uint32
|
||||
}
|
||||
|
||||
type QUERY_SERVICE_LOCK_STATUS struct {
|
||||
IsLocked uint32
|
||||
LockOwner *uint16
|
||||
LockDuration uint32
|
||||
}
|
||||
|
||||
//sys CloseServiceHandle(handle Handle) (err error) = advapi32.CloseServiceHandle
|
||||
//sys CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) [failretval==0] = advapi32.CreateServiceW
|
||||
//sys OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenServiceW
|
||||
//sys DeleteService(service Handle) (err error) = advapi32.DeleteService
|
||||
//sys StartService(service Handle, numArgs uint32, argVectors **uint16) (err error) = advapi32.StartServiceW
|
||||
//sys QueryServiceStatus(service Handle, status *SERVICE_STATUS) (err error) = advapi32.QueryServiceStatus
|
||||
//sys QueryServiceLockStatus(mgr Handle, lockStatus *QUERY_SERVICE_LOCK_STATUS, bufSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceLockStatusW
|
||||
//sys ControlService(service Handle, control uint32, status *SERVICE_STATUS) (err error) = advapi32.ControlService
|
||||
//sys StartServiceCtrlDispatcher(serviceTable *SERVICE_TABLE_ENTRY) (err error) = advapi32.StartServiceCtrlDispatcherW
|
||||
//sys SetServiceStatus(service Handle, serviceStatus *SERVICE_STATUS) (err error) = advapi32.SetServiceStatus
|
||||
|
238
go/vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
238
go/vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
@ -10,6 +10,7 @@ import (
|
||||
errorspkg "errors"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
@ -56,6 +57,10 @@ const (
|
||||
FILE_VOLUME_IS_COMPRESSED = 0x00008000
|
||||
FILE_VOLUME_QUOTAS = 0x00000020
|
||||
|
||||
// Flags for LockFileEx.
|
||||
LOCKFILE_FAIL_IMMEDIATELY = 0x00000001
|
||||
LOCKFILE_EXCLUSIVE_LOCK = 0x00000002
|
||||
|
||||
// Return values of SleepEx and other APC functions
|
||||
STATUS_USER_APC = 0x000000C0
|
||||
WAIT_IO_COMPLETION = STATUS_USER_APC
|
||||
@ -135,6 +140,8 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, err error) = LoadLibraryExW
|
||||
//sys FreeLibrary(handle Handle) (err error)
|
||||
//sys GetProcAddress(module Handle, procname string) (proc uintptr, err error)
|
||||
//sys GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
|
||||
//sys GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) = kernel32.GetModuleHandleExW
|
||||
//sys GetVersion() (ver uint32, err error)
|
||||
//sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW
|
||||
//sys ExitProcess(exitcode uint32)
|
||||
@ -159,6 +166,8 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys DeleteFile(path *uint16) (err error) = DeleteFileW
|
||||
//sys MoveFile(from *uint16, to *uint16) (err error) = MoveFileW
|
||||
//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
|
||||
//sys LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error)
|
||||
//sys UnlockFileEx(file Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error)
|
||||
//sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW
|
||||
//sys GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
|
||||
//sys SetEndOfFile(handle Handle) (err error)
|
||||
@ -171,13 +180,12 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys CancelIo(s Handle) (err error)
|
||||
//sys CancelIoEx(s Handle, o *Overlapped) (err error)
|
||||
//sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW
|
||||
//sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error)
|
||||
//sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) = shell32.ShellExecuteW
|
||||
//sys OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error)
|
||||
//sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) [failretval<=32] = shell32.ShellExecuteW
|
||||
//sys shGetKnownFolderPath(id *KNOWNFOLDERID, flags uint32, token Token, path **uint16) (ret error) = shell32.SHGetKnownFolderPath
|
||||
//sys TerminateProcess(handle Handle, exitcode uint32) (err error)
|
||||
//sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error)
|
||||
//sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW
|
||||
//sys GetCurrentProcess() (pseudoHandle Handle, err error)
|
||||
//sys GetCurrentThread() (pseudoHandle Handle, err error)
|
||||
//sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error)
|
||||
//sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error)
|
||||
//sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff]
|
||||
@ -194,6 +202,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW
|
||||
//sys CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock
|
||||
//sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock
|
||||
//sys getTickCount64() (ms uint64) = kernel32.GetTickCount64
|
||||
//sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error)
|
||||
//sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW
|
||||
//sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW
|
||||
@ -232,7 +241,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW
|
||||
//sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW
|
||||
//sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW
|
||||
//sys getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId
|
||||
//sys GetCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId
|
||||
//sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode
|
||||
//sys SetConsoleMode(console Handle, mode uint32) (err error) = kernel32.SetConsoleMode
|
||||
//sys GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) = kernel32.GetConsoleScreenBufferInfo
|
||||
@ -241,6 +250,8 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
|
||||
//sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW
|
||||
//sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW
|
||||
//sys Thread32First(snapshot Handle, threadEntry *ThreadEntry32) (err error)
|
||||
//sys Thread32Next(snapshot Handle, threadEntry *ThreadEntry32) (err error)
|
||||
//sys DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error)
|
||||
// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
|
||||
//sys CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) [failretval&0xff==0] = CreateSymbolicLinkW
|
||||
@ -252,6 +263,10 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys SetEvent(event Handle) (err error) = kernel32.SetEvent
|
||||
//sys ResetEvent(event Handle) (err error) = kernel32.ResetEvent
|
||||
//sys PulseEvent(event Handle) (err error) = kernel32.PulseEvent
|
||||
//sys CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16) (handle Handle, err error) = kernel32.CreateMutexW
|
||||
//sys CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) = kernel32.CreateMutexExW
|
||||
//sys OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) = kernel32.OpenMutexW
|
||||
//sys ReleaseMutex(mutex Handle) (err error) = kernel32.ReleaseMutex
|
||||
//sys SleepEx(milliseconds uint32, alertable bool) (ret uint32) = kernel32.SleepEx
|
||||
//sys CreateJobObject(jobAttr *SecurityAttributes, name *uint16) (handle Handle, err error) = kernel32.CreateJobObjectW
|
||||
//sys AssignProcessToJobObject(job Handle, process Handle) (err error) = kernel32.AssignProcessToJobObject
|
||||
@ -261,6 +276,10 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys SetPriorityClass(process Handle, priorityClass uint32) (err error) = kernel32.SetPriorityClass
|
||||
//sys GetPriorityClass(process Handle) (ret uint32, err error) = kernel32.GetPriorityClass
|
||||
//sys SetInformationJobObject(job Handle, JobObjectInformationClass uint32, JobObjectInformation uintptr, JobObjectInformationLength uint32) (ret int, err error)
|
||||
//sys GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error)
|
||||
//sys GetProcessId(process Handle) (id uint32, err error)
|
||||
//sys OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (handle Handle, err error)
|
||||
//sys SetProcessPriorityBoost(process Handle, disable bool) (err error) = kernel32.SetProcessPriorityBoost
|
||||
|
||||
// Volume Management Functions
|
||||
//sys DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) = DefineDosDeviceW
|
||||
@ -271,6 +290,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys FindNextVolumeMountPoint(findVolumeMountPoint Handle, volumeMountPoint *uint16, bufferLength uint32) (err error) = FindNextVolumeMountPointW
|
||||
//sys FindVolumeClose(findVolume Handle) (err error)
|
||||
//sys FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error)
|
||||
//sys GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) = GetDiskFreeSpaceExW
|
||||
//sys GetDriveType(rootPathName *uint16) (driveType uint32) = GetDriveTypeW
|
||||
//sys GetLogicalDrives() (drivesBitMask uint32, err error) [failretval==0]
|
||||
//sys GetLogicalDriveStrings(bufferLength uint32, buffer *uint16) (n uint32, err error) [failretval==0] = GetLogicalDriveStringsW
|
||||
@ -283,9 +303,54 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) = SetVolumeLabelW
|
||||
//sys SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) = SetVolumeMountPointW
|
||||
//sys MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW
|
||||
//sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx
|
||||
//sys InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) = advapi32.InitiateSystemShutdownExW
|
||||
//sys SetProcessShutdownParameters(level uint32, flags uint32) (err error) = kernel32.SetProcessShutdownParameters
|
||||
//sys GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) = kernel32.GetProcessShutdownParameters
|
||||
//sys clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) = ole32.CLSIDFromString
|
||||
//sys stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) = ole32.StringFromGUID2
|
||||
//sys coCreateGuid(pguid *GUID) (ret error) = ole32.CoCreateGuid
|
||||
//sys CoTaskMemFree(address unsafe.Pointer) = ole32.CoTaskMemFree
|
||||
//sys rtlGetVersion(info *OsVersionInfoEx) (ret error) = ntdll.RtlGetVersion
|
||||
//sys rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers
|
||||
//sys getProcessPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetProcessPreferredUILanguages
|
||||
//sys getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetThreadPreferredUILanguages
|
||||
//sys getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetUserPreferredUILanguages
|
||||
//sys getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetSystemPreferredUILanguages
|
||||
|
||||
// Process Status API (PSAPI)
|
||||
//sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
|
||||
|
||||
// syscall interface implementation for other packages
|
||||
|
||||
// GetCurrentProcess returns the handle for the current process.
|
||||
// It is a pseudo handle that does not need to be closed.
|
||||
// The returned error is always nil.
|
||||
//
|
||||
// Deprecated: use CurrentProcess for the same Handle without the nil
|
||||
// error.
|
||||
func GetCurrentProcess() (Handle, error) {
|
||||
return CurrentProcess(), nil
|
||||
}
|
||||
|
||||
// CurrentProcess returns the handle for the current process.
|
||||
// It is a pseudo handle that does not need to be closed.
|
||||
func CurrentProcess() Handle { return Handle(^uintptr(1 - 1)) }
|
||||
|
||||
// GetCurrentThread returns the handle for the current thread.
|
||||
// It is a pseudo handle that does not need to be closed.
|
||||
// The returned error is always nil.
|
||||
//
|
||||
// Deprecated: use CurrentThread for the same Handle without the nil
|
||||
// error.
|
||||
func GetCurrentThread() (Handle, error) {
|
||||
return CurrentThread(), nil
|
||||
}
|
||||
|
||||
// CurrentThread returns the handle for the current thread.
|
||||
// It is a pseudo handle that does not need to be closed.
|
||||
func CurrentThread() Handle { return Handle(^uintptr(2 - 1)) }
|
||||
|
||||
// GetProcAddressByOrdinal retrieves the address of the exported
|
||||
// function from module by ordinal.
|
||||
func GetProcAddressByOrdinal(module Handle, ordinal uintptr) (proc uintptr, err error) {
|
||||
@ -352,7 +417,11 @@ func Open(path string, mode int, perm uint32) (fd Handle, err error) {
|
||||
default:
|
||||
createmode = OPEN_EXISTING
|
||||
}
|
||||
h, e := CreateFile(pathp, access, sharemode, sa, createmode, FILE_ATTRIBUTE_NORMAL, 0)
|
||||
var attrs uint32 = FILE_ATTRIBUTE_NORMAL
|
||||
if perm&S_IWRITE == 0 {
|
||||
attrs = FILE_ATTRIBUTE_READONLY
|
||||
}
|
||||
h, e := CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0)
|
||||
return h, e
|
||||
}
|
||||
|
||||
@ -497,6 +566,10 @@ func ComputerName() (name string, err error) {
|
||||
return string(utf16.Decode(b[0:n])), nil
|
||||
}
|
||||
|
||||
func DurationSinceBoot() time.Duration {
|
||||
return time.Duration(getTickCount64()) * time.Millisecond
|
||||
}
|
||||
|
||||
func Ftruncate(fd Handle, length int64) (err error) {
|
||||
curoffset, e := Seek(fd, 0, 1)
|
||||
if e != nil {
|
||||
@ -628,6 +701,8 @@ const socket_error = uintptr(^uint32(0))
|
||||
//sys WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup
|
||||
//sys WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) [failretval==socket_error] = ws2_32.WSAIoctl
|
||||
//sys socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket
|
||||
//sys sendto(s Handle, buf []byte, flags int32, to unsafe.Pointer, tolen int32) (err error) [failretval==socket_error] = ws2_32.sendto
|
||||
//sys recvfrom(s Handle, buf []byte, flags int32, from *RawSockaddrAny, fromlen *int32) (n int32, err error) [failretval==-1] = ws2_32.recvfrom
|
||||
//sys Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==socket_error] = ws2_32.setsockopt
|
||||
//sys Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockopt
|
||||
//sys bind(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.bind
|
||||
@ -795,7 +870,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
|
||||
for n < len(pp.Path) && pp.Path[n] != 0 {
|
||||
n++
|
||||
}
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
|
||||
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
|
||||
sa.Name = string(bytes)
|
||||
return sa, nil
|
||||
|
||||
@ -1056,10 +1131,27 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||
// TODO(brainman): fix all needed for net
|
||||
|
||||
func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, syscall.EWINDOWS }
|
||||
|
||||
func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) {
|
||||
return 0, nil, syscall.EWINDOWS
|
||||
var rsa RawSockaddrAny
|
||||
l := int32(unsafe.Sizeof(rsa))
|
||||
n32, err := recvfrom(fd, p, int32(flags), &rsa, &l)
|
||||
n = int(n32)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
from, err = rsa.Sockaddr()
|
||||
return
|
||||
}
|
||||
func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return syscall.EWINDOWS }
|
||||
|
||||
func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) {
|
||||
ptr, l, err := to.sockaddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return sendto(fd, p, int32(flags), ptr, l)
|
||||
}
|
||||
|
||||
func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return syscall.EWINDOWS }
|
||||
|
||||
// The Linger struct is wrong but we only noticed after Go 1.
|
||||
@ -1106,7 +1198,7 @@ func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) {
|
||||
return syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func Getpid() (pid int) { return int(getCurrentProcessId()) }
|
||||
func Getpid() (pid int) { return int(GetCurrentProcessId()) }
|
||||
|
||||
func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
|
||||
// NOTE(rsc): The Win32finddata struct is wrong for the system call:
|
||||
@ -1234,3 +1326,129 @@ func Readlink(path string, buf []byte) (n int, err error) {
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// GUIDFromString parses a string in the form of
|
||||
// "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" into a GUID.
|
||||
func GUIDFromString(str string) (GUID, error) {
|
||||
guid := GUID{}
|
||||
str16, err := syscall.UTF16PtrFromString(str)
|
||||
if err != nil {
|
||||
return guid, err
|
||||
}
|
||||
err = clsidFromString(str16, &guid)
|
||||
if err != nil {
|
||||
return guid, err
|
||||
}
|
||||
return guid, nil
|
||||
}
|
||||
|
||||
// GenerateGUID creates a new random GUID.
|
||||
func GenerateGUID() (GUID, error) {
|
||||
guid := GUID{}
|
||||
err := coCreateGuid(&guid)
|
||||
if err != nil {
|
||||
return guid, err
|
||||
}
|
||||
return guid, nil
|
||||
}
|
||||
|
||||
// String returns the canonical string form of the GUID,
|
||||
// in the form of "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}".
|
||||
func (guid GUID) String() string {
|
||||
var str [100]uint16
|
||||
chars := stringFromGUID2(&guid, &str[0], int32(len(str)))
|
||||
if chars <= 1 {
|
||||
return ""
|
||||
}
|
||||
return string(utf16.Decode(str[:chars-1]))
|
||||
}
|
||||
|
||||
// KnownFolderPath returns a well-known folder path for the current user, specified by one of
|
||||
// the FOLDERID_ constants, and chosen and optionally created based on a KF_ flag.
|
||||
func KnownFolderPath(folderID *KNOWNFOLDERID, flags uint32) (string, error) {
|
||||
return Token(0).KnownFolderPath(folderID, flags)
|
||||
}
|
||||
|
||||
// KnownFolderPath returns a well-known folder path for the user token, specified by one of
|
||||
// the FOLDERID_ constants, and chosen and optionally created based on a KF_ flag.
|
||||
func (t Token) KnownFolderPath(folderID *KNOWNFOLDERID, flags uint32) (string, error) {
|
||||
var p *uint16
|
||||
err := shGetKnownFolderPath(folderID, flags, t, &p)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer CoTaskMemFree(unsafe.Pointer(p))
|
||||
return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:]), nil
|
||||
}
|
||||
|
||||
// RtlGetVersion returns the version of the underlying operating system, ignoring
|
||||
// manifest semantics but is affected by the application compatibility layer.
|
||||
func RtlGetVersion() *OsVersionInfoEx {
|
||||
info := &OsVersionInfoEx{}
|
||||
info.osVersionInfoSize = uint32(unsafe.Sizeof(*info))
|
||||
// According to documentation, this function always succeeds.
|
||||
// The function doesn't even check the validity of the
|
||||
// osVersionInfoSize member. Disassembling ntdll.dll indicates
|
||||
// that the documentation is indeed correct about that.
|
||||
_ = rtlGetVersion(info)
|
||||
return info
|
||||
}
|
||||
|
||||
// RtlGetNtVersionNumbers returns the version of the underlying operating system,
|
||||
// ignoring manifest semantics and the application compatibility layer.
|
||||
func RtlGetNtVersionNumbers() (majorVersion, minorVersion, buildNumber uint32) {
|
||||
rtlGetNtVersionNumbers(&majorVersion, &minorVersion, &buildNumber)
|
||||
buildNumber &= 0xffff
|
||||
return
|
||||
}
|
||||
|
||||
// GetProcessPreferredUILanguages retrieves the process preferred UI languages.
|
||||
func GetProcessPreferredUILanguages(flags uint32) ([]string, error) {
|
||||
return getUILanguages(flags, getProcessPreferredUILanguages)
|
||||
}
|
||||
|
||||
// GetThreadPreferredUILanguages retrieves the thread preferred UI languages for the current thread.
|
||||
func GetThreadPreferredUILanguages(flags uint32) ([]string, error) {
|
||||
return getUILanguages(flags, getThreadPreferredUILanguages)
|
||||
}
|
||||
|
||||
// GetUserPreferredUILanguages retrieves information about the user preferred UI languages.
|
||||
func GetUserPreferredUILanguages(flags uint32) ([]string, error) {
|
||||
return getUILanguages(flags, getUserPreferredUILanguages)
|
||||
}
|
||||
|
||||
// GetSystemPreferredUILanguages retrieves the system preferred UI languages.
|
||||
func GetSystemPreferredUILanguages(flags uint32) ([]string, error) {
|
||||
return getUILanguages(flags, getSystemPreferredUILanguages)
|
||||
}
|
||||
|
||||
func getUILanguages(flags uint32, f func(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) error) ([]string, error) {
|
||||
size := uint32(128)
|
||||
for {
|
||||
var numLanguages uint32
|
||||
buf := make([]uint16, size)
|
||||
err := f(flags, &numLanguages, &buf[0], &size)
|
||||
if err == ERROR_INSUFFICIENT_BUFFER {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf = buf[:size]
|
||||
if numLanguages == 0 || len(buf) == 0 { // GetProcessPreferredUILanguages may return numLanguages==0 with "\0\0"
|
||||
return []string{}, nil
|
||||
}
|
||||
if buf[len(buf)-1] == 0 {
|
||||
buf = buf[:len(buf)-1] // remove terminating null
|
||||
}
|
||||
languages := make([]string, 0, numLanguages)
|
||||
from := 0
|
||||
for i, c := range buf {
|
||||
if c == 0 {
|
||||
languages = append(languages, string(utf16.Decode(buf[from:i])))
|
||||
from = i + 1
|
||||
}
|
||||
}
|
||||
return languages, nil
|
||||
}
|
||||
}
|
||||
|
219
go/vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
219
go/vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
@ -62,11 +62,6 @@ var signals = [...]string{
|
||||
}
|
||||
|
||||
const (
|
||||
GENERIC_READ = 0x80000000
|
||||
GENERIC_WRITE = 0x40000000
|
||||
GENERIC_EXECUTE = 0x20000000
|
||||
GENERIC_ALL = 0x10000000
|
||||
|
||||
FILE_LIST_DIRECTORY = 0x00000001
|
||||
FILE_APPEND_DATA = 0x00000004
|
||||
FILE_WRITE_ATTRIBUTES = 0x00000100
|
||||
@ -158,17 +153,43 @@ const (
|
||||
WAIT_OBJECT_0 = 0x00000000
|
||||
WAIT_FAILED = 0xFFFFFFFF
|
||||
|
||||
PROCESS_TERMINATE = 1
|
||||
PROCESS_QUERY_INFORMATION = 0x00000400
|
||||
SYNCHRONIZE = 0x00100000
|
||||
// Access rights for process.
|
||||
PROCESS_CREATE_PROCESS = 0x0080
|
||||
PROCESS_CREATE_THREAD = 0x0002
|
||||
PROCESS_DUP_HANDLE = 0x0040
|
||||
PROCESS_QUERY_INFORMATION = 0x0400
|
||||
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
|
||||
PROCESS_SET_INFORMATION = 0x0200
|
||||
PROCESS_SET_QUOTA = 0x0100
|
||||
PROCESS_SUSPEND_RESUME = 0x0800
|
||||
PROCESS_TERMINATE = 0x0001
|
||||
PROCESS_VM_OPERATION = 0x0008
|
||||
PROCESS_VM_READ = 0x0010
|
||||
PROCESS_VM_WRITE = 0x0020
|
||||
|
||||
// Access rights for thread.
|
||||
THREAD_DIRECT_IMPERSONATION = 0x0200
|
||||
THREAD_GET_CONTEXT = 0x0008
|
||||
THREAD_IMPERSONATE = 0x0100
|
||||
THREAD_QUERY_INFORMATION = 0x0040
|
||||
THREAD_QUERY_LIMITED_INFORMATION = 0x0800
|
||||
THREAD_SET_CONTEXT = 0x0010
|
||||
THREAD_SET_INFORMATION = 0x0020
|
||||
THREAD_SET_LIMITED_INFORMATION = 0x0400
|
||||
THREAD_SET_THREAD_TOKEN = 0x0080
|
||||
THREAD_SUSPEND_RESUME = 0x0002
|
||||
THREAD_TERMINATE = 0x0001
|
||||
|
||||
FILE_MAP_COPY = 0x01
|
||||
FILE_MAP_WRITE = 0x02
|
||||
FILE_MAP_READ = 0x04
|
||||
FILE_MAP_EXECUTE = 0x20
|
||||
|
||||
CTRL_C_EVENT = 0
|
||||
CTRL_BREAK_EVENT = 1
|
||||
CTRL_C_EVENT = 0
|
||||
CTRL_BREAK_EVENT = 1
|
||||
CTRL_CLOSE_EVENT = 2
|
||||
CTRL_LOGOFF_EVENT = 5
|
||||
CTRL_SHUTDOWN_EVENT = 6
|
||||
|
||||
// Windows reserves errors >= 1<<29 for application use.
|
||||
APPLICATION_ERROR = 1 << 29
|
||||
@ -450,12 +471,6 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||
return
|
||||
}
|
||||
|
||||
type SecurityAttributes struct {
|
||||
Length uint32
|
||||
SecurityDescriptor uintptr
|
||||
InheritHandle uint32
|
||||
}
|
||||
|
||||
type Overlapped struct {
|
||||
Internal uintptr
|
||||
InternalHigh uintptr
|
||||
@ -629,6 +644,16 @@ type ProcessEntry32 struct {
|
||||
ExeFile [MAX_PATH]uint16
|
||||
}
|
||||
|
||||
type ThreadEntry32 struct {
|
||||
Size uint32
|
||||
Usage uint32
|
||||
ThreadID uint32
|
||||
OwnerProcessID uint32
|
||||
BasePri int32
|
||||
DeltaPri int32
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
type Systemtime struct {
|
||||
Year uint16
|
||||
Month uint16
|
||||
@ -665,6 +690,7 @@ const (
|
||||
SOCK_SEQPACKET = 5
|
||||
|
||||
IPPROTO_IP = 0
|
||||
IPPROTO_ICMP = 1
|
||||
IPPROTO_IPV6 = 0x29
|
||||
IPPROTO_TCP = 6
|
||||
IPPROTO_UDP = 17
|
||||
@ -676,6 +702,7 @@ const (
|
||||
SO_BROADCAST = 32
|
||||
SO_LINGER = 128
|
||||
SO_RCVBUF = 0x1002
|
||||
SO_RCVTIMEO = 0x1006
|
||||
SO_SNDBUF = 0x1001
|
||||
SO_UPDATE_ACCEPT_CONTEXT = 0x700b
|
||||
SO_UPDATE_CONNECT_CONTEXT = 0x7010
|
||||
@ -1147,6 +1174,28 @@ const (
|
||||
REG_QWORD = REG_QWORD_LITTLE_ENDIAN
|
||||
)
|
||||
|
||||
const (
|
||||
EVENT_MODIFY_STATE = 0x0002
|
||||
EVENT_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3
|
||||
|
||||
MUTANT_QUERY_STATE = 0x0001
|
||||
MUTANT_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | MUTANT_QUERY_STATE
|
||||
|
||||
SEMAPHORE_MODIFY_STATE = 0x0002
|
||||
SEMAPHORE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3
|
||||
|
||||
TIMER_QUERY_STATE = 0x0001
|
||||
TIMER_MODIFY_STATE = 0x0002
|
||||
TIMER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | TIMER_QUERY_STATE | TIMER_MODIFY_STATE
|
||||
|
||||
MUTEX_MODIFY_STATE = MUTANT_QUERY_STATE
|
||||
MUTEX_ALL_ACCESS = MUTANT_ALL_ACCESS
|
||||
|
||||
CREATE_EVENT_MANUAL_RESET = 0x1
|
||||
CREATE_EVENT_INITIAL_SET = 0x2
|
||||
CREATE_MUTEX_INITIAL_OWNER = 0x1
|
||||
)
|
||||
|
||||
type AddrinfoW struct {
|
||||
Flags int32
|
||||
Family int32
|
||||
@ -1590,3 +1639,141 @@ const (
|
||||
JobObjectNotificationLimitInformation2 = 34
|
||||
JobObjectSecurityLimitInformation = 5
|
||||
)
|
||||
|
||||
const (
|
||||
KF_FLAG_DEFAULT = 0x00000000
|
||||
KF_FLAG_FORCE_APP_DATA_REDIRECTION = 0x00080000
|
||||
KF_FLAG_RETURN_FILTER_REDIRECTION_TARGET = 0x00040000
|
||||
KF_FLAG_FORCE_PACKAGE_REDIRECTION = 0x00020000
|
||||
KF_FLAG_NO_PACKAGE_REDIRECTION = 0x00010000
|
||||
KF_FLAG_FORCE_APPCONTAINER_REDIRECTION = 0x00020000
|
||||
KF_FLAG_NO_APPCONTAINER_REDIRECTION = 0x00010000
|
||||
KF_FLAG_CREATE = 0x00008000
|
||||
KF_FLAG_DONT_VERIFY = 0x00004000
|
||||
KF_FLAG_DONT_UNEXPAND = 0x00002000
|
||||
KF_FLAG_NO_ALIAS = 0x00001000
|
||||
KF_FLAG_INIT = 0x00000800
|
||||
KF_FLAG_DEFAULT_PATH = 0x00000400
|
||||
KF_FLAG_NOT_PARENT_RELATIVE = 0x00000200
|
||||
KF_FLAG_SIMPLE_IDLIST = 0x00000100
|
||||
KF_FLAG_ALIAS_ONLY = 0x80000000
|
||||
)
|
||||
|
||||
type OsVersionInfoEx struct {
|
||||
osVersionInfoSize uint32
|
||||
MajorVersion uint32
|
||||
MinorVersion uint32
|
||||
BuildNumber uint32
|
||||
PlatformId uint32
|
||||
CsdVersion [128]uint16
|
||||
ServicePackMajor uint16
|
||||
ServicePackMinor uint16
|
||||
SuiteMask uint16
|
||||
ProductType byte
|
||||
_ byte
|
||||
}
|
||||
|
||||
const (
|
||||
EWX_LOGOFF = 0x00000000
|
||||
EWX_SHUTDOWN = 0x00000001
|
||||
EWX_REBOOT = 0x00000002
|
||||
EWX_FORCE = 0x00000004
|
||||
EWX_POWEROFF = 0x00000008
|
||||
EWX_FORCEIFHUNG = 0x00000010
|
||||
EWX_QUICKRESOLVE = 0x00000020
|
||||
EWX_RESTARTAPPS = 0x00000040
|
||||
EWX_HYBRID_SHUTDOWN = 0x00400000
|
||||
EWX_BOOTOPTIONS = 0x01000000
|
||||
|
||||
SHTDN_REASON_FLAG_COMMENT_REQUIRED = 0x01000000
|
||||
SHTDN_REASON_FLAG_DIRTY_PROBLEM_ID_REQUIRED = 0x02000000
|
||||
SHTDN_REASON_FLAG_CLEAN_UI = 0x04000000
|
||||
SHTDN_REASON_FLAG_DIRTY_UI = 0x08000000
|
||||
SHTDN_REASON_FLAG_USER_DEFINED = 0x40000000
|
||||
SHTDN_REASON_FLAG_PLANNED = 0x80000000
|
||||
SHTDN_REASON_MAJOR_OTHER = 0x00000000
|
||||
SHTDN_REASON_MAJOR_NONE = 0x00000000
|
||||
SHTDN_REASON_MAJOR_HARDWARE = 0x00010000
|
||||
SHTDN_REASON_MAJOR_OPERATINGSYSTEM = 0x00020000
|
||||
SHTDN_REASON_MAJOR_SOFTWARE = 0x00030000
|
||||
SHTDN_REASON_MAJOR_APPLICATION = 0x00040000
|
||||
SHTDN_REASON_MAJOR_SYSTEM = 0x00050000
|
||||
SHTDN_REASON_MAJOR_POWER = 0x00060000
|
||||
SHTDN_REASON_MAJOR_LEGACY_API = 0x00070000
|
||||
SHTDN_REASON_MINOR_OTHER = 0x00000000
|
||||
SHTDN_REASON_MINOR_NONE = 0x000000ff
|
||||
SHTDN_REASON_MINOR_MAINTENANCE = 0x00000001
|
||||
SHTDN_REASON_MINOR_INSTALLATION = 0x00000002
|
||||
SHTDN_REASON_MINOR_UPGRADE = 0x00000003
|
||||
SHTDN_REASON_MINOR_RECONFIG = 0x00000004
|
||||
SHTDN_REASON_MINOR_HUNG = 0x00000005
|
||||
SHTDN_REASON_MINOR_UNSTABLE = 0x00000006
|
||||
SHTDN_REASON_MINOR_DISK = 0x00000007
|
||||
SHTDN_REASON_MINOR_PROCESSOR = 0x00000008
|
||||
SHTDN_REASON_MINOR_NETWORKCARD = 0x00000009
|
||||
SHTDN_REASON_MINOR_POWER_SUPPLY = 0x0000000a
|
||||
SHTDN_REASON_MINOR_CORDUNPLUGGED = 0x0000000b
|
||||
SHTDN_REASON_MINOR_ENVIRONMENT = 0x0000000c
|
||||
SHTDN_REASON_MINOR_HARDWARE_DRIVER = 0x0000000d
|
||||
SHTDN_REASON_MINOR_OTHERDRIVER = 0x0000000e
|
||||
SHTDN_REASON_MINOR_BLUESCREEN = 0x0000000F
|
||||
SHTDN_REASON_MINOR_SERVICEPACK = 0x00000010
|
||||
SHTDN_REASON_MINOR_HOTFIX = 0x00000011
|
||||
SHTDN_REASON_MINOR_SECURITYFIX = 0x00000012
|
||||
SHTDN_REASON_MINOR_SECURITY = 0x00000013
|
||||
SHTDN_REASON_MINOR_NETWORK_CONNECTIVITY = 0x00000014
|
||||
SHTDN_REASON_MINOR_WMI = 0x00000015
|
||||
SHTDN_REASON_MINOR_SERVICEPACK_UNINSTALL = 0x00000016
|
||||
SHTDN_REASON_MINOR_HOTFIX_UNINSTALL = 0x00000017
|
||||
SHTDN_REASON_MINOR_SECURITYFIX_UNINSTALL = 0x00000018
|
||||
SHTDN_REASON_MINOR_MMC = 0x00000019
|
||||
SHTDN_REASON_MINOR_SYSTEMRESTORE = 0x0000001a
|
||||
SHTDN_REASON_MINOR_TERMSRV = 0x00000020
|
||||
SHTDN_REASON_MINOR_DC_PROMOTION = 0x00000021
|
||||
SHTDN_REASON_MINOR_DC_DEMOTION = 0x00000022
|
||||
SHTDN_REASON_UNKNOWN = SHTDN_REASON_MINOR_NONE
|
||||
SHTDN_REASON_LEGACY_API = SHTDN_REASON_MAJOR_LEGACY_API | SHTDN_REASON_FLAG_PLANNED
|
||||
SHTDN_REASON_VALID_BIT_MASK = 0xc0ffffff
|
||||
|
||||
SHUTDOWN_NORETRY = 0x1
|
||||
)
|
||||
|
||||
// Flags used for GetModuleHandleEx
|
||||
const (
|
||||
GET_MODULE_HANDLE_EX_FLAG_PIN = 1
|
||||
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 2
|
||||
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 4
|
||||
)
|
||||
|
||||
// MUI function flag values
|
||||
const (
|
||||
MUI_LANGUAGE_ID = 0x4
|
||||
MUI_LANGUAGE_NAME = 0x8
|
||||
MUI_MERGE_SYSTEM_FALLBACK = 0x10
|
||||
MUI_MERGE_USER_FALLBACK = 0x20
|
||||
MUI_UI_FALLBACK = MUI_MERGE_SYSTEM_FALLBACK | MUI_MERGE_USER_FALLBACK
|
||||
MUI_THREAD_LANGUAGES = 0x40
|
||||
MUI_CONSOLE_FILTER = 0x100
|
||||
MUI_COMPLEX_SCRIPT_FILTER = 0x200
|
||||
MUI_RESET_FILTERS = 0x001
|
||||
MUI_USER_PREFERRED_UI_LANGUAGES = 0x10
|
||||
MUI_USE_INSTALLED_LANGUAGES = 0x20
|
||||
MUI_USE_SEARCH_ALL_LANGUAGES = 0x40
|
||||
MUI_LANG_NEUTRAL_PE_FILE = 0x100
|
||||
MUI_NON_LANG_NEUTRAL_FILE = 0x200
|
||||
MUI_MACHINE_LANGUAGE_SETTINGS = 0x400
|
||||
MUI_FILETYPE_NOT_LANGUAGE_NEUTRAL = 0x001
|
||||
MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN = 0x002
|
||||
MUI_FILETYPE_LANGUAGE_NEUTRAL_MUI = 0x004
|
||||
MUI_QUERY_TYPE = 0x001
|
||||
MUI_QUERY_CHECKSUM = 0x002
|
||||
MUI_QUERY_LANGUAGE_NAME = 0x004
|
||||
MUI_QUERY_RESOURCE_TYPES = 0x008
|
||||
MUI_FILEINFO_VERSION = 0x001
|
||||
|
||||
MUI_FULL_LANGUAGE = 0x01
|
||||
MUI_PARTIAL_LANGUAGE = 0x02
|
||||
MUI_LIP_LANGUAGE = 0x04
|
||||
MUI_LANGUAGE_INSTALLED = 0x20
|
||||
MUI_LANGUAGE_LICENSED = 0x40
|
||||
)
|
||||
|
2
go/vendor/golang.org/x/sys/windows/zerrors_windows.go
generated
vendored
2
go/vendor/golang.org/x/sys/windows/zerrors_windows.go
generated
vendored
@ -1,4 +1,4 @@
|
||||
// Code generated by 'go generate'; DO NOT EDIT.
|
||||
// Code generated by 'mkerrors.bash'; DO NOT EDIT.
|
||||
|
||||
package windows
|
||||
|
||||
|
149
go/vendor/golang.org/x/sys/windows/zknownfolderids_windows.go
generated
vendored
Normal file
149
go/vendor/golang.org/x/sys/windows/zknownfolderids_windows.go
generated
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
// Code generated by 'mkknownfolderids.bash'; DO NOT EDIT.
|
||||
|
||||
package windows
|
||||
|
||||
type KNOWNFOLDERID GUID
|
||||
|
||||
var (
|
||||
FOLDERID_NetworkFolder = &KNOWNFOLDERID{0xd20beec4, 0x5ca8, 0x4905, [8]byte{0xae, 0x3b, 0xbf, 0x25, 0x1e, 0xa0, 0x9b, 0x53}}
|
||||
FOLDERID_ComputerFolder = &KNOWNFOLDERID{0x0ac0837c, 0xbbf8, 0x452a, [8]byte{0x85, 0x0d, 0x79, 0xd0, 0x8e, 0x66, 0x7c, 0xa7}}
|
||||
FOLDERID_InternetFolder = &KNOWNFOLDERID{0x4d9f7874, 0x4e0c, 0x4904, [8]byte{0x96, 0x7b, 0x40, 0xb0, 0xd2, 0x0c, 0x3e, 0x4b}}
|
||||
FOLDERID_ControlPanelFolder = &KNOWNFOLDERID{0x82a74aeb, 0xaeb4, 0x465c, [8]byte{0xa0, 0x14, 0xd0, 0x97, 0xee, 0x34, 0x6d, 0x63}}
|
||||
FOLDERID_PrintersFolder = &KNOWNFOLDERID{0x76fc4e2d, 0xd6ad, 0x4519, [8]byte{0xa6, 0x63, 0x37, 0xbd, 0x56, 0x06, 0x81, 0x85}}
|
||||
FOLDERID_SyncManagerFolder = &KNOWNFOLDERID{0x43668bf8, 0xc14e, 0x49b2, [8]byte{0x97, 0xc9, 0x74, 0x77, 0x84, 0xd7, 0x84, 0xb7}}
|
||||
FOLDERID_SyncSetupFolder = &KNOWNFOLDERID{0x0f214138, 0xb1d3, 0x4a90, [8]byte{0xbb, 0xa9, 0x27, 0xcb, 0xc0, 0xc5, 0x38, 0x9a}}
|
||||
FOLDERID_ConflictFolder = &KNOWNFOLDERID{0x4bfefb45, 0x347d, 0x4006, [8]byte{0xa5, 0xbe, 0xac, 0x0c, 0xb0, 0x56, 0x71, 0x92}}
|
||||
FOLDERID_SyncResultsFolder = &KNOWNFOLDERID{0x289a9a43, 0xbe44, 0x4057, [8]byte{0xa4, 0x1b, 0x58, 0x7a, 0x76, 0xd7, 0xe7, 0xf9}}
|
||||
FOLDERID_RecycleBinFolder = &KNOWNFOLDERID{0xb7534046, 0x3ecb, 0x4c18, [8]byte{0xbe, 0x4e, 0x64, 0xcd, 0x4c, 0xb7, 0xd6, 0xac}}
|
||||
FOLDERID_ConnectionsFolder = &KNOWNFOLDERID{0x6f0cd92b, 0x2e97, 0x45d1, [8]byte{0x88, 0xff, 0xb0, 0xd1, 0x86, 0xb8, 0xde, 0xdd}}
|
||||
FOLDERID_Fonts = &KNOWNFOLDERID{0xfd228cb7, 0xae11, 0x4ae3, [8]byte{0x86, 0x4c, 0x16, 0xf3, 0x91, 0x0a, 0xb8, 0xfe}}
|
||||
FOLDERID_Desktop = &KNOWNFOLDERID{0xb4bfcc3a, 0xdb2c, 0x424c, [8]byte{0xb0, 0x29, 0x7f, 0xe9, 0x9a, 0x87, 0xc6, 0x41}}
|
||||
FOLDERID_Startup = &KNOWNFOLDERID{0xb97d20bb, 0xf46a, 0x4c97, [8]byte{0xba, 0x10, 0x5e, 0x36, 0x08, 0x43, 0x08, 0x54}}
|
||||
FOLDERID_Programs = &KNOWNFOLDERID{0xa77f5d77, 0x2e2b, 0x44c3, [8]byte{0xa6, 0xa2, 0xab, 0xa6, 0x01, 0x05, 0x4a, 0x51}}
|
||||
FOLDERID_StartMenu = &KNOWNFOLDERID{0x625b53c3, 0xab48, 0x4ec1, [8]byte{0xba, 0x1f, 0xa1, 0xef, 0x41, 0x46, 0xfc, 0x19}}
|
||||
FOLDERID_Recent = &KNOWNFOLDERID{0xae50c081, 0xebd2, 0x438a, [8]byte{0x86, 0x55, 0x8a, 0x09, 0x2e, 0x34, 0x98, 0x7a}}
|
||||
FOLDERID_SendTo = &KNOWNFOLDERID{0x8983036c, 0x27c0, 0x404b, [8]byte{0x8f, 0x08, 0x10, 0x2d, 0x10, 0xdc, 0xfd, 0x74}}
|
||||
FOLDERID_Documents = &KNOWNFOLDERID{0xfdd39ad0, 0x238f, 0x46af, [8]byte{0xad, 0xb4, 0x6c, 0x85, 0x48, 0x03, 0x69, 0xc7}}
|
||||
FOLDERID_Favorites = &KNOWNFOLDERID{0x1777f761, 0x68ad, 0x4d8a, [8]byte{0x87, 0xbd, 0x30, 0xb7, 0x59, 0xfa, 0x33, 0xdd}}
|
||||
FOLDERID_NetHood = &KNOWNFOLDERID{0xc5abbf53, 0xe17f, 0x4121, [8]byte{0x89, 0x00, 0x86, 0x62, 0x6f, 0xc2, 0xc9, 0x73}}
|
||||
FOLDERID_PrintHood = &KNOWNFOLDERID{0x9274bd8d, 0xcfd1, 0x41c3, [8]byte{0xb3, 0x5e, 0xb1, 0x3f, 0x55, 0xa7, 0x58, 0xf4}}
|
||||
FOLDERID_Templates = &KNOWNFOLDERID{0xa63293e8, 0x664e, 0x48db, [8]byte{0xa0, 0x79, 0xdf, 0x75, 0x9e, 0x05, 0x09, 0xf7}}
|
||||
FOLDERID_CommonStartup = &KNOWNFOLDERID{0x82a5ea35, 0xd9cd, 0x47c5, [8]byte{0x96, 0x29, 0xe1, 0x5d, 0x2f, 0x71, 0x4e, 0x6e}}
|
||||
FOLDERID_CommonPrograms = &KNOWNFOLDERID{0x0139d44e, 0x6afe, 0x49f2, [8]byte{0x86, 0x90, 0x3d, 0xaf, 0xca, 0xe6, 0xff, 0xb8}}
|
||||
FOLDERID_CommonStartMenu = &KNOWNFOLDERID{0xa4115719, 0xd62e, 0x491d, [8]byte{0xaa, 0x7c, 0xe7, 0x4b, 0x8b, 0xe3, 0xb0, 0x67}}
|
||||
FOLDERID_PublicDesktop = &KNOWNFOLDERID{0xc4aa340d, 0xf20f, 0x4863, [8]byte{0xaf, 0xef, 0xf8, 0x7e, 0xf2, 0xe6, 0xba, 0x25}}
|
||||
FOLDERID_ProgramData = &KNOWNFOLDERID{0x62ab5d82, 0xfdc1, 0x4dc3, [8]byte{0xa9, 0xdd, 0x07, 0x0d, 0x1d, 0x49, 0x5d, 0x97}}
|
||||
FOLDERID_CommonTemplates = &KNOWNFOLDERID{0xb94237e7, 0x57ac, 0x4347, [8]byte{0x91, 0x51, 0xb0, 0x8c, 0x6c, 0x32, 0xd1, 0xf7}}
|
||||
FOLDERID_PublicDocuments = &KNOWNFOLDERID{0xed4824af, 0xdce4, 0x45a8, [8]byte{0x81, 0xe2, 0xfc, 0x79, 0x65, 0x08, 0x36, 0x34}}
|
||||
FOLDERID_RoamingAppData = &KNOWNFOLDERID{0x3eb685db, 0x65f9, 0x4cf6, [8]byte{0xa0, 0x3a, 0xe3, 0xef, 0x65, 0x72, 0x9f, 0x3d}}
|
||||
FOLDERID_LocalAppData = &KNOWNFOLDERID{0xf1b32785, 0x6fba, 0x4fcf, [8]byte{0x9d, 0x55, 0x7b, 0x8e, 0x7f, 0x15, 0x70, 0x91}}
|
||||
FOLDERID_LocalAppDataLow = &KNOWNFOLDERID{0xa520a1a4, 0x1780, 0x4ff6, [8]byte{0xbd, 0x18, 0x16, 0x73, 0x43, 0xc5, 0xaf, 0x16}}
|
||||
FOLDERID_InternetCache = &KNOWNFOLDERID{0x352481e8, 0x33be, 0x4251, [8]byte{0xba, 0x85, 0x60, 0x07, 0xca, 0xed, 0xcf, 0x9d}}
|
||||
FOLDERID_Cookies = &KNOWNFOLDERID{0x2b0f765d, 0xc0e9, 0x4171, [8]byte{0x90, 0x8e, 0x08, 0xa6, 0x11, 0xb8, 0x4f, 0xf6}}
|
||||
FOLDERID_History = &KNOWNFOLDERID{0xd9dc8a3b, 0xb784, 0x432e, [8]byte{0xa7, 0x81, 0x5a, 0x11, 0x30, 0xa7, 0x59, 0x63}}
|
||||
FOLDERID_System = &KNOWNFOLDERID{0x1ac14e77, 0x02e7, 0x4e5d, [8]byte{0xb7, 0x44, 0x2e, 0xb1, 0xae, 0x51, 0x98, 0xb7}}
|
||||
FOLDERID_SystemX86 = &KNOWNFOLDERID{0xd65231b0, 0xb2f1, 0x4857, [8]byte{0xa4, 0xce, 0xa8, 0xe7, 0xc6, 0xea, 0x7d, 0x27}}
|
||||
FOLDERID_Windows = &KNOWNFOLDERID{0xf38bf404, 0x1d43, 0x42f2, [8]byte{0x93, 0x05, 0x67, 0xde, 0x0b, 0x28, 0xfc, 0x23}}
|
||||
FOLDERID_Profile = &KNOWNFOLDERID{0x5e6c858f, 0x0e22, 0x4760, [8]byte{0x9a, 0xfe, 0xea, 0x33, 0x17, 0xb6, 0x71, 0x73}}
|
||||
FOLDERID_Pictures = &KNOWNFOLDERID{0x33e28130, 0x4e1e, 0x4676, [8]byte{0x83, 0x5a, 0x98, 0x39, 0x5c, 0x3b, 0xc3, 0xbb}}
|
||||
FOLDERID_ProgramFilesX86 = &KNOWNFOLDERID{0x7c5a40ef, 0xa0fb, 0x4bfc, [8]byte{0x87, 0x4a, 0xc0, 0xf2, 0xe0, 0xb9, 0xfa, 0x8e}}
|
||||
FOLDERID_ProgramFilesCommonX86 = &KNOWNFOLDERID{0xde974d24, 0xd9c6, 0x4d3e, [8]byte{0xbf, 0x91, 0xf4, 0x45, 0x51, 0x20, 0xb9, 0x17}}
|
||||
FOLDERID_ProgramFilesX64 = &KNOWNFOLDERID{0x6d809377, 0x6af0, 0x444b, [8]byte{0x89, 0x57, 0xa3, 0x77, 0x3f, 0x02, 0x20, 0x0e}}
|
||||
FOLDERID_ProgramFilesCommonX64 = &KNOWNFOLDERID{0x6365d5a7, 0x0f0d, 0x45e5, [8]byte{0x87, 0xf6, 0x0d, 0xa5, 0x6b, 0x6a, 0x4f, 0x7d}}
|
||||
FOLDERID_ProgramFiles = &KNOWNFOLDERID{0x905e63b6, 0xc1bf, 0x494e, [8]byte{0xb2, 0x9c, 0x65, 0xb7, 0x32, 0xd3, 0xd2, 0x1a}}
|
||||
FOLDERID_ProgramFilesCommon = &KNOWNFOLDERID{0xf7f1ed05, 0x9f6d, 0x47a2, [8]byte{0xaa, 0xae, 0x29, 0xd3, 0x17, 0xc6, 0xf0, 0x66}}
|
||||
FOLDERID_UserProgramFiles = &KNOWNFOLDERID{0x5cd7aee2, 0x2219, 0x4a67, [8]byte{0xb8, 0x5d, 0x6c, 0x9c, 0xe1, 0x56, 0x60, 0xcb}}
|
||||
FOLDERID_UserProgramFilesCommon = &KNOWNFOLDERID{0xbcbd3057, 0xca5c, 0x4622, [8]byte{0xb4, 0x2d, 0xbc, 0x56, 0xdb, 0x0a, 0xe5, 0x16}}
|
||||
FOLDERID_AdminTools = &KNOWNFOLDERID{0x724ef170, 0xa42d, 0x4fef, [8]byte{0x9f, 0x26, 0xb6, 0x0e, 0x84, 0x6f, 0xba, 0x4f}}
|
||||
FOLDERID_CommonAdminTools = &KNOWNFOLDERID{0xd0384e7d, 0xbac3, 0x4797, [8]byte{0x8f, 0x14, 0xcb, 0xa2, 0x29, 0xb3, 0x92, 0xb5}}
|
||||
FOLDERID_Music = &KNOWNFOLDERID{0x4bd8d571, 0x6d19, 0x48d3, [8]byte{0xbe, 0x97, 0x42, 0x22, 0x20, 0x08, 0x0e, 0x43}}
|
||||
FOLDERID_Videos = &KNOWNFOLDERID{0x18989b1d, 0x99b5, 0x455b, [8]byte{0x84, 0x1c, 0xab, 0x7c, 0x74, 0xe4, 0xdd, 0xfc}}
|
||||
FOLDERID_Ringtones = &KNOWNFOLDERID{0xc870044b, 0xf49e, 0x4126, [8]byte{0xa9, 0xc3, 0xb5, 0x2a, 0x1f, 0xf4, 0x11, 0xe8}}
|
||||
FOLDERID_PublicPictures = &KNOWNFOLDERID{0xb6ebfb86, 0x6907, 0x413c, [8]byte{0x9a, 0xf7, 0x4f, 0xc2, 0xab, 0xf0, 0x7c, 0xc5}}
|
||||
FOLDERID_PublicMusic = &KNOWNFOLDERID{0x3214fab5, 0x9757, 0x4298, [8]byte{0xbb, 0x61, 0x92, 0xa9, 0xde, 0xaa, 0x44, 0xff}}
|
||||
FOLDERID_PublicVideos = &KNOWNFOLDERID{0x2400183a, 0x6185, 0x49fb, [8]byte{0xa2, 0xd8, 0x4a, 0x39, 0x2a, 0x60, 0x2b, 0xa3}}
|
||||
FOLDERID_PublicRingtones = &KNOWNFOLDERID{0xe555ab60, 0x153b, 0x4d17, [8]byte{0x9f, 0x04, 0xa5, 0xfe, 0x99, 0xfc, 0x15, 0xec}}
|
||||
FOLDERID_ResourceDir = &KNOWNFOLDERID{0x8ad10c31, 0x2adb, 0x4296, [8]byte{0xa8, 0xf7, 0xe4, 0x70, 0x12, 0x32, 0xc9, 0x72}}
|
||||
FOLDERID_LocalizedResourcesDir = &KNOWNFOLDERID{0x2a00375e, 0x224c, 0x49de, [8]byte{0xb8, 0xd1, 0x44, 0x0d, 0xf7, 0xef, 0x3d, 0xdc}}
|
||||
FOLDERID_CommonOEMLinks = &KNOWNFOLDERID{0xc1bae2d0, 0x10df, 0x4334, [8]byte{0xbe, 0xdd, 0x7a, 0xa2, 0x0b, 0x22, 0x7a, 0x9d}}
|
||||
FOLDERID_CDBurning = &KNOWNFOLDERID{0x9e52ab10, 0xf80d, 0x49df, [8]byte{0xac, 0xb8, 0x43, 0x30, 0xf5, 0x68, 0x78, 0x55}}
|
||||
FOLDERID_UserProfiles = &KNOWNFOLDERID{0x0762d272, 0xc50a, 0x4bb0, [8]byte{0xa3, 0x82, 0x69, 0x7d, 0xcd, 0x72, 0x9b, 0x80}}
|
||||
FOLDERID_Playlists = &KNOWNFOLDERID{0xde92c1c7, 0x837f, 0x4f69, [8]byte{0xa3, 0xbb, 0x86, 0xe6, 0x31, 0x20, 0x4a, 0x23}}
|
||||
FOLDERID_SamplePlaylists = &KNOWNFOLDERID{0x15ca69b3, 0x30ee, 0x49c1, [8]byte{0xac, 0xe1, 0x6b, 0x5e, 0xc3, 0x72, 0xaf, 0xb5}}
|
||||
FOLDERID_SampleMusic = &KNOWNFOLDERID{0xb250c668, 0xf57d, 0x4ee1, [8]byte{0xa6, 0x3c, 0x29, 0x0e, 0xe7, 0xd1, 0xaa, 0x1f}}
|
||||
FOLDERID_SamplePictures = &KNOWNFOLDERID{0xc4900540, 0x2379, 0x4c75, [8]byte{0x84, 0x4b, 0x64, 0xe6, 0xfa, 0xf8, 0x71, 0x6b}}
|
||||
FOLDERID_SampleVideos = &KNOWNFOLDERID{0x859ead94, 0x2e85, 0x48ad, [8]byte{0xa7, 0x1a, 0x09, 0x69, 0xcb, 0x56, 0xa6, 0xcd}}
|
||||
FOLDERID_PhotoAlbums = &KNOWNFOLDERID{0x69d2cf90, 0xfc33, 0x4fb7, [8]byte{0x9a, 0x0c, 0xeb, 0xb0, 0xf0, 0xfc, 0xb4, 0x3c}}
|
||||
FOLDERID_Public = &KNOWNFOLDERID{0xdfdf76a2, 0xc82a, 0x4d63, [8]byte{0x90, 0x6a, 0x56, 0x44, 0xac, 0x45, 0x73, 0x85}}
|
||||
FOLDERID_ChangeRemovePrograms = &KNOWNFOLDERID{0xdf7266ac, 0x9274, 0x4867, [8]byte{0x8d, 0x55, 0x3b, 0xd6, 0x61, 0xde, 0x87, 0x2d}}
|
||||
FOLDERID_AppUpdates = &KNOWNFOLDERID{0xa305ce99, 0xf527, 0x492b, [8]byte{0x8b, 0x1a, 0x7e, 0x76, 0xfa, 0x98, 0xd6, 0xe4}}
|
||||
FOLDERID_AddNewPrograms = &KNOWNFOLDERID{0xde61d971, 0x5ebc, 0x4f02, [8]byte{0xa3, 0xa9, 0x6c, 0x82, 0x89, 0x5e, 0x5c, 0x04}}
|
||||
FOLDERID_Downloads = &KNOWNFOLDERID{0x374de290, 0x123f, 0x4565, [8]byte{0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b}}
|
||||
FOLDERID_PublicDownloads = &KNOWNFOLDERID{0x3d644c9b, 0x1fb8, 0x4f30, [8]byte{0x9b, 0x45, 0xf6, 0x70, 0x23, 0x5f, 0x79, 0xc0}}
|
||||
FOLDERID_SavedSearches = &KNOWNFOLDERID{0x7d1d3a04, 0xdebb, 0x4115, [8]byte{0x95, 0xcf, 0x2f, 0x29, 0xda, 0x29, 0x20, 0xda}}
|
||||
FOLDERID_QuickLaunch = &KNOWNFOLDERID{0x52a4f021, 0x7b75, 0x48a9, [8]byte{0x9f, 0x6b, 0x4b, 0x87, 0xa2, 0x10, 0xbc, 0x8f}}
|
||||
FOLDERID_Contacts = &KNOWNFOLDERID{0x56784854, 0xc6cb, 0x462b, [8]byte{0x81, 0x69, 0x88, 0xe3, 0x50, 0xac, 0xb8, 0x82}}
|
||||
FOLDERID_SidebarParts = &KNOWNFOLDERID{0xa75d362e, 0x50fc, 0x4fb7, [8]byte{0xac, 0x2c, 0xa8, 0xbe, 0xaa, 0x31, 0x44, 0x93}}
|
||||
FOLDERID_SidebarDefaultParts = &KNOWNFOLDERID{0x7b396e54, 0x9ec5, 0x4300, [8]byte{0xbe, 0x0a, 0x24, 0x82, 0xeb, 0xae, 0x1a, 0x26}}
|
||||
FOLDERID_PublicGameTasks = &KNOWNFOLDERID{0xdebf2536, 0xe1a8, 0x4c59, [8]byte{0xb6, 0xa2, 0x41, 0x45, 0x86, 0x47, 0x6a, 0xea}}
|
||||
FOLDERID_GameTasks = &KNOWNFOLDERID{0x054fae61, 0x4dd8, 0x4787, [8]byte{0x80, 0xb6, 0x09, 0x02, 0x20, 0xc4, 0xb7, 0x00}}
|
||||
FOLDERID_SavedGames = &KNOWNFOLDERID{0x4c5c32ff, 0xbb9d, 0x43b0, [8]byte{0xb5, 0xb4, 0x2d, 0x72, 0xe5, 0x4e, 0xaa, 0xa4}}
|
||||
FOLDERID_Games = &KNOWNFOLDERID{0xcac52c1a, 0xb53d, 0x4edc, [8]byte{0x92, 0xd7, 0x6b, 0x2e, 0x8a, 0xc1, 0x94, 0x34}}
|
||||
FOLDERID_SEARCH_MAPI = &KNOWNFOLDERID{0x98ec0e18, 0x2098, 0x4d44, [8]byte{0x86, 0x44, 0x66, 0x97, 0x93, 0x15, 0xa2, 0x81}}
|
||||
FOLDERID_SEARCH_CSC = &KNOWNFOLDERID{0xee32e446, 0x31ca, 0x4aba, [8]byte{0x81, 0x4f, 0xa5, 0xeb, 0xd2, 0xfd, 0x6d, 0x5e}}
|
||||
FOLDERID_Links = &KNOWNFOLDERID{0xbfb9d5e0, 0xc6a9, 0x404c, [8]byte{0xb2, 0xb2, 0xae, 0x6d, 0xb6, 0xaf, 0x49, 0x68}}
|
||||
FOLDERID_UsersFiles = &KNOWNFOLDERID{0xf3ce0f7c, 0x4901, 0x4acc, [8]byte{0x86, 0x48, 0xd5, 0xd4, 0x4b, 0x04, 0xef, 0x8f}}
|
||||
FOLDERID_UsersLibraries = &KNOWNFOLDERID{0xa302545d, 0xdeff, 0x464b, [8]byte{0xab, 0xe8, 0x61, 0xc8, 0x64, 0x8d, 0x93, 0x9b}}
|
||||
FOLDERID_SearchHome = &KNOWNFOLDERID{0x190337d1, 0xb8ca, 0x4121, [8]byte{0xa6, 0x39, 0x6d, 0x47, 0x2d, 0x16, 0x97, 0x2a}}
|
||||
FOLDERID_OriginalImages = &KNOWNFOLDERID{0x2c36c0aa, 0x5812, 0x4b87, [8]byte{0xbf, 0xd0, 0x4c, 0xd0, 0xdf, 0xb1, 0x9b, 0x39}}
|
||||
FOLDERID_DocumentsLibrary = &KNOWNFOLDERID{0x7b0db17d, 0x9cd2, 0x4a93, [8]byte{0x97, 0x33, 0x46, 0xcc, 0x89, 0x02, 0x2e, 0x7c}}
|
||||
FOLDERID_MusicLibrary = &KNOWNFOLDERID{0x2112ab0a, 0xc86a, 0x4ffe, [8]byte{0xa3, 0x68, 0x0d, 0xe9, 0x6e, 0x47, 0x01, 0x2e}}
|
||||
FOLDERID_PicturesLibrary = &KNOWNFOLDERID{0xa990ae9f, 0xa03b, 0x4e80, [8]byte{0x94, 0xbc, 0x99, 0x12, 0xd7, 0x50, 0x41, 0x04}}
|
||||
FOLDERID_VideosLibrary = &KNOWNFOLDERID{0x491e922f, 0x5643, 0x4af4, [8]byte{0xa7, 0xeb, 0x4e, 0x7a, 0x13, 0x8d, 0x81, 0x74}}
|
||||
FOLDERID_RecordedTVLibrary = &KNOWNFOLDERID{0x1a6fdba2, 0xf42d, 0x4358, [8]byte{0xa7, 0x98, 0xb7, 0x4d, 0x74, 0x59, 0x26, 0xc5}}
|
||||
FOLDERID_HomeGroup = &KNOWNFOLDERID{0x52528a6b, 0xb9e3, 0x4add, [8]byte{0xb6, 0x0d, 0x58, 0x8c, 0x2d, 0xba, 0x84, 0x2d}}
|
||||
FOLDERID_HomeGroupCurrentUser = &KNOWNFOLDERID{0x9b74b6a3, 0x0dfd, 0x4f11, [8]byte{0x9e, 0x78, 0x5f, 0x78, 0x00, 0xf2, 0xe7, 0x72}}
|
||||
FOLDERID_DeviceMetadataStore = &KNOWNFOLDERID{0x5ce4a5e9, 0xe4eb, 0x479d, [8]byte{0xb8, 0x9f, 0x13, 0x0c, 0x02, 0x88, 0x61, 0x55}}
|
||||
FOLDERID_Libraries = &KNOWNFOLDERID{0x1b3ea5dc, 0xb587, 0x4786, [8]byte{0xb4, 0xef, 0xbd, 0x1d, 0xc3, 0x32, 0xae, 0xae}}
|
||||
FOLDERID_PublicLibraries = &KNOWNFOLDERID{0x48daf80b, 0xe6cf, 0x4f4e, [8]byte{0xb8, 0x00, 0x0e, 0x69, 0xd8, 0x4e, 0xe3, 0x84}}
|
||||
FOLDERID_UserPinned = &KNOWNFOLDERID{0x9e3995ab, 0x1f9c, 0x4f13, [8]byte{0xb8, 0x27, 0x48, 0xb2, 0x4b, 0x6c, 0x71, 0x74}}
|
||||
FOLDERID_ImplicitAppShortcuts = &KNOWNFOLDERID{0xbcb5256f, 0x79f6, 0x4cee, [8]byte{0xb7, 0x25, 0xdc, 0x34, 0xe4, 0x02, 0xfd, 0x46}}
|
||||
FOLDERID_AccountPictures = &KNOWNFOLDERID{0x008ca0b1, 0x55b4, 0x4c56, [8]byte{0xb8, 0xa8, 0x4d, 0xe4, 0xb2, 0x99, 0xd3, 0xbe}}
|
||||
FOLDERID_PublicUserTiles = &KNOWNFOLDERID{0x0482af6c, 0x08f1, 0x4c34, [8]byte{0x8c, 0x90, 0xe1, 0x7e, 0xc9, 0x8b, 0x1e, 0x17}}
|
||||
FOLDERID_AppsFolder = &KNOWNFOLDERID{0x1e87508d, 0x89c2, 0x42f0, [8]byte{0x8a, 0x7e, 0x64, 0x5a, 0x0f, 0x50, 0xca, 0x58}}
|
||||
FOLDERID_StartMenuAllPrograms = &KNOWNFOLDERID{0xf26305ef, 0x6948, 0x40b9, [8]byte{0xb2, 0x55, 0x81, 0x45, 0x3d, 0x09, 0xc7, 0x85}}
|
||||
FOLDERID_CommonStartMenuPlaces = &KNOWNFOLDERID{0xa440879f, 0x87a0, 0x4f7d, [8]byte{0xb7, 0x00, 0x02, 0x07, 0xb9, 0x66, 0x19, 0x4a}}
|
||||
FOLDERID_ApplicationShortcuts = &KNOWNFOLDERID{0xa3918781, 0xe5f2, 0x4890, [8]byte{0xb3, 0xd9, 0xa7, 0xe5, 0x43, 0x32, 0x32, 0x8c}}
|
||||
FOLDERID_RoamingTiles = &KNOWNFOLDERID{0x00bcfc5a, 0xed94, 0x4e48, [8]byte{0x96, 0xa1, 0x3f, 0x62, 0x17, 0xf2, 0x19, 0x90}}
|
||||
FOLDERID_RoamedTileImages = &KNOWNFOLDERID{0xaaa8d5a5, 0xf1d6, 0x4259, [8]byte{0xba, 0xa8, 0x78, 0xe7, 0xef, 0x60, 0x83, 0x5e}}
|
||||
FOLDERID_Screenshots = &KNOWNFOLDERID{0xb7bede81, 0xdf94, 0x4682, [8]byte{0xa7, 0xd8, 0x57, 0xa5, 0x26, 0x20, 0xb8, 0x6f}}
|
||||
FOLDERID_CameraRoll = &KNOWNFOLDERID{0xab5fb87b, 0x7ce2, 0x4f83, [8]byte{0x91, 0x5d, 0x55, 0x08, 0x46, 0xc9, 0x53, 0x7b}}
|
||||
FOLDERID_SkyDrive = &KNOWNFOLDERID{0xa52bba46, 0xe9e1, 0x435f, [8]byte{0xb3, 0xd9, 0x28, 0xda, 0xa6, 0x48, 0xc0, 0xf6}}
|
||||
FOLDERID_OneDrive = &KNOWNFOLDERID{0xa52bba46, 0xe9e1, 0x435f, [8]byte{0xb3, 0xd9, 0x28, 0xda, 0xa6, 0x48, 0xc0, 0xf6}}
|
||||
FOLDERID_SkyDriveDocuments = &KNOWNFOLDERID{0x24d89e24, 0x2f19, 0x4534, [8]byte{0x9d, 0xde, 0x6a, 0x66, 0x71, 0xfb, 0xb8, 0xfe}}
|
||||
FOLDERID_SkyDrivePictures = &KNOWNFOLDERID{0x339719b5, 0x8c47, 0x4894, [8]byte{0x94, 0xc2, 0xd8, 0xf7, 0x7a, 0xdd, 0x44, 0xa6}}
|
||||
FOLDERID_SkyDriveMusic = &KNOWNFOLDERID{0xc3f2459e, 0x80d6, 0x45dc, [8]byte{0xbf, 0xef, 0x1f, 0x76, 0x9f, 0x2b, 0xe7, 0x30}}
|
||||
FOLDERID_SkyDriveCameraRoll = &KNOWNFOLDERID{0x767e6811, 0x49cb, 0x4273, [8]byte{0x87, 0xc2, 0x20, 0xf3, 0x55, 0xe1, 0x08, 0x5b}}
|
||||
FOLDERID_SearchHistory = &KNOWNFOLDERID{0x0d4c3db6, 0x03a3, 0x462f, [8]byte{0xa0, 0xe6, 0x08, 0x92, 0x4c, 0x41, 0xb5, 0xd4}}
|
||||
FOLDERID_SearchTemplates = &KNOWNFOLDERID{0x7e636bfe, 0xdfa9, 0x4d5e, [8]byte{0xb4, 0x56, 0xd7, 0xb3, 0x98, 0x51, 0xd8, 0xa9}}
|
||||
FOLDERID_CameraRollLibrary = &KNOWNFOLDERID{0x2b20df75, 0x1eda, 0x4039, [8]byte{0x80, 0x97, 0x38, 0x79, 0x82, 0x27, 0xd5, 0xb7}}
|
||||
FOLDERID_SavedPictures = &KNOWNFOLDERID{0x3b193882, 0xd3ad, 0x4eab, [8]byte{0x96, 0x5a, 0x69, 0x82, 0x9d, 0x1f, 0xb5, 0x9f}}
|
||||
FOLDERID_SavedPicturesLibrary = &KNOWNFOLDERID{0xe25b5812, 0xbe88, 0x4bd9, [8]byte{0x94, 0xb0, 0x29, 0x23, 0x34, 0x77, 0xb6, 0xc3}}
|
||||
FOLDERID_RetailDemo = &KNOWNFOLDERID{0x12d4c69e, 0x24ad, 0x4923, [8]byte{0xbe, 0x19, 0x31, 0x32, 0x1c, 0x43, 0xa7, 0x67}}
|
||||
FOLDERID_Device = &KNOWNFOLDERID{0x1c2ac1dc, 0x4358, 0x4b6c, [8]byte{0x97, 0x33, 0xaf, 0x21, 0x15, 0x65, 0x76, 0xf0}}
|
||||
FOLDERID_DevelopmentFiles = &KNOWNFOLDERID{0xdbe8e08e, 0x3053, 0x4bbc, [8]byte{0xb1, 0x83, 0x2a, 0x7b, 0x2b, 0x19, 0x1e, 0x59}}
|
||||
FOLDERID_Objects3D = &KNOWNFOLDERID{0x31c0dd25, 0x9439, 0x4f12, [8]byte{0xbf, 0x41, 0x7f, 0xf4, 0xed, 0xa3, 0x87, 0x22}}
|
||||
FOLDERID_AppCaptures = &KNOWNFOLDERID{0xedc0fe71, 0x98d8, 0x4f4a, [8]byte{0xb9, 0x20, 0xc8, 0xdc, 0x13, 0x3c, 0xb1, 0x65}}
|
||||
FOLDERID_LocalDocuments = &KNOWNFOLDERID{0xf42ee2d3, 0x909f, 0x4907, [8]byte{0x88, 0x71, 0x4c, 0x22, 0xfc, 0x0b, 0xf7, 0x56}}
|
||||
FOLDERID_LocalPictures = &KNOWNFOLDERID{0x0ddd015d, 0xb06c, 0x45d5, [8]byte{0x8c, 0x4c, 0xf5, 0x97, 0x13, 0x85, 0x46, 0x39}}
|
||||
FOLDERID_LocalVideos = &KNOWNFOLDERID{0x35286a68, 0x3c57, 0x41a1, [8]byte{0xbb, 0xb1, 0x0e, 0xae, 0x73, 0xd7, 0x6c, 0x95}}
|
||||
FOLDERID_LocalMusic = &KNOWNFOLDERID{0xa0c69a99, 0x21c8, 0x4671, [8]byte{0x87, 0x03, 0x79, 0x34, 0x16, 0x2f, 0xcf, 0x1d}}
|
||||
FOLDERID_LocalDownloads = &KNOWNFOLDERID{0x7d83ee9b, 0x2244, 0x4e70, [8]byte{0xb1, 0xf5, 0x53, 0x93, 0x04, 0x2a, 0xf1, 0xe4}}
|
||||
FOLDERID_RecordedCalls = &KNOWNFOLDERID{0x2f8b40c2, 0x83ed, 0x48ee, [8]byte{0xb3, 0x83, 0xa1, 0xf1, 0x57, 0xec, 0x6f, 0x9a}}
|
||||
FOLDERID_AllAppMods = &KNOWNFOLDERID{0x7ad67899, 0x66af, 0x43ba, [8]byte{0x91, 0x56, 0x6a, 0xad, 0x42, 0xe6, 0xc5, 0x96}}
|
||||
FOLDERID_CurrentAppMods = &KNOWNFOLDERID{0x3db40b20, 0x2a30, 0x4dbe, [8]byte{0x91, 0x7e, 0x77, 0x1d, 0xd2, 0x1d, 0xd0, 0x99}}
|
||||
FOLDERID_AppDataDesktop = &KNOWNFOLDERID{0xb2c5e279, 0x7add, 0x439f, [8]byte{0xb2, 0x8c, 0xc4, 0x1f, 0xe1, 0xbb, 0xf6, 0x72}}
|
||||
FOLDERID_AppDataDocuments = &KNOWNFOLDERID{0x7be16610, 0x1f7f, 0x44ac, [8]byte{0xbf, 0xf0, 0x83, 0xe1, 0x5f, 0x2f, 0xfc, 0xa1}}
|
||||
FOLDERID_AppDataFavorites = &KNOWNFOLDERID{0x7cfbefbc, 0xde1f, 0x45aa, [8]byte{0xb8, 0x43, 0xa5, 0x42, 0xac, 0x53, 0x6c, 0xc9}}
|
||||
FOLDERID_AppDataProgramData = &KNOWNFOLDERID{0x559d40a3, 0xa036, 0x40fa, [8]byte{0xaf, 0x61, 0x84, 0xcb, 0x43, 0x0a, 0x4d, 0x34}}
|
||||
)
|
1404
go/vendor/golang.org/x/sys/windows/zsyscall_windows.go
generated
vendored
1404
go/vendor/golang.org/x/sys/windows/zsyscall_windows.go
generated
vendored
File diff suppressed because it is too large
Load Diff
2
go/vendor/modules.txt
vendored
2
go/vendor/modules.txt
vendored
@ -4,5 +4,5 @@ github.com/Microsoft/go-winio/pkg/guid
|
||||
# github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95
|
||||
github.com/hectane/go-acl
|
||||
github.com/hectane/go-acl/api
|
||||
# golang.org/x/sys v0.0.0-20190529164535-6a60838ec259
|
||||
# golang.org/x/sys v0.0.0-20200107162124-548cf772de50
|
||||
golang.org/x/sys/windows
|
||||
|
@ -19,7 +19,12 @@
|
||||
#ifndef ZT_ZEROTIER_API_H
|
||||
#define ZT_ZEROTIER_API_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstdint>
|
||||
extern "C" {
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* For struct sockaddr_storage, which is referenced here. */
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
@ -39,10 +44,6 @@
|
||||
#define ZT_SDK_API
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/* Core constants */
|
||||
/****************************************************************************/
|
||||
@ -91,11 +92,6 @@ extern "C" {
|
||||
*/
|
||||
#define ZT_MAX_PHYSMTU (ZT_MAX_PHYSPAYLOAD + ZT_MAX_HEADROOM)
|
||||
|
||||
/**
|
||||
* Maximum size of a remote trace message's serialized Dictionary
|
||||
*/
|
||||
#define ZT_MAX_REMOTE_TRACE_SIZE 10000
|
||||
|
||||
/**
|
||||
* Maximum length of network short name
|
||||
*/
|
||||
@ -258,78 +254,6 @@ 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__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__CREDENTIAL_REVOCATION_TARGET "credRevocationTarget"
|
||||
#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__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
|
||||
|
||||
// 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__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"
|
||||
|
||||
/****************************************************************************/
|
||||
/* Structures and other types */
|
||||
/****************************************************************************/
|
||||
@ -397,35 +321,6 @@ enum ZT_ResultCode
|
||||
*/
|
||||
#define ZT_ResultCode_isFatal(x) ((((int)(x)) >= 100)&&(((int)(x)) < 1000))
|
||||
|
||||
/**
|
||||
* The multipath algorithm in use by this node.
|
||||
*/
|
||||
enum ZT_MultipathMode
|
||||
{
|
||||
/**
|
||||
* No active multipath.
|
||||
*
|
||||
* Traffic is merely sent over the strongest path. That being
|
||||
* said, this mode will automatically failover in the event that a link goes down.
|
||||
*/
|
||||
ZT_MULTIPATH_NONE = 0,
|
||||
|
||||
/**
|
||||
* Traffic is randomly distributed among all active paths.
|
||||
*
|
||||
* Will cease sending traffic over links that appear to be stale.
|
||||
*/
|
||||
ZT_MULTIPATH_RANDOM = 1,
|
||||
|
||||
/**
|
||||
* Traffic is allocated across all active paths in proportion to their strength and
|
||||
* reliability.
|
||||
*
|
||||
* Will cease sending traffic over links that appear to be stale.
|
||||
*/
|
||||
ZT_MULTIPATH_PROPORTIONALLY_BALANCED = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Status codes sent to status update callback when things happen
|
||||
*/
|
||||
@ -499,87 +394,23 @@ enum ZT_Event
|
||||
*
|
||||
* Meta-data: ZT_UserMessage structure
|
||||
*/
|
||||
ZT_EVENT_USER_MESSAGE = 6,
|
||||
|
||||
/**
|
||||
* Remote trace received
|
||||
*
|
||||
* NOTE: any node can fling a VERB_REMOTE_TRACE at you. It's up to you
|
||||
* to determine if you want to do anything with it or just silently
|
||||
* drop it on the floor. It's also up to you to handle these securely!
|
||||
*
|
||||
* Meta-data: ZT_RemoteTrace structure
|
||||
*/
|
||||
ZT_EVENT_REMOTE_TRACE = 7
|
||||
ZT_EVENT_USER_MESSAGE = 6
|
||||
};
|
||||
|
||||
/**
|
||||
* A root server
|
||||
* Identity type codes
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* Name of root
|
||||
*
|
||||
* This will be a DNS name for dynamic roots. For static roots
|
||||
* it will be the ZeroTier address. The presence or absence
|
||||
* of a dot is used internally as a distinguisher.
|
||||
*/
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* Serialized locator
|
||||
*/
|
||||
const void *locator;
|
||||
|
||||
/**
|
||||
* The size of locator in bytes
|
||||
*/
|
||||
unsigned int locatorSize;
|
||||
} ZT_Root;
|
||||
|
||||
/**
|
||||
* List of root servers
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* Number of root servers
|
||||
*/
|
||||
unsigned int count;
|
||||
|
||||
/**
|
||||
* Array of root servers
|
||||
*/
|
||||
ZT_Root roots[];
|
||||
} ZT_RootList;
|
||||
|
||||
/**
|
||||
* Payload of REMOTE_TRACE event
|
||||
*/
|
||||
typedef struct
|
||||
enum ZT_Identity_Type
|
||||
{
|
||||
/**
|
||||
* ZeroTier address of sender (in least significant 40 bits only)
|
||||
*/
|
||||
uint64_t origin;
|
||||
/* These values must be the same as in Identity.hpp in the core. */
|
||||
ZT_IDENTITY_TYPE_C25519 = 0,
|
||||
ZT_IDENTITY_TYPE_P384 = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
const char *data;
|
||||
|
||||
/**
|
||||
* Length of dict[] in bytes, INCLUDING terminating null
|
||||
*/
|
||||
unsigned int len;
|
||||
} ZT_RemoteTrace;
|
||||
/**
|
||||
* A ZeroTier identity (opaque)
|
||||
*/
|
||||
typedef void ZT_Identity;
|
||||
|
||||
/**
|
||||
* User message used with ZT_EVENT_USER_MESSAGE
|
||||
@ -624,6 +455,11 @@ typedef struct
|
||||
*/
|
||||
uint64_t address;
|
||||
|
||||
/**
|
||||
* Actual identity object for this node
|
||||
*/
|
||||
const ZT_Identity *identity;
|
||||
|
||||
/**
|
||||
* Public identity in string-serialized form (safe to send to others)
|
||||
*
|
||||
@ -1000,39 +836,6 @@ enum ZT_VirtualNetworkConfigOperation
|
||||
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
|
||||
};
|
||||
|
||||
/**
|
||||
* DNS record types for reporting DNS results
|
||||
*
|
||||
* These integer IDs (other than end of results) are the same as the DNS protocol's
|
||||
* internal IDs. Not all of these are used by ZeroTier, and not all DNS record types
|
||||
* are listed here. These are just common ones that are used now or may be used in
|
||||
* the future for some purpose.
|
||||
*/
|
||||
enum ZT_DNSRecordType
|
||||
{
|
||||
ZT_DNS_RECORD__END_OF_RESULTS = 0,
|
||||
ZT_DNS_RECORD_A = 1,
|
||||
ZT_DNS_RECORD_NS = 2,
|
||||
ZT_DNS_RECORD_CNAME = 5,
|
||||
ZT_DNS_RECORD_PTR = 12,
|
||||
ZT_DNS_RECORD_MX = 15,
|
||||
ZT_DNS_RECORD_TXT = 16,
|
||||
ZT_DNS_RECORD_AAAA = 28,
|
||||
ZT_DNS_RECORD_LOC = 29,
|
||||
ZT_DNS_RECORD_SRV = 33,
|
||||
ZT_DNS_RECORD_DNAME = 39
|
||||
};
|
||||
|
||||
/**
|
||||
* Virtual network configuration
|
||||
*/
|
||||
@ -1180,56 +983,6 @@ typedef struct
|
||||
*/
|
||||
uint64_t trustedPathId;
|
||||
|
||||
/**
|
||||
* One-way latency
|
||||
*/
|
||||
float latency;
|
||||
|
||||
/**
|
||||
* How much latency varies over time
|
||||
*/
|
||||
float packetDelayVariance;
|
||||
|
||||
/**
|
||||
* How much observed throughput varies over time
|
||||
*/
|
||||
float throughputDisturbCoeff;
|
||||
|
||||
/**
|
||||
* Packet Error Ratio (PER)
|
||||
*/
|
||||
float packetErrorRatio;
|
||||
|
||||
/**
|
||||
* Packet Loss Ratio (PLR)
|
||||
*/
|
||||
float packetLossRatio;
|
||||
|
||||
/**
|
||||
* Stability of the path
|
||||
*/
|
||||
float stability;
|
||||
|
||||
/**
|
||||
* Current throughput (moving average)
|
||||
*/
|
||||
uint64_t throughput;
|
||||
|
||||
/**
|
||||
* Maximum observed throughput for this path
|
||||
*/
|
||||
uint64_t maxThroughput;
|
||||
|
||||
/**
|
||||
* Percentage of traffic allocated to this path
|
||||
*/
|
||||
float allocation;
|
||||
|
||||
/**
|
||||
* Name of physical interface (for monitoring)
|
||||
*/
|
||||
char *ifname;
|
||||
|
||||
/**
|
||||
* Is path alive?
|
||||
*/
|
||||
@ -1241,6 +994,15 @@ typedef struct
|
||||
int preferred;
|
||||
} ZT_PeerPhysicalPath;
|
||||
|
||||
/**
|
||||
* What trust hierarchy role does this peer have?
|
||||
*/
|
||||
enum ZT_PeerRole
|
||||
{
|
||||
ZT_PEER_ROLE_LEAF = 0, // ordinary node
|
||||
ZT_PEER_ROLE_ROOT = 1 // root server
|
||||
};
|
||||
|
||||
/**
|
||||
* Peer status result buffer
|
||||
*/
|
||||
@ -1251,6 +1013,11 @@ typedef struct
|
||||
*/
|
||||
uint64_t address;
|
||||
|
||||
/**
|
||||
* Peer identity
|
||||
*/
|
||||
const ZT_Identity *identity;
|
||||
|
||||
/**
|
||||
* Remote major version or -1 if not known
|
||||
*/
|
||||
@ -1281,11 +1048,6 @@ typedef struct
|
||||
*/
|
||||
unsigned int pathCount;
|
||||
|
||||
/**
|
||||
* Whether this peer was ever reachable via an aggregate link
|
||||
*/
|
||||
int hadAggregateLink;
|
||||
|
||||
/**
|
||||
* Known network paths to peer
|
||||
*/
|
||||
@ -1541,8 +1303,9 @@ typedef int (*ZT_PathCheckFunction)(
|
||||
* (1) Node
|
||||
* (2) User pointer
|
||||
* (3) ZeroTier address (least significant 40 bits)
|
||||
* (4) Desired address family or -1 for any
|
||||
* (5) Buffer to fill with result
|
||||
* (4) Identity in string form
|
||||
* (5) Desired address family or -1 for any
|
||||
* (6) Buffer to fill with result
|
||||
*
|
||||
* If provided this function will be occasionally called to get physical
|
||||
* addresses that might be tried to reach a ZeroTier address. It must
|
||||
@ -1554,53 +1317,10 @@ typedef int (*ZT_PathLookupFunction)(
|
||||
void *, /* User ptr */
|
||||
void *, /* Thread ptr */
|
||||
uint64_t, /* ZeroTier address (40 bits) */
|
||||
const ZT_Identity *, /* Full identity of node */
|
||||
int, /* Desired ss_family or -1 for any */
|
||||
struct sockaddr_storage *); /* Result buffer */
|
||||
|
||||
/**
|
||||
* Function to request an asynchronous DNS TXT lookup
|
||||
*
|
||||
* Parameters:
|
||||
* (1) Node
|
||||
* (2) User pointer
|
||||
* (3) Thread pointer
|
||||
* (4) Array of DNS record types we want
|
||||
* (5) Number of DNS record types in array
|
||||
* (6) DNS name to fetch
|
||||
* (7) DNS request ID to supply to ZT_Node_processDNSResult()
|
||||
*
|
||||
* DNS is not handled in the core because every platform and runtime
|
||||
* typically has its own DNS functions or libraries and these may need
|
||||
* to interface with OS or network services in your local environment.
|
||||
* Instead this function and its result submission counterpart are
|
||||
* provided so you can provide a DNS implementation.
|
||||
*
|
||||
* If this callback is set in your callback struct to a NULL value,
|
||||
* DNS will not be available. The ZeroTier protocol is designed to
|
||||
* work in the absence of DNS but you may not get optimal results. For
|
||||
* example you may default to root servers that are not geographically
|
||||
* optimal or your node may cease to function if a root server's IP
|
||||
* changes and there's no way to signal this.
|
||||
*
|
||||
* This function requests resolution of a DNS record. The result
|
||||
* submission method ZT_Node_processDNSResult() must be called at
|
||||
* least once in response. See its documentation.
|
||||
*
|
||||
* Right now ZeroTier only requests resolution of TXT records, but
|
||||
* it's possible that this will change in the future.
|
||||
*
|
||||
* It's safe to call processDNSResult() from within your handler
|
||||
* for this function.
|
||||
*/
|
||||
typedef void (*ZT_DNSResolver)(
|
||||
ZT_Node *, /* Node */
|
||||
void *, /* User ptr */
|
||||
void *, /* Thread ptr */
|
||||
const enum ZT_DNSRecordType *, /* DNS record type(s) to fetch */
|
||||
unsigned int, /* Number of DNS record type(s) */
|
||||
const char *, /* DNS name to fetch */
|
||||
uintptr_t); /* Request ID for returning results */
|
||||
|
||||
/****************************************************************************/
|
||||
/* C Node API */
|
||||
/****************************************************************************/
|
||||
@ -1641,17 +1361,12 @@ struct ZT_Node_Callbacks
|
||||
ZT_EventCallback eventCallback;
|
||||
|
||||
/**
|
||||
* STRONGLY RECOMMENDED: Function to request a DNS lookup
|
||||
*/
|
||||
ZT_DNSResolver dnsResolver;
|
||||
|
||||
/**
|
||||
* OPTIONAL: Function to check whether a given physical path should be used
|
||||
* OPTIONAL: Function to check whether a given physical path should be used for ZeroTier traffic
|
||||
*/
|
||||
ZT_PathCheckFunction pathCheckFunction;
|
||||
|
||||
/**
|
||||
* OPTIONAL: Function to get hints to physical paths to ZeroTier addresses
|
||||
* RECOMMENDED: Function to look up paths to ZeroTier nodes
|
||||
*/
|
||||
ZT_PathLookupFunction pathLookupFunction;
|
||||
};
|
||||
@ -1750,60 +1465,6 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks(
|
||||
int64_t now,
|
||||
volatile int64_t *nextBackgroundTaskDeadline);
|
||||
|
||||
/**
|
||||
* Submit the result(s) of a requested DNS query
|
||||
*
|
||||
* This MUST be called at least once after the node requsts DNS resolution.
|
||||
* If there are no results or DNS is not implemented or available, just
|
||||
* send one ZT_DNS_RECORD__END_OF_RESULTS to signal that no results were
|
||||
* obtained.
|
||||
*
|
||||
* If result is non-NULL but resultLength is zero then result is assumed to
|
||||
* be a C string terminated by a zero. Passing an unterminated string with a
|
||||
* zero resultLength will result in a crash.
|
||||
*
|
||||
* The results of A and AAAA records can be returned as either strings or
|
||||
* binary IP address bytes (network byte order). If the result is a string,
|
||||
* resultLength must be 0 to signal that result is a C string. Otherwise for
|
||||
* A resultLength must be 4 and for AAAA it must be 16 if the result is
|
||||
* in binary format.
|
||||
*
|
||||
* The Node implementation makes an effort to ignore obviously invalid
|
||||
* submissions like an AAAA record in bianry form with length 25, but this
|
||||
* is not guaranteed. It's possible to crash your program by calling this
|
||||
* with garbage inputs.
|
||||
*
|
||||
* Results may be submitted in any order and order should not be assumed
|
||||
* to have any meaning.
|
||||
*
|
||||
* The ZT_DNS_RECORD__END_OF_RESULTS pseudo-response must be sent after all
|
||||
* results have been submitted. The result and resultLength paramters are
|
||||
* ignored for this type ID.
|
||||
*
|
||||
* It is safe to call this function from inside the DNS request callback,
|
||||
* such as to return a locally cached result or a result from some kind
|
||||
* of local database. It's also safe to call this function from threads
|
||||
* other than the one that received the DNS request.
|
||||
*
|
||||
* @param node Node instance that requested DNS resolution
|
||||
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
||||
* @param dnsRequestID Request ID supplied to DNS request callback
|
||||
* @param name DNS name
|
||||
* @param recordType Record type of this result
|
||||
* @param result Result (content depends on record type)
|
||||
* @param resultLength Length of result
|
||||
* @param resultIsString If non-zero, IP results for A and AAAA records are being given as C strings not binary IPs
|
||||
*/
|
||||
ZT_SDK_API void ZT_Node_processDNSResult(
|
||||
ZT_Node *node,
|
||||
void *tptr,
|
||||
uintptr_t dnsRequestID,
|
||||
const char *name,
|
||||
enum ZT_DNSRecordType recordType,
|
||||
const void *result,
|
||||
unsigned int resultLength,
|
||||
int resultIsString);
|
||||
|
||||
/**
|
||||
* Join a network
|
||||
*
|
||||
@ -1884,36 +1545,25 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,void *tpt
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
||||
|
||||
/**
|
||||
* List roots for this node
|
||||
* Add a root server (has no effect if already added)
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param now Current time
|
||||
* @return List of roots, use ZT_Node_freeQueryResult to free this when done
|
||||
* @param identity Identity of this root server in string format
|
||||
* @return OK (0) or error code if a fatal error condition has occurred
|
||||
*/
|
||||
ZT_SDK_API ZT_RootList *ZT_Node_listRoots(ZT_Node *node,int64_t now);
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_addRoot(ZT_Node *node,const char *identity);
|
||||
|
||||
/**
|
||||
* Add or update a root
|
||||
* Remove a root server
|
||||
*
|
||||
* The node will begin trying to resolve the DNS TXT record for
|
||||
* this root and possibly obtain it from other peers.
|
||||
* This removes this node's root designation but does not prevent this node
|
||||
* from communicating with it or close active paths to it.
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param name DNS name or simply the address in hex form for static roots
|
||||
* @param locator Binary-serialized locator of NULL if none
|
||||
* @param locatorSize Size of locator or 0 if none
|
||||
* @return OK (0) or error code
|
||||
* @param identity Identity in string format
|
||||
* @return OK (0) or error code if a fatal error condition has occurred
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_setRoot(ZT_Node *node,const char *name,const void *locator,unsigned int locatorSize);
|
||||
|
||||
/**
|
||||
* Remove a dynamic root
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param name DNS name of this dynamic root or the address in hex form for static roots
|
||||
* @return OK (0) or error code
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *name);
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *identity);
|
||||
|
||||
/**
|
||||
* Get this node's 40-bit ZeroTier address
|
||||
@ -2035,6 +1685,115 @@ ZT_SDK_API void ZT_Node_setController(ZT_Node *node,void *networkConfigMasterIns
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_setPhysicalPathConfiguration(ZT_Node *node,const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig);
|
||||
|
||||
/**
|
||||
* Generate a new identity
|
||||
*
|
||||
* Due to a small amount of proof of work this can be a time consuming and CPU
|
||||
* intensive operation. It takes less than a second on most desktop-class systems
|
||||
* but can take longer on e.g. phones.
|
||||
*
|
||||
* @param type Type of identity to generate
|
||||
* @return New identity or NULL on error
|
||||
*/
|
||||
ZT_SDK_API ZT_Identity *ZT_Identity_new(enum ZT_Identity_Type type);
|
||||
|
||||
/**
|
||||
* Create a new identity object from a string-serialized identity
|
||||
*
|
||||
* @param idStr Identity in string format
|
||||
* @return Identity object or NULL if the supplied identity string was not valid
|
||||
*/
|
||||
ZT_SDK_API ZT_Identity *ZT_Identity_fromString(const char *idStr);
|
||||
|
||||
/**
|
||||
* Validate this identity
|
||||
*
|
||||
* This can be slightly time consuming due to address derivation (work) checking.
|
||||
*
|
||||
* @return Non-zero if identity is valid
|
||||
*/
|
||||
ZT_SDK_API int ZT_Identity_validate(const ZT_Identity *id);
|
||||
|
||||
/**
|
||||
* Sign a data object with this identity
|
||||
*
|
||||
* The identity must have a private key or this will fail.
|
||||
*
|
||||
* @param id Identity to use to sign
|
||||
* @param data Data to sign
|
||||
* @param len Length of data
|
||||
* @param signature Buffer to store signature
|
||||
* @param signatureBufferLength Length of buffer (must be at least 96 bytes)
|
||||
* @return Length of signature in bytes or 0 on failure.
|
||||
*/
|
||||
ZT_SDK_API unsigned int ZT_Identity_sign(const ZT_Identity *id,const void *data,unsigned int len,void *signature,unsigned int signatureBufferLength);
|
||||
|
||||
/**
|
||||
* Verify a signature
|
||||
*
|
||||
* @param id Identity to use to verify
|
||||
* @param data Data to verify
|
||||
* @param len Length of data
|
||||
* @param signature Signature to check
|
||||
* @param sigLen Length of signature in bytes
|
||||
* @return Non-zero if signature is valid
|
||||
*/
|
||||
ZT_SDK_API int ZT_Identity_verify(const ZT_Identity *id,const void *data,unsigned int len,const void *signature,unsigned int sigLen);
|
||||
|
||||
/**
|
||||
* Get identity type
|
||||
*
|
||||
* @param id Identity to query
|
||||
* @return Identity type code
|
||||
*/
|
||||
ZT_SDK_API enum ZT_Identity_Type ZT_Identity_type(const ZT_Identity *id);
|
||||
|
||||
/**
|
||||
* Convert an identity to its string representation
|
||||
*
|
||||
* @param id Identity to convert
|
||||
* @param buf Buffer to store identity (should be at least about 1024 bytes in length)
|
||||
* @param capacity Capacity of buffer
|
||||
* @param includePrivate If true include the private key if present
|
||||
* @return Pointer to buf or NULL on overflow or other error
|
||||
*/
|
||||
ZT_SDK_API char *ZT_Identity_toString(const ZT_Identity *id,char *buf,int capacity,int includePrivate);
|
||||
|
||||
/**
|
||||
* Check whether this identity object also holds a private key
|
||||
*
|
||||
* @param id Identity to query
|
||||
* @return Non-zero if a private key is held
|
||||
*/
|
||||
ZT_SDK_API int ZT_Identity_hasPrivate(const ZT_Identity *id);
|
||||
|
||||
/**
|
||||
* Get the ZeroTier address associated with this identity
|
||||
*
|
||||
* @param id Identity to query
|
||||
* @return ZeroTier address (only least significant 40 bits are meaningful, rest will be 0)
|
||||
*/
|
||||
ZT_SDK_API uint64_t ZT_Identity_address(const ZT_Identity *id);
|
||||
|
||||
/**
|
||||
* Compute a hash of this identity's public keys (or both public and private if includePrivate is true)
|
||||
*
|
||||
* @param id Identity to query
|
||||
* @param h Buffer for 384-bit hash
|
||||
* @param includePrivate If true include private keys if any
|
||||
*/
|
||||
ZT_SDK_API void ZT_Identity_hash(const ZT_Identity *id,uint8_t h[48],int includePrivate);
|
||||
|
||||
/**
|
||||
* Delete an identity and free associated memory
|
||||
*
|
||||
* This should only be used with identities created via Identity_new
|
||||
* and Identity_fromString().
|
||||
*
|
||||
* @param id Identity to delete
|
||||
*/
|
||||
ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id);
|
||||
|
||||
/**
|
||||
* Get ZeroTier One version
|
||||
*
|
||||
|
168
node/AES-aesni.c
168
node/AES-aesni.c
@ -1,168 +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: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
/* This is done in plain C because the compiler (at least GCC and CLANG) seem
|
||||
* to do a *slightly* better job optimizing this intrinsic code when compiling
|
||||
* plain C. C also gives us the register hint keyword, which seems to actually
|
||||
* make a small difference. */
|
||||
|
||||
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
|
||||
|
||||
#include <stdint.h>
|
||||
#include <wmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#include <smmintrin.h>
|
||||
|
||||
#define ZT_AES_CTR_AESNI_ROUND(kk) c0 = _mm_aesenc_si128(c0,kk); c1 = _mm_aesenc_si128(c1,kk); c2 = _mm_aesenc_si128(c2,kk); c3 = _mm_aesenc_si128(c3,kk);
|
||||
|
||||
void zt_crypt_ctr_aesni(const __m128i key[14],const uint8_t iv[16],const uint8_t *in,unsigned int len,uint8_t *out)
|
||||
{
|
||||
/* Because our CTR supports full 128-bit nonces, we must do a full 128-bit (big-endian)
|
||||
* increment to be compatible with canonical NIST-certified CTR implementations. That's
|
||||
* because it's possible to have a lot of bit saturation in the least significant 64
|
||||
* bits, which could on rare occasions actually cause a 64-bit wrap. If this happened
|
||||
* without carry it would result in incompatibility and quietly dropped packets. The
|
||||
* probability is low, so this would be a one in billions packet loss bug that would
|
||||
* probably never be found.
|
||||
*
|
||||
* This crazy code does a branch-free 128-bit increment by adding a one or a zero to
|
||||
* the most significant 64 bits of the 128-bit vector based on whether the add we want
|
||||
* to do to the least significant 64 bits would overflow. This can be computed by
|
||||
* NOTing those bits and comparing with what we want to add, since NOT is the same
|
||||
* as subtracting from uint64_max. This generates branch-free ASM on x64 with most
|
||||
* good compilers. */
|
||||
register __m128i swap128 = _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
|
||||
register __m128i ctr0 = _mm_shuffle_epi8(_mm_loadu_si128((__m128i *)iv),swap128);
|
||||
register uint64_t notctr0msq = ~((uint64_t)_mm_extract_epi64(ctr0,0));
|
||||
register __m128i ctr1 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 1ULL),1LL)),swap128);
|
||||
register __m128i ctr2 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 2ULL),2LL)),swap128);
|
||||
register __m128i ctr3 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 3ULL),3LL)),swap128);
|
||||
ctr0 = _mm_shuffle_epi8(ctr0,swap128);
|
||||
|
||||
register __m128i k0 = key[0];
|
||||
register __m128i k1 = key[1];
|
||||
|
||||
while (len >= 64) {
|
||||
register __m128i ka = key[2];
|
||||
register __m128i c0 = _mm_xor_si128(ctr0,k0);
|
||||
register __m128i c1 = _mm_xor_si128(ctr1,k0);
|
||||
register __m128i c2 = _mm_xor_si128(ctr2,k0);
|
||||
register __m128i c3 = _mm_xor_si128(ctr3,k0);
|
||||
ctr0 = _mm_shuffle_epi8(ctr0,swap128);
|
||||
notctr0msq = ~((uint64_t)_mm_extract_epi64(ctr0,0));
|
||||
ctr1 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 5ULL),5LL)),swap128);
|
||||
ctr2 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 6ULL),6LL)),swap128);
|
||||
ctr3 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 7ULL),7LL)),swap128);
|
||||
ctr0 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 4ULL),4LL)),swap128);
|
||||
register __m128i kb = key[3];
|
||||
ZT_AES_CTR_AESNI_ROUND(k1);
|
||||
register __m128i kc = key[4];
|
||||
ZT_AES_CTR_AESNI_ROUND(ka);
|
||||
register __m128i kd = key[5];
|
||||
ZT_AES_CTR_AESNI_ROUND(kb);
|
||||
ka = key[6];
|
||||
ZT_AES_CTR_AESNI_ROUND(kc);
|
||||
kb = key[7];
|
||||
ZT_AES_CTR_AESNI_ROUND(kd);
|
||||
kc = key[8];
|
||||
ZT_AES_CTR_AESNI_ROUND(ka);
|
||||
kd = key[9];
|
||||
ZT_AES_CTR_AESNI_ROUND(kb);
|
||||
ka = key[10];
|
||||
ZT_AES_CTR_AESNI_ROUND(kc);
|
||||
kb = key[11];
|
||||
ZT_AES_CTR_AESNI_ROUND(kd);
|
||||
kc = key[12];
|
||||
ZT_AES_CTR_AESNI_ROUND(ka);
|
||||
kd = key[13];
|
||||
ZT_AES_CTR_AESNI_ROUND(kb);
|
||||
ka = key[14];
|
||||
ZT_AES_CTR_AESNI_ROUND(kc);
|
||||
ZT_AES_CTR_AESNI_ROUND(kd);
|
||||
_mm_storeu_si128((__m128i *)out,_mm_xor_si128(_mm_loadu_si128((const __m128i *)in),_mm_aesenclast_si128(c0,ka)));
|
||||
_mm_storeu_si128((__m128i *)(out + 16),_mm_xor_si128(_mm_loadu_si128((const __m128i *)(in + 16)),_mm_aesenclast_si128(c1,ka)));
|
||||
_mm_storeu_si128((__m128i *)(out + 32),_mm_xor_si128(_mm_loadu_si128((const __m128i *)(in + 32)),_mm_aesenclast_si128(c2,ka)));
|
||||
_mm_storeu_si128((__m128i *)(out + 48),_mm_xor_si128(_mm_loadu_si128((const __m128i *)(in + 48)),_mm_aesenclast_si128(c3,ka)));
|
||||
in += 64;
|
||||
out += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
register __m128i k2 = key[2];
|
||||
register __m128i k3 = key[3];
|
||||
register __m128i k4 = key[4];
|
||||
register __m128i k5 = key[5];
|
||||
register __m128i k6 = key[6];
|
||||
register __m128i k7 = key[7];
|
||||
|
||||
while (len >= 16) {
|
||||
register __m128i c0 = _mm_xor_si128(ctr0,k0);
|
||||
ctr0 = _mm_shuffle_epi8(ctr0,swap128);
|
||||
ctr0 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)((~((uint64_t)_mm_extract_epi64(ctr0,0))) < 1ULL),1LL)),swap128);
|
||||
c0 = _mm_aesenc_si128(c0,k1);
|
||||
c0 = _mm_aesenc_si128(c0,k2);
|
||||
c0 = _mm_aesenc_si128(c0,k3);
|
||||
c0 = _mm_aesenc_si128(c0,k4);
|
||||
c0 = _mm_aesenc_si128(c0,k5);
|
||||
c0 = _mm_aesenc_si128(c0,k6);
|
||||
register __m128i ka = key[8];
|
||||
c0 = _mm_aesenc_si128(c0,k7);
|
||||
register __m128i kb = key[9];
|
||||
c0 = _mm_aesenc_si128(c0,ka);
|
||||
ka = key[10];
|
||||
c0 = _mm_aesenc_si128(c0,kb);
|
||||
kb = key[11];
|
||||
c0 = _mm_aesenc_si128(c0,ka);
|
||||
ka = key[12];
|
||||
c0 = _mm_aesenc_si128(c0,kb);
|
||||
kb = key[13];
|
||||
c0 = _mm_aesenc_si128(c0,ka);
|
||||
ka = key[14];
|
||||
c0 = _mm_aesenc_si128(c0,kb);
|
||||
_mm_storeu_si128((__m128i *)out,_mm_xor_si128(_mm_loadu_si128((const __m128i *)in),_mm_aesenclast_si128(c0,ka)));
|
||||
in += 16;
|
||||
out += 16;
|
||||
len -= 16;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
register __m128i c0 = _mm_xor_si128(ctr0,k0);
|
||||
k0 = key[8];
|
||||
c0 = _mm_aesenc_si128(c0,k1);
|
||||
c0 = _mm_aesenc_si128(c0,k2);
|
||||
k1 = key[9];
|
||||
c0 = _mm_aesenc_si128(c0,k3);
|
||||
c0 = _mm_aesenc_si128(c0,k4);
|
||||
k2 = key[10];
|
||||
c0 = _mm_aesenc_si128(c0,k5);
|
||||
c0 = _mm_aesenc_si128(c0,k6);
|
||||
k3 = key[11];
|
||||
c0 = _mm_aesenc_si128(c0,k7);
|
||||
c0 = _mm_aesenc_si128(c0,k0);
|
||||
k0 = key[12];
|
||||
c0 = _mm_aesenc_si128(c0,k1);
|
||||
c0 = _mm_aesenc_si128(c0,k2);
|
||||
k1 = key[13];
|
||||
c0 = _mm_aesenc_si128(c0,k3);
|
||||
c0 = _mm_aesenc_si128(c0,k0);
|
||||
k2 = key[14];
|
||||
c0 = _mm_aesenc_si128(c0,k1);
|
||||
c0 = _mm_aesenclast_si128(c0,k2);
|
||||
uint8_t tmp[16];
|
||||
_mm_storeu_si128((__m128i *)tmp,c0);
|
||||
for(unsigned int i=0;i<len;++i)
|
||||
out[i] = in[i] ^ tmp[i];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
78
node/AES.cpp
78
node/AES.cpp
@ -11,12 +11,8 @@
|
||||
*/
|
||||
/****/
|
||||
|
||||
#include "AES.hpp"
|
||||
#include "Constants.hpp"
|
||||
|
||||
// This file contains the software implementations of AES and GHASH. They're
|
||||
// only used if your CPU lacks hardware acceleration as the hardware
|
||||
// accelerated code is 10-20X as fast in most cases.
|
||||
#include "AES.hpp"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <intrin.h>
|
||||
@ -25,7 +21,7 @@
|
||||
namespace ZeroTier {
|
||||
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
static ZT_ALWAYS_INLINE uint32_t readuint32_t(const void *in)
|
||||
static inline uint32_t readuint32_t(const void *in)
|
||||
{
|
||||
uint32_t v = ((const uint8_t *)in)[0];
|
||||
v <<= 8;
|
||||
@ -36,7 +32,7 @@ static ZT_ALWAYS_INLINE uint32_t readuint32_t(const void *in)
|
||||
v |= ((const uint8_t *)in)[3];
|
||||
return v;
|
||||
}
|
||||
static ZT_ALWAYS_INLINE void writeuint32_t(void *out,const uint32_t v)
|
||||
static inline void writeuint32_t(void *out,const uint32_t v)
|
||||
{
|
||||
((uint8_t *)out)[0] = (uint8_t)(v >> 24);
|
||||
((uint8_t *)out)[1] = (uint8_t)(v >> 16);
|
||||
@ -48,28 +44,6 @@ static ZT_ALWAYS_INLINE void writeuint32_t(void *out,const uint32_t v)
|
||||
#define writeuint32_t(o,v) (*((uint32_t *)(o)) = Utils::hton(v))
|
||||
#endif
|
||||
|
||||
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
|
||||
static bool _zt_aesni_supported()
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
int regs[4];
|
||||
__cpuid(regs,1);
|
||||
return ( (((regs[2] >> 25) & 1) != 0) && (((regs[2] >> 19) & 1) != 0) && (((regs[2] >> 1) & 1) != 0) ); // AES-NI, SSE4.1, PCLMUL
|
||||
#else
|
||||
uint32_t eax,ebx,ecx,edx;
|
||||
__asm__ __volatile__ (
|
||||
"cpuid"
|
||||
: "=a"(eax),"=b"(ebx),"=c"(ecx),"=d"(edx)
|
||||
: "a"(1),"c"(0)
|
||||
);
|
||||
return ( ((ecx & (1 << 25)) != 0) && ((ecx & (1 << 19)) != 0) && ((ecx & (1 << 1)) != 0) ); // AES-NI, SSE4.1, PCLMUL
|
||||
#endif
|
||||
}
|
||||
const bool AES::HW_ACCEL = _zt_aesni_supported();
|
||||
#else
|
||||
const bool AES::HW_ACCEL = false;
|
||||
#endif
|
||||
|
||||
const uint32_t AES::Te0[256] = { 0xc66363a5,0xf87c7c84,0xee777799,0xf67b7b8d,0xfff2f20d,0xd66b6bbd,0xde6f6fb1,0x91c5c554,0x60303050,0x02010103,0xce6767a9,0x562b2b7d,0xe7fefe19,0xb5d7d762,0x4dababe6,0xec76769a,0x8fcaca45,0x1f82829d,0x89c9c940,0xfa7d7d87,0xeffafa15,0xb25959eb,0x8e4747c9,0xfbf0f00b,0x41adadec,0xb3d4d467,0x5fa2a2fd,0x45afafea,0x239c9cbf,0x53a4a4f7,0xe4727296,0x9bc0c05b,0x75b7b7c2,0xe1fdfd1c,0x3d9393ae,0x4c26266a,0x6c36365a,0x7e3f3f41,0xf5f7f702,0x83cccc4f,0x6834345c,0x51a5a5f4,0xd1e5e534,0xf9f1f108,0xe2717193,0xabd8d873,0x62313153,0x2a15153f,0x0804040c,0x95c7c752,0x46232365,0x9dc3c35e,0x30181828,0x379696a1,0x0a05050f,0x2f9a9ab5,0x0e070709,0x24121236,0x1b80809b,0xdfe2e23d,0xcdebeb26,0x4e272769,0x7fb2b2cd,0xea75759f,0x1209091b,0x1d83839e,0x582c2c74,0x341a1a2e,0x361b1b2d,0xdc6e6eb2,0xb45a5aee,0x5ba0a0fb,0xa45252f6,0x763b3b4d,0xb7d6d661,0x7db3b3ce,0x5229297b,0xdde3e33e,0x5e2f2f71,0x13848497,0xa65353f5,0xb9d1d168,0x00000000,0xc1eded2c,0x40202060,0xe3fcfc1f,0x79b1b1c8,0xb65b5bed,0xd46a6abe,0x8dcbcb46,0x67bebed9,0x7239394b,0x944a4ade,0x984c4cd4,0xb05858e8,0x85cfcf4a,0xbbd0d06b,0xc5efef2a,0x4faaaae5,0xedfbfb16,0x864343c5,0x9a4d4dd7,0x66333355,0x11858594,0x8a4545cf,0xe9f9f910,0x04020206,0xfe7f7f81,0xa05050f0,0x783c3c44,0x259f9fba,0x4ba8a8e3,0xa25151f3,0x5da3a3fe,0x804040c0,0x058f8f8a,0x3f9292ad,0x219d9dbc,0x70383848,0xf1f5f504,0x63bcbcdf,0x77b6b6c1,0xafdada75,0x42212163,0x20101030,0xe5ffff1a,0xfdf3f30e,0xbfd2d26d,0x81cdcd4c,0x180c0c14,0x26131335,0xc3ecec2f,0xbe5f5fe1,0x359797a2,0x884444cc,0x2e171739,0x93c4c457,0x55a7a7f2,0xfc7e7e82,0x7a3d3d47,0xc86464ac,0xba5d5de7,0x3219192b,0xe6737395,0xc06060a0,0x19818198,0x9e4f4fd1,0xa3dcdc7f,0x44222266,0x542a2a7e,0x3b9090ab,0x0b888883,0x8c4646ca,0xc7eeee29,0x6bb8b8d3,0x2814143c,0xa7dede79,0xbc5e5ee2,0x160b0b1d,0xaddbdb76,0xdbe0e03b,0x64323256,0x743a3a4e,0x140a0a1e,0x924949db,0x0c06060a,0x4824246c,0xb85c5ce4,0x9fc2c25d,0xbdd3d36e,0x43acacef,0xc46262a6,0x399191a8,0x319595a4,0xd3e4e437,0xf279798b,0xd5e7e732,0x8bc8c843,0x6e373759,0xda6d6db7,0x018d8d8c,0xb1d5d564,0x9c4e4ed2,0x49a9a9e0,0xd86c6cb4,0xac5656fa,0xf3f4f407,0xcfeaea25,0xca6565af,0xf47a7a8e,0x47aeaee9,0x10080818,0x6fbabad5,0xf0787888,0x4a25256f,0x5c2e2e72,0x381c1c24,0x57a6a6f1,0x73b4b4c7,0x97c6c651,0xcbe8e823,0xa1dddd7c,0xe874749c,0x3e1f1f21,0x964b4bdd,0x61bdbddc,0x0d8b8b86,0x0f8a8a85,0xe0707090,0x7c3e3e42,0x71b5b5c4,0xcc6666aa,0x904848d8,0x06030305,0xf7f6f601,0x1c0e0e12,0xc26161a3,0x6a35355f,0xae5757f9,0x69b9b9d0,0x17868691,0x99c1c158,0x3a1d1d27,0x279e9eb9,0xd9e1e138,0xebf8f813,0x2b9898b3,0x22111133,0xd26969bb,0xa9d9d970,0x078e8e89,0x339494a7,0x2d9b9bb6,0x3c1e1e22,0x15878792,0xc9e9e920,0x87cece49,0xaa5555ff,0x50282878,0xa5dfdf7a,0x038c8c8f,0x59a1a1f8,0x09898980,0x1a0d0d17,0x65bfbfda,0xd7e6e631,0x844242c6,0xd06868b8,0x824141c3,0x299999b0,0x5a2d2d77,0x1e0f0f11,0x7bb0b0cb,0xa85454fc,0x6dbbbbd6,0x2c16163a };
|
||||
const uint32_t AES::Te1[256] = { 0xa5c66363,0x84f87c7c,0x99ee7777,0x8df67b7b,0x0dfff2f2,0xbdd66b6b,0xb1de6f6f,0x5491c5c5,0x50603030,0x03020101,0xa9ce6767,0x7d562b2b,0x19e7fefe,0x62b5d7d7,0xe64dabab,0x9aec7676,0x458fcaca,0x9d1f8282,0x4089c9c9,0x87fa7d7d,0x15effafa,0xebb25959,0xc98e4747,0x0bfbf0f0,0xec41adad,0x67b3d4d4,0xfd5fa2a2,0xea45afaf,0xbf239c9c,0xf753a4a4,0x96e47272,0x5b9bc0c0,0xc275b7b7,0x1ce1fdfd,0xae3d9393,0x6a4c2626,0x5a6c3636,0x417e3f3f,0x02f5f7f7,0x4f83cccc,0x5c683434,0xf451a5a5,0x34d1e5e5,0x08f9f1f1,0x93e27171,0x73abd8d8,0x53623131,0x3f2a1515,0x0c080404,0x5295c7c7,0x65462323,0x5e9dc3c3,0x28301818,0xa1379696,0x0f0a0505,0xb52f9a9a,0x090e0707,0x36241212,0x9b1b8080,0x3ddfe2e2,0x26cdebeb,0x694e2727,0xcd7fb2b2,0x9fea7575,0x1b120909,0x9e1d8383,0x74582c2c,0x2e341a1a,0x2d361b1b,0xb2dc6e6e,0xeeb45a5a,0xfb5ba0a0,0xf6a45252,0x4d763b3b,0x61b7d6d6,0xce7db3b3,0x7b522929,0x3edde3e3,0x715e2f2f,0x97138484,0xf5a65353,0x68b9d1d1,0x00000000,0x2cc1eded,0x60402020,0x1fe3fcfc,0xc879b1b1,0xedb65b5b,0xbed46a6a,0x468dcbcb,0xd967bebe,0x4b723939,0xde944a4a,0xd4984c4c,0xe8b05858,0x4a85cfcf,0x6bbbd0d0,0x2ac5efef,0xe54faaaa,0x16edfbfb,0xc5864343,0xd79a4d4d,0x55663333,0x94118585,0xcf8a4545,0x10e9f9f9,0x06040202,0x81fe7f7f,0xf0a05050,0x44783c3c,0xba259f9f,0xe34ba8a8,0xf3a25151,0xfe5da3a3,0xc0804040,0x8a058f8f,0xad3f9292,0xbc219d9d,0x48703838,0x04f1f5f5,0xdf63bcbc,0xc177b6b6,0x75afdada,0x63422121,0x30201010,0x1ae5ffff,0x0efdf3f3,0x6dbfd2d2,0x4c81cdcd,0x14180c0c,0x35261313,0x2fc3ecec,0xe1be5f5f,0xa2359797,0xcc884444,0x392e1717,0x5793c4c4,0xf255a7a7,0x82fc7e7e,0x477a3d3d,0xacc86464,0xe7ba5d5d,0x2b321919,0x95e67373,0xa0c06060,0x98198181,0xd19e4f4f,0x7fa3dcdc,0x66442222,0x7e542a2a,0xab3b9090,0x830b8888,0xca8c4646,0x29c7eeee,0xd36bb8b8,0x3c281414,0x79a7dede,0xe2bc5e5e,0x1d160b0b,0x76addbdb,0x3bdbe0e0,0x56643232,0x4e743a3a,0x1e140a0a,0xdb924949,0x0a0c0606,0x6c482424,0xe4b85c5c,0x5d9fc2c2,0x6ebdd3d3,0xef43acac,0xa6c46262,0xa8399191,0xa4319595,0x37d3e4e4,0x8bf27979,0x32d5e7e7,0x438bc8c8,0x596e3737,0xb7da6d6d,0x8c018d8d,0x64b1d5d5,0xd29c4e4e,0xe049a9a9,0xb4d86c6c,0xfaac5656,0x07f3f4f4,0x25cfeaea,0xafca6565,0x8ef47a7a,0xe947aeae,0x18100808,0xd56fbaba,0x88f07878,0x6f4a2525,0x725c2e2e,0x24381c1c,0xf157a6a6,0xc773b4b4,0x5197c6c6,0x23cbe8e8,0x7ca1dddd,0x9ce87474,0x213e1f1f,0xdd964b4b,0xdc61bdbd,0x860d8b8b,0x850f8a8a,0x90e07070,0x427c3e3e,0xc471b5b5,0xaacc6666,0xd8904848,0x05060303,0x01f7f6f6,0x121c0e0e,0xa3c26161,0x5f6a3535,0xf9ae5757,0xd069b9b9,0x91178686,0x5899c1c1,0x273a1d1d,0xb9279e9e,0x38d9e1e1,0x13ebf8f8,0xb32b9898,0x33221111,0xbbd26969,0x70a9d9d9,0x89078e8e,0xa7339494,0xb62d9b9b,0x223c1e1e,0x92158787,0x20c9e9e9,0x4987cece,0xffaa5555,0x78502828,0x7aa5dfdf,0x8f038c8c,0xf859a1a1,0x80098989,0x171a0d0d,0xda65bfbf,0x31d7e6e6,0xc6844242,0xb8d06868,0xc3824141,0xb0299999,0x775a2d2d,0x111e0f0f,0xcb7bb0b0,0xfca85454,0xd66dbbbb,0x3a2c1616 };
|
||||
const uint32_t AES::Te2[256] = { 0x63a5c663,0x7c84f87c,0x7799ee77,0x7b8df67b,0xf20dfff2,0x6bbdd66b,0x6fb1de6f,0xc55491c5,0x30506030,0x01030201,0x67a9ce67,0x2b7d562b,0xfe19e7fe,0xd762b5d7,0xabe64dab,0x769aec76,0xca458fca,0x829d1f82,0xc94089c9,0x7d87fa7d,0xfa15effa,0x59ebb259,0x47c98e47,0xf00bfbf0,0xadec41ad,0xd467b3d4,0xa2fd5fa2,0xafea45af,0x9cbf239c,0xa4f753a4,0x7296e472,0xc05b9bc0,0xb7c275b7,0xfd1ce1fd,0x93ae3d93,0x266a4c26,0x365a6c36,0x3f417e3f,0xf702f5f7,0xcc4f83cc,0x345c6834,0xa5f451a5,0xe534d1e5,0xf108f9f1,0x7193e271,0xd873abd8,0x31536231,0x153f2a15,0x040c0804,0xc75295c7,0x23654623,0xc35e9dc3,0x18283018,0x96a13796,0x050f0a05,0x9ab52f9a,0x07090e07,0x12362412,0x809b1b80,0xe23ddfe2,0xeb26cdeb,0x27694e27,0xb2cd7fb2,0x759fea75,0x091b1209,0x839e1d83,0x2c74582c,0x1a2e341a,0x1b2d361b,0x6eb2dc6e,0x5aeeb45a,0xa0fb5ba0,0x52f6a452,0x3b4d763b,0xd661b7d6,0xb3ce7db3,0x297b5229,0xe33edde3,0x2f715e2f,0x84971384,0x53f5a653,0xd168b9d1,0x00000000,0xed2cc1ed,0x20604020,0xfc1fe3fc,0xb1c879b1,0x5bedb65b,0x6abed46a,0xcb468dcb,0xbed967be,0x394b7239,0x4ade944a,0x4cd4984c,0x58e8b058,0xcf4a85cf,0xd06bbbd0,0xef2ac5ef,0xaae54faa,0xfb16edfb,0x43c58643,0x4dd79a4d,0x33556633,0x85941185,0x45cf8a45,0xf910e9f9,0x02060402,0x7f81fe7f,0x50f0a050,0x3c44783c,0x9fba259f,0xa8e34ba8,0x51f3a251,0xa3fe5da3,0x40c08040,0x8f8a058f,0x92ad3f92,0x9dbc219d,0x38487038,0xf504f1f5,0xbcdf63bc,0xb6c177b6,0xda75afda,0x21634221,0x10302010,0xff1ae5ff,0xf30efdf3,0xd26dbfd2,0xcd4c81cd,0x0c14180c,0x13352613,0xec2fc3ec,0x5fe1be5f,0x97a23597,0x44cc8844,0x17392e17,0xc45793c4,0xa7f255a7,0x7e82fc7e,0x3d477a3d,0x64acc864,0x5de7ba5d,0x192b3219,0x7395e673,0x60a0c060,0x81981981,0x4fd19e4f,0xdc7fa3dc,0x22664422,0x2a7e542a,0x90ab3b90,0x88830b88,0x46ca8c46,0xee29c7ee,0xb8d36bb8,0x143c2814,0xde79a7de,0x5ee2bc5e,0x0b1d160b,0xdb76addb,0xe03bdbe0,0x32566432,0x3a4e743a,0x0a1e140a,0x49db9249,0x060a0c06,0x246c4824,0x5ce4b85c,0xc25d9fc2,0xd36ebdd3,0xacef43ac,0x62a6c462,0x91a83991,0x95a43195,0xe437d3e4,0x798bf279,0xe732d5e7,0xc8438bc8,0x37596e37,0x6db7da6d,0x8d8c018d,0xd564b1d5,0x4ed29c4e,0xa9e049a9,0x6cb4d86c,0x56faac56,0xf407f3f4,0xea25cfea,0x65afca65,0x7a8ef47a,0xaee947ae,0x08181008,0xbad56fba,0x7888f078,0x256f4a25,0x2e725c2e,0x1c24381c,0xa6f157a6,0xb4c773b4,0xc65197c6,0xe823cbe8,0xdd7ca1dd,0x749ce874,0x1f213e1f,0x4bdd964b,0xbddc61bd,0x8b860d8b,0x8a850f8a,0x7090e070,0x3e427c3e,0xb5c471b5,0x66aacc66,0x48d89048,0x03050603,0xf601f7f6,0x0e121c0e,0x61a3c261,0x355f6a35,0x57f9ae57,0xb9d069b9,0x86911786,0xc15899c1,0x1d273a1d,0x9eb9279e,0xe138d9e1,0xf813ebf8,0x98b32b98,0x11332211,0x69bbd269,0xd970a9d9,0x8e89078e,0x94a73394,0x9bb62d9b,0x1e223c1e,0x87921587,0xe920c9e9,0xce4987ce,0x55ffaa55,0x28785028,0xdf7aa5df,0x8c8f038c,0xa1f859a1,0x89800989,0x0d171a0d,0xbfda65bf,0xe631d7e6,0x42c68442,0x68b8d068,0x41c38241,0x99b02999,0x2d775a2d,0x0f111e0f,0xb0cb7bb0,0x54fca854,0xbbd66dbb,0x163a2c16 };
|
||||
@ -175,6 +149,39 @@ void AES::_encryptSW(const uint8_t in[16],uint8_t out[16]) const
|
||||
writeuint32_t(out + 12,(Te2[(t3 >> 24)] & 0xff000000) ^ (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t2) & 0xff] & 0x000000ff) ^ rk[59]);
|
||||
}
|
||||
|
||||
void AES::_ctrSW(const uint8_t iv[16],const void *in,unsigned int len,void *out) const
|
||||
{
|
||||
uint64_t ctr[2],cenc[2];
|
||||
memcpy(ctr,iv,16);
|
||||
uint64_t bctr = Utils::ntoh(ctr[1]);
|
||||
|
||||
const uint8_t *i = (const uint8_t *)in;
|
||||
uint8_t *o = (uint8_t *)out;
|
||||
|
||||
while (len >= 16) {
|
||||
_encryptSW((const uint8_t *)ctr,(uint8_t *)cenc);
|
||||
ctr[1] = Utils::hton(++bctr);
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
for(unsigned int k=0;k<16;++k)
|
||||
*(o++) = *(i++) ^ ((uint8_t *)cenc)[k];
|
||||
#else
|
||||
*((uint64_t *)o) = *((const uint64_t *)i) ^ cenc[0];
|
||||
o += 8;
|
||||
i += 8;
|
||||
*((uint64_t *)o) = *((const uint64_t *)i) ^ cenc[1];
|
||||
o += 8;
|
||||
i += 8;
|
||||
#endif
|
||||
len -= 16;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
_encryptSW((const uint8_t *)ctr,(uint8_t *)cenc);
|
||||
for(unsigned int k=0;k<len;++k)
|
||||
*(o++) = *(i++) ^ ((uint8_t *)cenc)[k];
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined(__GNUC__) || defined(__clang)) && (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64) || defined(__aarch64__))
|
||||
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
@ -183,7 +190,7 @@ typedef unsigned __int128 uint128_t;
|
||||
typedef unsigned uint128_t __attribute__((mode(TI)));
|
||||
#endif
|
||||
|
||||
static ZT_ALWAYS_INLINE void s_bmul64(const uint64_t x,const uint64_t y,uint64_t &r_high,uint64_t &r_low)
|
||||
static inline void s_bmul64(const uint64_t x,const uint64_t y,uint64_t &r_high,uint64_t &r_low)
|
||||
{
|
||||
static uint128_t m1 = (uint128_t)0x2108421084210842ULL << 64 | 0x1084210842108421ULL;
|
||||
static uint128_t m2 = (uint128_t)0x4210842108421084ULL << 64 | 0x2108421084210842ULL;
|
||||
@ -214,7 +221,7 @@ static ZT_ALWAYS_INLINE void s_bmul64(const uint64_t x,const uint64_t y,uint64_t
|
||||
r_low = (uint64_t)r;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void s_gfmul(const uint64_t h_high,const uint64_t h_low,uint64_t &y0, uint64_t &y1)
|
||||
static inline void s_gfmul(const uint64_t h_high,const uint64_t h_low,uint64_t &y0, uint64_t &y1)
|
||||
{
|
||||
uint64_t z2_low,z2_high,z0_low,z0_high,z1a_low,z1a_high;
|
||||
uint64_t y_high = Utils::ntoh(y0);
|
||||
@ -236,7 +243,7 @@ static ZT_ALWAYS_INLINE void s_gfmul(const uint64_t h_high,const uint64_t h_low,
|
||||
|
||||
#else
|
||||
|
||||
static ZT_ALWAYS_INLINE void s_bmul32(uint32_t x,uint32_t y,uint32_t &r_high,uint32_t &r_low)
|
||||
static inline void s_bmul32(uint32_t x,uint32_t y,uint32_t &r_high,uint32_t &r_low)
|
||||
{
|
||||
const uint32_t m1 = (uint32_t)0x11111111;
|
||||
const uint32_t m2 = (uint32_t)0x22222222;
|
||||
@ -263,7 +270,7 @@ static ZT_ALWAYS_INLINE void s_bmul32(uint32_t x,uint32_t y,uint32_t &r_high,uin
|
||||
r_low = (uint32_t)z;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void s_gfmul(const uint64_t h_high,const uint64_t h_low,uint64_t &y0,uint64_t &y1)
|
||||
static inline void s_gfmul(const uint64_t h_high,const uint64_t h_low,uint64_t &y0,uint64_t &y1)
|
||||
{
|
||||
uint32_t h_high_h = (uint32_t)(h_high >> 32);
|
||||
uint32_t h_high_l = (uint32_t)h_high;
|
||||
@ -337,9 +344,8 @@ void AES::_gmacSW(const uint8_t iv[12],const uint8_t *in,unsigned int len,uint8_
|
||||
for(unsigned int i=0;i<8;++i) ((uint8_t *)&y1)[i] ^= *(in++);
|
||||
#else
|
||||
y0 ^= *((const uint64_t *)in);
|
||||
in += 8;
|
||||
y1 ^= *((const uint64_t *)in);
|
||||
in += 8;
|
||||
y1 ^= *((const uint64_t *)(in + 8));
|
||||
in += 16;
|
||||
#endif
|
||||
s_gfmul(h0,h1,y0,y1);
|
||||
len -= 16;
|
||||
|
218
node/AES.hpp
218
node/AES.hpp
@ -18,35 +18,24 @@
|
||||
#include "Utils.hpp"
|
||||
#include "SHA512.hpp"
|
||||
|
||||
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
|
||||
#include <cstdint>
|
||||
|
||||
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
|
||||
#include <xmmintrin.h>
|
||||
#include <wmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#include <smmintrin.h>
|
||||
|
||||
#define ZT_AES_AESNI 1
|
||||
|
||||
// AES-aesni.c
|
||||
extern "C" void zt_crypt_ctr_aesni(const __m128i key[14],const uint8_t iv[16],const uint8_t *in,unsigned int len,uint8_t *out);
|
||||
|
||||
#endif // x64
|
||||
|
||||
#define ZT_AES_KEY_SIZE 32
|
||||
#define ZT_AES_BLOCK_SIZE 16
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* AES-256 and pals
|
||||
* AES-256 and pals including GMAC, CTR, etc.
|
||||
*/
|
||||
class AES
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This will be true if your platform's type of AES acceleration is supported on this machine
|
||||
*/
|
||||
static const bool HW_ACCEL;
|
||||
|
||||
ZT_ALWAYS_INLINE AES() {}
|
||||
ZT_ALWAYS_INLINE AES(const uint8_t key[32]) { this->init(key); }
|
||||
ZT_ALWAYS_INLINE ~AES() { Utils::burn(&_k,sizeof(_k)); }
|
||||
@ -57,12 +46,11 @@ public:
|
||||
ZT_ALWAYS_INLINE void init(const uint8_t key[32])
|
||||
{
|
||||
#ifdef ZT_AES_AESNI
|
||||
if (likely(HW_ACCEL)) {
|
||||
if (likely(Utils::CPUID.aes)) {
|
||||
_init_aesni(key);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
_initSW(key);
|
||||
}
|
||||
|
||||
@ -75,12 +63,11 @@ public:
|
||||
ZT_ALWAYS_INLINE void encrypt(const uint8_t in[16],uint8_t out[16]) const
|
||||
{
|
||||
#ifdef ZT_AES_AESNI
|
||||
if (likely(HW_ACCEL)) {
|
||||
if (likely(Utils::CPUID.aes)) {
|
||||
_encrypt_aesni(in,out);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
_encryptSW(in,out);
|
||||
}
|
||||
|
||||
@ -95,12 +82,11 @@ public:
|
||||
ZT_ALWAYS_INLINE void gmac(const uint8_t iv[12],const void *in,const unsigned int len,uint8_t out[16]) const
|
||||
{
|
||||
#ifdef ZT_AES_AESNI
|
||||
if (likely(HW_ACCEL)) {
|
||||
if (likely(Utils::CPUID.aes)) {
|
||||
_gmac_aesni(iv,(const uint8_t *)in,len,out);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
_gmacSW(iv,(const uint8_t *)in,len,out);
|
||||
}
|
||||
|
||||
@ -119,41 +105,12 @@ public:
|
||||
ZT_ALWAYS_INLINE void ctr(const uint8_t iv[16],const void *in,unsigned int len,void *out) const
|
||||
{
|
||||
#ifdef ZT_AES_AESNI
|
||||
if (likely(HW_ACCEL)) {
|
||||
zt_crypt_ctr_aesni(_k.ni.k,iv,(const uint8_t *)in,len,(uint8_t *)out);
|
||||
if (likely(Utils::CPUID.aes)) {
|
||||
_ctr_aesni(_k.ni.k,iv,(const uint8_t *)in,len,(uint8_t *)out);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t ctr[2],cenc[2];
|
||||
memcpy(ctr,iv,16);
|
||||
uint64_t bctr = Utils::ntoh(ctr[1]);
|
||||
|
||||
const uint8_t *i = (const uint8_t *)in;
|
||||
uint8_t *o = (uint8_t *)out;
|
||||
|
||||
while (len >= 16) {
|
||||
_encryptSW((const uint8_t *)ctr,(uint8_t *)cenc);
|
||||
ctr[1] = Utils::hton(++bctr);
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
for(unsigned int k=0;k<16;++k)
|
||||
*(o++) = *(i++) ^ ((uint8_t *)cenc)[k];
|
||||
#else
|
||||
*((uint64_t *)o) = *((const uint64_t *)i) ^ cenc[0];
|
||||
o += 8;
|
||||
i += 8;
|
||||
*((uint64_t *)o) = *((const uint64_t *)i) ^ cenc[1];
|
||||
o += 8;
|
||||
i += 8;
|
||||
#endif
|
||||
len -= 16;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
_encryptSW((const uint8_t *)ctr,(uint8_t *)cenc);
|
||||
for(unsigned int k=0;k<len;++k)
|
||||
*(o++) = *(i++) ^ ((uint8_t *)cenc)[k];
|
||||
}
|
||||
_ctrSW(iv,in,len,out);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,7 +144,7 @@ public:
|
||||
* @param out Output buffer to receive ciphertext
|
||||
* @param tag Output buffer to receive 64-bit authentication tag
|
||||
*/
|
||||
static ZT_ALWAYS_INLINE void gmacSivEncrypt(const AES &k1,const AES &k2,const AES &k3,const AES &k4,const uint8_t iv[8],const uint8_t pc,const void *in,const unsigned int len,void *out,uint8_t tag[8])
|
||||
static inline void gmacSivEncrypt(const AES &k1,const AES &k2,const AES &k3,const AES &k4,const uint8_t iv[8],const uint8_t pc,const void *in,const unsigned int len,void *out,uint8_t tag[8])
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
uint8_t __attribute__ ((aligned (16))) miv[12];
|
||||
@ -246,7 +203,7 @@ public:
|
||||
* @param tag Authentication tag supplied with message
|
||||
* @return True if authentication tags match and message appears authentic
|
||||
*/
|
||||
static ZT_ALWAYS_INLINE bool gmacSivDecrypt(const AES &k1,const AES &k2,const AES &k3,const AES &k4,const uint8_t iv[8],const uint8_t pc,const void *in,const unsigned int len,void *out,const uint8_t tag[8])
|
||||
static inline bool gmacSivDecrypt(const AES &k1,const AES &k2,const AES &k3,const AES &k4,const uint8_t iv[8],const uint8_t pc,const void *in,const unsigned int len,void *out,const uint8_t tag[8])
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
uint8_t __attribute__ ((aligned (16))) miv[12];
|
||||
@ -307,7 +264,7 @@ public:
|
||||
* @param k3 CTR IV keyed hash key
|
||||
* @param k4 AES-CTR key
|
||||
*/
|
||||
static ZT_ALWAYS_INLINE void initGmacCtrKeys(const uint8_t masterKey[32],AES &k1,AES &k2,AES &k3,AES &k4)
|
||||
static inline void initGmacCtrKeys(const uint8_t masterKey[32],AES &k1,AES &k2,AES &k3,AES &k4)
|
||||
{
|
||||
uint8_t k[32];
|
||||
KBKDFHMACSHA384(masterKey,ZT_PROTO_KBKDF_LABEL_KEY_USE_AES_GMAC_SIV_K1,0,0,k);
|
||||
@ -329,6 +286,7 @@ private:
|
||||
|
||||
void _initSW(const uint8_t key[32]);
|
||||
void _encryptSW(const uint8_t in[16],uint8_t out[16]) const;
|
||||
void _ctrSW(const uint8_t iv[16],const void *in,unsigned int len,void *out) const;
|
||||
void _gmacSW(const uint8_t iv[12],const uint8_t *in,unsigned int len,uint8_t out[16]) const;
|
||||
|
||||
/**************************************************************************/
|
||||
@ -529,7 +487,7 @@ private:
|
||||
_mm_storeu_si128((__m128i *)out,_mm_aesenclast_si128(tmp,_k.ni.k[14]));
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE __m128i _mult_block_aesni(__m128i shuf,__m128i h,__m128i y)
|
||||
static ZT_ALWAYS_INLINE inline __m128i _mult_block_aesni(__m128i shuf,__m128i h,__m128i y)
|
||||
{
|
||||
y = _mm_shuffle_epi8(y,shuf);
|
||||
__m128i t1 = _mm_clmulepi64_si128(h,y,0x00);
|
||||
@ -569,7 +527,7 @@ private:
|
||||
t4 = _mm_xor_si128(t4,t5);
|
||||
return _mm_shuffle_epi8(t4,shuf);
|
||||
}
|
||||
static ZT_ALWAYS_INLINE __m128i _ghash_aesni(__m128i shuf,__m128i h,__m128i y,__m128i x) { return _mult_block_aesni(shuf,h,_mm_xor_si128(y,x)); }
|
||||
static inline __m128i _ghash_aesni(__m128i shuf,__m128i h,__m128i y,__m128i x) { return _mult_block_aesni(shuf,h,_mm_xor_si128(y,x)); }
|
||||
|
||||
ZT_ALWAYS_INLINE void _gmac_aesni(const uint8_t iv[12],const uint8_t *in,const unsigned int len,uint8_t out[16]) const
|
||||
{
|
||||
@ -687,6 +645,148 @@ private:
|
||||
t = _mm_aesenclast_si128(t,_k.ni.k[14]);
|
||||
_mm_storeu_si128((__m128i *)out,_mm_xor_si128(y,t));
|
||||
}
|
||||
|
||||
#define ZT_AES_CTR_AESNI_ROUND(kk) c0 = _mm_aesenc_si128(c0,kk); c1 = _mm_aesenc_si128(c1,kk); c2 = _mm_aesenc_si128(c2,kk); c3 = _mm_aesenc_si128(c3,kk);
|
||||
|
||||
static ZT_ALWAYS_INLINE void _ctr_aesni(const __m128i key[14],const uint8_t iv[16],const uint8_t *in,unsigned int len,uint8_t *out)
|
||||
{
|
||||
/* Because our CTR supports full 128-bit nonces, we must do a full 128-bit (big-endian)
|
||||
* increment to be compatible with canonical NIST-certified CTR implementations. That's
|
||||
* because it's possible to have a lot of bit saturation in the least significant 64
|
||||
* bits, which could on rare occasions actually cause a 64-bit wrap. If this happened
|
||||
* without carry it would result in incompatibility and quietly dropped packets. The
|
||||
* probability is low, so this would be a one in billions packet loss bug that would
|
||||
* probably never be found.
|
||||
*
|
||||
* This crazy code does a branch-free 128-bit increment by adding a one or a zero to
|
||||
* the most significant 64 bits of the 128-bit vector based on whether the add we want
|
||||
* to do to the least significant 64 bits would overflow. This can be computed by
|
||||
* NOTing those bits and comparing with what we want to add, since NOT is the same
|
||||
* as subtracting from uint64_max. This generates branch-free ASM on x64 with most
|
||||
* good compilers. */
|
||||
__m128i swap128 = _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
|
||||
__m128i ctr0 = _mm_shuffle_epi8(_mm_loadu_si128((__m128i *)iv),swap128);
|
||||
uint64_t notctr0msq = ~((uint64_t)_mm_extract_epi64(ctr0,0));
|
||||
__m128i ctr1 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 1ULL),1LL)),swap128);
|
||||
__m128i ctr2 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 2ULL),2LL)),swap128);
|
||||
__m128i ctr3 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 3ULL),3LL)),swap128);
|
||||
ctr0 = _mm_shuffle_epi8(ctr0,swap128);
|
||||
|
||||
__m128i k0 = key[0];
|
||||
__m128i k1 = key[1];
|
||||
|
||||
while (len >= 64) {
|
||||
__m128i ka = key[2];
|
||||
__m128i c0 = _mm_xor_si128(ctr0,k0);
|
||||
__m128i c1 = _mm_xor_si128(ctr1,k0);
|
||||
__m128i c2 = _mm_xor_si128(ctr2,k0);
|
||||
__m128i c3 = _mm_xor_si128(ctr3,k0);
|
||||
ctr0 = _mm_shuffle_epi8(ctr0,swap128);
|
||||
notctr0msq = ~((uint64_t)_mm_extract_epi64(ctr0,0));
|
||||
ctr1 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 5ULL),5LL)),swap128);
|
||||
ctr2 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 6ULL),6LL)),swap128);
|
||||
ctr3 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 7ULL),7LL)),swap128);
|
||||
ctr0 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)(notctr0msq < 4ULL),4LL)),swap128);
|
||||
__m128i kb = key[3];
|
||||
ZT_AES_CTR_AESNI_ROUND(k1);
|
||||
__m128i kc = key[4];
|
||||
ZT_AES_CTR_AESNI_ROUND(ka);
|
||||
__m128i kd = key[5];
|
||||
ZT_AES_CTR_AESNI_ROUND(kb);
|
||||
ka = key[6];
|
||||
ZT_AES_CTR_AESNI_ROUND(kc);
|
||||
kb = key[7];
|
||||
ZT_AES_CTR_AESNI_ROUND(kd);
|
||||
kc = key[8];
|
||||
ZT_AES_CTR_AESNI_ROUND(ka);
|
||||
kd = key[9];
|
||||
ZT_AES_CTR_AESNI_ROUND(kb);
|
||||
ka = key[10];
|
||||
ZT_AES_CTR_AESNI_ROUND(kc);
|
||||
kb = key[11];
|
||||
ZT_AES_CTR_AESNI_ROUND(kd);
|
||||
kc = key[12];
|
||||
ZT_AES_CTR_AESNI_ROUND(ka);
|
||||
kd = key[13];
|
||||
ZT_AES_CTR_AESNI_ROUND(kb);
|
||||
ka = key[14];
|
||||
ZT_AES_CTR_AESNI_ROUND(kc);
|
||||
ZT_AES_CTR_AESNI_ROUND(kd);
|
||||
_mm_storeu_si128((__m128i *)out,_mm_xor_si128(_mm_loadu_si128((const __m128i *)in),_mm_aesenclast_si128(c0,ka)));
|
||||
_mm_storeu_si128((__m128i *)(out + 16),_mm_xor_si128(_mm_loadu_si128((const __m128i *)(in + 16)),_mm_aesenclast_si128(c1,ka)));
|
||||
_mm_storeu_si128((__m128i *)(out + 32),_mm_xor_si128(_mm_loadu_si128((const __m128i *)(in + 32)),_mm_aesenclast_si128(c2,ka)));
|
||||
_mm_storeu_si128((__m128i *)(out + 48),_mm_xor_si128(_mm_loadu_si128((const __m128i *)(in + 48)),_mm_aesenclast_si128(c3,ka)));
|
||||
in += 64;
|
||||
out += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
__m128i k2 = key[2];
|
||||
__m128i k3 = key[3];
|
||||
__m128i k4 = key[4];
|
||||
__m128i k5 = key[5];
|
||||
__m128i k6 = key[6];
|
||||
__m128i k7 = key[7];
|
||||
|
||||
while (len >= 16) {
|
||||
__m128i c0 = _mm_xor_si128(ctr0,k0);
|
||||
ctr0 = _mm_shuffle_epi8(ctr0,swap128);
|
||||
ctr0 = _mm_shuffle_epi8(_mm_add_epi64(ctr0,_mm_set_epi64x((long long)((~((uint64_t)_mm_extract_epi64(ctr0,0))) < 1ULL),1LL)),swap128);
|
||||
c0 = _mm_aesenc_si128(c0,k1);
|
||||
c0 = _mm_aesenc_si128(c0,k2);
|
||||
c0 = _mm_aesenc_si128(c0,k3);
|
||||
c0 = _mm_aesenc_si128(c0,k4);
|
||||
c0 = _mm_aesenc_si128(c0,k5);
|
||||
c0 = _mm_aesenc_si128(c0,k6);
|
||||
__m128i ka = key[8];
|
||||
c0 = _mm_aesenc_si128(c0,k7);
|
||||
__m128i kb = key[9];
|
||||
c0 = _mm_aesenc_si128(c0,ka);
|
||||
ka = key[10];
|
||||
c0 = _mm_aesenc_si128(c0,kb);
|
||||
kb = key[11];
|
||||
c0 = _mm_aesenc_si128(c0,ka);
|
||||
ka = key[12];
|
||||
c0 = _mm_aesenc_si128(c0,kb);
|
||||
kb = key[13];
|
||||
c0 = _mm_aesenc_si128(c0,ka);
|
||||
ka = key[14];
|
||||
c0 = _mm_aesenc_si128(c0,kb);
|
||||
_mm_storeu_si128((__m128i *)out,_mm_xor_si128(_mm_loadu_si128((const __m128i *)in),_mm_aesenclast_si128(c0,ka)));
|
||||
in += 16;
|
||||
out += 16;
|
||||
len -= 16;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
__m128i c0 = _mm_xor_si128(ctr0,k0);
|
||||
k0 = key[8];
|
||||
c0 = _mm_aesenc_si128(c0,k1);
|
||||
c0 = _mm_aesenc_si128(c0,k2);
|
||||
k1 = key[9];
|
||||
c0 = _mm_aesenc_si128(c0,k3);
|
||||
c0 = _mm_aesenc_si128(c0,k4);
|
||||
k2 = key[10];
|
||||
c0 = _mm_aesenc_si128(c0,k5);
|
||||
c0 = _mm_aesenc_si128(c0,k6);
|
||||
k3 = key[11];
|
||||
c0 = _mm_aesenc_si128(c0,k7);
|
||||
c0 = _mm_aesenc_si128(c0,k0);
|
||||
k0 = key[12];
|
||||
c0 = _mm_aesenc_si128(c0,k1);
|
||||
c0 = _mm_aesenc_si128(c0,k2);
|
||||
k1 = key[13];
|
||||
c0 = _mm_aesenc_si128(c0,k3);
|
||||
c0 = _mm_aesenc_si128(c0,k0);
|
||||
k2 = key[14];
|
||||
c0 = _mm_aesenc_si128(c0,k1);
|
||||
c0 = _mm_aesenclast_si128(c0,k2);
|
||||
uint8_t tmp[16];
|
||||
_mm_storeu_si128((__m128i *)tmp,c0);
|
||||
for(unsigned int i=0;i<len;++i)
|
||||
out[i] = in[i] ^ tmp[i];
|
||||
}
|
||||
}
|
||||
#endif /* ZT_AES_AESNI ******************************************************/
|
||||
};
|
||||
|
||||
|
115
node/Address.hpp
115
node/Address.hpp
@ -14,12 +14,15 @@
|
||||
#ifndef ZT_ADDRESS_HPP
|
||||
#define ZT_ADDRESS_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
@ -34,8 +37,7 @@ class Address
|
||||
{
|
||||
public:
|
||||
ZT_ALWAYS_INLINE Address() : _a(0) {}
|
||||
ZT_ALWAYS_INLINE Address(const Address &a) : _a(a._a) {}
|
||||
ZT_ALWAYS_INLINE Address(uint64_t a) : _a(a & 0xffffffffffULL) {}
|
||||
explicit ZT_ALWAYS_INLINE Address(uint64_t a) : _a(a & 0xffffffffffULL) {}
|
||||
|
||||
/**
|
||||
* @param bits Raw address -- 5 bytes, big-endian byte order
|
||||
@ -43,7 +45,6 @@ public:
|
||||
*/
|
||||
ZT_ALWAYS_INLINE Address(const void *bits,unsigned int len) { setTo(bits,len); }
|
||||
|
||||
ZT_ALWAYS_INLINE Address &operator=(const Address &a) { _a = a._a; return *this; }
|
||||
ZT_ALWAYS_INLINE Address &operator=(const uint64_t a) { _a = (a & 0xffffffffffULL); return *this; }
|
||||
|
||||
/**
|
||||
@ -105,18 +106,13 @@ public:
|
||||
/**
|
||||
* @return Hash code for use with Hashtable
|
||||
*/
|
||||
ZT_ALWAYS_INLINE unsigned long hashCode() const { return reinterpret_cast<unsigned long>(_a); }
|
||||
ZT_ALWAYS_INLINE unsigned long hashCode() const { return (unsigned long)_a; }
|
||||
|
||||
/**
|
||||
* @return Hexadecimal string
|
||||
*/
|
||||
ZT_ALWAYS_INLINE char *toString(char buf[11]) const { return Utils::hex10(_a,buf); }
|
||||
|
||||
/**
|
||||
* @return True if this address is not zero
|
||||
*/
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (_a != 0); }
|
||||
|
||||
/**
|
||||
* Check if this address is reserved
|
||||
*
|
||||
@ -126,7 +122,7 @@ public:
|
||||
*
|
||||
* @return True if address is reserved and may not be used
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool isReserved() const { return ((!_a)||((_a >> 32) == ZT_ADDRESS_RESERVED_PREFIX)); }
|
||||
ZT_ALWAYS_INLINE bool isReserved() const { return ((!_a)||((_a >> 32U) == ZT_ADDRESS_RESERVED_PREFIX)); }
|
||||
|
||||
/**
|
||||
* @param i Value from 0 to 4 (inclusive)
|
||||
@ -134,9 +130,10 @@ public:
|
||||
*/
|
||||
ZT_ALWAYS_INLINE uint8_t operator[](unsigned int i) const { return (uint8_t)(_a >> (32 - (i * 8))); }
|
||||
|
||||
ZT_ALWAYS_INLINE operator unsigned int() const { return reinterpret_cast<unsigned int>(_a); }
|
||||
ZT_ALWAYS_INLINE operator unsigned long() const { return reinterpret_cast<unsigned long>(_a); }
|
||||
ZT_ALWAYS_INLINE operator unsigned long long() const { return reinterpret_cast<unsigned long long>(_a); }
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (_a != 0); }
|
||||
ZT_ALWAYS_INLINE operator unsigned int() const { return (unsigned int)_a; }
|
||||
ZT_ALWAYS_INLINE operator unsigned long() const { return (unsigned long)_a; }
|
||||
ZT_ALWAYS_INLINE operator unsigned long long() const { return (unsigned long long)_a; }
|
||||
|
||||
ZT_ALWAYS_INLINE void zero() { _a = 0; }
|
||||
|
||||
@ -154,6 +151,90 @@ public:
|
||||
ZT_ALWAYS_INLINE bool operator>=(const Address &a) const { return (_a >= a._a); }
|
||||
ZT_ALWAYS_INLINE bool operator<=(const Address &a) const { return (_a <= a._a); }
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Create a list of the first N bits of a list of unique addresses with N as the minimum unique size
|
||||
*
|
||||
* The list is stored in a space-efficient packed bit format.
|
||||
*
|
||||
* @param start Starting Address iterator/pointer
|
||||
* @param end Ending Address iterator/pointer
|
||||
* @param list Pointer to location to write list
|
||||
* @param listCapacityBytes Number of bytes available for list
|
||||
* @return Number of bytes written or -1 on overflow or other error
|
||||
* @tparam I Input iterator type
|
||||
*/
|
||||
template<typename I>
|
||||
static inline int createMinPrefixList(I start,I end,uint8_t *list,const int listCapacityBytes)
|
||||
{
|
||||
std::vector<Address> sortedAddrs(start,end);
|
||||
if (sortedAddrs.empty())
|
||||
return 0;
|
||||
if (listCapacityBytes == 0)
|
||||
return -1;
|
||||
std::sort(sortedAddrs.begin(),sortedAddrs.end());
|
||||
|
||||
unsigned int bits = (unsigned int)fmaxf(log2f((float)(sortedAddrs.size() * 2)),3.0F);
|
||||
uint64_t mask;
|
||||
try_additional_bits: {
|
||||
mask = 0xffffffffffffffffULL >> (64 - bits);
|
||||
std::vector<Address>::iterator a(sortedAddrs.begin());
|
||||
uint64_t aa = *(a++) & mask;
|
||||
aa |= (uint64_t)(aa == 0);
|
||||
uint64_t lastMaskedAddress = aa;
|
||||
while (a != sortedAddrs.end()) {
|
||||
aa = *(a++) & mask;
|
||||
aa |= (uint64_t)(aa == 0);
|
||||
if (aa == lastMaskedAddress) {
|
||||
++bits;
|
||||
goto try_additional_bits;
|
||||
}
|
||||
lastMaskedAddress = aa;
|
||||
}
|
||||
}
|
||||
|
||||
int l = 0;
|
||||
unsigned int bitPtr = 0;
|
||||
for(I a(start);a!=end;) {
|
||||
uint64_t aa = *(a++) & mask;
|
||||
aa |= (uint64_t)(aa == 0);
|
||||
unsigned int br = bits;
|
||||
if (bitPtr > 0) {
|
||||
unsigned int w = 8 - bitPtr;
|
||||
if (w > br) w = br;
|
||||
list[l] = (list[l] << w) | (((uint8_t)aa) & (0xff >> (8 - w)));
|
||||
bitPtr += w;
|
||||
if (bitPtr == 8) {
|
||||
bitPtr = 0;
|
||||
if (l >= listCapacityBytes)
|
||||
return -1;
|
||||
++l;
|
||||
}
|
||||
aa >>= w;
|
||||
br -= w;
|
||||
}
|
||||
while (br >= 8) {
|
||||
if (l >= listCapacityBytes)
|
||||
return -1;
|
||||
list[l++] = (uint8_t)aa;
|
||||
br -= 8;
|
||||
aa >>= 8;
|
||||
}
|
||||
if (br > 0) {
|
||||
list[l] = (uint8_t)aa;
|
||||
bitPtr = br;
|
||||
}
|
||||
}
|
||||
if (bitPtr > 0) {
|
||||
if (l >= listCapacityBytes)
|
||||
return -1;
|
||||
++l;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
uint64_t _a;
|
||||
};
|
||||
|
@ -24,25 +24,30 @@ namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Simple atomic counter supporting increment and decrement
|
||||
*
|
||||
* This is used as the reference counter in reference counted objects that
|
||||
* work with SharedPtr<>.
|
||||
*/
|
||||
class AtomicCounter
|
||||
{
|
||||
public:
|
||||
ZT_ALWAYS_INLINE AtomicCounter() { _v = 0; }
|
||||
ZT_ALWAYS_INLINE AtomicCounter() : _v(0) {}
|
||||
|
||||
ZT_ALWAYS_INLINE int load() const
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __sync_or_and_fetch(const_cast<int *>(&_v),0);
|
||||
return _v;
|
||||
#else
|
||||
return _v.load();
|
||||
#endif
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE void zero() { _v = 0; }
|
||||
|
||||
ZT_ALWAYS_INLINE int operator++()
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __sync_add_and_fetch(&_v,1);
|
||||
return __sync_add_and_fetch((int *)&_v,1);
|
||||
#else
|
||||
return ++_v;
|
||||
#endif
|
||||
@ -51,7 +56,7 @@ public:
|
||||
ZT_ALWAYS_INLINE int operator--()
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __sync_sub_and_fetch(&_v,1);
|
||||
return __sync_sub_and_fetch((int *)&_v,1);
|
||||
#else
|
||||
return --_v;
|
||||
#endif
|
||||
@ -62,7 +67,7 @@ private:
|
||||
ZT_ALWAYS_INLINE const AtomicCounter &operator=(const AtomicCounter &) { return *this; }
|
||||
|
||||
#ifdef __GNUC__
|
||||
int _v;
|
||||
volatile int _v;
|
||||
#else
|
||||
std::atomic_int _v;
|
||||
#endif
|
||||
|
116
node/Buf.cpp
Normal file
116
node/Buf.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c)2019 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#include "Buf.hpp"
|
||||
|
||||
#ifndef __GNUC__
|
||||
#include <atomic>
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
#ifdef __GNUC__
|
||||
static uintptr_t s_pool = 0;
|
||||
#else
|
||||
static std::atomic<uintptr_t> s_pool(0);
|
||||
#endif
|
||||
|
||||
void Buf::operator delete(void *ptr,std::size_t sz)
|
||||
{
|
||||
if (ptr) {
|
||||
uintptr_t bb;
|
||||
const uintptr_t locked = ~((uintptr_t)0);
|
||||
for (;;) {
|
||||
#ifdef __GNUC__
|
||||
bb = __sync_fetch_and_or(&s_pool,locked); // get value of s_pool and "lock" by filling with all 1's
|
||||
#else
|
||||
bb = s_pool.fetch_or(locked);
|
||||
#endif
|
||||
if (bb != locked)
|
||||
break;
|
||||
}
|
||||
|
||||
((Buf *)ptr)->__nextInPool = bb;
|
||||
#ifdef __GNUC__
|
||||
__sync_fetch_and_and(&s_pool,(uintptr_t)ptr);
|
||||
#else
|
||||
s_pool.store((uintptr_t)ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SharedPtr<Buf> Buf::get()
|
||||
{
|
||||
uintptr_t bb;
|
||||
const uintptr_t locked = ~((uintptr_t)0);
|
||||
for (;;) {
|
||||
#ifdef __GNUC__
|
||||
bb = __sync_fetch_and_or(&s_pool,locked); // get value of s_pool and "lock" by filling with all 1's
|
||||
#else
|
||||
bb = s_pool.fetch_or(locked);
|
||||
#endif
|
||||
if (bb != locked)
|
||||
break;
|
||||
}
|
||||
|
||||
Buf *b;
|
||||
if (bb == 0) {
|
||||
#ifdef __GNUC__
|
||||
__sync_fetch_and_and(&s_pool,bb);
|
||||
#else
|
||||
s_pool.store(bb);
|
||||
#endif
|
||||
b = (Buf *)malloc(sizeof(Buf));
|
||||
if (!b)
|
||||
return SharedPtr<Buf>();
|
||||
} else {
|
||||
b = (Buf *)bb;
|
||||
#ifdef __GNUC__
|
||||
__sync_fetch_and_and(&s_pool,b->__nextInPool);
|
||||
#else
|
||||
s_pool.store(b->__nextInPool);
|
||||
#endif
|
||||
}
|
||||
|
||||
b->__refCount.zero();
|
||||
return SharedPtr<Buf>(b);
|
||||
}
|
||||
|
||||
void Buf::freePool()
|
||||
{
|
||||
uintptr_t bb;
|
||||
const uintptr_t locked = ~((uintptr_t)0);
|
||||
for (;;) {
|
||||
#ifdef __GNUC__
|
||||
bb = __sync_fetch_and_or(&s_pool,locked); // get value of s_pool and "lock" by filling with all 1's
|
||||
#else
|
||||
bb = s_pool.fetch_or(locked);
|
||||
#endif
|
||||
if (bb != locked)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
__sync_fetch_and_and(&s_pool,(uintptr_t)0);
|
||||
#else
|
||||
s_pool.store((uintptr_t)0);
|
||||
#endif
|
||||
|
||||
while (bb != 0) {
|
||||
uintptr_t next = ((Buf *)bb)->__nextInPool;
|
||||
free((void *)bb);
|
||||
bb = next;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
472
node/Buf.hpp
Normal file
472
node/Buf.hpp
Normal file
@ -0,0 +1,472 @@
|
||||
/*
|
||||
* Copyright (c)2019 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#ifndef ZT_BUF_HPP
|
||||
#define ZT_BUF_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AtomicCounter.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
// Buffers are 16384 bytes in size because this is the smallest size that can hold any packet
|
||||
// and is a power of two. It needs to be a power of two because masking is significantly faster
|
||||
// than integer division modulus.
|
||||
#define ZT_BUF_MEM_SIZE 0x00004000
|
||||
#define ZT_BUF_MEM_MASK 0x00003fffU
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Buffer and methods for branch-free bounds-checked data assembly and parsing
|
||||
*
|
||||
* This implements an extremely fast buffer for packet assembly and parsing that avoids
|
||||
* branching whenever possible. To be safe it must be used correctly!
|
||||
*
|
||||
* The read methods are prefixed by 'r', and write methods with 'w'. All methods take
|
||||
* an iterator, which is just an int that should be initialized to 0 (or whatever starting
|
||||
* position is desired). All read methods will advance the iterator regardless of outcome.
|
||||
*
|
||||
* Read and write methods fail silently in the event of overflow. They do not corrupt or
|
||||
* access memory outside the bounds of Buf, but will otherwise produce undefined results.
|
||||
*
|
||||
* IT IS THE RESPONSIBILITY OF THE USER of this class to use the readOverflow() and
|
||||
* writeOverflow() static methods to check the iterator for overflow after each series
|
||||
* of reads and writes and BEFORE ANY PARSING or other decisions are made on the basis
|
||||
* of the data obtained from a buffer. Failure to do so can result in bugs due
|
||||
* to parsing and branching on undefined or corrupt data.
|
||||
*
|
||||
* ^^ THIS IS VERY IMPORTANT ^^
|
||||
*
|
||||
* A typical packet assembly consists of repeated calls to the write methods followed by
|
||||
* a check to writeOverflow() before final packet armoring and transport. A typical packet
|
||||
* disassembly and parsing consists of a series of read calls to obtain the packet's
|
||||
* fields followed by a call to readOverflow() to check that these fields are valid. The
|
||||
* packet is discarded if readOverflow() returns true. Some packet parsers may make
|
||||
* additional reads and in this case readOverflow() must be checked after each set of
|
||||
* reads to ensure that overflow did not occur.
|
||||
*
|
||||
* Buf uses a lock-free pool for extremely fast allocation and deallocation.
|
||||
*/
|
||||
class Buf
|
||||
{
|
||||
friend class SharedPtr<Buf>;
|
||||
|
||||
private:
|
||||
// Direct construction isn't allowed; use get().
|
||||
ZT_ALWAYS_INLINE Buf()
|
||||
{}
|
||||
|
||||
ZT_ALWAYS_INLINE Buf(const Buf &b)
|
||||
{}
|
||||
|
||||
public:
|
||||
static void operator delete(void *ptr,std::size_t sz);
|
||||
|
||||
/**
|
||||
* Get obtains a buffer from the pool or allocates a new buffer if the pool is empty
|
||||
*
|
||||
* @return Buffer
|
||||
*/
|
||||
static SharedPtr<Buf> get();
|
||||
|
||||
/**
|
||||
* Free buffers in the pool
|
||||
*
|
||||
* New buffers will be created and the pool repopulated if get() is called
|
||||
* and outstanding buffers will still be returned to the pool. This just
|
||||
* frees buffers currently held in reserve.
|
||||
*/
|
||||
static void freePool();
|
||||
|
||||
/**
|
||||
* Check for overflow beyond the size of the buffer
|
||||
*
|
||||
* This is used to check for overflow when writing. It returns true if the iterator
|
||||
* has passed beyond the capacity of the buffer.
|
||||
*
|
||||
* @param ii Iterator to check
|
||||
* @return True if iterator has read past the size of the buffer
|
||||
*/
|
||||
static ZT_ALWAYS_INLINE bool writeOverflow(const int &ii)
|
||||
{ return ((ii - ZT_BUF_MEM_SIZE) > 0); }
|
||||
|
||||
/**
|
||||
* Check for overflow beyond the size of the data that should be in the buffer
|
||||
*
|
||||
* This is used to check for overflow when reading, with the second argument being the
|
||||
* size of the meaningful data actually present in the buffer.
|
||||
*
|
||||
* @param ii Iterator to check
|
||||
* @param size Size of data that should be in buffer
|
||||
* @return True if iterator has read past the size of the data
|
||||
*/
|
||||
static ZT_ALWAYS_INLINE bool readOverflow(const int &ii,const unsigned int size)
|
||||
{ return ((ii - (int)size) > 0); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Read methods
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Read a byte
|
||||
*
|
||||
* @param ii Iterator
|
||||
* @return Byte (undefined on overflow)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE uint8_t rI8(int &ii) const
|
||||
{
|
||||
const unsigned int s = (unsigned int)ii++;
|
||||
return data[s & ZT_BUF_MEM_MASK];
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a 16-bit integer
|
||||
*
|
||||
* @param ii Integer
|
||||
* @return Integer (undefined on overflow)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE uint16_t rI16(int &ii) const
|
||||
{
|
||||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
ii += 2;
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
return (
|
||||
((uint16_t)data[s] << 8U) |
|
||||
(uint16_t)data[s + 1]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint16_t *>(data + s));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a 32-bit integer
|
||||
*
|
||||
* @param ii Integer
|
||||
* @return Integer (undefined on overflow)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE uint32_t rI32(int &ii) const
|
||||
{
|
||||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
ii += 4;
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
return (
|
||||
((uint32_t)data[s] << 24U) |
|
||||
((uint32_t)data[s + 1] << 16U) |
|
||||
((uint32_t)data[s + 2] << 8U) |
|
||||
(uint32_t)data[s + 3]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint32_t *>(data + s));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a 64-bit integer
|
||||
*
|
||||
* @param ii Integer
|
||||
* @return Integer (undefined on overflow)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE uint64_t rI64(int &ii) const
|
||||
{
|
||||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
ii += 8;
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
return (
|
||||
((uint64_t)data[s] << 56U) |
|
||||
((uint64_t)data[s + 1] << 48U) |
|
||||
((uint64_t)data[s + 2] << 40U) |
|
||||
((uint64_t)data[s + 3] << 32U) |
|
||||
((uint64_t)data[s + 4] << 24U) |
|
||||
((uint64_t)data[s + 5] << 16U) |
|
||||
((uint64_t)data[s + 6] << 8U) |
|
||||
(uint64_t)data[s + 7]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint64_t *>(data + s));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an object supporting the marshal/unmarshal interface
|
||||
*
|
||||
* If the return value is negative the object's state is undefined. A return value of
|
||||
* zero typically also indicates a problem, though this may depend on the object type.
|
||||
*
|
||||
* Since objects may be invalid even if there is no overflow, it's important to check
|
||||
* the return value of this function in all cases and discard invalid packets as it
|
||||
* indicates.
|
||||
*
|
||||
* @tparam T Object type
|
||||
* @param ii Iterator
|
||||
* @param obj Object to read
|
||||
* @return Bytes read or a negative value on unmarshal error (passed from object) or overflow
|
||||
*/
|
||||
template<typename T>
|
||||
ZT_ALWAYS_INLINE int rO(int &ii,T &obj) const
|
||||
{
|
||||
if (ii < ZT_BUF_MEM_SIZE) {
|
||||
int ms = obj.unmarshal(data + ii,ZT_BUF_MEM_SIZE - ii);
|
||||
if (ms > 0)
|
||||
ii += ms;
|
||||
return ms;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a C-style string from the buffer, making a copy and advancing the iterator
|
||||
*
|
||||
* Use this if the buffer's memory may get changed between reading and processing
|
||||
* what is read.
|
||||
*
|
||||
* @param ii Iterator
|
||||
* @param buf Buffer to receive string
|
||||
* @param bufSize Capacity of buffer in bytes
|
||||
* @return Pointer to buf or NULL on overflow or error
|
||||
*/
|
||||
ZT_ALWAYS_INLINE char *rS(int &ii,char *const buf,const unsigned int bufSize) const
|
||||
{
|
||||
const char *const s = (const char *)(data + ii);
|
||||
const int sii = ii;
|
||||
while (ii < ZT_BUF_MEM_SIZE) {
|
||||
if (data[ii++] == 0) {
|
||||
memcpy(buf,s,ii - sii);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a pointer to a C-style string in the buffer without copying and advance the iterator
|
||||
*
|
||||
* The iterator is advanced even if this fails and returns NULL so that readOverflow()
|
||||
* will indicate that an overflow occurred. As with other reads the string's contents are
|
||||
* undefined if readOverflow() returns true.
|
||||
*
|
||||
* This version avoids a copy and so is faster if the buffer won't be modified between
|
||||
* reading and processing.
|
||||
*
|
||||
* @param ii Iterator
|
||||
* @return Pointer to null-terminated C-style string or NULL on overflow or error
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const char *rSnc(int &ii) const
|
||||
{
|
||||
const char *const s = (const char *)(data + ii);
|
||||
while (ii < ZT_BUF_MEM_SIZE) {
|
||||
if (data[ii++] == 0)
|
||||
return s;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a byte array from the buffer, making a copy and advancing the iterator
|
||||
*
|
||||
* Use this if the buffer's memory may get changed between reading and processing
|
||||
* what is read.
|
||||
*
|
||||
* @param ii Iterator
|
||||
* @param bytes Buffer to contain data to read
|
||||
* @param len Length of buffer
|
||||
* @return Pointer to data or NULL on overflow or error
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void *rB(int &ii,void *bytes,unsigned int len) const
|
||||
{
|
||||
const void *const b = (const void *)(data + ii);
|
||||
if ((ii += (int)len) <= ZT_BUF_MEM_SIZE) {
|
||||
memcpy(bytes,b,len);
|
||||
return bytes;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a pointer to a field in the buffer without copying and advance the iterator
|
||||
*
|
||||
* The iterator is advanced even if this fails and returns NULL so that readOverflow()
|
||||
* will indicate that an overflow occurred.
|
||||
*
|
||||
* This version avoids a copy and so is faster if the buffer won't be modified between
|
||||
* reading and processing.
|
||||
*
|
||||
* @param ii Iterator
|
||||
* @param len Length of data field to obtain a pointer to
|
||||
* @return Pointer to field or NULL on overflow
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const void *rBnc(int &ii,unsigned int len) const
|
||||
{
|
||||
const void *const b = (const void *)(data + ii);
|
||||
return ((ii += (int)len) <= ZT_BUF_MEM_SIZE) ? b : nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Write methods
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Write a byte
|
||||
*
|
||||
* @param ii Iterator
|
||||
* @param n Byte
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void wI(int &ii,uint8_t n)
|
||||
{
|
||||
const unsigned int s = (unsigned int)ii++;
|
||||
data[s & ZT_BUF_MEM_MASK] = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a 16-bit integer in big-endian byte order
|
||||
*
|
||||
* @param ii Iterator
|
||||
* @param n Integer
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void wI(int &ii,uint16_t n)
|
||||
{
|
||||
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
|
||||
ii += 2;
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
data[s] = (uint8_t)(n >> 8U);
|
||||
data[s + 1] = (uint8_t)n;
|
||||
#else
|
||||
*reinterpret_cast<uint16_t *>(data + s) = Utils::hton(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a 32-bit integer in big-endian byte order
|
||||
*
|
||||
* @param ii Iterator
|
||||
* @param n Integer
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void wI(int &ii,uint32_t n)
|
||||
{
|
||||
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
|
||||
ii += 4;
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
data[s] = (uint8_t)(n >> 24U);
|
||||
data[s + 1] = (uint8_t)(n >> 16U);
|
||||
data[s + 2] = (uint8_t)(n >> 8U);
|
||||
data[s + 3] = (uint8_t)n;
|
||||
#else
|
||||
*reinterpret_cast<uint32_t *>(data + s) = Utils::hton(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a 64-bit integer in big-endian byte order
|
||||
*
|
||||
* @param ii Iterator
|
||||
* @param n Integer
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void wI(int &ii,uint64_t n)
|
||||
{
|
||||
const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
|
||||
ii += 8;
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
data[s] = (uint8_t)(n >> 56U);
|
||||
data[s + 1] = (uint8_t)(n >> 48U);
|
||||
data[s + 2] = (uint8_t)(n >> 40U);
|
||||
data[s + 3] = (uint8_t)(n >> 32U);
|
||||
data[s + 4] = (uint8_t)(n >> 24U);
|
||||
data[s + 5] = (uint8_t)(n >> 16U);
|
||||
data[s + 6] = (uint8_t)(n >> 8U);
|
||||
data[s + 7] = (uint8_t)n;
|
||||
#else
|
||||
*reinterpret_cast<uint64_t *>(data + s) = Utils::hton(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an object implementing the marshal interface
|
||||
*
|
||||
* @tparam T Object type
|
||||
* @param ii Iterator
|
||||
* @param t Object to write
|
||||
*/
|
||||
template<typename T>
|
||||
ZT_ALWAYS_INLINE void wO(int &ii,T &t)
|
||||
{
|
||||
const unsigned int s = (unsigned int)ii;
|
||||
if ((s + T::marshalSizeMax()) <= ZT_BUF_MEM_SIZE) {
|
||||
int ms = t.marshal(data + s);
|
||||
if (ms > 0)
|
||||
ii += ms;
|
||||
} else {
|
||||
ii += T::marshalSizeMax(); // mark as overflowed even if we didn't do anything
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a C-style null-terminated string (including the trailing zero)
|
||||
*
|
||||
* @param ii Iterator
|
||||
* @param s String to write (writes an empty string if this is NULL)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void wS(int &ii,const char *s)
|
||||
{
|
||||
if (s) {
|
||||
char c;
|
||||
do {
|
||||
c = *(s++);
|
||||
wI(ii,(uint8_t)c);
|
||||
} while (c);
|
||||
} else {
|
||||
wI(ii,(uint8_t)0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a byte array
|
||||
*
|
||||
* @param ii Iterator
|
||||
* @param bytes Bytes to write
|
||||
* @param len Size of data in bytes
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void wB(int &ii,const void *const bytes,const unsigned int len)
|
||||
{
|
||||
unsigned int s = (unsigned int)ii;
|
||||
if ((ii += (int)len) <= ZT_BUF_MEM_SIZE)
|
||||
memcpy(data + s,bytes,len);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ZT_ALWAYS_INLINE Buf &operator=(const Buf &b)
|
||||
{
|
||||
if (&b != this)
|
||||
memcpy(data,b.data,ZT_BUF_MEM_SIZE);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw buffer
|
||||
*
|
||||
* The extra eight bytes permit silent overflow of integer types without reading or writing
|
||||
* beyond Buf's memory and without branching or extra masks. They can be ignored otherwise.
|
||||
*/
|
||||
uint8_t data[ZT_BUF_MEM_SIZE + 8];
|
||||
|
||||
private:
|
||||
volatile uintptr_t __nextInPool;
|
||||
AtomicCounter __refCount;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
100
node/C25519.cpp
100
node/C25519.cpp
@ -7,16 +7,11 @@ Derived from public domain code by D. J. Bernstein.
|
||||
// Modified very slightly for ZeroTier One by Adam Ierymenko
|
||||
// This code remains in the public domain.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#pragma warning(disable: 4146)
|
||||
@ -28,10 +23,7 @@ Derived from public domain code by D. J. Bernstein.
|
||||
|
||||
namespace {
|
||||
|
||||
#define crypto_int32 int32_t
|
||||
#define crypto_uint32 uint32_t
|
||||
#define crypto_int64 int64_t
|
||||
#define crypto_uint64 uint64_t
|
||||
#define crypto_hash_sha512_BYTES 64
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -41,7 +33,7 @@ typedef uint8_t u8;
|
||||
typedef int32_t s32;
|
||||
typedef int64_t limb;
|
||||
|
||||
static ZT_ALWAYS_INLINE void fsum(limb *output, const limb *in) {
|
||||
static inline void fsum(limb *output, const limb *in) {
|
||||
unsigned i;
|
||||
for (i = 0; i < 10; i += 2) {
|
||||
output[0+i] = output[0+i] + in[0+i];
|
||||
@ -49,21 +41,21 @@ static ZT_ALWAYS_INLINE void fsum(limb *output, const limb *in) {
|
||||
}
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fdifference(limb *output, const limb *in) {
|
||||
static inline void fdifference(limb *output, const limb *in) {
|
||||
unsigned i;
|
||||
for (i = 0; i < 10; ++i) {
|
||||
output[i] = in[i] - output[i];
|
||||
}
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fscalar_product(limb *output, const limb *in, const limb scalar) {
|
||||
static inline void fscalar_product(limb *output, const limb *in, const limb scalar) {
|
||||
unsigned i;
|
||||
for (i = 0; i < 10; ++i) {
|
||||
output[i] = in[i] * scalar;
|
||||
}
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fproduct(limb *output, const limb *in2, const limb *in) {
|
||||
static inline void fproduct(limb *output, const limb *in2, const limb *in) {
|
||||
output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]);
|
||||
output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) +
|
||||
((limb) ((s32) in2[1])) * ((s32) in[0]);
|
||||
@ -166,7 +158,7 @@ static ZT_ALWAYS_INLINE void fproduct(limb *output, const limb *in2, const limb
|
||||
output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void freduce_degree(limb *output) {
|
||||
static inline void freduce_degree(limb *output) {
|
||||
output[8] += output[18] << 4;
|
||||
output[8] += output[18] << 1;
|
||||
output[8] += output[18];
|
||||
@ -200,7 +192,7 @@ static ZT_ALWAYS_INLINE void freduce_degree(limb *output) {
|
||||
#error "This code only works on a two's complement system"
|
||||
#endif
|
||||
|
||||
static ZT_ALWAYS_INLINE limb div_by_2_26(const limb v)
|
||||
static inline limb div_by_2_26(const limb v)
|
||||
{
|
||||
/* High word of v; no shift needed. */
|
||||
const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32);
|
||||
@ -212,7 +204,7 @@ static ZT_ALWAYS_INLINE limb div_by_2_26(const limb v)
|
||||
return (v + roundoff) >> 26;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE limb div_by_2_25(const limb v)
|
||||
static inline limb div_by_2_25(const limb v)
|
||||
{
|
||||
/* High word of v; no shift needed*/
|
||||
const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32);
|
||||
@ -224,7 +216,7 @@ static ZT_ALWAYS_INLINE limb div_by_2_25(const limb v)
|
||||
return (v + roundoff) >> 25;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void freduce_coefficients(limb *output) {
|
||||
static inline void freduce_coefficients(limb *output) {
|
||||
unsigned i;
|
||||
|
||||
output[10] = 0;
|
||||
@ -277,7 +269,7 @@ static inline void fmul(limb *output, const limb *in, const limb *in2) {
|
||||
memcpy(output, t, sizeof(limb) * 10);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fsquare_inner(limb *output, const limb *in) {
|
||||
static inline void fsquare_inner(limb *output, const limb *in) {
|
||||
output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]);
|
||||
output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]);
|
||||
output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) +
|
||||
@ -347,7 +339,7 @@ static inline void fsquare(limb *output, const limb *in) {
|
||||
memcpy(output, t, sizeof(limb) * 10);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fexpand(limb *output, const u8 *input) {
|
||||
static inline void fexpand(limb *output, const u8 *input) {
|
||||
#define F(n,start,shift,mask) \
|
||||
output[n] = ((((limb) input[start + 0]) | \
|
||||
((limb) input[start + 1]) << 8 | \
|
||||
@ -370,7 +362,7 @@ static ZT_ALWAYS_INLINE void fexpand(limb *output, const u8 *input) {
|
||||
#error "This code only works when >> does sign-extension on negative numbers"
|
||||
#endif
|
||||
|
||||
static ZT_ALWAYS_INLINE s32 s32_eq(s32 a, s32 b) {
|
||||
static inline s32 s32_eq(s32 a, s32 b) {
|
||||
a = ~(a ^ b);
|
||||
a &= a << 16;
|
||||
a &= a << 8;
|
||||
@ -380,7 +372,7 @@ static ZT_ALWAYS_INLINE s32 s32_eq(s32 a, s32 b) {
|
||||
return a >> 31;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE s32 s32_gte(s32 a, s32 b) {
|
||||
static inline s32 s32_gte(s32 a, s32 b) {
|
||||
a -= b;
|
||||
/* a >= 0 iff a >= b. */
|
||||
return ~(a >> 31);
|
||||
@ -560,7 +552,7 @@ static inline void fmonty(limb *x2, limb *z2, /* output 2Q */
|
||||
/* |z2|i| < 2^26 */
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void swap_conditional(limb a[19], limb b[19], limb iswap) {
|
||||
static inline void swap_conditional(limb a[19], limb b[19], limb iswap) {
|
||||
unsigned i;
|
||||
const s32 swap = (s32) -iswap;
|
||||
|
||||
@ -701,7 +693,7 @@ static inline void crypto_scalarmult(u8 *mypublic, const u8 *secret, const u8 *b
|
||||
}
|
||||
|
||||
static const unsigned char base[32] = {9};
|
||||
static ZT_ALWAYS_INLINE void crypto_scalarmult_base(unsigned char *q,const unsigned char *n) { crypto_scalarmult(q,n,base); }
|
||||
static inline void crypto_scalarmult_base(unsigned char *q,const unsigned char *n) { crypto_scalarmult(q,n,base); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -759,7 +751,7 @@ typedef struct
|
||||
|
||||
static inline void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y);
|
||||
|
||||
static ZT_ALWAYS_INLINE crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
|
||||
static inline crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
|
||||
{
|
||||
crypto_uint32 x = a ^ b; /* 0: yes; 1..65535: no */
|
||||
x -= 1; /* 4294967295: yes; 0..65534: no */
|
||||
@ -767,7 +759,7 @@ static ZT_ALWAYS_INLINE crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /*
|
||||
return x;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
|
||||
static inline crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
|
||||
{
|
||||
unsigned int x = a;
|
||||
x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */
|
||||
@ -776,10 +768,10 @@ static ZT_ALWAYS_INLINE crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-
|
||||
return x;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE crypto_uint32 times19(crypto_uint32 a) { return (a << 4) + (a << 1) + a; }
|
||||
static ZT_ALWAYS_INLINE crypto_uint32 times38(crypto_uint32 a) { return (a << 5) + (a << 2) + (a << 1); }
|
||||
static inline crypto_uint32 times19(crypto_uint32 a) { return (a << 4) + (a << 1) + a; }
|
||||
static inline crypto_uint32 times38(crypto_uint32 a) { return (a << 5) + (a << 2) + (a << 1); }
|
||||
|
||||
static ZT_ALWAYS_INLINE void reduce_add_sub(fe25519 *r)
|
||||
static inline void reduce_add_sub(fe25519 *r)
|
||||
{
|
||||
int i,rep;
|
||||
for(rep=0;rep<4;rep++)
|
||||
@ -797,7 +789,7 @@ static ZT_ALWAYS_INLINE void reduce_add_sub(fe25519 *r)
|
||||
}
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void reduce_mul(fe25519 *r)
|
||||
static inline void reduce_mul(fe25519 *r)
|
||||
{
|
||||
int i,rep;
|
||||
for(rep=0;rep<2;rep++)
|
||||
@ -815,7 +807,7 @@ static ZT_ALWAYS_INLINE void reduce_mul(fe25519 *r)
|
||||
}
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fe25519_freeze(fe25519 *r)
|
||||
static inline void fe25519_freeze(fe25519 *r)
|
||||
{
|
||||
int i;
|
||||
crypto_uint32 mm = equal(r->v[31],127);
|
||||
@ -831,14 +823,14 @@ static ZT_ALWAYS_INLINE void fe25519_freeze(fe25519 *r)
|
||||
r->v[0] -= mm&237;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fe25519_unpack(fe25519 *r, const unsigned char x[32])
|
||||
static inline void fe25519_unpack(fe25519 *r, const unsigned char x[32])
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<32;i++) r->v[i] = x[i];
|
||||
r->v[31] &= 127;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fe25519_pack(unsigned char r[32], const fe25519 *x)
|
||||
static inline void fe25519_pack(unsigned char r[32], const fe25519 *x)
|
||||
{
|
||||
int i;
|
||||
fe25519 y = *x;
|
||||
@ -859,7 +851,7 @@ static inline int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b)
|
||||
static inline void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b)
|
||||
{
|
||||
int i;
|
||||
crypto_uint32 mask = b;
|
||||
@ -867,27 +859,27 @@ static ZT_ALWAYS_INLINE void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned
|
||||
for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE unsigned char fe25519_getparity(const fe25519 *x)
|
||||
static inline unsigned char fe25519_getparity(const fe25519 *x)
|
||||
{
|
||||
fe25519 t = *x;
|
||||
fe25519_freeze(&t);
|
||||
return t.v[0] & 1;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fe25519_setone(fe25519 *r)
|
||||
static inline void fe25519_setone(fe25519 *r)
|
||||
{
|
||||
int i;
|
||||
r->v[0] = 1;
|
||||
for(i=1;i<32;i++) r->v[i]=0;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fe25519_setzero(fe25519 *r)
|
||||
static inline void fe25519_setzero(fe25519 *r)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<32;i++) r->v[i]=0;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fe25519_neg(fe25519 *r, const fe25519 *x)
|
||||
static inline void fe25519_neg(fe25519 *r, const fe25519 *x)
|
||||
{
|
||||
fe25519 t;
|
||||
int i;
|
||||
@ -896,14 +888,14 @@ static ZT_ALWAYS_INLINE void fe25519_neg(fe25519 *r, const fe25519 *x)
|
||||
fe25519_sub(r, r, &t);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y)
|
||||
static inline void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i];
|
||||
reduce_add_sub(r);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y)
|
||||
static inline void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y)
|
||||
{
|
||||
int i;
|
||||
crypto_uint32 t[32];
|
||||
@ -914,7 +906,7 @@ static ZT_ALWAYS_INLINE void fe25519_sub(fe25519 *r, const fe25519 *x, const fe2
|
||||
reduce_add_sub(r);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y)
|
||||
static inline void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y)
|
||||
{
|
||||
int i,j;
|
||||
crypto_uint32 t[63];
|
||||
@ -931,7 +923,7 @@ static ZT_ALWAYS_INLINE void fe25519_mul(fe25519 *r, const fe25519 *x, const fe2
|
||||
reduce_mul(r);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void fe25519_square(fe25519 *r, const fe25519 *x) { fe25519_mul(r, x, x); }
|
||||
static inline void fe25519_square(fe25519 *r, const fe25519 *x) { fe25519_mul(r, x, x); }
|
||||
|
||||
static inline void fe25519_invert(fe25519 *r, const fe25519 *x)
|
||||
{
|
||||
@ -1057,7 +1049,7 @@ static inline void fe25519_pow2523(fe25519 *r, const fe25519 *x)
|
||||
static const crypto_uint32 m[32] = {0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
|
||||
static const crypto_uint32 mu[33] = {0x1B, 0x13, 0x2C, 0x0A, 0xA3, 0xE5, 0x9C, 0xED, 0xA7, 0x29, 0x63, 0x08, 0x5D, 0x21, 0x06, 0x21, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F};
|
||||
|
||||
static ZT_ALWAYS_INLINE crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
|
||||
static inline crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
|
||||
{
|
||||
unsigned int x = a;
|
||||
x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */
|
||||
@ -1065,7 +1057,7 @@ static ZT_ALWAYS_INLINE crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-
|
||||
return x;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void reduce_add_sub(sc25519 *r)
|
||||
static inline void reduce_add_sub(sc25519 *r)
|
||||
{
|
||||
crypto_uint32 pb = 0;
|
||||
crypto_uint32 b;
|
||||
@ -1144,7 +1136,7 @@ static inline void sc25519_from64bytes(sc25519 *r, const unsigned char x[64])
|
||||
barrett_reduce(r, t);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void sc25519_to32bytes(unsigned char r[32], const sc25519 *x)
|
||||
static inline void sc25519_to32bytes(unsigned char r[32], const sc25519 *x)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<32;i++) r[i] = x->v[i];
|
||||
@ -1181,7 +1173,7 @@ static inline void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y)
|
||||
barrett_reduce(r, t);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void sc25519_window3(signed char r[85], const sc25519 *s)
|
||||
static inline void sc25519_window3(signed char r[85], const sc25519 *s)
|
||||
{
|
||||
char carry;
|
||||
int i;
|
||||
@ -1218,7 +1210,7 @@ static ZT_ALWAYS_INLINE void sc25519_window3(signed char r[85], const sc25519 *s
|
||||
r[84] += carry;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2)
|
||||
static inline void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<31;i++)
|
||||
@ -2107,21 +2099,21 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = {
|
||||
{{0x69, 0x3e, 0x47, 0x97, 0x2c, 0xaf, 0x52, 0x7c, 0x78, 0x83, 0xad, 0x1b, 0x39, 0x82, 0x2f, 0x02, 0x6f, 0x47, 0xdb, 0x2a, 0xb0, 0xe1, 0x91, 0x99, 0x55, 0xb8, 0x99, 0x3a, 0xa0, 0x44, 0x11, 0x51}}}
|
||||
};
|
||||
|
||||
static ZT_ALWAYS_INLINE void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p)
|
||||
static inline void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p)
|
||||
{
|
||||
fe25519_mul(&r->x, &p->x, &p->t);
|
||||
fe25519_mul(&r->y, &p->y, &p->z);
|
||||
fe25519_mul(&r->z, &p->z, &p->t);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void p1p1_to_p2_2(ge25519_p3 *r, const ge25519_p1p1 *p)
|
||||
static inline void p1p1_to_p2_2(ge25519_p3 *r, const ge25519_p1p1 *p)
|
||||
{
|
||||
fe25519_mul(&r->x, &p->x, &p->t);
|
||||
fe25519_mul(&r->y, &p->y, &p->z);
|
||||
fe25519_mul(&r->z, &p->z, &p->t);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p)
|
||||
static inline void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p)
|
||||
{
|
||||
p1p1_to_p2_2(r, p);
|
||||
fe25519_mul(&r->t, &p->x, &p->y);
|
||||
@ -2190,13 +2182,13 @@ static inline void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p)
|
||||
}
|
||||
|
||||
/* Constant-time version of: if(b) r = p */
|
||||
static ZT_ALWAYS_INLINE void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b)
|
||||
static inline void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b)
|
||||
{
|
||||
fe25519_cmov(&r->x, &p->x, b);
|
||||
fe25519_cmov(&r->y, &p->y, b);
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE unsigned char equal(signed char b,signed char c)
|
||||
static inline unsigned char equal(signed char b,signed char c)
|
||||
{
|
||||
unsigned char ub = b;
|
||||
unsigned char uc = c;
|
||||
@ -2207,7 +2199,7 @@ static ZT_ALWAYS_INLINE unsigned char equal(signed char b,signed char c)
|
||||
return (unsigned char)y;
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE unsigned char negative(signed char b)
|
||||
static inline unsigned char negative(signed char b)
|
||||
{
|
||||
unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
|
||||
x >>= 63; /* 1: yes; 0: no */
|
||||
@ -2356,7 +2348,7 @@ static inline void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s)
|
||||
}
|
||||
}
|
||||
|
||||
static ZT_ALWAYS_INLINE void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen)
|
||||
static inline void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen)
|
||||
{
|
||||
unsigned long long i;
|
||||
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
/**
|
||||
* Generate a C25519 elliptic curve key pair
|
||||
*/
|
||||
static ZT_ALWAYS_INLINE void generate(uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN],uint8_t priv[ZT_C25519_PRIVATE_KEY_LEN])
|
||||
static inline void generate(uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN],uint8_t priv[ZT_C25519_PRIVATE_KEY_LEN])
|
||||
{
|
||||
Utils::getSecureRandom(priv,ZT_C25519_PRIVATE_KEY_LEN);
|
||||
_calcPubDH(pub,priv);
|
||||
@ -53,7 +53,7 @@ public:
|
||||
* @tparam F Type of 'cond'
|
||||
*/
|
||||
template<typename F>
|
||||
static ZT_ALWAYS_INLINE void generateSatisfying(F cond,uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN],uint8_t priv[ZT_C25519_PRIVATE_KEY_LEN])
|
||||
static inline void generateSatisfying(F cond,uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN],uint8_t priv[ZT_C25519_PRIVATE_KEY_LEN])
|
||||
{
|
||||
Utils::getSecureRandom(priv,ZT_C25519_PRIVATE_KEY_LEN);
|
||||
_calcPubED(pub,priv); // do Ed25519 key -- bytes 32-63 of pub and priv
|
||||
|
@ -7,8 +7,8 @@ endif(WIN32)
|
||||
|
||||
set(core_headers
|
||||
Address.hpp
|
||||
AES.hpp
|
||||
AtomicCounter.hpp
|
||||
Buf.hpp
|
||||
Buffer.hpp
|
||||
C25519.hpp
|
||||
Capability.hpp
|
||||
@ -29,6 +29,7 @@ set(core_headers
|
||||
Network.hpp
|
||||
NetworkConfig.hpp
|
||||
Node.hpp
|
||||
OS.hpp
|
||||
Packet.hpp
|
||||
Path.hpp
|
||||
Peer.hpp
|
||||
@ -50,13 +51,14 @@ set(core_headers
|
||||
|
||||
set(core_src
|
||||
AES.cpp
|
||||
AES-aesni.c
|
||||
Buf.cpp
|
||||
C25519.cpp
|
||||
Credential.cpp
|
||||
ECC384.cpp
|
||||
Identity.cpp
|
||||
IncomingPacket.cpp
|
||||
InetAddress.cpp
|
||||
Locator.cpp
|
||||
Membership.cpp
|
||||
Network.cpp
|
||||
NetworkConfig.cpp
|
||||
@ -69,23 +71,10 @@ set(core_src
|
||||
SelfAwareness.cpp
|
||||
SHA512.cpp
|
||||
Switch.cpp
|
||||
Trace.cpp
|
||||
Topology.cpp
|
||||
Utils.cpp
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${core_src} ${core_headers})
|
||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR})
|
||||
|
||||
#if(UNIX)
|
||||
# set_source_files_properties(
|
||||
# AES.cpp
|
||||
# AES-aesni.c
|
||||
# ECC384.cpp
|
||||
# Salsa20.cpp
|
||||
# C25519.cpp
|
||||
# Poly1305.cpp
|
||||
# PROPERTIES
|
||||
# COMPILE_FLAGS "-Wall -O3"
|
||||
# )
|
||||
#endif(UNIX)
|
||||
|
@ -14,9 +14,9 @@
|
||||
#ifndef ZT_CAPABILITY_HPP
|
||||
#define ZT_CAPABILITY_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
@ -61,7 +61,7 @@ class Capability : public Credential
|
||||
public:
|
||||
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_CAPABILITY; }
|
||||
|
||||
ZT_ALWAYS_INLINE Capability() :
|
||||
inline Capability() :
|
||||
_nwid(0),
|
||||
_ts(0),
|
||||
_id(0),
|
||||
@ -80,7 +80,7 @@ public:
|
||||
* @param rules Network flow rules for this capability
|
||||
* @param ruleCount Number of flow rules
|
||||
*/
|
||||
ZT_ALWAYS_INLINE Capability(uint32_t id,uint64_t nwid,int64_t ts,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) :
|
||||
inline Capability(uint32_t id,uint64_t nwid,int64_t ts,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) :
|
||||
_nwid(nwid),
|
||||
_ts(ts),
|
||||
_id(id),
|
||||
@ -94,32 +94,32 @@ public:
|
||||
/**
|
||||
* @return Rules -- see ruleCount() for size of array
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const ZT_VirtualNetworkRule *rules() const { return _rules; }
|
||||
inline const ZT_VirtualNetworkRule *rules() const { return _rules; }
|
||||
|
||||
/**
|
||||
* @return Number of rules in rules()
|
||||
*/
|
||||
ZT_ALWAYS_INLINE unsigned int ruleCount() const { return _ruleCount; }
|
||||
inline unsigned int ruleCount() const { return _ruleCount; }
|
||||
|
||||
/**
|
||||
* @return ID and evaluation order of this capability in network
|
||||
*/
|
||||
ZT_ALWAYS_INLINE uint32_t id() const { return _id; }
|
||||
inline uint32_t id() const { return _id; }
|
||||
|
||||
/**
|
||||
* @return Network ID for which this capability was issued
|
||||
*/
|
||||
ZT_ALWAYS_INLINE uint64_t networkId() const { return _nwid; }
|
||||
inline uint64_t networkId() const { return _nwid; }
|
||||
|
||||
/**
|
||||
* @return Timestamp
|
||||
*/
|
||||
ZT_ALWAYS_INLINE int64_t timestamp() const { return _ts; }
|
||||
inline int64_t timestamp() const { return _ts; }
|
||||
|
||||
/**
|
||||
* @return Last 'to' address in chain of custody
|
||||
*/
|
||||
ZT_ALWAYS_INLINE Address issuedTo() const
|
||||
inline Address issuedTo() const
|
||||
{
|
||||
Address i2;
|
||||
for(unsigned int i=0;i<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH;++i) {
|
||||
@ -165,7 +165,7 @@ public:
|
||||
*
|
||||
* @param RR Runtime environment to provide for peer lookup, etc.
|
||||
*/
|
||||
ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||
inline Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||
|
||||
template<unsigned int C>
|
||||
static inline void serializeRules(Buffer<C> &b,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount)
|
||||
@ -460,10 +460,10 @@ public:
|
||||
}
|
||||
|
||||
// Provides natural sort order by ID
|
||||
ZT_ALWAYS_INLINE bool operator<(const Capability &c) const { return (_id < c._id); }
|
||||
inline bool operator<(const Capability &c) const { return (_id < c._id); }
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) == 0); }
|
||||
ZT_ALWAYS_INLINE bool operator!=(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) != 0); }
|
||||
inline bool operator==(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) == 0); }
|
||||
inline bool operator!=(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) != 0); }
|
||||
|
||||
private:
|
||||
uint64_t _nwid;
|
||||
|
@ -14,8 +14,8 @@
|
||||
#ifndef ZT_CERTIFICATEOFMEMBERSHIP_HPP
|
||||
#define ZT_CERTIFICATEOFMEMBERSHIP_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
@ -69,7 +69,7 @@ class CertificateOfMembership : public Credential
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COM; }
|
||||
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COM; }
|
||||
|
||||
/**
|
||||
* Reserved qualifier IDs
|
||||
@ -101,7 +101,7 @@ public:
|
||||
/**
|
||||
* Create an empty certificate of membership
|
||||
*/
|
||||
ZT_ALWAYS_INLINE CertificateOfMembership() :
|
||||
inline CertificateOfMembership() :
|
||||
_qualifierCount(0),
|
||||
_signatureLength(0) {}
|
||||
|
||||
@ -113,7 +113,7 @@ public:
|
||||
* @param nwid Network ID
|
||||
* @param issuedTo Certificate recipient
|
||||
*/
|
||||
ZT_ALWAYS_INLINE CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo)
|
||||
inline CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo)
|
||||
{
|
||||
_qualifiers[0].id = COM_RESERVED_ID_TIMESTAMP;
|
||||
_qualifiers[0].value = timestamp;
|
||||
@ -135,22 +135,22 @@ public:
|
||||
* @param startAt Position to start in buffer
|
||||
*/
|
||||
template<unsigned int C>
|
||||
ZT_ALWAYS_INLINE CertificateOfMembership(const Buffer<C> &b,unsigned int startAt = 0) { deserialize(b,startAt); }
|
||||
inline CertificateOfMembership(const Buffer<C> &b,unsigned int startAt = 0) { deserialize(b,startAt); }
|
||||
|
||||
/**
|
||||
* @return True if there's something here
|
||||
*/
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (_qualifierCount != 0); }
|
||||
inline operator bool() const { return (_qualifierCount != 0); }
|
||||
|
||||
/**
|
||||
* @return Credential ID, always 0 for COMs
|
||||
*/
|
||||
ZT_ALWAYS_INLINE uint32_t id() const { return 0; }
|
||||
inline uint32_t id() const { return 0; }
|
||||
|
||||
/**
|
||||
* @return Timestamp for this cert and maximum delta for timestamp
|
||||
*/
|
||||
ZT_ALWAYS_INLINE int64_t timestamp() const
|
||||
inline int64_t timestamp() const
|
||||
{
|
||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||
if (_qualifiers[i].id == COM_RESERVED_ID_TIMESTAMP)
|
||||
@ -162,7 +162,7 @@ public:
|
||||
/**
|
||||
* @return Address to which this cert was issued
|
||||
*/
|
||||
ZT_ALWAYS_INLINE Address issuedTo() const
|
||||
inline Address issuedTo() const
|
||||
{
|
||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||
if (_qualifiers[i].id == COM_RESERVED_ID_ISSUED_TO)
|
||||
@ -174,7 +174,7 @@ public:
|
||||
/**
|
||||
* @return Network ID for which this cert was issued
|
||||
*/
|
||||
ZT_ALWAYS_INLINE uint64_t networkId() const
|
||||
inline uint64_t networkId() const
|
||||
{
|
||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||
if (_qualifiers[i].id == COM_RESERVED_ID_NETWORK_ID)
|
||||
@ -211,7 +211,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE void setQualifier(ReservedId id,uint64_t value,uint64_t maxDelta) { setQualifier((uint64_t)id,value,maxDelta); }
|
||||
inline void setQualifier(ReservedId id,uint64_t value,uint64_t maxDelta) { setQualifier((uint64_t)id,value,maxDelta); }
|
||||
|
||||
/**
|
||||
* Compare two certificates for parameter agreement
|
||||
@ -294,17 +294,17 @@ public:
|
||||
* @param RR Runtime environment for looking up peers
|
||||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
||||
*/
|
||||
ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||
inline Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||
|
||||
/**
|
||||
* @return True if signed
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool isSigned() const { return (_signedBy); }
|
||||
inline bool isSigned() const { return (_signedBy); }
|
||||
|
||||
/**
|
||||
* @return Address that signed this certificate or null address if none
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const Address &signedBy() const { return _signedBy; }
|
||||
inline const Address &signedBy() const { return _signedBy; }
|
||||
|
||||
template<unsigned int C>
|
||||
inline void serialize(Buffer<C> &b) const
|
||||
@ -369,7 +369,7 @@ public:
|
||||
return (p - startAt);
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const CertificateOfMembership &c) const
|
||||
inline bool operator==(const CertificateOfMembership &c) const
|
||||
{
|
||||
if (_signedBy != c._signedBy)
|
||||
return false;
|
||||
@ -385,7 +385,7 @@ public:
|
||||
}
|
||||
return (memcmp(_signature,c._signature,_signatureLength) == 0);
|
||||
}
|
||||
ZT_ALWAYS_INLINE bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); }
|
||||
inline bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); }
|
||||
|
||||
private:
|
||||
struct _Qualifier
|
||||
|
@ -14,10 +14,10 @@
|
||||
#ifndef ZT_CERTIFICATEOFOWNERSHIP_HPP
|
||||
#define ZT_CERTIFICATEOFOWNERSHIP_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
@ -46,7 +46,7 @@ class CertificateOfOwnership : public Credential
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COO; }
|
||||
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COO; }
|
||||
|
||||
enum Thing
|
||||
{
|
||||
@ -56,12 +56,12 @@ public:
|
||||
THING_IPV6_ADDRESS = 3
|
||||
};
|
||||
|
||||
ZT_ALWAYS_INLINE CertificateOfOwnership()
|
||||
inline CertificateOfOwnership()
|
||||
{
|
||||
memset(reinterpret_cast<void *>(this),0,sizeof(CertificateOfOwnership));
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id)
|
||||
inline CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id)
|
||||
{
|
||||
memset(reinterpret_cast<void *>(this),0,sizeof(CertificateOfOwnership));
|
||||
_networkId = nwid;
|
||||
@ -70,19 +70,19 @@ public:
|
||||
_issuedTo = issuedTo;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE uint64_t networkId() const { return _networkId; }
|
||||
ZT_ALWAYS_INLINE int64_t timestamp() const { return _ts; }
|
||||
ZT_ALWAYS_INLINE uint32_t id() const { return _id; }
|
||||
ZT_ALWAYS_INLINE const Address &issuedTo() const { return _issuedTo; }
|
||||
ZT_ALWAYS_INLINE const Address &signer() const { return _signedBy; }
|
||||
ZT_ALWAYS_INLINE const uint8_t *signature() const { return _signature; }
|
||||
ZT_ALWAYS_INLINE unsigned int signatureLength() const { return _signatureLength; }
|
||||
inline uint64_t networkId() const { return _networkId; }
|
||||
inline int64_t timestamp() const { return _ts; }
|
||||
inline uint32_t id() const { return _id; }
|
||||
inline const Address &issuedTo() const { return _issuedTo; }
|
||||
inline const Address &signer() const { return _signedBy; }
|
||||
inline const uint8_t *signature() const { return _signature; }
|
||||
inline unsigned int signatureLength() const { return _signatureLength; }
|
||||
|
||||
ZT_ALWAYS_INLINE unsigned int thingCount() const { return (unsigned int)_thingCount; }
|
||||
ZT_ALWAYS_INLINE Thing thingType(const unsigned int i) const { return (Thing)_thingTypes[i]; }
|
||||
ZT_ALWAYS_INLINE const uint8_t *thingValue(const unsigned int i) const { return _thingValues[i]; }
|
||||
inline unsigned int thingCount() const { return (unsigned int)_thingCount; }
|
||||
inline Thing thingType(const unsigned int i) const { return (Thing)_thingTypes[i]; }
|
||||
inline const uint8_t *thingValue(const unsigned int i) const { return _thingValues[i]; }
|
||||
|
||||
ZT_ALWAYS_INLINE bool owns(const InetAddress &ip) const
|
||||
inline bool owns(const InetAddress &ip) const
|
||||
{
|
||||
if (ip.ss_family == AF_INET)
|
||||
return this->_owns(THING_IPV4_ADDRESS,&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4);
|
||||
@ -91,7 +91,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE bool owns(const MAC &mac) const
|
||||
inline bool owns(const MAC &mac) const
|
||||
{
|
||||
uint8_t tmp[6];
|
||||
mac.copyTo(tmp,6);
|
||||
@ -136,7 +136,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||
inline Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
|
||||
|
||||
template<unsigned int C>
|
||||
inline void serialize(Buffer<C> &b,const bool forSign = false) const
|
||||
@ -206,10 +206,10 @@ public:
|
||||
}
|
||||
|
||||
// Provides natural sort order by ID
|
||||
ZT_ALWAYS_INLINE bool operator<(const CertificateOfOwnership &coo) const { return (_id < coo._id); }
|
||||
inline bool operator<(const CertificateOfOwnership &coo) const { return (_id < coo._id); }
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) == 0); }
|
||||
ZT_ALWAYS_INLINE bool operator!=(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) != 0); }
|
||||
inline bool operator==(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) == 0); }
|
||||
inline bool operator!=(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) != 0); }
|
||||
|
||||
private:
|
||||
inline bool _owns(const Thing &t,const void *v,unsigned int l) const
|
||||
|
@ -14,11 +14,8 @@
|
||||
#ifndef ZT_CONSTANTS_HPP
|
||||
#define ZT_CONSTANTS_HPP
|
||||
|
||||
/****************************************************************************/
|
||||
/* Core includes and OS/platform setup stuff */
|
||||
/****************************************************************************/
|
||||
|
||||
#include "../include/ZeroTierCore.h"
|
||||
#include "OS.hpp"
|
||||
|
||||
#if __has_include("version.h")
|
||||
#include "version.h"
|
||||
@ -29,187 +26,25 @@
|
||||
#define ZEROTIER_ONE_VERSION_BUILD 255
|
||||
#endif
|
||||
|
||||
//
|
||||
// This include file also auto-detects and canonicalizes some environment
|
||||
// information defines:
|
||||
//
|
||||
// __LINUX__
|
||||
// __APPLE__
|
||||
// __BSD__ (OSX also defines this)
|
||||
// __UNIX_LIKE__ (Linux, BSD, etc.)
|
||||
// __WINDOWS__
|
||||
//
|
||||
// Also makes sure __BYTE_ORDER is defined reasonably.
|
||||
//
|
||||
|
||||
// Hack: make sure __GCC__ is defined on old GCC compilers
|
||||
#ifndef __GCC__
|
||||
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
|
||||
#define __GCC__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux)
|
||||
#ifndef __LINUX__
|
||||
#define __LINUX__
|
||||
#endif
|
||||
#ifndef __UNIX_LIKE__
|
||||
#define __UNIX_LIKE__
|
||||
#endif
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#ifndef __UNIX_LIKE__
|
||||
#define __UNIX_LIKE__
|
||||
#endif
|
||||
#ifndef __BSD__
|
||||
#define __BSD__
|
||||
#endif
|
||||
#include <machine/endian.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
#ifndef __UNIX_LIKE__
|
||||
#define __UNIX_LIKE__
|
||||
#endif
|
||||
#ifndef __BSD__
|
||||
#define __BSD__
|
||||
#endif
|
||||
#include <sys/endian.h>
|
||||
#ifndef __BYTE_ORDER
|
||||
#define __BYTE_ORDER _BYTE_ORDER
|
||||
#define __LITTLE_ENDIAN _LITTLE_ENDIAN
|
||||
#define __BIG_ENDIAN _BIG_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#ifndef __WINDOWS__
|
||||
#define __WINDOWS__
|
||||
#endif
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#pragma warning(disable : 4290)
|
||||
#pragma warning(disable : 4996)
|
||||
#pragma warning(disable : 4101)
|
||||
#undef __UNIX_LIKE__
|
||||
#undef __BSD__
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#ifndef RTF_MULTICAST
|
||||
#define RTF_MULTICAST 0x20000000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Define ZT_NO_TYPE_PUNNING to disable reckless casts on anything other than x86 and x86_64.
|
||||
#if (!(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__386)))
|
||||
#ifndef ZT_NO_TYPE_PUNNING
|
||||
#define ZT_NO_TYPE_PUNNING
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Assume little endian if not defined on Mac and Windows as these don't run on any BE architectures.
|
||||
#if (defined(__APPLE__) || defined(__WINDOWS__)) && (!defined(__BYTE_ORDER))
|
||||
#undef __BYTE_ORDER
|
||||
#undef __LITTLE_ENDIAN
|
||||
#undef __BIG_ENDIAN
|
||||
#define __BIG_ENDIAN 4321
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#define __BYTE_ORDER 1234
|
||||
#endif
|
||||
#ifndef __BYTE_ORDER
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#define ZT_PATH_SEPARATOR '\\'
|
||||
#define ZT_PATH_SEPARATOR_S "\\"
|
||||
#define ZT_EOL_S "\r\n"
|
||||
#else
|
||||
#define ZT_PATH_SEPARATOR '/'
|
||||
#define ZT_PATH_SEPARATOR_S "/"
|
||||
#define ZT_EOL_S "\n"
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
|
||||
#define ZT_ALWAYS_INLINE inline __attribute__((always_inline))
|
||||
#ifndef likely
|
||||
#define likely(x) __builtin_expect((x),1)
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(x) __builtin_expect((x),0)
|
||||
#endif
|
||||
#else
|
||||
#ifndef likely
|
||||
#define ZT_ALWAYS_INLINE inline
|
||||
#define likely(x) (x)
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__WINDOWS__) && !defined(__GNUC__) && !defined (__clang__) && !defined(__INTEL_COMPILER)
|
||||
#define ZT_PACKED_STRUCT(D) __pragma(pack(push,1)) D __pragma(pack(pop))
|
||||
#else
|
||||
#define ZT_PACKED_STRUCT(D) D __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#if __cplusplus > 199711L
|
||||
#ifndef __CPP11__
|
||||
#define __CPP11__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SOCKET
|
||||
#define ZT_SOCKET SOCKET
|
||||
#else
|
||||
#define ZT_SOCKET int
|
||||
#endif
|
||||
#ifdef INVALID_SOCKET
|
||||
#define ZT_INVALID_SOCKET INVALID_SOCKET
|
||||
#else
|
||||
#define ZT_INVALID_SOCKET -1
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/* Internal ZeroTier constants */
|
||||
/****************************************************************************/
|
||||
|
||||
/**
|
||||
* Length of a ZeroTier address in bytes
|
||||
*/
|
||||
#define ZT_ADDRESS_LENGTH 5
|
||||
|
||||
/**
|
||||
* Length of a hexadecimal ZeroTier address
|
||||
*/
|
||||
#define ZT_ADDRESS_LENGTH_HEX 10
|
||||
|
||||
/**
|
||||
* Addresses beginning with this byte are reserved for the joy of in-band signaling
|
||||
*/
|
||||
#define ZT_ADDRESS_RESERVED_PREFIX 0xff
|
||||
|
||||
/**
|
||||
* Secure DNS name for ZeroTier's default root
|
||||
*
|
||||
* This resolves via GeoDNS to the (probably) nearest actual root server's locator.
|
||||
* Maximum DNS or URL name size for an Endpoint (set so that max marshaled endpoint size is 64 bytes)
|
||||
*/
|
||||
#define ZT_DEFAULT_ROOT_NAME "ztl-aj4zes4l6zumq64na6borruuvd6diw2koxrjcaatolcekt2gj5rrhric.ztl-6lhxeo7n3z7kzkgcqzj3ndliaq.zerotier.network"
|
||||
#define ZT_ENDPOINT_MAX_NAME_SIZE 61
|
||||
|
||||
/**
|
||||
* Default locator for default root
|
||||
*
|
||||
* This is used before the root has been successfully fetched, or if DNS is unavailable.
|
||||
* Size of an identity hash (SHA384)
|
||||
*/
|
||||
#define ZT_DEFAULT_ROOT_LOCATOR "AAAAAW2OuYyfOkbxvzAAduZvqzPihUmmLuIGTRhDJzwsMAukXD8gvvAtutIlcju1mpu0sTU1cwlhruz1oWOs5HfM6wcnAluZrBSlFmoJowAEBLm0DVInCQS5tA1SAbsGKgJuoMgVAAAAAAAAAAAAACcJBioCbqDIFQAAAAAAAAAAAAABuwAAYDvTNB2snbn7TYom4PBTh/ohRgCnI2/A/nfKakGCb+2hGJTtxTCiGTzKZdbjd0vyKAKQLJxhj7RaoCo3XjPn8w9nDEmhdNCgCM/IITCJIzc9tEKFsSQnJY4VmB3dopBAfQAA"
|
||||
#define ZT_IDENTITY_HASH_SIZE 48
|
||||
|
||||
/**
|
||||
* Default virtual network MTU (not physical)
|
||||
@ -282,246 +117,34 @@
|
||||
#define ZT_RELAY_MAX_HOPS 4
|
||||
|
||||
/**
|
||||
* Expire time for multicast 'likes' and indirect multicast memberships in ms
|
||||
*/
|
||||
#define ZT_MULTICAST_LIKE_EXPIRE 600000
|
||||
|
||||
/**
|
||||
* Period for multicast LIKE re-announcements to connected nodes
|
||||
*/
|
||||
#define ZT_MULTICAST_ANNOUNCE_PERIOD 60000
|
||||
|
||||
/**
|
||||
* Period for multicast GATHER on multicast groups
|
||||
*/
|
||||
#define ZT_MULTICAST_GATHER_PERIOD ZT_MULTICAST_ANNOUNCE_PERIOD
|
||||
|
||||
/**
|
||||
* Period for multicast GATHER if there are no known recipients
|
||||
*/
|
||||
#define ZT_MULTICAST_GATHER_PERIOD_WHEN_NO_RECIPIENTS 2500
|
||||
|
||||
/**
|
||||
* Timeout for outgoing multicasts
|
||||
*
|
||||
* This is how long we wait for explicit or implicit gather results.
|
||||
*/
|
||||
#define ZT_MULTICAST_TRANSMIT_TIMEOUT 5000
|
||||
|
||||
/**
|
||||
* How frequently to check for changes to the system's network interfaces. When
|
||||
* the service decides to use this constant it's because we want to react more
|
||||
* quickly to new interfaces that pop up or go down.
|
||||
*/
|
||||
#define ZT_MULTIPATH_BINDER_REFRESH_PERIOD 5000
|
||||
|
||||
/**
|
||||
* Packets are only used for QoS/ACK statistical sampling if their packet ID is divisible by
|
||||
* this integer. This is to provide a mechanism for both peers to agree on which packets need
|
||||
* special treatment without having to exchange information. Changing this value would be
|
||||
* a breaking change and would necessitate a protocol version upgrade. Since each incoming and
|
||||
* outgoing packet ID is checked against this value its evaluation is of the form:
|
||||
* (id & (divisor - 1)) == 0, thus the divisor must be a power of 2.
|
||||
*
|
||||
* This value is set at (16) so that given a normally-distributed RNG output we will sample
|
||||
* 1/16th (or ~6.25%) of packets.
|
||||
*/
|
||||
#define ZT_PATH_QOS_ACK_PROTOCOL_DIVISOR 0x10
|
||||
|
||||
/**
|
||||
* Time horizon for VERB_QOS_MEASUREMENT and VERB_ACK packet processing cutoff
|
||||
*/
|
||||
#define ZT_PATH_QOS_ACK_CUTOFF_TIME 30000
|
||||
|
||||
/**
|
||||
* Maximum number of VERB_QOS_MEASUREMENT and VERB_ACK packets allowed to be
|
||||
* processed within cutoff time. Separate totals are kept for each type but
|
||||
* the limit is the same for both.
|
||||
*
|
||||
* This limits how often this peer will compute statistical estimates
|
||||
* of various QoS measures from a VERB_QOS_MEASUREMENT or VERB_ACK packets to
|
||||
* CUTOFF_LIMIT times per CUTOFF_TIME milliseconds per peer to prevent
|
||||
* this from being useful for DOS amplification attacks.
|
||||
*/
|
||||
#define ZT_PATH_QOS_ACK_CUTOFF_LIMIT 128
|
||||
|
||||
/**
|
||||
* Path choice history window size. This is used to keep track of which paths were
|
||||
* previously selected so that we can maintain a target allocation over time.
|
||||
*/
|
||||
#define ZT_MULTIPATH_PROPORTION_WIN_SZ 128
|
||||
|
||||
/**
|
||||
* Interval used for rate-limiting the computation of path quality estimates.
|
||||
*/
|
||||
#define ZT_PATH_QUALITY_COMPUTE_INTERVAL 1000
|
||||
|
||||
/**
|
||||
* Number of samples to consider when computing real-time path statistics
|
||||
*/
|
||||
#define ZT_PATH_QUALITY_METRIC_REALTIME_CONSIDERATION_WIN_SZ 128
|
||||
|
||||
/**
|
||||
* Number of samples to consider when computing performing long-term path quality analysis.
|
||||
* By default this value is set to ZT_PATH_QUALITY_METRIC_REALTIME_CONSIDERATION_WIN_SZ but can
|
||||
* be set to any value greater than that to observe longer-term path quality behavior.
|
||||
*/
|
||||
#define ZT_PATH_QUALITY_METRIC_WIN_SZ ZT_PATH_QUALITY_METRIC_REALTIME_CONSIDERATION_WIN_SZ
|
||||
|
||||
/**
|
||||
* Maximum acceptable Packet Delay Variance (PDV) over a path
|
||||
*/
|
||||
#define ZT_PATH_MAX_PDV 1000
|
||||
|
||||
/**
|
||||
* Maximum acceptable time interval between expectation and receipt of at least one ACK over a path
|
||||
*/
|
||||
#define ZT_PATH_MAX_AGE 30000
|
||||
|
||||
/**
|
||||
* Maximum acceptable mean latency over a path
|
||||
*/
|
||||
#define ZT_PATH_MAX_MEAN_LATENCY 1000
|
||||
|
||||
/**
|
||||
* How much each factor contributes to the "stability" score of a path
|
||||
*/
|
||||
#define ZT_PATH_CONTRIB_PDV (1.0 / 3.0)
|
||||
#define ZT_PATH_CONTRIB_LATENCY (1.0 / 3.0)
|
||||
#define ZT_PATH_CONTRIB_THROUGHPUT_DISTURBANCE (1.0 / 3.0)
|
||||
|
||||
/**
|
||||
* How much each factor contributes to the "quality" score of a path
|
||||
*/
|
||||
#define ZT_PATH_CONTRIB_STABILITY (0.75 / 3.0)
|
||||
#define ZT_PATH_CONTRIB_THROUGHPUT (1.50 / 3.0)
|
||||
#define ZT_PATH_CONTRIB_SCOPE (0.75 / 3.0)
|
||||
|
||||
/**
|
||||
* How often a QoS packet is sent
|
||||
*/
|
||||
#define ZT_PATH_QOS_INTERVAL 3000
|
||||
|
||||
/**
|
||||
* Min and max acceptable sizes for a VERB_QOS_MEASUREMENT packet
|
||||
*/
|
||||
#define ZT_PATH_MIN_QOS_PACKET_SZ 8 + 1
|
||||
#define ZT_PATH_MAX_QOS_PACKET_SZ 1400
|
||||
|
||||
/**
|
||||
* How many ID:sojourn time pairs in a single QoS packet
|
||||
*/
|
||||
#define ZT_PATH_QOS_TABLE_SIZE ((ZT_PATH_MAX_QOS_PACKET_SZ * 8) / (64 + 16))
|
||||
|
||||
/**
|
||||
* Maximum number of outgoing packets we monitor for QoS information
|
||||
*/
|
||||
#define ZT_PATH_MAX_OUTSTANDING_QOS_RECORDS 128
|
||||
|
||||
/**
|
||||
* Timeout for QoS records
|
||||
*/
|
||||
#define ZT_PATH_QOS_TIMEOUT (ZT_PATH_QOS_INTERVAL * 2)
|
||||
|
||||
/**
|
||||
* How often the service tests the path throughput
|
||||
*/
|
||||
#define ZT_PATH_THROUGHPUT_MEASUREMENT_INTERVAL (ZT_PATH_ACK_INTERVAL * 8)
|
||||
|
||||
/**
|
||||
* Minimum amount of time between each ACK packet
|
||||
*/
|
||||
#define ZT_PATH_ACK_INTERVAL 1000
|
||||
|
||||
/**
|
||||
* How often an aggregate link statistics report is emitted into this tracing system
|
||||
*/
|
||||
#define ZT_PATH_AGGREGATE_STATS_REPORT_INTERVAL 60000
|
||||
|
||||
/**
|
||||
* How much an aggregate link's component paths can vary from their target allocation
|
||||
* before the link is considered to be in a state of imbalance.
|
||||
*/
|
||||
#define ZT_PATH_IMBALANCE_THRESHOLD 0.20
|
||||
|
||||
/**
|
||||
* Max allowable time spent in any queue
|
||||
*/
|
||||
#define ZT_QOS_TARGET 5 // ms
|
||||
|
||||
/**
|
||||
* Time period where the time spent in the queue by a packet should fall below
|
||||
* target at least once
|
||||
*/
|
||||
#define ZT_QOS_INTERVAL 100 // ms
|
||||
|
||||
/**
|
||||
* The number of bytes that each queue is allowed to send during each DRR cycle.
|
||||
* This approximates a single-byte-based fairness queuing scheme
|
||||
*/
|
||||
#define ZT_QOS_QUANTUM ZT_DEFAULT_MTU
|
||||
|
||||
/**
|
||||
* The maximum total number of packets that can be queued among all
|
||||
* active/inactive, old/new queues
|
||||
*/
|
||||
#define ZT_QOS_MAX_ENQUEUED_PACKETS 1024
|
||||
|
||||
/**
|
||||
* Number of QoS queues (buckets)
|
||||
*/
|
||||
#define ZT_QOS_NUM_BUCKETS 9
|
||||
|
||||
/**
|
||||
* All unspecified traffic is put in this bucket. Anything in a bucket with a smaller
|
||||
* value is de-prioritized. Anything in a bucket with a higher value is prioritized over
|
||||
* other traffic.
|
||||
*/
|
||||
#define ZT_QOS_DEFAULT_BUCKET 0
|
||||
|
||||
/**
|
||||
* Do not accept HELLOs over a given path more often than this
|
||||
*/
|
||||
#define ZT_PATH_HELLO_RATE_LIMIT 1000
|
||||
|
||||
/**
|
||||
* Delay between full-fledge pings of directly connected peers
|
||||
* Period between keepalives sent to paths if no other traffic has been sent
|
||||
*
|
||||
* See https://conferences.sigcomm.org/imc/2010/papers/p260.pdf for
|
||||
* some real world data on NAT UDP timeouts. From the paper: "the
|
||||
* lowest measured timeout when a binding has seen bidirectional
|
||||
* traffic is 54 sec." 30 seconds is faster than really necessary.
|
||||
*/
|
||||
#define ZT_PEER_PING_PERIOD 30000
|
||||
#define ZT_PATH_KEEPALIVE_PERIOD 30000
|
||||
|
||||
/**
|
||||
* Delay between refreshes of locators via DNS or other methods
|
||||
* Timeout for path aliveness (measured from last receive)
|
||||
*/
|
||||
#define ZT_DYNAMIC_ROOT_UPDATE_PERIOD 120000
|
||||
#define ZT_PATH_ACTIVITY_TIMEOUT ((ZT_PATH_KEEPALIVE_PERIOD * 2) + 5000)
|
||||
|
||||
/**
|
||||
* Delay between full HELLO messages between peers
|
||||
*/
|
||||
#define ZT_PEER_PING_PERIOD 60000
|
||||
|
||||
/**
|
||||
* Timeout for overall peer activity (measured from last receive)
|
||||
*/
|
||||
#ifndef ZT_SDK
|
||||
#define ZT_PEER_ACTIVITY_TIMEOUT 500000
|
||||
#else
|
||||
#define ZT_PEER_ACTIVITY_TIMEOUT 30000
|
||||
#endif
|
||||
#define ZT_PEER_ACTIVITY_TIMEOUT ((ZT_PEER_PING_PERIOD * 2) + 5000)
|
||||
|
||||
/**
|
||||
* Rescan for best/fastest root every N milliseconds
|
||||
* Maximum interval between sort/prioritize of paths for a peer
|
||||
*/
|
||||
#define ZT_FIND_BEST_ROOT_PERIOD 2000
|
||||
|
||||
/**
|
||||
* General rate limit timeout for multiple packet types (HELLO, etc.)
|
||||
*/
|
||||
#define ZT_PEER_GENERAL_INBOUND_RATE_LIMIT 500
|
||||
|
||||
/**
|
||||
* General limit for max RTT for requests over the network
|
||||
*/
|
||||
#define ZT_GENERAL_RTT_LIMIT 5000
|
||||
#define ZT_PEER_PRIORITIZE_PATHS_INTERVAL 5000
|
||||
|
||||
/**
|
||||
* Delay between requests for updated network autoconf information
|
||||
@ -531,15 +154,6 @@
|
||||
*/
|
||||
#define ZT_NETWORK_AUTOCONF_DELAY 60000
|
||||
|
||||
/**
|
||||
* Minimum interval between attempts by relays to unite peers
|
||||
*
|
||||
* When a relay gets a packet destined for another peer, it sends both peers
|
||||
* a RENDEZVOUS message no more than this often. This instructs the peers
|
||||
* to attempt NAT-t and gives each the other's corresponding IP:port pair.
|
||||
*/
|
||||
#define ZT_MIN_UNITE_INTERVAL 30000
|
||||
|
||||
/**
|
||||
* Sanity limit on maximum bridge routes
|
||||
*
|
||||
@ -566,34 +180,10 @@
|
||||
*/
|
||||
#define ZT_DIRECT_PATH_PUSH_INTERVAL_HAVEPATH 120000
|
||||
|
||||
/**
|
||||
* Time horizon for push direct paths cutoff
|
||||
*/
|
||||
#define ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME 30000
|
||||
|
||||
/**
|
||||
* Maximum number of direct path pushes within cutoff time
|
||||
*
|
||||
* This limits response to PUSH_DIRECT_PATHS to CUTOFF_LIMIT responses
|
||||
* per CUTOFF_TIME milliseconds per peer to prevent this from being
|
||||
* useful for DOS amplification attacks.
|
||||
*/
|
||||
#define ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT 8
|
||||
|
||||
/**
|
||||
* Maximum number of paths per IP scope (e.g. global, link-local) and family (e.g. v4/v6)
|
||||
*/
|
||||
#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 8
|
||||
|
||||
/**
|
||||
* Time horizon for VERB_NETWORK_CREDENTIALS cutoff
|
||||
*/
|
||||
#define ZT_PEER_CREDENTIALS_CUTOFF_TIME 60000
|
||||
|
||||
/**
|
||||
* Maximum number of VERB_NETWORK_CREDENTIALS within cutoff time
|
||||
*/
|
||||
#define ZT_PEER_CREDEITIALS_CUTOFF_LIMIT 15
|
||||
#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 4
|
||||
|
||||
/**
|
||||
* WHOIS rate limit (we allow these to be pretty fast)
|
||||
@ -632,12 +222,7 @@
|
||||
*/
|
||||
#define ZT_SIGNATURE_BUFFER_SIZE 96
|
||||
|
||||
/**
|
||||
* Desired / recommended min stack size for threads (used on some platforms to reset thread stack size)
|
||||
*/
|
||||
#define ZT_THREAD_MIN_STACK_SIZE 1048576
|
||||
|
||||
// Internal cryptographic algorithm IDs
|
||||
// Internal cryptographic algorithm IDs (these match relevant identity types)
|
||||
#define ZT_CRYPTO_ALG_C25519 0
|
||||
#define ZT_CRYPTO_ALG_P384 1
|
||||
|
||||
@ -651,4 +236,9 @@
|
||||
#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN 202
|
||||
#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING 203
|
||||
|
||||
/* Ethernet frame types that might be relevant to us */
|
||||
#define ZT_ETHERTYPE_IPV4 0x0800
|
||||
#define ZT_ETHERTYPE_ARP 0x0806
|
||||
#define ZT_ETHERTYPE_IPV6 0x86dd
|
||||
|
||||
#endif
|
||||
|
@ -26,7 +26,7 @@
|
||||
namespace ZeroTier {
|
||||
|
||||
template<typename CRED>
|
||||
static ZT_ALWAYS_INLINE Credential::VerifyResult _credVerify(const RuntimeEnvironment *const RR,void *tPtr,CRED credential)
|
||||
static inline Credential::VerifyResult _credVerify(const RuntimeEnvironment *const RR,void *tPtr,CRED credential)
|
||||
{
|
||||
const Address signedBy(credential.signer());
|
||||
const uint64_t networkId = credential.networkId();
|
||||
|
@ -18,10 +18,10 @@
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "Constants.hpp"
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "Buffer.hpp"
|
||||
#include "Address.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
@ -49,9 +49,9 @@ template<unsigned int C>
|
||||
class Dictionary
|
||||
{
|
||||
public:
|
||||
ZT_ALWAYS_INLINE Dictionary() { memset(_d,0,sizeof(_d)); }
|
||||
ZT_ALWAYS_INLINE Dictionary(const char *s) { this->load(s); }
|
||||
ZT_ALWAYS_INLINE Dictionary(const char *s,unsigned int len)
|
||||
inline Dictionary() { memset(_d,0,sizeof(_d)); }
|
||||
inline Dictionary(const char *s) { this->load(s); }
|
||||
inline Dictionary(const char *s,unsigned int len)
|
||||
{
|
||||
for(unsigned int i=0;i<C;++i) {
|
||||
if ((s)&&(i < len)) {
|
||||
@ -62,15 +62,15 @@ public:
|
||||
}
|
||||
_d[C - 1] = (char)0;
|
||||
}
|
||||
ZT_ALWAYS_INLINE Dictionary(const Dictionary &d) { memcpy(_d,d._d,C); }
|
||||
inline Dictionary(const Dictionary &d) { memcpy(_d,d._d,C); }
|
||||
|
||||
ZT_ALWAYS_INLINE Dictionary &operator=(const Dictionary &d)
|
||||
inline Dictionary &operator=(const Dictionary &d)
|
||||
{
|
||||
memcpy(_d,d._d,C);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (_d[0] != 0); }
|
||||
inline operator bool() const { return (_d[0] != 0); }
|
||||
|
||||
/**
|
||||
* Load a dictionary from a C-string
|
||||
@ -78,7 +78,7 @@ public:
|
||||
* @param s Dictionary in string form
|
||||
* @return False if 's' was longer than our capacity
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool load(const char *s)
|
||||
inline bool load(const char *s)
|
||||
{
|
||||
for(unsigned int i=0;i<C;++i) {
|
||||
if (s) {
|
||||
@ -94,12 +94,12 @@ public:
|
||||
/**
|
||||
* Delete all entries
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void clear() { memset(_d,0,sizeof(_d)); }
|
||||
inline void clear() { memset(_d,0,sizeof(_d)); }
|
||||
|
||||
/**
|
||||
* @return Size of dictionary in bytes not including terminating NULL
|
||||
*/
|
||||
ZT_ALWAYS_INLINE unsigned int sizeBytes() const
|
||||
inline unsigned int sizeBytes() const
|
||||
{
|
||||
for(unsigned int i=0;i<C;++i) {
|
||||
if (!_d[i])
|
||||
@ -217,7 +217,7 @@ public:
|
||||
* @tparam BC Buffer capacity (usually inferred)
|
||||
*/
|
||||
template<unsigned int BC>
|
||||
ZT_ALWAYS_INLINE bool get(const char *key,Buffer<BC> &dest) const
|
||||
inline bool get(const char *key,Buffer<BC> &dest) const
|
||||
{
|
||||
const int r = this->get(key,const_cast<char *>(reinterpret_cast<const char *>(dest.data())),BC);
|
||||
if (r >= 0) {
|
||||
@ -236,7 +236,7 @@ public:
|
||||
* @param dfl Default value if not found in dictionary
|
||||
* @return Boolean value of key or 'dfl' if not found
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool getB(const char *key,bool dfl = false) const
|
||||
inline bool getB(const char *key,bool dfl = false) const
|
||||
{
|
||||
char tmp[4];
|
||||
if (this->get(key,tmp,sizeof(tmp)) >= 0)
|
||||
@ -251,7 +251,7 @@ public:
|
||||
* @param dfl Default value or 0 if unspecified
|
||||
* @return Decoded hex UInt value or 'dfl' if not found
|
||||
*/
|
||||
ZT_ALWAYS_INLINE uint64_t getUI(const char *key,uint64_t dfl = 0) const
|
||||
inline uint64_t getUI(const char *key,uint64_t dfl = 0) const
|
||||
{
|
||||
char tmp[128];
|
||||
if (this->get(key,tmp,sizeof(tmp)) >= 1)
|
||||
@ -266,7 +266,7 @@ public:
|
||||
* @param dfl Default value or 0 if unspecified
|
||||
* @return Decoded hex UInt value or 'dfl' if not found
|
||||
*/
|
||||
ZT_ALWAYS_INLINE int64_t getI(const char *key,int64_t dfl = 0) const
|
||||
inline int64_t getI(const char *key,int64_t dfl = 0) const
|
||||
{
|
||||
char tmp[128];
|
||||
if (this->get(key,tmp,sizeof(tmp)) >= 1)
|
||||
@ -366,7 +366,7 @@ public:
|
||||
/**
|
||||
* Add a boolean as a '1' or a '0'
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool add(const char *key,bool value)
|
||||
inline bool add(const char *key,bool value)
|
||||
{
|
||||
return this->add(key,(value) ? "1" : "0",1);
|
||||
}
|
||||
@ -374,7 +374,7 @@ public:
|
||||
/**
|
||||
* Add a 64-bit integer (unsigned) as a hex value
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool add(const char *key,uint64_t value)
|
||||
inline bool add(const char *key,uint64_t value)
|
||||
{
|
||||
char tmp[32];
|
||||
return this->add(key,Utils::hex(value,tmp),-1);
|
||||
@ -383,7 +383,7 @@ public:
|
||||
/**
|
||||
* Add a 64-bit integer (unsigned) as a hex value
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool add(const char *key,int64_t value)
|
||||
inline bool add(const char *key,int64_t value)
|
||||
{
|
||||
char tmp[32];
|
||||
if (value >= 0) {
|
||||
@ -397,7 +397,7 @@ public:
|
||||
/**
|
||||
* Add a 64-bit integer (unsigned) as a hex value
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool add(const char *key,const Address &a)
|
||||
inline bool add(const char *key,const Address &a)
|
||||
{
|
||||
char tmp[32];
|
||||
return this->add(key,Utils::hex(a.toInt(),tmp),-1);
|
||||
@ -409,7 +409,7 @@ public:
|
||||
* @tparam BC Buffer capacity (usually inferred)
|
||||
*/
|
||||
template<unsigned int BC>
|
||||
ZT_ALWAYS_INLINE bool add(const char *key,const Buffer<BC> &value)
|
||||
inline bool add(const char *key,const Buffer<BC> &value)
|
||||
{
|
||||
return this->add(key,(const char *)value.data(),(int)value.size());
|
||||
}
|
||||
@ -418,7 +418,7 @@ public:
|
||||
* @param key Key to check
|
||||
* @return True if key is present
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool contains(const char *key) const
|
||||
inline bool contains(const char *key) const
|
||||
{
|
||||
char tmp[2];
|
||||
return (this->get(key,tmp,2) >= 0);
|
||||
@ -427,10 +427,10 @@ public:
|
||||
/**
|
||||
* @return Value of C template parameter
|
||||
*/
|
||||
ZT_ALWAYS_INLINE unsigned int capacity() const { return C; }
|
||||
inline unsigned int capacity() const { return C; }
|
||||
|
||||
ZT_ALWAYS_INLINE const char *data() const { return _d; }
|
||||
ZT_ALWAYS_INLINE char *unsafeData() { return _d; }
|
||||
inline const char *data() const { return _d; }
|
||||
inline char *unsafeData() { return _d; }
|
||||
|
||||
private:
|
||||
char _d[C];
|
||||
|
@ -4,10 +4,9 @@
|
||||
// This code is under the BSD 2-clause license, not ZeroTier's license
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "ECC384.hpp"
|
||||
@ -141,7 +140,7 @@ static ZT_ALWAYS_INLINE void vli_set(uint64_t *p_dest, uint64_t *p_src)
|
||||
}
|
||||
|
||||
/* Returns sign of p_left - p_right. */
|
||||
static ZT_ALWAYS_INLINE int vli_cmp(uint64_t *p_left, uint64_t *p_right)
|
||||
static inline int vli_cmp(uint64_t *p_left, uint64_t *p_right)
|
||||
{
|
||||
int i;
|
||||
for(i = NUM_ECC_DIGITS-1; i >= 0; --i)
|
||||
@ -376,7 +375,7 @@ static inline void vli_square(uint64_t *p_result, uint64_t *p_left)
|
||||
|
||||
/* Computes p_result = (p_left + p_right) % p_mod.
|
||||
Assumes that p_left < p_mod and p_right < p_mod, p_result != p_mod. */
|
||||
static ZT_ALWAYS_INLINE void vli_modAdd(uint64_t *p_result, uint64_t *p_left, uint64_t *p_right, uint64_t *p_mod)
|
||||
static inline void vli_modAdd(uint64_t *p_result, uint64_t *p_left, uint64_t *p_right, uint64_t *p_mod)
|
||||
{
|
||||
uint64_t l_carry = vli_add(p_result, p_left, p_right);
|
||||
if(l_carry || vli_cmp(p_result, p_mod) >= 0)
|
||||
@ -387,7 +386,7 @@ static ZT_ALWAYS_INLINE void vli_modAdd(uint64_t *p_result, uint64_t *p_left, ui
|
||||
|
||||
/* Computes p_result = (p_left - p_right) % p_mod.
|
||||
Assumes that p_left < p_mod and p_right < p_mod, p_result != p_mod. */
|
||||
static ZT_ALWAYS_INLINE void vli_modSub(uint64_t *p_result, uint64_t *p_left, uint64_t *p_right, uint64_t *p_mod)
|
||||
static inline void vli_modSub(uint64_t *p_result, uint64_t *p_left, uint64_t *p_right, uint64_t *p_mod)
|
||||
{
|
||||
uint64_t l_borrow = vli_sub(p_result, p_left, p_right);
|
||||
if(l_borrow)
|
||||
|
248
node/Endpoint.hpp
Normal file
248
node/Endpoint.hpp
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c)2019 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#ifndef ZT_ENDPOINT_HPP
|
||||
#define ZT_ENDPOINT_HPP
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_ENDPOINT_MARSHAL_SIZE_MAX (ZT_ENDPOINT_MAX_NAME_SIZE+3)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Endpoint variant specifying some form of network endpoint
|
||||
*/
|
||||
class Endpoint
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
NIL = 0, // NIL value
|
||||
INETADDR = 1, // InetAddress (v4 or v6)
|
||||
DNSNAME = 2, // DNS name and port that resolves to InetAddress
|
||||
ZEROTIER = 3, // ZeroTier Address (for relaying and meshy behavior)
|
||||
URL = 4, // URL for http/https/ws/etc. (not implemented yet)
|
||||
ETHERNET = 5 // 48-bit LAN-local Ethernet address
|
||||
};
|
||||
|
||||
ZT_ALWAYS_INLINE Endpoint() { memset(reinterpret_cast<void *>(this),0,sizeof(Endpoint)); }
|
||||
|
||||
explicit ZT_ALWAYS_INLINE Endpoint(const InetAddress &sa) : _t(INETADDR) { _v.sa = sa; }
|
||||
ZT_ALWAYS_INLINE Endpoint(const Address &zt,const uint8_t identityHash[ZT_IDENTITY_HASH_SIZE]) : _t(ZEROTIER) { _v.zt.a = zt.toInt(); memcpy(_v.zt.idh,identityHash,ZT_IDENTITY_HASH_SIZE); }
|
||||
ZT_ALWAYS_INLINE Endpoint(const char *name,const int port) : _t(DNSNAME) { Utils::scopy(_v.dns.name,sizeof(_v.dns.name),name); _v.dns.port = port; }
|
||||
explicit ZT_ALWAYS_INLINE Endpoint(const char *url) : _t(URL) { Utils::scopy(_v.url,sizeof(_v.url),url); }
|
||||
|
||||
ZT_ALWAYS_INLINE const InetAddress *sockaddr() const { return (_t == INETADDR) ? reinterpret_cast<const InetAddress *>(&_v.sa) : nullptr; }
|
||||
ZT_ALWAYS_INLINE const char *dnsName() const { return (_t == DNSNAME) ? _v.dns.name : nullptr; }
|
||||
ZT_ALWAYS_INLINE int dnsPort() const { return (_t == DNSNAME) ? _v.dns.port : -1; }
|
||||
ZT_ALWAYS_INLINE Address ztAddress() const { return (_t == ZEROTIER) ? Address(_v.zt.a) : Address(); }
|
||||
ZT_ALWAYS_INLINE const uint8_t *ztIdentityHash() const { return (_t == ZEROTIER) ? _v.zt.idh : nullptr; }
|
||||
ZT_ALWAYS_INLINE const char *url() const { return (_t == URL) ? _v.url : nullptr; }
|
||||
ZT_ALWAYS_INLINE MAC ethernet() const { return (_t == ETHERNET) ? MAC(_v.eth) : MAC(); }
|
||||
|
||||
ZT_ALWAYS_INLINE Type type() const { return _t; }
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const Endpoint &ep) const
|
||||
{
|
||||
if (_t == ep._t) {
|
||||
switch(_t) {
|
||||
case INETADDR: return (*sockaddr() == *ep.sockaddr());
|
||||
case DNSNAME: return ((_v.dns.port == ep._v.dns.port)&&(strcmp(_v.dns.name,ep._v.dns.name) == 0));
|
||||
case ZEROTIER: return ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) == 0));
|
||||
case URL: return (strcmp(_v.url,ep._v.url) == 0);
|
||||
case ETHERNET: return (_v.eth == ep._v.eth);
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
ZT_ALWAYS_INLINE bool operator!=(const Endpoint &ep) const { return (!(*this == ep)); }
|
||||
ZT_ALWAYS_INLINE bool operator<(const Endpoint &ep) const
|
||||
{
|
||||
if ((int)_t < (int)ep._t) {
|
||||
return true;
|
||||
} else if (_t == ep._t) {
|
||||
int ncmp;
|
||||
switch(_t) {
|
||||
case INETADDR: return (*sockaddr() < *ep.sockaddr());
|
||||
case DNSNAME:
|
||||
ncmp = strcmp(_v.dns.name,ep._v.dns.name);
|
||||
return ((ncmp < 0) ? true : (ncmp == 0)&&(_v.dns.port < ep._v.dns.port));
|
||||
case ZEROTIER: return (_v.zt.a < ep._v.zt.a) ? true : ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) < 0));
|
||||
case URL: return (strcmp(_v.url,ep._v.url) < 0);
|
||||
case ETHERNET: return (_v.eth < ep._v.eth);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
ZT_ALWAYS_INLINE bool operator>(const Endpoint &ep) const { return (ep < *this); }
|
||||
ZT_ALWAYS_INLINE bool operator<=(const Endpoint &ep) const { return !(ep < *this); }
|
||||
ZT_ALWAYS_INLINE bool operator>=(const Endpoint &ep) const { return !(*this < ep); }
|
||||
|
||||
// Marshal interface ///////////////////////////////////////////////////////
|
||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_ENDPOINT_MARSHAL_SIZE_MAX; }
|
||||
inline int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const
|
||||
{
|
||||
int p;
|
||||
switch(_t) {
|
||||
case INETADDR:
|
||||
data[0] = (uint8_t)INETADDR;
|
||||
return 1 + reinterpret_cast<const InetAddress *>(&_v.sa)->marshal(data+1);
|
||||
case DNSNAME:
|
||||
data[0] = (uint8_t)DNSNAME;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((data[p] = (uint8_t)_v.dns.name[p-1]) == 0)
|
||||
break;
|
||||
++p;
|
||||
if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
|
||||
return -1;
|
||||
}
|
||||
data[p++] = (uint8_t)(_v.dns.port >> 8U);
|
||||
data[p++] = (uint8_t)_v.dns.port;
|
||||
return p;
|
||||
case ZEROTIER:
|
||||
data[0] = (uint8_t)ZEROTIER;
|
||||
data[1] = (uint8_t)(_v.zt.a >> 32U);
|
||||
data[2] = (uint8_t)(_v.zt.a >> 24U);
|
||||
data[3] = (uint8_t)(_v.zt.a >> 16U);
|
||||
data[4] = (uint8_t)(_v.zt.a >> 8U);
|
||||
data[5] = (uint8_t)_v.zt.a;
|
||||
memcpy(data + 6,_v.zt.idh,ZT_IDENTITY_HASH_SIZE);
|
||||
return (ZT_IDENTITY_HASH_SIZE + 6);
|
||||
case URL:
|
||||
data[0] = (uint8_t)URL;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((data[p] = (uint8_t)_v.url[p-1]) == 0)
|
||||
break;
|
||||
++p;
|
||||
if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1))
|
||||
return -1;
|
||||
}
|
||||
return p;
|
||||
case ETHERNET:
|
||||
data[0] = (uint8_t)ETHERNET;
|
||||
data[1] = (uint8_t)(_v.eth >> 40U);
|
||||
data[2] = (uint8_t)(_v.eth >> 32U);
|
||||
data[3] = (uint8_t)(_v.eth >> 24U);
|
||||
data[4] = (uint8_t)(_v.eth >> 16U);
|
||||
data[5] = (uint8_t)(_v.eth >> 8U);
|
||||
data[6] = (uint8_t)_v.eth;
|
||||
return 7;
|
||||
default:
|
||||
data[0] = (uint8_t)NIL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
inline int unmarshal(const uint8_t *restrict data,const int len)
|
||||
{
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
int p;
|
||||
switch((Type)data[0]) {
|
||||
case NIL:
|
||||
_t = NIL;
|
||||
return 1;
|
||||
case INETADDR:
|
||||
_t = INETADDR;
|
||||
return reinterpret_cast<InetAddress *>(&_v.sa)->unmarshal(data+1,len-1);
|
||||
case DNSNAME:
|
||||
if (len < 4)
|
||||
return -1;
|
||||
_t = DNSNAME;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((_v.dns.name[p-1] = (char)data[p]) == 0) {
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= (len-2)))
|
||||
return -1;
|
||||
}
|
||||
_v.dns.port = (uint16_t)(((unsigned int)data[p++]) << 8U);
|
||||
_v.dns.port |= (uint16_t)data[p++];
|
||||
return p;
|
||||
case ZEROTIER:
|
||||
if (len < (ZT_IDENTITY_HASH_SIZE + 6))
|
||||
return -1;
|
||||
_t = ZEROTIER;
|
||||
_v.zt.a = ((uint64_t)data[1]) << 32U;
|
||||
_v.zt.a |= ((uint64_t)data[2]) << 24U;
|
||||
_v.zt.a |= ((uint64_t)data[3]) << 16U;
|
||||
_v.zt.a |= ((uint64_t)data[4]) << 8U;
|
||||
_v.zt.a |= (uint64_t)data[5];
|
||||
memcpy(_v.zt.idh,data + 6,ZT_IDENTITY_HASH_SIZE);
|
||||
return (ZT_IDENTITY_HASH_SIZE + 6);
|
||||
case URL:
|
||||
if (len < 2)
|
||||
return -1;
|
||||
_t = URL;
|
||||
p = 1;
|
||||
for (;;) {
|
||||
if ((_v.url[p-1] = (char)data[p]) == 0) {
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= len))
|
||||
return -1;
|
||||
}
|
||||
return p;
|
||||
case ETHERNET:
|
||||
if (len < 7)
|
||||
return -1;
|
||||
_t = ZEROTIER;
|
||||
_v.eth = ((uint64_t)data[1]) << 40U;
|
||||
_v.eth |= ((uint64_t)data[2]) << 32U;
|
||||
_v.eth |= ((uint64_t)data[3]) << 24U;
|
||||
_v.eth |= ((uint64_t)data[4]) << 16U;
|
||||
_v.eth |= ((uint64_t)data[5]) << 8U;
|
||||
_v.eth |= (uint64_t)data[6];
|
||||
return 7;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
Type _t;
|
||||
union {
|
||||
struct sockaddr_storage sa;
|
||||
struct {
|
||||
char name[ZT_ENDPOINT_MAX_NAME_SIZE];
|
||||
uint16_t port;
|
||||
} dns;
|
||||
struct {
|
||||
uint64_t a;
|
||||
uint8_t idh[ZT_IDENTITY_HASH_SIZE];
|
||||
} zt;
|
||||
char url[ZT_ENDPOINT_MAX_NAME_SIZE];
|
||||
uint64_t eth;
|
||||
} _v;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
@ -94,7 +94,7 @@ public:
|
||||
/**
|
||||
* @param bc Initial capacity in buckets (default: 32, must be nonzero)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE Hashtable(unsigned long bc = 32) :
|
||||
inline Hashtable(unsigned long bc = 32) :
|
||||
_t(reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * bc))),
|
||||
_bc(bc),
|
||||
_s(0)
|
||||
@ -105,7 +105,7 @@ public:
|
||||
_t[i] = (_Bucket *)0;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE Hashtable(const Hashtable<K,V> &ht) :
|
||||
inline Hashtable(const Hashtable<K,V> &ht) :
|
||||
_t(reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * ht._bc))),
|
||||
_bc(ht._bc),
|
||||
_s(ht._s)
|
||||
@ -125,13 +125,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE ~Hashtable()
|
||||
inline ~Hashtable()
|
||||
{
|
||||
this->clear();
|
||||
::free(_t);
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE Hashtable &operator=(const Hashtable<K,V> &ht)
|
||||
inline Hashtable &operator=(const Hashtable<K,V> &ht)
|
||||
{
|
||||
this->clear();
|
||||
if (ht._s) {
|
||||
@ -149,7 +149,7 @@ public:
|
||||
/**
|
||||
* Erase all entries
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void clear()
|
||||
inline void clear()
|
||||
{
|
||||
if (_s) {
|
||||
for(unsigned long i=0;i<_bc;++i) {
|
||||
@ -168,7 +168,7 @@ public:
|
||||
/**
|
||||
* @return Vector of all keys
|
||||
*/
|
||||
ZT_ALWAYS_INLINE typename std::vector<K> keys() const
|
||||
inline typename std::vector<K> keys() const
|
||||
{
|
||||
typename std::vector<K> k;
|
||||
if (_s) {
|
||||
@ -191,7 +191,7 @@ public:
|
||||
* @tparam Type of V (generally inferred)
|
||||
*/
|
||||
template<typename C>
|
||||
ZT_ALWAYS_INLINE void appendKeys(C &v) const
|
||||
inline void appendKeys(C &v) const
|
||||
{
|
||||
if (_s) {
|
||||
for(unsigned long i=0;i<_bc;++i) {
|
||||
@ -207,7 +207,7 @@ public:
|
||||
/**
|
||||
* @return Vector of all entries (pairs of K,V)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE typename std::vector< std::pair<K,V> > entries() const
|
||||
inline typename std::vector< std::pair<K,V> > entries() const
|
||||
{
|
||||
typename std::vector< std::pair<K,V> > k;
|
||||
if (_s) {
|
||||
@ -227,7 +227,7 @@ public:
|
||||
* @param k Key
|
||||
* @return Pointer to value or NULL if not found
|
||||
*/
|
||||
ZT_ALWAYS_INLINE V *get(const K k)
|
||||
inline V *get(const K k)
|
||||
{
|
||||
_Bucket *b = _t[_hc(k) % _bc];
|
||||
while (b) {
|
||||
@ -237,14 +237,14 @@ public:
|
||||
}
|
||||
return (V *)0;
|
||||
}
|
||||
ZT_ALWAYS_INLINE const V *get(const K k) const { return const_cast<Hashtable *>(this)->get(k); }
|
||||
inline const V *get(const K k) const { return const_cast<Hashtable *>(this)->get(k); }
|
||||
|
||||
/**
|
||||
* @param k Key
|
||||
* @param v Value to fill with result
|
||||
* @return True if value was found and set (if false, v is not modified)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool get(const K &k,V &v) const
|
||||
inline bool get(const K &k,V &v) const
|
||||
{
|
||||
_Bucket *b = _t[_hc(k) % _bc];
|
||||
while (b) {
|
||||
@ -261,7 +261,7 @@ public:
|
||||
* @param k Key to check
|
||||
* @return True if key is present
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool contains(const K &k) const
|
||||
inline bool contains(const K &k) const
|
||||
{
|
||||
_Bucket *b = _t[_hc(k) % _bc];
|
||||
while (b) {
|
||||
@ -276,7 +276,7 @@ public:
|
||||
* @param k Key
|
||||
* @return True if value was present
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool erase(const K &k)
|
||||
inline bool erase(const K &k)
|
||||
{
|
||||
const unsigned long bidx = _hc(k) % _bc;
|
||||
_Bucket *lastb = (_Bucket *)0;
|
||||
@ -301,7 +301,7 @@ public:
|
||||
* @param v Value
|
||||
* @return Reference to value in table
|
||||
*/
|
||||
ZT_ALWAYS_INLINE V &set(const K &k,const V &v)
|
||||
inline V &set(const K &k,const V &v)
|
||||
{
|
||||
const unsigned long h = _hc(k);
|
||||
unsigned long bidx = h % _bc;
|
||||
@ -331,7 +331,7 @@ public:
|
||||
* @param k Key
|
||||
* @return Value, possibly newly created
|
||||
*/
|
||||
ZT_ALWAYS_INLINE V &operator[](const K k)
|
||||
inline V &operator[](const K k)
|
||||
{
|
||||
const unsigned long h = _hc(k);
|
||||
unsigned long bidx = h % _bc;
|
||||
@ -376,7 +376,7 @@ private:
|
||||
static ZT_ALWAYS_INLINE unsigned long _hc(void *p) { return ((unsigned long)((uintptr_t)p) * (unsigned long)0x9e3779b1); }
|
||||
static ZT_ALWAYS_INLINE unsigned long _hc(const void *p) { return ((unsigned long)((uintptr_t)p) * (unsigned long)0x9e3779b1); }
|
||||
|
||||
ZT_ALWAYS_INLINE void _grow()
|
||||
inline void _grow()
|
||||
{
|
||||
const unsigned long nc = _bc * 2;
|
||||
_Bucket **nt = reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * nc));
|
||||
|
@ -11,10 +11,8 @@
|
||||
*/
|
||||
/****/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Identity.hpp"
|
||||
@ -100,8 +98,13 @@ void Identity::generate(const Type t)
|
||||
delete [] genmem;
|
||||
|
||||
if (t == P384) {
|
||||
// We sign with both because in pure FIPS environments we might have to say
|
||||
// that we do not rely on any non-FIPS algorithms, or may even have to disable
|
||||
// them.
|
||||
ECC384GenerateKey(_pub.p384,_priv.p384);
|
||||
C25519::sign(_priv.c25519,_pub.c25519,&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE,_pub.p384s);
|
||||
C25519::sign(_priv.c25519,_pub.c25519,&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE,_pub.c25519s);
|
||||
SHA384(digest,&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE);
|
||||
ECC384ECDSASign(_priv.p384,digest,_pub.p384s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,7 +119,10 @@ bool Identity::locallyValidate() const
|
||||
case C25519:
|
||||
break;
|
||||
case P384:
|
||||
if (!C25519::verify(_pub.c25519,&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE,_pub.p384s,ZT_C25519_SIGNATURE_LEN))
|
||||
if (!C25519::verify(_pub.c25519,&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE,_pub.c25519s,ZT_C25519_SIGNATURE_LEN))
|
||||
return false;
|
||||
SHA384(digest,&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE);
|
||||
if (!ECC384ECDSAVerify(_pub.p384,digest,_pub.p384s))
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
@ -135,6 +141,108 @@ bool Identity::locallyValidate() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Identity::hash(uint8_t h[48],const bool includePrivate) const
|
||||
{
|
||||
switch(_type) {
|
||||
|
||||
case C25519:
|
||||
if ((_hasPrivate)&&(includePrivate))
|
||||
SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
|
||||
else SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||
return true;
|
||||
|
||||
case P384:
|
||||
if ((_hasPrivate)&&(includePrivate))
|
||||
SHA384(h,&_pub,sizeof(_pub),&_priv,sizeof(_priv));
|
||||
else SHA384(h,&_pub,sizeof(_pub));
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int Identity::sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const
|
||||
{
|
||||
if (_hasPrivate) {
|
||||
switch(_type) {
|
||||
|
||||
case C25519:
|
||||
if (siglen >= ZT_C25519_SIGNATURE_LEN) {
|
||||
C25519::sign(_priv.c25519,_pub.c25519,data,len,sig);
|
||||
return ZT_C25519_SIGNATURE_LEN;
|
||||
}
|
||||
|
||||
case P384:
|
||||
if (siglen >= ZT_ECC384_SIGNATURE_SIZE) {
|
||||
// When signing with P384 we also hash the C25519 public key as an
|
||||
// extra measure to ensure that only this identity can verify.
|
||||
uint8_t h[48];
|
||||
SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||
ECC384ECDSASign(_priv.p384,h,(uint8_t *)sig);
|
||||
return ZT_ECC384_SIGNATURE_SIZE;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Identity::verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const
|
||||
{
|
||||
switch(_type) {
|
||||
|
||||
case C25519:
|
||||
return C25519::verify(_pub.c25519,data,len,sig,siglen);
|
||||
|
||||
case P384:
|
||||
if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
|
||||
uint8_t h[48];
|
||||
SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||
return ECC384ECDSAVerify(_pub.p384,h,(const uint8_t *)sig);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Identity::agree(const Identity &id,uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]) const
|
||||
{
|
||||
uint8_t rawkey[128];
|
||||
uint8_t h[64];
|
||||
if (_hasPrivate) {
|
||||
if (_type == C25519) {
|
||||
|
||||
if ((id._type == C25519)||(id._type == P384)) {
|
||||
// If we are a C25519 key we can agree with another C25519 key or with only the
|
||||
// C25519 portion of a type 1 P-384 key.
|
||||
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
|
||||
SHA512(h,rawkey,ZT_C25519_SHARED_KEY_LEN);
|
||||
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
|
||||
return true;
|
||||
}
|
||||
|
||||
} else if (_type == P384) {
|
||||
|
||||
if (id._type == P384) {
|
||||
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
|
||||
ECC384ECDH(id._pub.p384,_priv.p384,rawkey + ZT_C25519_SHARED_KEY_LEN);
|
||||
SHA384(h,rawkey,ZT_C25519_SHARED_KEY_LEN + ZT_ECC384_SHARED_SECRET_SIZE);
|
||||
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
|
||||
return true;
|
||||
} else if (id._type == C25519) {
|
||||
// If the other identity is a C25519 identity we can agree using only that type.
|
||||
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
|
||||
SHA512(h,rawkey,ZT_C25519_SHARED_KEY_LEN);
|
||||
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
|
||||
{
|
||||
switch(_type) {
|
||||
@ -224,7 +332,7 @@ bool Identity::fromString(const char *str)
|
||||
switch(_type) {
|
||||
|
||||
case C25519:
|
||||
if (Utils::unhex(f,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) != ZT_C25519_PUBLIC_KEY_LEN) {
|
||||
if (Utils::unhex(f,strlen(f),_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) != ZT_C25519_PUBLIC_KEY_LEN) {
|
||||
_address.zero();
|
||||
return false;
|
||||
}
|
||||
@ -245,7 +353,7 @@ bool Identity::fromString(const char *str)
|
||||
switch(_type) {
|
||||
|
||||
case C25519:
|
||||
if (Utils::unhex(f,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN) != ZT_C25519_PRIVATE_KEY_LEN) {
|
||||
if (Utils::unhex(f,strlen(f),_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN) != ZT_C25519_PRIVATE_KEY_LEN) {
|
||||
_address.zero();
|
||||
return false;
|
||||
} else {
|
||||
@ -278,3 +386,99 @@ bool Identity::fromString(const char *str)
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
extern "C" {
|
||||
|
||||
ZT_Identity *ZT_Identity_new(enum ZT_Identity_Type type)
|
||||
{
|
||||
if ((type != ZT_IDENTITY_TYPE_C25519)&&(type != ZT_IDENTITY_TYPE_P384))
|
||||
return nullptr;
|
||||
try {
|
||||
ZeroTier::Identity *id = new ZeroTier::Identity();
|
||||
id->generate((ZeroTier::Identity::Type)type);
|
||||
return reinterpret_cast<ZT_Identity *>(id);
|
||||
} catch ( ... ) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_Identity *ZT_Identity_fromString(const char *idStr)
|
||||
{
|
||||
if (!idStr)
|
||||
return nullptr;
|
||||
try {
|
||||
ZeroTier::Identity *id = new ZeroTier::Identity();
|
||||
if (!id->fromString(idStr)) {
|
||||
delete id;
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<ZT_Identity *>(id);
|
||||
} catch ( ... ) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int ZT_Identity_validate(const ZT_Identity *id)
|
||||
{
|
||||
if (!id)
|
||||
return 0;
|
||||
return reinterpret_cast<const ZeroTier::Identity *>(id)->locallyValidate() ? 1 : 0;
|
||||
}
|
||||
|
||||
unsigned int ZT_Identity_sign(const ZT_Identity *id,const void *data,unsigned int len,void *signature,unsigned int signatureBufferLength)
|
||||
{
|
||||
if (!id)
|
||||
return 0;
|
||||
if (signatureBufferLength < ZT_SIGNATURE_BUFFER_SIZE)
|
||||
return 0;
|
||||
return reinterpret_cast<const ZeroTier::Identity *>(id)->sign(data,len,signature,signatureBufferLength);
|
||||
}
|
||||
|
||||
int ZT_Identity_verify(const ZT_Identity *id,const void *data,unsigned int len,const void *signature,unsigned int sigLen)
|
||||
{
|
||||
if ((!id)||(!signature)||(!sigLen))
|
||||
return 0;
|
||||
return reinterpret_cast<const ZeroTier::Identity *>(id)->verify(data,len,signature,sigLen) ? 1 : 0;
|
||||
}
|
||||
|
||||
enum ZT_Identity_Type ZT_Identity_type(const ZT_Identity *id)
|
||||
{
|
||||
if (!id)
|
||||
return (ZT_Identity_Type)0;
|
||||
return (enum ZT_Identity_Type)reinterpret_cast<const ZeroTier::Identity *>(id)->type();
|
||||
}
|
||||
|
||||
char *ZT_Identity_toString(const ZT_Identity *id,char *buf,int capacity,int includePrivate)
|
||||
{
|
||||
if ((!id)||(!buf)||(capacity < ZT_IDENTITY_STRING_BUFFER_LENGTH))
|
||||
return nullptr;
|
||||
reinterpret_cast<const ZeroTier::Identity *>(id)->toString(includePrivate != 0,buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
int ZT_Identity_hasPrivate(const ZT_Identity *id)
|
||||
{
|
||||
if (!id)
|
||||
return 0;
|
||||
return reinterpret_cast<const ZeroTier::Identity *>(id)->hasPrivate() ? 1 : 0;
|
||||
}
|
||||
|
||||
uint64_t ZT_Identity_address(const ZT_Identity *id)
|
||||
{
|
||||
if (!id)
|
||||
return 0;
|
||||
return reinterpret_cast<const ZeroTier::Identity *>(id)->address().toInt();
|
||||
}
|
||||
|
||||
void ZT_Identity_hash(const ZT_Identity *id,uint8_t h[48],int includePrivate)
|
||||
{
|
||||
reinterpret_cast<const ZeroTier::Identity *>(id)->hash(h,includePrivate != 0);
|
||||
}
|
||||
|
||||
ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id)
|
||||
{
|
||||
if (id)
|
||||
delete reinterpret_cast<ZeroTier::Identity *>(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,8 +14,8 @@
|
||||
#ifndef ZT_IDENTITY_HPP
|
||||
#define ZT_IDENTITY_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
@ -27,6 +27,11 @@
|
||||
|
||||
#define ZT_IDENTITY_STRING_BUFFER_LENGTH 1024
|
||||
|
||||
#define ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE (ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_C25519_SIGNATURE_LEN + ZT_ECC384_SIGNATURE_SIZE)
|
||||
#define ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE (ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE)
|
||||
|
||||
#define ZT_IDENTITY_MARSHAL_SIZE_MAX (ZT_ADDRESS_LENGTH + 4 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
@ -52,15 +57,17 @@ public:
|
||||
};
|
||||
|
||||
ZT_ALWAYS_INLINE Identity() { memset(reinterpret_cast<void *>(this),0,sizeof(Identity)); }
|
||||
ZT_ALWAYS_INLINE Identity(const char *str)
|
||||
{
|
||||
if (!fromString(str))
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
|
||||
}
|
||||
template<unsigned int C>
|
||||
ZT_ALWAYS_INLINE Identity(const Buffer<C> &b,unsigned int startAt = 0) { deserialize(b,startAt); }
|
||||
ZT_ALWAYS_INLINE ~Identity() { Utils::burn(reinterpret_cast<void *>(&this->_priv),sizeof(this->_priv)); }
|
||||
|
||||
ZT_ALWAYS_INLINE ~Identity() { Utils::burn(reinterpret_cast<void *>(this),sizeof(Identity)); }
|
||||
/**
|
||||
* Construct identity from string
|
||||
*
|
||||
* If the identity is not basically valid (no deep checking is done) the result will
|
||||
* be a null identity.
|
||||
*
|
||||
* @param str Identity in canonical string format
|
||||
*/
|
||||
explicit ZT_ALWAYS_INLINE Identity(const char *str) { fromString(str); }
|
||||
|
||||
/**
|
||||
* Set identity to NIL value (all zero)
|
||||
@ -68,18 +75,18 @@ public:
|
||||
ZT_ALWAYS_INLINE void zero() { memset(reinterpret_cast<void *>(this),0,sizeof(Identity)); }
|
||||
|
||||
/**
|
||||
* @return Identity type
|
||||
* @return Identity type (undefined if identity is null or invalid)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE Type type() const { return _type; }
|
||||
|
||||
/**
|
||||
* Generate a new identity (address, key pair)
|
||||
*
|
||||
* This is a time consuming operation.
|
||||
* This is a time consuming operation taking up to 5-10 seconds on some slower systems.
|
||||
*
|
||||
* @param t Type of identity to generate
|
||||
*/
|
||||
void generate(const Type t);
|
||||
void generate(Type t);
|
||||
|
||||
/**
|
||||
* Check the validity of this identity's pairing of key to address
|
||||
@ -94,41 +101,12 @@ public:
|
||||
ZT_ALWAYS_INLINE bool hasPrivate() const { return _hasPrivate; }
|
||||
|
||||
/**
|
||||
* Compute the SHA512 hash of our private key (if we have one)
|
||||
* This generates a SHA384 hash of this identity's keys.
|
||||
*
|
||||
* @param sha Buffer to receive SHA512 (MUST be ZT_SHA512_DIGEST_LEN (64) bytes in length)
|
||||
* @return True on success, false if no private key
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool sha512PrivateKey(void *const sha) const
|
||||
{
|
||||
if (_hasPrivate) {
|
||||
switch(_type) {
|
||||
case C25519:
|
||||
SHA512(sha,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
|
||||
return true;
|
||||
case P384:
|
||||
SHA512(sha,&_priv,sizeof(_priv));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param h Buffer to receive SHA384 of public key(s)
|
||||
* @param includePrivate If true, hash private key(s) as well
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool hash(uint8_t h[48]) const
|
||||
{
|
||||
switch(_type) {
|
||||
case C25519:
|
||||
SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||
return true;
|
||||
case P384:
|
||||
SHA384(h,&_pub,sizeof(_pub));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool hash(uint8_t h[48],bool includePrivate = false) const;
|
||||
|
||||
/**
|
||||
* Sign a message with this identity (private key required)
|
||||
@ -142,31 +120,7 @@ public:
|
||||
* @param siglen Length of buffer
|
||||
* @return Number of bytes actually written to sig or 0 on error
|
||||
*/
|
||||
ZT_ALWAYS_INLINE unsigned int sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const
|
||||
{
|
||||
if (_hasPrivate) {
|
||||
switch(_type) {
|
||||
|
||||
case C25519:
|
||||
if (siglen >= ZT_C25519_SIGNATURE_LEN) {
|
||||
C25519::sign(_priv.c25519,_pub.c25519,data,len,sig);
|
||||
return ZT_C25519_SIGNATURE_LEN;
|
||||
}
|
||||
|
||||
case P384:
|
||||
if (siglen >= ZT_ECC384_SIGNATURE_SIZE) {
|
||||
// Signature hash includes the C25519/Ed25519 public key after the message.
|
||||
// This is an added guard against divorcing these two bound keys.
|
||||
uint8_t h[48];
|
||||
SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||
ECC384ECDSASign(_priv.p384,h,(uint8_t *)sig);
|
||||
return ZT_ECC384_SIGNATURE_SIZE;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
unsigned int sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const;
|
||||
|
||||
/**
|
||||
* Verify a message signature against this identity
|
||||
@ -177,21 +131,7 @@ public:
|
||||
* @param siglen Length of signature in bytes
|
||||
* @return True if signature validates and data integrity checks
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const
|
||||
{
|
||||
switch(_type) {
|
||||
case C25519:
|
||||
return C25519::verify(_pub.c25519,data,len,sig,siglen);
|
||||
case P384:
|
||||
if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
|
||||
uint8_t h[48];
|
||||
SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||
return ECC384ECDSAVerify(_pub.p384,h,(const uint8_t *)sig);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const;
|
||||
|
||||
/**
|
||||
* Shortcut method to perform key agreement with another identity
|
||||
@ -202,78 +142,21 @@ public:
|
||||
* @param key Result parameter to fill with key bytes
|
||||
* @return Was agreement successful?
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool agree(const Identity &id,uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]) const
|
||||
{
|
||||
uint8_t rawkey[128];
|
||||
uint8_t h[64];
|
||||
if (_hasPrivate) {
|
||||
if (_type == C25519) {
|
||||
if ((id._type == C25519)||(id._type == P384)) {
|
||||
// If we are a C25519 key we can agree with another C25519 key or with only the
|
||||
// C25519 portion of a type 1 P-384 key.
|
||||
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
|
||||
SHA512(h,rawkey,ZT_C25519_SHARED_KEY_LEN);
|
||||
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
|
||||
return true;
|
||||
}
|
||||
} else if (_type == P384) {
|
||||
if (id._type == P384) {
|
||||
// Perform key agreement over both curves for the same reason that C25519 public
|
||||
// keys are included in P-384 signature inputs: to bind the keys together so
|
||||
// that a type 1 identity with the same C25519 public key (and therefore address)
|
||||
// but a different P-384 key will not work.
|
||||
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
|
||||
ECC384ECDH(id._pub.p384,_priv.p384,rawkey + ZT_C25519_SHARED_KEY_LEN);
|
||||
SHA384(h,rawkey,ZT_C25519_SHARED_KEY_LEN + ZT_ECC384_SHARED_SECRET_SIZE);
|
||||
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
|
||||
return true;
|
||||
} else if (id._type == C25519) {
|
||||
// If the other identity is a C25519 identity we can agree using only that type.
|
||||
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
|
||||
SHA512(h,rawkey,ZT_C25519_SHARED_KEY_LEN);
|
||||
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool agree(const Identity &id,uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]) const;
|
||||
|
||||
/**
|
||||
* @return This identity's address
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const Address &address() const { return _address; }
|
||||
|
||||
/**
|
||||
* Attempt to generate an older type identity from a newer type
|
||||
*
|
||||
* If this identity has its private key this is not transferred to
|
||||
* the downgraded identity.
|
||||
*
|
||||
* @param dest Destination to fill with downgraded identity
|
||||
* @param toType Desired identity type
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool downgrade(Identity &dest,const Type toType)
|
||||
{
|
||||
if ((_type == P384)&&(toType == C25519)) {
|
||||
dest._address = _address;
|
||||
dest._type = C25519;
|
||||
dest._hasPrivate = false;
|
||||
memcpy(dest._pub.c25519,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize this identity (binary)
|
||||
*
|
||||
* @param b Destination buffer to append to
|
||||
* @param includePrivate If true, include private key component (if present) (default: false)
|
||||
* @throws std::out_of_range Buffer too small
|
||||
*/
|
||||
template<unsigned int C>
|
||||
ZT_ALWAYS_INLINE void serialize(Buffer<C> &b,bool includePrivate = false) const
|
||||
inline void serialize(Buffer<C> &b,bool includePrivate = false) const
|
||||
{
|
||||
_address.appendTo(b);
|
||||
switch(_type) {
|
||||
@ -291,9 +174,7 @@ public:
|
||||
|
||||
case P384:
|
||||
b.append((uint8_t)P384);
|
||||
b.append(_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||
b.append(_pub.p384,ZT_ECC384_PUBLIC_KEY_SIZE);
|
||||
b.append(_pub.p384s,ZT_C25519_SIGNATURE_LEN);
|
||||
b.append(&_pub,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_C25519_SIGNATURE_LEN + ZT_ECC384_SIGNATURE_SIZE);
|
||||
if ((_hasPrivate)&&(includePrivate)) {
|
||||
b.append((uint8_t)(ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE));
|
||||
b.append(_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
|
||||
@ -301,7 +182,7 @@ public:
|
||||
} else {
|
||||
b.append((uint8_t)0);
|
||||
}
|
||||
b.append((uint16_t)0); // size of additional fields
|
||||
b.append((uint8_t)0); // size of additional fields (should have included such a thing in v0!)
|
||||
break;
|
||||
|
||||
}
|
||||
@ -316,11 +197,9 @@ public:
|
||||
* @param b Buffer containing serialized data
|
||||
* @param startAt Index within buffer of serialized data (default: 0)
|
||||
* @return Length of serialized data read from buffer
|
||||
* @throws std::out_of_range Serialized data invalid
|
||||
* @throws std::invalid_argument Serialized data invalid
|
||||
*/
|
||||
template<unsigned int C>
|
||||
ZT_ALWAYS_INLINE unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
|
||||
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
|
||||
{
|
||||
_hasPrivate = false;
|
||||
unsigned int p = startAt;
|
||||
@ -347,12 +226,8 @@ public:
|
||||
break;
|
||||
|
||||
case P384:
|
||||
memcpy(_pub.c25519,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN);
|
||||
p += ZT_C25519_PUBLIC_KEY_LEN;
|
||||
memcpy(_pub.p384,b.field(p,ZT_ECC384_PUBLIC_KEY_SIZE),ZT_ECC384_PUBLIC_KEY_SIZE);
|
||||
p += ZT_ECC384_PUBLIC_KEY_SIZE;
|
||||
memcpy(_pub.p384s,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
|
||||
p += ZT_ECC384_SIGNATURE_SIZE;
|
||||
memcpy(&_pub,b.field(p,ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_C25519_SIGNATURE_LEN + ZT_ECC384_SIGNATURE_SIZE),ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_C25519_SIGNATURE_LEN + ZT_ECC384_SIGNATURE_SIZE);
|
||||
p += ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_C25519_SIGNATURE_LEN + ZT_ECC384_SIGNATURE_SIZE;
|
||||
pkl = (unsigned int)b[p++];
|
||||
if (pkl) {
|
||||
if (pkl != (ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE))
|
||||
@ -365,7 +240,7 @@ public:
|
||||
} else {
|
||||
_hasPrivate = false;
|
||||
}
|
||||
p += b.template at<uint16_t>(p) + 2;
|
||||
p += b.template at<uint8_t>(p) + 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -381,7 +256,7 @@ public:
|
||||
*
|
||||
* @param includePrivate If true, include private key (if it exists)
|
||||
* @param buf Buffer to store string
|
||||
* @return ASCII string representation of identity
|
||||
* @return ASCII string representation of identity (pointer to buf)
|
||||
*/
|
||||
char *toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const;
|
||||
|
||||
@ -399,18 +274,15 @@ public:
|
||||
/**
|
||||
* @return True if this identity contains something
|
||||
*/
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (_address); }
|
||||
explicit ZT_ALWAYS_INLINE operator bool() const { return (_address); }
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const Identity &id) const
|
||||
{
|
||||
if ((_address == id._address)&&(_type == id._type)) {
|
||||
switch(_type) {
|
||||
case C25519:
|
||||
return (memcmp(_pub.c25519,id._pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) == 0);
|
||||
case P384:
|
||||
return (memcmp(&_pub,&id._pub,sizeof(_pub)) == 0);
|
||||
default:
|
||||
return false;
|
||||
case C25519: return (memcmp(_pub.c25519,id._pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) == 0);
|
||||
// case P384:
|
||||
default: return (memcmp(&_pub,&id._pub,sizeof(_pub)) == 0);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -424,10 +296,9 @@ public:
|
||||
return true;
|
||||
if (_type == id._type) {
|
||||
switch(_type) {
|
||||
case C25519:
|
||||
return (memcmp(_pub.c25519,id._pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) < 0);
|
||||
case P384:
|
||||
return (memcmp(&_pub,&id._pub,sizeof(_pub)) < 0);
|
||||
case C25519: return (memcmp(_pub.c25519,id._pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) < 0);
|
||||
// case P384:
|
||||
default: return (memcmp(&_pub,&id._pub,sizeof(_pub)) < 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -440,18 +311,102 @@ public:
|
||||
|
||||
ZT_ALWAYS_INLINE unsigned long hashCode() const { return ((unsigned long)_address.toInt() + (unsigned long)_pub.c25519[0] + (unsigned long)_pub.c25519[1] + (unsigned long)_pub.c25519[2]); }
|
||||
|
||||
// Marshal interface ///////////////////////////////////////////////////////
|
||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_IDENTITY_MARSHAL_SIZE_MAX; }
|
||||
inline int marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool includePrivate = false) const
|
||||
{
|
||||
_address.copyTo(data,ZT_ADDRESS_LENGTH);
|
||||
switch(_type) {
|
||||
|
||||
case C25519:
|
||||
data[ZT_ADDRESS_LENGTH] = (uint8_t)C25519;
|
||||
memcpy(data + ZT_ADDRESS_LENGTH + 1,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||
if ((includePrivate)&&(_hasPrivate)) {
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN] = ZT_C25519_PRIVATE_KEY_LEN;
|
||||
memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
|
||||
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN);
|
||||
}
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN] = 0;
|
||||
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1);
|
||||
|
||||
case P384:
|
||||
data[ZT_ADDRESS_LENGTH] = (uint8_t)P384;
|
||||
memcpy(data + ZT_ADDRESS_LENGTH + 1,&_pub,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
|
||||
if ((includePrivate)&&(_hasPrivate)) {
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE;
|
||||
memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,&_priv,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE] = 0;
|
||||
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1);
|
||||
}
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = 0;
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1] = 0;
|
||||
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2);
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
inline int unmarshal(const uint8_t *restrict data,const int len)
|
||||
{
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1))
|
||||
return -1;
|
||||
unsigned int privlen;
|
||||
switch((_type = (Type)data[ZT_ADDRESS_LENGTH])) {
|
||||
|
||||
case C25519:
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1))
|
||||
return -1;
|
||||
memcpy(_pub.c25519,data + ZT_ADDRESS_LENGTH + 1,ZT_C25519_PUBLIC_KEY_LEN);
|
||||
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN];
|
||||
if (privlen == ZT_C25519_PRIVATE_KEY_LEN) {
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN))
|
||||
return -1;
|
||||
_hasPrivate = true;
|
||||
memcpy(_priv.c25519,data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,ZT_C25519_PRIVATE_KEY_LEN);
|
||||
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN);
|
||||
} else if (privlen == 0) {
|
||||
_hasPrivate = false;
|
||||
return (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case P384:
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2))
|
||||
return -1;
|
||||
memcpy(&_pub,data + ZT_ADDRESS_LENGTH + 1,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
|
||||
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE];
|
||||
if (privlen == ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE) {
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1))
|
||||
return -1;
|
||||
_hasPrivate = true;
|
||||
memcpy(&_priv,data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
|
||||
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE];
|
||||
if (len < (privlen + (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1)))
|
||||
return -1;
|
||||
return (int)(privlen + (unsigned int)(ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE + 1));
|
||||
} else if (privlen == 0) {
|
||||
_hasPrivate = false;
|
||||
return (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 2);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
Address _address;
|
||||
Type _type;
|
||||
Type _type; // _type determines which fields in _priv and _pub are used
|
||||
bool _hasPrivate;
|
||||
ZT_PACKED_STRUCT(struct { // don't re-order these
|
||||
uint8_t c25519[ZT_C25519_PRIVATE_KEY_LEN];
|
||||
uint8_t p384[ZT_ECC384_PRIVATE_KEY_SIZE];
|
||||
}) _priv;
|
||||
ZT_PACKED_STRUCT(struct { // don't re-order these
|
||||
uint8_t c25519[ZT_C25519_PUBLIC_KEY_LEN];
|
||||
uint8_t p384[ZT_ECC384_PUBLIC_KEY_SIZE];
|
||||
uint8_t p384s[ZT_C25519_SIGNATURE_LEN]; // signature of both keys with ed25519 to confirm type 0 extension to type 1
|
||||
uint8_t c25519[ZT_C25519_PUBLIC_KEY_LEN]; // Curve25519 and Ed25519 public keys
|
||||
uint8_t p384[ZT_ECC384_PUBLIC_KEY_SIZE]; // NIST P-384 public key
|
||||
uint8_t c25519s[ZT_C25519_SIGNATURE_LEN]; // signature of both keys with ed25519
|
||||
uint8_t p384s[ZT_ECC384_SIGNATURE_SIZE]; // signature of both keys with p384
|
||||
}) _pub;
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,8 +14,6 @@
|
||||
#ifndef ZT_INCOMINGPACKET_HPP
|
||||
#define ZT_INCOMINGPACKET_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "Packet.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Utils.hpp"
|
||||
@ -43,17 +41,10 @@ namespace ZeroTier {
|
||||
class RuntimeEnvironment;
|
||||
class Network;
|
||||
|
||||
/**
|
||||
* Subclass of packet that handles the decoding of it
|
||||
*/
|
||||
class IncomingPacket : public Packet
|
||||
{
|
||||
public:
|
||||
ZT_ALWAYS_INLINE IncomingPacket() :
|
||||
Packet(),
|
||||
_receiveTime(0)
|
||||
{
|
||||
}
|
||||
ZT_ALWAYS_INLINE IncomingPacket() : Packet(),_receiveTime(0),_path() {}
|
||||
|
||||
/**
|
||||
* Create a new packet-in-decode
|
||||
@ -108,30 +99,6 @@ public:
|
||||
ZT_ALWAYS_INLINE uint64_t receiveTime() const { return _receiveTime; }
|
||||
|
||||
private:
|
||||
// These are called internally to handle packet contents once it has
|
||||
// been authenticated, decrypted, decompressed, and classified.
|
||||
bool _doERROR(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool alreadyAuthenticated);
|
||||
bool _doACK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doQOS_MEASUREMENT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doFRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doECHO(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doREMOTE_TRACE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
|
||||
void _sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,const uint64_t nwid);
|
||||
|
||||
uint64_t _receiveTime;
|
||||
SharedPtr<Path> _path;
|
||||
};
|
||||
|
@ -11,11 +11,8 @@
|
||||
*/
|
||||
/****/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
@ -33,20 +30,20 @@ InetAddress::IpScope InetAddress::ipScope() const
|
||||
|
||||
case AF_INET: {
|
||||
const uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
|
||||
switch(ip >> 24) {
|
||||
switch(ip >> 24U) {
|
||||
case 0x00: return IP_SCOPE_NONE; // 0.0.0.0/8 (reserved, never used)
|
||||
case 0x06: return IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army)
|
||||
case 0x0a: return IP_SCOPE_PRIVATE; // 10.0.0.0/8
|
||||
case 0x0b: return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD)
|
||||
case 0x15: return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN)
|
||||
case 0x16: return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA)
|
||||
case 0x19: return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense)
|
||||
case 0x1a: return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA)
|
||||
case 0x1c: return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North)
|
||||
case 0x1d: return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA)
|
||||
case 0x1e: return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA)
|
||||
case 0x33: return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security)
|
||||
case 0x37: return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
|
||||
case 0x0b: //return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD)
|
||||
case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN)
|
||||
case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA)
|
||||
case 0x19: //return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense)
|
||||
case 0x1a: //return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA)
|
||||
case 0x1c: //return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North)
|
||||
case 0x1d: //return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA)
|
||||
case 0x1e: //return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA)
|
||||
case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security)
|
||||
case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
|
||||
case 0x38: return IP_SCOPE_PSEUDOPRIVATE; // 56.0.0.0/8 (US Postal Service)
|
||||
case 0x64:
|
||||
if ((ip & 0xffc00000) == 0x64400000) return IP_SCOPE_PRIVATE; // 100.64.0.0/10
|
||||
@ -164,7 +161,7 @@ bool InetAddress::fromString(const char *ipSlashPort)
|
||||
unsigned int port = 0;
|
||||
if (*portAt) {
|
||||
*(portAt++) = (char)0;
|
||||
port = Utils::strToUInt(portAt) & 0xffff;
|
||||
port = Utils::strToUInt(portAt) & 0xffffU;
|
||||
}
|
||||
|
||||
if (strchr(buf,':')) {
|
||||
@ -189,7 +186,7 @@ InetAddress InetAddress::netmask() const
|
||||
InetAddress r(*this);
|
||||
switch(r.ss_family) {
|
||||
case AF_INET:
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits())));
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits())));
|
||||
break;
|
||||
case AF_INET6: {
|
||||
uint64_t nm[2];
|
||||
@ -211,7 +208,7 @@ InetAddress InetAddress::broadcast() const
|
||||
{
|
||||
if (ss_family == AF_INET) {
|
||||
InetAddress r(*this);
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffff >> netmaskBits()));
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffffU >> netmaskBits()));
|
||||
return r;
|
||||
}
|
||||
return InetAddress();
|
||||
@ -222,7 +219,7 @@ InetAddress InetAddress::network() const
|
||||
InetAddress r(*this);
|
||||
switch(r.ss_family) {
|
||||
case AF_INET:
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr &= Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits())));
|
||||
reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr &= Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits())));
|
||||
break;
|
||||
case AF_INET6: {
|
||||
uint64_t nm[2];
|
||||
@ -294,7 +291,7 @@ bool InetAddress::isNetwork() const
|
||||
if (bits >= 32)
|
||||
return false;
|
||||
uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
|
||||
return ((ip & (0xffffffff >> bits)) == 0);
|
||||
return ((ip & (0xffffffffU >> bits)) == 0);
|
||||
}
|
||||
case AF_INET6: {
|
||||
unsigned int bits = netmaskBits();
|
||||
@ -304,7 +301,7 @@ bool InetAddress::isNetwork() const
|
||||
return false;
|
||||
const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
|
||||
unsigned int p = bits / 8;
|
||||
if ((ip[p++] & (0xff >> (bits % 8))) != 0)
|
||||
if ((ip[p++] & (0xffU >> (bits % 8))) != 0)
|
||||
return false;
|
||||
while (p < 16) {
|
||||
if (ip[p++])
|
||||
@ -378,48 +375,49 @@ bool InetAddress::operator<(const InetAddress &a) const
|
||||
|
||||
InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac)
|
||||
{
|
||||
struct sockaddr_in6 sin6;
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_addr.s6_addr[0] = 0xfe;
|
||||
sin6.sin6_addr.s6_addr[1] = 0x80;
|
||||
sin6.sin6_addr.s6_addr[2] = 0x00;
|
||||
sin6.sin6_addr.s6_addr[3] = 0x00;
|
||||
sin6.sin6_addr.s6_addr[4] = 0x00;
|
||||
sin6.sin6_addr.s6_addr[5] = 0x00;
|
||||
sin6.sin6_addr.s6_addr[6] = 0x00;
|
||||
sin6.sin6_addr.s6_addr[7] = 0x00;
|
||||
sin6.sin6_addr.s6_addr[8] = mac[0] & 0xfd;
|
||||
sin6.sin6_addr.s6_addr[9] = mac[1];
|
||||
sin6.sin6_addr.s6_addr[10] = mac[2];
|
||||
sin6.sin6_addr.s6_addr[11] = 0xff;
|
||||
sin6.sin6_addr.s6_addr[12] = 0xfe;
|
||||
sin6.sin6_addr.s6_addr[13] = mac[3];
|
||||
sin6.sin6_addr.s6_addr[14] = mac[4];
|
||||
sin6.sin6_addr.s6_addr[15] = mac[5];
|
||||
sin6.sin6_port = Utils::hton((uint16_t)64);
|
||||
return InetAddress(sin6);
|
||||
InetAddress r;
|
||||
sockaddr_in6 *const sin6 = reinterpret_cast<sockaddr_in6 *>(&r);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_addr.s6_addr[0] = 0xfe;
|
||||
sin6->sin6_addr.s6_addr[1] = 0x80;
|
||||
sin6->sin6_addr.s6_addr[2] = 0x00;
|
||||
sin6->sin6_addr.s6_addr[3] = 0x00;
|
||||
sin6->sin6_addr.s6_addr[4] = 0x00;
|
||||
sin6->sin6_addr.s6_addr[5] = 0x00;
|
||||
sin6->sin6_addr.s6_addr[6] = 0x00;
|
||||
sin6->sin6_addr.s6_addr[7] = 0x00;
|
||||
sin6->sin6_addr.s6_addr[8] = mac[0] & 0xfdU;
|
||||
sin6->sin6_addr.s6_addr[9] = mac[1];
|
||||
sin6->sin6_addr.s6_addr[10] = mac[2];
|
||||
sin6->sin6_addr.s6_addr[11] = 0xff;
|
||||
sin6->sin6_addr.s6_addr[12] = 0xfe;
|
||||
sin6->sin6_addr.s6_addr[13] = mac[3];
|
||||
sin6->sin6_addr.s6_addr[14] = mac[4];
|
||||
sin6->sin6_addr.s6_addr[15] = mac[5];
|
||||
sin6->sin6_port = Utils::hton((uint16_t)64);
|
||||
return r;
|
||||
}
|
||||
|
||||
InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress)
|
||||
{
|
||||
InetAddress r;
|
||||
struct sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
|
||||
sockaddr_in6 *const sin6 = reinterpret_cast<sockaddr_in6 *>(&r);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_addr.s6_addr[0] = 0xfd;
|
||||
sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 56);
|
||||
sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 48);
|
||||
sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 40);
|
||||
sin6->sin6_addr.s6_addr[4] = (uint8_t)(nwid >> 32);
|
||||
sin6->sin6_addr.s6_addr[5] = (uint8_t)(nwid >> 24);
|
||||
sin6->sin6_addr.s6_addr[6] = (uint8_t)(nwid >> 16);
|
||||
sin6->sin6_addr.s6_addr[7] = (uint8_t)(nwid >> 8);
|
||||
sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 56U);
|
||||
sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 48U);
|
||||
sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 40U);
|
||||
sin6->sin6_addr.s6_addr[4] = (uint8_t)(nwid >> 32U);
|
||||
sin6->sin6_addr.s6_addr[5] = (uint8_t)(nwid >> 24U);
|
||||
sin6->sin6_addr.s6_addr[6] = (uint8_t)(nwid >> 16U);
|
||||
sin6->sin6_addr.s6_addr[7] = (uint8_t)(nwid >> 8U);
|
||||
sin6->sin6_addr.s6_addr[8] = (uint8_t)nwid;
|
||||
sin6->sin6_addr.s6_addr[9] = 0x99;
|
||||
sin6->sin6_addr.s6_addr[10] = 0x93;
|
||||
sin6->sin6_addr.s6_addr[11] = (uint8_t)(zeroTierAddress >> 32);
|
||||
sin6->sin6_addr.s6_addr[12] = (uint8_t)(zeroTierAddress >> 24);
|
||||
sin6->sin6_addr.s6_addr[13] = (uint8_t)(zeroTierAddress >> 16);
|
||||
sin6->sin6_addr.s6_addr[14] = (uint8_t)(zeroTierAddress >> 8);
|
||||
sin6->sin6_addr.s6_addr[11] = (uint8_t)(zeroTierAddress >> 32U);
|
||||
sin6->sin6_addr.s6_addr[12] = (uint8_t)(zeroTierAddress >> 24U);
|
||||
sin6->sin6_addr.s6_addr[13] = (uint8_t)(zeroTierAddress >> 16U);
|
||||
sin6->sin6_addr.s6_addr[14] = (uint8_t)(zeroTierAddress >> 8U);
|
||||
sin6->sin6_addr.s6_addr[15] = (uint8_t)zeroTierAddress;
|
||||
sin6->sin6_port = Utils::hton((uint16_t)88); // /88 includes 0xfd + network ID, discriminating by device ID below that
|
||||
return r;
|
||||
@ -427,19 +425,19 @@ InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress)
|
||||
|
||||
InetAddress InetAddress::makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress)
|
||||
{
|
||||
nwid ^= (nwid >> 32);
|
||||
nwid ^= (nwid >> 32U);
|
||||
InetAddress r;
|
||||
struct sockaddr_in6 *const sin6 = reinterpret_cast<struct sockaddr_in6 *>(&r);
|
||||
sockaddr_in6 *const sin6 = reinterpret_cast<sockaddr_in6 *>(&r);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_addr.s6_addr[0] = 0xfc;
|
||||
sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 24);
|
||||
sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 16);
|
||||
sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 8);
|
||||
sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 24U);
|
||||
sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 16U);
|
||||
sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 8U);
|
||||
sin6->sin6_addr.s6_addr[4] = (uint8_t)nwid;
|
||||
sin6->sin6_addr.s6_addr[5] = (uint8_t)(zeroTierAddress >> 32);
|
||||
sin6->sin6_addr.s6_addr[6] = (uint8_t)(zeroTierAddress >> 24);
|
||||
sin6->sin6_addr.s6_addr[7] = (uint8_t)(zeroTierAddress >> 16);
|
||||
sin6->sin6_addr.s6_addr[8] = (uint8_t)(zeroTierAddress >> 8);
|
||||
sin6->sin6_addr.s6_addr[5] = (uint8_t)(zeroTierAddress >> 32U);
|
||||
sin6->sin6_addr.s6_addr[6] = (uint8_t)(zeroTierAddress >> 24U);
|
||||
sin6->sin6_addr.s6_addr[7] = (uint8_t)(zeroTierAddress >> 16U);
|
||||
sin6->sin6_addr.s6_addr[8] = (uint8_t)(zeroTierAddress >> 8U);
|
||||
sin6->sin6_addr.s6_addr[9] = (uint8_t)zeroTierAddress;
|
||||
sin6->sin6_addr.s6_addr[15] = 0x01;
|
||||
sin6->sin6_port = Utils::hton((uint16_t)40);
|
||||
|
@ -14,12 +14,13 @@
|
||||
#ifndef ZT_INETADDRESS_HPP
|
||||
#define ZT_INETADDRESS_HPP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include "../include/ZeroTierOne.h"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "../include/ZeroTierOne.h"
|
||||
#include "Utils.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Buffer.hpp"
|
||||
@ -41,6 +42,16 @@ namespace ZeroTier {
|
||||
*/
|
||||
struct InetAddress : public sockaddr_storage
|
||||
{
|
||||
private:
|
||||
template<typename SA>
|
||||
ZT_ALWAYS_INLINE void copySockaddrToThis(const SA *sa)
|
||||
{
|
||||
memcpy(reinterpret_cast<void *>(this),sa,sizeof(SA));
|
||||
if (sizeof(SA) < sizeof(InetAddress))
|
||||
memset(reinterpret_cast<char *>(this) + sizeof(SA),0,sizeof(InetAddress) - sizeof(SA));
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Loopback IPv4 address (no port)
|
||||
*/
|
||||
@ -75,123 +86,86 @@ struct InetAddress : public sockaddr_storage
|
||||
IP_SCOPE_PRIVATE = 7 // 10.x.x.x, 192.168.x.x, etc.
|
||||
};
|
||||
|
||||
// Can be used with the unordered maps and sets in c++11. We don't use C++11 in the core
|
||||
// but this is safe to put here.
|
||||
struct Hasher
|
||||
{
|
||||
ZT_ALWAYS_INLINE std::size_t operator()(const InetAddress &a) const { return (std::size_t)a.hashCode(); }
|
||||
};
|
||||
// Hasher for unordered sets and maps in C++11
|
||||
struct Hasher { ZT_ALWAYS_INLINE std::size_t operator()(const InetAddress &a) const { return (std::size_t)a.hashCode(); } };
|
||||
|
||||
ZT_ALWAYS_INLINE InetAddress() { memset(this,0,sizeof(InetAddress)); }
|
||||
ZT_ALWAYS_INLINE InetAddress(const InetAddress &a) { memcpy(this,&a,sizeof(InetAddress)); }
|
||||
ZT_ALWAYS_INLINE InetAddress(const InetAddress *a) { memcpy(this,a,sizeof(InetAddress)); }
|
||||
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage &ss) { *this = ss; }
|
||||
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage *ss) { *this = ss; }
|
||||
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr &sa) { *this = sa; }
|
||||
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr *sa) { *this = sa; }
|
||||
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in &sa) { *this = sa; }
|
||||
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in *sa) { *this = sa; }
|
||||
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 &sa) { *this = sa; }
|
||||
ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 *sa) { *this = sa; }
|
||||
ZT_ALWAYS_INLINE InetAddress() { memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress)); }
|
||||
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage &ss) { *this = ss; }
|
||||
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage *ss) { *this = ss; }
|
||||
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr &sa) { *this = sa; }
|
||||
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr *sa) { *this = sa; }
|
||||
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in &sa) { *this = sa; }
|
||||
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in *sa) { *this = sa; }
|
||||
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 &sa) { *this = sa; }
|
||||
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 *sa) { *this = sa; }
|
||||
ZT_ALWAYS_INLINE InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) { this->set(ipBytes,ipLen,port); }
|
||||
ZT_ALWAYS_INLINE InetAddress(const uint32_t ipv4,unsigned int port) { this->set(&ipv4,4,port); }
|
||||
ZT_ALWAYS_INLINE InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); }
|
||||
explicit ZT_ALWAYS_INLINE InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); }
|
||||
|
||||
ZT_ALWAYS_INLINE void clear() { memset(this,0,sizeof(InetAddress)); }
|
||||
|
||||
ZT_ALWAYS_INLINE InetAddress &operator=(const InetAddress &a)
|
||||
{
|
||||
if (&a != this)
|
||||
memcpy(this,&a,sizeof(InetAddress));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE InetAddress &operator=(const InetAddress *a)
|
||||
{
|
||||
if (a != this)
|
||||
memcpy(this,a,sizeof(InetAddress));
|
||||
return *this;
|
||||
}
|
||||
ZT_ALWAYS_INLINE void clear() { memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress)); }
|
||||
|
||||
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_storage &ss)
|
||||
{
|
||||
if (reinterpret_cast<const InetAddress *>(&ss) != this)
|
||||
memcpy(this,&ss,sizeof(InetAddress));
|
||||
memcpy(reinterpret_cast<void *>(this),&ss,sizeof(InetAddress));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_storage *ss)
|
||||
{
|
||||
if (reinterpret_cast<const InetAddress *>(ss) != this)
|
||||
memcpy(this,ss,sizeof(InetAddress));
|
||||
if (ss)
|
||||
memcpy(reinterpret_cast<void *>(this),ss,sizeof(InetAddress));
|
||||
else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in &sa)
|
||||
{
|
||||
if (reinterpret_cast<const InetAddress *>(&sa) != this) {
|
||||
memset(this,0,sizeof(InetAddress));
|
||||
memcpy(this,&sa,sizeof(struct sockaddr_in));
|
||||
}
|
||||
copySockaddrToThis(&sa);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in *sa)
|
||||
{
|
||||
if (reinterpret_cast<const InetAddress *>(sa) != this) {
|
||||
memset(this,0,sizeof(InetAddress));
|
||||
memcpy(this,sa,sizeof(struct sockaddr_in));
|
||||
}
|
||||
if (sa)
|
||||
copySockaddrToThis(sa);
|
||||
else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in6 &sa)
|
||||
{
|
||||
if (reinterpret_cast<const InetAddress *>(&sa) != this) {
|
||||
memset(this,0,sizeof(InetAddress));
|
||||
memcpy(this,&sa,sizeof(struct sockaddr_in6));
|
||||
}
|
||||
copySockaddrToThis(&sa);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in6 *sa)
|
||||
{
|
||||
if (reinterpret_cast<const InetAddress *>(sa) != this) {
|
||||
memset(this,0,sizeof(InetAddress));
|
||||
memcpy(this,sa,sizeof(struct sockaddr_in6));
|
||||
}
|
||||
if (sa)
|
||||
copySockaddrToThis(sa);
|
||||
else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr &sa)
|
||||
{
|
||||
if (reinterpret_cast<const InetAddress *>(&sa) != this) {
|
||||
memset(this,0,sizeof(InetAddress));
|
||||
switch(sa.sa_family) {
|
||||
case AF_INET:
|
||||
memcpy(this,&sa,sizeof(struct sockaddr_in));
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(this,&sa,sizeof(struct sockaddr_in6));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sa.sa_family == AF_INET)
|
||||
copySockaddrToThis(reinterpret_cast<const sockaddr_in *>(&sa));
|
||||
else if (sa.sa_family == AF_INET6)
|
||||
copySockaddrToThis(reinterpret_cast<const sockaddr_in6 *>(&sa));
|
||||
else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr *sa)
|
||||
{
|
||||
if (reinterpret_cast<const InetAddress *>(sa) != this) {
|
||||
memset(this,0,sizeof(InetAddress));
|
||||
switch(sa->sa_family) {
|
||||
case AF_INET:
|
||||
memcpy(this,sa,sizeof(struct sockaddr_in));
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(this,sa,sizeof(struct sockaddr_in6));
|
||||
break;
|
||||
}
|
||||
if (sa) {
|
||||
if (sa->sa_family == AF_INET)
|
||||
copySockaddrToThis(reinterpret_cast<const sockaddr_in *>(sa));
|
||||
else if (sa->sa_family == AF_INET6)
|
||||
copySockaddrToThis(reinterpret_cast<const sockaddr_in6 *>(sa));
|
||||
return *this;
|
||||
}
|
||||
memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -468,16 +442,16 @@ struct InetAddress : public sockaddr_storage
|
||||
unsigned long h = 0;
|
||||
switch(ss_family) {
|
||||
case AF_INET:
|
||||
h = (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr) & 0xffffff00) >> 8;
|
||||
h ^= (h >> 14);
|
||||
h = (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr) & 0xffffff00U) >> 8U;
|
||||
h ^= (h >> 14U);
|
||||
break;
|
||||
case AF_INET6: {
|
||||
const uint8_t *ip = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
|
||||
h = ((unsigned long)ip[0]); h <<= 1;
|
||||
h += ((unsigned long)ip[1]); h <<= 1;
|
||||
h += ((unsigned long)ip[2]); h <<= 1;
|
||||
h += ((unsigned long)ip[3]); h <<= 1;
|
||||
h += ((unsigned long)ip[4]); h <<= 1;
|
||||
h = ((unsigned long)ip[0]); h <<= 1U;
|
||||
h += ((unsigned long)ip[1]); h <<= 1U;
|
||||
h += ((unsigned long)ip[2]); h <<= 1U;
|
||||
h += ((unsigned long)ip[3]); h <<= 1U;
|
||||
h += ((unsigned long)ip[4]); h <<= 1U;
|
||||
h += ((unsigned long)ip[5]);
|
||||
} break;
|
||||
}
|
||||
@ -487,10 +461,85 @@ struct InetAddress : public sockaddr_storage
|
||||
/**
|
||||
* @return True if address family is non-zero
|
||||
*/
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (ss_family != 0); }
|
||||
explicit ZT_ALWAYS_INLINE operator bool() const { return (ss_family != 0); }
|
||||
|
||||
// Marshal interface ///////////////////////////////////////////////////////
|
||||
static ZT_ALWAYS_INLINE int marshalSizeMax() { return 19; }
|
||||
inline int marshal(uint8_t data[19]) const
|
||||
{
|
||||
unsigned int port;
|
||||
switch(ss_family) {
|
||||
case AF_INET:
|
||||
port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in *>(this)->sin_port);
|
||||
data[0] = 4;
|
||||
data[1] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[0];
|
||||
data[2] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[1];
|
||||
data[3] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[2];
|
||||
data[4] = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const sockaddr_in *>(this)->sin_addr.s_addr))[3];
|
||||
data[5] = (uint8_t)(port >> 8U);
|
||||
data[6] = (uint8_t)port;
|
||||
return 7;
|
||||
case AF_INET6:
|
||||
port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in6 *>(this)->sin6_port);
|
||||
data[0] = 6;
|
||||
for(int i=0;i<16;++i)
|
||||
data[i+1] = reinterpret_cast<const sockaddr_in6 *>(this)->sin6_addr.s6_addr[i];
|
||||
data[17] = (uint8_t)(port >> 8U);
|
||||
data[18] = (uint8_t)port;
|
||||
return 19;
|
||||
default:
|
||||
data[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
inline int unmarshal(const uint8_t *restrict data,const int len)
|
||||
{
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
uint16_t tmp;
|
||||
#endif
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
switch(data[0]) {
|
||||
case 0:
|
||||
return 1;
|
||||
case 4:
|
||||
if (len < 7)
|
||||
return -1;
|
||||
memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
|
||||
reinterpret_cast<sockaddr_in *>(this)->sin_family = AF_INET;
|
||||
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[0] = data[1];
|
||||
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[1] = data[2];
|
||||
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[2] = data[3];
|
||||
reinterpret_cast<uint8_t *>(&(reinterpret_cast<sockaddr_in *>(this)->sin_addr.s_addr))[3] = data[4];
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
memcpy(&tmp,data + 5,2);
|
||||
reinterpret_cast<sockaddr_in *>(this)->sin_port = tmp;
|
||||
#else
|
||||
reinterpret_cast<sockaddr_in *>(this)->sin_port = *((const uint16_t *)(data + 5));
|
||||
#endif
|
||||
return 7;
|
||||
case 6:
|
||||
if (len < 19)
|
||||
return -1;
|
||||
memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
|
||||
reinterpret_cast<sockaddr_in6 *>(this)->sin6_family = AF_INET6;
|
||||
for(int i=0;i<16;i++)
|
||||
(reinterpret_cast<sockaddr_in6 *>(this)->sin6_addr.s6_addr)[i] = data[i+1];
|
||||
#ifdef ZT_NO_TYPE_PUNNING
|
||||
memcpy(&tmp,data + 17,2);
|
||||
reinterpret_cast<sockaddr_in *>(this)->sin_port = tmp;
|
||||
#else
|
||||
reinterpret_cast<sockaddr_in *>(this)->sin_port = *((const uint16_t *)(data + 17));
|
||||
#endif
|
||||
return 19;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<unsigned int C>
|
||||
ZT_ALWAYS_INLINE void serialize(Buffer<C> &b) const
|
||||
inline void serialize(Buffer<C> &b) const
|
||||
{
|
||||
// This is used in the protocol and must be the same as describe in places
|
||||
// like VERB_HELLO in Packet.hpp.
|
||||
@ -512,7 +561,7 @@ struct InetAddress : public sockaddr_storage
|
||||
}
|
||||
|
||||
template<unsigned int C>
|
||||
ZT_ALWAYS_INLINE unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
|
||||
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
|
||||
{
|
||||
memset(this,0,sizeof(InetAddress));
|
||||
unsigned int p = startAt;
|
||||
@ -607,6 +656,13 @@ struct InetAddress : public sockaddr_storage
|
||||
static InetAddress makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress);
|
||||
};
|
||||
|
||||
static ZT_ALWAYS_INLINE InetAddress *asInetAddress(sockaddr_in *p) { return reinterpret_cast<InetAddress *>(p); }
|
||||
static ZT_ALWAYS_INLINE InetAddress *asInetAddress(sockaddr_in6 *p) { return reinterpret_cast<InetAddress *>(p); }
|
||||
static ZT_ALWAYS_INLINE InetAddress *asInetAddress(sockaddr *p) { return reinterpret_cast<InetAddress *>(p); }
|
||||
static ZT_ALWAYS_INLINE const InetAddress *asInetAddress(const sockaddr_in *p) { return reinterpret_cast<const InetAddress *>(p); }
|
||||
static ZT_ALWAYS_INLINE const InetAddress *asInetAddress(const sockaddr_in6 *p) { return reinterpret_cast<const InetAddress *>(p); }
|
||||
static ZT_ALWAYS_INLINE const InetAddress *asInetAddress(const sockaddr *p) { return reinterpret_cast<const InetAddress *>(p); }
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
106
node/Locator.cpp
Normal file
106
node/Locator.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c)2019 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#include "Locator.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
bool Locator::sign(const int64_t ts,const Identity &id)
|
||||
{
|
||||
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||
if (!id.hasPrivate())
|
||||
return false;
|
||||
_ts = ts;
|
||||
if (_endpointCount > 0)
|
||||
std::sort(_at,_at + _endpointCount);
|
||||
const unsigned int signLen = marshal(signData,true);
|
||||
_signatureLength = id.sign(signData, signLen, _signature, sizeof(_signature));
|
||||
return (_signatureLength > 0);
|
||||
}
|
||||
|
||||
bool Locator::verify(const Identity &id) const
|
||||
{
|
||||
if ((_ts == 0)||(_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
||||
return false;
|
||||
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||
const unsigned int signLen = marshal(signData,true);
|
||||
return id.verify(signData,signLen,_signature,_signatureLength);
|
||||
}
|
||||
|
||||
int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool excludeSignature) const
|
||||
{
|
||||
if ((_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
||||
return -1;
|
||||
|
||||
Utils::putUInt64(data,(uint64_t)_ts);
|
||||
int p = 8;
|
||||
|
||||
data[p++] = (uint8_t)(_endpointCount >> 8U);
|
||||
data[p++] = (uint8_t)_endpointCount;
|
||||
for(unsigned int i=0;i<_endpointCount;++i) {
|
||||
int tmp = _at[i].marshal(data + p);
|
||||
if (tmp < 0)
|
||||
return -1;
|
||||
p += tmp;
|
||||
}
|
||||
|
||||
if (!excludeSignature) {
|
||||
data[p++] = (uint8_t)(_signatureLength >> 8U);
|
||||
data[p++] = (uint8_t)_signatureLength;
|
||||
memcpy(data + p,_signature,_signatureLength);
|
||||
p += (int)_signatureLength;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int Locator::unmarshal(const uint8_t *restrict data,const int len)
|
||||
{
|
||||
if (len <= (8 + 48))
|
||||
return -1;
|
||||
|
||||
_ts = (int64_t)Utils::readUInt64(data);
|
||||
int p = 8;
|
||||
|
||||
if ((p + 2) > len)
|
||||
return -1;
|
||||
unsigned int ec = (int)data[p++];
|
||||
ec <<= 8U;
|
||||
ec |= data[p++];
|
||||
if (ec > ZT_LOCATOR_MAX_ENDPOINTS)
|
||||
return -1;
|
||||
_endpointCount = ec;
|
||||
for(int i=0;i<ec;++i) {
|
||||
int tmp = _at[i].unmarshal(data + p,len - p);
|
||||
if (tmp < 0)
|
||||
return -1;
|
||||
p += tmp;
|
||||
}
|
||||
|
||||
if ((p + 2) > len)
|
||||
return -1;
|
||||
unsigned int sl = data[p++];
|
||||
sl <<= 8U;
|
||||
sl |= data[p++];
|
||||
if (sl > ZT_SIGNATURE_BUFFER_SIZE)
|
||||
return -1;
|
||||
_signatureLength = sl;
|
||||
if ((p + sl) > len)
|
||||
return -1;
|
||||
memcpy(_signature,data + p,sl);
|
||||
p += (int)sl;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user