Browse Source

Ad-hoc networks, a cool and easy to implement little feature that allows controllerless networks. These only allow IPv6 6plane, no multicast, and the network ID encodes the allowed port range.

Adam Ierymenko 8 years ago
parent
commit
b679ebde3b
3 changed files with 73 additions and 7 deletions
  1. 6 6
      include/ZeroTierOne.h
  2. 66 0
      node/Network.cpp
  3. 1 1
      rule-compiler/package.json

+ 6 - 6
include/ZeroTierOne.h

@@ -610,15 +610,15 @@ enum ZT_VirtualNetworkRuleType
 typedef struct
 {
 	/** 
-	 * Least significant 7 bits: ZT_VirtualNetworkRuleType, most significant 1 bit is NOT bit
+	 * Type and flags
 	 *
-	 * If the NOT bit is set, then matches will be interpreted as "does not
-	 * match." The NOT bit has no effect on actions.
+	 * Bits are: NOTTTTTT
 	 *
-	 * Use "& 0x7f" to get the enum and "& 0x80" to get the NOT flag.
+	 * N - If true, sense of match is inverted (no effect on actions)
+	 * O - If true, result is ORed with previous instead of ANDed (no effect on actions)
+	 * T - Rule or action type
 	 *
-	 * The union 'v' is a variant type, and this selects which field in 'v' is
-	 * actually used and valid.
+	 * AND with 0x3f to get type, 0x80 to get NOT bit, and 0x40 to get OR bit.
 	 */
 	uint8_t t;
 

+ 66 - 0
node/Network.cpp

@@ -1099,6 +1099,72 @@ int Network::setConfiguration(const NetworkConfig &nconf,bool saveToDisk)
 
 void Network::requestConfiguration()
 {
+	/* ZeroTier addresses can't begin with 0xff, so this is used to mark controllerless
+	 * network IDs. Controllerless network IDs only support unicast IPv6 using the 6plane
+	 * addressing scheme and have the following format: 0xffSSSSEEEE000000 where SSSS
+	 * is the 16-bit starting IP port range allowed and EEEE is the 16-bit ending IP port
+	 * range allowed. Remaining digits are reserved for future use and must be zero. */
+	if ((_id >> 56) == 0xff) {
+		const uint16_t startPortRange = (uint16_t)((_id >> 40) & 0xffff);
+		const uint16_t endPortRange = (uint16_t)((_id >> 24) & 0xffff);
+		if (((_id & 0xffffff) == 0)&&(endPortRange >= startPortRange)) {
+			NetworkConfig *const nconf = new NetworkConfig();
+
+			nconf->networkId = _id;
+			nconf->timestamp = RR->node->now();
+			nconf->credentialTimeMaxDelta = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA;
+			nconf->revision = 1;
+			nconf->issuedTo = RR->identity.address();
+			nconf->flags = ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION;
+			nconf->staticIpCount = 1;
+			nconf->ruleCount = 14;
+			nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,RR->identity.address().toInt());
+
+			// Drop everything but IPv6
+			nconf->rules[0].t = (uint8_t)ZT_NETWORK_RULE_MATCH_ETHERTYPE | 0x80; // NOT
+			nconf->rules[0].v.etherType = 0x86dd; // IPv6
+			nconf->rules[1].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP;
+
+			// Allow ICMPv6
+			nconf->rules[2].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL;
+			nconf->rules[2].v.ipProtocol = 0x3a; // ICMPv6
+			nconf->rules[3].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
+
+			// Allow destination ports within range
+			nconf->rules[4].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL;
+			nconf->rules[4].v.ipProtocol = 0x11; // UDP
+			nconf->rules[5].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_PROTOCOL | 0x40; // OR
+			nconf->rules[5].v.ipProtocol = 0x06; // TCP
+			nconf->rules[6].t = (uint8_t)ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE;
+			nconf->rules[6].v.port[0] = startPortRange;
+			nconf->rules[6].v.port[1] = endPortRange;
+			nconf->rules[7].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
+
+			// Allow non-SYN TCP packets to permit non-connection-initiating traffic
+			nconf->rules[8].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS | 0x80; // NOT
+			nconf->rules[8].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_SYN;
+			nconf->rules[9].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
+
+			// Also allow SYN+ACK which are replies to SYN
+			nconf->rules[10].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS;
+			nconf->rules[10].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_SYN;
+			nconf->rules[11].t = (uint8_t)ZT_NETWORK_RULE_MATCH_CHARACTERISTICS;
+			nconf->rules[11].v.characteristics = ZT_RULE_PACKET_CHARACTERISTICS_TCP_ACK;
+			nconf->rules[12].t = (uint8_t)ZT_NETWORK_RULE_ACTION_ACCEPT;
+
+			nconf->rules[13].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP;
+
+			nconf->type = ZT_NETWORK_TYPE_PUBLIC;
+			Utils::snprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange);
+
+			this->setConfiguration(*nconf,false);
+			delete nconf;
+		} else {
+			this->setNotFound();
+		}
+		return;
+	}
+
 	const Address ctrl(controller());
 
 	Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> rmd;

+ 1 - 1
rule-compiler/package.json

@@ -1,6 +1,6 @@
 {
   "name": "zerotier-rule-compiler",
-  "version": "1.1.17-0",
+  "version": "1.1.17-1",
   "description": "ZeroTier Rule Script Compiler",
   "main": "cli.js",
   "scripts": {