From 387039456d9dd0a3a7b20017aaa71188c63903af Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 20 Jul 2020 14:34:19 -0700 Subject: [PATCH] Pass 1 at adding DNS to controller --- controller/EmbeddedNetworkController.cpp | 44 ++++++++++++++++++ include/ZeroTierOne.h | 29 ++++++++++++ node/DNS.hpp | 59 ++++++++++++++++++++++++ node/NetworkConfig.cpp | 16 +++++++ node/NetworkConfig.hpp | 17 ++++++- 5 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 node/DNS.hpp diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index b2bd7bfb9..b6621f29a 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/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;idnsCount = 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) { diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index c93b4dbf8..8ff9ba2f4 100644 --- a/include/ZeroTierOne.h +++ b/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; /** diff --git a/node/DNS.hpp b/node/DNS.hpp new file mode 100644 index 000000000..ff685d32d --- /dev/null +++ b/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 +#include +#include + +#include "Buffer.hpp" +#include "InetAddress.hpp" +#include "../include/ZeroTierOne.h" + +namespace ZeroTier { + +/** + * DNS data serealization methods + */ +class DNS { +public: + template + static inline void serializeDNS(Buffer &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 + static inline void deserializeDNS(const Buffer &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(&(dns[i].server_addr[j]))->deserialize(b, p); + } + } + } +}; + +} + +#endif // ZT_DNS_HPP diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 97985c7af..503d7400a 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -176,6 +176,15 @@ bool NetworkConfig::toDictionary(Dictionary &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 Dictionaryrules,this->ruleCount,ZT_MAX_NETWORK_RULES); } + + if (d.get(ZT_NETWORKCONFIG_DICT_KEY_DNS, *tmp)) { + unsigned int p = 0; + this->dnsCount = tmp->at(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()); diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 8311a0743..1daf98d01 100644 --- a/node/NetworkConfig.hpp +++ b/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