123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- #include "MacDNSHelper.hpp"
- #include <stdio.h>
- #include <SystemConfiguration/SystemConfiguration.h>
- 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);
- CFStringRef *s = new CFStringRef[4];
- for (unsigned int i = 0; i < servers.size(); ++i) {
- char buf[64];
- ZeroTier::InetAddress a = servers[i];
- const char *ipStr = a.toIpString(buf);
- s[i] = CFStringCreateWithCString(NULL, ipStr, kCFStringEncodingUTF8);
- }
- CFArrayRef serverArray = CFArrayCreate(NULL, (const void**)s, servers.size(), &kCFTypeArrayCallBacks);
- CFStringRef keys[2];
- keys[0] = CFSTR("SupplementalMatchDomains");
- keys[1] = CFSTR("ServerAddresses");
- CFStringRef cfdomain = CFStringCreateWithCString(NULL, domain, kCFStringEncodingUTF8);
- CFArrayRef domainArray = CFArrayCreate(NULL, (const void**)&cfdomain, 1, &kCFTypeArrayCallBacks);
- CFTypeRef values[2];
- values[0] = domainArray;
- values[1] = serverArray;
- CFDictionaryRef dict = CFDictionaryCreate(NULL,
- (const void**)keys, (const void**)values, 2, &kCFCopyStringDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- char buf[256] = {0};
- sprintf(buf, "State:/Network/Service/%.16llx/DNS", nwid);
- CFStringRef key = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
- CFArrayRef list = SCDynamicStoreCopyKeyList(ds, key);
- CFIndex i = 0, j = CFArrayGetCount(list);
- bool dnsServersChanged = true;
- CFPropertyListRef oldDNSServers = NULL;
- if (j > 0) {
- oldDNSServers = SCDynamicStoreCopyValue(ds, (CFStringRef)CFArrayGetValueAtIndex(list, i));
- dnsServersChanged = !CFEqual(oldDNSServers,dict);
- }
- if (dnsServersChanged) {
- bool ret = TRUE;
- if (j <= 0) {
- ret &= SCDynamicStoreAddValue(ds, key, dict);
- } else {
- ret &= SCDynamicStoreSetValue(ds, (CFStringRef)CFArrayGetValueAtIndex(list, i), dict);
- }
- if (!ret) {
- fprintf(stderr, "Error writing DNS configuration\n");
- }
- }
- if (oldDNSServers != NULL) {
- CFRelease(oldDNSServers);
- }
- CFRelease(list);
- CFRelease(key);
- CFRelease(dict);
- CFRelease(domainArray);
- CFRelease(cfdomain);
- CFRelease(serverArray);
- for (int i = 0; i < servers.size(); ++i) {
- CFRelease(s[i]);
- }
- delete[] s;
- CFRelease(ds);
- }
- void MacDNSHelper::removeDNS(uint64_t nwid)
- {
- SCDynamicStoreRef ds = SCDynamicStoreCreate(NULL, CFSTR("zerotier"), NULL, NULL);
- char buf[256] = {0};
- sprintf(buf, "State:/Network/Service/%.16llx/DNS", nwid);
- CFStringRef key = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
- SCDynamicStoreRemoveValue(ds, key);
- CFRelease(key);
- 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;
- }
- }
|