Selaa lähdekoodia

Pass 1 at adding DNS to controller

Grant Limberg 5 vuotta sitten
vanhempi
commit
387039456d
5 muutettua tiedostoa jossa 164 lisäystä ja 1 poistoa
  1. 44 0
      controller/EmbeddedNetworkController.cpp
  2. 29 0
      include/ZeroTierOne.h
  3. 59 0
      node/DNS.hpp
  4. 16 0
      node/NetworkConfig.cpp
  5. 16 1
      node/NetworkConfig.hpp

+ 44 - 0
controller/EmbeddedNetworkController.cpp

@@ -1029,6 +1029,30 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
 						}
 					}
 
+					if (b.count("dns")) {
+						json &dns = b["dns"];
+						if (dns.is_array()) {
+							json nda = json::array();
+							for(unsigned int i=0;i<dns.size();++i) {
+								json &d = dns[i];
+								if (d.is_object()) {
+									json nd = json::object();
+									nd["domain"] = d["domain"];
+									json &srv = d["servers"];
+									if (srv.is_array()) {
+										json ns = json::array();
+										for(unsigned int j=0;j<srv.size();++j) {
+											ns.push_back(srv[i]);
+										}
+										nd["servers"] = ns;
+									}
+									nda.push_back(nd);
+								}
+							}
+							network["dns"] = nda;
+						}
+					}
+
 				} catch ( ... ) {
 					responseBody = "{ \"message\": \"exception occurred while parsing body variables\" }";
 					responseContentType = "application/json";
@@ -1392,6 +1416,7 @@ void EmbeddedNetworkController::_request(
 	json &tags = network["tags"];
 	json &memberCapabilities = member["capabilities"];
 	json &memberTags = member["tags"];
+	json &dns = member["dns"];
 
 	if (metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV,0) <= 0) {
 		// Old versions with no rules engine support get an allow everything rule.
@@ -1684,6 +1709,25 @@ void EmbeddedNetworkController::_request(
 			}
 		}
 	}
+	
+	if(dns.is_array()) {
+		nc->dnsCount = 0;
+		for(unsigned int p=0; p < dns.size(); ++p) {
+			json &d = dns[p];
+			if (d.is_object()) {
+				std::string domain = OSUtils::jsonString(d["domain"],"");
+				memcpy(nc->dns[nc->dnsCount].domain, domain.c_str(), domain.size());
+				json &addrArray = d["servers"];
+				if (addrArray.is_array()) {
+					for(unsigned int j = 0; j < addrArray.size() && j < ZT_MAX_DNS_SERVERS; ++j) {
+						json &addr = addrArray[j];
+						nc->dns[nc->dnsCount].server_addr[j] = InetAddress(OSUtils::jsonString(addr,"").c_str());
+					}
+				}
+				++nc->dnsCount;
+			}
+		}
+	}
 
 	// Issue a certificate of ownership for all static IPs
 	if (nc->staticIpCount) {

+ 29 - 0
include/ZeroTierOne.h

@@ -125,6 +125,11 @@ extern "C" {
  */
 #define ZT_MAX_NETWORK_ROUTES 32
 
+/**
+ * Maximum number of pushed DNS configurations on a network
+ */
+#define ZT_MAX_NETWORK_DNS 32
+
 /**
  * Maximum number of statically assigned IP addresses per network endpoint using ZT address management (not DHCP)
  */
@@ -195,6 +200,11 @@ extern "C" {
  */
 #define ZT_PATH_LINK_QUALITY_MAX 0xff
 
+/**
+ * Maximum number of DNS servers per domain
+ */
+#define ZT_MAX_DNS_SERVERS 4
+
 /**
  * Packet characteristics flag: packet direction, 1 if inbound 0 if outbound
  */
@@ -984,6 +994,15 @@ typedef struct
 	uint16_t metric;
 } ZT_VirtualNetworkRoute;
 
+/**
+ * DNS configuration to be pushed on a virtual network
+ */
+typedef struct
+{
+	char domain[128];
+	struct sockaddr_storage server_addr[ZT_MAX_DNS_SERVERS];
+} ZT_VirtualNetworkDNS;
+
 /**
  * An Ethernet multicast group
  */
@@ -1198,6 +1217,16 @@ typedef struct
 		uint64_t mac; /* MAC in lower 48 bits */
 		uint32_t adi; /* Additional distinguishing information, usually zero except for IPv4 ARP groups */
 	} multicastSubscriptions[ZT_MAX_MULTICAST_SUBSCRIPTIONS];
+
+	/**
+	 *  Number of ZT-pushed DNS configuraitons
+	 */ 
+	unsigned int dnsCount;
+	
+	/**
+	 * Network specific DNS configuration
+	 */
+	ZT_VirtualNetworkDNS dns[ZT_MAX_NETWORK_DNS];
 } ZT_VirtualNetworkConfig;
 
 /**

+ 59 - 0
node/DNS.hpp

@@ -0,0 +1,59 @@
+/*
+ * Copyright (c)2020 ZeroTier, Inc.
+ *
+ * Use of this software is governed by the Business Source License included
+ * in the LICENSE.TXT file in the project's root directory.
+ *
+ * Change Date: 2023-01-01
+ *
+ * On the date above, in accordance with the Business Source License, use
+ * of this software will be governed by version 2.0 of the Apache License.
+ */
+/****/
+
+#ifndef ZT_DNS_HPP
+#define ZT_DNS_HPP
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "Buffer.hpp"
+#include "InetAddress.hpp"
+#include "../include/ZeroTierOne.h"
+
+namespace ZeroTier {
+
+/**
+ * DNS data serealization methods
+ */
+class DNS {
+public:
+    template<unsigned int C>
+    static inline void serializeDNS(Buffer<C> &b, const ZT_VirtualNetworkDNS *dns, unsigned int dnsCount)
+    {
+        for(unsigned int i = 0; i < dnsCount; ++i) {
+            b.append(dns[i].domain, 128);
+            for(unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) {
+                InetAddress tmp(dns[i].server_addr[j]);
+                tmp.serialize(b);
+            }
+        }
+    }
+
+    template<unsigned int C>
+    static inline void deserializeDNS(const Buffer<C> &b, unsigned int &p, ZT_VirtualNetworkDNS *dns, const unsigned int dnsCount)
+    {
+        for(unsigned int i = 0; i < dnsCount; ++i) {
+            char *d = (char*)b.data()+p;
+            memcpy(dns[i].domain, d, 128);
+            p += 128;
+            for (unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) {
+                p += reinterpret_cast<InetAddress *>(&(dns[i].server_addr[j]))->deserialize(b, p);
+            }
+        }
+    }
+};
+
+}
+
+#endif // ZT_DNS_HPP

