-noinstallsrc -noinstallhdrs -noverify -nosum \
-arch i386 -arch x86_64 -arch ppc \
-target All \
- -project configd \
+ -project ${PROJECT}-${VERSION} \
-configuration Debug \
-release $(shell cat /usr/share/buildit/.releaseName) \
#----------------------------------------------------------------------
#
-# Build for SnowLeopard, SUSnowXXX, ...
-#
-# Note: assumes that the "pppcontroller_sendmsg" routine has been defined
-# in pppcontroller.defs.
+# Darwin build
#
#----------------------------------------------------------------------
-SNOW_CFLAGS += -D__MAC_10_7=1060
-SNOW_CFLAGS += -D__AVAILABILITY_INTERNAL__MAC_10_7=__AVAILABILITY_INTERNAL__MAC_10_6
-SNOW_CFLAGS += -D__AVAILABILITY_INTERNAL__MAC_10_5_DEP__MAC_10_7=__AVAILABILITY_INTERNAL__MAC_10_5
-#SNOW_CFLAGS += -DHAVE_PPPCONTROLLER_SENDMSG=YES
-
-snow :
+darwin :
/usr/local/bin/buildit . \
-noinstallsrc -noinstallhdrs -noverify -nosum \
- -arch i386 -arch x86_64 -arch ppc \
+ -arch i386 -arch x86_64 -arch ppc \
-target All \
- -project ${PROJECT} \
+ -project ${PROJECT}_darwin-${VERSION} \
-configuration Debug \
-release $(shell cat /usr/share/buildit/.releaseName) \
- -othercflags "\"$(SNOW_CFLAGS)\"" \
+ -othercflags "\"-D_OPEN_SOURCE_\"" \
#----------------------------------------------------------------------
#
#----------------------------------------------------------------------
LION_CFLAGS=
+LION_CFLAGS+=-D__MAC_10_8=1070
+LION_CFLAGS+=-D__AVAILABILITY_INTERNAL__MAC_10_8=__attribute__((visibility(\\\"default\\\")))
+LION_CFLAGS+=-DHAVE_REACHABILITY_SERVER=YES
lion :
/usr/local/bin/buildit . \
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.11.3</string>
+ <string>1.12</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.11</string>
+ <string>1.12</string>
<key>Requires</key>
<array>
<string>com.apple.SystemConfiguration.IPConfiguration</string>
<string>com.apple.SystemConfiguration.PreferencesMonitor</string>
+ <string>com.apple.SystemConfiguration.SCNetworkReachability</string>
</array>
<key>Builtin</key>
<true/>
cc -I../../dnsinfo -Wall -O0 -g -c shared_dns_infoUser.c
dnsinfo_create.o: shared_dns_info.h ../../dnsinfo/dnsinfo_create.h ../../dnsinfo/dnsinfo_create.c
- cc -I. -I../../dnsinfo -Wall -O0 -g -c ../../dnsinfo/dnsinfo_create.c
+ cc -I. -I../../dnsinfo -I../../nwi -Wall -O0 -g -c ../../dnsinfo/dnsinfo_create.c
dnsinfo_flatfile.o: ../../dnsinfo/dnsinfo_copy.c ../../dnsinfo/dnsinfo_flatfile.c shared_dns_info.h
- cc -I../../dnsinfo -D_PATH_RESOLVER_DIR='"/var/tmp/resolver"' -Wall -O0 -g -c ../../dnsinfo/dnsinfo_flatfile.c
+ cc -I../../dnsinfo -I../../nwi -D_PATH_RESOLVER_DIR='"/var/tmp/resolver"' -Wall -O0 -g -c ../../dnsinfo/dnsinfo_flatfile.c
dnsinfo_private.o: ../../dnsinfo/dnsinfo_private.h ../../dnsinfo/dnsinfo_private.c
cc -I../../dnsinfo -Wall -O0 -g -c ../../dnsinfo/dnsinfo_private.c
dns-configuration.o: dns-configuration.h dns-configuration.c dnsinfo_create.o
- cc -I. -I../../dnsinfo -DMAIN -Wall -O0 -g -c dns-configuration.c
+ cc -I. -I../../dnsinfo -I../../nwi -DMAIN -Wall -O0 -g -c dns-configuration.c
+
+network_information_priv.o: ../../nwi/network_information_priv.h ../../nwi/network_information_priv.c
+ cc -I. -I../../dnsinfo -I../../nwi -DMAIN -Wall -O0 -g -c ../../nwi/network_information_priv.c
proxy-configuration.o: proxy-configuration.h proxy-configuration.c
cc -I. -Wall -O0 -g -c proxy-configuration.c
# ----------
test_ipv4_routelist.o: ip_plugin.c
- cc -I. -I../../dnsinfo -DTEST_IPV4_ROUTELIST -Wall -O0 -g -c -o test_ipv4_routelist.o ip_plugin.c
+ cc -I. -I../../dnsinfo -I../../nwi -DTEST_IPV4_ROUTELIST -Wall -O0 -g -c -o test_ipv4_routelist.o ip_plugin.c
-test_ipv4_routelist: test_ipv4_routelist.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o shared_dns_infoUser.o smb-configuration.o
- cc -Wall -O0 -g -o test_ipv4_routelist test_ipv4_routelist.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o shared_dns_infoUser.o smb-configuration.o -framework SystemConfiguration -framework CoreFoundation
+test_ipv4_routelist: test_ipv4_routelist.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o shared_dns_infoUser.o network_information_priv.o smb-configuration.o proxy-configuration.o
+ cc -Wall -O0 -g -o test_ipv4_routelist test_ipv4_routelist.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o network_information_priv.o shared_dns_infoUser.o smb-configuration.o proxy-configuration.o -framework SystemConfiguration -framework CoreFoundation
test_ipv4_routelist_reference.txt: test_ipv4_routelist
sh test_reference.sh create test_ipv4_routelist test_ipv4_routelist_reference.txt test_ipv4_routelist_filter.sh
# ----------
IPMonitor.o: ip_plugin.c
- cc -I. -I../../dnsinfo -DTEST_IPMONITOR -Wall -O0 -g -c -o IPMonitor.o ip_plugin.c
+ cc -I. -I../../dnsinfo -I../../nwi -DTEST_IPMONITOR -Wall -O0 -g -c -o IPMonitor.o ip_plugin.c
IPMonitor: IPMonitor.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o shared_dns_infoUser.o smb-configuration.o
cc -Wall -O0 -g -o IPMonitor IPMonitor.o dnsinfo_create.o dnsinfo_flatfile.o dnsinfo_private.o shared_dns_infoUser.o smb-configuration.o -framework SystemConfiguration -framework CoreFoundation
#include <notify.h>
extern uint32_t notify_monitor_file(int token, const char *name, int flags);
#endif // !TARGET_OS_IPHONE
+#include <CommonCrypto/CommonDigest.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
#include <SystemConfiguration/SCValidation.h>
+#include "dns-configuration.h"
+
#include <dnsinfo.h>
#include <dnsinfo_create.h>
#define kDNSServiceCompPrivateDNS "PrivateDNS"
#endif
+#define DNS_CONFIGURATION_FLAGS_KEY CFSTR("__FLAGS__")
+#define DNS_CONFIGURATION_IF_INDEX_KEY CFSTR("__IF_INDEX__")
+#define DNS_CONFIGURATION_ORDER_KEY CFSTR("__ORDER__")
+
/* multicast DNS resolver configurations */
static CFNumberRef S_mdns_timeout = NULL;
add_resolver(CFMutableArrayRef resolvers, CFMutableDictionaryRef resolver)
{
CFIndex i;
+ CFStringRef interface;
CFIndex n_resolvers;
CFNumberRef order;
uint32_t order_val = 0;
}
}
- order = CFNumberCreate(NULL, kCFNumberIntType, &n_resolvers);
- CFDictionarySetValue(resolver, CFSTR("*ORDER*"), order);
+ order = CFNumberCreate(NULL, kCFNumberCFIndexType, &n_resolvers);
+ CFDictionarySetValue(resolver, DNS_CONFIGURATION_ORDER_KEY, order);
CFRelease(order);
+ interface = CFDictionaryGetValue(resolver, kSCPropInterfaceName);
+ if (interface != NULL) {
+ uint32_t flags;
+ unsigned int if_index = 0;
+ char if_name[IF_NAMESIZE];
+ CFNumberRef num;
+ CFBooleanRef val;
+
+ if (_SC_cfstring_to_cstring(interface,
+ if_name,
+ sizeof(if_name),
+ kCFStringEncodingASCII) != NULL) {
+ if_index = if_nametoindex(if_name);
+ }
+
+ if ((if_index != 0) &&
+ (
+ // check if this is a "scoped" configuration
+ (CFDictionaryGetValueIfPresent(resolver, DNS_CONFIGURATION_FLAGS_KEY, (const void **)&num) &&
+ isA_CFNumber(num) &&
+ CFNumberGetValue(num, kCFNumberSInt32Type, &flags) &&
+ (flags & DNS_RESOLVER_FLAGS_SCOPED) != 0)
+ ||
+ // check if we should scope all queries with this configuration
+ (CFDictionaryGetValueIfPresent(resolver, DNS_CONFIGURATION_SCOPED_QUERY_KEY, (const void **)&val) &&
+ isA_CFBoolean(val) &&
+ CFBooleanGetValue(val))
+ )
+ ) {
+ // if interface index available and it should be used
+ num = CFNumberCreate(NULL, kCFNumberIntType, &if_index);
+ CFDictionarySetValue(resolver, DNS_CONFIGURATION_IF_INDEX_KEY, num);
+ CFRelease(num);
+ }
+ }
+
CFArrayAppendValue(resolvers, resolver);
return;
}
if (order1 == order2) {
// if same "SearchOrder", retain original orderring for configurations
- if (CFDictionaryGetValueIfPresent(dns1, CFSTR("*ORDER*"), (const void **)&num1) &&
- CFDictionaryGetValueIfPresent(dns2, CFSTR("*ORDER*"), (const void **)&num2) &&
+ if (CFDictionaryGetValueIfPresent(dns1, DNS_CONFIGURATION_ORDER_KEY, (const void **)&num1) &&
+ CFDictionaryGetValueIfPresent(dns2, DNS_CONFIGURATION_ORDER_KEY, (const void **)&num2) &&
isA_CFNumber(num1) &&
isA_CFNumber(num2) &&
CFNumberGetValue(num1, kCFNumberIntType, &order1) &&
}
-static CFArrayRef
+static CF_RETURNS_RETAINED CFArrayRef
extract_search_domains(CFMutableDictionaryRef defaultDomain, CFArrayRef supplemental)
{
CFStringRef defaultDomainName = NULL;
for (i = 0; i < n_order; i++) {
CFDictionaryRef dns;
uint32_t flags;
- unsigned int if_index;
char if_name[IF_NAMESIZE];
CFStringRef interface;
CFMutableDictionaryRef newDNS;
if_name,
sizeof(if_name),
kCFStringEncodingASCII) == NULL) ||
- ((if_index = if_nametoindex(if_name)) == 0)) {
+ (if_nametoindex(if_name) == 0)) {
// if interface index not available
continue;
}
CFRelease(searchDomains);
}
- // set if_index
- num = CFNumberCreate(NULL, kCFNumberIntType, &if_index);
- CFDictionarySetValue(newDNS, CFSTR("*IF_INDEX*"), num);
- CFRelease(num);
-
- // set "scoped" flag
- flags = DNS_RESOLVER_FLAGS_SCOPED;
+ // set "scoped" configuration flag(s)
+ if (!CFDictionaryGetValueIfPresent(newDNS, DNS_CONFIGURATION_FLAGS_KEY, (const void **)&num) ||
+ !isA_CFNumber(num) ||
+ !CFNumberGetValue(num, kCFNumberSInt32Type, &flags)) {
+ flags = 0;
+ }
+ flags |= DNS_RESOLVER_FLAGS_SCOPED;
num = CFNumberCreate(NULL, kCFNumberSInt32Type, &flags);
- CFDictionarySetValue(newDNS, CFSTR("*FLAGS*"), num);
+ CFDictionarySetValue(newDNS, DNS_CONFIGURATION_FLAGS_KEY, num);
CFRelease(num);
// remove keys we don't want in a [scoped] resolver
}
+/*
+ * rankReachability()
+ * Not reachable == 0
+ * Connection Required == 1
+ * Reachable == 2
+ */
+static int
+rankReachability(SCNetworkReachabilityFlags flags)
+{
+ int rank = 0;
+
+ if (flags & kSCNetworkReachabilityFlagsReachable) rank = 2;
+ if (flags & kSCNetworkReachabilityFlagsConnectionRequired) rank = 1;
+ return rank;
+}
+
+
static dns_create_resolver_t
create_resolver(CFDictionaryRef dns)
{
CFNumberRef num;
dns_create_resolver_t _resolver;
CFStringRef str;
+ CFMutableArrayRef serverAddresses = NULL;
+ CFStringRef targetInterface = NULL;
+ unsigned int targetInterfaceIndex = 0;
_resolver = _dns_resolver_create();
}
}
+ // process interface index
+ num = CFDictionaryGetValue(dns, DNS_CONFIGURATION_IF_INDEX_KEY);
+ if (isA_CFNumber(num)) {
+ int if_index;
+
+ if (CFNumberGetValue(num, kCFNumberIntType, &if_index)) {
+ char if_name[IFNAMSIZ];
+
+ _dns_resolver_set_if_index(&_resolver, if_index);
+
+ if ((if_index != 0) &&
+ (if_indextoname(if_index, if_name) != NULL)) {
+ targetInterface = CFStringCreateWithCString(NULL,
+ if_name,
+ kCFStringEncodingASCII);
+ targetInterfaceIndex = if_index;
+ }
+ }
+ }
+
// process nameserver addresses
list = CFDictionaryGetValue(dns, kSCPropNetDNSServerAddresses);
if (isA_CFArray(list)) {
CFIndex i;
- CFIndex n = CFArrayGetCount(list);
+ CFIndex n = CFArrayGetCount(list);
+
+ serverAddresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
for (i = 0; i < n; i++) {
union {
- struct sockaddr sa;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
} addr;
- char buf[128];
+ char buf[64];
+ CFDataRef serverAddress;
str = CFArrayGetValueAtIndex(list, i);
if (!isA_CFString(str)) {
continue;
}
- bzero(&addr, sizeof(addr));
- if (inet_aton(buf, &addr.sin.sin_addr) == 1) {
- /* if IPv4 address */
- addr.sin.sin_len = sizeof(addr.sin);
- addr.sin.sin_family = AF_INET;
- _dns_resolver_add_nameserver(&_resolver, &addr.sa);
- } else if (inet_pton(AF_INET6, buf, &addr.sin6.sin6_addr) == 1) {
- /* if IPv6 address */
- char *p;
-
- p = strchr(buf, '%');
- if (p != NULL) {
- addr.sin6.sin6_scope_id = if_nametoindex(p + 1);
- }
-
- addr.sin6.sin6_len = sizeof(addr.sin6);
- addr.sin6.sin6_family = AF_INET6;
- _dns_resolver_add_nameserver(&_resolver, &addr.sa);
- } else {
+ if (_SC_string_to_sockaddr(buf, AF_UNSPEC, (void *)&addr, sizeof(addr)) == NULL) {
continue;
}
+
+ if ((addr.sa.sa_family == AF_INET6) &&
+ (IN6_IS_ADDR_LINKLOCAL(&addr.sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&addr.sin6.sin6_addr)) &&
+ (addr.sin6.sin6_scope_id == 0) &&
+ (targetInterfaceIndex != 0)) {
+ // for link local [IPv6] addresses, if the scope id is not
+ // set then we should use the interface associated with the
+ // resolver configuration
+ addr.sin6.sin6_scope_id = targetInterfaceIndex;
+ }
+
+ _dns_resolver_add_nameserver(&_resolver, &addr.sa);
+
+ serverAddress = CFDataCreate(NULL, (const void *)&addr.sa, addr.sa.sa_len);
+ CFArrayAppendValue(serverAddresses, serverAddress);
+ CFRelease(serverAddress);
}
}
}
}
- // process interface index
- num = CFDictionaryGetValue(dns, CFSTR("*IF_INDEX*"));
- if (isA_CFNumber(num)) {
- int if_index;
-
- if (CFNumberGetValue(num, kCFNumberIntType, &if_index)) {
- _dns_resolver_set_if_index(&_resolver, if_index);
- }
- }
-
// process flags
- num = CFDictionaryGetValue(dns, CFSTR("*FLAGS*"));
+ num = CFDictionaryGetValue(dns, DNS_CONFIGURATION_FLAGS_KEY);
if (isA_CFNumber(num)) {
uint32_t flags;
}
}
+ if (serverAddresses != NULL) {
+ SCNetworkReachabilityFlags flags = kSCNetworkReachabilityFlagsReachable;
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(serverAddresses);
+ CFMutableDictionaryRef targetOptions;
+
+ targetOptions = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (targetInterface != NULL) {
+ CFDictionarySetValue(targetOptions,
+ kSCNetworkReachabilityOptionInterface,
+ targetInterface);
+ }
+
+ for (i = 0; i < n; i++) {
+ SCNetworkReachabilityFlags ns_flags;
+ Boolean ok;
+ CFDataRef serverAddress;
+ SCNetworkReachabilityRef target;
+
+ serverAddress = CFArrayGetValueAtIndex(serverAddresses, i);
+ CFDictionarySetValue(targetOptions,
+ kSCNetworkReachabilityOptionRemoteAddress,
+ serverAddress);
+ target = SCNetworkReachabilityCreateWithOptions(NULL, targetOptions);
+ if (target == NULL) {
+ CFDictionaryRemoveValue(targetOptions, kSCNetworkReachabilityOptionInterface);
+ target = SCNetworkReachabilityCreateWithOptions(NULL, targetOptions);
+ if (target != NULL) {
+ // if interface name not (no longer) valid
+ CFRelease(target);
+ flags = 0;
+ break;
+ }
+
+ // address not valid?
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("create_resolver SCNetworkReachabilityCreateWithOptions() failed:\n options = %@"),
+ targetOptions);
+ break;
+ }
+
+ ok = SCNetworkReachabilityGetFlags(target, &ns_flags);
+ CFRelease(target);
+ if (!ok) {
+ break;
+ }
+
+ if ((i == 0) ||
+ (rankReachability(ns_flags) < rankReachability(flags))) {
+ /* return the worst case result */
+ flags = ns_flags;
+ }
+ }
+
+ _dns_resolver_set_reach_flags(&_resolver, flags);
+
+ CFRelease(targetOptions);
+ CFRelease(serverAddresses);
+ }
+
+ if (targetInterface != NULL) {
+ CFRelease(targetInterface);
+ }
+
return _resolver;
}
static __inline__ Boolean
-isScopedDNS(CFDictionaryRef dns)
+isScopedConfiguration(CFDictionaryRef dns)
{
uint32_t flags;
CFNumberRef num;
if ((dns != NULL) &&
- CFDictionaryGetValueIfPresent(dns, CFSTR("*FLAGS*"), (const void **)&num) &&
+ CFDictionaryGetValueIfPresent(dns, DNS_CONFIGURATION_FLAGS_KEY, (const void **)&num) &&
(num != NULL) &&
CFNumberGetValue(num, kCFNumberSInt32Type, &flags) &&
((flags & DNS_RESOLVER_FLAGS_SCOPED) != 0)) {
}
// sort non-scoped before scoped
- scoped1 = isScopedDNS(dns1);
- scoped2 = isScopedDNS(dns2);
+ scoped1 = isScopedConfiguration(dns1);
+ scoped2 = isScopedConfiguration(dns2);
if (scoped1 != scoped2) {
if (!scoped1) {
return kCFCompareLessThan;
__private_extern__
-void
+Boolean
dns_configuration_set(CFDictionaryRef defaultResolver,
CFDictionaryRef services,
CFArrayRef serviceOrder,
CFArrayRef multicastResolvers,
CFArrayRef privateResolvers)
{
+ dns_create_config_t _config;
+ Boolean changed = FALSE;
CFIndex i;
CFMutableDictionaryRef myDefault;
Boolean myOrderAdded = FALSE;
CFArrayRef mySearchDomains = NULL;
CFIndex n_resolvers;
CFMutableArrayRef resolvers;
+ unsigned char signature[CC_SHA1_DIGEST_LENGTH];
+ static unsigned char signature_last[CC_SHA1_DIGEST_LENGTH];
// establish list of resolvers
resolver = CFArrayGetValueAtIndex(resolvers, 1);
if (CFDictionaryContainsKey(resolver, kSCPropNetDNSDomainName) ||
- isScopedDNS(resolver)) {
+ isScopedConfiguration(resolver)) {
// if not a supplemental "default" resolver (a domain name is
- // present) or a if it's a scoped resolver
+ // present) or if it's a scoped configuration
CFDictionaryRemoveValue(myDefault, kSCPropNetDNSSearchOrder);
}
}
/*
* if no default and no supplemental/scoped resolvers
*/
- if (!_dns_configuration_store(NULL)) {
- SCLog(TRUE, LOG_ERR, CFSTR("dns_configuration_set: could not store configuration"));
- }
+ _config = NULL;
} else {
- dns_create_config_t _config;
-
/*
* if default and/or supplemental/scoped resolvers are defined
*/
_dnsinfo_flatfile_add_resolvers(&_config);
#endif // !TARGET_OS_IPHONE
+ }
- // save configuration
-
- if (!_dns_configuration_store(&_config)) {
- SCLog(TRUE, LOG_ERR, CFSTR("dns_configuration_set: could not store configuration"));
- }
+ // check if the configuration changed
+ _dns_configuration_signature(&_config, signature, sizeof(signature));
+ if (bcmp(signature, signature_last, sizeof(signature)) != 0) {
+ changed = TRUE;
+ }
+ bcopy(signature, signature_last, sizeof(signature));
- _dns_configuration_free(&_config);
+ // save configuration
+ if (!_dns_configuration_store(&_config)) {
+ SCLog(TRUE, LOG_ERR, CFSTR("dns_configuration_set: could not store configuration"));
}
+ if (_config != NULL) _dns_configuration_free(&_config);
CFRelease(resolvers);
- return;
+ return changed;
}
}
+#pragma mark -
+#pragma mark Standalone test code
+
+
#ifdef MAIN
static void
// update DNS configuration
dns_configuration_init(CFBundleGetMainBundle());
- dns_configuration_set(primaryDNS,
- service_state_dict,
- service_order,
- multicast_resolvers,
- private_resolvers);
+ (void)dns_configuration_set(primaryDNS,
+ service_state_dict,
+ service_order,
+ multicast_resolvers,
+ private_resolvers);
// cleanup
if (setup_global_ipv4 != NULL) CFRelease(setup_global_ipv4);
/*
- * Copyright (c) 2006, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2006, 2008, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <sys/cdefs.h>
#include <CoreFoundation/CoreFoundation.h>
+
+#define DNS_CONFIGURATION_SCOPED_QUERY_KEY CFSTR("__SCOPED_QUERY__")
+
+
__BEGIN_DECLS
+__private_extern__
void dns_configuration_init (CFBundleRef bundle);
#if !TARGET_OS_IPHONE
+__private_extern__
void dns_configuration_monitor (SCDynamicStoreRef store,
SCDynamicStoreCallBack callout);
#endif // !TARGET_OS_IPHONE
-void dns_configuration_set (CFDictionaryRef defaultResolver,
+__private_extern__
+Boolean dns_configuration_set (CFDictionaryRef defaultResolver,
CFDictionaryRef services,
CFArrayRef serviceOrder,
CFArrayRef multicastResolvers,
/*
- * Copyright (c) 2000-2011 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2000-2012 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <sys/sysctl.h>
#include <limits.h>
#include <notify.h>
+#include <mach/mach_time.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
#ifndef kDNSServiceCompPrivateDNS
#define kDNSServiceCompPrivateDNS "PrivateDNS"
#endif
+#include <network_information.h>
+#include "network_information_priv.h"
enum {
kProtocolFlagsNone = 0x0,
kDebugFlag2 = 0x00000002,
kDebugFlag4 = 0x00000004,
kDebugFlag8 = 0x00000008,
- kDebugFlagDefault = kDebugFlag1,
+ kDebugFlagDefault = kDebugFlag1,
kDebugFlagAll = 0xffffffff
};
#define IP_CH(ip) ((u_char *)(ip))
#define IP_LIST(ip) IP_CH(ip)[0],IP_CH(ip)[1],IP_CH(ip)[2],IP_CH(ip)[3]
-typedef uint32_t Rank;
-
-enum {
- kRankFirst = 0,
- kRankLast = UINT_MAX
-};
-
/*
* IPv4 Route management
*/
typedef uint32_t RouteFlags;
enum {
- kRouteIsDirectToInterfaceFlag = 0x00000001,
- kRouteIsNotSubnetLocalFlag = 0x00000002,
- kRouteChooseFirstFlag = 0x00000004,
- kRouteChooseLastFlag = 0x00000008,
- kRouteChooseNeverFlag = 0x00000010,
- kRouteIsScopedFlag = 0x00000020,
- kRouteWantScopedFlag = (kRouteChooseNeverFlag|kRouteIsScopedFlag),
+ kRouteIsDirectToInterfaceFlag = 0x00000001,
+ kRouteIsNotSubnetLocalFlag = 0x00000002,
+ kRouteIsScopedFlag = 0x00000004,
};
typedef struct {
kIPv4RouteListRemoveRouteCommand
};
+typedef struct {
+ char ifname[IFNAMSIZ];
+ uint32_t flags;
+ Rank rank;
+ struct in6_addr iaddr6;
+} IPv6RankedE, *IPv6RankedERef;
+
+typedef struct {
+ int count;
+ int size;
+ IPv6RankedE elem[1];
+} IPv6RankedList, *IPv6RankedListRef;
+
+/*
+ * Type: Rank
+ * Purpose:
+ * A 32-bit value to encode the relative rank of a service.
+ *
+ * The top 8 bits are used to hold the rank assertion (first, last, never, default),
+ * the bottom 24 bits are used to store the service index i.e. the position within
+ * the service order array.
+ */
+#define RANK_ASSERTION_MAKE(r) ((Rank)(r) << 24)
+#define kRankAssertionFirst RANK_ASSERTION_MAKE(0)
+#define kRankAssertionDefault RANK_ASSERTION_MAKE(1)
+#define kRankAssertionLast RANK_ASSERTION_MAKE(2)
+#define kRankAssertionNever RANK_ASSERTION_MAKE(3)
+#define kRankAssertionMask RANK_ASSERTION_MAKE(0xff)
+#define RANK_ASSERTION_MASK(r) ((Rank)(r) & kRankAssertionMask)
+
+#define RANK_INDEX_MAKE(r) ((Rank)(r))
+#define kRankIndexMask RANK_INDEX_MAKE(0xffffff)
+#define RANK_INDEX_MASK(r) ((Rank)(r) & kRankIndexMask)
+
+static __inline__ Rank
+RankMake(uint32_t service_index, Rank primary_rank)
+{
+ return (RANK_INDEX_MASK(service_index) | RANK_ASSERTION_MASK(primary_rank));
+}
+
+static __inline__ Rank
+PrimaryRankGetRankAssertion(CFStringRef primaryRank)
+{
+ if (CFEqual(primaryRank, kSCValNetServicePrimaryRankNever)) {
+ return kRankAssertionNever;
+ } else if (CFEqual(primaryRank, kSCValNetServicePrimaryRankFirst)) {
+ return kRankAssertionFirst;
+ } else if (CFEqual(primaryRank, kSCValNetServicePrimaryRankLast)) {
+ return kRankAssertionLast;
+ }
+ return kRankAssertionDefault;
+}
+
typedef uint32_t IPv4RouteListApplyCommand;
typedef void IPv4RouteListApplyCallBackFunc(IPv4RouteListApplyCommand cmd,
static CFMutableDictionaryRef S_ipv4_service_rank_dict = NULL;
static CFMutableDictionaryRef S_ipv6_service_rank_dict = NULL;
+/* dictionary to hold per-interface rank information */
+static CFMutableDictionaryRef S_if_rank_dict = NULL;
+
/* if set, a PPP interface overrides the primary */
static boolean_t S_ppp_override_primary = FALSE;
static boolean_t S_append_state = FALSE;
+static nwi_state_t S_nwi_state = NULL;
+
#if !TARGET_OS_IPHONE
static CFStringRef S_primary_smb = NULL;
static CFStringRef S_state_global_smb = NULL;
#ifndef KERN_NETBOOT
#define KERN_NETBOOT 40 /* int: are we netbooted? 1=yes,0=no */
-#endif KERN_NETBOOT
+#endif //KERN_NETBOOT
/**
** entityType*, GetEntityChanges*
#endif /* !TARGET_OS_IPHONE */
};
+#ifndef kSCEntNetIPv4RouteList
+#define kSCEntNetIPv4RouteList CFSTR("IPv4RouteList")
+#endif
+
+#ifndef kSCEntNetIPv4ServiceDict
+#define kSCEntNetIPv4ServiceDict CFSTR("IPv4ServiceDict")
+#endif
+
+static IPv4RouteListRef
+ipv4_dict_get_routelist(CFDictionaryRef ipv4_dict)
+{
+ CFDataRef routes;
+ IPv4RouteListRef routes_list = NULL;
+
+ if (isA_CFDictionary(ipv4_dict) == NULL) {
+ return (NULL);
+ }
+
+ routes = CFDictionaryGetValue(ipv4_dict, kSCEntNetIPv4RouteList);
+
+ if (routes != NULL) {
+ routes_list = (IPv4RouteListRef)(void*)CFDataGetBytePtr(routes);
+ }
+ return (routes_list);
+}
+
+static CFStringRef
+ipv4_dict_get_ifname(CFDictionaryRef ipv4_dict)
+{
+ CFDictionaryRef ipv4_service_dict = NULL;
+
+ if (isA_CFDictionary(ipv4_dict) == NULL) {
+ return (NULL);
+ }
+
+ ipv4_service_dict = CFDictionaryGetValue(ipv4_dict,
+ kSCEntNetIPv4ServiceDict);
+
+ if (isA_CFDictionary(ipv4_service_dict) == NULL) {
+ return NULL;
+ }
+
+ return CFDictionaryGetValue(ipv4_service_dict, kSCPropInterfaceName);
+}
+
typedef boolean_t GetEntityChangesFunc(CFStringRef serviceID,
CFDictionaryRef state_dict,
CFDictionaryRef setup_dict,
CFMutableDictionaryRef set;
} keyChangeList, * keyChangeListRef;
+static CFStringRef
+my_CFStringCopyComponent(CFStringRef path, CFStringRef separator,
+ CFIndex component_index)
+{
+ CFArrayRef arr;
+ CFStringRef component = NULL;
+
+ arr = CFStringCreateArrayBySeparatingStrings(NULL, path, separator);
+ if (arr == NULL) {
+ goto done;
+ }
+ if (CFArrayGetCount(arr) <= component_index) {
+ goto done;
+ }
+ component = CFRetain(CFArrayGetValueAtIndex(arr, component_index));
+
+ done:
+ my_CFRelease(&arr);
+ return (component);
+}
+
static void
keyChangeListInit(keyChangeListRef keys)
{
}
static void
-keyChangeListApplyToStore(keyChangeListRef keys, SCDynamicStoreRef session)
+keyChangeListApplyToStore(keyChangeListRef keys, SCDynamicStoreRef session,
+ CFStringRef network_change_msg)
{
CFArrayRef notify = keys->notify;
CFArrayRef remove = keys->remove;
status = notify_post("com.apple.system.config.network_change");
if (status == NOTIFY_STATUS_OK) {
- SCLog(TRUE, LOG_NOTICE, CFSTR("network configuration changed."));
+ if (CFStringGetLength(network_change_msg) != 0) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("network changed:%@"), network_change_msg);
+ } else {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("network changed."));
+ }
} else {
SCLog(TRUE, LOG_NOTICE,
CFSTR("IPMonitor: notify_post() failed: error=%ld"), status);
return (cfstring_to_ipvx(AF_INET6, str, ip6_p, sizeof(*ip6_p)));
}
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
setup_service_key(CFStringRef serviceID, CFStringRef entity)
{
return (SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
entity));
}
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
state_service_key(CFStringRef serviceID, CFStringRef entity)
{
return (SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
}
static CFDictionaryRef
-get_service_setup_entity(CFDictionaryRef service_info, CFStringRef serviceID,
+get_service_setup_entity(CFDictionaryRef services_info, CFStringRef serviceID,
CFStringRef entity)
{
CFStringRef setup_key;
CFDictionaryRef setup_dict;
setup_key = setup_service_key(serviceID, entity);
- setup_dict = my_CFDictionaryGetDictionary(service_info, setup_key);
+ setup_dict = my_CFDictionaryGetDictionary(services_info, setup_key);
my_CFRelease(&setup_key);
return (setup_dict);
}
static CFDictionaryRef
-get_service_state_entity(CFDictionaryRef service_info, CFStringRef serviceID,
+get_service_state_entity(CFDictionaryRef services_info, CFStringRef serviceID,
CFStringRef entity)
{
CFStringRef state_key;
CFDictionaryRef state_dict;
state_key = state_service_key(serviceID, entity);
- state_dict = my_CFDictionaryGetDictionary(service_info, state_key);
+ state_dict = my_CFDictionaryGetDictionary(services_info, state_key);
my_CFRelease(&state_key);
return (state_dict);
}
return (net);
}
-static __inline__ int
-uint32_cmp(uint32_t a, uint32_t b)
-{
- int ret;
-
- if (a == b) {
- ret = 0;
- }
- else if (a < b) {
- ret = -1;
- }
- else {
- ret = 1;
- }
- return (ret);
-}
-
static __inline__ int
in_addr_cmp(struct in_addr a, struct in_addr b)
{
return (uint32_cmp(ntohl(a.s_addr), ntohl(b.s_addr)));
}
-static __inline__ int
-RankCompare(Rank a, Rank b)
-{
- return (uint32_cmp(a, b));
-}
-
static __inline__ int
RouteFlagsCompare(RouteFlags a, RouteFlags b)
{
static void
IPv4RouteCopyDescriptionWithString(IPv4RouteRef r, CFMutableStringRef str)
{
+ Rank rank_assertion = RANK_ASSERTION_MASK(r->rank);
+
CFStringAppendFormat(str, NULL,
CFSTR("Dest " IP_FORMAT
" Mask " IP_FORMAT
else if ((r->flags & kRouteIsDirectToInterfaceFlag) != 0) {
CFStringAppend(str, CFSTR(" [direct]"));
}
- if ((r->flags & kRouteChooseFirstFlag) != 0) {
- CFStringAppend(str, CFSTR(" [first]"));
- }
- if ((r->flags & kRouteChooseLastFlag) != 0) {
- CFStringAppend(str, CFSTR(" [last]"));
- }
- if ((r->flags & kRouteChooseNeverFlag) != 0) {
- CFStringAppend(str, CFSTR(" [never]"));
+
+ switch(rank_assertion) {
+ case kRankAssertionFirst:
+ CFStringAppend(str, CFSTR(" [first]"));
+ break;
+ case kRankAssertionLast:
+ CFStringAppend(str, CFSTR(" [last]"));
+ break;
+ case kRankAssertionNever:
+ CFStringAppend(str, CFSTR(" [never]"));
+ break;
+ default:
+ break;
}
+
if ((r->flags & kRouteIsScopedFlag) != 0) {
CFStringAppend(str, CFSTR(" [SCOPED]"));
}
- else if ((r->flags & kRouteWantScopedFlag) != 0) {
- CFStringAppend(str, CFSTR(" [SCOPED*]"));
- }
return;
}
{
CFStringRef str = IPv4RouteCopyDescription(route);
- SCPrint(TRUE, stdout, CFSTR("%@"), str);
+ SCPrint(TRUE, stdout, CFSTR("%@\n"), str);
CFRelease(str);
return;
}
cmp = 0;
}
else {
- boolean_t a_never = (a->flags & kRouteChooseNeverFlag) != 0;
- boolean_t b_never = (b->flags & kRouteChooseNeverFlag) != 0;
*same_dest = TRUE;
-
- if (a_never != b_never) {
- if (a_never) {
- cmp = 1;
- }
- else {
- cmp = -1;
- }
- }
- else {
- boolean_t a_last = (a->flags & kRouteChooseLastFlag) != 0;
- boolean_t b_last = (b->flags & kRouteChooseLastFlag) != 0;
-
- if (a_last != b_last) {
- if (a_last) {
- cmp = 1;
- }
- else {
- cmp = -1;
- }
- }
- else {
- boolean_t a_first = (a->flags & kRouteChooseFirstFlag) != 0;
- boolean_t b_first = (b->flags & kRouteChooseFirstFlag) != 0;
-
- if (a_first != b_first) {
- if (a_first) {
- cmp = -1;
- }
- else {
- cmp = 1;
- }
- }
- else {
- cmp = RankCompare(a_rank, b_rank);
- if (cmp == 0) {
- cmp = name_cmp;
- }
- }
- }
+ cmp = RankCompare(a_rank, b_rank);
+ if (cmp == 0) {
+ cmp = name_cmp;
}
}
}
return (cmp);
}
-static CFStringRef
+static CFMutableStringRef
IPv4RouteListCopyDescription(IPv4RouteListRef routes)
{
int i;
CFStringAppendFormat(str, NULL, CFSTR("\n%2d. "), i);
IPv4RouteCopyDescriptionWithString(r, str);
}
- CFStringAppend(str, CFSTR("\n}\n"));
+ CFStringAppend(str, CFSTR("\n}"));
return (str);
}
{
CFStringRef str = IPv4RouteListCopyDescription(routes);
- SCPrint(TRUE, stdout, CFSTR("%@"), str);
+ SCPrint(TRUE, stdout, CFSTR("%@\n"), str);
CFRelease(str);
return;
}
&& (scan->mask.s_addr == route->mask.s_addr)
&& (strcmp(scan->ifname, route->ifname) == 0)
&& (scan->ifa.s_addr == route->ifa.s_addr)
- && (scan->gateway.s_addr == route->gateway.s_addr)) {
- /*
- * So far, the routes look the same. If the flags
- * are also equiv than we've found a match.
- */
- RouteFlags r_flags;
- RouteFlags s_flags;
-
- s_flags = scan->flags;
- if ((s_flags & kRouteWantScopedFlag) != 0) {
- s_flags |= kRouteWantScopedFlag;
- }
- r_flags = route->flags;
- if ((r_flags & kRouteWantScopedFlag) != 0) {
- r_flags |= kRouteWantScopedFlag;
- }
- if (s_flags == r_flags) {
+ && (scan->gateway.s_addr == route->gateway.s_addr)
+ && (scan->flags == route->flags)) {
scan_result = scan;
break;
- }
}
}
return (scan_result);
enum {
kScopeNone = 0,
kScopeThis = 1,
- kScopeNext = 2
+ kScopeNext = 2
};
static IPv4RouteListRef
IPv4RouteRef this_route, Rank this_rank)
{
int i;
+ IPv4RouteRef first_scan = NULL;
int scope_which = kScopeNone;
IPv4RouteRef scan;
int where = -1;
boolean_t same_dest;
cmp = IPv4RouteCompare(this_route, this_rank, scan, scan->rank, &same_dest);
+
+ if (same_dest == TRUE && first_scan == NULL) {
+ first_scan = scan;
+ }
+
if (cmp < 0) {
if (where == -1) {
- if (same_dest == TRUE) {
+ if (same_dest == TRUE
+ && (first_scan->flags & kRouteIsScopedFlag) == 0) {
if ((scan->flags & kRouteIsScopedFlag) != 0) {
ROUTELIST_DEBUG(("Hit 1: set scope on self\n"),
kDebugFlag8);
IPv4RouteListAddRouteList(IPv4RouteListRef routes, int init_size,
IPv4RouteListRef service_routes, Rank rank)
{
- int i;
+ int i;
IPv4RouteRef scan;
for (i = 0, scan = service_routes->list;
IPv4RouteRef r;
struct in_addr subnet = { 0 };
struct in_addr router = { 0 };
+ Rank rank = kRankAssertionDefault;
if (dict == NULL) {
return (NULL);
return (NULL);
}
if (router.s_addr == 0) {
- flags |= kRouteIsDirectToInterfaceFlag | kRouteChooseLastFlag;
+ flags |= kRouteIsDirectToInterfaceFlag;
+ rank = kRankAssertionLast;
}
else {
/*
flags |= kRouteIsDirectToInterfaceFlag;
}
if (primaryRank != NULL) {
- if (CFEqual(primaryRank, kSCValNetServicePrimaryRankNever)) {
- flags |= kRouteChooseNeverFlag;
- } else if (CFEqual(primaryRank, kSCValNetServicePrimaryRankFirst)) {
- flags |= kRouteChooseFirstFlag;
- } else if (CFEqual(primaryRank, kSCValNetServicePrimaryRankLast)) {
- flags |= kRouteChooseLastFlag;
- }
+ rank = PrimaryRankGetRankAssertion(primaryRank);
} else if (get_override_primary(dict)) {
- flags |= kRouteChooseFirstFlag;
+ rank = kRankAssertionFirst;
}
}
+
+ if (rank == kRankAssertionNever) {
+ flags |= kRouteIsScopedFlag;
+ }
+
if (add_subnet && (flags & kRouteIsDirectToInterfaceFlag) == 0
&& subnet.s_addr != subnet_addr(router, mask).s_addr) {
flags |= kRouteIsNotSubnetLocalFlag;
else {
r->gateway = addr;
}
+ r->rank = rank;
+ if (r->rank == kRankAssertionNever) {
+ r->flags |= kRouteIsScopedFlag;
+ }
r++;
}
r->mask = mask;
strlcpy(r->ifname, ifn, sizeof(r->ifname));
r->ifa = addr;
- r->flags = flags & (kRouteChooseFirstFlag|kRouteChooseLastFlag|kRouteChooseNeverFlag);
+ r->rank = rank;
+ if (r->rank == kRankAssertionNever) {
+ r->flags |= kRouteIsScopedFlag;
+ }
}
return (routes);
* 2. key = "a/b/c" prefix = "a/b/"
* returns "c"
*/
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
parse_component(CFStringRef key, CFStringRef prefix)
{
CFMutableStringRef comp;
dump_service_entity(CFStringRef serviceID, CFStringRef entity,
CFStringRef operation, CFTypeRef val)
{
- CFStringRef this_val = NULL;
- if (isA_CFData(val) && CFEqual(entity, kSCEntNetIPv4)) {
- this_val = IPv4RouteListCopyDescription((IPv4RouteListRef)
- CFDataGetBytePtr(val));
- if (this_val != NULL) {
- val = this_val;
+ CFDataRef route_list;
+ CFMutableStringRef this_val = NULL;
+
+ if (CFEqual(entity, kSCEntNetIPv4) && isA_CFDictionary(val) != NULL) {
+ CFDictionaryRef service_dict = NULL;
+
+ route_list = CFDictionaryGetValue(val, kSCEntNetIPv4RouteList);
+ if (route_list != NULL) {
+ /* ALIGN: CF should align to at least 8-byte boundaries */
+ this_val = IPv4RouteListCopyDescription((IPv4RouteListRef)
+ (void *)CFDataGetBytePtr(route_list));
+ }
+
+ service_dict = CFDictionaryGetValue(val, kSCEntNetIPv4ServiceDict);
+
+ if (service_dict != NULL && isA_CFDictionary(service_dict) != NULL) {
+ if (this_val == NULL) {
+ this_val = CFStringCreateMutable(NULL, 0);
+ }
+ CFStringAppendFormat(this_val, NULL, CFSTR("\n <IPv4Dictionary>: %@"), service_dict);
}
+ val = this_val;
}
if (val == NULL) {
val = CFSTR("<none>");
return (CFDictionaryGetValue(service_dict, entity));
}
+#ifndef kSCPropNetHostname
+#define kSCPropNetHostname CFSTR("Hostname")
+#endif
+
+__private_extern__
+CFStringRef
+copy_dhcp_hostname(CFStringRef serviceID)
+{
+ CFDictionaryRef dict = NULL;
+ CFStringRef hostname = NULL;
+ CFDictionaryRef service_dict = NULL;
+
+ dict = service_dict_get(serviceID, kSCEntNetIPv4);
+
+ if (dict == NULL || isA_CFDictionary(dict) == NULL) {
+ return (NULL);
+ }
+
+ service_dict =
+ CFDictionaryGetValue(dict, kSCEntNetIPv4ServiceDict);
+
+ if (service_dict == NULL
+ || isA_CFDictionary(service_dict) == NULL) {
+ return (NULL);
+ }
+
+ hostname =
+ CFDictionaryGetValue(service_dict, kSCPropNetHostname);
+
+ if (hostname != NULL) {
+ CFRetain(hostname);
+ }
+
+ return (hostname);
+}
+
static boolean_t
ipv6_service_dict_set(CFStringRef serviceID, CFDictionaryRef new_val)
{
int if_index;
char ifn[IFNAMSIZ];
CFStringRef new_router = NULL;
- char ntopbuf[INET6_ADDRSTRLEN];
+ char ntopbuf[INET6_ADDRSTRLEN];
CFDictionaryRef old_val = NULL;
CFStringRef old_router = NULL;
struct in6_addr router_ip;
&& (new_router == NULL || CFEqual(old_router, new_router) == FALSE)) {
/* remove the old Router */
if (cfstring_to_ip6(old_router, &router_ip)) {
- if (IN6_IS_ADDR_LINKLOCAL(&router_ip)) {
+ if (IN6_IS_ADDR_LINKLOCAL(&router_ip) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&router_ip)) {
/* scope it */
router_ip.__u6_addr.__u6_addr16[1] = htons(if_index);
}
}
/* add the new Router */
if (cfstring_to_ip6(new_router, &router_ip)) {
- if (IN6_IS_ADDR_LINKLOCAL(&router_ip)) {
+ if (IN6_IS_ADDR_LINKLOCAL(&router_ip) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&router_ip)) {
/* scope it */
router_ip.__u6_addr.__u6_addr16[1] = htons(if_index);
}
#define ALLOW_EMPTY_STRING 0x1
-static CFTypeRef
+static CF_RETURNS_RETAINED CFTypeRef
sanitize_prop(CFTypeRef val, uint32_t flags)
{
if (val != NULL) {
get_ipv4_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
CFDictionaryRef setup_dict, CFDictionaryRef info)
{
+ CFDictionaryRef aggregated_dict = NULL;
boolean_t changed = FALSE;
CFMutableDictionaryRef dict = NULL;
CFStringRef primaryRank = NULL;
IPv4RouteListRef r;
#define R_STATIC 3
IPv4RouteListRef routes;
- char routes_buf[IPv4RouteListComputeSize(R_STATIC)];
+ /* ALIGN: force align */
+ uint32_t routes_buf[roundup(IPv4RouteListComputeSize(R_STATIC), sizeof(uint32_t))];
CFDataRef routes_data = NULL;
CFDictionaryRef service_options;
router);
}
}
- routes = (IPv4RouteListRef)routes_buf;
+ routes = (IPv4RouteListRef)(void *)routes_buf;
routes->size = R_STATIC;
routes->count = 0;
r = IPv4RouteListCreateWithDictionary(routes, dict, primaryRank);
dict);
}
done:
- changed = service_dict_set(serviceID, kSCEntNetIPv4, routes_data);
+ if (routes_data != NULL) {
+ CFStringRef keys[2];
+ CFTypeRef values[2];
+
+ keys[0] = kSCEntNetIPv4ServiceDict;
+ values[0] = dict;
+ keys[1] = kSCEntNetIPv4RouteList;
+ values[1] = routes_data;
+
+ aggregated_dict = CFDictionaryCreate(NULL,
+ (const void**)keys,
+ values,
+ sizeof(keys)/sizeof(keys[0]),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ }
+ changed = service_dict_set(serviceID, kSCEntNetIPv4, aggregated_dict);
if (routes_data == NULL) {
/* clean up the rank too */
CFDictionaryRemoveValue(S_ipv4_service_rank_dict, serviceID);
}
my_CFRelease(&dict);
+ my_CFRelease(&aggregated_dict);
my_CFRelease(&routes_data);
return (changed);
}
static void
accumulate_dns_servers(CFArrayRef in_servers, ProtocolFlags active_protos,
- CFMutableArrayRef out_servers)
+ CFMutableArrayRef out_servers, CFStringRef interface)
{
int count;
int i;
}
continue;
}
+
+ CFRetain(addr);
}
else if (cfstring_to_ip6(addr, &ipv6_addr)) {
/* IPv6 address */
if ((active_protos & kProtocolFlagsIPv6) == 0
&& !IN6_IS_ADDR_LOOPBACK(&ipv6_addr)) {
if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
- char ntopbuf[INET6_ADDRSTRLEN];
+ char ntopbuf[INET6_ADDRSTRLEN];
syslog(LOG_NOTICE,
"IPMonitor: no IPv6 connectivity, "
}
continue;
}
+
+ if ((IN6_IS_ADDR_LINKLOCAL(&ipv6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&ipv6_addr))
+ && (interface != NULL)
+ && (CFStringFind(addr, CFSTR("%"), 0).location == kCFNotFound)) {
+ // append interface name to IPv6 link local address
+ addr = CFStringCreateWithFormat(NULL, NULL,
+ CFSTR("%@%%%@"),
+ addr,
+ interface);
+ } else {
+ CFRetain(addr);
+ }
}
else {
/* bad IP address */
addr);
continue;
}
+
/* DNS server is valid and one we want */
CFArrayAppendValue(out_servers, addr);
+ CFRelease(addr);
}
return;
}
merge_dns_servers(CFMutableDictionaryRef new_dict,
CFArrayRef state_servers,
CFArrayRef setup_servers,
- ProtocolFlags active_protos)
+ Boolean have_setup,
+ ProtocolFlags active_protos,
+ CFStringRef interface)
{
CFMutableArrayRef dns_servers;
+ Boolean have_dns_setup = FALSE;
if (state_servers == NULL && setup_servers == NULL) {
/* no DNS servers */
&kCFTypeArrayCallBacks);
if (setup_servers != NULL) {
accumulate_dns_servers(setup_servers, active_protos,
- dns_servers);
+ dns_servers, interface);
+ if (CFArrayGetCount(dns_servers) > 0) {
+ have_dns_setup = TRUE;
+ }
}
if ((CFArrayGetCount(dns_servers) == 0 || S_append_state)
&& state_servers != NULL) {
accumulate_dns_servers(state_servers, active_protos,
- dns_servers);
+ dns_servers, NULL);
}
+
+ /*
+ * Here, we determine whether or not we want all queries for this DNS
+ * configuration to be bound to the associated network interface.
+ *
+ * For dynamically derived network configurations (i.e. from State:)
+ * this would be the preferred option using the argument "Hey, the
+ * server told us to use these servers on this network so let's not
+ * argue".
+ *
+ * But, when a DNS configuration has been provided by the user/admin
+ * via the Network pref pane (i.e. from Setup:) we opt to not force
+ * binding of the outbound queries. The simplest example why we take
+ * this stance is with a multi-homing configuration. Consider a system
+ * with one network service associated with "en0" and a second service
+ * associated with "en1". The "en0" service has been set higher in
+ * the network service order so it would be primary but the user/admin
+ * wants the DNS queries to go to a server only accessible via "en1".
+ * Without this exception we would take the DNS server addresses from
+ * the Network pref pane (for "en0") and have the queries bound to
+ * "en0" where they'd never reach their intended destination (via
+ * "en1"). So, our exception to the rule is that we will not bind
+ * user/admin configurations to any specific network interface.
+ *
+ * We also add an exception to the "follow the dynamically derived
+ * network configuration" path for on-the-fly (no Setup: content)
+ * network services.
+ */
if (CFArrayGetCount(dns_servers) != 0) {
CFDictionarySetValue(new_dict,
kSCPropNetDNSServerAddresses, dns_servers);
+ if (have_setup && !have_dns_setup) {
+ CFDictionarySetValue(new_dict, DNS_CONFIGURATION_SCOPED_QUERY_KEY, kCFBooleanTrue);
+ }
}
+
my_CFRelease(&dns_servers);
return;
}
ProtocolFlags active_protos = kProtocolFlagsNone;
boolean_t changed = FALSE;
CFStringRef domain;
+ Boolean have_setup = FALSE;
CFStringRef interface = NULL;
- CFDataRef ipv4;
+ CFDictionaryRef ipv4;
CFDictionaryRef ipv6;
int i;
- struct {
+ const struct {
CFStringRef key;
uint32_t flags;
Boolean append;
{ kSCPropNetDNSSupplementalMatchOrders, 0, TRUE },
};
CFMutableDictionaryRef new_dict = NULL;
- CFStringRef pick_list[] = {
+ const CFStringRef pick_list[] = {
kSCPropNetDNSDomainName,
kSCPropNetDNSOptions,
kSCPropNetDNSSearchOrder,
kSCPropNetDNSServerPort,
kSCPropNetDNSServerTimeout,
};
+ IPv4RouteListRef routes = NULL;
if ((state_dict == NULL) && (setup_dict == NULL)) {
/* there is no DNS content */
goto done;
}
- ipv4 = (CFDataRef)service_dict_get(serviceID, kSCEntNetIPv4);
- if (ipv4 != NULL) {
- IPv4RouteListRef routes;
+ ipv4 = service_dict_get(serviceID, kSCEntNetIPv4);
+ routes = ipv4_dict_get_routelist(ipv4);
+
+ if (routes != NULL) {
+ if (get_service_setup_entity(info, serviceID, kSCEntNetIPv4) != NULL) {
+ have_setup = TRUE;
+ }
active_protos |= kProtocolFlagsIPv4;
- routes = (IPv4RouteListRef)CFDataGetBytePtr(ipv4);
- if (routes->count > 0) {
- interface = CFStringCreateWithCString(NULL,
- routes->list[0].ifname,
- kCFStringEncodingASCII);
- }
+ interface = ipv4_dict_get_ifname(ipv4);
}
ipv6 = service_dict_get(serviceID, kSCEntNetIPv6);
if (ipv6 != NULL) {
+ if (!have_setup &&
+ get_service_setup_entity(info, serviceID, kSCEntNetIPv6) != NULL) {
+ have_setup = TRUE;
+ }
+
active_protos |= kProtocolFlagsIPv6;
- if ((interface == NULL) &&
- CFDictionaryGetValueIfPresent(ipv6,
- kSCPropInterfaceName,
- (const void **)&interface)) {
- CFRetain(interface);
+ if (interface == NULL) {
+ interface = CFDictionaryGetValue(ipv6,
+ kSCPropInterfaceName);
}
}
+
if (active_protos == kProtocolFlagsNone) {
/* there is no IPv4 nor IPv6 */
if (state_dict == NULL) {
my_CFDictionaryGetArray(state_dict,
kSCPropNetDNSServerAddresses),
NULL,
- kProtocolFlagsIPv4 | kProtocolFlagsIPv6);
+ FALSE,
+ kProtocolFlagsIPv4 | kProtocolFlagsIPv6,
+ NULL);
}
else {
merge_dns_servers(new_dict,
kSCPropNetDNSServerAddresses),
my_CFDictionaryGetArray(setup_dict,
kSCPropNetDNSServerAddresses),
- active_protos);
+ have_setup,
+ active_protos,
+ interface);
}
for (i = 0; i < sizeof(merge_list)/sizeof(merge_list[0]); i++) {
done:
changed = service_dict_set(serviceID, kSCEntNetDNS, new_dict);
my_CFRelease(&new_dict);
- my_CFRelease(&interface);
return (changed);
}
#define PROXY_AUTO_DISCOVERY_URL 252
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
wpadURL_dhcp(CFDictionaryRef dhcp_options)
{
CFStringRef urlString = NULL;
return urlString;
}
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
wpadURL_dns(void)
{
CFURLRef url;
ProtocolFlags active_protos = kProtocolFlagsNone;
boolean_t changed = FALSE;
CFStringRef interface = NULL;
- CFDataRef ipv4;
+ CFDictionaryRef ipv4;
CFDictionaryRef ipv6;
CFMutableDictionaryRef new_dict = NULL;
- struct {
+ const struct {
CFStringRef key;
uint32_t flags;
Boolean append;
{ kSCPropNetProxiesSupplementalMatchDomains, ALLOW_EMPTY_STRING, TRUE },
{ kSCPropNetProxiesSupplementalMatchOrders, 0, TRUE },
};
- struct {
+ const struct {
CFStringRef key1; /* an "enable" key */
CFStringRef key2;
CFStringRef key3;
NULL,
NULL, }
};
+ IPv4RouteListRef routes = NULL;
if ((state_dict == NULL) && (setup_dict == NULL)) {
/* there is no proxy content */
goto done;
}
- ipv4 = (CFDataRef)service_dict_get(serviceID, kSCEntNetIPv4);
- if (ipv4 != NULL) {
- IPv4RouteListRef routes;
+ ipv4 = service_dict_get(serviceID, kSCEntNetIPv4);
+ routes = ipv4_dict_get_routelist(ipv4);
+ if (routes != NULL) {
active_protos |= kProtocolFlagsIPv4;
- routes = (IPv4RouteListRef)CFDataGetBytePtr(ipv4);
- if (routes->count > 0) {
- interface = CFStringCreateWithCString(NULL,
- routes->list[0].ifname,
- kCFStringEncodingASCII);
- }
+ interface = ipv4_dict_get_ifname(ipv4);
}
ipv6 = service_dict_get(serviceID, kSCEntNetIPv6);
if (ipv6 != NULL) {
active_protos |= kProtocolFlagsIPv6;
- if ((interface == NULL) &&
- CFDictionaryGetValueIfPresent(ipv6,
- kSCPropInterfaceName,
- (const void **)&interface)) {
- CFRetain(interface);
- }
+ if (interface == NULL) {
+ interface = CFDictionaryGetValue(ipv6,
+ kSCPropInterfaceName);
+ }
}
if (active_protos == kProtocolFlagsNone) {
done:
changed = service_dict_set(serviceID, kSCEntNetProxies, new_dict);
my_CFRelease(&new_dict);
- my_CFRelease(&interface);
return (changed);
}
boolean_t changed = FALSE;
int i;
CFMutableDictionaryRef new_dict = NULL;
- CFStringRef pick_list[] = {
+ const CFStringRef pick_list[] = {
kSCPropNetSMBNetBIOSName,
kSCPropNetSMBNetBIOSNodeType,
#ifdef ADD_NETBIOS_SCOPE
}
#endif /* !TARGET_OS_IPHONE */
+static CFStringRef
+services_info_get_interface(CFDictionaryRef services_info,
+ CFStringRef serviceID)
+{
+ CFStringRef interface = NULL;
+ CFDictionaryRef ipv4_dict;
+
+ ipv4_dict = get_service_state_entity(services_info, serviceID,
+ kSCEntNetIPv4);
+ if (isA_CFDictionary(ipv4_dict) != NULL) {
+ interface = CFDictionaryGetValue(ipv4_dict, kSCPropInterfaceName);
+ }
+ else {
+ CFDictionaryRef ipv6_dict;
+
+ ipv6_dict = get_service_state_entity(services_info, serviceID,
+ kSCEntNetIPv6);
+ if (isA_CFDictionary(ipv6_dict) != NULL) {
+ interface = CFDictionaryGetValue(ipv6_dict, kSCPropInterfaceName);
+ }
+ }
+ return (interface);
+}
+
static boolean_t
get_rank_changes(CFStringRef serviceID, CFDictionaryRef state_options,
- CFDictionaryRef setup_options, CFDictionaryRef info)
+ CFDictionaryRef setup_options, CFDictionaryRef services_info)
{
boolean_t changed = FALSE;
CFMutableDictionaryRef new_dict = NULL;
/*
* Check "PrimaryRank" setting
*
- * Note: Rank Never > Rank Last > Rank First > Rank None
+ * Note 1: Rank setting in setup/state option overwrites the
+ * Rank setting in interface
+ * Within each rank setting, the following precedence is defined:
+ *
+ * Note 2: Rank Never > Rank Last > Rank First > Rank None
*/
if (isA_CFDictionary(setup_options)) {
setup_rank = CFDictionaryGetValue(setup_options, kSCPropNetServicePrimaryRank);
new_rank = kSCValNetServicePrimaryRankFirst;
}
+ /* This corresponds to Note 1 */
+ if (setup_rank == NULL && state_rank == NULL) {
+ /* Fetch the interface associated with the service */
+ CFStringRef interface;
+
+ interface = services_info_get_interface(services_info, serviceID);
+
+ /* Get the rank on that interface */
+ if (interface != NULL) {
+ new_rank = CFDictionaryGetValue(S_if_rank_dict, interface);
+ if (S_IPMonitor_debug & kDebugFlag1) {
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR("serviceID %@ interface %@ rank = %@"),
+ serviceID, interface,
+ (new_rank != NULL) ? new_rank : CFSTR("<none>"));
+ }
+ }
+ }
+
if (new_rank != NULL) {
new_dict = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
return (changed);
}
+static CFStringRef
+if_rank_key_copy(CFStringRef ifname)
+{
+ return (SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ ifname,
+ kSCEntNetService));
+}
+
+static void
+if_rank_set(CFStringRef ifname, CFDictionaryRef rank_dict)
+{
+ CFStringRef rank = NULL;
+
+ if (isA_CFDictionary(rank_dict) != NULL) {
+ rank = CFDictionaryGetValue(rank_dict, kSCPropNetServicePrimaryRank);
+ rank = isA_CFString(rank);
+ }
+
+ /* specific rank is asserted */
+ if (rank != NULL) {
+ if (S_IPMonitor_debug & kDebugFlag1) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("Interface %@ asserted rank %@"),
+ ifname, rank);
+ }
+ CFDictionarySetValue(S_if_rank_dict, ifname, rank);
+ } else {
+ if (S_IPMonitor_debug & kDebugFlag1) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("Interface %@ removed rank."),
+ ifname);
+ }
+ CFDictionaryRemoveValue(S_if_rank_dict, ifname);
+ }
+ return;
+}
+
+static void
+if_rank_apply(const void * key, const void * value, void * context)
+{
+ CFStringRef ifname;
+ CFDictionaryRef rank_dict = (CFDictionaryRef)value;
+
+ /* State:/Network/Interface/<ifname>/Service, <ifname> is at index 3 */
+ ifname = my_CFStringCopyComponent(key, CFSTR("/"), 3);
+ if (ifname != NULL) {
+ if_rank_set(ifname, rank_dict);
+ CFRelease(ifname);
+ }
+ return;
+}
+
+static void
+if_rank_dict_init(void)
+{
+ CFDictionaryRef info;
+ CFStringRef pattern;
+ CFArrayRef patterns;
+
+ S_if_rank_dict
+ = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ pattern = if_rank_key_copy(kSCCompAnyRegex);
+ patterns = CFArrayCreate(NULL,
+ (const void **)&pattern, 1,
+ &kCFTypeArrayCallBacks);
+ CFRelease(pattern);
+ info = SCDynamicStoreCopyMultiple(S_session, NULL, patterns);
+ CFRelease(patterns);
+ if (info != NULL) {
+ CFDictionaryApplyFunction(info, if_rank_apply, NULL);
+ CFRelease(info);
+ }
+ return;
+
+}
+
static void
add_service_keys(CFStringRef serviceID, CFMutableArrayRef keys, CFMutableArrayRef patterns)
{
}
static CFDictionaryRef
-services_info_copy(SCDynamicStoreRef session, CFArrayRef service_list)
+services_info_copy(SCDynamicStoreRef session, CFArrayRef service_list,
+ CFArrayRef if_rank_list)
{
int count;
CFMutableArrayRef get_keys;
CFMutableArrayRef get_patterns;
+ int if_count;
CFDictionaryRef info;
int s;
add_service_keys(serviceID, get_keys, get_patterns);
}
+ if_count = (if_rank_list != NULL)
+ ? CFArrayGetCount(if_rank_list) : 0;
+ for (s = 0; s < if_count; s++) {
+ CFStringRef ifname = CFArrayGetValueAtIndex(if_rank_list, s);
+ CFStringRef key;
+
+ key = if_rank_key_copy(ifname);
+ CFArrayAppendValue(get_keys, key);
+ CFRelease(key);
+ }
+
info = SCDynamicStoreCopyMultiple(session, get_keys, get_patterns);
my_CFRelease(&get_keys);
my_CFRelease(&get_patterns);
else {
rtmsg.hdr.rtm_flags = RTF_UP | RTF_CLONING | RTF_STATIC;
}
- if ((flags & kRouteWantScopedFlag) != 0) {
+ if ((flags & kRouteIsScopedFlag) != 0) {
#ifdef RTF_IFSCOPE
if (!S_scopedroute) {
return (0);
default_route = (bcmp(&zeroes, &netaddr, sizeof(netaddr)) == 0);
- if (IN6_IS_ADDR_LINKLOCAL(&gateway) && ifname != NULL) {
+ if ((IN6_IS_ADDR_LINKLOCAL(&gateway) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&gateway)) &&
+ (ifname != NULL)) {
unsigned int index = if_nametoindex(ifname);
/* add the scope id to the link local address */
boolean_t is_direct)
{
if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
- char ntopbuf[INET6_ADDRSTRLEN];
+ char ntopbuf[INET6_ADDRSTRLEN];
SCLog(TRUE, LOG_NOTICE,
CFSTR("IPMonitor: IPv6 route add default"
static IPv4RouteListRef
service_dict_get_ipv4_routelist(CFDictionaryRef service_dict)
{
- CFDataRef data;
+ CFDictionaryRef dict;
IPv4RouteListRef routes = NULL;
- data = (CFDataRef)CFDictionaryGetValue(service_dict, kSCEntNetIPv4);
- if (data != NULL) {
- routes = (IPv4RouteListRef)CFDataGetBytePtr(data);
- }
+ dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv4);
+
+ routes = ipv4_dict_get_routelist(dict);
return (routes);
}
mask.s_addr = htonl(INADDR_BROADCAST);
return (ipv4_route(sockfd, cmd, def_route->ifa,
def_route->gateway, mask, ifn_p, def_route->ifindex,
- def_route->ifa,
- (def_route->flags & kRouteWantScopedFlag)));
+ def_route->ifa, def_route->flags));
}
/*
}
static void
-update_ipv6(CFDictionaryRef service_info,
+update_ipv6(CFDictionaryRef services_info,
CFStringRef primary,
keyChangeListRef keys)
{
}
static void
-update_dns(CFDictionaryRef service_info,
+update_dns(CFDictionaryRef services_info,
CFStringRef primary,
keyChangeListRef keys)
{
CFDictionaryRemoveValue(new_dict, kSCPropInterfaceName);
CFDictionaryRemoveValue(new_dict, kSCPropNetDNSSupplementalMatchDomains);
CFDictionaryRemoveValue(new_dict, kSCPropNetDNSSupplementalMatchOrders);
+ CFDictionaryRemoveValue(new_dict, DNS_CONFIGURATION_SCOPED_QUERY_KEY);
keyChangeListSetValue(keys, S_state_global_dns, new_dict);
CFRelease(new_dict);
}
}
static void
-update_dnsinfo(CFDictionaryRef service_info,
+update_dnsinfo(CFDictionaryRef services_info,
CFStringRef primary,
keyChangeListRef keys,
CFArrayRef service_order)
{
+ Boolean changed;
CFDictionaryRef dict = NULL;
CFArrayRef multicastResolvers;
CFArrayRef privateResolvers;
- multicastResolvers = CFDictionaryGetValue(service_info, S_multicast_resolvers);
- privateResolvers = CFDictionaryGetValue(service_info, S_private_resolvers);
+ multicastResolvers = CFDictionaryGetValue(services_info, S_multicast_resolvers);
+ privateResolvers = CFDictionaryGetValue(services_info, S_private_resolvers);
if (primary != NULL) {
CFDictionaryRef service_dict;
}
}
- dns_configuration_set(dict,
- S_service_state_dict,
- service_order,
- multicastResolvers,
- privateResolvers);
- keyChangeListNotifyKey(keys, S_state_global_dns);
+ changed = dns_configuration_set(dict,
+ S_service_state_dict,
+ service_order,
+ multicastResolvers,
+ privateResolvers);
+ if (changed) {
+ keyChangeListNotifyKey(keys, S_state_global_dns);
+ }
return;
}
static void
-update_proxies(CFDictionaryRef service_info,
+update_proxies(CFDictionaryRef services_info,
CFStringRef primary,
keyChangeListRef keys,
CFArrayRef service_order)
#if !TARGET_OS_IPHONE
static void
-update_smb(CFDictionaryRef service_info,
+update_smb(CFDictionaryRef services_info,
CFStringRef primary,
keyChangeListRef keys)
{
get_service_rank(CFArrayRef order, int n_order, CFStringRef serviceID)
{
CFIndex i;
- Rank rank = kRankLast;
+ Rank rank = kRankIndexMask;
if (serviceID != NULL && order != NULL && n_order > 0) {
for (i = 0; i < n_order; i++) {
rank_dict_get_service_rank(CFDictionaryRef rank_dict, CFStringRef serviceID)
{
CFNumberRef rank;
- Rank rank_val = kRankLast;
+ Rank rank_val = RankMake(kRankIndexMask, kRankAssertionDefault);
rank = CFDictionaryGetValue(rank_dict, serviceID);
if (rank != NULL) {
int n_order;
CFStringRef serviceID;
CFDictionaryRef service_dict;
- Rank service_rank;
- boolean_t choose_last;
+ Rank rank;
} election_info_t;
typedef boolean_t election_func_t(void * context, election_info_t * info);
static boolean_t
elect_ipv4(void * context, election_info_t * info)
{
+ Rank primary_rank;
IPv4RouteListRef * routes_p = (IPv4RouteListRef *)context;
IPv4RouteListRef service_routes;
service_routes = service_dict_get_ipv4_routelist(info->service_dict);
+
+ info->rank = get_service_rank(info->order, info->n_order,
+ info->serviceID);
+
if (service_routes == NULL) {
return (FALSE);
}
- if ((service_routes->list->flags & kRouteChooseFirstFlag) != 0) {
- info->service_rank = kRankFirst;
- }
- else if (S_ppp_override_primary
+
+ primary_rank = RANK_ASSERTION_MASK(service_routes->list->rank);
+
+ if (S_ppp_override_primary
&& (strncmp(PPP_PREFIX, service_routes->list->ifname,
sizeof(PPP_PREFIX) - 1) == 0)) {
/* PPP override: make ppp* look the best */
/* Hack: should use interface type, not interface name */
- info->service_rank = kRankFirst;
- }
- else {
- info->service_rank = get_service_rank(info->order, info->n_order,
- info->serviceID);
- if ((service_routes->list->flags & kRouteChooseLastFlag) != 0) {
- info->choose_last = TRUE;
- }
+ primary_rank = kRankAssertionFirst;
}
+
+ info->rank = RankMake(info->rank, primary_rank);
+
if (routes_p != NULL) {
*routes_p = IPv4RouteListAddRouteList(*routes_p,
info->n_services * 3,
service_routes,
- info->service_rank);
+ info->rank);
}
- if ((service_routes->list->flags & kRouteChooseNeverFlag) != 0) {
+
+ if (primary_rank == kRankAssertionNever) {
/* never elect as primary */
return (FALSE);
}
}
rank_dict_set_service_rank(S_ipv4_service_rank_dict,
- info->serviceID, info->service_rank);
+ info->serviceID, info->rank);
return (TRUE);
}
-static boolean_t
-elect_ipv6(void * context, election_info_t * info)
+static void
+IPv6RankedListInsertE(IPv6RankedListRef list, IPv6RankedERef e)
{
- CFStringRef if_name;
- CFStringRef primaryRank = NULL;
- CFDictionaryRef proto_dict;
- CFStringRef router;
- CFDictionaryRef service_options;
+ int idx = 0;
+ int elems_to_be_moved = 0;
+
+ if (list == NULL) return;
+
+ for (idx = 0; idx < list->count; idx++) {
+ if ((e->rank < list->elem[idx].rank)) {
+ break;
+ }
+ }
+
+ if ((S_IPMonitor_debug & kDebugFlag2) != 0) {
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR("IPv6RankedListInsertE: %s flags 0x%x at index %d with rank %u."),
+ e->ifname, e->flags, idx, e->rank);
+ }
+
+ elems_to_be_moved = list->count - idx;
+ if (elems_to_be_moved > 0) {
+ bcopy((void*) &list->elem[idx], (void*) &list->elem[idx+1],
+ elems_to_be_moved * sizeof(*e));
+ }
+
+ bcopy((void*) e, (void*) &list->elem[idx], sizeof(*e));
+ list->count++;
+ return;
+}
+
+static boolean_t
+elect_ipv6(void * context, election_info_t * info)
+{
+ CFStringRef if_name;
+ CFStringRef primaryRankStr = NULL;
+ CFDictionaryRef proto_dict;
+ CFStringRef router;
+ CFDictionaryRef service_options;
+ IPv6RankedListRef list = (IPv6RankedListRef) context;
+ IPv6RankedE elem;
+ CFDictionaryRef dns_dict = NULL;
+ Rank primary_rank = kRankAssertionDefault;
+
+ memset((void *)&elem, 0, sizeof(elem));
+
+ info->rank = get_service_rank(info->order, info->n_order, info->serviceID);
proto_dict = CFDictionaryGetValue(info->service_dict, kSCEntNetIPv6);
if (proto_dict == NULL) {
return (FALSE);
}
- service_options = service_dict_get(info->serviceID, kSCEntNetService);
- if (service_options != NULL) {
- primaryRank = CFDictionaryGetValue(service_options, kSCPropNetServicePrimaryRank);
- if ((primaryRank != NULL)
- && CFEqual(primaryRank, kSCValNetServicePrimaryRankNever)) {
- return (FALSE);
- }
- }
if_name = CFDictionaryGetValue(proto_dict, kSCPropInterfaceName);
- if (if_name != NULL && CFEqual(if_name, CFSTR("lo0"))) {
- /* never elect as primary */
+ if (if_name == NULL) {
+ /* we need an interface name */
+ return (FALSE);
+ }
+ if (CFEqual(if_name, CFSTR("lo0"))) {
+ /* don't ever elect loopback */
return (FALSE);
}
+ CFStringGetCString(if_name, elem.ifname,
+ sizeof(elem.ifname),
+ kCFStringEncodingASCII);
router = CFDictionaryGetValue(proto_dict,
kSCPropNetIPv6Router);
if (router == NULL) {
- info->choose_last = TRUE;
- info->service_rank = kRankLast;
+ /* can't become primary without a router */
+ return (FALSE);
}
- else if ((primaryRank != NULL)
- && CFEqual(primaryRank, kSCValNetServicePrimaryRankFirst)) {
- info->service_rank = kRankFirst;
+
+ dns_dict = service_dict_get(info->serviceID, kSCEntNetDNS);
+ if (dns_dict != NULL) {
+ elem.flags |= NWI_IFSTATE_FLAGS_HAS_DNS;
}
- else if (get_override_primary(proto_dict)) {
- info->service_rank = kRankFirst;
+
+ service_options = service_dict_get(info->serviceID, kSCEntNetService);
+ if (service_options != NULL) {
+ primaryRankStr = CFDictionaryGetValue(service_options, kSCPropNetServicePrimaryRank);
+ if (primaryRankStr != NULL) {
+ primary_rank = PrimaryRankGetRankAssertion(primaryRankStr);
+ }
+ if (primary_rank == kRankAssertionNever) {
+ elem.flags |= NWI_IFSTATE_FLAGS_NOT_IN_LIST;
+ elem.rank = RankMake(info->rank, primary_rank);
+ IPv6RankedListInsertE(list, &elem);
+ return (FALSE);
+ }
+ }
+
+ if (get_override_primary(proto_dict)) {
+ primary_rank = kRankAssertionFirst;
}
else if (S_ppp_override_primary
- && if_name != NULL
&& CFStringHasPrefix(if_name, CFSTR(PPP_PREFIX))) {
/* PPP override: make ppp* look the best */
/* Hack: should use interface type, not interface name */
- info->service_rank = kRankFirst;
- }
- else {
- info->service_rank = get_service_rank(info->order, info->n_order,
- info->serviceID);
+ primary_rank = kRankAssertionFirst;
}
+ elem.rank = RankMake(info->rank, primary_rank);
+ info->rank = RankMake(info->rank, primary_rank);
+
+ (void)cfstring_to_ip6(router, &elem.iaddr6);
+
+ IPv6RankedListInsertE(list, &elem);
rank_dict_set_service_rank(S_ipv6_service_rank_dict,
- info->serviceID, info->service_rank);
+ info->serviceID, info->rank);
return (TRUE);
}
+static void
+update_nwi_state_ipv6(nwi_state_t state, IPv6RankedListRef list)
+{
+ int idx;
+
+ if (state == NULL) {
+ return;
+ }
+
+ /* A null list indicates to clear the ifstates */
+ nwi_state_clear(state, AF_INET6);
+
+ if (list == NULL) {
+ return;
+ }
+
+ for (idx = 0 ; idx < list->count; idx++) {
+ if ((S_IPMonitor_debug & kDebugFlag2) != 0) {
+ char ntopbuf[INET6_ADDRSTRLEN];
+
+ inet_ntop(AF_INET6, &list->elem[idx].iaddr6, ntopbuf,
+ sizeof(ntopbuf));
+
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR("Inserting v6 [%s] into list with flags 0x%x"
+ " with rank %lu ipv6 addr %s"),
+ list->elem[idx].ifname, list->elem[idx].flags,
+ list->elem[idx].rank, ntopbuf);
+ }
+
+ nwi_insert_ifstate(state, list->elem[idx].ifname,
+ AF_INET6, list->elem[idx].flags,
+ list->elem[idx].rank,
+ (void *)&list->elem[idx].iaddr6);
+ }
+ nwi_state_set_last(state, AF_INET6);
+}
+
+static boolean_t
+interface_has_dns(const void * * values, int values_count,
+ const char * ifname)
+{
+ boolean_t has_dns = FALSE;
+ int i;
+ CFStringRef ifname_cf;
+
+ ifname_cf = CFStringCreateWithCString(NULL, ifname, kCFStringEncodingASCII);
+ for (i = 0; i < values_count; i++) {
+ CFDictionaryRef dns_dict;
+
+ dns_dict = CFDictionaryGetValue(values[i], kSCEntNetDNS);
+ if (dns_dict != NULL) {
+ CFStringRef this_ifname;
+
+ this_ifname = CFDictionaryGetValue(dns_dict, kSCPropInterfaceName);
+ if (this_ifname != NULL
+ && CFEqual(this_ifname, ifname_cf)) {
+ has_dns = TRUE;
+ break;
+ }
+ }
+ }
+ CFRelease(ifname_cf);
+ return (has_dns);
+}
+
+static void
+update_nwi_state_ipv4(nwi_state_t state, IPv4RouteListRef route)
+{
+ int idx;
+ IPv4RouteRef r;
+ const void * * values;
+ const void * values_buf[10];
+ int values_count;
+
+ if (state == NULL) {
+ return;
+ }
+ nwi_state_clear(state, AF_INET);
+ if (route == NULL) {
+ return;
+ }
+ values_count = CFDictionaryGetCount(S_service_state_dict);
+ if (values_count == 0) {
+ return;
+ }
+ if (values_count <= (sizeof(values_buf) / sizeof(values_buf[0]))) {
+ values = values_buf;
+ }
+ else {
+ values = (const void * *)malloc(sizeof(*values) * values_count);
+ }
+ CFDictionaryGetKeysAndValues(S_service_state_dict,
+ NULL, (const void * *)values);
+ for (idx = 0, r = route->list; idx < route->count; idx++, r++) {
+ uint64_t flags = 0ULL;
+
+ if (r->dest.s_addr != 0) {
+ /* we're done, no more default routes */
+ break;
+ }
+ if (RANK_ASSERTION_MASK(r->rank) == kRankAssertionNever) {
+ flags |= NWI_IFSTATE_FLAGS_NOT_IN_LIST;
+ }
+
+ if (interface_has_dns(values, values_count, r->ifname)) {
+ flags |= NWI_IFSTATE_FLAGS_HAS_DNS;
+ }
+ if ((S_IPMonitor_debug & kDebugFlag2) != 0) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("Inserting v4 [%s] with flags 0x%x primary_rank %u"),
+ r->ifname, flags, r->rank);
+ }
+ nwi_insert_ifstate(state, r->ifname, AF_INET, flags, r->rank,
+ (void *)&r->ifa);
+ }
+ if (values != values_buf) {
+ free(values);
+ }
+ nwi_state_set_last(state, AF_INET);
+ return;
+}
+
/*
* Function: elect_new_primary
* Purpose:
#define N_KEYS_VALUES_STATIC 10
void * keys_values_buf[N_KEYS_VALUES_STATIC * 2];
CFStringRef new_primary = NULL;
- Rank new_primary_rank = kRankLast;
- boolean_t new_primary_choose_last = FALSE;
+ Rank new_rank = 0;
void * * values;
count = CFDictionaryGetCount(S_service_state_dict);
info.n_services = count;
info.order = order;
info.n_order = n_order;
+ new_rank = 0;
for (i = 0; i < count; i++) {
boolean_t found_new_primary = FALSE;
info.serviceID = (CFStringRef)keys[i];
info.service_dict = (CFDictionaryRef)values[i];
- info.service_rank = kRankLast;
- info.choose_last = FALSE;
+ info.rank = kRankAssertionMask;
if ((*elect_func)(context, &info) == FALSE) {
continue;
}
- if (new_primary == NULL) {
- found_new_primary = TRUE;
- }
- else if (info.choose_last == new_primary_choose_last) {
- found_new_primary = (info.service_rank < new_primary_rank);
- }
- else if (new_primary_choose_last) {
+ if (new_primary == NULL
+ || (info.rank < new_rank)) {
found_new_primary = TRUE;
}
+
if (found_new_primary) {
new_primary = info.serviceID;
- new_primary_rank = info.service_rank;
- new_primary_choose_last = info.choose_last;
+ new_rank = info.rank;
}
}
if (new_primary != NULL) {
CFStringRef entity)
{
if (service_dict_get(serviceID, entity) == NULL) {
- return (kRankLast);
+ return (RankMake(kRankIndexMask, kRankAssertionDefault));
}
return (rank_dict_get_service_rank(rank_dict, serviceID));
}
+static __inline__ unsigned int
+IPv6RankedListComputeSize(int n)
+{
+ return (offsetof(IPv6RankedList, elem[n]));
+
+}
+
+static void
+update_interface_rank(CFDictionaryRef services_info, CFStringRef ifname)
+{
+ CFStringRef if_rank_key;
+ CFDictionaryRef rank_dict;
+
+ if_rank_key = if_rank_key_copy(ifname);
+ rank_dict = CFDictionaryGetValue(services_info, if_rank_key);
+ CFRelease(if_rank_key);
+ if_rank_set(ifname, rank_dict);
+ return;
+}
+
+static void
+append_serviceIDs_for_interface(CFMutableArrayRef services_changed,
+ CFStringRef ifname)
+{
+ int count;
+ int i;
+ void * * keys;
+#define N_KEYS_VALUES_STATIC 10
+ void * keys_values_buf[N_KEYS_VALUES_STATIC * 2];
+ void * * values;
+
+ count = CFDictionaryGetCount(S_service_state_dict);
+ if (count <= N_KEYS_VALUES_STATIC) {
+ keys = keys_values_buf;
+ } else {
+ keys = (void * *)malloc(sizeof(*keys) * count * 2);
+ }
+ values = keys + count;
+ CFDictionaryGetKeysAndValues(S_service_state_dict,
+ (const void * *)keys,
+ (const void * *)values);
+
+ for (i = 0; i < count; i++) {
+ CFDictionaryRef ipv4 = NULL;
+ CFStringRef interface = NULL;
+ CFStringRef serviceID;
+ CFDictionaryRef service_dict;
+
+ serviceID = (CFStringRef)keys[i];
+ service_dict = (CFDictionaryRef)values[i];
+
+ /* check if this is a ipv4 dictionary */
+ ipv4 = CFDictionaryGetValue(service_dict, kSCEntNetIPv4);
+ if (ipv4 != NULL) {
+ interface = ipv4_dict_get_ifname(ipv4);
+ if (interface != NULL && CFEqual(interface, ifname)) {
+ if (S_IPMonitor_debug & kDebugFlag1) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("Found ipv4 service %@ on interface %@."),
+ serviceID, ifname);
+ }
+
+ my_CFArrayAppendUniqueValue(services_changed, serviceID);
+ }
+ } else {
+ CFDictionaryRef proto_dict;
+
+ /* check if this is a ipv6 dictionary */
+ proto_dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv6);
+ if (proto_dict == NULL) {
+ continue;
+ }
+ interface = CFDictionaryGetValue(proto_dict, kSCPropInterfaceName);
+ if (interface != NULL && CFEqual(interface, ifname)) {
+ if (S_IPMonitor_debug & kDebugFlag1) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("Found ipv6 service %@ on interface %@."),
+ serviceID, ifname);
+ }
+
+ my_CFArrayAppendUniqueValue(services_changed, serviceID);
+ }
+ }
+ }
+
+ if (keys != keys_values_buf) {
+ free(keys);
+ }
+}
+
+static const CFStringRef *statusEntityNames[] = {
+ &kSCEntNetIPSec,
+ &kSCEntNetPPP,
+ &kSCEntNetVPN,
+};
+
+static void
+add_status_keys(CFMutableArrayRef patterns)
+{
+ int i;
+
+ for (i = 0; i < sizeof(statusEntityNames)/sizeof(statusEntityNames[0]); i++) {
+ CFStringRef pattern;
+
+ pattern = state_service_key(kSCCompAnyRegex, *statusEntityNames[i]);
+ CFArrayAppendValue(patterns, pattern);
+ CFRelease(pattern);
+ }
+
+ return;
+}
+
+static
+inline
+const char *
+get_changed_str(CFStringRef serviceID, CFStringRef entity, CFDictionaryRef old_dict)
+{
+ CFDictionaryRef new_dict = NULL;
+
+ if (serviceID != NULL) {
+ new_dict = service_dict_get(serviceID, entity);
+ }
+
+ if (old_dict == NULL) {
+ if (new_dict != NULL) {
+ return "+";
+ }
+ } else {
+ if (new_dict == NULL) {
+ return "-";
+ } else if (!CFEqual(old_dict, new_dict)) {
+ return "!";
+ }
+ }
+ return "";
+}
+
+static CF_RETURNS_RETAINED CFStringRef
+generate_log_changes(nwi_state_t changes_state,
+ boolean_t dns_changed,
+ boolean_t dnsinfo_changed,
+ CFDictionaryRef old_primary_dns,
+ boolean_t proxy_changed,
+ CFDictionaryRef old_primary_proxy,
+ boolean_t smb_changed,
+ CFDictionaryRef old_primary_smb
+ )
+{
+ int idx;
+ CFMutableStringRef log_output;
+ nwi_ifstate_t scan;
+
+ log_output = CFStringCreateMutable(NULL, 0);
+
+ if (changes_state != NULL) {
+ for (idx = 0; idx < sizeof(nwi_af_list)/sizeof(nwi_af_list[0]); idx++) {
+ CFMutableStringRef changes = NULL;
+ CFMutableStringRef primary_str = NULL;
+
+ scan = nwi_state_get_first_ifstate(changes_state, nwi_af_list[idx]);
+
+ while (scan != NULL) {
+ const char * changed_str;
+
+ changed_str = nwi_ifstate_get_diff_str(scan);
+ if (changed_str != NULL) {
+ void * address;
+ const char * addr_str;
+ char ntopbuf[INET6_ADDRSTRLEN];
+
+ address = (void *)nwi_ifstate_get_address(scan);
+ addr_str = inet_ntop(scan->af, address,
+ ntopbuf, sizeof(ntopbuf));
+
+ if (primary_str == NULL) {
+ primary_str = CFStringCreateMutable(NULL, 0);
+ CFStringAppendFormat(primary_str, NULL, CFSTR("%s%s:%s"),
+ nwi_ifstate_get_ifname(scan),
+ changed_str, addr_str);
+ } else {
+ if (changes == NULL) {
+ changes = CFStringCreateMutable(NULL, 0);
+ }
+ CFStringAppendFormat(changes, NULL, CFSTR(", %s"),
+ nwi_ifstate_get_ifname(scan));
+ if (strcmp(changed_str, "") != 0) {
+ CFStringAppendFormat(changes, NULL, CFSTR("%s:%s"),
+ changed_str, addr_str);
+ }
+ }
+ }
+ scan = nwi_ifstate_get_next(scan, scan->af);
+ }
+
+ if (primary_str != NULL) {
+ CFStringAppendFormat(log_output, NULL, CFSTR(" %s(%@"),
+ nwi_af_list[idx] == AF_INET ? "v4" : "v6",
+ primary_str);
+
+ if (changes != NULL && CFStringGetLength(changes) != 0) {
+ CFStringAppendFormat(log_output, NULL, CFSTR("%@"),
+ changes);
+ }
+ CFStringAppendFormat(log_output, NULL, CFSTR(")"));
+
+ my_CFRelease(&primary_str);
+ my_CFRelease(&changes);
+ }
+ }
+ }
+
+ if (dns_changed || dnsinfo_changed) {
+ const char *str;
+
+ str = get_changed_str(S_primary_dns, kSCEntNetDNS, old_primary_dns);
+ if ((strcmp(str, "") == 0) && dnsinfo_changed) {
+ str = "*"; // dnsinfo change w/no change to primary
+ }
+ CFStringAppendFormat(log_output, NULL, CFSTR(" DNS%s"), str);
+ } else if (S_primary_dns != NULL){
+ CFStringAppendFormat(log_output, NULL, CFSTR(" DNS"));
+ }
+
+ if (proxy_changed) {
+ const char *str;
+
+ str = get_changed_str(S_primary_proxies, kSCEntNetProxies, old_primary_proxy);
+ CFStringAppendFormat(log_output, NULL, CFSTR(" Proxy%s"), str);
+ } else if (S_primary_proxies != NULL) {
+ CFStringAppendFormat(log_output, NULL, CFSTR(" Proxy"));
+ }
+
+#if !TARGET_OS_IPHONE
+ if (smb_changed) {
+ const char *str;
+
+ str = get_changed_str(S_primary_smb, kSCEntNetSMB, old_primary_smb);
+ CFStringAppendFormat(log_output, NULL, CFSTR(" SMB%s"), str);
+ } else if (S_primary_smb != NULL) {
+ CFStringAppendFormat(log_output, NULL, CFSTR(" SMB"));
+ }
+#endif // !TARGET_OS_IPHONE
+
+ return log_output;
+}
+
static void
IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
void * not_used)
{
CFIndex count;
- boolean_t dnsinfo_changed = FALSE;
- boolean_t global_ipv4_changed = FALSE;
- boolean_t global_ipv6_changed = FALSE;
+ nwi_state_t changes_state = NULL;
+ boolean_t dns_changed = FALSE;
+ boolean_t dnsinfo_changed = FALSE;
+ boolean_t global_ipv4_changed = FALSE;
+ boolean_t global_ipv6_changed = FALSE;
int i;
+ CFMutableArrayRef if_rank_changes = NULL;
keyChangeList keys;
CFIndex n;
- int n_service_order = 0;
- boolean_t proxies_changed = FALSE;
+ CFStringRef network_change_msg;
+ int n_services;
+ int n_service_order = 0;
+ nwi_state_t old_nwi_state = NULL;
+ CFDictionaryRef old_primary_dns = NULL;
+ CFDictionaryRef old_primary_proxy = NULL;
+#if !TARGET_OS_IPHONE
+ CFDictionaryRef old_primary_smb = NULL;
+#endif // !TARGET_OS_IPHONE
+ boolean_t proxies_changed = FALSE;
CFArrayRef service_order;
- CFMutableArrayRef service_changes = NULL;
- CFDictionaryRef services_info = NULL;
+ CFMutableArrayRef service_changes = NULL;
+ CFDictionaryRef services_info = NULL;
+#if !TARGET_OS_IPHONE
+ boolean_t smb_changed = FALSE;
+#endif // !TARGET_OS_IPHONE
count = CFArrayGetCount(changed_keys);
if (count == 0) {
CFSTR("IPMonitor: changes %@ (%d)"), changed_keys, count);
}
+ if (S_primary_dns != NULL) {
+ old_primary_dns = service_dict_get(S_primary_dns, kSCEntNetDNS);
+ if (old_primary_dns != NULL) {
+ old_primary_dns = CFDictionaryCreateCopy(NULL, old_primary_dns);
+ }
+ }
+
+ if (S_primary_proxies != NULL) {
+ old_primary_proxy = service_dict_get(S_primary_proxies, kSCEntNetProxies);
+ if (old_primary_proxy != NULL) {
+ old_primary_proxy = CFDictionaryCreateCopy(NULL, old_primary_proxy);
+ }
+ }
+
+#if !TARGET_OS_IPHONE
+ if (S_primary_smb != NULL) {
+ old_primary_smb = service_dict_get(S_primary_smb, kSCEntNetSMB);
+ if (old_primary_smb != NULL) {
+ old_primary_smb = CFDictionaryCreateCopy(NULL, old_primary_smb);
+ }
+ }
+#endif // !TARGET_OS_IPHONE
+
keyChangeListInit(&keys);
service_changes = CFArrayCreateMutable(NULL, 0,
&kCFTypeArrayCallBacks);
+
for (i = 0; i < count; i++) {
CFStringRef change = CFArrayGetValueAtIndex(changed_keys, i);
if (CFEqual(change, S_setup_global_ipv4)) {
}
#endif /* !TARGET_OS_IPHONE */
else if (CFStringHasPrefix(change, S_state_service_prefix)) {
- CFStringRef serviceID = parse_component(change,
- S_state_service_prefix);
- if (serviceID) {
- my_CFArrayAppendUniqueValue(service_changes, serviceID);
- CFRelease(serviceID);
+ int i;
+ boolean_t status_changed = FALSE;
+
+ for (i = 0; i < sizeof(statusEntityNames)/sizeof(statusEntityNames[0]); i++) {
+ if (CFStringHasSuffix(change, *statusEntityNames[i])) {
+ status_changed = TRUE;
+ dnsinfo_changed = TRUE;
+ break;
+ }
+ }
+
+ if (!status_changed) {
+ CFStringRef serviceID = parse_component(change,
+ S_state_service_prefix);
+ if (serviceID) {
+ my_CFArrayAppendUniqueValue(service_changes, serviceID);
+ CFRelease(serviceID);
+ }
}
}
else if (CFStringHasPrefix(change, S_setup_service_prefix)) {
CFRelease(serviceID);
}
}
+ else if (CFStringHasSuffix(change, kSCEntNetService)) {
+ CFStringRef ifname = my_CFStringCopyComponent(change, CFSTR("/"), 3);
+
+ if (ifname != NULL) {
+ if (if_rank_changes == NULL) {
+ if_rank_changes = CFArrayCreateMutable(NULL, 0,
+ &kCFTypeArrayCallBacks);
+ }
+ my_CFArrayAppendUniqueValue(if_rank_changes, ifname);
+ CFRelease(ifname);
+ }
+ }
+ }
+
+ /* determine which serviceIDs are impacted by the interface rank changes */
+ if (if_rank_changes != NULL) {
+ n = CFArrayGetCount(if_rank_changes);
+ for (i = 0; i < n; i++) {
+ CFStringRef ifname = CFArrayGetValueAtIndex(if_rank_changes, i);
+
+ if (S_IPMonitor_debug & kDebugFlag1) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("Interface rank changed %@"),
+ ifname);
+ }
+ append_serviceIDs_for_interface(service_changes, ifname);
+ }
}
/* grab a snapshot of everything we need */
- services_info = services_info_copy(session, service_changes);
+ services_info = services_info_copy(session, service_changes,
+ if_rank_changes);
service_order = service_order_get(services_info);
if (service_order != NULL) {
n_service_order = CFArrayGetCount(service_order);
CFSTR("IPMonitor: service_order %@ "), service_order);
}
}
+
+ if (if_rank_changes != NULL) {
+ for (i = 0; i < n; i++) {
+ CFStringRef ifname = CFArrayGetValueAtIndex(if_rank_changes, i);
+ update_interface_rank(services_info, ifname);
+ }
+ }
+
n = CFArrayGetCount(service_changes);
for (i = 0; i < n; i++) {
uint32_t changes;
#endif /* !TARGET_OS_IPHONE */
}
- if (global_ipv4_changed) {
+ /* ensure S_nwi_state can hold as many services as we have currently */
+ n_services = CFDictionaryGetCount(S_service_state_dict);
+ old_nwi_state = nwi_state_copy_priv(S_nwi_state);
+ S_nwi_state = nwi_state_new(S_nwi_state, n_services);
+
+ if (global_ipv4_changed || dnsinfo_changed) {
IPv4RouteListRef new_routelist = NULL;
- CFStringRef new_primary;
+ CFStringRef new_primary;
if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
SCLog(TRUE, LOG_NOTICE,
}
new_primary = elect_new_primary(&elect_ipv4, &new_routelist,
service_order, n_service_order);
- (void)set_new_primary(&S_primary_ipv4, new_primary, "IPv4");
- update_ipv4(S_primary_ipv4, new_routelist, &keys);
+ update_nwi_state_ipv4(S_nwi_state, new_routelist);
+
+ if (global_ipv4_changed) {
+ (void)set_new_primary(&S_primary_ipv4, new_primary, "IPv4");
+ update_ipv4(S_primary_ipv4, new_routelist, &keys);
+ }
+ else if (new_routelist != NULL) {
+ free(new_routelist);
+ new_routelist = NULL;
+ }
my_CFRelease(&new_primary);
}
- if (global_ipv6_changed) {
- CFStringRef new_primary;
+ if (global_ipv6_changed || dnsinfo_changed) {
+ IPv6RankedListRef list = NULL;
+ CFStringRef new_primary;
+ int size;
+
+ size = (n_services != 0)
+ ? (sizeof(IPv6RankedList)
+ + IPv6RankedListComputeSize(n_services)) : 0;
+
+ if (size != 0) {
+ list = malloc(size);
+ }
+ if (list != NULL) {
+ list->count = 0;
+ list->size = size;
+ }
if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
SCLog(TRUE, LOG_NOTICE,
CFSTR("IPMonitor: IPv6 service election"));
}
- new_primary = elect_new_primary(&elect_ipv6, NULL,
+ new_primary = elect_new_primary(&elect_ipv6, list,
service_order, n_service_order);
- (void)set_new_primary(&S_primary_ipv6, new_primary, "IPv6");
- update_ipv6(services_info, S_primary_ipv6, &keys);
+ update_nwi_state_ipv6(S_nwi_state, list);
+
+ if (global_ipv6_changed) {
+ (void)set_new_primary(&S_primary_ipv6, new_primary, "IPv6");
+ update_ipv6(services_info, S_primary_ipv6, &keys);
+ }
+
+ if (list != NULL) {
+ free(list);
+ }
my_CFRelease(&new_primary);
}
if (global_ipv4_changed || global_ipv6_changed) {
if (set_new_primary(&S_primary_dns, new_primary_dns, "DNS")) {
update_dns(services_info, S_primary_dns, &keys);
+ dns_changed = TRUE;
dnsinfo_changed = TRUE;
}
if (set_new_primary(&S_primary_proxies, new_primary_proxies, "Proxies")) {
#if !TARGET_OS_IPHONE
if (set_new_primary(&S_primary_smb, new_primary_smb, "SMB")) {
update_smb(services_info, S_primary_smb, &keys);
+ smb_changed = TRUE;
}
#endif /* !TARGET_OS_IPHONE */
}
+ if (dnsinfo_changed || global_ipv4_changed || global_ipv6_changed) {
+ if (S_nwi_state != NULL) {
+ S_nwi_state->generation_count = mach_absolute_time();
+ if ((S_IPMonitor_debug & kDebugFlag1) != 0) {
+ syslog(LOG_NOTICE, "Updating network information");
+ _nwi_state_dump(LOG_NOTICE, S_nwi_state);
+ }
+ if (_nwi_state_store(S_nwi_state) == FALSE) {
+ SCLog(TRUE, LOG_ERR, CFSTR("Notifying nwi_state_store failed"));
+ }
+ }
+ }
if (dnsinfo_changed) {
update_dnsinfo(services_info, S_primary_dns, &keys, service_order);
}
- if (proxies_changed || dnsinfo_changed) { // note: supplemental Proxies may follow supplemental DNS
+ if (proxies_changed ||
+ (dnsinfo_changed && (G_supplemental_proxies_follow_dns != NULL) && CFBooleanGetValue(G_supplemental_proxies_follow_dns))
+ ) {
+ // if proxy change OR supplemental Proxies follow supplemental DNS
update_proxies(services_info, S_primary_proxies, &keys, service_order);
+ proxies_changed = TRUE;
}
my_CFRelease(&service_changes);
my_CFRelease(&services_info);
- keyChangeListApplyToStore(&keys, session);
+ my_CFRelease(&if_rank_changes);
+ changes_state = nwi_state_diff(old_nwi_state, S_nwi_state);
+ if ((S_IPMonitor_debug & kDebugFlag2) != 0) {
+ syslog(LOG_NOTICE, "network information diffs: ");
+ _nwi_state_dump(LOG_NOTICE, changes_state);
+ }
+ network_change_msg =
+ generate_log_changes(changes_state,
+ dns_changed,
+ dnsinfo_changed,
+ old_primary_dns,
+ proxies_changed,
+ old_primary_proxy,
+#if !TARGET_OS_IPHONE
+ smb_changed,
+ old_primary_smb
+#else // !TARGET_OS_IPHONE
+ FALSE,
+ NULL
+#endif // !TARGET_OS_IPHONE
+ );
+ keyChangeListApplyToStore(&keys, session, network_change_msg);
+ my_CFRelease(&old_primary_dns);
+ my_CFRelease(&old_primary_proxy);
+#if !TARGET_OS_IPHONE
+ my_CFRelease(&old_primary_smb);
+#endif // !TARGET_OS_IPHONE
+ my_CFRelease(&network_change_msg);
+
+ if (changes_state != NULL) {
+ nwi_state_release(changes_state);
+ }
+ if (old_nwi_state != NULL) {
+ nwi_state_release(old_nwi_state);
+ }
keyChangeListFree(&keys);
return;
}
ip_plugin_init()
{
CFMutableArrayRef keys = NULL;
+ CFStringRef pattern;
CFMutableArrayRef patterns = NULL;
CFRunLoopSourceRef rls = NULL;
kSCDynamicStoreDomainSetup,
kSCEntNetIPv4);
S_state_service_prefix
- = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@/"),
- kSCDynamicStoreDomainState,
- kSCCompNetwork,
- kSCCompService);
+ = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ CFSTR(""),
+ NULL);
S_setup_service_prefix
- = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@/"),
- kSCDynamicStoreDomainSetup,
- kSCCompNetwork,
- kSCCompService);
+ = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ CFSTR(""),
+ NULL);
S_service_state_dict
= CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
/* register for State: and Setup: per-service notifications */
add_service_keys(kSCCompAnyRegex, keys, patterns);
+ /* register for State: per-service PPP/VPN/IPSec status notifications */
+ add_status_keys(patterns);
+
+ /* register for interface rank notifications */
+ pattern = if_rank_key_copy(kSCCompAnyRegex);
+ CFArrayAppendValue(patterns, pattern);
+ CFRelease(pattern);
+
/* add notifier for ServiceOrder/PPPOverridePrimary changes for IPv4 */
CFArrayAppendValue(keys, S_setup_global_ipv4);
CFRelease(rls);
/* initialize dns configuration */
- dns_configuration_set(NULL, NULL, NULL, NULL, NULL);
+ (void)dns_configuration_set(NULL, NULL, NULL, NULL, NULL);
#if !TARGET_OS_IPHONE
empty_dns();
#endif /* !TARGET_OS_IPHONE */
(void)SCDynamicStoreRemoveValue(S_session, S_state_global_smb);
#endif /* !TARGET_OS_IPHONE */
+ if_rank_dict_init();
+
done:
my_CFRelease(&keys);
my_CFRelease(&patterns);
S_get_plist_boolean(CFDictionaryRef plist, CFStringRef key,
boolean_t def)
{
- CFBooleanRef b;
+ CFBooleanRef b;
boolean_t ret = def;
b = isA_CFBoolean(CFDictionaryGetValue(plist, key));
void
load_IPMonitor(CFBundleRef bundle, Boolean bundleVerbose)
{
- CFDictionaryRef info_dict;
+ CFDictionaryRef info_dict;
info_dict = CFBundleGetInfoDictionary(bundle);
if (info_dict != NULL) {
}
+#pragma mark -
+#pragma mark Standalone test code
+
+
#ifdef TEST_IPMONITOR
#include "dns-configuration.c"
#include "set-hostname.c"
};
/*
- * addr mask dest router ifname pri primaryRank
+ * addr mask dest router ifname pri primaryRank
*/
struct ipv4_service_contents en0_10 = {
- "10.0.0.10", "255.255.255.0", NULL, "10.0.0.1", "en0", 10, NULL
+ "10.0.0.10", "255.255.255.0", NULL, "10.0.0.1", "en0", 10, NULL
};
struct ipv4_service_contents en0_15 = {
- "10.0.0.19", "255.255.255.0", NULL, "10.0.0.1", "en0", 15, NULL
+ "10.0.0.19", "255.255.255.0", NULL, "10.0.0.1", "en0", 15, NULL
};
struct ipv4_service_contents en0_30 = {
- "10.0.0.11", "255.255.255.0", NULL, "10.0.0.1", "en0", 30, NULL
+ "10.0.0.11", "255.255.255.0", NULL, "10.0.0.1", "en0", 30, NULL
};
struct ipv4_service_contents en0_40 = {
- "10.0.0.12", "255.255.255.0", NULL, "10.0.0.1", "en0", 40, NULL
+ "10.0.0.12", "255.255.255.0", NULL, "10.0.0.1", "en0", 40, NULL
};
struct ipv4_service_contents en0_50 = {
- "10.0.0.13", "255.255.255.0", NULL, "10.0.0.1", "en0", 50, NULL
+ "10.0.0.13", "255.255.255.0", NULL, "10.0.0.1", "en0", 50, NULL
};
struct ipv4_service_contents en0_110 = {
- "192.168.2.10", "255.255.255.0", NULL, "192.168.2.1", "en0", 110, NULL
+ "192.168.2.10", "255.255.255.0", NULL, "192.168.2.1", "en0", 110, NULL
};
struct ipv4_service_contents en0_1 = {
- "17.202.40.191", "255.255.252.0", NULL, "17.202.20.1", "en0", 1, NULL
+ "17.202.40.191", "255.255.252.0", NULL, "17.202.20.1", "en0", 1, NULL
};
struct ipv4_service_contents en1_20 = {
- "10.0.0.20", "255.255.255.0", NULL, "10.0.0.1", "en1", 20, NULL
+ "10.0.0.20", "255.255.255.0", NULL, "10.0.0.1", "en1", 20, NULL
};
struct ipv4_service_contents en1_2 = {
- "17.202.42.24", "255.255.252.0", NULL, "17.202.20.1", "en1", 2, NULL
+ "17.202.42.24", "255.255.252.0", NULL, "17.202.20.1", "en1", 2, NULL
};
struct ipv4_service_contents en1_125 = {
- "192.168.2.20", "255.255.255.0", NULL, "192.168.2.1", "en1", 125, NULL
+ "192.168.2.20", "255.255.255.0", NULL, "192.168.2.1", "en1", 125, NULL
};
struct ipv4_service_contents fw0_25 = {
- "192.168.2.30", "255.255.255.0", NULL, "192.168.2.1", "fw0", 25, NULL
+ "192.168.2.30", "255.255.255.0", NULL, "192.168.2.1", "fw0", 25, NULL
};
struct ipv4_service_contents fw0_21 = {
- "192.168.3.30", "255.255.255.0", NULL, "192.168.3.1", "fw0", 21, NULL
+ "192.168.3.30", "255.255.255.0", NULL, "192.168.3.1", "fw0", 21, NULL
};
struct ipv4_service_contents ppp0_0_1 = {
- "17.219.156.22", NULL, "17.219.156.1", "17.219.156.1", "ppp0", 0, NULL
+ "17.219.156.22", NULL, "17.219.156.1", "17.219.156.1", "ppp0", 0, NULL
};
struct ipv4_service_contents en0_test6 = {
"17.255.98.164", "255.255.240.0", NULL, "17.255.96.1", "en2", 1, NULL
};
struct ipv4_service_contents fw0_test6_and_7 = {
- "169.254.11.33", "255.255.0.0", NULL, NULL, "fw0", UINT_MAX, NULL
+ "169.254.11.33", "255.255.0.0", NULL, NULL, "fw0", 0x0ffffff, NULL
};
struct ipv4_service_contents en0_10_last = {
- "10.0.0.10", "255.255.255.0", NULL, "10.0.0.1", "en0", 10, &kSCValNetServicePrimaryRankLast
+ "10.0.0.10", "255.255.255.0", NULL, "10.0.0.1", "en0", 10, &kSCValNetServicePrimaryRankLast
};
struct ipv4_service_contents en0_10_never = {
- "10.0.0.10", "255.255.255.0", NULL, "10.0.0.1", "en0", 10, &kSCValNetServicePrimaryRankNever
+ "10.0.0.10", "255.255.255.0", NULL, "10.0.0.1", "en0", 10, &kSCValNetServicePrimaryRankNever
};
struct ipv4_service_contents en1_20_first = {
- "10.0.0.20", "255.255.255.0", NULL, "10.0.0.1", "en1", 20, &kSCValNetServicePrimaryRankFirst
+ "10.0.0.20", "255.255.255.0", NULL, "10.0.0.1", "en1", 20, &kSCValNetServicePrimaryRankFirst
};
struct ipv4_service_contents en1_20_never = {
- "10.0.0.20", "255.255.255.0", NULL, "10.0.0.1", "en1", 20, &kSCValNetServicePrimaryRankNever
+ "10.0.0.20", "255.255.255.0", NULL, "10.0.0.1", "en1", 20, &kSCValNetServicePrimaryRankNever
};
struct ipv4_service_contents * test1[] = {
fprintf(stderr, "IPv4RouteListCreateWithDictionary failed\n");
exit(1);
}
+
+ (*scan_test)->rank = RankMake((*scan_test)->rank, kRankAssertionDefault);
+
+ if ((*scan_test)->primaryRank != NULL) {
+ (*scan_test)->rank = RankMake((*scan_test)->rank,
+ PrimaryRankGetRankAssertion(*(*scan_test)->primaryRank));
+ }
+
+ if ((*scan_test)->router == NULL) {
+ (*scan_test)->rank = RankMake((*scan_test)->rank,
+ PrimaryRankGetRankAssertion(kSCValNetServicePrimaryRankLast));
+ }
+
ret = IPv4RouteListAddRouteList(ret, 1, r, (*scan_test)->rank);
if (r != routes) {
free(r);
CFRelease(descr);
}
+ (*scan_test)->rank = RankMake((*scan_test)->rank, kRankAssertionDefault);
+
+ if ((*scan_test)->primaryRank != NULL) {
+ (*scan_test)->rank = RankMake((*scan_test)->rank,
+ PrimaryRankGetRankAssertion(*(*scan_test)->primaryRank));
+ }
+
routes1 = IPv4RouteListAddRouteList(routes1, 1, r, (*scan_test)->rank);
if (r != routes) {
free(r);
SCLog(TRUE, LOG_NOTICE, CFSTR("test: Adding %@"), descr);
CFRelease(descr);
}
+ if ((*scan_test)->primaryRank != NULL) {
+ (*scan_test)->rank = RankMake((*scan_test)->rank,
+ PrimaryRankGetRankAssertion(*(*scan_test)->primaryRank));
+ }
+
routes2 = IPv4RouteListAddRouteList(routes2, 1, r, (*scan_test)->rank);
if (r != routes) {
free(r);
case kIPv4RouteListAddRouteCommand:
printf("Add new[%ld] = ", route - context->new->list);
IPv4RoutePrint(route);
- printf("\n");
break;
case kIPv4RouteListRemoveRouteCommand:
printf("Remove old[%ld] = ", route - context->old->list);
IPv4RoutePrint(route);
- printf("\n");
break;
default:
break;
{
IPv4RouteListRef new_routes;
IPv4RouteListRef old_routes;
- compare_context_t context;
+ compare_context_t context;
old_routes = make_IPv4RouteList(old_test);
new_routes = make_IPv4RouteList(new_test);
#define ORDER_KEY CFSTR("__ORDER__")
-static CFBooleanRef S_proxies_follow_dns = NULL;
+CFBooleanRef G_supplemental_proxies_follow_dns = NULL;
static void
}
}
- order = CFNumberCreate(NULL, kCFNumberIntType, &n_proxies);
+ order = CFNumberCreate(NULL, kCFNumberCFIndexType, &n_proxies);
CFDictionarySetValue(proxy, ORDER_KEY, order);
CFRelease(order);
continue;
}
- if ((S_proxies_follow_dns != NULL) && CFBooleanGetValue(S_proxies_follow_dns)) {
+ if ((G_supplemental_proxies_follow_dns != NULL) && CFBooleanGetValue(G_supplemental_proxies_follow_dns)) {
CFDictionaryRef dns;
CFArrayRef matchDomains;
CFArrayRef matchOrders;
__private_extern__
-CFDictionaryRef
+CF_RETURNS_RETAINED CFDictionaryRef
proxy_configuration_update(CFDictionaryRef defaultProxy,
CFDictionaryRef services,
CFArrayRef serviceOrder)
CFDictionaryRef proxy;
CFMutableArrayRef proxies;
- SCLog(TRUE, LOG_DEBUG, CFSTR("defaultProxy : %@"), defaultProxy ? defaultProxy : (CFTypeRef)CFSTR("NULL"));
- SCLog(TRUE, LOG_DEBUG, CFSTR("services : %@"), services ? services : (CFTypeRef)CFSTR("NULL"));
- SCLog(TRUE, LOG_DEBUG, CFSTR("serviceOrder : %@"), serviceOrder ? serviceOrder : (CFTypeRef)CFSTR("NULL"));
-
// establish full list of proxies
proxies = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
dict = CFBundleGetInfoDictionary(bundle);
if (isA_CFDictionary(dict)) {
- S_proxies_follow_dns = CFDictionaryGetValue(dict, CFSTR("SupplementalProxiesFollowSupplementalDNS"));
- S_proxies_follow_dns = isA_CFBoolean(S_proxies_follow_dns);
+ G_supplemental_proxies_follow_dns = CFDictionaryGetValue(dict, CFSTR("SupplementalProxiesFollowSupplementalDNS"));
+ G_supplemental_proxies_follow_dns = isA_CFBoolean(G_supplemental_proxies_follow_dns);
}
return;
}
+#pragma mark -
+#pragma mark Standalone test code
+
+
#ifdef MAIN
static void
#include <sys/cdefs.h>
#include <CoreFoundation/CoreFoundation.h>
+
+CFBooleanRef G_supplemental_proxies_follow_dns;
+
+
__BEGIN_DECLS
-void proxy_configuration_init (CFBundleRef bundle);
+__private_extern__
+void
+proxy_configuration_init (CFBundleRef bundle);
-CFDictionaryRef proxy_configuration_update (CFDictionaryRef defaultProxy,
- CFDictionaryRef services,
- CFArrayRef serviceOrder);
+__private_extern__
+CF_RETURNS_RETAINED CFDictionaryRef
+proxy_configuration_update (CFDictionaryRef defaultProxy,
+ CFDictionaryRef services,
+ CFArrayRef serviceOrder);
__END_DECLS
/*
- * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#define HOSTNAME_NOTIFY_KEY "com.apple.system.hostname"
+CFStringRef copy_dhcp_hostname(CFStringRef serviceID);
static void
set_hostname(CFStringRef hostname)
return address;
}
-
-#define DHCP_OPTION_HOSTNAME 12
-
-static CFStringRef
-copy_dhcp_name(SCDynamicStoreRef store, CFStringRef serviceID)
-{
- CFDictionaryRef info;
- CFStringRef name = NULL;
-
- info = SCDynamicStoreCopyDHCPInfo(store, serviceID);
- if (info != NULL) {
- CFDataRef data;
-
- data = DHCPInfoGetOptionData(info, DHCP_OPTION_HOSTNAME);
- if (data != NULL) {
- name = CFStringCreateFromExternalRepresentation(NULL, data, kCFStringEncodingUTF8);
- }
-
- CFRelease(info);
- }
-
- return name;
-}
-
-
static void
reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
{
static void
start_dns_query(SCDynamicStoreRef store, CFStringRef address)
{
- char addr[64];
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } addr;
+ char buf[64];
SCNetworkReachabilityFlags flags;
Boolean haveDNS;
Boolean ok;
- struct sockaddr *sa;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- if (_SC_cfstring_to_cstring(address, addr, sizeof(addr), kCFStringEncodingASCII) == NULL) {
+ if (_SC_cfstring_to_cstring(address, buf, sizeof(buf), kCFStringEncodingASCII) == NULL) {
SCLog(TRUE, LOG_ERR, CFSTR("could not convert [primary] address"));
return;
}
- bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
-
- bzero(&sin6, sizeof(sin6));
- sin6.sin6_len = sizeof(sin6);
- sin6.sin6_family = AF_INET6;
-
- if (inet_aton(addr, &sin.sin_addr) == 1) {
- /*
- * if IPv4 address
- */
- sa = (struct sockaddr *)&sin;
- } else if (inet_pton(AF_INET6, addr, &sin6.sin6_addr) == 1) {
- /*
- * if IPv6 address
- */
- char *p;
-
- p = strchr(addr, '%');
- if (p != NULL) {
- sin6.sin6_scope_id = if_nametoindex(p + 1);
- }
-
- sa = (struct sockaddr *)&sin6;
- } else {
- goto done;
+ if (_SC_string_to_sockaddr(buf, AF_UNSPEC, (void *)&addr, sizeof(addr)) == NULL) {
+ /* if not an IP[v6] address */
+ SCLog(TRUE, LOG_ERR, CFSTR("could not parse [primary] address"));
+ return;
}
-
- ok = _SC_checkResolverReachabilityByAddress(&store, &flags, &haveDNS, sa);
+ ok = _SC_checkResolverReachabilityByAddress(&store, &flags, &haveDNS, &addr.sa);
if (ok) {
if (!(flags & kSCNetworkReachabilityFlagsReachable) ||
(flags & kSCNetworkReachabilityFlagsConnectionRequired)) {
(void) gettimeofday(&dnsQueryStart, NULL);
error = getnameinfo_async_start(&mp,
- sa,
- sa->sa_len,
+ &addr.sa,
+ addr.sa.sa_len,
NI_NAMEREQD, // flags
reverseDNSComplete,
NULL);
// get DHCP provided name, if available
- hostname = copy_dhcp_name(store, serviceID);
+ hostname = copy_dhcp_hostname(serviceID);
if (hostname != NULL) {
SCLog(TRUE, LOG_INFO, CFSTR("hostname (DHCP) = %@"), hostname);
set_hostname(hostname);
/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2006, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__BEGIN_DECLS
+__private_extern__
void load_hostname (Boolean verbose);
__END_DECLS
/*
- * Copyright (c) 2006-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2006-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
static Boolean
start_dns_query(SCDynamicStoreRef store, CFStringRef address)
{
- char addr[64];
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } addr;
+ char buf[64];
SCNetworkReachabilityFlags flags;
Boolean haveDNS;
Boolean ok = FALSE;
- struct sockaddr *sa;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- if (_SC_cfstring_to_cstring(address, addr, sizeof(addr), kCFStringEncodingASCII) == NULL) {
+ if (_SC_cfstring_to_cstring(address, buf, sizeof(buf), kCFStringEncodingASCII) == NULL) {
SCLog(TRUE, LOG_ERR, CFSTR("could not convert [primary] address"));
return FALSE;
}
- bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
-
- bzero(&sin6, sizeof(sin6));
- sin6.sin6_len = sizeof(sin6);
- sin6.sin6_family = AF_INET6;
-
- if (inet_aton(addr, &sin.sin_addr) == 1) {
- /*
- * if IPv4 address
- */
- sa = (struct sockaddr *)&sin;
- } else if (inet_pton(AF_INET6, addr, &sin6.sin6_addr) == 1) {
- /*
- * if IPv6 address
- */
- char *p;
-
- p = strchr(addr, '%');
- if (p != NULL) {
- sin6.sin6_scope_id = if_nametoindex(p + 1);
- }
-
- sa = (struct sockaddr *)&sin6;
- } else {
- goto done;
+ if (_SC_string_to_sockaddr(buf, AF_UNSPEC, (void *)&addr, sizeof(addr)) == NULL) {
+ /* if not an IP[v6] address */
+ SCLog(TRUE, LOG_ERR, CFSTR("could not parse [primary] address"));
+ return FALSE;
}
- ok = _SC_checkResolverReachabilityByAddress(&store, &flags, &haveDNS, sa);
+ ok = _SC_checkResolverReachabilityByAddress(&store, &flags, &haveDNS, &addr.sa);
if (ok) {
if (!(flags & kSCNetworkReachabilityFlagsReachable) ||
(flags & kSCNetworkReachabilityFlagsConnectionRequired)) {
(void) gettimeofday(&dnsQueryStart, NULL);
error = getnameinfo_async_start(&mp,
- sa,
- sa->sa_len,
+ &addr.sa,
+ addr.sa.sa_len,
NI_NAMEREQD, // flags
reverseDNSComplete,
(void *)store);
/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2006, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__BEGIN_DECLS
+__private_extern__
void load_smb_configuration (Boolean verbose);
__END_DECLS
3. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20 [never] [SCOPED]
}
New Routes = <IPv4RouteList[2]> = {
- 0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20 [never] [SCOPED*]
- 1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20 [never] [SCOPED*]
+ 0. Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en1 Ifa 10.0.0.20 [never] [SCOPED]
+ 1. Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.20 Ifp en1 Ifa 10.0.0.20 [never] [SCOPED]
}
Remove old[0] = Dest 0.0.0.0 Mask 0.0.0.0 Gate 10.0.0.1 Ifp en0 Ifa 10.0.0.10
Remove old[2] = Dest 10.0.0.0 Mask 255.255.255.0 Gate 10.0.0.10 Ifp en0 Ifa 10.0.0.10
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.11.3</string>
+ <string>1.12</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.11</string>
+ <string>1.12</string>
</dict>
</plist>
/*
- * Copyright (c) 2001-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2001-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_types.h>
+#include <pthread.h>
+#include <vproc.h>
+
+#include <CommonCrypto/CommonDigest.h>
#include <CoreFoundation/CoreFoundation.h>
*/
static io_iterator_t S_iter = MACH_PORT_NULL;
-/*
- * S_model
- * Hardware model for this network configuration.
- */
-static CFStringRef S_model = NULL;
-
/*
* S_notify
* notification object for receiving IOKit notifications of
static double S_stack_timeout = WAIT_STACK_TIMEOUT_DEFAULT;
static double S_quiet_timeout = WAIT_QUIET_TIMEOUT_DEFAULT;
+#if !TARGET_OS_EMBEDDED
+/*
+ * S_vproc_transaction
+ * The vproc transaction used to keep launchd from sending us
+ * a SIGKILL before we've had a chance to set the platform UUID
+ */
+vproc_transaction_t S_vproc_transaction = NULL;
+#endif // !TARGET_OS_EMBEDDED
/*
* Virtual network interface configuration
}
#define INTERFACES CFSTR("Interfaces")
-#define MODEL CFSTR("Model")
#define NETWORK_INTERFACES_PREFS CFSTR("NetworkInterfaces.plist")
-static CFStringRef
-hw_model()
-{
- if (S_model == NULL) {
- char hwModel[64];
- int mib[] = { CTL_HW, HW_MODEL };
- size_t n = sizeof(hwModel);
- int ret;
-
- // get HW model name
- bzero(&hwModel, sizeof(hwModel));
- ret = sysctl(mib, sizeof(mib) / sizeof(mib[0]), &hwModel, &n, NULL, 0);
- if (ret != 0) {
- SCLog(TRUE, LOG_ERR, CFSTR("sysctl() CTL_HW/HW_MODEL failed: %s"), strerror(errno));
- return NULL;
- }
- hwModel[sizeof(hwModel) - 1] = '\0';
-
- S_model = CFStringCreateWithCString(NULL, hwModel, kCFStringEncodingASCII);
- }
-
- return S_model;
-
-}
-
static CFComparisonResult
if_unit_compare(const void *val1, const void *val2, void *context)
{
}
old_model = SCPreferencesGetValue(prefs, MODEL);
- new_model = hw_model();
+ new_model = _SC_hw_model();
if ((new_model != NULL) && !_SC_CFEqual(old_model, new_model)) {
// if new hardware
if ((old_model != NULL) && (cur_list != NULL)) {
return;
}
-static CFMutableArrayRef
+static CF_RETURNS_RETAINED CFMutableArrayRef
readInterfaceList()
{
CFArrayRef if_list;
if (old_model != NULL) {
CFStringRef new_model;
- new_model = hw_model();
+ new_model = _SC_hw_model();
if (!_SC_CFEqual(old_model, new_model)) {
// if interface list was created on other hardware
if_list = NULL;
return (plist);
}
-static CFMutableArrayRef
+static CF_RETURNS_RETAINED CFMutableArrayRef
previouslyActiveInterfaces()
{
CFMutableArrayRef active;
updateStore(void)
{
CFStringRef key;
- SCDynamicStoreRef store;
-
- store = SCDynamicStoreCreate(NULL, CFSTR(MY_PLUGIN_NAME), NULL, NULL);
- if (store == NULL) {
- return;
- }
key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@" MY_PLUGIN_NAME),
kSCDynamicStoreDomainPlugin);
- (void)SCDynamicStoreSetValue(store, key, S_state);
+ (void)SCDynamicStoreSetValue(NULL, key, S_state);
CFRelease(key);
- CFRelease(store);
return;
}
+#if !TARGET_OS_IPHONE
static void
updateBondInterfaceConfiguration(SCPreferencesRef prefs)
{
return;
}
+#endif // !TARGET_OS_IPHONE
static void
updateBridgeInterfaceConfiguration(SCPreferencesRef prefs)
}
}
+#if !TARGET_OS_IPHONE
updateBondInterfaceConfiguration (prefs);
+#endif // !TARGET_OS_IPHONE
updateBridgeInterfaceConfiguration(prefs);
updateVLANInterfaceConfiguration (prefs);
CFMutableArrayRef matches;
} matchContext, *matchContextRef;
-static CFDictionaryRef
+static CF_RETURNS_RETAINED CFDictionaryRef
thinInterfaceInfo(CFDictionaryRef info)
{
CFNumberRef num;
return (ret_unit);
}
+/*
+ * Function: ensureInterfaceHasUnit
+ * Purpose:
+ * Ensure that the SCNetworkInterfaceRef has a unit number. If it doesn't,
+ * release the interface and return NULL.
+ */
+static SCNetworkInterfaceRef
+ensureInterfaceHasUnit(SCNetworkInterfaceRef net_if)
+{
+ if (net_if != NULL
+ && _SCNetworkInterfaceGetIOInterfaceUnit(net_if) == NULL) {
+ CFRelease(net_if);
+ net_if = NULL;
+ }
+ return (net_if);
+}
+
#ifdef USE_REGISTRY_ENTRY_ID
static kern_return_t
registerInterfaceWithIORegistryEntryID(io_connect_t connect,
}
static SCNetworkInterfaceRef
-lookupIORegistryEntryID(uint64_t entryID)
+copyInterfaceForIORegistryEntryID(uint64_t entryID)
{
io_registry_entry_t entry = MACH_PORT_NULL;
SCNetworkInterfaceRef interface = NULL;
return (interface);
}
+
+static SCNetworkInterfaceRef
+copyNamedInterfaceForIORegistryEntryID(uint64_t entryID)
+{
+ SCNetworkInterfaceRef net_if;
+
+ net_if = copyInterfaceForIORegistryEntryID(entryID);
+ return (ensureInterfaceHasUnit(net_if));
+}
+
#else // USE_REGISTRY_ENTRY_ID
/*
* Function: registerInterface
}
static SCNetworkInterfaceRef
-lookupIOKitPath(CFStringRef if_path)
+copyInterfaceForIOKitPath(CFStringRef if_path)
{
io_registry_entry_t entry = MACH_PORT_NULL;
SCNetworkInterfaceRef interface = NULL;
return (interface);
}
+
+static SCNetworkInterfaceRef
+copyNamedInterfaceForIOKitPath(CFStringRef if_path)
+{
+ SCNetworkInterfaceRef net_if;
+
+ net_if = copyInterfaceForIOKitPath(if_path);
+ return (ensureInterfaceHasUnit(net_if));
+}
+
#endif // USE_REGISTRY_ENTRY_ID
static void
for (i = 0; i < n; i++) {
uint64_t entryID;
SCNetworkInterfaceRef interface;
- Boolean ok = TRUE;
+ SCNetworkInterfaceRef new_interface;
CFStringRef path;
CFStringRef str;
CFNumberRef type;
&& lookupInterfaceByAddress(S_prev_active_list, interface, &where) != NULL) {
CFArrayRemoveValueAtIndex(S_prev_active_list, where);
}
+
+ replaceInterface(interface);
} else {
CFDictionaryRef dbdict;
boolean_t is_builtin;
unit,
(dbdict == NULL) ? kIONetworkStackRegisterInterfaceWithLowestUnit
: kIONetworkStackRegisterInterfaceWithUnit);
+ new_interface = copyNamedInterfaceForIORegistryEntryID(entryID);
#else // USE_REGISTRY_ENTRY_ID
kr = registerInterfaceWithIOServicePath(S_connect,
path,
unit,
(dbdict == NULL) ? kRegisterInterface
: kRegisterInterfaceWithFixedUnit);
+ new_interface = copyNamedInterfaceForIOKitPath(path);
#endif // USE_REGISTRY_ENTRY_ID
- if (kr != KERN_SUCCESS) {
+ if (new_interface == NULL) {
const char *signature;
signature = (dbdict == NULL) ? "failed to name new interface"
usleep(50 * 1000); // sleep 50ms between attempts
goto retry;
}
-
- ok = FALSE; // ... and don't update the database
- } else {
- SCNetworkInterfaceRef new_interface;
+ }
+ else {
+ CFNumberRef new_unit;
if (retries > 0) {
SCLog(TRUE, LOG_ERR,
#endif // SHOW_NAMING_FAILURE
}
-#ifdef USE_REGISTRY_ENTRY_ID
- new_interface = lookupIORegistryEntryID(entryID);
-#else // USE_REGISTRY_ENTRY_ID
- new_interface = lookupIOKitPath(path);
-#endif // USE_REGISTRY_ENTRY_ID
- if (new_interface != NULL) {
- CFNumberRef new_unit;
-
- new_unit = _SCNetworkInterfaceGetIOInterfaceUnit(new_interface);
- if (CFEqual(unit, new_unit) == FALSE) {
- SCLog(S_debug, LOG_INFO,
- CFSTR(MY_PLUGIN_NAME
- ": interface type %@ assigned "
- "unit %@ instead of %@"),
- type, new_unit, unit);
- }
- if (S_debug) {
- displayInterface(new_interface);
- }
+ new_unit = _SCNetworkInterfaceGetIOInterfaceUnit(new_interface);
+ if (CFEqual(unit, new_unit) == FALSE) {
+ SCLog(S_debug, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME
+ ": interface type %@ assigned "
+ "unit %@ instead of %@"),
+ type, new_unit, unit);
+ }
+ if (S_debug) {
+ displayInterface(new_interface);
+ }
- // update if_list (with the interface name & unit)
- CFArraySetValueAtIndex(if_list, i, new_interface);
- CFRelease(new_interface);
- interface = new_interface; // if_list holds the reference
+ // update if_list (with the interface name & unit)
+ CFArraySetValueAtIndex(if_list, i, new_interface);
+ CFRelease(new_interface);
+ interface = new_interface; // if_list holds the reference
- if (is_builtin && (S_prev_active_list != NULL)) {
- CFIndex where;
+ if (is_builtin && (S_prev_active_list != NULL)) {
+ CFIndex where;
- // update the list of [built-in] interfaces that were previously named
- if (lookupInterfaceByUnit(S_prev_active_list, interface, &where) != NULL) {
- SCLog(S_debug, LOG_INFO,
- CFSTR(MY_PLUGIN_NAME ": and updated database (new address)"));
- CFArrayRemoveValueAtIndex(S_prev_active_list, where);
- }
+ // update the list of [built-in] interfaces that were previously named
+ if (lookupInterfaceByUnit(S_prev_active_list, interface, &where) != NULL) {
+ SCLog(S_debug, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": and updated database (new address)"));
+ CFArrayRemoveValueAtIndex(S_prev_active_list, where);
}
}
+ replaceInterface(interface);
}
-
CFRelease(unit);
}
-
- // update db
- if (ok) {
- replaceInterface(interface);
- }
}
return;
}
return;
}
+#if !TARGET_OS_EMBEDDED
static CFComparisonResult
compareMacAddress(const void *val1, const void *val2, void *context)
{
return res;
}
-#ifndef kIOPlatformUUIDKey
-#define kIOPlatformUUIDKey "IOPlatformUUID"
-#endif
-static void
-updatePlatformUUID()
+static CFStringRef
+copyEthernetUUID()
{
CFDataRef addr;
CFMutableArrayRef addrs = NULL;
- CFStringRef guid;
+ CFStringRef guid = NULL;
CFIndex i;
CFIndex n;
- io_registry_entry_t platform;
-
- platform = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/");
- if (platform == MACH_PORT_NULL) {
- return;
- }
-
- guid = IORegistryEntryCreateCFProperty(platform, CFSTR(kIOPlatformUUIDKey), NULL, 0);
- if (guid != NULL) {
- // if GUID already defined
- goto done;
- }
addrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
n = (S_dblist != NULL) ? CFArrayGetCount(S_dblist) : 0;
n = CFArrayGetCount(addrs);
switch (n) {
case 0 :
- SCLog(TRUE, LOG_ERR,
- CFSTR(MY_PLUGIN_NAME ": no network interfaces, could not update platform UUID"));
+ // if no network interfaces
break;
default :
// sort by MAC address
case 1 : {
CFUUIDBytes bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- kern_return_t kr;
CFUUIDRef uuid;
// set GUID
CFRelease(uuid);
SCLog(TRUE, LOG_INFO,
- CFSTR(MY_PLUGIN_NAME ": setting platform UUID = %@"),
+ CFSTR(MY_PLUGIN_NAME ": setting platform UUID [MAC] = %@"),
guid);
- kr = IORegistryEntrySetCFProperty(platform, CFSTR(kIOPlatformUUIDKey), guid);
- if (kr != KERN_SUCCESS) {
- SCLog(TRUE, LOG_ERR,
- CFSTR(MY_PLUGIN_NAME ": IORegistryEntrySetCFProperty(platform UUID) failed, kr=0x%x"),
- kr);
- }
-
- addTimestamp(S_state, CFSTR("*PLATFORM-UUID*"));
- updateStore();
break;
}
}
+ if (addrs != NULL) CFRelease(addrs);
+ return guid;
+}
+
+#ifndef kIOPlatformUUIDKey
+#define kIOPlatformUUIDKey "IOPlatformUUID"
+#endif
+static void
+updatePlatformUUID()
+{
+ CFStringRef guid = NULL;
+ kern_return_t kr;
+ io_registry_entry_t platform;
+
+ platform = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/");
+ if (platform == MACH_PORT_NULL) {
+ goto done;
+ }
+
+ guid = IORegistryEntryCreateCFProperty(platform, CFSTR(kIOPlatformUUIDKey), NULL, 0);
+ if (guid != NULL) {
+ // if GUID already defined
+ goto done;
+ }
+
+ guid = copyEthernetUUID();
+ if (guid == NULL) {
+ CFUUIDRef uuid;
+
+ uuid = CFUUIDCreate(NULL);
+ guid = CFUUIDCreateString(NULL, uuid);
+ CFRelease(uuid);
+
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": setting platform UUID [random] = %@"),
+ guid);
+ }
+
+if (getenv("DO_NOT_SET_PLATFORM_UUID") == NULL) {
+ kr = IORegistryEntrySetCFProperty(platform, CFSTR(kIOPlatformUUIDKey), guid);
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR(MY_PLUGIN_NAME ": IORegistryEntrySetCFProperty(platform UUID) failed, kr=0x%x"),
+ kr);
+ }
+}
+
+ addTimestamp(S_state, CFSTR("*PLATFORM-UUID*"));
+ updateStore();
+
done :
- if (addrs != NULL) CFRelease(addrs);
+ if (S_vproc_transaction != NULL) {
+ vproc_transaction_end(NULL, S_vproc_transaction);
+ S_vproc_transaction = NULL;
+ }
+
if (platform != MACH_PORT_NULL) IOObjectRelease(platform);
if (guid != NULL) CFRelease(guid);
return;
}
+#endif // !TARGET_OS_EMBEDDED
static void
interfaceArrivalCallback(void *refcon, io_iterator_t iter)
// grab (and name) any additional interfaces.
interfaceArrivalCallback((void *)S_notify, S_iter);
+#if !TARGET_OS_EMBEDDED
updatePlatformUUID();
+#endif // !TARGET_OS_EMBEDDED
return;
}
(state & kIOServiceRegisteredState) ? "" : "!registered, ",
(state & kIOServiceMatchedState) ? "" : "!matched, ",
(state & kIOServiceInactiveState) ? "inactive, " : "",
+ busy_state,
accumulated_busy_time / kMillisecondScale);
CFRelease(path);
}
return;
}
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
captureBusy()
{
int count = 0;
CFBundleRef bundle = (CFBundleRef)arg;
CFDictionaryRef dict;
-#if !TARGET_OS_EMBEDDED
pthread_setname_np(MY_PLUGIN_NAME " thread");
-#endif // !TARGET_OS_EMBEDDED
dict = CFBundleGetInfoDictionary(bundle);
if (isA_CFDictionary(dict)) {
goto error;
}
+#if !TARGET_OS_EMBEDDED
+ // keep launchd from SIGKILL'ing us until after the platform-uuid has
+ // been updated
+ S_vproc_transaction = vproc_transaction_begin(NULL);
+#endif // !TARGET_OS_EMBEDDED
+
goto done;
error :
}
done :
-#if !TARGET_OS_EMBEDDED
CFRelease(bundle);
CFRunLoopRun();
-#endif // !TARGET_OS_EMBEDDED
return NULL;
}
void
load_InterfaceNamer(CFBundleRef bundle, Boolean bundleVerbose)
{
+ pthread_attr_t tattr;
+ pthread_t tid;
+
if (bundleVerbose) {
S_debug = TRUE;
}
-#if !TARGET_OS_EMBEDDED
- {
- pthread_attr_t tattr;
- pthread_t tid;
+ CFRetain(bundle); // released in exec_InterfaceNamer
- CFRetain(bundle); // released in exec_InterfaceNamer
-
- pthread_attr_init(&tattr);
- pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
- pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
-// pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack
- pthread_create(&tid, &tattr, exec_InterfaceNamer, bundle);
- pthread_attr_destroy(&tattr);
- }
-#else // !TARGET_OS_EMBEDDED
- (void)exec_InterfaceNamer(bundle);
-#endif // !TARGET_OS_EMBEDDED
+ pthread_attr_init(&tattr);
+ pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
+ pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
+// pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack
+ pthread_create(&tid, &tattr, exec_InterfaceNamer, bundle);
+ pthread_attr_destroy(&tattr);
return;
}
int
main(int argc, char ** argv)
{
+ CFBundleRef bundle;
+
_sc_log = FALSE;
_sc_verbose = (argc > 1) ? TRUE : FALSE;
- load_InterfaceNamer(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
- CFRunLoopRun();
+ S_debug = _sc_verbose;
+
+ bundle = CFBundleGetMainBundle();
+ CFRetain(bundle); // released in exec_InterfaceNamer
+
+ (void)exec_InterfaceNamer();
+
/* not reached */
exit(0);
return 0;
int
main(int argc, char ** argv)
{
+ CFStringRef guid;
CFArrayRef interfaces;
_sc_log = FALSE;
}
CFRelease(interfaces);
}
+
+ guid = copyEthernetUUID();
+ SCPrint(TRUE, stdout, CFSTR("copyEthernetUUID() = %@\n"), (guid != NULL) ? guid : CFSTR("NULL"));
+ if (guid != NULL) CFRelease(guid);
+
updatePlatformUUID();
CFRelease(S_dblist);
exit(0);
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.11.3</string>
+ <string>1.12</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.11</string>
+ <string>1.12</string>
<key>Requires</key>
<array>
<string>com.apple.SystemConfiguration.InterfaceNamer</string>
/*
- * Copyright (c) 2002-2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2006, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "cache.h"
#include "ev_dlil.h"
+#ifndef kSCEntNetIdleRoute
+#define kSCEntNetIdleRoute CFSTR("IdleRoute")
+#endif /* kSCEntNetIdleRoute */
+
static CFStringRef
create_interface_key(const char * if_name)
{
return;
}
+
+#ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED
+static CFStringRef
+create_linkquality_key(const char * if_name)
+{
+ CFStringRef interface;
+ CFStringRef key;
+
+ interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ interface,
+ kSCEntNetLinkQuality);
+ CFRelease(interface);
+ return (key);
+}
+
+
+__private_extern__
+void
+interface_update_quality_metric(const char *if_name,
+ int quality)
+{
+ CFStringRef key = NULL;
+ CFMutableDictionaryRef newDict = NULL;
+ CFNumberRef linkquality = NULL;
+
+ key = create_linkquality_key(if_name);
+ newDict = copy_entity(key);
+
+ if (quality != IFNET_LQM_THRESH_UNKNOWN) {
+ linkquality = CFNumberCreate(NULL, kCFNumberIntType, &quality);
+ CFDictionarySetValue(newDict, kSCPropNetLinkQuality, linkquality);
+ CFRelease(linkquality);
+ } else {
+ CFDictionaryRemoveValue(newDict, kSCPropNetLinkQuality);
+ }
+
+ /* update status */
+ if (CFDictionaryGetCount(newDict) > 0) {
+ cache_SCDynamicStoreSetValue(store, key, newDict);
+ } else {
+ cache_SCDynamicStoreRemoveValue(store, key);
+ }
+
+ CFRelease(key);
+ CFRelease(newDict);
+ return;
+}
+
+
+static
+void
+link_update_quality_metric(const char *if_name)
+{
+ struct ifreq ifr;
+ int quality = IFNET_LQM_THRESH_UNKNOWN;
+ int sock;
+
+ sock = dgram_socket(AF_INET);
+ if (sock == -1) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("socket_get_link_quality: socket open failed, %s"), strerror(errno));
+ goto done;
+ }
+
+ bzero((char *)&ifr, sizeof(ifr));
+ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", if_name);
+
+ if (ioctl(sock, SIOCGIFLINKQUALITYMETRIC, (caddr_t)&ifr) != -1) {
+ quality = ifr.ifr_link_quality_metric;
+ }
+
+done:
+ interface_update_quality_metric(if_name, quality);
+ if (sock != -1)
+ close(sock);
+ return;
+
+}
+#endif /* KEV_DL_LINK_QUALITY_METRIC_CHANGED */
+
+
__private_extern__
void
interface_detaching(const char *if_name)
key = create_interface_key(if_name);
cache_SCDynamicStoreRemoveValue(store, key);
CFRelease(key);
+
+#ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED
+ key = create_linkquality_key(if_name);
+ cache_SCDynamicStoreRemoveValue(store, key);
+ CFRelease(key);
+#endif /* KEV_DL_LINK_QUALITY_METRIC_CHANGED */
+
return;
}
}
cache_SCDynamicStoreSetValue(store, cacheKey, newDict);
link_update_status(if_name, TRUE);
+#ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED
+ link_update_quality_metric(if_name);
+#endif /* KEV_DL_LINK_QUALITY_METRIC_CHANGED */
CFRelease(cacheKey);
CFRelease(interface);
if (newDict) CFRelease(newDict);
return;
}
+
+
+#ifdef KEV_DL_IF_IDLE_ROUTE_REFCNT
+#define INVALID_SOCKET_REF -1
+static
+int
+socket_reference_count(const char* if_name) {
+ struct ifreq ifr;
+ int ref = INVALID_SOCKET_REF;
+ int s;
+
+ s = dgram_socket(AF_INET);
+ if (s == -1) {
+ return (ref);
+ }
+
+ bzero((char *)&ifr, sizeof(ifr));
+ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", if_name);
+
+ if (ioctl(s, SIOCGIFGETRTREFCNT, (caddr_t)&ifr) != -1) {
+ ref = ifr.ifr_route_refcnt;
+ } else {
+ ref = INVALID_SOCKET_REF;
+ }
+ close(s);
+ return (ref);
+}
+
+
+__private_extern__
+void
+interface_update_idle_state(const char *if_name)
+{
+ CFStringRef if_name_cf;
+ CFStringRef key;
+ int ref;
+
+ /* We will only update the SCDynamicStore if the idle ref count
+ * is still 0 */
+ ref = socket_reference_count(if_name);
+ if (ref != 0) {
+ return;
+ }
+
+ if_name_cf = CFStringCreateWithCString(NULL, if_name,
+ kCFStringEncodingASCII);
+
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ if_name_cf,
+ kSCEntNetIdleRoute);
+
+ cache_SCDynamicStoreNotifyValue(store, key);
+ CFRelease(key);
+ CFRelease(if_name_cf);
+ return;
+}
+#endif // KEV_DL_IF_IDLE_ROUTE_REFCNT
/*
- * Copyright (c) 2002, 2004, 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002, 2004, 2005, 2011 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__BEGIN_DECLS
-void interface_detaching (const char *if_name);
-void link_add (const char *if_name);
-void link_remove (const char *if_name);
-void link_update_status (const char *if_name, boolean_t attach);
+__private_extern__
+void interface_detaching (const char *if_name);
+
+__private_extern__
+void interface_update_idle_state (const char *if_name);
+
+__private_extern__
+void interface_update_quality_metric (const char *if_name, int quality);
+
+__private_extern__
+void link_add (const char *if_name);
+
+__private_extern__
+void link_remove (const char *if_name);
+
+__private_extern__
+void link_update_status (const char *if_name, boolean_t attach);
__END_DECLS
/*
- * Copyright (c) 2002-2005, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2005, 2007, 2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
static CFMutableDictionaryRef
-getIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
+copyIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
{
CFDictionaryRef dict = NULL;
CFMutableDictionaryRef newDict = NULL;
kSCEntNetIPv4);
CFRelease(interface);
- newDict = getIF(key, oldIFs, newIFs);
+ newDict = copyIF(key, oldIFs, newIFs);
- sin = (struct sockaddr_in *)ifa->ifa_addr;
+ /* ALIGN: cast ok, this should be aligned (getifaddrs). */
+ sin = (struct sockaddr_in *)(void *)ifa->ifa_addr;
appendAddress(newDict, kSCPropNetIPv4Addresses, &sin->sin_addr);
if (ifa->ifa_flags & IFF_POINTOPOINT) {
struct sockaddr_in *dst;
- dst = (struct sockaddr_in *)ifa->ifa_dstaddr;
+ /* ALIGN: cast ok, this should be aligned (getifaddrs). */
+ dst = (struct sockaddr_in *)(void *)ifa->ifa_dstaddr;
appendAddress(newDict, kSCPropNetIPv4DestAddresses, &dst->sin_addr);
} else {
struct sockaddr_in *brd;
struct sockaddr_in *msk;
- brd = (struct sockaddr_in *)ifa->ifa_broadaddr;
- appendAddress(newDict, kSCPropNetIPv4BroadcastAddresses, &brd->sin_addr);
- msk = (struct sockaddr_in *)ifa->ifa_netmask;
+ /* ALIGN: cast ok, this should be aligned (getifaddrs). */
+ brd = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr;
+ appendAddress(newDict, kSCPropNetIPv4BroadcastAddresses,&brd->sin_addr);
+
+ /* ALIGN: cast ok, this should be aligned (getifaddrs). */
+ msk = (struct sockaddr_in *)(void *)ifa->ifa_netmask;
appendAddress(newDict, kSCPropNetIPv4SubnetMasks, &msk->sin_addr);
}
kSCEntNetIPv4);
CFRelease(interface);
- newDict = getIF(key, oldIFs, newIFs);
+ newDict = copyIF(key, oldIFs, newIFs);
CFDictionarySetValue(newIFs, key, newDict);
CFRelease(newDict);
/*
- * Copyright (c) 2002-2005, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2005, 2007, 2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__BEGIN_DECLS
+__private_extern__
void interface_update_ipv4 (struct ifaddrs *ifap, const char *if_name);
+
+__private_extern__
void interface_collision_ipv4(const char *if_name,
struct in_addr ip_addr,
int hw_len, const void * hw_addr);
+
#if !TARGET_OS_IPHONE
-void port_in_use_ipv4(uint16_t port, pid_t req_pid);
+__private_extern__
+void port_in_use_ipv4 (uint16_t port, pid_t req_pid);
#endif /* !TARGET_OS_IPHONE */
__END_DECLS
/*
- * Copyright (c) 2002-2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2007, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
static CFMutableDictionaryRef
-getIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
+copyIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
{
CFDictionaryRef dict = NULL;
CFMutableDictionaryRef newDict = NULL;
kSCEntNetIPv6);
CFRelease(interface);
- newDict = getIF(key, oldIFs, newIFs);
+ newDict = copyIF(key, oldIFs, newIFs);
- sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+ /* ALIGN: ifa->ifa_addr aligned (getifaddrs), cast ok. */
+ sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_addr;
/* XXX: embedded link local addr check */
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) {
u_int16_t index;
index = sin6->sin6_addr.s6_addr16[1];
#ifdef NOTYET
appendScopeID (newDict, sin6);
#endif /* NOTYET */
- appendPrefixLen(newDict, (struct sockaddr_in6 *)ifa->ifa_netmask);
+ /* ALIGN: ifa should be aligned (from getifaddrs), cast ok.
+ * appendPrefixLen expect byte alignment */
+ appendPrefixLen(newDict, (struct sockaddr_in6 *)(void *)ifa->ifa_netmask);
appendFlags (newDict, flags6);
if (ifa->ifa_flags & IFF_POINTOPOINT) {
struct sockaddr_in6 *dst6;
- dst6 = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
+ /* ALIGN: ifa should be aligned (from getifaddrs), cast ok. */
+ dst6 = (struct sockaddr_in6 *)(void *)ifa->ifa_dstaddr;
/* XXX: embedded link local addr check */
- if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) {
+ if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&dst6->sin6_addr)) {
u_int16_t index;
index = dst6->sin6_addr.s6_addr16[1];
kSCEntNetIPv6);
CFRelease(interface);
- newDict = getIF(key, oldIFs, newIFs);
+ newDict = copyIF(key, oldIFs, newIFs);
CFDictionarySetValue(newIFs, key, newDict);
CFRelease(newDict);
/*
- * Copyright (c) 2002, 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002, 2004, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__BEGIN_DECLS
+__private_extern__
void interface_update_ipv6 (struct ifaddrs *ifap, const char *if_name);
__END_DECLS
/*
- * Copyright (c) 2000-2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008, 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
"KEV_DL_WAKEFLAGS_CHANGED",
#ifdef KEV_DL_IF_IDLE_ROUTE_REFCNT
"KEV_DL_IF_IDLE_ROUTE_REFCNT",
-#endif // KEV_DL_IF_IDLE_ROUTE_REFCNT
+#endif
+#ifdef KEV_DL_IFCAP_CHANGED
+ "KEV_DL_IFCAP_CHANGED",
+#endif
+#ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED
+ "KEV_DL_LINK_QUALITY_METRIC_CHANGED",
+#endif
};
static const char *inet6EventName[] = {
"KEV_INET6_DEFROUTER"
};
+#ifdef KEV_ND6_SUBCLASS
+static const char *nd6EventNameString[] = {
+ "",
+ "KEV_ND6_RA"
+};
+#endif // KEV_ND6_SUBCLASS
+
__private_extern__ Boolean network_changed = FALSE;
__private_extern__ SCDynamicStoreRef store = NULL;
__private_extern__ Boolean _verbose = FALSE;
break;
}
+#ifdef KEV_DL_IF_IDLE_ROUTE_REFCNT
+ case KEV_DL_IF_IDLE_ROUTE_REFCNT: {
+ /*
+ * interface route refcnt idle
+ */
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(ev, ifr_name, sizeof(ifr_name));
+ interface_update_idle_state(ifr_name);
+ break;
+ }
+#endif // KEV_DL_IF_IDLE_ROUTE_REFCNT
+
case KEV_DL_LINK_OFF :
case KEV_DL_LINK_ON :
/*
link_update_status(ifr_name, FALSE);
break;
+#ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED
+ case KEV_DL_LINK_QUALITY_METRIC_CHANGED: {
+ struct kev_dl_link_quality_metric_data * lqm_data;
+ lqm_data = (struct kev_dl_link_quality_metric_data *) event_data;
+
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(ev, ifr_name, sizeof(ifr_name));
+ interface_update_quality_metric(ifr_name,
+ lqm_data->link_quality_metric);
+ break;
+ }
+#endif // KEV_DL_LINK_QUALITY_METRIC_CHANGED
+
case KEV_DL_SIFFLAGS :
case KEV_DL_SIFMETRICS :
case KEV_DL_SIFMTU :
case KEV_DL_DELMULTI :
case KEV_DL_LINK_ADDRESS_CHANGED :
case KEV_DL_WAKEFLAGS_CHANGED :
-#ifdef KEV_DL_IF_IDLE_ROUTE_REFCNT
- case KEV_DL_IF_IDLE_ROUTE_REFCNT :
-#endif // KEV_DL_IF_IDLE_ROUTE_REFCNT
+#ifdef KEV_DL_IFCAP_CHANGED
+ case KEV_DL_IFCAP_CHANGED :
+#endif // KEV_DL_IFCAP_CHANGED
+ break;
+
+ default :
+ handled = FALSE;
+ break;
+ }
+ break;
+ }
+#ifdef KEV_ND6_SUBCLASS
+ case KEV_ND6_SUBCLASS : {
+ eventName = nd6EventNameString(ev_msg->event_code);
+ switch (ev_msg->event_code) {
+ case KEV_KEV_ND6_RA :
break;
default :
}
break;
}
+#endif // KEV_ND6_SUBCLASS
case KEV_LOG_SUBCLASS : {
break;
}
{
int so = CFSocketGetNative(s);
int status;
- char buf[1024];
- struct kern_event_msg *ev_msg = (struct kern_event_msg *)&buf[0];
+ union {
+ char bytes[1024];
+ struct kern_event_msg ev_msg1; // first kernel event
+ } buf;
+ struct kern_event_msg *ev_msg = &buf.ev_msg1;
int offset = 0;
status = recv(so, &buf, sizeof(buf), 0);
break;
}
offset += ev_msg->total_size;
- ev_msg = (struct kern_event_msg *)&buf[offset];
+ ev_msg = (struct kern_event_msg *)(void *)&buf.bytes[offset];
}
cache_write(store);
/*
- * Copyright (c) 2002, 2004, 2005, 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2002, 2004, 2005, 2007, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__BEGIN_DECLS
+__private_extern__
int dgram_socket (int domain);
__END_DECLS
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.11.3</string>
+ <string>1.12</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.11</string>
+ <string>1.12</string>
<key>Requires</key>
<array>
<string>com.apple.SystemConfiguration.InterfaceNamer</string>
* 2. key = "a/b/c" prefix = "a/b/"
* returns "c"
*/
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
parse_component(CFStringRef key, CFStringRef prefix)
{
CFMutableStringRef comp;
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.11.3</string>
+ <string>1.12</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.11</string>
+ <string>1.12</string>
<key>Enabled</key>
<false/>
<key>Verbose</key>
<true/>
<key>LOG_NETWORK_KERNEL_EVENTS</key>
<false/>
+ <key>LOG_NETWORK_INFORMATION</key>
+ <true/>
<key>LOG_NOTIFY_DNS_CONFIGURATION</key>
<true/>
<key>LOG_NOTIFY_NETWORK_CHANGE</key>
<array>
<string>mail.me.com</string>
</array>
+ <key>Requires</key>
+ <array>
+ <string>com.apple.SystemConfiguration.SCNetworkReachability</string>
+ </array>
</dict>
</plist>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.11.3</string>
+ <string>1.12</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.11</string>
+ <string>1.12</string>
<key>Enabled</key>
<false/>
<key>Verbose</key>
<false/>
<key>LOG_NETWORK_KERNEL_EVENTS</key>
<true/>
+ <key>LOG_NETWORK_INFORMATION</key>
+ <true/>
<key>LOG_NOTIFY_DNS_CONFIGURATION</key>
<true/>
<key>LOG_NOTIFY_NETWORK_CHANGE</key>
<array>
<string>mail.me.com</string>
</array>
+ <key>Requires</key>
+ <array>
+ <string>com.apple.SystemConfiguration.SCNetworkReachability</string>
+ </array>
</dict>
</plist>
/*
- * Copyright (c) 2005-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <IOKit/pwr_mgt/IOPMLibPrivate.h>
#include <dnsinfo.h>
+#include <network_information.h>
#include <notify.h>
#if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) && !TARGET_OS_EMBEDDED
#include <utmpx.h>
{
int so = CFSocketGetNative(s);
int status;
- char buf[1024];
- struct kern_event_msg *ev_msg = (struct kern_event_msg *)&buf[0];
+ union {
+ char bytes[1024];
+ struct kern_event_msg ev_msg1; // first kernel event
+ } buf;
+ struct kern_event_msg *ev_msg = &buf.ev_msg1;
int offset = 0;
status = recv(so, &buf, sizeof(buf), 0);
break;
}
offset += ev_msg->total_size;
- ev_msg = (struct kern_event_msg *)&buf[offset];
+ ev_msg = (struct kern_event_msg *)(void *)&buf.bytes[offset];
}
return;
NetworkChange_notification(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context)
{
CFIndex i;
- CFIndex n;
- CFMutableStringRef str = CFStringCreateMutable(NULL, 0);
+ CFIndex nk;
+ CFMutableStringRef str;
+ str = CFStringCreateMutable(NULL, 0);
CFStringAppendFormat(str,
NULL,
CFSTR("%s SCDynamicStore \"network\" notification"),
elapsed());
- n = CFArrayGetCount(changedKeys);
- for (i = 0; i < n; i++) {
+ nk = CFArrayGetCount(changedKeys);
+ for (i = 0; i < nk; i++) {
+ CFArrayRef components;
CFStringRef key;
+ CFIndex nc;
key = CFArrayGetValueAtIndex(changedKeys, i);
- if (CFStringHasSuffix(key, kSCEntNetLink)) {
- CFDictionaryRef dict;
- const char *val = "?";
- dict = SCDynamicStoreCopyValue(store, key);
- if (dict != NULL) {
- CFBooleanRef link;
+ components = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/"));
+ if (components == NULL) {
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key);
+ continue;
+ }
- link = CFDictionaryGetValue(dict, kSCPropNetLinkActive);
- if (link != NULL) {
- val = CFBooleanGetValue(link) ? "up" : "down";
- }
+ nc = CFArrayGetCount(components);
+ switch (nc) {
+ case 5 : {
+ CFStringRef entity_id;
- CFRelease(dict);
+ entity_id = CFArrayGetValueAtIndex(components, 4);
+ if (CFEqual(entity_id, kSCEntNetLink)) {
+ CFDictionaryRef dict;
+ const char *val = "?";
+
+ dict = SCDynamicStoreCopyValue(store, key);
+ if (dict != NULL) {
+ CFBooleanRef link;
+
+ link = CFDictionaryGetValue(dict, kSCPropNetLinkActive);
+ if (link != NULL) {
+ val = CFBooleanGetValue(link) ? "up" : "down";
+ }
+
+ CFRelease(dict);
+ }
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@ (%s)"), key, val);
+ } else if (CFEqual(entity_id, kSCEntNetIPv4) ||
+ CFEqual(entity_id, kSCEntNetIPv6) ||
+ CFEqual(entity_id, kSCEntNetDNS)) {
+ CFDictionaryRef dict;
+
+ dict = SCDynamicStoreCopyValue(store, key);
+ if (dict != NULL) {
+ CFStringRef val;
+
+ val = _SCCopyDescription(dict, NULL);
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@ : %@"), key, val);
+ CFRelease(val);
+ CFRelease(dict);
+ } else {
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@ : removed"), key);
+ }
+ } else if (CFEqual(entity_id, kSCEntNetAirPort)) {
+ CFDictionaryRef dict;
+
+ dict = SCDynamicStoreCopyValue(store, key);
+ if (dict != NULL) {
+ CFStringRef ssid_str;
+
+ ssid_str = CFDictionaryGetValue(dict, CFSTR("SSID_STR"));
+ if (ssid_str != NULL) {
+ CFDataRef bssid;
+
+ bssid = CFDictionaryGetValue(dict, CFSTR("BSSID"));
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@ : SSID: %@ BSSID: %s"),
+ key,
+ ssid_str,
+ (bssid != NULL) ? ether_ntoa((struct ether_addr *)CFDataGetBytePtr(bssid)) : "<unknown>");
+ } else {
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@ : no SSID"), key);
+ }
+ CFRelease(dict);
+ } else {
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@ : removed"), key);
+ }
+ } else if (CFEqual(entity_id, kSCEntNetService)) {
+ CFDictionaryRef dict;
+ CFStringRef rank = kSCNetworkServicePrimaryRankDefault;
+
+ dict = SCDynamicStoreCopyValue(store, key);
+ if ((dict == NULL) ||
+ !CFDictionaryGetValueIfPresent(dict,
+ kSCPropNetServicePrimaryRank,
+ (const void **)&rank)) {
+ rank = kSCNetworkServicePrimaryRankDefault;
+ }
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@ : Rank = %@"), key, rank);
+ if (dict != NULL) CFRelease(dict);
+ } else {
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key);
+ }
+ break;
}
- CFStringAppendFormat(str, NULL, CFSTR("\n%@ (%s)"), key, val);
- } else if (CFStringHasSuffix(key, kSCEntNetIPv4) ||
- CFStringHasSuffix(key, kSCEntNetIPv6) ||
- CFStringHasSuffix(key, kSCEntNetDNS)) {
- CFDictionaryRef dict;
-
- dict = SCDynamicStoreCopyValue(store, key);
- if (dict != NULL) {
- CFStringRef val;
-
- val = _SCCopyDescription(dict, NULL);
- CFStringAppendFormat(str, NULL, CFSTR("\n%@ : %@"), key, val);
- CFRelease(val);
- CFRelease(dict);
- } else {
- CFStringAppendFormat(str, NULL, CFSTR("\n%@ : removed"), key);
+
+ case 4 : {
+ static CFStringRef rank_setup_prefix = NULL;
+ static CFStringRef rank_state_prefix = NULL;
+
+ if (rank_setup_prefix == NULL) {
+ rank_setup_prefix = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ CFSTR(""),
+ NULL);
+ rank_state_prefix = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ CFSTR(""),
+ NULL);
+ }
+
+ if (CFStringHasPrefix(key, rank_setup_prefix) ||
+ CFStringHasPrefix(key, rank_state_prefix)) {
+ CFDictionaryRef dict;
+ CFStringRef rank = kSCNetworkServicePrimaryRankDefault;
+
+ dict = SCDynamicStoreCopyValue(store, key);
+ if ((dict == NULL) ||
+ !CFDictionaryGetValueIfPresent(dict,
+ kSCPropNetServicePrimaryRank,
+ (const void **)&rank)) {
+ rank = kSCNetworkServicePrimaryRankDefault;
+ }
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@ : Rank = %@"), key, rank);
+ if (dict != NULL) CFRelease(dict);
+ } else {
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key);
+ }
+ break;
}
- } else if (CFStringHasSuffix(key, CFSTR(kIOPMSystemPowerCapabilitiesKeySuffix))) {
- CFNumberRef num;
- num = SCDynamicStoreCopyValue(store, key);
- if (num != NULL) {
- IOPMSystemPowerStateCapabilities capabilities;
+ case 2 :
+ if (CFEqual(CFArrayGetValueAtIndex(components, 1),
+ CFSTR(kIOPMSystemPowerCapabilitiesKeySuffix))) {
+ CFNumberRef num;
- if (isA_CFNumber(num) &&
- CFNumberGetValue(num, kCFNumberSInt32Type, &capabilities)) {
- CFStringAppendFormat(str, NULL, CFSTR("\n%@ (0x%x)"), key, capabilities);
+ num = SCDynamicStoreCopyValue(store, key);
+ if (num != NULL) {
+ IOPMSystemPowerStateCapabilities capabilities;
+
+ if (isA_CFNumber(num) &&
+ CFNumberGetValue(num, kCFNumberSInt32Type, &capabilities)) {
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@ (0x%x)"), key, capabilities);
+ }
+
+ CFRelease(num);
+ }
+ } else {
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key);
}
+ break;
- CFRelease(num);
- }
- } else {
- CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key);
+ default :
+ CFStringAppendFormat(str, NULL, CFSTR("\n%@"), key);
+ break;
}
+
+ CFRelease(components);
}
SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO, CFSTR("%@"), str);
}
+static void
+add_NetworkChange_keys(CFMutableArrayRef keys,
+ CFMutableArrayRef patterns,
+ CFStringRef entity,
+ Boolean doGlobal,
+ Boolean doService,
+ Boolean doInterface)
+{
+ CFStringRef key;
+ CFStringRef pattern;
+
+ if (doGlobal) {
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainSetup, entity);
+ CFArrayAppendValue(keys, key);
+ CFRelease(key);
+
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, entity);
+ CFArrayAppendValue(keys, key);
+ CFRelease(key);
+ }
+
+ if (doService) {
+ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, entity);
+ CFArrayAppendValue(patterns, pattern);
+ CFRelease(pattern);
+
+ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, entity);
+ CFArrayAppendValue(patterns, pattern);
+ CFRelease(pattern);
+ }
+
+ if (doInterface) {
+ pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, entity);
+ CFArrayAppendValue(patterns, pattern);
+ CFRelease(pattern);
+ }
+
+ return;
+}
+
+
static void
add_NetworkChange_notification()
{
CFStringRef key;
CFMutableArrayRef keys;
Boolean ok;
- CFStringRef pattern;
CFMutableArrayRef patterns;
SCDynamicStoreRef store;
CFRunLoopSourceRef rls;
// IPv4
- key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
- CFArrayAppendValue(keys, key);
- CFRelease(key);
-
- pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4);
- CFArrayAppendValue(patterns, pattern);
- CFRelease(pattern);
-
- pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4);
- CFArrayAppendValue(patterns, pattern);
- CFRelease(pattern);
+ add_NetworkChange_keys(keys, patterns, kSCEntNetIPv4, TRUE, TRUE, TRUE);
// IPv6
- key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
- CFArrayAppendValue(keys, key);
- CFRelease(key);
-
- pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6);
- CFArrayAppendValue(patterns, pattern);
- CFRelease(pattern);
-
- pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6);
- CFArrayAppendValue(patterns, pattern);
- CFRelease(pattern);
+ add_NetworkChange_keys(keys, patterns, kSCEntNetIPv6, TRUE, TRUE, TRUE);
// PPP, VPN
- pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetPPP);
- CFArrayAppendValue(patterns, pattern);
- CFRelease(pattern);
-
- pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetPPP);
- CFArrayAppendValue(patterns, pattern);
- CFRelease(pattern);
-
- pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetVPN);
- CFArrayAppendValue(patterns, pattern);
- CFRelease(pattern);
-
- pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetVPN);
- CFArrayAppendValue(patterns, pattern);
- CFRelease(pattern);
+ add_NetworkChange_keys(keys, patterns, kSCEntNetPPP, FALSE, TRUE, TRUE);
+ add_NetworkChange_keys(keys, patterns, kSCEntNetVPN, FALSE, TRUE, TRUE);
+ add_NetworkChange_keys(keys, patterns, kSCEntNetL2TP, FALSE, TRUE, TRUE);
+ add_NetworkChange_keys(keys, patterns, kSCEntNetPPTP, FALSE, TRUE, TRUE);
+ add_NetworkChange_keys(keys, patterns, kSCEntNetIPSec, FALSE, TRUE, TRUE);
// Link
- pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetLink);
- CFArrayAppendValue(patterns, pattern);
- CFRelease(pattern);
+ add_NetworkChange_keys(keys, patterns, kSCEntNetLink, FALSE, FALSE, TRUE);
// AirPort (e.g. BSSID)
- pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetAirPort);
- CFArrayAppendValue(patterns, pattern);
- CFRelease(pattern);
+ add_NetworkChange_keys(keys, patterns, kSCEntNetAirPort, FALSE, FALSE, TRUE);
// DNS
- key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
- CFArrayAppendValue(keys, key);
- CFRelease(key);
+ add_NetworkChange_keys(keys, patterns, kSCEntNetDNS, TRUE, TRUE, TRUE);
dns_key = CFStringCreateWithCString(NULL,
dns_configuration_notify_key(),
CFArrayAppendValue(keys, key);
CFRelease(key);
+ // Rank
+
+ add_NetworkChange_keys(keys, patterns, NULL, FALSE, TRUE, FALSE); // per-service
+ add_NetworkChange_keys(keys, patterns, kSCEntNetService, FALSE, FALSE, TRUE); // per-interface
+
// ComputerName, LocalHostName
key = SCDynamicStoreKeyCreateComputerName(NULL);
CFArrayAppendValue(keys, key);
CFRelease(key);
+ // Power Management
+
key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@%@"),
kSCDynamicStoreDomainState,
CFSTR(kIOPMSystemPowerCapabilitiesKeySuffix));
CFArrayAppendValue(keys, key);
CFRelease(key);
+
+ // Setup monitoring
+
ok = SCDynamicStoreSetNotificationKeys(store, keys, patterns);
CFRelease(keys);
CFRelease(patterns);
}
+#pragma mark -
+#pragma mark Network Information Events
+
+
+static void
+nwi_notification(CFMachPortRef port, void *msg, CFIndex size, void *info)
+{
+ SCLOG(NULL, log_msg, ~ASL_LEVEL_INFO,
+ CFSTR("%s network_information notification"),
+ elapsed());
+
+ return;
+}
+
+
+static void
+add_nwi_notification()
+{
+ const char *key;
+ CFMachPortRef mp;
+ mach_port_t notify_port;
+ int notify_token;
+ CFRunLoopSourceRef rls;
+ uint32_t status;
+
+ key = nwi_state_get_notify_key();
+ status = notify_register_mach_port(key, ¬ify_port, 0, ¬ify_token);
+ if (status != NOTIFY_STATUS_OK) {
+ SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("notify_register_mach_port() failed"));
+ return;
+ }
+
+ mp = _SC_CFMachPortCreateWithPort("Logger/nwi", notify_port, nwi_notification, NULL);
+ if (mp == NULL) {
+ SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("CFMachPortCreateWithPort() failed"));
+ (void)notify_cancel(notify_token);
+ return;
+ }
+
+ rls = CFMachPortCreateRunLoopSource(NULL, mp, -1);
+ if (rls == NULL) {
+ SCLOG(NULL, NULL, ASL_LEVEL_ERR, CFSTR("SCDynamicStoreCreateRunLoopSource() failed"));
+ CFRelease(mp);
+ (void)notify_cancel(notify_token);
+ return;
+ }
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+ CFRelease(rls);
+
+ CFRelease(mp);
+ return;
+}
+
+
#pragma mark -
#pragma mark Network Configuration Change Events
add_KernelEvent_notification();
}
+ if (log_all || bValFromDictionary(config, CFSTR("LOG_NETWORK_INFORMATION"))) {
+ add_nwi_notification();
+ }
+
if (log_all || bValFromDictionary(config, CFSTR("LOG_NOTIFY_DNS_CONFIGURATION"))) {
add_dnsinfo_notification();
}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>English</string>
- <key>CFBundleExecutable</key>
- <string>NetworkIdentification</string>
- <key>CFBundleIdentifier</key>
- <string>com.apple.SystemConfiguration.NetworkIdentification</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>com.apple.SystemConfiguration.NetworkIdentification</string>
- <key>CFBundlePackageType</key>
- <string>BNDL</string>
- <key>CFBundleShortVersionString</key>
- <string>1.11.3</string>
- <key>CFBundleSignature</key>
- <string>????</string>
- <key>CFBundleVersion</key>
- <string>1.11</string>
- <key>Builtin</key>
- <true/>
-</dict>
-</plist>
+++ /dev/null
-netsig: NetworkIdentification.c
- cc -Wall -g -DTEST_NETWORKIDENTIFICATION -o netsig NetworkIdentification.c -framework CoreFoundation -framework SystemConfiguration
-
-clean:
- rm -f netsig
-
+++ /dev/null
-/*
- * Copyright (c) 2005-2007, 2009 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,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * 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@
- */
-
-/*
- * NetworkIdentification.c
- * - maintains a history of networks that the system has connected to by
- * watching the Network Services that post data to the SCDynamicStore
- */
-
-/*
- * Modification History
- *
- * November 9, 2006 Dieter Siegmund (dieter@apple.com)
- * - created
- */
-
-#include <notify.h>
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCValidation.h>
-#include <SystemConfiguration/SCPrivate.h>
-#include <CoreFoundation/CFDictionary.h>
-#include <SystemConfiguration/SCNetworkSignature.h>
-#include <SystemConfiguration/SCNetworkSignaturePrivate.h>
-
-/* debug output on/off */
-static Boolean S_NetworkIdentification_debug;
-
-/* should we bother keeping track of networks? */
-static Boolean S_NetworkIdentification_disabled;
-
-typedef struct ServiceWatcher_s ServiceWatcher, * ServiceWatcherRef;
-
-/* returns an array of currently available information */
-static CFArrayRef
-ServiceWatcherCopyCurrent(ServiceWatcherRef watcher);
-
-static ServiceWatcherRef
-ServiceWatcherCreate();
-
-static void
-ServiceWatcherFree(ServiceWatcherRef * watcher_p);
-
-/* XXX these should be made tunable */
-#define SIGNATURE_HISTORY_MAX 150
-#define SERVICE_HISTORY_MAX 5
-
-/* don't re-write the prefs file unless this time interval has elapsed */
-#define SIGNATURE_UPDATE_INTERVAL_SECS (24 * 3600) /* 24 hours */
-
-struct ServiceWatcher_s {
- CFRunLoopSourceRef rls;
- SCDynamicStoreRef store;
- CFMutableArrayRef signatures;
- CFArrayRef active_signatures;
- CFStringRef primary_ipv4;
- CFStringRef setup_ipv4_key;
- CFStringRef state_ipv4_key;
-};
-
-#define kIdentifier CFSTR("Identifier")
-#define kService CFSTR("Service")
-#define kServices CFSTR("Services")
-#define kSignature CFSTR("Signature")
-#define kSignatures CFSTR("Signatures")
-#define kTimestamp CFSTR("Timestamp")
-#define kServiceID CFSTR("ServiceID")
-#define kNetworkSignature CFSTR("NetworkSignature")
-#define kServiceIdentifiers kStoreKeyServiceIdentifiers
-
-static CFArrayRef
-make_service_entity_pattern_array(CFStringRef * keys, int n_keys)
-{
- int i;
- CFArrayRef list;
-
- for (i = 0; i < n_keys; i++) {
- /* re-use the array that was passed in to get the pattern */
- keys[i] = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
- kSCDynamicStoreDomainState,
- kSCCompAnyRegex,
- keys[i]);
- }
- list = CFArrayCreate(NULL, (const void * *)keys, n_keys,
- &kCFTypeArrayCallBacks);
- for (i = 0; i < n_keys; i++) {
- /* then release the allocated patterns */
- CFRelease(keys[i]);
- }
- return (list);
-}
-
-static CFArrayRef
-ServiceWatcherNotificationPatterns(void)
-{
- CFStringRef keys[1] = { kSCEntNetIPv4 };
-
- return (make_service_entity_pattern_array(keys,
- sizeof(keys) / sizeof(keys[0])));
-}
-
-static CFArrayRef
-ServiceWatcherPatterns(void)
-{
- CFStringRef keys[2] = { kSCEntNetIPv4, kSCEntNetDNS };
-
- return (make_service_entity_pattern_array(keys,
- sizeof(keys) / sizeof(keys[0])));
-}
-
-static CFTypeRef
-myCFDictionaryArrayGetValue(CFArrayRef array, CFStringRef key, CFTypeRef value,
- int * ret_index)
-{
- int count = 0;
- int i;
-
- if (array != NULL) {
- count = CFArrayGetCount(array);
- }
- if (count == 0) {
- goto done;
- }
- for (i = 0; i < count; i++) {
- CFDictionaryRef dict;
- CFTypeRef this_val;
-
- dict = CFArrayGetValueAtIndex(array, i);
- if (isA_CFDictionary(dict) == NULL) {
- continue;
- }
- this_val = CFDictionaryGetValue(dict, key);
- if (CFEqual(this_val, value)) {
- if (ret_index != NULL) {
- *ret_index = i;
- }
- return (dict);
- }
- }
- done:
- if (ret_index != NULL) {
- *ret_index = -1;
- }
- return (NULL);
-}
-
-static CFDictionaryRef
-copy_airport_dict(SCDynamicStoreRef store, CFStringRef if_name)
-{
- CFDictionaryRef dict;
- CFStringRef key;
-
- key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
- kSCDynamicStoreDomainState,
- if_name,
- kSCEntNetAirPort);
- dict = SCDynamicStoreCopyValue(store, key);
- CFRelease(key);
- return (dict);
-}
-
-static void
-add_airport_info(SCDynamicStoreRef store, CFMutableDictionaryRef dict)
-{
- CFDictionaryRef airport_dict = NULL;
- CFStringRef key;
- CFStringRef if_name;
- CFDictionaryRef simple_dict;
- CFStringRef value;
-
- if_name = CFDictionaryGetValue(dict, kSCPropInterfaceName);
- if (isA_CFString(if_name) == NULL) {
- goto done;
- }
- airport_dict = copy_airport_dict(store, if_name);
- if (airport_dict == NULL) {
- goto done;
- }
- key = CFSTR("SSID");
- value = CFDictionaryGetValue(airport_dict, key);
- if (value == NULL) {
- goto done;
- }
- simple_dict =
- CFDictionaryCreate(NULL,
- (const void * *)&key, (const void * *)&value, 1,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFDictionarySetValue(dict, kSCEntNetAirPort, simple_dict);
- CFRelease(simple_dict);
-
- done:
- if (airport_dict != NULL) {
- CFRelease(airport_dict);
- }
- return;
-}
-
-static CFDictionaryRef
-get_current_dict(CFDictionaryRef current, CFStringRef entity,
- CFArrayRef components)
-{
- CFDictionaryRef dict;
- CFStringRef key;
-
- if (CFArrayGetCount(components) < 5) {
- /* this can't happen, we already checked */
- return (NULL);
- }
- key = CFStringCreateWithFormat(NULL, NULL,
- CFSTR("%@/%@/%@/%@/%@"),
- CFArrayGetValueAtIndex(components, 0),
- CFArrayGetValueAtIndex(components, 1),
- CFArrayGetValueAtIndex(components, 2),
- CFArrayGetValueAtIndex(components, 3),
- entity);
- dict = CFDictionaryGetValue(current, key);
- CFRelease(key);
- return (isA_CFDictionary(dict));
-}
-
-static CFArrayRef
-process_dict(SCDynamicStoreRef store, CFDictionaryRef current)
-{
- CFMutableArrayRef array = NULL;
- int count = 0;
- int i;
- const void * * keys = NULL;
- const void * * values = NULL;
-
- count = CFDictionaryGetCount(current);
- if (count == 0) {
- goto done;
- }
- array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- keys = (const void * *)malloc(sizeof(keys) * count);
- values = (const void * *)malloc(sizeof(values) * count);
- CFDictionaryGetKeysAndValues(current, keys, values);
- for (i = 0; i < count; i++) {
- CFArrayRef components = NULL;
- CFDictionaryRef dns_dict;
- CFStringRef entity;
- CFMutableDictionaryRef entity_dict = NULL;
- CFMutableDictionaryRef new_dict = NULL;
- CFStringRef sig_str = NULL;
- CFMutableDictionaryRef service_dict = NULL;
- CFStringRef serviceID;
-
- if (isA_CFDictionary(values[i]) == NULL) {
- goto loop_done;
- }
- components = CFStringCreateArrayBySeparatingStrings(NULL, keys[i],
- CFSTR("/"));
- if (components == NULL) {
- goto loop_done;
- }
- if (CFArrayGetCount(components) < 5) {
- /* too few components */
- goto loop_done;
- }
- entity = CFArrayGetValueAtIndex(components, 4);
- if (!CFEqual(entity, kSCEntNetIPv4)) {
- goto loop_done;
- }
- serviceID = CFArrayGetValueAtIndex(components, 3);
- sig_str = CFDictionaryGetValue(values[i], kNetworkSignature);
- if (isA_CFString(sig_str) == NULL
- || CFStringGetLength(sig_str) == 0) {
- goto loop_done;
- }
- /* create a new entry */
- new_dict = CFDictionaryCreateMutable(NULL, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFDictionarySetValue(new_dict, kSignature, sig_str);
- service_dict = CFDictionaryCreateMutable(NULL, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFDictionarySetValue(service_dict, kServiceID, serviceID);
- add_airport_info(store, service_dict);
- entity_dict = CFDictionaryCreateMutableCopy(NULL, 0, values[i]);
- CFDictionaryRemoveValue(entity_dict, kNetworkSignature);
- CFDictionarySetValue(service_dict, kSCEntNetIPv4, entity_dict);
- dns_dict = get_current_dict(current, kSCEntNetDNS, components);
- if (dns_dict != NULL) {
- CFDictionarySetValue(service_dict, kSCEntNetDNS, dns_dict);
- }
- CFDictionarySetValue(new_dict, kService, service_dict);
- CFArrayAppendValue(array, new_dict);
-
- loop_done:
- if (entity_dict != NULL) {
- CFRelease(entity_dict);
- }
- if (service_dict != NULL) {
- CFRelease(service_dict);
- }
- if (components != NULL) {
- CFRelease(components);
- }
- if (new_dict != NULL) {
- CFRelease(new_dict);
- }
- }
- count = CFArrayGetCount(array);
- if (count == 0) {
- CFRelease(array);
- array = NULL;
- goto done;
- }
-
- done:
- if (keys != NULL) {
- free(keys);
- }
- if (values != NULL) {
- free(values);
- }
- return (array);
-
-}
-
-static CFArrayRef
-ServiceWatcherCopyCurrent(ServiceWatcherRef watcher)
-{
- CFDictionaryRef current;
- CFArrayRef list;
- CFArrayRef ret = NULL;
-
- list = ServiceWatcherPatterns();
- current = SCDynamicStoreCopyMultiple(watcher->store, NULL, list);
- CFRelease(list);
- if (current == NULL) {
- goto done;
- }
- ret = process_dict(watcher->store, current);
- done:
- if (current != NULL) {
- CFRelease(current);
- }
- return (ret);
-}
-
-static Boolean
-ServiceWatcherSetActiveSignatures(ServiceWatcherRef watcher, CFArrayRef active)
-{
- Boolean changed = FALSE;
- CFArrayRef prev_active;
-
- prev_active = watcher->active_signatures;
- if (prev_active == NULL && active == NULL) {
- /* nothing to do */
- goto done;
- }
- if (prev_active != NULL && active != NULL) {
- changed = !CFEqual(prev_active, active);
- }
- else {
- changed = TRUE;
- }
- if (active != NULL) {
- CFRetain(active);
- }
- if (prev_active != NULL) {
- CFRelease(prev_active);
- }
- watcher->active_signatures = active;
- if (changed) {
- if (active != NULL) {
- SCLog(S_NetworkIdentification_debug,
- LOG_NOTICE, CFSTR("Active Signatures %@"), active);
- }
- else {
- SCLog(S_NetworkIdentification_debug,
- LOG_NOTICE, CFSTR("No Active Signatures"));
- }
- }
- done:
- return (changed);
-}
-
-static Boolean
-ServiceWatcherSetPrimaryIPv4(ServiceWatcherRef watcher,
- CFStringRef primary_ipv4)
-{
- Boolean changed = FALSE;
- CFStringRef prev_ipv4_primary;
-
- prev_ipv4_primary = watcher->primary_ipv4;
- if (prev_ipv4_primary == NULL && primary_ipv4 == NULL) {
- /* nothing to do */
- goto done;
- }
- if (prev_ipv4_primary != NULL && primary_ipv4 != NULL) {
- changed = !CFEqual(prev_ipv4_primary, primary_ipv4);
- }
- else {
- changed = TRUE;
- }
- if (primary_ipv4 != NULL) {
- CFRetain(primary_ipv4);
- }
- if (prev_ipv4_primary != NULL) {
- CFRelease(prev_ipv4_primary);
- }
- watcher->primary_ipv4 = primary_ipv4;
- if (changed) {
- if (primary_ipv4 != NULL) {
- SCLog(S_NetworkIdentification_debug,
- LOG_NOTICE, CFSTR("Primary IPv4 %@"), primary_ipv4);
- }
- else {
- SCLog(S_NetworkIdentification_debug, LOG_NOTICE,
- CFSTR("No Primary IPv4"));
- }
- }
- done:
- return (changed);
-}
-
-
-static CFDictionaryRef
-signature_add_service(CFDictionaryRef sig_dict, CFDictionaryRef service,
- CFArrayRef active_services)
-{
- CFArrayRef list;
- CFMutableDictionaryRef new_dict = NULL;
- CFDateRef now;
-
- list = CFDictionaryGetValue(sig_dict, kServices);
- now = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
- if (list == NULL) {
- list = CFArrayCreate(NULL, (const void * *)&service, 1,
- &kCFTypeArrayCallBacks);
- }
- else {
- int list_count = CFArrayGetCount(list);
- CFMutableArrayRef new_list = NULL;
- CFRange range = CFRangeMake(0, list_count);
- int where;
-
- where = CFArrayGetFirstIndexOfValue(list, range, service);
- if (where != kCFNotFound) {
- CFDateRef date;
-
- date = CFDictionaryGetValue(sig_dict, kTimestamp);
- if (date != NULL) {
- CFTimeInterval time_interval;
-
- time_interval = CFDateGetTimeIntervalSinceDate(now, date);
- /* don't bother updating timestamp until interval has passed */
- if (time_interval < (SIGNATURE_UPDATE_INTERVAL_SECS)) {
- goto done;
- }
- }
- if (where == 0) {
- /* it's already in the right place */
- list = NULL;
- }
- }
-
- if (list != NULL) {
- new_list = CFArrayCreateMutableCopy(NULL, 0, list);
- if (where != kCFNotFound) {
- CFArrayRemoveValueAtIndex(new_list, where);
- }
- else {
- list_count++;
- }
- CFArrayInsertValueAtIndex(new_list, 0, service);
- /* try to remove stale entries */
- if (list_count > SERVICE_HISTORY_MAX) {
- int i;
- int remove_count = list_count - SERVICE_HISTORY_MAX;
-
- SCLog(S_NetworkIdentification_debug,
- LOG_NOTICE, CFSTR("Attempting to remove %d services"),
- remove_count);
- for (i = list_count - 1; i >= 0 && remove_count > 0; i--) {
- CFDictionaryRef dict;
-
- dict = CFArrayGetValueAtIndex(new_list, i);
- if (myCFDictionaryArrayGetValue(active_services,
- kService, dict, NULL)
- != NULL) {
- /* skip anything that's currently active */
- SCLog(S_NetworkIdentification_debug,
- LOG_NOTICE, CFSTR("Skipping Service %@"),
- dict);
- }
- else {
- SCLog(S_NetworkIdentification_debug, LOG_NOTICE,
- CFSTR("Removing Service %@"), dict);
- CFArrayRemoveValueAtIndex(new_list, i);
- remove_count--;
- }
- }
- }
- list = (CFArrayRef)new_list;
-
- }
- }
-
- new_dict = CFDictionaryCreateMutableCopy(NULL, 0, sig_dict);
- if (list != NULL) {
- CFDictionarySetValue(new_dict, kServices, list);
- CFRelease(list);
- }
- CFDictionarySetValue(new_dict, kTimestamp, now);
-
- done:
- CFRelease(now);
- return (new_dict);
-}
-
-#define ARBITRARILY_LARGE_NUMBER (1024 * 1024)
-static CFStringRef
-get_best_serviceID(CFArrayRef serviceID_list, CFArrayRef order)
-{
- int best_rank;
- CFStringRef best_serviceID;
- int count;
- int i;
- CFRange range;
-
- count = CFArrayGetCount(serviceID_list);
- if (count == 1 || order == NULL) {
- return (CFArrayGetValueAtIndex(serviceID_list, 0));
- }
- best_serviceID = NULL;
- best_rank = ARBITRARILY_LARGE_NUMBER;
- range = CFRangeMake(0, CFArrayGetCount(order));
- for (i = 0; i < count; i++) {
- CFStringRef serviceID = CFArrayGetValueAtIndex(serviceID_list, i);
- int this_rank;
-
- this_rank = CFArrayGetFirstIndexOfValue(order, range, serviceID);
- if (this_rank == kCFNotFound) {
- this_rank = ARBITRARILY_LARGE_NUMBER;
- }
- if (best_serviceID == NULL || this_rank < best_rank) {
- best_serviceID = serviceID;
- best_rank = this_rank;
- }
- }
- return (best_serviceID);
-}
-
-static CFArrayRef
-copy_service_order(SCDynamicStoreRef session, CFStringRef ipv4_key)
-{
- CFArrayRef order = NULL;
- CFDictionaryRef ipv4_dict = NULL;
-
- if (session == NULL) {
- return (NULL);
- }
- ipv4_dict = SCDynamicStoreCopyValue(session, ipv4_key);
- if (isA_CFDictionary(ipv4_dict) != NULL) {
- order = CFDictionaryGetValue(ipv4_dict, kSCPropNetServiceOrder);
- order = isA_CFArray(order);
- if (order) {
- CFRetain(order);
- }
- }
- if (ipv4_dict != NULL) {
- CFRelease(ipv4_dict);
- }
- return (order);
-}
-
-typedef struct service_order_with_range {
- CFArrayRef service_order;
- CFRange range;
-} service_order_with_range_t;
-
-static void
-add_netID_and_serviceID(service_order_with_range_t * order, int count,
- CFMutableArrayRef netID_list, CFStringRef netID,
- CFMutableArrayRef serviceID_list, CFStringRef serviceID)
-
-{
- int i;
- int serviceID_index;
-
- if (count == 0 || order->service_order == NULL) {
- goto add_to_end;
- }
- serviceID_index = CFArrayGetFirstIndexOfValue(order->service_order,
- order->range,
- serviceID);
- if (serviceID_index == kCFNotFound) {
- goto add_to_end;
- }
- for (i = 0; i < count; i++) {
- CFStringRef scan = CFArrayGetValueAtIndex(serviceID_list, i);
- int scan_index;
-
- scan_index = CFArrayGetFirstIndexOfValue(order->service_order,
- order->range,
- scan);
- if (scan_index == kCFNotFound
- || serviceID_index < scan_index) {
- /* found our insertion point */
- CFArrayInsertValueAtIndex(netID_list, i, netID);
- CFArrayInsertValueAtIndex(serviceID_list, i, serviceID);
- return;
- }
- }
-
- add_to_end:
- CFArrayAppendValue(netID_list, netID);
- CFArrayAppendValue(serviceID_list, serviceID);
- return;
-}
-
-static Boolean
-ServiceWatcherPublishActiveIdentifiers(ServiceWatcherRef watcher)
-{
- Boolean updated = FALSE;
-
- if (watcher->active_signatures == NULL) {
- CFDictionaryRef dict;
-
- dict = SCDynamicStoreCopyValue(watcher->store,
- kSCNetworkIdentificationStoreKey);
- if (dict != NULL) {
- updated = TRUE;
- SCLog(S_NetworkIdentification_debug,
- LOG_NOTICE, CFSTR("Removing %@"),
- kSCNetworkIdentificationStoreKey);
- SCDynamicStoreRemoveValue(watcher->store,
- kSCNetworkIdentificationStoreKey);
- CFRelease(dict);
- }
- }
- else {
- int count;
- CFDictionaryRef dict;
- int i;
- CFMutableArrayRef id_list;
- CFStringRef keys[3];
- int keys_count;
- service_order_with_range_t order;
- CFStringRef primary_ipv4_id = NULL;
- CFMutableArrayRef serviceID_list;
- CFDictionaryRef store_dict;
- CFTypeRef values[3];
-
- order.service_order = copy_service_order(watcher->store,
- watcher->setup_ipv4_key);
- if (order.service_order != NULL) {
- order.range = CFRangeMake(0, CFArrayGetCount(order.service_order));
- }
- id_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- serviceID_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- count = CFArrayGetCount(watcher->active_signatures);
- for (i = 0; i < count; i++) {
- CFStringRef this_id;
- CFStringRef serviceID;
- CFArrayRef this_list;
-
- dict = CFArrayGetValueAtIndex(watcher->active_signatures, i);
- this_id = CFDictionaryGetValue(dict, kIdentifier);
- this_list = CFDictionaryGetValue(dict, kServiceIdentifiers);
- if (primary_ipv4_id == NULL && watcher->primary_ipv4 != NULL) {
- CFRange range;
-
- range = CFRangeMake(0, CFArrayGetCount(this_list));
- if (CFArrayContainsValue(this_list, range,
- watcher->primary_ipv4)) {
- primary_ipv4_id = this_id;
- }
- }
- serviceID = get_best_serviceID(this_list, order.service_order);
- add_netID_and_serviceID(&order, i, id_list, this_id,
- serviceID_list, serviceID);
- }
- keys[0] = kStoreKeyActiveIdentifiers;
- values[0] = id_list;
- keys[1] = kStoreKeyServiceIdentifiers;
- values[1] = serviceID_list;
- if (primary_ipv4_id != NULL) {
- keys_count = 3;
- keys[2] = kStoreKeyPrimaryIPv4Identifier;
- values[2] = primary_ipv4_id;
- }
- else {
- keys_count = 2;
- }
- dict = CFDictionaryCreate(NULL, (const void * *)keys,
- (const void * *)values, keys_count,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- store_dict
- = SCDynamicStoreCopyValue(watcher->store,
- kSCNetworkIdentificationStoreKey);
- if (isA_CFDictionary(store_dict) == NULL
- || CFEqual(store_dict, dict) == FALSE) {
- updated = TRUE;
- SCDynamicStoreSetValue(watcher->store,
- kSCNetworkIdentificationStoreKey, dict);
- SCLog(S_NetworkIdentification_debug,
- LOG_NOTICE, CFSTR("Setting %@ = %@"),
- kSCNetworkIdentificationStoreKey,
- dict);
- }
- else {
- SCLog(S_NetworkIdentification_debug,
- LOG_NOTICE, CFSTR("Not setting %@"),
- kSCNetworkIdentificationStoreKey);
- }
- CFRelease(dict);
- CFRelease(id_list);
- CFRelease(serviceID_list);
- if (order.service_order != NULL) {
- CFRelease(order.service_order);
- }
- if (store_dict != NULL) {
- CFRelease(store_dict);
- }
- }
- return (updated);
-}
-
-static CFDictionaryRef
-signature_dict_create(CFStringRef this_sig, CFDictionaryRef service)
-{
- CFDictionaryRef dict;
- const void * keys[4];
- const void * values[4];
-
- keys[0] = kSignature;
- values[0] = this_sig;
-
- keys[1] = kServices;
- values[1] = CFArrayCreate(NULL, (const void * *)&service, 1,
- &kCFTypeArrayCallBacks);
- keys[2] = kIdentifier;
- values[2] = this_sig;
-
- keys[3] = kTimestamp;
- values[3] = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
-
- dict = CFDictionaryCreate(NULL, keys, values,
- sizeof(keys) / sizeof(keys[0]),
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFRelease(values[1]);
- CFRelease(values[3]);
- return (dict);
-}
-
-static void
-ServiceWatcherRemoveStaleSignatures(ServiceWatcherRef watcher)
-{
- int active_count = 0;
- int count;
- int i;
- int remove_count;
-
- count = CFArrayGetCount(watcher->signatures);
- if (watcher->active_signatures != NULL) {
- active_count = CFArrayGetCount(watcher->active_signatures);
- }
- if ((count - active_count) <= SIGNATURE_HISTORY_MAX) {
- return;
- }
- remove_count = count - active_count - SIGNATURE_HISTORY_MAX;
- for (i = count - 1; i >= 0 && remove_count > 0; i--) {
- CFDictionaryRef sig_dict;
- CFStringRef sig_str;
-
- sig_dict = CFArrayGetValueAtIndex(watcher->signatures, i);
- sig_str = CFDictionaryGetValue(sig_dict, kSignature);
-
- if (myCFDictionaryArrayGetValue(watcher->active_signatures,
- kSignature, sig_str, NULL)
- != NULL) {
- /* skip anything that's currently active */
- SCLog(S_NetworkIdentification_debug,
- LOG_NOTICE, CFSTR("Skipping %@"), sig_dict);
- }
- else {
- SCLog(S_NetworkIdentification_debug,
- LOG_NOTICE, CFSTR("ServiceWatcher: Removing %@"),
- sig_dict);
- CFArrayRemoveValueAtIndex(watcher->signatures, i);
- remove_count--;
- }
- }
- return;
-}
-
-static void
-ServiceWatcherSaveSignatures(ServiceWatcherRef watcher)
-{
- SCPreferencesRef prefs;
-
- prefs = SCPreferencesCreate(NULL, CFSTR("ServiceWatcher"),
- kSCNetworkIdentificationPrefsKey);
- if (prefs == NULL) {
- SCLog(TRUE, LOG_NOTICE, CFSTR("ServiceWatcherSaveSignatures: Create failed %s"),
- SCErrorString(SCError()));
- return;
- }
- ServiceWatcherRemoveStaleSignatures(watcher);
- if (SCPreferencesSetValue(prefs, kSignatures, watcher->signatures)
- == FALSE) {
- SCLog(TRUE, LOG_NOTICE, CFSTR("ServiceWatcherSaveSignatures: Set failed %s"),
- SCErrorString(SCError()));
- }
- else if (SCPreferencesCommitChanges(prefs) == FALSE) {
- // An EROFS error is expected during installation. All other
- // errors should be reported.
- if (SCError() != EROFS) {
- SCLog(TRUE, LOG_NOTICE, CFSTR("ServiceWatcherSaveSignatures: Commit failed %s"),
- SCErrorString(SCError()));
- }
- }
- CFRelease(prefs);
- return;
-
-}
-
-static void
-ServiceWatcherLoadSignatures(ServiceWatcherRef watcher)
-{
- int count;
- int i;
- SCPreferencesRef prefs;
- CFArrayRef signatures;
-
- watcher->signatures
- = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- prefs = SCPreferencesCreate(NULL, CFSTR("ServiceWatcher"),
- kSCNetworkIdentificationPrefsKey);
- if (prefs == NULL) {
- SCLog(TRUE, LOG_NOTICE, CFSTR("ServiceWatcherLoadSignatures: Create failed %s"),
- SCErrorString(SCError()));
- return;
- }
- signatures = SCPreferencesGetValue(prefs, kSignatures);
- if (signatures == NULL) {
- goto done;
- }
- if (isA_CFArray(signatures) == NULL) {
- SCLog(TRUE, LOG_NOTICE,
- CFSTR("ServiceWatcherLoadSignatures: Signatures is not an array"));
- goto done;
- }
- count = CFArrayGetCount(signatures);
- for (i = 0; i < count; i++) {
- CFDictionaryRef dict;
- CFArrayRef services;
- CFStringRef sig_id;
- CFStringRef sig_str;
- CFDateRef timestamp;
-
- dict = CFArrayGetValueAtIndex(signatures, i);
- if (isA_CFDictionary(dict) == NULL) {
- continue;
- }
- sig_id = CFDictionaryGetValue(dict, kIdentifier);
- if (isA_CFString(sig_id) == NULL) {
- continue;
- }
- sig_str = CFDictionaryGetValue(dict, kSignature);
- if (isA_CFString(sig_str) == NULL) {
- continue;
- }
- timestamp = CFDictionaryGetValue(dict, kTimestamp);
- if (isA_CFDate(timestamp) == NULL) {
- continue;
- }
- services = CFDictionaryGetValue(dict, kServices);
- if (isA_CFArray(services) == NULL) {
- continue;
- }
- CFArrayAppendValue(watcher->signatures, dict);
- }
-
- done:
- CFRelease(prefs);
- return;
-
-}
-
-static void
-ServiceWatcherUpdate(ServiceWatcherRef watcher, Boolean update_signatures)
-{
- CFMutableArrayRef active_signatures = NULL;
- int count;
- int i;
- Boolean save_signatures = FALSE;
- CFArrayRef service_list;
- Boolean update_store = FALSE;
-
- service_list = ServiceWatcherCopyCurrent(watcher);
- SCLog(S_NetworkIdentification_debug,
- LOG_NOTICE, CFSTR("service_list = %@"), service_list);
- if (service_list == NULL) {
- goto done;
- }
- active_signatures = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- count = CFArrayGetCount(service_list);
- for (i = 0; i < count; i++) {
- CFDictionaryRef dict;
- CFDictionaryRef active_dict;
- CFArrayRef id_list;
- CFMutableDictionaryRef new_active_dict;
- CFDictionaryRef new_sig_dict;
- CFStringRef serviceID;
- CFStringRef sig_id;
- CFDictionaryRef service;
- CFDictionaryRef sig_dict;
- CFStringRef this_sig;
- int where;
-
- dict = CFArrayGetValueAtIndex(service_list, i);
- service = CFDictionaryGetValue(dict, kService);
- this_sig = CFDictionaryGetValue(dict, kSignature);
- if (this_sig == NULL) {
- /* service has no signature */
- continue;
- }
- sig_dict = myCFDictionaryArrayGetValue(watcher->signatures, kSignature,
- this_sig, &where);
- if (sig_dict == NULL) {
- /* add a new signature entry */
- sig_dict = signature_dict_create(this_sig, service);
- CFArrayInsertValueAtIndex(watcher->signatures, 0, sig_dict);
- CFRelease(sig_dict);
- save_signatures = TRUE;
- sig_id = CFDictionaryGetValue(sig_dict, kIdentifier);
- active_dict = NULL;
- }
- else {
- /* update an existing signature entry */
-
- sig_id = CFDictionaryGetValue(sig_dict, kIdentifier);
- new_sig_dict = signature_add_service(sig_dict, service,
- service_list);
- if (new_sig_dict != NULL) {
- CFArrayRemoveValueAtIndex(watcher->signatures, where);
- CFArrayInsertValueAtIndex(watcher->signatures, 0,
- new_sig_dict);
- CFRelease(new_sig_dict);
- save_signatures = TRUE;
- }
- active_dict
- = myCFDictionaryArrayGetValue(active_signatures,
- kSignature, this_sig,
- &where);
- }
- if (active_dict == NULL) {
- /* signature now active, this is the first/only service */
- new_active_dict
- = CFDictionaryCreateMutable(NULL, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFDictionarySetValue(new_active_dict, kSignature, this_sig);
- CFDictionarySetValue(new_active_dict, kIdentifier, sig_id);
- serviceID = CFDictionaryGetValue(service, kServiceID);
- id_list = CFArrayCreate(NULL, (const void * *)&serviceID, 1,
- &kCFTypeArrayCallBacks);
- CFDictionarySetValue(new_active_dict, kServiceIdentifiers,
- id_list);
- CFArrayAppendValue(active_signatures, new_active_dict);
- CFRelease(new_active_dict);
- CFRelease(id_list);
- }
- else {
- /* signature already active, add this serviceID */
- CFRange range;
-
- id_list = CFDictionaryGetValue(active_dict,
- kServiceIdentifiers);
- range = CFRangeMake(0, CFArrayGetCount(id_list));
- serviceID = CFDictionaryGetValue(service, kServiceID);
- if (CFArrayContainsValue(id_list, range, serviceID) == FALSE) {
- CFMutableDictionaryRef new_active_dict;
- CFMutableArrayRef new_id_list;
-
- new_id_list = CFArrayCreateMutableCopy(NULL, 0, id_list);
- CFArrayAppendValue(new_id_list, serviceID);
- new_active_dict
- = CFDictionaryCreateMutableCopy(NULL, 0, active_dict);
- CFDictionarySetValue(new_active_dict, kServiceIdentifiers,
- new_id_list);
- CFArraySetValueAtIndex(active_signatures, where,
- new_active_dict);
- CFRelease(new_active_dict);
- CFRelease(new_id_list);
- }
- }
- }
- done:
- if (active_signatures == NULL
- || CFArrayGetCount(active_signatures) == 0) {
- update_store
- = ServiceWatcherSetActiveSignatures(watcher, NULL);
- }
- else {
- update_store
- = ServiceWatcherSetActiveSignatures(watcher, active_signatures);
- }
- if (save_signatures) {
- /* write out the file */
- ServiceWatcherSaveSignatures(watcher);
- }
-
- if (service_list != NULL) {
- CFRelease(service_list);
- }
- if (active_signatures != NULL) {
- CFRelease(active_signatures);
- }
- if (update_signatures || update_store) {
- if (ServiceWatcherPublishActiveIdentifiers(watcher)) {
- notify_post(kSCNetworkSignatureActiveChangedNotifyName);
- }
- }
- return;
-}
-
-static Boolean
-update_primary_ipv4(ServiceWatcherRef watcher)
-{
- Boolean changed = FALSE;
- CFDictionaryRef global_ipv4;
-
- global_ipv4 = SCDynamicStoreCopyValue(watcher->store,
- watcher->state_ipv4_key);
- if (isA_CFDictionary(global_ipv4) != NULL) {
- CFStringRef primary_ipv4;
-
- primary_ipv4
- = CFDictionaryGetValue(global_ipv4,
- kSCDynamicStorePropNetPrimaryService);
- changed = ServiceWatcherSetPrimaryIPv4(watcher,
- isA_CFString(primary_ipv4));
- }
- if (global_ipv4 != NULL) {
- CFRelease(global_ipv4);
- }
- return (changed);
-}
-
-static void
-ServiceWatcherNotifier(SCDynamicStoreRef not_used, CFArrayRef changes,
- void * info)
-{
- int count;
- int i;
- Boolean order_changed = FALSE;
- Boolean global_ipv4_changed = FALSE;
- Boolean primary_ipv4_changed = FALSE;
- ServiceWatcherRef watcher = (ServiceWatcherRef)info;
-
- count = CFArrayGetCount(changes);
- if (count == 0) {
- return;
- }
- for (i = 0; i < count; i++) {
- CFStringRef key = CFArrayGetValueAtIndex(changes, i);
-
- if (CFStringHasPrefix(key, kSCDynamicStoreDomainSetup)) {
- order_changed = TRUE;
- }
- else if (CFEqual(key, watcher->state_ipv4_key)) {
- global_ipv4_changed = TRUE;
- }
- }
- if (global_ipv4_changed) {
- primary_ipv4_changed = update_primary_ipv4(watcher);
- }
- if (count == 1
- && (order_changed || primary_ipv4_changed)) {
- /* just the service order or the primary service changed */
- if (ServiceWatcherPublishActiveIdentifiers(watcher)) {
- notify_post(kSCNetworkSignatureActiveChangedNotifyName);
- }
- }
- else {
- ServiceWatcherUpdate(watcher, order_changed || primary_ipv4_changed);
- }
- return;
-}
-
-static ServiceWatcherRef
-ServiceWatcherCreate()
-{
- SCDynamicStoreContext context = { 0, 0, 0, 0, 0};
- CFArrayRef patterns;
- CFStringRef keys[2];
- CFArrayRef key_list;
- ServiceWatcherRef watcher;
-
- watcher = malloc(sizeof(*watcher));
- bzero(watcher, sizeof(*watcher));
- context.info = watcher;
- watcher->store = SCDynamicStoreCreate(NULL, CFSTR("Service Watcher"),
- ServiceWatcherNotifier, &context);
- if (watcher->store == NULL) {
- SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreCreate failed: %s"),
- SCErrorString(SCError()));
- goto failed;
- }
- watcher->setup_ipv4_key
- = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
- kSCDynamicStoreDomainSetup,
- kSCEntNetIPv4);
- watcher->state_ipv4_key
- = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
- kSCDynamicStoreDomainState,
- kSCEntNetIPv4);
- keys[0] = watcher->setup_ipv4_key;
- keys[1] = watcher->state_ipv4_key;
- key_list = CFArrayCreate(NULL, (const void * *)keys, sizeof(keys) / sizeof(keys[0]),
- &kCFTypeArrayCallBacks);
- patterns = ServiceWatcherNotificationPatterns();
- (void)SCDynamicStoreSetNotificationKeys(watcher->store, key_list, patterns);
- CFRelease(patterns);
- CFRelease(key_list);
- watcher->rls = SCDynamicStoreCreateRunLoopSource(NULL, watcher->store, 0);
- CFRunLoopAddSource(CFRunLoopGetCurrent(), watcher->rls,
- kCFRunLoopDefaultMode);
- ServiceWatcherLoadSignatures(watcher);
- update_primary_ipv4(watcher);
- return (watcher);
- failed:
- ServiceWatcherFree(&watcher);
- return (NULL);
-}
-
-void
-ServiceWatcherFree(ServiceWatcherRef * watcher_p)
-{
- ServiceWatcherRef watcher;
-
- if (watcher_p == NULL) {
- return;
- }
- watcher = *watcher_p;
- if (watcher == NULL) {
- return;
- }
- *watcher_p = NULL;
- if (watcher->store != NULL) {
- CFRelease(watcher->store);
- watcher->store = NULL;
- }
- if (watcher->rls != NULL) {
- CFRunLoopSourceInvalidate(watcher->rls);
- CFRelease(watcher->rls);
- watcher->rls = NULL;
- }
- if (watcher->signatures != NULL) {
- CFRelease(watcher->signatures);
- watcher->signatures = NULL;
- }
- if (watcher->state_ipv4_key != NULL) {
- CFRelease(watcher->state_ipv4_key);
- watcher->state_ipv4_key = NULL;
- }
- if (watcher->setup_ipv4_key != NULL) {
- CFRelease(watcher->setup_ipv4_key);
- watcher->setup_ipv4_key = NULL;
- }
- free(watcher);
- return;
-}
-
-/* global service watcher instance */
-static ServiceWatcherRef S_watcher;
-
-__private_extern__
-void
-prime_NetworkIdentification()
-{
- if (S_NetworkIdentification_disabled) {
- return;
- }
- S_watcher = ServiceWatcherCreate();
- ServiceWatcherUpdate(S_watcher, TRUE);
-}
-
-__private_extern__
-void
-load_NetworkIdentification(CFBundleRef bundle, Boolean bundleVerbose)
-{
- if (bundleVerbose) {
- S_NetworkIdentification_debug = 1;
- }
- return;
-}
-
-#ifdef TEST_NETWORKIDENTIFICATION
-#undef TEST_NETWORKIDENTIFICATION
-
-int
-main(int argc, char **argv)
-{
- _sc_log = FALSE;
- _sc_verbose = (argc > 1) ? TRUE : FALSE;
-
- load_NetworkIdentification(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
- prime_NetworkIdentification();
- CFRunLoopRun();
- /* not reached */
- exit(0);
- return 0;
-}
-#endif
-
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.11.3</string>
+ <string>1.12</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.11</string>
+ <string>1.12</string>
<key>Builtin</key>
<true/>
<key>Requires</key>
/*
- * Copyright (c) 2000-2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008, 2010, 2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
{
CFBundleRef bundle;
SCNetworkSetRef current = NULL;
+ CFStringRef new_model;
Boolean ok = FALSE;
int sc_status = kSCStatusFailed;
SCNetworkSetRef set = NULL;
}
}
+ /* Ensure that the preferences has the new model */
+ new_model = _SC_hw_model();
+
+ /* Need to regenerate the new configuration for new model */
+ if (new_model != NULL) {
+ CFStringRef old_model;
+
+ old_model = SCPreferencesGetValue(prefs, MODEL);
+ if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) {
+ CFIndex count;
+ CFIndex index;
+ CFArrayRef keys;
+
+ keys = SCPreferencesCopyKeyList(prefs);
+ count = (keys != NULL) ? CFArrayGetCount(keys) : 0;
+ // if new hardware
+ for (index = 0; index < count; index++) {
+ CFStringRef existing_key;
+
+ existing_key = CFArrayGetValueAtIndex(keys, index);
+
+ if (isA_CFString(existing_key) != NULL) {
+ CFStringRef new_key;
+ CFPropertyListRef value;
+
+ /* If it already contains a Model
+ or if it already contains a MODEL:KEY key skip it*/
+ if (CFEqual(existing_key, MODEL)
+ || CFStringFind(existing_key, CFSTR(":"), 0).location
+ != kCFNotFound) {
+ continue;
+ }
+
+ value = SCPreferencesGetValue(prefs, existing_key);
+
+ /* Create a new key as OLD_MODEL:OLD_KEY */
+ new_key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"),
+ old_model, existing_key);
+ SCPreferencesSetValue(prefs, new_key, value);
+ SCPreferencesRemoveValue(prefs, existing_key);
+ CFRelease(new_key);
+ }
+ }
+
+ if (keys != NULL) {
+ CFRelease(keys);
+ }
+ }
+
+ /* Set the new model */
+ SCPreferencesSetValue(prefs, MODEL, new_model);
+ }
+
current = SCNetworkSetCopyCurrent(prefs);
if (current != NULL) {
set = current;
}
/* Update the dynamic store */
+#ifndef MAIN
if (!SCDynamicStoreSetMultiple(store, newPrefs, removedPrefsKeys, NULL)) {
SCLog(TRUE, LOG_ERR,
CFSTR("SCDynamicStoreSetMultiple() failed: %s"),
SCErrorString(SCError()));
}
+#else // !MAIN
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR("SCDynamicStore\nset: %@\nremove: %@\n"),
+ newPrefs,
+ removedPrefsKeys);
+#endif // !MAIN
CFRelease(currentPrefs);
CFRelease(newPrefs);
}
/* open a SCPreferences session */
+#ifndef MAIN
prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), NULL);
+#else // !MAIN
+ prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), CFSTR("/tmp/preferences.plist"));
+#endif // !MAIN
if (prefs != NULL) {
- SCNetworkSetRef current;
+ Boolean need_update = FALSE;
+ CFStringRef new_model;
- current = SCNetworkSetCopyCurrent(prefs);
- if (current != NULL) {
- /* network configuration available, disable template creation */
- initPrefs = FALSE;
- CFRelease(current);
+ new_model = _SC_hw_model();
+
+ /* Need to regenerate the new configuration for new model */
+ if (new_model != NULL) {
+ CFStringRef old_model;
+
+ old_model = SCPreferencesGetValue(prefs, MODEL);
+ if (old_model != NULL && !_SC_CFEqual(old_model, new_model)) {
+ // if new hardware
+ need_update = TRUE;
+ }
+ }
+
+ if (need_update == FALSE) {
+ SCNetworkSetRef current;
+
+ current = SCNetworkSetCopyCurrent(prefs);
+ if (current != NULL) {
+ /* network configuration available, disable template creation */
+ initPrefs = FALSE;
+ CFRelease(current);
+ }
}
} else {
SCLog(TRUE, LOG_ERR,
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Builtin</key>
+ <true/>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>SCNetworkReachability</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.SystemConfiguration.SCNetworkReachability</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>com.apple.SystemConfiguration.SCNetworkReachability</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.12</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.12</string>
+</dict>
+</plist>
--- /dev/null
+ARCHS = -arch i386 -arch x86_64
+CFLAGS = -Wall -pipe -O0 -gdwarf-2
+
+REACH_SERVER_C = ../../SystemConfiguration.fproj/reachability/SCNetworkReachabilityServer_server.c
+
+REACH_SERVER_PLIST = /Library/LaunchDaemons/com.apple.SCNetworkReachability.plist
+SYMROOT = ${shell basename ${shell dirname ${shell dirname ${PWD}}}}
+
+all: /var/tmp/reach_server ${REACH_SERVER_PLIST}
+
+${REACH_SERVER_PLIST}: Makefile
+ @sudo mkdir -p ${shell dirname ${REACH_SERVER_PLIST}}
+ @sudo launchctl unload -w ${REACH_SERVER_PLIST} > /dev/null 2>&1 || /usr/bin/true
+ @sudo rm -f ${REACH_SERVER_PLIST}
+ @sudo defaults write ${REACH_SERVER_PLIST} Label \
+ SCNetworkReachability-DEBUG
+ @sudo defaults write ${REACH_SERVER_PLIST} MachServices \
+ -dict \
+ SCNetworkReachability-DEBUG \
+ -bool TRUE
+ @sudo defaults write ${REACH_SERVER_PLIST} Program \
+ /var/tmp/reach_server
+ @sudo defaults write ${REACH_SERVER_PLIST} ProgramArguments \
+ -array \
+ SCNetworkReachability-DEBUG \
+ verbose
+ @sudo defaults write ${REACH_SERVER_PLIST} EnvironmentVariables \
+ -dict \
+ DYLD_FRAMEWORK_PATH \
+ ${BUILDIT_DIR}/${SYMROOT}.roots/${SYMROOT}~sym \
+ REACH_SERVER \
+ SCNetworkReachability-DEBUG
+ @sudo defaults write ${REACH_SERVER_PLIST} ThrottleInterval \
+ -int 5
+ @sudo chown root:wheel ${REACH_SERVER_PLIST}
+ @sudo chmod 644 ${REACH_SERVER_PLIST}
+ sudo launchctl load -w ${REACH_SERVER_PLIST}
+
+reach_server.o: ${REACH_SERVER_C}
+ cc ${ARCHS} ${CFLAGS} -DMAIN -I ../../SystemConfiguration.fproj -F ${BUILDIT_DIR}/${SYMROOT}.roots/${SYMROOT}~sym -c -o reach_server.o ${REACH_SERVER_C}
+
+reach_server: reach_server.o
+ cc ${ARCHS} -o reach_server reach_server.o -framework CoreFoundation -F ${BUILDIT_DIR}/${SYMROOT}.roots/${SYMROOT}~sym -framework SystemConfiguration
+ dsymutil reach_server -o reach_server.dSYM
+
+/var/tmp/reach_server: reach_server
+ @sudo rm -f /var/tmp/reach_server
+ cp -p reach_server /var/tmp/reach_server
+ @sudo chown root:wheel /var/tmp/reach_server
+ @sudo chmod 755 /var/tmp/reach_server
+
+clean:
+ sudo launchctl unload -w ${REACH_SERVER_PLIST} > /dev/null 2>&1 || /usr/bin/true
+ @sudo rm -f ${REACH_SERVER_PLIST}
+ @sudo rm -rf /var/tmp/reach_server
+ rm -rf *.o reach_server reach_server.dSYM
/*
- * Copyright (c) 2003, 2004, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2003, 2004, 2006, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFRangeMake(0, CFArrayGetCount(cached_removals)),
key)) {
// if we have "removed" the key
+ _SCErrorSet(kSCStatusNoKey);
return NULL;
}
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.11.3</string>
+ <string>1.12</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.11</string>
+ <string>1.12</string>
<key>CFPlugInDynamicRegistration</key>
<string>NO</string>
<key>CFPlugInFactories</key>
/*
- * Copyright (c) 2007-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* "Configure" Automatically configure this interface without any
* intervention.
*
- * Note: automatic configuration may require authorization if the logged
- * in user is NOT "root" (eUID==0) or if the "system.preferences"
- * administrator right is not currently available.
+ * Note: automatic configuration may not be possible if the logged in user
+ * is NOT "root" (eUID==0) or if the authorization right that governs
+ * SCHelper write operations (kSCPreferencesWriteAuthorizationRight)
+ * is not currently available.
*
* An [older] "User Intervention" key is also supported. That CFBoolean
* key, if present and TRUE, implies "Configure" configuration of the
AuthorizationRights rights;
OSStatus status;
- items[0].name = "system.preferences";
+ items[0].name = kSCPreferencesWriteAuthorizationRight;
items[0].value = NULL;
items[0].valueLength = 0;
items[0].flags = 0;
}
CFArrayAppendValue(myInstance->interfaces_configure, interface);
} else if (hasAuthorization(myInstance)) {
- // if we already have the "admin" (system.preferences) right, configure automatically (without user intervention)
+ // if we already have the "admin" (kSCPreferencesWriteAuthorizationRight)
+ // right, configure automatically (without user intervention)
if (myInstance->interfaces_configure == NULL) {
myInstance->interfaces_configure = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
MyType *myInstance;
MyNode *myNode;
- myNode = (MyNode *)CFDataGetBytePtr(myData);
+ /* ALIGN: CF aligns to at least >8 bytes */
+ myNode = (MyNode *)(void *)CFDataGetBytePtr(myData);
myInstance = myNode->myInstance;
switch (messageType) {
// wait for initialization to complete
myData = CFDataCreateMutable(NULL, sizeof(MyNode));
CFDataSetLength(myData, sizeof(MyNode));
- myNode = (MyNode *)CFDataGetBytePtr(myData);
+
+ /* ALIGN: CF aligns to at least >8 bytes */
+ myNode = (MyNode *)(void *)CFDataGetBytePtr(myData);
+
bzero(myNode, sizeof(MyNode));
if (interface != MACH_PORT_NULL) {
IOObjectRetain(interface);
MyNode *myNode;
myData = CFArrayGetValueAtIndex(myInstance->notifyNodes, i);
- myNode = (MyNode *)CFDataGetBytePtr(myData);
+
+ /* ALIGN: CF aligns to at least >8 bytes */
+ myNode = (MyNode *)(void *)CFDataGetBytePtr(myData);
+
if (myNode->interface != MACH_PORT_NULL) {
IOObjectRelease(myNode->interface);
}
available = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
excluded = CFSetCreateMutable (NULL, 0, &kCFTypeSetCallBacks);
+#if !TARGET_OS_IPHONE
// exclude Bond [member] interfaces
interfaces = SCBondInterfaceCopyAll(prefs);
if (interfaces != NULL) {
__SCBondInterfaceListCollectMembers(interfaces, excluded);
CFRelease(interfaces);
}
+#endif // !TARGET_OS_IPHONE
// exclude Bridge [member] interfaces
interfaces = SCBridgeInterfaceCopyAll(prefs);
#pragma mark -
#pragma mark CaptiveNetwork.framework APIs (exported through the SystemConfiguration.framework)
+
+#if TARGET_OS_EMBEDDED
const CFStringRef kCNNetworkInfoKeySSIDData = CFSTR("SSIDDATA");
const CFStringRef kCNNetworkInfoKeySSID = CFSTR("SSID");
const CFStringRef kCNNetworkInfoKeyBSSID = CFSTR("BSSID");
+#endif // TARGET_OS_EMBEDDED
+
static void *
__loadCaptiveNetwork(void) {
return dyfunc ? dyfunc() : NULL;
}
+
+#if TARGET_OS_EMBEDDED
CFDictionaryRef
CNCopyCurrentNetworkInfo(CFStringRef interfaceName)
{
}
return dyfunc ? dyfunc(interfaceName) : NULL;
}
+#endif // TARGET_OS_EMBEDDED
/*
- * Copyright (c) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
@function CNSetSupportedSSIDs
@discussion Provides Captive Network Support with an updated list of
SSIDs that this application will perform authentication on.
- When Captive Network Support would show the Web Sheet for a
- network with an SSID the application has registered for, it
- will suppress showing the Web Sheet if the application is
- still installed.
+
+ Captive Network Support suppresses showing the Web Sheet
+ for a captive Wi-Fi network if that network's SSID is in the
+ specified list.
+
+ On iOS, the registrations persist until the application is
+ removed from the device.
+
+ On MacOSX, the registrations persist as long as the application
+ is running.
+
@param ssidArray A CFArray of CFStrings of the SSIDs.
@result Returns TRUE if the operation succeeded, FALSE otherwise.
*/
Boolean
-CNSetSupportedSSIDs (CFArrayRef ssidArray) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_0);
+CNSetSupportedSSIDs (CFArrayRef ssidArray) __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_4_0);
/*!
@function CNMarkPortalOnline
@result Returns TRUE if the operation succeeded, FALSE otherwise.
*/
Boolean
-CNMarkPortalOnline (CFStringRef interfaceName) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_0);
+CNMarkPortalOnline (CFStringRef interfaceName) __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_4_0);
/*!
@function CNMarkPortalOffline
@result Returns TRUE if the operation succeeded, FALSE otherwise.
*/
Boolean
-CNMarkPortalOffline (CFStringRef interfaceName) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_0);
+CNMarkPortalOffline (CFStringRef interfaceName) __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_4_0);
/*!
You MUST release the returned value.
*/
CFArrayRef
-CNCopySupportedInterfaces (void) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_1);
+CNCopySupportedInterfaces (void) __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_4_1);
+
+#if TARGET_OS_EMBEDDED
/*!
@constant kCNNetworkInfoKeySSIDData
CFDictionaryRef
CNCopyCurrentNetworkInfo (CFStringRef interfaceName) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_4_1);
+#endif // TARGET_OS_EMBEDDED
+
__END_DECLS
#endif /* _CAPTIVENETWORK_H */
/*
- * Copyright (c) 2001, 2003-2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2001, 2003-2005, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
return;
}
-static __inline__ CFStringRef
+static __inline__ CF_RETURNS_RETAINED CFStringRef
S_application_path(CFStringRef applicationID)
{
return (CFStringCreateWithFormat(NULL, NULL,
{
CFDictionaryRef dhcp_dict = NULL;
CFStringRef key = NULL;
- boolean_t needs_close = FALSE;
CFDictionaryRef primary_dict = NULL;
- if (store == NULL) {
- needs_close = TRUE;
- store = SCDynamicStoreCreate(NULL,
- CFSTR("SCDynamicStoreCopyDHCPInfo"),
- NULL, NULL);
- if (store == NULL) {
- goto done;
- }
- }
-
if (serviceID == NULL) {
/* get the primary service name */
key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
if (primary_dict) {
CFRelease(primary_dict);
}
- if (needs_close == TRUE && store != NULL) {
- CFRelease(store);
- }
return (dhcp_dict);
}
return (CFDictionaryGetValue(dhcp_dict, CFSTR("LeaseStartTime")));
}
+CFDateRef
+DHCPInfoGetLeaseExpirationTime(CFDictionaryRef dhcp_dict)
+{
+ return (CFDictionaryGetValue(dhcp_dict, CFSTR("LeaseExpirationTime")));
+}
+
#ifdef TEST_DHCPCLIENT_PREFERENCES
void
print_data(u_char * data_p, int n_bytes)
exit(0);
return(0);
}
-#endif TEST_DHCPCLIENT_PREFERENCES
+#endif // TEST_DHCPCLIENT_PREFERENCES
<key>CFBundleExecutable</key>
<string>SystemConfiguration</string>
<key>CFBundleGetInfoString</key>
- <string>1.11</string>
+ <string>1.12</string>
<key>CFBundleIdentifier</key>
<string>com.apple.SystemConfiguration</string>
<key>CFBundleInfoDictionaryVersion</key>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
- <string>1.11.3</string>
+ <string>1.12</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.11</string>
+ <string>1.12</string>
</dict>
</plist>
<key>CFBundleExecutable</key>
<string>SystemConfiguration</string>
<key>CFBundleGetInfoString</key>
- <string>1.11</string>
+ <string>1.12</string>
<key>CFBundleIdentifier</key>
<string>com.apple.SystemConfiguration</string>
<key>CFBundleInfoDictionaryVersion</key>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
- <string>1.11.3</string>
+ <string>1.12</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.11</string>
+ <string>1.12</string>
</dict>
</plist>
/*
- * Copyright (c) 2000-2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008, 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
+#include "SCD.h"
#include "SCDynamicStoreInternal.h"
#include "config.h" /* MiG generated file */
#pragma mark Thread specific data
-typedef struct {
- aslclient _asl;
- int _sc_error;
-} __SCThreadSpecificData, *__SCThreadSpecificDataRef;
-
-
static pthread_once_t tsKeyInitialized = PTHREAD_ONCE_INIT;
static pthread_key_t tsDataKey;
__SCThreadSpecificDataRef tsd = (__SCThreadSpecificDataRef)arg;
if (tsd != NULL) {
- if (tsd->_asl != NULL) asl_close(tsd->_asl);
+ if (tsd->_asl != NULL) asl_close(tsd->_asl);
+ if (tsd->_sc_store != NULL) CFRelease(tsd->_sc_store);
CFAllocatorDeallocate(kCFAllocatorSystemDefault, tsd);
}
return;
}
-static __SCThreadSpecificDataRef
+__private_extern__
+__SCThreadSpecificDataRef
__SCGetThreadSpecificData()
{
__SCThreadSpecificDataRef tsd;
tsd = pthread_getspecific(tsDataKey);
if (tsd == NULL) {
tsd = CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(__SCThreadSpecificData), 0);
- tsd->_asl = asl_open(NULL, NULL, 0);
- asl_set_filter(tsd->_asl, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
+ tsd->_asl = NULL;
tsd->_sc_error = kSCStatusOK;
+ tsd->_sc_store = NULL;
pthread_setspecific(tsDataKey, tsd);
}
__SCThreadSpecificDataRef tsd;
tsd = __SCGetThreadSpecificData();
+ if (tsd->_asl == NULL) {
+ tsd->_asl = asl_open(NULL, NULL, 0);
+ asl_set_filter(tsd->_asl, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
+ }
asl = tsd->_asl;
}
--- /dev/null
+/*
+ * Copyright (c) 2011 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,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * 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@
+ */
+
+#ifndef _SCD_H
+#define _SCD_H
+
+#include <Availability.h>
+#include <TargetConditionals.h>
+#include <sys/cdefs.h>
+#include <asl.h>
+#include <SystemConfiguration/SCDynamicStore.h>
+
+
+typedef struct {
+ aslclient _asl;
+ int _sc_error;
+ SCDynamicStoreRef _sc_store;
+} __SCThreadSpecificData, *__SCThreadSpecificDataRef;
+
+
+
+__BEGIN_DECLS
+
+__SCThreadSpecificDataRef
+__SCGetThreadSpecificData (void);
+
+__END_DECLS
+
+#endif /* _SCD_H */
/*
- * Copyright (c) 2000-2005, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
&newInstance,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreAddTemporaryValue configadd_s(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreAddTemporaryValue configadd_s()")) {
+ goto retry;
}
/* clean up */
Boolean
SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ SCDynamicStorePrivateRef storePrivate;
kern_return_t status;
CFDataRef utfKey; /* serialized key */
xmlData_t myKeyRef;
int sc_status;
if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
+ store = __SCDynamicStoreNullSession();
+ if (store == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoStoreSession);
+ return FALSE;
+ }
}
+ storePrivate = (SCDynamicStorePrivateRef)store;
if (storePrivate->server == MACH_PORT_NULL) {
/* sorry, you must have an open session to play */
_SCErrorSet(kSCStatusNoStoreServer);
&newInstance,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreAddValue configadd(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreAddValue configadd()")) {
+ goto retry;
}
/* clean up */
/*
- * Copyright (c) 2000-2005, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFStringRef consoleUser = NULL;
CFDictionaryRef dict = NULL;
CFStringRef key;
- Boolean tempSession = FALSE;
-
- if (store == NULL) {
- store = SCDynamicStoreCreate(NULL,
- CFSTR("SCDynamicStoreCopyConsoleUser"),
- NULL,
- NULL);
- if (store == NULL) {
- return NULL;
- }
- tempSession = TRUE;
- }
key = SCDynamicStoreKeyCreateConsoleUser(NULL);
dict = SCDynamicStoreCopyValue(store, key);
done :
- if (tempSession) CFRelease(store);
if (dict) CFRelease(dict);
return consoleUser;
}
CFDictionaryRef dict = NULL;
CFArrayRef info = NULL;
CFStringRef key;
- Boolean tempSession = FALSE;
-
- if (store == NULL) {
- store = SCDynamicStoreCreate(NULL,
- CFSTR("SCDynamicStoreCopyConsoleUser"),
- NULL,
- NULL);
- if (store == NULL) {
- return NULL;
- }
- tempSession = TRUE;
- }
key = SCDynamicStoreKeyCreateConsoleUser(NULL);
dict = SCDynamicStoreCopyValue(store, key);
done :
- if (tempSession) CFRelease(store);
if (dict) CFRelease(dict);
return info;
}
CFMutableDictionaryRef dict = NULL;
CFStringRef key = SCDynamicStoreKeyCreateConsoleUser(NULL);
Boolean ok = FALSE;
- Boolean tempSession = FALSE;
-
- if (store == NULL) {
- store = SCDynamicStoreCreate(NULL,
- CFSTR("SCDynamicStoreSetConsoleUser"),
- NULL,
- NULL);
- if (store == NULL) {
- goto done;
- }
- tempSession = TRUE;
- }
if ((user == NULL) && (sessions == NULL)) {
ok = SCDynamicStoreRemoveValue(store, key);
if (dict) CFRelease(dict);
if (key) CFRelease(key);
- if (tempSession) CFRelease(store);
return ok;
}
CFStringRef key = SCDynamicStoreKeyCreateConsoleUser(NULL);
CFNumberRef num;
Boolean ok = FALSE;
- Boolean tempSession = FALSE;
-
- if (store == NULL) {
- store = SCDynamicStoreCreate(NULL,
- CFSTR("SCDynamicStoreSetConsoleUser"),
- NULL,
- NULL);
- if (store == NULL) {
- goto done;
- }
- tempSession = TRUE;
- }
if (user == NULL) {
ok = SCDynamicStoreRemoveValue(store, key);
if (dict) CFRelease(dict);
if (key) CFRelease(key);
- if (tempSession) CFRelease(store);
return ok;
}
/*
- * Copyright (c) 2000-2005, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFArrayRef keys,
CFArrayRef patterns)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ SCDynamicStorePrivateRef storePrivate;
kern_return_t status;
CFDataRef xmlKeys = NULL; /* keys (XML serialized) */
xmlData_t myKeysRef = NULL; /* keys (serialized) */
int sc_status;
if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return NULL;
+ store = __SCDynamicStoreNullSession();
+ if (store == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoStoreSession);
+ return NULL;
+ }
}
+ storePrivate = (SCDynamicStorePrivateRef)store;
if (storePrivate->server == MACH_PORT_NULL) {
_SCErrorSet(kSCStatusNoStoreServer);
return NULL; /* you must have an open session to play */
&xmlDictLen,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCopyMultiple configget_m(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreCopyMultiple configget_m()")) {
+ goto retry;
}
/* clean up */
CFPropertyListRef
SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ SCDynamicStorePrivateRef storePrivate;
kern_return_t status;
CFDataRef utfKey; /* key (XML serialized) */
xmlData_t myKeyRef; /* key (serialized) */
int sc_status;
if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return NULL;
+ store = __SCDynamicStoreNullSession();
+ if (store == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoStoreSession);
+ return NULL;
+ }
}
+ storePrivate = (SCDynamicStorePrivateRef)store;
if (storePrivate->server == MACH_PORT_NULL) {
_SCErrorSet(kSCStatusNoStoreServer);
return NULL; /* you must have an open session to play */
&newInstance,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCopyValue configget(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreCopyValue configget()")) {
+ goto retry;
}
/* clean up */
/*
- * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
SCDynamicStoreCopyComputerName(SCDynamicStoreRef store,
CFStringEncoding *nameEncoding)
{
- CFDictionaryRef dict;
+ CFDictionaryRef dict = NULL;
CFStringRef key;
CFStringRef name = NULL;
- Boolean tempSession = FALSE;
-
- if (store == NULL) {
- store = SCDynamicStoreCreate(NULL,
- CFSTR("SCDynamicStoreCopyComputerName"),
- NULL,
- NULL);
- if (store == NULL) {
- return NULL;
- }
- tempSession = TRUE;
- }
key = SCDynamicStoreKeyCreateComputerName(NULL);
dict = SCDynamicStoreCopyValue(store, key);
done :
- if (tempSession) CFRelease(store);
if (dict != NULL) CFRelease(dict);
return name;
}
CFStringRef
SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
{
- CFDictionaryRef dict;
+ CFDictionaryRef dict = NULL;
CFStringRef key;
CFStringRef name = NULL;
- Boolean tempSession = FALSE;
-
- if (store == NULL) {
- store = SCDynamicStoreCreate(NULL,
- CFSTR("SCDynamicStoreCopyLocalHostName"),
- NULL,
- NULL);
- if (store == NULL) {
- return NULL;
- }
- tempSession = TRUE;
- }
key = SCDynamicStoreKeyCreateHostNames(NULL);
dict = SCDynamicStoreCopyValue(store, key);
done :
- if (tempSession) CFRelease(store);
if (dict != NULL) CFRelease(dict);
return name;
}
/*
- * Copyright (c) 2000-2005, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFArrayRef
SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ SCDynamicStorePrivateRef storePrivate;
kern_return_t status;
CFDataRef utfPattern; /* serialized pattern */
xmlData_t myPatternRef;
CFArrayRef allKeys;
if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return NULL;
+ store = __SCDynamicStoreNullSession();
+ if (store == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoStoreSession);
+ return NULL;
+ }
}
+ storePrivate = (SCDynamicStorePrivateRef)store;
if (storePrivate->server == MACH_PORT_NULL) {
_SCErrorSet(kSCStatusNoStoreServer);
return NULL;
&xmlDataLen,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCopyKeyList configlist(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreCopyKeyList configlist()")) {
+ goto retry;
}
/* clean up */
+++ /dev/null
-/*
- * Copyright (c) 2000, 2001, 2004, 2005, 2009, 2010 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,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * 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@
- */
-
-/*
- * Modification History
- *
- * June 1, 2001 Allan Nathanson <ajn@apple.com>
- * - public API conversion
- *
- * March 24, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCPrivate.h>
-#include "SCDynamicStoreInternal.h"
-#include "config.h" /* MiG generated file */
-
-Boolean
-SCDynamicStoreLock(SCDynamicStoreRef store)
-{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- kern_return_t status;
- int sc_status;
-
- if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
- }
-
- if (storePrivate->server == MACH_PORT_NULL) {
- /* sorry, you must have an open session to play */
- _SCErrorSet(kSCStatusNoStoreServer);
- return FALSE;
- }
-
- retry :
-
- /* get the lock from the server */
- status = configlock(storePrivate->server, (int *)&sc_status);
-
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreLock configlock(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
- }
-
- if (sc_status != kSCStatusOK) {
- _SCErrorSet(sc_status);
- return FALSE;
- }
-
- return TRUE;
-}
/*
- * Copyright (c) 2000-2005, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
isRegex,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreAddWatchedKey notifyadd(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreAddWatchedKey notifyadd()")) {
+ goto retry;
}
/* clean up */
/*
- * Copyright (c) 2000-2005, 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
case NotifierNotRegistered :
/* if no notifications have been registered */
return TRUE;
- case Using_NotifierInformViaCallback :
- /* invalidate and release the run loop source */
- if (storePrivate->callbackRLS != NULL) {
- CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
- CFRelease(storePrivate->callbackRLS);
- storePrivate->callbackRLS = NULL;
- }
-
- /* invalidate and release the callback mach port */
- if (storePrivate->callbackPort != NULL) {
- __MACH_PORT_DEBUG(TRUE, "*** SCDynamicStoreNotifyCancel", CFMachPortGetPort(storePrivate->callbackPort));
- CFMachPortInvalidate(storePrivate->callbackPort);
- CFRelease(storePrivate->callbackPort);
- storePrivate->callbackPort = NULL;
- }
-
- storePrivate->callbackArgument = NULL;
- storePrivate->callbackFunction = NULL;
- break;
case Using_NotifierInformViaRunLoop :
CFRunLoopSourceInvalidate(storePrivate->rls);
storePrivate->rls = NULL;
}
status = notifycancel(storePrivate->server, (int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyCancel notifycancel(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if (((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED))
- && __SCDynamicStoreReconnect(store)) {
- sc_status = kSCStatusOK;
- } else {
- sc_status = status;
- }
+
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreNotifyCancel notifycancel()")) {
+ sc_status = kSCStatusOK;
}
done :
/*
- * Copyright (c) 2000, 2001, 2003-2005, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2005, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
&xmlDataLen,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCopyNotifiedKeys notifychanges(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreCopyNotifiedKeys notifychanges()")) {
+ goto retry;
}
if (sc_status != kSCStatusOK) {
/*
- * Copyright (c) 2000-2005, 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2008-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "config.h" /* MiG generated file */
-static void
-informCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
-{
- SCDynamicStoreRef store = (SCDynamicStoreRef)info;
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- mach_no_senders_notification_t *buf = msg;
- mach_msg_id_t msgid = buf->not_header.msgh_id;
- SCDynamicStoreCallBack_v1 cbFunc = storePrivate->callbackFunction;
- void *cbArg = storePrivate->callbackArgument;
-
- if (msgid == MACH_NOTIFY_NO_SENDERS) {
- /* the server died, disable additional callbacks */
-#ifdef DEBUG
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" notifier port closed, disabling notifier"));
-#endif /* DEBUG */
- } else if (cbFunc == NULL) {
- /* there is no (longer) a callback function, disable additional callbacks */
-#ifdef DEBUG
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" no callback function, disabling notifier"));
-#endif /* DEBUG */
- } else {
-#ifdef DEBUG
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" executing notification function"));
-#endif /* DEBUG */
- if ((*cbFunc)(store, cbArg)) {
- /*
- * callback function returned success.
- */
- return;
- } else {
-#ifdef DEBUG
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" callback returned error, disabling notifier"));
-#endif /* DEBUG */
- }
- }
-
-#ifdef DEBUG
- if (port != storePrivate->callbackPort) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("informCallback, why is port != callbackPort?"));
- }
-#endif /* DEBUG */
-
- /* invalidate the run loop source */
- if (storePrivate->callbackRLS != NULL) {
- CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
- CFRelease(storePrivate->callbackRLS);
- storePrivate->callbackRLS = NULL;
- }
-
- /* invalidate port */
- if (storePrivate->callbackPort != NULL) {
- __MACH_PORT_DEBUG(TRUE, "*** informCallback", CFMachPortGetPort(storePrivate->callbackPort));
- CFMachPortInvalidate(storePrivate->callbackPort);
- CFRelease(storePrivate->callbackPort);
- storePrivate->callbackPort = NULL;
- }
-
- /* disable notifier */
- storePrivate->notifyStatus = NotifierNotRegistered;
- storePrivate->callbackArgument = NULL;
- storePrivate->callbackFunction = NULL;
-
- return;
-}
-
-
static CFStringRef
notifyMPCopyDescription(const void *info)
{
}
-Boolean
-SCDynamicStoreNotifyCallback(SCDynamicStoreRef store,
- CFRunLoopRef runLoop,
- SCDynamicStoreCallBack_v1 func,
- void *arg)
-{
- CFMachPortContext context = { 0
- , (void *)store
- , CFRetain
- , CFRelease
- , notifyMPCopyDescription
- };
- mach_port_t oldNotify;
- mach_port_t port;
- int sc_status;
- kern_return_t status;
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
-
- if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
- }
-
- if (storePrivate->server == MACH_PORT_NULL) {
- /* sorry, you must have an open session to play */
- _SCErrorSet(kSCStatusNoStoreServer);
- return FALSE;
- }
-
- if (storePrivate->notifyStatus != NotifierNotRegistered) {
- /* sorry, you can only have one notification registered at once */
- _SCErrorSet(kSCStatusNotifierActive);
- return FALSE;
- }
-
- /* Allocating port (for server response) */
- status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
- if (status != KERN_SUCCESS) {
- SCLog(TRUE, LOG_ERR, CFSTR("mach_port_allocate(): %s"), mach_error_string(status));
- _SCErrorSet(status);
- return FALSE;
- }
-
- status = mach_port_insert_right(mach_task_self(),
- port,
- port,
- MACH_MSG_TYPE_MAKE_SEND);
- if (status != KERN_SUCCESS) {
- /*
- * We can't insert a send right into our own port! This should
- * only happen if someone stomped on OUR port (so let's leave
- * the port alone).
- */
- SCLog(TRUE, LOG_ERR, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status));
- _SCErrorSet(status);
- return FALSE;
- }
-
- /* Request a notification when/if the server dies */
- status = mach_port_request_notification(mach_task_self(),
- port,
- MACH_NOTIFY_NO_SENDERS,
- 1,
- port,
- MACH_MSG_TYPE_MAKE_SEND_ONCE,
- &oldNotify);
- if (status != KERN_SUCCESS) {
- /*
- * We can't request a notification for our own port! This should
- * only happen if someone stomped on OUR port (so let's leave
- * the port alone).
- */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyCallback mach_port_request_notification(): %s"), mach_error_string(status));
- _SCErrorSet(status);
- return FALSE;
- }
-
- if (oldNotify != MACH_PORT_NULL) {
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyCallback(): oldNotify != MACH_PORT_NULL"));
- }
-
- retry :
-
- /* Requesting notification via mach port */
- status = notifyviaport(storePrivate->server,
- port,
- 0,
- (int *)&sc_status);
-
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyCallback notifyviaport(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- /* remove the send right that we tried (but failed) to pass to the server */
- (void) mach_port_deallocate(mach_task_self(), port);
- }
-
- /* remove our receive right */
- (void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
- sc_status = status;
- }
-
- if (sc_status != kSCStatusOK) {
- _SCErrorSet(sc_status);
- return FALSE;
- }
-
- /* set notifier active */
- storePrivate->notifyStatus = Using_NotifierInformViaCallback;
-
- /* Creating/adding a run loop source for the port */
- __MACH_PORT_DEBUG(TRUE, "*** SCDynamicStoreNotifyCallback", port);
- storePrivate->callbackArgument = arg;
- storePrivate->callbackFunction = func;
- storePrivate->callbackPort = _SC_CFMachPortCreateWithPort("SCDynamicStoreNotifyCallback",
- port,
- informCallback,
- &context);
- storePrivate->callbackRLS = CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0);
- CFRunLoopAddSource(runLoop, storePrivate->callbackRLS, kCFRunLoopDefaultMode);
-
- return TRUE;
-}
-
-
static void
rlsCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
{
#endif /* DEBUG */
#ifdef DEBUG
- if (port != storePrivate->callbackPort) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("rlsCallback(), why is port != callbackPort?"));
+ if (port != storePrivate->rlsNotifyPort) {
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("rlsCallback(), why is port != rlsNotifyPort?"));
}
#endif /* DEBUG */
__MACH_PORT_DEBUG(TRUE, "*** rlsSchedule", port);
status = notifyviaport(storePrivate->server, port, 0, (int *)&sc_status);
+
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "rlsSchedule notifyviaport()")) {
+ goto retry;
+ }
+
if (status != KERN_SUCCESS) {
if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("rlsSchedule notifyviaport(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
/* remove the send right that we tried (but failed) to pass to the server */
(void) mach_port_deallocate(mach_task_self(), port);
}
}
__MACH_PORT_DEBUG(TRUE, "*** rlsSchedule (after notifyviaport)", port);
- storePrivate->callbackPort = _SC_CFMachPortCreateWithPort("SCDynamicStore",
- port,
- rlsCallback,
- &context);
- CFMachPortSetInvalidationCallBack(storePrivate->callbackPort, portInvalidate);
- storePrivate->callbackRLS = CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0);
+ storePrivate->rlsNotifyPort = _SC_CFMachPortCreateWithPort("SCDynamicStore",
+ port,
+ rlsCallback,
+ &context);
+ CFMachPortSetInvalidationCallBack(storePrivate->rlsNotifyPort, portInvalidate);
+ storePrivate->rlsNotifyRLS = CFMachPortCreateRunLoopSource(NULL, storePrivate->rlsNotifyPort, 0);
storePrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
- if ((rl != NULL) && (storePrivate->callbackRLS != NULL)) {
+ if ((rl != NULL) && (storePrivate->rlsNotifyRLS != NULL)) {
if (!_SC_isScheduled(store, rl, mode, storePrivate->rlList)) {
/*
* if we are not already scheduled with this runLoop / runLoopMode
*/
- CFRunLoopAddSource(rl, storePrivate->callbackRLS, mode);
- __MACH_PORT_DEBUG(TRUE, "*** rlsSchedule (after CFRunLoopAddSource)", CFMachPortGetPort(storePrivate->callbackPort));
+ CFRunLoopAddSource(rl, storePrivate->rlsNotifyRLS, mode);
+ __MACH_PORT_DEBUG(TRUE, "*** rlsSchedule (after CFRunLoopAddSource)", CFMachPortGetPort(storePrivate->rlsNotifyPort));
}
_SC_schedule(store, rl, mode, storePrivate->rlList);
(rl != NULL) ? mode : CFSTR("libdispatch"));
#endif /* DEBUG */
- if ((rl != NULL) && (storePrivate->callbackRLS != NULL)) {
+ if ((rl != NULL) && (storePrivate->rlsNotifyRLS != NULL)) {
if (_SC_unschedule(store, rl, mode, storePrivate->rlList, FALSE)) {
/*
* if currently scheduled on this runLoop / runLoopMode
* if we are no longer scheduled to receive notifications for
* this runLoop / runLoopMode
*/
- CFRunLoopRemoveSource(rl, storePrivate->callbackRLS, mode);
+ CFRunLoopRemoveSource(rl, storePrivate->rlsNotifyRLS, mode);
}
}
}
#ifdef DEBUG
SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" cancel callback runloop source"));
#endif /* DEBUG */
- __MACH_PORT_DEBUG((storePrivate->callbackPort != NULL),
+ __MACH_PORT_DEBUG((storePrivate->rlsNotifyPort != NULL),
"*** rlsCancel",
- CFMachPortGetPort(storePrivate->callbackPort));
+ CFMachPortGetPort(storePrivate->rlsNotifyPort));
- CFRelease(storePrivate->rlList);
- storePrivate->rlList = NULL;
+ if (storePrivate->rlList != NULL) {
+ CFRelease(storePrivate->rlList);
+ storePrivate->rlList = NULL;
+ }
- if (storePrivate->callbackRLS != NULL) {
+ if (storePrivate->rlsNotifyRLS != NULL) {
/* invalidate & remove the run loop source */
- CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
- CFRelease(storePrivate->callbackRLS);
- storePrivate->callbackRLS = NULL;
+ CFRunLoopSourceInvalidate(storePrivate->rlsNotifyRLS);
+ CFRelease(storePrivate->rlsNotifyRLS);
+ storePrivate->rlsNotifyRLS = NULL;
}
- if (storePrivate->callbackPort != NULL) {
+ if (storePrivate->rlsNotifyPort != NULL) {
/* invalidate port */
- __MACH_PORT_DEBUG((storePrivate->callbackPort != NULL),
+ __MACH_PORT_DEBUG((storePrivate->rlsNotifyPort != NULL),
"*** rlsCancel (before invalidating CFMachPort)",
- CFMachPortGetPort(storePrivate->callbackPort));
- CFMachPortInvalidate(storePrivate->callbackPort);
- CFRelease(storePrivate->callbackPort);
- storePrivate->callbackPort = NULL;
+ CFMachPortGetPort(storePrivate->rlsNotifyPort));
+ CFMachPortInvalidate(storePrivate->rlsNotifyPort);
+ CFRelease(storePrivate->rlsNotifyPort);
+ storePrivate->rlsNotifyPort = NULL;
}
if (storePrivate->server != MACH_PORT_NULL) {
status = notifycancel(storePrivate->server, (int *)&sc_status);
+
+ (void) __SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "rlsCancel notifycancel()");
+
if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("rlsCancel notifycancel(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- (void) __SCDynamicStoreReconnect(store);
- }
return;
}
}
}
CFStringAppendFormat(result, NULL, CFSTR(", context = %@"), description);
CFRelease(description);
- } else {
- CFStringAppendFormat(result, NULL, CFSTR(", callout = %p"), storePrivate->callbackFunction);
- CFStringAppendFormat(result, NULL, CFSTR(", info = %p"), storePrivate->callbackArgument);
}
CFStringAppendFormat(result, NULL, CFSTR("}"));
}
-static boolean_t
-SCDynamicStoreNotifyMIGCallback(mach_msg_header_t *message, mach_msg_header_t *reply)
-{
- mach_msg_empty_rcv_t *buf = (mach_msg_empty_rcv_t *)message;
- mach_msg_id_t msgid = buf->header.msgh_id;
- SCDynamicStoreRef store;
-
- store = dispatch_get_context(dispatch_get_current_queue());
- if (store != NULL) {
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
-
- CFRetain(storePrivate);
- dispatch_async(storePrivate->dispatchQueue, ^{
- if (msgid == MACH_NOTIFY_NO_SENDERS) {
- /* re-establish notification and inform the client */
- (void)__SCDynamicStoreReconnectNotifications(store);
- }
- rlsPerform(storePrivate);
- CFRelease(storePrivate);
- });
- }
- reply->msgh_remote_port = MACH_PORT_NULL;
- return false;
-}
-
-
Boolean
SCDynamicStoreSetDispatchQueue(SCDynamicStoreRef store, dispatch_queue_t queue)
{
+ dispatch_group_t drainGroup = NULL;
+ dispatch_queue_t drainQueue = NULL;
+ mach_port_t mp;
Boolean ok = FALSE;
+ dispatch_source_t source;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
if (store == NULL) {
- /* sorry, you must provide a session */
+ // sorry, you must provide a session
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
}
- if (queue != NULL) {
- mach_port_t mp;
-
- if (storePrivate->server == MACH_PORT_NULL) {
- /* sorry, you must have an open session to play */
- _SCErrorSet(kSCStatusNoStoreServer);
- return FALSE;
- }
-
- if ((storePrivate->dispatchQueue != NULL) || (storePrivate->rls != NULL)) {
+ if (queue == NULL) {
+ if (storePrivate->dispatchQueue == NULL) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
- if (storePrivate->notifyStatus != NotifierNotRegistered) {
- /* sorry, you can only have one notification registered at once... */
- _SCErrorSet(kSCStatusNotifierActive);
- return FALSE;
- }
+ ok = TRUE;
+ goto cleanup;
+ }
- /*
- * mark our using of the SCDynamicStore notifications, create and schedule
- * the notification port (storePrivate->callbackPort), and a bunch of other
- * "setup"
- */
- storePrivate->notifyStatus = Using_NotifierInformViaDispatch;
- rlsSchedule((void*)store, NULL, NULL);
- storePrivate->dispatchQueue = queue;
- dispatch_retain(storePrivate->dispatchQueue);
-
- if (storePrivate->callbackPort == NULL) {
- /* if we could not schedule the notification */
- _SCErrorSet(kSCStatusFailed);
- goto cleanup;
- }
+ if (storePrivate->server == MACH_PORT_NULL) {
+ // sorry, you must have an open session to play
+ _SCErrorSet(kSCStatusNoStoreServer);
+ return FALSE;
+ }
- /*
- * create a dispatch queue for the mach notifications source, we'll use
- * this queue's context to carry the store pointer for the callback code.
- */
- storePrivate->callbackQueue = dispatch_queue_create("com.apple.SCDynamicStore.notifications", NULL);
- if (storePrivate->callbackQueue == NULL){
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStore dispatch_queue_create() failed"));
- _SCErrorSet(kSCStatusFailed);
- goto cleanup;
- }
- CFRetain(store); // Note: will be released when the dispatch queue is released
- dispatch_set_context(storePrivate->callbackQueue, (void *)store);
- dispatch_set_finalizer_f(storePrivate->callbackQueue, (dispatch_function_t)CFRelease);
-
- /*
- * create a dispatch source for the mach notifications
- */
- mp = CFMachPortGetPort(storePrivate->callbackPort);
- storePrivate->callbackSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV,
- mp,
- 0,
- storePrivate->callbackQueue);
- if (storePrivate->callbackSource == NULL) {
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStore dispatch_source_create() failed"));
- _SCErrorSet(kSCStatusFailed);
- goto cleanup;
+ if ((storePrivate->dispatchQueue != NULL) || (storePrivate->rls != NULL)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ if (storePrivate->notifyStatus != NotifierNotRegistered) {
+ // sorry, you can only have one notification registered at once...
+ _SCErrorSet(kSCStatusNotifierActive);
+ return FALSE;
+ }
+
+ /*
+ * mark our using of the SCDynamicStore notifications, create and schedule
+ * the notification port (storePrivate->rlsNotifyPort), and a bunch of other
+ * "setup"
+ */
+ storePrivate->notifyStatus = Using_NotifierInformViaDispatch;
+ rlsSchedule((void*)store, NULL, NULL);
+ if (storePrivate->rlsNotifyPort == NULL) {
+ /* if we could not schedule the notification */
+ _SCErrorSet(kSCStatusFailed);
+ goto cleanup;
+ }
+
+ // retain the dispatch queue
+ storePrivate->dispatchQueue = queue;
+ dispatch_retain(storePrivate->dispatchQueue);
+
+ //
+ // We've taken a reference to the callers dispatch_queue and we
+ // want to hold on to that reference until we've processed any/all
+ // notifications. To facilitate this we create a group, dispatch
+ // any notification blocks to via that group, and when the caller
+ // has told us to stop the notifications (unschedule) we wait for
+ // the group to empty and use the group's finalizer to release
+ // our reference to the SCDynamicStore.
+ //
+ storePrivate->dispatchGroup = dispatch_group_create();
+ CFRetain(store);
+ dispatch_set_context(storePrivate->dispatchGroup, (void *)store);
+ dispatch_set_finalizer_f(storePrivate->dispatchGroup, (dispatch_function_t)CFRelease);
+
+ // create a dispatch source for the mach notifications
+ mp = CFMachPortGetPort(storePrivate->rlsNotifyPort);
+ source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, mp, 0, queue);
+ if (source == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStore dispatch_source_create() failed"));
+ _SCErrorSet(kSCStatusFailed);
+ goto cleanup;
+ }
+
+ dispatch_source_set_event_handler(source, ^{
+ kern_return_t kr;
+ mach_msg_id_t msgid;
+ union {
+ u_int8_t buf[sizeof(mach_msg_empty_t) + MAX_TRAILER_SIZE];
+ mach_msg_empty_rcv_t msg;
+ mach_no_senders_notification_t no_senders;
+ } notify_msg;
+
+ kr = mach_msg(¬ify_msg.msg.header, // msg
+ MACH_RCV_MSG, // options
+ 0, // send_size
+ sizeof(notify_msg), // rcv_size
+ mp, // rcv_name
+ MACH_MSG_TIMEOUT_NONE, // timeout
+ MACH_PORT_NULL); // notify
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCDynamicStore notification handler, kr=0x%x"),
+ kr);
+ return;
}
- dispatch_source_set_event_handler(storePrivate->callbackSource, ^{
- union MaxMsgSize {
- mach_msg_empty_rcv_t normal;
- mach_no_senders_notification_t no_senders;
- };
-
- dispatch_mig_server(storePrivate->callbackSource,
- sizeof(union MaxMsgSize),
- SCDynamicStoreNotifyMIGCallback);
+
+ msgid = notify_msg.msg.header.msgh_id;
+
+ CFRetain(store);
+ dispatch_group_async(storePrivate->dispatchGroup, storePrivate->dispatchQueue, ^{
+ if (msgid == MACH_NOTIFY_NO_SENDERS) {
+ // re-establish notification and inform the client
+ (void)__SCDynamicStoreReconnectNotifications(store);
+ }
+ rlsPerform(storePrivate);
+ CFRelease(store);
});
- dispatch_resume(storePrivate->callbackSource);
+ });
- ok = TRUE;
- goto done;
- } else {
- if (storePrivate->dispatchQueue == NULL) {
- _SCErrorSet(kSCStatusInvalidArgument);
- return FALSE;
- }
+ dispatch_source_set_cancel_handler(source, ^{
+ dispatch_release(source);
+ });
- ok = TRUE;
- }
+ storePrivate->dispatchSource = source;
+ dispatch_resume(source);
+
+ return TRUE;
cleanup :
- if (storePrivate->callbackSource != NULL) {
- dispatch_source_cancel(storePrivate->callbackSource);
- if (storePrivate->callbackQueue != dispatch_get_current_queue()) {
- // ensure the cancellation has completed
- dispatch_sync(storePrivate->callbackQueue, ^{});
- }
- dispatch_release(storePrivate->callbackSource);
- storePrivate->callbackSource = NULL;
- }
- if (storePrivate->callbackQueue != NULL) {
- dispatch_release(storePrivate->callbackQueue);
- storePrivate->callbackQueue = NULL;
+ CFRetain(store);
+
+ if (storePrivate->dispatchSource != NULL) {
+ dispatch_source_cancel(storePrivate->dispatchSource);
+ storePrivate->dispatchSource = NULL;
}
- dispatch_release(storePrivate->dispatchQueue);
+ drainGroup = storePrivate->dispatchGroup;
+ storePrivate->dispatchGroup = NULL;
+ drainQueue = storePrivate->dispatchQueue;
storePrivate->dispatchQueue = NULL;
+
rlsCancel((void*)store, NULL, NULL);
+
+ if (drainGroup != NULL) {
+ dispatch_group_notify(drainGroup, drainQueue, ^{
+ // release group/queue references
+ dispatch_release(drainQueue);
+ dispatch_release(drainGroup); // releases our store reference
+ });
+ }
+
storePrivate->notifyStatus = NotifierNotRegistered;
- done :
+ CFRelease(store);
return ok;
}
/*
- * Copyright (c) 2000, 2001, 2004, 2005, 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2004, 2005, 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
identifier,
(int *)&sc_status);
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreNotifyFileDescriptor notifyviafd()")) {
+ goto retry;
+ }
+
if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyFileDescriptor notifyviafd(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
_SCErrorSet(status);
return FALSE;
}
+++ /dev/null
-/*
- * Copyright (c) 2000, 2001, 2004, 2005, 2009, 2010 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,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * 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@
- */
-
-/*
- * Modification History
- *
- * June 1, 2001 Allan Nathanson <ajn@apple.com>
- * - public API conversion
- *
- * March 31, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCPrivate.h>
-#include "SCDynamicStoreInternal.h"
-#include "config.h" /* MiG generated file */
-
-Boolean
-SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier, mach_port_t *port)
-{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- kern_return_t status;
- mach_port_t oldNotify;
- int sc_status;
-
- if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
- }
-
- if (storePrivate->server == MACH_PORT_NULL) {
- /* sorry, you must have an open session to play */
- _SCErrorSet(kSCStatusNoStoreServer);
- return FALSE;
- }
-
- if (storePrivate->notifyStatus != NotifierNotRegistered) {
- /* sorry, you can only have one notification registered at once */
- _SCErrorSet(kSCStatusNotifierActive);
- return FALSE;
- }
-
- /* Allocating port (for server response) */
- status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, port);
- if (status != KERN_SUCCESS) {
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort mach_port_allocate(): %s"), mach_error_string(status));
- _SCErrorSet(status);
- return FALSE;
- }
-
- status = mach_port_insert_right(mach_task_self(),
- *port,
- *port,
- MACH_MSG_TYPE_MAKE_SEND);
- if (status != KERN_SUCCESS) {
- /*
- * We can't insert a send right into our own port! This should
- * only happen if someone stomped on OUR port (so let's leave
- * the port alone).
- */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort mach_port_insert_right(): %s"), mach_error_string(status));
- *port = MACH_PORT_NULL;
- _SCErrorSet(status);
- return FALSE;
- }
-
- /* Request a notification when/if the server dies */
- status = mach_port_request_notification(mach_task_self(),
- *port,
- MACH_NOTIFY_NO_SENDERS,
- 1,
- *port,
- MACH_MSG_TYPE_MAKE_SEND_ONCE,
- &oldNotify);
- if (status != KERN_SUCCESS) {
- /*
- * We can't request a notification for our own port! This should
- * only happen if someone stomped on OUR port (so let's leave
- * the port alone).
- */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort mach_port_request_notification(): %s"), mach_error_string(status));
- *port = MACH_PORT_NULL;
- _SCErrorSet(status);
- return FALSE;
- }
-
- if (oldNotify != MACH_PORT_NULL) {
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort(): oldNotify != MACH_PORT_NULL"));
- }
-
- retry :
-
- status = notifyviaport(storePrivate->server,
- *port,
- identifier,
- (int *)&sc_status);
-
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort notifyviaport(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- /* remove the send right that we tried (but failed) to pass to the server */
- (void) mach_port_deallocate(mach_task_self(), *port);
- }
-
- /* remove our receive right */
- (void) mach_port_mod_refs(mach_task_self(), *port, MACH_PORT_RIGHT_RECEIVE, -1);
- *port = MACH_PORT_NULL;
- _SCErrorSet(status);
- return FALSE;
- }
-
- /* set notifier active */
- __MACH_PORT_DEBUG(TRUE, "*** SCDynamicStoreNotifyMachPort", *port);
- storePrivate->notifyStatus = Using_NotifierInformViaMachPort;
-
- return TRUE;
-}
/*
- * Copyright (c) 2000, 2001, 2004, 2005, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2004, 2005, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
status = notifyviasignal(storePrivate->server, task, sig, (int *)&sc_status);
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreNotifySignal notifyviasignal()")) {
+ goto retry;
+ }
+
if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifySignal notifyviasignal(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
_SCErrorSet(status);
return FALSE;
}
/*
- * Copyright (c) 2000-2005, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
isRegex,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreRemoveWatchedKey notifyremove(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreRemoveWatchedKey notifyremove()")) {
+ goto retry;
}
/* clean up */
/*
- * Copyright (c) 2000, 2001, 2003-2005, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2005, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
myPatternsLen,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetNotificationKeys notifyset(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreSetNotificationKeys notifyset()")) {
+ goto retry;
}
/* clean up */
/*
- * Copyright (c) 2000, 2001, 2004, 2006, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2004, 2006, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
0,
(int *)&sc_status);
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreNotifyWait notifyviaport()")) {
+ goto retry;
+ }
+
if (status != KERN_SUCCESS) {
if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyWait notifyviaport(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
/* remove the send right that we tried (but failed) to pass to the server */
(void) mach_port_deallocate(mach_task_self(), port);
}
/* remove our receive right */
(void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
- sc_status = status;
}
if (sc_status != kSCStatusOK) {
status = notifycancel(storePrivate->server,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyWait notifycancel(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if (((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) &&
- __SCDynamicStoreReconnect(store)) {
- sc_status = kSCStatusOK;
- } else {
- sc_status = status;
- }
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreNotifyWait notifycancel()")) {
+ sc_status = kSCStatusOK;
}
/* remove our receive right */
/*
- * Copyright (c) 2000, 2001, 2003-2005, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2005, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
SCDynamicStoreNotifyValue(SCDynamicStoreRef store,
CFStringRef key)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ SCDynamicStorePrivateRef storePrivate;
kern_return_t status;
CFDataRef utfKey; /* serialized key */
xmlData_t myKeyRef;
int sc_status;
if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
+ store = __SCDynamicStoreNullSession();
+ if (store == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoStoreSession);
+ return FALSE;
+ }
}
+ storePrivate = (SCDynamicStorePrivateRef)store;
if (storePrivate->server == MACH_PORT_NULL) {
/* sorry, you must have an open session to play */
_SCErrorSet(kSCStatusNoStoreServer);
myKeyLen,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyValue confignotify(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreNotifyValue confignotify()")) {
+ goto retry;
}
/* clean up */
/*
- * Copyright (c) 2000-2006, 2008-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2006, 2008-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
+#include "SCD.h"
#include "SCDynamicStoreInternal.h"
#include "config.h" /* MiG generated file */
-static CFStringRef _sc_bundleID = NULL;
-static pthread_mutex_t _sc_lock = PTHREAD_MUTEX_INITIALIZER;
-static mach_port_t _sc_server = MACH_PORT_NULL;
+static CFStringRef _sc_bundleID = NULL;
+static pthread_mutex_t _sc_lock = PTHREAD_MUTEX_INITIALIZER;
+static mach_port_t _sc_server = MACH_PORT_NULL;
static const char *notifyType[] = {
} else {
CFStringAppendFormat(result, NULL, CFSTR("server not (no longer) available"));
}
- if (storePrivate->locked) {
- CFStringAppendFormat(result, NULL, CFSTR(", locked"));
- }
if (storePrivate->disconnectFunction != NULL) {
CFStringAppendFormat(result, NULL, CFSTR(", disconnect = %p"), storePrivate->disconnectFunction);
}
CFStringAppendFormat(result, NULL, CFSTR(", BSD signal notifications"));
break;
case Using_NotifierInformViaRunLoop :
- case Using_NotifierInformViaCallback :
+ case Using_NotifierInformViaDispatch :
if (storePrivate->notifyStatus == Using_NotifierInformViaRunLoop) {
CFStringAppendFormat(result, NULL, CFSTR(", runloop notifications"));
CFStringAppendFormat(result, NULL, CFSTR(" {callout = %p"), storePrivate->rlsFunction);
CFStringAppendFormat(result, NULL, CFSTR(", info = %p"), storePrivate->rlsContext.info);
CFStringAppendFormat(result, NULL, CFSTR(", rls = %p"), storePrivate->rls);
- } else {
- CFStringAppendFormat(result, NULL, CFSTR(", mach port/callback notifications"));
- CFStringAppendFormat(result, NULL, CFSTR(" {callout = %p"), storePrivate->callbackFunction);
- CFStringAppendFormat(result, NULL, CFSTR(", info = %p"), storePrivate->callbackArgument);
+ } else if (storePrivate->notifyStatus == Using_NotifierInformViaDispatch) {
+ CFStringAppendFormat(result, NULL, CFSTR(", dispatch notifications"));
+ CFStringAppendFormat(result, NULL, CFSTR(" {callout = %p"), storePrivate->rlsFunction);
+ CFStringAppendFormat(result, NULL, CFSTR(", info = %p"), storePrivate->rlsContext.info);
+ CFStringAppendFormat(result, NULL, CFSTR(", queue = %p"), storePrivate->dispatchQueue);
+ CFStringAppendFormat(result, NULL, CFSTR(", source = %p"), storePrivate->dispatchSource);
}
- if (storePrivate->callbackRLS != NULL) {
- CFStringAppendFormat(result, NULL, CFSTR(", notify rls = %@" ), storePrivate->callbackRLS);
+ if (storePrivate->rlsNotifyRLS != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(", notify rls = %@" ), storePrivate->rlsNotifyRLS);
}
CFStringAppendFormat(result, NULL, CFSTR("}"));
break;
__SCDynamicStoreDeallocate(CFTypeRef cf)
{
int oldThreadState;
- int sc_status;
SCDynamicStoreRef store = (SCDynamicStoreRef)cf;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
/* Remove/cancel any outstanding notification requests. */
(void) SCDynamicStoreNotifyCancel(store);
- if ((storePrivate->server != MACH_PORT_NULL) && storePrivate->locked) {
- (void) SCDynamicStoreUnlock(store); /* release the lock */
- }
-
if (storePrivate->server != MACH_PORT_NULL) {
- __MACH_PORT_DEBUG(TRUE, "*** __SCDynamicStoreDeallocate", storePrivate->server);
- (void) configclose(storePrivate->server, (int *)&sc_status);
- __MACH_PORT_DEBUG(TRUE, "*** __SCDynamicStoreDeallocate (after configclose)", storePrivate->server);
+ if (!storePrivate->serverNullSession) {
+ /*
+ * Remove our send right to the SCDynamicStore server (and that will
+ * result in our session being closed).
+ */
+ __MACH_PORT_DEBUG(TRUE, "*** __SCDynamicStoreDeallocate", storePrivate->server);
+ (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
+ }
- /*
- * the above call to configclose() should result in the SCDynamicStore
- * server code deallocating it's receive right. That, in turn, should
- * result in our send becoming a dead name. We could explicitly remove
- * the dead name right with a call to mach_port_mod_refs() but, to be
- * sure, we use mach_port_deallocate() since that will get rid of a
- * send, send_once, or dead name right.
- */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
}
}
/* client side of the "configd" session */
- storePrivate->name = NULL;
+ storePrivate->name = (name != NULL) ? CFRetain(name) : NULL;
storePrivate->options = NULL;
/* server side of the "configd" session */
storePrivate->server = MACH_PORT_NULL;
+ storePrivate->serverNullSession = FALSE;
/* flags */
- storePrivate->locked = FALSE;
storePrivate->useSessionKeys = FALSE;
/* Notification status */
storePrivate->rlsContext.info = (void *)(*context->retain)(context->info);
}
}
-
- /* "client" information associated with SCDynamicStoreNotifyCallback() */
- storePrivate->callbackFunction = NULL;
- storePrivate->callbackArgument = NULL;
- storePrivate->callbackPort = NULL;
- storePrivate->callbackRLS = NULL;
+ storePrivate->rlsNotifyPort = NULL;
+ storePrivate->rlsNotifyRLS = NULL;
/* "client" information associated with SCDynamicStoreSetDispatchQueue() */
+ storePrivate->dispatchGroup = NULL;
storePrivate->dispatchQueue = NULL;
- storePrivate->callbackSource = NULL;
- storePrivate->callbackQueue = NULL;
+ storePrivate->dispatchSource = NULL;
/* "client" information associated with SCDynamicStoreSetDisconnectCallBack() */
storePrivate->disconnectFunction = NULL;
static Boolean
__SCDynamicStoreAddSession(SCDynamicStorePrivateRef storePrivate)
{
- CFDataRef myName; /* serialized name */
- xmlData_t myNameRef;
- CFIndex myNameLen;
- CFDataRef myOptions = NULL; /* serialized options */
- xmlData_t myOptionsRef = NULL;
- CFIndex myOptionsLen = 0;
- int sc_status = kSCStatusFailed;
- mach_port_t server;
- kern_return_t status = KERN_SUCCESS;
+ CFDataRef myName; /* serialized name */
+ xmlData_t myNameRef;
+ CFIndex myNameLen;
+ CFDataRef myOptions = NULL; /* serialized options */
+ xmlData_t myOptionsRef = NULL;
+ CFIndex myOptionsLen = 0;
+ int sc_status = kSCStatusFailed;
+ mach_port_t server;
+ kern_return_t status = KERN_SUCCESS;
if (!_SCSerializeString(storePrivate->name, &myName, (void **)&myNameRef, &myNameLen)) {
goto done;
server = _sc_server;
while (TRUE) {
if (server != MACH_PORT_NULL) {
- status = configopen(server,
- myNameRef,
- myNameLen,
- myOptionsRef,
- myOptionsLen,
- &storePrivate->server,
- (int *)&sc_status);
+ if (!storePrivate->serverNullSession) {
+ // if SCDynamicStore session
+ status = configopen(server,
+ myNameRef,
+ myNameLen,
+ myOptionsRef,
+ myOptionsLen,
+ &storePrivate->server,
+ (int *)&sc_status);
+ } else {
+ // if NULL session
+ if (storePrivate->server == MACH_PORT_NULL) {
+ // use the [main] SCDynamicStore server port
+ storePrivate->server = server;
+ sc_status = kSCStatusOK;
+ status = KERN_SUCCESS;
+ } else {
+ // if the server port we used returned an error
+ storePrivate->server = MACH_PORT_NULL;
+ status = MACH_SEND_INVALID_DEST;
+ }
+ }
+
if (status == KERN_SUCCESS) {
break;
}
pthread_mutex_lock(&_sc_lock);
if (_sc_server != MACH_PORT_NULL) {
if (server == _sc_server) {
- // if the server we tried returned the error
+ // if the server we tried returned the error, deallocate
+ // our send [or dead name] right
(void)mach_port_deallocate(mach_task_self(), _sc_server);
+
+ // and [re-]lookup the name to the server
_sc_server = __SCDynamicStoreServerPort(&sc_status);
} else {
// another thread has refreshed the SCDynamicStore server port
SCLog(TRUE,
(status == KERN_SUCCESS) ? LOG_DEBUG : LOG_ERR,
CFSTR("SCDynamicStore server not available"));
+ sc_status = kSCStatusNoStoreServer;
break;
default :
SCLog(TRUE,
(status == KERN_SUCCESS) ? LOG_DEBUG : LOG_ERR,
- CFSTR("SCDynamicStoreCreateAddSession configopen(): %s"),
+ CFSTR("SCDynamicStoreAddSession configopen(): %s"),
SCErrorString(sc_status));
break;
}
__private_extern__
-Boolean
+SCDynamicStoreRef
+__SCDynamicStoreNullSession(void)
+{
+ SCDynamicStorePrivateRef storePrivate;
+ Boolean ok = TRUE;
+ __SCThreadSpecificDataRef tsd;
+
+ tsd = __SCGetThreadSpecificData();
+ if (tsd->_sc_store == NULL) {
+#if !TARGET_IPHONE_SIMULATOR
+ storePrivate = __SCDynamicStoreCreatePrivate(NULL,
+ CFSTR("NULL session"),
+ NULL,
+ NULL);
+ storePrivate->server = _sc_server;
+ storePrivate->serverNullSession = TRUE;
+#else
+ /*
+ * In the simulator, this code may be talking to an older version of
+ * configd that still requires a valid session. Instead of using a
+ * "NULL" session that uses the server mach port, set up a "normal"
+ * session in thread-local storage.
+ */
+ storePrivate = __SCDynamicStoreCreatePrivate(NULL,
+ CFSTR("Thread local session"),
+ NULL,
+ NULL);
+ /*
+ * Use MACH_PORT_NULL here to trigger the call to
+ * __SCDynamicStoreAddSession below.
+ */
+ storePrivate->server = MACH_PORT_NULL;
+#endif /* TARGET_IPHONE_SIMULATOR */
+ tsd->_sc_store = (SCDynamicStoreRef)storePrivate;
+ }
+
+ storePrivate = (SCDynamicStorePrivateRef)tsd->_sc_store;
+ if (storePrivate->server == MACH_PORT_NULL) {
+ ok = __SCDynamicStoreAddSession(storePrivate);
+ }
+
+ return ok ? tsd->_sc_store : NULL;
+}
+
+
+static Boolean
__SCDynamicStoreReconnect(SCDynamicStoreRef store)
{
Boolean ok;
}
+__private_extern__
+Boolean
+__SCDynamicStoreCheckRetryAndHandleError(SCDynamicStoreRef store,
+ kern_return_t status,
+ int *sc_status,
+ const char *log_str)
+{
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+
+ if (status == KERN_SUCCESS) {
+ /* no error */
+ return FALSE;
+ }
+
+ if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
+ /* the server's gone */
+ if (!storePrivate->serverNullSession) {
+ /*
+ * remove the session's dead name right (and not the
+ * not the "server" port)
+ */
+ (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
+ }
+ storePrivate->server = MACH_PORT_NULL;
+
+ /* reconnect */
+ if (__SCDynamicStoreReconnect(store)) {
+ /* retry needed */
+ return TRUE;
+ }
+ } else {
+ /* an unexpected error, leave the [session] port alone */
+ SCLog(TRUE, LOG_ERR, CFSTR("%s: %s"), log_str, mach_error_string(status));
+ storePrivate->server = MACH_PORT_NULL;
+ }
+
+ *sc_status = status;
+ return FALSE;
+}
+
+
static void
pushDisconnect(SCDynamicStoreRef store)
{
break;
}
-#ifdef NOTNOW
- // invalidate the run loop source(s)
- if (storePrivate->callbackRLS != NULL) {
- CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
- CFRelease(storePrivate->callbackRLS);
- storePrivate->callbackRLS = NULL;
- }
-
- // invalidate port
- if (storePrivate->callbackPort != NULL) {
- __MACH_PORT_DEBUG(TRUE, "*** __SCDynamicStoreReconnectNotifications w/MACH_NOTIFY_NO_SENDERS", CFMachPortGetPort(storePrivate->callbackPort));
- CFMachPortInvalidate(storePrivate->callbackPort);
- CFRelease(storePrivate->callbackPort);
- storePrivate->callbackPort = NULL;
- }
-#endif // NOTNOW
-
// cancel [old] notifications
- SCDynamicStoreNotifyCancel(store);
+ if (!SCDynamicStoreNotifyCancel(store)) {
+ // if we could not cancel / reconnect
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("__SCDynamicStoreReconnectNotifications: SCDynamicStoreNotifyCancel() failed: %s"),
+ SCErrorString(SCError()));
+ }
// set notification keys & patterns
if ((storePrivate->keys != NULL) || (storePrivate->patterns)) {
SCDynamicStorePrivateRef storePrivate;
// allocate and initialize a new session
- storePrivate = __SCDynamicStoreCreatePrivate(allocator, name, callout, context);
+ storePrivate = __SCDynamicStoreCreatePrivate(allocator, NULL, callout, context);
if (storePrivate == NULL) {
return NULL;
}
/*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <pthread.h>
#include <execinfo.h>
-#include <libproc.h>
#include <unistd.h>
#include <dlfcn.h>
void
_SC_sockaddr_to_string(const struct sockaddr *address, char *buf, size_t bufLen)
{
+ union {
+ const struct sockaddr *sa;
+ const struct sockaddr_in *sin;
+ const struct sockaddr_in6 *sin6;
+ const struct sockaddr_dl *sdl;
+ } addr;
+
+ addr.sa = address;
+
bzero(buf, bufLen);
switch (address->sa_family) {
case AF_INET :
- (void)inet_ntop(((struct sockaddr_in *)address)->sin_family,
- &((struct sockaddr_in *)address)->sin_addr,
+ (void)inet_ntop(addr.sin->sin_family,
+ &addr.sin->sin_addr,
buf,
bufLen);
break;
case AF_INET6 : {
- (void)inet_ntop(((struct sockaddr_in6 *)address)->sin6_family,
- &((struct sockaddr_in6 *)address)->sin6_addr,
+ (void)inet_ntop(addr.sin6->sin6_family,
+ &addr.sin6->sin6_addr,
buf,
bufLen);
- if (((struct sockaddr_in6 *)address)->sin6_scope_id != 0) {
+ if (addr.sin6->sin6_scope_id != 0) {
int n;
n = strlen(buf);
if ((n+IF_NAMESIZE+1) <= (int)bufLen) {
buf[n++] = '%';
- if_indextoname(((struct sockaddr_in6 *)address)->sin6_scope_id, &buf[n]);
+ if_indextoname(addr.sin6->sin6_scope_id, &buf[n]);
}
}
break;
}
case AF_LINK :
- if (((struct sockaddr_dl *)address)->sdl_len < bufLen) {
- bufLen = ((struct sockaddr_dl *)address)->sdl_len;
+ if (addr.sdl->sdl_len < bufLen) {
+ bufLen = addr.sdl->sdl_len;
} else {
bufLen = bufLen - 1;
}
- bcopy(((struct sockaddr_dl *)address)->sdl_data, buf, bufLen);
+ bcopy(addr.sdl->sdl_data, buf, bufLen);
break;
default :
snprintf(buf, bufLen, "unexpected address family %d", address->sa_family);
}
+struct sockaddr *
+_SC_string_to_sockaddr(const char *str, sa_family_t af, void *buf, size_t bufLen)
+{
+ union {
+ void *buf;
+ struct sockaddr *sa;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ } addr;
+
+ if (buf == NULL) {
+ bufLen = sizeof(struct sockaddr_storage);
+ addr.buf = CFAllocatorAllocate(NULL, bufLen, 0);
+ } else {
+ addr.buf = buf;
+ }
+
+ bzero(addr.buf, bufLen);
+ if (((af == AF_UNSPEC) || (af == AF_INET)) &&
+ (bufLen >= sizeof(struct sockaddr_in)) &&
+ inet_aton(str, &addr.sin->sin_addr) == 1) {
+ // if IPv4 address
+ addr.sin->sin_len = sizeof(struct sockaddr_in);
+ addr.sin->sin_family = AF_INET;
+ } else if (((af == AF_UNSPEC) || (af == AF_INET6)) &&
+ (bufLen >= sizeof(struct sockaddr_in6)) &&
+ inet_pton(AF_INET6, str, &addr.sin6->sin6_addr) == 1) {
+ // if IPv6 address
+ char *p;
+
+ addr.sin6->sin6_len = sizeof(struct sockaddr_in6);
+ addr.sin6->sin6_family = AF_INET6;
+
+ p = strchr(buf, '%');
+ if (p != NULL) {
+ addr.sin6->sin6_scope_id = if_nametoindex(p + 1);
+ }
+
+ if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6->sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&addr.sin6->sin6_addr)) {
+ uint16_t if_index;
+
+ if_index = ntohs(addr.sin6->sin6_addr.__u6_addr.__u6_addr16[1]);
+ addr.sin6->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
+ if (addr.sin6->sin6_scope_id == 0) {
+ // use the scope id that was embedded in the [link local] IPv6 address
+ addr.sin6->sin6_scope_id = if_index;
+ }
+ }
+ } else {
+ if (addr.buf != buf) {
+ CFAllocatorDeallocate(NULL, addr.buf);
+ }
+ addr.buf = NULL;
+ }
+
+ return addr.sa;
+}
+
+
void
_SC_sendMachMessage(mach_port_t port, mach_msg_id_t msg_id)
{
Boolean
_SCUnserialize(CFPropertyListRef *obj, CFDataRef xml, void *dataRef, CFIndex dataLen)
{
- CFErrorRef error;
+ CFErrorRef error = NULL;
if (xml == NULL) {
kern_return_t status;
}
-CFDictionaryRef
+CF_RETURNS_RETAINED CFDictionaryRef
_SCSerializeMultiple(CFDictionaryRef dict)
{
const void * keys_q[N_QUICK];
}
+CF_RETURNS_RETAINED
CFDictionaryRef
_SCUnserializeMultiple(CFDictionaryRef dict)
{
CFStringRef
_SC_CFBundleCopyNonLocalizedString(CFBundleRef bundle, CFStringRef key, CFStringRef value, CFStringRef tableName)
{
+ CFDataRef data = NULL;
+ SInt32 errCode = 0;
+ CFURLRef resourcesURL;
CFStringRef str = NULL;
CFURLRef url;
if ((tableName == NULL) || CFEqual(tableName, CFSTR(""))) tableName = CFSTR("Localizable");
- url = CFBundleCopyResourceURLForLocalization(bundle,
- tableName,
- CFSTR("strings"),
- NULL,
- CFSTR("English"));
- if (url != NULL) {
- CFDataRef data = NULL;
- SInt32 errCode = 0;
-
- if (CFURLCreateDataAndPropertiesFromResource(NULL,
- url,
- &data,
- NULL,
- NULL,
- &errCode)) {
- CFDictionaryRef table;
+ /*
+ * First, try getting the requested string using a manually constructed
+ * URL to <bundle>/Resources/English.lproj/<tableName>.strings. Do this
+ * because CFBundleCopyResourceURLForLocalization() uses CFPreferences
+ * to get the preferred localizations, CFPreferences talks to
+ * OpenDirectory, and OpenDirectory tries to obtain the platform UUID.
+ * On machines where the platform UUID is set by InterfaceNamer, a
+ * deadlock can occur if InterfaceNamer calls
+ * CFBundleCopyResourceURLForLocalization() before setting the
+ * platform UUID in the kernel.
+ */
+ resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
+ if (resourcesURL != NULL) {
+ CFStringRef fileName = CFStringCreateWithFormat(
+ NULL, NULL, CFSTR("%@.strings"), tableName);
+ CFURLRef enlproj = CFURLCreateCopyAppendingPathComponent(
+ NULL, resourcesURL, CFSTR("English.lproj"), true);
+ url = CFURLCreateCopyAppendingPathComponent(
+ NULL, enlproj, fileName, false);
+ CFRelease(enlproj);
+ CFRelease(fileName);
+ CFRelease(resourcesURL);
+
+ if (!CFURLCreateDataAndPropertiesFromResource(NULL,
+ url,
+ &data,
+ NULL,
+ NULL,
+ &errCode)) {
+ /*
+ * Failed to get the data using a manually-constructed URL
+ * for the given strings table. Fall back to using
+ * CFBundleCopyResourceURLForLocalization() below.
+ */
+ data = NULL;
+ }
+ CFRelease(url);
+ }
- table = CFPropertyListCreateWithData(NULL,
- data,
- kCFPropertyListImmutable,
+ if (data == NULL) {
+ url = CFBundleCopyResourceURLForLocalization(bundle,
+ tableName,
+ CFSTR("strings"),
NULL,
- NULL);
- if (table != NULL) {
- if (isA_CFDictionary(table)) {
- str = CFDictionaryGetValue(table, key);
- if (str != NULL) {
- CFRetain(str);
- }
- }
+ CFSTR("English"));
+ if (url != NULL) {
+ if (!CFURLCreateDataAndPropertiesFromResource(NULL,
+ url,
+ &data,
+ NULL,
+ NULL,
+ &errCode)) {
+ data = NULL;
+ }
+ CFRelease(url);
+ }
+ }
- CFRelease(table);
+ if (data != NULL) {
+ CFDictionaryRef table;
+
+ table = CFPropertyListCreateWithData(NULL,
+ data,
+ kCFPropertyListImmutable,
+ NULL,
+ NULL);
+ if (table != NULL) {
+ if (isA_CFDictionary(table)) {
+ str = CFDictionaryGetValue(table, key);
+ if (str != NULL) {
+ CFRetain(str);
+ }
}
- CFRelease(data);
+ CFRelease(table);
}
- CFRelease(url);
+ CFRelease(data);
}
if (str == NULL) {
CFMachPortRef
_SC_CFMachPortCreateWithPort(const char *portDescription,
- mach_port_t portNum,
- CFMachPortCallBack callout,
- CFMachPortContext *context)
+ mach_port_t portNum,
+ CFMachPortCallBack callout,
+ CFMachPortContext *context)
{
CFMachPortRef port;
Boolean shouldFree = FALSE;
if ((port == NULL) || shouldFree) {
CFStringRef err;
char *crash_info = NULL;
- char name[64] = "";
SCLog(TRUE, LOG_ERR,
CFSTR("%s: CFMachPortCreateWithPort() failed , port = %p"),
crash_info = _SC_cfstring_to_cstring(err, NULL, 0, kCFStringEncodingASCII);
CFRelease(err);
- (void) proc_name(getpid(), name, sizeof(name));
err = CFStringCreateWithFormat(NULL,
NULL,
CFSTR("A recycled mach_port has been detected by \"%s\"."),
- name);
+ getprogname());
_SC_crash(crash_info, CFSTR("CFMachPort error"), err);
CFAllocatorDeallocate(NULL, crash_info);
CFRelease(err);
static int is_configd = -1;
if (is_configd == -1) {
- char name[64] = "";
-
- (void) proc_name(getpid(), name, sizeof(name));
- is_configd = (strncmp(name, "configd", sizeof(name)) == 0);
+ is_configd = (strcmp(getprogname(), "configd") == 0);
}
if (is_configd == 1) {
// if "configd", add indication if this is the M[ain] or [P]lugin thread
status = mach_port_type(mach_task_self(), port, &pt);
if (status != KERN_SUCCESS) {
SCLog(TRUE, LOG_NOTICE,
- CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_SEND): %s"),
+ CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_SEND): %s"),
buf,
port,
mach_error_string(status));
+ return;
}
if ((pt & MACH_PORT_TYPE_SEND) != 0) {
status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, &refs_send);
if (status != KERN_SUCCESS) {
SCLog(TRUE, LOG_NOTICE,
- CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_SEND): %s"),
+ CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_SEND): %s"),
buf,
port,
mach_error_string(status));
+ return;
}
}
status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, &refs_recv);
if (status != KERN_SUCCESS) {
SCLog(TRUE, LOG_NOTICE,
- CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_RECEIVE): %s"),
+ CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_RECEIVE): %s"),
buf,
port,
mach_error_string(status));
+ return;
}
count = MACH_PORT_RECEIVE_STATUS_COUNT;
&count);
if (status != KERN_SUCCESS) {
SCLog(TRUE, LOG_NOTICE,
- CFSTR("%mach_port_get_attributes(..., %d, MACH_PORT_RECEIVE_STATUS): %s"),
+ CFSTR("%smach_port_get_attributes(..., 0x%x, MACH_PORT_RECEIVE_STATUS): %s"),
buf,
port,
mach_error_string(status));
+ return;
}
}
status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND_ONCE, &refs_once);
if (status != KERN_SUCCESS) {
SCLog(TRUE, LOG_NOTICE,
- CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_SEND_ONCE): %s"),
+ CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_SEND_ONCE): %s"),
buf,
port,
mach_error_string(status));
+ return;
}
}
status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_PORT_SET, &refs_pset);
if (status != KERN_SUCCESS) {
SCLog(TRUE, LOG_NOTICE,
- CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_PORT_SET): %s"),
+ CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_PORT_SET): %s"),
buf,
port,
mach_error_string(status));
+ return;
}
}
status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_DEAD_NAME, &refs_dead);
if (status != KERN_SUCCESS) {
SCLog(TRUE, LOG_NOTICE,
- CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_DEAD_NAME): %s"),
+ CFSTR("%smach_port_get_refs(..., 0x%x, MACH_PORT_RIGHT_DEAD_NAME): %s"),
buf,
port,
mach_error_string(status));
+ return;
}
}
static Boolean
_SC_SimulateCrash(const char *crash_info, CFStringRef notifyHeader, CFStringRef notifyMessage)
{
+ Boolean ok = FALSE;
+
+#if ! TARGET_IPHONE_SIMULATOR
static bool (*dyfunc_SimulateCrash)(pid_t, mach_exception_data_type_t, CFStringRef) = NULL;
static void *image = NULL;
- Boolean ok = FALSE;
if ((dyfunc_SimulateCrash == NULL) && (image == NULL)) {
- const char *framework = "/System/Library/PrivateFrameworks/CrashReporterSupport.framework/"
-#if !TARGET_OS_EMBEDDED
- "Versions/A/"
-#endif // !TARGET_OS_EMBEDDED
- "CrashReporterSupport";
+ const char *framework = "/System/Library/PrivateFrameworks/CrashReporterSupport.framework/CrashReporterSupport";
struct stat statbuf;
const char *suffix = getenv("DYLD_IMAGE_SUFFIX");
char path[MAXPATHLEN];
}
}
#endif // TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
+#endif /* ! TARGET_IPHONE_SIMULATOR */
return ok;
}
/*
- * Copyright (c) 2000-2005, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
Boolean
SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ SCDynamicStorePrivateRef storePrivate;
kern_return_t status;
CFDataRef utfKey; /* serialized key */
xmlData_t myKeyRef;
int sc_status;
if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
+ store = __SCDynamicStoreNullSession();
+ if (store == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoStoreSession);
+ return FALSE;
+ }
}
+ storePrivate = (SCDynamicStorePrivateRef)store;
if (storePrivate->server == MACH_PORT_NULL) {
/* sorry, you must have an open session to play */
_SCErrorSet(kSCStatusNoStoreServer);
myKeyLen,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreRemoveValue configremove(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreRemoveValue configremove()")) {
+ goto retry;
}
/* clean up */
/*
- * Copyright (c) 2000-2006, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2006, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFArrayRef keysToRemove,
CFArrayRef keysToNotify)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ SCDynamicStorePrivateRef storePrivate;
kern_return_t status;
CFDataRef xmlSet = NULL; /* key/value pairs to set (XML serialized) */
xmlData_t mySetRef = NULL; /* key/value pairs to set (serialized) */
int sc_status;
if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
+ store = __SCDynamicStoreNullSession();
+ if (store == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoStoreSession);
+ return FALSE;
+ }
}
+ storePrivate = (SCDynamicStorePrivateRef)store;
if (storePrivate->server == MACH_PORT_NULL) {
_SCErrorSet(kSCStatusNoStoreServer);
return FALSE; /* you must have an open session to play */
myNotifyLen,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetMultiple configset_m(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreSetMultiple configset_m()")) {
+ goto retry;
}
/* clean up */
Boolean
SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ SCDynamicStorePrivateRef storePrivate;
kern_return_t status;
CFDataRef utfKey; /* serialized key */
xmlData_t myKeyRef;
int newInstance;
if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
+ store = __SCDynamicStoreNullSession();
+ if (store == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoStoreSession);
+ return FALSE;
+ }
}
+ storePrivate = (SCDynamicStorePrivateRef)store;
if (storePrivate->server == MACH_PORT_NULL) {
/* sorry, you must have an open session to play */
_SCErrorSet(kSCStatusNoStoreServer);
&newInstance,
(int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetValue configset(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreSetValue configset()")) {
+ goto retry;
}
/* clean up */
/*
- * Copyright (c) 2000, 2001, 2004, 2005, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2004, 2005, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
Boolean
SCDynamicStoreSnapshot(SCDynamicStoreRef store)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ SCDynamicStorePrivateRef storePrivate;
kern_return_t status;
int sc_status;
if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
+ store = __SCDynamicStoreNullSession();
+ if (store == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoStoreSession);
+ return FALSE;
+ }
}
+ storePrivate = (SCDynamicStorePrivateRef)store;
if (storePrivate->server == MACH_PORT_NULL) {
/* sorry, you must have an open session to play */
_SCErrorSet(kSCStatusNoStoreServer);
status = snapshot(storePrivate->server, (int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSnapshot snapshot(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
+ if (__SCDynamicStoreCheckRetryAndHandleError(store,
+ status,
+ &sc_status,
+ "SCDynamicStoreSnapshot snapshot()")) {
+ goto retry;
}
if (sc_status != kSCStatusOK) {
+++ /dev/null
-/*
- * Copyright (c) 2000-2005, 2009, 2010 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,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * 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@
- */
-
-/*
- * Modification History
- *
- * June 1, 2001 Allan Nathanson <ajn@apple.com>
- * - public API conversion
- *
- * June 20, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCPrivate.h>
-#include "SCDynamicStoreInternal.h"
-#include "config.h" /* MiG generated file */
-
-Boolean
-SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key)
-{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- kern_return_t status;
- CFDataRef utfKey; /* serialized key */
- xmlData_t myKeyRef;
- CFIndex myKeyLen;
- int sc_status;
-
- if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
- }
-
- if (storePrivate->server == MACH_PORT_NULL) {
- /* sorry, you must have an open session to play */
- _SCErrorSet(kSCStatusNoStoreServer);
- return FALSE;
- }
-
- /* serialize the key */
- if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) {
- _SCErrorSet(kSCStatusFailed);
- return FALSE;
- }
-
- retry :
-
- /* send the key to the server */
- status = configtouch(storePrivate->server,
- myKeyRef,
- myKeyLen,
- (int *)&sc_status);
-
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreTouchValue configtouch(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- if (__SCDynamicStoreReconnect(store)) {
- goto retry;
- }
- }
- sc_status = status;
- }
-
- /* clean up */
- CFRelease(utfKey);
-
- if (sc_status != kSCStatusOK) {
- _SCErrorSet(sc_status);
- return FALSE;
- }
-
- return TRUE;
-}
+++ /dev/null
-/*
- * Copyright (c) 2000, 2001, 2004, 2005, 2009, 2010 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,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * 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@
- */
-
-/*
- * Modification History
- *
- * June 1, 2001 Allan Nathanson <ajn@apple.com>
- * - public API conversion
- *
- * March 24, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCPrivate.h>
-#include "SCDynamicStoreInternal.h"
-#include "config.h" /* MiG generated file */
-
-Boolean
-SCDynamicStoreUnlock(SCDynamicStoreRef store)
-{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- kern_return_t status;
- int sc_status;
-
- if (store == NULL) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
- }
-
- if (storePrivate->server == MACH_PORT_NULL) {
- /* sorry, you must have an open session to play */
- _SCErrorSet(kSCStatusNoStoreServer);
- return FALSE;
- }
-
- /* (attempt to) release the servers lock */
- status = configunlock(storePrivate->server, (int *)&sc_status);
- if (status != KERN_SUCCESS) {
- if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
- /* the server's gone and our session port's dead, remove the dead name right */
- (void) mach_port_deallocate(mach_task_self(), storePrivate->server);
- } else {
- /* we got an unexpected error, leave the [session] port alone */
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreUnlock configunlock(): %s"), mach_error_string(status));
- }
- storePrivate->server = MACH_PORT_NULL;
- if (((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED))
- && __SCDynamicStoreReconnect(store)) {
- sc_status = kSCStatusOK;
- } else {
- sc_status = status;
- }
- }
-
- if (sc_status != kSCStatusOK) {
- _SCErrorSet(sc_status);
- return FALSE;
- }
-
- return TRUE;
-}
CFDateRef
DHCPInfoGetLeaseStartTime (CFDictionaryRef info) __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_2_0/*SPI*/);
+
+/*!
+ @function DHCPInfoGetLeaseExpirationTime
+ @discussion Returns a CFDateRef corresponding to the lease expiration time,
+ if present.
+ @param info The non-NULL DHCP information dictionary returned by
+ calling SCDynamicStoreCopyDHCPInfo.
+ @result Returns a non-NULL CFDateRef if the DHCP lease has an expiration;
+ NULL if the lease is infinite i.e. has no expiration, or the
+ configuration method is not DHCP. An infinite lease can be determined
+ by a non-NULL lease start time (see DHCPInfoGetLeaseStartTime above).
+
+ The return value must NOT be released.
+*/
+CFDateRef
+DHCPInfoGetLeaseExpirationTime (CFDictionaryRef info) __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_NA);
+
__END_DECLS
#endif /* USE_SYSTEMCONFIGURATION_PRIVATE_HEADERS */
/*
- * Copyright (c) 2000-2004, 2006, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
typedef enum {
NotifierNotRegistered = 0,
Using_NotifierWait,
- Using_NotifierInformViaCallback,
Using_NotifierInformViaMachPort,
Using_NotifierInformViaFD,
Using_NotifierInformViaSignal,
/* server side of the "configd" session */
mach_port_t server;
+ Boolean serverNullSession;
/* per-session flags */
- Boolean locked;
Boolean useSessionKeys;
/* current status of notification requests */
CFRunLoopSourceRef rls;
SCDynamicStoreCallBack rlsFunction;
SCDynamicStoreContext rlsContext;
-
- /* "client" information associated with SCDynamicStoreNotifyCallback() */
- SCDynamicStoreCallBack_v1 callbackFunction;
- void *callbackArgument;
- CFMachPortRef callbackPort;
- CFRunLoopSourceRef callbackRLS;
+ CFMachPortRef rlsNotifyPort;
+ CFRunLoopSourceRef rlsNotifyRLS;
/* "client" information associated with SCDynamicStoreSetDispatchQueue() */
+ dispatch_group_t dispatchGroup;
dispatch_queue_t dispatchQueue;
- dispatch_source_t callbackSource;
- dispatch_queue_t callbackQueue;
+ dispatch_source_t dispatchSource;
/* "client" information associated with SCDynamicStoreSetDisconnectCallBack() */
SCDynamicStoreDisconnectCallBack disconnectFunction;
Boolean disconnectForceCallBack;
- /* "server" SCDynamicStoreKeys being watched */
+ /* SCDynamicStoreKeys being watched */
CFMutableArrayRef keys;
CFMutableArrayRef patterns;
- /* "server" information associated with SCDynamicStoreNotifyMachPort() */
+ /* "server" information associated with mach port based notifications */
mach_port_t notifyPort;
mach_msg_id_t notifyPortIdentifier;
SCDynamicStoreCallBack callout,
SCDynamicStoreContext *context);
+SCDynamicStoreRef
+__SCDynamicStoreNullSession (void);
+
Boolean
-__SCDynamicStoreReconnect (SCDynamicStoreRef store);
+__SCDynamicStoreCheckRetryAndHandleError(SCDynamicStoreRef store,
+ kern_return_t status,
+ int *sc_status,
+ const char *func);
Boolean
__SCDynamicStoreReconnectNotifications (SCDynamicStoreRef store);
/*
- * Copyright (c) 2000, 2001, 2004, 2005, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2004, 2005, 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
not make multiple calls to SCDynamicStoreSetValue).
*/
-/*!
- @typedef SCDynamicStoreCallBack
- @discussion Type of the callback function used when a
- dynamic store change is delivered.
- @param store The "dynamic store" session.
- @param info ....
- */
-typedef boolean_t (*SCDynamicStoreCallBack_v1) (
- SCDynamicStoreRef store,
- void *info
- );
-
/*!
@typedef SCDynamicStoreDisconnectCallBack
@discussion Type of callback function used when notification of
__BEGIN_DECLS
-/*!
- @function SCDynamicStoreLock
- @discussion Locks access to the configuration "dynamic store". All
- other clients attempting to access the "dynamic store" will
- block. All change notifications will be deferred until the
- lock is released.
- @param store The "dynamic store" session that should be locked.
- @result TRUE if the lock was obtained; FALSE if an error was encountered.
- */
-Boolean
-SCDynamicStoreLock (SCDynamicStoreRef store);
-
-/*!
- @function SCDynamicStoreUnlock
- @discussion Unlocks access to the configuration "dynamic store". Other
- clients will be able to access the "dynamic store". Any change
- notifications will be delivered.
- @param store The "dynamic store" session that should be unlocked.
- @result TRUE if the lock was released; FALSE if an error was encountered.
- */
-Boolean
-SCDynamicStoreUnlock (SCDynamicStoreRef store);
-
-/*!
- @function SCDynamicStoreTouchValue
- @discussion Updates the value of the specified key in the
- "dynamic store".
- If the value does not exist then a CFDate object
- will be associated with the key.
- If the associated data is already a CFDate object
- then it will be updated with the current time.
- @param store The "dynamic store" session.
- @param key The key of the value to updated.
- @result TRUE if the value was updated; FALSE if an error was encountered.
- */
-Boolean
-SCDynamicStoreTouchValue (SCDynamicStoreRef store,
- CFStringRef key);
-
/*!
@function SCDynamicStoreAddWatchedKey
@discussion Adds the specified key to the list of "dynamic store"
CFStringRef key,
Boolean isRegex);
-/*!
- @function SCDynamicStoreNotifyCallback
- @discussion Requests that the specified function be called whenever a
- change has been detected to one of the "dynamic store" values
- being monitored.
-
- The callback function will be called with two arguments, store and
- context, that correspond to the current "dynamic store" session and
- the provided context argument.
-
- The callback function should return a Boolean value indicating
- whether an error occurred during execution of the callback.
-
- Note: An additional run loop source will be added for the notification.
- This additional source will be removed if the notification is cancelled
- or if the callback indicates that an error was detected.
-
- @param store The "dynamic store" session.
- @param runLoop A pointer to the run loop.
- @param func The callback function to call for each notification.
- If this parameter is not a pointer to a function of the
- correct prototype, the behavior is undefined.
- @param context A pointer-sized user-defined value, that is passed as
- the second parameter to the notification callback function,
- but is otherwise unused by this function. If the context
- is not what is expected by the notification function, the
- behavior is undefined.
- @result TRUE if the notification callback runloop source was
- successfully added; FALSE if an error was encountered.
- */
-Boolean
-SCDynamicStoreNotifyCallback (SCDynamicStoreRef store,
- CFRunLoopRef runLoop,
- SCDynamicStoreCallBack_v1 func,
- void *context);
-
-/*!
- @function SCDynamicStoreNotifyMachPort
- @discussion Allocates a mach port that can be used to detect changes to
- one of the system configuration data entries associated with the
- current session's notifier keys. When a change is detected, an
- empty (no data) mach message with the specified identifier will
- be delivered to the calling application via the allocated port.
-
- @param store An SCDynamicStoreRef that should be used for communication with the server.
- @param msgid A mach message ID to be included with any notifications.
- @param port A pointer to a mach port. Upon return, port will be filled
- with the mach port that will be used for any notifications.
- @result A boolean indicating the success (or failure) of the call.
- */
-Boolean
-SCDynamicStoreNotifyMachPort (SCDynamicStoreRef store,
- mach_msg_id_t msgid,
- mach_port_t *port);
-
/*!
@function SCDynamicStoreNotifyFileDescriptor
@discussion Allocates a file descriptor that can be used to detect changes
/*
- * Copyright (c) 2002, 2004, 2006, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2002, 2004, 2006, 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFDictionaryRef dict = NULL;
CFStringRef key;
CFStringRef location = NULL;
- Boolean tempSession = FALSE;
-
- if (store == NULL) {
- store = SCDynamicStoreCreate(NULL,
- CFSTR("SCDynamicStoreCopyLocation"),
- NULL,
- NULL);
- if (store == NULL) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
- return NULL;
- }
- tempSession = TRUE;
- }
key = SCDynamicStoreKeyCreateLocation(NULL);
dict = SCDynamicStoreCopyValue(store, key);
}
location = CFDictionaryGetValue(dict, kSCDynamicStorePropSetupCurrentSet);
- if (!isA_CFString(location)) {
+ location = isA_CFString(location);
+ if (location == NULL) {
_SCErrorSet(kSCStatusNoKey);
goto done;
}
done :
- if (tempSession) CFRelease(store);
if (dict) CFRelease(dict);
return location;
CFDictionaryRef config,
Boolean keepInactive)
{
- CFMutableDictionaryRef newConfig = NULL;
+ CFMutableDictionaryRef newConfig = NULL;
Boolean ok;
if ((config != NULL) && !isA_CFDictionary(config)) {
return ok;
}
+
+
+__private_extern__ Boolean
+__rank_to_str(SCNetworkServicePrimaryRank rank, CFStringRef *rankStr)
+{
+ switch (rank) {
+ case kSCNetworkServicePrimaryRankDefault :
+ *rankStr = NULL;
+ break;
+ case kSCNetworkServicePrimaryRankFirst :
+ *rankStr = kSCValNetServicePrimaryRankFirst;
+ break;
+ case kSCNetworkServicePrimaryRankLast :
+ *rankStr = kSCValNetServicePrimaryRankLast;
+ break;
+ case kSCNetworkServicePrimaryRankNever :
+ *rankStr = kSCValNetServicePrimaryRankNever;
+ break;
+ default :
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+__private_extern__ Boolean
+__str_to_rank(CFStringRef rankStr, SCNetworkServicePrimaryRank *rank)
+{
+ if (isA_CFString(rankStr)) {
+ if (CFEqual(rankStr, kSCValNetServicePrimaryRankFirst)) {
+ *rank = kSCNetworkServicePrimaryRankFirst;
+ } else if (CFEqual(rankStr, kSCValNetServicePrimaryRankLast)) {
+ *rank = kSCNetworkServicePrimaryRankLast;
+ } else if (CFEqual(rankStr, kSCValNetServicePrimaryRankNever)) {
+ *rank = kSCNetworkServicePrimaryRankNever;
+ } else {
+ return FALSE;
+ }
+ } else if (rankStr == NULL) {
+ *rank = kSCNetworkServicePrimaryRankDefault;
+ } else {
+ return FALSE;
+ }
+
+ return TRUE;
+}
#include <CoreFoundation/CFRuntime.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPreferencesPathKey.h>
+#include <SystemConfiguration/SCNetworkConfigurationPrivate.h>
#include <IOKit/IOKitLib.h>
// prefs (for associated service, BOND interfaces, and VLAN interfaces)
SCPreferencesRef prefs;
+ // SCDynamicStore
+ SCDynamicStoreRef store;
+
// serviceID (NULL if not associated with a service)
CFStringRef serviceID;
__SCNetworkServiceExistsForInterface (CFArrayRef services,
SCNetworkInterfaceRef interface);
+CF_RETURNS_RETAINED
CFStringRef
__SCNetworkServiceNextName (SCNetworkServiceRef service);
CFStringRef unique_id,
CFDictionaryRef *newConfig);
+Boolean
+__rank_to_str (SCNetworkServicePrimaryRank rank,
+ CFStringRef *rankStr);
+
+Boolean
+__str_to_rank (CFStringRef rankStr,
+ SCNetworkServicePrimaryRank *rank);
+
__END_DECLS
#endif /* _SCNETWORKCONFIGURATIONINTERNAL_H */
*/
#pragma mark -
-#pragma mark SCNetworkInterface configuration (typedefs, consts)
+#pragma mark SCNetworkInterface configuration (typedefs, consts, enums)
/*!
@const kSCNetworkInterfaceTypeBridge
*/
typedef SCNetworkInterfaceRef SCBridgeInterfaceRef;
+enum {
+ kSCNetworkServicePrimaryRankDefault = 0,
+ kSCNetworkServicePrimaryRankFirst = 1,
+ kSCNetworkServicePrimaryRankLast = 2,
+ kSCNetworkServicePrimaryRankNever = 3
+};
+typedef uint32_t SCNetworkServicePrimaryRank;
+
#pragma mark -
#pragma mark SCNetworkInterface configuration (SPI)
const void *val2,
void *context) __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
+/*!
+ @function _SCNetworkInterfaceCopyActive
+ @discussion Creates an SCNetworkInterface and associated with interface name
+ and SCDynamicStoreRef
+ @param the interface name
+ @param the SCDynamicStoreRef
+ @result the SCNetworkInterface
+ */
+SCNetworkInterfaceRef
+_SCNetworkInterfaceCopyActive (SCDynamicStoreRef store,
+ CFStringRef bsdName) __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_5_0);
+
/*!
@function _SCNetworkInterfaceCopyAllWithPreferences
Returns all network capable interfaces on the system.
SCNetworkInterfaceRef
_SCNetworkInterfaceCreateWithIONetworkInterfaceObject (io_object_t if_obj) __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
+/*!
+ @function SCNetworkInterfaceGetPrimaryRank
+ @discussion We allow caller to retrieve the rank on an interface.
+ The key is stored in State:/Network/Interface/<ifname>/Service
+ @param the interface to get the rank
+ @result SCNetworkServicePrimaryRank
+ */
+SCNetworkServicePrimaryRank
+SCNetworkInterfaceGetPrimaryRank (SCNetworkInterfaceRef interface) __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_5_0);
+
+/*!
+ @function SCNetworkInterfaceSetPrimaryRank
+ @discussion We allow caller to set an assertion on an interface.
+ @param the interface to set the rank assertion
+ @param the new rank to be set
+ @result TRUE if operation is successful; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkInterfaceSetPrimaryRank (SCNetworkInterfaceRef interface,
+ SCNetworkServicePrimaryRank newRank) __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_5_0);
+
#define kSCNetworkInterfaceConfigurationActionKey CFSTR("New Interface Detected Action")
#define kSCNetworkInterfaceConfigurationActionValueNone CFSTR("None")
#define kSCNetworkInterfaceConfigurationActionValuePrompt CFSTR("Prompt")
Zero if no entry ID is available.
*/
uint64_t
-_SCNetworkInterfaceGetIORegistryEntryID (SCNetworkInterfaceRef interface) __OSX_AVAILABLE_STARTING(__MAC_10_7/*FIXME*/,__IPHONE_5_0);
+_SCNetworkInterfaceGetIORegistryEntryID (SCNetworkInterfaceRef interface) __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_5_0);
/*!
@function _SCNetworkInterfaceIsBluetoothPAN
return (isA_CFType(obj, SCNetworkServiceGetTypeID()));
}
-enum {
- kSCNetworkServicePrimaryRankDefault = 0,
- kSCNetworkServicePrimaryRankFirst = 1,
- kSCNetworkServicePrimaryRankLast = 2,
- kSCNetworkServicePrimaryRankNever = 3
-};
-typedef uint32_t SCNetworkServicePrimaryRank;
-
/*!
@function _SCNetworkServiceCompare
@discussion Compares two SCNetworkService objects.
SCNetworkServiceRef service) __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
__END_DECLS
-
#endif /* _SCNETWORKCONFIGURATIONPRIVATE_H */
/*
- * Copyright (c) 2003-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/* service */
SCNetworkServiceRef service;
+ /* client info (if we are proxying for another process */
+ mach_port_t client_audit_session;
+ uid_t client_uid;
+ gid_t client_gid;
+ pid_t client_pid;
+
/* ref to PPP controller for control messages */
mach_port_t session_port;
CFMutableArrayRef rlList;
/* SCNetworkConnectionSetDispatchQueue */
+ dispatch_group_t dispatchGroup;
dispatch_queue_t dispatchQueue;
- dispatch_queue_t callbackQueue;
- dispatch_source_t callbackSource;
+ dispatch_source_t dispatchSource;
} SCNetworkConnectionPrivate, *SCNetworkConnectionPrivateRef;
/* release resources */
pthread_mutex_destroy(&connectionPrivate->lock);
+ if (connectionPrivate->client_audit_session != MACH_PORT_NULL) {
+ mach_port_mod_refs(mach_task_self(),
+ connectionPrivate->client_audit_session,
+ MACH_PORT_RIGHT_SEND,
+ -1);
+ }
+
if (connectionPrivate->rls != NULL) {
CFRunLoopSourceInvalidate(connectionPrivate->rls);
CFRelease(connectionPrivate->rls);
/* save the service */
connectionPrivate->service = CFRetain(service);
+ connectionPrivate->client_audit_session = MACH_PORT_NULL;
+ connectionPrivate->client_uid = geteuid();
+ connectionPrivate->client_gid = getegid();
+ connectionPrivate->client_pid = getpid();
+
connectionPrivate->rlsFunction = callout;
if (context) {
}
+#if ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) && !TARGET_IPHONE_SIMULATOR
+#define HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
+#endif
+
+
+#if ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) && !TARGET_IPHONE_SIMULATOR
+#define HAVE_PPPCONTROLLER_ATTACHWITHPROXY
+#endif
+
+
static mach_port_t
__SCNetworkConnectionSessionPort(SCNetworkConnectionPrivateRef connectionPrivate)
{
int sc_status = kSCStatusFailed;
mach_port_t server = scnc_server;
kern_return_t status = KERN_SUCCESS;
+
+#ifdef HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
mach_port_t au_session = MACH_PORT_NULL;
+#endif // HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
if (connectionPrivate->session_port != MACH_PORT_NULL) {
return connectionPrivate->session_port;
mach_port_mod_refs(mach_task_self(), mp, MACH_PORT_RIGHT_RECEIVE, -1);
}
+#ifdef HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
au_session = audit_session_self();
+#endif // HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
// open a new session with the server
while (TRUE) {
}
if (server != MACH_PORT_NULL) {
- status = pppcontroller_attach(server,
- data,
- dataLen,
- bootstrap_port,
- notify_port,
- au_session,
- &connectionPrivate->session_port,
- &sc_status);
+#ifdef HAVE_PPPCONTROLLER_ATTACHWITHPROXY
+ if ((connectionPrivate->client_audit_session == MACH_PORT_NULL) &&
+ (connectionPrivate->client_uid == geteuid()) &&
+ (connectionPrivate->client_gid == getegid()) &&
+ (connectionPrivate->client_pid == getpid())
+ ) {
+#endif // HAVE_PPPCONTROLLER_ATTACHWITHPROXY
+ status = pppcontroller_attach(server,
+ data,
+ dataLen,
+ bootstrap_port,
+ notify_port,
+#ifdef HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
+ au_session,
+#endif // HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
+ &connectionPrivate->session_port,
+ &sc_status);
+#ifdef HAVE_PPPCONTROLLER_ATTACHWITHPROXY
+ } else {
+ mach_port_t client_au_session;
+
+ if (connectionPrivate->client_audit_session == MACH_PORT_NULL) {
+ client_au_session = au_session;
+ } else {
+ client_au_session = connectionPrivate->client_audit_session;
+ }
+
+ status = pppcontroller_attach_proxy(server,
+ data,
+ dataLen,
+ bootstrap_port,
+ notify_port,
+ client_au_session,
+ connectionPrivate->client_uid,
+ connectionPrivate->client_gid,
+ connectionPrivate->client_pid,
+ &connectionPrivate->session_port,
+ &sc_status);
+ }
+#endif // HAVE_PPPCONTROLLER_ATTACHWITHPROXY
if (status == KERN_SUCCESS) {
if (sc_status != kSCStatusOK) {
SCLog(TRUE, LOG_DEBUG,
done :
// clean up
- if (au_session != MACH_PORT_NULL) {
+
+#ifdef HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
+ if (au_session != MACH_PORT_NULL){
(void)mach_port_deallocate(mach_task_self(), au_session);
}
+#endif // HAVE_PPPCONTROLLER_ATTACHWITHAUDITSESSION
if (dataRef != NULL) CFRelease(dataRef);
__SCNetworkConnectionReconnectNotifications(SCNetworkConnectionRef connection)
{
SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ dispatch_group_t dispatchGroup = NULL;
dispatch_queue_t dispatchQueue = NULL;
Boolean ok = TRUE;
CFArrayRef rlList = NULL;
rlList = CFArrayCreateCopy(NULL, connectionPrivate->rlList);
}
if (connectionPrivate->dispatchQueue != NULL) {
+ // save dispatchQueue, release reference when we've queue'd blocks
+ // complete, allow re-scheduling
+ dispatchGroup = connectionPrivate->dispatchGroup;
+ connectionPrivate->dispatchGroup = NULL;
dispatchQueue = connectionPrivate->dispatchQueue;
+ connectionPrivate->dispatchQueue = NULL;
+
+ // and take an extra reference for rescheduling
dispatch_retain(dispatchQueue);
}
CFRelease(connectionPrivate->rls);
connectionPrivate->rls = NULL;
}
- if (connectionPrivate->callbackSource != NULL) {
- dispatch_source_cancel(connectionPrivate->callbackSource);
- if (connectionPrivate->callbackQueue != dispatch_get_current_queue()) {
- // ensure the cancellation has completed
- dispatch_sync(connectionPrivate->callbackQueue, ^{});
- }
- dispatch_release(connectionPrivate->callbackSource);
- connectionPrivate->callbackSource = NULL;
- }
- if (connectionPrivate->callbackQueue != NULL) {
- dispatch_release(connectionPrivate->callbackQueue);
- connectionPrivate->callbackQueue = NULL;
- }
- if (connectionPrivate->dispatchQueue != NULL) {
- dispatch_release(connectionPrivate->dispatchQueue);
- connectionPrivate->dispatchQueue = NULL;
+ if (connectionPrivate->dispatchSource != NULL) {
+ dispatch_source_cancel(connectionPrivate->dispatchSource);
+ connectionPrivate->dispatchSource = NULL;
}
connectionPrivate->scheduled = FALSE;
pthread_mutex_unlock(&connectionPrivate->lock);
+ if (dispatchGroup != NULL) {
+ dispatch_group_notify(dispatchGroup, dispatchQueue, ^{
+ // release group/queue references
+ dispatch_release(dispatchQueue);
+ dispatch_release(dispatchGroup); // releases our connection reference
+ });
+ }
+
// re-schedule
if (rlList != NULL) {
CFIndex i;
}
+Boolean
+SCNetworkConnectionSetClientInfo(SCNetworkConnectionRef connection,
+ mach_port_t client_audit_session,
+ uid_t client_uid,
+ gid_t client_gid,
+ pid_t client_pid)
+{
+ SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+
+ if (!isA_SCNetworkConnection(connection)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ // save client bootstrap port
+ if (connectionPrivate->client_audit_session != MACH_PORT_NULL) {
+ mach_port_mod_refs(mach_task_self(),
+ connectionPrivate->client_audit_session,
+ MACH_PORT_RIGHT_SEND,
+ -1);
+ connectionPrivate->client_audit_session = MACH_PORT_NULL;
+ }
+ connectionPrivate->client_audit_session = client_audit_session;
+ if (connectionPrivate->client_audit_session != MACH_PORT_NULL) {
+ mach_port_mod_refs(mach_task_self(),
+ connectionPrivate->client_audit_session,
+ MACH_PORT_RIGHT_SEND,
+ 1);
+ }
+
+ // save client UID, GID, and PID
+ connectionPrivate->client_uid = client_uid;
+ connectionPrivate->client_gid = client_gid;
+ connectionPrivate->client_pid = client_pid;
+
+ return TRUE;
+}
+
+
CFDictionaryRef
SCNetworkConnectionCopyStatistics(SCNetworkConnectionRef connection)
{
}
-static boolean_t
-SCNetworkConnectionNotifyMIGCallback(mach_msg_header_t *message, mach_msg_header_t *reply)
-{
- SCNetworkConnectionPrivateRef connectionPrivate = dispatch_get_context(dispatch_get_current_queue());
-
- if (connectionPrivate != NULL) {
- mach_msg_empty_rcv_t *buf = malloc(sizeof(*buf));
-
- bcopy(message, buf, sizeof(*buf));
- CFRetain(connectionPrivate);
- dispatch_async(connectionPrivate->dispatchQueue, ^{
- __SCNetworkConnectionCallBack(connectionPrivate->notify_port,
- buf,
- sizeof(*buf),
- connectionPrivate);
- CFRelease(connectionPrivate);
- free(buf);
- });
- }
- reply->msgh_remote_port = MACH_PORT_NULL;
- return false;
-}
-
-
static Boolean
__SCNetworkConnectionScheduleWithRunLoop(SCNetworkConnectionRef connection,
CFRunLoopRef runLoop,
}
if (queue != NULL) {
- mach_port_t mp;
- char qname[256];
-
- connectionPrivate->dispatchQueue = queue;
- dispatch_retain(connectionPrivate->dispatchQueue);
-
- snprintf(qname, sizeof(qname), "com.apple.SCNetworkConnection.%p", connection);
- connectionPrivate->callbackQueue = dispatch_queue_create(qname, NULL);
- if (connectionPrivate->callbackQueue == NULL){
- SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkConnection dispatch_queue_create() failed"));
- goto fail;
- }
- CFRetain(connection); // Note: will be released when the dispatch queue is released
- dispatch_set_context(connectionPrivate->callbackQueue, connectionPrivate);
- dispatch_set_finalizer_f(connectionPrivate->callbackQueue, (dispatch_function_t)CFRelease);
+ mach_port_t mp;
+ dispatch_source_t source;
mp = CFMachPortGetPort(connectionPrivate->notify_port);
- connectionPrivate->callbackSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV,
- mp,
- 0,
- connectionPrivate->callbackQueue);
- if (connectionPrivate->callbackSource == NULL) {
+ source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, mp, 0, queue);
+ if (source == NULL) {
SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkConnection dispatch_source_create() failed"));
- goto fail;
+ _SCErrorSet(kSCStatusFailed);
+ goto done;
}
- dispatch_source_set_event_handler(connectionPrivate->callbackSource, ^{
- union MaxMsgSize {
- mach_msg_empty_rcv_t normal;
+
+ // have our dispatch source hold a reference to the notification CFMachPort
+ CFRetain(connectionPrivate->notify_port);
+ dispatch_set_context(source, (void *)connectionPrivate->notify_port);
+ dispatch_set_finalizer_f(source, (dispatch_function_t)CFRelease);
+
+ // retain the dispatch queue
+ connectionPrivate->dispatchQueue = queue;
+ dispatch_retain(connectionPrivate->dispatchQueue);
+
+ //
+ // We've taken a reference to the callers dispatch_queue and we
+ // want to hold on to that reference until we've processed any/all
+ // notifications. To facilitate this we create a group, dispatch
+ // any notification blocks to via that group, and when the caller
+ // has told us to stop the notifications (unschedule) we wait for
+ // the group to empty and use the group's finalizer to release
+ // our reference to the SCNetworkConnection.
+ //
+ connectionPrivate->dispatchGroup = dispatch_group_create();
+ CFRetain(connection);
+ dispatch_set_context(connectionPrivate->dispatchGroup, (void *)connection);
+ dispatch_set_finalizer_f(connectionPrivate->dispatchGroup, (dispatch_function_t)CFRelease);
+
+ dispatch_source_set_event_handler(source, ^{
+ kern_return_t kr;
+ union {
+ u_int8_t buf[sizeof(mach_msg_empty_t) + MAX_TRAILER_SIZE];
+ mach_msg_empty_rcv_t msg;
mach_no_senders_notification_t no_senders;
- };
+ } notify_msg;
+ CFMachPortRef notify_port;
+
+ kr = mach_msg(¬ify_msg.msg.header, // msg
+ MACH_RCV_MSG, // options
+ 0, // send_size
+ sizeof(notify_msg), // rcv_size
+ mp, // rcv_name
+ MACH_MSG_TIMEOUT_NONE, // timeout
+ MACH_PORT_NULL); // notify
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCDynamicStore notification handler, kr=0x%x"),
+ kr);
+ return;
+ }
- dispatch_mig_server(connectionPrivate->callbackSource,
- sizeof(union MaxMsgSize),
- SCNetworkConnectionNotifyMIGCallback);
+ CFRetain(connection);
+ notify_port = dispatch_get_context(source);
+ dispatch_group_async(connectionPrivate->dispatchGroup, connectionPrivate->dispatchQueue, ^{
+ __SCNetworkConnectionCallBack(notify_port,
+ (void *)¬ify_msg.msg,
+ sizeof(notify_msg),
+ (void *)connection);
+ CFRelease(connection);
+ });
});
- dispatch_resume(connectionPrivate->callbackSource);
+
+ dispatch_source_set_cancel_handler(source, ^{
+ dispatch_release(source);
+ });
+
+ connectionPrivate->dispatchSource = source;
+ dispatch_resume(source);
} else {
if (!_SC_isScheduled(NULL, runLoop, runLoopMode, connectionPrivate->rlList)) {
/*
}
ok = TRUE;
- goto done;
-
- fail :
-
- if (connectionPrivate->callbackSource != NULL) {
- dispatch_source_cancel(connectionPrivate->callbackSource);
- dispatch_release(connectionPrivate->callbackSource);
- connectionPrivate->callbackSource = NULL;
- }
- if (connectionPrivate->callbackQueue != NULL) {
- dispatch_release(connectionPrivate->callbackQueue);
- connectionPrivate->callbackQueue = NULL;
- }
- if (connectionPrivate->dispatchQueue != NULL) {
- dispatch_release(connectionPrivate->dispatchQueue);
- connectionPrivate->dispatchQueue = NULL;
- }
- _SCErrorSet(kSCStatusFailed);
done :
dispatch_queue_t queue)
{
SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ dispatch_group_t drainGroup = NULL;
+ dispatch_queue_t drainQueue = NULL;
int sc_status = kSCStatusFailed;
CFIndex n = 0;
Boolean ok = FALSE;
mach_port_t session_port;
kern_return_t status;
+ // hold a reference while we unschedule
+ CFRetain(connection);
+
pthread_mutex_lock(&connectionPrivate->lock);
if ((runLoop != NULL) && !connectionPrivate->scheduled) { // if we should be scheduled (but are not)
goto done;
}
- if (runLoop == NULL) {
- dispatch_source_cancel(connectionPrivate->callbackSource);
- if (connectionPrivate->callbackQueue != dispatch_get_current_queue()) {
- // ensure the cancellation has completed
- dispatch_sync(connectionPrivate->callbackQueue, ^{});
+ if (connectionPrivate->dispatchQueue != NULL) {
+ // cancel dispatchSource
+ if (connectionPrivate->dispatchSource != NULL) {
+ dispatch_source_cancel(connectionPrivate->dispatchSource);
+ connectionPrivate->dispatchSource = NULL;
}
- dispatch_release(connectionPrivate->callbackSource);
- connectionPrivate->callbackSource = NULL;
- dispatch_release(connectionPrivate->callbackQueue);
- connectionPrivate->callbackQueue = NULL;
- dispatch_release(connectionPrivate->dispatchQueue);
+
+ // save dispatchQueue/group, release reference when all queue'd blocks
+ // have been processed, allow re-scheduling
+ drainGroup = connectionPrivate->dispatchGroup;
+ connectionPrivate->dispatchGroup = NULL;
+ drainQueue = connectionPrivate->dispatchQueue;
connectionPrivate->dispatchQueue = NULL;
} else {
if (!_SC_unschedule(connection, runLoop, runLoopMode, connectionPrivate->rlList, FALSE)) {
done :
pthread_mutex_unlock(&connectionPrivate->lock);
+
+ if (drainGroup != NULL) {
+ dispatch_group_notify(drainGroup, drainQueue, ^{
+ // release group/queue references
+ dispatch_release(drainQueue);
+ dispatch_release(drainGroup); // releases our connection reference
+ });
+ }
+
+ // release our reference
+ CFRelease(connection);
+
return ok;
}
/*
* return TRUE if domain1 ends with domain2, and will check for trailing "."
*/
-static Boolean
-domainEndsWithDomain(CFStringRef domain1, CFStringRef domain2)
+Boolean
+_SC_domainEndsWithDomain(CFStringRef compare_domain, CFStringRef match_domain)
{
CFRange range;
Boolean ret = FALSE;
Boolean s1_created = FALSE;
CFStringRef s2 = NULL;
Boolean s2_created = FALSE;
+ CFStringRef s3 = NULL;
- if (CFStringHasSuffix(domain1, CFSTR("."))) {
+ if (CFStringHasSuffix(compare_domain, CFSTR("."))) {
range.location = 0;
- range.length = CFStringGetLength(domain1) - 1;
- s1 = CFStringCreateWithSubstring(NULL, domain1, range);
+ range.length = CFStringGetLength(compare_domain) - 1;
+ s1 = CFStringCreateWithSubstring(NULL, compare_domain, range);
if (s1 == NULL) {
goto done;
}
s1_created = TRUE;
} else {
- s1 = domain1;
+ s1 = compare_domain;
}
- if (CFStringHasSuffix(domain2, CFSTR("."))) {
+ if (CFStringHasSuffix(match_domain, CFSTR("."))) {
range.location = 0;
- range.length = CFStringGetLength(domain2) - 1;
- s2 = CFStringCreateWithSubstring(NULL, domain2, range);
+ range.length = CFStringGetLength(match_domain) - 1;
+ s2 = CFStringCreateWithSubstring(NULL, match_domain, range);
if (s2 == NULL) {
goto done;
}
s2_created = TRUE;
} else {
- s2 = domain2;
+ s2 = match_domain;
+ }
+
+ if (CFStringHasPrefix(s2, CFSTR("*."))) {
+ range.location = 2;
+ range.length = CFStringGetLength(s2)-2;
+ s3 = CFStringCreateWithSubstring(NULL, s2, range);
+ if (s3 == NULL) {
+ goto done;
+ }
+ if (s2_created) {
+ CFRelease(s2);
+ }
+ s2 = s3;
+ s2_created = TRUE;
}
ret = CFStringHasSuffix(s1, s2);
continue;
}
- if (domainEndsWithDomain(hostName, domain)) {
+ if (_SC_domainEndsWithDomain(hostName, domain)) {
CFArrayRef exceptions;
int exceptionsCount;
int exceptionsIndex;
continue;
}
- if (domainEndsWithDomain(hostName, exception)) {
+ if (_SC_domainEndsWithDomain(hostName, exception)) {
// found matching exception
if (_sc_debug || (debug > 0)) {
SCLog(TRUE, LOG_INFO, CFSTR("OnDemand match exception"));
// if we have a matching domain and there were no exceptions
// then we pass back the OnDemand info
+ ok = TRUE;
+
if (!CFDictionaryGetValueIfPresent(trigger,
kSCNetworkConnectionOnDemandStatus,
(const void **)&num) ||
if (connectionServiceID != NULL) {
*connectionServiceID = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandServiceID);
*connectionServiceID = isA_CFString(*connectionServiceID);
- if (*connectionServiceID != NULL) {
+ if ((*connectionServiceID != NULL) && (CFStringGetLength(*connectionServiceID) > 0)) {
CFRetain(*connectionServiceID);
- }
+ } else {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("OnDemand%s configuration error, no serviceID"),
+ onDemandRetry ? " (on retry)" : "");
+ *connectionServiceID = NULL;
+ ok = FALSE;
+ }
}
if (vpnRemoteAddress != NULL) {
*vpnRemoteAddress = CFDictionaryGetValue(trigger, kSCNetworkConnectionOnDemandRemoteAddress);
*vpnRemoteAddress = isA_CFString(*vpnRemoteAddress);
- if (*vpnRemoteAddress != NULL) {
+ if ((*vpnRemoteAddress != NULL) && (CFStringGetLength(*vpnRemoteAddress) > 0)) {
CFRetain(*vpnRemoteAddress);
+ } else {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("OnDemand%s configuration error, no server address"),
+ onDemandRetry ? " (on retry)" : "");
+
+ *vpnRemoteAddress = NULL;
+ ok = FALSE;
}
}
+ if (!ok) {
+ if ((connectionServiceID != NULL) && (*connectionServiceID != NULL)) {
+ CFRelease(*connectionServiceID);
+ *connectionServiceID = NULL;
+ }
+ if ((vpnRemoteAddress != NULL) && (*vpnRemoteAddress != NULL)) {
+ CFRelease(*vpnRemoteAddress);
+ *vpnRemoteAddress = NULL;
+ }
+ continue;
+ }
+
if (_sc_debug || (debug > 0)) {
SCLog(TRUE, LOG_INFO,
CFSTR("OnDemand%s match, connection status = %d"),
onDemandStatus);
}
- ok = TRUE;
goto done;
}
}
catchAllConfig = configIndex;
}
- if (domainEndsWithDomain(hostName, domain)) {
+ if (_SC_domainEndsWithDomain(hostName, domain)) {
// found matching configuration
*serviceID = serviceName;
CFRetain(*serviceID);
/*
- * Copyright (c) 2006-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2006-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
}
-static CFDictionaryRef
+static CF_RETURNS_RETAINED CFDictionaryRef
setCurrentCallout(CFStringRef serviceID,
CFDictionaryRef current,
void *context1,
}
-static CFDictionaryRef
+static CF_RETURNS_RETAINED CFDictionaryRef
setNameCallout(CFStringRef serviceID,
CFDictionaryRef current,
void *context1,
}
-static CFDictionaryRef
+static CF_RETURNS_RETAINED CFDictionaryRef
setInterfaceConfigurationCallout(CFStringRef serviceID,
CFDictionaryRef current,
void *context1,
Boolean
SCNetworkConnectionResume (SCNetworkConnectionRef connection) __OSX_AVAILABLE_STARTING(__MAC_10_3,__IPHONE_2_0);
+Boolean
+SCNetworkConnectionSetClientInfo (SCNetworkConnectionRef connection,
+ mach_port_t client_audit_session,
+ uid_t client_uid,
+ gid_t client_gid,
+ pid_t client_pid) __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_5_0);
+
#pragma mark -
#pragma mark SCNetworkConnection "VPN on Demand" SPIs
#define kSCNetworkConnectionOnDemandMatchDomainsNever CFSTR("OnDemandMatchDomainsNever")
-__private_extern__
Boolean
__SCNetworkConnectionCopyOnDemandInfoWithName (SCDynamicStoreRef *storeP,
CFStringRef nodeName,
/*
- * Copyright (c) 2004-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
NULL, // localization arg2
NULL, // [layered] interface
NULL, // prefs
+ NULL, // store
NULL, // serviceID
NULL, // unsaved
NULL, // entity_device
NULL, // localization arg2
NULL, // [layered] interface
NULL, // prefs
+ NULL, // store
NULL, // serviceID
NULL, // unsaved
NULL, // entity_device
if (interfacePrivate->prefs != NULL)
CFRelease(interfacePrivate->prefs);
+ if (interfacePrivate->store != NULL)
+ CFRelease(interfacePrivate->store);
+
if (interfacePrivate->serviceID != NULL)
CFRelease(interfacePrivate->serviceID);
interfacePrivate->localized_arg2 = NULL;
interfacePrivate->interface = (interface != NULL) ? CFRetain(interface) : NULL;
interfacePrivate->prefs = (prefs != NULL) ? CFRetain(prefs) : NULL;
+ interfacePrivate->store = NULL;
interfacePrivate->serviceID = (serviceID != NULL) ? CFRetain(serviceID) : NULL;
interfacePrivate->unsaved = NULL;
interfacePrivate->entity_device = NULL;
}
// check the link type and hwassist flags
- ifm = (struct if_msghdr *)buf;
+ // ALIGN: buf is aligned
+ ifm = (struct if_msghdr *)(void *)buf;
switch (ifm->ifm_type) {
case RTM_IFINFO : {
#if defined(IF_HWASSIST_VLAN_TAGGING) && defined(IF_HWASSIST_VLAN_MTU)
#pragma mark Interface ordering
-static CFArrayRef
+static CF_RETURNS_RETAINED CFArrayRef
split_path(CFStringRef path)
{
CFArrayRef components;
};
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
pci_slot(io_registry_entry_t interface, CFTypeRef *pci_slot_name)
{
kern_return_t kr;
}
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
pci_port(CFTypeRef slot_name, int ift, CFStringRef bsdName)
{
CFIndex n;
}
-static CFArrayRef
+static CF_RETURNS_RETAINED CFArrayRef
findMatchingInterfaces(CFDictionaryRef matching, processInterface func)
{
CFMutableArrayRef interfaces;
}
-static CFArrayRef
+static CF_RETURNS_RETAINED CFArrayRef
extendedConfigurationTypes(SCNetworkInterfaceRef interface)
{
CFIndex i;
return NULL;
}
+#if !TARGET_OS_IPHONE
static SCNetworkInterfaceRef
findBondInterface(SCPreferencesRef prefs, CFStringRef ifDevice)
{
}
return interface;
}
+#endif // !TARGET_OS_IPHONE
static SCNetworkInterfaceRef
findBridgeInterface(SCPreferencesRef prefs, CFStringRef ifDevice)
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(entity, kSCPropNetInterfaceDeviceName, bsdName);
+#if !TARGET_OS_IPHONE
if ((flags & kIncludeBondInterfaces) == 0) {
CFDictionarySetValue(entity, CFSTR("_NO_BOND_INTERFACES_"), kCFBooleanTrue);
}
+#endif // !TARGET_OS_IPHONE
if ((flags & kIncludeBridgeInterfaces) == 0) {
CFDictionarySetValue(entity, CFSTR("_NO_BRIDGE_INTERFACES_"), kCFBooleanTrue);
if (prefs == NULL) {
break;
}
+#if !TARGET_OS_IPHONE
if (!CFDictionaryContainsKey(interface_entity, CFSTR("_NO_BOND_INTERFACES_"))) {
interfacePrivate = (SCNetworkInterfacePrivateRef)findBondInterface(prefs, ifDevice);
}
-
+#endif // !TARGET_OS_IPHONE
if ((interfacePrivate == NULL)
&& !CFDictionaryContainsKey(interface_entity, CFSTR("_NO_BRIDGE_INTERFACES_"))) {
interfacePrivate = (SCNetworkInterfacePrivateRef)findBridgeInterface(prefs, ifDevice);
__SCNetworkInterfaceSetService((SCNetworkInterfaceRef)interfacePrivate,
service);
+#if !TARGET_OS_IPHONE
// set prefs & serviceID to Bond member interfaces
if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBond)) {
CFIndex i;
__SCNetworkInterfaceSetService(member, service);
}
}
+#endif // !TARGET_OS_IPHONE
// set prefs & serviceID to Bridge member interfaces
if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBridge)) {
}
+#if !TARGET_OS_IPHONE
+static void
+addBTPANInterface(SCPreferencesRef prefs, CFMutableArrayRef all_interfaces)
+{
+ CFIndex i;
+ CFIndex n;
+ CFArrayRef services;
+
+ n = CFArrayGetCount(all_interfaces);
+ for (i = 0; i < n; i++) {
+ SCNetworkInterfaceRef interface;
+
+ interface = CFArrayGetValueAtIndex(all_interfaces, i);
+ if (_SCNetworkInterfaceIsBluetoothPAN(interface)) {
+ // if we already have a BT-PAN interface
+ return;
+ }
+ }
+
+ services = SCNetworkServiceCopyAll(prefs);
+ if (services != NULL) {
+ n = CFArrayGetCount(services);
+ for (i = 0; i < n; i++) {
+ SCNetworkInterfaceRef interface;
+ SCNetworkServiceRef service;
+
+ service = CFArrayGetValueAtIndex(services, i);
+ interface = SCNetworkServiceGetInterface(service);
+ if ((interface != NULL) &&
+ _SCNetworkInterfaceIsBluetoothPAN(interface)) {
+ // include BT-PAN interface
+ CFArrayAppendValue(all_interfaces, interface);
+ break;
+ }
+ }
+
+ CFRelease(services);
+ }
+
+ return;
+}
+#endif // !TARGET_OS_IPHONE
+
+
static void
add_interfaces(CFMutableArrayRef all_interfaces, CFArrayRef new_interfaces)
{
}
}
if (prefs != NULL) {
+#if !TARGET_OS_IPHONE
new_interfaces = SCBondInterfaceCopyAll(prefs);
if (new_interfaces != NULL) {
add_interfaces(all_interfaces, new_interfaces);
CFRelease(new_interfaces);
}
+#endif // !TARGET_OS_IPHONE
new_interfaces = SCBridgeInterfaceCopyAll(prefs);
if (new_interfaces != NULL) {
CFRelease(new_interfaces);
}
+#if !TARGET_OS_IPHONE
+ // add BT-PAN interface
+ addBTPANInterface(prefs, all_interfaces);
+#endif // !TARGET_OS_IPHONE
+
if (temp_preferences) CFRelease(prefs);
}
{
CFStringRef key;
Boolean ok = FALSE;
- SCDynamicStoreRef store;
if (!isA_CFString(ifName)) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
- store = SCDynamicStoreCreate(NULL, CFSTR("_SCNetworkInterfaceForceConfigurationRefresh"), NULL, NULL);
- if (store == NULL) {
- return FALSE;
- }
-
key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
kSCDynamicStoreDomainState,
ifName,
kSCEntNetRefreshConfiguration);
- ok = SCDynamicStoreNotifyValue(store, key);
+ ok = SCDynamicStoreNotifyValue(NULL, key);
CFRelease(key);
- CFRelease(store);
return ok;
}
members = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+#if !TARGET_OS_IPHONE
// add Bond [member] interfaces
interfaces = SCBondInterfaceCopyAll(prefs);
if (interfaces != NULL) {
__SCBondInterfaceListCollectMembers(interfaces, members);
CFRelease(interfaces);
}
+#endif // !TARGET_OS_IPHONE
// add Bridge [member] interfaces
interfaces = SCBridgeInterfaceCopyAll(prefs);
return;
}
+
+
+SCNetworkInterfaceRef
+_SCNetworkInterfaceCopyActive(SCDynamicStoreRef store, CFStringRef bsdName)
+{
+ SCNetworkInterfaceRef interface;
+
+ interface = _SCNetworkInterfaceCreateWithBSDName(NULL, bsdName, kIncludeAllVirtualInterfaces);
+ if (interface == NULL) {
+ return NULL;
+ }
+
+ if (store != NULL) {
+ SCNetworkInterfacePrivateRef interfacePrivate =
+ (SCNetworkInterfacePrivateRef)interface;
+
+ CFRetain(store);
+ interfacePrivate->store = store;
+ }
+
+ return interface;
+}
+
+
+SCNetworkServicePrimaryRank
+SCNetworkInterfaceGetPrimaryRank(SCNetworkInterfaceRef interface)
+{
+ CFDictionaryRef entity;
+ SCNetworkInterfacePrivateRef interfacePrivate =
+ (SCNetworkInterfacePrivateRef)interface;
+ CFStringRef ifName;
+ Boolean ok = FALSE;
+ CFStringRef path;
+ SCNetworkServicePrimaryRank rank = kSCNetworkServicePrimaryRankDefault;
+ SCDynamicStoreRef session;
+
+ ifName = SCNetworkInterfaceGetBSDName(interface);
+ if ((ifName == NULL) || (interfacePrivate->store == NULL)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return rank;
+ }
+
+ session = interfacePrivate->store;
+
+ path = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ ifName,
+ kSCEntNetService);
+ entity = SCDynamicStoreCopyValue(session, path);
+ CFRelease(path);
+
+ if (entity != NULL) {
+ if (isA_CFDictionary(entity)) {
+ CFStringRef rankStr =
+ CFDictionaryGetValue(entity, kSCPropNetServicePrimaryRank);
+ ok = __str_to_rank(rankStr, &rank);
+ }
+ CFRelease(entity);
+ }
+
+ if (!ok) {
+ rank = kSCNetworkServicePrimaryRankDefault;
+ _SCErrorSet(kSCStatusInvalidArgument);
+ } else if (rank == kSCNetworkServicePrimaryRankDefault) {
+ _SCErrorSet(kSCStatusOK);
+ }
+
+ return (rank);
+}
+
+Boolean
+SCNetworkInterfaceSetPrimaryRank(SCNetworkInterfaceRef interface,
+ SCNetworkServicePrimaryRank newRank)
+{
+ CFDictionaryRef entity;
+ SCNetworkInterfacePrivateRef interfacePrivate =
+ (SCNetworkInterfacePrivateRef)interface;
+ CFStringRef ifName;
+ CFMutableDictionaryRef newEntity;
+ Boolean ok = TRUE;
+ CFStringRef path = NULL;
+ CFStringRef rankStr;
+ SCDynamicStoreRef session;
+
+ ifName = SCNetworkInterfaceGetBSDName(interface);
+ if ((ifName == NULL) || (interfacePrivate->store == NULL)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ session = interfacePrivate->store;
+
+ ok = __rank_to_str(newRank, &rankStr);
+ if (!ok) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ path = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ ifName,
+ kSCEntNetService);
+
+ entity = SCDynamicStoreCopyValue(session, path);
+ if (entity != NULL) {
+ if (!isA_CFDictionary(entity)) {
+ CFRelease(entity);
+ _SCErrorSet(kSCStatusFailed);
+ goto done;
+ }
+ newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
+ CFRelease(entity);
+ } else {
+ newEntity = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ if (rankStr != NULL) {
+ CFDictionarySetValue(newEntity, kSCPropNetServicePrimaryRank, rankStr);
+ } else {
+ CFDictionaryRemoveValue(newEntity, kSCPropNetServicePrimaryRank);
+ }
+
+ if (CFDictionaryGetCount(newEntity) > 0) {
+ ok = SCDynamicStoreSetValue(session, path, newEntity);
+ } else {
+ ok = SCDynamicStoreRemoveValue(session, path);
+ }
+
+ CFRelease(newEntity);
+
+ done :
+
+ if (path != NULL) CFRelease(path);
+ return ok;
+}
/*
- * Copyright (c) 2003-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
* Modification History
*
+ * April 12, 2011 Allan Nathanson <ajn@apple.com>
+ * - add SCNetworkReachability "server"
+ *
* March 31, 2004 Allan Nathanson <ajn@apple.com>
* - use [SC] DNS configuration information
*
#include <TargetConditionals.h>
#include <sys/cdefs.h>
#include <dispatch/dispatch.h>
+#include <dispatch/private.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFRuntime.h>
#include <SystemConfiguration/SystemConfiguration.h>
#define s6_addr16 __u6_addr.__u6_addr16
#endif
+#include "SCNetworkReachabilityInternal.h"
+
#include <ppp/ppp_msg.h>
#if !TARGET_IPHONE_SIMULATOR
+#define DEBUG_REACHABILITY_TYPE_NAME "create w/name"
+#define DEBUG_REACHABILITY_TYPE_NAME_OPTIONS " + options"
+
+#define DEBUG_REACHABILITY_TYPE_ADDRESS "create w/address"
+#define DEBUG_REACHABILITY_TYPE_ADDRESS_OPTIONS " + options"
+
+#define DEBUG_REACHABILITY_TYPE_ADDRESSPAIR "create w/address pair"
+#define DEBUG_REACHABILITY_TYPE_ADDRESSPAIR_OPTIONS " + options"
+
+
+static pthread_mutexattr_t lock_attr;
+
+#define MUTEX_INIT(m) { \
+ int _lock_ = (pthread_mutex_init(m, &lock_attr) == 0); \
+ assert(_lock_); \
+}
+
+#define MUTEX_LOCK(m) { \
+ int _lock_ = (pthread_mutex_lock(m) == 0); \
+ assert(_lock_); \
+}
+
+#define MUTEX_UNLOCK(m) { \
+ int _unlock_ = (pthread_mutex_unlock(m) == 0); \
+ assert(_unlock_); \
+}
+
+#define MUTEX_ASSERT_HELD(m) { \
+ int _locked_ = (pthread_mutex_lock(m) == EDEADLK); \
+ assert(_locked_); \
+}
+
+
#ifdef HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL
/* Libinfo SPI */
mach_port_t
#endif /* HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL */
-#define kSCNetworkReachabilityFlagsFirstResolvePending (1<<31)
+#define SCNETWORKREACHABILITY_TRIGGER_KEY CFSTR("com.apple.SCNetworkReachability:FORCE-CHANGE")
-#define N_QUICK 64
-
-
-typedef enum { NO = 0, YES, UNKNOWN } lazyBoolean;
+// how long (minimum time, us) to wait before retrying DNS query after EAI_NONAME
+#define EAI_NONAME_RETRY_DELAY_USEC 250000 // 250ms
+// how long (maximum time, us) after DNS configuration change we accept EAI_NONAME
+// without question.
+#define EAI_NONAME_RETRY_LIMIT_USEC 2500000 // 2.5s
-typedef enum {
- reachabilityTypeAddress,
- reachabilityTypeAddressPair,
- reachabilityTypeName
-} addressType;
+// how long (maximum time, ns) to wait for a long-lived-query callback before
+// we assume EAI_NONAME.
+#define LLQ_TIMEOUT_NSEC 30 * NSEC_PER_SEC // 30s
-// how long (minimum time, us) to wait before retrying DNS query after EAI_NONAME
-#define EAI_NONAME_RETRY_DELAY_USEC 250000
-// how long (maximum time, us) after DNS configuration change we accept EAI_NONAME
-// without question.
-#define EAI_NONAME_RETRY_LIMIT_USEC 2500000
+#define N_QUICK 64
static CFStringRef __SCNetworkReachabilityCopyDescription (CFTypeRef cf);
static void __SCNetworkReachabilityDeallocate (CFTypeRef cf);
-static void rlsPerform(void *info);
+static void reachPerform (void *info);
static Boolean
Boolean onDemand);
-typedef struct {
- SCNetworkReachabilityFlags flags;
- unsigned int if_index;
- Boolean sleeping;
-} ReachabilityInfo;
-
-
-typedef struct {
-
- /* base CFType information */
- CFRuntimeBase cfBase;
-
- /* lock */
- pthread_mutex_t lock;
-
- /* address type */
- addressType type;
-
- /* target host name */
- const char *name;
- const char *serv;
- struct addrinfo hints;
- Boolean needResolve;
- CFArrayRef resolvedAddress; /* CFArray[CFData] */
- int resolvedAddressError;
-
- /* [scoped routing] interface constraints */
- unsigned int if_index;
- char if_name[IFNAMSIZ];
-
- /* local & remote addresses */
- struct sockaddr *localAddress;
- struct sockaddr *remoteAddress;
-
- /* current reachability flags */
- ReachabilityInfo info;
- ReachabilityInfo last_notify;
-
- /* run loop source, callout, context, rl scheduling info */
- Boolean scheduled;
- CFRunLoopSourceRef rls;
- SCNetworkReachabilityCallBack rlsFunction;
- SCNetworkReachabilityContext rlsContext;
- CFMutableArrayRef rlList;
-
- dispatch_queue_t dispatchQueue; // SCNetworkReachabilitySetDispatchQueue
- dispatch_queue_t asyncDNSQueue;
- dispatch_source_t asyncDNSSource;
-
- /* [async] DNS query info */
- Boolean haveDNS;
- mach_port_t dnsMP;
- CFMachPortRef dnsPort;
- CFRunLoopSourceRef dnsRLS;
- struct timeval dnsQueryStart;
- struct timeval dnsQueryEnd;
- dispatch_source_t dnsRetry; // != NULL if DNS retry request queued
- int dnsRetryCount; // number of retry attempts
-
- /* [async] processing info */
- struct timeval last_dns;
-
- /* on demand info */
- Boolean onDemandBypass;
- CFStringRef onDemandName;
- CFStringRef onDemandRemoteAddress;
- SCNetworkReachabilityRef onDemandServer;
- CFStringRef onDemandServiceID;
-
-
- /* logging */
- char log_prefix[32];
-
-} SCNetworkReachabilityPrivate, *SCNetworkReachabilityPrivateRef;
-
-
static CFTypeID __kSCNetworkReachabilityTypeID = _kCFRuntimeNotATypeID;
static pthread_once_t initialized = PTHREAD_ONCE_INIT;
-static const ReachabilityInfo NOT_REACHABLE = { 0, 0, FALSE };
-static const ReachabilityInfo NOT_REPORTED = { 0xFFFFFFFF, 0, FALSE };
+static const ReachabilityInfo NOT_REACHABLE = { 0, 0, 0, { 0 }, FALSE };
+static const ReachabilityInfo NOT_REPORTED = { 0, 0xFFFFFFFF, 0, { 0 }, FALSE };
static int rtm_seq = 0;
+static const struct addrinfo HINTS_DEFAULT = {
+#ifdef AI_PARALLEL
+ .ai_flags = AI_ADDRCONFIG | AI_PARALLEL,
+#else // AI_PARALLEL
+ .ai_flags = AI_ADDRCONFIG,
+#endif // AI_PARALLEL
+};
+
+
static const struct timeval TIME_ZERO = { 0, 0 };
+static Boolean D_llqBypass = FALSE;
+static int llqCount = 0;
+static DNSServiceRef llqMain = NULL;
+static CFMutableSetRef llqUpdated = NULL;
+
+
+#ifdef HAVE_REACHABILITY_SERVER
+static Boolean D_serverBypass = FALSE;
+#endif // HAVE_REACHABILITY_SERVER
+
+
#if !TARGET_OS_IPHONE
/*
* Power capabilities (sleep/wake)
* host "something has changed" notifications
*/
-static pthread_mutex_t hn_lock = PTHREAD_MUTEX_INITIALIZER;
static SCDynamicStoreRef hn_store = NULL;
static dispatch_queue_t hn_dispatchQueue = NULL;
static CFMutableSetRef hn_targets = NULL;
static Boolean dns_token_valid = FALSE;
-static __inline__ CFTypeRef
-isA_SCNetworkReachability(CFTypeRef obj)
-{
- return (isA_CFType(obj, SCNetworkReachabilityGetTypeID()));
-}
+typedef enum {
+ dns_query_sync,
+ dns_query_async,
+ dns_query_llq
+} dns_query_type;
static void
static void
__dns_query_end(SCNetworkReachabilityRef target,
Boolean found,
- Boolean async,
+ dns_query_type query_type,
struct timeval *dnsQueryStart,
struct timeval *dnsQueryEnd)
{
struct timeval dnsQueryElapsed;
+ Boolean firstQuery;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+ // report initial or updated query time
+ firstQuery = !timerisset(dnsQueryEnd);
+
(void) gettimeofday(dnsQueryEnd, NULL);
if (!_sc_debug) {
return;
}
- if (dnsQueryStart->tv_sec == 0) {
+ if (!timerisset(dnsQueryStart)) {
return;
}
timersub(dnsQueryEnd, dnsQueryStart, &dnsQueryElapsed);
- SCLog(TRUE, LOG_INFO,
- CFSTR("%s%ssync DNS complete%s (query time = %d.%3.3d)"),
- targetPrivate->log_prefix,
- async ? "a" : "",
- found ? "" : ", host not found",
- dnsQueryElapsed.tv_sec,
- dnsQueryElapsed.tv_usec / 1000);
+ switch (query_type) {
+
+// #define QUERY_TIME__FMT "%d.%3.3d"
+// #define QUERY_TIME__DIV 1000
+
+ #define QUERY_TIME__FMT "%d.%6.6d"
+ #define QUERY_TIME__DIV 1
+
+ case dns_query_sync :
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("%ssync DNS complete%s (query time = " QUERY_TIME__FMT ")"),
+ targetPrivate->log_prefix,
+ found ? "" : ", host not found",
+ dnsQueryElapsed.tv_sec,
+ dnsQueryElapsed.tv_usec / QUERY_TIME__DIV);
+ break;
+ case dns_query_async :
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("%sasync DNS complete%s (query time = " QUERY_TIME__FMT ")"),
+ targetPrivate->log_prefix,
+ found ? "" : ", host not found",
+ dnsQueryElapsed.tv_sec,
+ dnsQueryElapsed.tv_usec / QUERY_TIME__DIV);
+ break;
+ case dns_query_llq :
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("%sDNS updated%s (%s = " QUERY_TIME__FMT ")"),
+ targetPrivate->log_prefix,
+ found ? "" : ", host not found",
+ firstQuery ? "query time" : "updated after",
+ dnsQueryElapsed.tv_sec,
+ dnsQueryElapsed.tv_usec / QUERY_TIME__DIV);
+ break;
+ }
return;
}
static __inline__ Boolean
-__reach_equal(ReachabilityInfo *r1, ReachabilityInfo *r2)
+__reach_changed(ReachabilityInfo *r1, ReachabilityInfo *r2)
{
if (r1->flags != r2->flags) {
// if the reachability flags changed
- return FALSE;
+ return TRUE;
}
if (r1->if_index != r2->if_index) {
// if the target interface changed
- return FALSE;
+ return TRUE;
}
if ((r1->sleeping != r2->sleeping) && !r2->sleeping) {
// if our sleep/wake status changed and if we
// are no longer sleeping
- return FALSE;
+ return TRUE;
}
- return TRUE;
+ return FALSE;
+}
+
+
+static __inline__ void
+_reach_set(ReachabilityInfo *dst, const ReachabilityInfo *src, uint64_t cycle)
+{
+ memcpy(dst, src, sizeof(ReachabilityInfo));
+ dst->cycle = cycle;
+
+ return;
}
+#pragma mark -
+#pragma mark SCDynamicStore info
+
+
typedef struct {
SCDynamicStoreRef store;
- Boolean storeAdded;
CFStringRef entity;
CFDictionaryRef dict;
CFIndex n;
} ReachabilityStoreInfo, *ReachabilityStoreInfoRef;
+static ReachabilityStoreInfo S_storeInfo = { 0 };
+static Boolean S_storeInfoActive = FALSE;
+
+
+static dispatch_queue_t
+_storeInfo_queue()
+{
+ static dispatch_once_t once;
+ static dispatch_queue_t q;
+
+ dispatch_once(&once, ^{
+ q = dispatch_queue_create("SCNetworkReachabilty.storeInfo", NULL);
+ });
+
+ return q;
+}
+
+
static void
-initReachabilityStoreInfo(ReachabilityStoreInfoRef store_info)
+ReachabilityStoreInfo_copy(ReachabilityStoreInfoRef src,
+ ReachabilityStoreInfoRef dst)
{
- bzero(store_info, sizeof(ReachabilityStoreInfo));
+ if (src->dict != NULL) {
+ dst->store = src->store;
+ CFRetain(dst->store);
+
+ dst->dict = src->dict;
+ CFRetain(dst->dict);
+
+ dst->n = src->n;
+ if (dst->n > 0) {
+ if (dst->n <= (CFIndex)(sizeof(dst->keys_q) / sizeof(CFTypeRef))) {
+ dst->keys = dst->keys_q;
+ dst->values = dst->values_q;
+ } else {
+ dst->keys = CFAllocatorAllocate(NULL, dst->n * sizeof(CFTypeRef), 0);
+ dst->values = CFAllocatorAllocate(NULL, dst->n * sizeof(CFTypeRef), 0);
+ }
+ memcpy(dst->keys, src->keys, dst->n * sizeof(CFTypeRef));
+ memcpy(dst->values, src->values, dst->n * sizeof(CFTypeRef));
+ }
+ }
+
return;
}
-static Boolean
-updateReachabilityStoreInfo(ReachabilityStoreInfoRef store_info,
- SCDynamicStoreRef *storeP,
- sa_family_t sa_family)
+static void
+ReachabilityStoreInfo_enable(Boolean enable)
{
- CFStringRef pattern;
- CFMutableArrayRef patterns;
+ dispatch_sync(_storeInfo_queue(), ^{
+ S_storeInfoActive = enable;
+ });
- switch (sa_family) {
- case AF_UNSPEC :
- store_info->entity = NULL;
- break;
- case AF_INET :
- store_info->entity = kSCEntNetIPv4;
- break;
- case AF_INET6 :
- store_info->entity = kSCEntNetIPv6;
- break;
- default :
- return FALSE;
+ return;
+}
+
+
+static void
+ReachabilityStoreInfo_free(ReachabilityStoreInfoRef store_info)
+{
+ if ((store_info->n > 0) && (store_info->keys != store_info->keys_q)) {
+ CFAllocatorDeallocate(NULL, store_info->keys);
+ store_info->keys = NULL;
+
+ CFAllocatorDeallocate(NULL, store_info->values);
+ store_info->values = NULL;
}
+ store_info->n = 0;
if (store_info->dict != NULL) {
- // if info already available
- return TRUE;
+ CFRelease(store_info->dict);
+ store_info->dict = NULL;
}
- if (store_info->store == NULL) {
- store_info->store = (storeP != NULL) ? *storeP : NULL;
- if (store_info->store == NULL) {
- store_info->store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkReachability"), NULL, NULL);
- if (store_info->store == NULL) {
- SCLog(TRUE, LOG_ERR, CFSTR("updateReachabilityStoreInfo SCDynamicStoreCreate() failed"));
- return FALSE;
- }
+ if (store_info->store != NULL) {
+ CFRelease(store_info->store);
+ store_info->store = NULL;
+ }
- if (storeP != NULL) {
- /// pass back the allocated SCDynamicStoreRef
- *storeP = store_info->store;
- } else {
- // this one is ours
- store_info->storeAdded = TRUE;
+ return;
+}
+
+
+static void
+ReachabilityStoreInfo_init(ReachabilityStoreInfoRef store_info)
+{
+ dispatch_sync(_storeInfo_queue(), ^{
+ bzero(store_info, sizeof(ReachabilityStoreInfo));
+
+ if (S_storeInfoActive && (S_storeInfo.dict != NULL)) {
+ ReachabilityStoreInfo_copy(&S_storeInfo, store_info);
+ }
+ });
+
+ return;
+}
+
+
+static void
+ReachabilityStoreInfo_save(ReachabilityStoreInfoRef store_info)
+{
+ dispatch_sync(_storeInfo_queue(), ^{
+ if ((store_info == NULL) ||
+ !_SC_CFEqual(store_info->dict, S_storeInfo.dict)) {
+ // free any old info
+ ReachabilityStoreInfo_free(&S_storeInfo);
+
+ // save new info
+ if (S_storeInfoActive &&
+ (store_info != NULL) &&
+ (store_info->dict != NULL)) {
+ ReachabilityStoreInfo_copy(store_info, &S_storeInfo);
}
}
- }
+ });
- if (sa_family == AF_UNSPEC) {
- // if the address family was not specified than
- // all we wanted, for now, was to establish the
- // SCDynamicStore session
- return TRUE;
- }
+ return;
+}
+
+
+static Boolean
+ReachabilityStoreInfo_fill(ReachabilityStoreInfoRef store_info)
+{
+ CFStringRef pattern;
+ CFMutableArrayRef patterns;
patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
-static void
-freeReachabilityStoreInfo(ReachabilityStoreInfoRef store_info)
+static Boolean
+ReachabilityStoreInfo_update(ReachabilityStoreInfoRef store_info,
+ SCDynamicStoreRef *storeP,
+ sa_family_t sa_family)
{
- if ((store_info->n > 0) && (store_info->keys != store_info->keys_q)) {
- CFAllocatorDeallocate(NULL, store_info->keys);
- store_info->keys = NULL;
+ __block Boolean ok = TRUE;
- CFAllocatorDeallocate(NULL, store_info->values);
- store_info->values = NULL;
+ switch (sa_family) {
+ case AF_UNSPEC :
+ store_info->entity = NULL;
+ break;
+ case AF_INET :
+ store_info->entity = kSCEntNetIPv4;
+ break;
+ case AF_INET6 :
+ store_info->entity = kSCEntNetIPv6;
+ break;
+ default :
+ return FALSE;
}
if (store_info->dict != NULL) {
- CFRelease(store_info->dict);
- store_info->dict = NULL;
+ // if info already available
+ return TRUE;
}
- if (store_info->storeAdded && (store_info->store != NULL)) {
- CFRelease(store_info->store);
- store_info->store = NULL;
- }
+ dispatch_sync(_storeInfo_queue(), ^{
+ if (S_storeInfoActive && (S_storeInfo.dict != NULL)) {
+ // free any info
+ ReachabilityStoreInfo_free(store_info);
- return;
+ // copy the shared/available info
+ ReachabilityStoreInfo_copy(&S_storeInfo, store_info);
+ }
+
+ if (store_info->store == NULL) {
+ store_info->store = (storeP != NULL) ? *storeP : NULL;
+ if (store_info->store != NULL) {
+ // keep a reference to the passed in SCDynamicStore
+ CFRetain(store_info->store);
+ } else {
+ store_info->store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkReachability"), NULL, NULL);
+ if (store_info->store == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("ReachabilityStoreInfo_update SCDynamicStoreCreate() failed"));
+ return;
+ }
+
+ if (storeP != NULL) {
+ // and pass back a reference
+ *storeP = store_info->store;
+ CFRetain(*storeP);
+ }
+ }
+ }
+
+ if (sa_family == AF_UNSPEC) {
+ // if the address family was not specified than
+ // all we wanted, for now, was to establish the
+ // SCDynamicStore session
+ return;
+ }
+
+ if (store_info->dict != NULL) {
+ // or we have picked up the shared info
+ return;
+ }
+
+ ok = ReachabilityStoreInfo_fill(store_info);
+ if (!ok) {
+ return;
+ }
+
+ if (!_SC_CFEqual(store_info->dict, S_storeInfo.dict)) {
+ // free any old info
+ ReachabilityStoreInfo_free(&S_storeInfo);
+
+ // save new info
+ if (S_storeInfoActive &&
+ (store_info->dict != NULL)) {
+ ReachabilityStoreInfo_copy(store_info, &S_storeInfo);
+ }
+ }
+ });
+
+ return ok;
}
+#pragma mark -
+#pragma mark PPP info
+
+
static int
updatePPPStatus(ReachabilityStoreInfoRef store_info,
const struct sockaddr *sa,
CFStringRef ppp_if;
int sc_status = kSCStatusNoKey;
- if (!updateReachabilityStoreInfo(store_info, NULL, sa->sa_family)) {
+ if (!ReachabilityStoreInfo_update(store_info, NULL, sa->sa_family)) {
return kSCStatusReachabilityUnknown;
}
CFIndex i;
int sc_status = kSCStatusNoKey;
- if (!updateReachabilityStoreInfo(store_info,
+ if (!ReachabilityStoreInfo_update(store_info,
NULL,
(sa != NULL) ? sa->sa_family : AF_INET)) {
return kSCStatusReachabilityUnknown;
}
+#pragma mark -
+#pragma mark VPN info
+
+
#if !TARGET_IPHONE_SIMULATOR
static int
updateVPNStatus(ReachabilityStoreInfoRef store_info,
CFStringRef vpn_if;
int sc_status = kSCStatusNoKey;
- if (!updateReachabilityStoreInfo(store_info, NULL, sa->sa_family)) {
+ if (!ReachabilityStoreInfo_update(store_info, NULL, sa->sa_family)) {
return kSCStatusReachabilityUnknown;
}
CFIndex i;
int sc_status = kSCStatusNoKey;
- if (!updateReachabilityStoreInfo(store_info,
+ if (!ReachabilityStoreInfo_update(store_info,
NULL,
(sa != NULL) ? sa->sa_family : AF_INET)) {
return kSCStatusReachabilityUnknown;
#endif // !TARGET_IPHONE_SIMULATOR
+#pragma mark -
+#pragma mark IPSec info
+
+
static int
updateIPSecStatus(ReachabilityStoreInfoRef store_info,
const struct sockaddr *sa,
CFStringRef ipsec_if;
int sc_status = kSCStatusNoKey;
- if (!updateReachabilityStoreInfo(store_info, NULL, sa->sa_family)) {
+ if (!ReachabilityStoreInfo_update(store_info, NULL, sa->sa_family)) {
return kSCStatusReachabilityUnknown;
}
+#pragma mark -
+#pragma mark Reachability engine
+
+
#define ROUNDUP(a, size) \
(((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
typedef struct {
- char buf[BUFLEN];
+ union {
+ char bytes[BUFLEN];
+ struct rt_msghdr rtm;
+ } buf;
int error;
struct sockaddr *rti_info[RTAX_MAX];
struct rt_msghdr *rtm;
bzero(info, sizeof(*info));
- info->rtm = (struct rt_msghdr *)&info->buf;
+ info->rtm = &info->buf.rtm;
info->rtm->rtm_msglen = sizeof(struct rt_msghdr);
info->rtm->rtm_version = RTM_VERSION;
#ifdef RTM_GET_SILENT
case AF_INET6: {
struct sockaddr_in6 *sin6;
- sin6 = (struct sockaddr_in6 *)address;
+ /* ALIGN: caller ensures that the address is aligned */
+ sin6 = (struct sockaddr_in6 *)(void *)address;
if ((IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) &&
(sin6->sin6_scope_id != 0)) {
while (TRUE) {
int n;
- n = read(rsock, (void *)&info->buf, sizeof(info->buf));
+ n = read(rsock, &info->buf, sizeof(info->buf));
if (n == -1) {
int error = errno;
return EINVAL;
}
- info->sdl = (struct sockaddr_dl *) info->rti_info[RTAX_IFP];
+ /* ALIGN: accessors are retrieving byte values, cast ok. */
+ info->sdl = (struct sockaddr_dl *)(void *) info->rti_info[RTAX_IFP];
if ((info->sdl->sdl_nlen == 0) || (info->sdl->sdl_nlen > IFNAMSIZ)) {
/* no interface name */
return EHOSTUNREACH;
char *statusMessage = NULL;
struct sockaddr_in v4mapped;
- *reach_info = NOT_REACHABLE;
+ _reach_set(reach_info, &NOT_REACHABLE, reach_info->cycle);
if (address == NULL) {
/* special case: check only for available paths off the system */
}
if (address->sa_family == AF_INET6) {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)address;
+ /* ALIGN: sin6_addr accessed aligned, cast ok. */
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(void *)address;
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
bzero(&v4mapped, sizeof(v4mapped));
switch (address->sa_family) {
case AF_INET :
- addr1 = &((struct sockaddr_in *)address)->sin_addr;
- addr2 = &((struct sockaddr_in *)info.rti_info[RTAX_IFA])->sin_addr;
+ /* ALIGN: cast ok, because only bcmp is used. */
+ addr1 = &((struct sockaddr_in *)(void *)address)->sin_addr;
+ addr2 = &((struct sockaddr_in *)(void *)info.rti_info[RTAX_IFA])->sin_addr;
len = sizeof(struct in_addr);
/*
* check if 0.0.0.0
*/
- if (((struct sockaddr_in *)address)->sin_addr.s_addr == 0) {
+ /* ALIGN: sin_addr should be aligned, cast ok. */
+ if (((struct sockaddr_in *)(void *)address)->sin_addr.s_addr == 0) {
statusMessage = "isReachable (this host)";
reach_info->flags |= kSCNetworkReachabilityFlagsIsLocalAddress;
}
break;
case AF_INET6 :
- addr1 = &((struct sockaddr_in6 *)address)->sin6_addr;
- addr2 = &((struct sockaddr_in6 *)info.rti_info[RTAX_IFA])->sin6_addr;
+ /* ALIGN: cast ok, because only bcmp is used. */
+ addr1 = &((struct sockaddr_in6 *)(void *)address)->sin6_addr;
+ addr2 = &((struct sockaddr_in6 *)(void *)info.rti_info[RTAX_IFA])->sin6_addr;
len = sizeof(struct in6_addr);
break;
default :
if_name,
(info.sdl->sdl_nlen <= IFNAMSIZ) ? info.sdl->sdl_nlen : IFNAMSIZ);
+ strlcpy(reach_info->if_name, if_name, sizeof(reach_info->if_name));
reach_info->if_index = info.sdl->sdl_index;
if (_sc_debug) {
#pragma mark SCNetworkReachability APIs
-static CFStringRef
-__SCNetworkReachabilityCopyDescription(CFTypeRef cf)
+static __inline__ CFTypeRef
+isA_SCNetworkReachability(CFTypeRef obj)
{
- CFAllocatorRef allocator = CFGetAllocator(cf);
- CFMutableStringRef result;
- SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)cf;
+ return (isA_CFType(obj, SCNetworkReachabilityGetTypeID()));
+}
- result = CFStringCreateMutable(allocator, 0);
- CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkReachability %p [%p]> {"), cf, allocator);
+
+CFStringRef
+_SCNetworkReachabilityCopyTargetDescription(SCNetworkReachabilityRef target)
+{
+ CFAllocatorRef allocator = CFGetAllocator(target);
+ CFMutableStringRef str;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ str = CFStringCreateMutable(allocator, 0);
switch (targetPrivate->type) {
case reachabilityTypeAddress :
case reachabilityTypeAddressPair : {
if (targetPrivate->localAddress != NULL) {
_SC_sockaddr_to_string(targetPrivate->localAddress, buf, sizeof(buf));
- CFStringAppendFormat(result, NULL, CFSTR("local address = %s"),
+ CFStringAppendFormat(str, NULL, CFSTR("local address = %s"),
buf);
}
if (targetPrivate->remoteAddress != NULL) {
_SC_sockaddr_to_string(targetPrivate->remoteAddress, buf, sizeof(buf));
- CFStringAppendFormat(result, NULL, CFSTR("%s%saddress = %s"),
+ CFStringAppendFormat(str, NULL, CFSTR("%s%saddress = %s"),
targetPrivate->localAddress ? ", " : "",
(targetPrivate->type == reachabilityTypeAddressPair) ? "remote " : "",
buf);
}
case reachabilityTypeName : {
if ((targetPrivate->name != NULL)) {
- CFStringAppendFormat(result, NULL, CFSTR("name = %s"), targetPrivate->name);
+ CFStringAppendFormat(str, NULL, CFSTR("name = %s"), targetPrivate->name);
}
if ((targetPrivate->serv != NULL)) {
- CFStringAppendFormat(result, NULL, CFSTR("%sserv = %s"),
+ CFStringAppendFormat(str, NULL, CFSTR("%sserv = %s"),
targetPrivate->name != NULL ? ", " : "",
targetPrivate->serv);
}
- if ((targetPrivate->resolvedAddress != NULL) || (targetPrivate->resolvedAddressError != NETDB_SUCCESS)) {
- if (targetPrivate->resolvedAddress != NULL) {
- if (isA_CFArray(targetPrivate->resolvedAddress)) {
- CFIndex i;
- CFIndex n = CFArrayGetCount(targetPrivate->resolvedAddress);
-
- CFStringAppendFormat(result, NULL, CFSTR(" ("));
- for (i = 0; i < n; i++) {
- CFDataRef address;
- char buf[64];
- struct sockaddr *sa;
-
- address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddress, i);
- sa = (struct sockaddr *)CFDataGetBytePtr(address);
- _SC_sockaddr_to_string(sa, buf, sizeof(buf));
- CFStringAppendFormat(result, NULL, CFSTR("%s%s"),
- i > 0 ? ", " : "",
- buf);
- }
- CFStringAppendFormat(result, NULL, CFSTR(")"));
- } else {
- CFStringAppendFormat(result, NULL, CFSTR(" (no addresses)"));
+ break;
+ }
+ }
+
+ return str;
+}
+
+
+CFStringRef
+_SCNetworkReachabilityCopyTargetFlags(SCNetworkReachabilityRef target)
+{
+ CFAllocatorRef allocator = CFGetAllocator(target);
+ CFStringRef str;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ str = CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("flags = 0x%08x, if_index = %hu%s"),
+ targetPrivate->info.flags,
+ targetPrivate->info.if_index,
+ targetPrivate->info.sleeping ? ", z" : "");
+ return str;
+}
+
+
+static CFStringRef
+__SCNetworkReachabilityCopyDescription(CFTypeRef cf)
+{
+ CFAllocatorRef allocator = CFGetAllocator(cf);
+ CFMutableStringRef result;
+ CFStringRef str;
+ SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)cf;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ result = CFStringCreateMutable(allocator, 0);
+ CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkReachability %p [%p]> {"), cf, allocator);
+
+ // add target description
+ str = _SCNetworkReachabilityCopyTargetDescription(target);
+ CFStringAppend(result, str);
+ CFRelease(str);
+
+ // add additional "name" info
+ if (targetPrivate->type == reachabilityTypeName) {
+ if (targetPrivate->dnsMP != MACH_PORT_NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(" (DNS query active)"));
+ } else if (targetPrivate->dnsRetry != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(" (DNS retry queued)"));
+ } else if ((targetPrivate->resolvedAddress != NULL) || (targetPrivate->resolvedAddressError != NETDB_SUCCESS)) {
+ if (targetPrivate->resolvedAddress != NULL) {
+ if (isA_CFArray(targetPrivate->resolvedAddress)) {
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(targetPrivate->resolvedAddress);
+
+ CFStringAppendFormat(result, NULL, CFSTR(" ("));
+ for (i = 0; i < n; i++) {
+ CFDataRef address;
+ char buf[64];
+ struct sockaddr *sa;
+
+ address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddress, i);
+ sa = (struct sockaddr *)CFDataGetBytePtr(address);
+ _SC_sockaddr_to_string(sa, buf, sizeof(buf));
+ CFStringAppendFormat(result, NULL, CFSTR("%s%s"),
+ i > 0 ? ", " : "",
+ buf);
}
- } else {
- CFStringAppendFormat(result, NULL, CFSTR(" (%s)"),
+ } else if (CFEqual(targetPrivate->resolvedAddress, kCFNull)) {
+ CFStringAppendFormat(result, NULL, CFSTR(" (%s"),
gai_strerror(targetPrivate->resolvedAddressError));
+ } else {
+ CFStringAppendFormat(result, NULL, CFSTR(" (no addresses"));
}
- } else if (targetPrivate->dnsPort != NULL) {
- CFStringAppendFormat(result, NULL, CFSTR(" (DNS query active)"));
+ } else {
+ CFStringAppendFormat(result, NULL, CFSTR(" (%s"),
+ gai_strerror(targetPrivate->resolvedAddressError));
}
- break;
+ if (targetPrivate->llqActive) {
+ CFStringAppendFormat(result, NULL, CFSTR("), DNS llq active"));
+ } else {
+ CFStringAppendFormat(result, NULL, CFSTR(")"));
+ }
+ } else if (targetPrivate->llqActive) {
+ CFStringAppendFormat(result, NULL, CFSTR(" (DNS llq active)"));
}
}
+
+ // add flags
if (targetPrivate->scheduled) {
- CFStringAppendFormat(result,
- NULL,
- CFSTR(", flags = 0x%08x, if_index = %hu"),
- targetPrivate->info.flags,
- targetPrivate->info.if_index);
+ str = _SCNetworkReachabilityCopyTargetFlags(target);
+ CFStringAppendFormat(result, NULL, CFSTR(", %@"), str);
+ CFRelease(str);
}
+
CFStringAppendFormat(result, NULL, CFSTR("}"));
return result;
static void
__SCNetworkReachabilityDeallocate(CFTypeRef cf)
{
- SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)cf;
+ SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)cf;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%srelease"),
targetPrivate->log_prefix);
+#ifdef HAVE_REACHABILITY_SERVER
+ /* disconnect from the reachability server */
+
+ if (targetPrivate->serverActive) {
+ __SCNetworkReachabilityServer_targetRemove(target);
+ }
+#endif // HAVE_REACHABILITY_SERVER
+
/* release resources */
pthread_mutex_destroy(&targetPrivate->lock);
CFRelease(targetPrivate->onDemandServiceID);
}
+#ifdef HAVE_REACHABILITY_SERVER
+ if (targetPrivate->serverDigest != NULL) {
+ CFRelease(targetPrivate->serverDigest);
+ }
+
+ if (targetPrivate->serverGroup != NULL) {
+ dispatch_release(targetPrivate->serverGroup);
+ }
+
+ if (targetPrivate->serverQueue != NULL) {
+ dispatch_release(targetPrivate->serverQueue);
+ }
+
+ if (targetPrivate->serverWatchers != NULL) {
+ CFRelease(targetPrivate->serverWatchers);
+ }
+#endif // HAVE_REACHABILITY_SERVER
+
return;
}
_sc_debug = TRUE;
}
+ // set per-process "bypass" of the SCNetworkReachability server
+ if (getenv("LONG_LIVED_QUERY_BYPASS") != NULL) {
+ D_llqBypass = TRUE;
+ }
+
+#ifdef HAVE_REACHABILITY_SERVER
+ // set per-process "bypass" of the SCNetworkReachability server
+ if (getenv("REACH_SERVER_BYPASS") != NULL) {
+ D_serverBypass = TRUE;
+ }
+#endif // HAVE_REACHABILITY_SERVER
+
+ pthread_mutexattr_init(&lock_attr);
+ pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_ERRORCHECK);
+
return;
}
+__private_extern__
+dispatch_queue_t
+__SCNetworkReachability_concurrent_queue()
+{
+ static dispatch_once_t once;
+ static dispatch_queue_t q;
+
+ dispatch_once(&once, ^{
+ q = dispatch_queue_create("SCNetworkReachabilty.concurrent",
+ DISPATCH_QUEUE_CONCURRENT);
+ dispatch_queue_set_width(q, 32);
+ });
+
+ return q;
+}
+
+
/*
- * __SCNetworkReachabilityPerformInline
+ * __SCNetworkReachabilityPerformInlineNoLock
*
- * Calls rlsPerform()
+ * Calls reachPerform()
* - caller must be holding a reference to the target
* - caller must *not* be holding the target lock
+ * - caller must be running on the __SCNetworkReachability_concurrent_queue()
*/
static __inline__ void
-__SCNetworkReachabilityPerformInline(SCNetworkReachabilityRef target, Boolean needResolve)
+__SCNetworkReachabilityPerformInlineNoLock(SCNetworkReachabilityRef target, Boolean needResolve)
{
dispatch_queue_t queue;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- pthread_mutex_lock(&targetPrivate->lock);
+ MUTEX_LOCK(&targetPrivate->lock);
if (needResolve) {
// allow the DNS query to be [re-]started
queue = targetPrivate->dispatchQueue;
if (queue != NULL) {
+ dispatch_group_t group;
+
dispatch_retain(queue);
- pthread_mutex_unlock(&targetPrivate->lock);
+ group = targetPrivate->dispatchGroup;
+ dispatch_group_enter(group);
+
+ MUTEX_UNLOCK(&targetPrivate->lock);
dispatch_sync(queue, ^{
- rlsPerform((void *)target);
+ reachPerform((void *)target);
+ dispatch_group_leave(group);
dispatch_release(queue);
});
} else {
_SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
}
- pthread_mutex_unlock(&targetPrivate->lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
+ }
+
+ return;
+}
+
+
+#ifdef HAVE_REACHABILITY_SERVER
+/*
+ * __SCNetworkReachabilityPerformNoLock
+ *
+ * Calls reachPerform()
+ * - caller must *not* be holding the target lock
+ * - caller must *not* running on the __SCNetworkReachability_concurrent_queue()
+ */
+__private_extern__
+void
+__SCNetworkReachabilityPerformNoLock(SCNetworkReachabilityRef target)
+{
+ CFRetain(target);
+ dispatch_async(__SCNetworkReachability_concurrent_queue(), ^{
+ __SCNetworkReachabilityPerformInlineNoLock(target, FALSE);
+ CFRelease(target);
+ });
+
+ return;
+}
+#endif // HAVE_REACHABILITY_SERVER
+
+
+/*
+ * __SCNetworkReachabilityPerformConcurrent
+ *
+ * Calls reachPerform()
+ * - caller must be holding the target lock
+ * - caller running on the __SCNetworkReachability_concurrent_queue()
+ */
+static __inline__ void
+__SCNetworkReachabilityPerformConcurrent(SCNetworkReachabilityRef target)
+{
+ dispatch_queue_t queue;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
+ queue = targetPrivate->dispatchQueue;
+ if (queue != NULL) {
+ dispatch_retain(queue);
+ CFRetain(target);
+ dispatch_group_async(targetPrivate->dispatchGroup, queue, ^{
+ reachPerform((void *)target);
+ CFRelease(target);
+ dispatch_release(queue);
+ });
+ } else {
+ if (targetPrivate->rls != NULL) {
+ CFRunLoopSourceSignal(targetPrivate->rls);
+ _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
+ }
}
return;
}
+/*
+ * __SCNetworkReachabilityPerform
+ *
+ * Calls reachPerform()
+ * - caller must be holding the target lock
+ * - caller not running on the __SCNetworkReachability_concurrent_queue()
+ */
static void
__SCNetworkReachabilityPerform(SCNetworkReachabilityRef target)
{
+ dispatch_queue_t queue;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- if (targetPrivate->dispatchQueue != NULL) {
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
+ queue = targetPrivate->dispatchQueue;
+ if (queue != NULL) {
+ dispatch_retain(queue);
CFRetain(target);
- dispatch_async(targetPrivate->dispatchQueue,
- ^{
- rlsPerform((void *)target);
- CFRelease(target);
- });
+ dispatch_group_async(targetPrivate->dispatchGroup, __SCNetworkReachability_concurrent_queue(), ^{
+ dispatch_sync(queue, ^{
+ reachPerform((void *)target);
+ CFRelease(target);
+ dispatch_release(queue);
+ });
+ });
} else if (targetPrivate->rls != NULL) {
CFRunLoopSourceSignal(targetPrivate->rls);
_SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
return;
}
+
static SCNetworkReachabilityPrivateRef
__SCNetworkReachabilityCreatePrivate(CFAllocatorRef allocator)
{
return NULL;
}
- pthread_mutex_init(&targetPrivate->lock, NULL);
+ MUTEX_INIT(&targetPrivate->lock);
targetPrivate->name = NULL;
targetPrivate->serv = NULL;
- bzero(&targetPrivate->hints, sizeof(targetPrivate->hints));
- targetPrivate->hints.ai_flags = AI_ADDRCONFIG;
-#ifdef AI_PARALLEL
- targetPrivate->hints.ai_flags |= AI_PARALLEL;
-#endif /* AI_PARALLEL */
-
+ targetPrivate->hints = HINTS_DEFAULT;
targetPrivate->needResolve = FALSE;
targetPrivate->resolvedAddress = NULL;
targetPrivate->resolvedAddressError = NETDB_SUCCESS;
targetPrivate->localAddress = NULL;
targetPrivate->remoteAddress = NULL;
+ targetPrivate->cycle = 1;
targetPrivate->info = NOT_REACHABLE;
targetPrivate->last_notify = NOT_REPORTED;
targetPrivate->dnsMP = MACH_PORT_NULL;
targetPrivate->dnsPort = NULL;
targetPrivate->dnsRLS = NULL;
+ targetPrivate->dnsSource = NULL;
targetPrivate->dnsQueryStart = TIME_ZERO;
targetPrivate->dnsQueryEnd = TIME_ZERO;
targetPrivate->dnsRetry = NULL;
targetPrivate->dnsRetryCount = 0;
targetPrivate->last_dns = TIME_ZERO;
+ targetPrivate->last_network = TIME_ZERO;
+#if !TARGET_OS_IPHONE
+ targetPrivate->last_power = TIME_ZERO;
+#endif // !TARGET_OS_IPHONE
+ targetPrivate->last_push = TIME_ZERO;
targetPrivate->onDemandBypass = FALSE;
targetPrivate->onDemandName = NULL;
targetPrivate->onDemandServiceID = NULL;
+ targetPrivate->llqActive = FALSE;
+ targetPrivate->llqBypass = D_llqBypass;
+ targetPrivate->llqTarget = NULL;
+ targetPrivate->llqTimer = NULL;
+
+#ifdef HAVE_REACHABILITY_SERVER
+ targetPrivate->serverActive = FALSE;
+ targetPrivate->serverBypass = D_serverBypass;
+ targetPrivate->serverScheduled = FALSE;
+ targetPrivate->serverInfo = NOT_REACHABLE;
+
+ targetPrivate->serverDigest = NULL;
+ targetPrivate->serverGroup = NULL;
+ targetPrivate->serverInfoValid = FALSE;
+ targetPrivate->serverQueryActive = 0;
+ targetPrivate->serverQueue = NULL;
+ targetPrivate->serverReferences = 0;
+ targetPrivate->serverWatchers = NULL;
+#endif // HAVE_REACHABILITY_SERVER
+
targetPrivate->log_prefix[0] = '\0';
if (_sc_log > 0) {
snprintf(targetPrivate->log_prefix,
targetPrivate->remoteAddress = CFAllocatorAllocate(NULL, address->sa_len, 0);
bcopy(address, targetPrivate->remoteAddress, address->sa_len);
- SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%screate w/address %@"),
+ SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%s%s %@"),
targetPrivate->log_prefix,
+ DEBUG_REACHABILITY_TYPE_ADDRESS,
targetPrivate);
return (SCNetworkReachabilityRef)targetPrivate;
bcopy(remoteAddress, targetPrivate->remoteAddress, remoteAddress->sa_len);
}
- SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%screate w/address pair %@"),
+ SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%s%s %@"),
targetPrivate->log_prefix,
+ DEBUG_REACHABILITY_TYPE_ADDRESSPAIR,
targetPrivate);
return (SCNetworkReachabilityRef)targetPrivate;
SCNetworkReachabilityCreateWithName(CFAllocatorRef allocator,
const char *nodename)
{
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } addr;
int nodenameLen;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
SCNetworkReachabilityPrivateRef targetPrivate;
if (nodename == NULL) {
return NULL;
}
- /* check if this "nodename" is really an IP[v6] address in disguise */
-
- bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
- if (inet_aton(nodename, &sin.sin_addr) == 1) {
- /* if IPv4 address */
- return SCNetworkReachabilityCreateWithAddress(allocator, (struct sockaddr *)&sin);
- }
-
- bzero(&sin6, sizeof(sin6));
- sin6.sin6_len = sizeof(sin6);
- sin6.sin6_family = AF_INET6;
- if (inet_pton(AF_INET6, nodename, &sin6.sin6_addr) == 1) {
- /* if IPv6 address */
- char *p;
-
- p = strchr(nodename, '%');
- if (p != NULL) {
- sin6.sin6_scope_id = if_nametoindex(p + 1);
- }
-
- return SCNetworkReachabilityCreateWithAddress(allocator, (struct sockaddr *)&sin6);
+ if (_SC_string_to_sockaddr(nodename, AF_UNSPEC, (void *)&addr, sizeof(addr)) != NULL) {
+ /* if this "nodename" is really an IP[v6] address in disguise */
+ return SCNetworkReachabilityCreateWithAddress(allocator, &addr.sa);
}
targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
targetPrivate->needResolve = TRUE;
targetPrivate->info.flags |= kSCNetworkReachabilityFlagsFirstResolvePending;
+#ifdef HAVE_REACHABILITY_SERVER
+ targetPrivate->serverInfo.flags |= kSCNetworkReachabilityFlagsFirstResolvePending;
+#endif // HAVE_REACHABILITY_SERVER
- SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%screate w/name %@"),
+ SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%s%s %@"),
targetPrivate->log_prefix,
+ DEBUG_REACHABILITY_TYPE_NAME,
targetPrivate);
return (SCNetworkReachabilityRef)targetPrivate;
{
const struct sockaddr *addr_l = NULL;
const struct sockaddr *addr_r = NULL;
- CFBooleanRef bypass;
CFDataRef data;
struct addrinfo *hints = NULL;
CFStringRef interface = NULL;
+ CFBooleanRef llqBypass;
CFStringRef nodename;
+ CFBooleanRef onDemandBypass;
+ CFBooleanRef resolverBypass;
+#ifdef HAVE_REACHABILITY_SERVER
+ CFBooleanRef serverBypass;
+#endif // HAVE_REACHABILITY_SERVER
CFStringRef servname;
SCNetworkReachabilityRef target;
SCNetworkReachabilityPrivateRef targetPrivate;
return NULL;
}
- hints = (struct addrinfo *)CFDataGetBytePtr(data);
+ /* ALIGN: CF aligns to >8 byte boundries */
+ hints = (struct addrinfo *)(void *)CFDataGetBytePtr(data);
if ((hints->ai_addrlen != 0) ||
(hints->ai_addr != NULL) ||
(hints->ai_canonname != NULL) ||
_SCErrorSet(kSCStatusInvalidArgument);
return NULL;
}
- bypass = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionConnectionOnDemandByPass);
- if ((bypass != NULL) && !isA_CFBoolean(bypass)) {
+ onDemandBypass = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionConnectionOnDemandBypass);
+ if ((onDemandBypass != NULL) && !isA_CFBoolean(onDemandBypass)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+ resolverBypass = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionResolverBypass);
+ if ((resolverBypass != NULL) && !isA_CFBoolean(resolverBypass)) {
_SCErrorSet(kSCStatusInvalidArgument);
return NULL;
}
+ llqBypass = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionLongLivedQueryBypass);
+ if ((llqBypass != NULL) && !isA_CFBoolean(llqBypass)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+
+#ifdef HAVE_REACHABILITY_SERVER
+ serverBypass = CFDictionaryGetValue(options, kSCNetworkReachabilityOptionServerBypass);
+ if ((serverBypass != NULL) && !isA_CFBoolean(serverBypass)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+#endif // HAVE_REACHABILITY_SERVER
+
if ((nodename != NULL) || (servname != NULL)) {
const char *name;
}
- if (bypass != NULL) {
- targetPrivate->onDemandBypass = CFBooleanGetValue(bypass);
+ if (llqBypass != NULL) {
+ targetPrivate->llqBypass = CFBooleanGetValue(llqBypass);
}
- SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%s + options %@"),
- targetPrivate->log_prefix,
- targetPrivate);
+ if (onDemandBypass != NULL) {
+ targetPrivate->onDemandBypass = CFBooleanGetValue(onDemandBypass);
+ }
+
+ if (resolverBypass != NULL) {
+ targetPrivate->resolverBypass = CFBooleanGetValue(resolverBypass);
+ }
+
+#ifdef HAVE_REACHABILITY_SERVER
+ if (serverBypass != NULL) {
+ targetPrivate->serverBypass = CFBooleanGetValue(serverBypass);
+ }
+#endif // HAVE_REACHABILITY_SERVER
+
+ if (_sc_debug && (_sc_log > 0)) {
+ const char *opt;
+
+ switch (targetPrivate->type) {
+ case reachabilityTypeName :
+ opt = DEBUG_REACHABILITY_TYPE_NAME_OPTIONS;
+ break;
+ case reachabilityTypeAddress :
+ opt = DEBUG_REACHABILITY_TYPE_ADDRESS_OPTIONS;
+ break;
+ case reachabilityTypeAddressPair :
+ opt = DEBUG_REACHABILITY_TYPE_ADDRESSPAIR_OPTIONS;
+ break;
+ default :
+ opt = "???";
+ break;
+ }
+
+ SCLog(TRUE, LOG_INFO, CFSTR("%s%s %@"),
+ targetPrivate->log_prefix,
+ opt,
+ targetPrivate);
+ }
return (SCNetworkReachabilityRef)targetPrivate;
}
struct addrinfo *resP;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
if (targetPrivate->resolvedAddress != NULL) {
CFRelease(targetPrivate->resolvedAddress);
targetPrivate->resolvedAddress = NULL;
__dns_query_end(target,
((status == 0) && (res != NULL)), // if successful query
- TRUE, // async
+ dns_query_async, // async
&targetPrivate->dnsQueryStart, // start time
&targetPrivate->dnsQueryEnd); // end time
static void
-processAsyncDNSReply(mach_port_t mp, void *msg, SCNetworkReachabilityRef target);
+getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info);
-static void
-getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info)
+static Boolean
+enqueueAsyncDNSQuery_dispatch(SCNetworkReachabilityRef target)
{
- mach_port_t mp = CFMachPortGetPort(port);
- SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)info;
+ mach_port_t mp;
+ dispatch_source_t source;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- processAsyncDNSReply(mp, msg, target);
- return;
-}
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+ mp = targetPrivate->dnsMP;
-static boolean_t
-SCNetworkReachabilityNotifyMIGCallback(mach_msg_header_t *message, mach_msg_header_t *reply)
-{
- mach_port_t mp = message->msgh_local_port;
- SCNetworkReachabilityRef target = dispatch_get_context(dispatch_get_current_queue());
+ // mach_port context <-- NULL (no msg received)
+ mach_port_set_context(mach_task_self(), mp, (mach_vm_address_t)(uintptr_t)NULL);
- processAsyncDNSReply(mp, message, target);
- reply->msgh_remote_port = MACH_PORT_NULL;
- return false;
+ // create dispatch source to handle DNS reply
+ source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV,
+ mp,
+ 0,
+ __SCNetworkReachability_concurrent_queue());
+ if (source == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability dispatch_source_create() failed"));
+ return FALSE;
+ }
+
+ //
+ // We created the dispatch_source to listen for (and process) the mach IPC
+ // reply to our async DNS query. Because the source handler runs asychronously
+ // we need to ensure that we're holding a reference to the target. Here, we take
+ // a reference and setup the dispatch_source finalizer to drop it.
+ //
+ CFRetain(target);
+ dispatch_set_context(source, (void *)target);
+ dispatch_set_finalizer_f(source, (dispatch_function_t)CFRelease);
+
+ dispatch_source_set_event_handler(source, ^{
+ mach_msg_size_t msg_size = 8192;
+ const mach_msg_options_t options = MACH_RCV_MSG
+ | MACH_RCV_LARGE
+ | MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_CTX)
+ | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0);
+
+ while (TRUE) {
+ kern_return_t kr;
+ mach_msg_header_t *msg = (mach_msg_header_t *)malloc(msg_size);
+
+ kr = mach_msg(msg, /* msg */
+ options, /* options */
+ 0, /* send_size */
+ msg_size, /* rcv_size */
+ mp, /* rcv_name */
+ MACH_MSG_TIMEOUT_NONE, /* timeout */
+ MACH_PORT_NULL); /* notify */
+ if (kr == KERN_SUCCESS) {
+ // mach_port context <-- msg
+ mach_port_set_context(mach_task_self(),
+ mp,
+ (mach_vm_address_t)(uintptr_t)msg);
+ } else if (kr == MACH_RCV_TOO_LARGE) {
+ msg_size *= 2;
+ free(msg);
+ continue;
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCNetworkReachability async DNS handler, kr=0x%x"),
+ kr);
+ free(msg);
+ }
+ break;
+ }
+
+ dispatch_source_cancel(source);
+ });
+
+ dispatch_source_set_cancel_handler(source, ^{
+#if !TARGET_OS_EMBEDDED
+ mach_vm_address_t context;
+#else // !TARGET_OS_EMBEDDED
+ mach_port_context_t context;
+#endif // !TARGET_OS_EMBEDDED
+ kern_return_t kr;
+ mach_port_t mp;
+
+ // get the [async DNS query] mach port
+ mp = (mach_port_t)dispatch_source_get_handle(source);
+
+ // check if we have a received message
+ kr = mach_port_get_context(mach_task_self(), mp, &context);
+ if (kr == KERN_SUCCESS) {
+ void *msg;
+
+ msg = (void *)(uintptr_t)context;
+ if (msg != NULL) {
+ MUTEX_LOCK(&targetPrivate->lock);
+ getaddrinfo_async_handle_reply(msg);
+ targetPrivate->dnsSource = NULL;
+ targetPrivate->dnsMP = MACH_PORT_NULL;
+ MUTEX_UNLOCK(&targetPrivate->lock);
+ free(msg);
+ } else {
+ getaddrinfo_async_cancel(mp);
+ }
+ }
+
+ dispatch_release(source);
+ });
+
+ targetPrivate->dnsSource = source;
+ dispatch_resume(source);
+
+ return TRUE;
}
static Boolean
-enqueueAsyncDNSQuery(SCNetworkReachabilityRef target, mach_port_t mp)
+enqueueAsyncDNSQuery_CF(SCNetworkReachabilityRef target)
{
- CFMachPortContext context = { 0
- , (void *)target
- , CFRetain
- , CFRelease
- , replyMPCopyDescription
- };
+ CFMachPortContext context = { 0
+ , (void *)target
+ , CFRetain
+ , CFRelease
+ , replyMPCopyDescription
+ };
+ CFIndex i;
+ mach_port_t mp;
+ CFIndex n;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- targetPrivate->dnsMP = mp;
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
+ mp = targetPrivate->dnsMP;
+
targetPrivate->dnsPort = _SC_CFMachPortCreateWithPort("SCNetworkReachability",
mp,
getaddrinfo_async_handleCFReply,
&context);
- if (targetPrivate->dispatchQueue != NULL) {
- targetPrivate->asyncDNSQueue = dispatch_queue_create("com.apple.SCNetworkReachabilty.async_DNS_query", NULL);
- if (targetPrivate->asyncDNSQueue == NULL) {
- SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability dispatch_queue_create() failed"));
- goto fail;
- }
- CFRetain(target); // Note: will be released when the dispatch queue is released
- dispatch_set_context(targetPrivate->asyncDNSQueue, (void *)target);
- dispatch_set_finalizer_f(targetPrivate->asyncDNSQueue, (dispatch_function_t)CFRelease);
-
- targetPrivate->asyncDNSSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV,
- mp,
- 0,
- targetPrivate->asyncDNSQueue);
- if (targetPrivate->asyncDNSSource == NULL) {
- SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability dispatch_source_create() failed"));
- goto fail;
- }
- dispatch_source_set_event_handler(targetPrivate->asyncDNSSource, ^{
- dispatch_mig_server(targetPrivate->asyncDNSSource,
- sizeof(mach_msg_header_t),
- SCNetworkReachabilityNotifyMIGCallback);
- });
- dispatch_resume(targetPrivate->asyncDNSSource);
- } else if (targetPrivate->rls != NULL) {
- CFIndex i;
- CFIndex n;
+ if (targetPrivate->dnsPort == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability CFMachPortCreateWithPort() failed"));
+ goto fail;
+ }
- targetPrivate->dnsRLS = CFMachPortCreateRunLoopSource(NULL, targetPrivate->dnsPort, 0);
+ targetPrivate->dnsRLS = CFMachPortCreateRunLoopSource(NULL, targetPrivate->dnsPort, 0);
+ if (targetPrivate->dnsRLS == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability CFMachPortCreateRunLoopSource() failed"));
+ goto fail;
+ }
- n = CFArrayGetCount(targetPrivate->rlList);
- for (i = 0; i < n; i += 3) {
- CFRunLoopRef rl = (CFRunLoopRef)CFArrayGetValueAtIndex(targetPrivate->rlList, i+1);
- CFStringRef rlMode = (CFStringRef) CFArrayGetValueAtIndex(targetPrivate->rlList, i+2);
+ n = CFArrayGetCount(targetPrivate->rlList);
+ for (i = 0; i < n; i += 3) {
+ CFRunLoopRef rl = (CFRunLoopRef)CFArrayGetValueAtIndex(targetPrivate->rlList, i+1);
+ CFStringRef rlMode = (CFStringRef) CFArrayGetValueAtIndex(targetPrivate->rlList, i+2);
- CFRunLoopAddSource(rl, targetPrivate->dnsRLS, rlMode);
- }
+ CFRunLoopAddSource(rl, targetPrivate->dnsRLS, rlMode);
}
return TRUE;
fail :
- if (targetPrivate->asyncDNSSource != NULL) {
- dispatch_source_cancel(targetPrivate->asyncDNSSource);
- dispatch_release(targetPrivate->asyncDNSSource);
- targetPrivate->asyncDNSSource = NULL;
+ if (targetPrivate->dnsRLS != NULL) {
+ CFRunLoopSourceInvalidate(targetPrivate->dnsRLS);
+ CFRelease(targetPrivate->dnsRLS);
+ targetPrivate->dnsRLS = NULL;
}
- if (targetPrivate->asyncDNSQueue != NULL) {
- dispatch_release(targetPrivate->asyncDNSQueue);
- targetPrivate->asyncDNSQueue = NULL;
+ if (targetPrivate->dnsPort != NULL) {
+ CFMachPortInvalidate(targetPrivate->dnsPort);
+ CFRelease(targetPrivate->dnsPort);
+ targetPrivate->dnsPort = NULL;
}
- CFMachPortInvalidate(targetPrivate->dnsPort);
- CFRelease(targetPrivate->dnsPort);
- targetPrivate->dnsPort = NULL;
- targetPrivate->dnsMP = MACH_PORT_NULL;
-
- _SCErrorSet(kSCStatusFailed);
return FALSE;
}
-static void
-dequeueAsyncDNSQuery(SCNetworkReachabilityRef target)
+static Boolean
+enqueueAsyncDNSQuery(SCNetworkReachabilityRef target, mach_port_t mp)
{
+ Boolean ok = FALSE;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- if (targetPrivate->asyncDNSSource != NULL) {
- dispatch_source_cancel(targetPrivate->asyncDNSSource);
- if (targetPrivate->asyncDNSQueue != dispatch_get_current_queue()) {
- // ensure the cancellation has completed
- pthread_mutex_unlock(&targetPrivate->lock);
- dispatch_sync(targetPrivate->asyncDNSQueue, ^{});
- pthread_mutex_lock(&targetPrivate->lock);
- }
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
+ targetPrivate->dnsMP = mp;
+
+ if (targetPrivate->dispatchQueue != NULL) {
+ ok = enqueueAsyncDNSQuery_dispatch(target);
+ } else if (targetPrivate->rls != NULL) {
+ ok = enqueueAsyncDNSQuery_CF(target);
}
- if (targetPrivate->asyncDNSSource != NULL) {
- dispatch_release(targetPrivate->asyncDNSSource);
- targetPrivate->asyncDNSSource = NULL;
+
+ if (!ok) {
+ targetPrivate->dnsMP = MACH_PORT_NULL;
+ _SCErrorSet(kSCStatusFailed);
+ return FALSE;
}
- if (targetPrivate->asyncDNSQueue != NULL) {
- dispatch_release(targetPrivate->asyncDNSQueue);
- targetPrivate->asyncDNSQueue = NULL;
+
+ return TRUE;
+}
+
+
+static void
+dequeueAsyncDNSQuery(SCNetworkReachabilityRef target, Boolean cancel)
+{
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
+ if (targetPrivate->dnsPort != NULL) {
+ CFMachPortInvalidate(targetPrivate->dnsPort);
+ CFRelease(targetPrivate->dnsPort);
+ targetPrivate->dnsPort = NULL;
}
if (targetPrivate->dnsRLS != NULL) {
targetPrivate->dnsRLS = NULL;
}
- if (targetPrivate->dnsPort != NULL) {
- CFMachPortInvalidate(targetPrivate->dnsPort);
- CFRelease(targetPrivate->dnsPort);
- targetPrivate->dnsPort = NULL;
+ if (targetPrivate->dnsSource != NULL) {
+ dispatch_source_cancel(targetPrivate->dnsSource);
+ targetPrivate->dnsSource = NULL;
+ cancel = FALSE; // the cancellation handler does the work
+ }
+
+ if (targetPrivate->dnsMP != MACH_PORT_NULL) {
+ if (cancel) {
+ getaddrinfo_async_cancel(targetPrivate->dnsMP);
+ }
targetPrivate->dnsMP = MACH_PORT_NULL;
}
static void
-processAsyncDNSReply(mach_port_t mp, void *msg, SCNetworkReachabilityRef target)
+getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info)
{
+ mach_port_t mp = CFMachPortGetPort(port);
int32_t status;
+ SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)info;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- pthread_mutex_lock(&targetPrivate->lock);
+ MUTEX_LOCK(&targetPrivate->lock);
if (mp != targetPrivate->dnsMP) {
// we've received a callback on the async DNS port but since the
// associated CFMachPort doesn't match than the request must have
// already been cancelled.
SCLog(TRUE, LOG_ERR, CFSTR("processAsyncDNSReply(): mp != targetPrivate->dnsMP"));
- pthread_mutex_unlock(&targetPrivate->lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
return;
}
- dequeueAsyncDNSQuery(target);
+ dequeueAsyncDNSQuery(target, FALSE);
status = getaddrinfo_async_handle_reply(msg);
if ((status == 0) &&
(targetPrivate->resolvedAddress == NULL) && (targetPrivate->resolvedAddressError == NETDB_SUCCESS)) {
}
}
- pthread_mutex_unlock(&targetPrivate->lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
return;
}
dns_resolver_t *resolver,
SCNetworkReachabilityFlags *flags,
Boolean *haveDNS,
+ uint32_t *resolver_if_index,
const char *log_prefix)
{
- int i;
Boolean ok = TRUE;
- *flags = kSCNetworkReachabilityFlagsReachable;
- *haveDNS = FALSE;
+ if (resolver_if_index) *resolver_if_index = 0;
- for (i = 0; i < resolver->n_nameserver; i++) {
- struct sockaddr *address = resolver->nameserver[i];
- ReachabilityInfo ns_info;
+ if (resolver->n_nameserver > 0) {
+#if !TARGET_IPHONE_SIMULATOR
+ *flags = (SCNetworkReachabilityFlags)resolver->reach_flags;
+ if (resolver_if_index != NULL) {
+ *resolver_if_index = resolver->if_index;
+ }
+#else // !TARGET_IPHONE_SIMULATOR
+ int i;
- *haveDNS = TRUE;
+ *flags = kSCNetworkReachabilityFlagsReachable;
- if (address->sa_family != AF_INET) {
- /*
- * we need to skip non-IPv4 DNS server
- * addresses (at least until [3510431] has
- * been resolved).
- */
- continue;
- }
+ for (i = 0; i < resolver->n_nameserver; i++) {
+ struct sockaddr *address = resolver->nameserver[i];
+ ReachabilityInfo ns_info;
- ok = checkAddress(store_info, address, resolver->if_index, &ns_info, log_prefix);
- if (!ok) {
- /* not today */
- goto done;
- }
+ ok = checkAddress(store_info, address, resolver->if_index, &ns_info, log_prefix);
+ if (!ok) {
+ /* not today */
+ break;
+ }
- if (rankReachability(ns_info.flags) < rankReachability(*flags)) {
- /* return the worst case result */
- *flags = ns_info.flags;
+ if ((i == 0) ||
+ (rankReachability(ns_info.flags) < rankReachability(*flags))) {
+ /* return the worst case result */
+ *flags = ns_info.flags;
+ if (resolver_if_index != NULL) {
+ *resolver_if_index = ns_info.if_index;
+ }
+ }
}
+#endif // !TARGET_IPHONE_SIMULATOR
+ *haveDNS = TRUE;
+ } else {
+ *flags = kSCNetworkReachabilityFlagsReachable;
+ *haveDNS = FALSE;
}
- done :
-
return ok;
}
unsigned int if_index,
SCNetworkReachabilityFlags *flags,
Boolean *haveDNS,
+ uint32_t *resolver_if_index,
+ int *dns_config_index,
const char *log_prefix)
{
int i;
resolvers = dns_config->scoped_resolver;
}
+ /* In case we couldn't find a match, setting an index of -1
+ and resolver_if_index 0 */
+ if (dns_config_index != NULL) *dns_config_index = -1;
+ if (resolver_if_index != NULL) *resolver_if_index = 0;
+
while (!matched && (name != NULL)) {
int len;
* if name matches domain
*/
matched = TRUE;
- ok = check_resolver_reachability(store_info, resolver, flags, haveDNS, log_prefix);
+ ok = check_resolver_reachability(store_info, resolver, flags, haveDNS,
+ resolver_if_index, log_prefix);
if (!ok) {
/* not today */
return FALSE;
}
+ if (dns_config_index != NULL) *dns_config_index = i;
}
}
}
const char *nodename,
const char *servname,
unsigned int if_index,
- const char *log_prefix)
+ uint32_t *resolver_if_index,
+ int *dns_config_index,
+ const char *log_prefix
+ )
{
dns_resolver_t *default_resolver;
dns_configuration_t *dns;
Boolean ok = TRUE;
Boolean useDefault = FALSE;
+ if (resolver_if_index) *resolver_if_index = 0;
+ if (dns_config_index) *dns_config_index = -1;
+
/*
* We first assume that all of the configured DNS servers
* are available. Since we don't know which name server will
goto done;
}
- *flags = kSCNetworkReachabilityFlagsReachable;
-
if (fqdn[len - 1] == '.') {
isFQDN = TRUE;
/*
* check if the provided name matches a supplemental domain
*/
- found = check_matching_resolvers(store_info, dns->config, fqdn, if_index, flags, haveDNS, log_prefix);
+ found = check_matching_resolvers(store_info, dns->config, fqdn, if_index,
+ flags, haveDNS, resolver_if_index,
+ dns_config_index, log_prefix);
if (!found && !isFQDN) {
/*
if_index,
flags,
haveDNS,
+ resolver_if_index,
+ dns_config_index,
log_prefix);
free(search_fqdn);
}
if_index,
flags,
haveDNS,
+ resolver_if_index,
+ dns_config_index,
log_prefix);
free(search_fqdn);
/*
* check the reachability of the default resolver
*/
- ok = check_resolver_reachability(store_info, default_resolver, flags, haveDNS, log_prefix);
+ ok = check_resolver_reachability(store_info, default_resolver, flags, haveDNS,
+ resolver_if_index, log_prefix);
+ if (ok && dns_config_index != NULL) *dns_config_index = 0;
}
if (fqdn != nodename) free(fqdn);
Boolean ok;
ReachabilityStoreInfo store_info;
- initReachabilityStoreInfo(&store_info);
- ok = updateReachabilityStoreInfo(&store_info, storeP, AF_UNSPEC);
+ ReachabilityStoreInfo_init(&store_info);
+ ok = ReachabilityStoreInfo_update(&store_info, storeP, AF_UNSPEC);
if (!ok) {
goto done;
}
- ok = _SC_R_checkResolverReachability(&store_info, flags, haveDNS, nodename, servname, 0, "");
+ ok = _SC_R_checkResolverReachability(&store_info, flags, haveDNS, nodename,
+ servname, 0, NULL, NULL, "");
done :
- freeReachabilityStoreInfo(&store_info);
+ ReachabilityStoreInfo_free(&store_info);
return ok;
}
+Boolean
+__SC_checkResolverReachabilityInternal(SCDynamicStoreRef *storeP,
+ SCNetworkReachabilityFlags *flags,
+ Boolean *haveDNS,
+ const char *nodename,
+ const char *servname,
+ uint32_t *resolver_if_index,
+ int *dns_config_index)
+{
+ Boolean ok;
+ ReachabilityStoreInfo store_info;
+
+ ReachabilityStoreInfo_init(&store_info);
+ ok = ReachabilityStoreInfo_update(&store_info, storeP, AF_UNSPEC);
+ if (!ok) {
+ goto done;
+ }
+
+ ok = _SC_R_checkResolverReachability(&store_info, flags, haveDNS, nodename,
+ servname, 0, resolver_if_index, dns_config_index, "");
+
+ done :
+
+ ReachabilityStoreInfo_free(&store_info);
+ return ok;
+}
/*
* _SC_checkResolverReachabilityByAddress()
char ptr_name[128];
ReachabilityStoreInfo store_info;
- initReachabilityStoreInfo(&store_info);
- ok = updateReachabilityStoreInfo(&store_info, storeP, AF_UNSPEC);
+ ReachabilityStoreInfo_init(&store_info);
+ ok = ReachabilityStoreInfo_update(&store_info, storeP, AF_UNSPEC);
if (!ok) {
goto done;
}
in_addr_t s_addr;
unsigned char b[4];
} rev;
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ /* ALIGN: assuming sa is aligned, then cast ok. */
+ struct sockaddr_in *sin = (struct sockaddr_in *)(void *)sa;
/*
* build "PTR" query name
case AF_INET6 : {
int s = 0;
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ /* ALIGN: assume sa is aligned, cast ok. */
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(void *)sa;
int x = sizeof(ptr_name);
int n;
goto done;
}
- ok = _SC_R_checkResolverReachability(&store_info, flags, haveDNS, ptr_name, NULL, 0, "");
+ ok = _SC_R_checkResolverReachability(&store_info, flags, haveDNS, ptr_name, NULL, 0, NULL, NULL, "");
done :
- freeReachabilityStoreInfo(&store_info);
+ ReachabilityStoreInfo_free(&store_info);
return ok;
}
static Boolean
-startAsyncDNSQuery(SCNetworkReachabilityRef target) {
+startAsyncDNSQuery(SCNetworkReachabilityRef target)
+{
int error = 0;
mach_port_t mp = MACH_PORT_NULL;
Boolean ok;
}
-#pragma mark -
+#pragma mark -
+
+
+static Boolean
+enqueueAsyncDNSRetry(SCNetworkReachabilityRef target)
+{
+ int64_t delay;
+ dispatch_source_t source;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
+ source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
+ 0,
+ 0,
+ __SCNetworkReachability_concurrent_queue());
+ if (source == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability retry dispatch_source_create() failed"));
+ return FALSE;
+ }
+
+ // retain the target ... and release it when the [timer] source is released
+ CFRetain(target);
+ dispatch_set_context(source, (void *)target);
+ dispatch_set_finalizer_f(source, (dispatch_function_t)CFRelease);
+
+ dispatch_source_set_event_handler(source, ^(void) {
+ __SCNetworkReachabilityPerformInlineNoLock(target, TRUE);
+ });
+
+ // start a one-shot timer
+ delay = targetPrivate->dnsRetryCount * EAI_NONAME_RETRY_DELAY_USEC * NSEC_PER_USEC;
+ dispatch_source_set_timer(source,
+ dispatch_time(DISPATCH_TIME_NOW, delay), // start
+ 0, // interval
+ 10 * NSEC_PER_MSEC); // leeway
+
+ targetPrivate->dnsRetry = source;
+ dispatch_resume(source);
+
+ return TRUE;
+}
+
+
+static void
+dequeueAsyncDNSRetry(SCNetworkReachabilityRef target)
+{
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
+ if (targetPrivate->dnsRetry != NULL) {
+ dispatch_source_cancel(targetPrivate->dnsRetry);
+ dispatch_release(targetPrivate->dnsRetry);
+ targetPrivate->dnsRetry = NULL;
+ }
+
+ return;
+}
+
+
+#pragma mark -
+
+
+static dispatch_queue_t
+_llq_queue()
+{
+ static dispatch_once_t once;
+ static dispatch_queue_t q;
+
+ dispatch_once(&once, ^{
+ q = dispatch_queue_create("SCNetworkReachabilty.longLivedQueries", NULL);
+ });
+
+ return q;
+}
+
+
+/*
+ * _llq_notify
+ *
+ * Called to push out a target's DNS changes
+ * - caller must be running on the _llq_queue()
+ */
+static void
+_llq_notify(const void *value, void *context)
+{
+ SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)value;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ MUTEX_LOCK(&targetPrivate->lock);
+
+ __dns_query_end(target,
+ (targetPrivate->resolvedAddressError == NETDB_SUCCESS), // if successful query
+ dns_query_llq, // long-lived-query
+ &targetPrivate->dnsQueryStart, // start time
+ &targetPrivate->dnsQueryEnd); // end time
+
+ if (targetPrivate->scheduled) {
+ __SCNetworkReachabilityPerform(target);
+ }
+
+ // last long-lived-query end time is new start time
+ targetPrivate->dnsQueryStart = targetPrivate->dnsQueryEnd;
+
+ MUTEX_UNLOCK(&targetPrivate->lock);
+ return;
+}
+
+
+/*
+ * _llq_callback
+ *
+ * Called to process mDNSResponder long-lived-query updates
+ * - caller must be running on the _llq_queue()
+ */
+static void
+_llq_callback(DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *hostname,
+ const struct sockaddr *address,
+ uint32_t ttl,
+ void *context)
+{
+ SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)context;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ MUTEX_LOCK(&targetPrivate->lock);
+
+ if (targetPrivate->llqTimer != NULL) {
+ dispatch_source_cancel(targetPrivate->llqTimer);
+ dispatch_release(targetPrivate->llqTimer);
+ targetPrivate->llqTimer = NULL;
+ }
+
+ switch (errorCode) {
+ case kDNSServiceErr_NoError :
+ if (address != NULL) {
+ CFMutableArrayRef addresses;
+ CFDataRef llqAddress;
+
+ if (targetPrivate->resolvedAddress != NULL) {
+ if (isA_CFArray(targetPrivate->resolvedAddress)) {
+ addresses = CFArrayCreateMutableCopy(NULL, 0, targetPrivate->resolvedAddress);
+ } else {
+ addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ CFRelease(targetPrivate->resolvedAddress);
+ targetPrivate->resolvedAddress = NULL;
+ } else {
+ addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ llqAddress = CFDataCreate(NULL, (void *)address, address->sa_len);
+ if (flags & kDNSServiceFlagsAdd) {
+ // add address
+ CFArrayAppendValue(addresses, llqAddress);
+ } else {
+ CFIndex i;
+
+ // remove address
+ i = CFArrayGetFirstIndexOfValue(addresses,
+ CFRangeMake(0, CFArrayGetCount(addresses)),
+ llqAddress);
+ if (i != kCFNotFound) {
+ CFArrayRemoveValueAtIndex(addresses, i);
+ }
+ }
+ CFRelease(llqAddress);
+
+ if (CFArrayGetCount(addresses) > 0) {
+ targetPrivate->resolvedAddress = addresses;
+ targetPrivate->resolvedAddressError = NETDB_SUCCESS;
+ } else {
+ // if host not found
+ targetPrivate->resolvedAddress = CFRetain(kCFNull);
+ targetPrivate->resolvedAddressError = EAI_NONAME;
+ CFRelease(addresses);
+ }
+
+ targetPrivate->needResolve = FALSE;
+ }
+ break;
+ case kDNSServiceErr_NoSuchRecord :
+ if (address != NULL) {
+ // no IPv4/IPv6 address for name (NXDOMAIN)
+ if (targetPrivate->resolvedAddress == NULL) {
+ targetPrivate->resolvedAddress = CFRetain(kCFNull);
+ targetPrivate->resolvedAddressError = EAI_NONAME;
+ }
+ targetPrivate->needResolve = FALSE;
+ }
+ break;
+ case kDNSServiceErr_Timeout :
+ if (targetPrivate->resolvedAddress == NULL) {
+ targetPrivate->resolvedAddress = CFRetain(kCFNull);
+ targetPrivate->resolvedAddressError = EAI_NONAME;
+ }
+ targetPrivate->needResolve = FALSE;
+ break;
+ default :
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("%sSCNetworkReachability _llq_callback w/error=%d"),
+ targetPrivate->log_prefix,
+ errorCode);
+ break;
+ }
+
+ MUTEX_UNLOCK(&targetPrivate->lock);
+
+ // the "more coming" flag applies to DNSService callouts for any/all
+ // hosts that are being watched so we need to keep track of the targets
+ // we have updated. When we [finally] have the last callout then we
+ // push our notifications for all of the updated targets.
+
+ if (llqUpdated == NULL) {
+ llqUpdated = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+ }
+ CFSetAddValue(llqUpdated, target);
+
+ if (!(flags & kDNSServiceFlagsMoreComing)) {
+ CFSetApplyFunction(llqUpdated, _llq_notify, NULL);
+ CFRelease(llqUpdated);
+ llqUpdated = NULL;
+ }
+
+ return;
+}
+
+
+static Boolean
+enqueueLongLivedQuery(SCNetworkReachabilityRef target)
+{
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
+ if (targetPrivate->serv != NULL) {
+ // if "serv" provided, can't use DNSServiceGetAddrInfo
+ return FALSE;
+ }
+
+ if (memcmp(&targetPrivate->hints, &HINTS_DEFAULT, sizeof(targetPrivate->hints)) != 0) {
+ // non-default "hints" provided, can't use DNSServiceGetAddrInfo
+ return FALSE;
+ }
+
+ // mark the long lived query active
+ targetPrivate->llqActive = TRUE;
+
+ // track the DNS resolution time
+ __dns_query_start(&targetPrivate->dnsQueryStart, &targetPrivate->dnsQueryEnd);
+
+ CFRetain(target);
+ dispatch_async(_llq_queue(), ^{
+ DNSServiceErrorType err;
+ dispatch_source_t source;
+
+ MUTEX_LOCK(&targetPrivate->lock);
+
+ if (targetPrivate->llqTarget != NULL) {
+ // if already running
+ MUTEX_UNLOCK(&targetPrivate->lock);
+ CFRelease(target);
+ return;
+ }
+
+ // if needed, start interacting with mDNSResponder
+
+ if (llqMain == NULL) {
+ err = DNSServiceCreateConnection(&llqMain);
+ if (err != kDNSServiceErr_NoError) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("DNSServiceCreateConnection(&llqMain) failed, error = %d"),
+ err);
+
+ targetPrivate->llqActive = FALSE;
+
+ MUTEX_UNLOCK(&targetPrivate->lock);
+ CFRelease(target);
+ return;
+ }
+ err = DNSServiceSetDispatchQueue(llqMain, _llq_queue());
+ if (err != kDNSServiceErr_NoError) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("DNSServiceSetDispatchQueue() failed, error = %d"),
+ err);
+ DNSServiceRefDeallocate(llqMain);
+ llqMain = NULL;
-static Boolean
-enqueueAsyncDNSRetry(SCNetworkReachabilityRef target)
-{
- int64_t delay;
- dispatch_source_t source;
- SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+ targetPrivate->llqActive = FALSE;
- source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
- 0,
- 0,
- dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
- if (source == NULL) {
- SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability retry dispatch_source_create() failed"));
- return FALSE;
- }
+ MUTEX_UNLOCK(&targetPrivate->lock);
+ CFRelease(target);
+ return;
+ }
+ }
- // retain the target ... and release it when the [timer] source is released
- CFRetain(target);
- dispatch_set_context(source, (void *)target);
- dispatch_set_finalizer_f(source, (dispatch_function_t)CFRelease);
+ // start a long-lived-query for this target
- dispatch_source_set_event_handler(source, ^(void) {
- __SCNetworkReachabilityPerformInline(target, TRUE);
- });
+ targetPrivate->llqTarget = llqMain;
+ err = DNSServiceGetAddrInfo(&targetPrivate->llqTarget, // sdRef
+ kDNSServiceFlagsReturnIntermediates // flags
+ | kDNSServiceFlagsShareConnection,
+ targetPrivate->if_index, // interfaceIndex
+ 0, // protocol
+ targetPrivate->name, // hostname
+ _llq_callback, // callback
+ (void *)target); // context
+ if (err != kDNSServiceErr_NoError) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("DNSServiceGetAddrInfo() failed, error = %d"),
+ err);
+ targetPrivate->llqTarget = NULL;
+ if (llqCount == 0) {
+ // if this was the first request
+ DNSServiceRefDeallocate(llqMain);
+ llqMain = NULL;
+ }
- // start a one-shot timer
- delay = targetPrivate->dnsRetryCount * EAI_NONAME_RETRY_DELAY_USEC * NSEC_PER_USEC;
- dispatch_source_set_timer(source,
- dispatch_time(DISPATCH_TIME_NOW, delay), // start
- 0, // interval
- 10 * NSEC_PER_MSEC); // leeway
+ targetPrivate->llqActive = FALSE;
+
+ MUTEX_UNLOCK(&targetPrivate->lock);
+ CFRelease(target);
+ return;
+ }
+
+ llqCount++;
+
+ // if case we don't get any callbacks from our long-lived-query (this
+ // could happen if the DNS servers do not respond), we start a timer
+ // to ensure that we fire off at least one reachability callback.
+
+ source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
+ 0,
+ 0,
+ _llq_queue());
+ if (source != NULL) {
+ // retain the target ... and release it when the [timer] source is released
+ CFRetain(target);
+ dispatch_set_context(source, (void *)target);
+ dispatch_set_finalizer_f(source, (dispatch_function_t)CFRelease);
+
+ dispatch_source_set_event_handler(source, ^(void) {
+ _llq_callback(NULL, // sdRef
+ 0, // flags
+ 0, // interfaceIndex
+ kDNSServiceErr_Timeout, // errorCode
+ NULL, // hostname
+ NULL, // address
+ 0, // ttl
+ (void *)target); // context
+ });
+
+ dispatch_source_set_timer(source,
+ dispatch_time(DISPATCH_TIME_NOW,
+ LLQ_TIMEOUT_NSEC), // start
+ 0, // interval
+ 10 * NSEC_PER_MSEC); // leeway
+
+ targetPrivate->llqTimer = source;
+ dispatch_resume(source);
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCNetworkReachability llq dispatch_source_create(no-reply) failed"));
+ }
- targetPrivate->dnsRetry = source;
- dispatch_resume(source);
+ MUTEX_UNLOCK(&targetPrivate->lock);
+ return;
+ });
return TRUE;
}
static void
-dequeueAsyncDNSRetry(SCNetworkReachabilityRef target)
+dequeueLongLivedQuery(SCNetworkReachabilityRef target)
{
+ DNSServiceRef sdRef;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- if (targetPrivate->dnsRetry != NULL) {
- dispatch_source_cancel(targetPrivate->dnsRetry);
- dispatch_release(targetPrivate->dnsRetry);
- targetPrivate->dnsRetry = NULL;
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
+ // terminate the [target] llq timer
+ if (targetPrivate->llqTimer != NULL) {
+ dispatch_source_cancel(targetPrivate->llqTimer);
+ dispatch_release(targetPrivate->llqTimer);
+ targetPrivate->llqTimer = NULL;
+ }
+
+ // terminate the [target] long lived query
+ sdRef = targetPrivate->llqTarget;
+ targetPrivate->llqTarget = NULL;
+
+ // mark the long lived query NOT active
+ targetPrivate->llqActive = FALSE;
+
+ if (sdRef != NULL) {
+ dispatch_async(_llq_queue(), ^{
+ DNSServiceRefDeallocate(sdRef);
+ CFRelease(target);
+
+ llqCount--;
+ if (llqCount == 0) {
+ // if no more queries active
+ DNSServiceRefDeallocate(llqMain);
+ llqMain = NULL;
+ }
+ });
}
return;
SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)info;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- pthread_mutex_lock(&targetPrivate->lock);
+ MUTEX_LOCK(&targetPrivate->lock);
if (!targetPrivate->scheduled) {
// if not currently scheduled
- pthread_mutex_unlock(&targetPrivate->lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
return;
}
targetPrivate->log_prefix);
__SCNetworkReachabilityPerform(target);
- pthread_mutex_unlock(&targetPrivate->lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
return;
}
SCDynamicStoreRef store;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
// SCLog(_sc_debug, LOG_INFO,
// CFSTR("%s__SCNetworkReachabilityOnDemandCheck %s"),
// targetPrivate->log_prefix,
&onDemandServiceID,
&onDemandStatus,
&onDemandRemoteAddress);
- if (store_info->store != store) {
+ if ((store_info->store == NULL) && (store != NULL)) {
+ // if an SCDynamicStore session was added, keep it
store_info->store = store;
- store_info->storeAdded = TRUE;
}
if (!_SC_CFEqual(targetPrivate->onDemandRemoteAddress, onDemandRemoteAddress) ||
!_SC_CFEqual(targetPrivate->onDemandServiceID, onDemandServiceID)) {
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, onDemandRemoteAddress);
- CFDictionarySetValue(options, kSCNetworkReachabilityOptionConnectionOnDemandByPass, kCFBooleanTrue);
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionConnectionOnDemandBypass, kCFBooleanTrue);
+#ifdef HAVE_REACHABILITY_SERVER
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionServerBypass, kCFBooleanTrue);
+#endif // HAVE_REACHABILITY_SERVER
targetPrivate->onDemandServer = SCNetworkReachabilityCreateWithOptions(NULL, options);
CFRelease(options);
ReachabilityInfo my_info = NOT_REACHABLE;
Boolean ok = TRUE;
- *reach_info = NOT_REACHABLE;
+ MUTEX_ASSERT_HELD(&targetPrivate->lock);
+
+ _reach_set(reach_info, &NOT_REACHABLE, reach_info->cycle);
if (!isA_SCNetworkReachability(target)) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
+#ifdef HAVE_REACHABILITY_SERVER
+ if (!targetPrivate->serverBypass) {
+ if (!targetPrivate->serverActive) {
+ ok = __SCNetworkReachabilityServer_targetAdd(target);
+ if (!ok) {
+ targetPrivate->serverBypass = TRUE;
+ }
+ }
+
+ if (targetPrivate->serverActive) {
+ ok = __SCNetworkReachabilityServer_targetStatus(target);
+ if (!ok) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("__SCNetworkReachabilityGetFlags _targetStatus() failed"));
+ _SCErrorSet(kSCStatusFailed);
+ goto done;
+ }
+
+ targetPrivate->cycle = targetPrivate->serverInfo.cycle;
+ _reach_set(&my_info, &targetPrivate->serverInfo, targetPrivate->cycle);
+ goto done;
+ }
+ }
+#endif // HAVE_REACHABILITY_SERVER
+
switch (targetPrivate->type) {
case reachabilityTypeAddress :
case reachabilityTypeAddressPair : {
struct timeval dnsQueryEnd;
int error;
SCNetworkReachabilityFlags ns_flags;
+ uint32_t ns_if_index;
struct addrinfo *res;
addresses = (CFMutableArrayRef)SCNetworkReachabilityCopyResolvedAddress(target, &error);
if (!async) {
/* if not an async request */
goto checkResolvedAddress;
+ } else if (targetPrivate->llqActive) {
+ /* if long-lived-query active */
+ goto checkResolvedAddress;
} else if ((targetPrivate->dnsMP == MACH_PORT_NULL) && !targetPrivate->needResolve) {
struct timeval elapsed;
const struct timeval retry_limit = { EAI_NONAME_RETRY_LIMIT_USEC / USEC_PER_SEC,
targetPrivate->serv != NULL ? targetPrivate->serv : "");
enqueueAsyncDNSRetry(target);
-
break;
}
}
targetPrivate->name,
targetPrivate->serv,
targetPrivate->if_index,
+ &ns_if_index,
+ NULL,
targetPrivate->log_prefix);
if (!ok) {
/* if we could not get DNS server info */
break;
}
+ if (targetPrivate->resolverBypass) {
+ /* if we are not resolving the name,
+ * set the flags of the resolvers */
+ my_info.flags = ns_flags;
+ my_info.if_index = ns_if_index;
+ break;
+ }
+
if (async) {
/* for async requests we return the last known status */
my_info = targetPrivate->info;
- if (targetPrivate->dnsPort != NULL) {
+ if (targetPrivate->dnsMP != MACH_PORT_NULL) {
/* if request already in progress */
SCLog(_sc_debug, LOG_INFO,
CFSTR("%swaiting for DNS reply"),
break;
}
+ if (targetPrivate->llqActive) {
+ /* if long-lived-query active */
+ SCLog(_sc_debug, LOG_INFO,
+ CFSTR("%swaiting for DNS updates"),
+ targetPrivate->log_prefix);
+ if ((addresses != NULL) || (error != NETDB_SUCCESS)) {
+ /* updated reachability based on the previous reply */
+ goto checkResolvedAddress;
+ }
+ break;
+ }
+
+ if (!targetPrivate->llqBypass) {
+ SCLog(_sc_debug, LOG_INFO,
+ CFSTR("%sstart long-lived DNS query for %s%s%s%s%s"),
+ targetPrivate->log_prefix,
+ targetPrivate->name != NULL ? "name = " : "",
+ targetPrivate->name != NULL ? targetPrivate->name : "",
+ targetPrivate->name != NULL && targetPrivate->serv != NULL ? ", " : "",
+ targetPrivate->serv != NULL ? "serv = " : "",
+ targetPrivate->serv != NULL ? targetPrivate->serv : "");
+
+ /*
+ * initiate an long-lived DNS query
+ */
+ if (enqueueLongLivedQuery(target)) {
+ /* request initiated */
+ break;
+ }
+ }
+
SCLog(_sc_debug, LOG_INFO,
CFSTR("%sstart DNS query for %s%s%s%s%s"),
targetPrivate->log_prefix,
/*
* initiate an async DNS query
*/
- if (!startAsyncDNSQuery(target)) {
- /* if we could not initiate the request, process error */
- goto checkResolvedAddress;
+ if (startAsyncDNSQuery(target)) {
+ /* request initiated */
+ break;
}
- /* request initiated */
- break;
+ /* if we could not initiate the request, process error */
+ goto checkResolvedAddress;
}
SCLog(_sc_debug, LOG_INFO,
__dns_query_end(target,
((error == 0) && (res != NULL)), // if successful query
- FALSE, // sync
+ dns_query_sync, // sync
&dnsQueryStart, // start time
&dnsQueryEnd); // end time
done:
- *reach_info = my_info;
+ _reach_set(reach_info, &my_info, targetPrivate->cycle);
error :
return ok;
}
+int
+SCNetworkReachabilityGetInterfaceIndex(SCNetworkReachabilityRef target)
+{
+ SCNetworkReachabilityFlags flags;
+ int if_index = -1;
+ Boolean ok = TRUE;
+ ReachabilityStoreInfo store_info;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ if (!isA_SCNetworkReachability(target)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return if_index;
+ }
+
+ ReachabilityStoreInfo_init(&store_info);
+
+ MUTEX_LOCK(&targetPrivate->lock);
+
+ if (targetPrivate->scheduled) {
+ // if being watched, return the last known (and what should be current) status
+ flags = targetPrivate->info.flags & ~kSCNetworkReachabilityFlagsFirstResolvePending;
+ goto done;
+ }
+
+
+ ok = __SCNetworkReachabilityGetFlags(&store_info, target, &targetPrivate->info, FALSE);
+ flags = targetPrivate->info.flags & ~kSCNetworkReachabilityFlagsFirstResolvePending;
+
+ done :
+
+ /* Only return the if_index if the connection is reachable not for reachable connection
+ * required etc ... */
+ if (ok && rankReachability(flags) == 2) {
+ if_index = targetPrivate->info.if_index;
+ }
+
+ MUTEX_UNLOCK(&targetPrivate->lock);
+ ReachabilityStoreInfo_free(&store_info);
+ return if_index;
+}
+
Boolean
SCNetworkReachabilityGetFlags(SCNetworkReachabilityRef target,
return FALSE;
}
- initReachabilityStoreInfo(&store_info);
- pthread_mutex_lock(&targetPrivate->lock);
+ ReachabilityStoreInfo_init(&store_info);
+
+ MUTEX_LOCK(&targetPrivate->lock);
if (targetPrivate->scheduled) {
// if being watched, return the last known (and what should be current) status
done :
- pthread_mutex_unlock(&targetPrivate->lock);
- freeReachabilityStoreInfo(&store_info);
+ MUTEX_UNLOCK(&targetPrivate->lock);
+ ReachabilityStoreInfo_free(&store_info);
return ok;
}
#endif // TARGET_OS_IPHONE
+ // SCDynamicStore key to force posting a reachability change
+ CFArrayAppendValue(keys, SCNETWORKREACHABILITY_TRIGGER_KEY);
+
(void)SCDynamicStoreSetNotificationKeys(store, keys, patterns);
CFRelease(keys);
CFRelease(patterns);
}
+static dispatch_queue_t
+_hn_queue()
+{
+ static dispatch_once_t once;
+ static dispatch_queue_t q;
+
+ dispatch_once(&once, ^{
+ q = dispatch_queue_create("SCNetworkReachabilty.changes", NULL);
+ });
+
+ return q;
+}
+
+
static void
__SCNetworkReachabilityHandleChanges(SCDynamicStoreRef store,
CFArrayRef changedKeys,
#endif // !TARGET_OS_IPHONE
Boolean dnsConfigChanged = FALSE;
CFIndex i;
+ Boolean forcedChange = FALSE;
CFStringRef key;
- CFIndex nChanges = CFArrayGetCount(changedKeys);
+ CFIndex nChanges;
+ CFIndex nGlobals = 0;
CFIndex nTargets;
+ Boolean networkConfigChanged = FALSE;
struct timeval now;
#if !TARGET_OS_IPHONE
Boolean powerStatusChanged = FALSE;
ReachabilityStoreInfo store_info;
const void * targets_q[N_QUICK];
const void ** targets = targets_q;
+ __block CFSetRef watchers = NULL;
+ nChanges = CFArrayGetCount(changedKeys);
if (nChanges == 0) {
/* if no changes */
return;
}
- pthread_mutex_lock(&hn_lock);
+ /* "something" changed, start fresh */
+ ReachabilityStoreInfo_save(NULL);
+
+ dispatch_sync(_hn_queue(), ^{
+ /* grab the currently watched targets */
+ if (hn_targets != NULL) {
+ watchers = CFSetCreateCopy(NULL, hn_targets);
+ }
+ });
- nTargets = (hn_targets != NULL) ? CFSetGetCount(hn_targets) : 0;
+ nTargets = (watchers != NULL) ? CFSetGetCount(watchers) : 0;
if (nTargets == 0) {
/* if no addresses being monitored */
goto done;
if (CFArrayContainsValue(changedKeys, CFRangeMake(0, nChanges), key)) {
CFNumberRef num;
+ nGlobals++;
+
num = SCDynamicStoreCopyValue(store, key);
if (num != NULL) {
if (isA_CFNumber(num) &&
kSCDynamicStoreDomainState,
kSCEntNetDNS);
if (CFArrayContainsValue(changedKeys, CFRangeMake(0, nChanges), key)) {
+ nGlobals++;
dnsConfigChanged = TRUE; /* the DNS server(s) have changed */
}
CFRelease(key);
+ if (CFArrayContainsValue(changedKeys, CFRangeMake(0, nChanges), SCNETWORKREACHABILITY_TRIGGER_KEY)) {
+ nGlobals++;
+ forcedChange = TRUE; /* an SCDynamicStore driven "network" change */
+ }
+
+ if (nChanges > nGlobals) {
+ networkConfigChanged = TRUE;
+ }
+
if (_sc_debug) {
unsigned int changes = 0;
static const char *change_strings[] = {
"DNS and power ",
"network, DNS, and power ",
- // with no "power" status change (including CPU "on")
+ // with "power" status change (including CPU "on")
"power* ",
"network and power* ",
"DNS and power* ",
if (cpuStatusChanged) {
changes += PWR;
}
- nChanges -= 1;
}
#endif // !TARGET_OS_IPHONE
#define DNS 2
if (dnsConfigChanged) {
changes |= DNS;
- nChanges -= 1;
}
#define NET 1
- if (nChanges > 0) {
+ if (networkConfigChanged) {
changes |= NET;
}
SCLog(TRUE, LOG_INFO,
- CFSTR("process %sconfiguration change"),
+ CFSTR("process %s%sconfiguration change"),
+ forcedChange ? "[forced] " : "",
change_strings[changes]);
}
- initReachabilityStoreInfo(&store_info);
+ ReachabilityStoreInfo_init(&store_info);
if (nTargets > (CFIndex)(sizeof(targets_q) / sizeof(CFTypeRef)))
targets = CFAllocatorAllocate(NULL, nTargets * sizeof(CFTypeRef), 0);
- CFSetGetValues(hn_targets, targets);
+ CFSetGetValues(watchers, targets);
for (i = 0; i < nTargets; i++) {
SCNetworkReachabilityRef target = targets[i];
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- pthread_mutex_lock(&targetPrivate->lock);
+ MUTEX_LOCK(&targetPrivate->lock);
if (dnsConfigChanged) {
targetPrivate->last_dns = now;
targetPrivate->dnsRetryCount = 0;
}
+ if (networkConfigChanged) {
+ targetPrivate->last_network = now;
+ }
+
+#if !TARGET_OS_IPHONE
+ if (powerStatusChanged) {
+ targetPrivate->last_power = now;
+ }
+#endif // !TARGET_OS_IPHONE
+
if (targetPrivate->type == reachabilityTypeName) {
Boolean dnsChanged = dnsConfigChanged;
Boolean ok;
/* check the reachability of the DNS servers */
- ok = updateReachabilityStoreInfo(&store_info, &store, AF_UNSPEC);
+ ok = ReachabilityStoreInfo_update(&store_info, &store, AF_UNSPEC);
if (ok) {
ok = _SC_R_checkResolverReachability(&store_info,
&ns_flags,
targetPrivate->name,
targetPrivate->serv,
targetPrivate->if_index,
+ NULL,
+ NULL,
targetPrivate->log_prefix);
}
}
if (dnsChanged) {
- if (targetPrivate->dnsPort != NULL) {
- mach_port_t mp = CFMachPortGetPort(targetPrivate->dnsPort);
-
+ if (targetPrivate->dnsMP != MACH_PORT_NULL) {
/* cancel the outstanding DNS query */
SCLog(_sc_debug, LOG_INFO,
CFSTR("%scancel DNS query for %s%s%s%s%s"),
targetPrivate->name != NULL && targetPrivate->serv != NULL ? ", " : "",
targetPrivate->serv != NULL ? "serv = " : "",
targetPrivate->serv != NULL ? targetPrivate->serv : "");
- dequeueAsyncDNSQuery(target);
- getaddrinfo_async_cancel(mp);
+ dequeueAsyncDNSQuery(target, TRUE);
}
if (targetPrivate->dnsRetry != NULL) {
}
}
- __SCNetworkReachabilityPerform(target);
+ if (forcedChange) {
+ targetPrivate->cycle++;
+ }
+
+ if (targetPrivate->scheduled) {
+ __SCNetworkReachabilityPerform(target);
+ }
- pthread_mutex_unlock(&targetPrivate->lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
}
if (targets != targets_q) CFAllocatorDeallocate(NULL, targets);
- freeReachabilityStoreInfo(&store_info);
+ ReachabilityStoreInfo_free(&store_info);
done :
- pthread_mutex_unlock(&hn_lock);
+ if (watchers != NULL) CFRelease(watchers);
return;
}
static void
-rlsPerform(void *info)
+reachPerform(void *info)
{
void *context_info;
void (*context_release)(const void *);
+ uint64_t cycle;
Boolean defer = FALSE;
+ Boolean forced;
Boolean ok;
ReachabilityInfo reach_info = NOT_REACHABLE;
SCNetworkReachabilityCallBack rlsFunction;
targetPrivate->log_prefix);
- pthread_mutex_lock(&targetPrivate->lock);
+ MUTEX_LOCK(&targetPrivate->lock);
if (targetPrivate->dnsRetry != NULL) {
// cancel DNS retry
if (!targetPrivate->scheduled) {
// if not currently scheduled
- pthread_mutex_unlock(&targetPrivate->lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
return;
}
/* update reachability, notify if status changed */
- initReachabilityStoreInfo(&store_info);
+ ReachabilityStoreInfo_init(&store_info);
ok = __SCNetworkReachabilityGetFlags(&store_info, target, &reach_info, TRUE);
- freeReachabilityStoreInfo(&store_info);
+ ReachabilityStoreInfo_free(&store_info);
if (!ok) {
/* if reachability status not available */
SCLog(_sc_debug, LOG_INFO, CFSTR("%flags not available"),
* the same or "better"
*/
defer = !darkWakeNotify(target);
- } else if (__reach_equal(&targetPrivate->last_notify, &reach_info)) {
+ } else if (!__reach_changed(&targetPrivate->last_notify, &reach_info)) {
/*
* if we have already posted this change
*/
}
#endif // !TARGET_OS_IPHONE
- if (__reach_equal(&targetPrivate->info, &reach_info)) {
+ cycle = targetPrivate->cycle;
+ forced = ((cycle != 0) && (targetPrivate->info.cycle != cycle));
+
+ if (!forced && !__reach_changed(&targetPrivate->info, &reach_info)) {
if (_sc_debug) {
if (targetPrivate->info.sleeping == reach_info.sleeping) {
SCLog(TRUE, LOG_INFO,
}
}
- pthread_mutex_unlock(&targetPrivate->lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
return;
}
SCLog(_sc_debug, LOG_INFO,
- CFSTR("%sflags/interface have changed (was 0x%08x/%hu%s, now 0x%08x/%hu%s)%s"),
+ CFSTR("%sflags/interface have changed (was 0x%08x/%hu%s, now 0x%08x/%hu%s)%s%s"),
targetPrivate->log_prefix,
targetPrivate->info.flags,
targetPrivate->info.if_index,
reach_info.flags,
reach_info.if_index,
reach_info.sleeping ? ", z" : "",
- defer ? ", deferred" : "");
+ defer ? ", deferred" : "",
+ forced ? ", forced" : "");
/* as needed, defer the notification */
if (defer) {
- pthread_mutex_unlock(&targetPrivate->lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
return;
}
/* update flags / interface */
- targetPrivate->info = reach_info;
+ _reach_set(&targetPrivate->info, &reach_info, cycle);
/* save last notification info */
- targetPrivate->last_notify = reach_info;
+ _reach_set(&targetPrivate->last_notify, &reach_info, cycle);
+
+ /* save last notification time */
+ (void)gettimeofday(&targetPrivate->last_push, NULL);
/* callout */
rlsFunction = targetPrivate->rlsFunction;
context_release = NULL;
}
- pthread_mutex_unlock(&targetPrivate->lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
if (rlsFunction != NULL) {
(*rlsFunction)(target,
{
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- pthread_mutex_lock(&targetPrivate->lock);
+ MUTEX_LOCK(&targetPrivate->lock);
if (targetPrivate->rlsContext.release != NULL) {
/* let go of the current context */
}
}
- pthread_mutex_unlock(&targetPrivate->lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
return TRUE;
}
{
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
Boolean init = FALSE;
- Boolean ok = FALSE;
+ __block Boolean ok = FALSE;
- if (!onDemand) {
- pthread_mutex_lock(&hn_lock);
- }
- pthread_mutex_lock(&targetPrivate->lock);
+ MUTEX_LOCK(&targetPrivate->lock);
if ((targetPrivate->dispatchQueue != NULL) || // if we are already scheduled with a dispatch queue
((queue != NULL) && targetPrivate->scheduled)) { // if we are already scheduled on a CFRunLoop
goto done;
}
- /* schedule the SCNetworkReachability run loop source */
-
- if (!onDemand && (hn_store == NULL)) {
- /*
- * if we are not monitoring any hosts, start watching
- */
- if (!dns_configuration_watch()) {
- // if error
- _SCErrorSet(kSCStatusFailed);
- goto done;
+#ifdef HAVE_REACHABILITY_SERVER
+ if (!targetPrivate->serverBypass) {
+ if (!targetPrivate->serverActive) {
+ ok = __SCNetworkReachabilityServer_targetAdd(target);
+ if (!ok) {
+ targetPrivate->serverBypass = TRUE;
+ }
}
- hn_store = SCDynamicStoreCreate(NULL,
- CFSTR("SCNetworkReachability"),
- __SCNetworkReachabilityHandleChanges,
- NULL);
- if (hn_store == NULL) {
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCreate() failed"));
- goto done;
- }
+ if (targetPrivate->serverActive) {
+ if (targetPrivate->scheduled) {
+ // if already scheduled
+ goto watch;
+ }
- __SCNetworkReachabilityReachabilitySetNotifications(hn_store);
+ ok = __SCNetworkReachabilityServer_targetSchedule(target);
+ if (!ok) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("__SCNetworkReachabilityScheduleWithRunLoop _targetMonitor() failed"));
+ _SCErrorSet(kSCStatusFailed);
+ goto done;
+ }
- hn_dispatchQueue = dispatch_queue_create("com.apple.SCNetworkReachabilty.network_changes", NULL);
- if (hn_dispatchQueue == NULL) {
- SCLog(TRUE, LOG_ERR, CFSTR("__SCNetworkReachabilityScheduleWithRunLoop dispatch_queue_create() failed"));
- _SCErrorSet(kSCStatusFailed);
- CFRelease(hn_store);
- hn_store = NULL;
- goto done;
+ goto watch;
}
- CFRetain(hn_store); // Note: will be released when the dispatch queue is released
- dispatch_set_context(hn_dispatchQueue, (void *)hn_store);
- dispatch_set_finalizer_f(hn_dispatchQueue, (dispatch_function_t)CFRelease);
+ }
+#endif // HAVE_REACHABILITY_SERVER
- ok = SCDynamicStoreSetDispatchQueue(hn_store, hn_dispatchQueue);
- if (!ok) {
- SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetDispatchQueue() failed"));
- dispatch_release(hn_dispatchQueue);
- hn_dispatchQueue = NULL;
- CFRelease(hn_store);
- hn_store = NULL;
- goto done;
+ /* schedule the SCNetworkReachability did-something-change handler */
+
+ dispatch_sync(_hn_queue(), ^{
+ ok = FALSE;
+
+ if (!onDemand && (hn_store == NULL)) {
+ /*
+ * if we are not monitoring any hosts, start watching
+ */
+ if (!dns_configuration_watch()) {
+ // if error
+ _SCErrorSet(kSCStatusFailed);
+ return;
+ }
+
+ hn_store = SCDynamicStoreCreate(NULL,
+ CFSTR("SCNetworkReachability"),
+ __SCNetworkReachabilityHandleChanges,
+ NULL);
+ if (hn_store == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCreate() failed"));
+ dns_configuration_unwatch();
+ return;
+ }
+
+ __SCNetworkReachabilityReachabilitySetNotifications(hn_store);
+
+ hn_dispatchQueue = dispatch_queue_create("SCNetworkReachabilty.changes", NULL);
+ if (hn_dispatchQueue == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("__SCNetworkReachabilityScheduleWithRunLoop dispatch_queue_create() failed"));
+ CFRelease(hn_store);
+ hn_store = NULL;
+ dns_configuration_unwatch();
+ _SCErrorSet(kSCStatusFailed);
+ return;
+ }
+
+ ok = SCDynamicStoreSetDispatchQueue(hn_store, hn_dispatchQueue);
+ if (!ok) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetDispatchQueue() failed"));
+ dispatch_release(hn_dispatchQueue);
+ hn_dispatchQueue = NULL;
+ CFRelease(hn_store);
+ hn_store = NULL;
+ dns_configuration_unwatch();
+ return;
+ }
+ hn_targets = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+
+ ReachabilityStoreInfo_enable(TRUE);
}
- hn_targets = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+
+ CFSetAddValue(hn_targets, target);
+
+ ok = TRUE;
+ });
+
+ if (!ok) {
+ goto done;
}
+#ifdef HAVE_REACHABILITY_SERVER
+ watch :
+#endif // HAVE_REACHABILITY_SERVER
+
if (!targetPrivate->scheduled) {
CFRunLoopSourceContext context = { 0 // version
, (void *)target // info
, CFHash // hash
, NULL // schedule
, NULL // cancel
- , rlsPerform // perform
+ , reachPerform // perform
};
if (runLoop != NULL) {
targetPrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
- targetPrivate->scheduled = TRUE;
if (targetPrivate->type == reachabilityTypeName) {
+ /*
+ * we're now scheduled so let's ensure that we
+ * are starting with a clean slate before we
+ * resolve the name
+ */
+ if (targetPrivate->resolvedAddress != NULL) {
+ CFRelease(targetPrivate->resolvedAddress);
+ targetPrivate->resolvedAddress = NULL;
+ }
+ targetPrivate->resolvedAddressError = NETDB_SUCCESS;
targetPrivate->needResolve = TRUE;
+ _reach_set(&targetPrivate->info, &NOT_REACHABLE, targetPrivate->info.cycle);
+ targetPrivate->info.flags |= kSCNetworkReachabilityFlagsFirstResolvePending;
+#ifdef HAVE_REACHABILITY_SERVER
+ _reach_set(&targetPrivate->serverInfo, &NOT_REACHABLE, targetPrivate->serverInfo.cycle);
+ targetPrivate->serverInfo.flags |= kSCNetworkReachabilityFlagsFirstResolvePending;
+#endif // HAVE_REACHABILITY_SERVER
}
+
+ targetPrivate->scheduled = TRUE;
+
init = TRUE;
}
if (queue != NULL) {
+ // retain dispatch queue
+ dispatch_retain(queue);
targetPrivate->dispatchQueue = queue;
- dispatch_retain(targetPrivate->dispatchQueue);
+
+ //
+ // We've taken a reference to the client's dispatch_queue and we
+ // want to hold on to that reference until we've processed any/all
+ // notifications. To facilitate this we create a group, dispatch
+ // any notification blocks to via that group, and when the caller
+ // has told us to stop the notifications (unschedule) we wait for
+ // the group to empty and use the group's finalizer to release
+ // our reference to the client's queue.
+ //
+
+ // make sure that we have group to track any async requests
+ targetPrivate->dispatchGroup = dispatch_group_create();
+
+ // retain the target ... and release it when the group is released
+ CFRetain(target);
+ dispatch_set_context(targetPrivate->dispatchGroup, (void *)target);
+ dispatch_set_finalizer_f(targetPrivate->dispatchGroup, (dispatch_function_t)CFRelease);
} else {
if (!_SC_isScheduled(NULL, runLoop, runLoopMode, targetPrivate->rlList)) {
/*
CFRunLoopAddSource(runLoop, targetPrivate->rls, runLoopMode);
if (targetPrivate->dnsRLS != NULL) {
- /* if we have an active async DNS query too */
+ // if we have an active async DNS query too
CFRunLoopAddSource(runLoop, targetPrivate->dnsRLS, runLoopMode);
}
}
_SC_schedule(target, runLoop, runLoopMode, targetPrivate->rlList);
}
- CFSetAddValue(hn_targets, target);
-
if (init) {
ReachabilityInfo reach_info = NOT_REACHABLE;
ReachabilityStoreInfo store_info;
* if we have yet to schedule SC notifications for this address
* - initialize current reachability status
*/
- initReachabilityStoreInfo(&store_info);
+ ReachabilityStoreInfo_init(&store_info);
if (__SCNetworkReachabilityGetFlags(&store_info, target, &reach_info, TRUE)) {
/*
* if reachability status available
* - set flags
* - schedule notification to report status via callback
*/
- targetPrivate->info = reach_info;
+#ifdef HAVE_REACHABILITY_SERVER
+ reach_info.flags |= (targetPrivate->info.flags & kSCNetworkReachabilityFlagsFirstResolvePending);
+#endif // HAVE_REACHABILITY_SERVER
+ _reach_set(&targetPrivate->info, &reach_info, targetPrivate->cycle);
__SCNetworkReachabilityPerform(target);
} else {
/* if reachability status not available, async lookup started */
- targetPrivate->info = NOT_REACHABLE;
+ _reach_set(&targetPrivate->info, &NOT_REACHABLE, targetPrivate->cycle);
+#ifdef HAVE_REACHABILITY_SERVER
+ _reach_set(&targetPrivate->serverInfo, &NOT_REACHABLE, targetPrivate->cycle);
+#endif // HAVE_REACHABILITY_SERVER
}
- freeReachabilityStoreInfo(&store_info);
+ ReachabilityStoreInfo_free(&store_info);
}
if (targetPrivate->onDemandServer != NULL) {
done :
- pthread_mutex_unlock(&targetPrivate->lock);
- if (!onDemand) {
- pthread_mutex_unlock(&hn_lock);
- }
+ MUTEX_UNLOCK(&targetPrivate->lock);
return ok;
}
CFStringRef runLoopMode,
Boolean onDemand)
{
- SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+ dispatch_group_t drainGroup = NULL;
+ dispatch_queue_t drainQueue = NULL;
CFIndex n = 0;
Boolean ok = FALSE;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- if (!onDemand) {
- pthread_mutex_lock(&hn_lock);
- }
- pthread_mutex_lock(&targetPrivate->lock);
+ // hold a reference while we unschedule
+ CFRetain(target);
+
+ MUTEX_LOCK(&targetPrivate->lock);
if (((runLoop == NULL) && (targetPrivate->dispatchQueue == NULL)) || // if we should be scheduled on a dispatch queue (but are not)
((runLoop != NULL) && (targetPrivate->dispatchQueue != NULL))) { // if we should be scheduled on a CFRunLoop (but are not)
goto done;
}
- // first, unschedule the target specific sources
+ // unschedule the target specific sources
if (targetPrivate->dispatchQueue != NULL) {
if (targetPrivate->onDemandServer != NULL) {
__SCNetworkReachabilityUnscheduleFromRunLoop(targetPrivate->onDemandServer, NULL, NULL, TRUE);
}
+
+ // save dispatchQueue, release reference when we've queue'd blocks complete, allow re-scheduling
+ drainGroup = targetPrivate->dispatchGroup;
+ targetPrivate->dispatchGroup = NULL;
+ drainQueue = targetPrivate->dispatchQueue;
+ targetPrivate->dispatchQueue = NULL;
} else {
if (!_SC_unschedule(target, runLoop, runLoopMode, targetPrivate->rlList, FALSE)) {
// if not currently scheduled
}
if (n == 0) {
+#ifdef HAVE_REACHABILITY_SERVER
+ //
+ // Cancel our request for server monitoring
+ //
+ if (targetPrivate->serverActive) {
+ ok = __SCNetworkReachabilityServer_targetUnschedule(target);
+ if (!ok) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("__SCNetworkReachabilityUnscheduleFromRunLoop _targetMonitor() failed"));
+ _SCErrorSet(kSCStatusFailed);
+ }
+ }
+#endif // HAVE_REACHABILITY_SERVER
+
// if *all* notifications have been unscheduled
targetPrivate->scheduled = FALSE;
+ }
- if (!onDemand) {
- CFSetRemoveValue(hn_targets, target); // cleanup notification resources
- }
-
- if (targetPrivate->dnsPort != NULL) {
- mach_port_t mp = CFMachPortGetPort(targetPrivate->dnsPort);
+#ifdef HAVE_REACHABILITY_SERVER
+ if (targetPrivate->serverActive) {
+ goto unwatch;
+ }
+#endif // HAVE_REACHABILITY_SERVER
+ if (n == 0) {
+ if (targetPrivate->dnsMP != MACH_PORT_NULL) {
// if we have an active async DNS query
- dequeueAsyncDNSQuery(target);
- getaddrinfo_async_cancel(mp);
+ dequeueAsyncDNSQuery(target, TRUE);
}
if (targetPrivate->dnsRetry != NULL) {
// if we have an outstanding DNS retry
dequeueAsyncDNSRetry(target);
}
- }
- if (runLoop == NULL) {
- dispatch_release(targetPrivate->dispatchQueue);
- targetPrivate->dispatchQueue = NULL;
- }
+ if (targetPrivate->llqActive) {
+ // if we have a long-lived-query
+ dequeueLongLivedQuery(target);
+ }
- n = CFSetGetCount(hn_targets);
- if (n == 0) {
- // if we are no longer monitoring any targets
- SCDynamicStoreSetDispatchQueue(hn_store, NULL);
- dispatch_release(hn_dispatchQueue);
- hn_dispatchQueue = NULL;
- CFRelease(hn_store);
- hn_store = NULL;
- CFRelease(hn_targets);
- hn_targets = NULL;
+ dispatch_sync(_hn_queue(), ^{
+ CFSetRemoveValue(hn_targets, target);
- /*
- * until we start monitoring again, ensure that
- * any resources associated with tracking the
- * DNS configuration have been released.
- */
- dns_configuration_unwatch();
+ if (onDemand) {
+ return;
+ }
+
+ if (CFSetGetCount(hn_targets) > 0) {
+ return;
+ }
+
+ // if we are no longer monitoring any targets
+ SCDynamicStoreSetDispatchQueue(hn_store, NULL);
+ dispatch_release(hn_dispatchQueue);
+ hn_dispatchQueue = NULL;
+ CFRelease(hn_store);
+ hn_store = NULL;
+ CFRelease(hn_targets);
+ hn_targets = NULL;
+
+ ReachabilityStoreInfo_enable(FALSE);
+ ReachabilityStoreInfo_save(NULL);
+
+ /*
+ * until we start monitoring again, ensure that
+ * any resources associated with tracking the
+ * DNS configuration have been released.
+ */
+ dns_configuration_unwatch();
+ });
}
+#ifdef HAVE_REACHABILITY_SERVER
+ unwatch :
+#endif // HAVE_REACHABILITY_SERVER
+
SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%sunscheduled"),
targetPrivate->log_prefix);
done :
- pthread_mutex_unlock(&targetPrivate->lock);
- if (!onDemand) {
- pthread_mutex_unlock(&hn_lock);
+ MUTEX_UNLOCK(&targetPrivate->lock);
+
+ if (drainGroup != NULL) {
+ dispatch_group_notify(drainGroup, __SCNetworkReachability_concurrent_queue(), ^{
+ // release group/queue references
+ dispatch_release(drainQueue);
+ dispatch_release(drainGroup); // releases our target reference
+ });
}
+
+ // release our reference
+ CFRelease(target);
+
return ok;
}
--- /dev/null
+/*
+ * Copyright (c) 2003-2012 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,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * 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@
+ */
+
+#ifndef _SCNETWORKREACHABILITYINTERNAL_H
+#define _SCNETWORKREACHABILITYINTERNAL_H
+
+#include <Availability.h>
+#include <TargetConditionals.h>
+#include <sys/cdefs.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <dispatch/dispatch.h>
+
+#include <dns_sd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) && !TARGET_IPHONE_SIMULATOR
+#define HAVE_REACHABILITY_SERVER
+#include <xpc/xpc.h>
+#endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) && !TARGET_IPHONE_SIMULATOR
+
+
+#pragma mark -
+#pragma mark SCNetworkReachability
+
+
+#define kSCNetworkReachabilityFlagsFirstResolvePending (1<<31)
+
+
+typedef enum { NO = 0, YES, UNKNOWN } lazyBoolean;
+
+
+typedef enum {
+ reachabilityTypeAddress,
+ reachabilityTypeAddressPair,
+ reachabilityTypeName
+} ReachabilityAddressType;
+
+
+typedef struct {
+ uint64_t cycle;
+ SCNetworkReachabilityFlags flags;
+ unsigned int if_index;
+ char if_name[IFNAMSIZ];
+ Boolean sleeping;
+} ReachabilityInfo;
+
+
+typedef struct {
+
+ /* base CFType information */
+ CFRuntimeBase cfBase;
+
+ /* lock */
+ pthread_mutex_t lock;
+
+ /* address type */
+ ReachabilityAddressType type;
+
+ /* target host name */
+ const char *name;
+ const char *serv;
+ struct addrinfo hints;
+ Boolean needResolve;
+ CFArrayRef resolvedAddress; /* CFArray[CFData] */
+ int resolvedAddressError;
+
+ /* [scoped routing] interface constraints */
+ unsigned int if_index;
+ char if_name[IFNAMSIZ];
+
+ /* local & remote addresses */
+ struct sockaddr *localAddress;
+ struct sockaddr *remoteAddress;
+
+ /* current reachability flags */
+ uint64_t cycle;
+ ReachabilityInfo info;
+ ReachabilityInfo last_notify;
+
+ /* run loop source, callout, context, rl scheduling info */
+ Boolean scheduled;
+ CFRunLoopSourceRef rls;
+ SCNetworkReachabilityCallBack rlsFunction;
+ SCNetworkReachabilityContext rlsContext;
+ CFMutableArrayRef rlList;
+
+ dispatch_group_t dispatchGroup;
+ dispatch_queue_t dispatchQueue; // SCNetworkReachabilitySetDispatchQueue
+
+ /* [async] DNS query info */
+ Boolean haveDNS;
+ mach_port_t dnsMP; // != MACH_PORT_NULL (if active)
+ CFMachPortRef dnsPort; // for CFRunLoop queries
+ CFRunLoopSourceRef dnsRLS; // for CFRunLoop queries
+ dispatch_source_t dnsSource; // for dispatch queries
+ struct timeval dnsQueryStart;
+ struct timeval dnsQueryEnd;
+ dispatch_source_t dnsRetry; // != NULL if DNS retry request queued
+ int dnsRetryCount; // number of retry attempts
+
+ /* [async] processing info */
+ struct timeval last_dns;
+ struct timeval last_network;
+#if !TARGET_OS_IPHONE
+ struct timeval last_power;
+#endif // !TARGET_OS_IPHONE
+ struct timeval last_push;
+
+ /* on demand info */
+ Boolean onDemandBypass;
+ CFStringRef onDemandName;
+ CFStringRef onDemandRemoteAddress;
+ SCNetworkReachabilityRef onDemandServer;
+ CFStringRef onDemandServiceID;
+
+
+ Boolean llqActive;
+ Boolean llqBypass;
+ DNSServiceRef llqTarget;
+ dispatch_source_t llqTimer; // != NULL while waiting for first callback
+
+#ifdef HAVE_REACHABILITY_SERVER
+ /* SCNetworkReachability server "client" info */
+ Boolean serverActive;
+ Boolean serverBypass;
+ Boolean serverScheduled;
+ ReachabilityInfo serverInfo;
+
+ /* SCNetworkReachability server "server" info */
+ CFDataRef serverDigest;
+ dispatch_group_t serverGroup;
+ Boolean serverInfoValid;
+ unsigned int serverQueryActive; // 0 == no query active, else # waiting on group
+ dispatch_queue_t serverQueue;
+ unsigned int serverReferences; // how many [client] targets
+ CFMutableDictionaryRef serverWatchers; // [client_id/target_id] watchers
+#endif // HAVE_REACHABILITY_SERVER
+ Boolean resolverBypass; // set this flag to bypass resolving the name
+
+ /* logging */
+ char log_prefix[32];
+
+} SCNetworkReachabilityPrivate, *SCNetworkReachabilityPrivateRef;
+
+
+#ifdef HAVE_REACHABILITY_SERVER
+
+// ------------------------------------------------------------
+
+#pragma mark -
+#pragma mark [XPC] Reachability Server
+
+
+#define REACH_SERVER_VERSION 20110323
+#define REACH_SERVICE_NAME "com.apple.SystemConfiguration.SCNetworkReachability"
+
+// ------------------------------------------------------------
+
+
+#pragma mark -
+#pragma mark [XPC] Reachability Server (client->server request)
+
+
+#define REACH_CLIENT_PROC_NAME "proc_name" // string
+#define REACH_CLIENT_TARGET_ID "target_id" // uint64
+
+#define REACH_REQUEST "request_op" // int64
+
+enum {
+ REACH_REQUEST_CREATE = 0x0001,
+ REACH_REQUEST_REMOVE,
+ REACH_REQUEST_SCHEDULE,
+ REACH_REQUEST_STATUS,
+ REACH_REQUEST_UNSCHEDULE,
+ REACH_REQUEST_SNAPSHOT = 0x0101,
+};
+
+#define REACH_TARGET_NAME "name" // string
+#define REACH_TARGET_SERV "serv" // string
+#define REACH_TARGET_HINTS "hints" // data (struct addrinfo)
+#define REACH_TARGET_IF_INDEX "if_index" // int64
+#define REACH_TARGET_IF_NAME "if_name" // string
+#define REACH_TARGET_LOCAL_ADDR "localAddress" // data (struct sockaddr)
+#define REACH_TARGET_REMOTE_ADDR "remoteAddress" // data (struct sockaddr)
+#define REACH_TARGET_ONDEMAND_BYPASS "onDemandBypass" // bool
+#define REACH_TARGET_RESOLVER_BYPASS "resolverBypass" // bool
+
+
+#define REACH_REQUEST_REPLY "reply" // int64
+#define REACH_REQUEST_REPLY_DETAIL "reply_detail" // string
+
+enum {
+ REACH_REQUEST_REPLY_OK = 0x0000,
+ REACH_REQUEST_REPLY_FAILED,
+ REACH_REQUEST_REPLY_UNKNOWN,
+};
+
+
+// ------------------------------------------------------------
+
+
+#pragma mark -
+#pragma mark [XPC] Reachability Server (server->client request)
+
+
+#define MESSAGE_NOTIFY "notify_op" // int64
+
+enum {
+ MESSAGE_REACHABILITY_STATUS = 0x1001,
+};
+
+#define REACH_STATUS_CYCLE "cycle" // uint64
+#define REACH_STATUS_FLAGS "flags" // uint64
+#define REACH_STATUS_IF_INDEX "if_index" // uint64
+#define REACH_STATUS_IF_NAME "if_name" // data (char if_name[IFNAMSIZ])
+#define REACH_STATUS_RESOLVED_ADDRESS "resolvedAddress" // array[data]
+#define REACH_STATUS_RESOLVED_ADDRESS_ERROR "resolvedAddressError" // int64
+#define REACH_STATUS_SLEEPING "sleeping" // bool
+
+
+// ------------------------------------------------------------
+
+#endif // HAVE_REACHABILITY_SERVER
+
+
+__BEGIN_DECLS
+
+CFStringRef
+_SCNetworkReachabilityCopyTargetDescription (SCNetworkReachabilityRef target);
+
+CFStringRef
+_SCNetworkReachabilityCopyTargetFlags (SCNetworkReachabilityRef target);
+
+#ifdef HAVE_REACHABILITY_SERVER
+
+dispatch_queue_t
+__SCNetworkReachability_concurrent_queue (void);
+
+void
+__SCNetworkReachabilityPerformNoLock (SCNetworkReachabilityRef target);
+
+#pragma mark -
+#pragma mark [XPC] Reachability Server (client APIs)
+
+Boolean
+_SCNetworkReachabilityServer_snapshot (void);
+
+Boolean
+__SCNetworkReachabilityServer_targetAdd (SCNetworkReachabilityRef target);
+
+void
+__SCNetworkReachabilityServer_targetRemove (SCNetworkReachabilityRef target);
+
+Boolean
+__SCNetworkReachabilityServer_targetSchedule (SCNetworkReachabilityRef target);
+
+Boolean
+__SCNetworkReachabilityServer_targetStatus (SCNetworkReachabilityRef target);
+
+Boolean
+__SCNetworkReachabilityServer_targetUnschedule (SCNetworkReachabilityRef target);
+
+Boolean
+__SC_checkResolverReachabilityInternal (SCDynamicStoreRef *storeP,
+ SCNetworkReachabilityFlags *flags,
+ Boolean *haveDNS,
+ const char *nodename,
+ const char *servname,
+ uint32_t *resolver_if_index,
+ int *dns_config_index);
+
+#endif // HAVE_REACHABILITY_SERVER
+
+__END_DECLS
+
+#endif // _SCNETWORKREACHABILITYINTERNAL_H
}
-__private_extern__ CFStringRef
+__private_extern__ CF_RETURNS_RETAINED CFStringRef
__SCNetworkServiceNextName(SCNetworkServiceRef service)
{
CFArrayRef components;
}
-static CFDictionaryRef
+static CF_RETURNS_RETAINED CFDictionaryRef
_protocolTemplate(SCNetworkServiceRef service, CFStringRef protocolType)
{
SCNetworkInterfaceRef interface;
#pragma mark SCNetworkService SPIs
-static Boolean
-str_to_rank(CFStringRef rankStr, SCNetworkServicePrimaryRank *rank)
-{
- if (isA_CFString(rankStr)) {
- if (CFEqual(rankStr, kSCValNetServicePrimaryRankFirst)) {
- *rank = kSCNetworkServicePrimaryRankFirst;
- } else if (CFEqual(rankStr, kSCValNetServicePrimaryRankLast)) {
- *rank = kSCNetworkServicePrimaryRankLast;
- } else if (CFEqual(rankStr, kSCValNetServicePrimaryRankNever)) {
- *rank = kSCNetworkServicePrimaryRankNever;
- } else {
- return FALSE;
- }
- } else if (rankStr == NULL) {
- *rank = kSCNetworkServicePrimaryRankDefault;
- } else {
- return FALSE;
- }
-
- return TRUE;
-}
-
-
SCNetworkServicePrimaryRank
SCNetworkServiceGetPrimaryRank(SCNetworkServiceRef service)
{
CFRelease(path);
if (isA_CFDictionary(entity)) {
rankStr = CFDictionaryGetValue(entity, kSCPropNetServicePrimaryRank);
- ok = str_to_rank(rankStr, &rank);
+ ok = __str_to_rank(rankStr, &rank);
}
} else if (servicePrivate->store != NULL) {
path = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
if (entity != NULL) {
if (isA_CFDictionary(entity)) {
rankStr = CFDictionaryGetValue(entity, kSCPropNetServicePrimaryRank);
- ok = str_to_rank(rankStr, &rank);
+ ok = __str_to_rank(rankStr, &rank);
}
CFRelease(entity);
}
}
-static Boolean
-rank_to_str(SCNetworkServicePrimaryRank rank, CFStringRef *rankStr)
-{
- switch (rank) {
- case kSCNetworkServicePrimaryRankDefault :
- *rankStr = NULL;
- break;
- case kSCNetworkServicePrimaryRankFirst :
- *rankStr = kSCValNetServicePrimaryRankFirst;
- break;
- case kSCNetworkServicePrimaryRankLast :
- *rankStr = kSCValNetServicePrimaryRankLast;
- break;
- case kSCNetworkServicePrimaryRankNever :
- *rankStr = kSCValNetServicePrimaryRankNever;
- break;
- default :
- return FALSE;
- }
-
- return TRUE;
-}
-
-
Boolean
SCNetworkServiceSetPrimaryRank(SCNetworkServiceRef service,
SCNetworkServicePrimaryRank newRank)
return FALSE;
}
- ok = rank_to_str(newRank, &rankStr);
+ ok = __rank_to_str(newRank, &rankStr);
if (!ok) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
excluded = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+#if !TARGET_OS_IPHONE
// exclude Bond [member] interfaces
interfaces = SCBondInterfaceCopyAll(prefs);
if (interfaces != NULL) {
__SCBondInterfaceListCollectMembers(interfaces, excluded);
CFRelease(interfaces);
}
+#endif // !TARGET_OS_IPHONE
// exclude Bridge [member] interfaces
interfaces = SCBridgeInterfaceCopyAll(prefs);
const char * kSCNetworkSignatureActiveChangedNotifyName = NETWORK_ID_KEY ".active";
+#pragma mark SCNetworkSignature Supporting APIs
-#pragma mark SCNetworkSignature support routines
+static CFStringRef
+create_global_state_v4_key(void)
+{
+ return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCEntNetIPv4);
+
+}
+
+static CFStringRef
+create_global_setup_v4_key(void)
+{
+ return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ kSCEntNetIPv4);
+}
-static __inline__ SCDynamicStoreRef
-store_create(CFAllocatorRef alloc)
+static CFStringRef
+create_ipv4_services_pattern(void)
{
- return (SCDynamicStoreCreate(alloc, CFSTR("SCNetworkSignature"),
- NULL, NULL));
+ return SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCCompAnyRegex,
+ kSCEntNetIPv4);
+}
+
+static CFStringRef
+create_ipv6_services_pattern(void)
+{
+ return SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCCompAnyRegex,
+ kSCEntNetIPv6);
}
static CFDictionaryRef
-store_copy_id_dict(CFAllocatorRef alloc, SCDynamicStoreRef store)
+copy_services_for_address_family(CFAllocatorRef alloc,
+ int af)
{
- CFDictionaryRef id_dict = NULL;
- Boolean release_store = FALSE;
+ CFDictionaryRef info;
+ CFArrayRef patterns;
+ CFStringRef pattern;
+ CFStringRef prop;
+
+ prop = (af == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6;
+ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCCompAnyRegex,
+ prop);
+ patterns = CFArrayCreate(NULL,
+ (const void * *)&pattern, 1,
+ &kCFTypeArrayCallBacks);
+ CFRelease(pattern);
+ info = SCDynamicStoreCopyMultiple(NULL, NULL, patterns);
+ CFRelease(patterns);
+
+ return (info);
+}
- if (store == NULL) {
- store = store_create(alloc);
- if (store == NULL) {
- goto done;
- }
- release_store = TRUE;
- }
- id_dict = SCDynamicStoreCopyValue(store,
- kSCNetworkIdentificationStoreKey);
- if (isA_CFDictionary(id_dict) == NULL) {
- if (id_dict != NULL) {
- CFRelease(id_dict);
- id_dict = NULL;
- }
- goto done;
- }
- done:
- if (release_store) {
- CFRelease(store);
+
+static CF_RETURNS_RETAINED CFStringRef
+my_IPAddressToCFString(int af, const void * src_p)
+{
+ char ntopbuf[INET6_ADDRSTRLEN];
+
+ if (inet_ntop(af, src_p, ntopbuf, sizeof(ntopbuf)) != NULL) {
+ return (CFStringCreateWithCString(NULL, ntopbuf,
+ kCFStringEncodingASCII));
}
- return (id_dict);
+ return (NULL);
}
-#pragma -
+#pragma mark -
+
#pragma mark SCNetworkSignature APIs
SCNetworkSignatureCopyActiveIdentifierForAddress(CFAllocatorRef alloc,
const struct sockaddr * addr)
{
- CFDictionaryRef id_dict = NULL;
- CFStringRef ident = NULL;
+ CFStringRef ident = NULL;
+ CFDictionaryRef info = NULL;
+ CFStringRef global_state_v4_key = NULL;
+ CFDictionaryRef global_v4_state_dict = NULL;
+ CFArrayRef keys = NULL;
+ CFArrayRef patterns = NULL;
+ in_addr_t s_addr;
+ CFStringRef service = NULL;
+ CFDictionaryRef service_dict = NULL;
+ CFStringRef service_id = NULL;
struct sockaddr_in * sin_p;
-
+ CFStringRef v4_service_pattern = NULL;
/* only accept 0.0.0.0 (i.e. default) for now */
- sin_p = (struct sockaddr_in *)addr;
if (addr == NULL
|| addr->sa_family != AF_INET
- || addr->sa_len != sizeof(struct sockaddr_in)
- || sin_p->sin_addr.s_addr != 0) {
+ || addr->sa_len != sizeof(struct sockaddr_in)){
_SCErrorSet(kSCStatusInvalidArgument);
goto done;
}
- id_dict = store_copy_id_dict(alloc, NULL);
- if (id_dict == NULL) {
- _SCErrorSet(kSCStatusFailed);
+
+ /* ALIGN: force alignment */
+ sin_p = (struct sockaddr_in *)(void *)addr;
+ bcopy(&sin_p->sin_addr.s_addr, &s_addr, sizeof(s_addr));
+ if (s_addr != 0) {
+ _SCErrorSet(kSCStatusInvalidArgument);
goto done;
}
- ident = CFDictionaryGetValue(id_dict, kStoreKeyPrimaryIPv4Identifier);
- if (isA_CFString(ident) != NULL) {
- CFRetain(ident);
+
+ global_state_v4_key = create_global_state_v4_key();
+ keys = CFArrayCreate(NULL, (const void * *)&global_state_v4_key,
+ 1, &kCFTypeArrayCallBacks);
+
+ v4_service_pattern = create_ipv4_services_pattern();
+ patterns = CFArrayCreate(NULL, (const void * *)&v4_service_pattern, 1,
+ &kCFTypeArrayCallBacks);
+
+ info = SCDynamicStoreCopyMultiple(NULL, keys, patterns);
+
+ if (info == NULL
+ || CFDictionaryGetCount(info) == 0) {
+ goto done;
}
- else {
+
+ global_v4_state_dict = CFDictionaryGetValue(info, global_state_v4_key);
+
+ if (isA_CFDictionary(global_v4_state_dict) == NULL) {
+ goto done;
+ }
+
+ service_id = CFDictionaryGetValue(global_v4_state_dict,
+ kSCDynamicStorePropNetPrimaryService);
+
+ if (isA_CFString(service_id) == NULL) {
+ goto done;
+ }
+
+ service = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ service_id, kSCEntNetIPv4);
+
+ service_dict = CFDictionaryGetValue(info, service);
+
+
+ if (isA_CFDictionary(service_dict) == NULL
+ || CFDictionaryGetCount(service_dict) == 0) {
+ goto done;
+ }
+
+ ident = CFDictionaryGetValue(service_dict, kStoreKeyNetworkSignature);
+ ident = isA_CFString(ident);
+done:
+ if (ident != NULL) {
+ CFRetain(ident);
+ } else {
_SCErrorSet(kSCStatusFailed);
}
- done:
- if (id_dict != NULL) {
- CFRelease(id_dict);
+ if (info != NULL) {
+ CFRelease(info);
+ }
+ if (global_state_v4_key != NULL) {
+ CFRelease(global_state_v4_key);
+ }
+ if (service != NULL) {
+ CFRelease(service);
+ }
+ if (keys != NULL) {
+ CFRelease(keys);
+ }
+ if (patterns != NULL) {
+ CFRelease(patterns);
+ }
+ if (v4_service_pattern != NULL) {
+ CFRelease(v4_service_pattern);
}
return (ident);
}
CFArrayRef /* of CFStringRef's */
SCNetworkSignatureCopyActiveIdentifiers(CFAllocatorRef alloc)
{
- CFArrayRef active = NULL;
- int i;
+ CFMutableArrayRef active = NULL;
int count = 0;
- CFDictionaryRef id_dict = NULL;
+ CFStringRef global_setup_v4_key = NULL;
+ CFDictionaryRef global_v4_dict;
+ int i;
+ CFDictionaryRef info = NULL;
+ CFArrayRef keys = NULL;
+ CFMutableArrayRef patterns = NULL;
+ CFRange range;
+ CFMutableDictionaryRef services_dict = NULL;
+ CFArrayRef service_order;
+ CFStringRef v4_service_pattern = NULL;
+ CFStringRef v6_service_pattern = NULL;
+ const void * * values = NULL;
+#define KEYS_STATIC_COUNT 10
+ const void * values_static[KEYS_STATIC_COUNT];
- id_dict = store_copy_id_dict(alloc, NULL);
- if (id_dict == NULL) {
+ patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ global_setup_v4_key = create_global_setup_v4_key();
+ keys = CFArrayCreate(NULL, (const void * *)&global_setup_v4_key, 1,
+ &kCFTypeArrayCallBacks);
+
+ v4_service_pattern = create_ipv4_services_pattern();
+ CFArrayAppendValue(patterns, v4_service_pattern);
+
+ v6_service_pattern = create_ipv6_services_pattern();
+ CFArrayAppendValue(patterns, v6_service_pattern);
+
+ info = SCDynamicStoreCopyMultiple(NULL, keys, patterns);
+
+ if (info == NULL
+ || CFDictionaryGetCount(info) == 0) {
goto done;
}
- active = CFDictionaryGetValue(id_dict, kStoreKeyActiveIdentifiers);
- if (isA_CFArray(active) != NULL) {
- count = CFArrayGetCount(active);
+
+ services_dict = CFDictionaryCreateMutableCopy(NULL, 0, info);
+ /*
+ * The service_dict should only contain services and once each
+ * service has been visited, it will be removed from the dictionary.
+ */
+ CFDictionaryRemoveValue(services_dict, global_setup_v4_key);
+
+ global_v4_dict = CFDictionaryGetValue(info, global_setup_v4_key);
+
+ if (isA_CFDictionary(global_v4_dict) == NULL) {
+ service_order = CFDictionaryGetValue(global_v4_dict,
+ kSCPropNetServiceOrder);
+ if (isA_CFArray(service_order) != NULL) {
+ count = CFArrayGetCount(service_order);
+ }
}
- if (count == 0) {
- active = NULL;
- goto done;
+
+ active = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ range = CFRangeMake(0, 0);
+
+ for (i = 0; i < count ; i++) {
+ int j;
+ CFStringRef network_sig;
+ CFStringRef service;
+ CFStringRef service_id;
+ CFDictionaryRef service_info;
+ CFStringRef afs[2] = {kSCEntNetIPv4, kSCEntNetIPv6};
+
+ service_id = CFArrayGetValueAtIndex(service_order, i);
+
+ if (isA_CFString(service_id) == NULL) {
+ continue;
+ }
+
+ for (j = 0; j < 2; j++) {
+ service = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ service_id, afs[j]);
+
+ service_info = CFDictionaryGetValue(services_dict, service);
+
+ /* Does this service have a signature? */
+ if (isA_CFDictionary(service_info) != NULL) {
+ network_sig = CFDictionaryGetValue(service_info, kStoreKeyNetworkSignature);
+ if (isA_CFString(network_sig) != NULL
+ && CFArrayContainsValue(active, range, network_sig) == FALSE) {
+ CFArrayAppendValue(active, network_sig);
+ network_sig = NULL;
+ range.length++;
+ }
+ CFDictionaryRemoveValue(services_dict, service);
+ }
+ CFRelease(service);
+ }
}
- for (i = 0; i < count; i++) {
- CFStringRef ident = CFArrayGetValueAtIndex(active, i);
- if (isA_CFString(ident) == NULL) {
- active = NULL;
- goto done;
+ count = CFDictionaryGetCount(services_dict);
+
+ if (count != 0) {
+ if (count > KEYS_STATIC_COUNT) {
+ values = (const void * *)malloc(sizeof(*values) * count);
+ } else {
+ values = values_static;
}
+ CFDictionaryGetKeysAndValues(services_dict, NULL,
+ (const void * *)values);
}
- CFRetain(active);
+
+ for (i = 0; i < count; i++) {
+ CFStringRef network_sig;
+ CFDictionaryRef service_dict = (CFDictionaryRef)values[i];
+ if (isA_CFDictionary(service_dict) == NULL) {
+ continue;
+ }
+
+ network_sig = CFDictionaryGetValue(service_dict,
+ kStoreKeyNetworkSignature);
+ /* Does this service have a signature? */
+ if (isA_CFString(network_sig) != NULL
+ && CFArrayContainsValue(active, range, network_sig) == FALSE) {
+ CFArrayAppendValue(active, network_sig);
+ range.length++;
+ network_sig = NULL;
+ }
+ }
done:
- if (id_dict != NULL) {
- CFRelease(id_dict);
+ if (info != NULL) {
+ CFRelease(info);
+ }
+ if (services_dict != NULL) {
+ CFRelease(services_dict);
+ }
+ if (global_setup_v4_key != NULL) {
+ CFRelease(global_setup_v4_key);
+ }
+ if (v4_service_pattern != NULL) {
+ CFRelease(v4_service_pattern);
+ }
+ if (v6_service_pattern != NULL) {
+ CFRelease(v6_service_pattern);
+ }
+ if (values != NULL && values != values_static) {
+ free(values);
+ }
+ if (keys != NULL) {
+ CFRelease(keys);
+ }
+ if (patterns != NULL) {
+ CFRelease(patterns);
+ }
+ if (active != NULL && CFArrayGetCount(active) == 0) {
+ CFRelease(active);
+ active = NULL;
}
if (active == NULL) {
_SCErrorSet(kSCStatusFailed);
return (active);
}
-static CFDictionaryRef
-copy_services_for_address_family(CFAllocatorRef alloc,
- SCDynamicStoreRef store, int af)
-{
- CFDictionaryRef info;
- CFArrayRef patterns;
- CFStringRef pattern;
- CFStringRef prop;
- Boolean release_store = FALSE;
-
- if (store == NULL) {
- store = store_create(alloc);
- if (store == NULL) {
- return (NULL);
- }
- release_store = TRUE;
- }
- prop = (af == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6;
- pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
- kSCDynamicStoreDomainState,
- kSCCompAnyRegex,
- prop);
- patterns = CFArrayCreate(NULL,
- (const void * *)&pattern, 1,
- &kCFTypeArrayCallBacks);
- CFRelease(pattern);
- info = SCDynamicStoreCopyMultiple(store, NULL, patterns);
- CFRelease(patterns);
- if (release_store) {
- CFRelease(store);
- }
- return (info);
-}
-
-static CFStringRef
-my_IPAddressToCFString(int af, const void * src_p)
-{
- char ntopbuf[INET6_ADDRSTRLEN];
-
- if (inet_ntop(af, src_p, ntopbuf, sizeof(ntopbuf)) != NULL) {
- return (CFStringCreateWithCString(NULL, ntopbuf,
- kCFStringEncodingASCII));
- }
- return (NULL);
-}
CFStringRef
SCNetworkSignatureCopyIdentifierForConnectedSocket(CFAllocatorRef alloc,
const void * * keys = NULL;
#define KEYS_STATIC_COUNT 10
const void * keys_static[KEYS_STATIC_COUNT];
- static const void * local_ip_p;
+ const void * local_ip_p;
CFStringRef local_ip_str = NULL;
CFStringRef ret_signature = NULL;
CFDictionaryRef service_info = NULL;
}
/* find a service matching the local IP and get its network signature */
- service_info = copy_services_for_address_family(alloc, NULL, af);
+ service_info = copy_services_for_address_family(alloc, af);
if (service_info == NULL) {
goto done;
}
#define _SCNETWORKSIGNATURE_H
#include <Availability.h>
+#include <sys/cdefs.h>
#include <CoreFoundation/CFString.h>
#include <CoreFoundation/CFArray.h>
#include <netinet/in.h>
+__BEGIN_DECLS
+
/*!
@header SCNetworkSignature
@discussion The SCNetworkSignature API provides access to the
CFStringRef
SCNetworkSignatureCopyIdentifierForConnectedSocket(CFAllocatorRef alloc,
int sock_fd) __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/);
+
+__END_DECLS
+
#endif /* _SCNETWORKSIGNATURE_H */
/*
- * Copyright (c) 2000, 2001, 2003-2005, 2007-2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2005, 2007-2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <sys/errno.h>
#include <sys/param.h>
-__private_extern__ CFDataRef
+__private_extern__ CF_RETURNS_RETAINED CFDataRef
__SCPSignatureFromStatbuf(const struct stat *statBuf)
{
CFMutableDataRef signature;
signature = CFDataCreateMutable(NULL, sizeof(SCPSignatureData));
CFDataSetLength(signature, sizeof(SCPSignatureData));
- sig = (SCPSignatureDataRef)CFDataGetBytePtr(signature);
+
+ /* ALIGN: CFDataGetBytePtr aligns to at least 8 bytes */
+ sig = (SCPSignatureDataRef)(void *)CFDataGetBytePtr(signature);
+
sig->st_dev = statBuf->st_dev;
sig->st_ino = statBuf->st_ino;
sig->tv_sec = statBuf->st_mtimespec.tv_sec;
}
-__private_extern__ CFStringRef
+__private_extern__ CF_RETURNS_RETAINED CFStringRef
_SCPNotificationKey(CFAllocatorRef allocator,
CFStringRef prefsID,
int keyType)
#include "dy_framework.h"
#include <fcntl.h>
-#include <libproc.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/errno.h>
+const AuthorizationRef kSCPreferencesUseEntitlementAuthorization = (AuthorizationRef)CFSTR("UseEntitlement");
+
+
static __inline__ CFTypeRef
isA_SCPreferences(CFTypeRef obj)
{
{
CFDataRef data = NULL;
CFMutableDictionaryRef info;
- char name[64] = "???";
CFNumberRef num;
Boolean ok;
SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
CFRelease(num);
// save process name
- (void) proc_name(getpid(), name, sizeof(name));
- str = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
+ str = CFStringCreateWithCString(NULL, getprogname(), kCFStringEncodingUTF8);
CFDictionarySetValue(info, CFSTR("PROC_NAME"), str);
CFRelease(str);
if (statBuf.st_size > 0) {
CFDictionaryRef dict;
- CFErrorRef error;
+ CFErrorRef error = NULL;
CFMutableDataRef xmlData;
/*
{
SCPreferencesRef prefs;
-#if TARGET_OS_IPHONE
- authorization = (AuthorizationRef)1;
-#endif // TARGET_OS_IPHONE
+#if !TARGET_OS_IPHONE
+ if (authorization == NULL) {
+ authorization = kSCPreferencesUseEntitlementAuthorization;
+ }
+#else // !TARGET_OS_IPHONE
+ authorization = kSCPreferencesUseEntitlementAuthorization;
+#endif // !TARGET_OS_IPHONE
prefs = SCPreferencesCreateWithOptions(allocator, name, prefsID, authorization, NULL);
return prefs;
}
if (authorization != NULL) {
+ CFMutableDictionaryRef authorizationDict;
+ CFBundleRef bundle;
+ CFStringRef bundleID = NULL;
+
+ authorizationDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
#if !TARGET_OS_IPHONE
- AuthorizationExternalForm extForm;
- OSStatus os_status;
+ if (authorization != kSCPreferencesUseEntitlementAuthorization) {
+ CFDataRef authorizationRefData;
+ AuthorizationExternalForm extForm;
+ OSStatus os_status;
+
+ os_status = AuthorizationMakeExternalForm(authorization, &extForm);
+ if (os_status != errAuthorizationSuccess) {
+ SCLog(TRUE, LOG_INFO, CFSTR("_SCHelperOpen AuthorizationMakeExternalForm() failed"));
+ _SCErrorSet(kSCStatusInvalidArgument);
+ CFRelease(authorizationDict);
+ return NULL;
+ }
- os_status = AuthorizationMakeExternalForm(authorization, &extForm);
- if (os_status != errAuthorizationSuccess) {
- SCLog(TRUE, LOG_INFO, CFSTR("_SCHelperOpen AuthorizationMakeExternalForm() failed"));
- _SCErrorSet(kSCStatusInvalidArgument);
- return NULL;
+ authorizationRefData = CFDataCreate(NULL, (const UInt8 *)extForm.bytes, sizeof(extForm.bytes));
+ CFDictionaryAddValue(authorizationDict,
+ kSCHelperAuthAuthorization,
+ authorizationRefData);
+ CFRelease(authorizationRefData);
}
-
- authorizationData = CFDataCreate(NULL, (const UInt8 *)extForm.bytes, sizeof(extForm.bytes));
-#else // !TARGET_OS_IPHONE
- CFBundleRef bundle;
- CFStringRef bundleID = NULL;
+#endif
/* get the application/executable/bundle name */
bundle = CFBundleGetMainBundle();
if (bundleID == NULL) {
bundleID = CFStringCreateWithFormat(NULL, NULL, CFSTR("Unknown(%d)"), getpid());
}
-
- _SCSerializeString(bundleID, &authorizationData, NULL, NULL);
+ CFDictionaryAddValue(authorizationDict,
+ kSCHelperAuthCallerInfo,
+ bundleID);
CFRelease(bundleID);
-#endif // !TARGET_OS_IPHONE
+
+ if (authorizationDict != NULL) {
+ _SCSerialize((CFPropertyListRef)authorizationDict,
+ &authorizationData,
+ NULL,
+ NULL);
+ CFRelease(authorizationDict);
+ }
}
prefsPrivate = __SCPreferencesCreate(allocator, name, prefsID, authorizationData, options);
/*
- * Copyright (c) 2000-2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2006, 2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#define MAXLINKS 8
-static CFMutableArrayRef
+static CF_RETURNS_RETAINED CFMutableArrayRef
normalizePath(CFStringRef path)
{
CFMutableArrayRef elements;
Boolean
__SCPreferencesAddSession (SCPreferencesRef prefs);
+CF_RETURNS_RETAINED
CFDataRef
__SCPSignatureFromStatbuf (const struct stat *statBuf);
CFStringRef prefsID,
Boolean useNewPrefs);
+CF_RETURNS_RETAINED
CFStringRef
_SCPNotificationKey (CFAllocatorRef allocator,
CFStringRef prefsID,
/*
- * Copyright (c) 2000-2005, 2007-2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2007-2009, 2011, 2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#define kSCPreferencesOptionRemoveWhenEmpty CFSTR("remove-when-empty") // CFBooleanRef
+#define kSCPreferencesWriteAuthorizationRight "system.services.systemconfiguration.network"
+
/*!
@enum SCPreferencesKeyType
@discussion Used with the SCDynamicStoreKeyCreatePreferences() function
__BEGIN_DECLS
+/*!
+ @const kSCPreferencesUseEntitlementAuthorization
+ @discussion An authorization value that can be passed to
+ the SCPreferencesCreateWithAuthorization API (or
+ the SCPreferencesCreateWithOptions SPI) to indicate
+ that the entitlements of the current process should
+ be used for authorization purposes.
+
+ This value can ONLY be used with the SCPreferences
+ APIs.
+ */
+extern const AuthorizationRef kSCPreferencesUseEntitlementAuthorization;
+
/*!
@function SCDynamicStoreKeyCreatePreferences
@discussion Creates a key that can be used by the SCDynamicStoreSetNotificationKeys()
/*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <asl.h>
#include <sys/syslog.h>
#include <mach/message.h>
+#include <sys/sysctl.h>
#include <CoreFoundation/CoreFoundation.h>
@header SCPrivate
*/
+
+/* atomic operations */
+#define _SC_ATOMIC_CMPXCHG(p, o, n) __sync_bool_compare_and_swap((p), (o), (n))
+#define _SC_ATOMIC_INC(p) __sync_fetch_and_add((p), 1) // return (n++);
+#define _SC_ATOMIC_DEC(p) __sync_sub_and_fetch((p), 1) // return (--n);
+#define _SC_ATOMIC_ZERO(p) __sync_fetch_and_and((p), 0) // old_n = n; n = 0; return(old_n);
+
+
/* framework variables */
extern int _sc_debug; /* non-zero if debugging enabled */
extern int _sc_verbose; /* non-zero if verbose logging enabled */
*/
#define kSCNetworkReachabilityOptionInterface CFSTR("interface")
-
/*!
- @constant kSCNetworkReachabilityOptionConnectionOnDemandByPass
+ @constant kSCNetworkReachabilityOptionConnectionOnDemandBypass
@discussion A CFBoolean that indicates if we should bypass the VPNOnDemand
checks for this target.
*/
-#define kSCNetworkReachabilityOptionConnectionOnDemandByPass CFSTR("ConnectionOnDemandByPass")
+#define kSCNetworkReachabilityOptionConnectionOnDemandBypass CFSTR("ConnectionOnDemandBypass")
+/*!
+ @constant kSCNetworkReachabilityOptionResolverBypass
+ @discussion A CFBoolean that indicates if we should bypass resolving any
+ node names. Instead, the status of the DNS server configuration
+ associated with the name will be returned. */
+#define kSCNetworkReachabilityOptionResolverBypass CFSTR("ResolverBypass")
+
+
+/*!
+ @constant kSCNetworkReachabilityOptionLongLivedQueryBypass
+ @discussion A CFBoolean that indicates if we should bypass usage of any
+ long-lived-queries (w/DNSServiceCreateConnection) when resolving
+ hostnames for this target.
+ */
+#define kSCNetworkReachabilityOptionLongLivedQueryBypass CFSTR("LongLivedQueryBypass")
+
+/*!
+ @constant kSCNetworkReachabilityOptionServerBypass
+ @discussion A CFBoolean that indicates if we should bypass usage of the
+ SCNetworkReachability "server" for this target.
+ */
+#define kSCNetworkReachabilityOptionServerBypass CFSTR("ServerBypass")
/*!
@group
@param dict The CFDictionary with CFPropertyList values.
@result The serialized CFDictionary with CFData values
*/
+CF_RETURNS_RETAINED
CFDictionaryRef _SCSerializeMultiple (CFDictionaryRef dict);
/*!
@param dict The CFDictionary with CFData values.
@result The serialized CFDictionary with CFPropertyList values
*/
+CF_RETURNS_RETAINED
CFDictionaryRef _SCUnserializeMultiple (CFDictionaryRef dict);
size_t bufLen);
+/*!
+ * @function _SC_string_to_sockaddr
+ * @discussion Parses a string into a "struct sockaddr"
+ * @param str The address string to parse
+ * @param af Allowed address families (AF_UNSPEC, AF_INET, AF_INET6)
+ * @param buf A user provided buffer of the specified length; NULL
+ * if a new buffer should be allocated (and deallocated by the
+ * caller).
+ * @param bufLen The size of the user provided buffer.
+ * @result A pointer to the parsed "struct sockaddr"; NULL if
+ * the string could not be parsed as an IP[v6] address.
+ */
+struct sockaddr *
+_SC_string_to_sockaddr (const char *str,
+ sa_family_t af,
+ void *buf,
+ size_t bufLen);
+
/*!
* @function _SC_trimDomain
* @discussion Trims leading and trailing "."s from a domain or host name
* @param domain The domain name to trim
* @result The trimmed domain name.
*/
+CF_RETURNS_RETAINED
CFStringRef _SC_trimDomain (CFStringRef domain);
Boolean *haveDNS,
struct sockaddr *sa);
+/*!
+ @function SCNetworkReachabilityGetInterfaceIndex
+ @discussion Returns the interface index associated with network interface that will
+ be used to interact with the target host.
+ @param target The SCNetworkReachability reference associated with the address or
+ name to be checked for reachability.
+ @result Returns the interface index associated with the target. Returning -1 means that
+ the target is not reachable.
+ */
+int
+SCNetworkReachabilityGetInterfaceIndex (SCNetworkReachabilityRef target);
+
+#pragma mark -
+#pragma mark Domain
+
+/*!
+ @function _SC_domainEndsWithDomain
+ @discussion Checks if one domain is a subset of another
+ @param compare_domain The domain to be compared.
+ @param match_domain The domain to be matched.
+ @return TRUE if the match_domain is contained in the compare_domain.
+ FLASE otherwise.
+ */
+Boolean
+_SC_domainEndsWithDomain (CFStringRef compare_domain,
+ CFStringRef match_domain);
+
#pragma mark -
#pragma mark NetBIOS
return (isInternal == 1);
}
+#define MODEL CFSTR("Model")
+
+static __inline__ CFStringRef
+_SC_hw_model()
+{
+ /*
+ * S_model
+ * Hardware model for this network configuration.
+ */
+ static CFStringRef model = NULL;
+
+ if (model == NULL) {
+ char hwModel[64];
+ int mib[] = { CTL_HW, HW_MODEL };
+ size_t n = sizeof(hwModel);
+ int ret;
+
+ // get HW model name
+ bzero(&hwModel, sizeof(hwModel));
+ ret = sysctl(mib, sizeof(mib) / sizeof(mib[0]), &hwModel, &n, NULL, 0);
+ if (ret != 0) {
+ SCLog(TRUE, LOG_ERR, CFSTR("sysctl() CTL_HW/HW_MODEL failed: %s"), strerror(errno));
+ return NULL;
+ }
+ hwModel[sizeof(hwModel) - 1] = '\0';
+
+ model = CFStringCreateWithCString(NULL, hwModel, kCFStringEncodingASCII);
+ }
+
+ return model;
+
+}
+
/*
* debugging
*/
}
-CFDictionaryRef
-SCDynamicStoreCopyProxies(SCDynamicStoreRef store)
-{
- CFArrayRef array;
- CFStringRef key;
- CFMutableDictionaryRef newProxies = NULL;
- CFNumberRef num;
- CFDictionaryRef proxies;
- Boolean tempSession = FALSE;
+static void
+normalize_scoped_proxy(const void *key, const void *value, void *context);
- /* copy proxy information from dynamic store */
-
- if (store == NULL) {
- store = SCDynamicStoreCreate(NULL,
- CFSTR("SCDynamicStoreCopyProxies"),
- NULL,
- NULL);
- if (store == NULL) {
- return NULL;
- }
- tempSession = TRUE;
- }
-
- key = SCDynamicStoreKeyCreateProxies(NULL);
- proxies = SCDynamicStoreCopyValue(store, key);
- CFRelease(key);
+static void
+normalize_supplemental_proxy(const void *value, void *context);
- validate :
- if (proxies != NULL) {
- if (isA_CFDictionary(proxies)) {
- newProxies = CFDictionaryCreateMutableCopy(NULL, 0, proxies);
- }
- CFRelease(proxies);
- }
-
- if (newProxies == NULL) {
- newProxies = CFDictionaryCreateMutable(NULL,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
+static CF_RETURNS_RETAINED CFDictionaryRef
+__SCNetworkProxiesCopyNormalized(CFDictionaryRef proxy)
+{
+ CFArrayRef array;
+ CFMutableDictionaryRef newProxy;
+ CFNumberRef num;
+ CFDictionaryRef scoped;
+ CFArrayRef supplemental;
+
+ if (!isA_CFDictionary(proxy)) {
+ proxy = CFDictionaryCreate(NULL,
+ NULL,
+ NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ return proxy;
}
- /* validate [and augment] proxy content */
+ newProxy = CFDictionaryCreateMutableCopy(NULL, 0, proxy);
- validate_proxy_content(newProxies,
+ validate_proxy_content(newProxy,
kSCPropNetProxiesFTPEnable,
kSCPropNetProxiesFTPProxy,
kSCPropNetProxiesFTPPort,
"ftp",
21);
- validate_proxy_content(newProxies,
+ validate_proxy_content(newProxy,
kSCPropNetProxiesGopherEnable,
kSCPropNetProxiesGopherProxy,
kSCPropNetProxiesGopherPort,
"gopher",
70);
- validate_proxy_content(newProxies,
+ validate_proxy_content(newProxy,
kSCPropNetProxiesHTTPEnable,
kSCPropNetProxiesHTTPProxy,
kSCPropNetProxiesHTTPPort,
"http",
80);
- validate_proxy_content(newProxies,
+ validate_proxy_content(newProxy,
kSCPropNetProxiesHTTPSEnable,
kSCPropNetProxiesHTTPSProxy,
kSCPropNetProxiesHTTPSPort,
"https",
443);
- validate_proxy_content(newProxies,
+ validate_proxy_content(newProxy,
kSCPropNetProxiesRTSPEnable,
kSCPropNetProxiesRTSPProxy,
kSCPropNetProxiesRTSPPort,
"rtsp",
554);
- validate_proxy_content(newProxies,
+ validate_proxy_content(newProxy,
kSCPropNetProxiesSOCKSEnable,
kSCPropNetProxiesSOCKSProxy,
kSCPropNetProxiesSOCKSPort,
"socks",
1080);
- if (CFDictionaryContainsKey(newProxies, kSCPropNetProxiesProxyAutoConfigURLString)) {
- validate_proxy_content(newProxies,
+ if (CFDictionaryContainsKey(newProxy, kSCPropNetProxiesProxyAutoConfigURLString)) {
+ validate_proxy_content(newProxy,
kSCPropNetProxiesProxyAutoConfigEnable,
kSCPropNetProxiesProxyAutoConfigURLString,
NULL,
0);
// and we can't have both URLString and JavaScript keys
- CFDictionaryRemoveValue(newProxies, kSCPropNetProxiesProxyAutoConfigJavaScript);
+ CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesProxyAutoConfigJavaScript);
} else {
- validate_proxy_content(newProxies,
+ validate_proxy_content(newProxy,
kSCPropNetProxiesProxyAutoConfigEnable,
kSCPropNetProxiesProxyAutoConfigJavaScript,
NULL,
NULL,
0);
}
- validate_proxy_content(newProxies,
+ validate_proxy_content(newProxy,
kSCPropNetProxiesProxyAutoDiscoveryEnable,
NULL,
NULL,
0);
// validate FTP passive setting
- num = CFDictionaryGetValue(newProxies, kSCPropNetProxiesFTPPassive);
+ num = CFDictionaryGetValue(newProxy, kSCPropNetProxiesFTPPassive);
if (num != NULL) {
int enabled = 0;
// if we don't like the enabled key/value
enabled = 1;
num = CFNumberCreate(NULL, kCFNumberIntType, &enabled);
- CFDictionarySetValue(newProxies,
+ CFDictionarySetValue(newProxy,
kSCPropNetProxiesFTPPassive,
num);
CFRelease(num);
}
// validate proxy exception list
- array = CFDictionaryGetValue(newProxies, kSCPropNetProxiesExceptionsList);
+ array = CFDictionaryGetValue(newProxy, kSCPropNetProxiesExceptionsList);
if (array != NULL) {
CFIndex i;
CFIndex n;
}
if (n == 0) {
- CFDictionaryRemoveValue(newProxies, kSCPropNetProxiesExceptionsList);
+ CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesExceptionsList);
}
}
// validate exclude simple hostnames setting
- num = CFDictionaryGetValue(newProxies, kSCPropNetProxiesExcludeSimpleHostnames);
+ num = CFDictionaryGetValue(newProxy, kSCPropNetProxiesExcludeSimpleHostnames);
if (num != NULL) {
int enabled;
// if we don't like the enabled key/value
enabled = 0;
num = CFNumberCreate(NULL, kCFNumberIntType, &enabled);
- CFDictionarySetValue(newProxies,
+ CFDictionarySetValue(newProxy,
kSCPropNetProxiesExcludeSimpleHostnames,
num);
CFRelease(num);
}
}
+ // cleanup scoped proxies
+ scoped = CFDictionaryGetValue(newProxy, kSCPropNetProxiesScoped);
+ if (isA_CFDictionary(scoped)) {
+ CFMutableDictionaryRef newScoped;
+
+ newScoped = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionaryApplyFunction(scoped,
+ normalize_scoped_proxy,
+ newScoped);
+ CFDictionarySetValue(newProxy, kSCPropNetProxiesScoped, newScoped);
+ CFRelease(newScoped);
+ }
+
+ // cleanup split/supplemental proxies
+ supplemental = CFDictionaryGetValue(newProxy, kSCPropNetProxiesSupplemental);
+ if (isA_CFArray(supplemental)) {
+ CFMutableArrayRef newSupplemental;
+
+ newSupplemental = CFArrayCreateMutable(NULL,
+ 0,
+ &kCFTypeArrayCallBacks);
+ CFArrayApplyFunction(supplemental,
+ CFRangeMake(0, CFArrayGetCount(supplemental)),
+ normalize_supplemental_proxy,
+ newSupplemental);
+ CFDictionarySetValue(newProxy, kSCPropNetProxiesSupplemental, newSupplemental);
+ CFRelease(newSupplemental);
+ }
+
+ proxy = CFDictionaryCreateCopy(NULL,newProxy);
+ CFRelease(newProxy);
+
+ return proxy;
+}
+
+
+static void
+normalize_scoped_proxy(const void *key, const void *value, void *context)
+{
+ CFStringRef interface = (CFStringRef)key;
+ CFDictionaryRef proxy = (CFDictionaryRef)value;
+ CFMutableDictionaryRef newScoped = (CFMutableDictionaryRef)context;
+
+ proxy = __SCNetworkProxiesCopyNormalized(proxy);
+ CFDictionarySetValue(newScoped, interface, proxy);
+ CFRelease(proxy);
+
+ return;
+}
+
+
+static void
+normalize_supplemental_proxy(const void *value, void *context)
+{
+ CFDictionaryRef proxy = (CFDictionaryRef)value;
+ CFMutableArrayRef newSupplemental = (CFMutableArrayRef)context;
+
+ proxy = __SCNetworkProxiesCopyNormalized(proxy);
+ CFArrayAppendValue(newSupplemental, proxy);
+ CFRelease(proxy);
+
+ return;
+}
+
+
+CFDictionaryRef
+SCDynamicStoreCopyProxies(SCDynamicStoreRef store)
+{
+ CFStringRef key;
+ CFDictionaryRef proxies;
+
+
+ /* copy proxy information from dynamic store */
+
+ key = SCDynamicStoreKeyCreateProxies(NULL);
+ proxies = SCDynamicStoreCopyValue(store, key);
+ CFRelease(key);
+
+
+ if (proxies != NULL) {
+ CFDictionaryRef base = proxies;
+
+ proxies = __SCNetworkProxiesCopyNormalized(base);
+ CFRelease(base);
+ } else {
+ proxies = CFDictionaryCreate(NULL,
+ NULL,
+ NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
- proxies = CFDictionaryCreateCopy(NULL, newProxies);
- CFRelease(newProxies);
- if (tempSession) CFRelease(store);
return proxies;
}
if (server != NULL) {
CFIndex i;
CFMutableArrayRef matching = NULL;
- CFIndex n;
+ CFIndex n = 0;
CFIndex server_len;
CFArrayRef supplemental;
server_len = CFStringGetLength(server);
supplemental = CFDictionaryGetValue(globalConfiguration, kSCPropNetProxiesSupplemental);
- if (supplemental == NULL) {
- // if no supplemental configurations
- goto done;
- }
+ if (supplemental != NULL) {
+ if (!isA_CFArray(supplemental)) {
+ // if corrupt proxy configuration
+ sc_status = kSCStatusFailed;
+ goto done;
+ }
- if (!isA_CFArray(supplemental)) {
- // if corrupt proxy configuration
- sc_status = kSCStatusFailed;
- goto done;
+ n = CFArrayGetCount(supplemental);
}
- n = CFArrayGetCount(supplemental);
for (i = 0; i < n; i++) {
CFStringRef domain;
CFIndex domain_len;
const CFStringRef kSCEntNetEAPOL = CFSTR("EAPOL");
+const CFStringRef kSCEntNetLinkQuality = CFSTR("LinkQuality");
const CFStringRef kSCEntNetLoopback = CFSTR("Loopback");
const CFStringRef kSCEntNetOnDemand = CFSTR("OnDemand");
const CFStringRef kSCEntNetService = CFSTR("__SERVICE__");
const CFStringRef kSCPropNetIPv4RouteDestinationAddress = CFSTR("DestinationAddress");
const CFStringRef kSCPropNetIPv4RouteSubnetMask = CFSTR("SubnetMask");
const CFStringRef kSCPropNetIPv4RouteGatewayAddress = CFSTR("GatewayAddress");
+const CFStringRef kSCPropNetIPv4ARPResolvedHardwareAddress = CFSTR("ARPResolvedHardwareAddress");
+const CFStringRef kSCPropNetIPv4ARPResolvedIPAddress = CFSTR("ARPResolvedIPAddress");
const CFStringRef kSCPropNetIPv6Addresses = CFSTR("Addresses");
const CFStringRef kSCPropNetIPv6ConfigMethod = CFSTR("ConfigMethod");
const CFStringRef kSCPropNetIPv6DestAddresses = CFSTR("DestAddresses");
const CFStringRef kSCPropNet6to4Relay = CFSTR("Relay");
const CFStringRef kSCPropNetLinkActive = CFSTR("Active");
const CFStringRef kSCPropNetLinkDetaching = CFSTR("Detaching");
+const CFStringRef kSCPropNetLinkQuality = CFSTR("LinkQuality");
const CFStringRef kSCPropNetModemAccessPointName = CFSTR("AccessPointName");
const CFStringRef kSCPropNetModemConnectionPersonality = CFSTR("ConnectionPersonality");
const CFStringRef kSCPropNetModemConnectionScript = CFSTR("ConnectionScript");
*
* kSCEntNetCommCenter "com.apple.CommCenter" CFDictionary
* kSCEntNetEAPOL "EAPOL" CFDictionary
+ * kSCEntNetLinkQuality "LinkQuality" CFDictionary
* kSCEntNetLoopback "Loopback" CFDictionary
* kSCEntNetOnDemand "OnDemand" CFDictionary
* kSCEntNetService "__SERVICE__" CFDictionary
* kSCPropNetIPv4RouteSubnetMask "SubnetMask" CFString
* kSCPropNetIPv4RouteGatewayAddress "GatewayAddress" CFString
*
+ * kSCPropNetIPv4ARPResolvedHardwareAddress "ARPResolvedHardwareAddress" CFString
+ * kSCPropNetIPv4ARPResolvedIPAddress "ARPResolvedIPAddress" CFString
+ *
* kSCEntNetIPv6 Entity Keys
*
* kSCPropNetIPv6ExcludedRoutes "ExcludedRoutes" CFArray[CFDictionary]
* kSCPropNetIPv6RoutePrefixLength "PrefixLength" CFNumber
* kSCPropNetIPv6RouteGatewayAddress "GatewayAddress" CFString
*
+ * kSCEntNetLinkQuality Entity Keys
+ *
+ * kSCPropNetLinkQuality "LinkQuality" CFNumber
+ *
* kSCEntNetPPP Entity Keys
*
* --- OnDemand: ---
*/
extern const CFStringRef kSCEntNetEAPOL;
+/*!
+ @const kSCEntNetLinkQuality
+ @availability Introduced in Mac OS X 10.7.
+ */
+extern const CFStringRef kSCEntNetLinkQuality;
+
/*!
@const kSCEntNetLoopback
@availability Introduced in Mac OS X 10.7.
*/
extern const CFStringRef kSCPropNetIPv4RouteGatewayAddress;
+/*!
+ @const kSCPropNetIPv4ARPResolvedHardwareAddress
+ @availability Introduced in Mac OS X 10.7.
+ */
+extern const CFStringRef kSCPropNetIPv4ARPResolvedHardwareAddress;
+
+/*!
+ @const kSCPropNetIPv4ARPResolvedIPAddress
+ @availability Introduced in Mac OS X 10.7.
+ */
+extern const CFStringRef kSCPropNetIPv4ARPResolvedIPAddress;
+
/*!
@group kSCEntNetIPv6 Entity Keys
*/
*/
extern const CFStringRef kSCPropNetIPv6RouteGatewayAddress;
+/*!
+ @group kSCEntNetLinkQuality Entity Keys
+ */
+
+/*!
+ @const kSCPropNetLinkQuality
+ @availability Introduced in Mac OS X 10.7.
+ */
+extern const CFStringRef kSCPropNetLinkQuality;
+
/*!
@group kSCEntNetPPP Entity Keys
*/
,"EAPOL" \
,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetLinkQuality, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/))
+ #define kSCEntNetLinkQuality \
+ SC_SCHEMA_KV(kSCEntNetLinkQuality \
+ ,"LinkQuality" \
+ ,CFDictionary )
+
SC_SCHEMA_DECLARATION(kSCEntNetLoopback, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0/*SPI*/))
#define kSCEntNetLoopback \
SC_SCHEMA_KV(kSCEntNetLoopback \
,"GatewayAddress" \
,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv4ARPResolvedHardwareAddress, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/))
+ #define kSCPropNetIPv4ARPResolvedHardwareAddress \
+ SC_SCHEMA_KV(kSCPropNetIPv4ARPResolvedHardwareAddress \
+ ,"ARPResolvedHardwareAddress" \
+ ,CFString )
+
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv4ARPResolvedIPAddress, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/))
+ #define kSCPropNetIPv4ARPResolvedIPAddress \
+ SC_SCHEMA_KV(kSCPropNetIPv4ARPResolvedIPAddress \
+ ,"ARPResolvedIPAddress" \
+ ,CFString )
+
SC_SCHEMA_DECLARATION(kSCPropNetIPv6ExcludedRoutes, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0/*SPI*/))
#define kSCPropNetIPv6ExcludedRoutes \
SC_SCHEMA_KV(kSCPropNetIPv6ExcludedRoutes \
,"GatewayAddress" \
,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetLinkQuality, __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0/*SPI*/))
+ #define kSCPropNetLinkQuality \
+ SC_SCHEMA_KV(kSCPropNetLinkQuality \
+ ,"LinkQuality" \
+ ,CFNumber )
+
SC_SCHEMA_DECLARATION(kSCPropNetPPPOnDemandDomains, __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0/*SPI*/))
#define kSCPropNetPPPOnDemandDomains \
SC_SCHEMA_KV(kSCPropNetPPPOnDemandDomains \
prefs = SCPreferencesCreate(NULL, CFSTR("SCVLANInterfaceCopyAvailablePhysicalInterfaces"), NULL);
if (prefs != NULL) {
+#if !TARGET_OS_IPHONE
bond_interfaces = SCBondInterfaceCopyAll(prefs);
if (bond_interfaces != NULL) {
excluded = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
__SCBondInterfaceListCollectMembers(bond_interfaces, excluded);
}
+#endif // !TARGET_OS_IPHONE
bridge_interfaces = SCBridgeInterfaceCopyAll(prefs);
if (bridge_interfaces != NULL) {
/*
- * Copyright (c) 2000, 2001, 2003-2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2005, 2011, 2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
out status : int;
ServerAuditToken audit_token : audit_token_t);
-routine configclose ( server : mach_port_t;
- out status : int);
-
-routine configlock ( server : mach_port_t;
- out status : int);
-
-routine configunlock ( server : mach_port_t;
- out status : int);
+ skip; /* was configclose */
+ skip; /* was configlock */
+ skip; /* was configunlock */
skip; /* reserved for future use */
skip; /* reserved for future use */
xmlData : xmlData;
isRegex : int;
out list : xmlDataOut, dealloc;
- out status : int);
+ out status : int;
+ ServerAuditToken audit_token : audit_token_t);
routine configadd ( server : mach_port_t;
key : xmlData;
data : xmlData;
out newInstance : int;
- out status : int);
+ out status : int;
+ ServerAuditToken audit_token : audit_token_t);
routine configget ( server : mach_port_t;
key : xmlData;
out data : xmlDataOut, dealloc;
out newInstance : int;
- out status : int);
+ out status : int;
+ ServerAuditToken audit_token : audit_token_t);
routine configset ( server : mach_port_t;
key : xmlData;
data : xmlData;
instance : int;
out newInstance : int;
- out status : int);
+ out status : int;
+ ServerAuditToken audit_token : audit_token_t);
routine configremove ( server : mach_port_t;
key : xmlData;
- out status : int);
+ out status : int;
+ ServerAuditToken audit_token : audit_token_t);
-routine configtouch ( server : mach_port_t;
- key : xmlData;
- out status : int);
+ skip; /* was configtouch */
routine configadd_s ( server : mach_port_t;
key : xmlData;
routine confignotify ( server : mach_port_t;
key : xmlData;
- out status : int);
+ out status : int;
+ ServerAuditToken audit_token : audit_token_t);
routine configget_m ( server : mach_port_t;
keys : xmlData;
patterns : xmlData;
out data : xmlDataOut, dealloc;
- out status : int);
+ out status : int;
+ ServerAuditToken audit_token : audit_token_t);
routine configset_m ( server : mach_port_t;
data : xmlData;
remove : xmlData;
notify : xmlData;
- out status : int);
+ out status : int;
+ ServerAuditToken audit_token : audit_token_t);
/*
* Notification API's
*/
routine snapshot ( server : mach_port_t;
- out status : int);
+ out status : int;
+ ServerAuditToken audit_token : audit_token_t);
__loadIOKit(void) {
static void *image = NULL;
if (NULL == image) {
- const char *framework = "/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit";
+ const char *framework = "/System/Library/Frameworks/IOKit.framework/IOKit";
struct stat statbuf;
const char *suffix = getenv("DYLD_IMAGE_SUFFIX");
char path[MAXPATHLEN];
__loadSecurity(void) {
static void *image = NULL;
if (NULL == image) {
-#if TARGET_OS_IPHONE
const char *framework = "/System/Library/Frameworks/Security.framework/Security";
-#else
- const char *framework = "/System/Library/Frameworks/Security.framework/Versions/A/Security";
-#endif
struct stat statbuf;
const char *suffix = getenv("DYLD_IMAGE_SUFFIX");
char path[MAXPATHLEN];
return (void *)image;
}
-#if !TARGET_OS_IPHONE
-
#define SECURITY_FRAMEWORK_EXTERN(t, s) \
__private_extern__ t \
_ ## s() \
return (dysym != NULL) ? *dysym : NULL; \
}
+#if !TARGET_OS_IPHONE
SECURITY_FRAMEWORK_EXTERN(CFTypeRef, kSecAttrService)
SECURITY_FRAMEWORK_EXTERN(CFTypeRef, kSecClass)
SECURITY_FRAMEWORK_EXTERN(CFTypeRef, kSecClassGenericPassword)
return dyfunc ? dyfunc(path, app) : -1;
}
-#endif // !TARGET_OS_IPHONE
+#else // TARGET_OS_IPHONE
+
+SECURITY_FRAMEWORK_EXTERN(CFStringRef, kSecPropertyKeyValue)
+SECURITY_FRAMEWORK_EXTERN(CFStringRef, kSecPropertyKeyLabel)
+
+__private_extern__ CFArrayRef
+_SecCertificateCopyProperties(SecCertificateRef certRef)
+{
+ #undef SecCertificateCopyProperties
+ static typeof (SecCertificateCopyProperties) *dyfunc = NULL;
+ if (!dyfunc) {
+ void *image = __loadSecurity();
+ if (image) dyfunc = dlsym(image, "SecCertificateCopyProperties");
+ }
+ return dyfunc ? dyfunc(certRef) : NULL;
+}
+
+#endif // TARGET_OS_IPHONE
__private_extern__ SecCertificateRef
_SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data)
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <Security/Security.h>
+#include <Security/SecCertificatePriv.h>
#include <Security/SecItem.h> // only needed for Mac OS X 10.6[.x]
__BEGIN_DECLS
CFStringRef key,
CFAllocatorRef allocator,
IOOptionBits options
- );
+ ) CF_RETURNS_RETAINED;
#define IORegistryEntrySearchCFProperty _IORegistryEntrySearchCFProperty
kern_return_t
OSStatus
_SecKeychainCopyDomainDefault (
- SecPreferencesDomain domain,
- SecKeychainRef *keychain
+ SecPreferencesDomain domain,
+ SecKeychainRef *keychain
);
#define SecKeychainCopyDomainDefault _SecKeychainCopyDomainDefault
OSStatus
_SecKeychainGetPreferenceDomain (
- SecPreferencesDomain *domain
+ SecPreferencesDomain *domain
);
#define SecKeychainGetPreferenceDomain _SecKeychainGetPreferenceDomain
OSStatus
_SecKeychainOpen (
- const char *pathName,
- SecKeychainRef *keychain
+ const char *pathName,
+ SecKeychainRef *keychain
);
#define SecKeychainOpen _SecKeychainOpen
OSStatus
_SecKeychainSetDomainDefault (
- SecPreferencesDomain domain,
- SecKeychainRef keychain
+ SecPreferencesDomain domain,
+ SecKeychainRef keychain
);
#define SecKeychainSetDomainDefault _SecKeychainSetDomainDefault
OSStatus
_SecKeychainSetPreferenceDomain (
- SecPreferencesDomain domain
+ SecPreferencesDomain domain
);
#define SecKeychainSetPreferenceDomain _SecKeychainSetPreferenceDomain
);
#define SecTrustedApplicationCreateFromPath _SecTrustedApplicationCreateFromPath
-#endif // !TARGET_OS_IPHONE
+#else // TARGET_OS_IPHONE
+
+CFStringRef _kSecPropertyKeyValue();
+#define kSecPropertyKeyValue _kSecPropertyKeyValue()
+
+CFStringRef _kSecPropertyKeyLabel();
+#define kSecPropertyKeyLabel _kSecPropertyKeyLabel()
+
+CFArrayRef
+_SecCertificateCopyProperties (
+ SecCertificateRef certRef
+ );
+#define SecCertificateCopyProperties _SecCertificateCopyProperties
+
+#endif // TARGET_OS_IPHONE
SecCertificateRef
-_SecCertificateCreateWithData(
- CFAllocatorRef allocator,
- CFDataRef data
- );
+_SecCertificateCreateWithData (
+ CFAllocatorRef allocator,
+ CFDataRef data
+ );
#define SecCertificateCreateWithData _SecCertificateCreateWithData
__END_DECLS
#define CFNUMBER_BOOL "CFNumber (0 or 1)"
#define CFSTRING "CFString"
+#define ARP "ARP"
#define ACCESSPOINTNAME "AccessPointName"
#define ACSP "ACSP" // Apple Client Server Protocol
#define ACTIVE "Active"
#define LCP "LCP"
#define LINK "Link"
#define LINKLOCAL "LinkLocal"
+#define LINKQUALITY "LinkQuality"
#define LOCALCERTIFICATE "LocalCertificate"
#define LOCALHOSTNAME "LocalHostName"
#define LOCALIDENTIFIER "LocalIdentifier"
#define REMINDER "Reminder"
#define REMINDERTIME "ReminderTime"
#define REMOTEADDRESS "RemoteAddress"
+#define RESOLVED "Resolved"
#define RETRYCONNECTTIME "RetryConnectTime"
#define ROOTSEPARATOR "RootSeparator"
#define ROUTE "Route"
{ GROUP_PRIVATE, NETENT, "Network Entity Keys", NULL, NULL },
{ SC_10_5_PRIVATE, NETENT, EAPOL, NULL, CFDICTIONARY },
+ { SC_10_7_IPHONE_5_0_PRIVATE, NETENT, LINKQUALITY, NULL, CFDICTIONARY},
{ SC_10_7_IPHONE_4_0_PRIVATE, NETENT, LOOPBACK, NULL, CFDICTIONARY },
{ SC_10_6_IPHONE_3_0_PRIVATE, NETENT, ONDEMAND, NULL, CFDICTIONARY },
{ SC_10_6_IPHONE_2_0_PRIVATE, NETENT, SERVICE, "__SERVICE__", CFDICTIONARY },
{ SC_10_7_IPHONE_4_0_PRIVATE, NETPROP IPV4 ROUTE, SUBNETMASK, NULL, CFSTRING },
{ SC_10_7_IPHONE_4_0_PRIVATE, NETPROP IPV4 ROUTE, GATEWAY ADDRESS, NULL, CFSTRING },
{ COMMENT_PRIVATE, "", NULL, NULL, NULL },
+ { SC_10_7_IPHONE_5_0_PRIVATE, NETPROP IPV4, ARP RESOLVED HARDWARE ADDRESS, NULL, CFSTRING },
+ { SC_10_7_IPHONE_5_0_PRIVATE, NETPROP IPV4, ARP RESOLVED IP ADDRESS, NULL, CFSTRING },
+ { COMMENT_PRIVATE, "", NULL, NULL, NULL },
{ GROUP, NETPROP IPV6, KEY_PREFIX NETENT IPV6 " Entity Keys", NULL, NULL },
{ SC_10_2, NETPROP LINK, DETACHING, NULL, CFBOOLEAN },
{ COMMENT, "", NULL, NULL, NULL },
+ { GROUP_PRIVATE, NETPROP LINK, KEY_PREFIX NETENT LINKQUALITY " Entity Keys", NULL, NULL },
+
+ { SC_10_7_IPHONE_5_0_PRIVATE, NETPROP, LINKQUALITY, NULL, CFNUMBER},
+ { COMMENT_PRIVATE, "", NULL, NULL, NULL },
+
{ GROUP, NETPROP MODEM, KEY_PREFIX NETENT MODEM " (Hardware) Entity Keys", NULL, NULL },
{ SC_10_5, NETPROP MODEM, ACCESSPOINTNAME, NULL, CFSTRING },
/*
- * Copyright (c) 2005-2007, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2007, 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <mach/mach_error.h>
#include <servers/bootstrap.h>
#include <bootstrap_priv.h>
+#include <pthread.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SCPrivate.h>
}
+static CFDataRef
+_SCHelperExecCopyBacktrace()
+{
+ static Boolean loggingEnabled = FALSE;
+ static dispatch_once_t once;
+ CFDataRef traceData = NULL;
+
+ dispatch_once(&once, ^{
+ if(getenv("ENABLE_SCHELPER_BACKTRACES")) {
+ loggingEnabled = TRUE;
+ }
+ });
+
+ if (loggingEnabled) {
+ CFStringRef backtrace;
+
+ backtrace = _SC_copyBacktrace();
+ if (backtrace != NULL) {
+ _SCSerializeString(backtrace, &traceData, NULL, NULL);
+ CFRelease(backtrace);
+ }
+ }
+
+ return traceData;
+}
+
+
Boolean
_SCHelperExec(mach_port_t port, uint32_t msgID, CFDataRef data, uint32_t *status, CFDataRef *reply)
{
xmlDataOut_t replyRef = NULL; /* raw bytes */
mach_msg_type_number_t replyLen = 0;
uint32_t replyStatus = 0;
+ CFDataRef traceData;
+
+ traceData = _SCHelperExecCopyBacktrace();
kr = helperexec(port,
msgID,
(data != NULL) ? (void *)CFDataGetBytePtr(data) : NULL,
- (data != NULL) ? CFDataGetLength(data) : 0,
+ (data != NULL) ? CFDataGetLength(data) : 0,
+ (traceData != NULL) ? (void *)CFDataGetBytePtr(traceData) : NULL,
+ (traceData != NULL) ? CFDataGetLength(traceData) : 0,
&replyStatus,
&replyRef,
&replyLen);
+
+ if (traceData != NULL) {
+ CFRelease(traceData);
+ }
+
if (kr != KERN_SUCCESS) {
if (replyRef != NULL) {
(void) vm_deallocate(mach_task_self(), (vm_address_t)replyRef, replyLen);
/*
- * Copyright (c) 2005-2007, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2007, 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#define kSCKeychainOptionsPassword CFSTR("Password") // CFData
#define kSCKeychainOptionsUniqueID CFSTR("UniqueID") // CFString
+#define kSCHelperAuthAuthorization CFSTR("Authorization") // CFData[AuthorizationExternalForm]
+#define kSCHelperAuthCallerInfo CFSTR("CallerInfo") // CFString
+
enum {
// authorization
SCHELPER_MSG_AUTH = 1,
/*
- * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFRuntime.h>
+#include <Security/Security.h>
+#include <Security/SecTask.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
#include <SystemConfiguration/SCValidation.h>
#pragma mark SCHelper session managment
-#if TARGET_OS_IPHONE
-
//
// entitlement used to control write access to a given "prefsID"
//
//
#define kSCVPNFilterEntitlementName CFSTR("com.apple.networking.vpn.configuration")
-#endif // TARGET_OS_IPHONE
-
-
typedef enum { NO = 0, YES, UNKNOWN } lazyBoolean;
typedef const struct __SCHelperSession * SCHelperSessionRef;
// authorization
AuthorizationRef authorization;
+ Boolean use_entitlement;
// session mach port
mach_port_t port;
// preferences
SCPreferencesRef prefs;
+ /* backtraces */
+ CFMutableSetRef backtraces;
+
} SCHelperSessionPrivate, *SCHelperSessionPrivateRef;
static void __SCHelperSessionDeallocate (CFTypeRef cf);
+static void __SCHelperSessionLogBacktrace (const void *value, void *context);
+
+
static CFTypeID __kSCHelperSessionTypeID = _kCFRuntimeNotATypeID;
static Boolean debug = FALSE;
static pthread_once_t initialized = PTHREAD_ONCE_INIT;
#pragma mark -
+#pragma mark Helper session management
+
+
+#if !TARGET_OS_IPHONE
+static Boolean
+ __SCHelperSessionUseEntitlement(SCHelperSessionRef session)
+{
+ SCHelperSessionPrivateRef sessionPrivate = (SCHelperSessionPrivateRef)session;
+
+ return sessionPrivate->use_entitlement;
+}
+#endif //!TARGET_OS_IPHONE
static AuthorizationRef
pthread_mutex_lock(&sessionPrivate->lock);
-#if !TARGET_OS_IPHONE
if (sessionPrivate->authorization != NULL) {
- AuthorizationFree(sessionPrivate->authorization, kAuthorizationFlagDefaults);
-// AuthorizationFree(sessionPrivate->authorization, kAuthorizationFlagDestroyRights);
- sessionPrivate->authorization = NULL;
+#if !TARGET_OS_IPHONE
+ if (!__SCHelperSessionUseEntitlement(session)) {
+ AuthorizationFree(sessionPrivate->authorization, kAuthorizationFlagDefaults);
+// AuthorizationFree(sessionPrivate->authorization, kAuthorizationFlagDestroyRights);
+ sessionPrivate->authorization = NULL;
+ } else {
+#endif //!TARGET_OS_IPHONE
+ CFRelease(sessionPrivate->authorization);
+ sessionPrivate->authorization = NULL;
+#if !TARGET_OS_IPHONE
+ }
+#endif //!TARGET_OS_IPHONE
+ sessionPrivate->use_entitlement = FALSE;
}
+#if !TARGET_OS_IPHONE
if (isA_CFData(authorizationData)) {
AuthorizationExternalForm extForm;
ok = FALSE;
}
}
- }
-#else // !TARGET_OS_IPHONE
- if (sessionPrivate->authorization != NULL) {
- CFRelease(sessionPrivate->authorization);
- sessionPrivate->authorization = NULL;
- }
+ } else
+#endif //!TARGET_OS_IPHONE
if (isA_CFString(authorizationData)) {
sessionPrivate->authorization = (void *)CFRetain(authorizationData);
+ sessionPrivate->use_entitlement = TRUE;
}
-#endif // !TARGET_OS_IPHONE
pthread_mutex_unlock(&sessionPrivate->lock);
{
SCHelperSessionRef session = (SCHelperSessionRef)value;
SCHelperSessionPrivateRef sessionPrivate = (SCHelperSessionPrivateRef)session;
+ FILE **logFile = (FILE **)context;
pthread_mutex_lock(&sessionPrivate->lock);
prefsPrivate->name,
prefsPrivate->newPath ? prefsPrivate->newPath : prefsPrivate->path,
prefsPrivate->locked ? ", locked" : "");
+
+ if ((sessionPrivate->backtraces != NULL) &&
+ (CFSetGetCount(sessionPrivate->backtraces) > 0)) {
+ // log/report all collected backtraces
+ CFSetApplyFunction(sessionPrivate->backtraces,
+ __SCHelperSessionLogBacktrace,
+ (void *)logFile);
+
+ // to ensure that we don't log the same backtraces multiple
+ // times we remove any reported traces
+ CFRelease(sessionPrivate->backtraces);
+ sessionPrivate->backtraces = NULL;
+ }
}
pthread_mutex_unlock(&sessionPrivate->lock);
__SCHelperSessionSetPreferences (session, NULL);
__SCHelperSessionSetVPNFilter (session, NULL);
pthread_mutex_destroy(&sessionPrivate->lock);
+ if (sessionPrivate->backtraces != NULL) {
+ CFRelease(sessionPrivate->backtraces);
+ }
// we no longer need/want to track this session
CFSetRemoveValue(sessions, sessionPrivate);
return NULL;
}
sessionPrivate->authorization = NULL;
+ sessionPrivate->use_entitlement = FALSE;
sessionPrivate->port = MACH_PORT_NULL;
sessionPrivate->mp = NULL;
sessionPrivate->callerWriteAccess = UNKNOWN;
sessionPrivate->vpnFilter = NULL;
sessionPrivate->prefs = NULL;
+ sessionPrivate->backtraces = NULL;
// keep track this session
pthread_mutex_lock(&sessions_lock);
}
+#pragma mark -
+#pragma mark Session backtrace logging
+
+
+static void
+__SCHelperSessionAddBacktrace(SCHelperSessionRef session, CFStringRef backtrace, const char * command)
+{
+ CFStringRef logEntry;
+ SCPreferencesRef prefs;
+ SCPreferencesPrivateRef prefsPrivate;
+ SCHelperSessionPrivateRef sessionPrivate = (SCHelperSessionPrivateRef)session;
+
+ prefs = __SCHelperSessionGetPreferences((SCHelperSessionRef)sessionPrivate);
+ if (prefs == NULL) {
+ // if no prefs
+ return;
+ }
+ prefsPrivate = (SCPreferencesPrivateRef)prefs;
+
+ logEntry = CFStringCreateWithFormat(NULL, NULL,
+ CFSTR("%@ [%s]: %s\n\n%@"),
+ prefsPrivate->name,
+ prefsPrivate->newPath ? prefsPrivate->newPath : prefsPrivate->path,
+ command,
+ backtrace);
+
+ pthread_mutex_lock(&sessionPrivate->lock);
+
+ if (sessionPrivate->backtraces == NULL) {
+ sessionPrivate->backtraces = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+ }
+ CFSetSetValue(sessionPrivate->backtraces, logEntry);
+
+ pthread_mutex_unlock(&sessionPrivate->lock);
+
+ CFRelease(logEntry);
+ return;
+}
+
+
+static void
+__SCHelperSessionLogBacktrace(const void *value, void *context)
+{
+ CFSetRef backtrace = (CFSetRef)value;
+ FILE **logFile = (FILE **)context;
+
+ if (*logFile == NULL) {
+ char path[PATH_MAX];
+ struct tm tm_now;
+ struct timeval tv_now;
+
+ (void)gettimeofday(&tv_now, NULL);
+ (void)localtime_r(&tv_now.tv_sec, &tm_now);
+
+ snprintf(path,
+ sizeof(path),
+ "/Library/Logs/CrashReporter/SCHelper-%4d-%02d-%02d-%02d%02d%02d.log",
+ tm_now.tm_year + 1900,
+ tm_now.tm_mon + 1,
+ tm_now.tm_mday,
+ tm_now.tm_hour,
+ tm_now.tm_min,
+ tm_now.tm_sec);
+
+ *logFile = fopen(path, "a");
+ if (*logFile == NULL) {
+ // if log file could not be created
+ return;
+ }
+
+ SCLog(TRUE, LOG_INFO, CFSTR("created backtrace log: %s"), path);
+ }
+
+ SCPrint(TRUE, *logFile, CFSTR("%@\n"), backtrace);
+ return;
+}
+
+
#pragma mark -
#pragma mark Helpers
/*
* AUTHORIZE
- * (in) data = AuthorizationExternalForm
+ * (in) data = authorizationDict (in 2 flavors)
+ * kSCHelperAuthAuthorization - use provided AuthorizationExternalForm
+ * kSCHelperAuthCallerInfo - use entitlement
* (out) status = OSStatus
* (out) reply = N/A
*/
static Boolean
do_Auth(SCHelperSessionRef session, void *info, CFDataRef data, uint32_t *status, CFDataRef *reply)
{
- Boolean ok;
+ CFDictionaryRef authorizationDict;
+#if !TARGET_OS_IPHONE
+ CFDataRef authorizationData = NULL;
+#endif
+ Boolean ok = FALSE;
-#if !TARGET_OS_IPHONE
-
- ok = __SCHelperSessionSetAuthorization(session, data);
-
-#else //!TARGET_OS_IPHONE
-
- CFStringRef authorizationInfo = NULL;
-
- if ((data != NULL) && !_SCUnserializeString(&authorizationInfo, data, NULL, 0)) {
+ if (_SCUnserialize((CFPropertyListRef*)&authorizationDict, data, NULL, 0) == FALSE) {
return FALSE;
}
- if (!isA_CFString(authorizationInfo)) {
- if (authorizationInfo != NULL) CFRelease(authorizationInfo);
+ if (isA_CFDictionary(authorizationDict) == FALSE) {
+ CFRelease(authorizationDict);
return FALSE;
}
- ok = __SCHelperSessionSetAuthorization(session, authorizationInfo);
- if (authorizationInfo != NULL) CFRelease(authorizationInfo);
+#if !TARGET_OS_IPHONE
+ authorizationData = CFDictionaryGetValue(authorizationDict, kSCHelperAuthAuthorization);
+ if (authorizationData != NULL && isA_CFData(authorizationData)) {
+ ok = __SCHelperSessionSetAuthorization(session, authorizationData);
+ } else
+#endif
+ {
+ CFStringRef authorizationInfo;
-#endif // !TARGET_OS_IPHONE
+ authorizationInfo = CFDictionaryGetValue(authorizationDict, kSCHelperAuthCallerInfo);
+ if (authorizationInfo != NULL && isA_CFString(authorizationInfo)) {
+ ok = __SCHelperSessionSetAuthorization(session, authorizationInfo);
+ }
+ }
+ CFRelease(authorizationDict);
*status = ok ? 0 : 1;
return TRUE;
}
Boolean ok = FALSE;
if ((data != NULL) && !_SCUnserializeString(&ifName, data, NULL, 0)) {
+ *status = kSCStatusInvalidArgument;
SCLog(TRUE, LOG_ERR, CFSTR("interface name not valid"));
return FALSE;
}
- if (ifName != NULL) {
- if (isA_CFString(ifName)) {
- ok = _SCNetworkInterfaceForceConfigurationRefresh(ifName);
- if (!ok) {
- *status = SCError();
- }
- }
-
- CFRelease(ifName);
+ if (ifName == NULL) {
+ *status = kSCStatusInvalidArgument;
+ SCLog(TRUE, LOG_ERR, CFSTR("interface name not valid"));
+ return FALSE;
}
- if (!ok) {
+ if (isA_CFString(ifName)) {
+ ok = _SCNetworkInterfaceForceConfigurationRefresh(ifName);
+ if (!ok) {
+ *status = SCError();
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("interface \"%@\" not refreshed: %s"),
+ ifName,
+ SCErrorString(*status));
+ }
+ } else {
+ *status = kSCStatusInvalidArgument;
SCLog(TRUE, LOG_ERR, CFSTR("interface name not valid"));
}
+ CFRelease(ifName);
+
return ok;
}
#pragma mark Process commands
-#if TARGET_OS_IPHONE
-
-#include <Security/Security.h>
-#include <Security/SecTask.h>
-
static CFStringRef
sessionName(SCHelperSessionRef session)
{
return value;
}
-#endif // TARGET_OS_IPHONE
-
-
-
static Boolean
hasAuthorization(SCHelperSessionRef session)
{
- AuthorizationRef authorization = __SCHelperSessionGetAuthorization(session);
+ AuthorizationRef authorization = __SCHelperSessionGetAuthorization(session);
+ SCHelperSessionPrivateRef sessionPrivate = (SCHelperSessionPrivateRef)session;
if (authorization == NULL) {
return FALSE;
}
-#if !TARGET_OS_IPHONE
- AuthorizationFlags flags;
- AuthorizationItem items[1];
- AuthorizationRights rights;
- OSStatus status;
-
- items[0].name = "system.preferences";
- items[0].value = NULL;
- items[0].valueLength = 0;
- items[0].flags = 0;
-
- rights.count = sizeof(items) / sizeof(items[0]);
- rights.items = items;
-
- flags = kAuthorizationFlagDefaults;
- flags |= kAuthorizationFlagExtendRights;
- flags |= kAuthorizationFlagInteractionAllowed;
-// flags |= kAuthorizationFlagPartialRights;
-// flags |= kAuthorizationFlagPreAuthorize;
-
- status = AuthorizationCopyRights(authorization,
- &rights,
- kAuthorizationEmptyEnvironment,
- flags,
- NULL);
- if (status != errAuthorizationSuccess) {
- return FALSE;
- }
+#if !TARGET_OS_IPHONE
+ if (!__SCHelperSessionUseEntitlement(session)) {
+ AuthorizationFlags flags;
+ AuthorizationItem items[1];
+ AuthorizationRights rights;
+ OSStatus status;
+
+ items[0].name = kSCPreferencesWriteAuthorizationRight;
+ items[0].value = NULL;
+ items[0].valueLength = 0;
+ items[0].flags = 0;
+
+ rights.count = sizeof(items) / sizeof(items[0]);
+ rights.items = items;
+
+ flags = kAuthorizationFlagDefaults;
+ flags |= kAuthorizationFlagExtendRights;
+ flags |= kAuthorizationFlagInteractionAllowed;
+// flags |= kAuthorizationFlagPartialRights;
+// flags |= kAuthorizationFlagPreAuthorize;
+
+ status = AuthorizationCopyRights(authorization,
+ &rights,
+ kAuthorizationEmptyEnvironment,
+ flags,
+ NULL);
+ if (status != errAuthorizationSuccess) {
+ return FALSE;
+ }
- return TRUE;
-#else // !TARGET_OS_IPHONE
- SCHelperSessionPrivateRef sessionPrivate = (SCHelperSessionPrivateRef)session;
+ return TRUE;
+ }
+#endif // !TARGET_OS_IPHONE
if (sessionPrivate->callerWriteAccess == UNKNOWN) {
CFArrayRef entitlement;
}
return (sessionPrivate->callerWriteAccess == YES) ? TRUE : FALSE;
-#endif // TARGET_OS_IPHONE
}
uint32_t msgID,
xmlData_t dataRef, /* raw XML bytes */
mach_msg_type_number_t dataLen,
+ xmlData_t traceRef, /* raw XML bytes */
+ mach_msg_type_number_t traceLen,
uint32_t *status,
xmlDataOut_t *replyRef, /* raw XML bytes */
mach_msg_type_number_t *replyLen)
{
- CFDataRef data = NULL;
+ CFStringRef backtrace = NULL;
+ CFDataRef data = NULL;
int i;
- CFDataRef reply = NULL;
+ CFDataRef reply = NULL;
SCHelperSessionRef session;
*status = kSCStatusOK;
if ((dataRef != NULL) && (dataLen > 0)) {
if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
*status = SCError();
- return KERN_SUCCESS;
}
}
+ if ((traceRef != NULL) && (traceLen > 0)) {
+ if (!_SCUnserializeString(&backtrace, NULL, (void *)traceRef, traceLen)) {
+ *status = SCError();
+ }
+ }
+
+ if (*status != kSCStatusOK) {
+ goto done;
+ }
+
session = __SCHelperSessionFindWithPort(server);
if (session == NULL) {
*status = kSCStatusFailed; /* you must have an open session to play */
}
if (*status == kSCStatusOK) {
+ if (backtrace != NULL) {
+ __SCHelperSessionAddBacktrace(session, backtrace, helpers[i].commandName);
+ }
(*helpers[i].func)(session, helpers[i].info, data, status, &reply);
}
/* serialize the data */
if (reply != NULL) {
- ok = _SCSerializeData(reply, (void **)replyRef, (CFIndex *)replyLen);
+ CFIndex len;
+
+ ok = _SCSerializeData(reply, (void **)replyRef, &len);
+ *replyLen = len;
CFRelease(reply);
reply = NULL;
if (!ok) {
done :
if (data != NULL) CFRelease(data);
+ if (backtrace != NULL) CFRelease(backtrace);
if (reply != NULL) CFRelease(reply);
return KERN_SUCCESS;
}
launch_data_t l_reply;
launch_data_type_t l_type;
int n_listeners = 0;
- extern int optind;
+// extern int optind;
int opt;
int opti;
if (!done && (idle >= (2 * 60 / 15))) {
if (gen_reported != gen_current) {
+ FILE *logFile = NULL;
+
SCLog(TRUE, LOG_NOTICE, CFSTR("active (but IDLE) sessions"));
- CFSetApplyFunction(sessions, __SCHelperSessionLog, NULL);
+ CFSetApplyFunction(sessions, __SCHelperSessionLog, (void *)&logFile);
gen_reported = gen_current;
+
+ if (logFile != NULL) {
+ (void) fclose(logFile);
+ }
}
idle = 0;
}
/*
- * Copyright (c) 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
routine helperexec ( server : mach_port_t;
msgID : uint32_t;
data : xmlData;
+ trace : xmlData;
out status : uint32_t;
out reply : xmlDataOut, dealloc);
--- /dev/null
+/*
+ * Copyright (c) 2011, 2012 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,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * 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 <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include "SCNetworkReachabilityInternal.h"
+
+#ifdef HAVE_REACHABILITY_SERVER
+
+#include <xpc/xpc.h>
+#include <xpc/private.h>
+
+#include "rb.h"
+
+
+#pragma mark -
+#pragma mark Globals
+
+
+static const struct addrinfo hints0 = {
+#ifdef AI_PARALLEL
+ .ai_flags = AI_PARALLEL | AI_ADDRCONFIG
+#else // AI_PARALLEL
+ .ai_flags = AI_ADDRCONFIG
+#endif // AI_PARALLEL
+};
+
+
+static Boolean serverAvailable = TRUE;
+
+
+#pragma mark -
+#pragma mark Support functions
+
+
+static void
+log_xpc_object(const char *msg, xpc_object_t obj)
+{
+ char *desc;
+
+ desc = xpc_copy_description(obj);
+ SCLog(TRUE, LOG_DEBUG, CFSTR("%s = %s"), msg, desc);
+ free(desc);
+}
+
+
+#pragma mark -
+#pragma mark Reachability [RBT] client support
+
+
+typedef struct {
+ struct rb_node rbn;
+ SCNetworkReachabilityRef target;
+} reach_request_t;
+
+
+#define RBNODE_TO_REACH_REQUEST(node) \
+ ((reach_request_t *)((uintptr_t)node - offsetof(reach_request_t, rbn)))
+
+
+static int
+_rbt_compare_transaction_nodes(const struct rb_node *n1, const struct rb_node *n2)
+{
+ uint64_t a = (uintptr_t)(RBNODE_TO_REACH_REQUEST(n1)->target);
+ uint64_t b = (uintptr_t)(RBNODE_TO_REACH_REQUEST(n2)->target);
+
+ return (a - b);
+}
+
+
+static int
+_rbt_compare_transaction_key(const struct rb_node *n1, const void *key)
+{
+ uint64_t a = (uintptr_t)(RBNODE_TO_REACH_REQUEST(n1)->target);
+ uint64_t b = *(uint64_t *)key;
+
+ return (a - b);
+}
+
+
+static struct rb_tree *
+_reach_requests_rbt()
+{
+ static dispatch_once_t once;
+ static const struct rb_tree_ops ops = {
+ .rbto_compare_nodes = _rbt_compare_transaction_nodes,
+ .rbto_compare_key = _rbt_compare_transaction_key,
+ };
+ static struct rb_tree rbtree;
+
+ dispatch_once(&once, ^{
+ rb_tree_init(&rbtree, &ops);
+ });
+
+ return &rbtree;
+}
+
+
+static dispatch_queue_t
+_reach_requests_rbt_queue()
+{
+ static dispatch_once_t once;
+ static dispatch_queue_t q;
+
+ dispatch_once(&once, ^{
+ q = dispatch_queue_create(REACH_SERVICE_NAME ".rbt", NULL);
+ });
+
+ return q;
+}
+
+
+static reach_request_t *
+_reach_request_create(SCNetworkReachabilityRef target)
+{
+ reach_request_t *request;
+
+ request = calloc(1, sizeof(*request));
+ request->target = CFRetain(target);
+
+ return request;
+}
+
+
+static void
+_reach_request_release(reach_request_t *request)
+{
+ SCNetworkReachabilityRef target = request->target;
+
+ CFRelease(target);
+ free(request);
+
+ return;
+}
+
+
+static void
+_reach_request_add(SCNetworkReachabilityRef target)
+{
+ uint64_t target_id = (uintptr_t)target;
+
+ dispatch_sync(_reach_requests_rbt_queue(), ^{
+ struct rb_node *rbn;
+
+ rbn = rb_tree_find_node(_reach_requests_rbt(), &target_id);
+ if (rbn == NULL) {
+ reach_request_t *request;
+
+ request = _reach_request_create(target);
+ if (request == NULL || !rb_tree_insert_node(_reach_requests_rbt(), &request->rbn)) {
+ __builtin_trap();
+ }
+ }
+ });
+
+ return;
+}
+
+
+static void
+_reach_request_remove(SCNetworkReachabilityRef target)
+{
+ uint64_t target_id = (uintptr_t)target;
+
+ dispatch_sync(_reach_requests_rbt_queue(), ^{ // FIXME ?? use dispatch_async?
+ struct rb_node *rbn;
+ struct rb_tree *rbtree = _reach_requests_rbt();
+
+ rbn = rb_tree_find_node(rbtree, &target_id);
+ if (rbn != NULL) {
+ reach_request_t *request = RBNODE_TO_REACH_REQUEST(rbn);
+
+ rb_tree_remove_node(rbtree, rbn);
+ _reach_request_release(request);
+ }
+ });
+}
+
+
+static SCNetworkReachabilityRef
+_reach_request_copy_target(uint64_t target_id)
+{
+ __block SCNetworkReachabilityRef target = NULL;
+
+ dispatch_sync(_reach_requests_rbt_queue(), ^{
+ struct rb_node *rbn;
+
+ rbn = rb_tree_find_node(_reach_requests_rbt(), &target_id);
+ if (rbn != NULL) {
+ // handle the [async] reply
+ target = (SCNetworkReachabilityRef)(uintptr_t)target_id;
+ CFRetain(target);
+ }
+ });
+
+ return target;
+}
+
+
+#pragma mark -
+#pragma mark Reachability [XPC] client support
+
+
+static void
+handle_reachability_status(SCNetworkReachabilityRef target, xpc_object_t dict)
+{
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ if (_sc_debug) {
+ SCLog(TRUE, LOG_INFO, CFSTR("%sgot [async] notification"),
+ targetPrivate->log_prefix);
+// log_xpc_object(" status", dict);
+ }
+
+ __SCNetworkReachabilityPerformNoLock(target);
+
+ return;
+}
+
+
+static void
+handle_async_notification(SCNetworkReachabilityRef target, xpc_object_t dict)
+{
+ int64_t op;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ op = xpc_dictionary_get_int64(dict, MESSAGE_NOTIFY);
+ switch (op) {
+ case MESSAGE_REACHABILITY_STATUS :
+ handle_reachability_status(target, dict);
+ break;
+ default :
+ SCLog(TRUE, LOG_ERR, CFSTR("%sgot [async] unknown reply : %d"),
+ targetPrivate->log_prefix,
+ op);
+ log_xpc_object(" reply", dict);
+ break;
+ }
+
+ return;
+}
+
+
+static dispatch_queue_t
+_reach_xpc_queue()
+{
+ static dispatch_once_t once;
+ static dispatch_queue_t q;
+
+ dispatch_once(&once, ^{
+ q = dispatch_queue_create(REACH_SERVICE_NAME ".xpc", NULL);
+ });
+
+ return q;
+}
+
+
+static void
+_reach_connection_reconnect(xpc_connection_t connection);
+
+
+static xpc_connection_t
+_reach_connection_create()
+{
+ xpc_connection_t c;
+ const char *name;
+ dispatch_queue_t q = _reach_xpc_queue();
+
+ // create XPC connection
+ name = getenv("REACH_SERVER");
+ if ((name == NULL) || (issetugid() != 0)) {
+ name = REACH_SERVICE_NAME;
+ }
+
+ c = xpc_connection_create_mach_service(name,
+ q,
+ XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
+
+ xpc_connection_set_event_handler(c, ^(xpc_object_t xobj) {
+ xpc_type_t type;
+
+ type = xpc_get_type(xobj);
+ if (type == XPC_TYPE_DICTIONARY) {
+ SCNetworkReachabilityRef target;
+ uint64_t target_id;
+
+ target_id = xpc_dictionary_get_uint64(xobj, REACH_CLIENT_TARGET_ID);
+ if (target_id == 0) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("reach client %p: async reply with no target [ID]"),
+ c);
+ log_xpc_object(" reply", xobj);
+ return;
+ }
+
+ target = _reach_request_copy_target(target_id);
+ if (target == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("received unexpected target [ID] from SCNetworkReachability server"));
+ log_xpc_object(" reply", xobj);
+ return;
+ }
+
+ handle_async_notification(target, xobj);
+ CFRelease(target);
+
+ } else if (type == XPC_TYPE_ERROR) {
+ if (xobj == XPC_ERROR_CONNECTION_INVALID) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCNetworkReachability server not available"));
+ serverAvailable = FALSE;
+ } else if (xobj == XPC_ERROR_CONNECTION_INTERRUPTED) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("SCNetworkReachability server failure, reconnecting"));
+ _reach_connection_reconnect(c);
+ } else {
+ const char *desc;
+
+ desc = xpc_dictionary_get_string(xobj, XPC_ERROR_KEY_DESCRIPTION);
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("reach client %p: Connection error: %s"),
+ c,
+ desc);
+ }
+
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("reach client %p: unknown event type : %x"),
+ c,
+ type);
+ }
+ });
+ xpc_connection_resume(c);
+
+ return c;
+}
+
+
+static xpc_connection_t
+_reach_connection()
+{
+ static xpc_connection_t c;
+ static dispatch_once_t once;
+ static dispatch_queue_t q;
+
+ if (!serverAvailable) {
+ // if SCNetworkReachabilty [XPC] server not available
+ return NULL;
+ }
+
+ dispatch_once(&once, ^{
+ q = dispatch_queue_create(REACH_SERVICE_NAME ".connection", NULL);
+ });
+
+ dispatch_sync(q, ^{
+ if (c == NULL) {
+ c = _reach_connection_create();
+ }
+ });
+
+ return c;
+}
+
+
+typedef void (^reach_server_reply_handler_t)(xpc_object_t reply);
+
+
+static void
+add_proc_name(xpc_object_t reqdict)
+{
+ static const char *name = NULL;
+ static dispatch_once_t once;
+
+ // add the process name
+ dispatch_once(&once, ^{
+ name = getprogname();
+ });
+ xpc_dictionary_set_string(reqdict, REACH_CLIENT_PROC_NAME, name);
+
+ return;
+}
+
+
+static void
+_reach_server_target_reconnect(xpc_connection_t connection, SCNetworkReachabilityRef target);
+
+
+static Boolean
+_reach_server_target_add(xpc_connection_t connection, SCNetworkReachabilityRef target)
+{
+ Boolean ok = FALSE;
+ xpc_object_t reply;
+ xpc_object_t reqdict;
+ Boolean retry = FALSE;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ // create message
+ reqdict = xpc_dictionary_create(NULL, NULL, 0);
+
+ // set request
+ xpc_dictionary_set_int64(reqdict, REACH_REQUEST, REACH_REQUEST_CREATE);
+
+ // add reachability target info
+ if (targetPrivate->name != NULL) {
+ xpc_dictionary_set_string(reqdict,
+ REACH_TARGET_NAME,
+ targetPrivate->name);
+ }
+ if (targetPrivate->serv != NULL) {
+ xpc_dictionary_set_string(reqdict,
+ REACH_TARGET_SERV,
+ targetPrivate->serv);
+ }
+ if (targetPrivate->localAddress != NULL) {
+ xpc_dictionary_set_data(reqdict,
+ REACH_TARGET_LOCAL_ADDR,
+ targetPrivate->localAddress,
+ targetPrivate->localAddress->sa_len);
+ }
+ if (targetPrivate->remoteAddress != NULL) {
+ xpc_dictionary_set_data(reqdict,
+ REACH_TARGET_REMOTE_ADDR,
+ targetPrivate->remoteAddress,
+ targetPrivate->remoteAddress->sa_len);
+ }
+ if (bcmp(&targetPrivate->hints, &hints0, sizeof(struct addrinfo)) != 0) {
+ xpc_dictionary_set_data(reqdict,
+ REACH_TARGET_HINTS,
+ &targetPrivate->hints,
+ sizeof(targetPrivate->hints));
+ }
+ if (targetPrivate->if_index != 0) {
+ xpc_dictionary_set_int64(reqdict,
+ REACH_TARGET_IF_INDEX,
+ targetPrivate->if_index);
+ xpc_dictionary_set_string(reqdict,
+ REACH_TARGET_IF_NAME,
+ targetPrivate->if_name);
+ }
+ if (targetPrivate->onDemandBypass) {
+ xpc_dictionary_set_bool(reqdict,
+ REACH_TARGET_ONDEMAND_BYPASS,
+ TRUE);
+ }
+ if (targetPrivate->resolverBypass) {
+ xpc_dictionary_set_bool(reqdict,
+ REACH_TARGET_RESOLVER_BYPASS,
+ TRUE);
+ }
+
+
+ // add the target [ID]
+ xpc_dictionary_set_uint64(reqdict, REACH_CLIENT_TARGET_ID, (uintptr_t)target);
+
+ // add the process name (for debugging)
+ add_proc_name(reqdict);
+
+ retry :
+
+ // send request to the SCNetworkReachability server
+ reply = xpc_connection_send_message_with_reply_sync(connection, reqdict);
+ if (reply != NULL) {
+ xpc_type_t type;
+
+ type = xpc_get_type(reply);
+ if (type == XPC_TYPE_DICTIONARY) {
+ int64_t status;
+
+ status = xpc_dictionary_get_int64(reply, REACH_REQUEST_REPLY);
+ ok = (status == REACH_REQUEST_REPLY_OK);
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INVALID)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCNetworkReachability server not available"));
+ serverAvailable = FALSE;
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INTERRUPTED)) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("reach target %p: SCNetworkReachability server failure, retrying"),
+ target);
+ retry = TRUE;
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("reach target %p: _targetAdd with unexpected reply"),
+ target);
+ log_xpc_object(" reply", reply);
+ }
+
+ xpc_release(reply);
+ }
+
+ if (retry) {
+ retry = FALSE;
+ goto retry;
+ }
+
+ xpc_release(reqdict);
+ return ok;
+}
+
+
+static Boolean
+_reach_server_target_remove(xpc_connection_t connection, SCNetworkReachabilityRef target)
+{
+ Boolean ok = FALSE;
+ xpc_object_t reply;
+ xpc_object_t reqdict;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ // create message
+ reqdict = xpc_dictionary_create(NULL, NULL, 0);
+
+ // set request
+ xpc_dictionary_set_int64(reqdict, REACH_REQUEST, REACH_REQUEST_REMOVE);
+
+ // add the target [ID]
+ xpc_dictionary_set_uint64(reqdict, REACH_CLIENT_TARGET_ID, (uintptr_t)target);
+
+ reply = xpc_connection_send_message_with_reply_sync(connection, reqdict);
+ if (reply != NULL) {
+ xpc_type_t type;
+
+ type = xpc_get_type(reply);
+ if (type == XPC_TYPE_DICTIONARY) {
+ int64_t status;
+
+ status = xpc_dictionary_get_int64(reply, REACH_REQUEST_REPLY);
+ switch (status) {
+ case REACH_REQUEST_REPLY_OK :
+ ok = TRUE;
+ break;
+ case REACH_REQUEST_REPLY_UNKNOWN :
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("reach target %p: SCNetworkReachability server failure, no need to remove"),
+ target);
+ ok = TRUE;
+ break;
+ default : {
+ SCLog(TRUE, LOG_ERR, CFSTR("%s target remove failed"),
+ targetPrivate->log_prefix);
+ log_xpc_object(" reply", reply);
+ }
+ }
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INVALID)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCNetworkReachability server not available"));
+ serverAvailable = FALSE;
+ ok = TRUE;
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INTERRUPTED)) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("reach target %p: SCNetworkReachability server failure, no need to remove"),
+ target);
+ ok = TRUE;
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("reach target %p: _targetRemove with unexpected reply"),
+ target);
+ log_xpc_object(" reply", reply);
+ }
+
+ xpc_release(reply);
+ }
+
+ xpc_release(reqdict);
+ return ok;
+}
+
+
+static Boolean
+_reach_server_target_schedule(xpc_connection_t connection, SCNetworkReachabilityRef target)
+{
+ Boolean ok = FALSE;
+ xpc_object_t reply;
+ xpc_object_t reqdict;
+ Boolean retry = FALSE;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ // create message
+ reqdict = xpc_dictionary_create(NULL, NULL, 0);
+
+ // set request
+ xpc_dictionary_set_int64(reqdict, REACH_REQUEST, REACH_REQUEST_SCHEDULE);
+
+ // add the target [ID]
+ xpc_dictionary_set_uint64(reqdict, REACH_CLIENT_TARGET_ID, (uintptr_t)target);
+
+ retry :
+
+ reply = xpc_connection_send_message_with_reply_sync(connection, reqdict);
+ if (reply != NULL) {
+ xpc_type_t type;
+
+ type = xpc_get_type(reply);
+ if (type == XPC_TYPE_DICTIONARY) {
+ int64_t status;
+
+ status = xpc_dictionary_get_int64(reply, REACH_REQUEST_REPLY);
+ switch (status) {
+ case REACH_REQUEST_REPLY_OK :
+ ok = TRUE;
+ break;
+ case REACH_REQUEST_REPLY_UNKNOWN :
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("reach target %p: SCNetworkReachability server failure, retry schedule"),
+ target);
+ retry = TRUE;
+ break;
+ default : {
+ SCLog(TRUE, LOG_ERR, CFSTR("%s target schedule failed"),
+ targetPrivate->log_prefix);
+ log_xpc_object(" reply", reply);
+ }
+ }
+
+ if (ok) {
+ CFRetain(target);
+ }
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INVALID)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCNetworkReachability server not available"));
+ serverAvailable = FALSE;
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INTERRUPTED)) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("reach target %p: SCNetworkReachability server failure, retry schedule"),
+ target);
+ retry = TRUE;
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("reach target %p: _targetSchedule with unexpected reply"),
+ target);
+ log_xpc_object(" reply", reply);
+ }
+
+ xpc_release(reply);
+ }
+
+ if (retry) {
+ // reconnect
+ _reach_server_target_reconnect(connection, target);
+
+ // and retry
+ retry = FALSE;
+ goto retry;
+ }
+
+ xpc_release(reqdict);
+ return ok;
+}
+
+
+static void
+_reach_reply_set_reachability(SCNetworkReachabilityRef target,
+ xpc_object_t reply)
+{
+ char *if_name;
+ size_t len = 0;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ targetPrivate->serverInfo.cycle = xpc_dictionary_get_uint64(reply,
+ REACH_STATUS_CYCLE);
+
+ targetPrivate->serverInfo.flags = xpc_dictionary_get_uint64(reply,
+ REACH_STATUS_FLAGS);
+
+ targetPrivate->serverInfo.if_index = xpc_dictionary_get_uint64(reply,
+ REACH_STATUS_IF_INDEX);
+
+ bzero(&targetPrivate->serverInfo.if_name, sizeof(targetPrivate->serverInfo.if_name));
+ if_name = (void *)xpc_dictionary_get_data(reply,
+ REACH_STATUS_IF_NAME,
+ &len);
+ if ((if_name != NULL) && (len > 0)) {
+ if (len > sizeof(targetPrivate->serverInfo.if_name)) {
+ len = sizeof(targetPrivate->serverInfo.if_name);
+ }
+
+ bcopy(if_name, targetPrivate->serverInfo.if_name, len);
+ }
+
+ targetPrivate->serverInfo.sleeping = xpc_dictionary_get_bool(reply,
+ REACH_STATUS_SLEEPING);
+
+ if (targetPrivate->type == reachabilityTypeName) {
+ xpc_object_t addresses;
+
+ if (targetPrivate->resolvedAddress != NULL) {
+ CFRelease(targetPrivate->resolvedAddress);
+ targetPrivate->resolvedAddress = NULL;
+ }
+
+ targetPrivate->resolvedAddressError = xpc_dictionary_get_int64(reply,
+ REACH_STATUS_RESOLVED_ADDRESS_ERROR);
+
+ addresses = xpc_dictionary_get_value(reply, REACH_STATUS_RESOLVED_ADDRESS);
+ if ((addresses != NULL) && (xpc_get_type(addresses) != XPC_TYPE_ARRAY)) {
+ addresses = NULL;
+ }
+
+ if ((targetPrivate->resolvedAddressError == 0) && (addresses != NULL)) {
+ int i;
+ int n;
+ CFMutableArrayRef newAddresses;
+
+ newAddresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ n = xpc_array_get_count(addresses);
+ for (i = 0; i < n; i++) {
+ struct addrinfo *sa;
+ size_t len;
+ CFDataRef newAddress;
+
+ sa = (struct addrinfo *)xpc_array_get_data(addresses, i, &len);
+ newAddress = CFDataCreate(NULL, (const UInt8 *)sa, len);
+ CFArrayAppendValue(newAddresses, newAddress);
+ CFRelease(newAddress);
+ }
+
+ targetPrivate->resolvedAddress = newAddresses;
+ } else {
+ /* save the error associated with the attempt to resolve the name */
+ targetPrivate->resolvedAddress = CFRetain(kCFNull);
+ }
+ targetPrivate->needResolve = FALSE;
+ }
+
+ return;
+}
+
+
+__private_extern__
+Boolean
+_reach_server_target_status(xpc_connection_t connection, SCNetworkReachabilityRef target)
+{
+ Boolean ok = FALSE;
+ xpc_object_t reply;
+ xpc_object_t reqdict;
+ Boolean retry = FALSE;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ if (_sc_debug) {
+ CFStringRef str;
+
+ str = _SCNetworkReachabilityCopyTargetDescription(target);
+ SCLog(TRUE, LOG_INFO, CFSTR("%scheckReachability(%@)"),
+ targetPrivate->log_prefix,
+ str);
+ CFRelease(str);
+ }
+
+ // create message
+ reqdict = xpc_dictionary_create(NULL, NULL, 0);
+
+ // set request
+ xpc_dictionary_set_int64(reqdict, REACH_REQUEST, REACH_REQUEST_STATUS);
+
+ // add the target [ID]
+ xpc_dictionary_set_uint64(reqdict, REACH_CLIENT_TARGET_ID, (uintptr_t)target);
+
+ retry :
+
+ reply = xpc_connection_send_message_with_reply_sync(connection, reqdict);
+ if (reply != NULL) {
+ xpc_type_t type;
+
+ type = xpc_get_type(reply);
+ if (type == XPC_TYPE_DICTIONARY) {
+ int64_t status;
+
+ status = xpc_dictionary_get_int64(reply, REACH_REQUEST_REPLY);
+ switch (status) {
+ case REACH_REQUEST_REPLY_OK :
+ ok = TRUE;
+ break;
+ case REACH_REQUEST_REPLY_UNKNOWN :
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("reach target %p: SCNetworkReachability server failure, retry status"),
+ target);
+ retry = TRUE;
+ break;
+ default :
+ SCLog(TRUE, LOG_INFO, CFSTR("%s target status failed"),
+ targetPrivate->log_prefix);
+ log_xpc_object(" reply", reply);
+ }
+
+ if (ok) {
+ _reach_reply_set_reachability(target, reply);
+
+ if (_sc_debug) {
+ SCLog(TRUE, LOG_INFO, CFSTR("%s flags = 0x%08x"),
+ targetPrivate->log_prefix,
+ targetPrivate->serverInfo.flags);
+ if (targetPrivate->serverInfo.if_index != 0) {
+ SCLog(TRUE, LOG_INFO, CFSTR("%s device = %s (%hu%s)"),
+ targetPrivate->log_prefix,
+ targetPrivate->serverInfo.if_name,
+ targetPrivate->serverInfo.if_index,
+ targetPrivate->serverInfo.sleeping ? ", z" : "");
+ }
+ if (targetPrivate->serverInfo.cycle != targetPrivate->cycle) {
+ SCLog(TRUE, LOG_INFO, CFSTR("%s forced"),
+ targetPrivate->log_prefix);
+ }
+ }
+ }
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INVALID)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCNetworkReachability server not available"));
+ serverAvailable = FALSE;
+ ok = TRUE;
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INTERRUPTED)) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("reach target %p: SCNetworkReachability server failure, retry status"),
+ target);
+ retry = TRUE;
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("reach target %p: _targetStatus with unexpected reply"),
+ target);
+ log_xpc_object(" reply", reply);
+ }
+
+ xpc_release(reply);
+ }
+
+ if (retry) {
+ // reconnect
+ _reach_server_target_reconnect(connection, target);
+
+ // and retry
+ retry = FALSE;
+ goto retry;
+ }
+
+ xpc_release(reqdict);
+ return ok;
+}
+
+
+static Boolean
+_reach_server_target_unschedule(xpc_connection_t connection, SCNetworkReachabilityRef target)
+{
+ Boolean ok = FALSE;
+ xpc_object_t reply;
+ xpc_object_t reqdict;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ // create message
+ reqdict = xpc_dictionary_create(NULL, NULL, 0);
+
+ // set request
+ xpc_dictionary_set_int64(reqdict, REACH_REQUEST, REACH_REQUEST_UNSCHEDULE);
+
+ // add the target [ID]
+ xpc_dictionary_set_uint64(reqdict, REACH_CLIENT_TARGET_ID, (uintptr_t)target);
+
+ reply = xpc_connection_send_message_with_reply_sync(connection, reqdict);
+ if (reply != NULL) {
+ xpc_type_t type;
+
+ type = xpc_get_type(reply);
+ if (type == XPC_TYPE_DICTIONARY) {
+ int64_t status;
+
+ status = xpc_dictionary_get_int64(reply, REACH_REQUEST_REPLY);
+ switch (status) {
+ case REACH_REQUEST_REPLY_OK :
+ ok = TRUE;
+ break;
+ case REACH_REQUEST_REPLY_UNKNOWN :
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("reach target %p: SCNetworkReachability server failure, no need to unschedule"),
+ target);
+ break;
+ default :
+ SCLog(TRUE, LOG_INFO, CFSTR("%s target unschedule failed"),
+ targetPrivate->log_prefix);
+ log_xpc_object(" reply", reply);
+ }
+
+ if (ok) {
+ CFRelease(target);
+ }
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INVALID)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCNetworkReachability server not available"));
+ serverAvailable = FALSE;
+ ok = TRUE;
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INTERRUPTED)) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("reach target %p: SCNetworkReachability server failure, no need to unschedule"),
+ target);
+ ok = TRUE;
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("reach target %p: _targetUnschedule with unexpected reply"),
+ target);
+ log_xpc_object(" reply", reply);
+ }
+
+ xpc_release(reply);
+ }
+
+ xpc_release(reqdict);
+ return ok;
+}
+
+
+#pragma mark -
+#pragma mark Reconnect
+
+
+static void
+_reach_server_target_reconnect(xpc_connection_t connection, SCNetworkReachabilityRef target)
+{
+ Boolean ok;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ if (!targetPrivate->serverActive) {
+ // if target already removed
+ return;
+ }
+
+ // server has been restarted
+ targetPrivate->cycle = 0;
+
+ // re-associate with server
+ ok = _reach_server_target_add(connection, target);
+ if (!ok) {
+ // if we could not add the target
+ return;
+ }
+
+ if (!targetPrivate->serverScheduled) {
+ // if not scheduled
+ return;
+ }
+
+ // ... and re-schedule with server
+ ok = _reach_server_target_schedule(connection, target);
+ if (!ok) {
+ // if we could not reschedule the target
+ return;
+ }
+
+ // .. and update our status
+ __SCNetworkReachabilityPerformNoLock(target);
+
+ return;
+}
+
+
+static void
+_reach_connection_reconnect(xpc_connection_t connection)
+{
+ dispatch_queue_t q;
+
+ q = _reach_requests_rbt_queue();
+ dispatch_sync(q, ^{
+ struct rb_node *rbn;
+ struct rb_tree *rbt;
+
+ rbt = _reach_requests_rbt();
+ rbn = rb_tree_iterate(rbt, NULL, RB_DIR_RIGHT);
+ for ( ; rbn != NULL ; rbn = rb_tree_iterate(rbt, rbn, RB_DIR_LEFT)) {
+ reach_request_t *rbt_request;
+ SCNetworkReachabilityRef target;
+
+ rbt_request = RBNODE_TO_REACH_REQUEST(rbn);
+
+ target = rbt_request->target;
+ CFRetain(target);
+ dispatch_async(__SCNetworkReachability_concurrent_queue(), ^{
+ _reach_server_target_reconnect(connection, target);
+ CFRelease(target);
+ });
+ }
+ });
+
+ return;
+}
+
+
+#pragma mark -
+#pragma mark SPI (exposed)
+
+
+Boolean
+_SCNetworkReachabilityServer_snapshot(void)
+{
+ xpc_connection_t c;
+ Boolean ok = FALSE;
+ xpc_object_t reply;
+ xpc_object_t reqdict;
+
+ // initialize connection with SCNetworkReachability server
+ c = _reach_connection();
+ if (c == NULL) {
+ return FALSE;
+ }
+
+ // create message
+ reqdict = xpc_dictionary_create(NULL, NULL, 0);
+
+ // set request
+ xpc_dictionary_set_int64(reqdict, REACH_REQUEST, REACH_REQUEST_SNAPSHOT);
+
+ // add the process name (for debugging)
+ add_proc_name(reqdict);
+
+ retry :
+
+ // send request
+ reply = xpc_connection_send_message_with_reply_sync(c, reqdict);
+ if (reply != NULL) {
+ xpc_type_t type;
+
+ type = xpc_get_type(reply);
+ if (type == XPC_TYPE_DICTIONARY) {
+ int64_t status;
+
+ status = xpc_dictionary_get_int64(reply, REACH_REQUEST_REPLY);
+ ok = (status == REACH_REQUEST_REPLY_OK);
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INVALID)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCNetworkReachability server not available"));
+ serverAvailable = FALSE;
+ } else if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INTERRUPTED)) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("SCNetworkReachability server failure, retrying"));
+ xpc_release(reply);
+ goto retry;
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("_snapshot with unexpected reply"));
+ log_xpc_object(" reply", reply);
+ }
+
+ xpc_release(reply);
+ }
+
+ xpc_release(reqdict);
+ return ok;
+}
+
+
+__private_extern__
+Boolean
+__SCNetworkReachabilityServer_targetAdd(SCNetworkReachabilityRef target)
+{
+ xpc_connection_t c;
+ Boolean ok;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ c = _reach_connection();
+ if (c == NULL) {
+ return FALSE;
+ }
+
+ ok = _reach_server_target_add(c, target);
+ if (ok) {
+ _SC_ATOMIC_CMPXCHG(&targetPrivate->serverActive, FALSE, TRUE);
+ }
+
+ return ok;
+}
+
+
+__private_extern__
+void
+__SCNetworkReachabilityServer_targetRemove(SCNetworkReachabilityRef target)
+{
+ xpc_connection_t c;
+ Boolean ok;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ if (!targetPrivate->serverActive) {
+ // if not active
+ return;
+ }
+
+ c = _reach_connection();
+ if (c == NULL) {
+ return;
+ }
+
+ ok = _reach_server_target_remove(c, target);
+ if (ok) {
+ _SC_ATOMIC_CMPXCHG(&targetPrivate->serverActive, TRUE, FALSE);
+ }
+
+ return;
+}
+
+
+__private_extern__
+Boolean
+__SCNetworkReachabilityServer_targetSchedule(SCNetworkReachabilityRef target)
+{
+ xpc_connection_t c;
+ Boolean ok;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ c = _reach_connection();
+ if (c == NULL) {
+ return FALSE;
+ }
+
+ _reach_request_add(target);
+ ok = _reach_server_target_schedule(c, target);
+ if (ok) {
+ _SC_ATOMIC_CMPXCHG(&targetPrivate->serverScheduled, FALSE, TRUE);
+ } else {
+ _reach_request_remove(target);
+ }
+
+ return ok;
+}
+
+
+__private_extern__
+Boolean
+__SCNetworkReachabilityServer_targetStatus(SCNetworkReachabilityRef target)
+{
+ xpc_connection_t c;
+ Boolean ok;
+
+ c = _reach_connection();
+ if (c == NULL) {
+ return FALSE;
+ }
+
+ ok = _reach_server_target_status(c, target);
+ return ok;
+}
+
+
+__private_extern__
+Boolean
+__SCNetworkReachabilityServer_targetUnschedule(SCNetworkReachabilityRef target)
+{
+ xpc_connection_t c;
+ Boolean ok;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ if (!targetPrivate->serverScheduled) {
+ // if not scheduled
+ return TRUE;
+ }
+
+ c = _reach_connection();
+ if (c == NULL) {
+ return FALSE;
+ }
+
+ ok = _reach_server_target_unschedule(c, target);
+ if (ok) {
+ _SC_ATOMIC_CMPXCHG(&targetPrivate->serverScheduled, TRUE, FALSE);
+ _reach_request_remove(target);
+ } else {
+ // if unschedule failed
+ }
+
+ return ok;
+}
+
+#endif // HAVE_REACHABILITY_SERVER
--- /dev/null
+/*
+ * Copyright (c) 2011, 2012 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,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * 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 <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include "SCNetworkReachabilityInternal.h"
+
+#ifdef HAVE_REACHABILITY_SERVER
+
+#include <fcntl.h>
+#include <paths.h>
+#include <CommonCrypto/CommonDigest.h>
+#include <dispatch/dispatch.h>
+#include <dispatch/private.h>
+#include <xpc/xpc.h>
+#include <xpc/private.h>
+
+#include "rb.h"
+
+
+#pragma mark -
+#pragma mark Globals
+
+
+/*
+ * S_debug
+ * A boolean that enables additional logging.
+ */
+static boolean_t S_debug = FALSE;
+
+
+#pragma mark -
+#pragma mark Support functions
+
+
+static void
+log_xpc_object(const char *msg, xpc_object_t obj)
+{
+ char *desc;
+
+ desc = xpc_copy_description(obj);
+ SCLog(S_debug, LOG_INFO, CFSTR("%s = %s"), msg, desc);
+ free(desc);
+}
+
+
+static __inline__ void
+my_CFDictionaryApplyFunction(CFDictionaryRef theDict,
+ CFDictionaryApplierFunction applier,
+ void *context)
+{
+ CFAllocatorRef myAllocator;
+ CFDictionaryRef myDict;
+
+ myAllocator = CFGetAllocator(theDict);
+ myDict = CFDictionaryCreateCopy(myAllocator, theDict);
+ CFDictionaryApplyFunction(myDict, applier, context);
+ CFRelease(myDict);
+ return;
+}
+
+
+#pragma mark -
+#pragma mark SCNetworkReachability target support
+
+
+static CFMutableDictionaryRef reach_digest_map;
+
+
+static dispatch_queue_t
+_server_concurrent_queue()
+{
+ static dispatch_once_t once;
+ static dispatch_queue_t q;
+
+ dispatch_once(&once, ^{
+ q = dispatch_queue_create(REACH_SERVICE_NAME ".concurrent",
+ DISPATCH_QUEUE_CONCURRENT);
+ dispatch_queue_set_width(q, 32);
+ });
+
+ return q;
+}
+
+
+static dispatch_queue_t
+_server_digest_queue()
+{
+ static dispatch_once_t once;
+ static dispatch_queue_t q;
+
+ dispatch_once(&once, ^{
+ q = dispatch_queue_create(REACH_SERVICE_NAME ".digest", NULL);
+ });
+
+ return q;
+}
+
+
+static dispatch_group_t
+_target_group(SCNetworkReachabilityRef target)
+{
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ return targetPrivate->serverGroup;
+}
+
+
+static dispatch_queue_t
+_target_queue(SCNetworkReachabilityRef target)
+{
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ return targetPrivate->serverQueue;
+}
+
+
+#pragma mark -
+
+
+/*
+ * _target_reference_add
+ *
+ * Note: use dispatch_sync(_server_digest_queue(), ^{ ... });
+ */
+static void
+_target_reference_add(SCNetworkReachabilityRef target, CFDataRef digest, xpc_connection_t connection)
+{
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ // take a reference to the target
+ CFRetain(target);
+
+ // ensure that we have a dispatch group
+ if (targetPrivate->serverGroup == NULL) {
+ targetPrivate->serverGroup = dispatch_group_create();
+ }
+
+ // ensure that we have a dispatch queue
+ if (targetPrivate->serverQueue == NULL) {
+ char qname[256];
+
+ snprintf(qname, sizeof(qname), "com.apple.SCNetworkReachability.%p.server", target);
+ targetPrivate->serverQueue = dispatch_queue_create(qname, NULL);
+ }
+
+ // bump the reference count
+ if (_SC_ATOMIC_INC(&targetPrivate->serverReferences) == 0) {
+ // and maintain a digest-->target mapping
+ targetPrivate->serverDigest = CFRetain(digest);
+ CFDictionarySetValue(reach_digest_map, digest, target);
+ }
+
+ if (S_debug) {
+ CFStringRef str;
+
+ str = _SCNetworkReachabilityCopyTargetDescription(target);
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> target %p: reference added (%@, %d)"),
+ connection,
+ target,
+ str,
+ targetPrivate->serverReferences);
+ CFRelease(str);
+ }
+
+ return;
+}
+
+
+/*
+ * _target_reference_remove
+ *
+ * Note: use dispatch_sync(_server_digest_queue(), ^{ ... });
+ */
+static void
+_target_reference_remove(SCNetworkReachabilityRef target, xpc_connection_t connection)
+{
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ // drop the reference count
+ if (_SC_ATOMIC_DEC(&targetPrivate->serverReferences) == 0) {
+ /*
+ * if that was the last reference, we no longer need to
+ * keep the digest-->target mapping
+ */
+ CFDictionaryRemoveValue(reach_digest_map, targetPrivate->serverDigest);
+ CFRelease(targetPrivate->serverDigest);
+ targetPrivate->serverDigest = NULL;
+ }
+
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> target %p: reference removed (%d)"),
+ connection,
+ target,
+ targetPrivate->serverReferences);
+ }
+
+ // release a reference to the target
+ CFRelease(target);
+
+ return;
+}
+
+
+#pragma mark -
+
+
+#define MUTEX_LOCK(m) { \
+ int _lock_ = (pthread_mutex_lock(m) == 0); \
+ assert(_lock_); \
+}
+
+#define MUTEX_UNLOCK(m) { \
+ int _unlock_ = (pthread_mutex_unlock(m) == 0); \
+ assert(_unlock_); \
+}
+
+
+static void
+_target_reply_add_reachability(SCNetworkReachabilityRef target,
+ xpc_object_t reply)
+{
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ MUTEX_LOCK(&targetPrivate->lock);
+
+ xpc_dictionary_set_uint64(reply,
+ REACH_STATUS_CYCLE,
+ targetPrivate->info.cycle);
+ xpc_dictionary_set_uint64(reply,
+ REACH_STATUS_FLAGS,
+ targetPrivate->info.flags);
+ xpc_dictionary_set_uint64(reply,
+ REACH_STATUS_IF_INDEX,
+ targetPrivate->info.if_index);
+ xpc_dictionary_set_data (reply,
+ REACH_STATUS_IF_NAME,
+ targetPrivate->info.if_name,
+ sizeof(targetPrivate->info.if_name));
+ xpc_dictionary_set_bool (reply,
+ REACH_STATUS_SLEEPING,
+ targetPrivate->info.sleeping);
+ if (targetPrivate->type == reachabilityTypeName) {
+ if (isA_CFArray(targetPrivate->resolvedAddress)) {
+ xpc_object_t addresses;
+ CFIndex i;
+ CFIndex n;
+
+ addresses = xpc_array_create(NULL, 0);
+
+ n = CFArrayGetCount(targetPrivate->resolvedAddress);
+ for (i = 0; i < n; i++) {
+ CFDataRef address;
+
+ address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddress, i);
+ xpc_array_set_data(addresses,
+ XPC_ARRAY_APPEND,
+ CFDataGetBytePtr(address),
+ CFDataGetLength(address));
+ }
+
+ xpc_dictionary_set_value(reply,
+ REACH_STATUS_RESOLVED_ADDRESS,
+ addresses);
+ xpc_release(addresses);
+ }
+ xpc_dictionary_set_int64(reply,
+ REACH_STATUS_RESOLVED_ADDRESS_ERROR,
+ targetPrivate->resolvedAddressError);
+ }
+
+ MUTEX_UNLOCK(&targetPrivate->lock);
+
+ return;
+}
+
+
+#pragma mark -
+
+
+typedef struct {
+ xpc_connection_t connection;
+ uint64_t target_id;
+} reach_watcher_key_t;
+
+typedef struct {
+ unsigned int n_changes;
+} reach_watcher_val_t;
+
+
+static CFDataRef
+_target_watcher_key_create(xpc_connection_t connection,
+ uint64_t target_id)
+{
+ CFDataRef key;
+ reach_watcher_key_t watcher_key;
+
+ watcher_key.connection = connection;
+ watcher_key.target_id = target_id;
+
+ key = CFDataCreate(NULL, (UInt8 *)&watcher_key, sizeof(watcher_key));
+ return key;
+}
+
+
+static Boolean
+_target_watcher_add(SCNetworkReachabilityRef target,
+ xpc_connection_t connection,
+ uint64_t target_id)
+{
+ __block Boolean ok = TRUE;
+ dispatch_queue_t q;
+
+ q = _target_queue(target);
+ dispatch_sync(q, ^{
+ CFDataRef key;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ if (targetPrivate->serverWatchers == NULL) {
+ ok = SCNetworkReachabilitySetDispatchQueue(target, q);
+ if (!ok) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target %p: _watcher_add SCNetworkReachabilitySetDispatchQueue() failed: %s"),
+ connection,
+ target,
+ SCErrorString(SCError()));
+ return;
+ }
+
+ targetPrivate->serverWatchers = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ xpc_retain(connection);
+
+ key = _target_watcher_key_create(connection, target_id);
+ if (CFDictionaryContainsKey(targetPrivate->serverWatchers, key)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target %p: watcher not added, c=0x%0llx, \"serverWatchers\" key exists"),
+ connection,
+ target,
+ target_id);
+ } else {
+ CFDataRef val;
+ static const reach_watcher_val_t watcher_val0 = { 0 };
+
+ val = CFDataCreate(NULL, (UInt8 *)&watcher_val0, sizeof(watcher_val0));
+ CFDictionaryAddValue(targetPrivate->serverWatchers, key, val);
+ CFRelease(val);
+
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> target %p: watcher added, c=0x%0llx, n=%d"),
+ connection,
+ target,
+ target_id,
+ CFDictionaryGetCount(targetPrivate->serverWatchers));
+ }
+ }
+ CFRelease(key);
+ });
+
+ return ok;
+}
+
+
+static Boolean
+_target_watcher_checkin(SCNetworkReachabilityRef target,
+ xpc_connection_t connection,
+ uint64_t target_id)
+{
+ __block Boolean scheduled = FALSE;
+
+ dispatch_sync(_target_queue(target), ^{
+ CFDataRef key;
+ unsigned int n;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+ CFDataRef val;
+ reach_watcher_val_t *watcher_val;
+
+ if (targetPrivate->serverWatchers == NULL) {
+ // if no watchers
+ return;
+ }
+
+ key = _target_watcher_key_create(connection, target_id);
+ val = CFDictionaryGetValue(targetPrivate->serverWatchers, key);
+ CFRelease(key);
+ if (val == NULL) {
+ // if the target [for this client] was not scheduled
+ return;
+ }
+
+ // indicate that the target was scheduled
+ scheduled = TRUE;
+
+ /*
+ * and note that the reachability flags for this target have
+ * been picked up by the client
+ */
+ /* ALIGN: CF aligns to at least >8 byte boundries */
+ watcher_val = (reach_watcher_val_t *)(void *)CFDataGetBytePtr(val);
+ n = _SC_ATOMIC_ZERO(&watcher_val->n_changes);
+ if (S_debug && (n > 0)) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> target %p: SCNetworkReachabilityGetFlags() after %d notification%s"),
+ connection,
+ target,
+ n,
+ (n == 1) ? "" : "s");
+ }
+ });
+
+ return scheduled;
+}
+
+
+static Boolean
+_target_watcher_remove(SCNetworkReachabilityRef target,
+ xpc_connection_t connection,
+ uint64_t target_id)
+{
+ __block Boolean ok = TRUE;
+
+ dispatch_sync(_target_queue(target), ^{
+ CFDataRef key;
+ CFIndex n;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ if (targetPrivate->serverWatchers == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target %p: watcher not removed, c=0x%0llx, no \"serverWatchers\""),
+ connection,
+ target,
+ target_id);
+ return;
+ }
+
+ key = _target_watcher_key_create(connection, target_id);
+ if (!CFDictionaryContainsKey(targetPrivate->serverWatchers, key)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target %p: watcher not removed, c=0x%0llx, no \"serverWatchers\" key"),
+ connection,
+ target,
+ target_id);
+ CFRelease(key);
+ return;
+ }
+
+ CFDictionaryRemoveValue(targetPrivate->serverWatchers, key);
+ xpc_release(connection);
+ CFRelease(key);
+
+ n = CFDictionaryGetCount(targetPrivate->serverWatchers);
+
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> target %p: watcher removed, c=0x%0llx, n=%d"),
+ connection,
+ target, // server
+ target_id, // client
+ n);
+ }
+
+ if (n == 0) {
+ CFRelease(targetPrivate->serverWatchers);
+ targetPrivate->serverWatchers = NULL;
+
+ ok = SCNetworkReachabilitySetDispatchQueue(target, NULL);
+ if (!ok) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target %p: _watcher_remove SCNetworkReachabilitySetDispatchQueue() failed: %s"),
+ connection,
+ target,
+ SCErrorString(SCError()));
+ return;
+ }
+
+ // no more watchers, flags are no longer valid
+ (void) _SC_ATOMIC_CMPXCHG(&targetPrivate->serverInfoValid, TRUE, FALSE);
+ }
+ });
+
+ return ok;
+}
+
+
+#pragma mark -
+#pragma mark Reachability [RBT] client support
+
+
+typedef struct {
+ struct rb_node rbn;
+ xpc_connection_t connection;
+ pid_t pid;
+ const char *proc_name;
+ CFMutableDictionaryRef targets; // target_id --> SCNetworkReachabilityRef
+} reach_client_t;
+
+
+#define RBNODE_TO_REACH_CLIENT(node) \
+ ((reach_client_t *)((uintptr_t)node - offsetof(reach_client_t, rbn)))
+
+
+static int
+_rbt_compare_transaction_nodes(const struct rb_node *n1, const struct rb_node *n2)
+{
+ uint64_t a = (uintptr_t)RBNODE_TO_REACH_CLIENT(n1)->connection;
+ uint64_t b = (uintptr_t)RBNODE_TO_REACH_CLIENT(n2)->connection;
+
+ return (a - b);
+}
+
+
+static int
+_rbt_compare_transaction_key(const struct rb_node *n1, const void *key)
+{
+ uint64_t a = (uintptr_t)RBNODE_TO_REACH_CLIENT(n1)->connection;
+ uint64_t b = *(uintptr_t *)key;
+
+ return (a - b);
+}
+
+
+static struct rb_tree *
+_reach_clients_rbt()
+{
+ static dispatch_once_t once;
+ static const struct rb_tree_ops ops = {
+ .rbto_compare_nodes = _rbt_compare_transaction_nodes,
+ .rbto_compare_key = _rbt_compare_transaction_key,
+ };
+ static struct rb_tree rbtree;
+
+ dispatch_once(&once, ^{
+ rb_tree_init(&rbtree, &ops);
+ });
+
+ return &rbtree;
+}
+
+
+static dispatch_queue_t
+_reach_connection_queue()
+{
+ static dispatch_once_t once;
+ static dispatch_queue_t q;
+
+ dispatch_once(&once, ^{
+ q = dispatch_queue_create(REACH_SERVICE_NAME ".connection", NULL);
+ });
+
+ return q;
+}
+
+
+static reach_client_t *
+_reach_client_create(xpc_connection_t connection)
+{
+ reach_client_t *client;
+
+ client = calloc(1, sizeof(*client));
+ client->connection = connection;
+ client->pid = xpc_connection_get_pid(connection);
+ client->proc_name = NULL;
+ client->targets = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ return client;
+}
+
+
+static void
+_reach_client_release(reach_client_t *client)
+{
+ if (client->proc_name != NULL) {
+ free((void *)client->proc_name);
+ }
+ CFRelease(client->targets);
+ free(client);
+ return;
+}
+
+
+static void
+_reach_client_remove_target(const void *key, const void *value, void *context)
+{
+ xpc_connection_t connection = (xpc_connection_t)context;
+ SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)value;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ // check if we have anyone watching this target
+ if (targetPrivate->serverWatchers != NULL) {
+ CFIndex n;
+
+ n = CFDictionaryGetCount(targetPrivate->serverWatchers);
+ if (n > 0) {
+ CFIndex i;
+ const void * watchers_q[32];
+ const void ** watchers = watchers_q;
+
+ if (n > sizeof(watchers_q)/sizeof(watchers[0])) {
+ watchers = CFAllocatorAllocate(NULL, n * sizeof(CFDataRef), 0);
+ }
+ CFDictionaryGetKeysAndValues(targetPrivate->serverWatchers, watchers, NULL);
+
+ for (i = 0; i < n; i++) {
+ CFDataRef key;
+ reach_watcher_key_t *watcher_key;
+
+ key = (CFDataRef)watchers[i];
+ /* ALIGN: CF aligns to >8 byte boundries */
+ watcher_key = (reach_watcher_key_t *)(void *)CFDataGetBytePtr(key);
+ if (watcher_key->connection == connection) {
+ // remove watcher references for THIS connection
+ _target_watcher_remove(target,
+ watcher_key->connection,
+ watcher_key->target_id);
+ }
+ }
+
+ if (watchers != watchers_q) {
+ CFAllocatorDeallocate(NULL, watchers);
+ }
+ }
+ }
+
+ // remove our reference to this target
+ dispatch_sync(_server_digest_queue(), ^{
+ _target_reference_remove(target, connection);
+ });
+
+ return;
+}
+
+
+static void
+_reach_client_remove(xpc_connection_t connection)
+{
+ struct rb_tree *rbtree = _reach_clients_rbt();
+ struct rb_node *rbn;
+
+ rbn = rb_tree_find_node(rbtree, &connection);
+ if (rbn != NULL) {
+ reach_client_t *client;
+
+ client = RBNODE_TO_REACH_CLIENT(rbn);
+
+ // remove any remaining target references (for this client)
+ my_CFDictionaryApplyFunction(client->targets,
+ _reach_client_remove_target,
+ (void *)connection);
+
+ rb_tree_remove_node(rbtree, rbn);
+ _reach_client_release(client);
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> _reach_client_remove: unexpected client"),
+ connection);
+ }
+
+ return;
+}
+
+
+static __inline__ CFDataRef
+_client_target_key_create(uint64_t target_id)
+{
+ CFDataRef target_key;
+
+ target_key = CFDataCreate(NULL, (UInt8 *)&target_id, sizeof(target_id));
+ return target_key;
+}
+
+
+static SCNetworkReachabilityRef
+_client_target_copy(reach_client_t *client, uint64_t target_id)
+{
+ SCNetworkReachabilityRef target;
+ CFDataRef target_key;
+
+ target_key = _client_target_key_create(target_id);
+ target = CFDictionaryGetValue(client->targets, target_key);
+ CFRelease(target_key);
+
+ if (target != NULL) {
+ CFRetain(target);
+ }
+
+ return target;
+}
+
+
+static Boolean
+_client_target_set(reach_client_t *client, uint64_t target_id, SCNetworkReachabilityRef target)
+{
+ Boolean added;
+ CFDataRef target_key;
+
+ target_key = _client_target_key_create(target_id);
+ added = !CFDictionaryContainsKey(client->targets, target_key);
+ if (added) {
+ CFDictionarySetValue(client->targets, target_key, target);
+ }
+ CFRelease(target_key);
+
+ return added;
+}
+
+
+static void
+_client_target_remove(reach_client_t *client, uint64_t target_id)
+{
+ CFDataRef target_key;
+
+ target_key = _client_target_key_create(target_id);
+ CFDictionaryRemoveValue(client->targets, target_key);
+ CFRelease(target_key);
+
+ return;
+}
+
+
+#pragma mark -
+#pragma mark Reachability [XPC] server functions
+
+/*
+ * _reach_changed
+ *
+ * Note: should be exec'd on the target queue
+ */
+static void
+_reach_changed(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
+{
+ CFIndex i;
+ CFIndex n;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+ const void * watcher_keys_q[32];
+ const void ** watcher_keys = watcher_keys_q;
+ const void * watcher_vals_q[32];
+ const void ** watcher_vals = watcher_vals_q;
+
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("%sprocess reachability changed, flags = 0x%08x"),
+ targetPrivate->log_prefix,
+ flags);
+ }
+
+ if (targetPrivate->serverWatchers == NULL) {
+ // if no watchers
+ return;
+ }
+
+ n = CFDictionaryGetCount(targetPrivate->serverWatchers);
+ if (n == 0) {
+ // if no watchers
+ return;
+ }
+
+ /*
+ * Because we are actively watching for additional changes
+ * we mark the flags as "valid"
+ */
+ if (_SC_ATOMIC_CMPXCHG(&targetPrivate->serverInfoValid, FALSE, TRUE)) {
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO, CFSTR(" flags are now \"valid\""));
+ }
+ }
+
+ // notify all of the watchers
+ if (n > sizeof(watcher_keys_q)/sizeof(watcher_keys[0])) {
+ watcher_keys = CFAllocatorAllocate(NULL, n * sizeof(CFDataRef), 0);
+ watcher_vals = CFAllocatorAllocate(NULL, n * sizeof(CFDataRef), 0);
+ }
+
+ CFDictionaryGetKeysAndValues(targetPrivate->serverWatchers,
+ watcher_keys,
+ watcher_vals);
+
+ for (i = 0; i < n; i++) {
+ xpc_connection_t connection;
+ CFDataRef key;
+ uint64_t target_id;
+ CFDataRef val;
+ reach_watcher_key_t *watcher_key;
+ reach_watcher_val_t *watcher_val;
+
+ val = (CFDataRef)watcher_vals[i];
+ /* ALIGN: CF aligns to >8 byte boundries */
+ watcher_val = (reach_watcher_val_t *)(void *)CFDataGetBytePtr(val);
+
+ if (_SC_ATOMIC_INC(&watcher_val->n_changes) > 0) {
+ // if we've already sent a notification
+ continue;
+ }
+
+ key = (CFDataRef)watcher_keys[i];
+ /* ALIGN: CF aligns to >8 byte boundries */
+ watcher_key = (reach_watcher_key_t *)(void *)CFDataGetBytePtr(key);
+
+ connection = xpc_retain(watcher_key->connection);
+ target_id = watcher_key->target_id;
+ dispatch_async(_reach_connection_queue(), ^{
+ xpc_object_t reply;
+
+ // create our [async] notification
+ reply = xpc_dictionary_create(NULL, NULL, 0);
+
+ // set notification
+ xpc_dictionary_set_int64(reply,
+ MESSAGE_NOTIFY,
+ MESSAGE_REACHABILITY_STATUS);
+
+ // set target ID
+ xpc_dictionary_set_uint64(reply,
+ REACH_CLIENT_TARGET_ID,
+ target_id);
+
+ log_xpc_object(" reply [async]", reply);
+ xpc_connection_send_message(connection, reply);
+
+ xpc_release(reply);
+ xpc_release(connection);
+ });
+ }
+
+ if (n > sizeof(watcher_keys_q)/sizeof(watcher_keys[0])) {
+ CFAllocatorDeallocate(NULL, watcher_keys);
+ CFAllocatorDeallocate(NULL, watcher_vals);
+ }
+
+ return;
+}
+
+
+static void
+sanitize_address(const struct sockaddr *from, struct sockaddr *to)
+{
+ switch (from->sa_family) {
+ case AF_INET : {
+ /* ALIGN: cast okay, alignment not assumed. */
+ struct sockaddr_in *from4 = (struct sockaddr_in *)(void *)from;
+ struct sockaddr_in *to4 = (struct sockaddr_in *)(void *)to;
+
+ bzero(to4, sizeof(*to4));
+ to4->sin_len = sizeof(*to4);
+ to4->sin_family = AF_INET;
+ bcopy(&from4->sin_addr, &to4->sin_addr, sizeof(to4->sin_addr));
+ break;
+ }
+
+ case AF_INET6 : {
+ /* ALIGN: cast okay, alignment not assumed. */
+ struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)(void *)from;
+ struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)(void *)to;
+
+ bzero(to6, sizeof(*to6));
+ to6->sin6_len = sizeof(*to6);
+ to6->sin6_family = AF_INET6;
+ bcopy(&from6->sin6_addr, &to6->sin6_addr, sizeof(to6->sin6_addr));
+ to6->sin6_scope_id = from6->sin6_scope_id;
+ break;
+ }
+
+ default:
+ bcopy(from, to, from->sa_len);
+ break;
+ }
+
+ return;
+}
+
+
+static void
+target_add(reach_client_t *client, xpc_object_t request)
+{
+ const char *name;
+ const char *serv;
+ const struct sockaddr *localAddress;
+ struct sockaddr_storage localAddress0;
+ const struct sockaddr *remoteAddress;
+ struct sockaddr_storage remoteAddress0;
+ const struct addrinfo *hints;
+ int64_t if_index;
+ const char *if_name = NULL;
+ bool onDemandBypass = FALSE;
+ uint64_t target_id;
+
+
+ unsigned char bytes[CC_SHA1_DIGEST_LENGTH];
+ CC_SHA1_CTX ctx;
+ CFDataRef digest = NULL;
+ size_t len;
+ xpc_connection_t remote;
+ xpc_object_t reply;
+ bool resolverBypass = FALSE;
+ uint64_t status = REACH_REQUEST_REPLY_FAILED;
+
+ Boolean added;
+ __block Boolean ok = TRUE;
+ __block SCNetworkReachabilityRef target = NULL;
+
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> create reachability target"),
+ client->connection);
+// log_xpc_object(" create", request);
+ }
+
+ remote = xpc_dictionary_get_remote_connection(request);
+ reply = xpc_dictionary_create_reply(request);
+ if (reply == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target_add: xpc_dictionary_create_reply: failed"),
+ client->connection);
+ return;
+ }
+
+ target_id = xpc_dictionary_get_uint64(request, REACH_CLIENT_TARGET_ID);
+ if (target_id == 0) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "no target ID");
+ goto done;
+ }
+
+ // create a "digest" of the [new] target
+
+ CC_SHA1_Init(&ctx);
+
+ name = xpc_dictionary_get_string(request, REACH_TARGET_NAME);
+ if (name != NULL) {
+ CC_SHA1_Update(&ctx, name, strlen(name));
+ }
+
+ serv = xpc_dictionary_get_string(request, REACH_TARGET_SERV);
+ if (serv != NULL) {
+ CC_SHA1_Update(&ctx, serv, strlen(serv));
+ }
+
+ localAddress = xpc_dictionary_get_data(request, REACH_TARGET_LOCAL_ADDR, &len);
+ if (localAddress != NULL) {
+ if ((len == localAddress->sa_len) && (len <= sizeof(struct sockaddr_storage))) {
+ sanitize_address(localAddress, (struct sockaddr *)&localAddress0);
+ CC_SHA1_Update(&ctx, &localAddress0, len);
+ } else {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "local address: size error");
+ goto done;
+ }
+ }
+
+ remoteAddress = xpc_dictionary_get_data(request, REACH_TARGET_REMOTE_ADDR, &len);
+ if (remoteAddress != NULL) {
+ if ((len == remoteAddress->sa_len) && (len <= sizeof(struct sockaddr_storage))) {
+ sanitize_address(remoteAddress, (struct sockaddr *)&remoteAddress0);
+ CC_SHA1_Update(&ctx, &remoteAddress0, len);
+ } else {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "remote address: size error");
+ goto done;
+ }
+ }
+
+ hints = xpc_dictionary_get_data(request, REACH_TARGET_HINTS, &len);
+ if (hints != NULL) {
+ if (len == sizeof(struct addrinfo)) {
+ CC_SHA1_Update(&ctx, hints, len);
+ } else {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "hints: size error");
+ goto done;
+ }
+ }
+
+ if_index = xpc_dictionary_get_int64(request, REACH_TARGET_IF_INDEX);
+ if (if_index != 0) {
+ if_name = xpc_dictionary_get_string(request, REACH_TARGET_IF_NAME);
+ if (if_name != NULL) {
+ CC_SHA1_Update(&ctx, if_name, strlen(if_name));
+ }
+ }
+
+ onDemandBypass = xpc_dictionary_get_bool(request, REACH_TARGET_ONDEMAND_BYPASS);
+ if (onDemandBypass) {
+ CC_SHA1_Update(&ctx, &onDemandBypass, sizeof(onDemandBypass));
+ }
+
+ resolverBypass = xpc_dictionary_get_bool(request, REACH_TARGET_RESOLVER_BYPASS);
+ if (resolverBypass) {
+ CC_SHA1_Update(&ctx, &resolverBypass, sizeof(resolverBypass));
+ }
+
+
+ CC_SHA1_Final(bytes, &ctx);
+ digest = CFDataCreate(NULL, bytes, sizeof(bytes));
+
+ /*
+ * Check to see if we already have a SCNetworkReachability object
+ * for this digest. If so, we'll share the existing target. If not,
+ * create a new [shared] target.
+ */
+ dispatch_sync(_server_digest_queue(), ^{
+ target = CFDictionaryGetValue(reach_digest_map, digest);
+ if (target != NULL) {
+ CFRetain(target);
+ } else {
+ CFDataRef data;
+ CFMutableDictionaryRef options;
+ CFStringRef str;
+
+ options = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (name != NULL) {
+ str = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
+ CFRelease(str);
+ }
+ if (serv != NULL) {
+ str = CFStringCreateWithCString(NULL, serv, kCFStringEncodingUTF8);
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionServName, str);
+ CFRelease(str);
+ }
+ if (localAddress != NULL) {
+ data = CFDataCreate(NULL, (const UInt8 *)&localAddress0, localAddress0.ss_len);
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionLocalAddress, data);
+ CFRelease(data);
+ }
+ if (remoteAddress != NULL) {
+ data = CFDataCreate(NULL, (const UInt8 *)&remoteAddress0, remoteAddress0.ss_len);
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
+ CFRelease(data);
+ }
+ if (hints != NULL) {
+ data = CFDataCreate(NULL, (const UInt8 *)hints, sizeof(struct addrinfo));
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionHints, data);
+ CFRelease(data);
+ }
+ if (onDemandBypass) {
+ CFDictionarySetValue(options,
+ kSCNetworkReachabilityOptionConnectionOnDemandBypass,
+ kCFBooleanTrue);
+ }
+ if (resolverBypass) {
+ CFDictionarySetValue(options,
+ kSCNetworkReachabilityOptionResolverBypass,
+ kCFBooleanTrue);
+ }
+ CFDictionarySetValue(options,
+ kSCNetworkReachabilityOptionServerBypass,
+ kCFBooleanTrue);
+ target = SCNetworkReachabilityCreateWithOptions(NULL, options);
+ CFRelease(options);
+ if (target == NULL) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "SCNetworkReachabilityCreateWithOptions failed");
+ ok = FALSE;
+ return;
+ }
+
+ // because the interface name may not (no longer) be valid we set
+ // this after we've created the SCNetworkReachabilty object
+ if ((if_index != 0) && (if_name != NULL)) {
+ SCNetworkReachabilityPrivateRef targetPrivate;
+
+ targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+ targetPrivate->if_index = if_index;
+ strlcpy(targetPrivate->if_name, if_name, sizeof(targetPrivate->if_name));
+ }
+
+
+ ok = SCNetworkReachabilitySetCallback(target, _reach_changed, NULL);
+ if (!ok) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "SCNetworkReachabilitySetCallback failed");
+ CFRelease(target);
+ target = NULL;
+ return;
+ }
+ }
+
+ // bump the number of references to this target
+ _target_reference_add(target, digest, client->connection);
+ });
+
+ if (!ok) {
+ goto done;
+ }
+
+ /*
+ * add an association for the client's target_id to the [shared]
+ * SCNetworkReachability object.
+ */
+ added = _client_target_set(client, target_id, target);
+ if (!added) {
+ // if we already had a reference to the target (e.g. reconnect)
+ dispatch_sync(_server_digest_queue(), ^{
+ _target_reference_remove(target, client->connection);
+ });
+ }
+
+ status = REACH_REQUEST_REPLY_OK;
+
+ done :
+
+ xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, status);
+// log_xpc_object(" reply", reply);
+ xpc_connection_send_message(remote, reply);
+ xpc_release(reply);
+
+ if (digest != NULL) CFRelease(digest);
+ if (target != NULL) CFRelease(target);
+ return;
+}
+
+
+static void
+target_remove(reach_client_t *client, xpc_object_t request)
+{
+ xpc_connection_t remote;
+ xpc_object_t reply;
+ uint64_t status = REACH_REQUEST_REPLY_FAILED;
+ SCNetworkReachabilityRef target = NULL;
+ uint64_t target_id;
+
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> remove reachability target"),
+ client->connection);
+// log_xpc_object(" remove", request);
+ }
+
+ remote = xpc_dictionary_get_remote_connection(request);
+ reply = xpc_dictionary_create_reply(request);
+ if (reply == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target_remove: xpc_dictionary_create_reply: failed"),
+ client->connection);
+ return;
+ }
+
+ target_id = xpc_dictionary_get_uint64(request, REACH_CLIENT_TARGET_ID);
+ if (target_id == 0) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "no target ID");
+ goto done;
+ }
+
+ target = _client_target_copy(client, target_id);
+ if (target == NULL) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "no target");
+ status = REACH_REQUEST_REPLY_UNKNOWN;
+ goto done;
+ }
+
+ /*
+ * remove the association from the client's target_id to the [shared]
+ * SCNetworkReachability object.
+ */
+ _client_target_remove(client, target_id);
+
+ // drop the number of references to this target
+ dispatch_sync(_server_digest_queue(), ^{
+ _target_reference_remove(target, client->connection);
+ });
+
+ status = REACH_REQUEST_REPLY_OK;
+
+ done :
+
+ xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, status);
+// log_xpc_object(" reply", reply);
+ xpc_connection_send_message(remote, reply);
+ xpc_release(reply);
+
+ if (target != NULL) CFRelease(target);
+ return;
+}
+
+
+static void
+target_schedule(reach_client_t *client, xpc_object_t request)
+{
+ Boolean ok;
+ xpc_connection_t remote;
+ xpc_object_t reply;
+ uint64_t status = REACH_REQUEST_REPLY_FAILED;
+ SCNetworkReachabilityRef target = NULL;
+ uint64_t target_id;
+
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> schedule reachability target"),
+ client->connection);
+// log_xpc_object(" schedule", request);
+ }
+
+ remote = xpc_dictionary_get_remote_connection(request);
+ reply = xpc_dictionary_create_reply(request);
+ if (reply == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target_schedule: xpc_dictionary_create_reply: failed"),
+ client->connection);
+ return;
+ }
+
+ target_id = xpc_dictionary_get_uint64(request, REACH_CLIENT_TARGET_ID);
+ if (target_id == 0) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "no target ID");
+ goto done;
+ }
+
+ target = _client_target_copy(client, target_id);
+ if (target == NULL) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "no target");
+ status = REACH_REQUEST_REPLY_UNKNOWN;
+ goto done;
+ }
+
+ // enable monitoring
+ ok = _target_watcher_add(target, client->connection, target_id);
+ if (ok) {
+ status = REACH_REQUEST_REPLY_OK;
+ }
+
+ done :
+
+ xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, status);
+// log_xpc_object(" reply", reply);
+ xpc_connection_send_message(remote, reply);
+ xpc_release(reply);
+
+ if (target != NULL) CFRelease(target);
+ return;
+}
+
+
+static void
+target_status(reach_client_t *client, xpc_object_t request)
+{
+ xpc_connection_t remote;
+ xpc_object_t reply;
+ __block Boolean reply_now = TRUE;
+ Boolean scheduled;
+ uint64_t status = REACH_REQUEST_REPLY_FAILED;
+ SCNetworkReachabilityRef target = NULL;
+ uint64_t target_id;
+
+ if(S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> get status of reachability target"),
+ client->connection);
+// log_xpc_object(" status", request);
+ }
+
+ remote = xpc_dictionary_get_remote_connection(request);
+ reply = xpc_dictionary_create_reply(request);
+ if (reply == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target_status: xpc_dictionary_create_reply: failed"),
+ client->connection);
+ return;
+ }
+
+ target_id = xpc_dictionary_get_uint64(request, REACH_CLIENT_TARGET_ID);
+ if (target_id == 0) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target_status: no target"),
+ client->connection);
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "no target ID");
+ goto done;
+ }
+
+ target = _client_target_copy(client, target_id);
+ if (target == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target_status: no target (0x%0llx)"),
+ client->connection,
+ target_id);
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "no target");
+ status = REACH_REQUEST_REPLY_UNKNOWN;
+ goto done;
+ }
+
+ /*
+ * Check to see if the target [for this client] had been "scheduled".
+ *
+ * If so, also mark that we've picked up the current reachability
+ * flags and that any pending notifications have been processed.
+ */
+ scheduled = _target_watcher_checkin(target, client->connection, target_id);
+
+ /*
+ * return current reachability information to the caller
+ */
+ dispatch_sync(_target_queue(target), ^{
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ if (scheduled) {
+ /*
+ * The client "scheduled" this target. As such, we
+ * know that this an async query and that we only
+ * need to return the "last known" flags.
+ */
+ _target_reply_add_reachability(target, reply);
+// log_xpc_object(" reply [scheduled]", reply);
+
+ if (S_debug) {
+ CFStringRef str;
+
+ str = _SCNetworkReachabilityCopyTargetFlags(target);
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> reply [scheduled], %@"),
+ client->connection,
+ str);
+ CFRelease(str);
+ }
+ } else {
+ /*
+ * The client has NOT "scheduled" this target. As
+ * such, we know that this is a sync query and that
+ * must return "current" flags.
+ */
+ if (targetPrivate->scheduled && targetPrivate->serverInfoValid) {
+ /*
+ * The server target has been "scheduled" and we
+ * have flags that are "current".
+ */
+ _target_reply_add_reachability(target, reply);
+// log_xpc_object(" reply [scheduled/valid]", reply);
+
+ if (S_debug) {
+ CFStringRef str;
+
+ str = _SCNetworkReachabilityCopyTargetFlags(target);
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> reply [scheduled/valid], %@"),
+ client->connection,
+ str);
+ CFRelease(str);
+ }
+ } else {
+ dispatch_group_t group;
+
+ /*
+ * The server target has NOT been "scheduled" (or
+ * we do not have "current" flags. This means that
+ * we must query for the current information and
+ * return the flags to the client when they are
+ * available.
+ */
+
+ reply_now = FALSE;
+
+ group = _target_group(target);
+ if (_SC_ATOMIC_INC(&targetPrivate->serverQueryActive) == 0) {
+ CFRetain(target);
+ dispatch_group_async(group, _server_concurrent_queue(), ^{
+ SCNetworkReachabilityFlags flags;
+ unsigned int n;
+ Boolean ok;
+
+ // query for the flags
+ ok = SCNetworkReachabilityGetFlags(target, &flags);
+ flags = targetPrivate->info.flags; // get the "raw" flags
+ if (!ok) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCNetworkReachabilityGetFlags() [sync query] failed"
+ "\n target = %@"
+ "\n status = %s"),
+ target,
+ SCErrorString(SCError()));
+ }
+
+ // flags are now available
+ n = _SC_ATOMIC_ZERO(&targetPrivate->serverQueryActive);
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("%sSCNetworkReachabilityGetFlags() [sync query] complete, n = %d"),
+ targetPrivate->log_prefix,
+ n);
+ }
+
+ CFRelease(target);
+ });
+ }
+
+ CFRetain(target);
+ dispatch_group_notify(group, _target_queue(target), ^{
+ // flags are now available
+ _target_reply_add_reachability(target, reply);
+ xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, REACH_REQUEST_REPLY_OK);
+// log_xpc_object(" reply [delayed]", reply);
+
+ if (S_debug) {
+ CFStringRef str;
+
+ str = _SCNetworkReachabilityCopyTargetFlags(target);
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> reply [delayed], %@"),
+ client->connection,
+ str);
+ CFRelease(str);
+ }
+
+ xpc_connection_send_message(remote, reply);
+ xpc_release(reply);
+
+ CFRelease(target);
+ });
+ }
+ }
+ });
+
+ status = REACH_REQUEST_REPLY_OK;
+
+ done :
+
+ if (reply_now) {
+ xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, status);
+
+ if (status != REACH_REQUEST_REPLY_OK) {
+// log_xpc_object(" reply [!]", reply);
+
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> reply [!]"),
+ client->connection);
+ }
+ }
+
+ xpc_connection_send_message(remote, reply);
+ xpc_release(reply);
+ } else if (S_debug) {
+ CFStringRef str;
+
+ str = _SCNetworkReachabilityCopyTargetFlags(target);
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> no reply [yet], %@"),
+ client->connection,
+ str);
+ CFRelease(str);
+ }
+
+ if (target != NULL) CFRelease(target);
+ return;
+}
+
+
+static void
+target_unschedule(reach_client_t *client, xpc_object_t request)
+{
+ Boolean ok;
+ xpc_connection_t remote;
+ xpc_object_t reply;
+ uint64_t status = REACH_REQUEST_REPLY_FAILED;
+ SCNetworkReachabilityRef target = NULL;
+ uint64_t target_id;
+
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> unschedule reachability target"),
+ client->connection);
+// log_xpc_object(" unschedule", request);
+ }
+
+ remote = xpc_dictionary_get_remote_connection(request);
+ reply = xpc_dictionary_create_reply(request);
+ if (reply == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> target_unschedule: xpc_dictionary_create_reply: failed"),
+ client->connection);
+ return;
+ }
+
+ target_id = xpc_dictionary_get_uint64(request, REACH_CLIENT_TARGET_ID);
+ if (target_id == 0) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "no target ID");
+ goto done;
+ }
+
+ target = _client_target_copy(client, target_id);
+ if (target == NULL) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "no target");
+ status = REACH_REQUEST_REPLY_UNKNOWN;
+ goto done;
+ }
+
+ // disable monitoring
+ ok = _target_watcher_remove(target, client->connection, target_id);
+ if (ok) {
+ status = REACH_REQUEST_REPLY_OK;
+ }
+
+ done :
+
+ xpc_dictionary_set_int64(reply, REACH_REQUEST_REPLY, status);
+// log_xpc_object(" reply", reply);
+ xpc_connection_send_message(remote, reply);
+ xpc_release(reply);
+
+ if (target != NULL) CFRelease(target);
+ return;
+}
+
+
+#define SNAPSHOT_PATH_STATE _PATH_VARTMP "configd-reachability"
+
+
+static void
+_snapshot_digest_watcher(const void *key, const void *value, void *context)
+{
+ FILE *f = (FILE *)context;
+ static reach_client_t no_client = {
+ .pid = 0,
+ .proc_name = "?",
+ };
+ struct rb_node *rbn;
+ reach_client_t *rbt_client;
+ reach_watcher_key_t *watcher_key;
+ reach_watcher_val_t *watcher_val;
+
+ /* ALIGN: CF aligns to >8 byte boundries */
+ watcher_key = (reach_watcher_key_t *)(void *)CFDataGetBytePtr(key);
+ watcher_val = (reach_watcher_val_t *)(void *)CFDataGetBytePtr(value);
+
+ rbn = rb_tree_find_node(_reach_clients_rbt(), &watcher_key->connection);
+ if (rbn == NULL) {
+ rbn = &no_client.rbn;
+ }
+
+ rbt_client = RBNODE_TO_REACH_CLIENT(rbn);
+
+ SCPrint(TRUE, f,
+ CFSTR(" connection = %p, target(c) = 0x%0llx, command = %s, pid = %d, changes = %u\n"),
+ watcher_key->connection,
+ watcher_key->target_id,
+ rbt_client->proc_name,
+ rbt_client->pid,
+ watcher_val->n_changes);
+
+ return;
+}
+
+
+static void
+_snapshot_digest(const void *key, const void *value, void *context)
+{
+ FILE *f = (FILE *)context;
+ CFStringRef digest = (CFStringRef)key;
+ dispatch_queue_t q;
+ SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)value;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+
+ q = _target_queue(target);
+ dispatch_sync(q, ^{
+ SCPrint(TRUE, f, CFSTR("\n digest : %@\n"), digest);
+ SCPrint(TRUE, f, CFSTR(" %@\n"), target);
+ SCPrint(TRUE, f, CFSTR(" valid = %s, active = %u, refs = %u\n"),
+ targetPrivate->serverInfoValid ? "Y" : "N",
+ targetPrivate->serverQueryActive,
+ targetPrivate->serverReferences);
+
+ SCPrint(TRUE, f, CFSTR(" network %d.%3.3d"),
+ targetPrivate->last_network.tv_sec,
+ targetPrivate->last_network.tv_usec / 1000);
+#if !TARGET_OS_IPHONE
+ SCPrint(TRUE, f, CFSTR(", power %d.%3.3d"),
+ targetPrivate->last_power.tv_sec,
+ targetPrivate->last_power.tv_usec / 1000);
+#endif // !TARGET_OS_IPHONE
+ if (targetPrivate->type == reachabilityTypeName) {
+ SCPrint(TRUE, f, CFSTR(", DNS %d.%3.3d"),
+ targetPrivate->last_dns.tv_sec,
+ targetPrivate->last_dns.tv_usec / 1000);
+ if (timerisset(&targetPrivate->dnsQueryEnd)) {
+ struct timeval dnsQueryElapsed;
+
+ timersub(&targetPrivate->dnsQueryEnd,
+ &targetPrivate->dnsQueryStart,
+ &dnsQueryElapsed);
+ SCPrint(TRUE, f, CFSTR(" (query %d.%3.3d / reply %d.%3.3d)"),
+ targetPrivate->dnsQueryStart.tv_sec,
+ targetPrivate->dnsQueryStart.tv_usec / 1000,
+ dnsQueryElapsed.tv_sec,
+ dnsQueryElapsed.tv_usec / 1000);
+ }
+ }
+ if (timerisset(&targetPrivate->last_push)) {
+ SCPrint(TRUE, f, CFSTR(", last notify %d.%3.3d"),
+ targetPrivate->last_push.tv_sec,
+ targetPrivate->last_push.tv_usec / 1000);
+ }
+ SCPrint(TRUE, f, CFSTR("\n"));
+
+ if (targetPrivate->serverWatchers != NULL) {
+ CFDictionaryApplyFunction(targetPrivate->serverWatchers,
+ _snapshot_digest_watcher,
+ f);
+ }
+ });
+
+ return;
+}
+
+
+static void
+_snapshot_target(const void *key, const void *value, void *context)
+{
+ FILE *f = (FILE *)context;
+ SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)value;
+ uint64_t target_id;
+ CFDataRef target_key = (CFDataRef)key;
+
+ /* ALIGN: CF aligns > 8 byte boundries */
+ target_id = *(uint64_t *)(void *)CFDataGetBytePtr(target_key);
+
+ SCPrint(TRUE, f,
+ CFSTR(" target(c) = 0x%0llx, target(s) = %@\n"),
+ target_id,
+ target);
+
+ return;
+}
+
+
+static void
+_snapshot(reach_client_t *client, xpc_object_t request)
+{
+ uid_t euid;
+ FILE *f;
+ int fd;
+ Boolean ok = FALSE;
+ struct rb_node *rbn;
+ struct rb_tree *rbt;
+ xpc_connection_t remote;
+ xpc_object_t reply;
+
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p> snapshot"),
+ client->connection);
+// log_xpc_object(" create", request);
+ }
+
+ remote = xpc_dictionary_get_remote_connection(request);
+ reply = xpc_dictionary_create_reply(request);
+ if (reply == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> _snapshot: xpc_dictionary_create_reply: failed"),
+ client->connection);
+ return;
+ }
+
+ euid = xpc_connection_get_euid(remote);
+ if (euid != 0) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "Permission denied.");
+ goto done;
+ }
+
+ // Save a snapshot of the SCNetworkReachability server "state"
+
+ (void) unlink(SNAPSHOT_PATH_STATE);
+ fd = open(SNAPSHOT_PATH_STATE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
+ if (fd == -1) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "open: failed");
+ goto done;
+ }
+ f = fdopen(fd, "w");
+ if (f == NULL) {
+ xpc_dictionary_set_string(reply,
+ REACH_REQUEST_REPLY_DETAIL,
+ "fdopen: failed");
+ goto done;
+ }
+
+ // provide connection/client info
+
+ SCPrint(TRUE, f, CFSTR("Clients :\n"));
+ rbt = _reach_clients_rbt();
+ rbn = rb_tree_iterate(rbt, NULL, RB_DIR_RIGHT);
+ if (rbn != NULL) {
+ while (rbn != NULL) {
+ reach_client_t *rbt_client;
+
+ rbt_client = RBNODE_TO_REACH_CLIENT(rbn);
+ SCPrint(TRUE, f,
+ CFSTR("\n connection = %p, client = %p, command = %s, pid = %d\n"),
+ rbt_client->connection,
+ rbt_client,
+ rbt_client->proc_name != NULL ? rbt_client->proc_name : "?",
+ rbt_client->pid);
+ my_CFDictionaryApplyFunction(rbt_client->targets,
+ _snapshot_target,
+ f);
+
+ rbn = rb_tree_iterate(rbt, rbn, RB_DIR_LEFT);
+ }
+ } else {
+ SCPrint(TRUE, f, CFSTR(" None.\n"));
+ }
+ SCPrint(TRUE, f, CFSTR("\n"));
+
+ // provide "digest" info
+
+ SCPrint(TRUE, f, CFSTR("Digests :\n"));
+ dispatch_sync(_server_digest_queue(), ^{
+ if (reach_digest_map != NULL) {
+ CFDictionaryApplyFunction(reach_digest_map,
+ _snapshot_digest,
+ f);
+ }
+ });
+
+ (void) fclose(f);
+
+ ok = TRUE;
+
+ done :
+
+ xpc_dictionary_set_int64(reply,
+ REACH_REQUEST_REPLY,
+ ok ? REACH_REQUEST_REPLY_OK : REACH_REQUEST_REPLY_FAILED);
+// log_xpc_object(" reply", reply);
+ xpc_connection_send_message(remote, reply);
+ xpc_release(reply);
+
+ return;
+}
+
+
+static __inline__ void
+_extract_client_info(reach_client_t *client, xpc_object_t request)
+{
+ // if available/needed, save the process name
+ if (client->proc_name == NULL) {
+ const char *proc_name;
+
+ proc_name = xpc_dictionary_get_string(request, REACH_CLIENT_PROC_NAME);
+ if (proc_name != NULL) {
+ client->proc_name = strdup(proc_name);
+ }
+ }
+
+ return;
+}
+
+
+static void
+process_request(reach_client_t *client, xpc_object_t request)
+{
+ int64_t op;
+
+ op = xpc_dictionary_get_int64(request, REACH_REQUEST);
+ switch (op) {
+ case REACH_REQUEST_CREATE :
+ _extract_client_info(client, request);
+ target_add(client, request);
+ break;
+ case REACH_REQUEST_REMOVE :
+ target_remove(client, request);
+ break;
+ case REACH_REQUEST_STATUS :
+ target_status(client, request);
+ break;
+ case REACH_REQUEST_SCHEDULE :
+ target_schedule(client, request);
+ break;
+ case REACH_REQUEST_UNSCHEDULE :
+ target_unschedule(client, request);
+ break;
+ case REACH_REQUEST_SNAPSHOT :
+ _extract_client_info(client, request);
+ _snapshot(client, request);
+ break;
+ default :
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p> unknown request : %d"),
+ client->connection,
+ op);
+ break;
+ }
+
+ return;
+}
+
+
+static void
+process_new_connection(xpc_connection_t connection)
+{
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO, CFSTR("<%p> new reach client, pid=%d"),
+ connection,
+ xpc_connection_get_pid(connection));
+ }
+
+ dispatch_sync(_reach_connection_queue(), ^{
+ reach_client_t *client;
+
+ client = _reach_client_create(connection);
+ if (client == NULL || !rb_tree_insert_node(_reach_clients_rbt(), &client->rbn)) {
+ __builtin_trap();
+ }
+ });
+
+ xpc_connection_set_event_handler(connection, ^(xpc_object_t xobj) {
+ xpc_type_t type;
+
+ type = xpc_get_type(xobj);
+ if (type == XPC_TYPE_DICTIONARY) {
+ dispatch_sync(_reach_connection_queue(), ^{
+ struct rb_node *rbn;
+
+ rbn = rb_tree_find_node(_reach_clients_rbt(), &connection);
+ if (rbn != NULL) {
+ reach_client_t *client;
+
+ // process the request
+ client = RBNODE_TO_REACH_CLIENT(rbn);
+ process_request(client, xobj);
+ } else {
+ char *desc;
+
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p:%d> unexpected SCNetworkReachability request"),
+ connection,
+ xpc_connection_get_pid(connection));
+
+ desc = xpc_copy_description(xobj);
+ SCLog(TRUE, LOG_ERR,
+ CFSTR(" request = %s"),
+ desc);
+ free(desc);
+
+ xpc_connection_cancel(connection);
+ }
+ });
+
+ } else if (type == XPC_TYPE_ERROR) {
+ const char *desc;
+
+ desc = xpc_dictionary_get_string(xobj, XPC_ERROR_KEY_DESCRIPTION);
+ if (xobj == XPC_ERROR_CONNECTION_INVALID) {
+ if (S_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("<%p:%d> %s"),
+ connection,
+ xpc_connection_get_pid(connection),
+ desc);
+ }
+
+ xpc_retain(connection);
+ dispatch_async(_reach_connection_queue(), ^{
+ _reach_client_remove(connection);
+ xpc_release(connection);
+ });
+
+ } else if (xobj == XPC_ERROR_CONNECTION_INTERRUPTED) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p:%d> %s"),
+ connection,
+ xpc_connection_get_pid(connection),
+ desc);
+
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p:%d> Connection error: %d : %s"),
+ connection,
+ xpc_connection_get_pid(connection),
+ xobj,
+ desc);
+ }
+
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("<%p:%d> unknown event type : %x"),
+ connection,
+ xpc_connection_get_pid(connection),
+ type);
+ }
+ });
+
+ xpc_connection_resume(connection);
+
+ return;
+}
+
+
+#pragma mark -
+#pragma mark Reachability server "main"
+
+
+__private_extern__
+void
+load_SCNetworkReachability(CFBundleRef bundle, Boolean bundleVerbose)
+{
+ xpc_connection_t connection;
+ const char *name;
+ dispatch_queue_t reach_server_q;
+
+ S_debug = bundleVerbose;
+
+ /*
+ * create a dictionary mapping SCNetworkReachability [CFData] digests
+ * to SCNetworkReachability objects.
+ */
+ reach_digest_map = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ /*
+ * create dispatch queue for processing SCNetworkReachability
+ * service requests
+ */
+ reach_server_q = dispatch_queue_create(REACH_SERVICE_NAME, NULL);
+
+ // create XPC listener
+ name = getenv("REACH_SERVER");
+ if (name == NULL) {
+ name = REACH_SERVICE_NAME;
+ }
+ connection = xpc_connection_create_mach_service(name,
+ reach_server_q,
+ XPC_CONNECTION_MACH_SERVICE_LISTENER);
+
+ xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
+ xpc_type_t type;
+
+ type = xpc_get_type(event);
+ if (type == XPC_TYPE_CONNECTION) {
+ process_new_connection(event);
+
+ } else if (type == XPC_TYPE_ERROR) {
+ const char *desc;
+
+ desc = xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION);
+ if (event == XPC_ERROR_CONNECTION_INVALID) {
+ SCLog(TRUE, LOG_ERR, CFSTR("reach server: %s"), desc);
+ xpc_release(connection);
+ } else if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
+ SCLog(TRUE, LOG_ERR, CFSTR("reach server: %s"), desc);
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("reach server: Connection error: %d : %s"),
+ event,
+ desc);
+ }
+
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("reach server: unknown event type : %x"),
+ type);
+ }
+ });
+ xpc_connection_resume(connection);
+
+ return;
+}
+
+#ifdef MAIN
+
+int
+main(int argc, char **argv)
+{
+// _sc_log = FALSE;
+ _sc_verbose = (argc > 1) ? TRUE : FALSE;
+ _sc_debug = TRUE;
+
+ load_SCNetworkReachability(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+ CFRunLoopRun();
+ /* not reached */
+ exit(0);
+ return 0;
+}
+
+#endif /* MAIN */
+
+#endif // HAVE_REACHABILITY_SERVER
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include "SCNetworkReachabilityInternal.h"
+
+int
+main(int argc, char **argv)
+{
+ Boolean ok;
+ SCNetworkReachabilityRef target1;
+ SCNetworkReachabilityRef target2;
+ SCNetworkReachabilityRef target3;
+ SCNetworkReachabilityRef target4;
+ SCNetworkReachabilityRef target5;
+
+ _sc_log = FALSE;
+ _sc_debug = TRUE; // extra reachability logging
+
+ target1 = SCNetworkReachabilityCreateWithName(NULL, "web.apple.com");
+ ok = __SCNetworkReachabilityServer_targetAdd(target1);
+ if (!ok) {
+ SCLog(TRUE, LOG_ERR, CFSTR("No reachability server"));
+ exit(1);
+ }
+
+ target2 = SCNetworkReachabilityCreateWithName(NULL, "www.comcast.net");
+ __SCNetworkReachabilityServer_targetAdd(target2);
+
+ target3 = SCNetworkReachabilityCreateWithName(NULL, "www.comcast.net");
+ __SCNetworkReachabilityServer_targetAdd(target3);
+
+ target4 = SCNetworkReachabilityCreateWithName(NULL, "www.nonexistenthost.com");
+ __SCNetworkReachabilityServer_targetAdd(target4);
+
+ target5 = SCNetworkReachabilityCreateWithName(NULL, "www.washingtonpost.com");
+ __SCNetworkReachabilityServer_targetAdd(target5);
+
+ __SCNetworkReachabilityServer_targetStatus(target1);
+ __SCNetworkReachabilityServer_targetStatus(target2);
+ __SCNetworkReachabilityServer_targetStatus(target3);
+ __SCNetworkReachabilityServer_targetStatus(target4);
+
+ __SCNetworkReachabilityServer_targetMonitor(target1, TRUE);
+ __SCNetworkReachabilityServer_targetMonitor(target4, TRUE);
+ __SCNetworkReachabilityServer_targetMonitor(target5, TRUE);
+
+ __SCNetworkReachabilityServer_targetStatus(target4);
+ __SCNetworkReachabilityServer_targetStatus(target3);
+ __SCNetworkReachabilityServer_targetStatus(target2);
+ __SCNetworkReachabilityServer_targetStatus(target1);
+
+ sleep(2);
+
+ __SCNetworkReachabilityServer_targetStatus(target1);
+ __SCNetworkReachabilityServer_targetStatus(target4);
+ __SCNetworkReachabilityServer_targetStatus(target1);
+ __SCNetworkReachabilityServer_targetStatus(target4);
+
+ __SCNetworkReachabilityServer_targetMonitor(target1, FALSE);
+
+ __SCNetworkReachabilityServer_targetStatus(target1);
+ __SCNetworkReachabilityServer_targetStatus(target4);
+ __SCNetworkReachabilityServer_targetStatus(target1);
+ __SCNetworkReachabilityServer_targetStatus(target4);
+
+ __SCNetworkReachabilityServer_targetMonitor(target4, FALSE);
+
+ __SCNetworkReachabilityServer_targetStatus(target1);
+ __SCNetworkReachabilityServer_targetStatus(target4);
+
+// SCLog(TRUE, LOG_DEBUG, CFSTR("starting CFRunLoop"));
+// CFRunLoopRun();
+// SCLog(TRUE, LOG_DEBUG, CFSTR("CFRunLoop complete"));
+
+ SCLog(TRUE, LOG_DEBUG, CFSTR("sleeping"));
+ sleep(60);
+
+ __SCNetworkReachabilityServer_targetStatus(target5);
+ __SCNetworkReachabilityServer_targetRemove(target5);
+ CFRelease(target5);
+
+ __SCNetworkReachabilityServer_targetRemove(target4);
+ CFRelease(target4);
+
+ __SCNetworkReachabilityServer_targetRemove(target3);
+ CFRelease(target3);
+
+// __SCNetworkReachabilityServer_targetRemove(target2);
+// CFRelease(target2);
+
+// __SCNetworkReachabilityServer_targetRemove(target1);
+// CFRelease(target1);
+
+ exit(0);
+}
+
--- /dev/null
+/* $NetBSD: rb.c,v 1.4 2009/05/19 22:48:19 yamt Exp $ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt@3am-software.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#include <sys/types.h>
+#include <stddef.h>
+#include <assert.h>
+#include <stdbool.h>
+#ifdef RBDEBUG
+#define KASSERT(s) assert(s)
+#else
+#define KASSERT(s) do { } while (/*CONSTCOND*/ 0)
+#endif
+#else
+#include <lib/libkern/libkern.h>
+#endif
+
+#ifdef _LIBC
+__weak_alias(rb_tree_init, _rb_tree_init)
+__weak_alias(rb_tree_find_node, _rb_tree_find_node)
+__weak_alias(rb_tree_find_node_geq, _rb_tree_find_node_geq)
+__weak_alias(rb_tree_find_node_leq, _rb_tree_find_node_leq)
+__weak_alias(rb_tree_insert_node, _rb_tree_insert_node)
+__weak_alias(rb_tree_remove_node, _rb_tree_remove_node)
+__weak_alias(rb_tree_iterate, _rb_tree_iterate)
+#ifdef RBDEBUG
+__weak_alias(rb_tree_check, _rb_tree_check)
+__weak_alias(rb_tree_depths, _rb_tree_depths)
+#endif
+
+#define rb_tree_init _rb_tree_init
+#define rb_tree_find_node _rb_tree_find_node
+#define rb_tree_find_node_geq _rb_tree_find_node_geq
+#define rb_tree_find_node_leq _rb_tree_find_node_leq
+#define rb_tree_insert_node _rb_tree_insert_node
+#define rb_tree_remove_node _rb_tree_remove_node
+#define rb_tree_iterate _rb_tree_iterate
+#ifdef RBDEBUG
+#define rb_tree_check _rb_tree_check
+#define rb_tree_depths _rb_tree_depths
+#endif
+#endif
+
+#if defined(RBTEST) || defined(__APPLE__)
+#include "rb.h"
+#else
+#include <sys/rb.h>
+#endif
+
+#ifdef __APPLE__
+#define __predict_true(exp) __builtin_expect((exp), 1)
+#define __predict_false(exp) __builtin_expect((exp), 0)
+#endif
+
+static void rb_tree_insert_rebalance(struct rb_tree *, struct rb_node *);
+static void rb_tree_removal_rebalance(struct rb_tree *, struct rb_node *,
+ unsigned int);
+#ifdef RBDEBUG
+static const struct rb_node *rb_tree_iterate_const(const struct rb_tree *,
+ const struct rb_node *, const unsigned int);
+static bool rb_tree_check_node(const struct rb_tree *, const struct rb_node *,
+ const struct rb_node *, bool);
+#else
+#define rb_tree_check_node(a, b, c, d) true
+#endif
+
+#define RB_SENTINEL_NODE NULL
+
+void
+rb_tree_init(struct rb_tree *rbt, const struct rb_tree_ops *ops)
+{
+ rbt->rbt_ops = ops;
+ *((const struct rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE;
+ RB_TAILQ_INIT(&rbt->rbt_nodes);
+#ifndef RBSMALL
+ rbt->rbt_minmax[RB_DIR_LEFT] = rbt->rbt_root; /* minimum node */
+ rbt->rbt_minmax[RB_DIR_RIGHT] = rbt->rbt_root; /* maximum node */
+#endif
+ rbt->rbt_count = 0;
+#ifdef RBSTATS
+ rbt->rbt_insertions = 0;
+ rbt->rbt_removals = 0;
+ rbt->rbt_insertion_rebalance_calls = 0;
+ rbt->rbt_insertion_rebalance_passes = 0;
+ rbt->rbt_removal_rebalance_calls = 0;
+ rbt->rbt_removal_rebalance_passes = 0;
+#endif
+}
+
+struct rb_node *
+rb_tree_find_node(struct rb_tree *rbt, const void *key)
+{
+ rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
+ struct rb_node *parent = rbt->rbt_root;
+
+ while (!RB_SENTINEL_P(parent)) {
+ const signed int diff = (*compare_key)(parent, key);
+ if (diff == 0)
+ return parent;
+ parent = parent->rb_nodes[diff > 0];
+ }
+
+ return NULL;
+}
+
+struct rb_node *
+rb_tree_find_node_geq(struct rb_tree *rbt, const void *key)
+{
+ rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
+ struct rb_node *parent = rbt->rbt_root;
+ struct rb_node *last = NULL;
+
+ while (!RB_SENTINEL_P(parent)) {
+ const signed int diff = (*compare_key)(parent, key);
+ if (diff == 0)
+ return parent;
+ if (diff < 0)
+ last = parent;
+ parent = parent->rb_nodes[diff > 0];
+ }
+
+ return last;
+}
+
+struct rb_node *
+rb_tree_find_node_leq(struct rb_tree *rbt, const void *key)
+{
+ rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
+ struct rb_node *parent = rbt->rbt_root;
+ struct rb_node *last = NULL;
+
+ while (!RB_SENTINEL_P(parent)) {
+ const signed int diff = (*compare_key)(parent, key);
+ if (diff == 0)
+ return parent;
+ if (diff > 0)
+ last = parent;
+ parent = parent->rb_nodes[diff > 0];
+ }
+
+ return last;
+}
+\f
+bool
+rb_tree_insert_node(struct rb_tree *rbt, struct rb_node *self)
+{
+ rbto_compare_nodes_fn compare_nodes = rbt->rbt_ops->rbto_compare_nodes;
+ struct rb_node *parent, *tmp;
+ unsigned int position;
+ bool rebalance;
+
+ RBSTAT_INC(rbt->rbt_insertions);
+
+ tmp = rbt->rbt_root;
+ /*
+ * This is a hack. Because rbt->rbt_root is just a struct rb_node *,
+ * just like rb_node->rb_nodes[RB_DIR_LEFT], we can use this fact to
+ * avoid a lot of tests for root and know that even at root,
+ * updating RB_FATHER(rb_node)->rb_nodes[RB_POSITION(rb_node)] will
+ * update rbt->rbt_root.
+ */
+ parent = (struct rb_node *)(void *)&rbt->rbt_root;
+ position = RB_DIR_LEFT;
+
+ /*
+ * Find out where to place this new leaf.
+ */
+ while (!RB_SENTINEL_P(tmp)) {
+ const signed int diff = (*compare_nodes)(tmp, self);
+ if (__predict_false(diff == 0)) {
+ /*
+ * Node already exists; don't insert.
+ */
+ return false;
+ }
+ parent = tmp;
+ position = (diff > 0);
+ tmp = parent->rb_nodes[position];
+ }
+
+#ifdef RBDEBUG
+ {
+ struct rb_node *prev = NULL, *next = NULL;
+
+ if (position == RB_DIR_RIGHT)
+ prev = parent;
+ else if (tmp != rbt->rbt_root)
+ next = parent;
+
+ /*
+ * Verify our sequential position
+ */
+ KASSERT(prev == NULL || !RB_SENTINEL_P(prev));
+ KASSERT(next == NULL || !RB_SENTINEL_P(next));
+ if (prev != NULL && next == NULL)
+ next = TAILQ_NEXT(prev, rb_link);
+ if (prev == NULL && next != NULL)
+ prev = TAILQ_PREV(next, rb_node_qh, rb_link);
+ KASSERT(prev == NULL || !RB_SENTINEL_P(prev));
+ KASSERT(next == NULL || !RB_SENTINEL_P(next));
+ KASSERT(prev == NULL || (*compare_nodes)(prev, self) > 0);
+ KASSERT(next == NULL || (*compare_nodes)(self, next) > 0);
+ }
+#endif
+
+ /*
+ * Initialize the node and insert as a leaf into the tree.
+ */
+ RB_SET_FATHER(self, parent);
+ RB_SET_POSITION(self, position);
+ if (__predict_false(parent == (struct rb_node *)(void *)&rbt->rbt_root)) {
+ RB_MARK_BLACK(self); /* root is always black */
+#ifndef RBSMALL
+ rbt->rbt_minmax[RB_DIR_LEFT] = self;
+ rbt->rbt_minmax[RB_DIR_RIGHT] = self;
+#endif
+ rebalance = false;
+ } else {
+ KASSERT(position == RB_DIR_LEFT || position == RB_DIR_RIGHT);
+#ifndef RBSMALL
+ /*
+ * Keep track of the minimum and maximum nodes. If our
+ * parent is a minmax node and we on their min/max side,
+ * we must be the new min/max node.
+ */
+ if (parent == rbt->rbt_minmax[position])
+ rbt->rbt_minmax[position] = self;
+#endif /* !RBSMALL */
+ /*
+ * All new nodes are colored red. We only need to rebalance
+ * if our parent is also red.
+ */
+ RB_MARK_RED(self);
+ rebalance = RB_RED_P(parent);
+ }
+ KASSERT(RB_SENTINEL_P(parent->rb_nodes[position]));
+ self->rb_left = parent->rb_nodes[position];
+ self->rb_right = parent->rb_nodes[position];
+ parent->rb_nodes[position] = self;
+ KASSERT(RB_CHILDLESS_P(self));
+
+ /*
+ * Insert the new node into a sorted list for easy sequential access
+ */
+ rbt->rbt_count++;
+#ifdef RBDEBUG
+ if (RB_ROOT_P(rbt, self)) {
+ RB_TAILQ_INSERT_HEAD(&rbt->rbt_nodes, self, rb_link);
+ } else if (position == RB_DIR_LEFT) {
+ KASSERT((*compare_nodes)(self, RB_FATHER(self)) > 0);
+ RB_TAILQ_INSERT_BEFORE(RB_FATHER(self), self, rb_link);
+ } else {
+ KASSERT((*compare_nodes)(RB_FATHER(self), self) > 0);
+ RB_TAILQ_INSERT_AFTER(&rbt->rbt_nodes, RB_FATHER(self),
+ self, rb_link);
+ }
+#endif
+ KASSERT(rb_tree_check_node(rbt, self, NULL, !rebalance));
+
+ /*
+ * Rebalance tree after insertion
+ */
+ if (rebalance) {
+ rb_tree_insert_rebalance(rbt, self);
+ KASSERT(rb_tree_check_node(rbt, self, NULL, true));
+ }
+
+ return true;
+}
+\f
+/*
+ * Swap the location and colors of 'self' and its child @ which. The child
+ * can not be a sentinel node. This is our rotation function. However,
+ * since it preserves coloring, it great simplifies both insertion and
+ * removal since rotation almost always involves the exchanging of colors
+ * as a separate step.
+ */
+/*ARGSUSED*/
+static void
+rb_tree_reparent_nodes(struct rb_tree *rbt, struct rb_node *old_father,
+ const unsigned int which)
+{
+ const unsigned int other = which ^ RB_DIR_OTHER;
+ struct rb_node * const grandpa = RB_FATHER(old_father);
+ struct rb_node * const old_child = old_father->rb_nodes[which];
+ struct rb_node * const new_father = old_child;
+ struct rb_node * const new_child = old_father;
+
+ KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT);
+
+ KASSERT(!RB_SENTINEL_P(old_child));
+ KASSERT(RB_FATHER(old_child) == old_father);
+
+ KASSERT(rb_tree_check_node(rbt, old_father, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, old_child, NULL, false));
+ KASSERT(RB_ROOT_P(rbt, old_father) || rb_tree_check_node(rbt, grandpa, NULL, false));
+
+ /*
+ * Exchange descendant linkages.
+ */
+ grandpa->rb_nodes[RB_POSITION(old_father)] = new_father;
+ new_child->rb_nodes[which] = old_child->rb_nodes[other];
+ new_father->rb_nodes[other] = new_child;
+
+ /*
+ * Update ancestor linkages
+ */
+ RB_SET_FATHER(new_father, grandpa);
+ RB_SET_FATHER(new_child, new_father);
+
+ /*
+ * Exchange properties between new_father and new_child. The only
+ * change is that new_child's position is now on the other side.
+ */
+#if 0
+ {
+ struct rb_node tmp;
+ tmp.rb_info = 0;
+ RB_COPY_PROPERTIES(&tmp, old_child);
+ RB_COPY_PROPERTIES(new_father, old_father);
+ RB_COPY_PROPERTIES(new_child, &tmp);
+ }
+#else
+ RB_SWAP_PROPERTIES(new_father, new_child);
+#endif
+ RB_SET_POSITION(new_child, other);
+
+ /*
+ * Make sure to reparent the new child to ourself.
+ */
+ if (!RB_SENTINEL_P(new_child->rb_nodes[which])) {
+ RB_SET_FATHER(new_child->rb_nodes[which], new_child);
+ RB_SET_POSITION(new_child->rb_nodes[which], which);
+ }
+
+ KASSERT(rb_tree_check_node(rbt, new_father, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, new_child, NULL, false));
+ KASSERT(RB_ROOT_P(rbt, new_father) || rb_tree_check_node(rbt, grandpa, NULL, false));
+}
+\f
+static void
+rb_tree_insert_rebalance(struct rb_tree *rbt, struct rb_node *self)
+{
+ struct rb_node * father = RB_FATHER(self);
+ struct rb_node * grandpa;
+ struct rb_node * uncle;
+ unsigned int which;
+ unsigned int other;
+
+ KASSERT(!RB_ROOT_P(rbt, self));
+ KASSERT(RB_RED_P(self));
+ KASSERT(RB_RED_P(father));
+ RBSTAT_INC(rbt->rbt_insertion_rebalance_calls);
+
+ for (;;) {
+ KASSERT(!RB_SENTINEL_P(self));
+
+ KASSERT(RB_RED_P(self));
+ KASSERT(RB_RED_P(father));
+ /*
+ * We are red and our parent is red, therefore we must have a
+ * grandfather and he must be black.
+ */
+ grandpa = RB_FATHER(father);
+ KASSERT(RB_BLACK_P(grandpa));
+ KASSERT(RB_DIR_RIGHT == 1 && RB_DIR_LEFT == 0);
+ which = (father == grandpa->rb_right);
+ other = which ^ RB_DIR_OTHER;
+ uncle = grandpa->rb_nodes[other];
+
+ if (RB_BLACK_P(uncle))
+ break;
+
+ RBSTAT_INC(rbt->rbt_insertion_rebalance_passes);
+ /*
+ * Case 1: our uncle is red
+ * Simply invert the colors of our parent and
+ * uncle and make our grandparent red. And
+ * then solve the problem up at his level.
+ */
+ RB_MARK_BLACK(uncle);
+ RB_MARK_BLACK(father);
+ if (__predict_false(RB_ROOT_P(rbt, grandpa))) {
+ /*
+ * If our grandpa is root, don't bother
+ * setting him to red, just return.
+ */
+ KASSERT(RB_BLACK_P(grandpa));
+ return;
+ }
+ RB_MARK_RED(grandpa);
+ self = grandpa;
+ father = RB_FATHER(self);
+ KASSERT(RB_RED_P(self));
+ if (RB_BLACK_P(father)) {
+ /*
+ * If our greatgrandpa is black, we're done.
+ */
+ KASSERT(RB_BLACK_P(rbt->rbt_root));
+ return;
+ }
+ }
+
+ KASSERT(!RB_ROOT_P(rbt, self));
+ KASSERT(RB_RED_P(self));
+ KASSERT(RB_RED_P(father));
+ KASSERT(RB_BLACK_P(uncle));
+ KASSERT(RB_BLACK_P(grandpa));
+ /*
+ * Case 2&3: our uncle is black.
+ */
+ if (self == father->rb_nodes[other]) {
+ /*
+ * Case 2: we are on the same side as our uncle
+ * Swap ourselves with our parent so this case
+ * becomes case 3. Basically our parent becomes our
+ * child.
+ */
+ rb_tree_reparent_nodes(rbt, father, other);
+ KASSERT(RB_FATHER(father) == self);
+ KASSERT(self->rb_nodes[which] == father);
+ KASSERT(RB_FATHER(self) == grandpa);
+#ifdef RBDEBUG
+ // only read when RBDEBUG is enabled with KASSERT
+ self = father;
+ father = RB_FATHER(self);
+#endif
+ }
+ KASSERT(RB_RED_P(self) && RB_RED_P(father));
+ KASSERT(grandpa->rb_nodes[which] == father);
+ /*
+ * Case 3: we are opposite a child of a black uncle.
+ * Swap our parent and grandparent. Since our grandfather
+ * is black, our father will become black and our new sibling
+ * (former grandparent) will become red.
+ */
+ rb_tree_reparent_nodes(rbt, grandpa, which);
+ KASSERT(RB_FATHER(self) == father);
+ KASSERT(RB_FATHER(self)->rb_nodes[RB_POSITION(self) ^ RB_DIR_OTHER] == grandpa);
+ KASSERT(RB_RED_P(self));
+ KASSERT(RB_BLACK_P(father));
+ KASSERT(RB_RED_P(grandpa));
+
+ /*
+ * Final step: Set the root to black.
+ */
+ RB_MARK_BLACK(rbt->rbt_root);
+}
+\f
+static void
+rb_tree_prune_node(struct rb_tree *rbt, struct rb_node *self, bool rebalance)
+{
+ const unsigned int which = RB_POSITION(self);
+ struct rb_node *father = RB_FATHER(self);
+ const bool was_root = RB_ROOT_P(rbt, self);
+
+ KASSERT(rebalance || (RB_ROOT_P(rbt, self) || RB_RED_P(self)));
+ KASSERT(!rebalance || RB_BLACK_P(self));
+ KASSERT(RB_CHILDLESS_P(self));
+ KASSERT(rb_tree_check_node(rbt, self, NULL, false));
+
+ /*
+ * Since we are childless, we know that self->rb_left is pointing
+ * to the sentinel node.
+ */
+ father->rb_nodes[which] = self->rb_left;
+
+ /*
+ * Remove ourselves from the node list, decrement the count,
+ * and update min/max.
+ */
+ RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link);
+ rbt->rbt_count--;
+#ifndef RBSMALL
+ if (__predict_false(rbt->rbt_minmax[RB_POSITION(self)] == self)) {
+ rbt->rbt_minmax[RB_POSITION(self)] = father;
+ /*
+ * When removing the root, rbt->rbt_minmax[RB_DIR_LEFT] is
+ * updated automatically, but we also need to update
+ * rbt->rbt_minmax[RB_DIR_RIGHT];
+ */
+ if (__predict_false(was_root)) {
+ rbt->rbt_minmax[RB_DIR_RIGHT] = father;
+ }
+ }
+ RB_SET_FATHER(self, NULL);
+#endif
+
+ /*
+ * Rebalance if requested.
+ */
+ if (rebalance)
+ rb_tree_removal_rebalance(rbt, father, which);
+ KASSERT(was_root || rb_tree_check_node(rbt, father, NULL, true));
+}
+\f
+/*
+ * When deleting an interior node
+ */
+static void
+rb_tree_swap_prune_and_rebalance(struct rb_tree *rbt, struct rb_node *self,
+ struct rb_node *standin)
+{
+ const unsigned int standin_which = RB_POSITION(standin);
+ unsigned int standin_other = standin_which ^ RB_DIR_OTHER;
+ struct rb_node *standin_son;
+ struct rb_node *standin_father = RB_FATHER(standin);
+ bool rebalance = RB_BLACK_P(standin);
+
+ if (standin_father == self) {
+ /*
+ * As a child of self, any childen would be opposite of
+ * our parent.
+ */
+ KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_other]));
+ standin_son = standin->rb_nodes[standin_which];
+ } else {
+ /*
+ * Since we aren't a child of self, any childen would be
+ * on the same side as our parent.
+ */
+ KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_which]));
+ standin_son = standin->rb_nodes[standin_other];
+ }
+
+ /*
+ * the node we are removing must have two children.
+ */
+ KASSERT(RB_TWOCHILDREN_P(self));
+ /*
+ * If standin has a child, it must be red.
+ */
+ KASSERT(RB_SENTINEL_P(standin_son) || RB_RED_P(standin_son));
+
+ /*
+ * Verify things are sane.
+ */
+ KASSERT(rb_tree_check_node(rbt, self, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, standin, NULL, false));
+
+ if (__predict_false(RB_RED_P(standin_son))) {
+ /*
+ * We know we have a red child so if we flip it to black
+ * we don't have to rebalance.
+ */
+ KASSERT(rb_tree_check_node(rbt, standin_son, NULL, true));
+ RB_MARK_BLACK(standin_son);
+ rebalance = false;
+
+ if (standin_father == self) {
+ KASSERT(RB_POSITION(standin_son) == standin_which);
+ } else {
+ KASSERT(RB_POSITION(standin_son) == standin_other);
+ /*
+ * Change the son's parentage to point to his grandpa.
+ */
+ RB_SET_FATHER(standin_son, standin_father);
+ RB_SET_POSITION(standin_son, standin_which);
+ }
+ }
+
+ if (standin_father == self) {
+ /*
+ * If we are about to delete the standin's father, then when
+ * we call rebalance, we need to use ourselves as our father.
+ * Otherwise remember our original father. Also, sincef we are
+ * our standin's father we only need to reparent the standin's
+ * brother.
+ *
+ * | R --> S |
+ * | Q S --> Q T |
+ * | t --> |
+ */
+ KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_other]));
+ KASSERT(!RB_SENTINEL_P(self->rb_nodes[standin_other]));
+ KASSERT(self->rb_nodes[standin_which] == standin);
+ /*
+ * Have our son/standin adopt his brother as his new son.
+ */
+ standin_father = standin;
+ } else {
+ /*
+ * | R --> S . |
+ * | / \ | T --> / \ | / |
+ * | ..... | S --> ..... | T |
+ *
+ * Sever standin's connection to his father.
+ */
+ standin_father->rb_nodes[standin_which] = standin_son;
+ /*
+ * Adopt the far son.
+ */
+ standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
+ RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
+ KASSERT(RB_POSITION(self->rb_nodes[standin_other]) == standin_other);
+ /*
+ * Use standin_other because we need to preserve standin_which
+ * for the removal_rebalance.
+ */
+ standin_other = standin_which;
+ }
+
+ /*
+ * Move the only remaining son to our standin. If our standin is our
+ * son, this will be the only son needed to be moved.
+ */
+ KASSERT(standin->rb_nodes[standin_other] != self->rb_nodes[standin_other]);
+ standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
+ RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
+
+ /*
+ * Now copy the result of self to standin and then replace
+ * self with standin in the tree.
+ */
+ RB_COPY_PROPERTIES(standin, self);
+ RB_SET_FATHER(standin, RB_FATHER(self));
+ RB_FATHER(standin)->rb_nodes[RB_POSITION(standin)] = standin;
+
+ /*
+ * Remove ourselves from the node list, decrement the count,
+ * and update min/max.
+ */
+ RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link);
+ rbt->rbt_count--;
+#ifndef RBSMALL
+ if (__predict_false(rbt->rbt_minmax[RB_POSITION(self)] == self))
+ rbt->rbt_minmax[RB_POSITION(self)] = RB_FATHER(self);
+ RB_SET_FATHER(self, NULL);
+#endif
+
+ KASSERT(rb_tree_check_node(rbt, standin, NULL, false));
+ KASSERT(RB_FATHER_SENTINEL_P(standin)
+ || rb_tree_check_node(rbt, standin_father, NULL, false));
+ KASSERT(RB_LEFT_SENTINEL_P(standin)
+ || rb_tree_check_node(rbt, standin->rb_left, NULL, false));
+ KASSERT(RB_RIGHT_SENTINEL_P(standin)
+ || rb_tree_check_node(rbt, standin->rb_right, NULL, false));
+
+ if (!rebalance)
+ return;
+
+ rb_tree_removal_rebalance(rbt, standin_father, standin_which);
+ KASSERT(rb_tree_check_node(rbt, standin, NULL, true));
+}
+
+/*
+ * We could do this by doing
+ * rb_tree_node_swap(rbt, self, which);
+ * rb_tree_prune_node(rbt, self, false);
+ *
+ * But it's more efficient to just evalate and recolor the child.
+ */
+static void
+rb_tree_prune_blackred_branch(struct rb_tree *rbt, struct rb_node *self,
+ unsigned int which)
+{
+ struct rb_node *father = RB_FATHER(self);
+ struct rb_node *son = self->rb_nodes[which];
+ const bool was_root = RB_ROOT_P(rbt, self);
+
+ KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT);
+ KASSERT(RB_BLACK_P(self) && RB_RED_P(son));
+ KASSERT(!RB_TWOCHILDREN_P(son));
+ KASSERT(RB_CHILDLESS_P(son));
+ KASSERT(rb_tree_check_node(rbt, self, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, son, NULL, false));
+
+ /*
+ * Remove ourselves from the tree and give our former child our
+ * properties (position, color, root).
+ */
+ RB_COPY_PROPERTIES(son, self);
+ father->rb_nodes[RB_POSITION(son)] = son;
+ RB_SET_FATHER(son, father);
+
+ /*
+ * Remove ourselves from the node list, decrement the count,
+ * and update minmax.
+ */
+ RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link);
+ rbt->rbt_count--;
+#ifndef RBSMALL
+ if (__predict_false(was_root)) {
+ KASSERT(rbt->rbt_minmax[which] == son);
+ rbt->rbt_minmax[which ^ RB_DIR_OTHER] = son;
+ } else if (rbt->rbt_minmax[RB_POSITION(self)] == self) {
+ rbt->rbt_minmax[RB_POSITION(self)] = son;
+ }
+ RB_SET_FATHER(self, NULL);
+#endif
+
+ KASSERT(was_root || rb_tree_check_node(rbt, father, NULL, true));
+ KASSERT(rb_tree_check_node(rbt, son, NULL, true));
+}
+/*
+ *
+ */
+void
+rb_tree_remove_node(struct rb_tree *rbt, struct rb_node *self)
+{
+ struct rb_node *standin;
+ unsigned int which;
+
+ KASSERT(!RB_SENTINEL_P(self));
+ RBSTAT_INC(rbt->rbt_removals);
+
+ /*
+ * In the following diagrams, we (the node to be removed) are S. Red
+ * nodes are lowercase. T could be either red or black.
+ *
+ * Remember the major axiom of the red-black tree: the number of
+ * black nodes from the root to each leaf is constant across all
+ * leaves, only the number of red nodes varies.
+ *
+ * Thus removing a red leaf doesn't require any other changes to a
+ * red-black tree. So if we must remove a node, attempt to rearrange
+ * the tree so we can remove a red node.
+ *
+ * The simpliest case is a childless red node or a childless root node:
+ *
+ * | T --> T | or | R --> * |
+ * | s --> * |
+ */
+ if (RB_CHILDLESS_P(self)) {
+ const bool rebalance = RB_BLACK_P(self) && !RB_ROOT_P(rbt, self);
+ rb_tree_prune_node(rbt, self, rebalance);
+ return;
+ }
+ KASSERT(!RB_CHILDLESS_P(self));
+ if (!RB_TWOCHILDREN_P(self)) {
+ /*
+ * The next simpliest case is the node we are deleting is
+ * black and has one red child.
+ *
+ * | T --> T --> T |
+ * | S --> R --> R |
+ * | r --> s --> * |
+ */
+ which = RB_LEFT_SENTINEL_P(self) ? RB_DIR_RIGHT : RB_DIR_LEFT;
+ KASSERT(RB_BLACK_P(self));
+ KASSERT(RB_RED_P(self->rb_nodes[which]));
+ KASSERT(RB_CHILDLESS_P(self->rb_nodes[which]));
+ rb_tree_prune_blackred_branch(rbt, self, which);
+ return;
+ }
+ KASSERT(RB_TWOCHILDREN_P(self));
+
+ /*
+ * We invert these because we prefer to remove from the inside of
+ * the tree.
+ */
+ which = RB_POSITION(self) ^ RB_DIR_OTHER;
+
+ /*
+ * Let's find the node closes to us opposite of our parent
+ * Now swap it with ourself, "prune" it, and rebalance, if needed.
+ */
+ standin = rb_tree_iterate(rbt, self, which);
+ rb_tree_swap_prune_and_rebalance(rbt, self, standin);
+}
+
+static void
+rb_tree_removal_rebalance(struct rb_tree *rbt, struct rb_node *parent,
+ unsigned int which)
+{
+ KASSERT(!RB_SENTINEL_P(parent));
+ KASSERT(RB_SENTINEL_P(parent->rb_nodes[which]));
+ KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT);
+ RBSTAT_INC(rbt->rbt_removal_rebalance_calls);
+
+ while (RB_BLACK_P(parent->rb_nodes[which])) {
+ unsigned int other = which ^ RB_DIR_OTHER;
+ struct rb_node *brother = parent->rb_nodes[other];
+
+ RBSTAT_INC(rbt->rbt_removal_rebalance_passes);
+
+ KASSERT(!RB_SENTINEL_P(brother));
+ /*
+ * For cases 1, 2a, and 2b, our brother's children must
+ * be black and our father must be black
+ */
+ if (RB_BLACK_P(parent)
+ && RB_BLACK_P(brother->rb_left)
+ && RB_BLACK_P(brother->rb_right)) {
+ if (RB_RED_P(brother)) {
+ /*
+ * Case 1: Our brother is red, swap its
+ * position (and colors) with our parent.
+ * This should now be case 2b (unless C or E
+ * has a red child which is case 3; thus no
+ * explicit branch to case 2b).
+ *
+ * B -> D
+ * A d -> b E
+ * C E -> A C
+ */
+ KASSERT(RB_BLACK_P(parent));
+ rb_tree_reparent_nodes(rbt, parent, other);
+ brother = parent->rb_nodes[other];
+ KASSERT(!RB_SENTINEL_P(brother));
+ KASSERT(RB_RED_P(parent));
+ KASSERT(RB_BLACK_P(brother));
+ KASSERT(rb_tree_check_node(rbt, brother, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, parent, NULL, false));
+ } else {
+ /*
+ * Both our parent and brother are black.
+ * Change our brother to red, advance up rank
+ * and go through the loop again.
+ *
+ * B -> *B
+ * *A D -> A d
+ * C E -> C E
+ */
+ RB_MARK_RED(brother);
+ KASSERT(RB_BLACK_P(brother->rb_left));
+ KASSERT(RB_BLACK_P(brother->rb_right));
+ if (RB_ROOT_P(rbt, parent))
+ return; /* root == parent == black */
+ KASSERT(rb_tree_check_node(rbt, brother, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, parent, NULL, false));
+ if (parent != NULL) {
+ which = RB_POSITION(parent);
+ parent = RB_FATHER(parent);
+ }
+ continue;
+ }
+ }
+ /*
+ * Avoid an else here so that case 2a above can hit either
+ * case 2b, 3, or 4.
+ */
+ if (RB_RED_P(parent)
+ && (RB_SENTINEL_P(brother)
+ || (RB_BLACK_P(brother)
+ && RB_BLACK_P(brother->rb_left)
+ && RB_BLACK_P(brother->rb_right)))) {
+ KASSERT(RB_RED_P(parent));
+ KASSERT(RB_BLACK_P(brother));
+ KASSERT(RB_BLACK_P(brother->rb_left));
+ KASSERT(RB_BLACK_P(brother->rb_right));
+ /*
+ * We are black, our father is red, our brother and
+ * both nephews are black. Simply invert/exchange the
+ * colors of our father and brother (to black and red
+ * respectively).
+ *
+ * | f --> F |
+ * | * B --> * b |
+ * | N N --> N N |
+ */
+ RB_MARK_BLACK(parent);
+ if (!RB_SENTINEL_P(brother)) {
+ RB_MARK_RED(brother);
+ }
+ KASSERT(rb_tree_check_node(rbt, brother, NULL, true));
+ break; /* We're done! */
+ } else {
+ /*
+ * Our brother must be black and have at least one
+ * red child (it may have two).
+ */
+ KASSERT(RB_BLACK_P(brother));
+ KASSERT(RB_RED_P(brother->rb_nodes[which]) ||
+ RB_RED_P(brother->rb_nodes[other]));
+ if (RB_BLACK_P(brother->rb_nodes[other])) {
+ /*
+ * Case 3: our brother is black, our near
+ * nephew is red, and our far nephew is black.
+ * Swap our brother with our near nephew.
+ * This result in a tree that matches case 4.
+ * (Our father could be red or black).
+ *
+ * | F --> F |
+ * | x B --> x B |
+ * | n --> n |
+ */
+ KASSERT(RB_RED_P(brother->rb_nodes[which]));
+ rb_tree_reparent_nodes(rbt, brother, which);
+ KASSERT(RB_FATHER(brother) == parent->rb_nodes[other]);
+ brother = parent->rb_nodes[other];
+ KASSERT(RB_RED_P(brother->rb_nodes[other]));
+ }
+ /*
+ * Case 4: our brother is black and our far nephew
+ * is red. Swap our father and brother locations and
+ * change our far nephew to black. (these can be
+ * done in either order so we change the color first).
+ * The result is a valid red-black tree and is a
+ * terminal case. (again we don't care about the
+ * father's color)
+ *
+ * If the father is red, we will get a red-black-black
+ * tree:
+ * | f -> f --> b |
+ * | B -> B --> F N |
+ * | n -> N --> |
+ *
+ * If the father is black, we will get an all black
+ * tree:
+ * | F -> F --> B |
+ * | B -> B --> F N |
+ * | n -> N --> |
+ *
+ * If we had two red nephews, then after the swap,
+ * our former father would have a red grandson.
+ */
+ KASSERT(RB_BLACK_P(brother));
+ KASSERT(RB_RED_P(brother->rb_nodes[other]));
+ RB_MARK_BLACK(brother->rb_nodes[other]);
+ rb_tree_reparent_nodes(rbt, parent, other);
+ break; /* We're done! */
+ }
+ }
+ KASSERT(rb_tree_check_node(rbt, parent, NULL, true));
+}
+
+struct rb_node *
+rb_tree_iterate(struct rb_tree *rbt, struct rb_node *self,
+ const unsigned int direction)
+{
+ const unsigned int other = direction ^ RB_DIR_OTHER;
+ KASSERT(direction == RB_DIR_LEFT || direction == RB_DIR_RIGHT);
+
+ if (self == NULL) {
+#ifndef RBSMALL
+ if (RB_SENTINEL_P(rbt->rbt_root))
+ return NULL;
+ return rbt->rbt_minmax[direction];
+#else
+ self = rbt->rbt_root;
+ if (RB_SENTINEL_P(self))
+ return NULL;
+ while (!RB_SENTINEL_P(self->rb_nodes[other]))
+ self = self->rb_nodes[other];
+ return self;
+#endif /* !RBSMALL */
+ }
+ KASSERT(!RB_SENTINEL_P(self));
+ /*
+ * We can't go any further in this direction. We proceed up in the
+ * opposite direction until our parent is in direction we want to go.
+ */
+ if (RB_SENTINEL_P(self->rb_nodes[direction])) {
+ while (!RB_ROOT_P(rbt, self)) {
+ if (other == RB_POSITION(self))
+ return RB_FATHER(self);
+ self = RB_FATHER(self);
+ }
+ return NULL;
+ }
+
+ /*
+ * Advance down one in current direction and go down as far as possible
+ * in the opposite direction.
+ */
+ self = self->rb_nodes[direction];
+ KASSERT(!RB_SENTINEL_P(self));
+ while (!RB_SENTINEL_P(self->rb_nodes[other]))
+ self = self->rb_nodes[other];
+ return self;
+}
+
+#ifdef RBDEBUG
+static const struct rb_node *
+rb_tree_iterate_const(const struct rb_tree *rbt, const struct rb_node *self,
+ const unsigned int direction)
+{
+ const unsigned int other = direction ^ RB_DIR_OTHER;
+ KASSERT(direction == RB_DIR_LEFT || direction == RB_DIR_RIGHT);
+
+ if (self == NULL) {
+#ifndef RBSMALL
+ if (RB_SENTINEL_P(rbt->rbt_root))
+ return NULL;
+ return rbt->rbt_minmax[direction];
+#else
+ self = rbt->rbt_root;
+ if (RB_SENTINEL_P(self))
+ return NULL;
+ while (!RB_SENTINEL_P(self->rb_nodes[other]))
+ self = self->rb_nodes[other];
+ return self;
+#endif /* !RBSMALL */
+ }
+ KASSERT(!RB_SENTINEL_P(self));
+ /*
+ * We can't go any further in this direction. We proceed up in the
+ * opposite direction until our parent is in direction we want to go.
+ */
+ if (RB_SENTINEL_P(self->rb_nodes[direction])) {
+ while (!RB_ROOT_P(rbt, self)) {
+ if (other == RB_POSITION(self))
+ return RB_FATHER(self);
+ self = RB_FATHER(self);
+ }
+ return NULL;
+ }
+
+ /*
+ * Advance down one in current direction and go down as far as possible
+ * in the opposite direction.
+ */
+ self = self->rb_nodes[direction];
+ KASSERT(!RB_SENTINEL_P(self));
+ while (!RB_SENTINEL_P(self->rb_nodes[other]))
+ self = self->rb_nodes[other];
+ return self;
+}
+
+static unsigned int
+rb_tree_count_black(const struct rb_node *self)
+{
+ unsigned int left, right;
+
+ if (RB_SENTINEL_P(self))
+ return 0;
+
+ left = rb_tree_count_black(self->rb_left);
+ right = rb_tree_count_black(self->rb_right);
+
+ KASSERT(left == right);
+
+ return left + RB_BLACK_P(self);
+}
+
+static bool
+rb_tree_check_node(const struct rb_tree *rbt, const struct rb_node *self,
+ const struct rb_node *prev, bool red_check)
+{
+ rbto_compare_nodes_fn compare_nodes = rbt->rbt_ops->rbto_compare_nodes;
+
+ KASSERT(!RB_SENTINEL_P(self));
+ KASSERT(prev == NULL || (*compare_nodes)(prev, self) > 0);
+
+ /*
+ * Verify our relationship to our parent.
+ */
+ if (RB_ROOT_P(rbt, self)) {
+ KASSERT(self == rbt->rbt_root);
+ KASSERT(RB_POSITION(self) == RB_DIR_LEFT);
+ KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_LEFT] == self);
+ KASSERT(RB_FATHER(self) == (const struct rb_node *) &rbt->rbt_root);
+ } else {
+ KASSERT(self != rbt->rbt_root);
+ KASSERT(!RB_FATHER_SENTINEL_P(self));
+ if (RB_POSITION(self) == RB_DIR_LEFT) {
+ KASSERT((*compare_nodes)(self, RB_FATHER(self)) > 0);
+ KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_LEFT] == self);
+ } else {
+ KASSERT((*compare_nodes)(self, RB_FATHER(self)) < 0);
+ KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_RIGHT] == self);
+ }
+ }
+
+ /*
+ * Verify our position in the linked list against the tree itself.
+ */
+ {
+ const struct rb_node *prev0 = rb_tree_iterate_const(rbt, self, RB_DIR_LEFT);
+ const struct rb_node *next0 = rb_tree_iterate_const(rbt, self, RB_DIR_RIGHT);
+ KASSERT(prev0 == TAILQ_PREV(self, rb_node_qh, rb_link));
+ KASSERT(next0 == TAILQ_NEXT(self, rb_link));
+#ifndef RBSMALL
+ KASSERT(prev0 != NULL || self == rbt->rbt_minmax[RB_DIR_LEFT]);
+ KASSERT(next0 != NULL || self == rbt->rbt_minmax[RB_DIR_RIGHT]);
+#endif
+ }
+
+ /*
+ * The root must be black.
+ * There can never be two adjacent red nodes.
+ */
+ if (red_check) {
+ KASSERT(!RB_ROOT_P(rbt, self) || RB_BLACK_P(self));
+ (void) rb_tree_count_black(self);
+ if (RB_RED_P(self)) {
+ const struct rb_node *brother;
+ KASSERT(!RB_ROOT_P(rbt, self));
+ brother = RB_FATHER(self)->rb_nodes[RB_POSITION(self) ^ RB_DIR_OTHER];
+ KASSERT(RB_BLACK_P(RB_FATHER(self)));
+ /*
+ * I'm red and have no children, then I must either
+ * have no brother or my brother also be red and
+ * also have no children. (black count == 0)
+ */
+ KASSERT(!RB_CHILDLESS_P(self)
+ || RB_SENTINEL_P(brother)
+ || RB_RED_P(brother)
+ || RB_CHILDLESS_P(brother));
+ /*
+ * If I'm not childless, I must have two children
+ * and they must be both be black.
+ */
+ KASSERT(RB_CHILDLESS_P(self)
+ || (RB_TWOCHILDREN_P(self)
+ && RB_BLACK_P(self->rb_left)
+ && RB_BLACK_P(self->rb_right)));
+ /*
+ * If I'm not childless, thus I have black children,
+ * then my brother must either be black or have two
+ * black children.
+ */
+ KASSERT(RB_CHILDLESS_P(self)
+ || RB_BLACK_P(brother)
+ || (RB_TWOCHILDREN_P(brother)
+ && RB_BLACK_P(brother->rb_left)
+ && RB_BLACK_P(brother->rb_right)));
+ } else {
+ /*
+ * If I'm black and have one child, that child must
+ * be red and childless.
+ */
+ KASSERT(RB_CHILDLESS_P(self)
+ || RB_TWOCHILDREN_P(self)
+ || (!RB_LEFT_SENTINEL_P(self)
+ && RB_RIGHT_SENTINEL_P(self)
+ && RB_RED_P(self->rb_left)
+ && RB_CHILDLESS_P(self->rb_left))
+ || (!RB_RIGHT_SENTINEL_P(self)
+ && RB_LEFT_SENTINEL_P(self)
+ && RB_RED_P(self->rb_right)
+ && RB_CHILDLESS_P(self->rb_right)));
+
+ /*
+ * If I'm a childless black node and my parent is
+ * black, my 2nd closet relative away from my parent
+ * is either red or has a red parent or red children.
+ */
+ if (!RB_ROOT_P(rbt, self)
+ && RB_CHILDLESS_P(self)
+ && RB_BLACK_P(RB_FATHER(self))) {
+ const unsigned int which = RB_POSITION(self);
+ const unsigned int other = which ^ RB_DIR_OTHER;
+ const struct rb_node *relative0, *relative;
+
+ relative0 = rb_tree_iterate_const(rbt,
+ self, other);
+ KASSERT(relative0 != NULL);
+ relative = rb_tree_iterate_const(rbt,
+ relative0, other);
+ KASSERT(relative != NULL);
+ KASSERT(RB_SENTINEL_P(relative->rb_nodes[which]));
+#if 0
+ KASSERT(RB_RED_P(relative)
+ || RB_RED_P(relative->rb_left)
+ || RB_RED_P(relative->rb_right)
+ || RB_RED_P(RB_FATHER(relative)));
+#endif
+ }
+ }
+ /*
+ * A grandparent's children must be real nodes and not
+ * sentinels. First check out grandparent.
+ */
+ KASSERT(RB_ROOT_P(rbt, self)
+ || RB_ROOT_P(rbt, RB_FATHER(self))
+ || RB_TWOCHILDREN_P(RB_FATHER(RB_FATHER(self))));
+ /*
+ * If we are have grandchildren on our left, then
+ * we must have a child on our right.
+ */
+ KASSERT(RB_LEFT_SENTINEL_P(self)
+ || RB_CHILDLESS_P(self->rb_left)
+ || !RB_RIGHT_SENTINEL_P(self));
+ /*
+ * If we are have grandchildren on our right, then
+ * we must have a child on our left.
+ */
+ KASSERT(RB_RIGHT_SENTINEL_P(self)
+ || RB_CHILDLESS_P(self->rb_right)
+ || !RB_LEFT_SENTINEL_P(self));
+
+ /*
+ * If we have a child on the left and it doesn't have two
+ * children make sure we don't have great-great-grandchildren on
+ * the right.
+ */
+ KASSERT(RB_TWOCHILDREN_P(self->rb_left)
+ || RB_CHILDLESS_P(self->rb_right)
+ || RB_CHILDLESS_P(self->rb_right->rb_left)
+ || RB_CHILDLESS_P(self->rb_right->rb_left->rb_left)
+ || RB_CHILDLESS_P(self->rb_right->rb_left->rb_right)
+ || RB_CHILDLESS_P(self->rb_right->rb_right)
+ || RB_CHILDLESS_P(self->rb_right->rb_right->rb_left)
+ || RB_CHILDLESS_P(self->rb_right->rb_right->rb_right));
+
+ /*
+ * If we have a child on the right and it doesn't have two
+ * children make sure we don't have great-great-grandchildren on
+ * the left.
+ */
+ KASSERT(RB_TWOCHILDREN_P(self->rb_right)
+ || RB_CHILDLESS_P(self->rb_left)
+ || RB_CHILDLESS_P(self->rb_left->rb_left)
+ || RB_CHILDLESS_P(self->rb_left->rb_left->rb_left)
+ || RB_CHILDLESS_P(self->rb_left->rb_left->rb_right)
+ || RB_CHILDLESS_P(self->rb_left->rb_right)
+ || RB_CHILDLESS_P(self->rb_left->rb_right->rb_left)
+ || RB_CHILDLESS_P(self->rb_left->rb_right->rb_right));
+
+ /*
+ * If we are fully interior node, then our predecessors and
+ * successors must have no children in our direction.
+ */
+ if (RB_TWOCHILDREN_P(self)) {
+ const struct rb_node *prev0;
+ const struct rb_node *next0;
+
+ prev0 = rb_tree_iterate_const(rbt, self, RB_DIR_LEFT);
+ KASSERT(prev0 != NULL);
+ KASSERT(RB_RIGHT_SENTINEL_P(prev0));
+
+ next0 = rb_tree_iterate_const(rbt, self, RB_DIR_RIGHT);
+ KASSERT(next0 != NULL);
+ KASSERT(RB_LEFT_SENTINEL_P(next0));
+ }
+ }
+
+ return true;
+}
+
+void
+rb_tree_check(const struct rb_tree *rbt, bool red_check)
+{
+ const struct rb_node *self;
+ const struct rb_node *prev;
+#ifdef RBSTATS
+ unsigned int count = 0;
+#endif
+
+ KASSERT(rbt->rbt_root != NULL);
+ KASSERT(RB_LEFT_P(rbt->rbt_root));
+
+#if defined(RBSTATS) && !defined(RBSMALL)
+ KASSERT(rbt->rbt_count > 1
+ || rbt->rbt_minmax[RB_DIR_LEFT] == rbt->rbt_minmax[RB_DIR_RIGHT]);
+#endif
+
+ prev = NULL;
+ TAILQ_FOREACH(self, &rbt->rbt_nodes, rb_link) {
+ rb_tree_check_node(rbt, self, prev, false);
+#ifdef RBSTATS
+ count++;
+#endif
+ }
+#ifdef RBSTATS
+ KASSERT(rbt->rbt_count == count);
+#endif
+ if (red_check) {
+ KASSERT(RB_BLACK_P(rbt->rbt_root));
+ KASSERT(RB_SENTINEL_P(rbt->rbt_root)
+ || rb_tree_count_black(rbt->rbt_root));
+
+ /*
+ * The root must be black.
+ * There can never be two adjacent red nodes.
+ */
+ TAILQ_FOREACH(self, &rbt->rbt_nodes, rb_link) {
+ rb_tree_check_node(rbt, self, NULL, true);
+ }
+ }
+}
+#endif /* RBDEBUG */
+
+#ifdef RBSTATS
+static void
+rb_tree_mark_depth(const struct rb_tree *rbt, const struct rb_node *self,
+ size_t *depths, size_t depth)
+{
+ if (RB_SENTINEL_P(self))
+ return;
+
+ if (RB_TWOCHILDREN_P(self)) {
+ rb_tree_mark_depth(rbt, self->rb_left, depths, depth + 1);
+ rb_tree_mark_depth(rbt, self->rb_right, depths, depth + 1);
+ return;
+ }
+ depths[depth]++;
+ if (!RB_LEFT_SENTINEL_P(self)) {
+ rb_tree_mark_depth(rbt, self->rb_left, depths, depth + 1);
+ }
+ if (!RB_RIGHT_SENTINEL_P(self)) {
+ rb_tree_mark_depth(rbt, self->rb_right, depths, depth + 1);
+ }
+}
+
+void
+rb_tree_depths(const struct rb_tree *rbt, size_t *depths)
+{
+ rb_tree_mark_depth(rbt, rbt->rbt_root, depths, 1);
+}
+#endif /* RBSTATS */
--- /dev/null
+/* $NetBSD: rb.h,v 1.13 2009/08/16 10:57:01 yamt Exp $ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt@3am-software.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _SYS_RB_H_
+#define _SYS_RB_H_
+
+#if defined(_KERNEL) || defined(_STANDALONE)
+#include <sys/types.h>
+#else
+#include <stdbool.h>
+#include <inttypes.h>
+#endif
+#include <sys/queue.h>
+#ifndef __APPLE__
+#include <sys/endian.h>
+#endif
+
+struct rb_node {
+ struct rb_node *rb_nodes[2];
+#define RB_DIR_LEFT 0
+#define RB_DIR_RIGHT 1
+#define RB_DIR_OTHER 1
+#define rb_left rb_nodes[RB_DIR_LEFT]
+#define rb_right rb_nodes[RB_DIR_RIGHT]
+
+ /*
+ * rb_info contains the two flags and the parent back pointer.
+ * We put the two flags in the low two bits since we know that
+ * rb_node will have an alignment of 4 or 8 bytes.
+ */
+ uintptr_t rb_info;
+#define RB_FLAG_POSITION 0x2
+#define RB_FLAG_RED 0x1
+#define RB_FLAG_MASK (RB_FLAG_POSITION|RB_FLAG_RED)
+#define RB_FATHER(rb) \
+ ((struct rb_node *)((rb)->rb_info & ~RB_FLAG_MASK))
+#define RB_SET_FATHER(rb, father) \
+ ((void)((rb)->rb_info = (uintptr_t)(father)|((rb)->rb_info & RB_FLAG_MASK)))
+
+#define RB_SENTINEL_P(rb) ((rb) == NULL)
+#define RB_LEFT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_left)
+#define RB_RIGHT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_right)
+#define RB_FATHER_SENTINEL_P(rb) RB_SENTINEL_P(RB_FATHER((rb)))
+#define RB_CHILDLESS_P(rb) \
+ (RB_SENTINEL_P(rb) || (RB_LEFT_SENTINEL_P(rb) && RB_RIGHT_SENTINEL_P(rb)))
+#define RB_TWOCHILDREN_P(rb) \
+ (!RB_SENTINEL_P(rb) && !RB_LEFT_SENTINEL_P(rb) && !RB_RIGHT_SENTINEL_P(rb))
+
+#define RB_POSITION(rb) \
+ (((rb)->rb_info & RB_FLAG_POSITION) ? RB_DIR_RIGHT : RB_DIR_LEFT)
+#define RB_RIGHT_P(rb) (RB_POSITION(rb) == RB_DIR_RIGHT)
+#define RB_LEFT_P(rb) (RB_POSITION(rb) == RB_DIR_LEFT)
+#define RB_RED_P(rb) (!RB_SENTINEL_P(rb) && ((rb)->rb_info & RB_FLAG_RED) != 0)
+#define RB_BLACK_P(rb) (RB_SENTINEL_P(rb) || ((rb)->rb_info & RB_FLAG_RED) == 0)
+#define RB_MARK_RED(rb) ((void)((rb)->rb_info |= RB_FLAG_RED))
+#define RB_MARK_BLACK(rb) ((void)((rb)->rb_info &= ~RB_FLAG_RED))
+#define RB_INVERT_COLOR(rb) ((void)((rb)->rb_info ^= RB_FLAG_RED))
+#define RB_ROOT_P(rbt, rb) ((rbt)->rbt_root == (rb))
+#define RB_SET_POSITION(rb, position) \
+ ((void)((position) ? ((rb)->rb_info |= RB_FLAG_POSITION) : \
+ ((rb)->rb_info &= ~RB_FLAG_POSITION)))
+#define RB_ZERO_PROPERTIES(rb) ((void)((rb)->rb_info &= ~RB_FLAG_MASK))
+#define RB_COPY_PROPERTIES(dst, src) \
+ ((void)((dst)->rb_info ^= ((dst)->rb_info ^ (src)->rb_info) & RB_FLAG_MASK))
+#define RB_SWAP_PROPERTIES(a, b) do { \
+ uintptr_t xorinfo = ((a)->rb_info ^ (b)->rb_info) & RB_FLAG_MASK; \
+ (a)->rb_info ^= xorinfo; \
+ (b)->rb_info ^= xorinfo; \
+ } while (/*CONSTCOND*/ 0)
+#ifdef RBDEBUG
+ TAILQ_ENTRY(rb_node) rb_link;
+#endif
+};
+
+#define RB_TREE_MIN(T) rb_tree_iterate((T), NULL, RB_DIR_LEFT)
+#define RB_TREE_MAX(T) rb_tree_iterate((T), NULL, RB_DIR_RIGHT)
+#define RB_TREE_FOREACH(N, T) \
+ for ((N) = RB_TREE_MIN(T); (N); \
+ (N) = rb_tree_iterate((T), (N), RB_DIR_RIGHT))
+#define RB_TREE_FOREACH_REVERSE(N, T) \
+ for ((N) = RB_TREE_MAX(T); (N); \
+ (N) = rb_tree_iterate((T), (N), RB_DIR_LEFT))
+
+#ifdef RBDEBUG
+TAILQ_HEAD(rb_node_qh, rb_node);
+
+#define RB_TAILQ_REMOVE(a, b, c) TAILQ_REMOVE(a, b, c)
+#define RB_TAILQ_INIT(a) TAILQ_INIT(a)
+#define RB_TAILQ_INSERT_HEAD(a, b, c) TAILQ_INSERT_HEAD(a, b, c)
+#define RB_TAILQ_INSERT_BEFORE(a, b, c) TAILQ_INSERT_BEFORE(a, b, c)
+#define RB_TAILQ_INSERT_AFTER(a, b, c, d) TAILQ_INSERT_AFTER(a, b, c, d)
+#else
+#define RB_TAILQ_REMOVE(a, b, c) do { } while (/*CONSTCOND*/0)
+#define RB_TAILQ_INIT(a) do { } while (/*CONSTCOND*/0)
+#define RB_TAILQ_INSERT_HEAD(a, b, c) do { } while (/*CONSTCOND*/0)
+#define RB_TAILQ_INSERT_BEFORE(a, b, c) do { } while (/*CONSTCOND*/0)
+#define RB_TAILQ_INSERT_AFTER(a, b, c, d) do { } while (/*CONSTCOND*/0)
+#endif /* RBDEBUG */
+
+/*
+ * rbto_compare_nodes_fn:
+ * return a positive value if the first node < the second node.
+ * return a negative value if the first node > the second node.
+ * return 0 if they are considered same.
+ *
+ * rbto_compare_key_fn:
+ * return a positive value if the node < the key.
+ * return a negative value if the node > the key.
+ * return 0 if they are considered same.
+ */
+
+typedef signed int (*const rbto_compare_nodes_fn)(const struct rb_node *,
+ const struct rb_node *);
+typedef signed int (*const rbto_compare_key_fn)(const struct rb_node *,
+ const void *);
+
+struct rb_tree_ops {
+ rbto_compare_nodes_fn rbto_compare_nodes;
+ rbto_compare_key_fn rbto_compare_key;
+};
+
+struct rb_tree {
+ struct rb_node *rbt_root;
+ const struct rb_tree_ops *rbt_ops;
+ struct rb_node *rbt_minmax[2];
+#ifdef RBDEBUG
+ struct rb_node_qh rbt_nodes;
+#endif
+ unsigned int rbt_count;
+#ifdef RBSTATS
+ unsigned int rbt_insertions;
+ unsigned int rbt_removals;
+ unsigned int rbt_insertion_rebalance_calls;
+ unsigned int rbt_insertion_rebalance_passes;
+ unsigned int rbt_removal_rebalance_calls;
+ unsigned int rbt_removal_rebalance_passes;
+#endif
+};
+
+#ifdef RBSTATS
+#define RBSTAT_INC(v) ((void)((v)++))
+#define RBSTAT_DEC(v) ((void)((v)--))
+#else
+#define RBSTAT_INC(v) do { } while (/*CONSTCOND*/0)
+#define RBSTAT_DEC(v) do { } while (/*CONSTCOND*/0)
+#endif
+
+void rb_tree_init(struct rb_tree *, const struct rb_tree_ops *);
+bool rb_tree_insert_node(struct rb_tree *, struct rb_node *);
+struct rb_node *
+ rb_tree_find_node(struct rb_tree *, const void *);
+struct rb_node *
+ rb_tree_find_node_geq(struct rb_tree *, const void *);
+struct rb_node *
+ rb_tree_find_node_leq(struct rb_tree *, const void *);
+void rb_tree_remove_node(struct rb_tree *, struct rb_node *);
+struct rb_node *
+ rb_tree_iterate(struct rb_tree *, struct rb_node *, const unsigned int);
+#ifdef RBDEBUG
+void rb_tree_check(const struct rb_tree *, bool);
+#endif
+#ifdef RBSTATS
+void rb_tree_depths(const struct rb_tree *, size_t *);
+#endif
+
+#endif /* _SYS_RB_H_*/
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include "SCNetworkReachabilityInternal.h"
+
+int
+main(int argc, char **argv)
+{
+ _sc_log = FALSE; // no syslog
+ _sc_debug = TRUE; // extra reachability logging
+
+ _SCNetworkReachabilityServer_start();
+
+ SCLog(TRUE, LOG_DEBUG, CFSTR("starting CFRunLoop"));
+ CFRunLoopRun();
+ SCLog(TRUE, LOG_DEBUG, CFSTR("CFRunLoop complete"));
+
+ exit(0);
+}
/*
- * Copyright (c) 2000, 2001, 2003-2005, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2005, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__private_extern__ CFMutableDictionaryRef sessionData = NULL;
__private_extern__ CFMutableDictionaryRef storeData = NULL;
-__private_extern__ CFMutableDictionaryRef storeData_s = NULL;
__private_extern__ CFMutableDictionaryRef patternData = NULL;
-__private_extern__ CFMutableDictionaryRef patternData_s = NULL;
__private_extern__ CFMutableSetRef changedKeys = NULL;
-__private_extern__ CFMutableSetRef changedKeys_s = NULL;
__private_extern__ CFMutableSetRef deferredRemovals = NULL;
-__private_extern__ CFMutableSetRef deferredRemovals_s = NULL;
__private_extern__ CFMutableSetRef removedSessionKeys = NULL;
-__private_extern__ CFMutableSetRef removedSessionKeys_s = NULL;
__private_extern__ CFMutableSetRef needsNotification = NULL;
-__private_extern__ int storeLocked = 0; /* > 0 if dynamic store locked */
-
-
-__private_extern__
-void
-_swapLockedStoreData()
-{
- void *temp;
-
- temp = storeData;
- storeData = storeData_s;
- storeData_s = temp;
-
- temp = patternData;
- patternData = patternData_s;
- patternData_s = temp;
-
- temp = changedKeys;
- changedKeys = changedKeys_s;
- changedKeys_s = temp;
-
- temp = deferredRemovals;
- deferredRemovals = deferredRemovals_s;
- deferredRemovals_s = temp;
-
- temp = removedSessionKeys;
- removedSessionKeys = removedSessionKeys_s;
- removedSessionKeys_s = temp;
-
- return;
-}
-
__private_extern__
void
/*
- * Copyright (c) 2000, 2001, 2003, 2004, 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003, 2004, 2006, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#define kSCDSessionKeys CFSTR("sessionKeys")
-extern int storeLocked;
extern CFMutableDictionaryRef storeData;
extern CFMutableDictionaryRef sessionData;
extern CFMutableDictionaryRef patternData;
extern CFMutableSetRef removedSessionKeys;
extern CFMutableSetRef needsNotification;
-extern CFMutableDictionaryRef storeData_s;
-extern CFMutableDictionaryRef patternData_s;
-extern CFMutableSetRef changedKeys_s;
-extern CFMutableSetRef deferredRemovals_s;
-extern CFMutableSetRef removedSessionKeys_s;
-
__BEGIN_DECLS
__SCDynamicStoreOpen (SCDynamicStoreRef *store,
CFStringRef name);
int
-__SCDynamicStoreClose (SCDynamicStoreRef *store,
- Boolean internal);
+__SCDynamicStoreClose (SCDynamicStoreRef *store);
int
-__SCDynamicStoreLock (SCDynamicStoreRef store,
- Boolean recursive);
-
-int
-__SCDynamicStoreUnlock (SCDynamicStoreRef store,
- Boolean recursive);
+__SCDynamicStorePush (void);
int
__SCDynamicStoreCopyKeyList (SCDynamicStoreRef store,
int
__SCDynamicStoreAddValue (SCDynamicStoreRef store,
CFStringRef key,
- CFDataRef value,
- Boolean internal);
+ CFDataRef value);
int
__SCDynamicStoreCopyValue (SCDynamicStoreRef store,
CFStringRef key,
Boolean internal);
-int
-__SCDynamicStoreTouchValue (SCDynamicStoreRef store,
- CFStringRef key);
-
int
__SCDynamicStoreNotifyValue (SCDynamicStoreRef store,
CFStringRef key,
int
__SCDynamicStoreNotifyCancel (SCDynamicStoreRef store);
-void
-_swapLockedStoreData (void);
-
void
_addWatcher (CFNumberRef sessionNum,
CFStringRef watchedKey);
/*
- * Copyright (c) 2000, 2001, 2003, 2004, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003, 2004, 2006, 2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__private_extern__
int
-__SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value, Boolean internal)
+__SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
int sc_status = kSCStatusOK;
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
CFDataRef tempValue;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
CFSTR("%s%s : %5d : %@\n"),
- internal ? "*add " : "add ",
+ "add ",
storePrivate->useSessionKeys ? "t " : " ",
storePrivate->server,
key);
}
/*
- * 1. Ensure that we hold the lock.
- */
- sc_status = __SCDynamicStoreLock(store, TRUE);
- if (sc_status != kSCStatusOK) {
- return sc_status;
- }
-
- /*
- * 2. Ensure that this is a new key.
+ * Ensure that this is a new key.
*/
sc_status = __SCDynamicStoreCopyValue(store, key, &tempValue, TRUE);
switch (sc_status) {
}
/*
- * 3. Save the new key.
+ * Save the new key.
*/
sc_status = __SCDynamicStoreSetValue(store, key, value, TRUE);
- /*
- * 4. Release our lock.
- */
+ /* push changes */
+ __SCDynamicStorePush();
done:
- __SCDynamicStoreUnlock(store, TRUE);
-
return sc_status;
}
xmlData_t dataRef, /* raw XML bytes */
mach_msg_type_number_t dataLen,
int *newInstance,
- int *sc_status
-)
+ int *sc_status,
+ audit_token_t audit_token)
{
CFStringRef key = NULL; /* key (un-serialized) */
CFDataRef data = NULL; /* data (un-serialized) */
mySession = getSession(server);
if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
+ mySession = tempSession(server, CFSTR("SCDynamicStoreAddValue"), audit_token);
+ if (mySession == NULL) {
+ /* you must have an open session to play */
+ *sc_status = kSCStatusNoStoreSession;
+ goto done;
+ }
+ }
+
+ if (!hasWriteAccess(mySession)) {
+ *sc_status = kSCStatusAccessError;
goto done;
}
- *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data, FALSE);
+ *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data);
if (*sc_status == kSCStatusOK) {
*newInstance = 0;
}
xmlData_t dataRef, /* raw XML bytes */
mach_msg_type_number_t dataLen,
int *newInstance,
- int *sc_status
-)
+ int *sc_status)
{
CFDataRef data = NULL; /* data (un-serialized) */
CFStringRef key = NULL; /* key (un-serialized) */
mySession = getSession(server);
if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
+ /* you must have an open session to play */
+ *sc_status = kSCStatusNoStoreSession;
goto done;
}
useSessionKeys = storePrivate->useSessionKeys;
storePrivate->useSessionKeys = TRUE;
- *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data, FALSE);
+ *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data);
if (*sc_status == kSCStatusOK) {
*newInstance = 0;
}
/*
- * Copyright (c) 2000, 2001, 2003, 2004, 2006-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003, 2004, 2006-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__private_extern__
int
-__SCDynamicStoreClose(SCDynamicStoreRef *store, Boolean internal)
+__SCDynamicStoreClose(SCDynamicStoreRef *store)
{
CFDictionaryRef dict;
CFArrayRef keys;
CFStringRef sessionKey;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)*store;
- if ((*store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
- CFSTR("%s : %5d\n"),
- internal ? "*close " : "close ",
+ CFSTR("close : %5d\n"),
storePrivate->server);
}
dict = CFDictionaryGetValue(sessionData, sessionKey);
keys = CFDictionaryGetValue(dict, kSCDSessionKeys);
if (keys && ((keyCnt = CFArrayGetCount(keys)) > 0)) {
- Boolean wasLocked;
CFIndex i;
+ Boolean push = FALSE;
- /*
- * if necessary, claim a lock to ensure that we inform
- * any processes that a session key was removed.
- */
- wasLocked = (storeLocked > 0);
- if (!wasLocked) {
- (void) __SCDynamicStoreLock(*store, FALSE);
- }
-
- /* remove keys from "locked" store" */
+ /* remove session keys */
for (i = 0; i < keyCnt; i++) {
if (isMySessionKey(sessionKey, CFArrayGetValueAtIndex(keys, i))) {
(void) __SCDynamicStoreRemoveValue(*store, CFArrayGetValueAtIndex(keys, i), TRUE);
+ push = TRUE;
}
}
- if (wasLocked) {
- /* remove keys from "unlocked" store" */
- _swapLockedStoreData();
- for (i = 0; i < keyCnt; i++) {
- if (isMySessionKey(sessionKey, CFArrayGetValueAtIndex(keys, i)))
- (void) __SCDynamicStoreRemoveValue(*store, CFArrayGetValueAtIndex(keys, i), TRUE);
- }
- _swapLockedStoreData();
+ if (push) {
+ /* push changes */
+ (void) __SCDynamicStorePush();
}
-
- /*
- * Note: everyone who calls __SCDynamicStoreClose() ends
- * up removing this sessions dictionary. As such,
- * we don't need to worry about the session keys.
- */
}
CFRelease(sessionKey);
- /* release the lock */
- if (storePrivate->locked) {
- (void) __SCDynamicStoreUnlock(*store, FALSE);
- }
-
/*
* invalidate and release our run loop source on the server
* port (for this client). Then, release the port.
return kSCStatusOK;
}
-
-
-__private_extern__
-kern_return_t
-_configclose(mach_port_t server, int *sc_status)
-{
- serverSessionRef mySession = getSession(server);
-
- if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- return KERN_SUCCESS;
- }
-
- /*
- * Close the session.
- */
- __MACH_PORT_DEBUG(TRUE, "*** _configclose", server);
- *sc_status = __SCDynamicStoreClose(&mySession->store, FALSE);
- if (*sc_status != kSCStatusOK) {
- SCLog(TRUE, LOG_ERR,
- CFSTR("_configclose __SCDynamicStoreClose() failed, status = %s"),
- SCErrorString(*sc_status));
- return KERN_SUCCESS;
- }
- __MACH_PORT_DEBUG(TRUE, "*** _configclose (after __SCDynamicStoreClose)", server);
-
- /*
- * Remove our receive right.
- *
- * Note: there is no need to cancel the notification request because the
- * kernel will have no way to deliver the notification once the
- * receive right has been removed.
- */
- (void) mach_port_mod_refs(mach_task_self(), server, MACH_PORT_RIGHT_RECEIVE, -1);
-
- /*
- * Remove the session entry.
- */
- removeSession(server);
-
- return KERN_SUCCESS;
-}
/*
- * Copyright (c) 2000-2004, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
CFDictionaryRef dict;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
CFSTR("%s : %5d : %@\n"),
xmlDataOut_t *dataRef, /* raw XML bytes */
mach_msg_type_number_t *dataLen,
int *newInstance,
- int *sc_status
-)
+ int *sc_status,
+ audit_token_t audit_token)
{
CFStringRef key = NULL; /* key (un-serialized) */
+ CFIndex len;
serverSessionRef mySession;
Boolean ok;
CFDataRef value;
mySession = getSession(server);
if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- goto done;
+ mySession = tempSession(server, CFSTR("SCDynamicStoreCopyValue"), audit_token);
+ if (mySession == NULL) {
+ /* you must have an open session to play */
+ *sc_status = kSCStatusNoStoreSession;
+ goto done;
+ }
}
*sc_status = __SCDynamicStoreCopyValue(mySession->store, key, &value, FALSE);
}
/* serialize the data */
- ok = _SCSerializeData(value, (void **)dataRef, (CFIndex *)dataLen);
+ ok = _SCSerializeData(value, (void **)dataRef, &len);
+ *dataLen = len;
CFRelease(value);
if (!ok) {
*sc_status = kSCStatusFailed;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
addSpecific myContext;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
CFSTR("copy m : %5d : %d keys, %d patterns\n"),
mach_msg_type_number_t patternsLen,
xmlDataOut_t *dataRef,
mach_msg_type_number_t *dataLen,
- int *sc_status)
+ int *sc_status,
+ audit_token_t audit_token)
{
CFDictionaryRef dict = NULL; /* keys/values (un-serialized) */
CFArrayRef keys = NULL; /* keys (un-serialized) */
+ CFIndex len;
serverSessionRef mySession;
Boolean ok;
CFArrayRef patterns = NULL; /* patterns (un-serialized) */
mySession = getSession(server);
if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- goto done;
+ mySession = tempSession(server, CFSTR("SCDynamicStoreCopyMultiple"), audit_token);
+ if (mySession == NULL) {
+ /* you must have an open session to play */
+ *sc_status = kSCStatusNoStoreSession;
+ goto done;
+ }
}
/* fetch the requested information */
*sc_status = __SCDynamicStoreCopyMultiple(mySession->store, keys, patterns, &dict);
/* serialize the dictionary of matching keys/patterns */
- ok = _SCSerialize(dict, NULL, (void **)dataRef, (CFIndex *)dataLen);
+ ok = _SCSerialize(dict, NULL, (void **)dataRef, &len);
+ *dataLen = len;
CFRelease(dict);
if (!ok) {
*sc_status = kSCStatusFailed;
/*
- * Copyright (c) 2000-2004, 2006-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006-2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
int
__SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex, CFArrayRef *subKeys)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
CFMutableArrayRef keyArray;
CFIndex storeCnt;
CFStringRef storeStr;
CFDictionaryRef storeValue;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (isRegex) {
*subKeys = patternCopyMatches(key);
return (*subKeys != NULL) ? kSCStatusOK : kSCStatusFailed;
int isRegex,
xmlDataOut_t *listRef, /* raw XML bytes */
mach_msg_type_number_t *listLen,
- int *sc_status
-)
+ int *sc_status,
+ audit_token_t audit_token)
{
CFStringRef key = NULL; /* key (un-serialized) */
+ CFIndex len;
serverSessionRef mySession;
Boolean ok;
CFArrayRef subKeys; /* array of CFStringRef's */
mySession = getSession(server);
if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- goto done;
+ mySession = tempSession(server, CFSTR("SCDynamicStoreCopyKeyList"), audit_token);
+ if (mySession == NULL) {
+ /* you must have an open session to play */
+ *sc_status = kSCStatusNoStoreSession;
+ goto done;
+ }
}
*sc_status = __SCDynamicStoreCopyKeyList(mySession->store, key, isRegex != 0, &subKeys);
}
/* serialize the list of keys */
- ok = _SCSerialize(subKeys, NULL, (void **)listRef, (CFIndex *)listLen);
+ ok = _SCSerialize(subKeys, NULL, (void **)listRef, &len);
+ *listLen = len;
CFRelease(subKeys);
if (!ok) {
*sc_status = kSCStatusFailed;
+++ /dev/null
-/*
- * Copyright (c) 2000, 2001, 2003, 2004, 2006, 2009 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,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * 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@
- */
-
-/*
- * Modification History
- *
- * June 1, 2001 Allan Nathanson <ajn@apple.com>
- * - public API conversion
- *
- * March 24, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include "configd.h"
-#include "configd_server.h"
-#include "session.h"
-
-
-__private_extern__
-int
-__SCDynamicStoreLock(SCDynamicStoreRef store, Boolean recursive)
-{
- serverSessionRef mySession;
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
-
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
- if (storeLocked > 0) {
- if (storePrivate->locked && recursive) {
- /* if this session holds the lock and this is a recursive (internal) request */
- storeLocked++;
- return kSCStatusOK;
- }
- return kSCStatusLocked; /* sorry, someone (you) already have the lock */
- }
-
- /* check credentials */
- mySession = getSession(storePrivate->server);
- if (!hasWriteAccess(mySession)) {
- return kSCStatusAccessError;
- }
-
- if (!recursive && _configd_trace) {
- SCTrace(TRUE, _configd_trace, CFSTR("lock : %5d\n"), storePrivate->server);
- }
-
- storeLocked = 1; /* global lock flag */
- storePrivate->locked = TRUE; /* per-session lock flag */
-
- /*
- * defer all (actually, most) changes until the call to __SCDynamicStoreUnlock()
- */
- if (storeData_s) {
- CFRelease(storeData_s);
- CFRelease(patternData_s);
- CFRelease(changedKeys_s);
- CFRelease(deferredRemovals_s);
- CFRelease(removedSessionKeys_s);
- }
- storeData_s = CFDictionaryCreateMutableCopy(NULL, 0, storeData);
- patternData_s = CFDictionaryCreateMutableCopy(NULL, 0, patternData);
- changedKeys_s = CFSetCreateMutableCopy(NULL, 0, changedKeys);
- deferredRemovals_s = CFSetCreateMutableCopy(NULL, 0, deferredRemovals);
- removedSessionKeys_s = CFSetCreateMutableCopy(NULL, 0, removedSessionKeys);
-
- /* Add a "locked" mode run loop source for this port */
- CFRunLoopAddSource(CFRunLoopGetCurrent(), mySession->serverRunLoopSource, CFSTR("locked"));
-
- return kSCStatusOK;
-}
-
-
-__private_extern__
-kern_return_t
-_configlock(mach_port_t server, int *sc_status)
-{
- serverSessionRef mySession = getSession(server);
-
- if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- return KERN_SUCCESS;
- }
-
- *sc_status = __SCDynamicStoreLock(mySession->store, FALSE);
- if (*sc_status != kSCStatusOK) {
- return KERN_SUCCESS;
- }
-
- return KERN_SUCCESS;
-}
/*
- * Copyright (c) 2000-2004, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
int
__SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key, Boolean internal)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- int sc_status = kSCStatusOK;
CFDictionaryRef dict;
Boolean newValue = FALSE;
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ int sc_status = kSCStatusOK;
CFDataRef value;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
CFSTR("%s : %5d : %@\n"),
}
/*
- * 1. Ensure that we hold the lock.
- */
- sc_status = __SCDynamicStoreLock(store, TRUE);
- if (sc_status != kSCStatusOK) {
- return sc_status;
- }
-
- /*
- * 2. Tickle the value in the dynamic store
+ * Tickle the value in the dynamic store
*/
dict = CFDictionaryGetValue(storeData, key);
if (!dict || !CFDictionaryGetValueIfPresent(dict, kSCDData, (const void **)&value)) {
CFRelease(value);
}
- /*
- * 3. Release our lock.
- */
- __SCDynamicStoreUnlock(store, TRUE);
+ if (!internal) {
+ /* push changes */
+ __SCDynamicStorePush();
+ }
return sc_status;
}
_confignotify(mach_port_t server,
xmlData_t keyRef, /* raw XML bytes */
mach_msg_type_number_t keyLen,
- int *sc_status
-)
+ int *sc_status,
+ audit_token_t audit_token)
{
CFStringRef key = NULL; /* key (un-serialized) */
serverSessionRef mySession;
mySession = getSession(server);
if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
+ mySession = tempSession(server, CFSTR("SCDynamicStoreNotifyValue"), audit_token);
+ if (mySession == NULL) {
+ /* you must have an open session to play */
+ *sc_status = kSCStatusNoStoreSession;
+ goto done;
+ }
+ }
+
+ if (!hasWriteAccess(mySession)) {
+ *sc_status = kSCStatusAccessError;
goto done;
}
/*
- * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
}
}
- mySession = getSession(server);
- if ((mySession != NULL) && (mySession->store != NULL)) {
+ /*
+ * establish the new session
+ */
+ mySession = addSession(server, openMPCopyDescription);
+ if (mySession == NULL) {
#ifdef DEBUG
SCLog(TRUE, LOG_DEBUG, CFSTR("_configopen(): session is already open."));
#endif /* DEBUG */
goto done;
}
- /*
- * establish the new session
- */
- mySession = addSession(MACH_PORT_NULL, openMPCopyDescription);
*newServer = mySession->key;
__MACH_PORT_DEBUG(TRUE, "*** _configopen (after addSession)", *newServer);
/*
- * Copyright (c) 2000-2004, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
int
__SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key, Boolean internal)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- int sc_status = kSCStatusOK;
CFDictionaryRef dict;
CFMutableDictionaryRef newDict;
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ int sc_status = kSCStatusOK;
CFStringRef sessionKey;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
CFSTR("%s : %5d : %@\n"),
}
/*
- * 1. Ensure that we hold the lock.
- */
- sc_status = __SCDynamicStoreLock(store, TRUE);
- if (sc_status != kSCStatusOK) {
- return sc_status;
- }
-
- /*
- * 2. Ensure that this key exists.
+ * Ensure that this key exists.
*/
dict = CFDictionaryGetValue(storeData, key);
if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDData) == FALSE)) {
newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
/*
- * 3. Mark this key as "changed". Any "watchers" will be
- * notified as soon as the lock is released.
+ * Mark this key as "changed". Any "watchers" will be
+ * notified as soon as the lock is released.
*/
CFSetAddValue(changedKeys, key);
/*
- * 4. Add this key to a deferred cleanup list so that, after
- * the change notifications are posted, any associated
- * regex keys can be removed.
+ * Add this key to a deferred cleanup list so that, after
+ * the change notifications are posted, any associated
+ * regex keys can be removed.
*/
CFSetAddValue(deferredRemovals, key);
/*
- * 5. Check if this is a session key and, if so, add it
- * to the (session) removal list
+ * Check if this is a session key and, if so, add it
+ * to the (session) removal list
*/
sessionKey = CFDictionaryGetValue(newDict, kSCDSession);
if (sessionKey) {
}
/*
- * 6. Remove data and update/remove the dictionary store entry.
+ * Remove data and update/remove the dictionary store entry.
*/
CFDictionaryRemoveValue(newDict, kSCDData);
if (CFDictionaryGetCount(newDict) > 0) {
}
CFRelease(newDict);
- /*
- * 7. Release our lock.
- */
+ if (!internal) {
+ /* push changes */
+ __SCDynamicStorePush();
+ }
+
done:
- __SCDynamicStoreUnlock(store, TRUE);
return sc_status;
}
_configremove(mach_port_t server,
xmlData_t keyRef, /* raw XML bytes */
mach_msg_type_number_t keyLen,
- int *sc_status
-)
+ int *sc_status,
+ audit_token_t audit_token)
{
CFStringRef key = NULL; /* key (un-serialized) */
serverSessionRef mySession;
mySession = getSession(server);
if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
+ mySession = tempSession(server, CFSTR("SCDynamicStoreRemoveValue"), audit_token);
+ if (mySession == NULL) {
+ /* you must have an open session to play */
+ *sc_status = kSCStatusNoStoreSession;
+ goto done;
+ }
+ }
+
+ if (!hasWriteAccess(mySession)) {
+ *sc_status = kSCStatusAccessError;
goto done;
}
/*
- * Copyright (c) 2000-2004, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
int
__SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value, Boolean internal)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- int sc_status = kSCStatusOK;
CFDictionaryRef dict;
CFMutableDictionaryRef newDict;
Boolean newEntry = FALSE;
+ int sc_status = kSCStatusOK;
CFStringRef sessionKey;
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
CFStringRef storeSessionKey;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
CFSTR("%s%s : %5d : %@\n"),
}
/*
- * 1. Ensure that we hold the lock.
- */
- sc_status = __SCDynamicStoreLock(store, TRUE);
- if (sc_status != kSCStatusOK) {
- return sc_status;
- }
-
- /*
- * 2. Grab the current (or establish a new) dictionary for this key.
+ * Grab the current (or establish a new) dictionary for this key.
*/
dict = CFDictionaryGetValue(storeData, key);
}
/*
- * 3. Update the dictionary entry to be saved to the store.
+ * Update the dictionary entry to be saved to the store.
*/
newEntry = !CFDictionaryContainsKey(newDict, kSCDData);
CFDictionarySetValue(newDict, kSCDData, value);
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server);
/*
- * 4. Manage per-session keys.
+ * Manage per-session keys.
*/
if (storePrivate->useSessionKeys) {
if (newEntry) {
CFRelease(sessionKey);
/*
- * 5. Update the dictionary entry in the store.
+ * Update the dictionary entry in the store.
*/
CFDictionarySetValue(storeData, key, newDict);
CFRelease(newDict);
/*
- * 6. For "new" entries to the store, check the deferred cleanup
- * list. If the key is flagged for removal, remove it from the
- * list since any defined regex's for this key are still defined
- * and valid. If the key is not flagged then iterate over the
- * sessionData dictionary looking for regex keys which match the
- * updated key. If a match is found then we mark those keys as
- * being watched.
+ * For "new" entries to the store, check the deferred cleanup
+ * list. If the key is flagged for removal, remove it from the
+ * list since any defined regex's for this key are still defined
+ * and valid. If the key is not flagged then iterate over the
+ * sessionData dictionary looking for regex keys which match the
+ * updated key. If a match is found then we mark those keys as
+ * being watched.
*/
if (newEntry) {
}
/*
- * 7. Mark this key as "changed". Any "watchers" will be notified
- * as soon as the lock is released.
+ * Mark this key as "changed". Any "watchers" will be notified
+ * as soon as the lock is released.
*/
CFSetAddValue(changedKeys, key);
done :
- /*
- * 8. Release our lock.
- */
- __SCDynamicStoreUnlock(store, TRUE);
+ if (!internal) {
+ /* push changes */
+ __SCDynamicStorePush();
+ }
return sc_status;
}
mach_msg_type_number_t dataLen,
int oldInstance,
int *newInstance,
- int *sc_status
-)
+ int *sc_status,
+ audit_token_t audit_token)
{
CFDataRef data = NULL; /* data (un-serialized) */
CFStringRef key = NULL; /* key (un-serialized) */
mySession = getSession(server);
if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
+ mySession = tempSession(server, CFSTR("SCDynamicStoreSetValue"), audit_token);
+ if (mySession == NULL) {
+ /* you must have an open session to play */
+ *sc_status = kSCStatusNoStoreSession;
+ goto done;
+ }
+ }
+
+ if (!hasWriteAccess(mySession)) {
+ *sc_status = kSCStatusAccessError;
goto done;
}
int
__SCDynamicStoreSetMultiple(SCDynamicStoreRef store, CFDictionaryRef keysToSet, CFArrayRef keysToRemove, CFArrayRef keysToNotify)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
int sc_status = kSCStatusOK;
-
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
keysToNotify ? CFArrayGetCount (keysToNotify) : 0);
}
- /*
- * Ensure that we hold the lock
- */
- sc_status = __SCDynamicStoreLock(store, TRUE);
- if (sc_status != kSCStatusOK) {
- return sc_status;
- }
-
/*
* Set the new/updated keys
*/
(void *)store);
}
- /* Release our lock */
- __SCDynamicStoreUnlock(store, TRUE);
+ /* push changes */
+ __SCDynamicStorePush();
return sc_status;
}
mach_msg_type_number_t removeLen,
xmlData_t notifyRef,
mach_msg_type_number_t notifyLen,
- int *sc_status)
+ int *sc_status,
+ audit_token_t audit_token)
{
CFDictionaryRef dict = NULL; /* key/value dictionary (un-serialized) */
serverSessionRef mySession;
mySession = getSession(server);
if (mySession == NULL) {
- /* you must have an open session to play */
- *sc_status = kSCStatusNoStoreSession;
+ mySession = tempSession(server, CFSTR("SCDynamicStoreSetMultiple"), audit_token);
+ if (mySession == NULL) {
+ /* you must have an open session to play */
+ *sc_status = kSCStatusNoStoreSession;
+ goto done;
+ }
+ }
+
+ if (!hasWriteAccess(mySession)) {
+ *sc_status = kSCStatusAccessError;
goto done;
}
+++ /dev/null
-/*
- * Copyright (c) 2000-2004, 2006, 2008, 2009 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,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * 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@
- */
-
-/*
- * Modification History
- *
- * June 1, 2001 Allan Nathanson <ajn@apple.com>
- * - public API conversion
- *
- * June 20, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include "configd.h"
-#include "session.h"
-
-__private_extern__
-int
-__SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key)
-{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- int sc_status = kSCStatusOK;
- CFDataRef value;
-
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
- if (_configd_trace) {
- SCTrace(TRUE, _configd_trace, CFSTR("touch : %5d : %@\n"), storePrivate->server, key);
- }
-
- /*
- * 1. Ensure that we hold the lock.
- */
- sc_status = __SCDynamicStoreLock(store, TRUE);
- if (sc_status != kSCStatusOK) {
- return sc_status;
- }
-
- /*
- * 2. Grab the current (or establish a new) store entry for this key.
- */
- sc_status = __SCDynamicStoreCopyValue(store, key, &value, TRUE);
- switch (sc_status) {
- case kSCStatusNoKey : {
- CFDateRef now;
-
- /* store entry does not exist, create */
-
- now = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
- (void) _SCSerialize(now, &value, NULL, NULL);
- CFRelease(now);
- break;
- }
-
- case kSCStatusOK : {
- CFDateRef now;
-
- /* store entry exists */
-
- (void) _SCUnserialize((CFPropertyListRef *)&now, value, NULL, 0);
- if (isA_CFDate(now)) {
- /* the value is a CFDate, update the time stamp */
- CFRelease(now);
- CFRelease(value);
- now = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
- (void) _SCSerialize(now, &value, NULL, NULL);
- } /* else, we'll just save the data (again) to bump the instance */
- CFRelease(now);
-
- break;
- }
- default :
- goto done;
- }
-
- sc_status = __SCDynamicStoreSetValue(store, key, value, TRUE);
- CFRelease(value);
-
- done :
-
- /*
- * 8. Release our lock.
- */
- __SCDynamicStoreUnlock(store, TRUE);
-
- return sc_status;
-}
-
-
-__private_extern__
-kern_return_t
-_configtouch(mach_port_t server,
- xmlData_t keyRef, /* raw XML bytes */
- mach_msg_type_number_t keyLen,
- int *sc_status
-)
-{
- CFStringRef key = NULL; /* key (un-serialized) */
- serverSessionRef mySession;
-
- /* un-serialize the key */
- if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
- *sc_status = kSCStatusFailed;
- goto done;
- }
-
- if (!isA_CFString(key)) {
- *sc_status = kSCStatusInvalidArgument;
- goto done;
- }
-
- mySession = getSession(server);
- if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- goto done;
- }
-
- *sc_status = __SCDynamicStoreTouchValue(mySession->store, key);
-
- done :
-
- if (key) CFRelease(key);
- return KERN_SUCCESS;
-}
/*
- * Copyright (c) 2000-2004, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__private_extern__
int
-__SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive)
+__SCDynamicStorePush(void)
{
- serverSessionRef mySession;
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
-
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
- if ((storeLocked == 0) || !storePrivate->locked) {
- return kSCStatusNeedLock; /* sorry, you don't have the lock */
- }
-
- if ((storeLocked > 1) && recursive) {
- /* if the lock is being held for a recursive (internal) request */
- storeLocked--;
- return kSCStatusOK;
- }
-
- if (!recursive && _configd_trace) {
- SCTrace(TRUE, _configd_trace, CFSTR("unlock : %5d\n"), storePrivate->server);
- }
-
- /*
- * all of the changes can be committed to the (real) store.
- */
- CFDictionaryRemoveAllValues(storeData_s);
- CFDictionaryRemoveAllValues(patternData_s);
- CFSetRemoveAllValues (changedKeys_s);
- CFSetRemoveAllValues (deferredRemovals_s);
- CFSetRemoveAllValues (removedSessionKeys_s);
-
/*
* push notifications to any session watching those keys which
* were recently changed.
CFSetApplyFunction(removedSessionKeys, _cleanupRemovedSessionKeys, NULL);
CFSetRemoveAllValues(removedSessionKeys);
- /* Remove the "locked" run loop source for this port */
- mySession = getSession(storePrivate->server);
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), mySession->serverRunLoopSource, CFSTR("locked"));
-
- storeLocked = 0; /* global lock flag */
- storePrivate->locked = FALSE; /* per-session lock flag */
-
return kSCStatusOK;
}
-
-
-__private_extern__
-kern_return_t
-_configunlock(mach_port_t server, int *sc_status)
-{
- serverSessionRef mySession = getSession(server);
-
- if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- return KERN_SUCCESS;
- }
-
- *sc_status = __SCDynamicStoreUnlock(mySession->store, FALSE);
- if (*sc_status != kSCStatusOK) {
- return KERN_SUCCESS;
- }
-
- return KERN_SUCCESS;
-}
/*
- * Copyright (c) 2000-2004, 2006, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2008, 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFNumberRef sessionNum = NULL;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
CFSTR("%s : %5d : %s : %@\n"),
updateKeysContext myContext;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
CFSTR("watch : %5d : %d keys, %d patterns\n"),
/*
- * Copyright (c) 2000-2003, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2003, 2006, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFDictionaryRef info;
CFMutableDictionaryRef newInfo;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server);
info = CFDictionaryGetValue(sessionData, sessionKey);
if ((info == NULL) ||
int *sc_status
)
{
+ CFIndex len;
serverSessionRef mySession = getSession(server);
CFArrayRef notifierKeys; /* array of CFStringRef's */
Boolean ok;
}
/* serialize the array of keys */
- ok = _SCSerialize(notifierKeys, NULL, (void **)listRef, (CFIndex *)listLen);
+ ok = _SCSerialize(notifierKeys, NULL, (void **)listRef, &len);
+ *listLen = len;
CFRelease(notifierKeys);
if (!ok) {
*sc_status = kSCStatusFailed;
/*
- * Copyright (c) 2000-2004, 2006, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2008, 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFNumberRef sessionNum;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
CFSTR("%s : %5d : %s : %@\n"),
/*
- * Copyright (c) 2000, 2001, 2003-2006, 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2006, 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFStringRef sessionKey;
CFDictionaryRef info;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (storePrivate->notifyStatus != NotifierNotRegistered) {
/* sorry, you can only have one notification registered at once */
return kSCStatusNotifierActive;
/*
- * Copyright (c) 2000, 2001, 2003, 2004, 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003, 2004, 2006, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFStringRef sessionKey;
CFDictionaryRef info;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (storePrivate->notifyStatus != NotifierNotRegistered) {
/* sorry, you can only have one notification registered at once */
return kSCStatusNotifierActive;
/*
- * Copyright (c) 2000-2004, 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2006, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFStringRef sessionKey;
CFDictionaryRef info;
- if ((store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
if (storePrivate->notifyStatus != NotifierNotRegistered) {
/* sorry, you can only have one notification registered at once */
return kSCStatusNotifierActive;
/*
- * Copyright (c) 2000-2006, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2006, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#define N_QUICK 100
-static CFDictionaryRef
+static CF_RETURNS_RETAINED CFDictionaryRef
_expandStore(CFDictionaryRef storeData)
{
const void * keys_q[N_QUICK];
CFDictionaryRef expandedStoreData;
FILE *f;
int fd;
- serverSessionRef mySession;
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
CFDataRef xmlData;
- /* check credentials */
-
- mySession = getSession(storePrivate->server);
- if (!hasRootAccess(mySession)) {
- return kSCStatusAccessError;
- }
-
/* Save a snapshot of configd's "state" */
(void) unlink(SNAPSHOT_PATH_STATE);
__private_extern__
kern_return_t
-_snapshot(mach_port_t server, int *sc_status)
+_snapshot(mach_port_t server, int *sc_status, audit_token_t audit_token)
{
- serverSessionRef mySession = getSession(server);
+ serverSessionRef mySession;
+ mySession = getSession(server);
if (mySession == NULL) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- return KERN_SUCCESS;
+ mySession = tempSession(server, CFSTR("SCDynamicStoreSnapshot"), audit_token);
+ if (mySession == NULL) {
+ /* you must have an open session to play */
+ return kSCStatusNoStoreSession;
+ }
+ }
+
+ if (!hasRootAccess(mySession)) {
+ return kSCStatusAccessError;
}
*sc_status = __SCDynamicStoreSnapshot(mySession->store);
<dict>
<key>com.apple.SystemConfiguration.configd</key>
<true/>
+ <key>com.apple.SystemConfiguration.SCNetworkReachability</key>
+ <true/>
</dict>
+ <key>POSIXSpawnType</key>
+ <string>Interactive</string>
<key>ProgramArguments</key>
<array>
<string>/usr/libexec/configd</string>
/*
- * Copyright (c) 2000, 2001, 2003, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003, 2006, 2007, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
extern Boolean _configd_verbose; /* TRUE if verbose logging enabled */
extern FILE *_configd_trace; /* non-NULL if tracing enabled */
+extern CFMutableSetRef _plugins_allowed; /* bundle identifiers to allow when loading */
extern CFMutableSetRef _plugins_exclude; /* bundle identifiers to exclude from loading */
extern Boolean _plugins_fork; /* TRUE if plugins should be exec'd in their own process */
extern CFMutableSetRef _plugins_verbose; /* bundle identifiers to enable verbose logging */
/*
- * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* - created
*/
-//#define DO_NOT_INFORM
+#define DO_NOT_INFORM
#include <getopt.h>
#include <stdio.h>
__private_extern__
FILE *_configd_trace = NULL; /* non-NULL if tracing enabled */
+__private_extern__
+CFMutableSetRef _plugins_allowed = NULL; /* bundle identifiers to allow when loading */
+
__private_extern__
CFMutableSetRef _plugins_exclude = NULL; /* bundle identifiers to exclude from loading */
static const struct option longopts[] = {
+// { "include-plugin", required_argument, 0, 'A' },
// { "no-bundles", no_argument, 0, 'b' },
// { "exclude-plugin", required_argument, 0, 'B' },
// { "no-fork", no_argument, 0, 'd' },
static void
usage(const char *prog)
{
- SCPrint(TRUE, stderr, CFSTR("%s: [-d] [-v] [-V bundleID] [-b] [-B bundleID] [-t bundle-path]\n"), prog);
+ SCPrint(TRUE, stderr, CFSTR("%s: [-d] [-v] [-V bundleID] [-b] [-B bundleID] [-A bundleID] [-t bundle-path]\n"), prog);
SCPrint(TRUE, stderr, CFSTR("options:\n"));
SCPrint(TRUE, stderr, CFSTR("\t-d\tdisable daemon/run in foreground\n"));
SCPrint(TRUE, stderr, CFSTR("\t-v\tenable verbose logging\n"));
SCPrint(TRUE, stderr, CFSTR("\t-f\tload ALL plug-ins in a separate process\n"));
SCPrint(TRUE, stderr, CFSTR("\t-b\tdisable loading of ALL plug-ins\n"));
SCPrint(TRUE, stderr, CFSTR("\t-B\tdisable loading of the specified plug-in\n"));
+ SCPrint(TRUE, stderr, CFSTR("\t-A\tenable loading of the specified plug-in\n"));
SCPrint(TRUE, stderr, CFSTR("\t-t\tload/test the specified plug-in\n"));
SCPrint(TRUE, stderr, CFSTR("\t\t (Note: only the plug-in will be started)\n"));
exit (EX_USAGE);
return 0;
}
-
-static void
-writepid(void)
-{
- FILE *fp;
-
- fp = fopen("/var/run/configd.pid", "w");
- if (fp != NULL) {
- fprintf(fp, "%d\n", getpid());
- fclose(fp);
- }
-}
-
-
static CFStringRef
termMPCopyDescription(const void *info)
{
Boolean loadBundles = TRUE;
struct sigaction nact;
int opt;
- extern int optind;
+// extern int optind;
const char *prog = argv[0];
CFRunLoopSourceRef rls;
kern_return_t status;
CFStringRef str;
const char *testBundle = NULL;
+ _plugins_allowed = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
_plugins_exclude = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
_plugins_verbose = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
/* process any arguments */
- while ((opt = getopt_long(argc, argv, "bB:dt:vV:f", longopts, NULL)) != -1) {
+ while ((opt = getopt_long(argc, argv, "A:bB:dt:vV:f", longopts, NULL)) != -1) {
switch(opt) {
+ case 'A':
+ str = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingMacRoman);
+ CFSetSetValue(_plugins_allowed, str);
+ CFRelease(str);
+ break;
case 'b':
loadBundles = FALSE;
break;
/* check/enable trace logging */
set_trace();
- /* record process id */
- if (testBundle == NULL) {
- writepid();
- }
-
/* add signal handler to catch a SIGHUP */
nact.sa_handler = catcher;
sigemptyset(&nact.sa_mask);
/*
- * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
* Create and add a run loop source for the port and add this source
- * to both the default run loop mode and the "locked" mode. These two
- * modes will be used for normal (unlocked) communication with the
- * server and when multiple (locked) updates are requested by a single
- * session.
+ * to the default run loop mode.
*/
rls = CFMachPortCreateRunLoopSource(NULL, configd_port, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
- CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, CFSTR("locked"));
CFRelease(rls);
return;
void
server_loop()
{
- CFStringRef rlMode;
-
pthread_setname_np("SCDynamicStore");
while (TRUE) {
/*
* process one run loop event
*/
- rlMode = (storeLocked > 0) ? CFSTR("locked") : kCFRunLoopDefaultMode;
- CFRunLoopRunInMode(rlMode, 1.0e10, TRUE);
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, TRUE);
/*
* check for, and if necessary, push out change notifications
/*
- * Copyright (c) 2000-2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2006, 2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
void server_loop (void);
kern_return_t _snapshot (mach_port_t server,
- int *sc_status);
+ int *sc_status,
+ audit_token_t audit_token);
kern_return_t _configopen (mach_port_t server,
xmlData_t nameRef,
int *sc_status,
audit_token_t audit_token);
-kern_return_t _configclose (mach_port_t server,
- int *sc_status);
-
-kern_return_t _configlock (mach_port_t server,
- int *sc_status);
-
-kern_return_t _configunlock (mach_port_t server,
- int *sc_status);
-
kern_return_t _configlist (mach_port_t server,
xmlData_t keyRef,
mach_msg_type_number_t keyLen,
int isRegex,
xmlDataOut_t *listRef,
mach_msg_type_number_t *listLen,
- int *sc_status);
+ int *sc_status,
+ audit_token_t audit_token);
kern_return_t _configadd (mach_port_t server,
xmlData_t keyRef,
xmlData_t dataRef,
mach_msg_type_number_t dataLen,
int *newInstance,
- int *sc_status);
+ int *sc_status,
+ audit_token_t audit_token);
kern_return_t _configadd_s (mach_port_t server,
xmlData_t keyRef,
xmlDataOut_t *dataRef,
mach_msg_type_number_t *dataLen,
int *newInstance,
- int *sc_status);
+ int *sc_status,
+ audit_token_t audit_token);
kern_return_t _configset (mach_port_t server,
xmlData_t keyRef,
xmlData_t dataRef,
mach_msg_type_number_t dataLen,
int *newInstance,
- int *sc_status);
+ int *sc_status,
+ audit_token_t audit_token);
kern_return_t _configremove (mach_port_t server,
xmlData_t keyRef,
mach_msg_type_number_t keyLen,
- int *sc_status);
-
-kern_return_t _configtouch (mach_port_t server,
- xmlData_t keyRef,
- mach_msg_type_number_t keyLen,
- int *sc_status);
+ int *sc_status,
+ audit_token_t audit_token);
kern_return_t _confignotify (mach_port_t server,
xmlData_t keyRef,
mach_msg_type_number_t keyLen,
- int *sc_status);
+ int *sc_status,
+ audit_token_t audit_token);
kern_return_t _configget_m (mach_port_t server,
xmlData_t keysRef,
mach_msg_type_number_t patternsLen,
xmlDataOut_t *dataRef,
mach_msg_type_number_t *dataLen,
- int *sc_status);
+ int *sc_status,
+ audit_token_t audit_token);
kern_return_t _configset_m (mach_port_t server,
xmlData_t dataRef,
mach_msg_type_number_t removeLen,
xmlData_t notifyRef,
mach_msg_type_number_t notifyLen,
- int *sc_status);
+ int *sc_status,
+ audit_token_t audit_token);
kern_return_t _notifyadd (mach_port_t server,
xmlData_t keyRef,
<key>keychain-access-groups</key>
<array>
<string>apple</string>
+ <string>com.apple.certificates</string>
<string>com.apple.identities</string>
</array>
<key>com.apple.springboard.launchapplications</key>
<true/>
- <key>com.apple.wifi.manager-access</key>
+ <key>com.apple.multitasking.unlimitedassertions</key>
<true/>
- <key>com.apple.MobileInternetSharing.allow</key>
+ <key>com.apple.wifi.manager-access</key>
<true/>
</dict>
</plist>
/*
- * Copyright (c) 2003, 2004, 2006-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2003, 2004, 2006-2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
}
-static CFMutableArrayRef
+static CF_RETURNS_RETAINED CFMutableArrayRef
patternCopy(CFStringRef pattern)
{
CFArrayRef pInfo;
}
-static CFMutableArrayRef
+static CF_RETURNS_RETAINED CFMutableArrayRef
patternNew(CFStringRef pattern)
{
addContext context;
/* compile the regular expression from the pattern string. */
pRegex = CFDataCreateMutable(NULL, sizeof(regex_t));
CFDataSetLength(pRegex, sizeof(regex_t));
- if (!patternCompile(pattern, (regex_t *)CFDataGetBytePtr(pRegex), &err)) {
+ /* ALIGN: CF aligns to >8 byte boundries */
+ if (!patternCompile(pattern, (regex_t *)(void *)CFDataGetBytePtr(pRegex), &err)) {
CFRelease(err);
CFRelease(pRegex);
CFRelease(pInfo);
/* identify/add all existing keys that match the specified pattern */
context.pInfo = pInfo;
- context.preg = (regex_t *)CFDataGetBytePtr(pRegex);
+ /* ALIGN: CF aligns to >8 byte boundries */
+ context.preg = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
my_CFDictionaryApplyFunction(storeData,
(CFDictionaryApplierFunction)identifyKeyForPattern,
&context);
CFDataRef pRegex;
pRegex = CFArrayGetValueAtIndex(pInfo, 0);
- regfree((regex_t *)CFDataGetBytePtr(pRegex));
+ /* ALIGN: CF aligns to >8 byte boundries */
+ regfree((regex_t *)(void *)CFDataGetBytePtr(pRegex));
}
CFArrayReplaceValues(pInfo, CFRangeMake(0, 2), NULL, 0);
/* if no other sessions are watching this pattern */
pRegex = CFArrayGetValueAtIndex(pInfo, 0);
- regfree((regex_t *)CFDataGetBytePtr(pRegex));
+ /* ALIGN: CF aligns to >8 byte boundries */
+ regfree((regex_t *)(void *)CFDataGetBytePtr(pRegex));
CFDictionaryRemoveValue(patternData, pattern);
}
}
/* compare new store key to regular expression pattern */
- preg = (regex_t *)CFDataGetBytePtr(CFArrayGetValueAtIndex(pInfo, 0));
+ /* ALIGN: CF aligns to >8 byte boundries */
+ preg = (regex_t *)(void *)CFDataGetBytePtr(CFArrayGetValueAtIndex(pInfo, 0));
reError = regexec(preg, str, 0, NULL, 0);
switch (reError) {
case 0 : {
/*
- * Copyright (c) 2000-2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2009, 2011, 2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "configd.h"
#include "configd_server.h"
#include <SystemConfiguration/SCDPlugin.h>
+#include "SCNetworkReachabilityInternal.h"
void _SCDPluginExecInit();
#define BUNDLE_DIR_EXTENSION ".bundle"
+#define PLUGIN_ALL(p) CFSTR(p)
+#if !TARGET_OS_EMBEDDED
+#define PLUGIN_MACOSX(p) CFSTR(p)
+#define PLUGIN_IOS(p) NULL
+#else // !TARGET_OS_EMBEDDED
+#define PLUGIN_MACOSX(p) NULL
+#define PLUGIN_IOS(p) CFSTR(p)
+#endif // !TARGET_OS_EMBEDDED
+
+// white-listed (ok-to-load) bundle identifiers
+static const CFStringRef pluginWhitelist[] = {
+ PLUGIN_MACOSX("com.apple.SystemConfiguration.Apple80211"),
+ PLUGIN_MACOSX("com.apple.SystemConfiguration.ApplicationFirewall"),
+ PLUGIN_MACOSX("com.apple.SystemConfiguration.Bluetooth"),
+ PLUGIN_ALL ("com.apple.SystemConfiguration.EAPOLController"),
+ PLUGIN_ALL ("com.apple.SystemConfiguration.IPConfiguration"),
+ PLUGIN_ALL ("com.apple.SystemConfiguration.IPMonitor"),
+ PLUGIN_ALL ("com.apple.SystemConfiguration.InterfaceNamer"),
+ PLUGIN_ALL ("com.apple.SystemConfiguration.KernelEventMonitor"),
+ PLUGIN_ALL ("com.apple.SystemConfiguration.LinkConfiguration"),
+ PLUGIN_ALL ("com.apple.SystemConfiguration.Logger"),
+ PLUGIN_ALL ("com.apple.SystemConfiguration.PPPController"),
+ PLUGIN_ALL ("com.apple.SystemConfiguration.PreferencesMonitor"),
+#ifdef HAVE_REACHABILITY_SERVER
+ PLUGIN_ALL ("com.apple.SystemConfiguration.SCNetworkReachability"),
+#endif // HAVE_REACHABILITY_SERVER
+ PLUGIN_MACOSX("com.apple.SystemConfiguration.wwanConfig"),
+ PLUGIN_MACOSX("com.apple.print.notification"),
+};
+#define N_PLUGIN_WHITELIST (sizeof(pluginWhitelist) / sizeof(pluginWhitelist[0]))
+
+
typedef struct {
CFBundleRef bundle;
Boolean loaded;
Boolean builtin;
Boolean enabled;
+ Boolean forced;
Boolean verbose;
SCDynamicStoreBundleLoadFunction load;
SCDynamicStoreBundleStartFunction start;
extern SCDynamicStoreBundleLoadFunction load_LinkConfiguration;
extern SCDynamicStoreBundleLoadFunction load_PreferencesMonitor;
extern SCDynamicStoreBundlePrimeFunction prime_PreferencesMonitor;
-extern SCDynamicStoreBundleLoadFunction load_NetworkIdentification;
-extern SCDynamicStoreBundlePrimeFunction prime_NetworkIdentification;
+#ifdef HAVE_REACHABILITY_SERVER
+extern SCDynamicStoreBundleLoadFunction load_SCNetworkReachability;
+#endif // HAVE_REACHABILITY_SERVER
typedef struct {
NULL
},
{
- CFSTR("com.apple.SystemConfiguration.NetworkIdentification"),
- &load_NetworkIdentification,
+ CFSTR("com.apple.SystemConfiguration.PreferencesMonitor"),
+ &load_PreferencesMonitor,
NULL,
- &prime_NetworkIdentification,
+ &prime_PreferencesMonitor,
NULL
},
+#ifdef HAVE_REACHABILITY_SERVER
{
- CFSTR("com.apple.SystemConfiguration.PreferencesMonitor"),
- &load_PreferencesMonitor,
+ CFSTR("com.apple.SystemConfiguration.SCNetworkReachability"),
+ &load_SCNetworkReachability,
+ NULL,
NULL,
- &prime_PreferencesMonitor,
NULL
- }
+ },
+#endif // HAVE_REACHABILITY_SERVER
};
bundleInfo->loaded = FALSE;
bundleInfo->builtin = FALSE;
bundleInfo->enabled = TRUE;
+ bundleInfo->forced = forceEnabled;
bundleInfo->verbose = FALSE;
bundleInfo->load = NULL;
bundleInfo->start = NULL;
}
}
- if (forceEnabled) {
- bundleInfo->enabled = TRUE;
- }
-
CFArrayAppendValue(allBundles, bundleInfo);
return;
}
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
shortBundleIdentifier(CFStringRef bundleID)
{
CFIndex len = CFStringGetLength(bundleID);
static void
loadBundle(const void *value, void *context) {
CFStringRef bundleID;
+ Boolean bundleAllowed;
bundleInfoRef bundleInfo = (bundleInfoRef)value;
Boolean bundleExclude;
CFIndex *nLoaded = (CFIndex *)context;
shortID = shortBundleIdentifier(bundleID);
- bundleExclude = CFSetContainsValue(_plugins_exclude, bundleID);
- if (!bundleExclude) {
- if (shortID != NULL) {
- bundleExclude = CFSetContainsValue(_plugins_exclude, shortID);
- }
+ bundleAllowed = ((CFSetGetCount(_plugins_allowed) == 0) || // if no white-listing
+ CFSetContainsValue(_plugins_allowed, bundleID) || // if [bundleID] white-listed
+ ((shortID != NULL) &&
+ CFSetContainsValue(_plugins_allowed, shortID))|| // if [short bundleID] white-listed
+ bundleInfo->forced // if "testing" plugin
+ );
+ if (!bundleAllowed) {
+ SCLog(TRUE, LOG_WARNING, CFSTR("skipped %@ (not allowed)"), bundleID);
+ goto done;
}
+ bundleExclude = (CFSetContainsValue(_plugins_exclude, bundleID) || // if [bundleID] excluded
+ ((shortID != NULL) &&
+ CFSetContainsValue(_plugins_exclude, shortID)) // if [short bundleID] excluded
+ );
if (bundleExclude) {
// sorry, this bundle has been excluded
SCLog(TRUE, LOG_NOTICE, CFSTR("skipped %@ (excluded)"), bundleID);
goto done;
}
- if (!bundleInfo->enabled) {
+ if (!bundleInfo->enabled && !bundleInfo->forced) {
// sorry, this bundle has not been enabled
SCLog(TRUE, LOG_INFO, CFSTR("skipped %@ (disabled)"), bundleID);
goto done;
}
- if (_plugins_fork) {
+ if (_plugins_fork &&
+ !_SC_CFEqual(bundleID, CFSTR("com.apple.SystemConfiguration.SCNetworkReachability"))) {
forkBundle(bundleInfo->bundle, bundleID);
goto done;
}
void *
plugin_exec(void *arg)
{
+ int i;
CFIndex nLoaded = 0;
/* keep track of bundles */
allBundles = CFArrayCreateMutable(NULL, 0, NULL);
+ /* add white-listed plugins to those we'll allow to be loaded */
+ for (i = 0; i < N_PLUGIN_WHITELIST; i++) {
+ if (pluginWhitelist[i] != NULL) {
+ CFSetSetValue(_plugins_allowed, pluginWhitelist[i]);
+ }
+ }
+
/* allow plug-ins to exec child/helper processes */
_SCDPluginExecInit();
CFRelease(url);
}
+ /*
+ * Look for the InterfaceNamer plugin, and move it to the start
+ * of the list.
+ *
+ * Load the InterfaceNamer plugin (and thereby start its thread)
+ * first in an attempt to minimize the amount of time that
+ * opendirectoryd has to wait for the platform UUID to appear in
+ * nvram.
+ *
+ * InterfaceNamer is responsible for creating the platform UUID on
+ * platforms without a UUID in ROM. Until the platform UUID is created
+ * and stashed in nvram, all calls to opendirectoryd to do things like
+ * getpwuid() will block, because opendirectoryd will block while trying
+ * to read the platform UUID from the kernel.
+ *
+ * As an example, dlopen() causes XPC to do some intialization, and
+ * part of that initialization involves communicating with xpcd.
+ * Since xpcd calls getpwuid_r() during its initialization, it will
+ * block until the platform UUID is available.
+ */
+ for (int i = 0; i < CFArrayGetCount(allBundles); i++) {
+ bundleInfoRef bi = (bundleInfoRef)CFArrayGetValueAtIndex(allBundles, i);
+ CFStringRef bundleID = CFBundleGetIdentifier(bi->bundle);
+
+ if (_SC_CFEqual(bundleID,
+ CFSTR("com.apple.SystemConfiguration.InterfaceNamer")))
+ {
+ CFArrayRemoveValueAtIndex(allBundles, i);
+ CFArrayInsertValueAtIndex(allBundles, 0, bi);
+ break;
+ }
+ }
+
#ifdef DEBUG
traceBundle("before loading any plugins", NULL);
#endif /* DEBUG */
/* information maintained for each active session */
-static serverSessionRef *sessions = NULL;
-static int nSessions = 0;
+static serverSessionRef *sessions = NULL;
+static int nSessions = 0; /* # of allocated sessions */
+static int lastSession = -1; /* # of last used session */
/* CFMachPortInvalidation runloop */
static CFRunLoopRef sessionRunLoop = NULL;
+/* temp session */
+static serverSessionRef temp_session = NULL;
+
static void
CFMachPortInvalidateSessionCallback(CFMachPortRef port, void *info)
return NULL;
}
- for (i = 0; i < nSessions; i++) {
+ /* look for matching session (note: slot 0 is the "server" port) */
+ for (i = 1; i <= lastSession; i++) {
serverSessionRef thisSession = sessions[i];
if (thisSession == NULL) {
/* found an empty slot, skip it */
continue;
- } else if (thisSession->key == server) {
- return thisSession; /* we've seen this server before */
- } else if (thisSession->store &&
- (((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask == server)) {
+ }
+
+ if (thisSession->key == server) {
+ /* we've seen this server before */
+ return thisSession;
+ }
+
+ if ((thisSession->store != NULL) &&
+ (((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask == server)) {
+ /* we've seen this task port before */
return thisSession;
}
}
}
+__private_extern__
+serverSessionRef
+tempSession(mach_port_t server, CFStringRef name, audit_token_t auditToken)
+{
+ static dispatch_once_t once;
+ SCDynamicStorePrivateRef storePrivate;
+
+ if (sessions[0]->key != server) {
+ // if not SCDynamicStore "server" port
+ return NULL;
+ }
+
+ dispatch_once(&once, ^{
+ temp_session = sessions[0]; /* use "server" session */
+ (void) __SCDynamicStoreOpen(&temp_session->store, NULL);
+ });
+
+ /* save audit token */
+ temp_session->auditToken = auditToken;
+ temp_session->callerEUID = -1; /* not "root" */
+ temp_session->callerRootAccess = UNKNOWN;
+ temp_session->callerWriteAccess = UNKNOWN;
+
+ /* save name */
+ storePrivate = (SCDynamicStorePrivateRef)temp_session->store;
+ if (storePrivate->name != NULL) CFRelease(storePrivate->name);
+ storePrivate->name = CFRetain(name);
+
+ return temp_session;
+}
+
+
__private_extern__
serverSessionRef
addSession(mach_port_t server, CFStringRef (*copyDescription)(const void *info))
}
if (nSessions <= 0) {
- /* new session (actually, the first) found */
- sessions = malloc(sizeof(serverSessionRef));
- n = 0;
- nSessions = 1;
+ /* if first session (the "server" port) */
+ n = 0; /* use slot "0" */
+ lastSession = 0; /* last used slot */
+
+ nSessions = 64;
+ sessions = malloc(nSessions * sizeof(serverSessionRef));
} else {
int i;
- for (i = 0; i < nSessions; i++) {
- if (sessions[i] == NULL) {
- /* found an empty slot, use it */
- n = i;
- break;
+ /* check to see if we already have an open session (note: slot 0 is the "server" port) */
+ for (i = 1; i <= lastSession; i++) {
+ serverSessionRef thisSession = sessions[i];
+
+ if (thisSession == NULL) {
+ /* found an empty slot */
+ if (n < 0) {
+ /* keep track of the first [empty] slot */
+ n = i;
+ }
+
+ /* and keep looking for a matching session */
+ continue;
+ }
+
+ if (thisSession->key == server) {
+ /* we've seen this server before */
+ return NULL;
+ }
+
+ if ((thisSession->store != NULL) &&
+ (((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask == server)) {
+ /* we've seen this task port before */
+ return NULL;
}
}
- /* new session identified */
+
+ /* add a new session */
if (n < 0) {
- /* no empty slots, add one to the list */
- n = nSessions++;
- sessions = reallocf(sessions, ((nSessions) * sizeof(serverSessionRef)));
+ /* if no empty slots */
+ n = ++lastSession;
+ if (lastSession >= nSessions) {
+ /* expand the session list */
+ nSessions *= 2;
+ sessions = reallocf(sessions, (nSessions * sizeof(serverSessionRef)));
+ }
}
+
+ // create mach port for SCDynamicStore client
+ mp = MACH_PORT_NULL;
+ (void) mach_port_allocate(mach_task_self(),
+ MACH_PORT_RIGHT_RECEIVE,
+ &mp);
}
// allocate a new session for this server
bzero(sessions[n], sizeof(serverSession));
// create server port
- context.info = sessions[n];
- context.copyDescription = copyDescription;
-
- if (server == MACH_PORT_NULL) {
- // create mach port for SCDynamicStore client
- (void) mach_port_allocate(mach_task_self(),
- MACH_PORT_RIGHT_RECEIVE,
- &mp);
- }
+ context.info = sessions[n];
+ context.copyDescription = copyDescription;
//
// Note: we create the CFMachPort *before* we insert a send
CFMachPortSetInvalidationCallBack(sessions[n]->serverPort,
CFMachPortInvalidateSessionCallback);
- if (server == MACH_PORT_NULL) {
+ if (n > 0) {
// insert send right that will be moved to the client
(void) mach_port_insert_right(mach_task_self(),
mp,
__private_extern__
void
-removeSession(mach_port_t server)
+cleanupSession(mach_port_t server)
{
- int i;
- serverSessionRef thisSession;
- CFStringRef sessionKey;
+ int i;
- for (i = 0; i < nSessions; i++) {
- thisSession = sessions[i];
+ for (i = 1; i <= lastSession; i++) {
+ CFStringRef sessionKey;
+ serverSessionRef thisSession = sessions[i];
if (thisSession == NULL) {
/* found an empty slot, skip it */
continue;
- } else if (thisSession->key == server) {
- /*
- * We don't need any remaining information in the
- * sessionData dictionary, remove it.
- */
- sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), server);
- CFDictionaryRemoveValue(sessionData, sessionKey);
- CFRelease(sessionKey);
-
- /*
- * Lastly, get rid of the per-session structure.
- */
- free(thisSession);
- sessions[i] = NULL;
-
- return;
}
- }
-
- return;
-}
-
-
-__private_extern__
-void
-cleanupSession(mach_port_t server)
-{
- int i;
- for (i = 0; i < nSessions; i++) {
- serverSessionRef thisSession = sessions[i];
-
- if ((thisSession != NULL) && (thisSession->key == server)) {
+ if (thisSession->key == server) {
/*
* session entry still exists.
*/
SCTrace(TRUE, _configd_trace, CFSTR("cleanup : %5d\n"), server);
}
- /*
- * Ensure that any changes made while we held the "lock"
- * are discarded.
- */
- if ((storeLocked > 0) &&
- ((SCDynamicStorePrivateRef)thisSession->store)->locked) {
- /*
- * swap store and associated data which, after
- * being closed, will result in the restoration
- * of the original pre-"locked" data.
- */
- _swapLockedStoreData();
- }
-
/*
* Close any open connections including cancelling any outstanding
* notification requests and releasing any locks.
*/
__MACH_PORT_DEBUG(TRUE, "*** cleanupSession", server);
- (void) __SCDynamicStoreClose(&thisSession->store, TRUE);
+ (void) __SCDynamicStoreClose(&thisSession->store);
__MACH_PORT_DEBUG(TRUE, "*** cleanupSession (after __SCDynamicStoreClose)", server);
/*
(void) mach_port_mod_refs(mach_task_self(), server, MACH_PORT_RIGHT_RECEIVE, -1);
/*
- * Lastly, remove the session entry.
+ * We don't need any remaining information in the
+ * sessionData dictionary, remove it.
+ */
+ sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), server);
+ CFDictionaryRemoveValue(sessionData, sessionKey);
+ CFRelease(sessionKey);
+
+ /*
+ * get rid of the per-session structure.
*/
- removeSession(server);
+ free(thisSession);
+ sessions[i] = NULL;
+
+ if (i == lastSession) {
+ /* we are removing the last session, update last used slot */
+ while (--lastSession > 0) {
+ if (sessions[lastSession] != NULL) {
+ break;
+ }
+ }
+ }
return;
}
int i;
SCPrint(TRUE, f, CFSTR("Current sessions :\n"));
- for (i = 0; i < nSessions; i++) {
+ for (i = 0; i <= lastSession; i++) {
serverSessionRef thisSession = sessions[i];
if (thisSession == NULL) {
/*
- * Copyright (c) 2000, 2001, 2005-2007, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2005-2007, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
serverSessionRef getSession (mach_port_t server);
+serverSessionRef tempSession (mach_port_t server,
+ CFStringRef name,
+ audit_token_t auditToken);
+
serverSessionRef addSession (mach_port_t server,
CFStringRef (*copyDescription)(const void *info));
-void removeSession (mach_port_t server);
-
void cleanupSession (mach_port_t server);
void listSessions (FILE *f);
archiveVersion = 1;
classes = {
};
- objectVersion = 45;
+ objectVersion = 46;
objects = {
/* Begin PBXAggregateTarget section */
1558480607550D470046C2E9 /* PBXTargetDependency */,
1558480807550D470046C2E9 /* PBXTargetDependency */,
1558480A07550D470046C2E9 /* PBXTargetDependency */,
+ D6DDAC3D147A24BC00A2E902 /* PBXTargetDependency */,
150ECB300D0042DA0065E94D /* PBXTargetDependency */,
);
name = configd_executables;
);
dependencies = (
157BB8C0075924460025DA7A /* PBXTargetDependency */,
- 1520A386084681350010B584 /* PBXTargetDependency */,
);
name = configd_base;
productName = Frameworks;
buildPhases = (
);
dependencies = (
- 157A85480D56CA0B00B6F1A0 /* PBXTargetDependency */,
- 158317BB0CFB8660006F62B9 /* PBXTargetDependency */,
157A854A0D56CA2300B6F1A0 /* PBXTargetDependency */,
158317B90CFB8660006F62B9 /* PBXTargetDependency */,
+ 157A85480D56CA0B00B6F1A0 /* PBXTargetDependency */,
+ 158317BB0CFB8660006F62B9 /* PBXTargetDependency */,
157A854C0D56CA5100B6F1A0 /* PBXTargetDependency */,
158317B70CFB8660006F62B9 /* PBXTargetDependency */,
157A854E0D56CA6F00B6F1A0 /* PBXTargetDependency */,
158317B50CFB8660006F62B9 /* PBXTargetDependency */,
156CA4A80EF8550800C59A18 /* PBXTargetDependency */,
- 157A85500D56CA8800B6F1A0 /* PBXTargetDependency */,
- 158317B30CFB8660006F62B9 /* PBXTargetDependency */,
157A85520D56CA9E00B6F1A0 /* PBXTargetDependency */,
157A85540D56CACA00B6F1A0 /* PBXTargetDependency */,
+ 1528C00F135741C300691881 /* PBXTargetDependency */,
+ 1528C011135741C300691881 /* PBXTargetDependency */,
);
name = "configd_plugins-Embedded";
productName = Plugins;
buildPhases = (
);
dependencies = (
- 15AC5189108396D2004A9ED5 /* PBXTargetDependency */,
- 15AC5187108396D2004A9ED5 /* PBXTargetDependency */,
15AC5185108396D2004A9ED5 /* PBXTargetDependency */,
15AC5183108396D2004A9ED5 /* PBXTargetDependency */,
+ 15AC5189108396D2004A9ED5 /* PBXTargetDependency */,
+ 15AC5187108396D2004A9ED5 /* PBXTargetDependency */,
15AC5181108396D2004A9ED5 /* PBXTargetDependency */,
15AC517F108396D2004A9ED5 /* PBXTargetDependency */,
15AC517D108396D2004A9ED5 /* PBXTargetDependency */,
15AC517B108396D2004A9ED5 /* PBXTargetDependency */,
15AC5179108396D2004A9ED5 /* PBXTargetDependency */,
- 15AC5177108396D2004A9ED5 /* PBXTargetDependency */,
- 15AC5175108396D2004A9ED5 /* PBXTargetDependency */,
15AC5173108396D2004A9ED5 /* PBXTargetDependency */,
15AC5171108396D2004A9ED5 /* PBXTargetDependency */,
+ 1528C0131357420300691881 /* PBXTargetDependency */,
+ 1528C0151357420300691881 /* PBXTargetDependency */,
);
name = "configd_plugins-EmbeddedOther";
productName = Plugins;
buildPhases = (
);
dependencies = (
- 159D542807528E85004F8947 /* PBXTargetDependency */,
- 158AD9860754E72500124717 /* PBXTargetDependency */,
- 159D542607528E85004F8947 /* PBXTargetDependency */,
- 158AD9880754E72500124717 /* PBXTargetDependency */,
15828B070753B77E00AD4710 /* PBXTargetDependency */,
159D542207528E85004F8947 /* PBXTargetDependency */,
+ 159D542607528E85004F8947 /* PBXTargetDependency */,
+ 158AD9880754E72500124717 /* PBXTargetDependency */,
+ 159D542807528E85004F8947 /* PBXTargetDependency */,
+ 158AD9860754E72500124717 /* PBXTargetDependency */,
159D542A07528E85004F8947 /* PBXTargetDependency */,
158AD98C0754E72500124717 /* PBXTargetDependency */,
1521405B0E9400BF00DACD2C /* PBXTargetDependency */,
159D542C07528E85004F8947 /* PBXTargetDependency */,
158AD98E0754E72500124717 /* PBXTargetDependency */,
- F95B8A790B03FB9100993BA3 /* PBXTargetDependency */,
- F95B8A770B03FB9100993BA3 /* PBXTargetDependency */,
+ 1528BFEC135731B800691881 /* PBXTargetDependency */,
+ 1528BFEE135731B800691881 /* PBXTargetDependency */,
);
name = configd_plugins;
productName = Plugins;
15060818075A00A300B147BA /* SCSchemaDefinitions.c in Sources */ = {isa = PBXBuildFile; fileRef = 150607BD075A00A200B147BA /* SCSchemaDefinitions.c */; };
1506081A075A00A300B147BA /* SCSchemaDefinitions.h in Headers */ = {isa = PBXBuildFile; fileRef = 150607DE075A00A300B147BA /* SCSchemaDefinitions.h */; settings = {ATTRIBUTES = (Public, ); }; };
150D7E1E0D16DC6C00AF4BED /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1520A3DE0846B2DC0010B584 /* Security.framework */; };
+ 151E0CA31378EE1000C5DA2A /* network_information.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A781368913C0091C931 /* network_information.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 151E0CA51378EE3B00C5DA2A /* network_information.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A77136891300091C931 /* network_information.c */; };
1520A3870846829A0010B584 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
1520A3DF0846B2DD0010B584 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1520A3DE0846B2DC0010B584 /* Security.framework */; };
152140020E93EC6500DACD2C /* logger.c in Sources */ = {isa = PBXBuildFile; fileRef = 1531D3DB0E93E6DA00248432 /* logger.c */; };
1521400C0E93FFF500DACD2C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
152140580E93FFFC00DACD2C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1559C4440D349A4E0098FD59 /* SystemConfiguration.framework */; };
1522FCFB0FA7FE4B00B24128 /* dnsinfo_flatfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 1522FCE50FA7FD7000B24128 /* dnsinfo_flatfile.c */; };
- 152691D81129EE8A006BD2D5 /* BondConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 9EE943F306AF409B00772EB5 /* BondConfiguration.c */; };
- 152691D91129EE94006BD2D5 /* BondConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 9EE943F306AF409B00772EB5 /* BondConfiguration.c */; };
- 152691DA1129EE98006BD2D5 /* BondConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 9EE943F306AF409B00772EB5 /* BondConfiguration.c */; };
152691DB1129EEA6006BD2D5 /* BridgeConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FD7B3B101E439200C56621 /* BridgeConfiguration.c */; };
152691DC1129EEAD006BD2D5 /* BridgeConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FD7B3B101E439200C56621 /* BridgeConfiguration.c */; };
152691DD1129EEB1006BD2D5 /* BridgeConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FD7B3B101E439200C56621 /* BridgeConfiguration.c */; };
152691DE1129EEC2006BD2D5 /* VLANConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B605C0722B0099E85F /* VLANConfiguration.c */; };
152691DF1129EEC8006BD2D5 /* VLANConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B605C0722B0099E85F /* VLANConfiguration.c */; };
152691E01129EECB006BD2D5 /* VLANConfiguration.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69B605C0722B0099E85F /* VLANConfiguration.c */; };
+ 1528BFEF135733F500691881 /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
+ 1528BFF313573FEE00691881 /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
+ 1528C0021357401900691881 /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
+ 1528C0171357465900691881 /* libSCNetworkReachability.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1528BFF713573FEE00691881 /* libSCNetworkReachability.a */; };
+ 1528C019135746BB00691881 /* libSCNetworkReachability.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1528BFE21357305400691881 /* libSCNetworkReachability.a */; };
+ 1528C01A135746D700691881 /* libSCNetworkReachability.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1528C0061357401900691881 /* libSCNetworkReachability.a */; };
152E0E7F10FE820E00E402F2 /* helper.defs in Sources */ = {isa = PBXBuildFile; fileRef = 152E0E7E10FE820E00E402F2 /* helper.defs */; settings = {ATTRIBUTES = (Server, ); }; };
152E0E8010FE820E00E402F2 /* helper.defs in Sources */ = {isa = PBXBuildFile; fileRef = 152E0E7E10FE820E00E402F2 /* helper.defs */; settings = {ATTRIBUTES = (Server, ); }; };
152E0E8110FE820E00E402F2 /* helper.defs in Sources */ = {isa = PBXBuildFile; fileRef = 152E0E7E10FE820E00E402F2 /* helper.defs */; settings = {ATTRIBUTES = (Server, ); }; };
152E0E8B10FE824000E402F2 /* helper_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 152E0E8810FE824000E402F2 /* helper_types.h */; };
152E68C10A2C89C70011FDA8 /* SCPreferencesKeychainPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 152E68C00A2C89C70011FDA8 /* SCPreferencesKeychainPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
152E68C30A2C89E30011FDA8 /* SCPreferencesKeychainPrivate.c in Sources */ = {isa = PBXBuildFile; fileRef = 152E68C20A2C89E30011FDA8 /* SCPreferencesKeychainPrivate.c */; };
- 1533D77B0B10A14300CA4946 /* libNetworkIdentification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F95B8A5F0B03F81400993BA3 /* libNetworkIdentification.a */; };
1540E3610987DA9500157C07 /* com.apple.configd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1540E3600987DA9500157C07 /* com.apple.configd.plist */; };
154361E00752C81800A8EC6C /* set-hostname.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53AB07528B36004F8947 /* set-hostname.c */; };
1543636B0752D03C00A8EC6C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1543636A0752D03C00A8EC6C /* IOKit.framework */; };
1572C4E20CFB55B400E2776E /* SCDPrivate.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695405C0722B0099E85F /* SCDPrivate.c */; settings = {ATTRIBUTES = (); }; };
1572C4E30CFB55B400E2776E /* SCDPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695605C0722B0099E85F /* SCDPlugin.c */; settings = {ATTRIBUTES = (); }; };
1572C4E40CFB55B400E2776E /* SCDOpen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695805C0722B0099E85F /* SCDOpen.c */; settings = {ATTRIBUTES = (); }; };
- 1572C4E50CFB55B400E2776E /* SCDLock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695A05C0722B0099E85F /* SCDLock.c */; settings = {ATTRIBUTES = (); }; };
- 1572C4E60CFB55B400E2776E /* SCDUnlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695C05C0722B0099E85F /* SCDUnlock.c */; settings = {ATTRIBUTES = (); }; };
1572C4E70CFB55B400E2776E /* SCDList.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695E05C0722B0099E85F /* SCDList.c */; settings = {ATTRIBUTES = (); }; };
1572C4E80CFB55B400E2776E /* SCDAdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696005C0722B0099E85F /* SCDAdd.c */; settings = {ATTRIBUTES = (); }; };
1572C4E90CFB55B400E2776E /* SCDGet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696405C0722B0099E85F /* SCDGet.c */; settings = {ATTRIBUTES = (); }; };
1572C4EA0CFB55B400E2776E /* SCDSet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696605C0722B0099E85F /* SCDSet.c */; settings = {ATTRIBUTES = (); }; };
1572C4EB0CFB55B400E2776E /* SCDRemove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696805C0722B0099E85F /* SCDRemove.c */; settings = {ATTRIBUTES = (); }; };
- 1572C4EC0CFB55B400E2776E /* SCDTouch.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696A05C0722B0099E85F /* SCDTouch.c */; settings = {ATTRIBUTES = (); }; };
1572C4ED0CFB55B400E2776E /* SCDNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696C05C0722B0099E85F /* SCDNotify.c */; settings = {ATTRIBUTES = (); }; };
1572C4EE0CFB55B400E2776E /* SCDNotifierSetKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696E05C0722B0099E85F /* SCDNotifierSetKeys.c */; settings = {ATTRIBUTES = (); }; };
1572C4EF0CFB55B400E2776E /* SCDNotifierAdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697005C0722B0099E85F /* SCDNotifierAdd.c */; settings = {ATTRIBUTES = (); }; };
1572C4F10CFB55B400E2776E /* SCDNotifierGetChanges.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697405C0722B0099E85F /* SCDNotifierGetChanges.c */; settings = {ATTRIBUTES = (); }; };
1572C4F20CFB55B400E2776E /* SCDNotifierWait.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697605C0722B0099E85F /* SCDNotifierWait.c */; settings = {ATTRIBUTES = (); }; };
1572C4F30CFB55B400E2776E /* SCDNotifierInformViaCallback.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697805C0722B0099E85F /* SCDNotifierInformViaCallback.c */; settings = {ATTRIBUTES = (); }; };
- 1572C4F40CFB55B400E2776E /* SCDNotifierInformViaMachPort.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697A05C0722B0099E85F /* SCDNotifierInformViaMachPort.c */; settings = {ATTRIBUTES = (); }; };
1572C4F50CFB55B400E2776E /* SCDNotifierInformViaFD.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697C05C0722B0099E85F /* SCDNotifierInformViaFD.c */; settings = {ATTRIBUTES = (); }; };
1572C4F60CFB55B400E2776E /* SCDNotifierInformViaSignal.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697E05C0722B0099E85F /* SCDNotifierInformViaSignal.c */; settings = {ATTRIBUTES = (); }; };
1572C4F70CFB55B400E2776E /* SCDNotifierCancel.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698005C0722B0099E85F /* SCDNotifierCancel.c */; settings = {ATTRIBUTES = (); }; };
157A851D0D56C8E000B6F1A0 /* ev_ipv6.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53B407528B36004F8947 /* ev_ipv6.c */; };
157A851E0D56C8E000B6F1A0 /* eventmon.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53B007528B36004F8947 /* eventmon.c */; };
157A85290D56C91100B6F1A0 /* linkconfig.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53C107528B36004F8947 /* linkconfig.c */; };
- 157A85340D56C94F00B6F1A0 /* NetworkIdentification.c in Sources */ = {isa = PBXBuildFile; fileRef = F95B8A680B03F97800993BA3 /* NetworkIdentification.c */; };
157A853F0D56C96F00B6F1A0 /* prefsmon.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53C307528B36004F8947 /* prefsmon.c */; };
157A88890A470D0F003A4256 /* SCSchemaDefinitionsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 157A88880A470D0F003A4256 /* SCSchemaDefinitionsPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
158317250CFB80A1006F62B9 /* configd.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69CF05C0722B0099E85F /* configd.h */; };
158317330CFB80A1006F62B9 /* pattern.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69EC05C0722B0099E85F /* pattern.c */; settings = {ATTRIBUTES = (); }; };
158317340CFB80A1006F62B9 /* _configopen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F005C0722B0099E85F /* _configopen.c */; settings = {ATTRIBUTES = (); }; };
158317350CFB80A1006F62B9 /* _configclose.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F205C0722B0099E85F /* _configclose.c */; settings = {ATTRIBUTES = (); }; };
- 158317360CFB80A1006F62B9 /* _configlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F405C0722B0099E85F /* _configlock.c */; settings = {ATTRIBUTES = (); }; };
158317370CFB80A1006F62B9 /* _configunlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F605C0722B0099E85F /* _configunlock.c */; settings = {ATTRIBUTES = (); }; };
158317380CFB80A1006F62B9 /* _configlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F805C0722B0099E85F /* _configlist.c */; settings = {ATTRIBUTES = (); }; };
158317390CFB80A1006F62B9 /* _configadd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69FA05C0722B0099E85F /* _configadd.c */; settings = {ATTRIBUTES = (); }; };
1583173A0CFB80A1006F62B9 /* _configget.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69FE05C0722B0099E85F /* _configget.c */; settings = {ATTRIBUTES = (); }; };
1583173B0CFB80A1006F62B9 /* _configset.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0005C0722B0099E85F /* _configset.c */; settings = {ATTRIBUTES = (); }; };
1583173C0CFB80A1006F62B9 /* _configremove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0205C0722B0099E85F /* _configremove.c */; settings = {ATTRIBUTES = (); }; };
- 1583173D0CFB80A1006F62B9 /* _configtouch.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0405C0722B0099E85F /* _configtouch.c */; settings = {ATTRIBUTES = (); }; };
1583173E0CFB80A1006F62B9 /* _confignotify.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0605C0722B0099E85F /* _confignotify.c */; settings = {ATTRIBUTES = (); }; };
1583173F0CFB80A1006F62B9 /* _notifyadd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0805C0722B0099E85F /* _notifyadd.c */; settings = {ATTRIBUTES = (); }; };
158317400CFB80A1006F62B9 /* _notifyremove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0A05C0722B0099E85F /* _notifyremove.c */; settings = {ATTRIBUTES = (); }; };
158317530CFB80A1006F62B9 /* libInterfaceNamer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53E507528C4A004F8947 /* libInterfaceNamer.a */; };
158317540CFB80A1006F62B9 /* libIPMonitor.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53EC07528C61004F8947 /* libIPMonitor.a */; };
158317550CFB80A1006F62B9 /* libLinkConfiguration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53F307528C79004F8947 /* libLinkConfiguration.a */; };
- 158317560CFB80A1006F62B9 /* libNetworkIdentification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F95B8A5F0B03F81400993BA3 /* libNetworkIdentification.a */; };
158317570CFB80A1006F62B9 /* libPreferencesMonitor.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53FA07528C95004F8947 /* libPreferencesMonitor.a */; };
1583175C0CFB80A1006F62B9 /* com.apple.configd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1540E3600987DA9500157C07 /* com.apple.configd.plist */; };
1583379C0CFB6B9E0033AB93 /* SCHelper_client.h in Headers */ = {isa = PBXBuildFile; fileRef = 155B7BF60847776D00F0E262 /* SCHelper_client.h */; };
1583EA53108395BB00A3BC0C /* SCDPrivate.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695405C0722B0099E85F /* SCDPrivate.c */; settings = {ATTRIBUTES = (); }; };
1583EA54108395BB00A3BC0C /* SCDPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695605C0722B0099E85F /* SCDPlugin.c */; settings = {ATTRIBUTES = (); }; };
1583EA55108395BB00A3BC0C /* SCDOpen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695805C0722B0099E85F /* SCDOpen.c */; settings = {ATTRIBUTES = (); }; };
- 1583EA56108395BB00A3BC0C /* SCDLock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695A05C0722B0099E85F /* SCDLock.c */; settings = {ATTRIBUTES = (); }; };
- 1583EA57108395BB00A3BC0C /* SCDUnlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695C05C0722B0099E85F /* SCDUnlock.c */; settings = {ATTRIBUTES = (); }; };
1583EA58108395BB00A3BC0C /* SCDList.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695E05C0722B0099E85F /* SCDList.c */; settings = {ATTRIBUTES = (); }; };
1583EA59108395BB00A3BC0C /* SCDAdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696005C0722B0099E85F /* SCDAdd.c */; settings = {ATTRIBUTES = (); }; };
1583EA5A108395BB00A3BC0C /* SCDGet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696405C0722B0099E85F /* SCDGet.c */; settings = {ATTRIBUTES = (); }; };
1583EA5B108395BB00A3BC0C /* SCDSet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696605C0722B0099E85F /* SCDSet.c */; settings = {ATTRIBUTES = (); }; };
1583EA5C108395BB00A3BC0C /* SCDRemove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696805C0722B0099E85F /* SCDRemove.c */; settings = {ATTRIBUTES = (); }; };
- 1583EA5D108395BB00A3BC0C /* SCDTouch.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696A05C0722B0099E85F /* SCDTouch.c */; settings = {ATTRIBUTES = (); }; };
1583EA5E108395BB00A3BC0C /* SCDNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696C05C0722B0099E85F /* SCDNotify.c */; settings = {ATTRIBUTES = (); }; };
1583EA5F108395BB00A3BC0C /* SCDNotifierSetKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696E05C0722B0099E85F /* SCDNotifierSetKeys.c */; settings = {ATTRIBUTES = (); }; };
1583EA60108395BB00A3BC0C /* SCDNotifierAdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697005C0722B0099E85F /* SCDNotifierAdd.c */; settings = {ATTRIBUTES = (); }; };
1583EA62108395BB00A3BC0C /* SCDNotifierGetChanges.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697405C0722B0099E85F /* SCDNotifierGetChanges.c */; settings = {ATTRIBUTES = (); }; };
1583EA63108395BB00A3BC0C /* SCDNotifierWait.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697605C0722B0099E85F /* SCDNotifierWait.c */; settings = {ATTRIBUTES = (); }; };
1583EA64108395BB00A3BC0C /* SCDNotifierInformViaCallback.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697805C0722B0099E85F /* SCDNotifierInformViaCallback.c */; settings = {ATTRIBUTES = (); }; };
- 1583EA65108395BB00A3BC0C /* SCDNotifierInformViaMachPort.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697A05C0722B0099E85F /* SCDNotifierInformViaMachPort.c */; settings = {ATTRIBUTES = (); }; };
1583EA66108395BB00A3BC0C /* SCDNotifierInformViaFD.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697C05C0722B0099E85F /* SCDNotifierInformViaFD.c */; settings = {ATTRIBUTES = (); }; };
1583EA67108395BB00A3BC0C /* SCDNotifierInformViaSignal.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697E05C0722B0099E85F /* SCDNotifierInformViaSignal.c */; settings = {ATTRIBUTES = (); }; };
1583EA68108395BB00A3BC0C /* SCDNotifierCancel.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698005C0722B0099E85F /* SCDNotifierCancel.c */; settings = {ATTRIBUTES = (); }; };
1583EB1A108395BC00A3BC0C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
1583EB1B108395BC00A3BC0C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1559C4440D349A4E0098FD59 /* SystemConfiguration.framework */; };
1583EB1C108395BC00A3BC0C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1543636A0752D03C00A8EC6C /* IOKit.framework */; };
- 1583EB26108395BD00A3BC0C /* NetworkIdentification.c in Sources */ = {isa = PBXBuildFile; fileRef = F95B8A680B03F97800993BA3 /* NetworkIdentification.c */; };
1583EB35108395BD00A3BC0C /* prefsmon.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53C307528B36004F8947 /* prefsmon.c */; };
1583EB4D108395BD00A3BC0C /* configd.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69CF05C0722B0099E85F /* configd.h */; };
1583EB4E108395BD00A3BC0C /* _SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D105C0722B0099E85F /* _SCD.h */; };
1583EB5B108395BD00A3BC0C /* pattern.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69EC05C0722B0099E85F /* pattern.c */; settings = {ATTRIBUTES = (); }; };
1583EB5C108395BD00A3BC0C /* _configopen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F005C0722B0099E85F /* _configopen.c */; settings = {ATTRIBUTES = (); }; };
1583EB5D108395BD00A3BC0C /* _configclose.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F205C0722B0099E85F /* _configclose.c */; settings = {ATTRIBUTES = (); }; };
- 1583EB5E108395BD00A3BC0C /* _configlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F405C0722B0099E85F /* _configlock.c */; settings = {ATTRIBUTES = (); }; };
1583EB5F108395BD00A3BC0C /* _configunlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F605C0722B0099E85F /* _configunlock.c */; settings = {ATTRIBUTES = (); }; };
1583EB60108395BD00A3BC0C /* _configlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F805C0722B0099E85F /* _configlist.c */; settings = {ATTRIBUTES = (); }; };
1583EB61108395BD00A3BC0C /* _configadd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69FA05C0722B0099E85F /* _configadd.c */; settings = {ATTRIBUTES = (); }; };
1583EB62108395BD00A3BC0C /* _configget.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69FE05C0722B0099E85F /* _configget.c */; settings = {ATTRIBUTES = (); }; };
1583EB63108395BD00A3BC0C /* _configset.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0005C0722B0099E85F /* _configset.c */; settings = {ATTRIBUTES = (); }; };
1583EB64108395BD00A3BC0C /* _configremove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0205C0722B0099E85F /* _configremove.c */; settings = {ATTRIBUTES = (); }; };
- 1583EB65108395BD00A3BC0C /* _configtouch.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0405C0722B0099E85F /* _configtouch.c */; settings = {ATTRIBUTES = (); }; };
1583EB66108395BD00A3BC0C /* _confignotify.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0605C0722B0099E85F /* _confignotify.c */; settings = {ATTRIBUTES = (); }; };
1583EB67108395BD00A3BC0C /* _notifyadd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0805C0722B0099E85F /* _notifyadd.c */; settings = {ATTRIBUTES = (); }; };
1583EB68108395BD00A3BC0C /* _notifyremove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0A05C0722B0099E85F /* _notifyremove.c */; settings = {ATTRIBUTES = (); }; };
1583EB7A108395BD00A3BC0C /* libInterfaceNamer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53E507528C4A004F8947 /* libInterfaceNamer.a */; };
1583EB7B108395BD00A3BC0C /* libIPMonitor.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53EC07528C61004F8947 /* libIPMonitor.a */; };
1583EB7C108395BD00A3BC0C /* libLinkConfiguration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53F307528C79004F8947 /* libLinkConfiguration.a */; };
- 1583EB7D108395BD00A3BC0C /* libNetworkIdentification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F95B8A5F0B03F81400993BA3 /* libNetworkIdentification.a */; };
1583EB7E108395BD00A3BC0C /* libPreferencesMonitor.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 159D53FA07528C95004F8947 /* libPreferencesMonitor.a */; };
1583EB80108395BD00A3BC0C /* com.apple.configd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1540E3600987DA9500157C07 /* com.apple.configd.plist */; };
1583EB89108395BE00A3BC0C /* scselect.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A2E05C0722B0099E85F /* scselect.c */; settings = {ATTRIBUTES = (); }; };
159D54B207529FFF004F8947 /* pattern.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69EC05C0722B0099E85F /* pattern.c */; settings = {ATTRIBUTES = (); }; };
159D54B307529FFF004F8947 /* _configopen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F005C0722B0099E85F /* _configopen.c */; settings = {ATTRIBUTES = (); }; };
159D54B407529FFF004F8947 /* _configclose.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F205C0722B0099E85F /* _configclose.c */; settings = {ATTRIBUTES = (); }; };
- 159D54B507529FFF004F8947 /* _configlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F405C0722B0099E85F /* _configlock.c */; settings = {ATTRIBUTES = (); }; };
159D54B607529FFF004F8947 /* _configunlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F605C0722B0099E85F /* _configunlock.c */; settings = {ATTRIBUTES = (); }; };
159D54B707529FFF004F8947 /* _configlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69F805C0722B0099E85F /* _configlist.c */; settings = {ATTRIBUTES = (); }; };
159D54B807529FFF004F8947 /* _configadd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69FA05C0722B0099E85F /* _configadd.c */; settings = {ATTRIBUTES = (); }; };
159D54B907529FFF004F8947 /* _configget.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB69FE05C0722B0099E85F /* _configget.c */; settings = {ATTRIBUTES = (); }; };
159D54BA07529FFF004F8947 /* _configset.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0005C0722B0099E85F /* _configset.c */; settings = {ATTRIBUTES = (); }; };
159D54BB07529FFF004F8947 /* _configremove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0205C0722B0099E85F /* _configremove.c */; settings = {ATTRIBUTES = (); }; };
- 159D54BC07529FFF004F8947 /* _configtouch.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0405C0722B0099E85F /* _configtouch.c */; settings = {ATTRIBUTES = (); }; };
159D54BD07529FFF004F8947 /* _confignotify.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0605C0722B0099E85F /* _confignotify.c */; settings = {ATTRIBUTES = (); }; };
159D54BE07529FFF004F8947 /* _notifyadd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0805C0722B0099E85F /* _notifyadd.c */; settings = {ATTRIBUTES = (); }; };
159D54BF07529FFF004F8947 /* _notifyremove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB6A0A05C0722B0099E85F /* _notifyremove.c */; settings = {ATTRIBUTES = (); }; };
15A5A2210D5B94190087BDA0 /* SCDPrivate.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695405C0722B0099E85F /* SCDPrivate.c */; settings = {ATTRIBUTES = (); }; };
15A5A2220D5B94190087BDA0 /* SCDPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695605C0722B0099E85F /* SCDPlugin.c */; settings = {ATTRIBUTES = (); }; };
15A5A2230D5B94190087BDA0 /* SCDOpen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695805C0722B0099E85F /* SCDOpen.c */; settings = {ATTRIBUTES = (); }; };
- 15A5A2240D5B94190087BDA0 /* SCDLock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695A05C0722B0099E85F /* SCDLock.c */; settings = {ATTRIBUTES = (); }; };
- 15A5A2250D5B94190087BDA0 /* SCDUnlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695C05C0722B0099E85F /* SCDUnlock.c */; settings = {ATTRIBUTES = (); }; };
15A5A2260D5B94190087BDA0 /* SCDList.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695E05C0722B0099E85F /* SCDList.c */; settings = {ATTRIBUTES = (); }; };
15A5A2270D5B94190087BDA0 /* SCDAdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696005C0722B0099E85F /* SCDAdd.c */; settings = {ATTRIBUTES = (); }; };
15A5A2280D5B94190087BDA0 /* SCDGet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696405C0722B0099E85F /* SCDGet.c */; settings = {ATTRIBUTES = (); }; };
15A5A2290D5B94190087BDA0 /* SCDSet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696605C0722B0099E85F /* SCDSet.c */; settings = {ATTRIBUTES = (); }; };
15A5A22A0D5B94190087BDA0 /* SCDRemove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696805C0722B0099E85F /* SCDRemove.c */; settings = {ATTRIBUTES = (); }; };
- 15A5A22B0D5B94190087BDA0 /* SCDTouch.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696A05C0722B0099E85F /* SCDTouch.c */; settings = {ATTRIBUTES = (); }; };
15A5A22C0D5B94190087BDA0 /* SCDNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696C05C0722B0099E85F /* SCDNotify.c */; settings = {ATTRIBUTES = (); }; };
15A5A22D0D5B94190087BDA0 /* SCDNotifierSetKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696E05C0722B0099E85F /* SCDNotifierSetKeys.c */; settings = {ATTRIBUTES = (); }; };
15A5A22E0D5B94190087BDA0 /* SCDNotifierAdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697005C0722B0099E85F /* SCDNotifierAdd.c */; settings = {ATTRIBUTES = (); }; };
15A5A2300D5B94190087BDA0 /* SCDNotifierGetChanges.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697405C0722B0099E85F /* SCDNotifierGetChanges.c */; settings = {ATTRIBUTES = (); }; };
15A5A2310D5B94190087BDA0 /* SCDNotifierWait.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697605C0722B0099E85F /* SCDNotifierWait.c */; settings = {ATTRIBUTES = (); }; };
15A5A2320D5B94190087BDA0 /* SCDNotifierInformViaCallback.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697805C0722B0099E85F /* SCDNotifierInformViaCallback.c */; settings = {ATTRIBUTES = (); }; };
- 15A5A2330D5B94190087BDA0 /* SCDNotifierInformViaMachPort.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697A05C0722B0099E85F /* SCDNotifierInformViaMachPort.c */; settings = {ATTRIBUTES = (); }; };
15A5A2340D5B94190087BDA0 /* SCDNotifierInformViaFD.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697C05C0722B0099E85F /* SCDNotifierInformViaFD.c */; settings = {ATTRIBUTES = (); }; };
15A5A2350D5B94190087BDA0 /* SCDNotifierInformViaSignal.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697E05C0722B0099E85F /* SCDNotifierInformViaSignal.c */; settings = {ATTRIBUTES = (); }; };
15A5A2360D5B94190087BDA0 /* SCDNotifierCancel.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698005C0722B0099E85F /* SCDNotifierCancel.c */; settings = {ATTRIBUTES = (); }; };
15B274A5114467CD003414AD /* nc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B43727113C7BFC00EBF1B6 /* nc.c */; };
15B274A6114467D8003414AD /* nc.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B43726113C7BFC00EBF1B6 /* nc.h */; };
15BAA32307F0699A00D9EC95 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15BAA32207F0699A00D9EC95 /* libbsm.dylib */; };
+ 15C330BC134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */; };
+ 15C330BD134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */; };
+ 15C330BE134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */; };
+ 15C330BF134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */; };
+ 15C330C0134B92780028E36B /* rb.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B8134B92780028E36B /* rb.c */; };
+ 15C330C1134B92780028E36B /* rb.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B8134B92780028E36B /* rb.c */; };
+ 15C330C2134B92780028E36B /* rb.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B8134B92780028E36B /* rb.c */; };
+ 15C330C3134B92780028E36B /* rb.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330B8134B92780028E36B /* rb.c */; };
+ 15C330C4134B92780028E36B /* rb.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330B9134B92780028E36B /* rb.h */; };
+ 15C330C5134B92780028E36B /* rb.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330B9134B92780028E36B /* rb.h */; };
+ 15C330C6134B92780028E36B /* rb.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330B9134B92780028E36B /* rb.h */; };
+ 15C330C7134B92780028E36B /* rb.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330B9134B92780028E36B /* rb.h */; };
+ 15C330D1134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */; };
+ 15C330D2134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */; };
+ 15C330D3134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */; };
+ 15C330D4134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */; };
+ 15C330E5134BD2AC0028E36B /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
+ 15C330E6134BD2BB0028E36B /* SCNetworkReachabilityServer_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */; };
15D48EBF0F67061600B4711E /* dnsinfo_create.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521FC5C060F296A003B28F5 /* dnsinfo_create.c */; };
15D48EC00F67061700B4711E /* dnsinfo_create.h in Headers */ = {isa = PBXBuildFile; fileRef = 1532629006281C9D00B1C10C /* dnsinfo_create.h */; };
15D48EC10F67061F00B4711E /* dnsinfo_create.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521FC5C060F296A003B28F5 /* dnsinfo_create.c */; };
15D48EC20F67061F00B4711E /* dnsinfo_create.h in Headers */ = {isa = PBXBuildFile; fileRef = 1532629006281C9D00B1C10C /* dnsinfo_create.h */; };
15D48ED30F67079B00B4711E /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; };
15D48ED40F6707A600B4711E /* shared_dns_info.defs in Sources */ = {isa = PBXBuildFile; fileRef = 15FCAAD005FD0EBF00CB79E6 /* shared_dns_info.defs */; };
+ 15D8B22A1450D8450090CECF /* SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15D8B2291450D8450090CECF /* SCD.h */; };
+ 15D8B22B1450D8450090CECF /* SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15D8B2291450D8450090CECF /* SCD.h */; };
+ 15D8B22C1450D8450090CECF /* SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15D8B2291450D8450090CECF /* SCD.h */; };
+ 15D8B22D1450D8450090CECF /* SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15D8B2291450D8450090CECF /* SCD.h */; };
15D9DCFB10DD90A1004E545D /* AppWorkaround.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 15D9DCFA10DD90A1004E545D /* AppWorkaround.plist */; };
15DAD5E1075913CE0084A6ED /* dnsinfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B73F0905FD1B670096477F /* dnsinfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
15DAD5E2075913CE0084A6ED /* dnsinfo_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B73F0C05FD1B670096477F /* dnsinfo_private.h */; };
15DAD66F07591A1A0084A6ED /* SCDPrivate.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695405C0722B0099E85F /* SCDPrivate.c */; settings = {ATTRIBUTES = (); }; };
15DAD67007591A1A0084A6ED /* SCDPlugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695605C0722B0099E85F /* SCDPlugin.c */; settings = {ATTRIBUTES = (); }; };
15DAD67107591A1A0084A6ED /* SCDOpen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695805C0722B0099E85F /* SCDOpen.c */; settings = {ATTRIBUTES = (); }; };
- 15DAD67207591A1A0084A6ED /* SCDLock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695A05C0722B0099E85F /* SCDLock.c */; settings = {ATTRIBUTES = (); }; };
- 15DAD67307591A1A0084A6ED /* SCDUnlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695C05C0722B0099E85F /* SCDUnlock.c */; settings = {ATTRIBUTES = (); }; };
15DAD67407591A1A0084A6ED /* SCDList.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB695E05C0722B0099E85F /* SCDList.c */; settings = {ATTRIBUTES = (); }; };
15DAD67507591A1A0084A6ED /* SCDAdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696005C0722B0099E85F /* SCDAdd.c */; settings = {ATTRIBUTES = (); }; };
15DAD67607591A1A0084A6ED /* SCDGet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696405C0722B0099E85F /* SCDGet.c */; settings = {ATTRIBUTES = (); }; };
15DAD67707591A1A0084A6ED /* SCDSet.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696605C0722B0099E85F /* SCDSet.c */; settings = {ATTRIBUTES = (); }; };
15DAD67807591A1A0084A6ED /* SCDRemove.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696805C0722B0099E85F /* SCDRemove.c */; settings = {ATTRIBUTES = (); }; };
- 15DAD67907591A1A0084A6ED /* SCDTouch.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696A05C0722B0099E85F /* SCDTouch.c */; settings = {ATTRIBUTES = (); }; };
15DAD67A07591A1A0084A6ED /* SCDNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696C05C0722B0099E85F /* SCDNotify.c */; settings = {ATTRIBUTES = (); }; };
15DAD67B07591A1A0084A6ED /* SCDNotifierSetKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB696E05C0722B0099E85F /* SCDNotifierSetKeys.c */; settings = {ATTRIBUTES = (); }; };
15DAD67C07591A1A0084A6ED /* SCDNotifierAdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697005C0722B0099E85F /* SCDNotifierAdd.c */; settings = {ATTRIBUTES = (); }; };
15DAD67E07591A1A0084A6ED /* SCDNotifierGetChanges.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697405C0722B0099E85F /* SCDNotifierGetChanges.c */; settings = {ATTRIBUTES = (); }; };
15DAD67F07591A1A0084A6ED /* SCDNotifierWait.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697605C0722B0099E85F /* SCDNotifierWait.c */; settings = {ATTRIBUTES = (); }; };
15DAD68007591A1A0084A6ED /* SCDNotifierInformViaCallback.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697805C0722B0099E85F /* SCDNotifierInformViaCallback.c */; settings = {ATTRIBUTES = (); }; };
- 15DAD68107591A1A0084A6ED /* SCDNotifierInformViaMachPort.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697A05C0722B0099E85F /* SCDNotifierInformViaMachPort.c */; settings = {ATTRIBUTES = (); }; };
15DAD68207591A1A0084A6ED /* SCDNotifierInformViaFD.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697C05C0722B0099E85F /* SCDNotifierInformViaFD.c */; settings = {ATTRIBUTES = (); }; };
15DAD68307591A1A0084A6ED /* SCDNotifierInformViaSignal.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB697E05C0722B0099E85F /* SCDNotifierInformViaSignal.c */; settings = {ATTRIBUTES = (); }; };
15DAD68407591A1A0084A6ED /* SCDNotifierCancel.c in Sources */ = {isa = PBXBuildFile; fileRef = 15CB698005C0722B0099E85F /* SCDNotifierCancel.c */; settings = {ATTRIBUTES = (); }; };
15FEE80E0CCFD341001312F9 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15FEE80D0CCFD341001312F9 /* ApplicationServices.framework */; };
15FEE81F0CD03E75001312F9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 15FEE8180CD03CBB001312F9 /* Localizable.strings */; };
15FF5C370CDF776200EEC8AA /* com.apple.SCHelper.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 15FF5C290CDF770500EEC8AA /* com.apple.SCHelper.plist */; };
+ 7264C144147319E7004FD76D /* CaptiveNetwork.c in Sources */ = {isa = PBXBuildFile; fileRef = 15A1FF3110597F17004C9CC9 /* CaptiveNetwork.c */; };
+ 7264C14614731A1F004FD76D /* CaptiveNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 15A1FF3010597F17004C9CC9 /* CaptiveNetwork.h */; settings = {ATTRIBUTES = (Public, ); }; };
72B43728113C7BFC00EBF1B6 /* nc.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B43726113C7BFC00EBF1B6 /* nc.h */; };
72B43729113C7BFC00EBF1B6 /* nc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B43727113C7BFC00EBF1B6 /* nc.c */; };
72B4372A113C7BFC00EBF1B6 /* nc.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B43726113C7BFC00EBF1B6 /* nc.h */; };
72B4372B113C7BFC00EBF1B6 /* nc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B43727113C7BFC00EBF1B6 /* nc.c */; };
+ D661C2EF1368BB280030B977 /* network_information.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A781368913C0091C931 /* network_information.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ D661C2F11368BB600030B977 /* network_information.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A77136891300091C931 /* network_information.c */; };
+ D661C2F21368BB720030B977 /* network_information.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A781368913C0091C931 /* network_information.h */; settings = {ATTRIBUTES = (Public, ); }; };
D6623873120B2AA7007F8E95 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1520A3DE0846B2DC0010B584 /* Security.framework */; };
+ D6986A79136891650091C931 /* network_information.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A77136891300091C931 /* network_information.c */; };
+ E49173E1137C4E4F0000089F /* network_information_priv.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A75136891120091C931 /* network_information_priv.c */; };
+ E4F211D3137B0AB900BBB915 /* network_information_priv.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A75136891120091C931 /* network_information_priv.c */; };
+ E4F211D4137B0ABD00BBB915 /* network_information_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A761368911E0091C931 /* network_information_priv.h */; };
+ E4F211D5137B0AD700BBB915 /* network_information_priv.c in Sources */ = {isa = PBXBuildFile; fileRef = D6986A75136891120091C931 /* network_information_priv.c */; };
+ E4F211D6137B0ADB00BBB915 /* network_information_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A761368911E0091C931 /* network_information_priv.h */; };
+ E4F211D7137B0AF200BBB915 /* network_information_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = D6986A761368911E0091C931 /* network_information_priv.h */; };
F95B8A430B03E07A00993BA3 /* SCNetworkSignature.c in Sources */ = {isa = PBXBuildFile; fileRef = F95B8A420B03E07A00993BA3 /* SCNetworkSignature.c */; };
F95B8A460B03E09300993BA3 /* SCNetworkSignature.h in Headers */ = {isa = PBXBuildFile; fileRef = F95B8A440B03E09300993BA3 /* SCNetworkSignature.h */; settings = {ATTRIBUTES = (Private, ); }; };
F95B8A470B03E09300993BA3 /* SCNetworkSignaturePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F95B8A450B03E09300993BA3 /* SCNetworkSignaturePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
- F95B8A690B03F9B500993BA3 /* NetworkIdentification.c in Sources */ = {isa = PBXBuildFile; fileRef = F95B8A680B03F97800993BA3 /* NetworkIdentification.c */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
remoteGlobalIDString = 151FE2DD0D5B7046000D6DB1;
remoteInfo = "configd_base-EmbeddedSimulator";
};
- 1520A385084681350010B584 /* PBXContainerItemProxy */ = {
+ 1521405A0E9400BF00DACD2C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
proxyType = 1;
- remoteGlobalIDString = 1547001808455B98006787CE;
- remoteInfo = SCHelper;
+ remoteGlobalIDString = 15213FF90E93E9F500DACD2C;
+ remoteInfo = Logger.bundle;
};
- 1521405A0E9400BF00DACD2C /* PBXContainerItemProxy */ = {
+ 1528BFEB135731B800691881 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
proxyType = 1;
- remoteGlobalIDString = 15213FF90E93E9F500DACD2C;
- remoteInfo = Logger.bundle;
+ remoteGlobalIDString = 1528BFDB1357305400691881;
+ remoteInfo = SCNetworkReachability;
+ };
+ 1528BFED135731B800691881 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 1528BFE31357309700691881;
+ remoteInfo = SCNetworkReachability.bundle;
+ };
+ 1528C00E135741C300691881 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 1528BFF013573FEE00691881;
+ remoteInfo = "SCNetworkReachability-Embedded";
+ };
+ 1528C010135741C300691881 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 1528BFF813573FF500691881;
+ remoteInfo = "SCNetworkReachability.bundle-Embedded";
+ };
+ 1528C0121357420300691881 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 1528BFFF1357401900691881;
+ remoteInfo = "SCNetworkReachability-EmbeddedOther";
+ };
+ 1528C0141357420300691881 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 1528C0071357401D00691881;
+ remoteInfo = "SCNetworkReachability.bundle-EmbeddedOther";
};
1558480507550D470046C2E9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
remoteGlobalIDString = 157A85260D56C91100B6F1A0;
remoteInfo = "LinkConfiguration-Embedded";
};
- 157A854F0D56CA8800B6F1A0 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 157A85310D56C94F00B6F1A0;
- remoteInfo = "NetworkIdentification-Embedded";
- };
157A85510D56CA9E00B6F1A0 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
remoteGlobalIDString = 158317230CFB80A1006F62B9;
remoteInfo = "configd-Embedded";
};
- 158317B20CFB8660006F62B9 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 158317A00CFB8626006F62B9;
- remoteInfo = "NetworkIdentification.bundle-Embedded";
- };
158317B40CFB8660006F62B9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
remoteGlobalIDString = 1583EB32108395BD00A3BC0C;
remoteInfo = "PreferencesMonitor-EmbeddedOther";
};
- 15AC5174108396D2004A9ED5 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 1583EB2B108395BD00A3BC0C;
- remoteInfo = "NetworkIdentification.bundle-EmbeddedOther";
- };
- 15AC5176108396D2004A9ED5 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 1583EB23108395BD00A3BC0C;
- remoteInfo = "NetworkIdentification-EmbeddedOther";
- };
15AC5178108396D2004A9ED5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
remoteGlobalIDString = 157A84D80D56C63900B6F1A0;
remoteInfo = "DNSConfiguration-Embedded";
};
- F95B8A760B03FB9100993BA3 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = F95B8A6A0B03F9D100993BA3;
- remoteInfo = NetworkIdentification.bundle;
- };
- F95B8A780B03FB9100993BA3 /* PBXContainerItemProxy */ = {
+ D6DDAC3C147A24BC00A2E902 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
proxyType = 1;
- remoteGlobalIDString = F95B8A5E0B03F81400993BA3;
- remoteInfo = NetworkIdentification;
+ remoteGlobalIDString = 1547001808455B98006787CE;
+ remoteInfo = SCHelper;
};
/* End PBXContainerItemProxy section */
15213FFA0E93E9F500DACD2C /* Logger.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Logger.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
1521FC5C060F296A003B28F5 /* dnsinfo_create.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = dnsinfo_create.c; path = dnsinfo/dnsinfo_create.c; sourceTree = SOURCE_ROOT; };
1522FCE50FA7FD7000B24128 /* dnsinfo_flatfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnsinfo_flatfile.c; path = dnsinfo/dnsinfo_flatfile.c; sourceTree = "<group>"; };
+ 1528BFE21357305400691881 /* libSCNetworkReachability.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSCNetworkReachability.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1528BFE81357309800691881 /* SCNetworkReachability.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SCNetworkReachability.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1528BFE91357312E00691881 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Plugins/SCNetworkReachability/Info.plist; sourceTree = "<group>"; };
+ 1528BFF713573FEE00691881 /* libSCNetworkReachability.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSCNetworkReachability.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1528BFFE13573FF500691881 /* SCNetworkReachability.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SCNetworkReachability.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1528C0061357401900691881 /* libSCNetworkReachability.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSCNetworkReachability.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1528C00D1357401D00691881 /* SCNetworkReachability.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SCNetworkReachability.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
152CEED0070CF6640050F23C /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = /usr/lib/libedit.2.dylib; sourceTree = "<absolute>"; };
152E0E7E10FE820E00E402F2 /* helper.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; name = helper.defs; path = SystemConfiguration.fproj/helper/helper.defs; sourceTree = "<group>"; };
152E0E8810FE824000E402F2 /* helper_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = helper_types.h; path = SystemConfiguration.fproj/helper/helper_types.h; sourceTree = "<group>"; };
1559C4520D349A4E0098FD59 /* KernelEventMonitor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KernelEventMonitor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
1559C4530D349A4E0098FD59 /* LinkConfiguration.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LinkConfiguration.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
1559C4540D349A4E0098FD59 /* PreferencesMonitor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PreferencesMonitor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
- 1559C4550D349A4E0098FD59 /* NetworkIdentification.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NetworkIdentification.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
155A1E6B081079CC00F70D98 /* SCNetworkConfigurationPrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SCNetworkConfigurationPrivate.h; sourceTree = "<group>"; };
155B7BF60847776D00F0E262 /* SCHelper_client.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SCHelper_client.h; path = helper/SCHelper_client.h; sourceTree = "<group>"; };
155D22380AF13A7300D52ED0 /* dns-configuration.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "dns-configuration.h"; sourceTree = "<group>"; };
157A850D0D56C8AA00B6F1A0 /* libInterfaceNamer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libInterfaceNamer.a; sourceTree = BUILT_PRODUCTS_DIR; };
157A85230D56C8E000B6F1A0 /* libKernelEventMonitor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libKernelEventMonitor.a; sourceTree = BUILT_PRODUCTS_DIR; };
157A852E0D56C91100B6F1A0 /* libLinkConfiguration.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libLinkConfiguration.a; sourceTree = BUILT_PRODUCTS_DIR; };
- 157A85390D56C94F00B6F1A0 /* libNetworkIdentification.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libNetworkIdentification.a; sourceTree = BUILT_PRODUCTS_DIR; };
157A85440D56C96F00B6F1A0 /* libPreferencesMonitor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPreferencesMonitor.a; sourceTree = BUILT_PRODUCTS_DIR; };
157A88880A470D0F003A4256 /* SCSchemaDefinitionsPrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SCSchemaDefinitionsPrivate.h; sourceTree = "<group>"; };
15828AE70753B5F900AD4710 /* KernelEventMonitor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KernelEventMonitor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
- 1583EA10108395BB00A3BC0C /* dnsinfo.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = dnsinfo.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1583EA10108395BB00A3BC0C /* libdnsinfo.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libdnsinfo.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
1583EA99108395BB00A3BC0C /* SystemConfiguration.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SystemConfiguration.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1583EAAA108395BB00A3BC0C /* SCHelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SCHelper; sourceTree = BUILT_PRODUCTS_DIR; };
1583EAD8108395BB00A3BC0C /* libIPMonitor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libIPMonitor.a; sourceTree = BUILT_PRODUCTS_DIR; };
1583EB0E108395BC00A3BC0C /* libLinkConfiguration.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libLinkConfiguration.a; sourceTree = BUILT_PRODUCTS_DIR; };
1583EB14108395BC00A3BC0C /* LinkConfiguration.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LinkConfiguration.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
1583EB21108395BC00A3BC0C /* Logger.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Logger.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
- 1583EB2A108395BD00A3BC0C /* libNetworkIdentification.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libNetworkIdentification.a; sourceTree = BUILT_PRODUCTS_DIR; };
- 1583EB30108395BD00A3BC0C /* NetworkIdentification.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NetworkIdentification.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
1583EB39108395BD00A3BC0C /* libPreferencesMonitor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPreferencesMonitor.a; sourceTree = BUILT_PRODUCTS_DIR; };
1583EB3F108395BD00A3BC0C /* PreferencesMonitor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PreferencesMonitor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
1583EB84108395BD00A3BC0C /* configd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = configd; sourceTree = BUILT_PRODUCTS_DIR; };
15B73F0D05FD1B670096477F /* dnsinfo_server.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = dnsinfo_server.c; path = dnsinfo/dnsinfo_server.c; sourceTree = "<group>"; };
15B73F0E05FD1B670096477F /* dnsinfo_server.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dnsinfo_server.h; path = dnsinfo/dnsinfo_server.h; sourceTree = "<group>"; };
15BAA32207F0699A00D9EC95 /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = /usr/lib/libbsm.dylib; sourceTree = "<absolute>"; };
+ 15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SCNetworkReachabilityServer_client.c; path = reachability/SCNetworkReachabilityServer_client.c; sourceTree = "<group>"; };
+ 15C330B8134B92780028E36B /* rb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = rb.c; path = reachability/rb.c; sourceTree = "<group>"; };
+ 15C330B9134B92780028E36B /* rb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rb.h; path = reachability/rb.h; sourceTree = "<group>"; };
+ 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SCNetworkReachabilityServer_server.c; path = reachability/SCNetworkReachabilityServer_server.c; sourceTree = "<group>"; };
+ 15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCNetworkReachabilityInternal.h; sourceTree = "<group>"; };
15CB691305C0722B0099E85F /* SystemConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SystemConfiguration.h; sourceTree = "<group>"; };
15CB691505C0722B0099E85F /* SCPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SCPrivate.h; sourceTree = "<group>"; };
15CB691705C0722B0099E85F /* SCDPlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SCDPlugin.h; sourceTree = "<group>"; };
15CB695405C0722B0099E85F /* SCDPrivate.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDPrivate.c; sourceTree = "<group>"; };
15CB695605C0722B0099E85F /* SCDPlugin.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDPlugin.c; sourceTree = "<group>"; };
15CB695805C0722B0099E85F /* SCDOpen.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDOpen.c; sourceTree = "<group>"; };
- 15CB695A05C0722B0099E85F /* SCDLock.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDLock.c; sourceTree = "<group>"; };
- 15CB695C05C0722B0099E85F /* SCDUnlock.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDUnlock.c; sourceTree = "<group>"; };
15CB695E05C0722B0099E85F /* SCDList.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDList.c; sourceTree = "<group>"; };
15CB696005C0722B0099E85F /* SCDAdd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDAdd.c; sourceTree = "<group>"; };
15CB696405C0722B0099E85F /* SCDGet.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDGet.c; sourceTree = "<group>"; };
15CB696605C0722B0099E85F /* SCDSet.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDSet.c; sourceTree = "<group>"; };
15CB696805C0722B0099E85F /* SCDRemove.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDRemove.c; sourceTree = "<group>"; };
- 15CB696A05C0722B0099E85F /* SCDTouch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDTouch.c; sourceTree = "<group>"; };
15CB696C05C0722B0099E85F /* SCDNotify.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDNotify.c; sourceTree = "<group>"; };
15CB696E05C0722B0099E85F /* SCDNotifierSetKeys.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDNotifierSetKeys.c; sourceTree = "<group>"; };
15CB697005C0722B0099E85F /* SCDNotifierAdd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDNotifierAdd.c; sourceTree = "<group>"; };
15CB697405C0722B0099E85F /* SCDNotifierGetChanges.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDNotifierGetChanges.c; sourceTree = "<group>"; };
15CB697605C0722B0099E85F /* SCDNotifierWait.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDNotifierWait.c; sourceTree = "<group>"; };
15CB697805C0722B0099E85F /* SCDNotifierInformViaCallback.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDNotifierInformViaCallback.c; sourceTree = "<group>"; };
- 15CB697A05C0722B0099E85F /* SCDNotifierInformViaMachPort.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDNotifierInformViaMachPort.c; sourceTree = "<group>"; };
15CB697C05C0722B0099E85F /* SCDNotifierInformViaFD.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDNotifierInformViaFD.c; sourceTree = "<group>"; };
15CB697E05C0722B0099E85F /* SCDNotifierInformViaSignal.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDNotifierInformViaSignal.c; sourceTree = "<group>"; };
15CB698005C0722B0099E85F /* SCDNotifierCancel.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCDNotifierCancel.c; sourceTree = "<group>"; };
15CB69EC05C0722B0099E85F /* pattern.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pattern.c; sourceTree = "<group>"; };
15CB69F005C0722B0099E85F /* _configopen.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _configopen.c; sourceTree = "<group>"; };
15CB69F205C0722B0099E85F /* _configclose.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _configclose.c; sourceTree = "<group>"; };
- 15CB69F405C0722B0099E85F /* _configlock.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _configlock.c; sourceTree = "<group>"; };
15CB69F605C0722B0099E85F /* _configunlock.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _configunlock.c; sourceTree = "<group>"; };
15CB69F805C0722B0099E85F /* _configlist.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _configlist.c; sourceTree = "<group>"; };
15CB69FA05C0722B0099E85F /* _configadd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _configadd.c; sourceTree = "<group>"; };
15CB69FE05C0722B0099E85F /* _configget.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _configget.c; sourceTree = "<group>"; };
15CB6A0005C0722B0099E85F /* _configset.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _configset.c; sourceTree = "<group>"; };
15CB6A0205C0722B0099E85F /* _configremove.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _configremove.c; sourceTree = "<group>"; };
- 15CB6A0405C0722B0099E85F /* _configtouch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _configtouch.c; sourceTree = "<group>"; };
15CB6A0605C0722B0099E85F /* _confignotify.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _confignotify.c; sourceTree = "<group>"; };
15CB6A0805C0722B0099E85F /* _notifyadd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _notifyadd.c; sourceTree = "<group>"; };
15CB6A0A05C0722B0099E85F /* _notifyremove.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = _notifyremove.c; sourceTree = "<group>"; };
15CB6A6A05C0722B0099E85F /* scutil.8 */ = {isa = PBXFileReference; explicitFileType = text.man; path = scutil.8; sourceTree = "<group>"; };
15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
15CFC229068B222F00123568 /* get-mobility-info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.sh; path = "get-mobility-info"; sourceTree = SOURCE_ROOT; };
+ 15D8B2291450D8450090CECF /* SCD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCD.h; sourceTree = "<group>"; };
15D9DCFA10DD90A1004E545D /* AppWorkaround.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AppWorkaround.plist; sourceTree = "<group>"; };
15DAD5EE075913CE0084A6ED /* libdnsinfo.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libdnsinfo.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
15DAF2D808466D4900D1B2BD /* SCHelper_client.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = SCHelper_client.c; path = helper/SCHelper_client.c; sourceTree = "<group>"; };
72B43726113C7BFC00EBF1B6 /* nc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nc.h; sourceTree = "<group>"; };
72B43727113C7BFC00EBF1B6 /* nc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nc.c; sourceTree = "<group>"; };
9EE943F306AF409B00772EB5 /* BondConfiguration.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = BondConfiguration.c; sourceTree = "<group>"; };
+ D6986A75136891120091C931 /* network_information_priv.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = network_information_priv.c; path = nwi/network_information_priv.c; sourceTree = "<group>"; };
+ D6986A761368911E0091C931 /* network_information_priv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = network_information_priv.h; path = nwi/network_information_priv.h; sourceTree = "<group>"; };
+ D6986A77136891300091C931 /* network_information.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = network_information.c; path = nwi/network_information.c; sourceTree = "<group>"; };
+ D6986A781368913C0091C931 /* network_information.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = network_information.h; path = nwi/network_information.h; sourceTree = "<group>"; };
F95B8A420B03E07A00993BA3 /* SCNetworkSignature.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SCNetworkSignature.c; sourceTree = "<group>"; };
F95B8A440B03E09300993BA3 /* SCNetworkSignature.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SCNetworkSignature.h; sourceTree = "<group>"; };
F95B8A450B03E09300993BA3 /* SCNetworkSignaturePrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SCNetworkSignaturePrivate.h; sourceTree = "<group>"; };
- F95B8A5F0B03F81400993BA3 /* libNetworkIdentification.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libNetworkIdentification.a; sourceTree = BUILT_PRODUCTS_DIR; };
- F95B8A670B03F97800993BA3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
- F95B8A680B03F97800993BA3 /* NetworkIdentification.c */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = NetworkIdentification.c; sourceTree = "<group>"; };
- F95B8A700B03F9D100993BA3 /* NetworkIdentification.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NetworkIdentification.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
158317530CFB80A1006F62B9 /* libInterfaceNamer.a in Frameworks */,
158317540CFB80A1006F62B9 /* libIPMonitor.a in Frameworks */,
158317550CFB80A1006F62B9 /* libLinkConfiguration.a in Frameworks */,
- 158317560CFB80A1006F62B9 /* libNetworkIdentification.a in Frameworks */,
158317570CFB80A1006F62B9 /* libPreferencesMonitor.a in Frameworks */,
+ 1528C0171357465900691881 /* libSCNetworkReachability.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
1583EB7A108395BD00A3BC0C /* libInterfaceNamer.a in Frameworks */,
1583EB7B108395BD00A3BC0C /* libIPMonitor.a in Frameworks */,
1583EB7C108395BD00A3BC0C /* libLinkConfiguration.a in Frameworks */,
- 1583EB7D108395BD00A3BC0C /* libNetworkIdentification.a in Frameworks */,
1583EB7E108395BD00A3BC0C /* libPreferencesMonitor.a in Frameworks */,
+ 1528C01A135746D700691881 /* libSCNetworkReachability.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
159D54D007529FFF004F8947 /* libInterfaceNamer.a in Frameworks */,
159D54D107529FFF004F8947 /* libIPMonitor.a in Frameworks */,
159D54D207529FFF004F8947 /* libLinkConfiguration.a in Frameworks */,
- 1533D77B0B10A14300CA4946 /* libNetworkIdentification.a in Frameworks */,
159D54D307529FFF004F8947 /* libPreferencesMonitor.a in Frameworks */,
+ 1528C019135746BB00691881 /* libSCNetworkReachability.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
1513E399108420A700088779 /* EmbeddedOther */ = {
isa = PBXGroup;
children = (
- 1583EA10108395BB00A3BC0C /* dnsinfo.dylib */,
+ 1583EA10108395BB00A3BC0C /* libdnsinfo.dylib */,
1583EA99108395BB00A3BC0C /* SystemConfiguration.framework */,
1513E39D108420DE00088779 /* Plugins */,
1583EAAA108395BB00A3BC0C /* SCHelper */,
1583EB0E108395BC00A3BC0C /* libLinkConfiguration.a */,
1583EB14108395BC00A3BC0C /* LinkConfiguration.bundle */,
1583EB21108395BC00A3BC0C /* Logger.bundle */,
- 1583EB2A108395BD00A3BC0C /* libNetworkIdentification.a */,
- 1583EB30108395BD00A3BC0C /* NetworkIdentification.bundle */,
1583EB39108395BD00A3BC0C /* libPreferencesMonitor.a */,
1583EB3F108395BD00A3BC0C /* PreferencesMonitor.bundle */,
+ 1528C0061357401900691881 /* libSCNetworkReachability.a */,
+ 1528C00D1357401D00691881 /* SCNetworkReachability.bundle */,
);
name = Plugins;
sourceTree = "<group>";
name = SCMonitor;
sourceTree = "<group>";
};
+ 1528BFDA13572FC200691881 /* SCNetworkReachability */ = {
+ isa = PBXGroup;
+ children = (
+ 1528BFE91357312E00691881 /* Info.plist */,
+ );
+ name = SCNetworkReachability;
+ sourceTree = "<group>";
+ };
1531D3D90E93E6AA00248432 /* Logger */ = {
isa = PBXGroup;
children = (
156CA4850EF853BB00C59A18 /* Logger.bundle */,
157A85440D56C96F00B6F1A0 /* libPreferencesMonitor.a */,
1559C4540D349A4E0098FD59 /* PreferencesMonitor.bundle */,
- 157A85390D56C94F00B6F1A0 /* libNetworkIdentification.a */,
- 1559C4550D349A4E0098FD59 /* NetworkIdentification.bundle */,
+ 1528BFF713573FEE00691881 /* libSCNetworkReachability.a */,
+ 1528BFFE13573FF500691881 /* SCNetworkReachability.bundle */,
);
name = Plugins;
sourceTree = "<group>";
15FF5C390CDF9C4000EEC8AA /* Supporting Files */,
);
name = SCHelper;
- path = SystemConfiguration.fproj;
sourceTree = "<group>";
};
1547002F084561ED006787CE /* Headers */ = {
15828AE70753B5F900AD4710 /* KernelEventMonitor.bundle */,
159D53F307528C79004F8947 /* libLinkConfiguration.a */,
15FD72B50754DA69001CC321 /* LinkConfiguration.bundle */,
- F95B8A5F0B03F81400993BA3 /* libNetworkIdentification.a */,
15213FFA0E93E9F500DACD2C /* Logger.bundle */,
- F95B8A700B03F9D100993BA3 /* NetworkIdentification.bundle */,
159D53FA07528C95004F8947 /* libPreferencesMonitor.a */,
15FD72C90754DA7E001CC321 /* PreferencesMonitor.bundle */,
+ 1528BFE21357305400691881 /* libSCNetworkReachability.a */,
+ 1528BFE81357309800691881 /* SCNetworkReachability.bundle */,
);
name = Plugins;
sourceTree = "<group>";
159D53AF07528B36004F8947 /* KernelEventMonitor */,
159D53C007528B36004F8947 /* LinkConfiguration */,
1531D3D90E93E6AA00248432 /* Logger */,
- F95B8A660B03F97800993BA3 /* NetworkIdentification */,
159D53C207528B36004F8947 /* PreferencesMonitor */,
+ 1528BFDA13572FC200691881 /* SCNetworkReachability */,
);
name = Plugins;
sourceTree = "<group>";
name = "Supporting Files";
sourceTree = "<group>";
};
- 15CB68FC05C072220099E85F /* configd */ = {
+ 15C330B4134B91930028E36B /* SCNetworkReachability */ = {
isa = PBXGroup;
children = (
- 15CB6A8605C072500099E85F /* MiG */,
- 15CB6A8305C072410099E85F /* Schema */,
- 1582B36B05FD1A4D009C2750 /* DNSConfiguration */,
- 15CB690705C0722A0099E85F /* SystemConfiguration */,
- 1547002E084561B4006787CE /* SCHelper */,
- 151F5DA80CCE995D0093AC3B /* SCMonitor */,
- 15CB69C205C0722B0099E85F /* configd */,
- 15CB6A2205C0722B0099E85F /* scselect */,
- 15CB6A3705C0722B0099E85F /* scutil */,
- 159D53A207528B06004F8947 /* Plugins */,
- 15CB6A6E05C0722B0099E85F /* External Frameworks and Libraries */,
- 15CB690F05C0722B0099E85F /* Products */,
- 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */,
- 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */,
+ 15C330B5134B91C40028E36B /* Headers */,
+ 15C330B6134B91CB0028E36B /* Sources */,
);
- indentWidth = 8;
- name = configd;
+ name = SCNetworkReachability;
sourceTree = "<group>";
- tabWidth = 8;
- usesTabs = 1;
};
- 15CB690705C0722A0099E85F /* SystemConfiguration */ = {
+ 15C330B5134B91C40028E36B /* Headers */ = {
isa = PBXGroup;
children = (
- 15CB691205C0722B0099E85F /* Headers */,
- 15CB694F05C0722B0099E85F /* Sources */,
- 15B6861D0678B61900FF4023 /* Supporting Files */,
+ 15CB693705C0722B0099E85F /* SCNetworkReachability.h */,
+ 15C330D0134B95AA0028E36B /* SCNetworkReachabilityInternal.h */,
+ 15C330B9134B92780028E36B /* rb.h */,
);
- name = SystemConfiguration;
- path = SystemConfiguration.fproj;
+ name = Headers;
sourceTree = "<group>";
};
- 15CB690F05C0722B0099E85F /* Products */ = {
+ 15C330B6134B91CB0028E36B /* Sources */ = {
isa = PBXGroup;
children = (
- 151F63EC09328A3C0096DCC9 /* genSCPreferences */,
- 154083530D5B824400E07907 /* MacOSX */,
- 1540835A0D5B825200E07907 /* Embedded */,
- 154083890D5B82A900E07907 /* EmbeddedSimulator */,
- 1513E399108420A700088779 /* EmbeddedOther */,
+ 15CB69A205C0722B0099E85F /* SCNetwork.c */,
+ 15CB69A605C0722B0099E85F /* SCNetworkReachability.c */,
+ 15C330B7134B92780028E36B /* SCNetworkReachabilityServer_client.c */,
+ 15C330BB134B92780028E36B /* SCNetworkReachabilityServer_server.c */,
+ 15C330B8134B92780028E36B /* rb.c */,
);
- name = Products;
+ name = Sources;
sourceTree = "<group>";
};
- 15CB691205C0722B0099E85F /* Headers */ = {
+ 15C330D5134B99EF0028E36B /* SCDynamicStore */ = {
+ isa = PBXGroup;
+ children = (
+ 15C330D6134B9A1C0028E36B /* Headers */,
+ 15C330D7134B9A290028E36B /* Sources */,
+ );
+ name = SCDynamicStore;
+ sourceTree = "<group>";
+ };
+ 15C330D6134B9A1C0028E36B /* Headers */ = {
isa = PBXGroup;
children = (
- 15CB691305C0722B0099E85F /* SystemConfiguration.h */,
- 150607DE075A00A300B147BA /* SCSchemaDefinitions.h */,
- 157A88880A470D0F003A4256 /* SCSchemaDefinitionsPrivate.h */,
- 15CB691705C0722B0099E85F /* SCDPlugin.h */,
15CB691B05C0722B0099E85F /* SCDynamicStoreInternal.h */,
15CB691D05C0722B0099E85F /* SCDynamicStore.h */,
15CB691F05C0722B0099E85F /* SCDynamicStorePrivate.h */,
15CB692305C0722B0099E85F /* SCDynamicStoreCopySpecific.h */,
15CB692505C0722B0099E85F /* SCDynamicStoreCopySpecificPrivate.h */,
15CB692705C0722B0099E85F /* SCDynamicStoreSetSpecificPrivate.h */,
- 15CB692905C0722B0099E85F /* SCPreferencesInternal.h */,
- 15CB692B05C0722B0099E85F /* SCPreferences.h */,
- 15CB692D05C0722B0099E85F /* SCPreferencesPrivate.h */,
- 15CB692F05C0722B0099E85F /* SCPreferencesPath.h */,
- 151BDA2B05D9E28B00657BC7 /* SCPreferencesPathKey.h */,
- 154CF3F307E1EA4D00D8302E /* SCPreferencesGetSpecificPrivate.h */,
- 15CB693105C0722B0099E85F /* SCPreferencesSetSpecific.h */,
- 156BD6BB07E0DFA9008698FF /* SCPreferencesSetSpecificPrivate.h */,
- 152E68C00A2C89C70011FDA8 /* SCPreferencesKeychainPrivate.h */,
- 15CB691505C0722B0099E85F /* SCPrivate.h */,
- 15AD7A380670A85900BFE03C /* SCNetworkConfiguration.h */,
- 155A1E6B081079CC00F70D98 /* SCNetworkConfigurationPrivate.h */,
- 15AD7A3A0670A85900BFE03C /* SCNetworkConfigurationInternal.h */,
- 15CB693305C0722B0099E85F /* SCNetwork.h */,
- 15CB693505C0722B0099E85F /* SCNetworkConnection.h */,
- 15A2972E0A13C08C009879B3 /* SCNetworkConnectionPrivate.h */,
- 15CB693705C0722B0099E85F /* SCNetworkReachability.h */,
- F95B8A440B03E09300993BA3 /* SCNetworkSignature.h */,
- F95B8A450B03E09300993BA3 /* SCNetworkSignaturePrivate.h */,
- 15CB693905C0722B0099E85F /* SCValidation.h */,
- 15A1FF3010597F17004C9CC9 /* CaptiveNetwork.h */,
- 15CB694505C0722B0099E85F /* DeviceOnHold.h */,
- 15CB693D05C0722B0099E85F /* DHCPClientPreferences.h */,
- 15CB694705C0722B0099E85F /* LinkConfiguration.h */,
- 15CB694905C0722B0099E85F /* dy_framework.h */,
- 15CB694305C0722B0099E85F /* moh.h */,
- 15CB694105C0722B0099E85F /* moh_msg.h */,
- 23C1E2BE062DD5DB00835B54 /* pppcontroller.h */,
- 159A7513107FEAA400A57EAB /* VPNPrivate.h */,
- 159A7515107FEAA400A57EAB /* VPNConfiguration.h */,
- 15AAA7F2108E310700C2A607 /* VPNTunnel.h */,
- 15AAA7F1108E310700C2A607 /* VPNTunnelPrivate.h */,
);
name = Headers;
sourceTree = "<group>";
};
- 15CB694F05C0722B0099E85F /* Sources */ = {
+ 15C330D7134B9A290028E36B /* Sources */ = {
isa = PBXGroup;
children = (
- 150607BD075A00A200B147BA /* SCSchemaDefinitions.c */,
- 15CB695005C0722B0099E85F /* SCD.c */,
- 15CB695405C0722B0099E85F /* SCDPrivate.c */,
15CB695205C0722B0099E85F /* SCDKeys.c */,
15CB695805C0722B0099E85F /* SCDOpen.c */,
- 15CB695A05C0722B0099E85F /* SCDLock.c */,
- 15CB695C05C0722B0099E85F /* SCDUnlock.c */,
15CB695E05C0722B0099E85F /* SCDList.c */,
15CB696005C0722B0099E85F /* SCDAdd.c */,
15CB696405C0722B0099E85F /* SCDGet.c */,
15CB696605C0722B0099E85F /* SCDSet.c */,
15CB696805C0722B0099E85F /* SCDRemove.c */,
- 15CB696A05C0722B0099E85F /* SCDTouch.c */,
15CB696C05C0722B0099E85F /* SCDNotify.c */,
15CB696E05C0722B0099E85F /* SCDNotifierSetKeys.c */,
15CB697005C0722B0099E85F /* SCDNotifierAdd.c */,
15CB697405C0722B0099E85F /* SCDNotifierGetChanges.c */,
15CB697605C0722B0099E85F /* SCDNotifierWait.c */,
15CB697805C0722B0099E85F /* SCDNotifierInformViaCallback.c */,
- 15CB697A05C0722B0099E85F /* SCDNotifierInformViaMachPort.c */,
15CB697C05C0722B0099E85F /* SCDNotifierInformViaFD.c */,
15CB697E05C0722B0099E85F /* SCDNotifierInformViaSignal.c */,
15CB698005C0722B0099E85F /* SCDNotifierCancel.c */,
15CB698205C0722B0099E85F /* SCDSnapshot.c */,
+ );
+ name = Sources;
+ sourceTree = "<group>";
+ };
+ 15C330D8134B9A730028E36B /* SCPreferences */ = {
+ isa = PBXGroup;
+ children = (
+ 15C330D9134B9A850028E36B /* Headers */,
+ 15C330DA134B9A940028E36B /* Sources */,
+ );
+ name = SCPreferences;
+ sourceTree = "<group>";
+ };
+ 15C330D9134B9A850028E36B /* Headers */ = {
+ isa = PBXGroup;
+ children = (
+ 15CB692905C0722B0099E85F /* SCPreferencesInternal.h */,
+ 15CB692B05C0722B0099E85F /* SCPreferences.h */,
+ 15CB692D05C0722B0099E85F /* SCPreferencesPrivate.h */,
+ 15CB692F05C0722B0099E85F /* SCPreferencesPath.h */,
+ 151BDA2B05D9E28B00657BC7 /* SCPreferencesPathKey.h */,
+ 154CF3F307E1EA4D00D8302E /* SCPreferencesGetSpecificPrivate.h */,
+ 15CB693105C0722B0099E85F /* SCPreferencesSetSpecific.h */,
+ 156BD6BB07E0DFA9008698FF /* SCPreferencesSetSpecificPrivate.h */,
+ 152E68C00A2C89C70011FDA8 /* SCPreferencesKeychainPrivate.h */,
+ );
+ name = Headers;
+ sourceTree = "<group>";
+ };
+ 15C330DA134B9A940028E36B /* Sources */ = {
+ isa = PBXGroup;
+ children = (
15CB698405C0722B0099E85F /* SCP.c */,
15CB698605C0722B0099E85F /* SCPOpen.c */,
15CB698805C0722B0099E85F /* SCPLock.c */,
15CB699A05C0722B0099E85F /* SCPPath.c */,
151BDA5D05D9E2ED00657BC7 /* SCPreferencesPathKey.c */,
152E68C20A2C89E30011FDA8 /* SCPreferencesKeychainPrivate.c */,
+ );
+ name = Sources;
+ sourceTree = "<group>";
+ };
+ 15C330DB134B9B8B0028E36B /* SCNetworkConfiguration */ = {
+ isa = PBXGroup;
+ children = (
+ 15C330DC134B9BA20028E36B /* Headers */,
+ 15C330DD134B9BB20028E36B /* Sources */,
+ );
+ name = SCNetworkConfiguration;
+ sourceTree = "<group>";
+ };
+ 15C330DC134B9BA20028E36B /* Headers */ = {
+ isa = PBXGroup;
+ children = (
+ 15AD7A380670A85900BFE03C /* SCNetworkConfiguration.h */,
+ 155A1E6B081079CC00F70D98 /* SCNetworkConfigurationPrivate.h */,
+ 15AD7A3A0670A85900BFE03C /* SCNetworkConfigurationInternal.h */,
+ 15CB694705C0722B0099E85F /* LinkConfiguration.h */,
+ );
+ name = Headers;
+ sourceTree = "<group>";
+ };
+ 15C330DD134B9BB20028E36B /* Sources */ = {
+ isa = PBXGroup;
+ children = (
15AD7A390670A85900BFE03C /* SCNetworkConfigurationInternal.c */,
15AD7A3B0670A85900BFE03C /* SCNetworkInterface.c */,
15AD7A3C0670A85900BFE03C /* SCNetworkProtocol.c */,
9EE943F306AF409B00772EB5 /* BondConfiguration.c */,
15FD7B3B101E439200C56621 /* BridgeConfiguration.c */,
15CB69B605C0722B0099E85F /* VLANConfiguration.c */,
- 15CB695605C0722B0099E85F /* SCDPlugin.c */,
- 15CB699C05C0722B0099E85F /* SCDConsoleUser.c */,
- 15CB699E05C0722B0099E85F /* SCDHostName.c */,
- 15CB69A005C0722B0099E85F /* SCLocation.c */,
- 15CB69A205C0722B0099E85F /* SCNetwork.c */,
+ );
+ name = Sources;
+ sourceTree = "<group>";
+ };
+ 15C330DE134B9C290028E36B /* SCNetworkConnection */ = {
+ isa = PBXGroup;
+ children = (
+ 15C330E0134B9C4C0028E36B /* Headers */,
+ 15C330DF134B9C3F0028E36B /* Sources */,
+ );
+ name = SCNetworkConnection;
+ sourceTree = "<group>";
+ };
+ 15C330DF134B9C3F0028E36B /* Sources */ = {
+ isa = PBXGroup;
+ children = (
15CB69A405C0722B0099E85F /* SCNetworkConnection.c */,
15A2972D0A13C08C009879B3 /* SCNetworkConnectionPrivate.c */,
- 15CB69A605C0722B0099E85F /* SCNetworkReachability.c */,
- F95B8A420B03E07A00993BA3 /* SCNetworkSignature.c */,
- 15CB69A805C0722B0099E85F /* SCProxies.c */,
- 15A1FF3110597F17004C9CC9 /* CaptiveNetwork.c */,
- 15CB69AC05C0722B0099E85F /* DHCP.c */,
- 15CB69AE05C0722B0099E85F /* moh.c */,
- 15CB69B005C0722B0099E85F /* DeviceOnHold.c */,
- 15CB69B405C0722B0099E85F /* dy_framework.c */,
- 159A7517107FEAA400A57EAB /* VPNPrivate.c */,
- 159A7519107FEAA400A57EAB /* VPNConfiguration.c */,
- 15AAA7F3108E310700C2A607 /* VPNTunnel.c */,
);
name = Sources;
sourceTree = "<group>";
};
- 15CB69C205C0722B0099E85F /* configd */ = {
+ 15C330E0134B9C4C0028E36B /* Headers */ = {
isa = PBXGroup;
children = (
- 15CB69CE05C0722B0099E85F /* Headers */,
- 15CB69DF05C0722B0099E85F /* Sources */,
- 15CB6A1805C0722B0099E85F /* Supporting Files */,
+ 15CB693505C0722B0099E85F /* SCNetworkConnection.h */,
+ 15A2972E0A13C08C009879B3 /* SCNetworkConnectionPrivate.h */,
+ 23C1E2BE062DD5DB00835B54 /* pppcontroller.h */,
);
- name = configd;
- path = configd.tproj;
+ name = Headers;
sourceTree = "<group>";
};
- 15CB69CE05C0722B0099E85F /* Headers */ = {
+ 15C330E1134B9C8E0028E36B /* VPN */ = {
isa = PBXGroup;
children = (
- 15CB69CF05C0722B0099E85F /* configd.h */,
- 15CB69D105C0722B0099E85F /* _SCD.h */,
- 15CB69D305C0722B0099E85F /* configd_server.h */,
- 15CB69D505C0722B0099E85F /* notify_server.h */,
- 15CB69D705C0722B0099E85F /* plugin_support.h */,
- 15CB69D905C0722B0099E85F /* session.h */,
- 15CB69DB05C0722B0099E85F /* pattern.h */,
+ 15C330E3134B9CA30028E36B /* Headers */,
+ 15C330E2134B9C9B0028E36B /* Sources */,
);
- name = Headers;
+ name = VPN;
sourceTree = "<group>";
};
- 15CB69DF05C0722B0099E85F /* Sources */ = {
+ 15C330E2134B9C9B0028E36B /* Sources */ = {
isa = PBXGroup;
children = (
- 15CB69E005C0722B0099E85F /* configd.m */,
- 15CB69E205C0722B0099E85F /* _SCD.c */,
- 15CB69E405C0722B0099E85F /* configd_server.c */,
- 15CB69E605C0722B0099E85F /* notify_server.c */,
- 15CB69E805C0722B0099E85F /* plugin_support.c */,
- 15CB69EA05C0722B0099E85F /* session.c */,
- 15CB69EC05C0722B0099E85F /* pattern.c */,
- 15CB69F005C0722B0099E85F /* _configopen.c */,
- 15CB69F205C0722B0099E85F /* _configclose.c */,
- 15CB69F405C0722B0099E85F /* _configlock.c */,
- 15CB69F605C0722B0099E85F /* _configunlock.c */,
- 15CB69F805C0722B0099E85F /* _configlist.c */,
+ 159A7517107FEAA400A57EAB /* VPNPrivate.c */,
+ 159A7519107FEAA400A57EAB /* VPNConfiguration.c */,
+ 15AAA7F3108E310700C2A607 /* VPNTunnel.c */,
+ );
+ name = Sources;
+ sourceTree = "<group>";
+ };
+ 15C330E3134B9CA30028E36B /* Headers */ = {
+ isa = PBXGroup;
+ children = (
+ 159A7513107FEAA400A57EAB /* VPNPrivate.h */,
+ 159A7515107FEAA400A57EAB /* VPNConfiguration.h */,
+ 15AAA7F2108E310700C2A607 /* VPNTunnel.h */,
+ 15AAA7F1108E310700C2A607 /* VPNTunnelPrivate.h */,
+ );
+ name = Headers;
+ sourceTree = "<group>";
+ };
+ 15CB68FC05C072220099E85F /* configd */ = {
+ isa = PBXGroup;
+ children = (
+ 15CB6A8605C072500099E85F /* MiG */,
+ 15CB6A8305C072410099E85F /* Schema */,
+ D6986A70136890B60091C931 /* NetworkInformation */,
+ 1582B36B05FD1A4D009C2750 /* DNSConfiguration */,
+ 15CB690705C0722A0099E85F /* SystemConfiguration */,
+ 151F5DA80CCE995D0093AC3B /* SCMonitor */,
+ 15CB69C205C0722B0099E85F /* configd */,
+ 15CB6A2205C0722B0099E85F /* scselect */,
+ 15CB6A3705C0722B0099E85F /* scutil */,
+ 159D53A207528B06004F8947 /* Plugins */,
+ 15CB6A6E05C0722B0099E85F /* External Frameworks and Libraries */,
+ 15CB690F05C0722B0099E85F /* Products */,
+ 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */,
+ 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */,
+ );
+ indentWidth = 8;
+ name = configd;
+ sourceTree = "<group>";
+ tabWidth = 8;
+ usesTabs = 1;
+ };
+ 15CB690705C0722A0099E85F /* SystemConfiguration */ = {
+ isa = PBXGroup;
+ children = (
+ 15C330D5134B99EF0028E36B /* SCDynamicStore */,
+ 15C330D8134B9A730028E36B /* SCPreferences */,
+ 1547002E084561B4006787CE /* SCHelper */,
+ 15C330DB134B9B8B0028E36B /* SCNetworkConfiguration */,
+ 15C330DE134B9C290028E36B /* SCNetworkConnection */,
+ 15C330B4134B91930028E36B /* SCNetworkReachability */,
+ 15C330E1134B9C8E0028E36B /* VPN */,
+ 15CB691205C0722B0099E85F /* Other Headers */,
+ 15CB694F05C0722B0099E85F /* Other Sources */,
+ 15B6861D0678B61900FF4023 /* Supporting Files */,
+ );
+ name = SystemConfiguration;
+ path = SystemConfiguration.fproj;
+ sourceTree = "<group>";
+ };
+ 15CB690F05C0722B0099E85F /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 151F63EC09328A3C0096DCC9 /* genSCPreferences */,
+ 154083530D5B824400E07907 /* MacOSX */,
+ 1540835A0D5B825200E07907 /* Embedded */,
+ 154083890D5B82A900E07907 /* EmbeddedSimulator */,
+ 1513E399108420A700088779 /* EmbeddedOther */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 15CB691205C0722B0099E85F /* Other Headers */ = {
+ isa = PBXGroup;
+ children = (
+ 15D8B2291450D8450090CECF /* SCD.h */,
+ 15CB691305C0722B0099E85F /* SystemConfiguration.h */,
+ 150607DE075A00A300B147BA /* SCSchemaDefinitions.h */,
+ 157A88880A470D0F003A4256 /* SCSchemaDefinitionsPrivate.h */,
+ 15CB691705C0722B0099E85F /* SCDPlugin.h */,
+ 15CB691505C0722B0099E85F /* SCPrivate.h */,
+ 15CB693305C0722B0099E85F /* SCNetwork.h */,
+ F95B8A440B03E09300993BA3 /* SCNetworkSignature.h */,
+ F95B8A450B03E09300993BA3 /* SCNetworkSignaturePrivate.h */,
+ 15CB693905C0722B0099E85F /* SCValidation.h */,
+ 15A1FF3010597F17004C9CC9 /* CaptiveNetwork.h */,
+ 15CB694505C0722B0099E85F /* DeviceOnHold.h */,
+ 15CB693D05C0722B0099E85F /* DHCPClientPreferences.h */,
+ 15CB694905C0722B0099E85F /* dy_framework.h */,
+ 15CB694305C0722B0099E85F /* moh.h */,
+ 15CB694105C0722B0099E85F /* moh_msg.h */,
+ );
+ name = "Other Headers";
+ sourceTree = "<group>";
+ };
+ 15CB694F05C0722B0099E85F /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 150607BD075A00A200B147BA /* SCSchemaDefinitions.c */,
+ 15CB695005C0722B0099E85F /* SCD.c */,
+ 15CB695405C0722B0099E85F /* SCDPrivate.c */,
+ 15CB695605C0722B0099E85F /* SCDPlugin.c */,
+ 15CB699C05C0722B0099E85F /* SCDConsoleUser.c */,
+ 15CB699E05C0722B0099E85F /* SCDHostName.c */,
+ 15CB69A005C0722B0099E85F /* SCLocation.c */,
+ F95B8A420B03E07A00993BA3 /* SCNetworkSignature.c */,
+ 15CB69A805C0722B0099E85F /* SCProxies.c */,
+ 15A1FF3110597F17004C9CC9 /* CaptiveNetwork.c */,
+ 15CB69AC05C0722B0099E85F /* DHCP.c */,
+ 15CB69AE05C0722B0099E85F /* moh.c */,
+ 15CB69B005C0722B0099E85F /* DeviceOnHold.c */,
+ 15CB69B405C0722B0099E85F /* dy_framework.c */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+ 15CB69C205C0722B0099E85F /* configd */ = {
+ isa = PBXGroup;
+ children = (
+ 15CB69CE05C0722B0099E85F /* Headers */,
+ 15CB69DF05C0722B0099E85F /* Sources */,
+ 15CB6A1805C0722B0099E85F /* Supporting Files */,
+ );
+ name = configd;
+ path = configd.tproj;
+ sourceTree = "<group>";
+ };
+ 15CB69CE05C0722B0099E85F /* Headers */ = {
+ isa = PBXGroup;
+ children = (
+ 15CB69CF05C0722B0099E85F /* configd.h */,
+ 15CB69D105C0722B0099E85F /* _SCD.h */,
+ 15CB69D305C0722B0099E85F /* configd_server.h */,
+ 15CB69D505C0722B0099E85F /* notify_server.h */,
+ 15CB69D705C0722B0099E85F /* plugin_support.h */,
+ 15CB69D905C0722B0099E85F /* session.h */,
+ 15CB69DB05C0722B0099E85F /* pattern.h */,
+ );
+ name = Headers;
+ sourceTree = "<group>";
+ };
+ 15CB69DF05C0722B0099E85F /* Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 15CB69E005C0722B0099E85F /* configd.m */,
+ 15CB69E205C0722B0099E85F /* _SCD.c */,
+ 15CB69E405C0722B0099E85F /* configd_server.c */,
+ 15CB69E605C0722B0099E85F /* notify_server.c */,
+ 15CB69E805C0722B0099E85F /* plugin_support.c */,
+ 15CB69EA05C0722B0099E85F /* session.c */,
+ 15CB69EC05C0722B0099E85F /* pattern.c */,
+ 15CB69F005C0722B0099E85F /* _configopen.c */,
+ 15CB69F205C0722B0099E85F /* _configclose.c */,
+ 15CB69F605C0722B0099E85F /* _configunlock.c */,
+ 15CB69F805C0722B0099E85F /* _configlist.c */,
15CB69FA05C0722B0099E85F /* _configadd.c */,
15CB69FE05C0722B0099E85F /* _configget.c */,
15CB6A0005C0722B0099E85F /* _configset.c */,
15CB6A0205C0722B0099E85F /* _configremove.c */,
- 15CB6A0405C0722B0099E85F /* _configtouch.c */,
15CB6A0605C0722B0099E85F /* _confignotify.c */,
15CB6A0805C0722B0099E85F /* _notifyadd.c */,
15CB6A0A05C0722B0099E85F /* _notifyremove.c */,
name = "Supporting Files";
sourceTree = "<group>";
};
- F95B8A660B03F97800993BA3 /* NetworkIdentification */ = {
+ D6986A70136890B60091C931 /* NetworkInformation */ = {
+ isa = PBXGroup;
+ children = (
+ D6986A72136890C90091C931 /* Headers */,
+ D6986A74136890DB0091C931 /* Sources */,
+ );
+ name = NetworkInformation;
+ sourceTree = "<group>";
+ };
+ D6986A72136890C90091C931 /* Headers */ = {
+ isa = PBXGroup;
+ children = (
+ D6986A781368913C0091C931 /* network_information.h */,
+ D6986A761368911E0091C931 /* network_information_priv.h */,
+ );
+ name = Headers;
+ sourceTree = "<group>";
+ };
+ D6986A74136890DB0091C931 /* Sources */ = {
isa = PBXGroup;
children = (
- F95B8A670B03F97800993BA3 /* Info.plist */,
- F95B8A680B03F97800993BA3 /* NetworkIdentification.c */,
+ D6986A77136891300091C931 /* network_information.c */,
+ D6986A75136891120091C931 /* network_information_priv.c */,
);
- name = NetworkIdentification;
- path = Plugins/NetworkIdentification;
+ name = Sources;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
+ 1528BFDC1357305400691881 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1528BFF113573FEE00691881 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1528C0001357401900691881 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
1547001908455B98006787CE /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
159A751C107FEAA400A57EAB /* VPNConfiguration.h in Headers */,
15AAA7F5108E310700C2A607 /* VPNTunnel.h in Headers */,
15AAA7F4108E310700C2A607 /* VPNTunnelPrivate.h in Headers */,
+ 15C330C5134B92780028E36B /* rb.h in Headers */,
+ 15C330D2134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */,
+ 15D8B22B1450D8450090CECF /* SCD.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
buildActionMask = 2147483647;
files = (
157A84DA0D56C63900B6F1A0 /* dnsinfo.h in Headers */,
+ D661C2F21368BB720030B977 /* network_information.h in Headers */,
157A84DB0D56C63900B6F1A0 /* dnsinfo_private.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
buildActionMask = 2147483647;
files = (
157A84F60D56C7E800B6F1A0 /* dns-configuration.h in Headers */,
+ 15D48EC20F67061F00B4711E /* dnsinfo_create.h in Headers */,
+ E4F211D4137B0ABD00BBB915 /* network_information_priv.h in Headers */,
1575FD2812CD15C60003D86E /* proxy-configuration.h in Headers */,
157A84F70D56C7E800B6F1A0 /* set-hostname.h in Headers */,
- 15D48EC20F67061F00B4711E /* dnsinfo_create.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
);
runOnlyForDeploymentPostprocessing = 0;
};
- 157A85320D56C94F00B6F1A0 /* Headers */ = {
- isa = PBXHeadersBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
157A853D0D56C96F00B6F1A0 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
buildActionMask = 2147483647;
files = (
1583EA06108395BB00A3BC0C /* dnsinfo.h in Headers */,
+ 151E0CA31378EE1000C5DA2A /* network_information.h in Headers */,
1583EA07108395BB00A3BC0C /* dnsinfo_private.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
1583EA42108395BB00A3BC0C /* SCNetworkSignature.h in Headers */,
1583EA43108395BB00A3BC0C /* SCNetworkSignaturePrivate.h in Headers */,
1583EA44108395BB00A3BC0C /* CaptiveNetwork.h in Headers */,
+ 15C330C7134B92780028E36B /* rb.h in Headers */,
+ 15C330D4134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */,
+ 15D8B22D1450D8450090CECF /* SCD.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
buildActionMask = 2147483647;
files = (
1583EACC108395BB00A3BC0C /* dns-configuration.h in Headers */,
+ 1583EACE108395BB00A3BC0C /* dnsinfo_create.h in Headers */,
+ E4F211D6137B0ADB00BBB915 /* network_information_priv.h in Headers */,
1575FD2C12CD15C60003D86E /* proxy-configuration.h in Headers */,
1583EACD108395BB00A3BC0C /* set-hostname.h in Headers */,
- 1583EACE108395BB00A3BC0C /* dnsinfo_create.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
);
runOnlyForDeploymentPostprocessing = 0;
};
- 1583EB24108395BD00A3BC0C /* Headers */ = {
- isa = PBXHeadersBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
1583EB33108395BD00A3BC0C /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
buildActionMask = 2147483647;
files = (
155D223B0AF13A7300D52ED0 /* dns-configuration.h in Headers */,
+ 15D48EC00F67061700B4711E /* dnsinfo_create.h in Headers */,
+ E4F211D7137B0AF200BBB915 /* network_information_priv.h in Headers */,
1575FD2A12CD15C60003D86E /* proxy-configuration.h in Headers */,
155D223C0AF13A7300D52ED0 /* set-hostname.h in Headers */,
155D223D0AF13A7300D52ED0 /* smb-configuration.h in Headers */,
- 15D48EC00F67061700B4711E /* dnsinfo_create.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
15A1FF3410597F17004C9CC9 /* CaptiveNetwork.h in Headers */,
159A7528107FEAA400A57EAB /* VPNPrivate.h in Headers */,
159A752A107FEAA400A57EAB /* VPNConfiguration.h in Headers */,
+ 15C330C6134B92780028E36B /* rb.h in Headers */,
+ 15C330D3134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */,
+ 15D8B22C1450D8450090CECF /* SCD.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
buildActionMask = 2147483647;
files = (
15DAD5E1075913CE0084A6ED /* dnsinfo.h in Headers */,
+ D661C2EF1368BB280030B977 /* network_information.h in Headers */,
15DAD5E2075913CE0084A6ED /* dnsinfo_private.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
15DAD64B07591A1A0084A6ED /* SCDynamicStoreCopySpecificPrivate.h in Headers */,
15DAD64C07591A1A0084A6ED /* SCDynamicStoreSetSpecificPrivate.h in Headers */,
15DAD64D07591A1A0084A6ED /* SCPreferencesInternal.h in Headers */,
+ 7264C14614731A1F004FD76D /* CaptiveNetwork.h in Headers */,
15DAD64E07591A1A0084A6ED /* SCPreferences.h in Headers */,
15DAD64F07591A1A0084A6ED /* SCPreferencesPrivate.h in Headers */,
15DAD65007591A1A0084A6ED /* SCPreferencesPath.h in Headers */,
154CF3F407E1EA4D00D8302E /* SCPreferencesGetSpecificPrivate.h in Headers */,
155A1E6C081079CC00F70D98 /* SCNetworkConfigurationPrivate.h in Headers */,
155B7BF80847776D00F0E262 /* SCHelper_client.h in Headers */,
+ 15D8B22A1450D8450090CECF /* SCD.h in Headers */,
15A297300A13C08C009879B3 /* SCNetworkConnectionPrivate.h in Headers */,
152E68C10A2C89C70011FDA8 /* SCPreferencesKeychainPrivate.h in Headers */,
157A88890A470D0F003A4256 /* SCSchemaDefinitionsPrivate.h in Headers */,
159A7523107FEAA400A57EAB /* VPNConfiguration.h in Headers */,
15AAA7F8108E310700C2A607 /* VPNTunnel.h in Headers */,
15AAA7F7108E310700C2A607 /* VPNTunnelPrivate.h in Headers */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- F95B8A5B0B03F81400993BA3 /* Headers */ = {
- isa = PBXHeadersBuildPhase;
- buildActionMask = 2147483647;
- files = (
+ 15C330C4134B92780028E36B /* rb.h in Headers */,
+ 15C330D1134B95AA0028E36B /* SCNetworkReachabilityInternal.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
productReference = 15213FFA0E93E9F500DACD2C /* Logger.bundle */;
productType = "com.apple.product-type.bundle";
};
+ 1528BFDB1357305400691881 /* SCNetworkReachability */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1528BFDF1357305400691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability" */;
+ buildPhases = (
+ 1528BFDC1357305400691881 /* Headers */,
+ 1528BFDD1357305400691881 /* Sources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = SCNetworkReachability;
+ productName = PreferencesMonitor;
+ productReference = 1528BFE21357305400691881 /* libSCNetworkReachability.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ 1528BFE31357309700691881 /* SCNetworkReachability.bundle */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1528BFE51357309700691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability.bundle" */;
+ buildPhases = (
+ 1528BFE41357309700691881 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = SCNetworkReachability.bundle;
+ productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+ productName = PreferencesMonitor.bundle;
+ productReference = 1528BFE81357309800691881 /* SCNetworkReachability.bundle */;
+ productType = "com.apple.product-type.bundle";
+ };
+ 1528BFF013573FEE00691881 /* SCNetworkReachability-Embedded */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1528BFF413573FEE00691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability-Embedded" */;
+ buildPhases = (
+ 1528BFF113573FEE00691881 /* Headers */,
+ 1528BFF213573FEE00691881 /* Sources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "SCNetworkReachability-Embedded";
+ productName = PreferencesMonitor;
+ productReference = 1528BFF713573FEE00691881 /* libSCNetworkReachability.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ 1528BFF813573FF500691881 /* SCNetworkReachability.bundle-Embedded */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1528BFFB13573FF500691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability.bundle-Embedded" */;
+ buildPhases = (
+ 1528BFF913573FF500691881 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "SCNetworkReachability.bundle-Embedded";
+ productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+ productName = PreferencesMonitor.bundle;
+ productReference = 1528BFFE13573FF500691881 /* SCNetworkReachability.bundle */;
+ productType = "com.apple.product-type.bundle";
+ };
+ 1528BFFF1357401900691881 /* SCNetworkReachability-EmbeddedOther */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1528C0031357401900691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability-EmbeddedOther" */;
+ buildPhases = (
+ 1528C0001357401900691881 /* Headers */,
+ 1528C0011357401900691881 /* Sources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "SCNetworkReachability-EmbeddedOther";
+ productName = PreferencesMonitor;
+ productReference = 1528C0061357401900691881 /* libSCNetworkReachability.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ 1528C0071357401D00691881 /* SCNetworkReachability.bundle-EmbeddedOther */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1528C00A1357401D00691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability.bundle-EmbeddedOther" */;
+ buildPhases = (
+ 1528C0081357401D00691881 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "SCNetworkReachability.bundle-EmbeddedOther";
+ productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+ productName = PreferencesMonitor.bundle;
+ productReference = 1528C00D1357401D00691881 /* SCNetworkReachability.bundle */;
+ productType = "com.apple.product-type.bundle";
+ };
1547001808455B98006787CE /* SCHelper */ = {
isa = PBXNativeTarget;
buildConfigurationList = 156EB5E20905594A00EEF749 /* Build configuration list for PBXNativeTarget "SCHelper" */;
productReference = 157A852E0D56C91100B6F1A0 /* libLinkConfiguration.a */;
productType = "com.apple.product-type.library.static";
};
- 157A85310D56C94F00B6F1A0 /* NetworkIdentification-Embedded */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 157A85350D56C94F00B6F1A0 /* Build configuration list for PBXNativeTarget "NetworkIdentification-Embedded" */;
- buildPhases = (
- 157A85320D56C94F00B6F1A0 /* Headers */,
- 157A85330D56C94F00B6F1A0 /* Sources */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = "NetworkIdentification-Embedded";
- productName = NetworkIdentification;
- productReference = 157A85390D56C94F00B6F1A0 /* libNetworkIdentification.a */;
- productType = "com.apple.product-type.library.static";
- };
157A853C0D56C96F00B6F1A0 /* PreferencesMonitor-Embedded */ = {
isa = PBXNativeTarget;
buildConfigurationList = 157A85400D56C96F00B6F1A0 /* Build configuration list for PBXNativeTarget "PreferencesMonitor-Embedded" */;
productReference = 1559C4530D349A4E0098FD59 /* LinkConfiguration.bundle */;
productType = "com.apple.product-type.bundle";
};
- 158317A00CFB8626006F62B9 /* NetworkIdentification.bundle-Embedded */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 158317A20CFB8626006F62B9 /* Build configuration list for PBXNativeTarget "NetworkIdentification.bundle-Embedded" */;
- buildPhases = (
- 158317A10CFB8626006F62B9 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = "NetworkIdentification.bundle-Embedded";
- productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
- productName = NetworkIdentification.bundle;
- productReference = 1559C4550D349A4E0098FD59 /* NetworkIdentification.bundle */;
- productType = "com.apple.product-type.bundle";
- };
158317A80CFB8639006F62B9 /* PreferencesMonitor.bundle-Embedded */ = {
isa = PBXNativeTarget;
buildConfigurationList = 158317AA0CFB8639006F62B9 /* Build configuration list for PBXNativeTarget "PreferencesMonitor.bundle-Embedded" */;
name = "DNSConfiguration-EmbeddedOther";
productInstallPath = /usr/local/lib/system;
productName = DNSConfiguration;
- productReference = 1583EA10108395BB00A3BC0C /* dnsinfo.dylib */;
+ productReference = 1583EA10108395BB00A3BC0C /* libdnsinfo.dylib */;
productType = "com.apple.product-type.library.dynamic";
};
1583EA19108395BB00A3BC0C /* SystemConfiguration.framework-EmbeddedOther */ = {
);
dependencies = (
);
- name = "Logger.bundle-EmbeddedOther";
- productName = Logger.bundle;
- productReference = 1583EB21108395BC00A3BC0C /* Logger.bundle */;
- productType = "com.apple.product-type.bundle";
- };
- 1583EB23108395BD00A3BC0C /* NetworkIdentification-EmbeddedOther */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 1583EB27108395BD00A3BC0C /* Build configuration list for PBXNativeTarget "NetworkIdentification-EmbeddedOther" */;
- buildPhases = (
- 1583EB24108395BD00A3BC0C /* Headers */,
- 1583EB25108395BD00A3BC0C /* Sources */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = "NetworkIdentification-EmbeddedOther";
- productName = NetworkIdentification;
- productReference = 1583EB2A108395BD00A3BC0C /* libNetworkIdentification.a */;
- productType = "com.apple.product-type.library.static";
- };
- 1583EB2B108395BD00A3BC0C /* NetworkIdentification.bundle-EmbeddedOther */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 1583EB2D108395BD00A3BC0C /* Build configuration list for PBXNativeTarget "NetworkIdentification.bundle-EmbeddedOther" */;
- buildPhases = (
- 1583EB2C108395BD00A3BC0C /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = "NetworkIdentification.bundle-EmbeddedOther";
- productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
- productName = NetworkIdentification.bundle;
- productReference = 1583EB30108395BD00A3BC0C /* NetworkIdentification.bundle */;
+ name = "Logger.bundle-EmbeddedOther";
+ productName = Logger.bundle;
+ productReference = 1583EB21108395BC00A3BC0C /* Logger.bundle */;
productType = "com.apple.product-type.bundle";
};
1583EB32108395BD00A3BC0C /* PreferencesMonitor-EmbeddedOther */ = {
productReference = 15FD72C90754DA7E001CC321 /* PreferencesMonitor.bundle */;
productType = "com.apple.product-type.bundle";
};
- F95B8A5E0B03F81400993BA3 /* NetworkIdentification */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = F95B8A610B03F83200993BA3 /* Build configuration list for PBXNativeTarget "NetworkIdentification" */;
- buildPhases = (
- F95B8A5B0B03F81400993BA3 /* Headers */,
- F95B8A5C0B03F81400993BA3 /* Sources */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = NetworkIdentification;
- productName = NetworkIdentification;
- productReference = F95B8A5F0B03F81400993BA3 /* libNetworkIdentification.a */;
- productType = "com.apple.product-type.library.static";
- };
- F95B8A6A0B03F9D100993BA3 /* NetworkIdentification.bundle */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = F95B8A6C0B03F9D100993BA3 /* Build configuration list for PBXNativeTarget "NetworkIdentification.bundle" */;
- buildPhases = (
- F95B8A6B0B03F9D100993BA3 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = NetworkIdentification.bundle;
- productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
- productName = NetworkIdentification.bundle;
- productReference = F95B8A700B03F9D100993BA3 /* NetworkIdentification.bundle */;
- productType = "com.apple.product-type.bundle";
- };
/* End PBXNativeTarget section */
/* Begin PBXProject section */
15CB6A7705C0722B0099E85F /* Project object */ = {
isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0430;
+ };
buildConfigurationList = 156EB63E0905594A00EEF749 /* Build configuration list for PBXProject "configd" */;
- compatibilityVersion = "Xcode 3.1";
+ compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
159D53F207528C79004F8947 /* LinkConfiguration */,
15FD72B10754DA69001CC321 /* LinkConfiguration.bundle */,
15213FF90E93E9F500DACD2C /* Logger.bundle */,
- F95B8A5E0B03F81400993BA3 /* NetworkIdentification */,
- F95B8A6A0B03F9D100993BA3 /* NetworkIdentification.bundle */,
159D53F907528C95004F8947 /* PreferencesMonitor */,
15FD72C50754DA7E001CC321 /* PreferencesMonitor.bundle */,
+ 1528BFDB1357305400691881 /* SCNetworkReachability */,
+ 1528BFE31357309700691881 /* SCNetworkReachability.bundle */,
155847FA07550D210046C2E9 /* configd_executables */,
159D549F07529FFF004F8947 /* configd */,
1558481207550EC10046C2E9 /* scselect */,
157A85260D56C91100B6F1A0 /* LinkConfiguration-Embedded */,
158317980CFB860C006F62B9 /* LinkConfiguration.bundle-Embedded */,
156CA4790EF853BB00C59A18 /* Logger.bundle-Embedded */,
- 157A85310D56C94F00B6F1A0 /* NetworkIdentification-Embedded */,
- 158317A00CFB8626006F62B9 /* NetworkIdentification.bundle-Embedded */,
157A853C0D56C96F00B6F1A0 /* PreferencesMonitor-Embedded */,
158317A80CFB8639006F62B9 /* PreferencesMonitor.bundle-Embedded */,
+ 1528BFF013573FEE00691881 /* SCNetworkReachability-Embedded */,
+ 1528BFF813573FF500691881 /* SCNetworkReachability.bundle-Embedded */,
158317040CFB7782006F62B9 /* configd_executables-Embedded */,
158317230CFB80A1006F62B9 /* configd-Embedded */,
157433DD0D4A8122002ACA73 /* scselect-Embedded */,
1583EB07108395BC00A3BC0C /* LinkConfiguration-EmbeddedOther */,
1583EB0F108395BC00A3BC0C /* LinkConfiguration.bundle-EmbeddedOther */,
1583EB16108395BC00A3BC0C /* Logger.bundle-EmbeddedOther */,
- 1583EB23108395BD00A3BC0C /* NetworkIdentification-EmbeddedOther */,
- 1583EB2B108395BD00A3BC0C /* NetworkIdentification.bundle-EmbeddedOther */,
1583EB32108395BD00A3BC0C /* PreferencesMonitor-EmbeddedOther */,
1583EB3A108395BD00A3BC0C /* PreferencesMonitor.bundle-EmbeddedOther */,
+ 1528BFFF1357401900691881 /* SCNetworkReachability-EmbeddedOther */,
+ 1528C0071357401D00691881 /* SCNetworkReachability.bundle-EmbeddedOther */,
1583EB41108395BD00A3BC0C /* configd_executables-EmbeddedOther */,
1583EB4B108395BD00A3BC0C /* configd-EmbeddedOther */,
1583EB86108395BE00A3BC0C /* scselect-EmbeddedOther */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 1528BFE41357309700691881 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1528BFF913573FF500691881 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1528C0081357401D00691881 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
156CA4810EF853BB00C59A18 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
);
runOnlyForDeploymentPostprocessing = 0;
};
- 158317A10CFB8626006F62B9 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
158317A90CFB8639006F62B9 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
);
runOnlyForDeploymentPostprocessing = 0;
};
- 1583EB2C108395BD00A3BC0C /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
1583EB3B108395BD00A3BC0C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
);
runOnlyForDeploymentPostprocessing = 0;
};
- F95B8A6B0B03F9D100993BA3 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 1528BFDD1357305400691881 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1528BFEF135733F500691881 /* SCNetworkReachabilityServer_server.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1528BFF213573FEE00691881 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1528BFF313573FEE00691881 /* SCNetworkReachabilityServer_server.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1528C0011357401900691881 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1528C0021357401900691881 /* SCNetworkReachabilityServer_server.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
1547001A08455B98006787CE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
1572C4E20CFB55B400E2776E /* SCDPrivate.c in Sources */,
1572C4E30CFB55B400E2776E /* SCDPlugin.c in Sources */,
1572C4E40CFB55B400E2776E /* SCDOpen.c in Sources */,
- 1572C4E50CFB55B400E2776E /* SCDLock.c in Sources */,
- 1572C4E60CFB55B400E2776E /* SCDUnlock.c in Sources */,
1572C4E70CFB55B400E2776E /* SCDList.c in Sources */,
1572C4E80CFB55B400E2776E /* SCDAdd.c in Sources */,
1572C4E90CFB55B400E2776E /* SCDGet.c in Sources */,
1572C4EA0CFB55B400E2776E /* SCDSet.c in Sources */,
1572C4EB0CFB55B400E2776E /* SCDRemove.c in Sources */,
- 1572C4EC0CFB55B400E2776E /* SCDTouch.c in Sources */,
1572C4ED0CFB55B400E2776E /* SCDNotify.c in Sources */,
1572C4EE0CFB55B400E2776E /* SCDNotifierSetKeys.c in Sources */,
1572C4EF0CFB55B400E2776E /* SCDNotifierAdd.c in Sources */,
1572C4F10CFB55B400E2776E /* SCDNotifierGetChanges.c in Sources */,
1572C4F20CFB55B400E2776E /* SCDNotifierWait.c in Sources */,
1572C4F30CFB55B400E2776E /* SCDNotifierInformViaCallback.c in Sources */,
- 1572C4F40CFB55B400E2776E /* SCDNotifierInformViaMachPort.c in Sources */,
1572C4F50CFB55B400E2776E /* SCDNotifierInformViaFD.c in Sources */,
1572C4F60CFB55B400E2776E /* SCDNotifierInformViaSignal.c in Sources */,
1572C4F70CFB55B400E2776E /* SCDNotifierCancel.c in Sources */,
159A7520107FEAA400A57EAB /* VPNConfiguration.c in Sources */,
15AAA7F6108E310700C2A607 /* VPNTunnel.c in Sources */,
158E595F1107CAE80062081E /* helper.defs in Sources */,
- 152691D81129EE8A006BD2D5 /* BondConfiguration.c in Sources */,
152691DB1129EEA6006BD2D5 /* BridgeConfiguration.c in Sources */,
152691DE1129EEC2006BD2D5 /* VLANConfiguration.c in Sources */,
+ 15C330BD134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */,
+ 15C330C1134B92780028E36B /* rb.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
157A84DE0D56C63900B6F1A0 /* shared_dns_info.defs in Sources */,
157A84DF0D56C63900B6F1A0 /* dnsinfo_copy.c in Sources */,
157A84E00D56C63900B6F1A0 /* dnsinfo_private.c in Sources */,
+ D661C2F11368BB600030B977 /* network_information.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 155281020E3E4A0F00C54315 /* ip_plugin.c in Sources */,
157A84FB0D56C7E800B6F1A0 /* dns-configuration.c in Sources */,
+ 15D48EC10F67061F00B4711E /* dnsinfo_create.c in Sources */,
+ 155281020E3E4A0F00C54315 /* ip_plugin.c in Sources */,
+ E4F211D3137B0AB900BBB915 /* network_information_priv.c in Sources */,
1575FD2712CD15C60003D86E /* proxy-configuration.c in Sources */,
157A84FC0D56C7E800B6F1A0 /* set-hostname.c in Sources */,
- 15D48EC10F67061F00B4711E /* dnsinfo_create.c in Sources */,
15D48ED40F6707A600B4711E /* shared_dns_info.defs in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
);
runOnlyForDeploymentPostprocessing = 0;
};
- 157A85330D56C94F00B6F1A0 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 157A85340D56C94F00B6F1A0 /* NetworkIdentification.c in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
157A853E0D56C96F00B6F1A0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
158317330CFB80A1006F62B9 /* pattern.c in Sources */,
158317340CFB80A1006F62B9 /* _configopen.c in Sources */,
158317350CFB80A1006F62B9 /* _configclose.c in Sources */,
- 158317360CFB80A1006F62B9 /* _configlock.c in Sources */,
158317370CFB80A1006F62B9 /* _configunlock.c in Sources */,
158317380CFB80A1006F62B9 /* _configlist.c in Sources */,
158317390CFB80A1006F62B9 /* _configadd.c in Sources */,
1583173A0CFB80A1006F62B9 /* _configget.c in Sources */,
1583173B0CFB80A1006F62B9 /* _configset.c in Sources */,
1583173C0CFB80A1006F62B9 /* _configremove.c in Sources */,
- 1583173D0CFB80A1006F62B9 /* _configtouch.c in Sources */,
1583173E0CFB80A1006F62B9 /* _confignotify.c in Sources */,
1583173F0CFB80A1006F62B9 /* _notifyadd.c in Sources */,
158317400CFB80A1006F62B9 /* _notifyremove.c in Sources */,
158317480CFB80A1006F62B9 /* dnsinfo_private.c in Sources */,
158317490CFB80A1006F62B9 /* dnsinfo_server.c in Sources */,
1583174A0CFB80A1006F62B9 /* shared_dns_info.defs in Sources */,
+ 15C330E5134BD2AC0028E36B /* SCNetworkReachabilityServer_server.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
1583EA09108395BB00A3BC0C /* shared_dns_info.defs in Sources */,
1583EA0A108395BB00A3BC0C /* dnsinfo_copy.c in Sources */,
1583EA0B108395BB00A3BC0C /* dnsinfo_private.c in Sources */,
+ 151E0CA51378EE3B00C5DA2A /* network_information.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
1583EA53108395BB00A3BC0C /* SCDPrivate.c in Sources */,
1583EA54108395BB00A3BC0C /* SCDPlugin.c in Sources */,
1583EA55108395BB00A3BC0C /* SCDOpen.c in Sources */,
- 1583EA56108395BB00A3BC0C /* SCDLock.c in Sources */,
- 1583EA57108395BB00A3BC0C /* SCDUnlock.c in Sources */,
1583EA58108395BB00A3BC0C /* SCDList.c in Sources */,
1583EA59108395BB00A3BC0C /* SCDAdd.c in Sources */,
1583EA5A108395BB00A3BC0C /* SCDGet.c in Sources */,
1583EA5B108395BB00A3BC0C /* SCDSet.c in Sources */,
1583EA5C108395BB00A3BC0C /* SCDRemove.c in Sources */,
- 1583EA5D108395BB00A3BC0C /* SCDTouch.c in Sources */,
1583EA5E108395BB00A3BC0C /* SCDNotify.c in Sources */,
1583EA5F108395BB00A3BC0C /* SCDNotifierSetKeys.c in Sources */,
1583EA60108395BB00A3BC0C /* SCDNotifierAdd.c in Sources */,
1583EA62108395BB00A3BC0C /* SCDNotifierGetChanges.c in Sources */,
1583EA63108395BB00A3BC0C /* SCDNotifierWait.c in Sources */,
1583EA64108395BB00A3BC0C /* SCDNotifierInformViaCallback.c in Sources */,
- 1583EA65108395BB00A3BC0C /* SCDNotifierInformViaMachPort.c in Sources */,
1583EA66108395BB00A3BC0C /* SCDNotifierInformViaFD.c in Sources */,
1583EA67108395BB00A3BC0C /* SCDNotifierInformViaSignal.c in Sources */,
1583EA68108395BB00A3BC0C /* SCDNotifierCancel.c in Sources */,
1583EA8E108395BB00A3BC0C /* SCNetworkSignature.c in Sources */,
1583EA8F108395BB00A3BC0C /* CaptiveNetwork.c in Sources */,
158E59601107CAF10062081E /* helper.defs in Sources */,
- 152691D91129EE94006BD2D5 /* BondConfiguration.c in Sources */,
152691DD1129EEB1006BD2D5 /* BridgeConfiguration.c in Sources */,
152691E01129EECB006BD2D5 /* VLANConfiguration.c in Sources */,
+ 15C330BF134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */,
+ 15C330C3134B92780028E36B /* rb.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 1583EAD0108395BB00A3BC0C /* ip_plugin.c in Sources */,
1583EAD1108395BB00A3BC0C /* dns-configuration.c in Sources */,
+ 1583EAD3108395BB00A3BC0C /* dnsinfo_create.c in Sources */,
+ 1583EAD0108395BB00A3BC0C /* ip_plugin.c in Sources */,
+ E4F211D5137B0AD700BBB915 /* network_information_priv.c in Sources */,
1575FD2B12CD15C60003D86E /* proxy-configuration.c in Sources */,
1583EAD2108395BB00A3BC0C /* set-hostname.c in Sources */,
- 1583EAD3108395BB00A3BC0C /* dnsinfo_create.c in Sources */,
1583EAD4108395BB00A3BC0C /* shared_dns_info.defs in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
);
runOnlyForDeploymentPostprocessing = 0;
};
- 1583EB25108395BD00A3BC0C /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 1583EB26108395BD00A3BC0C /* NetworkIdentification.c in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
1583EB34108395BD00A3BC0C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
1583EB5B108395BD00A3BC0C /* pattern.c in Sources */,
1583EB5C108395BD00A3BC0C /* _configopen.c in Sources */,
1583EB5D108395BD00A3BC0C /* _configclose.c in Sources */,
- 1583EB5E108395BD00A3BC0C /* _configlock.c in Sources */,
1583EB5F108395BD00A3BC0C /* _configunlock.c in Sources */,
1583EB60108395BD00A3BC0C /* _configlist.c in Sources */,
1583EB61108395BD00A3BC0C /* _configadd.c in Sources */,
1583EB62108395BD00A3BC0C /* _configget.c in Sources */,
1583EB63108395BD00A3BC0C /* _configset.c in Sources */,
1583EB64108395BD00A3BC0C /* _configremove.c in Sources */,
- 1583EB65108395BD00A3BC0C /* _configtouch.c in Sources */,
1583EB66108395BD00A3BC0C /* _confignotify.c in Sources */,
1583EB67108395BD00A3BC0C /* _notifyadd.c in Sources */,
1583EB68108395BD00A3BC0C /* _notifyremove.c in Sources */,
1583EB70108395BD00A3BC0C /* dnsinfo_private.c in Sources */,
1583EB71108395BD00A3BC0C /* dnsinfo_server.c in Sources */,
1583EB72108395BD00A3BC0C /* shared_dns_info.defs in Sources */,
+ 15C330E6134BD2BB0028E36B /* SCNetworkReachabilityServer_server.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 159D541707528E05004F8947 /* ip_plugin.c in Sources */,
159D541807528E09004F8947 /* dns-configuration.c in Sources */,
+ 15D48EBF0F67061600B4711E /* dnsinfo_create.c in Sources */,
+ 1522FCFB0FA7FE4B00B24128 /* dnsinfo_flatfile.c in Sources */,
+ 159D541707528E05004F8947 /* ip_plugin.c in Sources */,
+ E49173E1137C4E4F0000089F /* network_information_priv.c in Sources */,
1575FD2912CD15C60003D86E /* proxy-configuration.c in Sources */,
154361E00752C81800A8EC6C /* set-hostname.c in Sources */,
1572EB7B0A506D3B00D02459 /* smb-configuration.c in Sources */,
- 15D48EBF0F67061600B4711E /* dnsinfo_create.c in Sources */,
15D48ED30F67079B00B4711E /* shared_dns_info.defs in Sources */,
- 1522FCFB0FA7FE4B00B24128 /* dnsinfo_flatfile.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
159D54B207529FFF004F8947 /* pattern.c in Sources */,
159D54B307529FFF004F8947 /* _configopen.c in Sources */,
159D54B407529FFF004F8947 /* _configclose.c in Sources */,
- 159D54B507529FFF004F8947 /* _configlock.c in Sources */,
159D54B607529FFF004F8947 /* _configunlock.c in Sources */,
159D54B707529FFF004F8947 /* _configlist.c in Sources */,
159D54B807529FFF004F8947 /* _configadd.c in Sources */,
159D54B907529FFF004F8947 /* _configget.c in Sources */,
159D54BA07529FFF004F8947 /* _configset.c in Sources */,
159D54BB07529FFF004F8947 /* _configremove.c in Sources */,
- 159D54BC07529FFF004F8947 /* _configtouch.c in Sources */,
159D54BD07529FFF004F8947 /* _confignotify.c in Sources */,
159D54BE07529FFF004F8947 /* _notifyadd.c in Sources */,
159D54BF07529FFF004F8947 /* _notifyremove.c in Sources */,
15A5A2210D5B94190087BDA0 /* SCDPrivate.c in Sources */,
15A5A2220D5B94190087BDA0 /* SCDPlugin.c in Sources */,
15A5A2230D5B94190087BDA0 /* SCDOpen.c in Sources */,
- 15A5A2240D5B94190087BDA0 /* SCDLock.c in Sources */,
- 15A5A2250D5B94190087BDA0 /* SCDUnlock.c in Sources */,
15A5A2260D5B94190087BDA0 /* SCDList.c in Sources */,
15A5A2270D5B94190087BDA0 /* SCDAdd.c in Sources */,
15A5A2280D5B94190087BDA0 /* SCDGet.c in Sources */,
15A5A2290D5B94190087BDA0 /* SCDSet.c in Sources */,
15A5A22A0D5B94190087BDA0 /* SCDRemove.c in Sources */,
- 15A5A22B0D5B94190087BDA0 /* SCDTouch.c in Sources */,
15A5A22C0D5B94190087BDA0 /* SCDNotify.c in Sources */,
15A5A22D0D5B94190087BDA0 /* SCDNotifierSetKeys.c in Sources */,
15A5A22E0D5B94190087BDA0 /* SCDNotifierAdd.c in Sources */,
15A5A2300D5B94190087BDA0 /* SCDNotifierGetChanges.c in Sources */,
15A5A2310D5B94190087BDA0 /* SCDNotifierWait.c in Sources */,
15A5A2320D5B94190087BDA0 /* SCDNotifierInformViaCallback.c in Sources */,
- 15A5A2330D5B94190087BDA0 /* SCDNotifierInformViaMachPort.c in Sources */,
15A5A2340D5B94190087BDA0 /* SCDNotifierInformViaFD.c in Sources */,
15A5A2350D5B94190087BDA0 /* SCDNotifierInformViaSignal.c in Sources */,
15A5A2360D5B94190087BDA0 /* SCDNotifierCancel.c in Sources */,
159A752C107FEAA400A57EAB /* VPNPrivate.c in Sources */,
159A752E107FEAA400A57EAB /* VPNConfiguration.c in Sources */,
158E59611107CAF40062081E /* helper.defs in Sources */,
- 152691DA1129EE98006BD2D5 /* BondConfiguration.c in Sources */,
152691DC1129EEAD006BD2D5 /* BridgeConfiguration.c in Sources */,
152691DF1129EEC8006BD2D5 /* VLANConfiguration.c in Sources */,
+ 15C330BE134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */,
+ 15C330C2134B92780028E36B /* rb.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
15DAD5E5075913CE0084A6ED /* shared_dns_info.defs in Sources */,
15DAD5E6075913CE0084A6ED /* dnsinfo_copy.c in Sources */,
15DAD5E7075913CE0084A6ED /* dnsinfo_private.c in Sources */,
+ D6986A79136891650091C931 /* network_information.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
15DAD66E07591A1A0084A6ED /* SCDKeys.c in Sources */,
15DAD66F07591A1A0084A6ED /* SCDPrivate.c in Sources */,
15DAD67007591A1A0084A6ED /* SCDPlugin.c in Sources */,
+ 7264C144147319E7004FD76D /* CaptiveNetwork.c in Sources */,
15DAD67107591A1A0084A6ED /* SCDOpen.c in Sources */,
- 15DAD67207591A1A0084A6ED /* SCDLock.c in Sources */,
- 15DAD67307591A1A0084A6ED /* SCDUnlock.c in Sources */,
15DAD67407591A1A0084A6ED /* SCDList.c in Sources */,
15DAD67507591A1A0084A6ED /* SCDAdd.c in Sources */,
15DAD67607591A1A0084A6ED /* SCDGet.c in Sources */,
15DAD67707591A1A0084A6ED /* SCDSet.c in Sources */,
15DAD67807591A1A0084A6ED /* SCDRemove.c in Sources */,
- 15DAD67907591A1A0084A6ED /* SCDTouch.c in Sources */,
15DAD67A07591A1A0084A6ED /* SCDNotify.c in Sources */,
15DAD67B07591A1A0084A6ED /* SCDNotifierSetKeys.c in Sources */,
15DAD67C07591A1A0084A6ED /* SCDNotifierAdd.c in Sources */,
15DAD67E07591A1A0084A6ED /* SCDNotifierGetChanges.c in Sources */,
15DAD67F07591A1A0084A6ED /* SCDNotifierWait.c in Sources */,
15DAD68007591A1A0084A6ED /* SCDNotifierInformViaCallback.c in Sources */,
- 15DAD68107591A1A0084A6ED /* SCDNotifierInformViaMachPort.c in Sources */,
15DAD68207591A1A0084A6ED /* SCDNotifierInformViaFD.c in Sources */,
15DAD68307591A1A0084A6ED /* SCDNotifierInformViaSignal.c in Sources */,
15DAD68407591A1A0084A6ED /* SCDNotifierCancel.c in Sources */,
159A7527107FEAA400A57EAB /* VPNConfiguration.c in Sources */,
15AAA7F9108E310700C2A607 /* VPNTunnel.c in Sources */,
158E595E1107CAE40062081E /* helper.defs in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- F95B8A5C0B03F81400993BA3 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- F95B8A690B03F9B500993BA3 /* NetworkIdentification.c in Sources */,
+ 15C330BC134B92780028E36B /* SCNetworkReachabilityServer_client.c in Sources */,
+ 15C330C0134B92780028E36B /* rb.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
target = 151FE2DD0D5B7046000D6DB1 /* configd_base-EmbeddedSimulator */;
targetProxy = 151FE3790D5B713C000D6DB1 /* PBXContainerItemProxy */;
};
- 1520A386084681350010B584 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 1547001808455B98006787CE /* SCHelper */;
- targetProxy = 1520A385084681350010B584 /* PBXContainerItemProxy */;
- };
1521405B0E9400BF00DACD2C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 15213FF90E93E9F500DACD2C /* Logger.bundle */;
targetProxy = 1521405A0E9400BF00DACD2C /* PBXContainerItemProxy */;
};
+ 1528BFEC135731B800691881 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 1528BFDB1357305400691881 /* SCNetworkReachability */;
+ targetProxy = 1528BFEB135731B800691881 /* PBXContainerItemProxy */;
+ };
+ 1528BFEE135731B800691881 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 1528BFE31357309700691881 /* SCNetworkReachability.bundle */;
+ targetProxy = 1528BFED135731B800691881 /* PBXContainerItemProxy */;
+ };
+ 1528C00F135741C300691881 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 1528BFF013573FEE00691881 /* SCNetworkReachability-Embedded */;
+ targetProxy = 1528C00E135741C300691881 /* PBXContainerItemProxy */;
+ };
+ 1528C011135741C300691881 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 1528BFF813573FF500691881 /* SCNetworkReachability.bundle-Embedded */;
+ targetProxy = 1528C010135741C300691881 /* PBXContainerItemProxy */;
+ };
+ 1528C0131357420300691881 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 1528BFFF1357401900691881 /* SCNetworkReachability-EmbeddedOther */;
+ targetProxy = 1528C0121357420300691881 /* PBXContainerItemProxy */;
+ };
+ 1528C0151357420300691881 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 1528C0071357401D00691881 /* SCNetworkReachability.bundle-EmbeddedOther */;
+ targetProxy = 1528C0141357420300691881 /* PBXContainerItemProxy */;
+ };
1558480607550D470046C2E9 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 159D549F07529FFF004F8947 /* configd */;
target = 157A85260D56C91100B6F1A0 /* LinkConfiguration-Embedded */;
targetProxy = 157A854D0D56CA6F00B6F1A0 /* PBXContainerItemProxy */;
};
- 157A85500D56CA8800B6F1A0 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 157A85310D56C94F00B6F1A0 /* NetworkIdentification-Embedded */;
- targetProxy = 157A854F0D56CA8800B6F1A0 /* PBXContainerItemProxy */;
- };
157A85520D56CA9E00B6F1A0 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 157A853C0D56C96F00B6F1A0 /* PreferencesMonitor-Embedded */;
target = 158317230CFB80A1006F62B9 /* configd-Embedded */;
targetProxy = 158317650CFB80D5006F62B9 /* PBXContainerItemProxy */;
};
- 158317B30CFB8660006F62B9 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 158317A00CFB8626006F62B9 /* NetworkIdentification.bundle-Embedded */;
- targetProxy = 158317B20CFB8660006F62B9 /* PBXContainerItemProxy */;
- };
158317B50CFB8660006F62B9 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 158317980CFB860C006F62B9 /* LinkConfiguration.bundle-Embedded */;
target = 1583EB32108395BD00A3BC0C /* PreferencesMonitor-EmbeddedOther */;
targetProxy = 15AC5172108396D2004A9ED5 /* PBXContainerItemProxy */;
};
- 15AC5175108396D2004A9ED5 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 1583EB2B108395BD00A3BC0C /* NetworkIdentification.bundle-EmbeddedOther */;
- targetProxy = 15AC5174108396D2004A9ED5 /* PBXContainerItemProxy */;
- };
- 15AC5177108396D2004A9ED5 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 1583EB23108395BD00A3BC0C /* NetworkIdentification-EmbeddedOther */;
- targetProxy = 15AC5176108396D2004A9ED5 /* PBXContainerItemProxy */;
- };
15AC5179108396D2004A9ED5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 1583EB16108395BC00A3BC0C /* Logger.bundle-EmbeddedOther */;
target = 157A84D80D56C63900B6F1A0 /* DNSConfiguration-Embedded */;
targetProxy = 15C64A300F684C8F00D78394 /* PBXContainerItemProxy */;
};
- F95B8A770B03FB9100993BA3 /* PBXTargetDependency */ = {
+ D6DDAC3D147A24BC00A2E902 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = F95B8A6A0B03F9D100993BA3 /* NetworkIdentification.bundle */;
- targetProxy = F95B8A760B03FB9100993BA3 /* PBXContainerItemProxy */;
- };
- F95B8A790B03FB9100993BA3 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = F95B8A5E0B03F81400993BA3 /* NetworkIdentification */;
- targetProxy = F95B8A780B03FB9100993BA3 /* PBXContainerItemProxy */;
+ target = 1547001808455B98006787CE /* SCHelper */;
+ targetProxy = D6DDAC3C147A24BC00A2E902 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
151C1CC70CFB487000C5AFD6 /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd (Aggregate/Embedded)";
};
};
151C1CC80CFB487000C5AFD6 /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd (Aggregate/Embedded)";
};
FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
INFOPLIST_FILE = SCMonitor/Info.plist;
INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = /System/Library/UserEventPlugins;
- PRODUCT_NAME = SCMonitor;
- WRAPPER_EXTENSION = plugin;
+ INSTALL_PATH = /System/Library/UserEventPlugins;
+ PRODUCT_NAME = SCMonitor;
+ WRAPPER_EXTENSION = plugin;
+ };
+ name = Release;
+ };
+ 151F63DD09328A3C0096DCC9 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ INSTALLHDRS_SCRIPT_PHASE = YES;
+ PRODUCT_NAME = genSCPreferences;
+ WARNING_CFLAGS = (
+ "-Wall",
+ "-Wno-four-char-constants",
+ "-Wno-unknown-pragmas",
+ );
+ };
+ name = Debug;
+ };
+ 151F63DE09328A3C0096DCC9 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ INSTALLHDRS_SCRIPT_PHASE = YES;
+ PRODUCT_NAME = genSCPreferences;
+ WARNING_CFLAGS = (
+ "-Wall",
+ "-Wno-four-char-constants",
+ "-Wno-unknown-pragmas",
+ );
+ };
+ name = Release;
+ };
+ 151FE2E50D5B7046000D6DB1 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+ buildSettings = {
+ PRODUCT_NAME = "configd_base (EmbeddedSimulator)";
+ };
+ name = Debug;
+ };
+ 151FE2E60D5B7046000D6DB1 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+ buildSettings = {
+ PRODUCT_NAME = "configd_base (EmbeddedSimulator)";
+ };
+ name = Release;
+ };
+ 15213FFC0E93E9F600DACD2C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = Plugins/Logger/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ PRODUCT_NAME = Logger;
+ };
+ name = Debug;
+ };
+ 15213FFD0E93E9F600DACD2C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = Plugins/Logger/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ PRODUCT_NAME = Logger;
+ };
+ name = Release;
+ };
+ 1528BFE01357305400691881 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ PRODUCT_NAME = SCNetworkReachability;
+ STRIP_INSTALLED_PRODUCT = NO;
+ };
+ name = Debug;
+ };
+ 1528BFE11357305400691881 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ PRODUCT_NAME = SCNetworkReachability;
+ STRIP_INSTALLED_PRODUCT = NO;
+ };
+ name = Release;
+ };
+ 1528BFE61357309700691881 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ PRODUCT_NAME = SCNetworkReachability;
+ };
+ name = Debug;
+ };
+ 1528BFE71357309700691881 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ PRODUCT_NAME = SCNetworkReachability;
+ };
+ name = Release;
+ };
+ 1528BFF513573FEE00691881 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+ buildSettings = {
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ PRODUCT_NAME = SCNetworkReachability;
+ STRIP_INSTALLED_PRODUCT = NO;
+ };
+ name = Debug;
+ };
+ 1528BFF613573FEE00691881 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
+ buildSettings = {
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ PRODUCT_NAME = SCNetworkReachability;
+ STRIP_INSTALLED_PRODUCT = NO;
};
name = Release;
};
- 151F63DD09328A3C0096DCC9 /* Debug */ = {
+ 1528BFFC13573FF500691881 /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
- COPY_PHASE_STRIP = NO;
- INSTALLHDRS_SCRIPT_PHASE = YES;
- PRODUCT_NAME = genSCPreferences;
- WARNING_CFLAGS = (
- "-Wall",
- "-Wno-four-char-constants",
- "-Wno-unknown-pragmas",
- );
+ INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ PRODUCT_NAME = SCNetworkReachability;
};
name = Debug;
};
- 151F63DE09328A3C0096DCC9 /* Release */ = {
+ 1528BFFD13573FF500691881 /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
- COPY_PHASE_STRIP = YES;
- INSTALLHDRS_SCRIPT_PHASE = YES;
- PRODUCT_NAME = genSCPreferences;
- WARNING_CFLAGS = (
- "-Wall",
- "-Wno-four-char-constants",
- "-Wno-unknown-pragmas",
- );
+ INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ PRODUCT_NAME = SCNetworkReachability;
};
name = Release;
};
- 151FE2E50D5B7046000D6DB1 /* Debug */ = {
+ 1528C0041357401900691881 /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
- PRODUCT_NAME = "configd_base (EmbeddedSimulator)";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ PRODUCT_NAME = SCNetworkReachability;
+ STRIP_INSTALLED_PRODUCT = NO;
};
name = Debug;
};
- 151FE2E60D5B7046000D6DB1 /* Release */ = {
+ 1528C0051357401900691881 /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 15FD147B0D594FE700F9409C /* IndigoSDK.xcconfig */;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
- PRODUCT_NAME = "configd_base (EmbeddedSimulator)";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ PRODUCT_NAME = SCNetworkReachability;
+ STRIP_INSTALLED_PRODUCT = NO;
};
name = Release;
};
- 15213FFC0E93E9F600DACD2C /* Debug */ = {
+ 1528C00B1357401D00691881 /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
- INFOPLIST_FILE = Plugins/Logger/Info.plist;
+ INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
- PRODUCT_NAME = Logger;
+ PRODUCT_NAME = SCNetworkReachability;
};
name = Debug;
};
- 15213FFD0E93E9F600DACD2C /* Release */ = {
+ 1528C00C1357401D00691881 /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
- INFOPLIST_FILE = Plugins/Logger/Info.plist;
+ INFOPLIST_FILE = Plugins/SCNetworkReachability/Info.plist;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
- PRODUCT_NAME = Logger;
+ PRODUCT_NAME = SCNetworkReachability;
};
name = Release;
};
INSTALLHDRS_COPY_PHASE = YES;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = /usr/lib/system;
+ LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
MACH_O_TYPE = mh_dylib;
OTHER_CFLAGS_debug = "-O0";
OTHER_LDFLAGS = (
INSTALLHDRS_COPY_PHASE = YES;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = /usr/lib/system;
+ LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
MACH_O_TYPE = mh_dylib;
OTHER_CFLAGS_debug = "-O0";
OTHER_CFLAGS_normal = "";
buildSettings = {
CODE_SIGN_IDENTITY = "-";
FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+ GCC_DYNAMIC_NO_PIC = NO;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/SystemConfiguration.framework/Versions/A/Resources";
PRODUCT_NAME = SCHelper;
buildSettings = {
CODE_SIGN_IDENTITY = "-";
FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+ GCC_DYNAMIC_NO_PIC = NO;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/SystemConfiguration.framework/Versions/A/Resources";
PRODUCT_NAME = SCHelper;
buildSettings = {
CODE_SIGN_IDENTITY = "-";
FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+ GCC_DYNAMIC_NO_PIC = NO;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = /usr/libexec;
LIBRARY_SEARCH_PATHS = (
buildSettings = {
CODE_SIGN_IDENTITY = "-";
FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+ GCC_DYNAMIC_NO_PIC = NO;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = /usr/libexec;
LIBRARY_SEARCH_PATHS = (
buildSettings = {
CODE_SIGN_IDENTITY = "-";
FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+ GCC_DYNAMIC_NO_PIC = NO;
INSTALL_MODE_FLAG = "a-w,a+rX,u+s";
INSTALL_PATH = /usr/sbin;
PRODUCT_NAME = scselect;
buildSettings = {
CODE_SIGN_IDENTITY = "-";
FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+ GCC_DYNAMIC_NO_PIC = NO;
INSTALL_MODE_FLAG = "a-w,a+rX,u+s";
INSTALL_PATH = /usr/sbin;
PRODUCT_NAME = scselect;
buildSettings = {
CODE_SIGN_IDENTITY = "-";
FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+ GCC_DYNAMIC_NO_PIC = NO;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = /usr/sbin;
LIBRARY_SEARCH_PATHS = (
buildSettings = {
CODE_SIGN_IDENTITY = "-";
FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+ GCC_DYNAMIC_NO_PIC = NO;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = /usr/sbin;
LIBRARY_SEARCH_PATHS = (
156EB63F0905594A00EEF749 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ "ARCHS[sdk=iphoneos*]" = "$(NATIVE_ARCH)";
+ "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_32_64_BIT)";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
DEAD_CODE_STRIPPING = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
GCC_OPTIMIZATION_LEVEL = 0;
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
"-Wformat-security",
+ "-Wcast-align",
);
};
name = Debug;
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
"-Wformat-security",
+ "-Wcast-align",
);
};
name = Release;
INSTALLHDRS_COPY_PHASE = YES;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = /usr/lib/system;
+ LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
MACH_O_TYPE = mh_dylib;
OTHER_CFLAGS_debug = "-O0";
OTHER_CFLAGS_normal = "";
INSTALLHDRS_COPY_PHASE = YES;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = /usr/lib/system;
+ LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
MACH_O_TYPE = mh_dylib;
OTHER_CFLAGS_debug = "-O0";
OTHER_CFLAGS_normal = "";
};
name = Release;
};
- 157A85360D56C94F00B6F1A0 /* Debug */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
- buildSettings = {
- DEBUG_INFORMATION_FORMAT = dwarf;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = /usr/local/lib/SystemConfiguration;
- LIBRARY_STYLE = STATIC;
- PRODUCT_NAME = NetworkIdentification;
- STRIP_INSTALLED_PRODUCT = NO;
- };
- name = Debug;
- };
- 157A85370D56C94F00B6F1A0 /* Release */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
- buildSettings = {
- DEBUG_INFORMATION_FORMAT = dwarf;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = /usr/local/lib/SystemConfiguration;
- LIBRARY_STYLE = STATIC;
- PRODUCT_NAME = NetworkIdentification;
- STRIP_INSTALLED_PRODUCT = NO;
- };
- name = Release;
- };
157A85410D56C96F00B6F1A0 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
};
158316D90CFB774B006F62B9 /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_base (Embedded)";
};
};
158316DA0CFB774B006F62B9 /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_base (Embedded)";
};
};
158317010CFB7761006F62B9 /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_plugins (Embedded)";
};
};
158317020CFB7761006F62B9 /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_plugins (Embedded)";
};
};
1583170C0CFB7782006F62B9 /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_executables (Embedded)";
};
};
1583170D0CFB7782006F62B9 /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_executables (Embedded)";
};
};
name = Release;
};
- 158317A30CFB8626006F62B9 /* Debug */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
- buildSettings = {
- INFOPLIST_FILE = Plugins/NetworkIdentification/Info.plist;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
- PRODUCT_NAME = NetworkIdentification;
- };
- name = Debug;
- };
- 158317A40CFB8626006F62B9 /* Release */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
- buildSettings = {
- INFOPLIST_FILE = Plugins/NetworkIdentification/Info.plist;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
- PRODUCT_NAME = NetworkIdentification;
- };
- name = Release;
- };
158317AB0CFB8639006F62B9 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
};
1583E9EA1083959E00A3BC0C /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd (Aggregate/EmbeddedOther)";
};
};
1583E9EB1083959E00A3BC0C /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd (Aggregate/EmbeddedOther)";
};
INSTALLHDRS_COPY_PHASE = YES;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = /usr/lib/system;
+ LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
MACH_O_TYPE = mh_dylib;
OTHER_CFLAGS_debug = "-O0";
OTHER_CFLAGS_normal = "";
System,
);
OTHER_MIGFLAGS = "-DLIBDNSINFO";
- PRODUCT_NAME = dnsinfo;
+ PRODUCT_NAME = libdnsinfo;
STRIP_INSTALLED_PRODUCT_debug = NO;
STRIP_INSTALLED_PRODUCT_normal = YES;
STRIP_INSTALLED_PRODUCT_profile = NO;
INSTALLHDRS_COPY_PHASE = YES;
INSTALL_MODE_FLAG = "a-w,a+rX";
INSTALL_PATH = /usr/lib/system;
+ LD_DYLIB_INSTALL_NAME = /usr/lib/system/libdnsinfo.dylib;
MACH_O_TYPE = mh_dylib;
OTHER_CFLAGS_debug = "-O0";
OTHER_CFLAGS_normal = "";
System,
);
OTHER_MIGFLAGS = "-DLIBDNSINFO";
- PRODUCT_NAME = dnsinfo;
+ PRODUCT_NAME = libdnsinfo;
STRIP_INSTALLED_PRODUCT_debug = NO;
STRIP_INSTALLED_PRODUCT_normal = YES;
STRIP_INSTALLED_PRODUCT_profile = NO;
};
1583EA17108395BB00A3BC0C /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_base (EmbeddedOther)";
};
};
1583EA18108395BB00A3BC0C /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_base (EmbeddedOther)";
};
};
1583EAC8108395BB00A3BC0C /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_plugins (EmbeddedOther)";
};
};
1583EAC9108395BB00A3BC0C /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_plugins (EmbeddedOther)";
};
};
name = Release;
};
- 1583EB28108395BD00A3BC0C /* Debug */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
- buildSettings = {
- DEBUG_INFORMATION_FORMAT = dwarf;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = /usr/local/lib/SystemConfiguration;
- LIBRARY_STYLE = STATIC;
- PRODUCT_NAME = NetworkIdentification;
- STRIP_INSTALLED_PRODUCT = NO;
- };
- name = Debug;
- };
- 1583EB29108395BD00A3BC0C /* Release */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
- buildSettings = {
- DEBUG_INFORMATION_FORMAT = dwarf;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = /usr/local/lib/SystemConfiguration;
- LIBRARY_STYLE = STATIC;
- PRODUCT_NAME = NetworkIdentification;
- STRIP_INSTALLED_PRODUCT = NO;
- };
- name = Release;
- };
- 1583EB2E108395BD00A3BC0C /* Debug */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
- buildSettings = {
- INFOPLIST_FILE = Plugins/NetworkIdentification/Info.plist;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
- PRODUCT_NAME = NetworkIdentification;
- };
- name = Debug;
- };
- 1583EB2F108395BD00A3BC0C /* Release */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
- buildSettings = {
- INFOPLIST_FILE = Plugins/NetworkIdentification/Info.plist;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
- PRODUCT_NAME = NetworkIdentification;
- };
- name = Release;
- };
1583EB37108395BD00A3BC0C /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
};
1583EB49108395BD00A3BC0C /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_executables (EmbeddedOther)";
};
};
1583EB4A108395BD00A3BC0C /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 15AEABBC0DAD5B3000D1C969 /* AspenSDK.xcconfig */;
buildSettings = {
PRODUCT_NAME = "configd_executables (EmbeddedOther)";
};
};
name = Release;
};
- F95B8A620B03F83200993BA3 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- DEBUG_INFORMATION_FORMAT = dwarf;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = /usr/local/lib/SystemConfiguration;
- LIBRARY_STYLE = STATIC;
- PRODUCT_NAME = NetworkIdentification;
- STRIP_INSTALLED_PRODUCT = NO;
- };
- name = Debug;
- };
- F95B8A630B03F83200993BA3 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- DEBUG_INFORMATION_FORMAT = dwarf;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = /usr/local/lib/SystemConfiguration;
- LIBRARY_STYLE = STATIC;
- PRODUCT_NAME = NetworkIdentification;
- STRIP_INSTALLED_PRODUCT = NO;
- };
- name = Release;
- };
- F95B8A6D0B03F9D100993BA3 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- INFOPLIST_FILE = Plugins/NetworkIdentification/Info.plist;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
- PRODUCT_NAME = NetworkIdentification;
- };
- name = Debug;
- };
- F95B8A6E0B03F9D100993BA3 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- INFOPLIST_FILE = Plugins/NetworkIdentification/Info.plist;
- INSTALL_MODE_FLAG = "a-w,a+rX";
- INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
- PRODUCT_NAME = NetworkIdentification;
- };
- name = Release;
- };
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 1528BFDF1357305400691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1528BFE01357305400691881 /* Debug */,
+ 1528BFE11357305400691881 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1528BFE51357309700691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability.bundle" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1528BFE61357309700691881 /* Debug */,
+ 1528BFE71357309700691881 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1528BFF413573FEE00691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability-Embedded" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1528BFF513573FEE00691881 /* Debug */,
+ 1528BFF613573FEE00691881 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1528BFFB13573FF500691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability.bundle-Embedded" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1528BFFC13573FF500691881 /* Debug */,
+ 1528BFFD13573FF500691881 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1528C0031357401900691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability-EmbeddedOther" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1528C0041357401900691881 /* Debug */,
+ 1528C0051357401900691881 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1528C00A1357401D00691881 /* Build configuration list for PBXNativeTarget "SCNetworkReachability.bundle-EmbeddedOther" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1528C00B1357401D00691881 /* Debug */,
+ 1528C00C1357401D00691881 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
156CA4820EF853BB00C59A18 /* Build configuration list for PBXNativeTarget "Logger.bundle-Embedded" */ = {
isa = XCConfigurationList;
buildConfigurations = (
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 157A85350D56C94F00B6F1A0 /* Build configuration list for PBXNativeTarget "NetworkIdentification-Embedded" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 157A85360D56C94F00B6F1A0 /* Debug */,
- 157A85370D56C94F00B6F1A0 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
157A85400D56C96F00B6F1A0 /* Build configuration list for PBXNativeTarget "PreferencesMonitor-Embedded" */ = {
isa = XCConfigurationList;
buildConfigurations = (
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 158317A20CFB8626006F62B9 /* Build configuration list for PBXNativeTarget "NetworkIdentification.bundle-Embedded" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 158317A30CFB8626006F62B9 /* Debug */,
- 158317A40CFB8626006F62B9 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
158317AA0CFB8639006F62B9 /* Build configuration list for PBXNativeTarget "PreferencesMonitor.bundle-Embedded" */ = {
isa = XCConfigurationList;
buildConfigurations = (
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 1583EB27108395BD00A3BC0C /* Build configuration list for PBXNativeTarget "NetworkIdentification-EmbeddedOther" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 1583EB28108395BD00A3BC0C /* Debug */,
- 1583EB29108395BD00A3BC0C /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 1583EB2D108395BD00A3BC0C /* Build configuration list for PBXNativeTarget "NetworkIdentification.bundle-EmbeddedOther" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 1583EB2E108395BD00A3BC0C /* Debug */,
- 1583EB2F108395BD00A3BC0C /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
1583EB36108395BD00A3BC0C /* Build configuration list for PBXNativeTarget "PreferencesMonitor-EmbeddedOther" */ = {
isa = XCConfigurationList;
buildConfigurations = (
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- F95B8A610B03F83200993BA3 /* Build configuration list for PBXNativeTarget "NetworkIdentification" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- F95B8A620B03F83200993BA3 /* Debug */,
- F95B8A630B03F83200993BA3 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- F95B8A6C0B03F9D100993BA3 /* Build configuration list for PBXNativeTarget "NetworkIdentification.bundle" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- F95B8A6D0B03F9D100993BA3 /* Debug */,
- F95B8A6E0B03F9D100993BA3 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
/* End XCConfigurationList section */
};
rootObject = 15CB6A7705C0722B0099E85F /* Project object */;
/*
- * Copyright (c) 2004-2006, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2006, 2008, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <sys/socket.h>
#include <netinet/in.h>
-#define DNSINFO_VERSION 20091104
+#define DNSINFO_VERSION 20111104
#define DEFAULT_SEARCH_ORDER 200000 /* search order for the "default" resolver domain name */
DNS_VAR(uint32_t, search_order); /* search_order */
DNS_VAR(uint32_t, if_index);
DNS_VAR(uint32_t, flags);
- DNS_VAR(uint32_t, reserved[6]);
+ DNS_VAR(uint32_t, reach_flags); /* SCNetworkReachabilityFlags */
+ DNS_VAR(uint32_t, reserved[5]);
} dns_resolver_t;
#pragma pack()
-#define DNS_RESOLVER_FLAGS_SCOPED 1
+#define DNS_RESOLVER_FLAGS_SCOPED 1 /* configuration is for scoped questions */
#pragma pack(4)
void
dns_configuration_free (dns_config_t *config) __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
+void
+_dns_configuration_ack (dns_config_t *config,
+ const char *bundle_id) __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
+
__END_DECLS
#endif /* __DNSINFO_H__ */
/*
- * Copyright (c) 2004, 2006, 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2004, 2006, 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "dnsinfo.h"
#include "dnsinfo_private.h"
#include "shared_dns_info.h"
+#include "network_information_priv.h"
static pthread_once_t _dns_initialized = PTHREAD_ONCE_INIT;
static pthread_mutex_t _dns_lock = PTHREAD_MUTEX_INITIALIZER;
static mach_port_t _dns_server = MACH_PORT_NULL;
+enum {
+ get_dns_info = 1,
+ get_nwi_state = 2,
+};
+
+typedef uint32_t getflags;
static void
__dns_fork_handler()
#define DNS_CONFIG_BUF_MAX 1024*1024
-static _dns_config_buf_t *
-copy_dns_info()
-{
- uint8_t *buf = NULL;
- dnsDataOut_t dataRef = NULL;
- mach_msg_type_number_t dataLen = 0;
- mach_port_t server;
- kern_return_t status;
+static kern_return_t
+_dns_server_copy(void* dataRef, mach_msg_type_number_t* dataLen, getflags flags){
+ mach_port_t server;
+ kern_return_t status = KERN_FAILURE;
// initialize runtime
pthread_once(&_dns_initialized, __dns_initialize);
server = _dns_server;
while (TRUE) {
if (server != MACH_PORT_NULL) {
- status = shared_dns_infoGet(server, &dataRef, &dataLen);
+ if (flags == get_dns_info) {
+ status = shared_dns_infoGet(server, dataRef, dataLen);
+ } else {
+ status = shared_nwi_stateGet(server, dataRef, dataLen);
+ }
if (status == KERN_SUCCESS) {
break;
}
}
}
+ return status;
+}
+
+
+__private_extern__
+nwi_state*
+_nwi_state_copy() {
+ dnsDataOut_t dataRef = NULL;
+ mach_msg_type_number_t dataLen = 0;
+ kern_return_t status;
+ nwi_state* state = NULL;
+
+ status = _dns_server_copy(&dataRef, &dataLen, get_nwi_state);
+ if (status != KERN_SUCCESS) {
+ return NULL;
+ }
+
+ if (dataRef != NULL) {
+ state = malloc(dataLen);
+ if (state == NULL) {
+ vm_deallocate(mach_task_self(), (vm_address_t)dataRef,
+ dataLen);
+ return NULL;
+ }
+ memcpy((void*) state, (void*) dataRef, dataLen);
+ state->ref = 0;
+ status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
+ if (status != KERN_SUCCESS) {
+ mach_error("vm_deallocate():", status);
+ free(state);
+ return NULL;
+ }
+ }
+
+ return state;
+}
+
+
+static _dns_config_buf_t *
+copy_dns_info()
+{
+ uint8_t *buf = NULL;
+ dnsDataOut_t dataRef = NULL;
+ mach_msg_type_number_t dataLen = 0;
+ kern_return_t status;
+
+ status = _dns_server_copy(&dataRef, &dataLen, get_dns_info);
+ if (status != KERN_SUCCESS) {
+ return NULL;
+ }
+
if (dataRef != NULL) {
if ((dataLen >= sizeof(_dns_config_buf_t)) && (dataLen <= DNS_CONFIG_BUF_MAX)) {
- _dns_config_buf_t *config = (_dns_config_buf_t *)dataRef;
- uint32_t n_padding = ntohl(config->n_padding);
+ /* ALIGN: cast okay since _dns_config_buf_t is int aligned */
+ _dns_config_buf_t *config = (_dns_config_buf_t *)(void *)dataRef;
+ uint32_t n_padding = ntohl(config->n_padding);
if (n_padding <= (DNS_CONFIG_BUF_MAX - dataLen)) {
uint32_t len;
}
}
- return (_dns_config_buf_t *)buf;
+ /* ALIGN: buf malloc'ed, should be aligned >8 bytes */
+ return (_dns_config_buf_t *)(void *)buf;
}
resolver->flags = ntohl(resolver->flags);
+ // initialize SCNetworkReachability flags
+
+ resolver->reach_flags = ntohl(resolver->reach_flags);
+
// process resolver buffer "attribute" data
n_attribute = n_buf - sizeof(_dns_resolver_buf_t);
- attribute = (dns_attribute_t *)&buf->attribute[0];
+ /* ALIGN: alignment not assumed, using accessors */
+ attribute = (dns_attribute_t *)(void *)&buf->attribute[0];
if (n_attribute != ntohl(buf->n_attribute)) {
goto error;
}
break;
case RESOLVER_ATTRIBUTE_SORTADDR :
- resolver->sortaddr[n_sortaddr++] = (dns_sortaddr_t *)&attribute->attribute[0];
+ resolver->sortaddr[n_sortaddr++] = (dns_sortaddr_t *)(void *)&attribute->attribute[0];
break;
case RESOLVER_ATTRIBUTE_OPTIONS :
// process configuration buffer "attribute" data
n_attribute = ntohl(buf->n_attribute);
- attribute = (dns_attribute_t *)&buf->attribute[0];
+ attribute = (dns_attribute_t *)(void *)&buf->attribute[0];
while (n_attribute >= sizeof(dns_attribute_t)) {
uint32_t attribute_length = ntohl(attribute->length);
// expand resolver buffer
- resolver = expand_resolver((_dns_resolver_buf_t *)&attribute->attribute[0],
+ resolver = expand_resolver((_dns_resolver_buf_t *)(void *)&attribute->attribute[0],
attribute_length - sizeof(dns_attribute_t),
&padding,
&n_padding);
return;
}
+
+void
+_dns_configuration_ack(dns_config_t *config, const char *bundle_id)
+{
+ return;
+}
+
#ifdef MAIN
int
/*
- * Copyright (c) 2004, 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2004, 2006, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <strings.h>
#include <mach/mach.h>
#include <mach/mach_error.h>
+#include <CommonCrypto/CommonDigest.h>
#include "dnsinfo_create.h"
#include "dnsinfo_private.h"
#include "shared_dns_info.h"
+#include "network_information_priv.h"
#define ROUNDUP(a, size) \
// add attribute [header]
- header = (dns_attribute_t *)&config->attribute[oldLen];
+ /* ALIGN: _dns_config_buf_t is int aligned */
+ header = (dns_attribute_t *)(void *)&config->attribute[oldLen];
header->type = htonl(attribute_type);
header->length = htonl(newLen);
return;
}
+_Bool
+_nwi_state_store(nwi_state* state)
+{
+ mach_port_t server;
+ kern_return_t status;
+ dnsDataOut_t dataRef = (dnsDataOut_t) state;
+ mach_msg_type_number_t dataLen = state->size;
+
+ server = _dns_configuration_server_port();
+ if (server == MACH_PORT_NULL) {
+ return FALSE;
+ }
+
+ status = shared_nwi_stateSet(server, dataRef, dataLen);
+
+ (void) mach_port_deallocate(mach_task_self(), server);
+
+ if (status != KERN_SUCCESS) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+void
+_dns_configuration_signature(dns_create_config_t *_config,
+ unsigned char *signature,
+ size_t signature_len)
+{
+ bzero(signature, signature_len);
+
+ if (_config != NULL) {
+ _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
+
+ if (config != NULL) {
+ CC_SHA1_CTX ctx;
+ unsigned char *sha1;
+ unsigned char sha1_buf[CC_SHA1_DIGEST_LENGTH];
+
+ sha1 = (signature_len >= CC_SHA1_DIGEST_LENGTH) ? signature : sha1_buf;
+ CC_SHA1_Init(&ctx);
+ CC_SHA1_Update(&ctx,
+ config,
+ sizeof(_dns_config_buf_t) + ntohl(config->n_attribute));
+ CC_SHA1_Final(sha1, &ctx);
+ if (sha1 != signature) {
+ bcopy(sha1, signature, signature_len);
+ }
+ }
+ }
+
+ return;
+}
+
_Bool
_dns_configuration_store(dns_create_config_t *_config)
// add attribute [header]
- header = (dns_attribute_t *)&resolver->attribute[oldLen];
+ /* ALIGN: _dns_config_buf_t is int aligned */
+ header = (dns_attribute_t *)(void *)&resolver->attribute[oldLen];
header->type = htonl(attribute_type);
header->length = htonl(newLen);
}
+void
+_dns_resolver_add_sortaddr(dns_create_resolver_t *_resolver, dns_sortaddr_t *sortaddr)
+{
+ _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
+
+ resolver->resolver.n_sortaddr = htonl(ntohl(resolver->resolver.n_sortaddr) + 1);
+ _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_SORTADDR, sizeof(dns_sortaddr_t), (void *)sortaddr);
+ return;
+}
+
+
void
_dns_resolver_set_domain(dns_create_resolver_t *_resolver, const char *domain)
{
void
-_dns_resolver_add_sortaddr(dns_create_resolver_t *_resolver, dns_sortaddr_t *sortaddr)
+_dns_resolver_set_reach_flags(dns_create_resolver_t *_resolver, uint32_t reach_flags)
{
_dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
- resolver->resolver.n_sortaddr = htonl(ntohl(resolver->resolver.n_sortaddr) + 1);
- _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_SORTADDR, sizeof(dns_sortaddr_t), (void *)sortaddr);
+ resolver->resolver.reach_flags = htonl(reach_flags);
return;
}
/*
- * Copyright (c) 2004-2006, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2006, 2008, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
_dns_configuration_add_resolver (dns_create_config_t *_config,
dns_create_resolver_t _resolver) /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
+__private_extern__
+void
+_dns_configuration_signature (dns_create_config_t *_config,
+ unsigned char *signature,
+ size_t signature_len) /*__OSX_AVAILABLE_STARTING(__MAC_10_7+,__IPHONE_5_0)*/; // signature_len >= CC_SHA1_DIGEST_LENGTH
+
__private_extern__
_Bool
_dns_configuration_store (dns_create_config_t *_config) /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/;
_dns_resolver_set_port (dns_create_resolver_t *_resolver,
uint16_t port) /*__OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0)*/; // host byte order
+__private_extern__
+void
+_dns_resolver_set_reach_flags (dns_create_resolver_t *_resolver,
+ uint32_t reach_flags) /*__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0)*/;
+
__private_extern__
void
_dns_resolver_set_timeout (dns_create_resolver_t *_resolver,
/*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
switch (sa->sa_family) {
case AF_INET :
- ((struct sockaddr_in *)sa)->sin_port = port;
+ /* ALIGN: cast ok, sockaddr was malloc'd */
+ ((struct sockaddr_in *)(void *)sa)->sin_port = port;
break;
case AF_INET6 :
- ((struct sockaddr_in6 *)sa)->sin6_port = port;
+ /* ALIGN: cast ok, sockaddr was malloc'd */
+ ((struct sockaddr_in6 *)(void *)sa)->sin6_port = port;
break;
}
}
// if not AF_INET
goto done;
} else {
- addr = ((struct sockaddr_in *)sa)->sin_addr;
+ /* ALIGN: cast ok, sockaddr was malloc'd */
+ addr = ((struct sockaddr_in *)(void *)sa)->sin_addr;
free(sa);
sa = NULL;
}
// if mask not AF_INET
goto done;
} else {
- mask = ((struct sockaddr_in *)sa)->sin_addr;
+ /* ALIGN: cast ok, sockaddr was malloc'd */
+ mask = ((struct sockaddr_in *)(void *)sa)->sin_addr;
free(sa);
sa = NULL;
}
/*
- * Copyright (c) 2004-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2008, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "dnsinfo_server.h"
#include "dnsinfo_private.h"
+#include <network_information.h>
-static CFDataRef shared_dns_info = NULL;
+static CFDataRef shared_dns_info = NULL;
+static CFDataRef shared_nwi_state = NULL;
__private_extern__
kern_return_t
*dataLen = 0;
if (shared_dns_info != NULL) {
- if (!_SCSerializeData(shared_dns_info, (void **)dataRef, (CFIndex *)dataLen)) {
+ CFIndex len;
+ Boolean ok;
+
+ ok = _SCSerializeData(shared_dns_info, (void **)dataRef, &len);
+ *dataLen = len;
+ if (!ok) {
return KERN_FAILURE;
}
}
}
-__private_extern__
+static
kern_return_t
-_shared_dns_infoSet(mach_port_t server,
- dnsData_t dataRef,
- mach_msg_type_number_t dataLen,
- audit_token_t audit_token)
+_shared_infoSet_common(mach_port_t server,
+ dnsData_t dataRef,
+ mach_msg_type_number_t dataLen,
+ audit_token_t audit_token,
+ CFDataRef* cache,
+ const char* notify_key)
{
uid_t euid = 0;
- CFDataRef new_dns_info = NULL;
- const char *notify_key;
+ CFDataRef new_info = NULL;
+ CFDataRef n_cache = *cache;
if ((dataRef != NULL) && (dataLen > 0)) {
- if (!_SCUnserializeData(&new_dns_info, (void *)dataRef, dataLen)) {
+ if (!_SCUnserializeData(&new_info, (void *)dataRef, dataLen)) {
goto error;
}
}
goto error;
}
- if ((shared_dns_info != NULL) &&
- (new_dns_info != NULL) &&
- CFEqual(shared_dns_info, new_dns_info)) {
- CFRelease(new_dns_info);
+ if ((n_cache != NULL) &&
+ (new_info != NULL) &&
+ CFEqual(n_cache, new_info)) {
+ CFRelease(new_info);
return KERN_SUCCESS;
}
- if (shared_dns_info != NULL) CFRelease(shared_dns_info);
- shared_dns_info = new_dns_info;
+ if (n_cache != NULL) CFRelease(n_cache);
+ *cache = new_info;
- notify_key = _dns_configuration_notify_key();
if (notify_key != NULL) {
uint32_t status;
error :
- if (new_dns_info != NULL) CFRelease(new_dns_info);
+ if (new_info != NULL) CFRelease(new_info);
return KERN_FAILURE;
}
+
+
+__private_extern__
+kern_return_t
+_shared_dns_infoSet(mach_port_t server,
+ dnsData_t dataRef,
+ mach_msg_type_number_t dataLen,
+ audit_token_t audit_token)
+{
+ const char *notify_key;
+
+ notify_key = _dns_configuration_notify_key();
+ return _shared_infoSet_common(server, dataRef, dataLen,
+ audit_token, &shared_dns_info,
+ notify_key);
+}
+
+
+__private_extern__
+kern_return_t
+_shared_nwi_stateGet(mach_port_t server, dnsDataOut_t *dataRef, mach_msg_type_number_t *dataLen)
+{
+ *dataRef = NULL;
+ *dataLen = 0;
+
+ if (shared_nwi_state != NULL) {
+ CFIndex len;
+ Boolean ok;
+
+ ok = _SCSerializeData(shared_nwi_state, (void **)dataRef, &len);
+ *dataLen = len;
+ if (!ok) {
+ return KERN_FAILURE;
+ }
+ }
+
+ return KERN_SUCCESS;
+
+}
+
+
+__private_extern__
+kern_return_t
+_shared_nwi_stateSet(mach_port_t server,
+ dnsData_t dataRef,
+ mach_msg_type_number_t dataLen,
+ audit_token_t audit_token)
+{
+ const char *notify_key;
+
+ notify_key = nwi_state_get_notify_key();
+
+ return _shared_infoSet_common(server, dataRef, dataLen,
+ audit_token, &shared_nwi_state,
+ notify_key);
+}
/*
- * Copyright (c) 2004, 2005, 2009 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004, 2005, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
mach_msg_type_number_t dataLen,
audit_token_t audit_token);
+__private_extern__
+kern_return_t _shared_nwi_stateGet (mach_port_t server,
+ dnsDataOut_t *dataRef,
+ mach_msg_type_number_t *dataLen);
+
+__private_extern__
+kern_return_t _shared_nwi_stateSet (mach_port_t server,
+ dnsData_t dataRef,
+ mach_msg_type_number_t dataLen,
+ audit_token_t audit_token);
+
__END_DECLS
#endif /* !_S_DNSINFO_SERVER_H */
/*
- * Copyright (c) 2004, 2005, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2004, 2005, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
ServerAuditToken audit_token : audit_token_t);
#else // LIBDNSINFO_A
skip; /* shared_dns_infoSet */
-#endif LIBDNSINFO_A
+#endif // LIBDNSINFO_A
+
+routine shared_nwi_stateGet ( server : mach_port_t;
+ out data : dnsDataOut, dealloc);
+
+#ifndef LIBDNSINFO_A
+routine shared_nwi_stateSet ( server : mach_port_t;
+ data : dnsData;
+ ServerAuditToken audit_token : audit_token_t);
+#else // LIBDNSINFO_A
+ skip; /* shared_nwi_stateSet */
+#endif // LIBDNSINFO_A
+
#!/bin/sh
-# Copyright (c) 2004-2011 Apple Inc.
+# Copyright (c) 2004-2012 Apple Inc.
#
# get-mobility-info
#
cd "${WORKDIR}"
+echo ""
+echo "Please wait, collecting information and statistics"
+echo ""
+
#
# processes
#
ioreg -i -l -w 0 > ioreg 2>&1
ioreg -i -l -p IODeviceTree -w 0 >> ioreg 2>&1
+#
+# Power Management info
+#
+echo "#" > pmset
+echo "# pmset -g" >> pmset
+echo "#" >> pmset
+pmset -g >> pmset 2>&1
+
+echo "#" >> pmset
+echo "# pmset -g ps" >> pmset
+echo "#" >> pmset
+pmset -g ps >> pmset 2>&1
+
+echo "#" >> pmset
+echo "# pmset -g assertions" >> pmset
+echo "#" >> pmset
+pmset -g assertions >> pmset 2>&1
+
+echo "#" >> pmset
+echo "# pmset -g log" >> pmset
+echo "#" >> pmset
+pmset -g log | tail -n 25000 >> pmset 2>&1
+
#
# Host name
#
#
# Proxy configuration
#
-scutil --proxy > proxy-configuration 2>&1
+scutil -d -v --proxy > proxy-configuration 2>&1
+
+#
+# Network information
+#
+scutil --nwi > network-information 2>&1
#
# System / network preferences
/Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist \
/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist \
/Library/Preferences/SystemConfiguration/com.apple.nat.plist \
- /Library/Preferences/SystemConfiguration/com.apple.network.identification.plist \
/Library/Preferences/SystemConfiguration/com.apple.smb.server.plist \
/Library/Preferences/SystemConfiguration/com.apple.wifi.plist \
/Library/Preferences/SystemConfiguration/preferences.plist \
#
if [ -e /etc/bootpd.plist ]; then
cat /etc/bootpd.plist > bootpd.plist 2>&1
- cat /etc/com.apple.named.proxy.conf > com.apple.named.proxy.conf 2>&1
+ cat /etc/com.apple.named.proxy.conf > com.apple.named.proxy.conf 2>/dev/null
elif [ -e /Library/Preferences/SystemConfiguration/bootpd.plist ]; then
cat /Library/Preferences/SystemConfiguration/bootpd.plist > bootpd.plist 2>&1
- cat /Library/Preferences/SystemConfiguration/com.apple.named.proxy.conf > com.apple.named.proxy.conf 2>&1
+ cat /Library/Preferences/SystemConfiguration/com.apple.named.proxy.conf > com.apple.named.proxy.conf 2>/dev/null
fi
#
# configd's cache
#
-${PRIV} scutil -p <<_END_OF_INPUT
-open
-snapshot
-quit
-_END_OF_INPUT
+${PRIV} scutil -p --snapshot
if [ -f /var/tmp/configd-store.plist ]; then
cat /var/tmp/configd-store.plist > configd-store.plist 2>&1
fi
if [ -f /var/tmp/configd-state ]; then
cat /var/tmp/configd-state > configd-state 2>&1
fi
-
-#
-# check configd's executable
-#
-if [ -x /usr/bin/codesign ]; then
- echo "#" >> configd-state
- echo "# codesign --verbose --display --entitlements - /usr/libexec/configd" >> configd-state
- echo "#" >> configd-state
- /usr/bin/codesign --verbose --display --entitlements - /usr/libexec/configd >> configd-state 2>&1
-
- echo "#" >> configd-state
- echo "# codesign --verbose --verify /usr/libexec/configd" >> configd-state
- echo "#" >> configd-state
- /usr/bin/codesign --verbose --verify /usr/libexec/configd >> configd-state 2>&1
+if [ -f /var/tmp/configd-reachability ]; then
+ cat /var/tmp/configd-reachability > configd-reachability 2>&1
fi
#
# network reachability
#
-scutil -d -v -r www.apple.com > reachability-info 2>&1
+scutil -d -v -r www.apple.com "" no-server > reachability-info 2>&1
if [ -x /usr/bin/dig -a -f /etc/resolv.conf ]; then
/usr/bin/dig -t any -c any www.apple.com > dig-results 2>/dev/null
fi
mount > mounted-filesystems 2>&1
#
-# mDNSResponder info
+# mDNSResponder, networkd info
#
if [ -x /usr/bin/killall ]; then
${PRIV} killall -INFO mDNSResponder
+ ${PRIV} killall -INFO networkd
# and wait a short amount of time for mDNSResponder
# to actually log the requested information
echo "#" >> network-statistics
netstat -i -n -d >> network-statistics 2>&1
+echo "#" >> network-statistics
+echo "# netstat -g -n -s" >> network-statistics
+echo "#" >> network-statistics
+netstat -g -n -s >> network-statistics 2>&1
+
if [ -x /usr/sbin/ndp ]; then
echo "#" >> network-statistics
echo "# ndp -n -a" >> network-statistics
echo "# ndp -n -r" >> network-statistics
echo "#" >> network-statistics
ndp -n -r >> network-statistics 2>&1
+
+ for if in `ifconfig -l`
+ do
+ echo "#" >> network-statistics
+ echo "# ndp -i ${if}" >> network-statistics
+ echo "#" >> network-statistics
+ ndp -i ${if} >> network-statistics 2>&1
+ done
fi
if [ -x /sbin/ipfw ]; then
${PRIV} ipfw -at show >> network-statistics 2>&1
fi
+if [ -x /sbin/ip6fw ]; then
+ echo "#" >> network-statistics
+ echo "# ip6fw -at show" >> network-statistics
+ echo "#" >> network-statistics
+ ${PRIV} ip6fw -at show >> network-statistics 2>&1
+fi
+
if [ -x /sbin/pfctl ]; then
echo "#" > pf
echo "# pfctl -s all" >> pf
echo "# pfctl -s References" >> pf
echo "#" >> pf
${PRIV} pfctl -s References >> pf 2>&1
- for ANCHOR in `pfctl -s Anchors 2>/dev/null`
+ for ANCHOR in `${PRIV} pfctl -s Anchors -v 2>/dev/null`
do
echo "==============================" >> pf
echo "#" >> pf
echo "# setkey -D" >> ipsec
echo "#" >> ipsec
${PRIV} setkey -D \
-| perl -nle '
+| perl -M'Digest::MD5 qw(md5_hex)' -l -n -e '
if (/^(\s+[AE]:\s+\S+\s+)"?(.*)"?\s*$/) {
- chop($sha1=`echo "$2" | openssl sha1`);
- printf "%s[SHA-1:%s]\n", $1, $sha1;
+ printf "%s[MD5:%s]%s\n", $1, md5_hex($2 . "\n"), $3;
} else {
printf "%s\n", $_;
}
echo "# ${CF}" >> ipsec
echo "#" >> ipsec
${PRIV} cat ${CF} \
- | perl -nle '
+ | perl -M'Digest::MD5 qw(md5_hex)' -l -n -e '
if (/^(\s+shared_secret\s+use\s+)"?([^\s;"]+)"?(.*)/) {
- chop($sha1=`echo "$2" | openssl sha1`);
- printf "%s[SHA-1:%s]%s\n", $1, $sha1, $3;
+ printf "%s[MD5:%s]%s\n", $1, md5_hex($2 . "\n"), $3;
} else {
printf "%s\n", $_;
}
BTMM_DIG()
{
rm -f .digsync
-
+
nc -6 -l "${BTMMPORT}" < .btmmfifo \
| openssl s_client -connect "${HOSTPORT}" -quiet > .btmmfifo 2>.digsync &
-
+
N_RETRY=0
while [ $N_RETRY -lt 50 -a ! -s .digsync ]
do
N_RETRY=$((N_RETRY + 1))
sleep 0.1
done
-
+
dig @::1 -p "${BTMMPORT}" \
-y "${TSIG}" \
+short \
+tcp \
"${1}" "${2}" 2>/dev/null
-
+
wait %1
}
fi
}
-# get hostname, port, TSIG name and TSIG data from keychain
+# get hostname, port, TSIG name and TSIG data from keychain
# params: UNIQUEID
BTMM_GETINFO()
{
${PRIV} security find-generic-password \
-s "${1}" \
-g /Library/Keychains/System.keychain \
- 2>&1 \
+ 2>&1 > /dev/null \
| sed -n 's/^password: \"\(.*\)\"$/\1/p'
}
if [ $? -eq 0 ]; then
return
fi
-
+
SECRET=`BTMM_GETINFO "btmmrelay:${1}"`
-
+
if [ -z "${SECRET}" ]; then
echo " No Relay keychain item." >> btmm
return
fi
-
+
if [ `echo "${SECRET}" | wc -l` -ne 1 ]; then
echo " More than one Relay keychain item." >> btmm
return
fi
-
+
URLISH=`BTMM_URLISH "${DOMAIN}"`
ACCOUNT=`cat .btmminfo | sed -n 's/.*\"acct\"<blob>=\"\(.*\)\"/\1/p'`
- KEYHASH="[SHA-1:`echo ${SECRET} | openssl sha1`]"
+ KEYHASH="`perl -M'Digest::SHA1 qw(sha1_hex)' -l -e '
+ printf "[SHA1:%s]\n", sha1_hex($ARGV[0] . "\n");
+ ' ${SECRET}`"
echo " RHP: ${URLISH}" >> btmm
echo " RAC: ${ACCOUNT}" >> btmm
echo " RKY: ${KEYHASH}" >> btmm
BTMM_REPORTZONE()
{
DOMAIN="${1}"
-
+
echo >> btmm
echo "${DOMAIN}" >> btmm
-
+
DNSID=`BTMM_UNIQUEIDFROMZONE "${DOMAIN}"`
SECRET=`BTMM_GETINFO "${DNSID}"`
echo " No DNS keychain item." >> btmm
return
fi
-
+
if [ `echo "${SECRET}" | wc -l` -ne 1 ]; then
echo " More than one DNS keychain item." >> btmm
return
fi
-
+
URLISH=`BTMM_URLISH "${DOMAIN}"`
HOSTPORT=`echo "${URLISH}" | cut -d@ -f2`
ACCOUNT=`cat .btmminfo | sed -n 's/.*\"acct\"<blob>=\"\(.*\)\"/\1/p'`
TSIG="${ACCOUNT}:${SECRET}"
- KEYHASH="[SHA-1:`echo ${SECRET} | openssl sha1`]"
+ KEYHASH="`perl -M'Digest::SHA1 qw(sha1_hex)' -l -e '
+ printf "[SHA1:%s]\n", sha1_hex($ARGV[0] . "\n");
+ ' ${SECRET}`"
echo "" >> btmm
echo " DHP: ${URLISH}" >> btmm
echo " DAC: ${ACCOUNT}" >> btmm
echo " DKY: ${KEYHASH}" >> btmm
-
+
BTMM_RELAYINFO "${DOMAIN}"
+ REACHHOST=`echo "${HOSTPORT}" | cut -d: -f1`
+ STATUSES=`scutil -r "${REACHHOST}"`
+ for REACHSTATUS in `echo ${STATUSES} | tr -d ' ' | tr ',' ' '`; do
+ if [ "$REACHSTATUS" == "NotReachable" ] \
+ || [ "$REACHSTATUS" == "ConnectionRequired" ]; then
+ echo " Skipping DNS queries, no connectivity" >> btmm
+ return
+ fi
+ done
+
for TYPE in \
_afpovertcp._tcp \
_airport._tcp \
pppd \
racoon \
socketfilterfw \
+ InternetSharing \
SCHelper \
SCMonitor \
do
/bin/ls -1 /Library/Logs/DiagnosticReports/${daemon}_*.crash \
/Library/Logs/CrashReporter/${daemon}_*.crash \
+ /Library/Logs/CrashReporter/${daemon}_*.plist \
2>/dev/null \
| while read log
do
done
done
+#
+# system profiler
+#
+if [ -x /usr/sbin/system_profiler ]; then
+ system_profiler -xml SPEthernetDataType \
+ SPFibreChannelDataType \
+ SPFireWireDataType \
+ SPFirewallDataType \
+ SPModemDataType \
+ SPNetworkDataType \
+ SPThunderboltDataType \
+ SPWWANDataType \
+ SPAirPortDataType > system_profiler.spx 2>&1
+fi
+
#
# system usage statistics
#
echo "#" >> system-statistics
echo "# top -l5 -s2" >> system-statistics
echo "#" >> system-statistics
-echo ""
-echo "Please wait, collecting statistics"
-echo ""
top -s 2 -l 5 >> system-statistics 2>&1
#
--- /dev/null
+/*
+ * Copyright (c) 2011 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,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * 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 <pthread.h>
+#include <notify.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include "network_information.h"
+#include "network_information_priv.h"
+
+static nwi_state_t G_nwi_state = NULL;
+static pthread_mutex_t nwi_store_lock = PTHREAD_MUTEX_INITIALIZER;
+static boolean_t nwi_store_token_valid = FALSE;
+
+static pthread_once_t initialized = PTHREAD_ONCE_INIT;
+static int nwi_store_token;
+
+
+/* Private */
+static
+void
+_nwi_state_initialize(void)
+{
+ const char *nwi_key = nwi_state_get_notify_key();
+ uint32_t status = notify_register_check(nwi_key,
+ &nwi_store_token);
+
+ if (status != NOTIFY_STATUS_OK) {
+ fprintf(stderr, "nwi_state: registration failed (%u)\n", status);
+ }
+ else {
+ nwi_store_token_valid = TRUE;
+ }
+}
+
+static
+void
+nwi_set_alias(nwi_state* state, nwi_ifstate* ifstate)
+{
+ nwi_ifstate* ifstate_alias;
+ int af = ifstate->af;
+ int af_alias;
+
+ af_alias = (af == AF_INET)?AF_INET6:AF_INET;
+
+ ifstate_alias =
+ nwi_state_get_ifstate_with_name(state, af_alias,
+ ifstate->ifname);
+
+ if (ifstate_alias != NULL) {
+ ifstate_alias->af_alias = ifstate;
+ }
+ ifstate->af_alias = ifstate_alias;
+ return;
+}
+
+static
+void
+_nwi_state_reset_alias(nwi_state_t state) {
+ int i;
+
+ for (i = 0; i < state->ipv4_count; i++) {
+ state->nwi_ifstates[i].af_alias = NULL;
+ }
+
+ for (i = state->ipv6_start;
+ i < state->ipv6_start + state->ipv6_count; i++) {
+ nwi_set_alias(state, &state->nwi_ifstates[i]);
+ }
+}
+
+/* Public APIs' */
+/*
+ * Function: nwi_state_get_notify_key
+ * Purpose:
+ * Returns the BSD notify key to use to monitor when the state changes.
+ *
+ * Note:
+ * The nwi_state_copy API uses this notify key to monitor when the state
+ * changes, so each invocation of nwi_state_copy returns the current
+ * information.
+ */
+const char *
+nwi_state_get_notify_key()
+{
+ return "com.apple.system.SystemConfiguration.nwi";
+}
+
+#define ATOMIC_INC(p) __sync_fetch_and_add((p), 1) // return (n++);
+#define ATOMIC_DEC(p) __sync_sub_and_fetch((p), 1) // return (--n);
+
+static void
+nwi_state_retain(nwi_state_t state)
+{
+ ATOMIC_INC(&state->ref);
+ return;
+}
+
+/*
+ * Function: nwi_state_release
+ * Purpose:
+ * Release the memory associated with the network state.
+ */
+void
+nwi_state_release(nwi_state_t state)
+{
+ if (ATOMIC_DEC(&state->ref) == 0) {
+ free(state);
+ }
+ return;
+}
+
+/*
+ * Function: nwi_state_copy
+ * Purpose:
+ * Returns the current network state information.
+ * Release after use by calling nwi_state_release().
+ */
+nwi_state_t
+nwi_state_copy(void)
+{
+ nwi_state_t nwi_state = NULL;
+ nwi_state_t old_state = NULL;
+
+ pthread_once(&initialized, _nwi_state_initialize);
+ pthread_mutex_lock(&nwi_store_lock);
+
+ if (G_nwi_state != NULL) {
+ int check = 0;
+ uint32_t status;
+
+ if (nwi_store_token_valid == FALSE) {
+ /* have to throw cached copy away every time */
+ check = 1;
+ }
+ else {
+ status = notify_check(nwi_store_token, &check);
+ if (status != NOTIFY_STATUS_OK) {
+ fprintf(stderr, "nwi notify_check: failed with %u\n",
+ status);
+ /* assume that it changed, throw cached copy away */
+ check = 1;
+ }
+ }
+ if (check != 0) {
+ /* new need snapshot */
+ old_state = G_nwi_state;
+ G_nwi_state = NULL;
+ }
+ }
+ /* Let's populate the cache if it's empty */
+ if (G_nwi_state == NULL) {
+ G_nwi_state = _nwi_state_copy();
+ if (G_nwi_state != NULL) {
+ /* one reference for G_nwi_state */
+ nwi_state_retain(G_nwi_state);
+ _nwi_state_reset_alias(G_nwi_state);
+ }
+ }
+ if (G_nwi_state != NULL) {
+ /* another reference for this caller */
+ nwi_state_retain(G_nwi_state);
+ }
+ nwi_state = G_nwi_state;
+ pthread_mutex_unlock(&nwi_store_lock);
+
+ if (old_state != NULL) {
+ /* get rid of G_nwi_state reference */
+ nwi_state_release(old_state);
+ }
+ return nwi_state;
+}
+
+/*
+ * Function: _nwi_state_ack
+ * Purpose:
+ * Acknowledge receipt and any changes associated with the [new or
+ * updated] network state.
+ */
+void
+_nwi_state_ack(nwi_state_t state, const char *bundle_id)
+{
+ return;
+}
+
+/*
+ * Function: nwi_state_get_generation
+ * Purpose:
+ * Returns the generation (mach_time) of the nwi_state data.
+ * Every time the data is updated due to changes
+ * in the network, this value will change.
+ */
+uint64_t
+nwi_state_get_generation(nwi_state_t state)
+{
+ return (state->generation_count);
+}
+
+/*
+ * Function: nwi_ifstate_get_ifname
+ * Purpose:
+ * Return the interface name of the specified ifstate.
+ */
+const char *
+nwi_ifstate_get_ifname(nwi_ifstate_t ifstate)
+{
+ return (ifstate != NULL?ifstate->ifname:NULL);
+
+}
+
+static uint64_t
+flags_from_af(int af)
+{
+ return ((af == AF_INET)
+ ? NWI_IFSTATE_FLAGS_HAS_IPV4
+ : NWI_IFSTATE_FLAGS_HAS_IPV6);
+}
+/*
+ * Function: nwi_ifstate_get_flags
+ * Purpose:
+ * Return the flags for the given ifstate (see above for bit definitions).
+ */
+nwi_ifstate_flags
+nwi_ifstate_get_flags(nwi_ifstate_t ifstate)
+{
+ nwi_ifstate_t alias = ifstate->af_alias;
+ nwi_ifstate_flags flags = 0ULL;
+
+ flags |= flags_from_af(ifstate->af);
+ if ((ifstate->flags & NWI_IFSTATE_FLAGS_HAS_DNS) != 0) {
+ flags |= NWI_IFSTATE_FLAGS_HAS_DNS;
+
+ }
+ if (alias != NULL) {
+ flags |= flags_from_af(alias->af);
+ if ((alias->flags & NWI_IFSTATE_FLAGS_HAS_DNS) != 0) {
+ flags |= NWI_IFSTATE_FLAGS_HAS_DNS;
+ }
+ }
+ return flags;
+}
+
+/*
+ * Function: nwi_state_get_first_ifstate
+ * Purpose:
+ * Returns the first and highest priority interface that has connectivity
+ * for the specified address family 'af'. 'af' is either AF_INET or AF_INET6.
+ * The connectivity provided is for general networking. To get information
+ * about an interface that isn't available for general networking, use
+ * nwi_state_get_ifstate().
+ *
+ * Use nwi_ifstate_get_next() to get the next, lower priority interface
+ * in the list.
+ *
+ * Returns NULL if no connectivity for the specified address family is
+ * available.
+ */
+nwi_ifstate_t
+nwi_state_get_first_ifstate(nwi_state_t state, int af)
+{
+ nwi_ifstate_t ifstate;
+
+ if (state == NULL) {
+ return NULL;
+ }
+
+ ifstate =
+ nwi_state_get_ifstate_with_index(state, af, 0);
+
+ if ((ifstate->flags & NWI_IFSTATE_FLAGS_NOT_IN_LIST)
+ != 0) {
+ ifstate = NULL;
+ }
+
+ return ifstate;
+
+}
+
+/*
+ * Function: nwi_state_get_ifstate
+ * Purpose:
+ * Return information for the specified interface 'ifname'.
+ *
+ * This API directly returns the ifstate for the specified interface.
+ * This is the only way to access information about an interface that isn't
+ * available for general networking.
+ *
+ * Returns NULL if no information is available for that interface.
+ */
+nwi_ifstate_t
+nwi_state_get_ifstate(nwi_state_t state, const char * ifname)
+{
+ nwi_ifstate_t ifstate = nwi_state_get_ifstate_with_name(state, AF_INET, ifname);
+ if (ifstate == NULL) {
+ ifstate = nwi_state_get_ifstate_with_name(state, AF_INET6, ifname);
+ }
+ return ifstate;
+
+}
+
+/*
+ * Function: nwi_ifstate_get_next
+ * Purpose:
+ * Returns the next, lower priority nwi_ifstate_t after the specified
+ * 'ifstate' for the protocol family 'af'.
+ *
+ * Returns NULL when the end of the list is reached.
+ */
+nwi_ifstate_t
+nwi_ifstate_get_next(nwi_ifstate_t ifstate, int af)
+{
+ nwi_ifstate_t alias, next;
+
+ alias =
+ (af == ifstate->af)?ifstate:ifstate->af_alias;
+
+ if (alias == NULL) {
+ return NULL;
+ }
+
+ /* We don't return interfaces marked rank never */
+ if ((alias->flags & NWI_IFSTATE_FLAGS_NOT_IN_LIST) != 0) {
+ return NULL;
+ }
+
+ next = ++alias;
+
+ if ((next->flags & NWI_IFSTATE_FLAGS_NOT_IN_LIST) == 0) {
+ return next;
+ }
+ return NULL;
+}
+
+/*
+ * Function: nwi_ifstate_compare_rank
+ * Purpose:
+ * Compare the relative rank of two nwi_ifstate_t objects.
+ *
+ * The "rank" indicates the importance of the underlying interface.
+ *
+ * Returns:
+ * 0 if ifstate1 and ifstate2 are ranked equally
+ * -1 if ifstate1 is ranked ahead of ifstate2
+ * 1 if ifstate2 is ranked ahead of ifstate1
+ */
+int
+nwi_ifstate_compare_rank(nwi_ifstate_t ifstate1, nwi_ifstate_t ifstate2)
+{
+ return RankCompare(ifstate1->rank, ifstate2->rank);
+}
--- /dev/null
+/*
+ * Copyright (c) 2011 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,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * 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@
+ */
+
+
+#ifndef _NETWORK_INFORMATION_H_
+#define _NETWORK_INFORMATION_H_
+
+#include <stdint.h>
+
+typedef struct _nwi_state * nwi_state_t;
+typedef struct _nwi_ifstate * nwi_ifstate_t;
+
+/*
+ * Function: nwi_state_copy
+ * Purpose:
+ * Returns the current network state information.
+ * Release after use by calling nwi_state_release().
+ */
+nwi_state_t
+nwi_state_copy(void);
+
+/*
+ * Function: nwi_state_release
+ * Purpose:
+ * Release the memory associated with the network state.
+ */
+void
+nwi_state_release(nwi_state_t state);
+
+/*
+ * Function: nwi_state_get_notify_key
+ * Purpose:
+ * Returns the BSD notify key to use to monitor when the state changes.
+ *
+ * Note:
+ * The nwi_state_copy API uses this notify key to monitor when the state
+ * changes, so each invocation of nwi_state_copy returns the current
+ * information.
+ */
+const char *
+nwi_state_get_notify_key(void);
+
+/*
+ * Function: nwi_state_get_first_ifstate
+ * Purpose:
+ * Returns the first and highest priority interface that has connectivity
+ * for the specified address family 'af'. 'af' is either AF_INET or AF_INET6.
+ * The connectivity provided is for general networking. To get information
+ * about an interface that isn't available for general networking, use
+ * nwi_state_get_ifstate().
+ *
+ * Use nwi_ifstate_get_next() to get the next, lower priority interface
+ * in the list.
+ *
+ * Returns NULL if no connectivity for the specified address family is
+ * available.
+ */
+nwi_ifstate_t
+nwi_state_get_first_ifstate(nwi_state_t state, int af);
+
+/*
+ * Function: nwi_state_get_generation
+ * Purpose:
+ * Returns the generation (mach_time) of the nwi_state data.
+ * Every time the data is updated due to changes
+ * in the network, this value will change.
+ */
+uint64_t
+nwi_state_get_generation(nwi_state_t state);
+
+/*
+ * Function: nwi_state_get_ifstate
+ * Purpose:
+ * Return information for the specified interface 'ifname'.
+ *
+ * This API directly returns the ifstate for the specified interface.
+ * This is the only way to access information about an interface that isn't
+ * available for general networking.
+ *
+ * Returns NULL if no information is available for that interface.
+ */
+nwi_ifstate_t
+nwi_state_get_ifstate(nwi_state_t state, const char * ifname);
+
+/*
+ * Function: nwi_ifstate_get_ifname
+ * Purpose:
+ * Return the interface name of the specified ifstate.
+ */
+const char *
+nwi_ifstate_get_ifname(nwi_ifstate_t ifstate);
+
+/*
+ * Type: nwi_ifstate_flags
+ * Purpose:
+ * Provide information about the interface, including its IPv4 and IPv6
+ * connectivity, and whether DNS is configured or not.
+ */
+#define NWI_IFSTATE_FLAGS_HAS_IPV4 0x1 /* has IPv4 connectivity */
+#define NWI_IFSTATE_FLAGS_HAS_IPV6 0x2 /* has IPv6 connectivity */
+#define NWI_IFSTATE_FLAGS_HAS_DNS 0x4 /* has DNS configured */
+
+typedef uint64_t nwi_ifstate_flags;
+/*
+ * Function: nwi_ifstate_get_flags
+ * Purpose:
+ * Return the flags for the given ifstate (see above for bit definitions).
+ */
+nwi_ifstate_flags
+nwi_ifstate_get_flags(nwi_ifstate_t ifstate);
+
+/*
+ * Function: nwi_ifstate_get_next
+ * Purpose:
+ * Returns the next, lower priority nwi_ifstate_t after the specified
+ * 'ifstate' for the protocol family 'af'.
+ *
+ * Returns NULL when the end of the list is reached.
+ */
+nwi_ifstate_t
+nwi_ifstate_get_next(nwi_ifstate_t ifstate, int af);
+
+/*
+ * Function: nwi_ifstate_compare_rank
+ * Purpose:
+ * Compare the relative rank of two nwi_ifstate_t objects.
+ *
+ * The "rank" indicates the importance of the underlying interface.
+ *
+ * Returns:
+ * 0 if ifstate1 and ifstate2 are ranked equally
+ * -1 if ifstate1 is ranked ahead of ifstate2
+ * 1 if ifstate2 is ranked ahead of ifstate1
+ */
+int
+nwi_ifstate_compare_rank(nwi_ifstate_t ifstate1, nwi_ifstate_t ifstate2);
+
+/*
+ * Function: _nwi_state_ack
+ * Purpose:
+ * Acknowledge receipt and any changes associated with the [new or
+ * updated] network state.
+ */
+void
+_nwi_state_ack(nwi_state_t state, const char *bundle_id)
+ __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2011 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,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * 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 <arpa/inet.h>
+#include <notify.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <stdbool.h>
+#include "network_information_priv.h"
+#include <limits.h>
+
+sa_family_t nwi_af_list[] = {AF_INET, AF_INET6};
+
+static __inline__ unsigned int
+nwi_state_compute_size(unsigned int n)
+{
+ return (offsetof(nwi_state, nwi_ifstates[n]));
+
+}
+__private_extern__
+nwi_state_t
+nwi_state_copy_priv(nwi_state_t src)
+{
+ nwi_state_t dest = NULL;
+
+ if (src == NULL) {
+ return dest;
+ }
+
+ dest = malloc(src->size);
+
+ if (dest != NULL) {
+ bcopy(src, dest, src->size);
+
+ dest->ref = 1;
+ }
+ return dest;
+}
+
+__private_extern__
+nwi_state_t
+nwi_state_new(nwi_state_t old_state, int elems)
+{
+ nwi_state_t state = NULL;
+ int new_size;
+
+ if (old_state == NULL && elems == 0) {
+ return NULL;
+ }
+
+ /* Need to insert a last node for each of the v4/v6 list */
+ new_size = (elems != 0)?
+ (sizeof(nwi_state) + nwi_state_compute_size((elems+1) * 2)):0;
+
+ /* Should we reallocate? */
+ if (old_state != NULL) {
+ if (old_state->size >= new_size) {
+ return (old_state);
+ }
+ }
+
+ state = malloc(new_size);
+ if (state == NULL) {
+ return NULL;
+ }
+
+ state->size = new_size;
+
+ /*
+ * v4 list is stored 0 to elems,
+ * v6 list is stored elems + 1 to 2 * elems + 2
+ */
+ state->ipv6_start = elems + 1;
+
+ if (old_state != NULL) {
+ state->ipv6_count = old_state->ipv6_count;
+ if (state->ipv6_count > 0) {
+ bcopy((void*) &old_state->nwi_ifstates[old_state->ipv6_start],
+ (void*) &state->nwi_ifstates[state->ipv6_start],
+ old_state->ipv6_count * sizeof(nwi_ifstate));
+ }
+
+ state->ipv4_count = old_state->ipv4_count;
+
+ if (state->ipv4_count > 0) {
+ bcopy((void*) old_state->nwi_ifstates,
+ (void*) state->nwi_ifstates,
+ old_state->ipv4_count * sizeof(nwi_ifstate));
+ }
+
+ free(old_state);
+ } else {
+ state->ipv4_count = 0;
+ state->ipv6_count = 0;
+ }
+ nwi_state_set_last(state, AF_INET);
+ nwi_state_set_last(state, AF_INET6);
+
+ state->ref = 1;
+ return state;
+}
+
+static inline
+nwi_ifstate_t nwi_ifstate_get_last(nwi_state_t state, int af, uint32_t** last)
+{
+ uint32_t* count;
+ int idx;
+
+ count = (af == AF_INET)
+ ?&state->ipv4_count:&state->ipv6_count;
+
+ idx = (af == AF_INET)
+ ?state->ipv4_count:(state->ipv6_start + state->ipv6_count);
+
+ *last = count;
+
+ return &state->nwi_ifstates[idx];
+
+}
+
+__private_extern__
+void
+nwi_insert_ifstate(nwi_state_t state,
+ const char* ifname, int af,
+ uint64_t flags, Rank rank,
+ void* ifa)
+{
+ nwi_ifstate_t ifstate;
+
+ /* Will only insert unique elements in the list */
+ ifstate = nwi_state_get_ifstate_with_name(state, af, ifname);
+
+ /* Already present, just ignore it */
+ if (ifstate != NULL) {
+ if (ifstate->rank < rank) {
+ return;
+ }
+ }
+
+ if (ifstate == NULL) {
+ uint32_t *last;
+
+ /* We need to append it as the last element */
+ ifstate = nwi_ifstate_get_last(state, af, &last);
+ strcpy(ifstate->ifname, ifname);
+ ifstate->af_alias = NULL;
+ ifstate->af = af;
+ ifstate->diff_ch = NULL;
+ (*last)++;
+ }
+
+ /* We need to update the address/rank/flag fields for the existing/new
+ * element */
+ if (ifa != NULL) {
+ switch (af) {
+ case AF_INET:
+ ifstate->iaddr = *((struct in_addr *) ifa);
+ break;
+ case AF_INET6:
+ ifstate->iaddr6 = *((struct in6_addr *) ifa);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ ifstate->rank = rank;
+ ifstate->flags = flags;
+
+ return;
+}
+
+__private_extern__
+void
+nwi_state_clear(nwi_state_t state, int af)
+{
+ uint32_t* count;
+
+ count = (af == AF_INET)
+ ?&state->ipv4_count:&state->ipv6_count;
+
+ *count = 0;
+ nwi_state_set_last(state, af);
+ return;
+
+}
+
+__private_extern__
+void
+nwi_state_set_last(nwi_state_t state, int af)
+{
+ int last_elem_idx;
+
+ if (state == NULL) {
+ return;
+ }
+
+ /* The last element is an element with the flags set as
+ * NWI_IFSTATE_FLAGS_NOT_IN_LIST */
+ last_elem_idx = (af == AF_INET)
+ ?state->ipv4_count
+ :(state->ipv6_start + state->ipv6_count);
+
+ state->nwi_ifstates[last_elem_idx].ifname[0] = '\0';
+ state->nwi_ifstates[last_elem_idx].flags
+ |= NWI_IFSTATE_FLAGS_NOT_IN_LIST;
+}
+
+__private_extern__
+void
+_nwi_state_dump(int level, nwi_state_t state)
+{
+ const char * addr_str;
+ void * address;
+ int i;
+ char ntopbuf[INET6_ADDRSTRLEN];
+ nwi_ifstate_t scan;
+
+
+ if (state == NULL) {
+ syslog(level, "<empty nwi_state>");
+ return;
+ }
+ syslog(level, "nwi_state = { gen = %llu size = %u #ipv4 = %u #ipv6 = %u }",
+ state->generation_count,
+ state->size,
+ state->ipv4_count,
+ state->ipv6_count);
+
+ if (state->ipv4_count) {
+ syslog(level, "IPv4:");
+ for (i = 0, scan = state->nwi_ifstates;
+ i < state->ipv4_count; i++, scan++) {
+ bool has_dns = (scan->flags & NWI_IFSTATE_FLAGS_HAS_DNS) != 0;
+ bool never = (scan->flags & NWI_IFSTATE_FLAGS_NOT_IN_LIST) != 0;
+
+ address = nwi_ifstate_get_address(scan);
+ addr_str = inet_ntop(scan->af, address, ntopbuf, sizeof(ntopbuf));
+
+ syslog(level, " [%d]: %s%s%s%s rank %u iaddr: %s " ,
+ i, scan->ifname, scan->diff_ch != NULL?scan->diff_ch:"",
+ has_dns ? " dns" : "",
+ never ? " never" : "",
+ scan->rank,
+ addr_str);
+ }
+ }
+ if (state->ipv6_count) {
+ syslog(level, "IPv6:");
+ for (i = 0, scan = state->nwi_ifstates + state->ipv6_start;
+ i < state->ipv6_count; i++, scan++) {
+ bool has_dns = (scan->flags & NWI_IFSTATE_FLAGS_HAS_DNS) != 0;
+ bool never = (scan->flags & NWI_IFSTATE_FLAGS_NOT_IN_LIST) != 0;
+
+ address = nwi_ifstate_get_address(scan);
+ addr_str = inet_ntop(scan->af, address, ntopbuf, sizeof(ntopbuf));
+ syslog(level, " [%d]: %s%s%s%s rank %u iaddr6: %s ",
+ i, scan->ifname, scan->diff_ch != NULL?scan->diff_ch:"",
+ has_dns ? " dns" : "",
+ never ? " never" : "",
+ scan->rank,
+ addr_str);
+ }
+ }
+ return;
+}
+
+
+#define unchanged ""
+#define added "+"
+#define deleted "-"
+#define changed "!"
+
+__private_extern__
+void *
+nwi_ifstate_get_address(nwi_ifstate_t ifstate)
+{
+ return (void *)&ifstate->iaddr;
+}
+
+__private_extern__
+const char *
+nwi_ifstate_get_diff_str(nwi_ifstate_t ifstate)
+{
+ return ifstate->diff_ch;
+}
+
+static
+inline
+boolean_t
+nwi_ifstate_has_changed(nwi_ifstate_t ifstate1, nwi_ifstate_t ifstate2)
+{
+ if (ifstate1->rank != ifstate2->rank) {
+ return TRUE;
+ }
+
+ if (ifstate1->flags != ifstate2->flags) {
+ return TRUE;
+ }
+
+ if (ifstate1->af == AF_INET) {
+ if (memcmp(&ifstate1->iaddr, &ifstate2->iaddr, sizeof(struct in_addr)) != 0) {
+ return TRUE;
+ }
+ } else {
+ if (memcmp(&ifstate1->iaddr6, &ifstate2->iaddr6, sizeof(struct in6_addr)) != 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static
+inline
+nwi_ifstate_t
+nwi_ifstate_append(nwi_state_t state, nwi_ifstate_t scan)
+{
+ nwi_ifstate_t new_ifstate = NULL;
+ uint32_t *last;
+
+ new_ifstate = nwi_ifstate_get_last(state, scan->af, &last);
+ memcpy(new_ifstate, scan, sizeof(*scan));
+ (*last)++;
+ return new_ifstate;
+}
+
+static
+inline
+void
+nwi_ifstate_set_diff_str(nwi_ifstate_t ifstate, const char * ch)
+{
+ ifstate->diff_ch = ch;
+}
+
+static
+void
+nwi_state_merge_added(nwi_state_t state, nwi_state_t old_state,
+ nwi_state_t new_state)
+{
+ int idx;
+ nwi_ifstate_t scan;
+
+ /* Iterate through v4 and v6 list and annotate the diff flags */
+ for (idx = 0; idx < sizeof(nwi_af_list)/sizeof(nwi_af_list[0]); idx++) {
+ scan = nwi_state_get_first_ifstate(new_state, nwi_af_list[idx]);
+
+ while (scan != NULL) {
+ nwi_ifstate_t existing_ifstate, new_ifstate;
+ const char* ifname;
+
+ ifname = nwi_ifstate_get_ifname(scan);
+
+ existing_ifstate = nwi_state_get_ifstate_with_name(old_state, scan->af, ifname);
+
+ /* Add the element that is not in the store */
+ new_ifstate = nwi_ifstate_append(state, scan);
+
+ /* These are potentially "added" elements unless they are
+ * in the old list */
+ nwi_ifstate_set_diff_str(new_ifstate, added);
+
+ if (existing_ifstate != NULL) {
+ if (nwi_ifstate_has_changed(existing_ifstate, new_ifstate) == TRUE) {
+ nwi_ifstate_set_diff_str(new_ifstate, changed);
+ } else {
+ nwi_ifstate_set_diff_str(new_ifstate, unchanged);
+ }
+ }
+ scan = nwi_ifstate_get_next(scan, scan->af);
+ }
+ nwi_state_set_last(state, nwi_af_list[idx]);
+ }
+
+ return;
+}
+
+static
+void
+nwi_state_merge_removed(nwi_state_t state, nwi_state_t old_state)
+{
+ int idx;
+ nwi_ifstate_t scan;
+
+ /* Iterate through v4 and v6 list and annotate the diff flags */
+ for (idx = 0; idx < sizeof(nwi_af_list)/sizeof(nwi_af_list[0]); idx++) {
+ scan = nwi_state_get_first_ifstate(old_state, nwi_af_list[idx]);
+
+ while (scan != NULL) {
+ nwi_ifstate_t existing_ifstate;
+ const char* ifname;
+
+ ifname = nwi_ifstate_get_ifname(scan);
+
+ existing_ifstate = nwi_state_get_ifstate_with_name(state, scan->af, ifname);
+
+ /* Any elements that has not been added means that they are removed */
+ if (existing_ifstate == NULL) {
+ nwi_ifstate_t new_ifstate = nwi_ifstate_append(state, scan);
+ nwi_ifstate_set_diff_str(new_ifstate, deleted);
+ }
+ scan = nwi_ifstate_get_next(scan, scan->af);
+ }
+ nwi_state_set_last(state, nwi_af_list[idx]);
+ }
+
+}
+
+
+__private_extern__
+nwi_state_t
+nwi_state_diff(nwi_state_t old_state, nwi_state_t new_state)
+{
+ nwi_state_t diff;
+ int total_count = 0;
+
+ if (old_state != NULL) {
+ total_count = old_state->ipv4_count + old_state->ipv6_count;
+ }
+
+ if (new_state != NULL) {
+ total_count += new_state->ipv4_count + new_state->ipv6_count;
+ }
+
+ if (total_count == 0) {
+ return NULL;
+ }
+
+ diff = nwi_state_new(NULL, total_count);
+
+ nwi_state_merge_added(diff, old_state, new_state);
+ nwi_state_merge_removed(diff, old_state);
+
+ /* Diff consists of a nwi_state_t with annotated diff_ch's */
+ return diff;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2011 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,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * 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@
+ */
+
+#ifndef _NETWORK_INFORMATION_PRIV_H_
+#define _NETWORK_INFORMATION_PRIV_H_
+
+#include <net/if.h>
+#include <stdint.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include "network_information.h"
+
+__private_extern__
+sa_family_t nwi_af_list[2];
+
+#define NWI_IFSTATE_FLAGS_NOT_IN_LIST 0x8
+
+typedef uint32_t Rank;
+
+typedef struct _nwi_ifstate {
+ char ifname[IFNAMSIZ];
+ uint64_t flags;
+ nwi_ifstate_t af_alias;
+ Rank rank;
+ int af;
+ union {
+ struct in_addr iaddr;
+ struct in6_addr iaddr6;
+ };
+ const char* diff_ch;
+} nwi_ifstate;
+
+/*
+ * nwi_state
+ *
+ *+---------------------------------------------+
+ *| generation_count |
+ *| |
+ *----------------------------------------------+
+ *| size |
+ *| |
+ *|---------------------------------------------+
+ *| ipv4_count |
+ *| |
+ *|---------------------------------------------+
+ *| ipv6_count |
+ *| |
+ *|---------------------------------------------+
+ *| ipv6_start |-------+
+ *| | |
+ *|---------------------------------------------+ |ipv6_start stores the index of the start of the v6 list.
+ *| ref | |
+ *| | |
+ *|---------------------------------------------+ |
+ *| IPv4 nwi_ifstates | |
+ *| |<------|-------+
+ *| ... | | |
+ *|---------------------------------------------+ | |
+ *| Sentinel nwi_ifstates | | |
+ *| flags =NWI_IFSTATE_FLAGS_RANK_NEVER) | | | af_alias points to the same ifstate in the
+ *| | | | opposite (v4 -> v6 and vice versa) af list.
+ *|---------------------------------------------+ | |
+ *| IPv6 nwi_ifstates |<------+ |
+ *| |<--------------+
+ *| ... |
+ *|---------------------------------------------+
+ *| Sentinel nwi_ifstates |
+ *| flags =NWI_IFSTATE_FLAGS_RANK_NEVER) |
+ *| |
+ *|---------------------------------------------+
+ *
+ */
+typedef struct _nwi_state {
+ uint64_t generation_count;
+ uint32_t size;
+ uint32_t ipv4_count;
+ uint32_t ipv6_count;
+ uint32_t ipv6_start;
+ uint32_t ref;
+ nwi_ifstate nwi_ifstates[0];
+} nwi_state;
+
+static __inline__ int
+uint32_cmp(uint32_t a, uint32_t b)
+{
+ int ret;
+
+ if (a == b) {
+ ret = 0;
+ }
+ else if (a < b) {
+ ret = -1;
+ }
+ else {
+ ret = 1;
+ }
+ return (ret);
+}
+
+static __inline__ int
+RankCompare(Rank a, Rank b)
+{
+ return (uint32_cmp(a, b));
+}
+
+/*
+ * Function: nwi_state_get_ifstate_count
+ * Purpose:
+ * Return the number of ifstate elements for the specified address family
+ * 'af'. 'af' is either AF_INET or AF_INET6.
+ *
+ * Returns zero if there are no elements.
+ */
+static __inline__
+int
+nwi_state_get_ifstate_count(nwi_state_t state, int af)
+{
+ return (af == AF_INET)?state->ipv4_count:state->ipv6_count;
+}
+
+/*
+ * The ifstate list is sorted in order of decreasing priority, with the
+ * highest priority element appearing at index zero.
+ *
+ * If 'idx' is outside of the bounds of the corresponding array, returns NULL.
+ */
+static __inline__
+nwi_ifstate_t
+nwi_state_get_ifstate_with_index(nwi_state_t state, int af, int idx)
+{
+ nwi_ifstate_t nwi_ifstate = NULL;
+ int i_idx = idx;
+
+ if (idx > nwi_state_get_ifstate_count(state, af)) {
+ return (nwi_ifstate);
+ }
+
+ if (af == AF_INET6) {
+ i_idx = idx + state->ipv6_start;
+ }
+
+ return &state->nwi_ifstates[i_idx];
+}
+
+/*
+ * Function: nwi_state_get_ifstate_with_name
+ * Purpose:
+ * Return the ifstate for the specified ifstate for the specified address
+ * family 'af'. 'af' is either AF_INET or AF_INET6.
+ *
+ * Returns NULL if no such information exists.
+ */
+static __inline__
+nwi_ifstate_t
+nwi_state_get_ifstate_with_name(nwi_state_t state,
+ int af, const char * name)
+{
+ int idx = 0;
+ int count;
+ nwi_ifstate_t ifstate = NULL;
+
+ if (state == NULL) {
+ return ifstate;
+ }
+
+ count = (af == AF_INET)
+ ?state->ipv4_count:state->ipv6_count;
+
+
+ while (idx < count) {
+ ifstate = nwi_state_get_ifstate_with_index(state, af, idx);
+ if (ifstate == NULL) {
+ break;
+ }
+ if (strcmp(name,
+ nwi_ifstate_get_ifname(ifstate)) == 0) {
+ return (ifstate);
+ }
+ idx++;
+ }
+ return (NULL);
+}
+
+__private_extern__
+nwi_state_t
+nwi_state_new(nwi_state_t old_state, int elems);
+
+__private_extern__
+nwi_state_t
+nwi_state_copy_priv(nwi_state_t old_state);
+
+__private_extern__
+void
+nwi_insert_ifstate(nwi_state_t state, const char* ifname, int af,
+ uint64_t flags, Rank rank,
+ void * ifa);
+
+__private_extern__
+void
+nwi_state_clear(nwi_state_t state, int af);
+
+__private_extern__
+void
+nwi_state_set_last(nwi_state_t state, int af);
+
+__private_extern__
+nwi_state_t
+nwi_state_diff(nwi_state_t old_state, nwi_state_t new_state);
+
+__private_extern__
+void *
+nwi_ifstate_get_address(nwi_ifstate_t ifstate);
+
+__private_extern__
+const char *
+nwi_ifstate_get_diff_str(nwi_ifstate_t ifstate);
+
+__private_extern__
+_Bool
+_nwi_state_store(nwi_state_t state);
+
+__private_extern__
+nwi_state_t
+_nwi_state_copy(void);
+
+__private_extern__
+void
+_nwi_state_dump(int level, nwi_state_t state);
+
+#endif
/*
- * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__loadSecurity(void) {
static void *image = NULL;
if (NULL == image) {
- const char *framework = "/System/Library/Frameworks/Security.framework/Versions/A/Security";
+ const char *framework = "/System/Library/Frameworks/Security.framework/Security";
struct stat statbuf;
const char *suffix = getenv("DYLD_IMAGE_SUFFIX");
char path[MAXPATHLEN];
/* process any arguments */
- while ((opt = getopt_long(argc, argv, "dvn", longopts, NULL)) != -1)
+ while ((opt = getopt_long(argc, argv, "dvn", longopts, NULL)) != -1) {
switch(opt) {
- case 'd':
- _sc_debug = TRUE;
- _sc_log = FALSE; /* enable framework logging */
- break;
- case 'v':
- _sc_verbose = TRUE;
- break;
- case 'n':
- apply = FALSE;
- break;
- case '?':
- default :
- usage(command);
+ case 'd':
+ _sc_debug = TRUE;
+ _sc_log = FALSE; /* enable framework logging */
+ break;
+ case 'v':
+ _sc_verbose = TRUE;
+ break;
+ case 'n':
+ apply = FALSE;
+ break;
+ case '?':
+ default :
+ usage(command);
+ }
}
argc -= optind;
argv += optind;
prefix = CFStringCreateWithFormat(NULL, NULL, CFSTR("/%@/"), kSCPrefSets);
- newSet = (argc == 1)
- ? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman)
- : CFRetain(CFSTR(""));
+ if (argc == 1) {
+ newSet = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
- prefs = SCPreferencesCreate(NULL, CFSTR("Select Set Command"), NULL);
- if (prefs == NULL) {
- SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n"));
- exit (1);
- }
+ /* check if a full path to the new "set" was specified */
+ if ((CFStringGetLength(newSet) > 0) && CFStringHasPrefix(newSet, prefix)) {
+ CFRange range;
+ CFMutableStringRef str;
- /* check if a full path to the new "set" was specified */
- if ((CFStringGetLength(newSet) > 0) && CFStringHasPrefix(newSet, prefix)) {
- CFRange range;
- CFMutableStringRef str;
+ str = CFStringCreateMutableCopy(NULL, 0, newSet);
+ CFRelease(newSet);
- str = CFStringCreateMutableCopy(NULL, 0, newSet);
- CFStringDelete(str, CFRangeMake(0, CFStringGetLength(prefix)));
+ CFStringDelete(str, CFRangeMake(0, CFStringGetLength(prefix)));
+ newSet = CFStringCreateCopy(NULL, newSet);
+ CFRelease(str);
- range = CFStringFind(str, CFSTR("/"), 0);
- if (range.location != kCFNotFound) {
- SCPrint(TRUE, stderr, CFSTR("Set \"%@\" not available\n."), newSet);
- exit (1);
+ range = CFStringFind(newSet, CFSTR("/"), 0);
+ if (range.location != kCFNotFound) {
+ SCPrint(TRUE, stderr, CFSTR("Set \"%@\" not available\n."), newSet);
+ exit (1);
+ }
}
+ } else {
+ newSet = CFRetain(CFSTR(""));
+ }
- CFRelease(newSet);
- newSet = str;
+
+ prefs = SCPreferencesCreate(NULL, CFSTR("Select Set Command"), NULL);
+ if (prefs == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n"));
+ exit (1);
}
sets = SCPreferencesGetValue(prefs, kSCPrefSets);
/*
- * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "cache.h"
+#pragma mark -
+#pragma mark SCDynamicStore "cache"
+
+
+static Boolean use_cache = FALSE;
+
+static CFMutableDictionaryRef cached_keys = NULL;
+static CFMutableDictionaryRef cached_set = NULL;
+static CFMutableArrayRef cached_removals = NULL;
+static CFMutableArrayRef cached_notifys = NULL;
+
+
+static void
+cache_open(void)
+{
+ if (use_cache) {
+ // if we are already using the cache
+ cache_close();
+ }
+
+ cached_keys = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ cached_set = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ cached_removals = CFArrayCreateMutable(NULL,
+ 0,
+ &kCFTypeArrayCallBacks);
+ cached_notifys = CFArrayCreateMutable(NULL,
+ 0,
+ &kCFTypeArrayCallBacks);
+
+ use_cache = TRUE;
+ return;
+}
+
+
+static CFPropertyListRef
+cache_SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key)
+{
+ CFPropertyListRef value;
+
+ value = CFDictionaryGetValue(cached_set, key);
+ if (value) {
+ // if we have "set" a new value
+ return (CFRetain(value));
+ }
+
+ if (CFArrayContainsValue(cached_removals,
+ CFRangeMake(0, CFArrayGetCount(cached_removals)),
+ key)) {
+ // if we have "removed" the key
+ _SCErrorSet(kSCStatusNoKey);
+ return NULL;
+ }
+
+ value = CFDictionaryGetValue(cached_keys, key);
+ if (value) {
+ // if we have a cached value
+ return (CFRetain(value));
+ }
+
+ value = SCDynamicStoreCopyValue(store, key);
+ if (value) {
+ CFDictionarySetValue(cached_keys, key, value);
+ }
+
+ return value;
+}
+
+
+static void
+cache_SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
+{
+ CFIndex i;
+
+ i = CFArrayGetFirstIndexOfValue(cached_removals,
+ CFRangeMake(0, CFArrayGetCount(cached_removals)),
+ key);
+ if (i != kCFNotFound) {
+ // if previously "removed"
+ CFArrayRemoveValueAtIndex(cached_removals, i);
+ }
+
+ CFDictionarySetValue(cached_set, key, value);
+
+ return;
+}
+
+static void
+cache_SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key)
+{
+ CFDictionaryRemoveValue(cached_set, key);
+
+ if (!CFArrayContainsValue(cached_removals,
+ CFRangeMake(0, CFArrayGetCount(cached_removals)),
+ key)) {
+ CFArrayAppendValue(cached_removals, key);
+ }
+
+ return;
+}
+
+
+static void
+cache_SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key)
+{
+ if (!CFArrayContainsValue(cached_notifys,
+ CFRangeMake(0, CFArrayGetCount(cached_notifys)),
+ key)) {
+ CFArrayAppendValue(cached_notifys, key);
+ }
+
+ return;
+}
+
+
+static void
+cache_write(SCDynamicStoreRef store)
+{
+ if ((CFDictionaryGetCount(cached_set) > 0) ||
+ (CFArrayGetCount(cached_removals) > 0) ||
+ (CFArrayGetCount(cached_notifys) > 0)) {
+ if (!SCDynamicStoreSetMultiple(store,
+ cached_set,
+ cached_removals,
+ cached_notifys)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ }
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+cache_close(void)
+{
+ if (!use_cache) {
+ return;
+ }
+
+ CFRelease(cached_keys);
+ CFRelease(cached_set);
+ CFRelease(cached_removals);
+ CFRelease(cached_notifys);
+
+ use_cache = FALSE;
+ return;
+}
+
+
+#pragma mark -
+#pragma mark SCDynamicStore operations
+
+
+__private_extern__
+void
+do_block(int argc, char **argv)
+{
+ Boolean enable = FALSE;
+
+ if (argc >= 1) {
+ if ((strcasecmp(argv[0], "begin") == 0) ||
+ (strcasecmp(argv[0], "start") == 0) ||
+ (strcasecmp(argv[0], "on" ) == 0) ||
+ (strcasecmp(argv[0], "1" ) == 0)) {
+ enable = TRUE;
+ } else if ((strcasecmp(argv[0], "end" ) == 0) ||
+ (strcasecmp(argv[0], "stop" ) == 0) ||
+ (strcasecmp(argv[0], "off" ) == 0) ||
+ (strcasecmp(argv[0], "0" ) == 0)) {
+ enable = FALSE;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
+ return;
+ }
+ } else {
+ enable = !use_cache; // toggle
+ }
+
+ if (enable) {
+ // begin block of SCDynamicStore operations
+ if (use_cache) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusLocked));
+ return;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("Begin block of SCDynamicStore operations\n"));
+
+ cache_open();
+ } else {
+ CFIndex n;
+
+ // end block of SCDynamicStore operations
+ if (!use_cache) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusNeedLock));
+ return;
+ }
+
+ n = CFDictionaryGetCount(cached_keys) +
+ CFArrayGetCount(cached_removals) +
+ CFArrayGetCount(cached_notifys);
+ SCPrint(TRUE, stdout,
+ CFSTR("End block of SCDynamicStore operations%s\n"),
+ (n > 0) ? ", posting changes" : "");
+ if (n > 0) {
+ cache_write(store);
+ }
+ cache_close();
+ }
+
+ return;
+}
+
+
static CFComparisonResult
sort_keys(const void *p1, const void *p2, void *context) {
CFStringRef key1 = (CFStringRef)p1;
}
+#define N_QUICK 64
+
+
__private_extern__
void
do_list(int argc, char **argv)
if (list == NULL) {
if (SCError() != kSCStatusOK) {
SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ return;
} else {
+ if (!use_cache) {
SCPrint(TRUE, stdout, CFSTR(" no keys.\n"));
+ return;
+ } else {
+ CFIndex n;
+
+ n = CFDictionaryGetCount(cached_set);
+ if (n > 0){
+ const void * cachedKeys_q[N_QUICK];
+ const void ** cachedKeys = cachedKeys_q;
+
+ if (n > (CFIndex)(sizeof(cachedKeys_q) / sizeof(CFStringRef))) {
+ cachedKeys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
+ }
+ CFDictionaryGetKeysAndValues(cached_set, cachedKeys, NULL);
+ list = CFArrayCreate(NULL, cachedKeys, n, &kCFTypeArrayCallBacks);
+ if (cachedKeys != cachedKeys_q) {
+ CFAllocatorDeallocate(NULL, cachedKeys);
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR(" no keys.\n"));
+ return;
+ }
+ }
}
- return;
+ } else if (use_cache &&
+ ((CFDictionaryGetCount(cached_set) > 0) || (CFArrayGetCount(cached_removals) > 0))) {
+ SCPrint(TRUE, stdout,
+ CFSTR(" Note: SCDynamicStore transactions in progress, key list (below) may be out of date.\n\n"));
}
listCnt = CFArrayGetCount(list);
key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
if (argc < 2) {
- if (!SCDynamicStoreAddValue(store, key, value)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ if (!use_cache) {
+ if (!SCDynamicStoreAddValue(store, key, value)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ }
+ } else {
+ CFTypeRef val;
+
+ val = cache_SCDynamicStoreCopyValue(store, key);
+ if (val != NULL) {
+ CFRelease(val);
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusKeyExists));
+ } else {
+ cache_SCDynamicStoreSetValue(store, key, value);
+ }
}
} else {
- if (!SCDynamicStoreAddTemporaryValue(store, key, value)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ if (!use_cache) {
+ if (!SCDynamicStoreAddTemporaryValue(store, key, value)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ }
+ } else {
+ CFTypeRef val;
+
+ val = cache_SCDynamicStoreCopyValue(store, key);
+ if (val != NULL) {
+ CFRelease(val);
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusKeyExists));
+ } else {
+ if (!SCDynamicStoreAddTemporaryValue(store, key, value)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ } else {
+ // and save the temp value in the cache too!
+ cache_SCDynamicStoreSetValue(store, key, value);
+ }
+ }
}
}
CFPropertyListRef newValue;
key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
- newValue = SCDynamicStoreCopyValue(store, key);
+ if (!use_cache) {
+ newValue = SCDynamicStoreCopyValue(store, key);
+ } else {
+ newValue = cache_SCDynamicStoreCopyValue(store, key);
+ }
CFRelease(key);
if (newValue == NULL) {
SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
CFStringRef key;
key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
- if (!SCDynamicStoreSetValue(store, key, value)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ if (!use_cache) {
+ if (!SCDynamicStoreSetValue(store, key, value)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ }
+ } else {
+ cache_SCDynamicStoreSetValue(store, key, value);
}
CFRelease(key);
return;
key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
if (argc == 1) {
- newValue = SCDynamicStoreCopyValue(store, key);
+ if (!use_cache) {
+ newValue = SCDynamicStoreCopyValue(store, key);
+ } else {
+ newValue = cache_SCDynamicStoreCopyValue(store, key);
+ }
} else {
CFArrayRef patterns;
patterns = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks);
- newValue = SCDynamicStoreCopyMultiple(store, NULL, patterns);
+ if (!use_cache) {
+ newValue = SCDynamicStoreCopyMultiple(store, NULL, patterns);
+ } else {
+ CFArrayRef keys;
+ CFMutableDictionaryRef newDict;
+
+ newDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ keys = SCDynamicStoreCopyKeyList(store, key);
+ if (keys != NULL) {
+ CFIndex i;
+ CFIndex n;
+
+ n = CFArrayGetCount(keys);
+ for (i = 0; i < n; i++) {
+ CFStringRef storeKey;
+ CFTypeRef storeVal;
+
+ storeKey = CFArrayGetValueAtIndex(keys, i);
+ storeVal = cache_SCDynamicStoreCopyValue(store, storeKey);
+ if (storeVal != NULL) {
+ CFDictionarySetValue(newDict, storeKey, storeVal);
+ CFRelease(storeVal);
+ }
+ }
+ CFRelease(keys);
+ }
+
+ if ((CFDictionaryGetCount(cached_set) > 0) || (CFArrayGetCount(cached_removals) > 0)) {
+ SCPrint(TRUE, stdout, CFSTR(" Note: SCDynamicStore locked, keys included (below) may be out of date.\n\n"));
+ }
+
+ newValue = newDict;
+ }
CFRelease(patterns);
}
CFStringRef key;
key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
- if (!SCDynamicStoreRemoveValue(store, key)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ if (!use_cache) {
+ if (!SCDynamicStoreRemoveValue(store, key)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ }
+ } else {
+ cache_SCDynamicStoreRemoveValue(store, key);
}
CFRelease(key);
return;
CFStringRef key;
key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
- if (!SCDynamicStoreNotifyValue(store, key)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- }
- CFRelease(key);
- return;
-}
-
-
-__private_extern__
-void
-do_touch(int argc, char **argv)
-{
- CFStringRef key;
-
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
- if (!SCDynamicStoreTouchValue(store, key)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ if (!use_cache) {
+ if (!SCDynamicStoreNotifyValue(store, key)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ }
+ } else {
+ cache_SCDynamicStoreNotifyValue(store, key);
}
CFRelease(key);
return;
/*
- * Copyright (c) 2000, 2001 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#ifndef _CACHE_H
#define _CACHE_H
+#include <Availability.h>
+#include <TargetConditionals.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
+void cache_close (void);
+
+void do_block (int argc, char **argv);
+
void do_list (int argc, char **argv);
void do_add (int argc, char **argv);
void do_get (int argc, char **argv);
void do_show (int argc, char **argv);
void do_remove (int argc, char **argv);
void do_notify (int argc, char **argv);
-void do_touch (int argc, char **argv);
__END_DECLS
{ "d.add", 2, 101, do_dictSetKey, 1, 0,
" d.add key [*#?] val [v2 ...] : add information to dictionary\n"
- " (*=array, #=number, ?=boolean)" },
+ " (*=array, #=number, ?=boolean, %=hex data)" },
{ "d.remove", 1, 1, do_dictRemoveKey, 1, 0,
" d.remove key : remove key from dictionary" },
{ "close", 0, 0, do_close, 2, 1,
" close : close current \"configd\" session" },
- { "lock", 0, 0, do_lock, 3, 1,
- " lock : locks write access to data store" },
-
- { "unlock", 0, 0, do_unlock, 3, 1,
- " unlock : unlocks write access to data store" },
+ { "block", 0, 1, do_block, 3, 1,
+ " block [\"begin\" | \"end\"] : block multiple data store transactions" },
{ "list", 0, 2, do_list, 4, 0,
" list [pattern] : list keys in data store" },
{ "notify", 1, 1, do_notify, 4, 0,
" notify key : notify key in data store" },
- { "touch", 1, 1, do_touch, 4, 1,
- " touch key : touch key in data store" },
-
{ "n.list", 0, 1, do_notify_list, 5, 0,
" n.list [\"pattern\"] : list notification keys" },
{ "n.wait", 0, 0, do_notify_wait, 5, 2,
" n.wait : wait for changes" },
- { "n.callback", 0, 1, do_notify_callback, 5, 2,
- " n.callback [\"verbose\"] : watch for changes" },
-
{ "n.signal", 1, 2, do_notify_signal, 5, 2,
" n.signal sig [pid] : signal changes" },
{ "d.add", 2, 101, do_dictSetKey, 1, 0,
" d.add key [*#?] val [v2 ...] : add information to dictionary\n"
- " (*=array, #=number, ?=boolean)" },
+ " (*=array, #=number, ?=boolean, %=hex data)" },
{ "d.remove", 1, 1, do_dictRemoveKey, 1, 0,
" d.remove key : remove key from dictionary" },
/*
- * Copyright (c) 2000-2004, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFMutableArrayRef array = NULL;
Boolean doArray = FALSE;
Boolean doBoolean = FALSE;
+ Boolean doData = FALSE;
Boolean doNumeric = FALSE;
CFStringRef key;
CFMutableDictionaryRef newValue;
} else if (strcmp(argv[0], "?") == 0) {
/* if boolean values requested */
doBoolean = TRUE;
+ } else if (strcmp(argv[0], "%") == 0) {
+ /* if [hex] data values requested */
+ doData = TRUE;
} else if (strcmp(argv[0], "#") == 0) {
/* if numeric values requested */
doNumeric = TRUE;
CFRelease(key);
return;
}
+ } else if (doData) {
+ uint8_t *bytes;
+ CFMutableDataRef data;
+ int i;
+ int j;
+ int n;
+
+ n = strlen(argv[0]);
+ if ((n % 2) == 1) {
+ SCPrint(TRUE, stdout, CFSTR("d.add: not enough bytes.\n"));
+ if (doArray) CFRelease(array);
+ CFRelease(key);
+ return;
+ }
+
+ data = CFDataCreateMutable(NULL, (n / 2));
+ CFDataSetLength(data, (n / 2));
+
+ bytes = (uint8_t *)CFDataGetBytePtr(data);
+ for (i = 0, j = 0; i < n; i += 2, j++) {
+ unsigned long byte;
+ char *end;
+ char str[3] = { 0 };
+
+ str[0] = argv[0][i];
+ str[1] = argv[0][i + 1];
+ errno = 0;
+ byte = strtoul(str, &end, 16);
+ if ((*end != '\0') || (errno != 0)) {
+ CFRelease(data);
+ data = NULL;
+ break;
+ }
+
+ bytes[j] = byte;
+ }
+
+ if (data == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("d.add: invalid data.\n"));
+ if (doArray) CFRelease(array);
+ CFRelease(key);
+ return;
+ }
+
+ val = data;
} else if (doNumeric) {
int intValue;
/*
- * Copyright (c) 2010-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2010-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* - initial revision
* February 8, 2011 Kevin Wells <kcw@apple.com>
* - added "select" command
+ * January 2012 Kevin Wells <kcw@apple.com>
+ * - added arguments to "start" command to pass authentication credentials
+ * - "show" now takes a service name as an alternative to a service ID
+ * - fixes a bug whereby "IPv4" was being displayed as a subtype to IPsec services
+ * - improved format of "list" output
+ * - general cleanup of error messages and some variable names
*/
#include <sys/time.h>
+CFStringRef username = NULL;
+CFStringRef password = NULL;
+CFStringRef sharedsecret = NULL;
-static SCNetworkConnectionRef connectionRef = NULL;
+static SCNetworkConnectionRef connection = NULL;
static int n_callback = 0;
}
/* -----------------------------------------------------------------------------
------------------------------------------------------------------------------ */
-static CFStringRef
-nc_copy_serviceID(int argc, char **argv)
-{
- CFStringRef serviceIDRef = NULL;
+ ----------------------------------------------------------------------------- */
+static void
+nc_get_service_type_and_subtype(SCNetworkServiceRef service, CFStringRef *iftype, CFStringRef *ifsubtype) {
+ SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
+ SCNetworkInterfaceRef child = SCNetworkInterfaceGetInterface(interface);
- if (argc == 0) {
- serviceIDRef = _copyStringFromSTDIN();
- } else {
- serviceIDRef = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ *iftype = SCNetworkInterfaceGetInterfaceType(interface);
+ *ifsubtype = NULL;
+ if (CFEqual(*iftype, kSCNetworkInterfaceTypePPP) ||
+ CFEqual(*iftype, kSCNetworkInterfaceTypeVPN)) {
+ *ifsubtype = (child != NULL) ? SCNetworkInterfaceGetInterfaceType(child) : NULL;
}
-
- return serviceIDRef;
}
/* -----------------------------------------------------------------------------
} else {
// if multiple services match
selected = NULL;
- SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
+ SCPrint(TRUE, stderr, CFSTR("Multiple services match\n"));
goto done;
}
}
}
- done :
+done :
if (selected != NULL) CFRetain(selected);
if (services != NULL) CFRelease(services);
return selected;
}
+/* -----------------------------------------------------------------------------
+ ----------------------------------------------------------------------------- */
+static SCNetworkServiceRef
+nc_copy_service_from_arguments(int argc, char **argv, SCNetworkSetRef set) {
+ CFStringRef serviceID = NULL;
+ SCNetworkServiceRef service = NULL;
+
+ if (argc == 0) {
+ serviceID = _copyStringFromSTDIN();
+ } else {
+ serviceID = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ }
+ if (serviceID == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("No service ID specified\n"));
+ return NULL;
+ }
+ service = nc_copy_service(set, serviceID);
+ my_CFRelease(&serviceID);
+ return service;
+}
+
/* -----------------------------------------------------------------------------
----------------------------------------------------------------------------- */
{
SCNetworkConnectionContext context = { 0, &n_callback, NULL, NULL, NULL };
SCNetworkServiceRef service;
- CFStringRef serviceIDRef;
- serviceIDRef = nc_copy_serviceID(argc, argv);
- if (serviceIDRef == NULL) {
- SCPrint(TRUE, stderr, CFSTR("No service identifier\n"));
- if (exit_on_failure)
- exit(1);
- return;
- }
-
- service = nc_copy_service(NULL, serviceIDRef);
- CFRelease(serviceIDRef);
+ service = nc_copy_service_from_arguments(argc, argv, NULL);
if (service == NULL) {
SCPrint(TRUE, stderr, CFSTR("No service\n"));
if (exit_on_failure)
return;
}
- connectionRef = SCNetworkConnectionCreateWithService(NULL, service, nc_callback, &context);
- if (connectionRef == NULL) {
- SCPrint(TRUE, stderr, CFSTR("nc_create_connection SCNetworkConnectionCreateWithServiceID() failed to create connectionRef: %s\n"), SCErrorString(SCError()));
+ connection = SCNetworkConnectionCreateWithService(NULL, service, nc_callback, &context);
+ CFRelease(service);
+ if (connection == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("Could not create connection: %s\n"), SCErrorString(SCError()));
if (exit_on_failure)
exit(1);
return;
static void
nc_release_connection()
{
- my_CFRelease(&connectionRef);
+ my_CFRelease(&connection);
}
/* -----------------------------------------------------------------------------
static void
nc_start(int argc, char **argv)
{
+ CFMutableDictionaryRef userOptions = NULL;
+ CFStringRef iftype = NULL;
+ CFStringRef ifsubtype = NULL;
+ SCNetworkServiceRef service = NULL;
+
nc_create_connection(argc, argv, TRUE);
- SCNetworkConnectionStart(connectionRef, 0, TRUE);
+ service = SCNetworkConnectionGetService(connection);
+ nc_get_service_type_and_subtype(service, &iftype, &ifsubtype);
+
+ userOptions = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ Boolean isL2TP = (CFEqual(iftype, kSCEntNetPPP) &&
+ (ifsubtype != NULL) && CFEqual(ifsubtype, kSCValNetInterfaceSubTypeL2TP));
+
+ if (CFEqual(iftype, kSCEntNetPPP)) {
+ CFMutableDictionaryRef pppEntity = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ if (username != NULL) {
+ CFDictionarySetValue(pppEntity, kSCPropNetPPPAuthName, username);
+ }
+ if (password != NULL) {
+ CFDictionarySetValue(pppEntity, kSCPropNetPPPAuthPassword, password);
+ }
+ CFDictionarySetValue(userOptions, kSCEntNetPPP, pppEntity);
+ my_CFRelease(&pppEntity);
+ }
+ if (CFEqual(iftype, kSCEntNetIPSec) || isL2TP) {
+ CFMutableDictionaryRef ipsecEntity = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (!isL2TP) {
+ if (username != NULL) {
+ CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecXAuthName, username);
+ }
+ if (password != NULL) {
+ CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecXAuthPassword, password);
+ }
+ }
+ if (sharedsecret != NULL) {
+ CFDictionarySetValue(ipsecEntity, kSCPropNetIPSecSharedSecret, sharedsecret);
+ }
+ CFDictionarySetValue(userOptions, kSCEntNetIPSec, ipsecEntity);
+ my_CFRelease(&ipsecEntity);
+ }
+ if (CFEqual(iftype, kSCEntNetVPN)) {
+ CFMutableDictionaryRef vpnEntity = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (username != NULL) {
+ CFDictionarySetValue(vpnEntity, kSCPropNetVPNAuthName, username);
+ }
+ if (password != NULL) {
+ CFDictionarySetValue(vpnEntity, kSCPropNetVPNAuthPassword, password);
+ }
+ CFDictionarySetValue(userOptions, kSCEntNetVPN, vpnEntity);
+ my_CFRelease(&vpnEntity);
+ }
+ // If it doesn't match any VPN type, fail silently
+
+ if (!SCNetworkConnectionStart(connection, userOptions, TRUE)) {
+ SCPrint(TRUE, stderr, CFSTR("Could not start connection: %s\n"), SCErrorString(SCError()));
+ exit(1);
+ };
+
+ CFRelease(userOptions);
nc_release_connection();
exit(0);
}
{
nc_create_connection(argc, argv, TRUE);
- SCNetworkConnectionStop(connectionRef, TRUE);
+ if (!SCNetworkConnectionStop(connection, TRUE)) {
+ SCPrint(TRUE, stderr, CFSTR("Could not stop connection: %s\n"), SCErrorString(SCError()));
+ exit(1);
+ };
nc_release_connection();
exit(0);
{
nc_create_connection(argc, argv, TRUE);
- SCNetworkConnectionSuspend(connectionRef);
+ SCNetworkConnectionSuspend(connection);
nc_release_connection();
exit(0);
{
nc_create_connection(argc, argv, TRUE);
- SCNetworkConnectionResume(connectionRef);
+ SCNetworkConnectionResume(connection);
nc_release_connection();
exit(0);
nc_create_connection(argc, argv, TRUE);
- status = SCNetworkConnectionGetStatus(connectionRef);
- nc_callback(connectionRef, status, NULL);
+ status = SCNetworkConnectionGetStatus(connection);
+ nc_callback(connection, status, NULL);
nc_release_connection();
exit(0);
nc_create_connection(argc, argv, TRUE);
- status = SCNetworkConnectionGetStatus(connectionRef);
+ status = SCNetworkConnectionGetStatus(connection);
// report initial status
n_callback = 0;
- nc_callback(connectionRef, status, &n_callback);
+ nc_callback(connection, status, &n_callback);
// setup watcher
if (doDispatch) {
- if (!SCNetworkConnectionSetDispatchQueue(connectionRef, dispatch_get_current_queue())) {
- printf("SCNetworkConnectionSetDispatchQueue() failed: %s\n", SCErrorString(SCError()));
+ if (!SCNetworkConnectionSetDispatchQueue(connection, dispatch_get_current_queue())) {
+ SCPrint(TRUE, stderr, CFSTR("Unable to schedule watch process: %s\n"), SCErrorString(SCError()));
exit(1);
}
} else {
- if (!SCNetworkConnectionScheduleWithRunLoop(connectionRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
- printf("SCNetworkConnectinScheduleWithRunLoop() failed: %s\n", SCErrorString(SCError()));
+ if (!SCNetworkConnectionScheduleWithRunLoop(connection, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
+ SCPrint(TRUE, stderr, CFSTR("Unable to schedule watch process: %s\n"), SCErrorString(SCError()));
exit(1);
}
}
nc_create_connection(argc, argv, TRUE);
- stats_dict = SCNetworkConnectionCopyStatistics(connectionRef);
+ stats_dict = SCNetworkConnectionCopyStatistics(connection);
if (stats_dict) {
SCPrint(TRUE, stdout, CFSTR("%@\n"), stats_dict);
/* -----------------------------------------------------------------------------
----------------------------------------------------------------------------- */
+static void
+checkOnDemandHost(SCDynamicStoreRef store, CFStringRef nodeName, Boolean retry)
+{
+ Boolean ok;
+ CFStringRef connectionServiceID = NULL;
+ SCNetworkConnectionStatus connectionStatus = 0;
+ CFStringRef vpnRemoteAddress = NULL;
+
+ SCPrint(TRUE, stdout, CFSTR("OnDemand host/domain check (%sretry)\n"), retry ? "" : "no ");
+
+ ok = __SCNetworkConnectionCopyOnDemandInfoWithName(&store,
+ nodeName,
+ retry,
+ &connectionServiceID,
+ &connectionStatus,
+ &vpnRemoteAddress);
+
+ if (ok) {
+ SCPrint(TRUE, stdout, CFSTR(" serviceID = %@\n"), connectionServiceID);
+ SCPrint(TRUE, stdout, CFSTR(" remote address = %@\n"), vpnRemoteAddress);
+ } else if (SCError() != kSCStatusOK) {
+ SCPrint(TRUE, stdout, CFSTR("%sretry\n"), retry ? "" : "no ");
+ SCPrint(TRUE, stdout,
+ CFSTR(" Unable to copy OnDemand information for connection: %s\n"),
+ SCErrorString(SCError()));
+ } else {
+ SCPrint(TRUE, stdout, CFSTR(" no match\n"));
+ }
+
+ if (connectionServiceID != NULL) {
+ CFRelease(connectionServiceID);
+ connectionServiceID = NULL;
+ }
+ if (vpnRemoteAddress != NULL) {
+ CFRelease(vpnRemoteAddress);
+ vpnRemoteAddress = NULL;
+ }
+
+ return;
+}
+
static void
nc_ondemand(int argc, char **argv)
{
store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), NULL, NULL);
if (store == NULL) {
- SCPrint(TRUE, stderr, CFSTR("do_nc_ondemand SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
+ SCPrint(TRUE, stderr, CFSTR("Unable to create dynamic store: %s\n"), SCErrorString(SCError()));
goto done;
}
- key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetOnDemand);
- if (key == NULL) {
- SCPrint(TRUE, stderr, CFSTR("do_nc_ondemand SCDynamicStoreKeyCreateNetworkGlobalEntity() failed: %s\n"), SCErrorString(SCError()));
+ if (argc > 0) {
+ CFStringRef nodeName;
+
+ nodeName = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ checkOnDemandHost(store, nodeName, FALSE);
+ checkOnDemandHost(store, nodeName, TRUE);
goto done;
}
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetOnDemand);
+
ondemand_dict = SCDynamicStoreCopyValue(store, key);
if (ondemand_dict) {
SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), kSCEntNetOnDemand, ondemand_dict);
exit(exit_code);
}
+
/* -----------------------------------------------------------------------------
- Given a string 'key' and a string prefix 'prefix',
- return the next component in the slash '/' separated
- key. If no slash follows the prefix, return NULL.
+ ----------------------------------------------------------------------------- */
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
- Examples:
- 1. key = "a/b/c" prefix = "a/" returns "b"
- 2. key = "a/b/c" prefix = "a/b/" returns NULL
------------------------------------------------------------------------------ */
-CFStringRef parse_component(CFStringRef key, CFStringRef prefix)
+CFStringRef
+copy_padded_string(CFStringRef original, int width)
{
- CFMutableStringRef comp;
- CFRange range;
+ CFMutableStringRef padded;
- if (!CFStringHasPrefix(key, prefix))
- return NULL;
+ padded = CFStringCreateMutableCopy(NULL, 0, original);
+ CFStringPad(padded, CFSTR(" "), MAX(CFStringGetLength(original), width), 0);
+ return padded;
+}
- comp = CFStringCreateMutableCopy(NULL, 0, key);
- CFStringDelete(comp, CFRangeMake(0, CFStringGetLength(prefix)));
- range = CFStringFind(comp, CFSTR("/"), 0);
- if (range.location == kCFNotFound) {
- CFRelease(comp);
- return NULL;
- }
- range.length = CFStringGetLength(comp) - range.location;
- CFStringDelete(comp, range);
- return comp;
+
+static void
+nc_print_VPN_service(SCNetworkServiceRef service)
+{
+ CFStringRef type = NULL;
+ CFStringRef sub_type = NULL;
+
+ nc_get_service_type_and_subtype(service, &type, &sub_type);
+
+ CFStringRef service_name = SCNetworkServiceGetName(service);
+ if (service_name == NULL)
+ service_name = CFSTR("");
+ CFStringRef service_name_quoted = CFStringCreateWithFormat(NULL, NULL, CFSTR("\"%@\""), service_name);
+ if (service_name_quoted == NULL) {
+ service_name_quoted = CFRetain(CFSTR(""));
+ }
+ CFStringRef service_name_padded = copy_padded_string(service_name, 30);
+
+ CFStringRef service_id = SCNetworkServiceGetServiceID(service);
+ SCNetworkInterfaceRef interface = SCNetworkServiceGetInterface(service);
+ CFStringRef display_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+ if (display_name == NULL)
+ display_name = CFSTR("");
+ CFStringRef display_name_padded = copy_padded_string(display_name, 18);
+
+
+ SCPrint(TRUE,
+ stdout,
+ CFSTR("%@ %@ %@ %@ [%@%@%@]\n"),
+ SCNetworkServiceGetEnabled(service) ? CFSTR("*") : CFSTR(" "),
+ service_id,
+ display_name_padded,
+ service_name_padded,
+ type,
+ (sub_type == NULL) ? CFSTR("") : CFSTR(":"),
+ (sub_type == NULL) ? CFSTR("") : sub_type);
+ CFRelease(service_name_quoted);
+ CFRelease(display_name_padded);
+ CFRelease(service_name_padded);
}
nc_list(int argc, char **argv)
{
int count;
- int exit_code = 1;
int i;
- CFStringRef key = NULL;
- CFMutableDictionaryRef names = NULL;
CFArrayRef services = NULL;
- CFStringRef setup = NULL;
- SCDynamicStoreRef store;
- store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), NULL, NULL);
- if (store == NULL) {
- SCPrint(TRUE, stderr, CFSTR("nc_list SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
- goto done;
- }
- key = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetInterface);
- if (key == NULL ) {
- SCPrint(TRUE, stderr, CFSTR("nc_list SCDynamicStoreKeyCreateNetworkServiceEntity() failed to create key string\n"));
- goto done;
- }
- setup = SCDynamicStoreKeyCreate(0, CFSTR("%@/%@/%@/"), kSCDynamicStoreDomainSetup, kSCCompNetwork, kSCCompService);
- if (setup == NULL) {
- SCPrint(TRUE, stderr, CFSTR("nc_list SCDynamicStoreKeyCreate() failed to create setup string\n"));
- goto done;
- }
- names = CFDictionaryCreateMutable(NULL,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- if (names == NULL) {
- SCPrint(TRUE, stderr, CFSTR("nc_list CFDictionaryCreateMutable() failed to create names dictionary\n"));
- goto done;
- }
+ SCPrint(TRUE, stdout, CFSTR("Available network connection services in the current set (*=enabled):\n"));
services = SCNetworkConnectionCopyAvailableServices(NULL);
if (services != NULL) {
count = CFArrayGetCount(services);
for (i = 0; i < count; i++) {
SCNetworkServiceRef service;
- CFStringRef serviceID;
- CFStringRef serviceName;
service = CFArrayGetValueAtIndex(services, i);
- serviceID = SCNetworkServiceGetServiceID(service);
- serviceName = SCNetworkServiceGetName(service);
- if (serviceName != NULL) {
- CFDictionarySetValue(names, serviceID, serviceName);
- }
+ nc_print_VPN_service(service);
}
- CFRelease(services);
- }
-
- services = SCDynamicStoreCopyKeyList(store, key);
- if (services == NULL ) {
- SCPrint(TRUE, stderr, CFSTR("nc_list SCDynamicStoreCopyKeyList() failed: %s\n"), SCErrorString(SCError()));
- goto done;
}
-
- count = CFArrayGetCount(services);
- for (i = 0; i < count; i++) {
- CFStringRef serviceID;
-
- serviceID = parse_component(CFArrayGetValueAtIndex(services, i), setup);
- if (serviceID) {
- CFStringRef iftype;
- CFStringRef ifsubtype;
- CFStringRef interface_key = NULL;
- CFDictionaryRef interface_dict = NULL;
- CFStringRef service_name;
-
- interface_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, kSCEntNetInterface);
- if (!interface_key) {
- SCPrint(TRUE, stderr, CFSTR("nc_list SCDynamicStoreKeyCreateNetworkServiceEntity() failed to interface key string\n"));
- goto endloop;
- }
-
- interface_dict = SCDynamicStoreCopyValue(store, interface_key);
- if (!interface_dict) {
- SCPrint(TRUE, stderr, CFSTR("nc_list SCDynamicStoreCopyValue() to copy interface dictionary: %s\n"), SCErrorString(SCError()));
- goto endloop;
- }
-
- iftype = CFDictionaryGetValue(interface_dict, kSCPropNetInterfaceType);
- if (!iftype) {
- // is that an error condition ???
- goto endloop;
- }
-
- if (!CFEqual(iftype, kSCEntNetPPP) &&
- !CFEqual(iftype, kSCEntNetIPSec) &&
- !CFEqual(iftype, kSCEntNetVPN))
- goto endloop;
-
- ifsubtype = CFDictionaryGetValue(interface_dict, kSCPropNetInterfaceSubType);
-
- service_name = CFDictionaryGetValue(names, serviceID);
-
- SCPrint(TRUE, stdout, CFSTR("[%@%@%@] %@%s%@\n"),
- iftype ? iftype : CFSTR("?"),
- ifsubtype ? CFSTR("/") : CFSTR(""),
- ifsubtype ? ifsubtype : CFSTR(""),
- serviceID,
- service_name ? " : " : "",
- service_name ? service_name : CFSTR(""));
-
- endloop:
- my_CFRelease(&interface_key);
- my_CFRelease(&interface_dict);
- my_CFRelease(&serviceID);
- }
- }
-
- exit_code = 0;
-done:
my_CFRelease(&services);
- my_CFRelease(&names);
- my_CFRelease(&setup);
- my_CFRelease(&key);
- my_CFRelease(&store);
- exit(exit_code);
+ exit(0);
}
+
/* -----------------------------------------------------------------------------
----------------------------------------------------------------------------- */
static void
nc_show(int argc, char **argv)
{
+ SCNetworkServiceRef service = NULL;
SCDynamicStoreRef store = NULL;
int exit_code = 1;
- CFStringRef setup = NULL;
- CFStringRef serviceIDRef = NULL;
- CFArrayRef services = NULL;
+ CFStringRef serviceID = NULL;
CFStringRef iftype = NULL;
CFStringRef ifsubtype = NULL;
- CFStringRef interface_key = NULL;
- CFDictionaryRef interface_dict = NULL;
CFStringRef type_entity_key = NULL;
CFStringRef subtype_entity_key = NULL;
CFDictionaryRef type_entity_dict = NULL;
CFDictionaryRef subtype_entity_dict = NULL;
- serviceIDRef = nc_copy_serviceID(argc, argv);
- if (serviceIDRef == NULL) {
- SCPrint(TRUE, stderr, CFSTR("No service ID\n"));
- goto done;
- }
-
- store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), NULL, NULL);
- if (store == NULL) {
- SCPrint(TRUE, stderr, CFSTR("nc_show SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
- goto done;
+ service = nc_copy_service_from_arguments(argc, argv, NULL);
+ if (service == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("No service\n"));
+ exit(exit_code);
}
- interface_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceIDRef, kSCEntNetInterface);
- if (!interface_key) {
- SCPrint(TRUE, stderr, CFSTR("nc_show SCDynamicStoreKeyCreateNetworkServiceEntity() failed to create interface key\n"));
- goto done;
- }
+ serviceID = SCNetworkServiceGetServiceID(service);
- interface_dict = SCDynamicStoreCopyValue(store, interface_key);
- if (!interface_dict) {
- SCPrint(TRUE, stdout, CFSTR("Interface dictionary missing for service ID : %@\n"), serviceIDRef);
- goto done;
- }
-
- iftype = CFDictionaryGetValue(interface_dict, kSCPropNetInterfaceType);
- if (!iftype) {
- SCPrint(TRUE, stdout, CFSTR("Interface Type missing for service ID : %@\n"), serviceIDRef);
- goto done;
- }
+ nc_get_service_type_and_subtype(service, &iftype, &ifsubtype);
if (!CFEqual(iftype, kSCEntNetPPP) &&
- !CFEqual(iftype, kSCEntNetIPSec) &&
- !CFEqual(iftype, kSCEntNetVPN)) {
- SCPrint(TRUE, stdout, CFSTR("Interface Type [%@] invalid for service ID : %@\n"), iftype, serviceIDRef);
+ !CFEqual(iftype, kSCEntNetIPSec) &&
+ !CFEqual(iftype, kSCEntNetVPN)) {
+ SCPrint(TRUE, stderr, CFSTR("Not a connection oriented service: %@\n"), serviceID);
goto done;
}
- ifsubtype = CFDictionaryGetValue(interface_dict, kSCPropNetInterfaceSubType);
- SCPrint(TRUE, stdout, CFSTR("[%@%@%@] %@\n"),
- iftype ? iftype : CFSTR("?"),
- ifsubtype ? CFSTR("/") : CFSTR(""),
- ifsubtype ? ifsubtype : CFSTR(""),
- serviceIDRef);
+ type_entity_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, iftype);
+
+ nc_print_VPN_service(service);
- type_entity_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceIDRef, iftype);
- if (!type_entity_key) {
- SCPrint(TRUE, stderr, CFSTR("nc_show SCDynamicStoreKeyCreateNetworkServiceEntity() failed to create type entity key\n"));
+ store = SCDynamicStoreCreate(NULL, CFSTR("scutil --nc"), NULL, NULL);
+ if (store == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("Unable to create dynamic store: %s\n"), SCErrorString(SCError()));
goto done;
}
type_entity_dict = SCDynamicStoreCopyValue(store, type_entity_key);
+
if (!type_entity_dict) {
- SCPrint(TRUE, stdout, CFSTR("%@ dictionary missing for service ID : %@\n"), iftype, serviceIDRef);
+ SCPrint(TRUE, stderr, CFSTR("No \"%@\" configuration available\n"), iftype);
} else {
SCPrint(TRUE, stdout, CFSTR("%@ %@\n"), iftype, type_entity_dict);
}
if (ifsubtype) {
- subtype_entity_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceIDRef, ifsubtype);
- if (!subtype_entity_key) {
- SCPrint(TRUE, stderr, CFSTR("nc_show SCDynamicStoreKeyCreateNetworkServiceEntity() failed to create subtype entity key\n"));
- goto done;
- }
+ subtype_entity_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, ifsubtype);
subtype_entity_dict = SCDynamicStoreCopyValue(store, subtype_entity_key);
if (!subtype_entity_dict) {
//
exit_code = 0;
done:
- my_CFRelease(&serviceIDRef);
- my_CFRelease(&interface_key);
- my_CFRelease(&interface_dict);
my_CFRelease(&type_entity_key);
my_CFRelease(&type_entity_dict);
my_CFRelease(&subtype_entity_key);
my_CFRelease(&subtype_entity_dict);
- my_CFRelease(&services);
- my_CFRelease(&setup);
my_CFRelease(&store);
-
+ my_CFRelease(&service);
exit(exit_code);
}
SCNetworkSetRef current_set;
int exit_code = 1;
SCNetworkServiceRef service = NULL;
- CFStringRef service_id;
Boolean status;
- service_id = nc_copy_serviceID(argc, argv);
- if (service_id == NULL) {
- SCPrint(TRUE, stderr, CFSTR("No service identifier\n"));
- exit(exit_code);
- }
-
do_prefs_init(); /* initialization */
do_prefs_open(0, NULL); /* open default prefs */
current_set = SCNetworkSetCopyCurrent(prefs);
if (current_set == NULL) {
- SCPrint(TRUE, stdout, CFSTR("nc_select SCNetworkSetCopyCurrent() failed: %s\n"), SCErrorString(SCError()));
+ SCPrint(TRUE, stderr, CFSTR("No current location\n"), SCErrorString(SCError()));
goto done;
}
- service = nc_copy_service(current_set, service_id);
+ service = nc_copy_service_from_arguments(argc, argv, current_set);
if (service == NULL) {
- SCPrint(TRUE, stdout, CFSTR("No service\n"));
+ SCPrint(TRUE, stderr, CFSTR("No service\n"));
goto done;
}
#if !TARGET_OS_IPHONE
status = SCNetworkServiceSetEnabled(service, TRUE);
if (!status) {
- SCPrint(TRUE, stdout, CFSTR("nc_select SCNetworkServiceSetEnabled() failed: %s\n"), SCErrorString(SCError()));
+ SCPrint(TRUE, stderr, CFSTR("Unable to enable service: %s\n"), SCErrorString(SCError()));
goto done;
}
#else
status = SCNetworkSetSetSelectedVPNService(current_set, service);
if (!status) {
- SCPrint(TRUE, stdout, CFSTR("nc_select SCNetworkSetSetSelectedVPNService() failed: %s\n"), SCErrorString(SCError()));
+ SCPrint(TRUE, stderr, CFSTR("Unable to select service: %s\n"), SCErrorString(SCError()));
goto done;
}
#endif
_prefs_save();
exit_code = 0;
done:
-
- my_CFRelease(&service_id);
+ my_CFRelease(&service);
my_CFRelease(¤t_set);
_prefs_close();
exit(exit_code);
/*
- * Copyright (c) 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2010-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
* Modification History
*
- * March1, 2010 Christophe Allie <callie@apple.com>
+ * March 1, 2010 Christophe Allie <callie@apple.com>
* - initial revision
*/
#include <sys/cdefs.h>
#include <SystemConfiguration/SystemConfiguration.h>
+extern CFStringRef username;
+extern CFStringRef password;
+extern CFStringRef sharedsecret;
__BEGIN_DECLS
__private_extern__
-CFNumberRef
+CF_RETURNS_RETAINED CFNumberRef
_copy_number(const char *arg)
{
int val;
n = CFArrayGetCount(sets);
CFRelease(sets);
+ sets = NULL;
if (n > 0) {
SCPrint(TRUE, stdout, CFSTR("no current set\n"));
return;
/*
- * Copyright (c) 2004, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004, 2006, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
char **argv,
CFMutableDictionaryRef newConfiguration);
+CF_RETURNS_RETAINED
CFNumberRef _copy_number (const char *arg);
CFIndex _find_option (const char *option,
void _show_entity (CFDictionaryRef entity, CFStringRef prefix);
-void do_net_init (void);
-void do_net_quit (int argc, char **argv);
+void do_net_init (void);
+void do_net_quit (int argc, char **argv);
-void do_net_open (int argc, char **argv);
-void do_net_commit (int argc, char **argv);
-void do_net_apply (int argc, char **argv);
-void do_net_close (int argc, char **argv);
+void do_net_open (int argc, char **argv);
+void do_net_commit (int argc, char **argv);
+void do_net_apply (int argc, char **argv);
+void do_net_close (int argc, char **argv);
-void do_net_create (int argc, char **argv);
-void do_net_disable (int argc, char **argv);
-void do_net_enable (int argc, char **argv);
-void do_net_remove (int argc, char **argv);
-void do_net_select (int argc, char **argv);
-void do_net_set (int argc, char **argv);
-void do_net_show (int argc, char **argv);
-void do_net_update (int argc, char **argv);
+void do_net_create (int argc, char **argv);
+void do_net_disable (int argc, char **argv);
+void do_net_enable (int argc, char **argv);
+void do_net_remove (int argc, char **argv);
+void do_net_select (int argc, char **argv);
+void do_net_set (int argc, char **argv);
+void do_net_show (int argc, char **argv);
+void do_net_update (int argc, char **argv);
-void do_net_snapshot (int argc, char **argv);
+void do_net_snapshot (int argc, char **argv);
__END_DECLS
*/
+#include <TargetConditionals.h>
#include "scutil.h"
#include "net.h"
#include "prefs.h"
#include <SystemConfiguration/LinkConfiguration.h>
+#if TARGET_OS_EMBEDDED
+#define INLINE_PASSWORDS_USE_CFSTRING
+#endif // TARGET_OS_EMBEDDED
+
+
#pragma mark -
#pragma mark Interface management
goto done;
}
+#if !TARGET_OS_IPHONE
else if (strcasecmp(argv[0], "$bond") == 0) {
CFStringRef interfaceType;
}
allowIndex = FALSE;
}
+#endif // !TARGET_OS_IPHONE
else if (strcasecmp(argv[0], "$bridge") == 0) {
CFStringRef interfaceType;
/* -------------------- */
+static int
+__doRank(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ SCNetworkInterfaceRef interface;
+ CFStringRef interfaceName;
+ Boolean ok = FALSE;
+ SCNetworkServicePrimaryRank rank = kSCNetworkServicePrimaryRankDefault;
+ SCDynamicStoreRef store;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout,
+ CFSTR("%s not specified\n"),
+ description != NULL ? description : "rank");
+ return -1;
+ }
+
+ if (strlen(argv[0]) == 0) {
+ rank = kSCNetworkServicePrimaryRankDefault;
+ } else if ((strcasecmp(argv[0], "First") == 0)) {
+ rank = kSCNetworkServicePrimaryRankFirst;
+ } else if ((strcasecmp(argv[0], "Last") == 0)) {
+ rank = kSCNetworkServicePrimaryRankLast;
+ } else if ((strcasecmp(argv[0], "Never") == 0)) {
+ rank = kSCNetworkServicePrimaryRankNever;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("invalid rank\n"));
+ return -1;
+ }
+
+ interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
+ if (interfaceName == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
+ return FALSE;
+ }
+
+ store = SCDynamicStoreCreate(NULL, CFSTR("scutil --net"), NULL, NULL);
+ interface = _SCNetworkInterfaceCopyActive(store, interfaceName);
+ CFRelease(store);
+ if (interface == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("No active interface\n"));
+ return -1;
+ }
+
+ ok = SCNetworkInterfaceSetPrimaryRank(interface, rank);
+ CFRelease(interface);
+ if (!ok) {
+ SCPrint(TRUE, stdout, CFSTR("could not update per-interface rank\n"));
+ return -1;
+ }
+
+ return 1;
+}
+
+
+/* -------------------- */
+
+
static void
_replaceOne(const void *key, const void *value, void *context)
{
{ "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL },
{ "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL },
- { "?" , NULL , isHelp , NULL , NULL,
+ { "rank" , NULL, isOther , NULL , __doRank, NULL },
+
+ { "?" , NULL, isHelp , NULL , NULL,
"\nAirPort configuration commands\n\n"
" set interface [mtu n] [media type] [mediaopts opts]\n"
}
{ "tso" , NULL, isOther , &kSCPropNetEthernetCapabilityTSO , __doCapability, NULL },
{ "txcsum" , NULL, isOther , &kSCPropNetEthernetCapabilityTXCSUM, __doCapability, NULL },
- { "?" , NULL , isHelp , NULL , NULL,
+ { "rank" , NULL, isOther , NULL , __doRank, NULL },
+
+ { "?" , NULL, isHelp , NULL , NULL,
"\nEthernet configuration commands\n\n"
" set interface [mtu n] [media type] [mediaopts opts]\n"
}
encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetIPSecSharedSecretEncryption);
if (strlen(argv[0]) > 0) {
if (encryptionType == NULL) {
+#ifdef INLINE_PASSWORDS_USE_CFSTRING
+ CFStringRef pw;
+
+ pw = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+#else // INLINE_PASSWORDS_USE_CFSTRING
CFIndex n;
CFMutableDataRef pw;
CFStringRef str;
n = CFStringGetLength(str);
pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
CFDataSetLength(pw, n * sizeof(UniChar));
+ /* ALIGN: CF aligns to at least >8 bytes */
CFStringGetCharacters(str,
CFRangeMake(0, n),
- (UniChar *)CFDataGetMutableBytePtr(pw));
+ (UniChar *)(void *)CFDataGetMutableBytePtr(pw));
CFRelease(str);
+#endif // INLINE_PASSWORDS_USE_CFSTRING
CFDictionarySetValue(newConfiguration, key, pw);
CFRelease(pw);
encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetIPSecXAuthPasswordEncryption);
if (strlen(argv[0]) > 0) {
if (encryptionType == NULL) {
+#ifdef INLINE_PASSWORDS_USE_CFSTRING
+ CFStringRef pw;
+
+ pw = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+#else // INLINE_PASSWORDS_USE_CFSTRING
CFIndex n;
CFMutableDataRef pw;
CFStringRef str;
n = CFStringGetLength(str);
pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
CFDataSetLength(pw, n * sizeof(UniChar));
+ /* ALIGN: CF aligns to at least >8 byte boundries */
CFStringGetCharacters(str,
CFRangeMake(0, n),
- (UniChar *)CFDataGetMutableBytePtr(pw));
+ (UniChar *)(void *)CFDataGetMutableBytePtr(pw));
CFRelease(str);
+#endif // INLINE_PASSWORDS_USE_CFSTRING
CFDictionarySetValue(newConfiguration, key, pw);
CFRelease(pw);
}
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
__cleanupDomainName(CFStringRef domain)
{
CFMutableStringRef newDomain;
encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetPPPAuthPasswordEncryption);
if (strlen(argv[0]) > 0) {
if (encryptionType == NULL) {
+#ifdef INLINE_PASSWORDS_USE_CFSTRING
+ CFStringRef pw;
+
+ pw = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+#else // INLINE_PASSWORDS_USE_CFSTRING
CFIndex n;
CFMutableDataRef pw;
CFStringRef str;
n = CFStringGetLength(str);
pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
CFDataSetLength(pw, n * sizeof(UniChar));
+ /* ALIGN: CF aligns to at least >8 byte boundries */
CFStringGetCharacters(str,
CFRangeMake(0, n),
- (UniChar *)CFDataGetMutableBytePtr(pw));
+ (UniChar *)(void *)CFDataGetMutableBytePtr(pw));
CFRelease(str);
+#endif // INLINE_PASSWORDS_USE_CFSTRING
CFDictionarySetValue(newConfiguration, key, pw);
CFRelease(pw);
encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetVPNAuthPasswordEncryption);
if (strlen(argv[0]) > 0) {
if (encryptionType == NULL) {
-#ifdef USE_INLINE_CFDATA
+#ifdef INLINE_PASSWORDS_USE_CFSTRING
+ CFStringRef pw;
+
+ pw = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+#else // INLINE_PASSWORDS_USE_CFSTRING
CFIndex n;
CFMutableDataRef pw;
CFStringRef str;
CFDataSetLength(pw, n * sizeof(UniChar));
CFStringGetCharacters(str,
CFRangeMake(0, n),
- (UniChar *)CFDataGetMutableBytePtr(pw));
+ (UniChar *)(void *)CFDataGetMutableBytePtr(pw));
CFRelease(str);
-#else // USE_INLINE_CFDATA
- CFStringRef pw;
-
- pw = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
-#endif // USE_INLINE_CFDATA
+#endif // INLINE_PASSWORDS_USE_CFSTRING
CFDictionarySetValue(newConfiguration, key, pw);
CFRelease(pw);
__private_extern__
-CFStringRef
+CF_RETURNS_RETAINED CFStringRef
_interface_description(SCNetworkInterfaceRef interface)
{
CFMutableStringRef description;
/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__BEGIN_DECLS
+CF_RETURNS_RETAINED
CFStringRef _interface_description (SCNetworkInterfaceRef interface);
+
SCNetworkInterfaceRef _find_interface (int argc, char **argv, int *nArgs);
-void create_interface (int argc, char **argv);
-void select_interface (int argc, char **argv);
-void set_interface (int argc, char **argv);
-void show_interface (int argc, char **argv);
-void show_interfaces (int argc, char **argv);
+void create_interface (int argc, char **argv);
+void select_interface (int argc, char **argv);
+void set_interface (int argc, char **argv);
+void show_interface (int argc, char **argv);
+void show_interfaces (int argc, char **argv);
__END_DECLS
/*
- * Copyright (c) 2004-2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
char buf[128];
struct sockaddr_in sin;
- bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
- if (inet_aton(arg, &sin.sin_addr) != 1) {
+ if (_SC_string_to_sockaddr(arg, AF_INET, (void *)&sin, sizeof(sin)) == NULL) {
return NULL;
}
__copyIPv6Address(const char *arg)
{
char buf[128];
- char *p;
struct sockaddr_in6 sin6;
- bzero(&sin6, sizeof(sin6));
- sin6.sin6_len = sizeof(sin6);
- sin6.sin6_family = AF_INET6;
- if (inet_pton(AF_INET6, arg, &sin6.sin6_addr) != 1) {
+ if (_SC_string_to_sockaddr(arg, AF_INET6, (void *)&sin6, sizeof(sin6)) == NULL) {
return NULL;
}
- p = strchr(arg, '%');
- if (p != NULL) {
- sin6.sin6_scope_id = if_nametoindex(p + 1);
- }
-
_SC_sockaddr_to_string((struct sockaddr *)&sin6, buf, sizeof(buf));
return CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
}
#pragma mark DNS
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
__cleanupDomainName(CFStringRef domain)
{
CFMutableStringRef newDomain;
!CFNumberGetValue(num, kCFNumberIntType, &port) ||
(port < 0) || (port > 65535)) {
SCPrint(TRUE, stdout, CFSTR("invalid %s proxy port number\n"), currentProxy->proxy);
+ if (num != NULL) CFRelease(num);
return -1;
}
#if !TARGET_OS_IPHONE
-static CFStringRef
+static CF_RETURNS_RETAINED CFStringRef
__cleanupName(CFStringRef name)
{
CFMutableStringRef newName;
__private_extern__
-CFStringRef
+CF_RETURNS_RETAINED CFStringRef
_protocol_description(SCNetworkProtocolRef protocol, Boolean skipEmpty)
{
CFDictionaryRef configuration;
/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004, 2011 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__BEGIN_DECLS
CFComparisonResult _compare_protocols (const void *val1, const void *val2, void *context);
+
+CF_RETURNS_RETAINED
CFStringRef _protocol_description (SCNetworkProtocolRef protocol, Boolean skipEmpty);
-void create_protocol (int argc, char **argv);
-void disable_protocol (int argc, char **argv);
-void enable_protocol (int argc, char **argv);
-void remove_protocol (int argc, char **argv);
-void select_protocol (int argc, char **argv);
-void set_protocol (int argc, char **argv);
-void show_protocol (int argc, char **argv);
-void show_protocols (int argc, char **argv);
+void create_protocol (int argc, char **argv);
+void disable_protocol (int argc, char **argv);
+void enable_protocol (int argc, char **argv);
+void remove_protocol (int argc, char **argv);
+void select_protocol (int argc, char **argv);
+void set_protocol (int argc, char **argv);
+void show_protocol (int argc, char **argv);
+void show_protocols (int argc, char **argv);
__END_DECLS
/*
- * Copyright (c) 2000-2004, 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/time.h>
#include <sys/un.h>
#include <unistd.h>
static struct sigaction *oact = NULL;
+static char *
+elapsed()
+{
+ int n;
+ static char str[128];
+ struct tm tm_diff;
+ struct tm tm_now;
+ struct timeval tv_diff;
+ struct timeval tv_now;
+ static struct timeval tv_then = { 0, 0 };
+
+ (void)gettimeofday(&tv_now, NULL);
+
+ (void)localtime_r(&tv_now.tv_sec, &tm_now);
+
+ timersub(&tv_now, &tv_then, &tv_diff);
+ (void)localtime_r(&tv_diff.tv_sec, &tm_diff);
+ n = snprintf(str, sizeof(str), "%2d:%02d:%02d.%03d",
+ tm_now.tm_hour,
+ tm_now.tm_min,
+ tm_now.tm_sec,
+ tv_now.tv_usec / 1000);
+ if (((tv_then.tv_sec != 0) || (tv_then.tv_usec != 0)) && (n < sizeof(str))) {
+ snprintf(&str[n], sizeof(str) - n, " (+%ld.%03d)",
+ tv_diff.tv_sec,
+ tv_diff.tv_usec / 1000);
+ }
+
+ tv_then = tv_now;
+ return str;
+}
+
+
static CFComparisonResult
sort_keys(const void *p1, const void *p2, void *context) {
CFStringRef key1 = (CFStringRef)p1;
for (i = 0; i < n; i++) {
SCPrint(TRUE,
stdout,
- CFSTR(" changed key [%d] = %@\n"),
+ CFSTR(" %s changedKey [%d] = %@\n"),
+ elapsed(),
i,
CFArrayGetValueAtIndex(changedKeys, i));
}
for (i = 0; i < listCnt; i++) {
SCPrint(TRUE,
stdout,
- CFSTR(" changedKey [%d] = %@\n"),
+ CFSTR(" %s changedKey [%d] = %@\n"),
+ elapsed(),
i,
CFArrayGetValueAtIndex(list, i));
}
}
-static boolean_t
-notificationWatcher(SCDynamicStoreRef store, void *arg)
-{
- SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
- SCPrint(TRUE, stdout, CFSTR(" arg = %s.\n"), (char *)arg);
- return TRUE;
-}
-
-
-static boolean_t
-notificationWatcherVerbose(SCDynamicStoreRef store, void *arg)
-{
- SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
- SCPrint(TRUE, stdout, CFSTR(" arg = %s.\n"), (char *)arg);
- do_notify_changes(0, NULL); /* report the keys that changed */
- return TRUE;
-}
-
-
-static void *
-_callback(void *arg)
-{
- SCDynamicStoreCallBack_v1 func = (SCDynamicStoreCallBack_v1)arg;
-
- notifyRl = CFRunLoopGetCurrent();
- if (notifyRl == NULL) {
- SCPrint(TRUE, stdout, CFSTR(" CFRunLoopGetCurrent() failed\n"));
- return NULL;
- }
-
- if (!SCDynamicStoreNotifyCallback(store, notifyRl, func, "Changed detected by callback handler!")) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- notifyRl = NULL;
- return NULL;
- }
-
- pthread_setname_np("n.callback");
- CFRunLoopRun();
- notifyRl = NULL;
- return NULL;
-}
-
-
-__private_extern__
-void
-do_notify_callback(int argc, char **argv)
-{
- SCDynamicStoreCallBack_v1 func = notificationWatcher;
- pthread_attr_t tattr;
- pthread_t tid;
-
- if (notifyRl != NULL) {
- SCPrint(TRUE, stdout, CFSTR("already active\n"));
- return;
- }
-
- if ((argc == 1) && (strcmp(argv[0], "verbose") == 0)) {
- func = notificationWatcherVerbose;
- }
-
- pthread_attr_init(&tattr);
- pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
- pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
-// pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack
- pthread_create(&tid, &tattr, _callback, (void *)func);
- pthread_attr_destroy(&tattr);
-
- return;
-}
-
-
__private_extern__
void
do_notify_file(int argc, char **argv)
/*
- * Copyright (c) 2000, 2001, 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2004, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
void do_notify_changes (int argc, char **argv);
void do_notify_watch (int argc, char **argv);
void do_notify_wait (int argc, char **argv);
-void do_notify_callback (int argc, char **argv);
void do_notify_signal (int argc, char **argv);
void do_notify_file (int argc, char **argv);
void do_notify_cancel (int argc, char **argv);
__loadSecurity(void) {
static void *image = NULL;
if (NULL == image) {
- const char *framework = "/System/Library/Frameworks/Security.framework/Versions/A/Security";
+ const char *framework = "/System/Library/Frameworks/Security.framework/Security";
struct stat statbuf;
const char *suffix = getenv("DYLD_IMAGE_SUFFIX");
char path[MAXPATHLEN];
#if !TARGET_OS_IPHONE
authorization = _createAuthorization();
+#else
+ authorization = (AuthorizationRef)kSCPreferencesUseEntitlementAuthorization;
#endif /* !TARGET_OS_IPHONE */
}
/*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
{ "dns", no_argument, NULL, 0 },
{ "get", required_argument, NULL, 0 },
{ "help", no_argument, NULL, '?' },
+ { "nc", required_argument, NULL, 0 },
{ "net", no_argument, NULL, 0 },
+ { "nwi", no_argument, NULL, 0 },
{ "prefs", no_argument, NULL, 0 },
{ "proxy", no_argument, NULL, 0 },
{ "set", required_argument, NULL, 0 },
- { "nc", required_argument, NULL, 0 },
+ { "snapshot", no_argument, NULL, 0 },
+ { "user", required_argument, NULL, 0 },
+ { "password", required_argument, NULL, 0 },
+ { "secret", required_argument, NULL, 0 },
{ NULL, 0, NULL, 0 }
};
SCPrint(TRUE, stderr, CFSTR("\n"));
SCPrint(TRUE, stderr, CFSTR(" or: %s --proxy\n"), command);
SCPrint(TRUE, stderr, CFSTR("\tshow \"proxy\" configuration.\n"));
+ SCPrint(TRUE, stderr, CFSTR("\n"));
+ SCPrint(TRUE, stderr, CFSTR(" or: %s --nwi\n"), command);
+ SCPrint(TRUE, stderr, CFSTR("\tshow network information\n"));
if (getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) {
SCPrint(TRUE, stderr, CFSTR("\n"));
{
Boolean doDNS = FALSE;
Boolean doNet = FALSE;
+ Boolean doNWI = FALSE;
Boolean doPrefs = FALSE;
Boolean doProxy = FALSE;
Boolean doReach = FALSE;
+ Boolean doSnap = FALSE;
char *get = NULL;
extern int optind;
int opt;
} else if (strcmp(longopts[opti].name, "get") == 0) {
get = optarg;
xStore++;
+ } else if (strcmp(longopts[opti].name, "nc") == 0) {
+ nc_cmd = optarg;
+ xStore++;
} else if (strcmp(longopts[opti].name, "net") == 0) {
doNet = TRUE;
xStore++;
+ } else if (strcmp(longopts[opti].name, "nwi") == 0) {
+ doNWI = TRUE;
+ xStore++;
} else if (strcmp(longopts[opti].name, "prefs") == 0) {
doPrefs = TRUE;
xStore++;
} else if (strcmp(longopts[opti].name, "set") == 0) {
set = optarg;
xStore++;
- } else if (strcmp(longopts[opti].name, "nc") == 0) {
- nc_cmd = optarg;
+ } else if (strcmp(longopts[opti].name, "snapshot") == 0) {
+ doSnap = TRUE;
xStore++;
+ } else if (strcmp(longopts[opti].name, "user") == 0) {
+ username = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
+ } else if (strcmp(longopts[opti].name, "password") == 0) {
+ password = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
+ } else if (strcmp(longopts[opti].name, "secret") == 0) {
+ sharedsecret = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
}
break;
case '?':
/* NOT REACHED */
}
+ if (doNWI) {
+ do_nwi(argc, (char**)argv);
+ /* NOT REACHED */
+ }
+
+ if (doSnap) {
+ if (!enablePrivateAPI || (geteuid() != 0)) {
+ usage(prog);
+ }
+
+ do_open(0, NULL); /* open the dynamic store */
+ do_snapshot(argc, (char**)argv);
+ exit(0);
+ }
+
/* are we looking up a preference value */
if (get) {
if (findPref(get) < 0) {
/*
- * Copyright (c) 2000-2004, 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2004, 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*/
#include "scutil.h"
+#include "cache.h"
#include "session.h"
#include "notifications.h"
watchedKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
watchedPatterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ cache_close();
+
return;
}
CFRelease(watchedPatterns);
watchedPatterns = NULL;
}
- return;
-}
+ cache_close();
-__private_extern__
-void
-do_lock(int argc, char **argv)
-{
- if (!SCDynamicStoreLock(store)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- }
- return;
-}
-
-
-__private_extern__
-void
-do_unlock(int argc, char **argv)
-{
- if (!SCDynamicStoreUnlock(store)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- }
return;
}
/*
- * Copyright (c) 2000, 2001 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
void do_open (int argc, char **argv);
void do_close (int argc, char **argv);
-void do_lock (int argc, char **argv);
-void do_unlock (int argc, char **argv);
__END_DECLS
/*
- * Copyright (c) 2000, 2001, 2003-2005, 2007-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2003-2005, 2007-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <arpa/inet.h>
#include <dnsinfo.h>
+#include <network_information.h>
+#include "SCNetworkReachabilityInternal.h"
+
+static Boolean resolver_bypass;
+
+static CF_RETURNS_RETAINED CFMutableDictionaryRef
+_setupReachabilityOptions(int argc, char **argv, const char *interface)
+{
+ CFMutableDictionaryRef options;
+
+ options = CFDictionaryCreateMutable(NULL,
+ 0,
+ &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;
+ }
+
+
+ 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], "no-resolve") == 0) {
+ CFDictionarySetValue(options,
+ kSCNetworkReachabilityOptionResolverBypass,
+ kCFBooleanTrue);
+ resolver_bypass = TRUE;
+ 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 (n_hints > 0) {
+ CFDataRef data;
+
+ data = CFDataCreate(NULL, (const UInt8 *)&hints, sizeof(hints));
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionHints, data);
+ CFRelease(data);
+ }
+ }
+
+ if (interface != NULL) {
+ CFStringRef str;
+
+ if (if_nametoindex(interface) == 0) {
+ SCPrint(TRUE, stderr, CFSTR("No interface: %s\n"), interface);
+ exit(1);
+ }
+
+ str = CFStringCreateWithCString(NULL, interface, kCFStringEncodingASCII);
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionInterface, str);
+ CFRelease(str);
+ }
+
+ if (CFDictionaryGetCount(options) == 0) {
+ CFRelease(options);
+ options = NULL;
+ }
+
+ return options;
+}
+
static SCNetworkReachabilityRef
_setupReachability(int argc, char **argv, SCNetworkReachabilityContext *context)
{
char *ip_address = argv[0];
const char *interface;
+ CFMutableDictionaryRef options = NULL;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
- SCNetworkReachabilityRef target = NULL;
+ SCNetworkReachabilityRef target = NULL;
bzero(&sin, sizeof(sin));
sin.sin_len = sizeof(sin);
}
if (inet_aton(ip_address, &sin.sin_addr) == 1) {
- if (argc == 1) {
- if (interface == NULL) {
+ if ((argc == 1) ||
+ ((argc > 1) && (strlen(argv[1]) == 0))) {
+ options = _setupReachabilityOptions(argc, argv, interface);
+ if (options == NULL) {
target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin);
if (context != NULL) {
context->info = "by address";
}
} else {
- CFDataRef data;
- CFStringRef str;
- CFMutableDictionaryRef options;
+ CFDataRef data;
- if (if_nametoindex(interface) == 0) {
- SCPrint(TRUE, stderr, CFSTR("No interface: %s\n"), interface);
- exit(1);
- }
-
- options = CFDictionaryCreateMutable(NULL,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
data = CFDataCreate(NULL, (const UInt8 *)&sin, sizeof(sin));
CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
CFRelease(data);
- str = CFStringCreateWithCString(NULL, interface, kCFStringEncodingASCII);
- CFDictionarySetValue(options, kSCNetworkReachabilityOptionInterface, str);
- CFRelease(str);
- target = SCNetworkReachabilityCreateWithOptions(NULL, options);
+
if (context != NULL) {
- context->info = "by address w/scope";
+ if (CFDictionaryContainsKey(options,
+ kSCNetworkReachabilityOptionInterface)) {
+ if (CFDictionaryGetCount(options) == 2) {
+ context->info = "by address w/scope";
+ } else {
+ context->info = "by address w/scope and options";
+ }
+ } else {
+ context->info = "by address w/options";
+ }
}
- CFRelease(options);
}
} else {
char *remote_address = argv[1];
free(remote_address);
}
- if (interface == NULL) {
+ options = _setupReachabilityOptions(argc, argv, interface);
+ if (options == NULL) {
target = SCNetworkReachabilityCreateWithAddressPair(NULL,
(struct sockaddr *)&sin,
(struct sockaddr *)&r_sin);
context->info = "by address pair";
}
} else {
- CFDataRef data;
- CFStringRef str;
- CFMutableDictionaryRef options;
-
- if (if_nametoindex(interface) == 0) {
- SCPrint(TRUE, stderr, CFSTR("No interface: %s\n"), interface);
- exit(1);
- }
+ CFDataRef data;
- options = CFDictionaryCreateMutable(NULL,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
data = CFDataCreate(NULL, (const UInt8 *)&sin, sizeof(sin));
CFDictionarySetValue(options, kSCNetworkReachabilityOptionLocalAddress, data);
CFRelease(data);
data = CFDataCreate(NULL, (const UInt8 *)&r_sin, sizeof(r_sin));
CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
CFRelease(data);
- str = CFStringCreateWithCString(NULL, interface, kCFStringEncodingASCII);
- CFDictionarySetValue(options, kSCNetworkReachabilityOptionInterface, str);
- CFRelease(str);
- target = SCNetworkReachabilityCreateWithOptions(NULL, options);
+
if (context != NULL) {
- context->info = "by address pair w/scope";
+ if (CFDictionaryContainsKey(options,
+ kSCNetworkReachabilityOptionInterface)) {
+ if (CFDictionaryGetCount(options) == 3) {
+ context->info = "by address pair w/scope";
+ } else {
+ context->info = "by address pair w/scope and options";
+ }
+ } else {
+ context->info = "by address pair w/options";
+ }
}
- CFRelease(options);
}
}
} else if (inet_pton(AF_INET6, argv[0], &sin6.sin6_addr) == 1) {
sin6.sin6_scope_id = if_nametoindex(interface);
}
- if (argc == 1) {
- target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin6);
- if (context != NULL) {
- context->info = "by (v6) address";
+ if ((argc == 1) ||
+ ((argc > 1) && (strlen(argv[1]) == 0))) {
+ options = _setupReachabilityOptions(argc, argv, NULL);
+ if (options == NULL) {
+ target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin6);
+ if (context != NULL) {
+ context->info = "by (v6) address";
+ }
+ } else {
+ CFDataRef data;
+
+ data = CFDataCreate(NULL, (const UInt8 *)&sin6, sizeof(sin6));
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
+ CFRelease(data);
+
+ if (context != NULL) {
+ context->info = "by (v6) address w/options";
+ }
}
} else {
struct sockaddr_in6 r_sin6;
r_sin6.sin6_scope_id = if_nametoindex(interface);
}
- target = SCNetworkReachabilityCreateWithAddressPair(NULL,
- (struct sockaddr *)&sin6,
- (struct sockaddr *)&r_sin6);
- if (context != NULL) {
- context->info = "by (v6) address pair";
+ options = _setupReachabilityOptions(argc, argv, NULL);
+ if (options == NULL) {
+ target = SCNetworkReachabilityCreateWithAddressPair(NULL,
+ (struct sockaddr *)&sin6,
+ (struct sockaddr *)&r_sin6);
+ if (context != NULL) {
+ context->info = "by (v6) address pair";
+ }
+ } else {
+ CFDataRef data;
+
+ data = CFDataCreate(NULL, (const UInt8 *)&sin6, sizeof(sin6));
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionLocalAddress, data);
+ CFRelease(data);
+ data = CFDataCreate(NULL, (const UInt8 *)&r_sin6, sizeof(r_sin6));
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, data);
+ CFRelease(data);
+
+ if (context != NULL) {
+ context->info = "by (v6) address pair w/options";
+ }
}
}
} else {
- if (argc == 1) {
- target = SCNetworkReachabilityCreateWithName(NULL, argv[0]);
- if (context != NULL) {
- context->info = "by name";
+ 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 (options == NULL) {
+ target = SCNetworkReachabilityCreateWithName(NULL, argv[0]);
+ if (context != NULL) {
+ context->info = "by name";
+ }
+ } else {
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
+ CFRelease(str);
+
+ if (context != NULL) {
+ context->info = "by name w/options";
+ }
}
} else {
- CFStringRef str;
- CFMutableDictionaryRef options;
+ CFIndex n_options;
+
+ if (options == NULL) {
+ options = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+ n_options = CFDictionaryGetCount(options);
- options = CFDictionaryCreateMutable(NULL,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
if (strlen(argv[0]) > 0) {
str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
CFDictionarySetValue(options, kSCNetworkReachabilityOptionNodeName, str);
CFDictionarySetValue(options, kSCNetworkReachabilityOptionServName, str);
CFRelease(str);
}
- if (argc > 2) {
- CFDataRef data;
- struct addrinfo hints = { 0 };
- int i;
- int n_hints = 0;
-
- 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);
- }
- if (if_nametoindex(argv[i]) == 0) {
- SCPrint(TRUE, stderr, CFSTR("No interface: %s\n"), argv[i]);
- CFRelease(options);
- exit(1);
- }
- str = CFStringCreateWithCString(NULL, argv[i], kCFStringEncodingASCII);
- CFDictionarySetValue(options, kSCNetworkReachabilityOptionInterface, str);
- CFRelease(str);
- 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;
+ if (CFDictionaryGetCount(options) > n_options) {
+ if (context != NULL) {
+ if (n_options == 0) {
+ context->info = "by (node and/or serv) name";
} else {
- SCPrint(TRUE, stderr, CFSTR("Unrecognized hint: %s\n"), argv[i]);
- CFRelease(options);
- exit(1);
+ context->info = "by (node and/or serv) name w/options";
}
- n_hints++;
- }
-
- if (n_hints > 0) {
- data = CFDataCreate(NULL, (const UInt8 *)&hints, sizeof(hints));
- CFDictionarySetValue(options, kSCNetworkReachabilityOptionHints, data);
- CFRelease(data);
- }
- }
- if (CFDictionaryGetCount(options) > 0) {
- target = SCNetworkReachabilityCreateWithOptions(NULL, options);
- if (context != NULL) {
- context->info = "by (node and/or serv) name";
}
} else {
SCPrint(TRUE, stderr, CFSTR("Must specify nodename or servname\n"));
CFRelease(options);
exit(1);
}
- CFRelease(options);
}
}
free(ip_address);
}
+ if ((target == NULL) && (options != NULL)) {
+ target = SCNetworkReachabilityCreateWithOptions(NULL, options);
+ CFRelease(options);
+ }
+
return target;
}
static void
-_printReachability(SCNetworkReachabilityRef target)
+_printReachabilityFlags(SCNetworkReachabilityFlags flags)
{
- SCNetworkReachabilityFlags flags;
- Boolean ok;
-
- ok = SCNetworkReachabilityGetFlags(target, &flags);
- if (!ok) {
- printf(" could not determine reachability, %s\n", SCErrorString(SCError()));
- return;
- }
-
- SCPrint(_sc_debug, stdout, CFSTR("flags = 0x%08x"), flags);
if (flags != 0) {
- SCPrint(_sc_debug, stdout, CFSTR(" ("));
if (flags & kSCNetworkReachabilityFlagsReachable) {
SCPrint(TRUE, stdout, CFSTR("Reachable"));
flags &= ~kSCNetworkReachabilityFlagsReachable;
if (flags != 0) {
SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags);
}
- SCPrint(_sc_debug, stdout, CFSTR(")"));
} else {
- SCPrint(_sc_debug, stdout, CFSTR(" ("));
SCPrint(TRUE, stdout, CFSTR("Not Reachable"));
- SCPrint(_sc_debug, stdout, CFSTR(")"));
}
+
+ return;
+}
+
+static void
+_printReachability(SCNetworkReachabilityRef target)
+{
+ SCNetworkReachabilityFlags flags;
+ Boolean ok;
+
+ ok = SCNetworkReachabilityGetFlags(target, &flags);
+ if (!ok) {
+ printf(" 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(")"));
+
+ if (resolver_bypass) {
+ int if_index =
+ SCNetworkReachabilityGetInterfaceIndex(target);
+ SCPrint(_sc_debug, stdout, CFSTR("interface index = %d"), if_index);
+ }
+
SCPrint(TRUE, stdout, CFSTR("\n"));
return;
}
+static void
+_printNWIFlags(nwi_ifstate_flags flags)
+{
+ 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 != 0) {
+ SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags);
+ }
+ SCPrint(TRUE, stdout, CFSTR(")"));
+
+ return;
+}
+
+
+__private_extern__
+void
+do_nwi(int argc, char **argv)
+{
+ nwi_ifstate_t ifstate;
+ nwi_state_t state = nwi_state_copy();
+
+ if (state == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("No network information\n"));
+ exit(1);
+ }
+
+ 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"));
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("No network information (for %s)\n"), argv[0]);
+ }
+
+ goto done;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("Network information\n"));
+ 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"));
+ }
+
+ while (ifstate != NULL) {
+ nwi_ifstate_flags flags = nwi_ifstate_get_flags(ifstate);
+
+ 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);
+ }
+
+ 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"));
+ }
+
+ while (ifstate != NULL) {
+ nwi_ifstate_flags flags = nwi_ifstate_get_flags(ifstate);
+
+ 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);
+ }
+
+ done :
+
+ nwi_state_release(state);
+ exit(0);
+}
+
+
static void
callout(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
{
// 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()
+ // To test the case were an application first calls SCNetworkReachabilityGetFlags()
// we provide the "CHECK_REACHABILITY_BEFORE_SCHEDULING" environment variable.
if (getenv("CHECK_REACHABILITY_BEFORE_SCHEDULING") != NULL) {
CFRelease(target_async);
// schedule the target
SCPrint(TRUE, stdout, CFSTR(" 1: start\n"));
SCPrint(TRUE, stdout, CFSTR(" %@\n"), target_async);
- //_printReachability(target_async);
+// _printReachability(target_async);
SCPrint(TRUE, stdout, CFSTR("\n"));
if (!SCNetworkReachabilitySetCallback(target_async, callout, &context)) {
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;
if (flags != 0) {
SCPrint(TRUE, stdout, CFSTR("0x%08x"), flags);
}
+ SCPrint(_sc_debug, stdout, CFSTR(")"));
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+ }
+
+ 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"));
}
void
do_showDNSConfiguration(int argc, char **argv)
{
- dns_config_t *dns_config;
+ dns_config_t *dns_config;
+ SCNetworkReachabilityRef target;
dns_config = dns_configuration_copy();
- if (dns_config) {
+
+ if (dns_config == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("No DNS configuration available\n"));
+ 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"));
showResolver(resolver, i + 1);
}
}
-
- dns_configuration_free(dns_config);
- } else {
- SCPrint(TRUE, stdout, CFSTR("No DNS configuration available\n"));
}
+ dns_configuration_free(dns_config);
exit(0);
}
if (!SCDynamicStoreSnapshot(store)) {
SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
}
+
+#ifdef HAVE_REACHABILITY_SERVER
+ (void) _SCNetworkReachabilityServer_snapshot();
+#endif // HAVE_REACHABILITY_SERVER
+
return;
}
/*
- * Copyright (c) 2000, 2001, 2004, 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2001, 2004, 2007, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
void do_showProxyConfiguration (int argc, char **argv);
void do_snapshot (int argc, char **argv);
void do_wait (char *waitKey, int timeout);
+void do_nwi (int argc, char **argv);
__END_DECLS