diff --git a/node/Buffer.hpp b/node/Buffer.hpp index 0b1715925..1a478894f 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -61,11 +61,11 @@ public: // STL container idioms typedef unsigned char value_type; typedef unsigned char * pointer; - typedef const unsigned char * const_pointer; - typedef unsigned char & reference; - typedef const unsigned char & const_reference; - typedef unsigned char * iterator; - typedef const unsigned char * const_iterator; + typedef const char * const_pointer; + typedef char & reference; + typedef const char & const_reference; + typedef char * iterator; + typedef const char * const_iterator; typedef unsigned int size_type; typedef int difference_type; typedef std::reverse_iterator reverse_iterator; diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 86158a91d..27027d3b8 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -121,6 +121,15 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_VirtualNetw case ZT_NETWORK_TYPE_PUBLIC: ntype = "PUBLIC"; break; } + std::string allowManaged = (localSettings.allowManaged) ? "true" : "false"; + if (localSettings.allowManagedWhitelist.size() != 0) { + allowManaged = ""; + for (InetAddress address : localSettings.allowManagedWhitelist) { + if (allowManaged.size() != 0) allowManaged += ','; + allowManaged += address.toIpString() + "/" + std::to_string(address.netmaskBits()); + } + } + Utils::snprintf(json,sizeof(json), "%s{\n" "%s\t\"id\": \"%.16llx\",\n" @@ -158,7 +167,7 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_VirtualNetw prefix,_jsonEnumerate(nc->assignedAddresses,nc->assignedAddressCount).c_str(), prefix,_jsonEnumerate(nc->routes,nc->routeCount).c_str(), prefix,_jsonEscape(portDeviceName).c_str(), - prefix,(localSettings.allowManaged) ? "true" : "false", + prefix,allowManaged.c_str(), prefix,(localSettings.allowGlobal) ? "true" : "false", prefix,(localSettings.allowDefault) ? "true" : "false", prefix); diff --git a/service/OneService.cpp b/service/OneService.cpp index 93f5b5f07..603234a22 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1039,6 +1039,18 @@ public: { if (!n.settings.allowManaged) return false; + + if (n.settings.allowManagedWhitelist.size() > 0) { + bool allowed = false; + for (InetAddress addr : n.settings.allowManagedWhitelist) { + if (addr.containsAddress(target) && addr.netmaskBits() <= target.netmaskBits()) { + allowed = true; + break; + } + } + if (!allowed) return false; + } + if (target.isDefaultRoute()) return n.settings.allowDefault; switch(target.ipScope()) { @@ -1423,9 +1435,32 @@ public: if (OSUtils::readFile(nlcpath,nlcbuf)) { Dictionary<4096> nc; nc.load(nlcbuf.c_str()); - n.settings.allowManaged = nc.getB("allowManaged",true); - n.settings.allowGlobal = nc.getB("allowGlobal",false); - n.settings.allowDefault = nc.getB("allowDefault",false); + Buffer<1024> allowManaged; + if (nc.get("allowManaged", allowManaged) && allowManaged.size() != 0) { + std::string addresses (allowManaged.begin(), allowManaged.size()); + if (allowManaged.size() <= 5) { // untidy parsing for backward compatibility + if (allowManaged[0] == '1' || allowManaged[0] == 't' || allowManaged[0] == 'T') { + n.settings.allowManaged = true; + } else { + n.settings.allowManaged = false; + } + } else { + // this should be a list of IP addresses + n.settings.allowManaged = true; + size_t pos = 0; + while (true) { + size_t nextPos = addresses.find(',', pos); + std::string address = addresses.substr(pos, (nextPos == std::string::npos ? addresses.size() : nextPos) - pos); + n.settings.allowManagedWhitelist.push_back(InetAddress(address)); + if (nextPos == std::string::npos) break; + pos = nextPos + 1; + } + } + } else { + n.settings.allowManaged = true; + } + n.settings.allowGlobal = nc.getB("allowGlobal", false); + n.settings.allowDefault = nc.getB("allowDefault", false); } } catch (std::exception &exc) { #ifdef __WINDOWS__ diff --git a/service/OneService.hpp b/service/OneService.hpp index 7aa3b3619..88225da4d 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -20,6 +20,7 @@ #define ZT_ONESERVICE_HPP #include +#include namespace ZeroTier { @@ -65,6 +66,12 @@ public: */ bool allowManaged; + /** + * Whitelist of addresses that can be configured by this network. + * If empty and allowManaged is true, allow all private/pseudoprivate addresses. + */ + std::vector allowManagedWhitelist; + /** * Allow configuration of IPs and routes within global (Internet) IP space? */