ソースを参照

Fix network DNS on macOS

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
}

```
travisladuke 2 年 前
コミット
fb6af1971b
4 ファイル変更136 行追加7 行削除
  1. 4 2
      osdep/MacDNSHelper.hpp
  2. 124 3
      osdep/MacDNSHelper.mm
  3. 2 1
      osdep/MacEthernetTap.cpp
  4. 6 1
      service/OneService.cpp

+ 4 - 2
osdep/MacDNSHelper.hpp

@@ -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);
 };
 
 }

+ 124 - 3
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<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()) {
@@ -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;
+}
+
+
 }

+ 2 - 1
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

+ 6 - 1
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);
 		}