Browse Source

Full and clearer implementation of GitHub issue #588

Adam Ierymenko 7 years ago
parent
commit
395d8b3139
4 changed files with 77 additions and 6 deletions
  1. 29 0
      controller/EmbeddedNetworkController.cpp
  2. 6 6
      include/ZeroTierOne.h
  3. 13 0
      node/Capability.hpp
  4. 29 0
      node/Network.cpp

+ 29 - 0
controller/EmbeddedNetworkController.cpp

@@ -227,6 +227,16 @@ static json _renderRule(ZT_VirtualNetworkRule &rule)
 				r["id"] = rule.v.tag.id;
 				r["id"] = rule.v.tag.id;
 				r["value"] = rule.v.tag.value;
 				r["value"] = rule.v.tag.value;
 				break;
 				break;
+			case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE:
+				r["type"] = "INTEGER_RANGE";
+				OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.intRange.start);
+				r["start"] = tmp;
+				OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.intRange.start + (uint64_t)rule.v.intRange.end);
+				r["end"] = tmp;
+				r["idx"] = rule.v.intRange.idx;
+				r["little"] = ((rule.v.intRange.format & 0x80) != 0);
+				r["bits"] = (rule.v.intRange.format & 63) + 1;
+				break;
 			default:
 			default:
 				break;
 				break;
 		}
 		}
@@ -417,7 +427,26 @@ static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
 	} else if (t == "MATCH_TAG_RECEIVER") {
 	} else if (t == "MATCH_TAG_RECEIVER") {
 		rule.t |= ZT_NETWORK_RULE_MATCH_TAG_RECEIVER;
 		rule.t |= ZT_NETWORK_RULE_MATCH_TAG_RECEIVER;
 		tag = true;
 		tag = true;
+	} else if (t == "INTEGER_RANGE") {
+		json &s = r["start"];
+		if (s.is_string()) {
+			std::string tmp = s;
+			rule.v.intRange.start = Utils::hexStrToU64(tmp.c_str());
+		} else {
+			rule.v.intRange.start = OSUtils::jsonInt(s,0ULL);
+		}
+		json &e = r["end"];
+		if (e.is_string()) {
+			std::string tmp = e;
+			rule.v.intRange.end = (uint32_t)(Utils::hexStrToU64(tmp.c_str()) - rule.v.intRange.start);
+		} else {
+			rule.v.intRange.end = (uint32_t)(OSUtils::jsonInt(e,0ULL) - rule.v.intRange.start);
+		}
+		rule.v.intRange.idx = (uint16_t)OSUtils::jsonInt(r["idx"],0ULL);
+		rule.v.intRange.format = (OSUtils::jsonBool(r["little"],false)) ? 0x80 : 0x00;
+		rule.v.intRange.format |= (uint8_t)((OSUtils::jsonInt(r["bits"],1ULL) - 1) & 63);
 	}
 	}
+
 	if (tag) {
 	if (tag) {
 		rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL);
 		rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL);
 		rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
 		rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);

+ 6 - 6
include/ZeroTierOne.h

@@ -52,13 +52,13 @@
 #else
 #else
 #define ZT_SDK_API __declspec(dllimport)
 #define ZT_SDK_API __declspec(dllimport)
 #ifdef _DEBUG
 #ifdef _DEBUG
-#ifdef _WIN64 
+#ifdef _WIN64
 #pragma comment(lib, "ZeroTierOne_x64d.lib")
 #pragma comment(lib, "ZeroTierOne_x64d.lib")
 #else
 #else
 #pragma comment(lib, "ZeroTierOne_x86d.lib")
 #pragma comment(lib, "ZeroTierOne_x86d.lib")
 #endif
 #endif
 #else
 #else
-#ifdef _WIN64 
+#ifdef _WIN64
 #pragma comment(lib, "ZeroTierOne_x64.lib")
 #pragma comment(lib, "ZeroTierOne_x64.lib")
 #else
 #else
 #pragma comment(lib, "ZeroTierOne_x86.lib")
 #pragma comment(lib, "ZeroTierOne_x86.lib")
@@ -750,6 +750,7 @@ enum ZT_VirtualNetworkRuleType
 	ZT_NETWORK_RULE_MATCH_TAGS_EQUAL = 48,
 	ZT_NETWORK_RULE_MATCH_TAGS_EQUAL = 48,
 	ZT_NETWORK_RULE_MATCH_TAG_SENDER = 49,
 	ZT_NETWORK_RULE_MATCH_TAG_SENDER = 49,
 	ZT_NETWORK_RULE_MATCH_TAG_RECEIVER = 50,
 	ZT_NETWORK_RULE_MATCH_TAG_RECEIVER = 50,
