|
|
|
|
@ -6,6 +6,11 @@
|
|
|
|
|
|
|
|
|
|
namespace ZeroTier { |
|
|
|
|
|
|
|
|
|
static void printKeys (const void* key, const void* value, void* context) { |
|
|
|
|
CFShow(key); |
|
|
|
|
CFShow(value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MacDNSHelper::setDNS(uint64_t nwid, const char *domain, const std::vector<InetAddress> &servers) |
|
|
|
|
{ |
|
|
|
|
SCDynamicStoreRef ds = SCDynamicStoreCreate(NULL, CFSTR("zerotier"), NULL, NULL); |
|
|
|
|
@ -85,4 +90,130 @@ void MacDNSHelper::removeDNS(uint64_t nwid)
|
|
|
|
|
CFRelease(ds); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
// Make macOS believe we do in fact have ipv6 connectivity and that it should resolve dns names |
|
|
|
|
// over ipv6 if we ask for them. |
|
|
|
|
// 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) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
bool hasV6 = false; |
|
|
|
|
for (unsigned int i = 0; i < addrs.size(); ++i) { |
|
|
|
|
if (addrs[i].isV6()) { |
|
|
|
|
hasV6 = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!hasV6) { |
|
|
|
|
MacDNSHelper::removeIps(nwid); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SCDynamicStoreRef ds = SCDynamicStoreCreate(NULL, CFSTR("zerotier"), NULL, NULL); |
|
|
|
|
char buf[256] = { 0 }; |
|
|
|
|
sprintf(buf, "State:/Network/Service/%.16llx/IPv6", nwid); |
|
|
|
|
|
|
|
|
|
InetAddress ll = InetAddress::makeIpv6LinkLocal(mac); |
|
|
|
|
char buf2[256] = {0}; |
|
|
|
|
const char* llStr = ll.toIpString(buf2); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CFStringRef key = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); |
|
|
|
|
CFStringRef* cfaddrs = new CFStringRef[1]; |
|
|
|
|
CFStringRef* cfprefixes = new CFStringRef[1]; |
|
|
|
|
CFStringRef* cfdestaddrs = new CFStringRef[1]; |
|
|
|
|
CFStringRef* cfflags = new CFStringRef[1]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cfaddrs[0] = CFStringCreateWithCString(NULL, llStr, kCFStringEncodingUTF8); |
|
|
|
|
cfprefixes[0] = CFStringCreateWithCString(NULL, "64", kCFStringEncodingUTF8); |
|
|
|
|
cfdestaddrs[0] = CFStringCreateWithCString(NULL, "::ffff:ffff:ffff:ffff:0:0", kCFStringEncodingUTF8); |
|
|
|
|
cfflags[0] = CFStringCreateWithCString(NULL, "0", kCFStringEncodingUTF8); |
|
|
|
|
|
|
|
|
|
CFArrayRef addrArray = CFArrayCreate(NULL, (const void**)cfaddrs, 1, &kCFTypeArrayCallBacks); |
|
|
|
|
CFArrayRef prefixArray = CFArrayCreate(NULL, (const void**)cfprefixes, 1, &kCFTypeArrayCallBacks); |
|
|
|
|
CFArrayRef destArray = CFArrayCreate(NULL, (const void**)cfdestaddrs, 1, &kCFTypeArrayCallBacks); |
|
|
|
|
CFArrayRef flagsArray = CFArrayCreate(NULL, (const void**)cfflags, 1, &kCFTypeArrayCallBacks); |
|
|
|
|
CFStringRef cfdev = CFStringCreateWithCString(NULL, dev, kCFStringEncodingUTF8); |
|
|
|
|
|
|
|
|
|
const int SIZE = 5; |
|
|
|
|
CFStringRef keys[SIZE]; |
|
|
|
|
keys[0] = CFSTR("Addresses"); |
|
|
|
|
keys[1] = CFSTR("DestAddresses"); |
|
|
|
|
keys[2] = CFSTR("Flags"); |
|
|
|
|
keys[3] = CFSTR("InterfaceName"); |
|
|
|
|
keys[4] = CFSTR("PrefixLength"); |
|
|
|
|
|
|
|
|
|
CFTypeRef values[SIZE]; |
|
|
|
|
values[0] = addrArray; |
|
|
|
|
values[1] = destArray; |
|
|
|
|
values[2] = flagsArray; |
|
|
|
|
// values[3] = devArray; |
|
|
|
|
values[3] = cfdev; |
|
|
|
|
values[4] = prefixArray; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CFRelease(addrArray); |
|
|
|
|
CFRelease(prefixArray); |
|
|
|
|
CFRelease(destArray); |
|
|
|
|
CFRelease(flagsArray); |
|
|
|
|
CFRelease(cfdev); |
|
|
|
|
|
|
|
|
|
CFRelease(list); |
|
|
|
|
CFRelease(dict); |
|
|
|
|
|
|
|
|
|
CFRelease(ds); |
|
|
|
|
CFRelease(key); |
|
|
|
|
|
|
|
|
|
delete[] cfaddrs; |
|
|
|
|
delete[] cfprefixes; |
|
|
|
|
delete[] cfdestaddrs; |
|
|
|
|
delete[] cfflags; |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
bool MacDNSHelper::removeIps(uint64_t nwid) |
|
|
|
|
{ |
|
|
|
|
SCDynamicStoreRef ds = SCDynamicStoreCreate(NULL, CFSTR("zerotier"), NULL, NULL); |
|
|
|
|
|
|
|
|
|
char buf[256] = {0}; |
|
|
|
|
sprintf(buf, "State:/Network/Service/%.16llx/IPv6", nwid); |
|
|
|
|
CFStringRef key = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); |
|
|
|
|
bool res = SCDynamicStoreRemoveValue(ds, key); |
|
|
|
|
CFRelease(key); |
|
|
|
|
CFRelease(ds); |
|
|
|
|
|
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|