]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/tests.c
configd-596.12.tar.gz
[apple/configd.git] / scutil.tproj / tests.c
1 /*
2 * Copyright (c) 2000, 2001, 2003-2005, 2007-2013 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 * July 9, 2001 Allan Nathanson <ajn@apple.com>
28 * - added "-r" option for checking network reachability
29 * - added "-w" option to check/wait for the presence of a
30 * dynamic store key.
31 *
32 * June 1, 2001 Allan Nathanson <ajn@apple.com>
33 * - public API conversion
34 *
35 * November 9, 2000 Allan Nathanson <ajn@apple.com>
36 * - initial revision
37 */
38
39 #include "scutil.h"
40 #include "prefs.h"
41 #include "tests.h"
42
43 #include <netdb.h>
44 #include <netdb_async.h>
45 #include <sys/time.h>
46 #include <net/if.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
49
50 #include <dnsinfo.h>
51 #include "dnsinfo_internal.h"
52 #include <network_information.h>
53 #include "SCNetworkReachabilityInternal.h"
54 #include <CommonCrypto/CommonDigest.h>
55
56 static Boolean resolver_bypass;
57
58 static CF_RETURNS_RETAINED CFMutableDictionaryRef
59 _setupReachabilityOptions(int argc, char **argv, const char *interface)
60 {
61 int i;
62 CFMutableDictionaryRef options;
63
64 options = CFDictionaryCreateMutable(NULL,
65 0,
66 &kCFTypeDictionaryKeyCallBacks,
67 &kCFTypeDictionaryValueCallBacks);
68
69 for (i = 0; i < argc; i++) {
70 if (strcasecmp(argv[i], "interface") == 0) {
71 if (++i >= argc) {
72 SCPrint(TRUE, stderr, CFSTR("No interface\n"));
73 CFRelease(options);
74 exit(1);
75 }
76
77 interface = argv[i];
78 continue;
79 }
80
81
82 if (strcasecmp(argv[i], "server") == 0) {
83 CFDictionarySetValue(options,
84 kSCNetworkReachabilityOptionServerBypass,
85 kCFBooleanFalse);
86 continue;
87 } else if (strcasecmp(argv[i], "no-server") == 0) {
88 CFDictionarySetValue(options,
89 kSCNetworkReachabilityOptionServerBypass,
90 kCFBooleanTrue);
91 continue;
92 }
93
94
95 if (strcasecmp(argv[i], "no-connection-on-demand") == 0) {
96 CFDictionarySetValue(options,
97 kSCNetworkReachabilityOptionConnectionOnDemandBypass,
98 kCFBooleanTrue);
99 continue;
100 }
101
102 if (strcasecmp(argv[i], "no-resolve") == 0) {
103 CFDictionarySetValue(options,
104 kSCNetworkReachabilityOptionResolverBypass,
105 kCFBooleanTrue);
106 resolver_bypass = TRUE;
107 continue;
108 }
109
110 if (strlen(argv[i]) == 0) {
111 continue;
112 }
113
114 SCPrint(TRUE, stderr, CFSTR("Unrecognized option: %s\n"), argv[i]);
115 CFRelease(options);
116 exit(1);
117 }
118
119 if (interface != NULL) {
120 CFStringRef str;
121
122 if (if_nametoindex(interface) == 0) {
123 SCPrint(TRUE, stderr, CFSTR("No interface: %s\n"), interface);
124 exit(1);
125 }
126
127 str = CFStringCreateWithCString(NULL, interface, kCFStringEncodingASCII);
128 CFDictionarySetValue(options, kSCNetworkReachabilityOptionInterface, str);
129 CFRelease(str);
130 }
131
132 if (CFDictionaryGetCount(options) == 0) {
133 CFRelease(options);
134 options = NULL;
135 }
136
137 return options;
138 }
139
140
141 static SCNetworkReachabilityRef
142 _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
143 {
144 char *ip_address = argv[0];
145 const char *interface;
146 CFMutableDictionaryRef options = NULL;
147 char *remote_address = NULL;
148 struct sockaddr_in r_sin;
149 struct sockaddr_in sin;
150 struct sockaddr_in6 sin6;
151 SCNetworkReachabilityRef target = NULL;
152
153 bzero(&sin, sizeof(sin));
154 sin.sin_len = sizeof(sin);
155 sin.sin_family = AF_INET;
156
157 bzero(&sin6, sizeof(sin6));
158 sin6.sin6_len = sizeof(sin6);
159 sin6.sin6_family = AF_INET6;
160
161 interface = strchr(argv[0], '%');
162 if (interface != NULL) {
163 ip_address = strdup(argv[0]);
164 ip_address[interface - argv[0]] = '\0';
165 interface++;
166 }
167
168 if (inet_aton(ip_address, &sin.sin_addr) == 1) {
169 if (argc > 1) {
170 bzero(&r_sin, sizeof(r_sin));
171 r_sin.sin_len = sizeof(r_sin);
172 r_sin.sin_family = AF_INET;
173 remote_address = argv[1];
174 }
175
176 if ((argc == 1)
177 || ((argc > 1) && (strlen(argv[1]) == 0))
178 || inet_aton(remote_address, &r_sin.sin_addr) == 0) {
179 if (argc > 2) {
180 options = _setupReachabilityOptions(argc - 2, argv + 2, interface);
181 }
182 if (options == NULL) {
183 target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin);
184 if (context != NULL) {
185 context->info = "by address";
186 }
187 } else {
188 CFDataRef data;
189
190 data = CFDataCreate(NULL, (const UInt8 *)&sin, sizeof(sin));
191 CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
192 CFRelease(data);
193
194 if (context != NULL) {
195 if (CFDictionaryContainsKey(options,
196 kSCNetworkReachabilityOptionInterface)) {
197 if (CFDictionaryGetCount(options) == 2) {
198 context->info = "by address w/scope";
199 } else {
200 context->info = "by address w/scope and options";
201 }
202 } else {
203 context->info = "by address w/options";
204 }
205 }
206 }
207 } else {
208 const char *interface2;
209
210 interface2 = strchr(argv[1], '%');
211 if (interface2 != NULL) {
212 remote_address = strdup(argv[1]);
213 remote_address[interface2 - argv[1]] = '\0';
214 interface2++;
215
216 if ((interface != NULL) && (strcmp(interface, interface2) != 0)) {
217 SCPrint(TRUE, stderr,
218 CFSTR("Interface mismatch \"%s\" != \"%s\"\n"),
219 interface,
220 interface2);
221 exit(1);
222 }
223
224 interface = interface2;
225 }
226
227 if (remote_address != argv[1]) {
228 free(remote_address);
229 }
230
231 options = _setupReachabilityOptions(argc - 2, argv + 2, interface);
232 if (options == NULL) {
233 target = SCNetworkReachabilityCreateWithAddressPair(NULL,
234 (struct sockaddr *)&sin,
235 (struct sockaddr *)&r_sin);
236 if (context != NULL) {
237 context->info = "by address pair";
238 }
239 } else {
240 CFDataRef data;
241
242 data = CFDataCreate(NULL, (const UInt8 *)&sin, sizeof(sin));
243 CFDictionarySetValue(options, kSCNetworkReachabilityOptionLocalAddress, data);
244 CFRelease(data);
245 data = CFDataCreate(NULL, (const UInt8 *)&r_sin, sizeof(r_sin));
246 CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
247 CFRelease(data);
248
249 if (context != NULL) {
250 if (CFDictionaryContainsKey(options,
251 kSCNetworkReachabilityOptionInterface)) {
252 if (CFDictionaryGetCount(options) == 3) {
253 context->info = "by address pair w/scope";
254 } else {
255 context->info = "by address pair w/scope and options";
256 }
257 } else {
258 context->info = "by address pair w/options";
259 }
260 }
261 }
262 }
263 } else if (inet_pton(AF_INET6, argv[0], &sin6.sin6_addr) == 1) {
264 struct sockaddr_in6 r_sin6;
265
266 if (interface != NULL) {
267 sin6.sin6_scope_id = if_nametoindex(interface);
268 }
269
270 if (argc >1) {
271 bzero(&r_sin6, sizeof(r_sin6));
272 r_sin6.sin6_len = sizeof(r_sin6);
273 r_sin6.sin6_family = AF_INET6;
274 }
275
276 if ((argc == 1)
277 || ((argc > 1) && (strlen(argv[1]) == 0))
278 || inet_pton(AF_INET6, argv[1], &r_sin6.sin6_addr) == 0) {
279 if (argc > 2) {
280 options = _setupReachabilityOptions(argc - 2, argv + 2, NULL);
281 }
282 if (options == NULL) {
283 target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin6);
284 if (context != NULL) {
285 context->info = "by (v6) address";
286 }
287 } else {
288 CFDataRef data;
289
290 data = CFDataCreate(NULL, (const UInt8 *)&sin6, sizeof(sin6));
291 CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
292 CFRelease(data);
293
294 if (context != NULL) {
295 context->info = "by (v6) address w/options";
296 }
297 }
298 } else {
299 interface = strchr(argv[1], '%');
300 if (interface != NULL) {
301 r_sin6.sin6_scope_id = if_nametoindex(interface);
302 }
303
304 options = _setupReachabilityOptions(argc - 2, argv + 2, NULL);
305 if (options == NULL) {
306 target = SCNetworkReachabilityCreateWithAddressPair(NULL,
307 (struct sockaddr *)&sin6,
308 (struct sockaddr *)&r_sin6);
309 if (context != NULL) {
310 context->info = "by (v6) address pair";
311 }
312 } else {
313 CFDataRef data;
314
315 data = CFDataCreate(NULL, (const UInt8 *)&sin6, sizeof(sin6));
316 CFDictionarySetValue(options, kSCNetworkReachabilityOptionLocalAddress, data);
317 CFRelease(data);
318 data = CFDataCreate(NULL, (const UInt8 *)&r_sin6, sizeof(r_sin6));
319 CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
320 CFRelease(data);
321
322 if (context != NULL) {
323 context->info = "by (v6) address pair w/options";
324 }
325 }
326 }
327 } else {
328 if (argc == 1) {
329 target = SCNetworkReachabilityCreateWithName(NULL, argv[0]);
330 if (context != NULL) {
331 context->info = "by name";
332 }
333 } else {
334 options = _setupReachabilityOptions(argc - 1, argv + 1, NULL);
335 if (options == NULL) {
336 target = SCNetworkReachabilityCreateWithName(NULL, argv[0]);
337 if (context != NULL) {
338 context->info = "by name";
339 }
340 } else {
341 CFStringRef str;
342
343 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
344 CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
345 CFRelease(str);
346
347 if (context != NULL) {
348 context->info = "by name w/options";
349 }
350 }
351 }
352 }
353
354 if (ip_address != argv[0]) {
355 free(ip_address);
356 }
357
358 if ((target == NULL) && (options != NULL)) {
359 target = SCNetworkReachabilityCreateWithOptions(NULL, options);
360 CFRelease(options);
361 }
362
363 return target;
364 }
365
366
367 static void
368 _printReachability(SCNetworkReachabilityRef target)
369 {
370 SCNetworkReachabilityFlags flags;
371 Boolean ok;
372
373 ok = SCNetworkReachabilityGetFlags(target, &flags);
374 if (!ok) {
375 SCPrint(TRUE, stderr, CFSTR(" could not determine reachability, %s\n"), SCErrorString(SCError()));
376 return;
377 }
378
379 SCPrint(_sc_debug, stdout, CFSTR("flags = 0x%08x ("), flags);
380 __SCNetworkReachabilityPrintFlags(flags);
381 SCPrint(_sc_debug, stdout, CFSTR(")"));
382 SCPrint(TRUE, stdout, CFSTR("\n"));
383
384 if (resolver_bypass) {
385 int if_index;
386
387 if_index = SCNetworkReachabilityGetInterfaceIndex(target);
388 SCPrint(_sc_debug, stdout, CFSTR("interface index = %d\n"), if_index);
389 }
390
391 return;
392 }
393
394
395 __private_extern__
396 void
397 do_checkReachability(int argc, char **argv)
398 {
399 SCNetworkReachabilityRef target;
400
401 target = _setupReachability(argc, argv, NULL);
402 if (target == NULL) {
403 SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
404 exit(1);
405 }
406
407 _printReachability(target);
408 CFRelease(target);
409 exit(0);
410 }
411
412
413 static void
414 _printNWIFlags(nwi_ifstate_flags flags)
415 {
416 if (flags == 0) {
417 return;
418 }
419
420 SCPrint(TRUE, stdout, CFSTR(" ("));
421 if (flags & NWI_IFSTATE_FLAGS_HAS_IPV4) {
422 SCPrint(TRUE, stdout, CFSTR("IPv4"));
423 flags &= ~NWI_IFSTATE_FLAGS_HAS_IPV4;
424 SCPrint(flags != 0, stdout, CFSTR(","));
425 }
426 if (flags & NWI_IFSTATE_FLAGS_HAS_IPV6) {
427 SCPrint(TRUE, stdout, CFSTR("IPv6"));
428 flags &= ~NWI_IFSTATE_FLAGS_HAS_IPV6;
429 SCPrint(flags != 0, stdout, CFSTR(","));
430 }
431 if (flags & NWI_IFSTATE_FLAGS_HAS_DNS) {
432 SCPrint(TRUE, stdout, CFSTR("DNS"));
433 flags &= ~NWI_IFSTATE_FLAGS_HAS_DNS;
434 SCPrint(flags != 0, stdout, CFSTR(","));
435 }
436 if (flags != 0) {
437 SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags);
438 }
439 SCPrint(TRUE, stdout, CFSTR(")"));
440
441 return;
442 }
443
444
445 static void
446 _printNWIInfo(nwi_ifstate_t ifstate)
447 {
448 nwi_ifstate_flags ifstate_flags = nwi_ifstate_get_flags(ifstate);
449 SCNetworkReachabilityFlags reach_flags = nwi_ifstate_get_reachability_flags(ifstate);
450 const uint8_t *signature;
451 int signature_length;
452 const struct sockaddr *vpn_addr = nwi_ifstate_get_vpn_server(ifstate);
453
454 SCPrint(TRUE, stdout,
455 CFSTR(" %7s : flags %p"),
456 nwi_ifstate_get_ifname(ifstate),
457 ifstate_flags);
458 _printNWIFlags(ifstate_flags);
459
460 SCPrint(TRUE, stdout, CFSTR("\n reach %p ("), reach_flags);
461 __SCNetworkReachabilityPrintFlags(reach_flags);
462 SCPrint(TRUE, stdout, CFSTR(")"));
463
464 if (vpn_addr != NULL) {
465 char vpn_ntopbuf[INET6_ADDRSTRLEN];
466
467 _SC_sockaddr_to_string(vpn_addr, vpn_ntopbuf, sizeof(vpn_ntopbuf));
468 SCPrint(TRUE, stdout, CFSTR("\n VPN server: %s"), vpn_ntopbuf);
469 }
470
471 signature = nwi_ifstate_get_signature(ifstate, AF_UNSPEC, &signature_length);
472 if (signature != NULL) {
473 CFDataRef digest = NULL;
474
475 digest = CFDataCreate(NULL, signature, CC_SHA1_DIGEST_LENGTH);
476 SCPrint(TRUE, stdout, CFSTR("\n Signature Hash: %@"), digest);
477 CFRelease(digest);
478 } else {
479 SCPrint(TRUE, stdout, CFSTR("\n Signature Hash: <empty>"));
480 }
481
482 SCPrint(TRUE, stdout, CFSTR("\n generation %llu\n"),
483 nwi_ifstate_get_generation(ifstate));
484
485 return;
486 }
487
488
489 __private_extern__
490 void
491 do_nwi(int argc, char **argv)
492 {
493 nwi_ifstate_t ifstate;
494 nwi_state_t state = nwi_state_copy();
495
496 if (state == NULL) {
497 SCPrint(TRUE, stdout, CFSTR("No network information\n"));
498 exit(1);
499 }
500
501 if (argc > 0) {
502 ifstate = nwi_state_get_ifstate(state, argv[0]);
503 if (ifstate != NULL) {
504 _printNWIInfo(ifstate);
505 } else {
506 SCPrint(TRUE, stdout, CFSTR("No network information (for %s)\n"), argv[0]);
507 }
508
509 goto done;
510 }
511
512 SCPrint(TRUE, stdout, CFSTR("Network information (generation %llu)"),
513 nwi_state_get_generation(state));
514
515 SCPrint(TRUE, stdout, CFSTR("\nIPv4 network interface information\n"));
516 ifstate = nwi_state_get_first_ifstate(state, AF_INET);
517
518 if (ifstate == NULL) {
519 SCPrint(TRUE, stdout, CFSTR(" No IPv4 states found\n"));
520 }
521
522 while (ifstate != NULL) {
523 _printNWIInfo(ifstate);
524 ifstate = nwi_ifstate_get_next(ifstate, AF_INET);
525 }
526
527 SCPrint(TRUE, stdout, CFSTR("\nIPv6 network interface information\n"));
528 ifstate = nwi_state_get_first_ifstate(state, AF_INET6);
529
530 if (ifstate == NULL) {
531 SCPrint(TRUE, stdout, CFSTR(" No IPv6 states found\n"));
532 }
533
534 while (ifstate != NULL) {
535 _printNWIInfo(ifstate);
536 ifstate = nwi_ifstate_get_next(ifstate, AF_INET6);
537 }
538
539 done :
540
541 nwi_state_release(state);
542 exit(0);
543 }
544
545
546 static void
547 callout(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
548 {
549 static int n = 3;
550 struct tm tm_now;
551 struct timeval tv_now;
552
553 (void)gettimeofday(&tv_now, NULL);
554 (void)localtime_r(&tv_now.tv_sec, &tm_now);
555
556 SCPrint(TRUE, stdout, CFSTR("\n*** %2d:%02d:%02d.%03d\n\n"),
557 tm_now.tm_hour,
558 tm_now.tm_min,
559 tm_now.tm_sec,
560 tv_now.tv_usec / 1000);
561 SCPrint(TRUE, stdout, CFSTR("%2d: callback w/flags=0x%08x (info=\"%s\")\n"), n++, flags, (char *)info);
562 SCPrint(TRUE, stdout, CFSTR(" %@\n"), target);
563 _printReachability(target);
564 SCPrint(TRUE, stdout, CFSTR("\n"));
565 return;
566 }
567
568
569 __private_extern__
570 void
571 do_watchReachability(int argc, char **argv)
572 {
573 SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL };
574 SCNetworkReachabilityRef target;
575 SCNetworkReachabilityRef target_async;
576
577 target = _setupReachability(argc, argv, NULL);
578 if (target == NULL) {
579 SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
580 exit(1);
581 }
582
583 target_async = _setupReachability(argc, argv, &context);
584 if (target_async == NULL) {
585 SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
586 exit(1);
587 }
588
589 // Normally, we don't want to make any calls to SCNetworkReachabilityGetFlags()
590 // until after the "target" has been scheduled on a run loop. Otherwise, we'll
591 // end up making a synchronous DNS request and that's not what we want.
592 //
593 // To test the case were an application first calls SCNetworkReachabilityGetFlags()
594 // we provide the "CHECK_REACHABILITY_BEFORE_SCHEDULING" environment variable.
595 if (getenv("CHECK_REACHABILITY_BEFORE_SCHEDULING") != NULL) {
596 CFRelease(target_async);
597 target_async = CFRetain(target);
598 }
599
600 // Direct check of reachability
601 SCPrint(TRUE, stdout, CFSTR(" 0: direct\n"));
602 SCPrint(TRUE, stdout, CFSTR(" %@\n"), target);
603 _printReachability(target);
604 CFRelease(target);
605 SCPrint(TRUE, stdout, CFSTR("\n"));
606
607 // schedule the target
608 SCPrint(TRUE, stdout, CFSTR(" 1: start\n"));
609 SCPrint(TRUE, stdout, CFSTR(" %@\n"), target_async);
610 // _printReachability(target_async);
611 SCPrint(TRUE, stdout, CFSTR("\n"));
612
613 if (!SCNetworkReachabilitySetCallback(target_async, callout, &context)) {
614 printf("SCNetworkReachabilitySetCallback() failed: %s\n", SCErrorString(SCError()));
615 exit(1);
616 }
617
618 if (doDispatch) {
619 if (!SCNetworkReachabilitySetDispatchQueue(target_async, dispatch_get_main_queue())) {
620 printf("SCNetworkReachabilitySetDispatchQueue() failed: %s\n", SCErrorString(SCError()));
621 exit(1);
622 }
623 } else {
624 if (!SCNetworkReachabilityScheduleWithRunLoop(target_async, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
625 printf("SCNetworkReachabilityScheduleWithRunLoop() failed: %s\n", SCErrorString(SCError()));
626 exit(1);
627 }
628 }
629
630 // Note: now that we are scheduled on a run loop we can call SCNetworkReachabilityGetFlags()
631 // to get the current status. For "names", a DNS lookup has already been initiated.
632 SCPrint(TRUE, stdout, CFSTR(" 2: on %s\n"), doDispatch ? "dispatch queue" : "runloop");
633 SCPrint(TRUE, stdout, CFSTR(" %@\n"), target_async);
634 _printReachability(target_async);
635 SCPrint(TRUE, stdout, CFSTR("\n"));
636
637 CFRunLoopRun();
638 exit(0);
639 }
640
641
642 __private_extern__
643 void
644 do_showDNSConfiguration(int argc, char **argv)
645 {
646 dns_config_t *dns_config;
647 SCNetworkReachabilityRef target;
648
649 dns_config = dns_configuration_copy();
650
651 if (dns_config == NULL) {
652 SCPrint(TRUE, stdout, CFSTR("No DNS configuration available\n"));
653 exit(1);
654 }
655
656 if (argc > 1) {
657 int dns_config_index = -1;
658 SCNetworkReachabilityFlags flags = 0;
659 Boolean haveDNS = FALSE;
660 Boolean ok = FALSE;
661 dns_resolver_t *resolver;
662 uint32_t resolver_if_index;
663 SCNetworkReachabilityPrivateRef targetPrivate;
664
665 target = _setupReachability(argc, argv, NULL);
666
667 targetPrivate = (SCNetworkReachabilityPrivateRef)target;
668
669 if (targetPrivate->type != reachabilityTypeName) {
670 SCPrint(TRUE, stdout, CFSTR("\"%s\" is not a hostname.\n"), argv[0]);
671 exit(1);
672 }
673
674 ok = __SC_checkResolverReachabilityInternal(&store, &flags,
675 &haveDNS, targetPrivate->name,
676 &resolver_if_index, &dns_config_index);
677
678 if (!ok) {
679 SCPrint(TRUE, stdout, CFSTR("No DNS configuration available.\n" ));
680 exit(1);
681 }
682
683 SCPrint(TRUE, stdout, CFSTR("DNS configuration for %s\n"),
684 targetPrivate->name);
685
686 if (targetPrivate->if_index == 0) {
687 resolver = dns_config->resolver[dns_config_index];
688 } else {
689 resolver = dns_config->scoped_resolver[dns_config_index];
690 }
691
692 _dns_resolver_print(resolver, dns_config_index + 1);
693
694 if (target != NULL) CFRelease(target);
695 } else {
696 _dns_configuration_print(dns_config);
697 }
698
699 if (_sc_debug) {
700 SCPrint(TRUE, stdout, CFSTR("\ngeneration = %lu\n"), dns_config->generation);
701 }
702
703 dns_configuration_free(dns_config);
704 exit(0);
705 }
706
707
708 static void
709 showProxy(CFDictionaryRef proxy)
710 {
711 CFMutableDictionaryRef cleaned = NULL;
712
713 if (!_sc_debug) {
714 cleaned = CFDictionaryCreateMutableCopy(NULL, 0, proxy);
715 CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesScoped);
716 CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesServices);
717 CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesSupplemental);
718 proxy = cleaned;
719 }
720
721 SCPrint(TRUE, stdout, CFSTR("%@\n"), proxy);
722 if (cleaned != NULL) CFRelease(cleaned);
723 return;
724 }
725
726
727 __private_extern__
728 void
729 do_showProxyConfiguration(int argc, char **argv)
730 {
731 CFMutableDictionaryRef options = NULL;
732 CFDictionaryRef proxies;
733
734 if (getenv("BYPASS_GLOBAL_PROXY") != NULL) {
735 options = CFDictionaryCreateMutable(NULL, 0,
736 &kCFTypeDictionaryKeyCallBacks,
737 &kCFTypeDictionaryValueCallBacks);
738 CFDictionaryAddValue(options, kSCProxiesNoGlobal, kCFBooleanTrue);
739 }
740
741 proxies = SCDynamicStoreCopyProxiesWithOptions(NULL, options);
742
743 if (options != NULL) {
744 CFRelease(options);
745 }
746
747 if (proxies != NULL) {
748 CFStringRef interface = NULL;
749 CFStringRef server = NULL;
750
751 while (argc > 0) {
752 if (strcasecmp(argv[0], "interface") == 0) {
753 argv++;
754 argc--;
755
756 if (argc < 1) {
757 SCPrint(TRUE, stderr, CFSTR("No interface\n"));
758 exit(1);
759 }
760
761 if (if_nametoindex(argv[0]) == 0) {
762 SCPrint(TRUE, stderr, CFSTR("No interface: %s\n"), argv[0]);
763 exit(1);
764 }
765
766 interface = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
767 argv++;
768 argc--;
769 } else {
770 if (server != NULL) {
771 CFRelease(server);
772 }
773
774 server = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
775 argv++;
776 argc--;
777 }
778 }
779
780 if ((server != NULL) || (interface != NULL)) {
781 CFArrayRef matching;
782
783 matching = SCNetworkProxiesCopyMatching(proxies, server, interface);
784 if (matching != NULL) {
785 CFIndex i;
786 CFIndex n;
787
788 if (server != NULL) {
789 if (interface != NULL) {
790 SCPrint(TRUE, stdout,
791 CFSTR("server = %@, interface = %@\n"),
792 server,
793 interface);
794 } else {
795 SCPrint(TRUE, stdout,
796 CFSTR("server = %@\n"),
797 server);
798 }
799 } else {
800 SCPrint(TRUE, stdout,
801 CFSTR("interface = %@\n"),
802 interface);
803 }
804
805 n = CFArrayGetCount(matching);
806 for (i = 0; i < n; i++) {
807 CFDictionaryRef proxy;
808
809 proxy = CFArrayGetValueAtIndex(matching, i);
810 SCPrint(TRUE, stdout, CFSTR("\nproxy #%d\n"), i + 1);
811 showProxy(proxy);
812 }
813
814 CFRelease(matching);
815 } else {
816 SCPrint(TRUE, stdout, CFSTR("No matching proxy configurations\n"));
817 }
818 } else {
819 showProxy(proxies);
820 }
821
822 if (interface != NULL) CFRelease(interface);
823 if (server != NULL) CFRelease(server);
824 CFRelease(proxies);
825 } else {
826 SCPrint(TRUE, stdout, CFSTR("No proxy configuration available\n"));
827 }
828
829 exit(0);
830 }
831
832
833 __private_extern__
834 void
835 do_snapshot(int argc, char **argv)
836 {
837 if (!SCDynamicStoreSnapshot(store)) {
838 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
839 }
840
841 #ifdef HAVE_REACHABILITY_SERVER
842 (void) _SCNetworkReachabilityServer_snapshot();
843 #endif // HAVE_REACHABILITY_SERVER
844
845 return;
846 }
847
848
849 __private_extern__
850 void
851 do_renew(char *if_name)
852 {
853 CFArrayRef services;
854 Boolean ok = FALSE;
855
856 if ((if_name == NULL) || (strlen(if_name) == 0)) {
857 SCPrint(TRUE, stderr, CFSTR("No interface name\n"));
858 exit(1);
859 }
860
861 if (getenv("ATTEMPT_DHCP_RENEW_WITH_SCDYNAMICSTORE") != NULL) {
862 CFArrayRef interfaces;
863
864 interfaces = SCNetworkInterfaceCopyAll();
865 if (interfaces != NULL) {
866 CFIndex i;
867 CFStringRef match_name;
868 CFIndex n;
869
870 match_name = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII);
871 assert(match_name != NULL);
872
873 n = CFArrayGetCount(interfaces);
874 for (i = 0; i < n; i++) {
875 CFStringRef bsd_name;
876 SCNetworkInterfaceRef interface;
877
878 interface = CFArrayGetValueAtIndex(interfaces, i);
879 bsd_name = SCNetworkInterfaceGetBSDName(interface);
880 if (_SC_CFEqual(bsd_name, match_name)) {
881 // if match
882 ok = SCNetworkInterfaceForceConfigurationRefresh(interface);
883 if (!ok) {
884 int status;
885
886 status = SCError();
887 if (status != kSCStatusAccessError) {
888 SCPrint(TRUE, stderr, CFSTR("%s\n"), SCErrorString(status));
889 exit(1);
890 }
891
892 // ... and if can't write the SCDynamicStore, try w/prefs
893 }
894
895 break;
896 }
897 }
898
899 CFRelease(match_name);
900 CFRelease(interfaces);
901 }
902
903 if (ok) {
904 exit(0);
905 }
906 }
907
908 do_prefs_init(); /* initialization */
909 do_prefs_open(0, NULL); /* open default prefs */
910
911 services = SCNetworkServiceCopyAll(prefs);
912 if (services != NULL) {
913 CFIndex i;
914 CFStringRef match_name;
915 CFIndex n;
916
917 match_name = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII);
918 assert(match_name != NULL);
919
920 n = CFArrayGetCount(services);
921 for (i = 0; i < n; i++) {
922 CFStringRef bsd_name;
923 SCNetworkInterfaceRef interface;
924 SCNetworkServiceRef service;
925
926 service = CFArrayGetValueAtIndex(services, i);
927 interface = SCNetworkServiceGetInterface(service);
928 if (interface == NULL) {
929 // if no interface
930 continue;
931 }
932
933 bsd_name = SCNetworkInterfaceGetBSDName(interface);
934 if (_SC_CFEqual(bsd_name, match_name)) {
935 // if match
936 ok = SCNetworkInterfaceForceConfigurationRefresh(interface);
937 if (!ok) {
938 SCPrint(TRUE, stderr, CFSTR("%s\n"), SCErrorString(SCError()));
939 exit(1);
940 }
941
942 break;
943 }
944 }
945
946 CFRelease(match_name);
947 CFRelease(services);
948 }
949
950 if (!ok) {
951 SCPrint(TRUE, stderr, CFSTR("No interface\n"));
952 exit(1);
953 }
954
955 _prefs_close();
956 exit(0);
957 }
958
959
960 static void
961 waitKeyFound()
962 {
963 exit(0);
964 }
965
966
967 static void
968 waitTimeout(int sigraised)
969 {
970 exit(1);
971 }
972
973
974 __private_extern__
975 void
976 do_wait(char *waitKey, int timeout)
977 {
978 struct itimerval itv;
979 CFStringRef key;
980 CFMutableArrayRef keys;
981 Boolean ok;
982
983 store = SCDynamicStoreCreate(NULL, CFSTR("scutil (wait)"), waitKeyFound, NULL);
984 if (store == NULL) {
985 SCPrint(TRUE, stderr,
986 CFSTR("SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
987 exit(1);
988 }
989
990 key = CFStringCreateWithCString(NULL, waitKey, kCFStringEncodingUTF8);
991
992 keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
993 CFArrayAppendValue(keys, key);
994 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL);
995 CFRelease(keys);
996 if (!ok) {
997 SCPrint(TRUE, stderr,
998 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s\n"), SCErrorString(SCError()));
999 exit(1);
1000 }
1001
1002 notifyRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
1003 if (!notifyRls) {
1004 SCPrint(TRUE, stderr,
1005 CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s\n"), SCErrorString(SCError()));
1006 exit(1);
1007 }
1008
1009 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifyRls, kCFRunLoopDefaultMode);
1010
1011 value = SCDynamicStoreCopyValue(store, key);
1012 if (value) {
1013 /* if the key is already present */
1014 exit(0);
1015 }
1016 CFRelease(key);
1017
1018 if (timeout > 0) {
1019 signal(SIGALRM, waitTimeout);
1020 bzero(&itv, sizeof(itv));
1021 itv.it_value.tv_sec = timeout;
1022 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
1023 SCPrint(TRUE, stderr,
1024 CFSTR("setitimer() failed: %s\n"), strerror(errno));
1025 exit(1);
1026 }
1027 }
1028
1029 CFRunLoopRun();
1030 }
1031
1032 #ifdef TEST_DNS_CONFIGURATION
1033
1034 Boolean doDispatch = FALSE;
1035 CFRunLoopSourceRef notifyRls = NULL;
1036 SCDynamicStoreRef store = NULL;
1037 CFPropertyListRef value = NULL;
1038
1039 int
1040 main(int argc, char **argv)
1041 {
1042 dns_config_t *dns_config;
1043
1044 fprintf(stdout, "copy configuration\n");
1045 dns_config = dns_configuration_copy();
1046 if (dns_config != NULL) {
1047
1048 fprintf(stdout, "sleeping for 120 seconds\n");
1049 sleep(120);
1050
1051 fprintf(stdout, "sending ack\n");
1052 _dns_configuration_ack(dns_config, "TEST_DNS_CONFIGURATION");
1053
1054 fprintf(stdout, "sleeping for 120 seconds\n");
1055 sleep(120);
1056
1057 dns_configuration_free(dns_config);
1058 }
1059
1060 do_showDNSConfiguration(argc, argv);
1061 exit(0);
1062 }
1063
1064 #endif // TEST_DNS_CONFIGURATION