mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-20 08:50:49 +00:00
Merge branch 'dev' into systemtray
This commit is contained in:
commit
b4bacd50a1
File diff suppressed because it is too large
Load Diff
@ -37,11 +37,15 @@
|
||||
|
||||
#include "../osdep/OSUtils.hpp"
|
||||
#include "../osdep/Thread.hpp"
|
||||
#include "../osdep/BlockingQueue.hpp"
|
||||
|
||||
#include "../ext/json/json.hpp"
|
||||
|
||||
#include "JSONDB.hpp"
|
||||
|
||||
// Number of background threads to start -- not actually started until needed
|
||||
#define ZT_EMBEDDEDNETWORKCONTROLLER_BACKGROUND_THREAD_COUNT 2
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class Node;
|
||||
@ -52,13 +56,14 @@ public:
|
||||
EmbeddedNetworkController(Node *node,const char *dbPath);
|
||||
virtual ~EmbeddedNetworkController();
|
||||
|
||||
virtual NetworkController::ResultCode doNetworkConfigRequest(
|
||||
const InetAddress &fromAddr,
|
||||
const Identity &signingId,
|
||||
const Identity &identity,
|
||||
virtual void init(const Identity &signingId,Sender *sender);
|
||||
|
||||
virtual void request(
|
||||
uint64_t nwid,
|
||||
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData,
|
||||
NetworkConfig &nc);
|
||||
const InetAddress &fromAddr,
|
||||
uint64_t requestPacketId,
|
||||
const Identity &identity,
|
||||
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
|
||||
|
||||
unsigned int handleControlPlaneHttpGET(
|
||||
const std::vector<std::string> &path,
|
||||
@ -82,8 +87,31 @@ public:
|
||||
std::string &responseBody,
|
||||
std::string &responseContentType);
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
|
||||
private:
|
||||
static void _circuitTestCallback(ZT_Node *node,ZT_CircuitTest *test,const ZT_CircuitTestReport *report);
|
||||
void _request(
|
||||
uint64_t nwid,
|
||||
const InetAddress &fromAddr,
|
||||
uint64_t requestPacketId,
|
||||
const Identity &identity,
|
||||
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
|
||||
|
||||
struct _RQEntry
|
||||
{
|
||||
uint64_t nwid;
|
||||
uint64_t requestPacketId;
|
||||
InetAddress fromAddr;
|
||||
Identity identity;
|
||||
Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData;
|
||||
};
|
||||
BlockingQueue<_RQEntry *> _queue;
|
||||
|
||||
Thread _threads[ZT_EMBEDDEDNETWORKCONTROLLER_BACKGROUND_THREAD_COUNT];
|
||||
bool _threadsStarted;
|
||||
Mutex _threads_m;
|
||||
|
||||
// Gathers a bunch of statistics about members of a network, IP assignments, etc. that we need in various places
|
||||
// This does lock _networkMemberCache_m
|
||||
@ -96,9 +124,14 @@ private:
|
||||
unsigned long activeMemberCount;
|
||||
unsigned long totalMemberCount;
|
||||
uint64_t mostRecentDeauthTime;
|
||||
uint64_t nmiTimestamp; // time this NMI structure was computed
|
||||
};
|
||||
std::map<uint64_t,_NetworkMemberInfo> _nmiCache;
|
||||
Mutex _nmiCache_m;
|
||||
void _getNetworkMemberInfo(uint64_t now,uint64_t nwid,_NetworkMemberInfo &nmi);
|
||||
|
||||
void _pushMemberUpdate(uint64_t now,uint64_t nwid,const nlohmann::json &member);
|
||||
|
||||
// These init objects with default and static/informational fields
|
||||
inline void _initMember(nlohmann::json &member)
|
||||
{
|
||||
@ -112,7 +145,8 @@ private:
|
||||
if (!member.count("creationTime")) member["creationTime"] = OSUtils::now();
|
||||
if (!member.count("noAutoAssignIps")) member["noAutoAssignIps"] = false;
|
||||
if (!member.count("revision")) member["revision"] = 0ULL;
|
||||
if (!member.count("enableBroadcast")) member["enableBroadcast"] = true;
|
||||
if (!member.count("lastDeauthorizedTime")) member["lastDeauthorizedTime"] = 0ULL;
|
||||
if (!member.count("lastAuthorizedTime")) member["lastAuthorizedTime"] = 0ULL;
|
||||
member["objtype"] = "member";
|
||||
}
|
||||
inline void _initNetwork(nlohmann::json &network)
|
||||
@ -121,6 +155,7 @@ private:
|
||||
if (!network.count("creationTime")) network["creationTime"] = OSUtils::now();
|
||||
if (!network.count("name")) network["name"] = "";
|
||||
if (!network.count("multicastLimit")) network["multicastLimit"] = (uint64_t)32;
|
||||
if (!network.count("enableBroadcast")) network["enableBroadcast"] = true;
|
||||
if (!network.count("v4AssignMode")) network["v4AssignMode"] = {{"zt",false}};
|
||||
if (!network.count("v6AssignMode")) network["v6AssignMode"] = {{"rfc4193",false},{"zt",false},{"6plane",false}};
|
||||
if (!network.count("authTokens")) network["authTokens"] = nlohmann::json::array();
|
||||
@ -154,6 +189,9 @@ private:
|
||||
Node *const _node;
|
||||
std::string _path;
|
||||
|
||||
NetworkController::Sender *_sender;
|
||||
Identity _signingId;
|
||||
|
||||
struct _CircuitTestEntry
|
||||
{
|
||||
ZT_CircuitTest *test;
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
{
|
||||
for(std::map<std::string,_E>::iterator i(_db.lower_bound(prefix));i!=_db.end();) {
|
||||
if ((i->first.length() >= prefix.length())&&(!memcmp(i->first.data(),prefix.data(),prefix.length()))) {
|
||||
if (!func(i->first,get(i->second.obj,maxSinceCheck))) {
|
||||
if (!func(i->first,get(i->first,maxSinceCheck))) {
|
||||
std::map<std::string,_E>::iterator i2(i); ++i2;
|
||||
this->erase(i->first);
|
||||
i = i2;
|
||||
|
@ -1018,16 +1018,6 @@ typedef struct
|
||||
*/
|
||||
uint64_t address;
|
||||
|
||||
/**
|
||||
* Time we last received a unicast frame from this peer
|
||||
*/
|
||||
uint64_t lastUnicastFrame;
|
||||
|
||||
/**
|
||||
* Time we last received a multicast rame from this peer
|
||||
*/
|
||||
uint64_t lastMulticastFrame;
|
||||
|
||||
/**
|
||||
* Remote major version or -1 if not known
|
||||
*/
|
||||
|
@ -475,8 +475,6 @@ jobject newPeer(JNIEnv *env, const ZT_Peer &peer)
|
||||
jclass peerClass = NULL;
|
||||
|
||||
jfieldID addressField = NULL;
|
||||
jfieldID lastUnicastFrameField = NULL;
|
||||
jfieldID lastMulticastFrameField = NULL;
|
||||
jfieldID versionMajorField = NULL;
|
||||
jfieldID versionMinorField = NULL;
|
||||
jfieldID versionRevField = NULL;
|
||||
@ -500,20 +498,6 @@ jobject newPeer(JNIEnv *env, const ZT_Peer &peer)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lastUnicastFrameField = lookup.findField(peerClass, "lastUnicastFrame", "J");
|
||||
if(env->ExceptionCheck() || lastUnicastFrameField == NULL)
|
||||
{
|
||||
LOGE("Error finding lastUnicastFrame field of Peer object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lastMulticastFrameField = lookup.findField(peerClass, "lastMulticastFrame", "J");
|
||||
if(env->ExceptionCheck() || lastMulticastFrameField == NULL)
|
||||
{
|
||||
LOGE("Error finding lastMulticastFrame field of Peer object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
versionMajorField = lookup.findField(peerClass, "versionMajor", "I");
|
||||
if(env->ExceptionCheck() || versionMajorField == NULL)
|
||||
{
|
||||
@ -571,8 +555,6 @@ jobject newPeer(JNIEnv *env, const ZT_Peer &peer)
|
||||
}
|
||||
|
||||
env->SetLongField(peerObject, addressField, (jlong)peer.address);
|
||||
env->SetLongField(peerObject, lastUnicastFrameField, (jlong)peer.lastUnicastFrame);
|
||||
env->SetLongField(peerObject, lastMulticastFrameField, (jlong)peer.lastMulticastFrame);
|
||||
env->SetIntField(peerObject, versionMajorField, peer.versionMajor);
|
||||
env->SetIntField(peerObject, versionMinorField, peer.versionMinor);
|
||||
env->SetIntField(peerObject, versionRevField, peer.versionRev);
|
||||
|
@ -34,8 +34,6 @@ import java.util.ArrayList;
|
||||
*/
|
||||
public final class Peer {
|
||||
private long address;
|
||||
private long lastUnicastFrame;
|
||||
private long lastMulticastFrame;
|
||||
private int versionMajor;
|
||||
private int versionMinor;
|
||||
private int versionRev;
|
||||
@ -52,20 +50,6 @@ public final class Peer {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time we last received a unicast frame from this peer
|
||||
*/
|
||||
public final long lastUnicastFrame() {
|
||||
return lastUnicastFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time we last received a multicast rame from this peer
|
||||
*/
|
||||
public final long lastMulticastFrame() {
|
||||
return lastMulticastFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remote major version or -1 if not known
|
||||
*/
|
||||
|
@ -59,4 +59,10 @@ enum NetworkType {
|
||||
- (NSString*)statusString;
|
||||
- (NSString*)typeString;
|
||||
|
||||
- (BOOL)hasSameNetworkId:(UInt64)networkId;
|
||||
|
||||
- (BOOL)isEqualToNetwork:(Network*)network;
|
||||
- (BOOL)isEqual:(id)object;
|
||||
- (NSUInteger)hash;
|
||||
|
||||
@end
|
||||
|
@ -275,4 +275,63 @@ NSString *NetworkAllowDefaultKey = @"allowDefault";
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)hasSameNetworkId:(UInt64)networkId
|
||||
{
|
||||
return self.nwid == networkId;
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToNetwork:(Network*)network
|
||||
{
|
||||
return [self.assignedAddresses isEqualToArray:network.assignedAddresses] &&
|
||||
self.bridge == network.bridge &&
|
||||
self.broadcastEnabled == network.broadcastEnabled &&
|
||||
self.dhcp == network.dhcp &&
|
||||
[self.mac isEqualToString:network.mac] &&
|
||||
self.mtu == network.mtu &&
|
||||
self.netconfRevision == network.netconfRevision &&
|
||||
[self.name isEqualToString:network.name] &&
|
||||
self.nwid == network.nwid &&
|
||||
[self.portDeviceName isEqualToString:network.portDeviceName] &&
|
||||
self.status == network.status &&
|
||||
self.type == network.type &&
|
||||
self.allowManaged == network.allowManaged &&
|
||||
self.allowGlobal == network.allowGlobal &&
|
||||
self.allowDefault == network.allowDefault &&
|
||||
self.connected == network.connected;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[Network class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self isEqualToNetwork:object];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash
|
||||
{
|
||||
return [self.assignedAddresses hash] ^
|
||||
self.bridge ^
|
||||
self.broadcastEnabled ^
|
||||
self.dhcp ^
|
||||
[self.mac hash] ^
|
||||
self.mtu ^
|
||||
self.netconfRevision ^
|
||||
[self.name hash] ^
|
||||
self.nwid ^
|
||||
[self.portDeviceName hash] ^
|
||||
self.portError ^
|
||||
self.status ^
|
||||
self.type ^
|
||||
self.allowManaged ^
|
||||
self.allowGlobal ^
|
||||
self.allowDefault ^
|
||||
self.connected;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
@interface ShowNetworksViewController : NSViewController<NSTableViewDelegate, NSTableViewDataSource>
|
||||
|
||||
@property (nonatomic) NSArray<Network*> *networkList;
|
||||
@property (nonatomic) NSMutableArray<Network*> *networkList;
|
||||
@property (nonatomic) NetworkMonitor *netMonitor;
|
||||
@property (nonatomic) BOOL visible;
|
||||
|
||||
|
@ -21,6 +21,17 @@
|
||||
#import "NetworkInfoCell.h"
|
||||
#import "Network.h"
|
||||
|
||||
BOOL hasNetworkWithID(NSArray<Network*> *list, UInt64 nwid)
|
||||
{
|
||||
for(Network *n in list) {
|
||||
if(n.nwid == nwid) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@interface ShowNetworksViewController ()
|
||||
|
||||
@end
|
||||
@ -30,6 +41,8 @@
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
self.networkList = [NSMutableArray array];
|
||||
|
||||
[self.tableView setDelegate:self];
|
||||
[self.tableView setDataSource:self];
|
||||
[self.tableView setBackgroundColor:[NSColor clearColor]];
|
||||
@ -50,9 +63,30 @@
|
||||
}
|
||||
|
||||
- (void)setNetworks:(NSArray<Network *> *)list {
|
||||
_networkList = list;
|
||||
if(_visible) {
|
||||
[_tableView reloadData];
|
||||
for (Network *n in list) {
|
||||
if ([_networkList containsObject:n]) {
|
||||
// don't need to do anything here. Already an identical object in the list
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// network not in the list based on equality. Did an object change? or is it a new item?
|
||||
if (hasNetworkWithID(_networkList, n.nwid)) {
|
||||
|
||||
for (int i = 0; i < [_networkList count]; ++i) {
|
||||
Network *n2 = [_networkList objectAtIndex:i];
|
||||
if (n.nwid == n2.nwid)
|
||||
{
|
||||
[_networkList replaceObjectAtIndex:i withObject:n];
|
||||
[_tableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:i]
|
||||
columnIndexes:[NSIndexSet indexSetWithIndex:0]];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
[_networkList addObject:n];
|
||||
[_tableView reloadData];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10116" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11542" systemVersion="16B2555" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10116"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11542"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="ShowNetworksViewController" customModule="ZeroTier_One" customModuleProvider="target">
|
||||
@ -24,7 +25,7 @@
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="none" columnReordering="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="386" rowSizeStyle="automatic" viewBased="YES" id="w5O-vn-cYB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="530" height="0.0"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="530" height="481"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.59999999999999998" colorSpace="calibratedRGB"/>
|
||||
@ -50,7 +51,7 @@
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="EUT-1A-lgY">
|
||||
<rect key="frame" x="480" y="364" width="44" height="19"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="bf8-gi-tpp">
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Label" id="bf8-gi-tpp">
|
||||
<font key="font" size="13" name="AndaleMono"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
@ -242,7 +243,7 @@
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="GEJ-6D-gWU">
|
||||
<rect key="frame" x="102" y="86" width="424" height="19"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Multiline Label" id="A3M-ZZ-6h7">
|
||||
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" alignment="right" title="Multiline Label" id="A3M-ZZ-6h7">
|
||||
<font key="font" size="13" name="AndaleMono"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
@ -250,7 +251,7 @@
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lO9-Jg-9f8">
|
||||
<rect key="frame" x="1" y="364" width="44" height="19"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="p7O-rs-RvR">
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Label" id="p7O-rs-RvR">
|
||||
<font key="font" size="13" name="AndaleMono"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
|
@ -84,6 +84,10 @@ ifeq ($(ZT_TRACE),1)
|
||||
DEFS+=-DZT_TRACE
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_RULES_ENGINE_DEBUGGING),1)
|
||||
DEFS+=-DZT_RULES_ENGINE_DEBUGGING
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_DEBUG),1)
|
||||
DEFS+=-DZT_TRACE
|
||||
override CFLAGS+=-Wall -g -O -pthread $(INCLUDES) $(DEFS)
|
||||
|
@ -256,12 +256,12 @@
|
||||
/**
|
||||
* How frequently to send heartbeats over in-use paths
|
||||
*/
|
||||
#define ZT_PATH_HEARTBEAT_PERIOD 10000
|
||||
#define ZT_PATH_HEARTBEAT_PERIOD 14000
|
||||
|
||||
/**
|
||||
* Paths are considered inactive if they have not received traffic in this long
|
||||
*/
|
||||
#define ZT_PATH_ALIVE_TIMEOUT 25000
|
||||
#define ZT_PATH_ALIVE_TIMEOUT 45000
|
||||
|
||||
/**
|
||||
* Minimum time between attempts to check dead paths to see if they can be re-awakened
|
||||
|
@ -865,92 +865,12 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
|
||||
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID);
|
||||
const unsigned int hopCount = hops();
|
||||
const uint64_t requestPacketId = packetId();
|
||||
bool trustEstablished = false;
|
||||
|
||||
if (RR->localNetworkController) {
|
||||
const unsigned int metaDataLength = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN);
|
||||
const char *metaDataBytes = (const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,metaDataLength);
|
||||
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData(metaDataBytes,metaDataLength);
|
||||
|
||||
NetworkConfig *netconf = new NetworkConfig();
|
||||
try {
|
||||
switch(RR->localNetworkController->doNetworkConfigRequest((hopCount > 0) ? InetAddress() : _path->address(),RR->identity,peer->identity(),nwid,metaData,*netconf)) {
|
||||
|
||||
case NetworkController::NETCONF_QUERY_OK: {
|
||||
trustEstablished = true;
|
||||
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
||||
try {
|
||||
if (netconf->toDictionary(*dconf,metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,0) < 6)) {
|
||||
uint64_t configUpdateId = RR->node->prng();
|
||||
if (!configUpdateId) ++configUpdateId;
|
||||
const unsigned int totalSize = dconf->sizeBytes();
|
||||
unsigned int chunkIndex = 0;
|
||||
while (chunkIndex < totalSize) {
|
||||
const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_UDP_DEFAULT_PAYLOAD_MTU - (ZT_PACKET_IDX_PAYLOAD + 256)));
|
||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
|
||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||
outp.append(requestPacketId);
|
||||
|
||||
const unsigned int sigStart = outp.size();
|
||||
outp.append(nwid);
|
||||
outp.append((uint16_t)chunkLen);
|
||||
outp.append((const void *)(dconf->data() + chunkIndex),chunkLen);
|
||||
|
||||
outp.append((uint8_t)0); // no flags
|
||||
outp.append((uint64_t)configUpdateId);
|
||||
outp.append((uint32_t)totalSize);
|
||||
outp.append((uint32_t)chunkIndex);
|
||||
|
||||
C25519::Signature sig(RR->identity.sign(reinterpret_cast<const uint8_t *>(outp.data()) + sigStart,outp.size() - sigStart));
|
||||
outp.append((uint8_t)1);
|
||||
outp.append((uint16_t)ZT_C25519_SIGNATURE_LEN);
|
||||
outp.append(sig.data,ZT_C25519_SIGNATURE_LEN);
|
||||
|
||||
outp.compress();
|
||||
RR->sw->send(outp,true);
|
||||
chunkIndex += chunkLen;
|
||||
}
|
||||
}
|
||||
delete dconf;
|
||||
} catch ( ... ) {
|
||||
delete dconf;
|
||||
throw;
|
||||
}
|
||||
} break;
|
||||
|
||||
case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: {
|
||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
|
||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||
outp.append(requestPacketId);
|
||||
outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND);
|
||||
outp.append(nwid);
|
||||
outp.armor(peer->key(),true);
|
||||
_path->send(RR,outp.data(),outp.size(),RR->node->now());
|
||||
} break;
|
||||
|
||||
case NetworkController::NETCONF_QUERY_ACCESS_DENIED: {
|
||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
|
||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||
outp.append(requestPacketId);
|
||||
outp.append((unsigned char)Packet::ERROR_NETWORK_ACCESS_DENIED_);
|
||||
outp.append(nwid);
|
||||
outp.armor(peer->key(),true);
|
||||
_path->send(RR,outp.data(),outp.size(),RR->node->now());
|
||||
} break;
|
||||
|
||||
case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR:
|
||||
break;
|
||||
case NetworkController::NETCONF_QUERY_IGNORE:
|
||||
break;
|
||||
default:
|
||||
TRACE("NETWORK_CONFIG_REQUEST failed: invalid return value from NetworkController::doNetworkConfigRequest()");
|
||||
break;
|
||||
}
|
||||
delete netconf;
|
||||
} catch ( ... ) {
|
||||
delete netconf;
|
||||
throw;
|
||||
}
|
||||
RR->localNetworkController->request(nwid,(hopCount > 0) ? InetAddress() : _path->address(),requestPacketId,peer->identity(),metaData);
|
||||
} else {
|
||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
|
||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||
@ -961,7 +881,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
|
||||
_path->send(RR,outp.data(),outp.size(),RR->node->now());
|
||||
}
|
||||
|
||||
peer->received(_path,hopCount,requestPacketId,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,trustEstablished);
|
||||
peer->received(_path,hopCount,requestPacketId,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,false);
|
||||
} catch (std::exception &exc) {
|
||||
fprintf(stderr,"WARNING: network config request failed with exception: %s" ZT_EOL_S,exc.what());
|
||||
TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): %s",source().toString().c_str(),_path->address().toString().c_str(),exc.what());
|
||||
|
105
node/Network.cpp
105
node/Network.cpp
@ -599,7 +599,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
|
||||
if (conf.length()) {
|
||||
dconf->load(conf.c_str());
|
||||
if (nconf->fromDictionary(*dconf)) {
|
||||
this->_setConfiguration(*nconf,false);
|
||||
this->setConfiguration(*nconf,false);
|
||||
_lastConfigUpdate = 0; // we still want to re-request a new config from the network
|
||||
gotConf = true;
|
||||
}
|
||||
@ -1015,7 +1015,7 @@ uint64_t Network::handleConfigChunk(const Packet &chunk,unsigned int ptr)
|
||||
}
|
||||
|
||||
if (nc) {
|
||||
this->_setConfiguration(*nc,true);
|
||||
this->setConfiguration(*nc,true);
|
||||
delete nc;
|
||||
return configUpdateId;
|
||||
} else {
|
||||
@ -1025,6 +1025,46 @@ uint64_t Network::handleConfigChunk(const Packet &chunk,unsigned int ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
|
||||
{
|
||||
// _lock is NOT locked when this is called
|
||||
try {
|
||||
if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != _id))
|
||||
return 0;
|
||||
if (_config == nconf)
|
||||
return 1; // OK config, but duplicate of what we already have
|
||||
|
||||
ZT_VirtualNetworkConfig ctmp;
|
||||
bool oldPortInitialized;
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
_config = nconf;
|
||||
_lastConfigUpdate = RR->node->now();
|
||||
_netconfFailure = NETCONF_FAILURE_NONE;
|
||||
oldPortInitialized = _portInitialized;
|
||||
_portInitialized = true;
|
||||
_externalConfig(&ctmp);
|
||||
}
|
||||
_portError = RR->node->configureVirtualNetworkPort(_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
|
||||
|
||||
if (saveToDisk) {
|
||||
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *d = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
||||
try {
|
||||
char n[64];
|
||||
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
|
||||
if (nconf.toDictionary(*d,false))
|
||||
RR->node->dataStorePut(n,(const void *)d->data(),d->sizeBytes(),true);
|
||||
} catch ( ... ) {}
|
||||
delete d;
|
||||
}
|
||||
|
||||
return 2; // OK and configuration has changed
|
||||
} catch ( ... ) {
|
||||
TRACE("ignored invalid configuration for network %.16llx",(unsigned long long)_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Network::requestConfiguration()
|
||||
{
|
||||
const Address ctrl(controller());
|
||||
@ -1046,26 +1086,7 @@ void Network::requestConfiguration()
|
||||
|
||||
if (ctrl == RR->identity.address()) {
|
||||
if (RR->localNetworkController) {
|
||||
NetworkConfig *nconf = new NetworkConfig();
|
||||
try {
|
||||
switch(RR->localNetworkController->doNetworkConfigRequest(InetAddress(),RR->identity,RR->identity,_id,rmd,*nconf)) {
|
||||
case NetworkController::NETCONF_QUERY_OK:
|
||||
this->_setConfiguration(*nconf,true);
|
||||
break;
|
||||
case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND:
|
||||
this->setNotFound();
|
||||
break;
|
||||
case NetworkController::NETCONF_QUERY_ACCESS_DENIED:
|
||||
this->setAccessDenied();
|
||||
break;
|
||||
default:
|
||||
this->setNotFound();
|
||||
break;
|
||||
}
|
||||
} catch ( ... ) {
|
||||
this->setNotFound();
|
||||
}
|
||||
delete nconf;
|
||||
RR->localNetworkController->request(_id,InetAddress(),0xffffffffffffffffULL,RR->identity,rmd);
|
||||
} else {
|
||||
this->setNotFound();
|
||||
}
|
||||
@ -1257,46 +1278,6 @@ ZT_VirtualNetworkStatus Network::_status() const
|
||||
}
|
||||
}
|
||||
|
||||
int Network::_setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
|
||||
{
|
||||
// _lock is NOT locked when this is called
|
||||
try {
|
||||
if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != _id))
|
||||
return 0;
|
||||
if (_config == nconf)
|
||||
return 1; // OK config, but duplicate of what we already have
|
||||
|
||||
ZT_VirtualNetworkConfig ctmp;
|
||||
bool oldPortInitialized;
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
_config = nconf;
|
||||
_lastConfigUpdate = RR->node->now();
|
||||
_netconfFailure = NETCONF_FAILURE_NONE;
|
||||
oldPortInitialized = _portInitialized;
|
||||
_portInitialized = true;
|
||||
_externalConfig(&ctmp);
|
||||
}
|
||||
_portError = RR->node->configureVirtualNetworkPort(_id,&_uPtr,(oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
|
||||
|
||||
if (saveToDisk) {
|
||||
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *d = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
||||
try {
|
||||
char n[64];
|
||||
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
|
||||
if (nconf.toDictionary(*d,false))
|
||||
RR->node->dataStorePut(n,(const void *)d->data(),d->sizeBytes(),true);
|
||||
} catch ( ... ) {}
|
||||
delete d;
|
||||
}
|
||||
|
||||
return 2; // OK and configuration has changed
|
||||
} catch ( ... ) {
|
||||
TRACE("ignored invalid configuration for network %.16llx",(unsigned long long)_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
|
||||
{
|
||||
// assumes _lock is locked
|
||||
|
@ -187,6 +187,15 @@ public:
|
||||
*/
|
||||
uint64_t handleConfigChunk(const Packet &chunk,unsigned int ptr);
|
||||
|
||||
/**
|
||||
* Set network configuration
|
||||
*
|
||||
* @param nconf Network configuration
|
||||
* @param saveToDisk Save to disk? Used during loading, should usually be true otherwise.
|
||||
* @return 0 == bad, 1 == accepted but duplicate/unchanged, 2 == accepted and new
|
||||
*/
|
||||
int setConfiguration(const NetworkConfig &nconf,bool saveToDisk);
|
||||
|
||||
/**
|
||||
* Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this
|
||||
*/
|
||||
@ -328,7 +337,6 @@ public:
|
||||
inline void **userPtr() throw() { return &_uPtr; }
|
||||
|
||||
private:
|
||||
int _setConfiguration(const NetworkConfig &nconf,bool saveToDisk);
|
||||
ZT_VirtualNetworkStatus _status() const;
|
||||
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
|
||||
bool _gate(const SharedPtr<Peer> &peer);
|
||||
|
@ -27,7 +27,6 @@
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class RuntimeEnvironment;
|
||||
class Identity;
|
||||
class Address;
|
||||
struct InetAddress;
|
||||
@ -38,45 +37,69 @@ struct InetAddress;
|
||||
class NetworkController
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Return value of doNetworkConfigRequest
|
||||
*/
|
||||
enum ResultCode
|
||||
enum ErrorCode
|
||||
{
|
||||
NETCONF_QUERY_OK = 0,
|
||||
NETCONF_QUERY_OBJECT_NOT_FOUND = 1,
|
||||
NETCONF_QUERY_ACCESS_DENIED = 2,
|
||||
NETCONF_QUERY_INTERNAL_SERVER_ERROR = 3,
|
||||
NETCONF_QUERY_IGNORE = 4
|
||||
NC_ERROR_NONE = 0,
|
||||
NC_ERROR_OBJECT_NOT_FOUND = 1,
|
||||
NC_ERROR_ACCESS_DENIED = 2,
|
||||
NC_ERROR_INTERNAL_SERVER_ERROR = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for sender used to send pushes and replies
|
||||
*/
|
||||
class Sender
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Send a configuration to a remote peer
|
||||
*
|
||||
* @param nwid Network ID
|
||||
* @param requestPacketId Request packet ID to send OK(NETWORK_CONFIG_REQUEST) or 0 to send NETWORK_CONFIG (push)
|
||||
* @param destination Destination peer Address
|
||||
* @param nc Network configuration to send
|
||||
* @param sendLegacyFormatConfig If true, send an old-format network config
|
||||
*/
|
||||
virtual void ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig) = 0;
|
||||
|
||||
/**
|
||||
* Send a network configuration request error
|
||||
*
|
||||
* @param nwid Network ID
|
||||
* @param requestPacketId Request packet ID or 0 if none
|
||||
* @param destination Destination peer Address
|
||||
* @param errorCode Error code
|
||||
*/
|
||||
virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode) = 0;
|
||||
};
|
||||
|
||||
NetworkController() {}
|
||||
virtual ~NetworkController() {}
|
||||
|
||||
/**
|
||||
* Handle a network config request, sending replies if necessary
|
||||
* Called when this is added to a Node to initialize and supply info
|
||||
*
|
||||
* This call is permitted to block, and may be called concurrently from more
|
||||
* than one thread. Implementations must use locks if needed.
|
||||
* @param signingId Identity for signing of network configurations, certs, etc.
|
||||
* @param sender Sender implementation for sending replies or config pushes
|
||||
*/
|
||||
virtual void init(const Identity &signingId,Sender *sender) = 0;
|
||||
|
||||
/**
|
||||
* Handle a network configuration request
|
||||
*
|
||||
* On internal server errors, the 'error' field in result can be filled in
|
||||
* to indicate the error.
|
||||
*
|
||||
* @param fromAddr Originating wire address or null address if packet is not direct (or from self)
|
||||
* @param signingId Identity that should be used to sign results -- must include private key
|
||||
* @param identity Originating peer ZeroTier identity
|
||||
* @param nwid 64-bit network ID
|
||||
* @param fromAddr Originating wire address or null address if packet is not direct (or from self)
|
||||
* @param requestPacketId Packet ID of request packet or 0 if not initiated by remote request
|
||||
* @param identity ZeroTier identity of originating peer
|
||||
* @param metaData Meta-data bundled with request (if any)
|
||||
* @param nc NetworkConfig to fill with results
|
||||
* @return Returns NETCONF_QUERY_OK if result 'nc' is valid, or an error code on error
|
||||
*/
|
||||
virtual NetworkController::ResultCode doNetworkConfigRequest(
|
||||
const InetAddress &fromAddr,
|
||||
const Identity &signingId,
|
||||
const Identity &identity,
|
||||
virtual void request(
|
||||
uint64_t nwid,
|
||||
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData,
|
||||
NetworkConfig &nc) = 0;
|
||||
const InetAddress &fromAddr,
|
||||
uint64_t requestPacketId,
|
||||
const Identity &identity,
|
||||
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData) = 0;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
@ -405,8 +405,6 @@ ZT_PeerList *Node::peers() const
|
||||
for(std::vector< std::pair< Address,SharedPtr<Peer> > >::iterator pi(peers.begin());pi!=peers.end();++pi) {
|
||||
ZT_Peer *p = &(pl->peers[pl->peerCount++]);
|
||||
p->address = pi->second->address().toInt();
|
||||
p->lastUnicastFrame = pi->second->lastUnicastFrame();
|
||||
p->lastMulticastFrame = pi->second->lastMulticastFrame();
|
||||
if (pi->second->remoteVersionKnown()) {
|
||||
p->versionMajor = pi->second->remoteVersionMajor();
|
||||
p->versionMinor = pi->second->remoteVersionMinor();
|
||||
@ -492,6 +490,7 @@ void Node::clearLocalInterfaceAddresses()
|
||||
void Node::setNetconfMaster(void *networkControllerInstance)
|
||||
{
|
||||
RR->localNetworkController = reinterpret_cast<NetworkController *>(networkControllerInstance);
|
||||
RR->localNetworkController->init(RR->identity,this);
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
|
||||
@ -720,6 +719,92 @@ void Node::setTrustedPaths(const struct sockaddr_storage *networks,const uint64_
|
||||
RR->topology->setTrustedPaths(reinterpret_cast<const InetAddress *>(networks),ids,count);
|
||||
}
|
||||
|
||||
void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig)
|
||||
{
|
||||
if (destination == RR->identity.address()) {
|
||||
SharedPtr<Network> n(network(nwid));
|
||||
if (!n) return;
|
||||
n->setConfiguration(nc,true);
|
||||
} else {
|
||||
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
||||
try {
|
||||
if (nc.toDictionary(*dconf,sendLegacyFormatConfig)) {
|
||||
uint64_t configUpdateId = prng();
|
||||
if (!configUpdateId) ++configUpdateId;
|
||||
|
||||
const unsigned int totalSize = dconf->sizeBytes();
|
||||
unsigned int chunkIndex = 0;
|
||||
while (chunkIndex < totalSize) {
|
||||
const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_UDP_DEFAULT_PAYLOAD_MTU - (ZT_PACKET_IDX_PAYLOAD + 256)));
|
||||
Packet outp(destination,RR->identity.address(),(requestPacketId) ? Packet::VERB_OK : Packet::VERB_NETWORK_CONFIG);
|
||||
if (requestPacketId) {
|
||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||
outp.append(requestPacketId);
|
||||
}
|
||||
|
||||
const unsigned int sigStart = outp.size();
|
||||
outp.append(nwid);
|
||||
outp.append((uint16_t)chunkLen);
|
||||
outp.append((const void *)(dconf->data() + chunkIndex),chunkLen);
|
||||
|
||||
outp.append((uint8_t)0); // no flags
|
||||
outp.append((uint64_t)configUpdateId);
|
||||
outp.append((uint32_t)totalSize);
|
||||
outp.append((uint32_t)chunkIndex);
|
||||
|
||||
C25519::Signature sig(RR->identity.sign(reinterpret_cast<const uint8_t *>(outp.data()) + sigStart,outp.size() - sigStart));
|
||||
outp.append((uint8_t)1);
|
||||
outp.append((uint16_t)ZT_C25519_SIGNATURE_LEN);
|
||||
outp.append(sig.data,ZT_C25519_SIGNATURE_LEN);
|
||||
|
||||
outp.compress();
|
||||
RR->sw->send(outp,true);
|
||||
chunkIndex += chunkLen;
|
||||
}
|
||||
}
|
||||
delete dconf;
|
||||
} catch ( ... ) {
|
||||
delete dconf;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode)
|
||||
{
|
||||
if (destination == RR->identity.address()) {
|
||||
SharedPtr<Network> n(network(nwid));
|
||||
if (!n) return;
|
||||
switch(errorCode) {
|
||||
case NetworkController::NC_ERROR_OBJECT_NOT_FOUND:
|
||||
case NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR:
|
||||
n->setNotFound();
|
||||
break;
|
||||
case NetworkController::NC_ERROR_ACCESS_DENIED:
|
||||
n->setAccessDenied();
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else if (requestPacketId) {
|
||||
Packet outp(destination,RR->identity.address(),Packet::VERB_ERROR);
|
||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||
outp.append(requestPacketId);
|
||||
switch(errorCode) {
|
||||
//case NetworkController::NC_ERROR_OBJECT_NOT_FOUND:
|
||||
//case NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR:
|
||||
default:
|
||||
outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND);
|
||||
break;
|
||||
case NetworkController::NC_ERROR_ACCESS_DENIED:
|
||||
outp.append((unsigned char)Packet::ERROR_NETWORK_ACCESS_DENIED_);
|
||||
break;
|
||||
}
|
||||
outp.append(nwid);
|
||||
RR->sw->send(outp,true);
|
||||
} // else we can't send an ERROR() in response to nothing, so discard
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
/****************************************************************************/
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "Network.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "NetworkController.hpp"
|
||||
|
||||
#undef TRACE
|
||||
#ifdef ZT_TRACE
|
||||
@ -55,7 +56,7 @@ namespace ZeroTier {
|
||||
*
|
||||
* The pointer returned by ZT_Node_new() is an instance of this class.
|
||||
*/
|
||||
class Node
|
||||
class Node : public NetworkController::Sender
|
||||
{
|
||||
public:
|
||||
Node(
|
||||
@ -69,7 +70,7 @@ public:
|
||||
ZT_PathCheckFunction pathCheckFunction,
|
||||
ZT_EventCallback eventCallback);
|
||||
|
||||
~Node();
|
||||
virtual ~Node();
|
||||
|
||||
// Public API Functions ----------------------------------------------------
|
||||
|
||||
@ -282,6 +283,9 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig);
|
||||
virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode);
|
||||
|
||||
private:
|
||||
inline SharedPtr<Network> _network(uint64_t nwid) const
|
||||
{
|
||||
|
@ -42,8 +42,7 @@ static uint32_t _natKeepaliveBuf = 0;
|
||||
|
||||
Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) :
|
||||
_lastReceive(0),
|
||||
_lastUnicastFrame(0),
|
||||
_lastMulticastFrame(0),
|
||||
_lastNontrivialReceive(0),
|
||||
_lastDirectPathPushSent(0),
|
||||
_lastDirectPathPushReceive(0),
|
||||
_lastCredentialRequestSent(0),
|
||||
@ -128,10 +127,16 @@ void Peer::received(
|
||||
#endif
|
||||
|
||||
_lastReceive = now;
|
||||
if ((verb == Packet::VERB_FRAME)||(verb == Packet::VERB_EXT_FRAME))
|
||||
_lastUnicastFrame = now;
|
||||
else if (verb == Packet::VERB_MULTICAST_FRAME)
|
||||
_lastMulticastFrame = now;
|
||||
switch (verb) {
|
||||
case Packet::VERB_FRAME:
|
||||
case Packet::VERB_EXT_FRAME:
|
||||
case Packet::VERB_NETWORK_CONFIG_REQUEST:
|
||||
case Packet::VERB_NETWORK_CONFIG:
|
||||
case Packet::VERB_MULTICAST_FRAME:
|
||||
_lastNontrivialReceive = now;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (trustEstablished) {
|
||||
_lastTrustEstablishedPacketReceived = now;
|
||||
|
@ -226,25 +226,10 @@ public:
|
||||
*/
|
||||
inline bool isAlive(const uint64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
|
||||
|
||||
/**
|
||||
* @return Time of most recent unicast frame received
|
||||
*/
|
||||
inline uint64_t lastUnicastFrame() const { return _lastUnicastFrame; }
|
||||
|
||||
/**
|
||||
* @return Time of most recent multicast frame received
|
||||
*/
|
||||
inline uint64_t lastMulticastFrame() const { return _lastMulticastFrame; }
|
||||
|
||||
/**
|
||||
* @return Time of most recent frame of any kind (unicast or multicast)
|
||||
*/
|
||||
inline uint64_t lastFrame() const { return std::max(_lastUnicastFrame,_lastMulticastFrame); }
|
||||
|
||||
/**
|
||||
* @return True if this peer has sent us real network traffic recently
|
||||
*/
|
||||
inline uint64_t isActive(uint64_t now) const { return ((now - lastFrame()) < ZT_PEER_ACTIVITY_TIMEOUT); }
|
||||
inline uint64_t isActive(uint64_t now) const { return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
|
||||
|
||||
/**
|
||||
* @return Latency in milliseconds or 0 if unknown
|
||||
@ -469,8 +454,7 @@ private:
|
||||
uint8_t _key[ZT_PEER_SECRET_KEY_LENGTH];
|
||||
uint8_t _remoteClusterOptimal6[16];
|
||||
uint64_t _lastReceive; // direct or indirect
|
||||
uint64_t _lastUnicastFrame;
|
||||
uint64_t _lastMulticastFrame;
|
||||
uint64_t _lastNontrivialReceive; // frames, things like netconf, etc.
|
||||
uint64_t _lastDirectPathPushSent;
|
||||
uint64_t _lastDirectPathPushReceive;
|
||||
uint64_t _lastCredentialRequestSent;
|
||||
|
11
one.cpp
11
one.cpp
@ -973,6 +973,7 @@ int main(int argc,char **argv)
|
||||
std::string homeDir;
|
||||
unsigned int port = ZT_DEFAULT_PORT;
|
||||
bool skipRootCheck = false;
|
||||
const char *allowManagementFrom = (const char *)0;
|
||||
|
||||
for(int i=1;i<argc;++i) {
|
||||
if (argv[i][0] == '-') {
|
||||
@ -986,6 +987,14 @@ int main(int argc,char **argv)
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M': // allow management from this IP/bits network
|
||||
allowManagementFrom = argv[i] + 2;
|
||||
if (!strlen(allowManagementFrom)) {
|
||||
printHelp(argv[0],stdout);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
case 'd': // Run in background as daemon
|
||||
runAsDaemon = true;
|
||||
@ -1167,7 +1176,7 @@ int main(int argc,char **argv)
|
||||
unsigned int returnValue = 0;
|
||||
|
||||
for(;;) {
|
||||
zt1Service = OneService::newInstance(homeDir.c_str(),port);
|
||||
zt1Service = OneService::newInstance(homeDir.c_str(),port,allowManagementFrom);
|
||||
switch(zt1Service->run()) {
|
||||
case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done
|
||||
case OneService::ONE_NORMAL_TERMINATION:
|
||||
|
64
osdep/BlockingQueue.hpp
Normal file
64
osdep/BlockingQueue.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ZT_BLOCKINGQUEUE_HPP
|
||||
#define ZT_BLOCKINGQUEUE_HPP
|
||||
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Simple C++11 thread-safe queue
|
||||
*
|
||||
* Do not use in node/ since we have not gone C++11 there yet.
|
||||
*/
|
||||
template <class T>
|
||||
class BlockingQueue
|
||||
{
|
||||
public:
|
||||
BlockingQueue(void) {}
|
||||
|
||||
inline void post(T t)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
q.push(t);
|
||||
c.notify_one();
|
||||
}
|
||||
|
||||
inline T get(void)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
while(q.empty())
|
||||
c.wait(lock);
|
||||
T val = q.front();
|
||||
q.pop();
|
||||
return val;
|
||||
}
|
||||
|
||||
private:
|
||||
std::queue<T> q;
|
||||
mutable std::mutex m;
|
||||
std::condition_variable c;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
@ -102,6 +102,8 @@ void dropPrivileges(std::string homeDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
createOwnedHomedir(homeDir, targetUser);
|
||||
|
||||
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_RAW, 0, 0) < 0) {
|
||||
// Kernel has no support for ambient capabilities.
|
||||
notDropping(homeDir);
|
||||
@ -113,8 +115,6 @@ void dropPrivileges(std::string homeDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
createOwnedHomedir(homeDir, targetUser);
|
||||
|
||||
if (setCapabilities((1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID) | (1 << CAP_SETGID)) < 0) {
|
||||
fprintf(stderr, "ERROR: failed to set capabilities (not running as real root?)\n");
|
||||
exit(1);
|
||||
|
@ -222,8 +222,6 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_Peer *peer)
|
||||
Utils::snprintf(json,sizeof(json),
|
||||
"%s{\n"
|
||||
"%s\t\"address\": \"%.10llx\",\n"
|
||||
"%s\t\"lastUnicastFrame\": %llu,\n"
|
||||
"%s\t\"lastMulticastFrame\": %llu,\n"
|
||||
"%s\t\"versionMajor\": %d,\n"
|
||||
"%s\t\"versionMinor\": %d,\n"
|
||||
"%s\t\"versionRev\": %d,\n"
|
||||
@ -234,8 +232,6 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_Peer *peer)
|
||||
"%s}",
|
||||
prefix,
|
||||
prefix,peer->address,
|
||||
prefix,peer->lastUnicastFrame,
|
||||
prefix,peer->lastMulticastFrame,
|
||||
prefix,peer->versionMajor,
|
||||
prefix,peer->versionMinor,
|
||||
prefix,peer->versionRev,
|
||||
@ -274,9 +270,6 @@ unsigned int ControlPlane::handleRequest(
|
||||
std::map<std::string,std::string> urlArgs;
|
||||
Mutex::Lock _l(_lock);
|
||||
|
||||
if (!((fromAddress.ipsEqual(InetAddress::LO4))||(fromAddress.ipsEqual(InetAddress::LO6))))
|
||||
return 403; // Forbidden: we only allow access from localhost right now
|
||||
|
||||
/* Note: this is kind of restricted in what it'll take. It does not support
|
||||
* URL encoding, and /'s in URL args will screw it up. But the only URL args
|
||||
* it really uses in ?jsonp=funcionName, and otherwise it just takes simple
|
||||
|
@ -483,6 +483,7 @@ public:
|
||||
|
||||
const std::string _homePath;
|
||||
BackgroundResolver _tcpFallbackResolver;
|
||||
InetAddress _allowManagementFrom;
|
||||
EmbeddedNetworkController *_controller;
|
||||
Phy<OneServiceImpl *> _phy;
|
||||
Node *_node;
|
||||
@ -570,7 +571,7 @@ public:
|
||||
|
||||
// end member variables ----------------------------------------------------
|
||||
|
||||
OneServiceImpl(const char *hp,unsigned int port) :
|
||||
OneServiceImpl(const char *hp,unsigned int port,const char *allowManagementFrom) :
|
||||
_homePath((hp) ? hp : ".")
|
||||
,_tcpFallbackResolver(ZT_TCP_FALLBACK_RELAY)
|
||||
,_controller((EmbeddedNetworkController *)0)
|
||||
@ -595,6 +596,9 @@ public:
|
||||
#endif
|
||||
,_run(true)
|
||||
{
|
||||
if (allowManagementFrom)
|
||||
_allowManagementFrom.fromString(allowManagementFrom);
|
||||
|
||||
_ports[0] = 0;
|
||||
_ports[1] = 0;
|
||||
_ports[2] = 0;
|
||||
@ -614,7 +618,7 @@ public:
|
||||
struct sockaddr_in in4;
|
||||
memset(&in4,0,sizeof(in4));
|
||||
in4.sin_family = AF_INET;
|
||||
in4.sin_addr.s_addr = Utils::hton((uint32_t)0x7f000001); // right now we just listen for TCP @127.0.0.1
|
||||
in4.sin_addr.s_addr = Utils::hton((uint32_t)((allowManagementFrom) ? 0 : 0x7f000001)); // right now we just listen for TCP @127.0.0.1
|
||||
in4.sin_port = Utils::hton((uint16_t)port);
|
||||
_v4TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in4,this);
|
||||
|
||||
@ -622,7 +626,8 @@ public:
|
||||
memset((void *)&in6,0,sizeof(in6));
|
||||
in6.sin6_family = AF_INET6;
|
||||
in6.sin6_port = in4.sin_port;
|
||||
in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1
|
||||
if (!allowManagementFrom)
|
||||
in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1
|
||||
_v6TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in6,this);
|
||||
|
||||
// We must bind one of IPv4 or IPv6 -- support either failing to support hosts that
|
||||
@ -1259,12 +1264,10 @@ public:
|
||||
|
||||
inline void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from)
|
||||
{
|
||||
if ((!from)||(reinterpret_cast<const InetAddress *>(from)->ipScope() != InetAddress::IP_SCOPE_LOOPBACK)) {
|
||||
// Non-Loopback: deny (for now)
|
||||
if (!from) {
|
||||
_phy.close(sockN,false);
|
||||
return;
|
||||
} else {
|
||||
// Loopback == HTTP JSON API request
|
||||
TcpConnection *tc = new TcpConnection();
|
||||
_tcpConnections.insert(tc);
|
||||
tc->type = TcpConnection::TCP_HTTP_INCOMING;
|
||||
@ -1701,16 +1704,20 @@ public:
|
||||
std::string contentType("text/plain"); // default if not changed in handleRequest()
|
||||
unsigned int scode = 404;
|
||||
|
||||
try {
|
||||
if (_controlPlane)
|
||||
scode = _controlPlane->handleRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType);
|
||||
else scode = 500;
|
||||
} catch (std::exception &exc) {
|
||||
fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what());
|
||||
scode = 500;
|
||||
} catch ( ... ) {
|
||||
fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: unknown exceptino" ZT_EOL_S);
|
||||
scode = 500;
|
||||
if ( ((!_allowManagementFrom)&&(tc->from.ipScope() == InetAddress::IP_SCOPE_LOOPBACK)) || (_allowManagementFrom.containsAddress(tc->from)) ) {
|
||||
try {
|
||||
if (_controlPlane)
|
||||
scode = _controlPlane->handleRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType);
|
||||
else scode = 500;
|
||||
} catch (std::exception &exc) {
|
||||
fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: %s" ZT_EOL_S,exc.what());
|
||||
scode = 500;
|
||||
} catch ( ... ) {
|
||||
fprintf(stderr,"WARNING: unexpected exception processing control HTTP request: unknown exceptino" ZT_EOL_S);
|
||||
scode = 500;
|
||||
}
|
||||
} else {
|
||||
scode = 401;
|
||||
}
|
||||
|
||||
const char *scodestr;
|
||||
@ -1975,7 +1982,7 @@ std::string OneService::autoUpdateUrl()
|
||||
return std::string();
|
||||
}
|
||||
|
||||
OneService *OneService::newInstance(const char *hp,unsigned int port) { return new OneServiceImpl(hp,port); }
|
||||
OneService *OneService::newInstance(const char *hp,unsigned int port,const char *allowManagementFrom) { return new OneServiceImpl(hp,port,allowManagementFrom); }
|
||||
OneService::~OneService() {}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
@ -98,10 +98,12 @@ public:
|
||||
*
|
||||
* @param hp Home path
|
||||
* @param port TCP and UDP port for packets and HTTP control (if 0, pick random port)
|
||||
* @param allowManagementFrom If non-NULL, allow control from supplied IP/netmask
|
||||
*/
|
||||
static OneService *newInstance(
|
||||
const char *hp,
|
||||
unsigned int port);
|
||||
unsigned int port,
|
||||
const char *allowManagementFrom = (const char *)0);
|
||||
|
||||
virtual ~OneService();
|
||||
|
||||
|
@ -25,6 +25,8 @@ A *jsonp* URL argument may be supplied to request JSONP encapsulation. A JSONP r
|
||||
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Writable</b></td></tr>
|
||||
<tr><td>address</td><td>string</td><td>10-digit hexadecimal ZeroTier address of this node</td><td>no</td></tr>
|
||||
<tr><td>publicIdentity</td><td>string</td><td>Full public ZeroTier identity of this node</td><td>no</td></tr>
|
||||
<tr><td>worldId</td><td>integer</td><td>Fixed value representing the virtual data center of Earth.</td><td>no</td></tr>
|
||||
<tr><td>worldTimestamp</td><td>integer</td><td>Timestamp of the last root server topology change.</td><td>no</td></tr>
|
||||
<tr><td>online</td><td>boolean</td><td>Does this node appear to have upstream network access?</td><td>no</td></tr>
|
||||
<tr><td>tcpFallbackActive</td><td>boolean</td><td>Is TCP fallback mode active?</td><td>no</td></tr>
|
||||
<tr><td>versionMajor</td><td>integer</td><td>ZeroTier major version</td><td>no</td></tr>
|
||||
@ -77,9 +79,22 @@ Most network settings are not writable, as they are defined by the network contr
|
||||
<tr><td>broadcastEnabled</td><td>boolean</td><td>Is Ethernet broadcast (ff:ff:ff:ff:ff:ff) allowed?</td><td>no</td></tr>
|
||||
<tr><td>portError</td><td>integer</td><td>Error code (if any) returned by underlying OS "tap" driver</td><td>no</td></tr>
|
||||
<tr><td>netconfRevision</td><td>integer</td><td>Network configuration revision ID</td><td>no</td></tr>
|
||||
<tr><td>multicastSubscriptions</td><td>[string]</td><td>Multicast memberships as array of MAC/ADI tuples</td><td>no</td></tr>
|
||||
<tr><td>assignedAddresses</td><td>[string]</td><td>ZeroTier-managed IP address assignments as array of IP/netmask bits tuples</td><td>no</td></tr>
|
||||
<tr><td>routes</td><td>[route]</td><td>ZeroTier-managed route assignments for a network. See below for a description of the route object.</td><td>no</td></tr>
|
||||
<tr><td>portDeviceName</td><td>string</td><td>OS-specific network device name (if available)</td><td>no</td></tr>
|
||||
<tr><td>allowManaged</td><td>boolean</td><td>Whether ZeroTier-managed IP addresses are allowed.</td><td>yes</td></tr>
|
||||
<tr><td>allowGlobal</td><td>boolean</td><td>Whether globally-reachable IP addresses are allowed to be assigned.</td><td>yes</td></tr>
|
||||
<tr><td>allowDefault</td><td>boolean</td><td>Whether a default route is allowed to be assigned for the network (route all traffic via ZeroTier)</td><td>yes</td></tr>
|
||||
</table>
|
||||
|
||||
`route` objects
|
||||
|
||||
<table>
|
||||
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Writable</b></td></tr>
|
||||
<tr><td>target</td><td>string</td><td>Target network / netmask bits, NULL, or 0.0.0.0/0 for default route</td><td>no</td></tr>
|
||||
<tr><td>via</td><td>string</td><td>Gateway IP address</td><td>no</td></tr>
|
||||
<tr><td>flags</td><td>integer</td><td>Route flags</td><td>no</td></tr>
|
||||
<tr><td>metric</td><td>integer</td><td>Route metric (not currently used)</td><td>no</td></tr>
|
||||
</table>
|
||||
|
||||
#### /peer
|
||||
@ -99,8 +114,6 @@ Getting /peer returns an array of peer objects for all current peers. See below
|
||||
<table>
|
||||
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Writable</b></td></tr>
|
||||
<tr><td>address</td><td>string</td><td>10-digit hex ZeroTier address</td><td>no</td></tr>
|
||||
<tr><td>lastUnicastFrame</td><td>integer</td><td>Time of last unicast frame in ms since epoch</td><td>no</td></tr>
|
||||
<tr><td>lastMulticastFrame</td><td>integer</td><td>Time of last multicast frame in ms since epoch</td><td>no</td></tr>
|
||||
<tr><td>versionMajor</td><td>integer</td><td>Major version of remote if known</td><td>no</td></tr>
|
||||
<tr><td>versionMinor</td><td>integer</td><td>Minor version of remote if known</td><td>no</td></tr>
|
||||
<tr><td>versionRev</td><td>integer</td><td>Revision of remote if known</td><td>no</td></tr>
|
||||
|
233
windows/WinUI/MainWindow.xaml.cs
Normal file
233
windows/WinUI/MainWindow.xaml.cs
Normal file
@ -0,0 +1,233 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Timers;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace WinUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
APIHandler handler;
|
||||
Regex charRegex = new Regex("[0-9a-fxA-FX]");
|
||||
Regex wholeStringRegex = new Regex("^[0-9a-fxA-FX]+$");
|
||||
|
||||
Timer timer = new Timer();
|
||||
|
||||
bool connected = false;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
if (InitAPIHandler())
|
||||
{
|
||||
networksPage.SetAPIHandler(handler);
|
||||
|
||||
updateStatus();
|
||||
if (!connected)
|
||||
{
|
||||
MessageBox.Show("Unable to connect to ZeroTier Service.");
|
||||
}
|
||||
|
||||
updateNetworks();
|
||||
//updatePeers();
|
||||
|
||||
DataObject.AddPastingHandler(joinNetworkID, OnPaste);
|
||||
|
||||
timer.Elapsed += new ElapsedEventHandler(OnUpdateTimer);
|
||||
timer.Interval = 2000;
|
||||
timer.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String readAuthToken(String path)
|
||||
{
|
||||
String authToken = "";
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] tmp = File.ReadAllBytes(path);
|
||||
authToken = System.Text.Encoding.UTF8.GetString(tmp).Trim();
|
||||
}
|
||||
catch
|
||||
{
|
||||
MessageBox.Show("Unable to read ZeroTier One Auth Token from:\r\n" + path, "ZeroTier One");
|
||||
}
|
||||
}
|
||||
|
||||
return authToken;
|
||||
}
|
||||
|
||||
private Int32 readPort(String path)
|
||||
{
|
||||
Int32 port = 9993;
|
||||
|
||||
try
|
||||
{
|
||||
byte[] tmp = File.ReadAllBytes(path);
|
||||
port = Int32.Parse(System.Text.Encoding.ASCII.GetString(tmp).Trim());
|
||||
if ((port <= 0) || (port > 65535))
|
||||
port = 9993;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
private bool InitAPIHandler()
|
||||
{
|
||||
String localZtDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\ZeroTier\\One";
|
||||
String globalZtDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\ZeroTier\\One";
|
||||
|
||||
String authToken = "";
|
||||
Int32 port = 9993;
|
||||
|
||||
if (!File.Exists(localZtDir + "\\authtoken.secret") || !File.Exists(localZtDir + "\\zerotier-one.port"))
|
||||
{
|
||||
// launch external process to copy file into place
|
||||
String curPath = System.Reflection.Assembly.GetEntryAssembly().Location;
|
||||
int index = curPath.LastIndexOf("\\");
|
||||
curPath = curPath.Substring(0, index);
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo(curPath + "\\copyutil.exe", globalZtDir + " " + localZtDir);
|
||||
startInfo.Verb = "runas";
|
||||
|
||||
|
||||
var process = Process.Start(startInfo);
|
||||
process.WaitForExit();
|
||||
}
|
||||
|
||||
authToken = readAuthToken(localZtDir + "\\authtoken.secret");
|
||||
|
||||
if ((authToken == null) || (authToken.Length <= 0))
|
||||
{
|
||||
MessageBox.Show("Unable to read ZeroTier One authtoken", "ZeroTier One");
|
||||
this.Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
port = readPort(localZtDir + "\\zerotier-one.port");
|
||||
handler = new APIHandler(port, authToken);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateStatus()
|
||||
{
|
||||
var status = handler.GetStatus();
|
||||
|
||||
if (status != null)
|
||||
{
|
||||
connected = true;
|
||||
|
||||
networkId.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
this.networkId.Text = status.Address;
|
||||
}));
|
||||
versionString.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
this.versionString.Content = status.Version;
|
||||
}));
|
||||
onlineStatus.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
this.onlineStatus.Content = (status.Online ? "ONLINE" : "OFFLINE");
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
connected = false;
|
||||
|
||||
networkId.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
this.networkId.Text = "";
|
||||
}));
|
||||
versionString.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
this.versionString.Content = "0";
|
||||
}));
|
||||
onlineStatus.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
this.onlineStatus.Content = "OFFLINE";
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNetworks()
|
||||
{
|
||||
var networks = handler.GetNetworks();
|
||||
|
||||
networksPage.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
networksPage.setNetworks(networks);
|
||||
}));
|
||||
}
|
||||
|
||||
private void updatePeers()
|
||||
{
|
||||
//var peers = handler.GetPeers();
|
||||
|
||||
//peersPage.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
//{
|
||||
// peersPage.SetPeers(peers);
|
||||
//}));
|
||||
}
|
||||
|
||||
private void OnUpdateTimer(object source, ElapsedEventArgs e)
|
||||
{
|
||||
updateStatus();
|
||||
updateNetworks();
|
||||
//updatePeers();
|
||||
}
|
||||
|
||||
private void joinButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (joinNetworkID.Text.Length < 16)
|
||||
{
|
||||
MessageBox.Show("Invalid Network ID");
|
||||
}
|
||||
else
|
||||
{
|
||||
handler.JoinNetwork(joinNetworkID.Text);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnNetworkEntered(object sender, TextCompositionEventArgs e)
|
||||
{
|
||||
e.Handled = !charRegex.IsMatch(e.Text);
|
||||
}
|
||||
|
||||
private void OnPaste(object sender, DataObjectPastingEventArgs e)
|
||||
{
|
||||
var isText = e.SourceDataObject.GetDataPresent(DataFormats.UnicodeText, true);
|
||||
if (!isText) return;
|
||||
|
||||
var text = e.SourceDataObject.GetData(DataFormats.UnicodeText) as string;
|
||||
|
||||
if (!wholeStringRegex.IsMatch(text))
|
||||
{
|
||||
e.CancelCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -64,7 +64,7 @@
|
||||
<TextBlock x:Name="broadcastEnabled" FontFamily="Lucida Console" TextWrapping="Wrap" Text="ENABLED" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="6" Foreground="#FF000000"/>
|
||||
<TextBlock x:Name="bridgingEnabled" FontFamily="Lucida Console" TextWrapping="Wrap" Text="DISABLED" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="7" Background="#FFEEEEEE" Foreground="#FF000000"/>
|
||||
<TextBlock x:Name="deviceName" FontFamily="Lucida Console" TextWrapping="Wrap" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="8" Foreground="#FF000000"><Span><Run Text="ethernet_32771"/></Span></TextBlock>
|
||||
<TextBlock x:Name="managedIps" TextWrapping="Wrap" FontFamily="Lucida Console" HorizontalAlignment="Right" TextAlignment="Right" Grid.Column="2" Grid.Row="9" Foreground="#FF000000"><Span><Run Text="28.2.169.248/7 "/></Span><LineBreak/><Span><Run Text="fd80:56c2:e21c:0000:0199:9383:4a02:a9f8/88"/></Span></TextBlock>
|
||||
<TextBox x:Name="managedIps" TextWrapping="Wrap" FontFamily="Lucida Console" HorizontalAlignment="Right" TextAlignment="Right" Grid.Column="2" Grid.Row="9" Foreground="#FF000000" IsReadOnly="True" BorderThickness="0" Background="#FFEEEEEE" Text="28.2.169.248/7
fd80:56c2:e21c:0000:0199:9383:4a02:a9f8/88"/>
|
||||
<CheckBox x:Name="allowGlobal" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="10" />
|
||||
<CheckBox x:Name="allowManaged" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="11" />
|
||||
<CheckBox x:Name="allowDefault" HorizontalAlignment="Right" Grid.Column="2" Grid.Row="12" />
|
||||
|
@ -20,7 +20,7 @@ namespace WinUI
|
||||
/// </summary>
|
||||
public partial class NetworkInfoView : UserControl
|
||||
{
|
||||
private ZeroTierNetwork network;
|
||||
public ZeroTierNetwork network;
|
||||
|
||||
public NetworkInfoView(ZeroTierNetwork network)
|
||||
{
|
||||
@ -29,19 +29,41 @@ namespace WinUI
|
||||
this.network = network;
|
||||
|
||||
UpdateNetworkData();
|
||||
|
||||
allowDefault.Checked += AllowDefault_CheckStateChanged;
|
||||
allowDefault.Unchecked += AllowDefault_CheckStateChanged;
|
||||
allowGlobal.Checked += AllowGlobal_CheckStateChanged;
|
||||
allowGlobal.Unchecked += AllowGlobal_CheckStateChanged;
|
||||
allowManaged.Checked += AllowManaged_CheckStateChanged;
|
||||
allowManaged.Unchecked += AllowManaged_CheckStateChanged;
|
||||
}
|
||||
|
||||
private void UpdateNetworkData()
|
||||
{
|
||||
this.networkId.Text = network.NetworkId;
|
||||
this.networkName.Text = network.NetworkName;
|
||||
this.networkStatus.Text = network.NetworkStatus;
|
||||
this.networkType.Text = network.NetworkType;
|
||||
this.macAddress.Text = network.MacAddress;
|
||||
this.mtu.Text = network.MTU.ToString();
|
||||
|
||||
if (this.networkId.Text != network.NetworkId)
|
||||
this.networkId.Text = network.NetworkId;
|
||||
|
||||
if (this.networkName.Text != network.NetworkName)
|
||||
this.networkName.Text = network.NetworkName;
|
||||
|
||||
if (this.networkStatus.Text != network.NetworkStatus)
|
||||
this.networkStatus.Text = network.NetworkStatus;
|
||||
|
||||
if (this.networkType.Text != network.NetworkType)
|
||||
this.networkType.Text = network.NetworkType;
|
||||
|
||||
if (this.macAddress.Text != network.MacAddress)
|
||||
this.macAddress.Text = network.MacAddress;
|
||||
|
||||
if (this.mtu.Text != network.MTU.ToString())
|
||||
this.mtu.Text = network.MTU.ToString();
|
||||
|
||||
this.broadcastEnabled.Text = (network.BroadcastEnabled ? "ENABLED" : "DISABLED");
|
||||
this.bridgingEnabled.Text = (network.Bridge ? "ENABLED" : "DISABLED");
|
||||
this.deviceName.Text = network.DeviceName;
|
||||
|
||||
if (this.deviceName.Text != network.DeviceName)
|
||||
this.deviceName.Text = network.DeviceName;
|
||||
|
||||
string iplist = "";
|
||||
for (int i = 0; i < network.AssignedAddresses.Length; ++i)
|
||||
@ -51,19 +73,12 @@ namespace WinUI
|
||||
iplist += "\n";
|
||||
}
|
||||
|
||||
this.managedIps.Text = iplist;
|
||||
if (this.managedIps.Text != iplist)
|
||||
this.managedIps.Text = iplist;
|
||||
|
||||
this.allowDefault.IsChecked = network.AllowDefault;
|
||||
this.allowGlobal.IsChecked = network.AllowGlobal;
|
||||
this.allowManaged.IsChecked = network.AllowManaged;
|
||||
|
||||
allowDefault.Checked += AllowDefault_CheckStateChanged;
|
||||
allowDefault.Unchecked += AllowDefault_CheckStateChanged;
|
||||
allowGlobal.Checked += AllowGlobal_CheckStateChanged;
|
||||
allowGlobal.Unchecked += AllowGlobal_CheckStateChanged;
|
||||
allowManaged.Checked += AllowManaged_CheckStateChanged;
|
||||
allowManaged.Unchecked += AllowManaged_CheckStateChanged;
|
||||
|
||||
}
|
||||
|
||||
public bool HasNetwork(ZeroTierNetwork network)
|
||||
@ -74,6 +89,13 @@ namespace WinUI
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetNetworkInfo(ZeroTierNetwork network)
|
||||
{
|
||||
this.network = network;
|
||||
|
||||
UpdateNetworkData();
|
||||
}
|
||||
|
||||
private void leaveButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
APIHandler.Instance.LeaveNetwork(network.NetworkId);
|
||||
|
@ -93,7 +93,9 @@
|
||||
</Grid>
|
||||
</ItemsPanelTemplate>
|
||||
</StatusBar.ItemsPanel>
|
||||
<StatusBarItem Grid.Column="0" x:Name="networkId" Content="deadbeef00" Foreground="White" FontFamily="Lucida Console"/>
|
||||
<StatusBarItem Grid.Column="0" x:Name="networkId_placeholder">
|
||||
<TextBox x:Name="networkId" Text="deadbeef00" HorizontalAlignment="Left" Grid.Column="0" Foreground="White" FontFamily="Lucida Console" BorderThickness="0" IsReadOnly="true" Background="Transparent"/>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem Grid.Column="1" x:Name="onlineStatus" Content="ONLINE" Foreground="White" FontFamily="Lucida Console"/>
|
||||
<StatusBarItem Grid.Column="2" x:Name="versionString" Content="1.0.5" Foreground="White" FontFamily="Lucida Console"/>
|
||||
<StatusBarItem Grid.Column="3" x:Name="blank" Content="" Height="43" Foreground="White"/>
|
||||
|
@ -63,7 +63,7 @@ namespace WinUI
|
||||
|
||||
networkId.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
this.networkId.Content = status.Address;
|
||||
this.networkId.Text = status.Address;
|
||||
}));
|
||||
versionString.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
@ -80,7 +80,7 @@ namespace WinUI
|
||||
|
||||
networkId.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
this.networkId.Content = "";
|
||||
this.networkId.Text = "";
|
||||
}));
|
||||
versionString.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
|
@ -27,18 +27,73 @@ namespace WinUI
|
||||
|
||||
public void setNetworks(List<ZeroTierNetwork> networks)
|
||||
{
|
||||
this.wrapPanel.Children.Clear();
|
||||
if (networks == null)
|
||||
{
|
||||
this.wrapPanel.Children.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < networks.Count; ++i)
|
||||
foreach (ZeroTierNetwork network in networks)
|
||||
{
|
||||
this.wrapPanel.Children.Add(
|
||||
new NetworkInfoView(
|
||||
networks.ElementAt<ZeroTierNetwork>(i)));
|
||||
NetworkInfoView view = ChildWithNetwork(network);
|
||||
if (view != null)
|
||||
{
|
||||
view.SetNetworkInfo(network);
|
||||
}
|
||||
else
|
||||
{
|
||||
wrapPanel.Children.Add(
|
||||
new NetworkInfoView(
|
||||
network));
|
||||
}
|
||||
}
|
||||
|
||||
// remove networks we're no longer joined to.
|
||||
List<ZeroTierNetwork> tmpList = GetNetworksFromChildren();
|
||||
foreach (ZeroTierNetwork n in networks)
|
||||
{
|
||||
if (tmpList.Contains(n))
|
||||
{
|
||||
tmpList.Remove(n);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ZeroTierNetwork n in tmpList)
|
||||
{
|
||||
NetworkInfoView view = ChildWithNetwork(n);
|
||||
if (view != null)
|
||||
{
|
||||
wrapPanel.Children.Remove(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private NetworkInfoView ChildWithNetwork(ZeroTierNetwork network)
|
||||
{
|
||||
List<NetworkInfoView> list = wrapPanel.Children.OfType<NetworkInfoView>().ToList();
|
||||
|
||||
foreach (NetworkInfoView view in list)
|
||||
{
|
||||
if (view.HasNetwork(network))
|
||||
{
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<ZeroTierNetwork> GetNetworksFromChildren()
|
||||
{
|
||||
List<ZeroTierNetwork> networks = new List<ZeroTierNetwork>(wrapPanel.Children.Count);
|
||||
|
||||
List<NetworkInfoView> list = wrapPanel.Children.OfType<NetworkInfoView>().ToList();
|
||||
foreach (NetworkInfoView n in list)
|
||||
{
|
||||
networks.Add(n.network);
|
||||
}
|
||||
|
||||
return networks;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\controller\EmbeddedNetworkController.cpp" />
|
||||
<ClCompile Include="..\..\controller\JSONDB.cpp" />
|
||||
<ClCompile Include="..\..\ext\http-parser\http_parser.c" />
|
||||
<ClCompile Include="..\..\ext\libnatpmp\getgateway.c" />
|
||||
<ClCompile Include="..\..\ext\libnatpmp\natpmp.c" />
|
||||
@ -269,7 +270,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>
|
||||
</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NOMINMAX;STATICLIB;WIN32;ZT_TRACE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NOMINMAX;STATICLIB;WIN32;ZT_TRACE;ZT_RULES_ENGINE_DEBUGGING;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>false</MultiProcessorCompilation>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
|
@ -261,6 +261,9 @@
|
||||
<ClCompile Include="..\..\controller\EmbeddedNetworkController.cpp">
|
||||
<Filter>Source Files\controller</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\controller\JSONDB.cpp">
|
||||
<Filter>Source Files\controller</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="resource.h">
|
||||
|
Loading…
x
Reference in New Issue
Block a user