/*
- * Copyright (c) 2000, 2001, 2003-2005, 2007-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2015 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
+ *
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
- *
+ *
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
- *
+ *
* @APPLE_LICENSE_HEADER_END@
*/
*/
#include "scutil.h"
+#include "prefs.h"
#include "tests.h"
#include <netdb.h>
#include <netdb_async.h>
+#include <notify.h>
#include <sys/time.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#define my_log(__level, fmt, ...) SCPrint(TRUE, stdout, CFSTR(fmt "\n"), ## __VA_ARGS__)
+
#include <dnsinfo.h>
+#include "dnsinfo_internal.h"
#include <network_information.h>
+#include "network_information_priv.h"
#include "SCNetworkReachabilityInternal.h"
+#include <CommonCrypto/CommonDigest.h>
+
static Boolean resolver_bypass;
+
static CF_RETURNS_RETAINED CFMutableDictionaryRef
_setupReachabilityOptions(int argc, char **argv, const char *interface)
{
+ int i;
CFMutableDictionaryRef options;
options = CFDictionaryCreateMutable(NULL,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
- if (argc > 2) {
- struct addrinfo hints = { 0 };
- int n_hints = 0;
- int i;
-
- for (i = 2; i < argc; i++) {
- if (strcasecmp(argv[i], "interface") == 0) {
- if (++i >= argc) {
- SCPrint(TRUE, stderr, CFSTR("No interface\n"));
- CFRelease(options);
- exit(1);
- }
-
- interface = argv[i];
- continue;
+ for (i = 0; i < argc; i++) {
+ if (strcasecmp(argv[i], "interface") == 0) {
+ if (++i >= argc) {
+ SCPrint(TRUE, stderr, CFSTR("No interface\n"));
+ CFRelease(options);
+ exit(1);
}
+ interface = argv[i];
+ continue;
+ }
- if (strcasecmp(argv[i], "llq") == 0) {
- CFDictionarySetValue(options,
- kSCNetworkReachabilityOptionLongLivedQueryBypass,
- kCFBooleanFalse);
- continue;
- } else if (strcasecmp(argv[i], "no-llq") == 0) {
- CFDictionarySetValue(options,
- kSCNetworkReachabilityOptionLongLivedQueryBypass,
- kCFBooleanTrue);
- continue;
- }
- if (strcasecmp(argv[i], "server") == 0) {
- CFDictionarySetValue(options,
- kSCNetworkReachabilityOptionServerBypass,
- kCFBooleanFalse);
- continue;
- } else if (strcasecmp(argv[i], "no-server") == 0) {
- CFDictionarySetValue(options,
- kSCNetworkReachabilityOptionServerBypass,
- kCFBooleanTrue);
- continue;
- }
+ if (strcasecmp(argv[i], "server") == 0) {
+ CFDictionarySetValue(options,
+ kSCNetworkReachabilityOptionServerBypass,
+ kCFBooleanFalse);
+ continue;
+ } else if (strcasecmp(argv[i], "no-server") == 0) {
+ CFDictionarySetValue(options,
+ kSCNetworkReachabilityOptionServerBypass,
+ kCFBooleanTrue);
+ continue;
+ }
- if (strcasecmp(argv[i], "no-resolve") == 0) {
- CFDictionarySetValue(options,
- kSCNetworkReachabilityOptionResolverBypass,
- kCFBooleanTrue);
- resolver_bypass = TRUE;
- continue;
- }
+ if (strcasecmp(argv[i], "no-connection-on-demand") == 0) {
+ CFDictionarySetValue(options,
+ kSCNetworkReachabilityOptionConnectionOnDemandBypass,
+ kCFBooleanTrue);
+ continue;
+ }
- if (strcasecmp(argv[i], "AI_ADDRCONFIG") == 0) {
- hints.ai_flags |= AI_ADDRCONFIG;
- } else if (strcasecmp(argv[i], "AI_ALL") == 0) {
- hints.ai_flags |= AI_ALL;
- } else if (strcasecmp(argv[i], "AI_V4MAPPED") == 0) {
- hints.ai_flags |= AI_V4MAPPED;
- } else if (strcasecmp(argv[i], "AI_V4MAPPED_CFG") == 0) {
- hints.ai_flags |= AI_V4MAPPED_CFG;
- } else if (strcasecmp(argv[i], "AI_ADDRCONFIG") == 0) {
- hints.ai_flags |= AI_ADDRCONFIG;
- } else if (strcasecmp(argv[i], "AI_V4MAPPED") == 0) {
- hints.ai_flags |= AI_V4MAPPED;
- } else if (strcasecmp(argv[i], "AI_DEFAULT") == 0) {
- hints.ai_flags |= AI_DEFAULT;
-#ifdef AI_PARALLEL
- } else if (strcasecmp(argv[i], "AI_PARALLEL") == 0) {
- hints.ai_flags |= AI_PARALLEL;
-#endif // AI_PARALLEL
- } else if (strcasecmp(argv[i], "PF_INET") == 0) {
- hints.ai_family = PF_INET;
- } else if (strcasecmp(argv[i], "PF_INET6") == 0) {
- hints.ai_family = PF_INET6;
- } else if (strcasecmp(argv[i], "SOCK_STREAM") == 0) {
- hints.ai_socktype = SOCK_STREAM;
- } else if (strcasecmp(argv[i], "SOCK_DGRAM") == 0) {
- hints.ai_socktype = SOCK_DGRAM;
- } else if (strcasecmp(argv[i], "SOCK_RAW") == 0) {
- hints.ai_socktype = SOCK_RAW;
- } else if (strcasecmp(argv[i], "IPPROTO_TCP") == 0) {
- hints.ai_protocol = IPPROTO_TCP;
- } else if (strcasecmp(argv[i], "IPPROTO_UDP") == 0) {
- hints.ai_protocol = IPPROTO_UDP;
- } else {
- SCPrint(TRUE, stderr, CFSTR("Unrecognized hint: %s\n"), argv[i]);
- CFRelease(options);
- exit(1);
- }
- n_hints++;
+ if (strcasecmp(argv[i], "no-resolve") == 0) {
+ CFDictionarySetValue(options,
+ kSCNetworkReachabilityOptionResolverBypass,
+ kCFBooleanTrue);
+ resolver_bypass = TRUE;
+ continue;
}
- if (n_hints > 0) {
- CFDataRef data;
+ if (strcasecmp(argv[i], "ptr") == 0) {
+ CFDictionarySetValue(options,
+ kSCNetworkReachabilityOptionPTRAddress,
+ kCFBooleanTrue);
+ continue;
+ }
- data = CFDataCreate(NULL, (const UInt8 *)&hints, sizeof(hints));
- CFDictionarySetValue(options, kSCNetworkReachabilityOptionHints, data);
- CFRelease(data);
+ if (strlen(argv[i]) == 0) {
+ continue;
}
+
+ SCPrint(TRUE, stderr, CFSTR("Unrecognized option: %s\n"), argv[i]);
+ CFRelease(options);
+ exit(1);
}
if (interface != NULL) {
static SCNetworkReachabilityRef
_setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
{
- char *ip_address = argv[0];
+ const char *ip_address = argv[0];
+ char *ip_addressN = NULL;
const char *interface;
CFMutableDictionaryRef options = NULL;
+ const char *remote_address = NULL;
+ char *remote_addressN= NULL;
+ const char *remote_interface;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
SCNetworkReachabilityRef target = NULL;
sin6.sin6_len = sizeof(sin6);
sin6.sin6_family = AF_INET6;
- interface = strchr(argv[0], '%');
+ interface = strchr(ip_address, '%');
if (interface != NULL) {
- ip_address = strdup(argv[0]);
- ip_address[interface - argv[0]] = '\0';
+ ip_addressN = strdup(ip_address);
+ ip_addressN[interface - ip_address] = '\0';
+ ip_address = ip_addressN;
interface++;
}
+ if ((argc > 1) && (strlen(argv[1]) > 0)) {
+ remote_address = argv[1];
+
+ remote_interface = strchr(remote_address, '%');
+ if (remote_interface != NULL) {
+ remote_addressN = strdup(remote_address);
+ remote_addressN[remote_interface - remote_address] = '\0';
+ remote_address = remote_addressN;
+ remote_interface++;
+ }
+ }
+
if (inet_aton(ip_address, &sin.sin_addr) == 1) {
- if ((argc == 1) ||
- ((argc > 1) && (strlen(argv[1]) == 0))) {
- options = _setupReachabilityOptions(argc, argv, interface);
+ struct sockaddr_in r_sin;
+
+ if (argc > 1) {
+ bzero(&r_sin, sizeof(r_sin));
+ r_sin.sin_len = sizeof(r_sin);
+ r_sin.sin_family = AF_INET;
+ }
+
+ if ((argc == 1)
+ || (remote_address == NULL)
+ || (inet_aton(remote_address, &r_sin.sin_addr) == 0)) {
+ if (argc > 2) {
+ options = _setupReachabilityOptions(argc - 2, argv + 2, interface);
+ }
if (options == NULL) {
target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin);
if (context != NULL) {
}
}
} else {
- char *remote_address = argv[1];
- const char *interface2;
- struct sockaddr_in r_sin;
-
- interface2 = strchr(argv[1], '%');
- if (interface2 != NULL) {
- remote_address = strdup(argv[1]);
- remote_address[interface2 - argv[1]] = '\0';
- interface2++;
-
- if ((interface != NULL) && (strcmp(interface, interface2) != 0)) {
+ if (remote_interface != NULL) {
+ if ((interface != NULL) && (strcmp(interface, remote_interface) != 0)) {
SCPrint(TRUE, stderr,
CFSTR("Interface mismatch \"%s\" != \"%s\"\n"),
interface,
- interface2);
+ remote_interface);
exit(1);
}
- interface = interface2;
- }
-
- bzero(&r_sin, sizeof(r_sin));
- r_sin.sin_len = sizeof(r_sin);
- r_sin.sin_family = AF_INET;
- if (inet_aton(remote_address, &r_sin.sin_addr) == 0) {
- SCPrint(TRUE, stderr, CFSTR("Could not interpret address \"%s\"\n"), remote_address);
- exit(1);
- }
-
- if (remote_address != argv[1]) {
- free(remote_address);
+ interface = remote_interface;
}
- options = _setupReachabilityOptions(argc, argv, interface);
+ options = _setupReachabilityOptions(argc - 2, argv + 2, interface);
if (options == NULL) {
target = SCNetworkReachabilityCreateWithAddressPair(NULL,
(struct sockaddr *)&sin,
}
}
}
- } else if (inet_pton(AF_INET6, argv[0], &sin6.sin6_addr) == 1) {
+ } else if (inet_pton(AF_INET6, ip_address, &sin6.sin6_addr) == 1) {
+ struct sockaddr_in6 r_sin6;
+
if (interface != NULL) {
sin6.sin6_scope_id = if_nametoindex(interface);
}
- if ((argc == 1) ||
- ((argc > 1) && (strlen(argv[1]) == 0))) {
- options = _setupReachabilityOptions(argc, argv, NULL);
+ if (argc > 1) {
+ bzero(&r_sin6, sizeof(r_sin6));
+ r_sin6.sin6_len = sizeof(r_sin6);
+ r_sin6.sin6_family = AF_INET6;
+ }
+
+ if ((argc == 1)
+ || (remote_address == NULL)
+ || (inet_pton(AF_INET6, remote_address, &r_sin6.sin6_addr) == 0)) {
+ if (argc > 2) {
+ options = _setupReachabilityOptions(argc - 2, argv + 2, NULL);
+ }
if (options == NULL) {
target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin6);
if (context != NULL) {
}
}
} else {
- struct sockaddr_in6 r_sin6;
-
- bzero(&r_sin6, sizeof(r_sin6));
- r_sin6.sin6_len = sizeof(r_sin6);
- r_sin6.sin6_family = AF_INET6;
- if (inet_pton(AF_INET6, argv[1], &r_sin6.sin6_addr) == 0) {
- SCPrint(TRUE, stderr, CFSTR("Could not interpret address \"%s\"\n"), argv[1]);
- exit(1);
- }
+ if (remote_interface != NULL) {
+ r_sin6.sin6_scope_id = if_nametoindex(remote_interface);
- interface = strchr(argv[1], '%');
- if (interface != NULL) {
- r_sin6.sin6_scope_id = if_nametoindex(interface);
+ if ((interface != NULL) && (strcmp(interface, remote_interface) != 0)) {
+ SCPrint(TRUE, stderr,
+ CFSTR("Interface mismatch \"%s\" != \"%s\"\n"),
+ interface,
+ remote_interface);
+ exit(1);
+ }
}
- options = _setupReachabilityOptions(argc, argv, NULL);
+ options = _setupReachabilityOptions(argc - 2, argv + 2, NULL);
if (options == NULL) {
target = SCNetworkReachabilityCreateWithAddressPair(NULL,
(struct sockaddr *)&sin6,
}
}
} else {
- CFStringRef str;
-
- options = _setupReachabilityOptions(argc, argv, NULL);
-
- if (((argc == 1) && (strlen(argv[0]) > 0)) ||
- ((argc > 1) && (strlen(argv[0]) > 0) && (strlen(argv[1]) == 0))) {
+ if (argc == 1) {
+ target = SCNetworkReachabilityCreateWithName(NULL, argv[0]);
+ if (context != NULL) {
+ context->info = "by name";
+ }
+ } else {
+ options = _setupReachabilityOptions(argc - 1, argv + 1, NULL);
if (options == NULL) {
target = SCNetworkReachabilityCreateWithName(NULL, argv[0]);
if (context != NULL) {
context->info = "by name";
}
} else {
+ CFStringRef str;
+
str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
CFRelease(str);
context->info = "by name w/options";
}
}
- } else {
- CFIndex n_options;
+ }
+ }
- if (options == NULL) {
- options = CFDictionaryCreateMutable(NULL,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- }
- n_options = CFDictionaryGetCount(options);
+ if (ip_addressN != NULL) {
+ free(ip_addressN);
+ }
- if (strlen(argv[0]) > 0) {
- str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
- CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
- CFRelease(str);
- }
- if (strlen(argv[1]) > 0) {
- str = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
- CFDictionarySetValue(options, kSCNetworkReachabilityOptionServName, str);
- CFRelease(str);
- }
+ if (remote_addressN != NULL) {
+ free(remote_addressN);
+ }
- if (CFDictionaryGetCount(options) > n_options) {
- if (context != NULL) {
- if (n_options == 0) {
- context->info = "by (node and/or serv) name";
+ if ((target == NULL) && (options != NULL)) {
+ if (CFDictionaryContainsKey(options, kSCNetworkReachabilityOptionPTRAddress)) {
+ CFDataRef address;
+
+ address = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionRemoteAddress);
+ if (address == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("No address\n"));
+ exit(1);
+ }
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionPTRAddress, address);
+ CFDictionaryRemoveValue(options, kSCNetworkReachabilityOptionRemoteAddress);
+
+ if (context != NULL) {
+ CFIndex n = CFDictionaryGetCount(options);
+
+ if (n == 1) {
+ context->info = "by PTR";
+ } else if (CFDictionaryContainsKey(options,
+ kSCNetworkReachabilityOptionInterface)) {
+ if (n == 2) {
+ context->info = "by PTR w/scope";
} else {
- context->info = "by (node and/or serv) name w/options";
+ context->info = "by PTR w/scope and options";
}
+ } else {
+ context->info = "by PTR w/options";
}
- } else {
- SCPrint(TRUE, stderr, CFSTR("Must specify nodename or servname\n"));
- CFRelease(options);
- exit(1);
}
}
- }
- if (ip_address != argv[0]) {
- free(ip_address);
- }
-
- if ((target == NULL) && (options != NULL)) {
target = SCNetworkReachabilityCreateWithOptions(NULL, options);
CFRelease(options);
}
return target;
}
-static void
-_printReachabilityFlags(SCNetworkReachabilityFlags flags)
-{
- if (flags != 0) {
- if (flags & kSCNetworkReachabilityFlagsReachable) {
- SCPrint(TRUE, stdout, CFSTR("Reachable"));
- flags &= ~kSCNetworkReachabilityFlagsReachable;
- SCPrint(flags != 0, stdout, CFSTR(","));
- }
- if (flags & kSCNetworkReachabilityFlagsTransientConnection) {
- SCPrint(TRUE, stdout, CFSTR("Transient Connection"));
- flags &= ~kSCNetworkReachabilityFlagsTransientConnection;
- SCPrint(flags != 0, stdout, CFSTR(","));
- }
- if (flags & kSCNetworkReachabilityFlagsConnectionRequired) {
- SCPrint(TRUE, stdout, CFSTR("Connection Required"));
- flags &= ~kSCNetworkReachabilityFlagsConnectionRequired;
- SCPrint(flags != 0, stdout, CFSTR(","));
- }
- if (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) {
- SCPrint(TRUE, stdout, CFSTR("Automatic Connection On Traffic"));
- flags &= ~kSCNetworkReachabilityFlagsConnectionOnTraffic;
- SCPrint(flags != 0, stdout, CFSTR(","));
- }
- if (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) {
- SCPrint(TRUE, stdout, CFSTR("Automatic Connection On Demand"));
- flags &= ~kSCNetworkReachabilityFlagsConnectionOnDemand;
- SCPrint(flags != 0, stdout, CFSTR(","));
- }
- if (flags & kSCNetworkReachabilityFlagsInterventionRequired) {
- SCPrint(TRUE, stdout, CFSTR("Intervention Required"));
- flags &= ~kSCNetworkReachabilityFlagsInterventionRequired;
- SCPrint(flags != 0, stdout, CFSTR(","));
- }
- if (flags & kSCNetworkReachabilityFlagsIsLocalAddress) {
- SCPrint(TRUE, stdout, CFSTR("Local Address"));
- flags &= ~kSCNetworkReachabilityFlagsIsLocalAddress;
- SCPrint(flags != 0, stdout, CFSTR(","));
- }
- if (flags & kSCNetworkReachabilityFlagsIsDirect) {
- SCPrint(TRUE, stdout, CFSTR("Directly Reachable Address"));
- flags &= ~kSCNetworkReachabilityFlagsIsDirect;
- SCPrint(flags != 0, stdout, CFSTR(","));
- }
-#if TARGET_OS_IPHONE
- if (flags & kSCNetworkReachabilityFlagsIsWWAN) {
- SCPrint(TRUE, stdout, CFSTR("WWAN"));
- flags &= ~kSCNetworkReachabilityFlagsIsWWAN;
- SCPrint(flags != 0, stdout, CFSTR(","));
- }
-#endif // TARGET_OS_IPHONE
- if (flags != 0) {
- SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags);
- }
- } else {
- SCPrint(TRUE, stdout, CFSTR("Not Reachable"));
- }
-
- return;
-}
static void
_printReachability(SCNetworkReachabilityRef target)
{
SCNetworkReachabilityFlags flags;
Boolean ok;
+ CFStringRef str;
ok = SCNetworkReachabilityGetFlags(target, &flags);
if (!ok) {
- printf(" could not determine reachability, %s\n", SCErrorString(SCError()));
+ SCPrint(TRUE, stderr, CFSTR(" could not determine reachability, %s\n"), SCErrorString(SCError()));
return;
}
- SCPrint(_sc_debug, stdout, CFSTR("flags = 0x%08x ("), flags);
- _printReachabilityFlags(flags);
- SCPrint(_sc_debug, stdout, CFSTR(")"));
+ str = __SCNetworkReachabilityCopyFlags(flags, CFSTR("flags = "), _sc_debug);
+ SCPrint(TRUE, stdout, CFSTR("%@\n"), str);
+ CFRelease(str);
- if (resolver_bypass) {
- int if_index =
- SCNetworkReachabilityGetInterfaceIndex(target);
- SCPrint(_sc_debug, stdout, CFSTR("interface index = %d"), if_index);
- }
+ if (resolver_bypass && _sc_debug) {
+ int if_index;
- SCPrint(TRUE, stdout, CFSTR("\n"));
+ if_index = SCNetworkReachabilityGetInterfaceIndex(target);
+ SCPrint(TRUE, stdout, CFSTR("interface index = %d\n"), if_index);
+ }
return;
}
static void
_printNWIFlags(nwi_ifstate_flags flags)
{
+ flags &= NWI_IFSTATE_FLAGS_MASK;
if (flags == 0) {
return;
}
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("0x%08x"), flags);
+ SCPrint(TRUE, stdout, CFSTR("%p"), (void *)flags);
}
SCPrint(TRUE, stdout, CFSTR(")"));
}
-__private_extern__
-void
-do_nwi(int argc, char **argv)
+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;
- nwi_state_t state = nwi_state_copy();
if (state == NULL) {
SCPrint(TRUE, stdout, CFSTR("No network information\n"));
- exit(1);
+ return;
}
if (argc > 0) {
ifstate = nwi_state_get_ifstate(state, argv[0]);
if (ifstate != NULL) {
- nwi_ifstate_flags flags = nwi_ifstate_get_flags(ifstate);
-
- SCPrint(TRUE, stdout, CFSTR("Network interface information\n"), argv[0]);
- SCPrint(TRUE, stdout,
- CFSTR(" %7s : flags %p"),
- nwi_ifstate_get_ifname(ifstate),
- flags);
- _printNWIFlags(flags);
- SCPrint(TRUE, stdout, CFSTR("\n"));
+ 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]);
}
-
- goto done;
+ return;
}
- SCPrint(TRUE, stdout, CFSTR("Network information\n"));
+ 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);
+ }
+ }
+ _printNWIReachInfo(state, AF_INET);
+ SCPrint(TRUE, stdout, CFSTR("\nIPv6 network interface information\n"));
+
+ ifstate = nwi_state_get_first_ifstate(state, AF_INET6);
if (ifstate == NULL) {
- SCPrint(TRUE, stdout, CFSTR(" No IPv4 states found\n"));
+ SCPrint(TRUE, stdout, CFSTR(" No IPv6 states found\n"));
+ } else {
+ while (ifstate != NULL) {
+ _printNWIInfo(ifstate);
+ ifstate = nwi_ifstate_get_next(ifstate, AF_INET6);
+ }
}
+ _printNWIReachInfo(state, AF_INET6);
- while (ifstate != NULL) {
- nwi_ifstate_flags flags = nwi_ifstate_get_flags(ifstate);
+ count = nwi_state_get_interface_names(state, NULL, 0);
+ if (count > 0) {
+ const char * names[count];
- SCPrint(TRUE, stdout,
- CFSTR(" %7s : flags %p"),
- nwi_ifstate_get_ifname(ifstate),
- flags);
- _printNWIFlags(flags);
- SCPrint(TRUE, stdout, CFSTR("\n"));
- ifstate = nwi_ifstate_get_next(ifstate, AF_INET);
+ count = nwi_state_get_interface_names(state, names, count);
+ if (count > 0) {
+ int i;
+
+ printf("\nNetwork interfaces:");
+ for (i = 0; i < count; i++) {
+ printf(" %s", names[i]);
+ }
+ printf("\n");
+ }
}
+ return;
+}
- SCPrint(TRUE, stdout, CFSTR("\nIPv6 network interface information\n"));
- ifstate = nwi_state_get_first_ifstate(state, AF_INET6);
- if (ifstate == NULL) {
- SCPrint(TRUE, stdout, CFSTR(" No IPv6 states found\n"));
+__private_extern__
+void
+do_showNWI(int argc, char **argv)
+{
+ nwi_state_t state;
+
+ state = nwi_state_copy();
+ do_printNWI(argc, argv, state);
+ if (state != NULL) {
+ nwi_state_release(state);
+ } else {
+ exit(1);
}
- while (ifstate != NULL) {
- nwi_ifstate_flags flags = nwi_ifstate_get_flags(ifstate);
+ exit(0);
+}
+
- SCPrint(TRUE, stdout,
- CFSTR(" %7s : flags %p"),
- nwi_ifstate_get_ifname(ifstate),
- flags);
- _printNWIFlags(flags);
- SCPrint(TRUE, stdout, CFSTR("\n"));
- ifstate = nwi_ifstate_get_next(ifstate, AF_INET6);
+__private_extern__
+void
+do_watchNWI(int argc, char **argv)
+{
+ nwi_state_t state;
+ int status;
+ int token;
+
+ state = nwi_state_copy();
+ do_printNWI(argc, argv, state);
+ if (state != NULL) {
+ nwi_state_release(state);
}
- done :
+ status = notify_register_dispatch(nwi_state_get_notify_key(),
+ &token,
+ dispatch_get_main_queue(),
+ ^(int token){
+ nwi_state_t state;
+ 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);
+
+ state = nwi_state_copy();
+ do_printNWI(argc, argv, state);
+ if (state != NULL) {
+ nwi_state_release(state);
+ }
+ });
+ if (status != NOTIFY_STATUS_OK) {
+ SC_log(LOG_INFO, "notify_register_dispatch() failed for nwi changes, status=%u", status);
+ exit(1);
+ }
- nwi_state_release(state);
+ CFRunLoopRun();
exit(0);
}
}
if (doDispatch) {
- if (!SCNetworkReachabilitySetDispatchQueue(target_async, dispatch_get_current_queue())) {
+ if (!SCNetworkReachabilitySetDispatchQueue(target_async, dispatch_get_main_queue())) {
printf("SCNetworkReachabilitySetDispatchQueue() failed: %s\n", SCErrorString(SCError()));
exit(1);
}
static void
-showResolver(dns_resolver_t *resolver, int index)
+do_printDNSConfiguration(int argc, char **argv, dns_config_t *dns_config)
{
- int i;
-
- SCPrint(TRUE, stdout, CFSTR("\nresolver #%d\n"), index);
-
- 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);
- }
+ int _sc_log_save;
- if (resolver->if_index != 0) {
- char buf[IFNAMSIZ];
- char *if_name;
-
- if_name = if_indextoname(resolver->if_index, buf);
- SCPrint(TRUE, stdout, CFSTR(" if_index : %d (%s)\n"),
- resolver->if_index,
- (if_name != NULL) ? if_name : "?");
- }
-
- if (resolver->flags != 0) {
- uint32_t flags = resolver->flags;
-
- SCPrint(TRUE, stdout, CFSTR(" flags : "));
- SCPrint(_sc_debug, stdout, CFSTR("0x%08x ("), flags);
- if (flags & DNS_RESOLVER_FLAGS_SCOPED) {
- SCPrint(TRUE, stdout, CFSTR("Scoped"));
- flags &= ~DNS_RESOLVER_FLAGS_SCOPED;
- SCPrint(flags != 0, stdout, CFSTR(","));
- }
- if (flags != 0) {
- SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags);
- }
- SCPrint(_sc_debug, stdout, CFSTR(")"));
- SCPrint(TRUE, stdout, CFSTR("\n"));
+ if (dns_config == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("No DNS configuration available\n"));
+ return;
}
- if (resolver->reach_flags != 0) {
- uint32_t flags = resolver->reach_flags;
-
- SCPrint(TRUE, stdout, CFSTR(" reach : "));
- SCPrint(_sc_debug, stdout, CFSTR("0x%08x ("), flags);
- _printReachabilityFlags(flags);
- SCPrint(_sc_debug, stdout, CFSTR(")"));
- SCPrint(TRUE, stdout, CFSTR("\n"));
- }
+ _sc_log_save = _sc_log;
+ _sc_log = FALSE;
+ _dns_configuration_log(dns_config, _sc_debug);
+ _sc_log = _sc_log_save;
- if (resolver->search_order != 0) {
- SCPrint(TRUE, stdout, CFSTR(" order : %d\n"), resolver->search_order);
+ if (_sc_debug) {
+ SCPrint(TRUE, stdout, CFSTR("\ngeneration = %llu\n"), dns_config->generation);
}
return;
void
do_showDNSConfiguration(int argc, char **argv)
{
- dns_config_t *dns_config;
- SCNetworkReachabilityRef target;
+ dns_config_t *dns_config;
dns_config = dns_configuration_copy();
-
- if (dns_config == NULL) {
- SCPrint(TRUE, stdout, CFSTR("No DNS configuration available\n"));
+ do_printDNSConfiguration(argc, argv, dns_config);
+ if (dns_config != NULL) {
+ dns_configuration_free(dns_config);
+ } else {
exit(1);
}
- if (argc > 1) {
- int dns_config_index = -1;
- SCNetworkReachabilityFlags flags = 0;
- Boolean haveDNS = FALSE;
- Boolean ok = FALSE;
- dns_resolver_t *resolver;
- uint32_t resolver_if_index;
- SCNetworkReachabilityPrivateRef targetPrivate;
-
- target = _setupReachability(argc, argv, NULL);
-
- targetPrivate = (SCNetworkReachabilityPrivateRef)target;
-
- if (targetPrivate->type != reachabilityTypeName) {
- SCPrint(TRUE, stdout, CFSTR("\"%s\" is not a hostname.\n"), argv[0]);
- exit(1);
- }
-
- ok = __SC_checkResolverReachabilityInternal(&store, &flags,
- &haveDNS, targetPrivate->name, NULL,
- &resolver_if_index, &dns_config_index);
-
- if (!ok) {
- SCPrint(TRUE, stdout, CFSTR("No DNS configuration available.\n" ));
- exit(1);
- }
-
- SCPrint(TRUE, stdout, CFSTR("DNS configuration for %s\n"),
- targetPrivate->name);
-
- if (targetPrivate->if_index == 0) {
- resolver = dns_config->resolver[dns_config_index];
- } else {
- resolver = dns_config->scoped_resolver[dns_config_index];
- }
-
- showResolver(resolver, dns_config_index + 1);
-
- if (target != NULL) CFRelease(target);
- } else {
- int i;
-
- SCPrint(TRUE, stdout, CFSTR("DNS configuration\n"));
-
- for (i = 0; i < dns_config->n_resolver; i++) {
- dns_resolver_t *resolver = dns_config->resolver[i];
+ exit(0);
+}
- showResolver(resolver, i + 1);
- }
- if ((dns_config->n_scoped_resolver > 0) && (dns_config->scoped_resolver != NULL)) {
- SCPrint(TRUE, stdout, CFSTR("\nDNS configuration (for scoped queries)\n"));
+__private_extern__
+void
+do_watchDNSConfiguration(int argc, char **argv)
+{
+ dns_config_t *dns_config;
+ int status;
+ int token;
- for (i = 0; i < dns_config->n_scoped_resolver; i++) {
- dns_resolver_t *resolver = dns_config->scoped_resolver[i];
+ dns_config = dns_configuration_copy();
+ do_printDNSConfiguration(argc, argv, dns_config);
+ if (dns_config != NULL) {
+ dns_configuration_free(dns_config);
+ }
- showResolver(resolver, i + 1);
- }
- }
+ status = notify_register_dispatch(dns_configuration_notify_key(),
+ &token,
+ dispatch_get_main_queue(),
+ ^(int token){
+ dns_config_t *dns_config;
+ 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);
+
+ dns_config = dns_configuration_copy();
+ do_printDNSConfiguration(argc, argv, dns_config);
+ if (dns_config != NULL) {
+ dns_configuration_free(dns_config);
+ }
+ });
+ if (status != NOTIFY_STATUS_OK) {
+ SC_log(LOG_INFO, "notify_register_dispatch() failed for DNS configuration changes, status=%u", status);
+ exit(1);
}
- dns_configuration_free(dns_config);
+ CFRunLoopRun();
exit(0);
}
if (!_sc_debug) {
cleaned = CFDictionaryCreateMutableCopy(NULL, 0, proxy);
- CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesSupplemental);
CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesScoped);
+ CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesServices);
+ CFDictionaryRemoveValue(cleaned, kSCPropNetProxiesSupplemental);
proxy = cleaned;
}
void
do_showProxyConfiguration(int argc, char **argv)
{
- CFDictionaryRef proxies;
+ CFMutableDictionaryRef options = NULL;
+ CFDictionaryRef proxies;
+
+ if (getenv("BYPASS_GLOBAL_PROXY") != NULL) {
+ options = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionaryAddValue(options, kSCProxiesNoGlobal, kCFBooleanTrue);
+ }
+
+ proxies = SCDynamicStoreCopyProxiesWithOptions(NULL, options);
+
+ if (options != NULL) {
+ CFRelease(options);
+ }
- proxies = SCDynamicStoreCopyProxies(NULL);
if (proxies != NULL) {
CFStringRef interface = NULL;
CFStringRef server = NULL;
CFDictionaryRef proxy;
proxy = CFArrayGetValueAtIndex(matching, i);
- SCPrint(TRUE, stdout, CFSTR("\nproxy #%d\n"), i + 1);
+ SCPrint(TRUE, stdout, CFSTR("\nproxy #%ld\n"), i + 1);
showProxy(proxy);
}
SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
}
-#ifdef HAVE_REACHABILITY_SERVER
- (void) _SCNetworkReachabilityServer_snapshot();
-#endif // HAVE_REACHABILITY_SERVER
-
return;
}
+__private_extern__
+void
+do_renew(char *if_name)
+{
+ CFArrayRef services;
+ Boolean ok = FALSE;
+
+ if ((if_name == NULL) || (strlen(if_name) == 0)) {
+ SCPrint(TRUE, stderr, CFSTR("No interface name\n"));
+ exit(1);
+ }
+
+ if (getenv("ATTEMPT_DHCP_RENEW_WITH_SCDYNAMICSTORE") != NULL) {
+ CFArrayRef interfaces;
+
+ interfaces = SCNetworkInterfaceCopyAll();
+ if (interfaces != NULL) {
+ CFIndex i;
+ CFStringRef match_name;
+ CFIndex n;
+
+ match_name = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII);
+ assert(match_name != NULL);
+
+ n = CFArrayGetCount(interfaces);
+ for (i = 0; i < n; i++) {
+ CFStringRef bsd_name;
+ SCNetworkInterfaceRef interface;
+
+ interface = CFArrayGetValueAtIndex(interfaces, i);
+ bsd_name = SCNetworkInterfaceGetBSDName(interface);
+ if (_SC_CFEqual(bsd_name, match_name)) {
+ // if match
+ ok = SCNetworkInterfaceForceConfigurationRefresh(interface);
+ if (!ok) {
+ int status;
+
+ status = SCError();
+ if (status != kSCStatusAccessError) {
+ SCPrint(TRUE, stderr, CFSTR("%s\n"), SCErrorString(status));
+ exit(1);
+ }
+
+ // ... and if can't write the SCDynamicStore, try w/prefs
+ }
+
+ break;
+ }
+ }
+
+ CFRelease(match_name);
+ CFRelease(interfaces);
+ }
+
+ if (ok) {
+ exit(0);
+ }
+ }
+
+ do_prefs_init(); /* initialization */
+ do_prefs_open(0, NULL); /* open default prefs */
+
+ services = SCNetworkServiceCopyAll(prefs);
+ if (services != NULL) {
+ CFIndex i;
+ CFStringRef match_name;
+ CFIndex n;
+
+ match_name = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII);
+ assert(match_name != NULL);
+
+ n = CFArrayGetCount(services);
+ for (i = 0; i < n; i++) {
+ CFStringRef bsd_name;
+ SCNetworkInterfaceRef interface;
+ SCNetworkServiceRef service;
+
+ service = CFArrayGetValueAtIndex(services, i);
+ interface = SCNetworkServiceGetInterface(service);
+ if (interface == NULL) {
+ // if no interface
+ continue;
+ }
+
+ bsd_name = SCNetworkInterfaceGetBSDName(interface);
+ if (_SC_CFEqual(bsd_name, match_name)) {
+ // if match
+ ok = SCNetworkInterfaceForceConfigurationRefresh(interface);
+ if (!ok) {
+ SCPrint(TRUE, stderr, CFSTR("%s\n"), SCErrorString(SCError()));
+ exit(1);
+ }
+
+ break;
+ }
+ }
+
+ CFRelease(match_name);
+ CFRelease(services);
+ }
+
+ if (!ok) {
+ SCPrint(TRUE, stderr, CFSTR("No interface\n"));
+ exit(1);
+ }
+
+ _prefs_close();
+ exit(0);
+}
+
+
static void
waitKeyFound()
{
CFRunLoopRun();
}
-#ifdef TEST_DNS_CONFIGURATION_COPY
+#ifdef TEST_DNS_CONFIGURATION
+Boolean doDispatch = FALSE;
CFRunLoopSourceRef notifyRls = NULL;
SCDynamicStoreRef store = NULL;
CFPropertyListRef value = NULL;
int
main(int argc, char **argv)
{
+ dns_config_t *dns_config;
+
+fprintf(stdout, "copy configuration\n");
+ dns_config = dns_configuration_copy();
+ if (dns_config != NULL) {
+
+fprintf(stdout, "sleeping for 120 seconds\n");
+sleep(120);
+
+fprintf(stdout, "sending ack\n");
+ _dns_configuration_ack(dns_config, "TEST_DNS_CONFIGURATION");
+
+fprintf(stdout, "sleeping for 120 seconds\n");
+sleep(120);
+
+ dns_configuration_free(dns_config);
+ }
+
do_showDNSConfiguration(argc, argv);
exit(0);
}
-#endif // TEST_DNS_CONFIGURATION_COPY
+#endif // TEST_DNS_CONFIGURATION