]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCDHostName.c
configd-802.40.13.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCDHostName.c
1 /*
2 * Copyright (c) 2000-2008, 2011, 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
29 *
30 * January 8, 2001 Allan Nathanson <ajn@apple.com>
31 * - initial revision
32 */
33
34
35 #include <CoreFoundation/CoreFoundation.h>
36 #include <CoreFoundation/CFStringDefaultEncoding.h> // for __CFStringGetUserDefaultEncoding
37 #include <SystemConfiguration/SystemConfiguration.h>
38 #include <SystemConfiguration/SCValidation.h>
39 #include <SystemConfiguration/SCPrivate.h>
40 #include "dy_framework.h"
41
42
43 #pragma mark ComputerName
44
45
46 CFStringRef
47 _SCPreferencesCopyComputerName(SCPreferencesRef prefs,
48 CFStringEncoding *nameEncoding)
49 {
50 CFDictionaryRef dict;
51 CFStringRef name = NULL;
52 CFStringRef path;
53 Boolean tempPrefs = FALSE;
54
55 if (prefs == NULL) {
56 prefs = SCPreferencesCreate(NULL, CFSTR("_SCPreferencesCopyComputerName"), NULL);
57 if (prefs == NULL) {
58 return NULL;
59 }
60 tempPrefs = TRUE;
61 }
62
63 path = CFStringCreateWithFormat(NULL,
64 NULL,
65 CFSTR("/%@/%@"),
66 kSCPrefSystem,
67 kSCCompSystem);
68 dict = SCPreferencesPathGetValue(prefs, path);
69 CFRelease(path);
70
71 if (dict != NULL) {
72 if (isA_CFDictionary(dict)) {
73 name = CFDictionaryGetValue(dict, kSCPropSystemComputerName);
74 name = isA_CFString(name);
75 if (name != NULL) {
76 CFRetain(name);
77 }
78 }
79
80 if (nameEncoding != NULL) {
81 CFNumberRef num;
82
83 num = CFDictionaryGetValue(dict,
84 kSCPropSystemComputerNameEncoding);
85 if (isA_CFNumber(num)) {
86 CFNumberGetValue(num, kCFNumberIntType, nameEncoding);
87 } else {
88 *nameEncoding = CFStringGetSystemEncoding();
89 }
90 }
91 }
92
93 if (tempPrefs) CFRelease(prefs);
94 _SCErrorSet(name != NULL ? kSCStatusOK : kSCStatusNoKey);
95 return name;
96 }
97
98
99 CFStringRef
100 SCDynamicStoreKeyCreateComputerName(CFAllocatorRef allocator)
101 {
102 return SCDynamicStoreKeyCreate(allocator,
103 CFSTR("%@/%@"),
104 kSCDynamicStoreDomainSetup,
105 kSCCompSystem);
106 }
107
108
109 CFStringRef
110 SCDynamicStoreCopyComputerName(SCDynamicStoreRef store,
111 CFStringEncoding *nameEncoding)
112 {
113 CFDictionaryRef dict = NULL;
114 CFStringRef key;
115 CFStringRef name = NULL;
116
117 key = SCDynamicStoreKeyCreateComputerName(NULL);
118 dict = SCDynamicStoreCopyValue(store, key);
119 CFRelease(key);
120 if (dict == NULL) {
121 /*
122 * Let's try looking in the preferences.plist file until
123 * (a) we add an API to retrieve the name regardless of
124 * where it is stored and
125 * (b) this API is deprecated
126 */
127 name = _SCPreferencesCopyComputerName(NULL, nameEncoding);
128 goto done;
129 }
130 if (!isA_CFDictionary(dict)) {
131 _SCErrorSet(kSCStatusNoKey);
132 goto done;
133 }
134
135 name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemComputerName));
136 if (name == NULL) {
137 _SCErrorSet(kSCStatusNoKey);
138 goto done;
139 }
140 CFRetain(name);
141
142 if (nameEncoding != NULL) {
143 CFNumberRef num;
144
145 num = CFDictionaryGetValue(dict,
146 kSCPropSystemComputerNameEncoding);
147 if (isA_CFNumber(num)) {
148 CFNumberGetValue(num, kCFNumberIntType, nameEncoding);
149 } else {
150 *nameEncoding = CFStringGetSystemEncoding();
151 }
152 }
153
154 _SCErrorSet(kSCStatusOK);
155
156 done :
157
158
159 if (dict != NULL) CFRelease(dict);
160 return name;
161 }
162
163
164 Boolean
165 SCPreferencesSetComputerName(SCPreferencesRef prefs,
166 CFStringRef name,
167 CFStringEncoding encoding)
168 {
169 CFDictionaryRef dict;
170 CFMutableDictionaryRef newDict;
171 CFNumberRef num;
172 Boolean ok;
173 CFStringRef path;
174
175 if (name != NULL) {
176 CFIndex len;
177
178 if (!isA_CFString(name)) {
179 _SCErrorSet(kSCStatusInvalidArgument);
180 return FALSE;
181 }
182
183 len = CFStringGetLength(name);
184 if (len == 0) {
185 name = NULL;
186 }
187 }
188
189 path = CFStringCreateWithFormat(NULL,
190 NULL,
191 CFSTR("/%@/%@"),
192 kSCPrefSystem,
193 kSCCompSystem);
194
195 dict = SCPreferencesPathGetValue(prefs, path);
196 if (dict != NULL) {
197 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
198 } else {
199 newDict = CFDictionaryCreateMutable(NULL,
200 0,
201 &kCFTypeDictionaryKeyCallBacks,
202 &kCFTypeDictionaryValueCallBacks);
203 }
204
205 if ((name != NULL) && (CFStringGetLength(name) > 0)) {
206 CFDictionarySetValue(newDict, kSCPropSystemComputerName, name);
207
208 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &encoding);
209 CFDictionarySetValue(newDict, kSCPropSystemComputerNameEncoding, num);
210 CFRelease(num);
211
212 CFDictionaryRemoveValue(newDict, kSCPropSystemComputerNameRegion);
213 if (encoding == kCFStringEncodingMacRoman) {
214 UInt32 userEncoding = 0;
215 UInt32 userRegion = 0;
216
217 __CFStringGetUserDefaultEncoding(&userEncoding, &userRegion);
218 if ((userEncoding == kCFStringEncodingMacRoman) && (userRegion != 0)) {
219 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &userRegion);
220 CFDictionarySetValue(newDict, kSCPropSystemComputerNameRegion, num);
221 CFRelease(num);
222 }
223 }
224 } else {
225 CFDictionaryRemoveValue(newDict, kSCPropSystemComputerName);
226 CFDictionaryRemoveValue(newDict, kSCPropSystemComputerNameEncoding);
227 CFDictionaryRemoveValue(newDict, kSCPropSystemComputerNameRegion);
228 }
229
230 if (CFDictionaryGetCount(newDict) > 0) {
231 ok = SCPreferencesPathSetValue(prefs, path, newDict);
232 } else {
233 ok = SCPreferencesPathRemoveValue(prefs, path);
234 }
235
236 if (ok) {
237 if (name != NULL) {
238 SC_log(LOG_NOTICE, "attempting to set the computer name to \"%@\"", name);
239 } else {
240 SC_log(LOG_NOTICE, "attempting to reset the computer name");
241 }
242 }
243
244 CFRelease(path);
245 CFRelease(newDict);
246
247 return ok;
248 }
249
250
251 #pragma mark -
252 #pragma mark HostName
253
254
255 CFStringRef
256 SCPreferencesGetHostName(SCPreferencesRef prefs)
257 {
258 CFDictionaryRef dict;
259 CFStringRef name;
260 CFStringRef path;
261
262 path = CFStringCreateWithFormat(NULL,
263 NULL,
264 CFSTR("/%@/%@"),
265 kSCPrefSystem,
266 kSCCompSystem);
267 dict = SCPreferencesPathGetValue(prefs, path);
268 CFRelease(path);
269
270 if (!isA_CFDictionary(dict)) {
271 _SCErrorSet(kSCStatusNoKey);
272 return NULL;
273 }
274
275 name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemHostName));
276 if (name == NULL) {
277 _SCErrorSet(kSCStatusNoKey);
278 return NULL;
279 }
280
281 return name;
282 }
283
284
285 Boolean
286 SCPreferencesSetHostName(SCPreferencesRef prefs,
287 CFStringRef name)
288 {
289 CFDictionaryRef dict;
290 CFMutableDictionaryRef newDict;
291 Boolean ok;
292 CFStringRef path;
293
294 if (name != NULL) {
295 CFIndex len;
296
297 if (!isA_CFString(name)) {
298 _SCErrorSet(kSCStatusInvalidArgument);
299 return FALSE;
300 }
301
302 len = CFStringGetLength(name);
303 if (len == 0) {
304 name = NULL;
305 }
306 }
307
308 path = CFStringCreateWithFormat(NULL,
309 NULL,
310 CFSTR("/%@/%@"),
311 kSCPrefSystem,
312 kSCCompSystem);
313
314 dict = SCPreferencesPathGetValue(prefs, path);
315 if (dict != NULL) {
316 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
317 } else {
318 newDict = CFDictionaryCreateMutable(NULL,
319 0,
320 &kCFTypeDictionaryKeyCallBacks,
321 &kCFTypeDictionaryValueCallBacks);
322 }
323
324 if (name != NULL) {
325 CFDictionarySetValue(newDict, kSCPropSystemHostName, name);
326 } else {
327 CFDictionaryRemoveValue(newDict, kSCPropSystemHostName);
328 }
329
330 if (CFDictionaryGetCount(newDict) > 0) {
331 ok = SCPreferencesPathSetValue(prefs, path, newDict);
332 } else {
333 ok = SCPreferencesPathRemoveValue(prefs, path);
334 }
335
336 if (ok) {
337 if (name != NULL) {
338 SC_log(LOG_NOTICE, "attempting to set the host name to \"%@\"", name);
339 } else {
340 SC_log(LOG_NOTICE, "attempting to reset the host name");
341 }
342 }
343
344 CFRelease(path);
345 CFRelease(newDict);
346
347 return ok;
348 }
349
350
351 #pragma mark -
352 #pragma mark LocalHostName
353
354
355 __private_extern__ CFStringRef
356 _SCPreferencesCopyLocalHostName(SCPreferencesRef prefs)
357 {
358 CFDictionaryRef dict;
359 CFStringRef name = NULL;
360 CFStringRef path;
361 Boolean tempPrefs = FALSE;
362
363 if (prefs == NULL) {
364 prefs = SCPreferencesCreate(NULL, CFSTR("_SCPreferencesCopyLocalHostName"), NULL);
365 if (prefs == NULL) {
366 return NULL;
367 }
368 tempPrefs = TRUE;
369 }
370
371 path = CFStringCreateWithFormat(NULL,
372 NULL,
373 CFSTR("/%@/%@/%@"),
374 kSCPrefSystem,
375 kSCCompNetwork,
376 kSCCompHostNames);
377 dict = SCPreferencesPathGetValue(prefs, path);
378 CFRelease(path);
379
380 if (dict != NULL) {
381 if (isA_CFDictionary(dict)) {
382 name = CFDictionaryGetValue(dict, kSCPropNetLocalHostName);
383 name = isA_CFString(name);
384 if (name != NULL) {
385 CFRetain(name);
386 }
387 }
388 }
389
390 if (tempPrefs) CFRelease(prefs);
391 _SCErrorSet(name != NULL ? kSCStatusOK : kSCStatusNoKey);
392 return name;
393 }
394
395
396 CFStringRef
397 SCDynamicStoreKeyCreateHostNames(CFAllocatorRef allocator)
398 {
399 return SCDynamicStoreKeyCreate(allocator,
400 CFSTR("%@/%@/%@"),
401 kSCDynamicStoreDomainSetup,
402 kSCCompNetwork,
403 kSCCompHostNames);
404 }
405
406
407 CFStringRef
408 SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
409 {
410 CFDictionaryRef dict = NULL;
411 CFStringRef key;
412 CFStringRef name = NULL;
413
414 key = SCDynamicStoreKeyCreateHostNames(NULL);
415 dict = SCDynamicStoreCopyValue(store, key);
416 CFRelease(key);
417 if (dict == NULL) {
418 /*
419 * Let's try looking in the preferences.plist file until
420 * (a) we add an API to retrieve the name regardless of
421 * where it is stored and
422 * (b) this API is deprecated
423 */
424 name = _SCPreferencesCopyLocalHostName(NULL);
425 goto done;
426 }
427 if (!isA_CFDictionary(dict)) {
428 _SCErrorSet(kSCStatusNoKey);
429 goto done;
430 }
431
432 name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetLocalHostName));
433 if (name == NULL) {
434 _SCErrorSet(kSCStatusNoKey);
435 goto done;
436 }
437 CFRetain(name);
438
439 _SCErrorSet(kSCStatusOK);
440
441 done :
442
443
444 if (dict != NULL) CFRelease(dict);
445 return name;
446 }
447
448
449 Boolean
450 _SC_stringIsValidDNSName(const char *name)
451 {
452 int i;
453 size_t len = strlen(name);
454 char prev = '\0';
455 const char *scan;
456
457 if (len == 0) {
458 return FALSE;
459 }
460
461 for (scan = name, i = 0; i < len; i++, scan++) {
462 char ch = *scan;
463 char next = *(scan + 1);
464
465 if (prev == '.' || prev == '\0') {
466 if (isalnum(ch) == 0) {
467 /* a label must begin with a letter or digit */
468 return FALSE;
469 }
470 } else if (next == '\0' || next == '.') {
471 if (isalnum(ch) == 0) {
472 /* a label must end with a letter or digit */
473 return FALSE;
474 }
475 } else if (isalnum(ch) == 0) {
476 switch (ch) {
477 case '.':
478 if (prev == '.') {
479 /* no empty labels */
480 return FALSE;
481 }
482 break;
483 case '-':
484 /* hyphens are OK within a label */
485 break;
486 default:
487 /* an invalid character */
488 return FALSE;
489 break;
490 }
491 }
492 prev = ch;
493 }
494
495 return TRUE;
496 }
497
498
499 Boolean
500 _SC_CFStringIsValidDNSName(CFStringRef name)
501 {
502 Boolean clean = FALSE;
503 char *str = NULL;
504
505 if (!isA_CFString(name)) {
506 return FALSE;
507 }
508
509 str = _SC_cfstring_to_cstring(name, NULL, 0, kCFStringEncodingASCII);
510 if (str == NULL) {
511 return FALSE;
512 }
513
514 clean = _SC_stringIsValidDNSName(str);
515
516 if (str != NULL) CFAllocatorDeallocate(NULL, str);
517 return clean;
518 }
519
520
521 Boolean
522 SCPreferencesSetLocalHostName(SCPreferencesRef prefs,
523 CFStringRef name)
524 {
525 CFDictionaryRef dict;
526 CFMutableDictionaryRef newDict;
527 Boolean ok;
528 CFStringRef path;
529
530 if (name != NULL) {
531 CFIndex len;
532
533 if (!isA_CFString(name)) {
534 _SCErrorSet(kSCStatusInvalidArgument);
535 return FALSE;
536 }
537
538 len = CFStringGetLength(name);
539 if (len > 0) {
540 if (!_SC_CFStringIsValidDNSName(name)) {
541 _SCErrorSet(kSCStatusInvalidArgument);
542 return FALSE;
543 }
544
545 if (CFStringFindWithOptions(name, CFSTR("."), CFRangeMake(0, len), 0, NULL)) {
546 _SCErrorSet(kSCStatusInvalidArgument);
547 return FALSE;
548 }
549 } else {
550 name = NULL;
551 }
552 }
553
554 path = CFStringCreateWithFormat(NULL,
555 NULL,
556 CFSTR("/%@/%@/%@"),
557 kSCPrefSystem,
558 kSCCompNetwork,
559 kSCCompHostNames);
560
561 dict = SCPreferencesPathGetValue(prefs, path);
562 if (dict != NULL) {
563 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
564 } else {
565 newDict = CFDictionaryCreateMutable(NULL,
566 0,
567 &kCFTypeDictionaryKeyCallBacks,
568 &kCFTypeDictionaryValueCallBacks);
569 }
570
571 if (name != NULL) {
572 CFDictionarySetValue(newDict, kSCPropNetLocalHostName, name);
573 } else {
574 CFDictionaryRemoveValue(newDict, kSCPropNetLocalHostName);
575 }
576
577 if (CFDictionaryGetCount(newDict) > 0) {
578 ok = SCPreferencesPathSetValue(prefs, path, newDict);
579 } else {
580 ok = SCPreferencesPathRemoveValue(prefs, path);
581 }
582
583 if (ok) {
584 if (name != NULL) {
585 SC_log(LOG_NOTICE, "attempting to set the local host name to \"%@\"", name);
586 } else {
587 SC_log(LOG_NOTICE, "attempting to reset the local host name");
588 }
589 }
590
591 CFRelease(path);
592 CFRelease(newDict);
593
594 return ok;
595 }
596
597
598 Boolean
599 _SC_CFStringIsValidNetBIOSName(CFStringRef name)
600 {
601 if (!isA_CFString(name)) {
602 return FALSE;
603 }
604
605 if (CFStringGetLength(name) > 15) {
606 return FALSE;
607 }
608
609 return TRUE;
610 }