]> git.saurik.com Git - apple/configd.git/blob - Plugins/IPMonitor/dns-configuration.c
configd-137.2.tar.gz
[apple/configd.git] / Plugins / IPMonitor / dns-configuration.c
1 /*
2 * Copyright (c) 2004 Apple Computer, 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 * March 22, 2004 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31 #include <fcntl.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/stat.h>
38 #include <net/if.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <arpa/nameser.h>
42 #include <resolv.h>
43
44 #include <CoreFoundation/CoreFoundation.h>
45 #include <SystemConfiguration/SystemConfiguration.h>
46 #include <SystemConfiguration/SCPrivate.h>
47 #include <SystemConfiguration/SCValidation.h>
48
49 #include <dnsinfo.h>
50 #include <dnsinfo_create.h>
51
52
53 /* pre-defined (supplemental) resolver configurations */
54 static CFArrayRef S_predefined = NULL;
55
56
57 static void
58 add_supplemental(CFMutableArrayRef supplemental, CFDictionaryRef dns, uint32_t defaultOrder)
59 {
60 CFArrayRef domains;
61 CFIndex i;
62 CFIndex n_domains;
63 CFArrayRef orders;
64
65
66 domains = CFDictionaryGetValue(dns, kSCPropNetDNSSupplementalMatchDomains);
67 n_domains = isA_CFArray(domains) ? CFArrayGetCount(domains) : 0;
68 if (n_domains == 0) {
69 return;
70 }
71
72 orders = CFDictionaryGetValue(dns, kSCPropNetDNSSupplementalMatchOrders);
73 if (orders != NULL) {
74 if (!isA_CFArray(orders) || (n_domains != CFArrayGetCount(orders))) {
75 return;
76 }
77 }
78
79 /*
80 * yes, this is a "supplemental" resolver configuration, expand
81 * the match domains and add each to the supplemental list.
82 */
83 for (i = 0; i < n_domains; i++) {
84 CFIndex j;
85 CFStringRef match_domain;
86 CFNumberRef match_order;
87 uint32_t match_order_val = 0;
88 CFMutableDictionaryRef match_resolver;
89 CFIndex n_supplemental;
90
91 match_domain = CFArrayGetValueAtIndex(domains, i);
92 if (!isA_CFString(match_domain)) {
93 continue;
94 }
95
96 match_order = (orders != NULL) ? CFArrayGetValueAtIndex(orders, i) : NULL;
97
98 match_resolver = CFDictionaryCreateMutableCopy(NULL, 0, dns);
99 CFDictionaryRemoveValue(match_resolver, kSCPropNetDNSSupplementalMatchDomains);
100 CFDictionaryRemoveValue(match_resolver, kSCPropNetDNSSupplementalMatchOrders);
101 CFDictionaryRemoveValue(match_resolver, kSCPropNetDNSSearchDomains);
102 CFDictionarySetValue(match_resolver, kSCPropNetDNSDomainName, match_domain);
103 if (isA_CFNumber(match_order)) {
104 CFDictionarySetValue(match_resolver, kSCPropNetDNSSearchOrder, match_order);
105 } else if (!CFDictionaryContainsKey(match_resolver, kSCPropNetDNSSearchOrder)) {
106 CFNumberRef num;
107
108 num = CFNumberCreate(NULL, kCFNumberIntType, &defaultOrder);
109 CFDictionarySetValue(match_resolver, kSCPropNetDNSSearchOrder, num);
110 CFRelease(num);
111 }
112
113 match_order = CFDictionaryGetValue(match_resolver, kSCPropNetDNSSearchOrder);
114 if (!isA_CFNumber(match_order) ||
115 !CFNumberGetValue(match_order, kCFNumberIntType, &match_order_val)) {
116 match_order = NULL;
117 match_order_val = 0;
118 }
119
120 n_supplemental = CFArrayGetCount(supplemental);
121 for (j = 0; j < n_supplemental; j++) {
122 CFMutableDictionaryRef compare;
123 Boolean match;
124 CFDictionaryRef supplemental_resolver;
125
126 supplemental_resolver = CFArrayGetValueAtIndex(supplemental, j);
127 if (CFEqual(match_resolver, supplemental_resolver)) {
128 // a real duplicate
129 CFRelease(match_resolver);
130 match_resolver = NULL;
131 break;
132 }
133
134 compare = CFDictionaryCreateMutableCopy(NULL, 0, supplemental_resolver);
135 if (match_order != NULL) {
136 CFDictionarySetValue(compare, kSCPropNetDNSSearchOrder, match_order);
137 }
138 match = CFEqual(match_resolver, compare);
139 CFRelease(compare);
140
141 if (match) {
142 CFNumberRef supplemental_order;
143 uint32_t supplemental_order_val = 0;
144
145 // if only the search order's are different
146 supplemental_order = CFDictionaryGetValue(supplemental_resolver, kSCPropNetDNSSearchOrder);
147 if (!isA_CFNumber(supplemental_order) ||
148 !CFNumberGetValue(supplemental_order, kCFNumberIntType, &supplemental_order_val)) {
149 supplemental_order_val = 0;
150 }
151
152 if (match_order_val < supplemental_order_val ) {
153 // if we should prefer this match resolver, else just skip it
154 CFArraySetValueAtIndex(supplemental, j, match_resolver);
155 }
156
157 CFRelease(match_resolver);
158 match_resolver = NULL;
159 break;
160 }
161 }
162
163 if (match_resolver != NULL) {
164 CFArrayAppendValue(supplemental, match_resolver);
165 CFRelease(match_resolver);
166 }
167 }
168
169 return;
170 }
171
172
173 static void
174 add_predefined_resolvers(CFMutableArrayRef supplemental)
175 {
176 CFIndex i;
177 CFIndex n;
178
179 if (S_predefined == NULL) {
180 return;
181 }
182
183 n = CFArrayGetCount(S_predefined);
184 for (i = 0; i < n; i++) {
185 uint32_t defaultOrder;
186 CFDictionaryRef dns;
187
188 dns = CFArrayGetValueAtIndex(S_predefined, i);
189 if (!isA_CFDictionary(dns)) {
190 continue;
191 }
192
193 defaultOrder = DEFAULT_SEARCH_ORDER +
194 (DEFAULT_SEARCH_ORDER / 2) +
195 ((DEFAULT_SEARCH_ORDER / 1000) * i);
196 add_supplemental(supplemental, dns, defaultOrder);
197 }
198
199 return;
200 }
201
202
203 #define N_QUICK 32
204
205
206 static void
207 add_supplemental_resolvers(CFMutableArrayRef supplemental, CFDictionaryRef services, CFArrayRef service_order)
208 {
209 const void * keys_q[N_QUICK];
210 const void ** keys = keys_q;
211 CFIndex i;
212 CFIndex n_order;
213 CFIndex n_services;
214 const void * vals_q[N_QUICK];
215 const void ** vals = vals_q;
216
217 n_services = isA_CFDictionary(services) ? CFDictionaryGetCount(services) : 0;
218 if (n_services == 0) {
219 return; // if no services
220 }
221
222 if (n_services > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
223 keys = CFAllocatorAllocate(NULL, n_services * sizeof(CFTypeRef), 0);
224 vals = CFAllocatorAllocate(NULL, n_services * sizeof(CFTypeRef), 0);
225 }
226
227 n_order = isA_CFArray(service_order) ? CFArrayGetCount(service_order) : 0;
228
229 CFDictionaryGetKeysAndValues(services, keys, vals);
230 for (i = 0; i < n_services; i++) {
231 uint32_t defaultOrder;
232 CFDictionaryRef dns;
233 CFDictionaryRef service = (CFDictionaryRef)vals[i];
234
235 if (!isA_CFDictionary(service)) {
236 continue;
237 }
238
239 dns = CFDictionaryGetValue(service, kSCEntNetDNS);
240 if (!isA_CFDictionary(dns)) {
241 continue;
242 }
243
244 defaultOrder = DEFAULT_SEARCH_ORDER -
245 (DEFAULT_SEARCH_ORDER / 2) +
246 ((DEFAULT_SEARCH_ORDER / 1000) * i);
247 if ((n_order > 0) &&
248 !CFArrayContainsValue(service_order, CFRangeMake(0, n_order), keys[i])) {
249 // push out services not specified in service order
250 defaultOrder += (DEFAULT_SEARCH_ORDER / 1000) * n_services;
251 }
252
253 add_supplemental(supplemental, dns, defaultOrder);
254 }
255
256 if (keys != keys_q) {
257 CFAllocatorDeallocate(NULL, keys);
258 CFAllocatorDeallocate(NULL, vals);
259 }
260
261 return;
262 }
263
264
265 static CFComparisonResult
266 compareBySearchOrder(const void *val1, const void *val2, void *context)
267 {
268 CFDictionaryRef dns1 = (CFDictionaryRef)val1;
269 CFDictionaryRef dns2 = (CFDictionaryRef)val2;
270 CFNumberRef num;
271 uint32_t order1 = DEFAULT_SEARCH_ORDER;
272 uint32_t order2 = DEFAULT_SEARCH_ORDER;
273
274 num = CFDictionaryGetValue(dns1, kSCPropNetDNSSearchOrder);
275 if (!isA_CFNumber(num) ||
276 !CFNumberGetValue(num, kCFNumberIntType, &order1)) {
277 order1 = DEFAULT_SEARCH_ORDER;
278 }
279
280 num = CFDictionaryGetValue(dns2, kSCPropNetDNSSearchOrder);
281 if (!isA_CFNumber(num) ||
282 !CFNumberGetValue(num, kCFNumberIntType, &order2)) {
283 order2 = DEFAULT_SEARCH_ORDER;
284 }
285
286 if (order1 == order2) {
287 return kCFCompareEqualTo;
288 }
289
290 return (order1 < order2) ? kCFCompareLessThan : kCFCompareGreaterThan;
291 }
292
293
294 static void
295 update_search_domains(CFMutableDictionaryRef *defaultDomain, CFArrayRef supplemental)
296 {
297 CFStringRef defaultDomainName = NULL;
298 uint32_t defaultOrder = DEFAULT_SEARCH_ORDER;
299 CFArrayRef defaultSearchDomains = NULL;
300 CFIndex defaultSearchIndex = 0;
301 CFIndex i;
302 CFIndex n;
303 CFMutableArrayRef mySearchDomains;
304 CFMutableArrayRef mySupplemental = (CFMutableArrayRef)supplemental;
305 Boolean searchDomainAdded = FALSE;
306
307 n = CFArrayGetCount(supplemental);
308 if (n == 0) {
309 // if no supplemental domains
310 return;
311 }
312
313 if (*defaultDomain != NULL) {
314 CFNumberRef num;
315
316 num = CFDictionaryGetValue(*defaultDomain, kSCPropNetDNSSearchOrder);
317 if (!isA_CFNumber(num) ||
318 !CFNumberGetValue(num, kCFNumberIntType, &defaultOrder)) {
319 defaultOrder = DEFAULT_SEARCH_ORDER;
320 }
321
322 defaultDomainName = CFDictionaryGetValue(*defaultDomain, kSCPropNetDNSDomainName);
323 defaultSearchDomains = CFDictionaryGetValue(*defaultDomain, kSCPropNetDNSSearchDomains);
324 }
325
326 if (isA_CFArray(defaultSearchDomains)) {
327 mySearchDomains = CFArrayCreateMutableCopy(NULL, 0, defaultSearchDomains);
328 } else {
329 mySearchDomains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
330 if (isA_CFString(defaultDomainName)) {
331 char *domain;
332 int domain_parts = 1;
333 char *dp;
334
335 domain = _SC_cfstring_to_cstring(defaultDomainName,
336 NULL,
337 0,
338 kCFStringEncodingUTF8);
339
340 for (dp = domain; *dp != '\0'; dp++) {
341 if (*dp == '.') {
342 domain_parts++;
343 }
344 }
345
346 dp = domain;
347 for (i = LOCALDOMAINPARTS; i <= domain_parts; i++) {
348 CFStringRef searchDomain;
349
350 searchDomain = CFStringCreateWithCString(NULL,
351 dp,
352 kCFStringEncodingUTF8);
353 CFArrayAppendValue(mySearchDomains, searchDomain);
354 CFRelease(searchDomain);
355
356 dp = strchr(dp, '.') + 1;
357 }
358
359 CFAllocatorDeallocate(NULL, domain);
360 }
361 }
362
363 if (n > 1) {
364 mySupplemental = CFArrayCreateMutableCopy(NULL, 0, supplemental);
365 CFArraySortValues(mySupplemental,
366 CFRangeMake(0, n),
367 compareBySearchOrder,
368 NULL);
369 }
370
371 for (i = 0; i < n; i++) {
372 CFDictionaryRef dns;
373 CFNumberRef num;
374 CFStringRef supplementalDomain;
375 uint32_t supplementalOrder;
376
377 dns = CFArrayGetValueAtIndex(mySupplemental, i);
378
379 supplementalDomain = CFDictionaryGetValue(dns, kSCPropNetDNSDomainName);
380 if (CFArrayContainsValue(mySearchDomains,
381 CFRangeMake(0, CFArrayGetCount(mySearchDomains)),
382 supplementalDomain)) {
383 // if supplemental domain is already in the search list
384 continue;
385 }
386
387 num = CFDictionaryGetValue(dns, kSCPropNetDNSSearchOrder);
388 if (!isA_CFNumber(num) ||
389 !CFNumberGetValue(num, kCFNumberIntType, &supplementalOrder)) {
390 supplementalOrder = DEFAULT_SEARCH_ORDER;
391 }
392
393 if (supplementalOrder < defaultOrder) {
394 CFArrayInsertValueAtIndex(mySearchDomains,
395 defaultSearchIndex,
396 supplementalDomain);
397 defaultSearchIndex++;
398 } else {
399 CFArrayAppendValue(mySearchDomains, supplementalDomain);
400 }
401
402 searchDomainAdded = TRUE;
403 }
404
405 if (searchDomainAdded) {
406 if (*defaultDomain == NULL) {
407 *defaultDomain = CFDictionaryCreateMutable(NULL,
408 0,
409 &kCFTypeDictionaryKeyCallBacks,
410 &kCFTypeDictionaryValueCallBacks);
411 }
412 CFDictionarySetValue(*defaultDomain, kSCPropNetDNSSearchDomains, mySearchDomains);
413 }
414
415 CFRelease(mySearchDomains);
416 if (mySupplemental != supplemental) CFRelease(mySupplemental);
417 return;
418 }
419
420
421 static dns_create_resolver_t
422 create_resolver(CFDictionaryRef dns)
423 {
424 CFArrayRef list;
425 CFNumberRef num;
426 dns_create_resolver_t _resolver;
427 CFStringRef str;
428
429 _resolver = _dns_resolver_create();
430
431 // process domain
432 str = CFDictionaryGetValue(dns, kSCPropNetDNSDomainName);
433 if (isA_CFString(str)) {
434 char domain[NS_MAXDNAME];
435
436 if (_SC_cfstring_to_cstring(str, domain, sizeof(domain), kCFStringEncodingUTF8) != NULL) {
437 _dns_resolver_set_domain(&_resolver, domain);
438 }
439 }
440
441 // process search domains
442 list = CFDictionaryGetValue(dns, kSCPropNetDNSSearchDomains);
443 if (isA_CFArray(list)) {
444 CFIndex i;
445 CFIndex n = CFArrayGetCount(list);
446
447 // add "search" domains
448 for (i = 0; i < n; i++) {
449 str = CFArrayGetValueAtIndex(list, i);
450 if (isA_CFString(str)) {
451 char search[NS_MAXDNAME];
452
453 if (_SC_cfstring_to_cstring(str, search, sizeof(search), kCFStringEncodingUTF8) != NULL) {
454 _dns_resolver_add_search(&_resolver, search);
455 }
456 }
457 }
458 }
459
460 // process nameserver addresses
461 list = CFDictionaryGetValue(dns, kSCPropNetDNSServerAddresses);
462 if (isA_CFArray(list)) {
463 CFIndex i;
464 CFIndex n = CFArrayGetCount(list);
465
466 for (i = 0; i < n; i++) {
467 union {
468 struct sockaddr sa;
469 struct sockaddr_in sin;
470 struct sockaddr_in6 sin6;
471 } addr;
472 char buf[128];
473
474 str = CFArrayGetValueAtIndex(list, i);
475 if (!isA_CFString(str)) {
476 continue;
477 }
478
479 if (_SC_cfstring_to_cstring(str, buf, sizeof(buf), kCFStringEncodingASCII) == NULL) {
480 continue;
481 }
482
483 bzero(&addr, sizeof(addr));
484 if (inet_aton(buf, &addr.sin.sin_addr) == 1) {
485 /* if IPv4 address */
486 addr.sin.sin_len = sizeof(addr.sin);
487 addr.sin.sin_family = AF_INET;
488 _dns_resolver_add_nameserver(&_resolver, &addr.sa);
489 } else if (inet_pton(AF_INET6, buf, &addr.sin6.sin6_addr) == 1) {
490 /* if IPv6 address */
491 char *p;
492
493 p = strchr(buf, '%');
494 if (p != NULL) {
495 addr.sin6.sin6_scope_id = if_nametoindex(p+1);
496 }
497
498 addr.sin6.sin6_len = sizeof(addr.sin6);
499 addr.sin6.sin6_family = AF_INET6;
500 _dns_resolver_add_nameserver(&_resolver, &addr.sa);
501 } else {
502 continue;
503 }
504 }
505 }
506
507 // process search order
508 num = CFDictionaryGetValue(dns, kSCPropNetDNSSearchOrder);
509 if (isA_CFNumber(num)) {
510 uint32_t order;
511
512 if (CFNumberGetValue(num, kCFNumberIntType, &order)) {
513 _dns_resolver_set_order(&_resolver, order);
514 }
515 }
516
517 // process port
518 num = CFDictionaryGetValue(dns, kSCPropNetDNSServerPort);
519 if (isA_CFNumber(num)) {
520 int port;
521
522 if (CFNumberGetValue(num, kCFNumberIntType, &port)) {
523 _dns_resolver_set_port(&_resolver, (uint16_t)port);
524 }
525 }
526
527 // process timeout
528 num = CFDictionaryGetValue(dns, kSCPropNetDNSServerTimeout);
529 if (isA_CFNumber(num)) {
530 int timeout;
531
532 if (CFNumberGetValue(num, kCFNumberIntType, &timeout)) {
533 _dns_resolver_set_timeout(&_resolver, (uint32_t)timeout);
534 }
535 }
536
537 // process options
538 str = CFDictionaryGetValue(dns, kSCPropNetDNSOptions);
539 if (isA_CFString(str)) {
540 char *options;
541
542 options = _SC_cfstring_to_cstring(str, NULL, 0, kCFStringEncodingUTF8);
543 if (options != NULL) {
544 _dns_resolver_set_options(&_resolver, options);
545 CFAllocatorDeallocate(NULL, options);
546 }
547 }
548
549 return _resolver;
550 }
551
552
553 __private_extern__
554 void
555 dns_configuration_set(CFDictionaryRef defaultResolver,
556 CFDictionaryRef services,
557 CFArrayRef serviceOrder)
558 {
559 CFIndex i;
560 CFMutableDictionaryRef myDefault;
561 CFStringRef myDomain = NULL;
562 uint32_t myOrder = DEFAULT_SEARCH_ORDER;
563 Boolean myOrderAdded = FALSE;
564 CFIndex n_supplemental;
565 CFNumberRef order;
566 dns_create_resolver_t resolver;
567 CFArrayRef search;
568 CFMutableArrayRef supplemental;
569
570 if (defaultResolver == NULL) {
571 myDefault = CFDictionaryCreateMutable(NULL,
572 0,
573 &kCFTypeDictionaryKeyCallBacks,
574 &kCFTypeDictionaryValueCallBacks);
575 } else {
576 myDefault = CFDictionaryCreateMutableCopy(NULL, 0, defaultResolver);
577
578 // ensure that the default resolver has a search order
579
580 order = CFDictionaryGetValue(myDefault, kSCPropNetDNSSearchOrder);
581 if (!isA_CFNumber(order) ||
582 !CFNumberGetValue(order, kCFNumberIntType, &myOrder)) {
583 myOrderAdded = TRUE;
584 myOrder = DEFAULT_SEARCH_ORDER;
585 order = CFNumberCreate(NULL, kCFNumberIntType, &myOrder);
586 CFDictionarySetValue(myDefault, kSCPropNetDNSSearchOrder, order);
587 CFRelease(order);
588 }
589 }
590
591 // establish list of supplemental resolvers
592
593 supplemental = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
594
595 // identify search[] list and/or domain name
596
597 search = CFDictionaryGetValue(myDefault, kSCPropNetDNSSearchDomains);
598 if (isA_CFArray(search) && (CFArrayGetCount(search) > 0)) {
599 myDomain = CFArrayGetValueAtIndex(search, 0);
600 myDomain = isA_CFString(myDomain);
601 }
602
603 if (myDomain == NULL) {
604 myDomain = CFDictionaryGetValue(myDefault, kSCPropNetDNSDomainName);
605 myDomain = isA_CFString(myDomain);
606 }
607
608 // add match for default domain
609
610 if (myDomain != NULL) {
611 CFMutableDictionaryRef mySupplemental;
612
613 mySupplemental = CFDictionaryCreateMutableCopy(NULL, 0, myDefault);
614 CFDictionarySetValue (mySupplemental, kSCPropNetDNSDomainName, myDomain);
615 CFDictionaryRemoveValue(mySupplemental, kSCPropNetDNSSearchDomains);
616 CFDictionaryRemoveValue(mySupplemental, kSCPropNetDNSSupplementalMatchDomains);
617 CFDictionaryRemoveValue(mySupplemental, kSCPropNetDNSSupplementalMatchOrders);
618 CFArrayAppendValue(supplemental, mySupplemental);
619 CFRelease(mySupplemental);
620 }
621
622 // collect (and add) any supplemental resolver configurations
623
624 add_supplemental_resolvers(supplemental, services, serviceOrder);
625
626 // update the "search" list
627
628 update_search_domains(&myDefault, supplemental);
629
630 // add any pre-defined resolver configurations
631
632 add_predefined_resolvers(supplemental);
633
634 // check if the "match for default domain" (above) is really needed
635
636 if (myDomain != NULL) {
637 Boolean sharedDomain = FALSE;
638
639 n_supplemental = CFArrayGetCount(supplemental);
640 for (i = 1; i < n_supplemental; i++) {
641 CFStringRef domain;
642 CFDictionaryRef mySupplemental;
643
644 mySupplemental = CFArrayGetValueAtIndex(supplemental, i);
645 domain = CFDictionaryGetValue(mySupplemental, kSCPropNetDNSDomainName);
646 if (isA_CFString(domain)) {
647 if (CFEqual(myDomain, domain)) {
648 sharedDomain = TRUE;
649 break;
650 }
651
652 if (CFStringHasSuffix(myDomain, domain)) {
653 CFIndex dotIndex;
654
655 dotIndex = CFStringGetLength(myDomain) - CFStringGetLength(domain) - 1;
656 if (dotIndex > 0) {
657 UniChar dot;
658
659 dot = CFStringGetCharacterAtIndex(myDomain, dotIndex);
660 if (dot == (UniChar)'.') {
661 sharedDomain = TRUE;
662 break;
663 }
664 }
665 }
666 }
667 }
668
669 if (!sharedDomain) {
670 // if the default resolver domain name is not shared
671 CFArrayRemoveValueAtIndex(supplemental, 0);
672 }
673 }
674
675 // establish resolver configuration
676
677 n_supplemental = CFArrayGetCount(supplemental);
678 if ((defaultResolver == NULL) && (n_supplemental == 0)) {
679 /*
680 * if no default or supplemental resolvers
681 */
682 if (!_dns_configuration_store(NULL)) {
683 SCLog(TRUE, LOG_ERR, CFSTR("set_dns_configuration: could not store configuration"));
684 }
685 } else {
686 dns_create_config_t _config;
687
688 /*
689 * if default and/or supplemental resolvers are defined
690 */
691 _config = _dns_configuration_create();
692
693 // add [default] resolver
694
695 if ((n_supplemental == 0) && myOrderAdded) {
696 CFDictionaryRemoveValue(myDefault, kSCPropNetDNSSearchOrder);
697 }
698 resolver = create_resolver(myDefault);
699 _dns_configuration_add_resolver(&_config, resolver);
700 _dns_resolver_free(&resolver);
701
702 // add [supplemental] resolvers
703
704 for (i = 0; i < n_supplemental; i++) {
705 CFDictionaryRef supplementalResolver;
706
707 supplementalResolver = CFArrayGetValueAtIndex(supplemental, i);
708 resolver = create_resolver(supplementalResolver);
709 _dns_configuration_add_resolver(&_config, resolver);
710 _dns_resolver_free(&resolver);
711 }
712
713 // save configuration
714
715 if (!_dns_configuration_store(&_config)) {
716 SCLog(TRUE, LOG_ERR, CFSTR("set_dns_configuration() failed: could not store configuration"));
717 }
718
719 _dns_configuration_free(&_config);
720 }
721
722 CFRelease(myDefault);
723 CFRelease(supplemental);
724
725 return;
726 }
727
728
729 static void
730 load_predefined_resolvers(CFBundleRef bundle)
731 {
732 Boolean ok;
733 CFURLRef url;
734 CFStringRef xmlError = NULL;
735 CFDataRef xmlResolvers = NULL;
736
737 url = CFBundleCopyResourceURL(bundle, CFSTR("Resolvers"), CFSTR("plist"), NULL);
738 if (url == NULL) {
739 return;
740 }
741
742 ok = CFURLCreateDataAndPropertiesFromResource(NULL, url, &xmlResolvers, NULL, NULL, NULL);
743 CFRelease(url);
744 if (!ok || (xmlResolvers == NULL)) {
745 return;
746 }
747
748 /* convert the XML data into a property list */
749 S_predefined = CFPropertyListCreateFromXMLData(NULL, xmlResolvers, kCFPropertyListImmutable, &xmlError);
750 CFRelease(xmlResolvers);
751 if (S_predefined == NULL) {
752 if (xmlError != NULL) {
753 SCLog(TRUE, LOG_DEBUG, CFSTR("add_predefined_resolvers: %@"), xmlError);
754 CFRelease(xmlError);
755 }
756 return;
757 }
758
759 if (!isA_CFArray(S_predefined)) {
760 CFRelease(S_predefined);
761 S_predefined = NULL;
762 return;
763 }
764
765 return;
766 }
767
768
769 __private_extern__
770 void
771 dns_configuration_init(CFBundleRef bundle)
772 {
773 load_predefined_resolvers(bundle);
774 return;
775 }
776