+static void
+callout(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
+{
+ static int n = 3;
+ struct tm tm_now;
+ struct timeval tv_now;
+
+ (void)gettimeofday(&tv_now, NULL);
+ (void)localtime_r(&tv_now.tv_sec, &tm_now);
+
+ SCPrint(TRUE, stdout, CFSTR("\n*** %2d:%02d:%02d.%03d\n\n"),
+ tm_now.tm_hour,
+ tm_now.tm_min,
+ tm_now.tm_sec,
+ tv_now.tv_usec / 1000);
+ SCPrint(TRUE, stdout, CFSTR("%2d: callback w/flags=0x%08x (info=\"%s\")\n"), n++, flags, (char *)info);
+ SCPrint(TRUE, stdout, CFSTR(" %@\n"), target);
+ _printReachability(target);
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+ return;
+}
+
+
+__private_extern__
+void
+do_watchReachability(int argc, char **argv)
+{
+ SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL };
+ SCNetworkReachabilityRef target;
+ SCNetworkReachabilityRef target_async;
+
+ target = _setupReachability(argc, argv, NULL);
+ if (target == NULL) {
+ SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
+ exit(1);
+ }
+
+ target_async = _setupReachability(argc, argv, &context);
+ if (target_async == NULL) {
+ SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
+ exit(1);
+ }
+
+ // Normally, we don't want to make any calls to SCNetworkReachabilityGetFlags()
+ // until after the "target" has been scheduled on a run loop. Otherwise, we'll
+ // end up making a synchronous DNS request and that's not what we want.
+ //
+ // But, to test the case were an application call SCNetworkReachabilityGetFlags()
+ // we provide the "CHECK_REACHABILITY_BEFORE_SCHEDULING" environment variable.
+ if (getenv("CHECK_REACHABILITY_BEFORE_SCHEDULING") != NULL) {
+ CFRelease(target_async);
+ target_async = CFRetain(target);
+ }
+
+ // Direct check of reachability
+ SCPrint(TRUE, stdout, CFSTR(" 0: direct\n"));
+ SCPrint(TRUE, stdout, CFSTR(" %@\n"), target);
+ _printReachability(target);
+ CFRelease(target);
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+
+ // schedule the target
+ SCPrint(TRUE, stdout, CFSTR(" 1: start\n"));
+ SCPrint(TRUE, stdout, CFSTR(" %@\n"), target_async);
+ //_printReachability(target_async);
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+
+ if (!SCNetworkReachabilitySetCallback(target_async, callout, &context)) {
+ printf("SCNetworkReachabilitySetCallback() failed: %s\n", SCErrorString(SCError()));
+ exit(1);
+ }
+
+#if !TARGET_OS_IPHONE
+ if (doDispatch) {
+ if (!SCNetworkReachabilitySetDispatchQueue(target_async, dispatch_get_current_queue())) {
+ printf("SCNetworkReachabilitySetDispatchQueue() failed: %s\n", SCErrorString(SCError()));
+ exit(1);
+ }
+ } else
+#endif // !TARGET_OS_IPHONE
+ {
+ if (!SCNetworkReachabilityScheduleWithRunLoop(target_async, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
+ printf("SCNetworkReachabilityScheduleWithRunLoop() failed: %s\n", SCErrorString(SCError()));
+ exit(1);
+ }
+ }
+
+ // Note: now that we are scheduled on a run loop we can call SCNetworkReachabilityGetFlags()
+ // to get the current status. For "names", a DNS lookup has already been initiated.
+ SCPrint(TRUE, stdout, CFSTR(" 2: on %s\n"), doDispatch ? "dispatch queue" : "runloop");
+ SCPrint(TRUE, stdout, CFSTR(" %@\n"), target_async);
+ _printReachability(target_async);
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+
+ CFRunLoopRun();
+ exit(0);
+}
+
+
+__private_extern__
+void
+do_showDNSConfiguration(int argc, char **argv)
+{
+ dns_config_t *dns_config;
+
+ dns_config = dns_configuration_copy();
+ if (dns_config) {
+ int n;
+
+ SCPrint(TRUE, stdout, CFSTR("DNS configuration\n"));
+
+ for (n = 0; n < dns_config->n_resolver; n++) {
+ int i;
+ dns_resolver_t *resolver = dns_config->resolver[n];
+
+ SCPrint(TRUE, stdout, CFSTR("\nresolver #%d\n"), n + 1);
+
+ if (resolver->domain != NULL) {
+ SCPrint(TRUE, stdout, CFSTR(" domain : %s\n"), resolver->domain);
+ }
+
+ for (i = 0; i < resolver->n_search; i++) {
+ SCPrint(TRUE, stdout, CFSTR(" search domain[%d] : %s\n"), i, resolver->search[i]);
+ }
+
+ for (i = 0; i < resolver->n_nameserver; i++) {
+ char buf[128];
+
+ _SC_sockaddr_to_string(resolver->nameserver[i], buf, sizeof(buf));
+ SCPrint(TRUE, stdout, CFSTR(" nameserver[%d] : %s\n"), i, buf);
+ }
+
+ for (i = 0; i < resolver->n_sortaddr; i++) {
+ char abuf[32];
+ char mbuf[32];
+
+ (void)inet_ntop(AF_INET, &resolver->sortaddr[i]->address, abuf, sizeof(abuf));
+ (void)inet_ntop(AF_INET, &resolver->sortaddr[i]->mask, mbuf, sizeof(mbuf));
+ SCPrint(TRUE, stdout, CFSTR(" sortaddr[%d] : %s/%s\n"), i, abuf, mbuf);
+ }
+
+ if (resolver->options != NULL) {
+ SCPrint(TRUE, stdout, CFSTR(" options : %s\n"), resolver->options);
+ }
+
+ if (resolver->port != 0) {
+ SCPrint(TRUE, stdout, CFSTR(" port : %hd\n"), resolver->port);
+ }
+
+ if (resolver->timeout != 0) {
+ SCPrint(TRUE, stdout, CFSTR(" timeout : %d\n"), resolver->timeout);
+ }
+
+ if (resolver->search_order != 0) {
+ SCPrint(TRUE, stdout, CFSTR(" order : %d\n"), resolver->search_order);
+ }
+ }
+
+ dns_configuration_free(dns_config);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("No DNS configuration available\n"));
+ }
+
+ exit(0);
+}
+
+
+__private_extern__
+void
+do_showProxyConfiguration(int argc, char **argv)
+{
+ CFDictionaryRef proxies;
+
+ proxies = SCDynamicStoreCopyProxies(NULL);
+ if (proxies != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%@\n"), proxies);
+ CFRelease(proxies);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("No proxy configuration available\n"));
+ }
+
+ exit(0);
+}
+
+
+__private_extern__