single dns config per network

This commit is contained in:
Grant Limberg 2020-08-12 13:08:47 -07:00
parent 058d888311
commit c0c215c83c
No known key found for this signature in database
GPG key ID: 2BA62CCABBB4095A
9 changed files with 76 additions and 147 deletions

View file

@ -1711,25 +1711,18 @@ void EmbeddedNetworkController::_request(
} }
} }
if(dns.is_array()) { if(dns.is_object()) {
nc->dnsCount = 0; std::string domain = OSUtils::jsonString(dns["domain"],"");
for(unsigned int p=0; p < dns.size(); ++p) { memcpy(nc->dns.domain, domain.c_str(), domain.size());
json &d = dns[p]; json &addrArray = dns["servers"];
if (d.is_object()) { if (addrArray.is_array()) {
std::string domain = OSUtils::jsonString(d["domain"],""); for(unsigned int j = 0; j < addrArray.size() && j < ZT_MAX_DNS_SERVERS; ++j) {
memcpy(nc->dns[nc->dnsCount].domain, domain.c_str(), domain.size()); json &addr = addrArray[j];
json &addrArray = d["servers"]; nc->dns.server_addr[j] = InetAddress(OSUtils::jsonString(addr,"").c_str());
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;
} }
} }
} else { } else {
dns = json::array(); dns = json::object();
} }
// Issue a certificate of ownership for all static IPs // Issue a certificate of ownership for all static IPs

View file

