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