]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/tests.c
471ac4c67cadfd683b03cde4e7f8c517054e7036
[apple/configd.git] / scutil.tproj / tests.c
1 /*
2 * Copyright (c) 2000, 2001, 2003-2005, 2007-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 * 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 "tests.h"
41
42 #include <netdb.h>
43 #include <netdb_async.h>
44 #include <sys/time.h>
45 #include <net/if.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48
49 #include <dnsinfo.h>
50
51 static SCNetworkReachabilityRef
52 _setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
53 {
54 char *ip_address = argv[0];
55 const char *interface;
56 struct sockaddr_in sin;
57 struct sockaddr_in6 sin6;
58 SCNetworkReachabilityRef target = NULL;
59
60 bzero(&sin, sizeof(sin));
61 sin.sin_len = sizeof(sin);
62 sin.sin_family = AF_INET;
63
64 bzero(&sin6, sizeof(sin6));
65 sin6.sin6_len = sizeof(sin6);
66 sin6.sin6_family = AF_INET6;
67
68 interface = strchr(argv[0], '%');
69 if (interface != NULL) {
70 ip_address = strdup(argv[0]);
71 ip_address[interface - argv[0]] = '\0';
72 interface++;
73 }
74
75 if (inet_aton(ip_address, &sin.sin_addr) == 1) {
76 if (argc == 1) {
77 if (interface == NULL) {
78 target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin);
79 if (context != NULL) {
80 context->info = "by address";
81 }
82 } else {
83 CFDataRef data;
84 CFStringRef str;
85 CFMutableDictionaryRef options;
86
87 if (if_nametoindex(interface) == 0) {
88 SCPrint(TRUE, stderr, CFSTR("No interface: %s\n"), interface);
89 exit(1);
90 }
91
92 options = CFDictionaryCreateMutable(NULL,
93 0,
94 &kCFTypeDictionaryKeyCallBacks,
95 &kCFTypeDictionaryValueCallBacks);
96 data = CFDataCreate(NULL, (const UInt8 *)&sin, sizeof(sin));
97 CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
98 CFRelease(data);
99 str = CFStringCreateWithCString(NULL, interface, kCFStringEncodingASCII);
100 CFDictionarySetValue(options, kSCNetworkReachabilityOptionInterface, str);
101 CFRelease(str);
102 target = SCNetworkReachabilityCreateWithOptions(NULL, options);
103 if (context != NULL) {
104 context->info = "by address w/scope";
105 }
106 CFRelease(options);
107 }
108 } else {
109 char *remote_address = argv[1];
110 const char *interface2;
111 struct sockaddr_in r_sin;
112
113 interface2 = strchr(argv[1], '%');
114 if (interface2 != NULL) {
115 remote_address = strdup(argv[1]);
116 remote_address[interface2 - argv[1]] = '\0';
117 interface2++;
118
119 if ((interface != NULL) && (strcmp(interface, interface2) != 0)) {
120 SCPrint(TRUE, stderr,
121 CFSTR("Interface mismatch \"%s\" != \"%s\"\n"),
122 interface,
123 interface2);
124 exit(1);
125 }
126
127 interface = interface2;
128 }
129
130 bzero(&r_sin, sizeof(r_sin));
131 r_sin.sin_len = sizeof(r_sin);
132 r_sin.sin_family = AF_INET;
133 if (inet_aton(remote_address, &r_sin.sin_addr) == 0) {
134 SCPrint(TRUE, stderr, CFSTR("Could not interpret address \"%s\"\n"), remote_address);
135 exit(1);
136 }
137
138 if (remote_address != argv[1]) {
139 free(remote_address);
140 }
141
142 if (interface == NULL) {
143 target = SCNetworkReachabilityCreateWithAddressPair(NULL,
144 (struct sockaddr *)&sin,
145 (struct sockaddr *)&r_sin);
146 if (context != NULL) {
147 context->info = "by address pair";
148 }
149 } else {
150 CFDataRef data;
151 CFStringRef str;
152 CFMutableDictionaryRef options;
153
154 if (if_nametoindex(interface) == 0) {
155 SCPrint(TRUE, stderr, CFSTR("No interface: %s\n"), interface);
156 exit(1);
157 }
158
159 options = CFDictionaryCreateMutable(NULL,
160 0,
161 &kCFTypeDictionaryKeyCallBacks,
162 &kCFTypeDictionaryValueCallBacks);
163 data = CFDataCreate(NULL, (const UInt8 *)&sin, sizeof(sin));
164 CFDictionarySetValue(options, kSCNetworkReachabilityOptionLocalAddress, data);
165 CFRelease(data);
166 data = CFDataCreate(NULL, (const UInt8 *)&r_sin, sizeof(r_sin));
167 CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
168 CFRelease(data);
169 str = CFStringCreateWithCString(NULL, interface, kCFStringEncodingASCII);
170 CFDictionarySetValue(options, kSCNetworkReachabilityOptionInterface, str);
171 CFRelease(str);
172 target = SCNetworkReachabilityCreateWithOptions(NULL, options);
173 if (context != NULL) {
174 context->info = "by address pair w/scope";
175 }
176 CFRelease(options);
177 }
178 }
179 } else if (inet_pton(AF_INET6, argv[0], &sin6.sin6_addr) == 1) {
180 if (interface != NULL) {
181 sin6.sin6_scope_id = if_nametoindex(interface);
182 }
183
184 if (argc == 1) {
185 target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin6);
186 if (context != NULL) {
187 context->info = "by (v6) address";
188 }
189 } else {
190 struct sockaddr_in6 r_sin6;
191
192 bzero(&r_sin6, sizeof(r_sin6));
193 r_sin6.sin6_len = sizeof(r_sin6);
194 r_sin6.sin6_family = AF_INET6;
195 if (inet_pton(AF_INET6, argv[1], &r_sin6.sin6_addr) == 0) {
196 SCPrint(TRUE, stderr, CFSTR("Could not interpret address \"%s\"\n"), argv[1]);
197 exit(1);
198 }
199
200 interface = strchr(argv[1], '%');
201 if (interface != NULL) {
202 r_sin6.sin6_scope_id = if_nametoindex(interface);
203 }
204
205 target = SCNetworkReachabilityCreateWithAddressPair(NULL,
206 (struct sockaddr *)&sin6,
207 (struct sockaddr *)&r_sin6);
208 if (context != NULL) {
209 context->info = "by (v6) address pair";
210 }
211 }
212 } else {
213 if (argc == 1) {
214 target = SCNetworkReachabilityCreateWithName(NULL, argv[0]);
215 if (context != NULL) {
216 context->info = "by name";
217 }
218 } else {
219 CFStringRef str;
220 CFMutableDictionaryRef options;
221
222 options = CFDictionaryCreateMutable(NULL,
223 0,
224 &kCFTypeDictionaryKeyCallBacks,
225 &kCFTypeDictionaryValueCallBacks);
226 if (strlen(argv[0]) > 0) {
227 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
228 CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
229 CFRelease(str);
230 }
231 if (strlen(argv[1]) > 0) {
232 str = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
233 CFDictionarySetValue(options, kSCNetworkReachabilityOptionServName, str);
234 CFRelease(str);
235 }
236 if (argc > 2) {
237 CFDataRef data;
238 struct addrinfo hints = { 0 };
239 int i;
240 int n_hints = 0;
241
242 for (i = 2; i < argc; i++) {
243 if (strcasecmp(argv[i], "interface") == 0) {
244 if (++i >= argc) {
245 SCPrint(TRUE, stderr, CFSTR("No interface\n"));
246 CFRelease(options);
247 exit(1);
248 }
249 if (if_nametoindex(argv[i]) == 0) {
250 SCPrint(TRUE, stderr, CFSTR("No interface: %s\n"), argv[i]);
251 CFRelease(options);
252 exit(1);
253 }
254 str = CFStringCreateWithCString(NULL, argv[i], kCFStringEncodingASCII);
255 CFDictionarySetValue(options, kSCNetworkReachabilityOptionInterface, str);
256 CFRelease(str);
257 continue;
258 }
259
260 if (strcasecmp(argv[i], "AI_ADDRCONFIG") == 0) {
261 hints.ai_flags |= AI_ADDRCONFIG;
262 } else if (strcasecmp(argv[i], "AI_ALL") == 0) {
263 hints.ai_flags |= AI_ALL;
264 } else if (strcasecmp(argv[i], "AI_V4MAPPED") == 0) {
265 hints.ai_flags |= AI_V4MAPPED;
266 } else if (strcasecmp(argv[i], "AI_V4MAPPED_CFG") == 0) {
267 hints.ai_flags |= AI_V4MAPPED_CFG;
268 } else if (strcasecmp(argv[i], "AI_ADDRCONFIG") == 0) {
269 hints.ai_flags |= AI_ADDRCONFIG;
270 } else if (strcasecmp(argv[i], "AI_V4MAPPED") == 0) {
271 hints.ai_flags |= AI_V4MAPPED;
272 } else if (strcasecmp(argv[i], "AI_DEFAULT") == 0) {
273 hints.ai_flags |= AI_DEFAULT;
274 #ifdef AI_PARALLEL
275 } else if (strcasecmp(argv[i], "AI_PARALLEL") == 0) {
276 hints.ai_flags |= AI_PARALLEL;
277 #endif // AI_PARALLEL
278 } else if (strcasecmp(argv[i], "PF_INET") == 0) {
279 hints.ai_family = PF_INET;
280 } else if (strcasecmp(argv[i], "PF_INET6") == 0) {
281 hints.ai_family = PF_INET6;
282 } else if (strcasecmp(argv[i], "SOCK_STREAM") == 0) {
283 hints.ai_socktype = SOCK_STREAM;
284 } else if (strcasecmp(argv[i], "SOCK_DGRAM") == 0) {
285 hints.ai_socktype = SOCK_DGRAM;
286 } else if (strcasecmp(argv[i], "SOCK_RAW") == 0) {
287 hints.ai_socktype = SOCK_RAW;
288 } else if (strcasecmp(argv[i], "IPPROTO_TCP") == 0) {
289 hints.ai_protocol = IPPROTO_TCP;
290 } else if (strcasecmp(argv[i], "IPPROTO_UDP") == 0) {
291 hints.ai_protocol = IPPROTO_UDP;
292 } else {
293 SCPrint(TRUE, stderr, CFSTR("Unrecognized hint: %s\n"), argv[i]);
294 CFRelease(options);
295 exit(1);
296 }
297 n_hints++;
298 }
299
300 if (n_hints > 0) {
301 data = CFDataCreate(NULL, (const UInt8 *)&hints, sizeof(hints));
302 CFDictionarySetValue(options, kSCNetworkReachabilityOptionHints, data);
303 CFRelease(data);
304 }
305 }
306 if (CFDictionaryGetCount(options) > 0) {
307 target = SCNetworkReachabilityCreateWithOptions(NULL, options);
308 if (context != NULL) {
309 context->info = "by (node and/or serv) name";
310 }
311 } else {
312 SCPrint(TRUE, stderr, CFSTR("Must specify nodename or servname\n"));
313 CFRelease(options);
314 exit(1);
315 }
316 CFRelease(options);
317 }
318 }
319
320 if (ip_address != argv[0]) {
321 free(ip_address);
322 }
323
324 return target;
325 }
326
327 static void
328 _printReachability(SCNetworkReachabilityRef target)
329 {
330 SCNetworkReachabilityFlags flags;
331 Boolean ok;
332
333 ok = SCNetworkReachabilityGetFlags(target, &flags);
334 if (!ok) {
335 printf(" could not determine reachability, %s\n", SCErrorString(SCError()));
336 return;
337 }
338
339 SCPrint(_sc_debug, stdout, CFSTR("flags = 0x%08x"), flags);
340 if (flags != 0) {
341 SCPrint(_sc_debug, stdout, CFSTR(" ("));
342 if (flags & kSCNetworkReachabilityFlagsReachable) {
343 SCPrint(TRUE, stdout, CFSTR("Reachable"));
344 flags &= ~kSCNetworkReachabilityFlagsReachable;
345 SCPrint(flags != 0, stdout, CFSTR(","));
346 }
347 if (flags & kSCNetworkReachabilityFlagsTransientConnection) {
348 SCPrint(TRUE, stdout, CFSTR("Transient Connection"));
349 flags &= ~kSCNetworkReachabilityFlagsTransientConnection;
350 SCPrint(flags != 0, stdout, CFSTR(","));
351 }
352 if (flags & kSCNetworkReachabilityFlagsConnectionRequired) {
353 SCPrint(TRUE, stdout, CFSTR("Connection Required"));
354 flags &= ~kSCNetworkReachabilityFlagsConnectionRequired;
355 SCPrint(flags != 0, stdout, CFSTR(","));
356 }
357 if (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) {
358 SCPrint(TRUE, stdout, CFSTR("Automatic Connection On Traffic"));
359 flags &= ~kSCNetworkReachabilityFlagsConnectionOnTraffic;
360 SCPrint(flags != 0, stdout, CFSTR(","));
361 }
362 if (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) {
363 SCPrint(TRUE, stdout, CFSTR("Automatic Connection On Demand"));
364 flags &= ~kSCNetworkReachabilityFlagsConnectionOnDemand;
365 SCPrint(flags != 0, stdout, CFSTR(","));
366 }
367 if (flags & kSCNetworkReachabilityFlagsInterventionRequired) {
368 SCPrint(TRUE, stdout, CFSTR("Intervention Required"));
369 flags &= ~kSCNetworkReachabilityFlagsInterventionRequired;
370 SCPrint(flags != 0, stdout, CFSTR(","));
371 }
372 if (flags & kSCNetworkReachabilityFlagsIsLocalAddress) {
373 SCPrint(TRUE, stdout, CFSTR("Local Address"));
374 flags &= ~kSCNetworkReachabilityFlagsIsLocalAddress;
375 SCPrint(flags != 0, stdout, CFSTR(","));
376 }
377 if (flags & kSCNetworkReachabilityFlagsIsDirect) {
378 SCPrint(TRUE, stdout, CFSTR("Directly Reachable Address"));
379 flags &= ~kSCNetworkReachabilityFlagsIsDirect;
380 SCPrint(flags != 0, stdout, CFSTR(","));
381 }
382 #if TARGET_OS_IPHONE
383 if (flags & kSCNetworkReachabilityFlagsIsWWAN) {
384 SCPrint(TRUE, stdout, CFSTR("WWAN"));
385 flags &= ~kSCNetworkReachabilityFlagsIsWWAN;
386 SCPrint(flags != 0, stdout, CFSTR(","));
387 }
388 #endif // TARGET_OS_IPHONE
389 if (flags != 0) {
390 SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags);
391 }
392 SCPrint(_sc_debug, stdout, CFSTR(")"));
393 } else {
394 SCPrint(_sc_debug, stdout, CFSTR(" ("));
395 SCPrint(TRUE, stdout, CFSTR("Not Reachable"));
396 SCPrint(_sc_debug, stdout, CFSTR(")"));
397 }
398 SCPrint(TRUE, stdout, CFSTR("\n"));
399
400 return;
401 }
402
403
404 __private_extern__
405 void
406 do_checkReachability(int argc, char **argv)
407 {
408 SCNetworkReachabilityRef target;
409
410 target = _setupReachability(argc, argv, NULL);
411 if (target == NULL) {
412 SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
413 exit(1);
414 }
415
416 _printReachability(target);
417 CFRelease(target);
418 exit(0);
419 }
420
421
422 static void
423 callout(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
424 {
425 static int n = 3;
426 struct tm tm_now;
427 struct timeval tv_now;
428
429 (void)gettimeofday(&tv_now, NULL);
430 (void)localtime_r(&tv_now.tv_sec, &tm_now);
431
432 SCPrint(TRUE, stdout, CFSTR("\n*** %2d:%02d:%02d.%03d\n\n"),
433 tm_now.tm_hour,
434 tm_now.tm_min,
435 tm_now.tm_sec,
436 tv_now.tv_usec / 1000);
437 SCPrint(TRUE, stdout, CFSTR("%2d: callback w/flags=0x%08x (info=\"%s\")\n"), n++, flags, (char *)info);
438 SCPrint(TRUE, stdout, CFSTR(" %@\n"), target);
439 _printReachability(target);
440 SCPrint(TRUE, stdout, CFSTR("\n"));
441 return;
442 }
443
444
445 __private_extern__
446 void
447 do_watchReachability(int argc, char **argv)
448 {
449 SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL };
450 SCNetworkReachabilityRef target;
451 SCNetworkReachabilityRef target_async;
452
453 target = _setupReachability(argc, argv, NULL);
454 if (target == NULL) {
455 SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
456 exit(1);
457 }
458
459 target_async = _setupReachability(argc, argv, &context);
460 if (target_async == NULL) {
461 SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
462 exit(1);
463 }
464
465 // Normally, we don't want to make any calls to SCNetworkReachabilityGetFlags()
466 // until after the "target" has been scheduled on a run loop. Otherwise, we'll
467 // end up making a synchronous DNS request and that's not what we want.
468 //
469 // But, to test the case were an application call SCNetworkReachabilityGetFlags()
470 // we provide the "CHECK_REACHABILITY_BEFORE_SCHEDULING" environment variable.
471 if (getenv("CHECK_REACHABILITY_BEFORE_SCHEDULING") != NULL) {
472 CFRelease(target_async);
473 target_async = CFRetain(target);
474 }
475
476 // Direct check of reachability
477 SCPrint(TRUE, stdout, CFSTR(" 0: direct\n"));
478 SCPrint(TRUE, stdout, CFSTR(" %@\n"), target);
479 _printReachability(target);
480 CFRelease(target);
481 SCPrint(TRUE, stdout, CFSTR("\n"));
482
483 // schedule the target
484 SCPrint(TRUE, stdout, CFSTR(" 1: start\n"));
485 SCPrint(TRUE, stdout, CFSTR(" %@\n"), target_async);
486 //_printReachability(target_async);
487 SCPrint(TRUE, stdout, CFSTR("\n"));
488
489 if (!SCNetworkReachabilitySetCallback(target_async, callout, &context)) {
490 printf("SCNetworkReachabilitySetCallback() failed: %s\n", SCErrorString(SCError()));
491 exit(1);
492 }
493
494 if (doDispatch) {
495 if (!SCNetworkReachabilitySetDispatchQueue(target_async, dispatch_get_current_queue())) {
496 printf("SCNetworkReachabilitySetDispatchQueue() failed: %s\n", SCErrorString(SCError()));
497 exit(1);
498 }
499 } else {
500 if (!SCNetworkReachabilityScheduleWithRunLoop(target_async, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
501 printf("SCNetworkReachabilityScheduleWithRunLoop() failed: %s\n", SCErrorString(SCError()));
502 exit(1);
503 }
504 }
505
506 // Note: now that we are scheduled on a run loop we can call SCNetworkReachabilityGetFlags()
507 // to get the current status. For "names", a DNS lookup has already been initiated.
508 SCPrint(TRUE, stdout, CFSTR(" 2: on %s\n"), doDispatch ? "dispatch queue" : "runloop");
509 SCPrint(TRUE, stdout, CFSTR(" %@\n"), target_async);
510 _printReachability(target_async);
511 SCPrint(TRUE, stdout, CFSTR("\n"));
512
513 CFRunLoopRun();
514 exit(0);
515 }
516
517
518 static void
519 showResolver(dns_resolver_t *resolver, int index)
520 {
521 int i;
522
523 SCPrint(TRUE, stdout, CFSTR("\nresolver #%d\n"), index);
524
525 if (resolver->domain != NULL) {
526 SCPrint(TRUE, stdout, CFSTR(" domain : %s\n"), resolver->domain);
527 }
528
529 for (i = 0; i < resolver->n_search; i++) {
530 SCPrint(TRUE, stdout, CFSTR(" search domain[%d] : %s\n"), i, resolver->search[i]);
531 }
532
533 for (i = 0; i < resolver->n_nameserver; i++) {
534 char buf[128];
535
536 _SC_sockaddr_to_string(resolver->nameserver[i], buf, sizeof(buf));
537 SCPrint(TRUE, stdout, CFSTR(" nameserver[%d] : %s\n"), i, buf);
538 }
539
540 for (i = 0; i < resolver->n_sortaddr; i++) {
541 char abuf[32];
542 char mbuf[32];
543
544 (void)inet_ntop(AF_INET, &resolver->sortaddr[i]->address, abuf, sizeof(abuf));
545 (void)inet_ntop(AF_INET, &resolver->sortaddr[i]->mask, mbuf, sizeof(mbuf));
546 SCPrint(TRUE, stdout, CFSTR(" sortaddr[%d] : %s/%s\n"), i, abuf, mbuf);
547 }
548
549 if (resolver->options != NULL) {
550 SCPrint(TRUE, stdout, CFSTR(" options : %s\n"), resolver->options);
551 }
552
553 if (resolver->port != 0) {
554 SCPrint(TRUE, stdout, CFSTR(" port : %hd\n"), resolver->port);
555 }
556
557 if (resolver->timeout != 0) {
558 SCPrint(TRUE, stdout, CFSTR(" timeout : %d\n"), resolver->timeout);
559 }
560
561 if (resolver->if_index != 0) {
562 char buf[IFNAMSIZ];
563 char *if_name;
564
565 if_name = if_indextoname(resolver->if_index, buf);
566 SCPrint(TRUE, stdout, CFSTR(" if_index : %d (%s)\n"),
567 resolver->if_index,
568 (if_name != NULL) ? if_name : "?");
569 }
570
571 if (resolver->flags != 0) {
572 uint32_t flags = resolver->flags;
573
574 SCPrint(TRUE, stdout, CFSTR(" flags : "));
575 if (flags & DNS_RESOLVER_FLAGS_SCOPED) {
576 SCPrint(TRUE, stdout, CFSTR("Scoped"));
577 flags &= ~DNS_RESOLVER_FLAGS_SCOPED;
578 SCPrint(flags != 0, stdout, CFSTR(","));
579 }
580 if (flags != 0) {
581 SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags);
582 }
583 SCPrint(TRUE, stdout, CFSTR("\n"));
584 }
585
586 if (resolver->search_order != 0) {
587 SCPrint(TRUE, stdout, CFSTR(" order : %d\n"), resolver->search_order);
588 }
589
590 return;
591 }
592
593
594 __private_extern__
595 void
596 do_showDNSConfiguration(int argc, char **argv)
597 {
598 dns_config_t *dns_config;
599
600 dns_config = dns_configuration_copy();
601 if (dns_config) {
602 int i;
603
604 SCPrint(TRUE, stdout, CFSTR("DNS configuration\n"));
605
606 for (i = 0; i < dns_config->n_resolver; i++) {
607 dns_resolver_t *resolver = dns_config->resolver[i];
608
609 showResolver(resolver, i + 1);
610 }
611
612 if ((dns_config->n_scoped_resolver > 0) && (dns_config->scoped_resolver != NULL)) {
613 SCPrint(TRUE, stdout, CFSTR("\nDNS configuration (for scoped queries)\n"));
614
615 for (i = 0; i < dns_config->n_scoped_resolver; i++) {
616 dns_resolver_t *resolver = dns_config->scoped_resolver[i];
617
618 showResolver(resolver, i + 1);
619 }
620 }
621
622 dns_configuration_free(dns_config);
623 } else {
624 SCPrint(TRUE, stdout, CFSTR("No DNS configuration available\n"));
625 }
626
627 exit(0);
628 }
629
630
631 static void
632 showProxy(CFDictionaryRef proxy)
633 {
634 CFMutableDictionaryRef cleaned = NULL;
635
636 if (!_sc_debug) {
637 cleaned = CFDictionaryCreateMutableCopy(NULL, 0, proxy);
638 CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesSupplemental);
639 CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesScoped);
640 proxy = cleaned;
641 }
642
643 SCPrint(TRUE, stdout, CFSTR("%@\n"), proxy);
644 if (cleaned != NULL) CFRelease(cleaned);
645 return;
646 }
647
648
649 __private_extern__
650 void
651 do_showProxyConfiguration(int argc, char **argv)
652 {
653 CFDictionaryRef proxies;
654
655 proxies = SCDynamicStoreCopyProxies(NULL);
656 if (proxies != NULL) {
657 CFStringRef interface = NULL;
658 CFStringRef server = NULL;
659
660 while (argc > 0) {
661 if (strcasecmp(argv[0], "interface") == 0) {
662 argv++;
663 argc--;
664
665 if (argc < 1) {
666 SCPrint(TRUE, stderr, CFSTR("No interface\n"));
667 exit(1);
668 }
669
670 if (if_nametoindex(argv[0]) == 0) {
671 SCPrint(TRUE, stderr, CFSTR("No interface: %s\n"), argv[0]);
672 exit(1);
673 }
674
675 interface = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
676 argv++;
677 argc--;
678 } else {
679 if (server != NULL) {
680 CFRelease(server);
681 }
682
683 server = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
684 argv++;
685 argc--;
686 }
687 }
688
689 if ((server != NULL) || (interface != NULL)) {
690 CFArrayRef matching;
691
692 matching = SCNetworkProxiesCopyMatching(proxies, server, interface);
693 if (matching != NULL) {
694 CFIndex i;
695 CFIndex n;
696
697 if (server != NULL) {
698 if (interface != NULL) {
699 SCPrint(TRUE, stdout,
700 CFSTR("server = %@, interface = %@\n"),
701 server,
702 interface);
703 } else {
704 SCPrint(TRUE, stdout,
705 CFSTR("server = %@\n"),
706 server);
707 }
708 } else {
709 SCPrint(TRUE, stdout,
710 CFSTR("interface = %@\n"),
711 interface);
712 }
713
714 n = CFArrayGetCount(matching);
715 for (i = 0; i < n; i++) {
716 CFDictionaryRef proxy;
717
718 proxy = CFArrayGetValueAtIndex(matching, i);
719 SCPrint(TRUE, stdout, CFSTR("\nproxy #%d\n"), i + 1);
720 showProxy(proxy);
721 }
722
723 CFRelease(matching);
724 } else {
725 SCPrint(TRUE, stdout, CFSTR("No matching proxy configurations\n"));
726 }
727 } else {
728 showProxy(proxies);
729 }
730
731 if (interface != NULL) CFRelease(interface);
732 if (server != NULL) CFRelease(server);
733 CFRelease(proxies);
734 } else {
735 SCPrint(TRUE, stdout, CFSTR("No proxy configuration available\n"));
736 }
737
738 exit(0);
739 }
740
741
742 __private_extern__
743 void
744 do_snapshot(int argc, char **argv)
745 {
746 if (!SCDynamicStoreSnapshot(store)) {
747 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
748 }
749 return;
750 }
751
752
753 static void
754 waitKeyFound()
755 {
756 exit(0);
757 }
758
759
760 static void
761 waitTimeout(int sigraised)
762 {
763 exit(1);
764 }
765
766
767 __private_extern__
768 void
769 do_wait(char *waitKey, int timeout)
770 {
771 struct itimerval itv;
772 CFStringRef key;
773 CFMutableArrayRef keys;
774 Boolean ok;
775
776 store = SCDynamicStoreCreate(NULL, CFSTR("scutil (wait)"), waitKeyFound, NULL);
777 if (store == NULL) {
778 SCPrint(TRUE, stderr,
779 CFSTR("SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
780 exit(1);
781 }
782
783 key = CFStringCreateWithCString(NULL, waitKey, kCFStringEncodingUTF8);
784
785 keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
786 CFArrayAppendValue(keys, key);
787 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL);
788 CFRelease(keys);
789 if (!ok) {
790 SCPrint(TRUE, stderr,
791 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s\n"), SCErrorString(SCError()));
792 exit(1);
793 }
794
795 notifyRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
796 if (!notifyRls) {
797 SCPrint(TRUE, stderr,
798 CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s\n"), SCErrorString(SCError()));
799 exit(1);
800 }
801
802 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifyRls, kCFRunLoopDefaultMode);
803
804 value = SCDynamicStoreCopyValue(store, key);
805 if (value) {
806 /* if the key is already present */
807 exit(0);
808 }
809 CFRelease(key);
810
811 if (timeout > 0) {
812 signal(SIGALRM, waitTimeout);
813 bzero(&itv, sizeof(itv));
814 itv.it_value.tv_sec = timeout;
815 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
816 SCPrint(TRUE, stderr,
817 CFSTR("setitimer() failed: %s\n"), strerror(errno));
818 exit(1);
819 }
820 }
821
822 CFRunLoopRun();
823 }
824
825 #ifdef TEST_DNS_CONFIGURATION_COPY
826
827 CFRunLoopSourceRef notifyRls = NULL;
828 SCDynamicStoreRef store = NULL;
829 CFPropertyListRef value = NULL;
830
831 int
832 main(int argc, char **argv)
833 {
834 do_showDNSConfiguration(argc, argv);
835 exit(0);
836 }
837
838 #endif // TEST_DNS_CONFIGURATION_COPY