@ -447,12 +447,12 @@ void PostgreSQL::initializeNetworks(PGconn *conn)
} }
n = PQntuples(r2); n = PQntuples(r2);
config["dns"] = json::array(); if (n > 1) {
for (int j = 0; j < n; ++j) { fprintf(stderr, "ERROR: invalid number of DNS configurations for network %s. Must be 0 or 1\n", nwid.c_str());
} else if (n == 1) {
json obj; json obj;
std::string domain = PQgetvalue(r2, j, 0); std::string domain = PQgetvalue(r2, 0, 0);
std::string serverList = PQgetvalue(r2, j, 1); std::string serverList = PQgetvalue(r2, 0, 1);
auto servers = json::array(); auto servers = json::array();
if (serverList.rfind("{",0) != std::string::npos) { if (serverList.rfind("{",0) != std::string::npos) {
serverList = serverList.substr(1, serverList.size()-2); serverList = serverList.substr(1, serverList.size()-2);
@ -465,7 +465,7 @@ void PostgreSQL::initializeNetworks(PGconn *conn)
} }
obj["domain"] = domain; obj["domain"] = domain;
obj["servers"] = servers; obj["servers"] = servers;
config["dns"].push_back(obj); config["dns"] = obj;
} }
PQclear(r2); PQclear(r2);
@ -1461,67 +1461,38 @@ void PostgreSQL::commitThread()
config = nullptr; config = nullptr;
continue; continue;
} }
auto dns = (*config)["dns"];
std::string domain = dns["domain"];
std::stringstream servers;
servers << "{";
for (auto j = dns["servers"].begin(); j < dns["servers"].end(); ++j) {
servers << *j;
if ( (j+1) != dns["servers"].end()) {
servers << ",";
}
}
servers << "}";
const char *p[3] = {
id.c_str(),
domain.c_str(),
servers.str().c_str()
};
res = PQexecParams(conn, res = PQexecParams(conn, "INSERT INTO ztc_network_dns (network_id, domain, servers) VALUES ($1, $2, $3) ON CONFLICT (network_id) DO UPDATE SET domain = EXCLUDED.domain, servers = EXCLUDED.servers",
"DELETE FROM ztc_network_dns WHERE network_id = $1", 3,
1,
NULL, NULL,
params, p,
NULL, NULL,
NULL, NULL,
0); 0);
if (PQresultStatus(res) != PGRES_COMMAND_OK) { if (PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "ERROR: Error updating dns: %s\n", PQresultErrorMessage(res)); fprintf(stderr, "ERROR: Error updating DNS: %s\n", PQresultErrorMessage(res));
PQclear(res); PQclear(res);
PQclear(PQexec(conn, "ROLLBACK")); err = true;
delete config; break;
config = nullptr;
continue;
}
auto dns = (*config)["dns"];
err = false;
for (auto i = dns.begin(); i < dns.end(); ++i) {
std::string domain = (*i)["domain"];
std::stringstream servers;
servers << "{";
for (auto j = dns["servers"].begin(); j < dns["servers"].end(); ++j) {
servers << *j;
if ( (j+1) != dns["servers"].end()) {
servers << ",";
}
}
servers << "}";
const char *p[3] = {
id.c_str(),
domain.c_str(),
servers.str().c_str()
};
res = PQexecParams(conn, "INSERT INTO ztc_network_dns (network_id, domain, servers) VALUES ($1, $2, $3)",
3,
NULL,
p,
NULL,
NULL,
0);
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "ERROR: Error updating DNS: %s\n", PQresultErrorMessage(res));
PQclear(res);
err = true;
break;
}
PQclear(res);
}
if (err) {
PQclear(PQexec(conn, "ROLLBACK"));
delete config;
config = nullptr;
continue;
} }
PQclear(res);
res = PQexec(conn, "COMMIT"); res = PQexec(conn, "COMMIT");
if (PQresultStatus(res) != PGRES_COMMAND_OK) { if (PQresultStatus(res) != PGRES_COMMAND_OK) {

View file

@ -125,11 +125,6 @@ extern "C" {
*/ */
#define ZT_MAX_NETWORK_ROUTES 32 #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) * Maximum number of statically assigned IP addresses per network endpoint using ZT address management (not DHCP)
*/ */
@ -1339,16 +1334,11 @@ typedef struct
uint64_t mac; /* MAC in lower 48 bits */ uint64_t mac; /* MAC in lower 48 bits */
uint32_t adi; /* Additional distinguishing information, usually zero except for IPv4 ARP groups */ uint32_t adi; /* Additional distinguishing information, usually zero except for IPv4 ARP groups */
} multicastSubscriptions[ZT_MAX_MULTICAST_SUBSCRIPTIONS]; } multicastSubscriptions[ZT_MAX_MULTICAST_SUBSCRIPTIONS];
/**
* Number of ZT-pushed DNS configuraitons
*/
unsigned int dnsCount;
/** /**
* Network specific DNS configuration * Network specific DNS configuration
*/ */
ZT_VirtualNetworkDNS dns[ZT_MAX_NETWORK_DNS]; ZT_VirtualNetworkDNS dns;
} ZT_VirtualNetworkConfig; } ZT_VirtualNetworkConfig;
/** /**

View file

@ -29,28 +29,24 @@ namespace ZeroTier {
class DNS { class DNS {
public: public:
template<unsigned int C> template<unsigned int C>
static inline void serializeDNS(Buffer<C> &b, const ZT_VirtualNetworkDNS *dns, unsigned int dnsCount) static inline void serializeDNS(Buffer<C> &b, const ZT_VirtualNetworkDNS *dns)
{ {
for(unsigned int i = 0; i < dnsCount; ++i) { b.append(dns->domain, 128);
b.append(dns[i].domain, 128); for(unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) {
for(unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) { InetAddress tmp(dns->server_addr[j]);
InetAddress tmp(dns[i].server_addr[j]); tmp.serialize(b);
tmp.serialize(b);
}
} }
} }
template<unsigned int C> template<unsigned int C>
static inline void deserializeDNS(const Buffer<C> &b, unsigned int &p, ZT_VirtualNetworkDNS *dns, const unsigned int dnsCount) static inline void deserializeDNS(const Buffer<C> &b, unsigned int &p, ZT_VirtualNetworkDNS *dns)
{ {
memset(dns, 0, sizeof(ZT_VirtualNetworkDNS)*ZT_MAX_NETWORK_DNS); char *d = (char*)b.data()+p;
for(unsigned int i = 0; i < dnsCount; ++i) { memset(dns, 0, sizeof(ZT_VirtualNetworkDNS));
char *d = (char*)b.data()+p; memcpy(dns->domain, d, 128);
memcpy(dns[i].domain, d, 128); p += 128;
p += 128; for (unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) {
for (unsigned int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) { p += reinterpret_cast<InetAddress *>(&(dns->server_addr[j]))->deserialize(b, p);
p += reinterpret_cast<InetAddress *>(&(dns[i].server_addr[j]))->deserialize(b, p);
}
} }
} }
}; };

View file

@ -1428,11 +1428,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
ec->multicastSubscriptions[i].adi = _myMulticastGroups[i].adi(); ec->multicastSubscriptions[i].adi = _myMulticastGroups[i].adi();
} }
ec->dnsCount = _config.dnsCount; memcpy(&ec->dns, &_config.dns, sizeof(ZT_VirtualNetworkDNS));
fprintf(stderr, "Network::_externalConfig dnsCount: %d\n", ec->dnsCount);
if (ec->dnsCount > 0) {
memcpy(&ec->dns, &_config.dns, sizeof(ZT_VirtualNetworkDNS));
}
} }
void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup) void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup)

View file

@ -177,12 +177,9 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
} }
tmp->clear(); tmp->clear();
if (dnsCount > 0) { DNS::serializeDNS(*tmp, &dns);
tmp->append(dnsCount); if (tmp->size()) {
DNS::serializeDNS(*tmp, dns, dnsCount); if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_DNS,*tmp)) return false;
if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_DNS,*tmp)) return false;
}
} }
delete tmp; delete tmp;
@ -366,9 +363,7 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_DNS, *tmp)) { if (d.get(ZT_NETWORKCONFIG_DICT_KEY_DNS, *tmp)) {
unsigned int p = 0; unsigned int p = 0;
this->dnsCount = tmp->at<unsigned int>(p); DNS::deserializeDNS(*tmp, p, &dns);
p += sizeof(unsigned int);
DNS::deserializeDNS(*tmp, p, dns, (this->dnsCount <= ZT_MAX_NETWORK_DNS) ? this->dnsCount : ZT_MAX_NETWORK_DNS);
} }
} }

View file

@ -240,7 +240,7 @@ public:
memset(routes, 0, sizeof(ZT_VirtualNetworkRoute)*ZT_MAX_NETWORK_ROUTES); memset(routes, 0, sizeof(ZT_VirtualNetworkRoute)*ZT_MAX_NETWORK_ROUTES);
memset(staticIps, 0, sizeof(InetAddress)*ZT_MAX_ZT_ASSIGNED_ADDRESSES); memset(staticIps, 0, sizeof(InetAddress)*ZT_MAX_ZT_ASSIGNED_ADDRESSES);
memset(rules, 0, sizeof(ZT_VirtualNetworkRule)*ZT_MAX_NETWORK_RULES); memset(rules, 0, sizeof(ZT_VirtualNetworkRule)*ZT_MAX_NETWORK_RULES);
memset(dns, 0, sizeof(ZT_VirtualNetworkDNS)*ZT_MAX_NETWORK_DNS); memset(&dns, 0, sizeof(ZT_VirtualNetworkDNS));
} }
/** /**
@ -603,7 +603,7 @@ public:
/** /**
* ZT pushed DNS configuration * ZT pushed DNS configuration
*/ */
ZT_VirtualNetworkDNS dns[ZT_MAX_NETWORK_DNS]; ZT_VirtualNetworkDNS dns;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -34,7 +34,6 @@ void MacDNSHelper::setDNS(uint64_t nwid, const char *domain, const std::vector<I
CFDictionaryRef dict = CFDictionaryCreate(NULL, CFDictionaryRef dict = CFDictionaryCreate(NULL,
(const void**)keys, (const void**)values, 2, &kCFCopyStringDictionaryKeyCallBacks, (const void**)keys, (const void**)values, 2, &kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks); &kCFTypeDictionaryValueCallBacks);
CFShow(dict);
char buf[256] = {0}; char buf[256] = {0};
sprintf(buf, "State:/Network/Service/%.16llx/DNS", nwid); sprintf(buf, "State:/Network/Service/%.16llx/DNS", nwid);

View file

@ -232,20 +232,19 @@ static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc,
} }
nj["multicastSubscriptions"] = mca; nj["multicastSubscriptions"] = mca;
nj["dns"] = nlohmann::json::array(); nlohmann::json m;
for(unsigned int i=0;i<nc->dnsCount;++i) { m["domain"] = nc->dns.domain;
nlohmann::json m; m["servers"] = nlohmann::json::array();
m["domain"] = nc->dns[i].domain; for(int j=0;j<ZT_MAX_DNS_SERVERS;++j) {
m["servers"] = nlohmann::json::array();
for(int j=0;j<ZT_MAX_DNS_SERVERS;++j) { InetAddress a(nc->dns.server_addr[j]);
if (a.isV4() || a.isV6()) {
InetAddress a(nc->dns[i].server_addr[j]); char buf[256];
if (a.isV4() || a.isV6()) { m["servers"].push_back(a.toIpString(buf));
char buf[256];
m["servers"].push_back(a.toIpString(buf));
}
} }
} }
nj["dns"] = m;
} }
static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer) static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer)
@ -2002,25 +2001,15 @@ public:
} }
if (syncDns) { if (syncDns) {
char buf[128]; if (strlen(n.config.dns.domain) != 0) {
if (n.config.dnsCount > ZT_MAX_NETWORK_DNS) { std::vector<InetAddress> servers;
fprintf(stderr, "ERROR: %d records > max %d. Skipping DNS\n", n.config.dnsCount, ZT_MAX_NETWORK_DNS); for (int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) {
return; InetAddress a(n.config.dns.server_addr[j]);
} if (a.isV4() || a.isV6()) {
fprintf(stderr, "Syncing %d DNS configurations for network [%.16llx]\n", n.config.dnsCount, n.config.nwid); servers.push_back(a);
for (int i = 0; i < n.config.dnsCount; ++i) {
if (strlen(n.config.dns[i].domain) != 0) {
fprintf(stderr, "Syncing DNS for domain: %s\n", n.config.dns[i].domain);
std::vector<InetAddress> servers;
for (int j = 0; j < ZT_MAX_DNS_SERVERS; ++j) {
InetAddress a(n.config.dns[i].server_addr[j]);
if (a.isV4() || a.isV6()) {
fprintf(stderr, "\t Server %d: %s\n", j+1, a.toIpString(buf));
servers.push_back(a);
}
} }
n.tap->setDns(n.config.dns[i].domain, servers);
} }
n.tap->setDns(n.config.dns.domain, servers);
} }
} }
} }