+ 16 - 0
node/NetworkConfig.cpp

@@ -176,6 +176,15 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
 			}
 		}
 
+		tmp->clear();
+		if (dnsCount > 0) {
+			tmp->append(dnsCount);
+			DNS::serializeDNS(*tmp, dns, dnsCount);
+			if (tmp->size()) {
+				if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_DNS,*tmp)) return false;
+			}
+		}
+
 		delete tmp;
 	} catch ( ... ) {
 		delete tmp;
@@ -354,6 +363,13 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
 				unsigned int p = 0;
 				Capability::deserializeRules(*tmp,p,this->rules,this->ruleCount,ZT_MAX_NETWORK_RULES);
 			}
+
+			if (d.get(ZT_NETWORKCONFIG_DICT_KEY_DNS, *tmp)) {
+				unsigned int p = 0;
+				this->dnsCount = tmp->at<unsigned int>(p);
+				p += sizeof(unsigned int);
+				DNS::deserializeDNS(*tmp, p, dns, (this->dnsCount <= ZT_MAX_NETWORK_DNS) ? this->dnsCount : ZT_MAX_NETWORK_DNS);
+			}
 		}
 
 		//printf("~~~\n%s\n~~~\n",d.data());

+ 16 - 1
node/NetworkConfig.hpp

@@ -26,6 +26,7 @@
 
 #include "Constants.hpp"
 #include "Buffer.hpp"
+#include "DNS.hpp"
 #include "InetAddress.hpp"
 #include "MulticastGroup.hpp"
 #include "Address.hpp"
@@ -175,6 +176,8 @@ namespace ZeroTier {
 #define ZT_NETWORKCONFIG_DICT_KEY_TAGS "TAG"
 // tags (binary blobs)
 #define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP "COO"
+// dns (binary blobs)
+#define ZT_NETWORKCONFIG_DICT_KEY_DNS "DNS"
 
 // Legacy fields -- these are obsoleted but are included when older clients query
 
@@ -229,13 +232,15 @@ public:
 		capabilities(),
 		tags(),
 		certificatesOfOwnership(),
-		type(ZT_NETWORK_TYPE_PRIVATE)
+		type(ZT_NETWORK_TYPE_PRIVATE),
+		dnsCount(0)
 	{
 		name[0] = 0;
 		memset(specialists, 0, sizeof(uint64_t)*ZT_MAX_NETWORK_SPECIALISTS);
 		memset(routes, 0, sizeof(ZT_VirtualNetworkRoute)*ZT_MAX_NETWORK_ROUTES);
 		memset(staticIps, 0, sizeof(InetAddress)*ZT_MAX_ZT_ASSIGNED_ADDRESSES);
 		memset(rules, 0, sizeof(ZT_VirtualNetworkRule)*ZT_MAX_NETWORK_RULES);
+		memset(dns, 0, sizeof(ZT_VirtualNetworkDNS)*ZT_MAX_NETWORK_DNS);
 	}
 
 	/**
@@ -589,6 +594,16 @@ public:
 	 * Certificate of membership (for private networks)
 	 */
 	CertificateOfMembership com;
+
+	/**
+	 * Number of ZT-pushed DNS configurations
+	 */
+	unsigned int dnsCount;
+
+	/**
+	 * ZT pushed DNS configuration
+	 */
+	ZT_VirtualNetworkDNS dns[ZT_MAX_NETWORK_DNS];
 };
 
 } // namespace ZeroTier