2 * Copyright (c) 2000-2008, 2011, 2013-2020 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
30 * January 8, 2001 Allan Nathanson <ajn@apple.com>
35 #include <CoreFoundation/CoreFoundation.h>
36 #include <CoreFoundation/CFStringDefaultEncoding.h> // for __CFStringGetUserDefaultEncoding
37 #include "SCPreferencesInternal.h"
38 #include "SCNetworkConfigurationInternal.h"
39 #include "dy_framework.h"
42 #pragma mark ComputerName
45 static CFStringEncoding
46 getNameEncoding(CFDictionaryRef dict
)
48 CFStringEncoding encoding
;
51 if (!CFDictionaryGetValueIfPresent(dict
,
52 kSCPropSystemComputerNameEncoding
,
53 (const void **)&num
) ||
55 !CFNumberGetValue(num
, kCFNumberSInt32Type
, &encoding
)) {
56 encoding
= CFStringGetSystemEncoding();
64 _SCPreferencesCopyComputerName(SCPreferencesRef prefs
,
65 CFStringEncoding
*nameEncoding
)
68 CFStringRef name
= NULL
;
70 Boolean tempPrefs
= FALSE
;
73 prefs
= SCPreferencesCreate(NULL
, CFSTR("_SCPreferencesCopyComputerName"), NULL
);
80 path
= CFStringCreateWithFormat(NULL
,
85 dict
= SCPreferencesPathGetValue(prefs
, path
);
89 if (isA_CFDictionary(dict
)) {
90 name
= CFDictionaryGetValue(dict
, kSCPropSystemComputerName
);
91 name
= isA_CFString(name
);
97 if (nameEncoding
!= NULL
) {
98 *nameEncoding
= getNameEncoding(dict
);
102 if (tempPrefs
) CFRelease(prefs
);
103 _SCErrorSet(name
!= NULL
? kSCStatusOK
: kSCStatusNoKey
);
109 SCDynamicStoreKeyCreateComputerName(CFAllocatorRef allocator
)
111 return SCDynamicStoreKeyCreate(allocator
,
113 kSCDynamicStoreDomainSetup
,
119 SCDynamicStoreCopyComputerName(SCDynamicStoreRef store
,
120 CFStringEncoding
*nameEncoding
)
122 CFDictionaryRef dict
= NULL
;
124 CFStringRef name
= NULL
;
126 key
= SCDynamicStoreKeyCreateComputerName(NULL
);
127 dict
= SCDynamicStoreCopyValue(store
, key
);
131 * Let's try looking in the preferences.plist file until
132 * (a) we add an API to retrieve the name regardless of
133 * where it is stored and
134 * (b) this API is deprecated
136 name
= _SCPreferencesCopyComputerName(NULL
, nameEncoding
);
139 if (!isA_CFDictionary(dict
)) {
140 _SCErrorSet(kSCStatusNoKey
);
144 name
= isA_CFString(CFDictionaryGetValue(dict
, kSCPropSystemComputerName
));
146 _SCErrorSet(kSCStatusNoKey
);
151 if (nameEncoding
!= NULL
) {
152 *nameEncoding
= getNameEncoding(dict
);
155 _SCErrorSet(kSCStatusOK
);
160 if (dict
!= NULL
) CFRelease(dict
);
166 SCPreferencesSetComputerName(SCPreferencesRef prefs
,
168 CFStringEncoding encoding
)
170 CFDictionaryRef dict
;
171 CFMutableDictionaryRef newDict
;
179 if (!isA_CFString(name
)) {
180 _SCErrorSet(kSCStatusInvalidArgument
);
184 len
= CFStringGetLength(name
);
190 path
= CFStringCreateWithFormat(NULL
,
196 dict
= SCPreferencesPathGetValue(prefs
, path
);
198 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
200 newDict
= CFDictionaryCreateMutable(NULL
,
202 &kCFTypeDictionaryKeyCallBacks
,
203 &kCFTypeDictionaryValueCallBacks
);
206 if ((name
!= NULL
) && (CFStringGetLength(name
) > 0)) {
207 CFDictionarySetValue(newDict
, kSCPropSystemComputerName
, name
);
209 num
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &encoding
);
210 CFDictionarySetValue(newDict
, kSCPropSystemComputerNameEncoding
, num
);
213 CFDictionaryRemoveValue(newDict
, kSCPropSystemComputerNameRegion
);
214 if (encoding
== kCFStringEncodingMacRoman
) {
215 UInt32 userEncoding
= 0;
216 UInt32 userRegion
= 0;
218 __CFStringGetUserDefaultEncoding(&userEncoding
, &userRegion
);
219 if ((userEncoding
== kCFStringEncodingMacRoman
) && (userRegion
!= 0)) {
220 num
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &userRegion
);
221 CFDictionarySetValue(newDict
, kSCPropSystemComputerNameRegion
, num
);
226 CFDictionaryRemoveValue(newDict
, kSCPropSystemComputerName
);
227 CFDictionaryRemoveValue(newDict
, kSCPropSystemComputerNameEncoding
);
228 CFDictionaryRemoveValue(newDict
, kSCPropSystemComputerNameRegion
);
231 ok
= __SCNetworkConfigurationSetValue(prefs
, path
, newDict
, FALSE
);
234 SC_log(LOG_NOTICE
, "attempting to set the computer name to \"%@\"", name
);
236 SC_log(LOG_NOTICE
, "attempting to reset the computer name");
248 #pragma mark HostName
252 SCPreferencesGetHostName(SCPreferencesRef prefs
)
254 CFDictionaryRef dict
;
258 path
= CFStringCreateWithFormat(NULL
,
263 dict
= SCPreferencesPathGetValue(prefs
, path
);
266 if (!isA_CFDictionary(dict
)) {
267 _SCErrorSet(kSCStatusNoKey
);
271 name
= isA_CFString(CFDictionaryGetValue(dict
, kSCPropSystemHostName
));
273 _SCErrorSet(kSCStatusNoKey
);
282 SCPreferencesSetHostName(SCPreferencesRef prefs
,
285 CFDictionaryRef dict
;
286 CFMutableDictionaryRef newDict
;
293 if (!isA_CFString(name
)) {
294 _SCErrorSet(kSCStatusInvalidArgument
);
298 len
= CFStringGetLength(name
);
304 path
= CFStringCreateWithFormat(NULL
,
310 dict
= SCPreferencesPathGetValue(prefs
, path
);
312 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
314 newDict
= CFDictionaryCreateMutable(NULL
,
316 &kCFTypeDictionaryKeyCallBacks
,
317 &kCFTypeDictionaryValueCallBacks
);
321 CFDictionarySetValue(newDict
, kSCPropSystemHostName
, name
);
323 CFDictionaryRemoveValue(newDict
, kSCPropSystemHostName
);
326 ok
= __SCNetworkConfigurationSetValue(prefs
, path
, newDict
, FALSE
);
329 SC_log(LOG_NOTICE
, "attempting to set the host name to \"%@\"", name
);
331 SC_log(LOG_NOTICE
, "attempting to reset the host name");
343 #pragma mark LocalHostName
347 _SCPreferencesCopyLocalHostName(SCPreferencesRef prefs
)
349 CFDictionaryRef dict
;
350 CFStringRef name
= NULL
;
352 Boolean tempPrefs
= FALSE
;
355 prefs
= SCPreferencesCreate(NULL
, CFSTR("_SCPreferencesCopyLocalHostName"), NULL
);
362 path
= CFStringCreateWithFormat(NULL
,
368 dict
= SCPreferencesPathGetValue(prefs
, path
);
372 if (isA_CFDictionary(dict
)) {
373 name
= CFDictionaryGetValue(dict
, kSCPropNetLocalHostName
);
374 name
= isA_CFString(name
);
381 if (tempPrefs
) CFRelease(prefs
);
382 _SCErrorSet(name
!= NULL
? kSCStatusOK
: kSCStatusNoKey
);
388 SCDynamicStoreKeyCreateHostNames(CFAllocatorRef allocator
)
390 return SCDynamicStoreKeyCreate(allocator
,
392 kSCDynamicStoreDomainSetup
,
399 SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store
)
401 CFDictionaryRef dict
= NULL
;
403 CFStringRef name
= NULL
;
405 key
= SCDynamicStoreKeyCreateHostNames(NULL
);
406 dict
= SCDynamicStoreCopyValue(store
, key
);
410 * Let's try looking in the preferences.plist file until
411 * (a) we add an API to retrieve the name regardless of
412 * where it is stored and
413 * (b) this API is deprecated
415 name
= _SCPreferencesCopyLocalHostName(NULL
);
418 if (!isA_CFDictionary(dict
)) {
419 _SCErrorSet(kSCStatusNoKey
);
423 name
= isA_CFString(CFDictionaryGetValue(dict
, kSCPropNetLocalHostName
));
425 _SCErrorSet(kSCStatusNoKey
);
430 _SCErrorSet(kSCStatusOK
);
435 if (dict
!= NULL
) CFRelease(dict
);
441 _SC_stringIsValidDNSName(const char *name
)
444 size_t len
= strlen(name
);
452 for (scan
= name
, i
= 0; i
< len
; i
++, scan
++) {
454 char next
= *(scan
+ 1);
456 if (prev
== '.' || prev
== '\0') {
457 if (isalnum(ch
) == 0) {
458 /* a label must begin with a letter or digit */
461 } else if (next
== '\0' || next
== '.') {
462 if (isalnum(ch
) == 0) {
463 /* a label must end with a letter or digit */
466 } else if (isalnum(ch
) == 0) {
469 /* a label separator */
472 /* hyphens are OK within a label */
475 /* an invalid character */
488 _SC_CFStringIsValidDNSName(CFStringRef name
)
490 Boolean clean
= FALSE
;
493 if (!isA_CFString(name
)) {
497 str
= _SC_cfstring_to_cstring(name
, NULL
, 0, kCFStringEncodingASCII
);
502 clean
= _SC_stringIsValidDNSName(str
);
504 if (str
!= NULL
) CFAllocatorDeallocate(NULL
, str
);
510 SCPreferencesSetLocalHostName(SCPreferencesRef prefs
,
513 CFDictionaryRef dict
;
514 CFMutableDictionaryRef newDict
;
521 if (!isA_CFString(name
)) {
522 _SCErrorSet(kSCStatusInvalidArgument
);
526 len
= CFStringGetLength(name
);
528 if (!_SC_CFStringIsValidDNSName(name
)) {
529 _SCErrorSet(kSCStatusInvalidArgument
);
533 if (CFStringFindWithOptions(name
, CFSTR("."), CFRangeMake(0, len
), 0, NULL
)) {
534 _SCErrorSet(kSCStatusInvalidArgument
);
542 path
= CFStringCreateWithFormat(NULL
,
549 dict
= SCPreferencesPathGetValue(prefs
, path
);
551 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
553 newDict
= CFDictionaryCreateMutable(NULL
,
555 &kCFTypeDictionaryKeyCallBacks
,
556 &kCFTypeDictionaryValueCallBacks
);
560 CFDictionarySetValue(newDict
, kSCPropNetLocalHostName
, name
);
562 CFDictionaryRemoveValue(newDict
, kSCPropNetLocalHostName
);
565 ok
= __SCNetworkConfigurationSetValue(prefs
, path
, newDict
, FALSE
);
568 SC_log(LOG_NOTICE
, "attempting to set the local host name to \"%@\"", name
);
570 SC_log(LOG_NOTICE
, "attempting to reset the local host name");
582 _SC_CFStringIsValidNetBIOSName(CFStringRef name
)
584 if (!isA_CFString(name
)) {
588 if (CFStringGetLength(name
) > 15) {