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