+ target = SCNetworkReachabilityCreateWithOptions(NULL, options);
+ CFRelease(options);
+ }
+
+ return target;
+}
+
+
+static void
+_printReachability(SCNetworkReachabilityRef target)
+{
+ SCNetworkReachabilityFlags flags;
+ Boolean ok;
+ CFStringRef str;
+
+ ok = SCNetworkReachabilityGetFlags(target, &flags);
+ if (!ok) {
+ SCPrint(TRUE, stderr, CFSTR(" could not determine reachability, %s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ str = __SCNetworkReachabilityCopyFlags(flags, CFSTR("flags = "), _sc_debug);
+ SCPrint(TRUE, stdout, CFSTR("%@\n"), str);
+ CFRelease(str);
+
+ if (resolver_bypass && _sc_debug) {
+ int if_index;
+
+ if_index = SCNetworkReachabilityGetInterfaceIndex(target);
+ SCPrint(TRUE, stdout, CFSTR("interface index = %d\n"), if_index);
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+do_checkReachability(int argc, char **argv)
+{
+ SCNetworkReachabilityRef target;
+
+ target = _setupReachability(argc, argv, NULL);
+ if (target == NULL) {
+ SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError()));
+ exit(1);
+ }
+
+ _printReachability(target);
+ CFRelease(target);
+ exit(0);
+}
+
+
+static void
+_printNWIFlags(nwi_ifstate_flags flags)
+{
+ flags &= NWI_IFSTATE_FLAGS_MASK;
+ if (flags == 0) {
+ return;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR(" ("));
+ if (flags & NWI_IFSTATE_FLAGS_HAS_IPV4) {
+ SCPrint(TRUE, stdout, CFSTR("IPv4"));
+ flags &= ~NWI_IFSTATE_FLAGS_HAS_IPV4;
+ SCPrint(flags != 0, stdout, CFSTR(","));
+ }
+ if (flags & NWI_IFSTATE_FLAGS_HAS_IPV6) {
+ SCPrint(TRUE, stdout, CFSTR("IPv6"));
+ flags &= ~NWI_IFSTATE_FLAGS_HAS_IPV6;
+ SCPrint(flags != 0, stdout, CFSTR(","));
+ }
+ if (flags & NWI_IFSTATE_FLAGS_HAS_DNS) {
+ SCPrint(TRUE, stdout, CFSTR("DNS"));
+ flags &= ~NWI_IFSTATE_FLAGS_HAS_DNS;
+ SCPrint(flags != 0, stdout, CFSTR(","));
+ }
+ if (flags & NWI_IFSTATE_FLAGS_NOT_IN_LIST) {
+ SCPrint(TRUE, stdout, CFSTR("NOT-IN-LIST"));
+ flags &= ~NWI_IFSTATE_FLAGS_NOT_IN_LIST;
+ SCPrint(flags != 0, stdout, CFSTR(","));
+ }
+ if (flags & NWI_IFSTATE_FLAGS_HAS_SIGNATURE) {
+ SCPrint(TRUE, stdout, CFSTR("SIGNATURE"));
+ flags &= ~NWI_IFSTATE_FLAGS_HAS_SIGNATURE;
+ SCPrint(flags != 0, stdout, CFSTR(","));
+ }
+ if (flags & NWI_IFSTATE_FLAGS_NOT_IN_IFLIST) {
+ SCPrint(TRUE, stdout, CFSTR("NOT-IN-IFLIST"));
+ flags &= ~NWI_IFSTATE_FLAGS_NOT_IN_IFLIST;
+ SCPrint(flags != 0, stdout, CFSTR(","));
+ }
+ if (flags != 0) {
+ SCPrint(TRUE, stdout, CFSTR("%p"), (void *)flags);
+ }
+ SCPrint(TRUE, stdout, CFSTR(")"));
+
+ return;
+}
+
+
+static void
+_printNWIInfo(nwi_ifstate_t ifstate)
+{
+ nwi_ifstate_flags ifstate_flags;
+ SCNetworkReachabilityFlags reach_flags = nwi_ifstate_get_reachability_flags(ifstate);
+ const uint8_t *signature;
+ int signature_length;
+ CFStringRef str;
+ const struct sockaddr *vpn_addr = nwi_ifstate_get_vpn_server(ifstate);
+
+ ifstate_flags = nwi_ifstate_get_flags(ifstate);
+ if (_sc_debug) {
+ ifstate_flags |= ifstate->flags;
+ }
+
+ SCPrint(TRUE, stdout,
+ CFSTR(" %7s : flags %p"),
+ nwi_ifstate_get_ifname(ifstate),
+ (void *)ifstate_flags);
+ _printNWIFlags(ifstate_flags);
+
+ str = __SCNetworkReachabilityCopyFlags(reach_flags, CFSTR(" reach "), TRUE);
+ SCPrint(TRUE, stdout, CFSTR("\n%@"), str);
+ CFRelease(str);
+
+ if (vpn_addr != NULL) {
+ char vpn_ntopbuf[INET6_ADDRSTRLEN];
+
+ _SC_sockaddr_to_string(vpn_addr, vpn_ntopbuf, sizeof(vpn_ntopbuf));
+ SCPrint(TRUE, stdout, CFSTR("\n VPN server: %s"), vpn_ntopbuf);
+ }
+
+ signature = nwi_ifstate_get_signature(ifstate, AF_UNSPEC, &signature_length);
+ if (signature != NULL) {
+ CFDataRef digest = NULL;
+
+ digest = CFDataCreate(NULL, signature, CC_SHA1_DIGEST_LENGTH);
+ SCPrint(TRUE, stdout, CFSTR("\n Signature Hash: %@"), digest);
+ CFRelease(digest);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("\n Signature Hash: <empty>"));
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("\n generation %llu\n"),
+ nwi_ifstate_get_generation(ifstate));
+
+ return;
+}
+
+
+static void
+_printNWIReachInfo(nwi_state_t state, int af)
+{
+ uint32_t reach_flags;
+ CFStringRef str;
+
+ reach_flags = nwi_state_get_reachability_flags(state, af);
+
+ str = __SCNetworkReachabilityCopyFlags(reach_flags, CFSTR(" REACH : flags "), TRUE);
+ SCPrint(TRUE, stdout, CFSTR("\n%@\n"), str);
+ CFRelease(str);
+
+ return;
+}
+
+
+static void
+do_printNWI(int argc, char **argv, nwi_state_t state)
+{
+ unsigned int count;
+ nwi_ifstate_t ifstate;
+
+ if (state == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("No network information\n"));
+ return;
+ }
+
+ if (argc > 0) {
+ ifstate = nwi_state_get_ifstate(state, argv[0]);
+ if (ifstate != NULL) {
+ nwi_ifstate_t alias;
+
+ _printNWIInfo(ifstate);
+
+ alias = nwi_ifstate_get_alias(ifstate,
+ ifstate->af == AF_INET ? AF_INET6 : AF_INET);
+ if (alias != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+ _printNWIInfo(alias);
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("No network information (for %s)\n"), argv[0]);
+ }
+ return;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("Network information (generation %llu)"),
+ nwi_state_get_generation(state));
+
+ SCPrint(TRUE, stdout, CFSTR("\nIPv4 network interface information\n"));
+
+ ifstate = nwi_state_get_first_ifstate(state, AF_INET);
+ if (ifstate == NULL) {
+ SCPrint(TRUE, stdout, CFSTR(" No IPv4 states found\n"));
+ } else {
+ while (ifstate != NULL) {
+ _printNWIInfo(ifstate);
+ ifstate = nwi_ifstate_get_next(ifstate, AF_INET);