summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--netconf-service/index.js500
-rw-r--r--netconf-service/redis-schema.md2
-rw-r--r--node/NetworkConfig.cpp6
-rw-r--r--node/NetworkConfig.hpp26
4 files changed, 293 insertions, 241 deletions
diff --git a/netconf-service/index.js b/netconf-service/index.js
index d76b4c6a..db55487c 100644
--- a/netconf-service/index.js
+++ b/netconf-service/index.js
@@ -26,20 +26,15 @@
//
// Fields in netconf response dictionary
-var ZT_NETWORKCONFIG_DICT_KEY_NETCONF_SERVICE_VERSION = "ncver";
var ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES = "et";
var ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID = "nwid";
var ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP = "ts";
var ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO = "id";
var ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_PREFIX_BITS = "mpb";
var ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_DEPTH = "md";
-var ZT_NETWORKCONFIG_DICT_KEY_ARP_CACHE_TTL = "cARP";
-var ZT_NETWORKCONFIG_DICT_KEY_NDP_CACHE_TTL = "cNDP";
-var ZT_NETWORKCONFIG_DICT_KEY_EMULATE_ARP = "eARP";
-var ZT_NETWORKCONFIG_DICT_KEY_EMULATE_NDP = "eNDP";
-var ZT_NETWORKCONFIG_DICT_KEY_IS_OPEN = "o";
-var ZT_NETWORKCONFIG_DICT_KEY_NAME = "name";
-var ZT_NETWORKCONFIG_DICT_KEY_DESC = "desc";
+var ZT_NETWORKCONFIG_DICT_KEY_PRIVATE = "p";
+var ZT_NETWORKCONFIG_DICT_KEY_NAME = "n";
+var ZT_NETWORKCONFIG_DICT_KEY_DESC = "d";
var ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC = "v4s";
var ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC = "v6s";
var ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES = "mr";
@@ -48,6 +43,9 @@ var ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP = "com";
// Path to zerotier-idtool binary, invoked to enerate certificates of membership
var ZEROTIER_IDTOOL = '/usr/local/bin/zerotier-idtool';
+// From Constants.hpp in node/
+var ZT_NETWORK_AUTOCONF_DELAY = 60000;
+
// Connect to redis, assuming database 0 and no auth (for now)
var redis = require('redis');
var DB = redis.createClient();
@@ -58,6 +56,8 @@ DB.on("error",function(err) {
// Global variables -- these are initialized on startup or netconf-init message
var netconfSigningIdentity = null; // identity of netconf master, with private key portion
+var spawn = require('child_process').spawn;
+
function ztDbTrue(v) { return ((v === '1')||(v === 'true')||(v > 0)); }
function csvToArray(csv) { return (((typeof csv === 'string')&&(csv.length > 0)) ? csv.split(',') : []); }
function arrayToCsv(a) { return ((Array.isArray(a)) ? ((a.length > 0) ? a.join(',') : '') : (((a !== null)&&(typeof a !== 'undefined')) ? a.toString() : '')); }
@@ -208,241 +208,309 @@ function Identity(idstr)
thiz.fromString(idstr);
};
+function generateCertificateOfMembership(nwid,peerAddress,callback)
+{
+ var comTimestamp = '0,' + Date.now().toString(16) + ',' + (ZT_NETWORK_AUTOCONF_DELAY * 4).toString(16);
+ var comNwid = '1,' + nwid + ',0';
+ var comIssuedTo = '2,' + peerAddress + ',ffffffffffffffff';
+ var cert = '';
+ var idtool = spawn(ZEROTIER_IDTOOL,[ 'mkcom',netconfSigningIdentity,comTimestamp,comNwid,comIssuedTo ]);
+ idtool.stdout.on('data',function(data) {
+ if (typeof data === 'string')
+ cert += data;
+ });
+ idtool.on('close',function(exitCode) {
+ return callback((cert.length > 0) ? cert : null,exitCode);
+ });
+};
+
//
// Message handler for messages over ZeroTier One service bus
//
-function handleMessage(dictStr)
+function doNetconfInit(message)
{
- var message = new Dictionary(dictStr);
+ netconfSigningIdentity = new Identity(message.data['netconfId']);
+ if (!netconfSigningIdentity.hasPrivate()) {
+ netconfSigningIdentity = null;
+ console.error('got invalid netconf signing identity in netconf-init');
+ }
+}
- if (!('type' in message.data)) {
- console.error('ignored message without request type field');
+function doNetconfRequest(message)
+{
+ if ((!netconfSigningIdentity)||(!netconfSigningIdentity.hasPrivate())) {
+ console.error('got netconf-request before netconf-init, ignored');
return;
}
- if (message.data['type'] === 'netconf-init') {
+ // Get required fields
+ var peerId = new Identity(message.data['peerId']);
+ var fromIpAndPort = message.data['from'];
+ var nwid = message.data['nwid'];
+ var requestId = message.data['requestId'];
+ if ((!peerId)||(!peerId.isValid())||(!fromIpAndPort)||(!nwid)||(nwid.length !== 16)||(!requestId))
+ return;
- netconfSigningIdentity = new Identity(message.data['netconfId']);
- if (!netconfSigningIdentity.hasPrivate()) {
- netconfSigningIdentity = null;
- console.error('got invalid netconf signing identity');
- }
+ var network = null;
+ var member = null;
- } else if (message.data['type'] === 'netconf-request') {
- if ((!netconfSigningIdentity)||(!netconfSigningIdentity.hasPrivate())) {
- console.error('got netconf-request before netconf-init, ignored');
- return;
- }
+ var authorized = false;
- // Get required fields
- var peerId = new Identity(message.data['peerId']);
- var fromIpAndPort = message.data['from'];
- var nwid = message.data['nwid'];
- var requestId = message.data['requestId'];
- if ((!peerId)||(!peerId.isValid())||(!fromIpAndPort)||(!nwid)||(nwid.length !== 16)||(!requestId))
- return;
+ var v4NeedAssign = false;
+ var v6NeedAssign = false;
+ var v4Assignments = [];
+ var v6Assignments = [];
+ var ipAssignments = []; // both v4 and v6
+
+ async.series([function(next) {
- // Get optional fields
- var meta = new Dictionary(message.data['meta']);
- var clientVersion = message.data['clientVersion'];
- var clientOs = message.data['clientOs'];
-
- var network = null;
- var member = null;
- var authorized = false;
- var v4NeedAssign = false;
- var v6NeedAssign = false;
- var v4Assignments = [];
- var v6Assignments = [];
-
- async.series([function(next) { // network lookup
- DB.hgetall('zt1:network:'+nwid+':~',function(err,obj) {
- network = obj;
+ // network lookup
+ DB.hgetall('zt1:network:'+nwid+':~',function(err,obj) {
+ network = obj;
+ return next(err);
+ });
+
+ },function(next) {
+
+ // member record lookup, unless public network
+ if ((!network)||(!('nwid' in network)||(network['nwid'] !== nwid))
+ return next(null);
+
+ var memberKey = 'zt1:network:'+nwid+':member:'+peerId.address()+':~';
+ DB.hgetall(memberKey,function(err,obj) {
+ if (err)
return next(err);
- });
- },function(next) { // member record lookup, unless public network
- if ((!network)||(!('nwid' in network)||(network['nwid'] !== nwid))
- return next(null);
- var memberKey = 'zt1:network:'+nwid+':member:'+peerId.address()+':~';
- DB.hgetall(memberKey,function(err,obj) {
- if (err)
- return next(err);
- else if (obj) {
- // Update member object
- member = obj;
- authorized = (ztDbTrue(network['private']) || ztDbTrue(member['authorized']));
- DB.hmset(memberKey,{
- 'lastSeen': Date.now(),
- 'lastAt': fromIpAndPort,
- 'clientVersion': (clientVersion) ? clientVersion : '?.?.?',
- 'clientOs': (clientOs) ? clientOs : '?'
- },next);
- } else {
- // Add member object for new and unauthorized member
- authorized = false;
- member = {
- 'id': peerId.address(),
- 'nwid': nwid,
- 'authorized': 0,
- 'identity': peerId.toString(),
- 'firstSeen': Date.now(),
- 'lastSeen': Date.now(),
- 'lastAt': fromIpAndPort,
- 'clientVersion': (clientVersion) ? clientVersion : '?.?.?',
- 'clientOs': (clientOs) ? clientOs : '?'
- };
- DB.hmset(memberKey,member,next);
- }
- });
- },function(next) { // IP address auto-assignment, if needed
- if (!authorized)
- return next(null);
-
- v4NeedAssign = (network['v4AssignMode'] === 'zt');
- v6NeedAssign = (network['v6AssignMode'] === 'zt');
-
- var ipa = csvToArray(member['ipAssignments']);
- for(var i=0;i<ipa.length;++i) {
- if ((ipa[i].indexOf('.') > 0)&&(v4NeedAssign))
- v4Assignments.push(ipa[i]);
- else if ((ipa[i].indexOf(':') > 0)&&(v6NeedAssign))
- v6Assignments.push(ipa[i]);
+
+ if (obj) {
+ // Update existing member record with new last seen time, etc.
+ member = obj;
+ authorized = (ztDbTrue(network['private']) || ztDbTrue(member['authorized']));
+ DB.hmset(memberKey,{
+ 'lastSeen': Date.now(),
+ 'lastAt': fromIpAndPort,
+ 'clientVersion': (clientVersion) ? clientVersion : '?.?.?',
+ 'clientOs': (clientOs) ? clientOs : '?'
+ },next);
+ } else {
+ // Add member record to network for newly seen peer
+ authorized = ztDbTrue(network['private']) ? false : true; // public networks authorize everyone by default
+ var now = Date.now().toString();
+ member = {
+ 'id': peerId.address(),
+ 'nwid': nwid,
+ 'authorized': authorized ? '1' : '0',
+ 'identity': peerId.toString(),
+ 'firstSeen': now,
+ 'lastSeen': now,
+ 'lastAt': fromIpAndPort,
+ 'clientVersion': (message.data['clientVersion']) ? message.data['clientVersion'] : '?.?.?',
+ 'clientOs': (message.data['clientOs']) ? message.data['clientOs'] : '?'
+ };
+ DB.hmset(memberKey,member,next);
}
+ });
+ },function(next) {
+
+ // Figure out which IP address auto-assignments we need to look up or make
+ if (!authorized)
return next(null);
- },function(next) { // assign IPv4 if needed
- if ((!authorized)||(!v4NeedAssign))
- return next(null);
-
- var ipAssignmentAttempts = 0; // for sanity-checking
- var v4pool = network['v4AssignPool'];
- var ztaddr = peerId.address();
-
- var network = 0;
- var netmask = 0;
- var netmaskBits = 0;
- if (v4pool) {
- var v4poolSplit = v4Pool.split('/');
- if (v4poolSplit.length === 2) {
- var networkSplit = v4poolSplit[0].split('.');
- if (networkSplit.length === 4) {
- network |= (parseInt(networkSplit[0],10) << 24) & 0xff000000;
- network |= (parseInt(networkSplit[1],10) << 16) & 0x00ff0000;
- network |= (parseInt(networkSplit[2],10) << 8) & 0x0000ff00;
- network |= parseInt(networkSplit[3],10) & 0x000000ff;
- netmaskBits = parseInt(v4poolSplit[1],10);
- if (netmaskBits > 32)
- netmaskBits = 32; // sanity check
- for(var i=0;i<netmaskBits;++i)
- netmask |= (0x80000000 >> i);
- }
+
+ v4NeedAssign = (network['v4AssignMode'] === 'zt');
+ v6NeedAssign = (network['v6AssignMode'] === 'zt');
+
+ var ipa = csvToArray(member['ipAssignments']);
+ for(var i=0;i<ipa.length;++i) {
+ if (ipa[i])
+ ipAssignments.push(ipa[i]);
+ if ((ipa[i].indexOf('.') > 0)&&(v4NeedAssign)) {
+ v4Assignments.push(ipa[i]);
+ } else if ((ipa[i].indexOf(':') > 0)&&(v6NeedAssign)) {
+ v6Assignments.push(ipa[i]);
+ }
+ }
+
+ return next(null);
+
+ },function(next) {
+
+ // assign IPv4 if needed
+ if ((!authorized)||(!v4NeedAssign)||(v4Assignments.length > 0))
+ return next(null);
+
+ var ipAssignmentAttempts = 0;
+ var v4pool = network['v4AssignPool']; // technically csv but only one netblock currently supported
+ var peerAddress = peerId.address();
+
+ var network = 0;
+ var netmask = 0;
+ var netmaskBits = 0;
+ if (v4pool) {
+ var v4poolSplit = v4Pool.split('/');
+ if (v4poolSplit.length === 2) {
+ var networkSplit = v4poolSplit[0].split('.');
+ if (networkSplit.length === 4) {
+ network |= (parseInt(networkSplit[0],10) << 24) & 0xff000000;
+ network |= (parseInt(networkSplit[1],10) << 16) & 0x00ff0000;
+ network |= (parseInt(networkSplit[2],10) << 8) & 0x0000ff00;
+ network |= parseInt(networkSplit[3],10) & 0x000000ff;
+ netmaskBits = parseInt(v4poolSplit[1],10);
+ if (netmaskBits > 32)
+ netmaskBits = 32; // sanity check
+ for(var i=0;i<netmaskBits;++i)
+ netmask |= (0x80000000 >> i);
+ netmask &= 0xffffffff;
}
}
- var invmask = netmask ^ 0xffffffff;
- var abcd = 0;
- var assignment = null;
-
- var ipAssignmentsKey = 'zt1:network:'+nwid+':ipAssignments';
- var memberKey = 'zt1:network:'+nwid+':member:'+ztaddr+':~';
-
- async.whilst(
- function() { return ((v4NeedAssign)&&(v4Assignments.length === 0)&&(network !== 0)&&(netmask !== 0xffffffff)&&(ipAssignmentAttempts < 1000)); },
- function(next2) {
- ++ipAssignmentAttempts;
-
- // Generate or increment IP address
- if (abcd === 0) {
- var a = parseInt(ztaddr.substr(2,2),16) & 0xff;
- var b = parseInt(ztaddr.substr(4,2),16) & 0xff;
- var c = parseInt(ztaddr.substr(6,2),16) & 0xff;
- var d = parseInt(ztaddr.substr(8,2),16) & 0xff;
- abcd = (a << 24) | (b << 16) | (c << 8) | d;
- } else ++abcd;
- if ((abcd & 0xff) === 0)
- abcd |= 1;
-
- // Derive an IP to test and generate assignment ip/bits string
- var ip = (abcd & invmask) | (network & netmask);
- assignment = ((ip >> 24) & 0xff).toString(10) + '.' + ((ip >> 16) & 0xff).toString(10) + '.' + ((ip >> 8) & 0xff).toString(10) + '.' + (ip & 0xff).toString(10) + '/' + netmaskBits.toString(10);
-
- DB.hget(ipAssignmentsKey,assignment,function(err,value) {
+ }
+ if ((network === 0)||(netmask === 0xffffffff))
+ return next(null);
+ var invmask = netmask ^ 0xffffffff;
+ var abcd = 0;
+
+ var assignment = null;
+
+ var ipAssignmentsKey = 'zt1:network:'+nwid+':ipAssignments';
+ var memberKey = 'zt1:network:'+nwid+':member:'+peerAddress+':~';
+
+ async.whilst(
+ function() { return ((v4Assignments.length === 0)&&(ipAssignmentAttempts < 1000)); },
+ function(next2) {
+ ++ipAssignmentAttempts;
+
+ // Generate or increment IP address source bits
+ if (abcd === 0) {
+ var a = parseInt(peerAddress.substr(2,2),16) & 0xff;
+ var b = parseInt(peerAddress.substr(4,2),16) & 0xff;
+ var c = parseInt(peerAddress.substr(6,2),16) & 0xff;
+ var d = parseInt(peerAddress.substr(8,2),16) & 0xff;
+ abcd = (a << 24) | (b << 16) | (c << 8) | d;
+ } else ++abcd;
+ if ((abcd & 0xff) === 0)
+ abcd |= 1;
+ abcd &= 0xffffffff;
+
+ // Derive an IP to test and generate assignment ip/bits string
+ var ip = (abcd & invmask) | (network & netmask);
+ assignment = ((ip >> 24) & 0xff).toString(10) + '.' + ((ip >> 16) & 0xff).toString(10) + '.' + ((ip >> 8) & 0xff).toString(10) + '.' + (ip & 0xff).toString(10) + '/' + netmaskBits.toString(10);
+
+ // Check :ipAssignments to see if this IP is already taken
+ DB.hget(ipAssignmentsKey,assignment,function(err,value) {
+ if (err)
+ return next2(err);
+
+ // IP is already taken, try again via async.whilst()
+ if ((value)&&(value !== peerAddress))
+ return next2(null); // if someone's already got this IP, keep looking
+
+ v4Assignments.push(assignment);
+ ipAssignments.push(assignment);
+
+ // Save assignment to :ipAssignments hash
+ DB.hset(ipAssignmentsKey,assignment,peerAddress,function(err) {
if (err)
return next2(err);
- if ((value)&&(value !== ztaddr))
- return next2(null); // if someone's already got this IP, keep looking
-
- v4Assignments.push(assignment);
-
- // Save assignment to :ipAssignments hash
- DB.hset(ipAssignmentsKey,assignment,ztaddr,function(err) {
- if (err)
- return next2(err);
-
- // Save updated CSV list of assignments to member record
- var ipAssignments = member['ipAssignments'];
- if (!ipAssignments)
- ipAssignments = '';
- if (ipAssignments.length > 0)
- ipAssignments += ',';
- ipAssignments += assignment;
- member['ipAssignments'] = ipAssignments;
- DB.hset(memberKey,'ipAssignments',ipAssignments,next2);
- });
+
+ // Save updated CSV list of assignments to member record
+ var ipacsv = ipAssignments.join(',');
+ member['ipAssignments'] = ipacsv;
+ DB.hset(memberKey,'ipAssignments',ipacsv,next2);
});
- },
- next
- );
+ });
+ },
+ next
+ );
- },function(next) { // assign IPv6 if needed -- TODO
- if ((!authorized)||(!v6NeedAssign))
- return next(null);
+ },function(next) {
+ // assign IPv6 if needed -- TODO
+ if ((!authorized)||(!v6NeedAssign)||(v6Assignments.length > 0))
return next(null);
- }],function(err) {
- if (err) {
- console.log('error composing response for '+peerId.address()+': '+err);
- return;
- } else if (authorized) {
- // TODO: COM!!!
- var certificateOfMembership = null;
-
- var netconf = new Dictionary();
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_NETCONF_SERVICE_VERSION] = '0.0.0';
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES] = network['etherTypes'];
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID] = nwid;
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP] = Date.now().toString();
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO] = peerId.address();
- //netconf.data[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_PREFIX_BITS] = 0;
- //netconf.data[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_DEPTH] = 0;
- //netconf.data[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES] = '';
- //netconf.data[ZT_NETWORKCONFIG_DICT_KEY_ARP_CACHE_TTL] = 0;
- //netconf.data[ZT_NETWORKCONFIG_DICT_KEY_NDP_CACHE_TTL] = 0;
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_EMULATE_ARP] = '0';
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_EMULATE_NDP] = '0';
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_IS_OPEN] = ztDbTrue(network['private']) ? '0' : '1';
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_NAME] = network['name'];
- if (network['desc'])
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_DESC] = network['desc'];
- if (v4NeedAssign)
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC] = (v4Assignments.length > 0) ? v4Assignments.join(',') : '';
- if (v6NeedAssign)
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC] = (v6Assignments.length > 0) ? v6Assignments.join(',') : '';
- if (certificateOfMembership !== null)
- netconf.data[ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP] = certificateOfMembership;
-
- var response = new Dictionary();
- response.data['peer'] = peerId.address();
- response.data['nwid'] = nwid;
- response.data['type'] = 'netconf-response';
- response.data['requestId'] = requestId;
- response.data['netconf'] = netconf.toString();
+
+ return next(null);
+
+ }],function(err) {
+
+ if (err) {
+ console.log('error composing response for '+peerId.address()+': '+err);
+ return;
+ }
+
+ var response = new Dictionary();
+ response.data['peer'] = peerId.address();
+ response.data['nwid'] = nwid;
+ response.data['type'] = 'netconf-response';
+ response.data['requestId'] = requestId;
+
+ if (authorized) {
+ var certificateOfMembership = null;
+ var privateNetwork = ztDbTrue(network['private']);
+
+ async.series([function(next) {
+
+ // Generate certificate of membership if necessary
+ if (privateNetwork) {
+ generateCertificateOfMembership(nwid,peerId.address(),function(cert,exitCode) {
+ if (cert) {
+ certificateOfMembership = cert;
+ return next(null);
+ } else return next(new Error('zerotier-idtool returned '+exitCode));
+ });
+ } else return next(null);
+
+ }],function(err) {
+
+ if (err) {
+ console.error('unable to generate certificate for peer '+peerId.address()+' on network '+nwid+': '+err);
+ response.data['error'] = 'ACCESS_DENIED'; // unable to generate certificate
+ } else {
+ var netconf = new Dictionary();
+ netconf.data[ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES] = network['etherTypes'];
+ netconf.data[ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID] = nwid;
+ netconf.data[ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP] = Date.now().toString(16);
+ netconf.data[ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO] = peerId.address();
+ //netconf.data[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_PREFIX_BITS] = 0;
+ //netconf.data[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_DEPTH] = 0;
+ //netconf.data[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES] = '';
+ netconf.data[ZT_NETWORKCONFIG_DICT_KEY_PRIVATE] = privateNetwork ? '1' : '0';
+ netconf.data[ZT_NETWORKCONFIG_DICT_KEY_NAME] = network['name'];
+ if (network['desc'])
+ netconf.data[ZT_NETWORKCONFIG_DICT_KEY_DESC] = network['desc'];
+ if ((v4NeedAssign)&&(v4Assignments.length > 0))
+ netconf.data[ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC] = v4Assignments.join(',');
+ if ((v6NeedAssign)&&(v6Assignments.length > 0))
+ netconf.data[ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC] = v6Assignments.join(',');
+ if (certificateOfMembership !== null)
+ netconf.data[ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP] = certificateOfMembership;
+ response.data['netconf'] = netconf.toString();
+ }
process.stdout.write(response.toString()+'\n');
- return;
- } else {
- }
- });
+
+ });
+
+ } else {
+
+ // Peer not authorized to join network
+ response.data['error'] = 'ACCESS_DENIED';
+ process.stdout.write(response.toString()+'\n');
+
+ }
+
+ });
+}
+
+function handleMessage(dictStr)
+{
+ var message = new Dictionary(dictStr);
+ if (!('type' in message.data)) {
+ console.error('ignored message without request type field');
+ return;
+ } else if (message.data['type'] === 'netconf-init') {
+ doNetconfInit(message);
+ } else if (message.data['type'] === 'netconf-request') {
+ doNetconfRequest(message);
} else {
console.error('ignored unrecognized message type: '+message.data['type']);
}
diff --git a/netconf-service/redis-schema.md b/netconf-service/redis-schema.md
index 58593d3c..c53b8354 100644
--- a/netconf-service/redis-schema.md
+++ b/netconf-service/redis-schema.md
@@ -58,7 +58,7 @@ Each network has a network record indexed by its 64-bit network ID in lower-case
- R infrastructure :: if true, network can't be deleted through API or web UI
- M private :: if true, network requires authentication
- R creationTime :: timestamp of network creation
-- M etherTypes :: comma-delimited list of integers indicating Ethernet types permitted on network
+- M etherTypes :: comma-delimited list of *hexadecimal* integers indicating Ethernet types permitted on network
- M enableBroadcast :: if true, ff:ff:ff:ff:ff:ff is enabled network-wide
- M v4AssignMode :: 'none' (or null/empty/etc.), 'zt', 'dhcp'
- M v4AssignPool :: network/bits from which to assign IPs
diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp
index 0c170406..0d6cd049 100644
--- a/node/NetworkConfig.cpp
+++ b/node/NetworkConfig.cpp
@@ -84,11 +84,7 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
_issuedTo = Address(d.get(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO));
_multicastPrefixBits = Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_PREFIX_BITS,_zero).c_str());
_multicastDepth = Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_DEPTH,_zero).c_str());
- _arpCacheTtl = Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_ARP_CACHE_TTL,_zero).c_str());
- _ndpCacheTtl = Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_NDP_CACHE_TTL,_zero).c_str());
- _emulateArp = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_EMULATE_ARP,_zero).c_str()) != 0);
- _emulateNdp = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_EMULATE_NDP,_zero).c_str()) != 0);
- _isOpen = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_IS_OPEN,_zero).c_str()) != 0);
+ _private = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE,_zero).c_str()) != 0);
_name = d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME);
_description = d.get(ZT_NETWORKCONFIG_DICT_KEY_DESC,std::string());
diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp
index 2941d562..6e040436 100644
--- a/node/NetworkConfig.hpp
+++ b/node/NetworkConfig.hpp
@@ -48,23 +48,18 @@ namespace ZeroTier {
// These dictionary keys are short so they don't take up much room in
// netconf response packets.
-#define ZT_NETWORKCONFIG_DICT_KEY_NETCONF_SERVICE_VERSION "ncver"
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et"
#define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid"
#define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts"
#define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id"
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_PREFIX_BITS "mpb"
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_DEPTH "md"
-#define ZT_NETWORKCONFIG_DICT_KEY_ARP_CACHE_TTL "cARP"
-#define ZT_NETWORKCONFIG_DICT_KEY_NDP_CACHE_TTL "cNDP"
-#define ZT_NETWORKCONFIG_DICT_KEY_EMULATE_ARP "eARP"
-#define ZT_NETWORKCONFIG_DICT_KEY_EMULATE_NDP "eNDP"
-#define ZT_NETWORKCONFIG_DICT_KEY_IS_OPEN "o"
-#define ZT_NETWORKCONFIG_DICT_KEY_NAME "name"
-#define ZT_NETWORKCONFIG_DICT_KEY_DESC "desc"
+#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES "mr"
+#define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p"
+#define ZT_NETWORKCONFIG_DICT_KEY_NAME "n"
+#define ZT_NETWORKCONFIG_DICT_KEY_DESC "d"
#define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s"
#define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s"
-#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES "mr"
#define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com"
/**
@@ -122,11 +117,8 @@ public:
inline const Address &issuedTo() const throw() { return _issuedTo; }
inline unsigned int multicastPrefixBits() const throw() { return _multicastPrefixBits; }
inline unsigned int multicastDepth() const throw() { return _multicastDepth; }
- inline unsigned int arpCacheTtl() const throw() { return _arpCacheTtl; }
- inline unsigned int ndpCacheTtl() const throw() { return _ndpCacheTtl; }
- inline bool emulateArp() const throw() { return _emulateArp; }
- inline bool emulateNdp() const throw() { return _emulateNdp; }
- inline bool isOpen() const throw() { return _isOpen; }
+ inline bool isOpen() const throw() { return (!_private); }
+ inline bool isPrivate() const throw() { return _private; }
inline const std::string &name() const throw() { return _name; }
inline const std::string &description() const throw() { return _description; }
inline const std::set<InetAddress> &staticIps() const throw() { return _staticIps; }
@@ -162,11 +154,7 @@ private:
Address _issuedTo;
unsigned int _multicastPrefixBits;
unsigned int _multicastDepth;
- unsigned int _arpCacheTtl;
- unsigned int _ndpCacheTtl;
- bool _emulateArp;
- bool _emulateNdp;
- bool _isOpen;
+ bool _private;
std::string _name;
std::string _description;
std::set<InetAddress> _staticIps;