2 * Copyright (c) 2000, 2001, 2003-2005, 2007-2013 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>
44 #include <netdb_async.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
51 #include "dnsinfo_internal.h"
52 #include <network_information.h>
53 #include "SCNetworkReachabilityInternal.h"
54 #include <CommonCrypto/CommonDigest.h>
56 static Boolean resolver_bypass
;
58 static CF_RETURNS_RETAINED CFMutableDictionaryRef
59 _setupReachabilityOptions(int argc
, char **argv
, const char *interface
)
62 CFMutableDictionaryRef options
;
64 options
= CFDictionaryCreateMutable(NULL
,
66 &kCFTypeDictionaryKeyCallBacks
,
67 &kCFTypeDictionaryValueCallBacks
);
69 for (i
= 0; i
< argc
; i
++) {
70 if (strcasecmp(argv
[i
], "interface") == 0) {
72 SCPrint(TRUE
, stderr
, CFSTR("No interface\n"));
82 if (strcasecmp(argv
[i
], "server") == 0) {
83 CFDictionarySetValue(options
,
84 kSCNetworkReachabilityOptionServerBypass
,
87 } else if (strcasecmp(argv
[i
], "no-server") == 0) {
88 CFDictionarySetValue(options
,
89 kSCNetworkReachabilityOptionServerBypass
,
95 if (strcasecmp(argv
[i
], "no-connection-on-demand") == 0) {
96 CFDictionarySetValue(options
,
97 kSCNetworkReachabilityOptionConnectionOnDemandBypass
,
102 if (strcasecmp(argv
[i
], "no-resolve") == 0) {
103 CFDictionarySetValue(options
,
104 kSCNetworkReachabilityOptionResolverBypass
,
106 resolver_bypass
= TRUE
;
110 if (strlen(argv
[i
]) == 0) {
114 SCPrint(TRUE
, stderr
, CFSTR("Unrecognized option: %s\n"), argv
[i
]);
119 if (interface
!= NULL
) {
122 if (if_nametoindex(interface
) == 0) {
123 SCPrint(TRUE
, stderr
, CFSTR("No interface: %s\n"), interface
);
127 str
= CFStringCreateWithCString(NULL
, interface
, kCFStringEncodingASCII
);
128 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionInterface
, str
);
132 if (CFDictionaryGetCount(options
) == 0) {
141 static SCNetworkReachabilityRef
142 _setupReachability(int argc
, char **argv
, SCNetworkReachabilityContext
*context
)
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
;
153 bzero(&sin
, sizeof(sin
));
154 sin
.sin_len
= sizeof(sin
);
155 sin
.sin_family
= AF_INET
;
157 bzero(&sin6
, sizeof(sin6
));
158 sin6
.sin6_len
= sizeof(sin6
);
159 sin6
.sin6_family
= AF_INET6
;
161 interface
= strchr(argv
[0], '%');
162 if (interface
!= NULL
) {
163 ip_address
= strdup(argv
[0]);
164 ip_address
[interface
- argv
[0]] = '\0';
168 if (inet_aton(ip_address
, &sin
.sin_addr
) == 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];
177 || ((argc
> 1) && (strlen(argv
[1]) == 0))
178 || inet_aton(remote_address
, &r_sin
.sin_addr
) == 0) {
180 options
= _setupReachabilityOptions(argc
- 2, argv
+ 2, interface
);
182 if (options
== NULL
) {
183 target
= SCNetworkReachabilityCreateWithAddress(NULL
, (struct sockaddr
*)&sin
);
184 if (context
!= NULL
) {
185 context
->info
= "by address";
190 data
= CFDataCreate(NULL
, (const UInt8
*)&sin
, sizeof(sin
));
191 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionRemoteAddress
, data
);
194 if (context
!= NULL
) {
195 if (CFDictionaryContainsKey(options
,
196 kSCNetworkReachabilityOptionInterface
)) {
197 if (CFDictionaryGetCount(options
) == 2) {
198 context
->info
= "by address w/scope";
200 context
->info
= "by address w/scope and options";
203 context
->info
= "by address w/options";
208 const char *interface2
;
210 interface2
= strchr(argv
[1], '%');
211 if (interface2
!= NULL
) {
212 remote_address
= strdup(argv
[1]);
213 remote_address
[interface2
- argv
[1]] = '\0';
216 if ((interface
!= NULL
) && (strcmp(interface
, interface2
) != 0)) {
217 SCPrint(TRUE
, stderr
,
218 CFSTR("Interface mismatch \"%s\" != \"%s\"\n"),
224 interface
= interface2
;
227 if (remote_address
!= argv
[1]) {
228 free(remote_address
);
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";
242 data
= CFDataCreate(NULL
, (const UInt8
*)&sin
, sizeof(sin
));
243 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionLocalAddress
, data
);
245 data
= CFDataCreate(NULL
, (const UInt8
*)&r_sin
, sizeof(r_sin
));
246 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionRemoteAddress
, data
);
249 if (context
!= NULL
) {
250 if (CFDictionaryContainsKey(options
,
251 kSCNetworkReachabilityOptionInterface
)) {
252 if (CFDictionaryGetCount(options
) == 3) {
253 context
->info
= "by address pair w/scope";
255 context
->info
= "by address pair w/scope and options";
258 context
->info
= "by address pair w/options";
263 } else if (inet_pton(AF_INET6
, argv
[0], &sin6
.sin6_addr
) == 1) {
264 struct sockaddr_in6 r_sin6
;
266 if (interface
!= NULL
) {
267 sin6
.sin6_scope_id
= if_nametoindex(interface
);
271 bzero(&r_sin6
, sizeof(r_sin6
));
272 r_sin6
.sin6_len
= sizeof(r_sin6
);
273 r_sin6
.sin6_family
= AF_INET6
;
277 || ((argc
> 1) && (strlen(argv
[1]) == 0))
278 || inet_pton(AF_INET6
, argv
[1], &r_sin6
.sin6_addr
) == 0) {
280 options
= _setupReachabilityOptions(argc
- 2, argv
+ 2, NULL
);
282 if (options
== NULL
) {
283 target
= SCNetworkReachabilityCreateWithAddress(NULL
, (struct sockaddr
*)&sin6
);
284 if (context
!= NULL
) {
285 context
->info
= "by (v6) address";
290 data
= CFDataCreate(NULL
, (const UInt8
*)&sin6
, sizeof(sin6
));
291 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionRemoteAddress
, data
);
294 if (context
!= NULL
) {
295 context
->info
= "by (v6) address w/options";
299 interface
= strchr(argv
[1], '%');
300 if (interface
!= NULL
) {
301 r_sin6
.sin6_scope_id
= if_nametoindex(interface
);
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";
315 data
= CFDataCreate(NULL
, (const UInt8
*)&sin6
, sizeof(sin6
));
316 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionLocalAddress
, data
);
318 data
= CFDataCreate(NULL
, (const UInt8
*)&r_sin6
, sizeof(r_sin6
));
319 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionRemoteAddress
, data
);
322 if (context
!= NULL
) {
323 context
->info
= "by (v6) address pair w/options";
329 target
= SCNetworkReachabilityCreateWithName(NULL
, argv
[0]);
330 if (context
!= NULL
) {
331 context
->info
= "by name";
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";
343 str
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
344 CFDictionarySetValue(options
, kSCNetworkReachabilityOptionNodeName
, str
);
347 if (context
!= NULL
) {
348 context
->info
= "by name w/options";
354 if (ip_address
!= argv
[0]) {
358 if ((target
== NULL
) && (options
!= NULL
)) {
359 target
= SCNetworkReachabilityCreateWithOptions(NULL
, options
);
368 _printReachability(SCNetworkReachabilityRef target
)
370 SCNetworkReachabilityFlags flags
;
373 ok
= SCNetworkReachabilityGetFlags(target
, &flags
);
375 SCPrint(TRUE
, stderr
, CFSTR(" could not determine reachability, %s\n"), SCErrorString(SCError()));
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"));
384 if (resolver_bypass
) {
387 if_index
= SCNetworkReachabilityGetInterfaceIndex(target
);
388 SCPrint(_sc_debug
, stdout
, CFSTR("interface index = %d\n"), if_index
);
397 do_checkReachability(int argc
, char **argv
)
399 SCNetworkReachabilityRef target
;
401 target
= _setupReachability(argc
, argv
, NULL
);
402 if (target
== NULL
) {
403 SCPrint(TRUE
, stderr
, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
407 _printReachability(target
);
414 _printNWIFlags(nwi_ifstate_flags flags
)
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(","));
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(","));
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(","));
437 SCPrint(TRUE
, stdout
, CFSTR("0x%08x"), flags
);
439 SCPrint(TRUE
, stdout
, CFSTR(")"));
446 _printNWIInfo(nwi_ifstate_t ifstate
)
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
);
454 SCPrint(TRUE
, stdout
,
455 CFSTR(" %7s : flags %p"),
456 nwi_ifstate_get_ifname(ifstate
),
458 _printNWIFlags(ifstate_flags
);
460 SCPrint(TRUE
, stdout
, CFSTR("\n reach %p ("), reach_flags
);
461 __SCNetworkReachabilityPrintFlags(reach_flags
);
462 SCPrint(TRUE
, stdout
, CFSTR(")"));
464 if (vpn_addr
!= NULL
) {
465 char vpn_ntopbuf
[INET6_ADDRSTRLEN
];
467 _SC_sockaddr_to_string(vpn_addr
, vpn_ntopbuf
, sizeof(vpn_ntopbuf
));
468 SCPrint(TRUE
, stdout
, CFSTR("\n VPN server: %s"), vpn_ntopbuf
);
471 signature
= nwi_ifstate_get_signature(ifstate
, AF_UNSPEC
, &signature_length
);
472 if (signature
!= NULL
) {
473 CFDataRef digest
= NULL
;
475 digest
= CFDataCreate(NULL
, signature
, CC_SHA1_DIGEST_LENGTH
);
476 SCPrint(TRUE
, stdout
, CFSTR("\n Signature Hash: %@"), digest
);
479 SCPrint(TRUE
, stdout
, CFSTR("\n Signature Hash: <empty>"));
482 SCPrint(TRUE
, stdout
, CFSTR("\n generation %llu\n"),
483 nwi_ifstate_get_generation(ifstate
));
491 do_nwi(int argc
, char **argv
)
493 nwi_ifstate_t ifstate
;
494 nwi_state_t state
= nwi_state_copy();
497 SCPrint(TRUE
, stdout
, CFSTR("No network information\n"));
502 ifstate
= nwi_state_get_ifstate(state
, argv
[0]);
503 if (ifstate
!= NULL
) {
504 _printNWIInfo(ifstate
);
506 SCPrint(TRUE
, stdout
, CFSTR("No network information (for %s)\n"), argv
[0]);
512 SCPrint(TRUE
, stdout
, CFSTR("Network information (generation %llu)"),
513 nwi_state_get_generation(state
));
515 SCPrint(TRUE
, stdout
, CFSTR("\nIPv4 network interface information\n"));
516 ifstate
= nwi_state_get_first_ifstate(state
, AF_INET
);
518 if (ifstate
== NULL
) {
519 SCPrint(TRUE
, stdout
, CFSTR(" No IPv4 states found\n"));
522 while (ifstate
!= NULL
) {
523 _printNWIInfo(ifstate
);
524 ifstate
= nwi_ifstate_get_next(ifstate
, AF_INET
);
527 SCPrint(TRUE
, stdout
, CFSTR("\nIPv6 network interface information\n"));
528 ifstate
= nwi_state_get_first_ifstate(state
, AF_INET6
);
530 if (ifstate
== NULL
) {
531 SCPrint(TRUE
, stdout
, CFSTR(" No IPv6 states found\n"));
534 while (ifstate
!= NULL
) {
535 _printNWIInfo(ifstate
);
536 ifstate
= nwi_ifstate_get_next(ifstate
, AF_INET6
);
541 nwi_state_release(state
);
547 callout(SCNetworkReachabilityRef target
, SCNetworkReachabilityFlags flags
, void *info
)
551 struct timeval tv_now
;
553 (void)gettimeofday(&tv_now
, NULL
);
554 (void)localtime_r(&tv_now
.tv_sec
, &tm_now
);
556 SCPrint(TRUE
, stdout
, CFSTR("\n*** %2d:%02d:%02d.%03d\n\n"),
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"));
571 do_watchReachability(int argc
, char **argv
)
573 SCNetworkReachabilityContext context
= { 0, NULL
, NULL
, NULL
, NULL
};
574 SCNetworkReachabilityRef target
;
575 SCNetworkReachabilityRef target_async
;
577 target
= _setupReachability(argc
, argv
, NULL
);
578 if (target
== NULL
) {
579 SCPrint(TRUE
, stderr
, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
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()));
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.
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
);
600 // Direct check of reachability
601 SCPrint(TRUE
, stdout
, CFSTR(" 0: direct\n"));
602 SCPrint(TRUE
, stdout
, CFSTR(" %@\n"), target
);
603 _printReachability(target
);
605 SCPrint(TRUE
, stdout
, CFSTR("\n"));
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"));
613 if (!SCNetworkReachabilitySetCallback(target_async
, callout
, &context
)) {
614 printf("SCNetworkReachabilitySetCallback() failed: %s\n", SCErrorString(SCError()));
619 if (!SCNetworkReachabilitySetDispatchQueue(target_async
, dispatch_get_main_queue())) {
620 printf("SCNetworkReachabilitySetDispatchQueue() failed: %s\n", SCErrorString(SCError()));
624 if (!SCNetworkReachabilityScheduleWithRunLoop(target_async
, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode
)) {
625 printf("SCNetworkReachabilityScheduleWithRunLoop() failed: %s\n", SCErrorString(SCError()));
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"));
644 do_showDNSConfiguration(int argc
, char **argv
)
646 dns_config_t
*dns_config
;
647 SCNetworkReachabilityRef target
;
649 dns_config
= dns_configuration_copy();
651 if (dns_config
== NULL
) {
652 SCPrint(TRUE
, stdout
, CFSTR("No DNS configuration available\n"));
657 int dns_config_index
= -1;
658 SCNetworkReachabilityFlags flags
= 0;
659 Boolean haveDNS
= FALSE
;
661 dns_resolver_t
*resolver
;
662 uint32_t resolver_if_index
;
663 SCNetworkReachabilityPrivateRef targetPrivate
;
665 target
= _setupReachability(argc
, argv
, NULL
);
667 targetPrivate
= (SCNetworkReachabilityPrivateRef
)target
;
669 if (targetPrivate
->type
!= reachabilityTypeName
) {
670 SCPrint(TRUE
, stdout
, CFSTR("\"%s\" is not a hostname.\n"), argv
[0]);
674 ok
= __SC_checkResolverReachabilityInternal(&store
, &flags
,
675 &haveDNS
, targetPrivate
->name
,
676 &resolver_if_index
, &dns_config_index
);
679 SCPrint(TRUE
, stdout
, CFSTR("No DNS configuration available.\n" ));
683 SCPrint(TRUE
, stdout
, CFSTR("DNS configuration for %s\n"),
684 targetPrivate
->name
);
686 if (targetPrivate
->if_index
== 0) {
687 resolver
= dns_config
->resolver
[dns_config_index
];
689 resolver
= dns_config
->scoped_resolver
[dns_config_index
];
692 _dns_resolver_print(resolver
, dns_config_index
+ 1);
694 if (target
!= NULL
) CFRelease(target
);
696 _dns_configuration_print(dns_config
);
700 SCPrint(TRUE
, stdout
, CFSTR("\ngeneration = %lu\n"), dns_config
->generation
);
703 dns_configuration_free(dns_config
);
709 showProxy(CFDictionaryRef proxy
)
711 CFMutableDictionaryRef cleaned
= NULL
;
714 cleaned
= CFDictionaryCreateMutableCopy(NULL
, 0, proxy
);
715 CFDictionaryRemoveValue(cleaned
, kSCPropNetProxiesScoped
);
716 CFDictionaryRemoveValue(cleaned
, kSCPropNetProxiesServices
);
717 CFDictionaryRemoveValue(cleaned
, kSCPropNetProxiesSupplemental
);
721 SCPrint(TRUE
, stdout
, CFSTR("%@\n"), proxy
);
722 if (cleaned
!= NULL
) CFRelease(cleaned
);
729 do_showProxyConfiguration(int argc
, char **argv
)
731 CFMutableDictionaryRef options
= NULL
;
732 CFDictionaryRef proxies
;
734 if (getenv("BYPASS_GLOBAL_PROXY") != NULL
) {
735 options
= CFDictionaryCreateMutable(NULL
, 0,
736 &kCFTypeDictionaryKeyCallBacks
,
737 &kCFTypeDictionaryValueCallBacks
);
738 CFDictionaryAddValue(options
, kSCProxiesNoGlobal
, kCFBooleanTrue
);
741 proxies
= SCDynamicStoreCopyProxiesWithOptions(NULL
, options
);
743 if (options
!= NULL
) {
747 if (proxies
!= NULL
) {
748 CFStringRef interface
= NULL
;
749 CFStringRef server
= NULL
;
752 if (strcasecmp(argv
[0], "interface") == 0) {
757 SCPrint(TRUE
, stderr
, CFSTR("No interface\n"));
761 if (if_nametoindex(argv
[0]) == 0) {
762 SCPrint(TRUE
, stderr
, CFSTR("No interface: %s\n"), argv
[0]);
766 interface
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
770 if (server
!= NULL
) {
774 server
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
780 if ((server
!= NULL
) || (interface
!= NULL
)) {
783 matching
= SCNetworkProxiesCopyMatching(proxies
, server
, interface
);
784 if (matching
!= NULL
) {
788 if (server
!= NULL
) {
789 if (interface
!= NULL
) {
790 SCPrint(TRUE
, stdout
,
791 CFSTR("server = %@, interface = %@\n"),
795 SCPrint(TRUE
, stdout
,
796 CFSTR("server = %@\n"),
800 SCPrint(TRUE
, stdout
,
801 CFSTR("interface = %@\n"),
805 n
= CFArrayGetCount(matching
);
806 for (i
= 0; i
< n
; i
++) {
807 CFDictionaryRef proxy
;
809 proxy
= CFArrayGetValueAtIndex(matching
, i
);
810 SCPrint(TRUE
, stdout
, CFSTR("\nproxy #%d\n"), i
+ 1);
816 SCPrint(TRUE
, stdout
, CFSTR("No matching proxy configurations\n"));
822 if (interface
!= NULL
) CFRelease(interface
);
823 if (server
!= NULL
) CFRelease(server
);
826 SCPrint(TRUE
, stdout
, CFSTR("No proxy configuration available\n"));
835 do_snapshot(int argc
, char **argv
)
837 if (!SCDynamicStoreSnapshot(store
)) {
838 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
841 #ifdef HAVE_REACHABILITY_SERVER
842 (void) _SCNetworkReachabilityServer_snapshot();
843 #endif // HAVE_REACHABILITY_SERVER
851 do_renew(char *if_name
)
856 if ((if_name
== NULL
) || (strlen(if_name
) == 0)) {
857 SCPrint(TRUE
, stderr
, CFSTR("No interface name\n"));
861 if (getenv("ATTEMPT_DHCP_RENEW_WITH_SCDYNAMICSTORE") != NULL
) {
862 CFArrayRef interfaces
;
864 interfaces
= SCNetworkInterfaceCopyAll();
865 if (interfaces
!= NULL
) {
867 CFStringRef match_name
;
870 match_name
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingASCII
);
871 assert(match_name
!= NULL
);
873 n
= CFArrayGetCount(interfaces
);
874 for (i
= 0; i
< n
; i
++) {
875 CFStringRef bsd_name
;
876 SCNetworkInterfaceRef interface
;
878 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
879 bsd_name
= SCNetworkInterfaceGetBSDName(interface
);
880 if (_SC_CFEqual(bsd_name
, match_name
)) {
882 ok
= SCNetworkInterfaceForceConfigurationRefresh(interface
);
887 if (status
!= kSCStatusAccessError
) {
888 SCPrint(TRUE
, stderr
, CFSTR("%s\n"), SCErrorString(status
));
892 // ... and if can't write the SCDynamicStore, try w/prefs
899 CFRelease(match_name
);
900 CFRelease(interfaces
);
908 do_prefs_init(); /* initialization */
909 do_prefs_open(0, NULL
); /* open default prefs */
911 services
= SCNetworkServiceCopyAll(prefs
);
912 if (services
!= NULL
) {
914 CFStringRef match_name
;
917 match_name
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingASCII
);
918 assert(match_name
!= NULL
);
920 n
= CFArrayGetCount(services
);
921 for (i
= 0; i
< n
; i
++) {
922 CFStringRef bsd_name
;
923 SCNetworkInterfaceRef interface
;
924 SCNetworkServiceRef service
;
926 service
= CFArrayGetValueAtIndex(services
, i
);
927 interface
= SCNetworkServiceGetInterface(service
);
928 if (interface
== NULL
) {
933 bsd_name
= SCNetworkInterfaceGetBSDName(interface
);
934 if (_SC_CFEqual(bsd_name
, match_name
)) {
936 ok
= SCNetworkInterfaceForceConfigurationRefresh(interface
);
938 SCPrint(TRUE
, stderr
, CFSTR("%s\n"), SCErrorString(SCError()));
946 CFRelease(match_name
);
951 SCPrint(TRUE
, stderr
, CFSTR("No interface\n"));
968 waitTimeout(int sigraised
)
976 do_wait(char *waitKey
, int timeout
)
978 struct itimerval itv
;
980 CFMutableArrayRef keys
;
983 store
= SCDynamicStoreCreate(NULL
, CFSTR("scutil (wait)"), waitKeyFound
, NULL
);
985 SCPrint(TRUE
, stderr
,
986 CFSTR("SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
990 key
= CFStringCreateWithCString(NULL
, waitKey
, kCFStringEncodingUTF8
);
992 keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
993 CFArrayAppendValue(keys
, key
);
994 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
997 SCPrint(TRUE
, stderr
,
998 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s\n"), SCErrorString(SCError()));
1002 notifyRls
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
1004 SCPrint(TRUE
, stderr
,
1005 CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s\n"), SCErrorString(SCError()));
1009 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifyRls
, kCFRunLoopDefaultMode
);
1011 value
= SCDynamicStoreCopyValue(store
, key
);
1013 /* if the key is already present */
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
));
1032 #ifdef TEST_DNS_CONFIGURATION
1034 Boolean doDispatch
= FALSE
;
1035 CFRunLoopSourceRef notifyRls
= NULL
;
1036 SCDynamicStoreRef store
= NULL
;
1037 CFPropertyListRef value
= NULL
;
1040 main(int argc
, char **argv
)
1042 dns_config_t
*dns_config
;
1044 fprintf(stdout
, "copy configuration\n");
1045 dns_config
= dns_configuration_copy();
1046 if (dns_config
!= NULL
) {
1048 fprintf(stdout
, "sleeping for 120 seconds\n");
1051 fprintf(stdout
, "sending ack\n");
1052 _dns_configuration_ack(dns_config
, "TEST_DNS_CONFIGURATION");
1054 fprintf(stdout
, "sleeping for 120 seconds\n");
1057 dns_configuration_free(dns_config
);
1060 do_showDNSConfiguration(argc
, argv
);
1064 #endif // TEST_DNS_CONFIGURATION