diff --git a/osdep/MacDNSHelper.hpp b/osdep/MacDNSHelper.hpp index 2fa283621..fafbeec54 100644 --- a/osdep/MacDNSHelper.hpp +++ b/osdep/MacDNSHelper.hpp @@ -12,8 +12,10 @@ class MacDNSHelper public: static void setDNS(uint64_t nwid, const char *domain, const std::vector &servers); static void removeDNS(uint64_t nwid); - static bool addIps(uint64_t nwid, const MAC mac, const char *dev, const std::vector &addrs); - static bool removeIps(uint64_t nwid); + static bool addIps4(uint64_t nwid, const MAC mac, const char *dev, const std::vector &addrs); + static bool addIps6(uint64_t nwid, const MAC mac, const char *dev, const std::vector &addrs); + static bool removeIps4(uint64_t nwid); + static bool removeIps6(uint64_t nwid); }; } diff --git a/osdep/MacDNSHelper.mm b/osdep/MacDNSHelper.mm index 5d6d14927..66de9e8cb 100644 --- a/osdep/MacDNSHelper.mm +++ b/osdep/MacDNSHelper.mm @@ -95,9 +95,114 @@ void MacDNSHelper::removeDNS(uint64_t nwid) // Originally I planned to put all the v6 ip addresses from the network into the config. // But only the link local address is necessary and sufficient. Added other v6 addresses // doesn't do anything. -bool MacDNSHelper::addIps(uint64_t nwid, const MAC mac, const char *dev, const std::vector& addrs) -{ +// +// As of Monterey we need IPv4 set up too. +bool MacDNSHelper::addIps4(uint64_t nwid, const MAC mac, const char *dev, const std::vector& addrs) +{ + const char* ipStr = {0}; + const char* ipStr2 = {0}; + char buf2[256] = {0}; + + bool hasV4 = false; + for (unsigned int i = 0; i < addrs.size(); ++i) { + if (addrs[i].isV4()) { + hasV4 = true; + + ipStr = addrs[i].toIpString(buf2); + ipStr2 = addrs[i].toIpString(buf2); + + break; + } + } + + if (!hasV4) { + MacDNSHelper::removeIps4(nwid); + return true; + } + + + SCDynamicStoreRef ds = SCDynamicStoreCreate(NULL, CFSTR("zerotier"), NULL, NULL); + char buf[256] = { 0 }; + sprintf(buf, "State:/Network/Service/%.16llx/IPv4", nwid); + + + CFStringRef key = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); + + CFStringRef cfaddr = CFStringCreateWithCString(NULL, ipStr, kCFStringEncodingUTF8); + CFArrayRef addrArray = CFArrayCreate(NULL, (const void**)&cfaddr, 1, &kCFTypeArrayCallBacks); + + CFStringRef cfdev = CFStringCreateWithCString(NULL, dev, kCFStringEncodingUTF8); + + CFStringRef cfserver = CFStringCreateWithCString(NULL, "127.0.0.1", kCFStringEncodingUTF8); + CFStringRef cfrouter = CFStringCreateWithCString(NULL, ipStr2, kCFStringEncodingUTF8); + + const int SIZE = 4; + CFStringRef keys[SIZE]; + keys[0] = CFSTR("Addresses"); + keys[1] = CFSTR("InterfaceName"); + keys[2] = CFSTR("ServerAddress"); + keys[3] = CFSTR("Router"); + + CFTypeRef values[SIZE]; + values[0] = addrArray; + values[1] = cfdev; + values[2] = cfserver; + values[3] = cfrouter; + + + CFDictionaryRef dict = CFDictionaryCreate(NULL, + (const void**)keys, (const void**)values, SIZE, &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + // CFDictionaryApplyFunction(dict, printKeys, NULL); + + CFArrayRef list = SCDynamicStoreCopyKeyList(ds, key); + CFIndex i = 0, j = CFArrayGetCount(list); + bool addrsChanged = true; + CFPropertyListRef oldAddrs = NULL; + + bool ret = TRUE; + if (j > 0) { + oldAddrs = SCDynamicStoreCopyValue(ds, (CFStringRef)CFArrayGetValueAtIndex(list, i)); + addrsChanged = !CFEqual(oldAddrs,dict); + } + if (addrsChanged) { + if (j <= 0) { + ret &= SCDynamicStoreAddValue(ds, key, dict); + } else { + ret &= SCDynamicStoreSetValue(ds, (CFStringRef)CFArrayGetValueAtIndex(list, i), dict); + } + if (!ret) { + fprintf(stderr, "Error writing IPv6 configuration\n"); + } + } + if (oldAddrs != NULL) { + CFRelease(oldAddrs); + } + + CFRelease(cfaddr); + + CFRelease(addrArray); + CFRelease(cfdev); + CFRelease(cfserver); + CFRelease(cfrouter); + + CFRelease(ds); + CFRelease(key); + + // for (unsigned int i = 0; i < SIZE; ++i) { + // values[i] = NULL; + // } + + CFRelease(list); + CFRelease(dict); + + return ret; + +} +bool MacDNSHelper::addIps6(uint64_t nwid, const MAC mac, const char *dev, const std::vector& addrs) +{ bool hasV6 = false; for (unsigned int i = 0; i < addrs.size(); ++i) { if (addrs[i].isV6()) { @@ -107,7 +212,7 @@ bool MacDNSHelper::addIps(uint64_t nwid, const MAC mac, const char *dev, const s } if (!hasV6) { - MacDNSHelper::removeIps(nwid); + MacDNSHelper::removeIps6(nwid); return true; } @@ -204,7 +309,7 @@ bool MacDNSHelper::addIps(uint64_t nwid, const MAC mac, const char *dev, const s return ret; } -bool MacDNSHelper::removeIps(uint64_t nwid) +bool MacDNSHelper::removeIps6(uint64_t nwid) { SCDynamicStoreRef ds = SCDynamicStoreCreate(NULL, CFSTR("zerotier"), NULL, NULL); @@ -218,4 +323,20 @@ bool MacDNSHelper::removeIps(uint64_t nwid) return res; } + +bool MacDNSHelper::removeIps4(uint64_t nwid) +{ + SCDynamicStoreRef ds = SCDynamicStoreCreate(NULL, CFSTR("zerotier"), NULL, NULL); + + char buf[256] = {0}; + sprintf(buf, "State:/Network/Service/%.16llx/IPv4", nwid); + CFStringRef key = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); + bool res = SCDynamicStoreRemoveValue(ds, key); + CFRelease(key); + CFRelease(ds); + + return res; +} + + } diff --git a/osdep/MacEthernetTap.cpp b/osdep/MacEthernetTap.cpp index 392f222b8..37f27f87a 100644 --- a/osdep/MacEthernetTap.cpp +++ b/osdep/MacEthernetTap.cpp @@ -245,7 +245,8 @@ MacEthernetTap::~MacEthernetTap() pid_t pid0,pid1; MacDNSHelper::removeDNS(_nwid); - MacDNSHelper::removeIps(_nwid); + MacDNSHelper::removeIps4(_nwid); + MacDNSHelper::removeIps6(_nwid); Mutex::Lock _gl(globalTapCreateLock); ::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit diff --git a/service/OneService.cpp b/service/OneService.cpp index edaca9c8c..ead7a8346 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -2531,8 +2531,13 @@ public: } #ifdef __APPLE__ - if (!MacDNSHelper::addIps(n.config().nwid, n.config().mac, n.tap()->deviceName().c_str(), newManagedIps)) + if (!MacDNSHelper::addIps6(n.config().nwid, n.config().mac, n.tap()->deviceName().c_str(), newManagedIps)) { fprintf(stderr, "ERROR: unable to add v6 addresses to system configuration" ZT_EOL_S); + } + + if (!MacDNSHelper::addIps4(n.config().nwid, n.config().mac, n.tap()->deviceName().c_str(), newManagedIps)) { + fprintf(stderr, "ERROR: unable to add v4 addresses to system configuration" ZT_EOL_S); + } #endif n.setManagedIps(newManagedIps); }