#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCValidation.h>
#include <SystemConfiguration/SCPrivate.h>
CFStringRef
SCDynamicStoreKeyCreateComputerName(CFAllocatorRef allocator)
{
return SCDynamicStoreKeyCreate(allocator,
CFSTR("%@/%@"),
kSCDynamicStoreDomainSetup,
kSCCompSystem);
}
CFStringRef
SCDynamicStoreCopyComputerName(SCDynamicStoreRef store,
CFStringEncoding *nameEncoding)
{
CFDictionaryRef dict = NULL;
CFStringRef key;
CFStringRef name = NULL;
Boolean tempSession = FALSE;
if (!store) {
store = SCDynamicStoreCreate(NULL,
CFSTR("SCDynamicStoreCopyComputerName"),
NULL,
NULL);
if (!store) {
SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
return NULL;
}
tempSession = TRUE;
}
key = SCDynamicStoreKeyCreateComputerName(NULL);
dict = SCDynamicStoreCopyValue(store, key);
CFRelease(key);
if (!dict) {
goto done;
}
if (!isA_CFDictionary(dict)) {
_SCErrorSet(kSCStatusNoKey);
goto done;
}
name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemComputerName));
if (!name) {
_SCErrorSet(kSCStatusNoKey);
goto done;
}
CFRetain(name);
if (nameEncoding) {
CFNumberRef num;
num = CFDictionaryGetValue(dict,
kSCPropSystemComputerNameEncoding);
if (isA_CFNumber(num)) {
CFNumberGetValue(num, kCFNumberIntType, nameEncoding);
} else {
*nameEncoding = CFStringGetSystemEncoding();
}
}
done :
if (tempSession) CFRelease(store);
if (dict) CFRelease(dict);
return name;
}
Boolean
SCPreferencesSetComputerName(SCPreferencesRef session,
CFStringRef name,
CFStringEncoding encoding)
{
CFDictionaryRef dict;
CFMutableDictionaryRef newDict = NULL;
CFNumberRef num;
Boolean ok = FALSE;
CFStringRef path = NULL;
if (!isA_CFString(name)) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
path = CFStringCreateWithFormat(NULL,
NULL,
CFSTR("/%@/%@"),
kSCPrefSystem,
kSCCompSystem);
dict = SCPreferencesPathGetValue(session, path);
if (dict) {
newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
} else {
newDict = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
CFDictionarySetValue(newDict, kSCPropSystemComputerName, name);
num = CFNumberCreate(NULL, kCFNumberIntType, &encoding);
CFDictionarySetValue(newDict, kSCPropSystemComputerNameEncoding, num);
CFRelease(num);
ok = SCPreferencesPathSetValue(session, path, newDict);
if (!ok) {
SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesPathSetValue() failed"));
}
if (path) CFRelease(path);
if (newDict) CFRelease(newDict);
return ok;
}
CFStringRef
SCDynamicStoreKeyCreateHostNames(CFAllocatorRef allocator)
{
return SCDynamicStoreKeyCreate(allocator,
CFSTR("%@/%@/%@"),
kSCDynamicStoreDomainSetup,
kSCCompNetwork,
kSCCompHostNames);
}
CFStringRef
SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
{
CFDictionaryRef dict = NULL;
CFStringRef key;
CFStringRef name = NULL;
Boolean tempSession = FALSE;
if (!store) {
store = SCDynamicStoreCreate(NULL,
CFSTR("SCDynamicStoreCopyLocalHostName"),
NULL,
NULL);
if (!store) {
SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
return NULL;
}
tempSession = TRUE;
}
key = SCDynamicStoreKeyCreateHostNames(NULL);
dict = SCDynamicStoreCopyValue(store, key);
CFRelease(key);
if (!dict) {
goto done;
}
if (!isA_CFDictionary(dict)) {
_SCErrorSet(kSCStatusNoKey);
goto done;
}
name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetLocalHostName));
if (!name) {
_SCErrorSet(kSCStatusNoKey);
goto done;
}
CFRetain(name);
done :
if (tempSession) CFRelease(store);
if (dict) CFRelease(dict);
return name;
}
Boolean
_SC_stringIsValidDNSName(const char *name)
{
int i;
int len = strlen(name);
char prev = '\0';
const char *scan;
if (len == 0) {
return FALSE;
}
for (scan = name, i = 0; i < len; i++, scan++) {
char ch = *scan;
char next = *(scan + 1);
if (prev == '.' || prev == '\0') {
if (isalnum(ch) == 0) {
return FALSE;
}
} else if (next == '\0' || next == '.') {
if (isalnum(ch) == 0) {
return FALSE;
}
} else if (isalnum(ch) == 0) {
switch (ch) {
case '.':
case '-':
if (prev == '.' || prev == '-') {
return FALSE;
}
break;
default:
return FALSE;
break;
}
}
prev = ch;
}
return TRUE;
}
Boolean
_SC_CFStringIsValidDNSName(CFStringRef name)
{
Boolean clean = FALSE;
char *str = NULL;
if (!isA_CFString(name)) {
return FALSE;
}
str = _SC_cfstring_to_cstring(name, NULL, 0, kCFStringEncodingASCII);
if (str == NULL) {
return FALSE;
}
clean = _SC_stringIsValidDNSName(str);
if (str) CFAllocatorDeallocate(NULL, str);
return clean;
}
Boolean
SCPreferencesSetLocalHostName(SCPreferencesRef session,
CFStringRef name)
{
CFDictionaryRef dict;
CFMutableDictionaryRef newDict = NULL;
Boolean ok = FALSE;
CFStringRef path = NULL;
if (name) {
CFIndex len;
if (!isA_CFString(name)) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
len = CFStringGetLength(name);
if (len > 0) {
if (!_SC_CFStringIsValidDNSName(name)) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
if (CFStringFindWithOptions(name, CFSTR("."), CFRangeMake(0, len), 0, NULL)) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
} else {
name = NULL;
}
}
path = CFStringCreateWithFormat(NULL,
NULL,
CFSTR("/%@/%@/%@"),
kSCPrefSystem,
kSCCompNetwork,
kSCCompHostNames);
dict = SCPreferencesPathGetValue(session, path);
if (dict) {
newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
} else {
newDict = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if (name) {
CFDictionarySetValue(newDict, kSCPropNetLocalHostName, name);
} else {
CFDictionaryRemoveValue(newDict, kSCPropNetLocalHostName);
}
if (CFDictionaryGetCount(newDict) > 0) {
ok = SCPreferencesPathSetValue(session, path, newDict);
if (!ok) {
SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesPathSetValue() failed"));
}
} else {
ok = SCPreferencesPathRemoveValue(session, path);
if (!ok) {
SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesPathRemoveValue() failed"));
}
}
if (path) CFRelease(path);
if (newDict) CFRelease(newDict);
return ok;
}