2 * Copyright (c) 2000, 2001, 2003-2005, 2007-2011 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
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
32 * June 1, 2001 Allan Nathanson <ajn@apple.com>
33 * - public API conversion
35 * November 9, 2000 Allan Nathanson <ajn@apple.com>
43 #include <netdb_async.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
51 static SCNetworkReachabilityRef
52 _setupReachability(int argc
, char **argv
, SCNetworkReachabilityContext
*context
)
54 char *ip_address
= argv
[0];
55 const char *interface
;
56 struct sockaddr_in sin
;
57 struct sockaddr_in6 sin6
;
58 SCNetworkReachabilityRef target
= NULL
;
60 bzero(&sin
, sizeof(sin
));
61 sin
.sin_len
= sizeof(sin
);
62 sin
.sin_family
= AF_INET
;
64 bzero(&sin6
, sizeof(sin6
));
65 sin6
.sin6_len
= sizeof(sin6
);
66 sin6
.sin6_family
= AF_INET6
;
68 interface
= strchr(argv
[0], '%');
69 if (interface
!= NULL
) {
70 ip_address
= strdup(argv
[0]);
71 ip_address
[interface
- argv
[0]] = '\0';
75 if (inet_aton(ip_address
, &sin
.sin_addr
) == 1) {
77 if (interface
== NULL
) {
78 target
= SCNetworkReachabilityCreateWithAddress(NULL
, (struct sockaddr
*)&sin
);
79 if (context
!= NULL
) {
80 context
->info
= "by address";
85 CFMutableDictionaryRef options
;
87 if (if_nametoindex(interface
) == 0) {
88 SCPrint(TRUE
, stderr
, CFSTR("No interface: %s\n"), interface
);
92 options
= CFDictionaryCreateMutable(NULL
,
94 &kCFTypeDictionaryKeyCallBacks
,
95 &kCFTypeDictionaryValueCallBacks
);
96 data
= CFDataCreate(NULL
, (const UInt8
*)&sin
, sizeof(sin
));
97 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionRemoteAddress
, data
);
99 str
= CFStringCreateWithCString(NULL
, interface
, kCFStringEncodingASCII
);
100 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionInterface
, str
);
102 target
= SCNetworkReachabilityCreateWithOptions(NULL
, options
);
103 if (context
!= NULL
) {
104 context
->info
= "by address w/scope";
109 char *remote_address
= argv
[1];
110 const char *interface2
;
111 struct sockaddr_in r_sin
;
113 interface2
= strchr(argv
[1], '%');
114 if (interface2
!= NULL
) {
115 remote_address
= strdup(argv
[1]);
116 remote_address
[interface2
- argv
[1]] = '\0';
119 if ((interface
!= NULL
) && (strcmp(interface
, interface2
) != 0)) {
120 SCPrint(TRUE
, stderr
,
121 CFSTR("Interface mismatch \"%s\" != \"%s\"\n"),
127 interface
= interface2
;
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
);
138 if (remote_address
!= argv
[1]) {
139 free(remote_address
);
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";
152 CFMutableDictionaryRef options
;
154 if (if_nametoindex(interface
) == 0) {
155 SCPrint(TRUE
, stderr
, CFSTR("No interface: %s\n"), interface
);
159 options
= CFDictionaryCreateMutable(NULL
,
161 &kCFTypeDictionaryKeyCallBacks
,
162 &kCFTypeDictionaryValueCallBacks
);
163 data
= CFDataCreate(NULL
, (const UInt8
*)&sin
, sizeof(sin
));
164 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionLocalAddress
, data
);
166 data
= CFDataCreate(NULL
, (const UInt8
*)&r_sin
, sizeof(r_sin
));
167 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionRemoteAddress
, data
);
169 str
= CFStringCreateWithCString(NULL
, interface
, kCFStringEncodingASCII
);
170 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionInterface
, str
);
172 target
= SCNetworkReachabilityCreateWithOptions(NULL
, options
);
173 if (context
!= NULL
) {
174 context
->info
= "by address pair w/scope";
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
);
185 target
= SCNetworkReachabilityCreateWithAddress(NULL
, (struct sockaddr
*)&sin6
);
186 if (context
!= NULL
) {
187 context
->info
= "by (v6) address";
190 struct sockaddr_in6 r_sin6
;
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]);
200 interface
= strchr(argv
[1], '%');
201 if (interface
!= NULL
) {
202 r_sin6
.sin6_scope_id
= if_nametoindex(interface
);
205 target
= SCNetworkReachabilityCreateWithAddressPair(NULL
,
206 (struct sockaddr
*)&sin6
,
207 (struct sockaddr
*)&r_sin6
);
208 if (context
!= NULL
) {
209 context
->info
= "by (v6) address pair";
214 target
= SCNetworkReachabilityCreateWithName(NULL
, argv
[0]);
215 if (context
!= NULL
) {
216 context
->info
= "by name";
220 CFMutableDictionaryRef options
;
222 options
= CFDictionaryCreateMutable(NULL
,
224 &kCFTypeDictionaryKeyCallBacks
,
225 &kCFTypeDictionaryValueCallBacks
);
226 if (strlen(argv
[0]) > 0) {
227 str
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
228 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionNodeName
, str
);
231 if (strlen(argv
[1]) > 0) {
232 str
= CFStringCreateWithCString(NULL
, argv
[1], kCFStringEncodingUTF8
);
233 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionServName
, str
);
238 struct addrinfo hints
= { 0 };
242 for (i
= 2; i
< argc
; i
++) {
243 if (strcasecmp(argv
[i
], "interface") == 0) {
245 SCPrint(TRUE
, stderr
, CFSTR("No interface\n"));
249 if (if_nametoindex(argv
[i
]) == 0) {
250 SCPrint(TRUE
, stderr
, CFSTR("No interface: %s\n"), argv
[i
]);
254 str
= CFStringCreateWithCString(NULL
, argv
[i
], kCFStringEncodingASCII
);
255 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionInterface
, str
);
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
;
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
;
293 SCPrint(TRUE
, stderr
, CFSTR("Unrecognized hint: %s\n"), argv
[i
]);
301 data
= CFDataCreate(NULL
, (const UInt8
*)&hints
, sizeof(hints
));
302 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionHints
, data
);
306 if (CFDictionaryGetCount(options
) > 0) {
307 target
= SCNetworkReachabilityCreateWithOptions(NULL
, options
);
308 if (context
!= NULL
) {
309 context
->info
= "by (node and/or serv) name";
312 SCPrint(TRUE
, stderr
, CFSTR("Must specify nodename or servname\n"));
320 if (ip_address
!= argv
[0]) {
328 _printReachability(SCNetworkReachabilityRef target
)
330 SCNetworkReachabilityFlags flags
;
333 ok
= SCNetworkReachabilityGetFlags(target
, &flags
);
335 printf(" could not determine reachability, %s\n", SCErrorString(SCError()));
339 SCPrint(_sc_debug
, stdout
, CFSTR("flags = 0x%08x"), flags
);
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(","));
347 if (flags
& kSCNetworkReachabilityFlagsTransientConnection
) {
348 SCPrint(TRUE
, stdout
, CFSTR("Transient Connection"));
349 flags
&= ~kSCNetworkReachabilityFlagsTransientConnection
;
350 SCPrint(flags
!= 0, stdout
, CFSTR(","));
352 if (flags
& kSCNetworkReachabilityFlagsConnectionRequired
) {
353 SCPrint(TRUE
, stdout
, CFSTR("Connection Required"));
354 flags
&= ~kSCNetworkReachabilityFlagsConnectionRequired
;
355 SCPrint(flags
!= 0, stdout
, CFSTR(","));
357 if (flags
& kSCNetworkReachabilityFlagsConnectionOnTraffic
) {
358 SCPrint(TRUE
, stdout
, CFSTR("Automatic Connection On Traffic"));
359 flags
&= ~kSCNetworkReachabilityFlagsConnectionOnTraffic
;
360 SCPrint(flags
!= 0, stdout
, CFSTR(","));
362 if (flags
& kSCNetworkReachabilityFlagsConnectionOnDemand
) {
363 SCPrint(TRUE
, stdout
, CFSTR("Automatic Connection On Demand"));
364 flags
&= ~kSCNetworkReachabilityFlagsConnectionOnDemand
;
365 SCPrint(flags
!= 0, stdout
, CFSTR(","));
367 if (flags
& kSCNetworkReachabilityFlagsInterventionRequired
) {
368 SCPrint(TRUE
, stdout
, CFSTR("Intervention Required"));
369 flags
&= ~kSCNetworkReachabilityFlagsInterventionRequired
;
370 SCPrint(flags
!= 0, stdout
, CFSTR(","));
372 if (flags
& kSCNetworkReachabilityFlagsIsLocalAddress
) {
373 SCPrint(TRUE
, stdout
, CFSTR("Local Address"));
374 flags
&= ~kSCNetworkReachabilityFlagsIsLocalAddress
;
375 SCPrint(flags
!= 0, stdout
, CFSTR(","));
377 if (flags
& kSCNetworkReachabilityFlagsIsDirect
) {
378 SCPrint(TRUE
, stdout
, CFSTR("Directly Reachable Address"));
379 flags
&= ~kSCNetworkReachabilityFlagsIsDirect
;
380 SCPrint(flags
!= 0, stdout
, CFSTR(","));
383 if (flags
& kSCNetworkReachabilityFlagsIsWWAN
) {
384 SCPrint(TRUE
, stdout
, CFSTR("WWAN"));
385 flags
&= ~kSCNetworkReachabilityFlagsIsWWAN
;
386 SCPrint(flags
!= 0, stdout
, CFSTR(","));
388 #endif // TARGET_OS_IPHONE
390 SCPrint(TRUE
, stdout
, CFSTR("0x%08x"), flags
);
392 SCPrint(_sc_debug
, stdout
, CFSTR(")"));
394 SCPrint(_sc_debug
, stdout
, CFSTR(" ("));
395 SCPrint(TRUE
, stdout
, CFSTR("Not Reachable"));
396 SCPrint(_sc_debug
, stdout
, CFSTR(")"));
398 SCPrint(TRUE
, stdout
, CFSTR("\n"));
406 do_checkReachability(int argc
, char **argv
)
408 SCNetworkReachabilityRef target
;
410 target
= _setupReachability(argc
, argv
, NULL
);
411 if (target
== NULL
) {
412 SCPrint(TRUE
, stderr
, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
416 _printReachability(target
);
423 callout(SCNetworkReachabilityRef target
, SCNetworkReachabilityFlags flags
, void *info
)
427 struct timeval tv_now
;
429 (void)gettimeofday(&tv_now
, NULL
);
430 (void)localtime_r(&tv_now
.tv_sec
, &tm_now
);
432 SCPrint(TRUE
, stdout
, CFSTR("\n*** %2d:%02d:%02d.%03d\n\n"),
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"));
447 do_watchReachability(int argc
, char **argv
)
449 SCNetworkReachabilityContext context
= { 0, NULL
, NULL
, NULL
, NULL
};
450 SCNetworkReachabilityRef target
;
451 SCNetworkReachabilityRef target_async
;
453 target
= _setupReachability(argc
, argv
, NULL
);
454 if (target
== NULL
) {
455 SCPrint(TRUE
, stderr
, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
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()));
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.
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
);
476 // Direct check of reachability
477 SCPrint(TRUE
, stdout
, CFSTR(" 0: direct\n"));
478 SCPrint(TRUE
, stdout
, CFSTR(" %@\n"), target
);
479 _printReachability(target
);
481 SCPrint(TRUE
, stdout
, CFSTR("\n"));
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"));
489 if (!SCNetworkReachabilitySetCallback(target_async
, callout
, &context
)) {
490 printf("SCNetworkReachabilitySetCallback() failed: %s\n", SCErrorString(SCError()));
495 if (!SCNetworkReachabilitySetDispatchQueue(target_async
, dispatch_get_current_queue())) {
496 printf("SCNetworkReachabilitySetDispatchQueue() failed: %s\n", SCErrorString(SCError()));
500 if (!SCNetworkReachabilityScheduleWithRunLoop(target_async
, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode
)) {
501 printf("SCNetworkReachabilityScheduleWithRunLoop() failed: %s\n", SCErrorString(SCError()));
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"));
519 showResolver(dns_resolver_t
*resolver
, int index
)
523 SCPrint(TRUE
, stdout
, CFSTR("\nresolver #%d\n"), index
);
525 if (resolver
->domain
!= NULL
) {
526 SCPrint(TRUE
, stdout
, CFSTR(" domain : %s\n"), resolver
->domain
);
529 for (i
= 0; i
< resolver
->n_search
; i
++) {
530 SCPrint(TRUE
, stdout
, CFSTR(" search domain[%d] : %s\n"), i
, resolver
->search
[i
]);
533 for (i
= 0; i
< resolver
->n_nameserver
; i
++) {
536 _SC_sockaddr_to_string(resolver
->nameserver
[i
], buf
, sizeof(buf
));
537 SCPrint(TRUE
, stdout
, CFSTR(" nameserver[%d] : %s\n"), i
, buf
);
540 for (i
= 0; i
< resolver
->n_sortaddr
; i
++) {
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
);
549 if (resolver
->options
!= NULL
) {
550 SCPrint(TRUE
, stdout
, CFSTR(" options : %s\n"), resolver
->options
);
553 if (resolver
->port
!= 0) {
554 SCPrint(TRUE
, stdout
, CFSTR(" port : %hd\n"), resolver
->port
);
557 if (resolver
->timeout
!= 0) {
558 SCPrint(TRUE
, stdout
, CFSTR(" timeout : %d\n"), resolver
->timeout
);
561 if (resolver
->if_index
!= 0) {
565 if_name
= if_indextoname(resolver
->if_index
, buf
);
566 SCPrint(TRUE
, stdout
, CFSTR(" if_index : %d (%s)\n"),
568 (if_name
!= NULL
) ? if_name
: "?");
571 if (resolver
->flags
!= 0) {
572 uint32_t flags
= resolver
->flags
;
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(","));
581 SCPrint(TRUE
, stdout
, CFSTR("0x%08x"), flags
);
583 SCPrint(TRUE
, stdout
, CFSTR("\n"));
586 if (resolver
->search_order
!= 0) {
587 SCPrint(TRUE
, stdout
, CFSTR(" order : %d\n"), resolver
->search_order
);
596 do_showDNSConfiguration(int argc
, char **argv
)
598 dns_config_t
*dns_config
;
600 dns_config
= dns_configuration_copy();
604 SCPrint(TRUE
, stdout
, CFSTR("DNS configuration\n"));
606 for (i
= 0; i
< dns_config
->n_resolver
; i
++) {
607 dns_resolver_t
*resolver
= dns_config
->resolver
[i
];
609 showResolver(resolver
, i
+ 1);
612 if ((dns_config
->n_scoped_resolver
> 0) && (dns_config
->scoped_resolver
!= NULL
)) {
613 SCPrint(TRUE
, stdout
, CFSTR("\nDNS configuration (for scoped queries)\n"));
615 for (i
= 0; i
< dns_config
->n_scoped_resolver
; i
++) {
616 dns_resolver_t
*resolver
= dns_config
->scoped_resolver
[i
];
618 showResolver(resolver
, i
+ 1);
622 dns_configuration_free(dns_config
);
624 SCPrint(TRUE
, stdout
, CFSTR("No DNS configuration available\n"));
632 showProxy(CFDictionaryRef proxy
)
634 CFMutableDictionaryRef cleaned
= NULL
;
637 cleaned
= CFDictionaryCreateMutableCopy(NULL
, 0, proxy
);
638 CFDictionaryRemoveValue(cleaned
, kSCPropNetProxiesSupplemental
);
639 CFDictionaryRemoveValue(cleaned
, kSCPropNetProxiesScoped
);
643 SCPrint(TRUE
, stdout
, CFSTR("%@\n"), proxy
);
644 if (cleaned
!= NULL
) CFRelease(cleaned
);
651 do_showProxyConfiguration(int argc
, char **argv
)
653 CFDictionaryRef proxies
;
655 proxies
= SCDynamicStoreCopyProxies(NULL
);
656 if (proxies
!= NULL
) {
657 CFStringRef interface
= NULL
;
658 CFStringRef server
= NULL
;
661 if (strcasecmp(argv
[0], "interface") == 0) {
666 SCPrint(TRUE
, stderr
, CFSTR("No interface\n"));
670 if (if_nametoindex(argv
[0]) == 0) {
671 SCPrint(TRUE
, stderr
, CFSTR("No interface: %s\n"), argv
[0]);
675 interface
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
679 if (server
!= NULL
) {
683 server
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
689 if ((server
!= NULL
) || (interface
!= NULL
)) {
692 matching
= SCNetworkProxiesCopyMatching(proxies
, server
, interface
);
693 if (matching
!= NULL
) {
697 if (server
!= NULL
) {
698 if (interface
!= NULL
) {
699 SCPrint(TRUE
, stdout
,
700 CFSTR("server = %@, interface = %@\n"),
704 SCPrint(TRUE
, stdout
,
705 CFSTR("server = %@\n"),
709 SCPrint(TRUE
, stdout
,
710 CFSTR("interface = %@\n"),
714 n
= CFArrayGetCount(matching
);
715 for (i
= 0; i
< n
; i
++) {
716 CFDictionaryRef proxy
;
718 proxy
= CFArrayGetValueAtIndex(matching
, i
);
719 SCPrint(TRUE
, stdout
, CFSTR("\nproxy #%d\n"), i
+ 1);
725 SCPrint(TRUE
, stdout
, CFSTR("No matching proxy configurations\n"));
731 if (interface
!= NULL
) CFRelease(interface
);
732 if (server
!= NULL
) CFRelease(server
);
735 SCPrint(TRUE
, stdout
, CFSTR("No proxy configuration available\n"));
744 do_snapshot(int argc
, char **argv
)
746 if (!SCDynamicStoreSnapshot(store
)) {
747 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
761 waitTimeout(int sigraised
)
769 do_wait(char *waitKey
, int timeout
)
771 struct itimerval itv
;
773 CFMutableArrayRef keys
;
776 store
= SCDynamicStoreCreate(NULL
, CFSTR("scutil (wait)"), waitKeyFound
, NULL
);
778 SCPrint(TRUE
, stderr
,
779 CFSTR("SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
783 key
= CFStringCreateWithCString(NULL
, waitKey
, kCFStringEncodingUTF8
);
785 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
786 CFArrayAppendValue(keys
, key
);
787 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
790 SCPrint(TRUE
, stderr
,
791 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s\n"), SCErrorString(SCError()));
795 notifyRls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
797 SCPrint(TRUE
, stderr
,
798 CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s\n"), SCErrorString(SCError()));
802 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifyRls
, kCFRunLoopDefaultMode
);
804 value
= SCDynamicStoreCopyValue(store
, key
);
806 /* if the key is already present */
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
));
825 #ifdef TEST_DNS_CONFIGURATION_COPY
827 CFRunLoopSourceRef notifyRls
= NULL
;
828 SCDynamicStoreRef store
= NULL
;
829 CFPropertyListRef value
= NULL
;
832 main(int argc
, char **argv
)
834 do_showDNSConfiguration(argc
, argv
);
838 #endif // TEST_DNS_CONFIGURATION_COPY