1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

Tuesday, November 8, 2011

HOWTO: Change dns settings programmatically in OSX

Recently I searched high and low to find an example of changing DNS settings under OSX and was surprised to find the same question a few times, but no clues to the answer.  I did find some examples of changing the settings from the shell:

http://hints.macworld.com/article.php?story=20050621051643993
http://yourmacguy.wordpress.com/2008/08/07/networksetup-command/

If you got here searching for a solution here's mine:
#include <stdio.h>
#include <systemconfiguration/scpreferences.h>
#include <systemconfiguration/scdynamicstore.h>

int main (int argc, const char * argv[])
{
    //get current values
    SCDynamicStoreRef dynRef=SCDynamicStoreCreate(kCFAllocatorSystemDefault, CFSTR("iked"), NULL, NULL);
    CFDictionaryRef ipv4key = SCDynamicStoreCopyValue(dynRef,CFSTR("State:/Network/Global/IPv4"));
    CFStringRef primaryserviceid = CFDictionaryGetValue(ipv4key,CFSTR("PrimaryService"));
    CFStringRef primaryservicepath = CFStringCreateWithFormat(NULL,NULL,CFSTR("State:/Network/Service/%@/DNS"),primaryserviceid);
    CFDictionaryRef dnskey = SCDynamicStoreCopyValue(dynRef,primaryservicepath);
    
    //create new values
    CFMutableDictionaryRef newdnskey = CFDictionaryCreateMutableCopy(NULL,0,dnskey);
    CFDictionarySetValue(newdnskey,CFSTR("DomainName"),CFSTR("example.com"));
    
    CFMutableArrayRef dnsserveraddresses = CFArrayCreateMutable(NULL,0,NULL);
    CFArrayAppendValue(dnsserveraddresses, CFSTR("8.8.8.8"));
    CFArrayAppendValue(dnsserveraddresses, CFSTR("4.2.2.2"));
    CFDictionarySetValue(newdnskey, CFSTR("ServerAddresses"), dnsserveraddresses);
    
    //set values
    bool success = SCDynamicStoreSetValue(dynRef, primaryservicepath, newdnskey);
    
    //clean up
    CFRelease(dynRef);
    CFRelease(primaryservicepath);
    CFRelease(dnskey);
    CFRelease(dnsserveraddresses);
    CFRelease(newdnskey);
}

Note that this does not change these settings are not persistent. There are separate calls for that, but that's not what I needed to do, so I don't have the code.