]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCDHostName.c
3a96c629b82fc51351aefef7993f3d84f2e24674
[apple/configd.git] / SystemConfiguration.fproj / SCDHostName.c
1 /*
2 * Copyright (c) 2000-2007 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 CFStringRef
46 SCDynamicStoreKeyCreateComputerName(CFAllocatorRef allocator)
47 {
48 return SCDynamicStoreKeyCreate(allocator,
49 CFSTR("%@/%@"),
50 kSCDynamicStoreDomainSetup,
51 kSCCompSystem);
52 }
53
54
55 CFStringRef
56 SCDynamicStoreCopyComputerName(SCDynamicStoreRef store,
57 CFStringEncoding *nameEncoding)
58 {
59 CFDictionaryRef dict;
60 CFStringRef key;
61 CFStringRef name = NULL;
62 Boolean tempSession = FALSE;
63
64 if (store == NULL) {
65 store = SCDynamicStoreCreate(NULL,
66 CFSTR("SCDynamicStoreCopyComputerName"),
67 NULL,
68 NULL);
69 if (store == NULL) {
70 return NULL;
71 }
72 tempSession = TRUE;
73 }
74
75 key = SCDynamicStoreKeyCreateComputerName(NULL);
76 dict = SCDynamicStoreCopyValue(store, key);
77 CFRelease(key);
78 if (dict == NULL) {
79 goto done;
80 }
81 if (!isA_CFDictionary(dict)) {
82 _SCErrorSet(kSCStatusNoKey);
83 goto done;
84 }
85
86 name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemComputerName));
87 if (name == NULL) {
88 _SCErrorSet(kSCStatusNoKey);
89 goto done;
90 }
91 CFRetain(name);
92
93 if (nameEncoding != NULL) {
94 CFNumberRef num;
95
96 num = CFDictionaryGetValue(dict,
97 kSCPropSystemComputerNameEncoding);
98 if (isA_CFNumber(num)) {
99 CFNumberGetValue(num, kCFNumberIntType, nameEncoding);
100 } else {
101 *nameEncoding = CFStringGetSystemEncoding();
102 }
103 }
104
105 done :
106
107 if (tempSession) CFRelease(store);
108 if (dict != NULL) CFRelease(dict);
109 return name;
110 }
111
112
113 Boolean
114 SCPreferencesSetComputerName(SCPreferencesRef prefs,
115 CFStringRef name,
116 CFStringEncoding encoding)
117 {
118 CFDictionaryRef dict;
119 CFMutableDictionaryRef newDict;
120 CFNumberRef num;
121 Boolean ok;
122 CFStringRef path;
123
124 if (!isA_CFString(name)) {
125 _SCErrorSet(kSCStatusInvalidArgument);
126 return FALSE;
127 }
128
129 path = CFStringCreateWithFormat(NULL,
130 NULL,
131 CFSTR("/%@/%@"),
132 kSCPrefSystem,
133 kSCCompSystem);
134
135 dict = SCPreferencesPathGetValue(prefs, path);
136 if (dict != NULL) {
137 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
138 } else {
139 newDict = CFDictionaryCreateMutable(NULL,
140 0,
141 &kCFTypeDictionaryKeyCallBacks,
142 &kCFTypeDictionaryValueCallBacks);
143 }
144
145 CFDictionarySetValue(newDict, kSCPropSystemComputerName, name);
146
147 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &encoding);
148 CFDictionarySetValue(newDict, kSCPropSystemComputerNameEncoding, num);
149 CFRelease(num);
150
151 CFDictionaryRemoveValue(newDict, kSCPropSystemComputerNameRegion);
152 if (encoding == kCFStringEncodingMacRoman) {
153 UInt32 userEncoding = 0;
154 UInt32 userRegion = 0;
155
156 __CFStringGetUserDefaultEncoding(&userEncoding, &userRegion);
157 if ((userEncoding == kCFStringEncodingMacRoman) && (userRegion != 0)) {
158 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &userRegion);
159 CFDictionarySetValue(newDict, kSCPropSystemComputerNameRegion, num);
160 CFRelease(num);
161 }
162 }
163
164 ok = SCPreferencesPathSetValue(prefs, path, newDict);
165
166 CFRelease(path);
167 CFRelease(newDict);
168
169 return ok;
170 }
171
172
173 #pragma mark -
174 #pragma mark HostName
175
176
177 CFStringRef
178 SCPreferencesGetHostName(SCPreferencesRef prefs)
179 {
180 CFDictionaryRef dict;
181 CFStringRef name;
182 CFStringRef path;
183
184 path = CFStringCreateWithFormat(NULL,
185 NULL,
186 CFSTR("/%@/%@"),
187 kSCPrefSystem,
188 kSCCompSystem);
189 dict = SCPreferencesPathGetValue(prefs, path);
190 CFRelease(path);
191
192 if (!isA_CFDictionary(dict)) {
193 _SCErrorSet(kSCStatusNoKey);
194 return NULL;
195 }
196
197 name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemHostName));
198 if (name == NULL) {
199 _SCErrorSet(kSCStatusNoKey);
200 return NULL;
201 }
202
203 return name;
204 }
205
206
207 Boolean
208 SCPreferencesSetHostName(SCPreferencesRef prefs,
209 CFStringRef name)
210 {
211 CFDictionaryRef dict;
212 CFMutableDictionaryRef newDict;
213 Boolean ok;
214 CFStringRef path;
215
216 if (name != NULL) {
217 CFIndex len;
218
219 if (!isA_CFString(name)) {
220 _SCErrorSet(kSCStatusInvalidArgument);
221 return FALSE;
222 }
223
224 len = CFStringGetLength(name);
225 if (len == 0) {
226 name = NULL;
227 }
228 }
229
230 path = CFStringCreateWithFormat(NULL,
231 NULL,
232 CFSTR("/%@/%@"),
233 kSCPrefSystem,
234 kSCCompSystem);
235
236 dict = SCPreferencesPathGetValue(prefs, path);
237 if (dict != NULL) {
238 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
239 } else {
240 newDict = CFDictionaryCreateMutable(NULL,
241 0,
242 &kCFTypeDictionaryKeyCallBacks,
243 &kCFTypeDictionaryValueCallBacks);
244 }
245
246 if (name != NULL) {
247 CFDictionarySetValue(newDict, kSCPropSystemHostName, name);
248 } else {
249 CFDictionaryRemoveValue(newDict, kSCPropSystemHostName);
250 }
251
252 if (CFDictionaryGetCount(newDict) > 0) {
253 ok = SCPreferencesPathSetValue(prefs, path, newDict);
254 } else {
255 ok = SCPreferencesPathRemoveValue(prefs, path);
256 }
257
258 CFRelease(path);
259 CFRelease(newDict);
260
261 return ok;
262 }
263
264
265 #pragma mark -
266 #pragma mark LocalHostName
267
268
269 CFStringRef
270 SCDynamicStoreKeyCreateHostNames(CFAllocatorRef allocator)
271 {
272 return SCDynamicStoreKeyCreate(allocator,
273 CFSTR("%@/%@/%@"),
274 kSCDynamicStoreDomainSetup,
275 kSCCompNetwork,
276 kSCCompHostNames);
277 }
278
279
280 CFStringRef
281 SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
282 {
283 CFDictionaryRef dict;
284 CFStringRef key;
285 CFStringRef name = NULL;
286 Boolean tempSession = FALSE;
287
288 if (store == NULL) {
289 store = SCDynamicStoreCreate(NULL,
290 CFSTR("SCDynamicStoreCopyLocalHostName"),
291 NULL,
292 NULL);
293 if (store == NULL) {
294 return NULL;
295 }
296 tempSession = TRUE;
297 }
298
299 key = SCDynamicStoreKeyCreateHostNames(NULL);
300 dict = SCDynamicStoreCopyValue(store, key);
301 CFRelease(key);
302 if (dict == NULL) {
303 goto done;
304 }
305 if (!isA_CFDictionary(dict)) {
306 _SCErrorSet(kSCStatusNoKey);
307 goto done;
308 }
309
310 name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetLocalHostName));
311 if (name == NULL) {
312 _SCErrorSet(kSCStatusNoKey);
313 goto done;
314 }
315 CFRetain(name);
316
317 done :
318
319 if (tempSession) CFRelease(store);
320 if (dict != NULL) CFRelease(dict);
321 return name;
322 }
323
324
325 Boolean
326 _SC_stringIsValidDNSName(const char *name)
327 {
328 int i;
329 int len = strlen(name);
330 char prev = '\0';
331 const char *scan;
332
333 if (len == 0) {
334 return FALSE;
335 }
336
337 for (scan = name, i = 0; i < len; i++, scan++) {
338 char ch = *scan;
339 char next = *(scan + 1);
340
341 if (prev == '.' || prev == '\0') {
342 if (isalnum(ch) == 0) {
343 /* a label must begin with a letter or digit */
344 return FALSE;
345 }
346 } else if (next == '\0' || next == '.') {
347 if (isalnum(ch) == 0) {
348 /* a label must end with a letter or digit */
349 return FALSE;
350 }
351 } else if (isalnum(ch) == 0) {
352 switch (ch) {
353 case '.':
354 case '-':
355 if (prev == '.' || prev == '-') {
356 /* a label cannot begin or end with a hyphen */
357 return FALSE;
358 }
359 break;
360 default:
361 /* an invalid character */
362 return FALSE;
363 break;
364 }
365 }
366 prev = ch;
367 }
368
369 return TRUE;
370 }
371
372
373 Boolean
374 _SC_CFStringIsValidDNSName(CFStringRef name)
375 {
376 Boolean clean = FALSE;
377 char *str = NULL;
378
379 if (!isA_CFString(name)) {
380 return FALSE;
381 }
382
383 str = _SC_cfstring_to_cstring(name, NULL, 0, kCFStringEncodingASCII);
384 if (str == NULL) {
385 return FALSE;
386 }
387
388 clean = _SC_stringIsValidDNSName(str);
389
390 if (str != NULL) CFAllocatorDeallocate(NULL, str);
391 return clean;
392 }
393
394
395 Boolean
396 SCPreferencesSetLocalHostName(SCPreferencesRef prefs,
397 CFStringRef name)
398 {
399 CFDictionaryRef dict;
400 CFMutableDictionaryRef newDict;
401 Boolean ok;
402 CFStringRef path;
403
404 if (name != NULL) {
405 CFIndex len;
406
407 if (!isA_CFString(name)) {
408 _SCErrorSet(kSCStatusInvalidArgument);
409 return FALSE;
410 }
411
412 len = CFStringGetLength(name);
413 if (len > 0) {
414 if (!_SC_CFStringIsValidDNSName(name)) {
415 _SCErrorSet(kSCStatusInvalidArgument);
416 return FALSE;
417 }
418
419 if (CFStringFindWithOptions(name, CFSTR("."), CFRangeMake(0, len), 0, NULL)) {
420 _SCErrorSet(kSCStatusInvalidArgument);
421 return FALSE;
422 }
423 } else {
424 name = NULL;
425 }
426 }
427
428 path = CFStringCreateWithFormat(NULL,
429 NULL,
430 CFSTR("/%@/%@/%@"),
431 kSCPrefSystem,
432 kSCCompNetwork,
433 kSCCompHostNames);
434
435 dict = SCPreferencesPathGetValue(prefs, path);
436 if (dict != NULL) {
437 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
438 } else {
439 newDict = CFDictionaryCreateMutable(NULL,
440 0,
441 &kCFTypeDictionaryKeyCallBacks,
442 &kCFTypeDictionaryValueCallBacks);
443 }
444
445 if (name != NULL) {
446 CFDictionarySetValue(newDict, kSCPropNetLocalHostName, name);
447 } else {
448 CFDictionaryRemoveValue(newDict, kSCPropNetLocalHostName);
449 }
450
451 if (CFDictionaryGetCount(newDict) > 0) {
452 ok = SCPreferencesPathSetValue(prefs, path, newDict);
453 } else {
454 ok = SCPreferencesPathRemoveValue(prefs, path);
455 }
456
457 CFRelease(path);
458 CFRelease(newDict);
459
460 return ok;
461 }
462
463
464 Boolean
465 _SC_CFStringIsValidNetBIOSName(CFStringRef name)
466 {
467 if (!isA_CFString(name)) {
468 return FALSE;
469 }
470
471 if (CFStringGetLength(name) > 15) {
472 return FALSE;
473 }
474
475 return TRUE;
476 }