mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 03:53:44 +02:00
Add bindToWildcard local.conf option.
This commit is contained in:
parent
384e5b66de
commit
125ec622ca
3 changed files with 182 additions and 175 deletions
346
osdep/Binder.hpp
346
osdep/Binder.hpp
|
@ -125,184 +125,32 @@ public:
|
||||||
*
|
*
|
||||||
* @param phy Physical interface
|
* @param phy Physical interface
|
||||||
* @param ports Ports to bind on all interfaces
|
* @param ports Ports to bind on all interfaces
|
||||||
* @param ignoreInterfacesByName Ignore these interfaces by name
|
* @param portCount Number of ports
|
||||||
* @param ignoreInterfacesByNamePrefix Ignore these interfaces by name-prefix (starts-with, e.g. zt ignores zt*)
|
* @param bindtoWildcard If true, bind wildcard instead of per-interface IPs
|
||||||
* @param ignoreInterfacesByAddress Ignore these interfaces by address
|
* @param ifChecker Interface checker function to see if an interface should be used
|
||||||
* @tparam PHY_HANDLER_TYPE Type for Phy<> template
|
* @tparam PHY_HANDLER_TYPE Type for Phy<> template
|
||||||
* @tparam INTERFACE_CHECKER Type for class containing shouldBindInterface() method
|
* @tparam INTERFACE_CHECKER Type for class containing shouldBindInterface() method
|
||||||
*/
|
*/
|
||||||
template<typename PHY_HANDLER_TYPE,typename INTERFACE_CHECKER>
|
template<typename PHY_HANDLER_TYPE,typename INTERFACE_CHECKER>
|
||||||
void refresh(Phy<PHY_HANDLER_TYPE> &phy,unsigned int *ports,unsigned int portCount,INTERFACE_CHECKER &ifChecker)
|
void refresh(Phy<PHY_HANDLER_TYPE> &phy,unsigned int *ports,unsigned int portCount,bool bindToWildcard,INTERFACE_CHECKER &ifChecker)
|
||||||
{
|
{
|
||||||
std::map<InetAddress,std::string> localIfAddrs;
|
std::map<InetAddress,std::string> localIfAddrs;
|
||||||
PhySocket *udps,*tcps;
|
PhySocket *udps,*tcps;
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
bool interfacesEnumerated = true;
|
bool interfacesEnumerated = true;
|
||||||
|
|
||||||
|
if (!bindToWildcard) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
|
||||||
char aabuf[32768];
|
char aabuf[32768];
|
||||||
ULONG aalen = sizeof(aabuf);
|
ULONG aalen = sizeof(aabuf);
|
||||||
if (GetAdaptersAddresses(AF_UNSPEC,GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER,(void *)0,reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf),&aalen) == NO_ERROR) {
|
if (GetAdaptersAddresses(AF_UNSPEC,GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER,(void *)0,reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf),&aalen) == NO_ERROR) {
|
||||||
PIP_ADAPTER_ADDRESSES a = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf);
|
PIP_ADAPTER_ADDRESSES a = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf);
|
||||||
while (a) {
|
while (a) {
|
||||||
PIP_ADAPTER_UNICAST_ADDRESS ua = a->FirstUnicastAddress;
|
PIP_ADAPTER_UNICAST_ADDRESS ua = a->FirstUnicastAddress;
|
||||||
while (ua) {
|
while (ua) {
|
||||||
InetAddress ip(ua->Address.lpSockaddr);
|
InetAddress ip(ua->Address.lpSockaddr);
|
||||||
if (ifChecker.shouldBindInterface("",ip)) {
|
if (ifChecker.shouldBindInterface("",ip)) {
|
||||||
switch(ip.ipScope()) {
|
|
||||||
default: break;
|
|
||||||
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
|
||||||
case InetAddress::IP_SCOPE_GLOBAL:
|
|
||||||
case InetAddress::IP_SCOPE_SHARED:
|
|
||||||
case InetAddress::IP_SCOPE_PRIVATE:
|
|
||||||
for(int x=0;x<(int)portCount;++x) {
|
|
||||||
ip.setPort(ports[x]);
|
|
||||||
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ua = ua->Next;
|
|
||||||
}
|
|
||||||
a = a->Next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
interfacesEnumerated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // not __WINDOWS__
|
|
||||||
|
|
||||||
/* On Linux we use an alternative method if available since getifaddrs()
|
|
||||||
* gets very slow when there are lots of network namespaces. This won't
|
|
||||||
* work unless /proc/PID/net/if_inet6 exists and it may not on some
|
|
||||||
* embedded systems, so revert to getifaddrs() there. */
|
|
||||||
|
|
||||||
#ifdef __LINUX__
|
|
||||||
char fn[256],tmp[256];
|
|
||||||
std::set<std::string> ifnames;
|
|
||||||
const unsigned long pid = (unsigned long)getpid();
|
|
||||||
|
|
||||||
// Get all device names
|
|
||||||
OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid);
|
|
||||||
FILE *procf = fopen(fn,"r");
|
|
||||||
if (procf) {
|
|
||||||
while (fgets(tmp,sizeof(tmp),procf)) {
|
|
||||||
tmp[255] = 0;
|
|
||||||
char *saveptr = (char *)0;
|
|
||||||
for(char *f=Utils::stok(tmp," \t\r\n:|",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n:|",&saveptr)) {
|
|
||||||
if ((strcmp(f,"Inter-") != 0)&&(strcmp(f,"face") != 0)&&(f[0] != 0))
|
|
||||||
ifnames.insert(f);
|
|
||||||
break; // we only want the first field
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(procf);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
interfacesEnumerated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get IPv6 addresses (and any device names we don't already know)
|
|
||||||
OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid);
|
|
||||||
procf = fopen(fn,"r");
|
|
||||||
if (procf) {
|
|
||||||
while (fgets(tmp,sizeof(tmp),procf)) {
|
|
||||||
tmp[255] = 0;
|
|
||||||
char *saveptr = (char *)0;
|
|
||||||
unsigned char ipbits[16];
|
|
||||||
memset(ipbits,0,sizeof(ipbits));
|
|
||||||
char *devname = (char *)0;
|
|
||||||
int n = 0;
|
|
||||||
for(char *f=Utils::stok(tmp," \t\r\n",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n",&saveptr)) {
|
|
||||||
switch(n++) {
|
|
||||||
case 0: // IP in hex
|
|
||||||
Utils::unhex(f,32,ipbits,16);
|
|
||||||
break;
|
|
||||||
case 5: // device name
|
|
||||||
devname = f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (devname) {
|
|
||||||
ifnames.insert(devname);
|
|
||||||
InetAddress ip(ipbits,16,0);
|
|
||||||
if (ifChecker.shouldBindInterface(devname,ip)) {
|
|
||||||
switch(ip.ipScope()) {
|
|
||||||
default: break;
|
|
||||||
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
|
||||||
case InetAddress::IP_SCOPE_GLOBAL:
|
|
||||||
case InetAddress::IP_SCOPE_SHARED:
|
|
||||||
case InetAddress::IP_SCOPE_PRIVATE:
|
|
||||||
for(int x=0;x<(int)portCount;++x) {
|
|
||||||
ip.setPort(ports[x]);
|
|
||||||
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string(devname)));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(procf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get IPv4 addresses for each device
|
|
||||||
if (ifnames.size() > 0) {
|
|
||||||
const int controlfd = (int)socket(AF_INET,SOCK_DGRAM,0);
|
|
||||||
struct ifconf configuration;
|
|
||||||
configuration.ifc_len = 0;
|
|
||||||
configuration.ifc_buf = nullptr;
|
|
||||||
|
|
||||||
if (controlfd < 0) goto ip4_address_error;
|
|
||||||
if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error;
|
|
||||||
configuration.ifc_buf = (char*)malloc(configuration.ifc_len);
|
|
||||||
if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error;
|
|
||||||
|
|
||||||
for (int i=0; i < (int)(configuration.ifc_len / sizeof(ifreq)); i ++) {
|
|
||||||
struct ifreq& request = configuration.ifc_req[i];
|
|
||||||
struct sockaddr* addr = &request.ifr_ifru.ifru_addr;
|
|
||||||
if (addr->sa_family != AF_INET) continue;
|
|
||||||
std::string ifname = request.ifr_ifrn.ifrn_name;
|
|
||||||
// name can either be just interface name or interface name followed by ':' and arbitrary label
|
|
||||||
if (ifname.find(':') != std::string::npos)
|
|
||||||
ifname = ifname.substr(0, ifname.find(':'));
|
|
||||||
|
|
||||||
InetAddress ip(&(((struct sockaddr_in *)addr)->sin_addr),4,0);
|
|
||||||
if (ifChecker.shouldBindInterface(ifname.c_str(), ip)) {
|
|
||||||
switch(ip.ipScope()) {
|
|
||||||
default: break;
|
|
||||||
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
|
||||||
case InetAddress::IP_SCOPE_GLOBAL:
|
|
||||||
case InetAddress::IP_SCOPE_SHARED:
|
|
||||||
case InetAddress::IP_SCOPE_PRIVATE:
|
|
||||||
for(int x=0;x<(int)portCount;++x) {
|
|
||||||
ip.setPort(ports[x]);
|
|
||||||
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,ifname));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ip4_address_error:
|
|
||||||
free(configuration.ifc_buf);
|
|
||||||
if (controlfd > 0) close(controlfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool gotViaProc = (localIfAddrs.size() > 0);
|
|
||||||
#else
|
|
||||||
const bool gotViaProc = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!gotViaProc) {
|
|
||||||
struct ifaddrs *ifatbl = (struct ifaddrs *)0;
|
|
||||||
struct ifaddrs *ifa;
|
|
||||||
if ((getifaddrs(&ifatbl) == 0)&&(ifatbl)) {
|
|
||||||
ifa = ifatbl;
|
|
||||||
while (ifa) {
|
|
||||||
if ((ifa->ifa_name)&&(ifa->ifa_addr)) {
|
|
||||||
InetAddress ip = *(ifa->ifa_addr);
|
|
||||||
if (ifChecker.shouldBindInterface(ifa->ifa_name,ip)) {
|
|
||||||
switch(ip.ipScope()) {
|
switch(ip.ipScope()) {
|
||||||
default: break;
|
default: break;
|
||||||
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
||||||
|
@ -311,22 +159,176 @@ public:
|
||||||
case InetAddress::IP_SCOPE_PRIVATE:
|
case InetAddress::IP_SCOPE_PRIVATE:
|
||||||
for(int x=0;x<(int)portCount;++x) {
|
for(int x=0;x<(int)portCount;++x) {
|
||||||
ip.setPort(ports[x]);
|
ip.setPort(ports[x]);
|
||||||
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string(ifa->ifa_name)));
|
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ua = ua->Next;
|
||||||
|
}
|
||||||
|
a = a->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
interfacesEnumerated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // not __WINDOWS__
|
||||||
|
|
||||||
|
/* On Linux we use an alternative method if available since getifaddrs()
|
||||||
|
* gets very slow when there are lots of network namespaces. This won't
|
||||||
|
* work unless /proc/PID/net/if_inet6 exists and it may not on some
|
||||||
|
* embedded systems, so revert to getifaddrs() there. */
|
||||||
|
|
||||||
|
#ifdef __LINUX__
|
||||||
|
char fn[256],tmp[256];
|
||||||
|
std::set<std::string> ifnames;
|
||||||
|
const unsigned long pid = (unsigned long)getpid();
|
||||||
|
|
||||||
|
// Get all device names
|
||||||
|
OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid);
|
||||||
|
FILE *procf = fopen(fn,"r");
|
||||||
|
if (procf) {
|
||||||
|
while (fgets(tmp,sizeof(tmp),procf)) {
|
||||||
|
tmp[255] = 0;
|
||||||
|
char *saveptr = (char *)0;
|
||||||
|
for(char *f=Utils::stok(tmp," \t\r\n:|",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n:|",&saveptr)) {
|
||||||
|
if ((strcmp(f,"Inter-") != 0)&&(strcmp(f,"face") != 0)&&(f[0] != 0))
|
||||||
|
ifnames.insert(f);
|
||||||
|
break; // we only want the first field
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(procf);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
interfacesEnumerated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get IPv6 addresses (and any device names we don't already know)
|
||||||
|
OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid);
|
||||||
|
procf = fopen(fn,"r");
|
||||||
|
if (procf) {
|
||||||
|
while (fgets(tmp,sizeof(tmp),procf)) {
|
||||||
|
tmp[255] = 0;
|
||||||
|
char *saveptr = (char *)0;
|
||||||
|
unsigned char ipbits[16];
|
||||||
|
memset(ipbits,0,sizeof(ipbits));
|
||||||
|
char *devname = (char *)0;
|
||||||
|
int n = 0;
|
||||||
|
for(char *f=Utils::stok(tmp," \t\r\n",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n",&saveptr)) {
|
||||||
|
switch(n++) {
|
||||||
|
case 0: // IP in hex
|
||||||
|
Utils::unhex(f,32,ipbits,16);
|
||||||
|
break;
|
||||||
|
case 5: // device name
|
||||||
|
devname = f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (devname) {
|
||||||
|
ifnames.insert(devname);
|
||||||
|
InetAddress ip(ipbits,16,0);
|
||||||
|
if (ifChecker.shouldBindInterface(devname,ip)) {
|
||||||
|
switch(ip.ipScope()) {
|
||||||
|
default: break;
|
||||||
|
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
||||||
|
case InetAddress::IP_SCOPE_GLOBAL:
|
||||||
|
case InetAddress::IP_SCOPE_SHARED:
|
||||||
|
case InetAddress::IP_SCOPE_PRIVATE:
|
||||||
|
for(int x=0;x<(int)portCount;++x) {
|
||||||
|
ip.setPort(ports[x]);
|
||||||
|
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string(devname)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ifa = ifa->ifa_next;
|
|
||||||
}
|
}
|
||||||
freeifaddrs(ifatbl);
|
fclose(procf);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
interfacesEnumerated = false;
|
// Get IPv4 addresses for each device
|
||||||
|
if (ifnames.size() > 0) {
|
||||||
|
const int controlfd = (int)socket(AF_INET,SOCK_DGRAM,0);
|
||||||
|
struct ifconf configuration;
|
||||||
|
configuration.ifc_len = 0;
|
||||||
|
configuration.ifc_buf = nullptr;
|
||||||
|
|
||||||
|
if (controlfd < 0) goto ip4_address_error;
|
||||||
|
if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error;
|
||||||
|
configuration.ifc_buf = (char*)malloc(configuration.ifc_len);
|
||||||
|
if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error;
|
||||||
|
|
||||||
|
for (int i=0; i < (int)(configuration.ifc_len / sizeof(ifreq)); i ++) {
|
||||||
|
struct ifreq& request = configuration.ifc_req[i];
|
||||||
|
struct sockaddr* addr = &request.ifr_ifru.ifru_addr;
|
||||||
|
if (addr->sa_family != AF_INET) continue;
|
||||||
|
std::string ifname = request.ifr_ifrn.ifrn_name;
|
||||||
|
// name can either be just interface name or interface name followed by ':' and arbitrary label
|
||||||
|
if (ifname.find(':') != std::string::npos)
|
||||||
|
ifname = ifname.substr(0, ifname.find(':'));
|
||||||
|
|
||||||
|
InetAddress ip(&(((struct sockaddr_in *)addr)->sin_addr),4,0);
|
||||||
|
if (ifChecker.shouldBindInterface(ifname.c_str(), ip)) {
|
||||||
|
switch(ip.ipScope()) {
|
||||||
|
default: break;
|
||||||
|
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
||||||
|
case InetAddress::IP_SCOPE_GLOBAL:
|
||||||
|
case InetAddress::IP_SCOPE_SHARED:
|
||||||
|
case InetAddress::IP_SCOPE_PRIVATE:
|
||||||
|
for(int x=0;x<(int)portCount;++x) {
|
||||||
|
ip.setPort(ports[x]);
|
||||||
|
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,ifname));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ip4_address_error:
|
||||||
|
free(configuration.ifc_buf);
|
||||||
|
if (controlfd > 0) close(controlfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool gotViaProc = (localIfAddrs.size() > 0);
|
||||||
|
#else
|
||||||
|
const bool gotViaProc = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!gotViaProc) {
|
||||||
|
struct ifaddrs *ifatbl = (struct ifaddrs *)0;
|
||||||
|
struct ifaddrs *ifa;
|
||||||
|
if ((getifaddrs(&ifatbl) == 0)&&(ifatbl)) {
|
||||||
|
ifa = ifatbl;
|
||||||
|
while (ifa) {
|
||||||
|
if ((ifa->ifa_name)&&(ifa->ifa_addr)) {
|
||||||
|
InetAddress ip = *(ifa->ifa_addr);
|
||||||
|
if (ifChecker.shouldBindInterface(ifa->ifa_name,ip)) {
|
||||||
|
switch(ip.ipScope()) {
|
||||||
|
default: break;
|
||||||
|
case InetAddress::IP_SCOPE_PSEUDOPRIVATE:
|
||||||
|
case InetAddress::IP_SCOPE_GLOBAL:
|
||||||
|
case InetAddress::IP_SCOPE_SHARED:
|
||||||
|
case InetAddress::IP_SCOPE_PRIVATE:
|
||||||
|
for(int x=0;x<(int)portCount;++x) {
|
||||||
|
ip.setPort(ports[x]);
|
||||||
|
localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string(ifa->ifa_name)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ifa = ifa->ifa_next;
|
||||||
|
}
|
||||||
|
freeifaddrs(ifatbl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
interfacesEnumerated = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Default to binding to wildcard if we can't enumerate addresses
|
// Default to binding to wildcard if we can't enumerate addresses
|
||||||
if (!interfacesEnumerated && localIfAddrs.empty()) {
|
if (!interfacesEnumerated && localIfAddrs.empty()) {
|
||||||
|
|
|
@ -565,6 +565,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read local configuration
|
// Read local configuration
|
||||||
|
bool bindToWildcard = false;
|
||||||
{
|
{
|
||||||
std::map<InetAddress,ZT_PhysicalPathConfiguration> ppc;
|
std::map<InetAddress,ZT_PhysicalPathConfiguration> ppc;
|
||||||
|
|
||||||
|
@ -626,12 +627,15 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow controller DB path to be put somewhere else
|
|
||||||
json &settings = _localConfig["settings"];
|
json &settings = _localConfig["settings"];
|
||||||
if (settings.is_object()) {
|
if (settings.is_object()) {
|
||||||
|
// Allow controller DB path to be put somewhere else
|
||||||
const std::string cdbp(OSUtils::jsonString(settings["controllerDbPath"],""));
|
const std::string cdbp(OSUtils::jsonString(settings["controllerDbPath"],""));
|
||||||
if (cdbp.length() > 0)
|
if (cdbp.length() > 0)
|
||||||
_controllerDbPath = cdbp;
|
_controllerDbPath = cdbp;
|
||||||
|
|
||||||
|
// Bind to wildcard instead of to specific interfaces (disables full tunnel capability)
|
||||||
|
bindToWildcard = OSUtils::jsonBool(settings["bindToWildcard"],false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set trusted paths if there are any
|
// Set trusted paths if there are any
|
||||||
|
@ -801,7 +805,7 @@ public:
|
||||||
if (_ports[i])
|
if (_ports[i])
|
||||||
p[pc++] = _ports[i];
|
p[pc++] = _ports[i];
|
||||||
}
|
}
|
||||||
_binder.refresh(_phy,p,pc,*this);
|
_binder.refresh(_phy,p,pc,bindToWildcard,*this);
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_nets_m);
|
Mutex::Lock _l(_nets_m);
|
||||||
for(std::map<uint64_t,NetworkState>::iterator n(_nets.begin());n!=_nets.end();++n) {
|
for(std::map<uint64_t,NetworkState>::iterator n(_nets.begin());n!=_nets.end();++n) {
|
||||||
|
|
|
@ -31,7 +31,8 @@ Settings available in `local.conf` (this is not valid JSON, and JSON does not al
|
||||||
"softwareUpdateChannel": "release"|"beta", /* Software update channel */
|
"softwareUpdateChannel": "release"|"beta", /* Software update channel */
|
||||||
"softwareUpdateDist": true|false, /* If true, distribute software updates (only really useful to ZeroTier, Inc. itself, default is false) */
|
"softwareUpdateDist": true|false, /* If true, distribute software updates (only really useful to ZeroTier, Inc. itself, default is false) */
|
||||||
"interfacePrefixBlacklist": [ "XXX",... ], /* Array of interface name prefixes (e.g. eth for eth#) to blacklist for ZT traffic */
|
"interfacePrefixBlacklist": [ "XXX",... ], /* Array of interface name prefixes (e.g. eth for eth#) to blacklist for ZT traffic */
|
||||||
"allowManagementFrom": "NETWORK/bits"|null /* If non-NULL, allow JSON/HTTP management from this IP network. Default is 127.0.0.1 only. */
|
"allowManagementFrom": "NETWORK/bits"|null, /* If non-NULL, allow JSON/HTTP management from this IP network. Default is 127.0.0.1 only. */
|
||||||
|
"bindToWildcard": true|false /* If true, bind to wildcard e.g. 0.0.0.0 instead of per interface */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
Loading…
Add table
Reference in a new issue