+	ZT_NETWORK_RULE_MATCH_INTEGER_RANGE = 51,
 
 
 	/**
 	/**
 	 * Maximum ID allowed for a MATCH entry in the rules table
 	 * Maximum ID allowed for a MATCH entry in the rules table
@@ -770,7 +771,7 @@ enum ZT_VirtualNetworkRuleType
  */
  */
 typedef struct
 typedef struct
 {
 {
-	/** 
+	/**
 	 * Type and flags
 	 * Type and flags
 	 *
 	 *
 	 * Bits are: NOTTTTTT
 	 * Bits are: NOTTTTTT
@@ -812,10 +813,9 @@ typedef struct
 		 */
 		 */
 		struct {
 		struct {
 			uint64_t start; // integer range start
 			uint64_t start; // integer range start
-			int32_t delta; // +/- offset from start of integer range end
+			uint32_t end; // end of integer range (relative to start, inclusive, 0 for equality w/start)
 			uint16_t idx; // index in packet of integer
 			uint16_t idx; // index in packet of integer
-			uint8_t bits; // number of bits in integer (range: 1-64)
-			uint8_t endian; // endianness of integer in packet (0 == big, 1 == little)
+			uint8_t format; // bits in integer (range 1-64, ((format&63)+1)) and endianness (MSB 1 for little, 0 for big)
 		} intRange;
 		} intRange;
 
 
 		/**
 		/**

+ 13 - 0
node/Capability.hpp

@@ -278,6 +278,13 @@ public:
 					b.append((uint32_t)rules[i].v.tag.id);
 					b.append((uint32_t)rules[i].v.tag.id);
 					b.append((uint32_t)rules[i].v.tag.value);
 					b.append((uint32_t)rules[i].v.tag.value);
 					break;
 					break;
+				case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE:
+					b.append((uint8_t)19);
+					b.append((uint64_t)rules[i].v.intRange.start);
+					b.append((uint64_t)(rules[i].v.intRange.start + (uint64_t)rules[i].v.intRange.end)); // more future-proof
+					b.append((uint16_t)rules[i].v.intRange.idx);
+					b.append((uint8_t)rules[i].v.intRange.format);
+					break;
 			}
 			}
 		}
 		}
 	}
 	}
@@ -366,6 +373,12 @@ public:
 					rules[ruleCount].v.tag.id = b.template at<uint32_t>(p);
 					rules[ruleCount].v.tag.id = b.template at<uint32_t>(p);
 					rules[ruleCount].v.tag.value = b.template at<uint32_t>(p + 4);
 					rules[ruleCount].v.tag.value = b.template at<uint32_t>(p + 4);
 					break;
 					break;
+				case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE:
+					rules[ruleCount].v.intRange.start = b.template at<uint64_t>(p);
+					rules[ruleCount].v.intRange.end = (uint32_t)(b.template at<uint64_t>(p + 8) - rules[ruleCount].v.intRange.start);
+					rules[ruleCount].v.intRange.idx = b.template at<uint16_t>(p + 16);
+					rules[ruleCount].v.intRange.format = (uint8_t)b[p + 18];
+					break;
 			}
 			}
 			p += fieldLen;
 			p += fieldLen;
 			++ruleCount;
 			++ruleCount;

+ 29 - 0
node/Network.cpp

@@ -493,6 +493,35 @@ static _doZtFilterResult _doZtFilter(
 					}
 					}
 				}
 				}
 			}	break;
 			}	break;
+			case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE: {
+				uint64_t integer = 0;
+				const unsigned int bits = (rules[rn].v.intRange.format & 63) + 1;
+				const unsigned int bytes = ((bits + 8 - 1) / 8); // integer ceiling of division by 8
+				if ((rules[rn].v.intRange.format & 0x80) == 0) {
+					// Big-endian
+					unsigned int idx = rules[rn].v.intRange.idx + (8 - bytes);
+					const unsigned int eof = idx + bytes;
+					if (eof <= frameLen) {
+						while (idx < eof) {
+							integer <<= 8;
+							integer |= frameData[idx++];
+						}
+					}
+					integer &= 0xffffffffffffffffULL >> (64 - bits);
+				} else {
+					// Little-endian
+					unsigned int idx = rules[rn].v.intRange.idx;
+					const unsigned int eof = idx + bytes;
+					if (eof <= frameLen) {
+						while (idx < eof) {
+							integer >>= 8;
+							integer |= ((uint64_t)frameData[idx++]) << 56;
+						}
+					}
+					integer >>= (64 - bits);
+				}
+				thisRuleMatches = (uint8_t)((integer >= rules[rn].v.intRange.start)&&(integer <= (rules[rn].v.intRange.start + (uint64_t)rules[rn].v.intRange.end)));
+			}	break;
 
 
 			// The result of an unsupported MATCH is configurable at the network
 			// The result of an unsupported MATCH is configurable at the network
 			// level via a flag.
 			// level via a flag.