Skip to content

Commit

Permalink
Fix network DNS on macOS
Browse files Browse the repository at this point in the history
It stopped working for ipv4 only networks in Monterey.
See #1696

We add some config like so to System Configuration

```
scutil
show State:/Network/Service/9bee8941b5xxxxxx/IPv4
<dictionary> {
  Addresses : <array> {
    0 : 10.2.1.36
  }
  InterfaceName : feth4823
  Router : 10.2.1.36
  ServerAddress : 127.0.0.1
}

```
  • Loading branch information
laduke committed Jul 27, 2023
1 parent 41f9bdc commit fb6af19
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 7 deletions.
6 changes: 4 additions & 2 deletions osdep/MacDNSHelper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ class MacDNSHelper
public:
static void setDNS(uint64_t nwid, const char *domain, const std::vector<InetAddress> &servers);
static void removeDNS(uint64_t nwid);
static bool addIps(uint64_t nwid, const MAC mac, const char *dev, const std::vector<InetAddress> &addrs);
static bool removeIps(uint64_t nwid);
static bool addIps4(uint64_t nwid, const MAC mac, const char *dev, const std::vector<InetAddress> &addrs);
static bool addIps6(uint64_t nwid, const MAC mac, const char *dev, const std::vector<InetAddress> &addrs);
static bool removeIps4(uint64_t nwid);
static bool removeIps6(uint64_t nwid);
};

}
Expand Down
127 changes: 124 additions & 3 deletions osdep/MacDNSHelper.mm
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,114 @@ static void printKeys (const void* key, const void* value, void* context) {
// 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<InetAddress>& 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<InetAddress>& 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<InetAddress>& addrs)
{
bool hasV6 = false;
for (unsigned int i = 0; i < addrs.size(); ++i) {
if (addrs[i].isV6()) {
Expand All @@ -107,7 +212,7 @@ static void printKeys (const void* key, const void* value, void* context) {
}

if (!hasV6) {
MacDNSHelper::removeIps(nwid);
MacDNSHelper::removeIps6(nwid);
return true;
}

Expand Down Expand Up @@ -204,7 +309,7 @@ static void printKeys (const void* key, const void* value, void* context) {

return ret;
}
bool MacDNSHelper::removeIps(uint64_t nwid)
bool MacDNSHelper::removeIps6(uint64_t nwid)
{
SCDynamicStoreRef ds = SCDynamicStoreCreate(NULL, CFSTR("zerotier"), NULL, NULL);

Expand All @@ -218,4 +323,20 @@ static void printKeys (const void* key, const void* value, void* context) {
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;
}


}
3 changes: 2 additions & 1 deletion osdep/MacEthernetTap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion service/OneService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2531,8 +2531,13 @@ class OneServiceImpl : public OneService
}

#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);
}
Expand Down

0 comments on commit fb6af19

Please sign in to comment.