]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCDHostName.c
configd-212.2.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 case '-':
486 if (prev == '.' || prev == '-') {
487 /* a label cannot begin or end with a hyphen */
488 return FALSE;
489 }
490 break;
491 default:
492 /* an invalid character */
493 return FALSE;
494 break;
495 }
496 }
497 prev = ch;
498 }
499
500 return TRUE;
501 }
502
503
504 Boolean
505 _SC_CFStringIsValidDNSName(CFStringRef name)
506 {
507 Boolean clean = FALSE;
508 char *str = NULL;
509
510 if (!isA_CFString(name)) {
511 return FALSE;
512 }
513
514 str = _SC_cfstring_to_cstring(name, NULL, 0, kCFStringEncodingASCII);
515 if (str == NULL) {
516 return FALSE;
517 }
518
519 clean = _SC_stringIsValidDNSName(str);
520
521 if (str != NULL) CFAllocatorDeallocate(NULL, str);
522 return clean;
523 }
524
525
526 Boolean
527 SCPreferencesSetLocalHostName(SCPreferencesRef prefs,
528 CFStringRef name)
529 {
530 CFDictionaryRef dict;
531 CFMutableDictionaryRef newDict;
532 Boolean ok;
533 CFStringRef path;
534
535 if (name != NULL) {
536 CFIndex len;
537
538 if (!isA_CFString(name)) {
539 _SCErrorSet(kSCStatusInvalidArgument);
540 return FALSE;
541 }
542
543 len = CFStringGetLength(name);
544 if (len > 0) {
545 if (!_SC_CFStringIsValidDNSName(name)) {
546 _SCErrorSet(kSCStatusInvalidArgument);
547 return FALSE;
548 }
549
550 if (CFStringFindWithOptions(name, CFSTR("."), CFRangeMake(0, len), 0, NULL)) {
551 _SCErrorSet(kSCStatusInvalidArgument);
552 return FALSE;
553 }
554 } else {
555 name = NULL;
556 }
557 }
558
559 path = CFStringCreateWithFormat(NULL,
560 NULL,
561 CFSTR("/%@/%@/%@"),
562 kSCPrefSystem,
563 kSCCompNetwork,
564 kSCCompHostNames);
565
566 dict = SCPreferencesPathGetValue(prefs, path);
567 if (dict != NULL) {
568 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
569 } else {
570 newDict = CFDictionaryCreateMutable(NULL,
571 0,
572 &kCFTypeDictionaryKeyCallBacks,
573 &kCFTypeDictionaryValueCallBacks);
574 }
575
576 if (name != NULL) {
577 CFDictionarySetValue(newDict, kSCPropNetLocalHostName, name);
578 } else {
579 CFDictionaryRemoveValue(newDict, kSCPropNetLocalHostName);
580 }
581
582 if (CFDictionaryGetCount(newDict) > 0) {
583 ok = SCPreferencesPathSetValue(prefs, path, newDict);
584 } else {
585 ok = SCPreferencesPathRemoveValue(prefs, path);
586 }
587
588 CFRelease(path);
589 CFRelease(newDict);
590
591 return ok;
592 }
593
594
595 Boolean
596 _SC_CFStringIsValidNetBIOSName(CFStringRef name)
597 {
598 if (!isA_CFString(name)) {
599 return FALSE;
600 }
601
602 if (CFStringGetLength(name) > 15) {
603 return FALSE;
604 }
605
606 return TRUE;
607 }