#ifndef CONFIGAGENTDEFINES_H
#define CONFIGAGENTDEFINES_H
-#define kConfigAgentDomain "SystemConfig"
+#import "config_agent_info.h"
+
#define kConfigAgentType "AgentType"
#define kConfigAgentTypeGeneric "ConfigAgent"
-#define kConfigAgentTypeProxy "ProxyAgent"
-#define kConfigAgentTypeDNS "DNSAgent"
#define kConfigAgentTypeDNSMulticast kConfigAgentTypeDNS "(m)"
#define kConfigAgentTypeDNSPrivate kConfigAgentTypeDNS "(p)"
- (NSData *)dataForProxyArray:(CFArrayRef)proxy_array_for_data
{
- NSData *data = [NSPropertyListSerialization dataWithPropertyList:(__bridge id _Nonnull)(proxy_array_for_data)
- format:NSPropertyListBinaryFormat_v1_0
- options:0
- error:nil];
-
- return data;
+ CFDataRef data = NULL;
+ (void)_SCSerialize(proxy_array_for_data, &data, NULL, NULL);
+ return (__bridge_transfer NSData *)data;
}
- (NSData *)dataForProxyDictionary:(CFDictionaryRef)domain_proxy
{
NSData * data = nil;
CFMutableDictionaryRef domain_proxy_dict;
- CFArrayRef domain_proxy_array;
if (domain_proxy == NULL) {
SC_log(LOG_NOTICE, "Invalid domain proxy dict");
domain_proxy_dict = CFDictionaryCreateMutableCopy(NULL, 0, domain_proxy);
CFDictionaryRemoveValue(domain_proxy_dict, kSCPropNetProxiesSupplementalMatchDomain);
- domain_proxy_array = CFArrayCreate(NULL, (const void **)&domain_proxy_dict, 1, &kCFTypeArrayCallBacks);
+ data = (__bridge_transfer NSData *)(SCNetworkProxiesCreateProxyAgentData(domain_proxy_dict));
CFRelease(domain_proxy_dict);
- data = [self dataForProxyArray:domain_proxy_array];
- CFRelease(domain_proxy_array);
-
return data;
}
/*
- * Copyright (c) 2004-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFIndex i;
CFIndex n_domains;
CFArrayRef orders;
+ CFArrayRef servers;
domains = CFDictionaryGetValue(dns, kSCPropNetDNSSupplementalMatchDomains);
n_domains = isA_CFArray(domains) ? CFArrayGetCount(domains) : 0;
if (n_domains == 0) {
+ // if no supplemental match domains
return;
}
orders = CFDictionaryGetValue(dns, kSCPropNetDNSSupplementalMatchOrders);
if (orders != NULL) {
if (!isA_CFArray(orders) || (n_domains != CFArrayGetCount(orders))) {
+ // if supplemental match orders... but too many/not enough
return;
}
}
+ servers = CFDictionaryGetValue(dns, kSCPropNetDNSServerAddresses);
+ if (!isA_CFArray(servers) || (CFArrayGetCount(servers) == 0)) {
+ // if no DNS server addresses
+ return;
+ }
+
/*
* yes, this is a "supplemental" resolver configuration, expand
* the match domains and add each to the resolvers list.
CFArrayRef searchDomains;
CFDictionaryRef service;
CFStringRef serviceID;
+ CFArrayRef servers;
serviceID = CFArrayGetValueAtIndex(order, i);
service = CFDictionaryGetValue(services, serviceID);
continue;
}
+ servers = CFDictionaryGetValue(dns, kSCPropNetDNSServerAddresses);
+ if (!isA_CFArray(servers) || (CFArrayGetCount(servers) == 0)) {
+ // if no DNS server addresses
+ continue;
+ }
+
interface = CFDictionaryGetValue(dns, kSCPropInterfaceName);
if ((interface == NULL) || CFEqual(interface, CFSTR("*"))) {
// if no [scoped] interface or supplemental configuration w/match-all
// add the "default" resolver
+ if (defaultResolver != NULL) {
+ CFArrayRef servers;
+
+ servers = CFDictionaryGetValue(defaultResolver, kSCPropNetDNSServerAddresses);
+ if (!isA_CFArray(servers) || (CFArrayGetCount(servers) == 0)) {
+ // if no DNS server addresses
+ defaultResolver = NULL;
+ }
+ }
+
add_default_resolver(resolvers, defaultResolver, &myOrderAdded, &mySearchDomains);
// collect (and add) any "multicast" resolver configurations
/*
- * Copyright (c) 2000-2016 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2000-2017 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
return (comp);
}
-__private_extern__ boolean_t
-service_contains_protocol(CFDictionaryRef service, int af)
+
+static boolean_t
+entity_routes_protocol(CFDictionaryRef entity_dict)
{
- boolean_t contains_protocol = FALSE;
- CFStringRef entity;
RouteListRef routes;
- CFDictionaryRef dict;
- entity = (af == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6;
- dict = CFDictionaryGetValue(service, entity);
- if (dict == NULL) {
- goto done;
- }
- routes = ipdict_get_routelist(dict);
+ routes = ipdict_get_routelist(entity_dict);
if (routes == NULL) {
- goto done;
+ // if no routes
+ return FALSE;
+ }
+
+ if ((routes->flags & kRouteListFlagsHasDefault) == 0) {
+ // if service has no default route
+ return FALSE;
}
+
if ((routes->flags & kRouteListFlagsExcludeNWI) != 0) {
- goto done;
+ // if service should be excluded from NWI
+ return FALSE;
}
- contains_protocol = TRUE;
- done:
- return (contains_protocol);
+ return TRUE;
+}
+
+
+__private_extern__ boolean_t
+service_contains_protocol(CFDictionaryRef service_dict, int af)
+{
+ boolean_t contains_protocol;
+ CFStringRef entity;
+ CFDictionaryRef entity_dict;
+
+ entity = (af == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6;
+ entity_dict = CFDictionaryGetValue(service_dict, entity);
+ if (entity_dict == NULL) {
+ return FALSE;
+ }
+
+ contains_protocol = entity_routes_protocol(entity_dict);
+ return contains_protocol;
}
if (((proto == kProtocolFlagsIPv4) && (v4_n == 1)) ||
((proto == kProtocolFlagsIPv6) && (v6_n == 1))) {
/* if we now have the 1st server address of another protocol */
- favor_v4 = (sa_dst_compare_no_stats((struct sockaddr *)&v4_dns1,
- (struct sockaddr *)&v6_dns1,
- 0) >= 0);
+ favor_v4 = (sa_dst_compare_no_dependencies((struct sockaddr *)&v4_dns1,
+ (struct sockaddr *)&v6_dns1) >= 0);
#ifdef TEST_DNS_ORDER
char v4_buf[INET_ADDRSTRLEN];
char v6_buf[INET6_ADDRSTRLEN];
}
ipv4 = service_dict_get(serviceID, kSCEntNetIPv4);
- if (ipv4 != NULL) {
+ if (entity_routes_protocol(ipv4)) {
if (get_service_setup_entity(info, serviceID, kSCEntNetIPv4) != NULL) {
have_setup = TRUE;
}
}
ipv6 = service_dict_get(serviceID, kSCEntNetIPv6);
- if (ipv6 != NULL) {
- if (!have_setup
- && (get_service_setup_entity(info, serviceID, kSCEntNetIPv6)
- != NULL)) {
+ if (entity_routes_protocol(ipv6)) {
+ if (!have_setup &&
+ (get_service_setup_entity(info, serviceID, kSCEntNetIPv6) != NULL)) {
have_setup = TRUE;
}
active_protos |= kProtocolFlagsIPv6;
goto done;
}
ipv4 = service_dict_get(serviceID, kSCEntNetIPv4);
- if (ipdict_get_routelist(ipv4) != NULL) {
+ if (entity_routes_protocol(ipv4)) {
active_protos |= kProtocolFlagsIPv4;
interface = ipdict_get_ifname(ipv4);
}
ipv6 = service_dict_get(serviceID, kSCEntNetIPv6);
- if (ipdict_get_routelist(ipv6) != NULL) {
+ if (entity_routes_protocol(ipv6)) {
active_protos |= kProtocolFlagsIPv6;
if (interface == NULL) {
interface = ipdict_get_ifname(ipv6);
/*
- * Copyright (c) 2012-2016 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2012-2017 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
my_if_indextoname(unsigned int idx, char if_name[IFNAMSIZ]);
boolean_t
-service_contains_protocol(CFDictionaryRef service, int af);
+service_contains_protocol(CFDictionaryRef service_dict, int af);
boolean_t
-service_is_scoped_only(CFDictionaryRef service);
+service_is_scoped_only(CFDictionaryRef service_dict);
boolean_t
check_if_service_expensive(CFStringRef serviceID);
/*
- * Copyright (c) 2001-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2001-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <SystemConfiguration/SCPrivate.h>
#include <SystemConfiguration/SCValidation.h>
#include "plugin_shared.h"
+#if !TARGET_OS_IPHONE
+#include "InterfaceNamerControlPrefs.h"
+#endif // !TARGET_OS_IPHONE
#include <IOKit/IOKitLib.h>
#include <IOKit/IOKitLibPrivate.h>
+#include <IOKit/IOKitKeysPrivate.h>
#include <IOKit/IOBSD.h>
#include <IOKit/IOMessage.h>
#include <IOKit/network/IONetworkController.h>
return n;
}
+#if !TARGET_OS_IPHONE
+static boolean_t
+blockNewInterfaces()
+{
+ static boolean_t allow = TRUE;
+ static dispatch_once_t once;
+
+ dispatch_once(&once, ^{
+ allow = InterfaceNamerControlPrefsAllowNewInterfaces();
+ });
+
+ return !allow;
+}
+
+
+static boolean_t
+isConsoleLocked()
+{
+ CFArrayRef console_sessions;
+ boolean_t locked = FALSE;
+ io_registry_entry_t root;
+
+ root = IORegistryGetRootEntry(kIOMasterPortDefault);
+ console_sessions = IORegistryEntryCreateCFProperty(root,
+ CFSTR(kIOConsoleUsersKey),
+ NULL,
+ 0);
+ if (isA_CFArray(console_sessions)) {
+ CFIndex n;
+
+ n = CFArrayGetCount(console_sessions);
+ for (CFIndex i = 0; i < n; i++) {
+ CFBooleanRef isLocked;
+ CFBooleanRef isLoginDone;
+ CFBooleanRef onConsole;
+ CFDictionaryRef session;
+
+ session = CFArrayGetValueAtIndex(console_sessions, i);
+ if (!isA_CFDictionary(session)) {
+ // if not dictionary
+ continue;
+ }
+
+ if (!CFDictionaryGetValueIfPresent(session,
+ CFSTR(kIOConsoleSessionOnConsoleKey),
+ (const void **)&onConsole) ||
+ !isA_CFBoolean(onConsole) ||
+ !CFBooleanGetValue(onConsole)) {
+ // if not "on console" session
+ continue;
+ }
+
+ if ((n > 1) &&
+ CFDictionaryGetValueIfPresent(session,
+ CFSTR(kIOConsoleSessionLoginDoneKey),
+ (const void **)&isLoginDone) &&
+ isA_CFBoolean(isLoginDone) &&
+ !CFBooleanGetValue(isLoginDone)) {
+ // if @ loginwindow
+ SC_log(LOG_INFO, "multiple sessions, console @ loginwindow");
+ locked = TRUE;
+ goto done;
+ }
+
+ if (CFDictionaryGetValueIfPresent(session,
+ CFSTR(kIOConsoleSessionScreenIsLockedKey),
+ (const void **)&isLocked) &&
+ isA_CFBoolean(isLocked) &&
+ CFBooleanGetValue(isLocked)) {
+ // if screen locked
+ SC_log(LOG_INFO, "console screen locked");
+ locked = TRUE;
+ goto done;
+ }
+ }
+ }
+
+ SC_log(LOG_INFO, "console not locked");
+
+ done :
+
+ if (console_sessions != NULL) {
+ CFRelease(console_sessions);
+ }
+ IOObjectRelease(root);
+
+ return locked;
+}
+#endif // !TARGET_OS_IPHONE
+
static __inline__ boolean_t
isQuiet(void)
{
if_list,
i + 1,
is_builtin ? kCFBooleanTrue : kCFBooleanFalse);
+
+#if !TARGET_OS_IPHONE
+ if (!is_builtin &&
+ (dbdict != NULL) &&
+ blockNewInterfaces() &&
+ !_SCNetworkInterfaceIsApplePreconfigured(interface) &&
+ isConsoleLocked()) {
+ CFDataRef addr;
+
+ // if new (but matching) interface and console locked, ignore
+ SC_log(LOG_NOTICE, "Console locked, network interface* ignored");
+ SC_log(LOG_INFO, " path = %@", path);
+ addr = _SCNetworkInterfaceGetHardwareAddress(interface);
+ if (addr != NULL) {
+ SC_log(LOG_INFO, " addr = %@", addr);
+ }
+ continue;
+ }
+#endif // !TARGET_OS_IPHONE
+
if (dbdict != NULL) {
unit = CFDictionaryGetValue(dbdict, CFSTR(kIOInterfaceUnit));
CFRetain(unit);
}
}
+#if !TARGET_OS_IPHONE
+ if (!is_builtin &&
+ (unit == NULL) &&
+ blockNewInterfaces() &&
+ !_SCNetworkInterfaceIsApplePreconfigured(interface) &&
+ isConsoleLocked()) {
+ CFDataRef addr;
+
+ // if new interface and console locked, ignore
+ SC_log(LOG_NOTICE, "Console locked, network interface ignored");
+ SC_log(LOG_INFO, " path = %@", path);
+ addr = _SCNetworkInterfaceGetHardwareAddress(interface);
+ if (addr != NULL) {
+ SC_log(LOG_INFO, " addr = %@", addr);
+ }
+ continue;
+ }
+#endif // !TARGET_OS_IPHONE
+
if (unit == NULL) {
// not built-in (or built-in unit not available), allocate from
// the non-reserved slots
/*
- * Copyright (c) 2000-2008, 2010, 2012-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008, 2010, 2012-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/* InterfaceNamer[.plugin] monitoring globals */
Boolean haveConfiguration = FALSE;
static CFStringRef namerKey = NULL;
-static CFArrayRef preconfigured = NULL;
+static CFMutableArrayRef preconfigured_names = NULL; // of CFStringRef (BSD name)
+static CFMutableArrayRef preconfigured_interfaces= NULL; // of SCNetworkInterfaceRef
/* KernelEventMonitor[.plugin] monitoring globals */
static CFStringRef interfacesKey = NULL;
storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
{
CFDictionaryRef dict;
- CFArrayRef interfaces = NULL;
Boolean quiet = FALSE;
Boolean timeout = FALSE;
Boolean updated = FALSE;
- /*
- * Capture/process KernelEventMonitor[.bundle] info
- * 1. get list of active network interfaces
- */
- dict = SCDynamicStoreCopyValue(store, interfacesKey);
- if (dict != NULL) {
- if (isA_CFDictionary(dict)) {
- interfaces = CFDictionaryGetValue(dict, kSCPropNetInterfaces);
- interfaces = isA_CFArray(interfaces);
- if (interfaces != NULL) {
- CFRetain(interfaces);
- }
- }
-
- CFRelease(dict);
- }
-
/*
* Capture/process InterfaceNamer[.bundle] info
* 1. check if IORegistry "quiet", "timeout"
- * 2. get list of named pre-configured interfaces
- * 3. merge list of active interfaces (from KEV) with the
- * list of preconfigured interfaces.
+ * 2. update list of named pre-configured interfaces
*/
dict = SCDynamicStoreCopyValue(store, namerKey);
if (dict != NULL) {
if (isA_CFDictionary(dict)) {
- CFArrayRef cur_preconfigured;
- CFMutableArrayRef new_preconfigured = NULL;
+ CFIndex n;
+ CFArrayRef preconfigured;
if (CFDictionaryContainsKey(dict, kInterfaceNamerKey_Quiet)) {
quiet = TRUE;
timeout = TRUE;
}
- cur_preconfigured = CFDictionaryGetValue(dict, kInterfaceNamerKey_PreConfiguredInterfaces);
- cur_preconfigured = isA_CFArray(cur_preconfigured);
- if ((cur_preconfigured != NULL) && (interfaces != NULL)) {
- CFIndex i;
- CFIndex n;
- CFRange r = CFRangeMake(0, CFArrayGetCount(interfaces));
+ preconfigured = CFDictionaryGetValue(dict, kInterfaceNamerKey_PreConfiguredInterfaces);
+ preconfigured = isA_CFArray(preconfigured);
- n = CFArrayGetCount(cur_preconfigured);
- for (i = 0; i < n; i++) {
- CFStringRef bsdName;
+ n = (preconfigured != NULL) ? CFArrayGetCount(preconfigured) : 0;
+ for (CFIndex i = 0; i < n; i++) {
+ CFStringRef bsdName = CFArrayGetValueAtIndex(preconfigured, i);
+ SCNetworkInterfaceRef interface;
+ CFRange range;
- bsdName = CFArrayGetValueAtIndex(cur_preconfigured, i);
- if (!CFArrayContainsValue(interfaces, r, bsdName)) {
- // if interface not currently active
- continue;
+ range.location = 0;
+ range.length = (preconfigured_names != NULL) ? CFArrayGetCount(preconfigured_names) : 0;
+ if ((range.length > 0) &&
+ CFArrayContainsValue(preconfigured_names, range, bsdName)) {
+ // if we already know about this interface
+ continue;
+ }
+
+ for (int retry = 0; retry < 10; retry++) {
+ if (retry != 0) {
+ // add short delay (before retry)
+ usleep(20 * 1000); // 20ms
+ }
+
+ interface = _SCNetworkInterfaceCreateWithBSDName(NULL, bsdName, kIncludeNoVirtualInterfaces);
+ if (interface == NULL) {
+ SC_log(LOG_ERR, "could not create network interface for %@", bsdName);
+ } else if (_SCNetworkInterfaceGetIOPath(interface) == NULL) {
+ SC_log(LOG_ERR, "could not get IOPath for %@", bsdName);
+ CFRelease(interface);
+ interface = NULL;
}
- if (new_preconfigured == NULL) {
- new_preconfigured = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (interface != NULL) {
+ // if we have an interface
+ break;
}
- CFArrayAppendValue(new_preconfigured, bsdName);
}
- }
- if (!_SC_CFEqual(preconfigured, new_preconfigured)) {
- SC_log(LOG_INFO, "pre-configured interface list changed");
+ if (interface == NULL) {
+ // if SCNetworkInterface not [currently] available
+ continue;
+ }
- if (preconfigured != NULL) {
- CFRelease(preconfigured);
+ // keep track of the interface name (quicker than having to iterate the list
+ // of SCNetworkInterfaces, extract the name, and compare).
+ if (preconfigured_names == NULL) {
+ preconfigured_names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
- if (new_preconfigured != NULL) {
- CFRetain(new_preconfigured);
+ CFArrayAppendValue(preconfigured_names, bsdName);
+
+ if (preconfigured_interfaces == NULL) {
+ preconfigured_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
- preconfigured = new_preconfigured;
+ CFArrayAppendValue(preconfigured_interfaces, interface);
+ CFRelease(interface);
updated = TRUE;
}
- if (new_preconfigured != NULL) {
- CFRelease(new_preconfigured);
+ if (updated) {
+ CFStringRef interfaces = CFSTR("<empty>");
+
+ // report [new] pre-configured interfaces
+ if (preconfigured_names != NULL) {
+ interfaces = CFStringCreateByCombiningStrings(NULL, preconfigured_names, CFSTR(","));
+ } else {
+ CFRetain(interfaces);
+ }
+ SC_log(LOG_INFO, "pre-configured interface list changed: %@", interfaces);
+ CFRelease(interfaces);
}
}
CFRelease(dict);
}
- if (interfaces != NULL) {
- CFRelease(interfaces);
- }
-
if (!haveConfiguration && (quiet || timeout)) {
static int logged = 0;
SCNetworkSetRef set;
Boolean updated = FALSE;
- range.length = (preconfigured != NULL) ? CFArrayGetCount(preconfigured) : 0;
+ range.length = (preconfigured_names != NULL) ? CFArrayGetCount(preconfigured_names) : 0;
if (range.length == 0) {
// if no [preconfigured] interfaces
return;
CFArrayRef services;
/*
- * Check for (and remove) and network services associated with
+ * Check for (and remove) any network services associated with
* a pre-configured interface from the prefs.
*/
- services = SCNetworkSetCopyServices(set);
+ services = SCNetworkServiceCopyAll(prefs);
if (services != NULL) {
CFIndex n;
continue;
}
- if (!CFArrayContainsValue(preconfigured, range, bsdName)) {
+ if (!CFArrayContainsValue(preconfigured_names, range, bsdName)) {
// if not preconfigured
continue;
}
// remove [preconfigured] network service from the prefs
SC_log(LOG_NOTICE, "removing network service for %@", bsdName);
- SCNetworkServiceRemove(service);
+ ok = SCNetworkServiceRemove(service);
+ if (!ok) {
+ SC_log(LOG_ERR, "SCNetworkServiceRemove() failed: %s",
+ SCErrorString(SCError()));
+ }
updated = TRUE;
}
ok = SCPreferencesCommitChanges(prefs);
if (!ok) {
if (SCError() != EROFS) {
- SC_log(LOG_NOTICE, "SCPreferencesCommitChanges() failed: %s",
+ SC_log(LOG_ERR, "SCPreferencesCommitChanges() failed: %s",
SCErrorString(SCError()));
}
}
/*
* Now, add a new network service for each pre-configured interface
*/
+ range.length = (preconfigured_interfaces != NULL) ? CFArrayGetCount(preconfigured_interfaces) : 0;
for (CFIndex i = 0; i < range.length; i++) {
CFStringRef bsdName;
- SCNetworkInterfaceRef interface;
+ SCNetworkInterfaceRef interface = CFArrayGetValueAtIndex(preconfigured_interfaces, i);
SCNetworkServiceRef service;
- bsdName = CFArrayGetValueAtIndex(preconfigured, i);
- interface = _SCNetworkInterfaceCreateWithBSDName(NULL, bsdName, kIncludeNoVirtualInterfaces);
- if (interface == NULL) {
- SC_log(LOG_ERR, "could not create network interface for %@", bsdName);
- continue;
- }
-
- if (_SCNetworkInterfaceGetIOPath(interface) == NULL) {
- // if no [real] interface exists
- CFRelease(interface);
- continue;
- }
-
+ bsdName = SCNetworkInterfaceGetBSDName(interface);
ok = SCNetworkSetEstablishDefaultInterfaceConfiguration(set, interface);
- CFRelease(interface);
if (!ok) {
- SC_log(LOG_ERR, "could not create network service for %@", bsdName);
+ SC_log(LOG_ERR, "could not establish network service for %@: %s",
+ bsdName,
+ SCErrorString(SCError()));
continue;
}
--- /dev/null
+/*
+ * Copyright (c) 2017 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@
+ */
+
+/*
+ * InterfaceNamerControlPrefs.c
+ * - definitions for accessing InterfaceNamer control preferences
+ */
+
+/*
+ * Modification History
+ *
+ * January 12, 2017 Allan Nathanson (ajn@apple.com)
+ * - created
+ */
+
+#include <TargetConditionals.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/scprefs_observer.h>
+#include "InterfaceNamerControlPrefs.h"
+
+os_log_t __log_InterfaceNamer();
+
+/*
+ * kInterfaceNamerControlPrefsID
+ * - identifies the InterfaceNamer preferences file that contains 'AllowNewInterfaces'
+ */
+#define kInterfaceNamerControlPrefsIDStr "com.apple.InterfaceNamer.control.plist"
+#define kInterfaceNamerControlPrefsID CFSTR(kInterfaceNamerControlPrefsIDStr)
+
+/*
+ * kAllowNewInterfaces
+ * - indicates whether InterfaceNamer is allowed to create new interfaces
+ * while the screen is locked or not
+ */
+#define kAllowNewInterfaces CFSTR("AllowNewInterfaces")
+
+static SCPreferencesRef S_prefs;
+static InterfaceNamerControlPrefsCallBack S_callback;
+
+static SCPreferencesRef
+InterfaceNamerControlPrefsGet(void)
+{
+ if (S_prefs == NULL) {
+ InterfaceNamerControlPrefsInit(NULL, NULL);
+ }
+
+ return (S_prefs);
+}
+
+static void
+prefs_changed(void * arg)
+{
+#pragma unused(arg)
+ os_activity_t activity;
+
+ activity = os_activity_create("processing InterfaceNamer preference change",
+ OS_ACTIVITY_CURRENT,
+ OS_ACTIVITY_FLAG_DEFAULT);
+ os_activity_scope(activity);
+
+ /* get the current value */
+ if (S_callback != NULL) {
+ (*S_callback)(S_prefs);
+ }
+
+ os_release(activity);
+
+ return;
+}
+
+#if TARGET_OS_IPHONE
+/*
+ * kInterfaceNamerControlManangedPrefsID
+ * - identifies the location of the managed preferences file
+ */
+#define kManagedPrefsDirStr "/Library/Managed Preferences/mobile/"
+#define kInterfaceNamerControlManagedPrefsID CFSTR(kManagedPrefsDirStr \
+ kInterfaceNamerControlPrefsIDStr)
+static SCPreferencesRef S_managed_prefs;
+
+static SCPreferencesRef
+InterfaceNamerControlManagedPrefsGet(void)
+{
+ if (S_managed_prefs == NULL) {
+ CFMutableDictionaryRef options;
+
+ options = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionarySetValue(options, kSCPreferencesOptionRemoveWhenEmpty, kCFBooleanTrue);
+ S_managed_prefs = SCPreferencesCreateWithOptions(NULL,
+ CFSTR("InterfaceNamerControlPrefs"),
+ kInterfaceNamerControlManagedPrefsID,
+ NULL,
+ options);
+ CFRelease(options);
+ }
+ return (S_managed_prefs);
+}
+
+static void
+enable_prefs_observer(CFRunLoopRef runloop)
+{
+ CFRunLoopSourceContext context;
+ dispatch_queue_t queue;
+ CFRunLoopSourceRef source;
+
+ bzero(&context, sizeof(context));
+ context.perform = prefs_changed;
+ source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
+ CFRunLoopAddSource(runloop, source, kCFRunLoopCommonModes);
+ queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+ _scprefs_observer_watch(scprefs_observer_type_global,
+ kInterfaceNamerControlPrefsIDStr,
+ queue,
+ ^{
+ if (source != NULL) {
+ CFRunLoopSourceSignal(source);
+ if (runloop != NULL) {
+ CFRunLoopWakeUp(runloop);
+ }
+ };
+ });
+ return;
+}
+
+#else /* TARGET_OS_IPHONE */
+
+static void
+enable_prefs_observer(CFRunLoopRef runloop)
+{
+#pragma unused(runloop)
+ return;
+}
+
+#endif /* TARGET_OS_IPHONE */
+
+static void
+InterfaceNamerControlPrefsChanged(SCPreferencesRef prefs,
+ SCPreferencesNotification type,
+ void *info)
+{
+#pragma unused(prefs)
+#pragma unused(type)
+#pragma unused(info)
+ prefs_changed(NULL);
+ return;
+}
+
+__private_extern__ SCPreferencesRef
+InterfaceNamerControlPrefsInit(CFRunLoopRef runloop,
+ InterfaceNamerControlPrefsCallBack callback)
+{
+ CFMutableDictionaryRef options;
+
+ options = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionarySetValue(options, kSCPreferencesOptionRemoveWhenEmpty, kCFBooleanTrue);
+ S_prefs = SCPreferencesCreateWithOptions(NULL,
+ CFSTR("InterfaceNamerControlPrefs"),
+ kInterfaceNamerControlPrefsID,
+ NULL,
+ options);
+ CFRelease(options);
+
+ if ((runloop != NULL) && (callback != NULL)) {
+ S_callback = callback;
+ if (!SCPreferencesSetCallback(S_prefs, InterfaceNamerControlPrefsChanged, NULL)) {
+ SC_log(LOG_NOTICE, "SCPreferencesSetCallBack() failed: %s", SCErrorString(SCError()));
+ goto done;
+ }
+
+ if (!SCPreferencesScheduleWithRunLoop(S_prefs, runloop, kCFRunLoopCommonModes)) {
+ SC_log(LOG_NOTICE, "SCPreferencesScheduleWithRunLoop() failed: %s", SCErrorString(SCError()));
+ (void) SCPreferencesSetCallback(S_prefs, NULL, NULL);
+ }
+
+ enable_prefs_observer(runloop);
+ }
+
+ done :
+ return (S_prefs);
+}
+
+static Boolean
+InterfaceNamerControlPrefsSave(void)
+{
+ Boolean saved = FALSE;
+
+ if (S_prefs != NULL) {
+ saved = SCPreferencesCommitChanges(S_prefs);
+ SCPreferencesSynchronize(S_prefs);
+ }
+ return (saved);
+}
+
+static CFBooleanRef
+prefs_get_boolean(CFStringRef key)
+{
+ CFBooleanRef b = NULL;
+ SCPreferencesRef prefs;
+
+#if TARGET_OS_IPHONE
+ prefs = InterfaceNamerControlManagedPrefsGet();
+ if (prefs != NULL) {
+ b = SCPreferencesGetValue(prefs, key);
+ b = isA_CFBoolean(b);
+ if (b != NULL) {
+ return (b);
+ }
+ }
+#endif /* TARGET_OS_IPHONE */
+
+ prefs = InterfaceNamerControlPrefsGet();
+ if (prefs != NULL) {
+ b = SCPreferencesGetValue(prefs, key);
+ b = isA_CFBoolean(b);
+ }
+ return (b);
+}
+
+static void
+prefs_set_boolean(CFStringRef key, CFBooleanRef b)
+{
+ SCPreferencesRef prefs;
+
+ prefs = InterfaceNamerControlPrefsGet();
+ if (prefs != NULL) {
+ if (isA_CFBoolean(b) == NULL) {
+ SCPreferencesRemoveValue(prefs, key);
+ }
+ else {
+ SCPreferencesSetValue(prefs, key, b);
+ }
+ }
+ return;
+}
+
+static void
+InterfaceNamerControlPrefsRefresh(void)
+{
+ if (S_prefs != NULL) {
+ SCPreferencesSynchronize(S_prefs);
+ }
+#if TARGET_OS_IPHONE
+ if (S_managed_prefs != NULL) {
+ SCPreferencesSynchronize(S_managed_prefs);
+ }
+#endif /* TARGET_OS_IPHONE */
+ return;
+}
+
+/**
+ ** Get
+ **/
+__private_extern__ Boolean
+InterfaceNamerControlPrefsAllowNewInterfaces(void)
+{
+ CFBooleanRef b;
+ Boolean allow = FALSE;
+
+ b = prefs_get_boolean(kAllowNewInterfaces);
+ if (b != NULL) {
+ allow = CFBooleanGetValue(b);
+ }
+ /* flush the backing store */
+ InterfaceNamerControlPrefsRefresh();
+ return (allow);
+}
+
+/**
+ ** Set
+ **/
+__private_extern__ Boolean
+InterfaceNamerControlPrefsSetAllowNewInterfaces(Boolean allow)
+{
+ if (allow) {
+ prefs_set_boolean(kAllowNewInterfaces, kCFBooleanTrue);
+ } else {
+ prefs_set_boolean(kAllowNewInterfaces, NULL);
+ }
+ return (InterfaceNamerControlPrefsSave());
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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 _INTERFACENAMERCONTROLPREFS_H
+#define _INTERFACENAMERCONTROLPREFS_H
+
+/*
+ * InterfaceNamerControlPrefs.h
+ * - definitions for accessing InterfaceNamer control preferences
+ */
+
+/*
+ * Modification History
+ *
+ * January 12, 2017 Allan Nathanson (ajn@apple.com)
+ * - created
+ */
+
+typedef void (*InterfaceNamerControlPrefsCallBack)(SCPreferencesRef prefs);
+
+SCPreferencesRef
+InterfaceNamerControlPrefsInit (CFRunLoopRef runloop,
+ InterfaceNamerControlPrefsCallBack callback);
+
+Boolean
+InterfaceNamerControlPrefsAllowNewInterfaces (void);
+
+Boolean
+InterfaceNamerControlPrefsSetAllowNewInterfaces (Boolean verbose);
+
+#endif /* _INTERFACENAMERCONTROLPREFS_H */
/*
- * Copyright (c) 2007-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <SystemConfiguration/SCPrivate.h>
#include <IOKit/IOKitLib.h>
+#include <IOKit/IOKitKeysPrivate.h>
#include <IOKit/IOMessage.h>
#include <ApplicationServices/ApplicationServices.h>
#include "UserEventAgentInterface.h"
}
+#pragma mark -
+
+static Boolean
+onConsole()
+{
+ CFArrayRef console_sessions;
+ Boolean on = FALSE;
+ io_registry_entry_t root;
+ uid_t uid = geteuid();
+
+ root = IORegistryGetRootEntry(kIOMasterPortDefault);
+ console_sessions = IORegistryEntryCreateCFProperty(root,
+ CFSTR(kIOConsoleUsersKey),
+ NULL,
+ 0);
+ if (console_sessions != NULL) {
+ CFIndex n;
+
+ n = isA_CFArray(console_sessions) ? CFArrayGetCount(console_sessions) : 0;
+ for (CFIndex i = 0; i < n; i++) {
+ CFBooleanRef bVal;
+ CFDictionaryRef session;
+ uint64_t sessionUID;
+ CFNumberRef val;
+
+ session = CFArrayGetValueAtIndex(console_sessions, i);
+ if (!isA_CFDictionary(session)) {
+ // if not dictionary
+ continue;
+ }
+
+ if (!CFDictionaryGetValueIfPresent(session,
+ CFSTR(kIOConsoleSessionUIDKey),
+ (const void **)&val) ||
+ !isA_CFNumber(val) ||
+ !CFNumberGetValue(val, kCFNumberSInt64Type, (void *)&sessionUID) ||
+ (uid != sessionUID)) {
+ // if not my session
+ continue;
+ }
+
+ if (CFDictionaryGetValueIfPresent(session,
+ CFSTR(kIOConsoleSessionOnConsoleKey),
+ (const void **)&bVal) &&
+ isA_CFBoolean(bVal) &&
+ CFBooleanGetValue(bVal)) {
+ // if "on console" session
+ on = TRUE;
+ }
+
+ break;
+ }
+
+ CFRelease(console_sessions);
+ }
+ IOObjectRelease(root);
+
+ return on;
+}
+
+
#pragma mark -
SCPreferencesRef prefs;
SCNetworkSetRef set = NULL;
+ if (!onConsole()) {
+ return;
+ }
+
prefs = SCPreferencesCreate(NULL, CFSTR("SCMonitor"), NULL);
if (prefs == NULL) {
return;
/*
- * Copyright (c) 2004-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
}
// identify available interfaces
- interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface();
+ interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface(FALSE);
if (interfaces != NULL) {
CFIndex i;
CFIndex n;
/*
- * Copyright (c) 2009-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
}
// identify available interfaces
- interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface();
+ interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface(FALSE);
if (interfaces != NULL) {
CFIndex i;
CFIndex n;
/*
- * Copyright (c) 2004-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__SCNetworkInterfaceMatchesName (CFStringRef name, CFStringRef key);
CFArrayRef
-__SCNetworkInterfaceCopyAll_IONetworkInterface (void);
+__SCNetworkInterfaceCopyAll_IONetworkInterface (Boolean keep_pre_configured);
/*!
@function __SCNetworkInterfaceCopyStorageEntity
/*
- * Copyright (c) 2004-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
{
#if !TARGET_OS_SIMULATOR
// capture USB info
- interfacePrivate->usb.name = IORegistryEntrySearchCFProperty(interface,
- kIOServicePlane,
- CFSTR(kUSBProductString),
- NULL,
- kIORegistryIterateRecursively | kIORegistryIterateParents);
- interfacePrivate->usb.vid = IORegistryEntrySearchCFProperty(interface,
- kIOServicePlane,
- CFSTR(kUSBVendorID),
- NULL,
- kIORegistryIterateRecursively | kIORegistryIterateParents);
- interfacePrivate->usb.pid = IORegistryEntrySearchCFProperty(interface,
- kIOServicePlane,
- CFSTR(kUSBProductID),
- NULL,
- kIORegistryIterateRecursively | kIORegistryIterateParents);
+ if (interfacePrivate->usb.name == NULL) {
+ interfacePrivate->usb.name = IORegistryEntrySearchCFProperty(interface,
+ kIOServicePlane,
+ CFSTR(kUSBProductString),
+ NULL,
+ kIORegistryIterateRecursively | kIORegistryIterateParents);
+ }
+ if (interfacePrivate->usb.vid == NULL) {
+ interfacePrivate->usb.vid = IORegistryEntrySearchCFProperty(interface,
+ kIOServicePlane,
+ CFSTR(kUSBVendorID),
+ NULL,
+ kIORegistryIterateRecursively | kIORegistryIterateParents);
+ }
+ if (interfacePrivate->usb.pid == NULL) {
+ interfacePrivate->usb.pid = IORegistryEntrySearchCFProperty(interface,
+ kIOServicePlane,
+ CFSTR(kUSBProductID),
+ NULL,
+ kIORegistryIterateRecursively | kIORegistryIterateParents);
+ }
#endif // !TARGET_OS_SIMULATOR
return;
CFNumberGetValue(num, kCFNumberIntType, &ift)) {
interfacePrivate->type = CFRetain(num);
} else {
- SC_log(LOG_INFO, "no interface type");
+ SC_log(LOG_INFO, "no interface type: %@", interface_dict);
return FALSE;
}
__private_extern__
CFArrayRef
-__SCNetworkInterfaceCopyAll_IONetworkInterface(void)
+__SCNetworkInterfaceCopyAll_IONetworkInterface(Boolean keep_pre_configured)
{
CFDictionaryRef matching;
CFArrayRef new_interfaces;
new_interfaces = findMatchingInterfaces(matching,
processNetworkInterface,
kSCNetworkInterfaceHiddenInterfaceKey,
- FALSE);
+ keep_pre_configured);
CFRelease(matching);
return new_interfaces;
all_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
// get Ethernet, Firewire, Thunderbolt, and AirPort interfaces
- new_interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface();
+ new_interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface(FALSE);
if (new_interfaces != NULL) {
add_interfaces(all_interfaces, new_interfaces);
CFRelease(new_interfaces);
/*
- * Copyright (c) 2014-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2014-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
SCPreferencesRef ni_prefs;
CFComparisonResult res;
-
- networkInterfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface();
-
+ networkInterfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface(TRUE);
if (networkInterfaces == NULL) {
SC_log(LOG_NOTICE, "networkInterfaces is NULL");
return NULL;
else {
migrationComplete = _SCNetworkConfigurationMigrateConfiguration(sourceDirConfig, targetDirConfig);
}
- SC_log(LOG_NOTICE, "Migration %s", migrationComplete ? "complete" : "failed");
if (migrationComplete) {
+ SC_log(LOG_NOTICE, "Migration complete");
paths = _SCNetworkConfigurationCopyMigrationPaths(NULL);
- }
- else {
+ } else {
+ SC_log(LOG_NOTICE, "Migration failed: %s", SCErrorString(SCError()));
+
// If migration fails, then remove configuration files from target config if they are
// copied from the current directory
if (removeTargetOnFailure) {
if (currentSourceSet != NULL) {
CFRelease(currentSourceSet);
}
+
+ if (setMapping != NULL) {
+ SC_log(LOG_NOTICE, "Set mapping: %@", setMapping);
+ } else {
+ SC_log(LOG_INFO, "Set mapping: NULL");
+ }
+
return setMapping;
}
if (targetSCNetworkServicesMutable != NULL) {
CFRelease(targetSCNetworkServicesMutable);
}
+
+ if (serviceMapping != NULL) {
+ SC_log(LOG_NOTICE, "Service mapping: %@", serviceMapping);
+ } else {
+ SC_log(LOG_INFO, "Service mapping: NULL");
+ }
+
return serviceMapping;
}
}
SC_log(LOG_DEBUG, "BSD Name Mapping: %@", bsdNameMapping);
serviceMapping = _SCNetworkMigrationCreateServiceMappingUsingBSDMapping(sourcePrefs, targetPrefs, bsdNameMapping);
-
- if (isA_CFDictionary(serviceMapping) == NULL) {
- SC_log(LOG_INFO, "Service mapping is NULL");
+ if (serviceMapping == NULL) {
goto done;
}
- SC_log(LOG_NOTICE, "Service mapping: %@", serviceMapping);
setMapping = _SCNetworkMigrationCreateSetMapping(sourcePrefs, targetPrefs);
sourceServiceSetMapping = _SCNetworkMigrationCreateServiceSetMapping(sourcePrefs);
SCNetworkReachabilityPrivateRef targetPrivate;
unsigned int if_index = 0;
char if_name[IFNAMSIZ];
+ CFDataRef sourceAppAuditToken = NULL;
+ CFStringRef sourceAppBundleID = NULL;
if (!isA_CFDictionary(options)) {
_SCErrorSet(kSCStatusInvalidArgument);
_SCErrorSet(kSCStatusInvalidArgument);
return NULL;
}
+ sourceAppAuditToken =
+ CFDictionaryGetValue(options, kSCNetworkReachabilityOptionSourceAppAuditToken);
+ if ((sourceAppAuditToken != NULL) &&
+ (!isA_CFData(sourceAppAuditToken) ||
+ (CFDataGetLength(sourceAppAuditToken) != sizeof(audit_token_t)))) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+ sourceAppBundleID =
+ CFDictionaryGetValue(options, kSCNetworkReachabilityOptionSourceAppBundleIdentifier);
+ if ((sourceAppBundleID != NULL) &&
+ (!isA_CFString(sourceAppBundleID) ||
+ (CFStringGetLength(sourceAppBundleID) == 0))) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+
if (nodename != NULL) {
const char *name;
haveOpt = TRUE;
}
+ if (sourceAppAuditToken != NULL) {
+ audit_token_t atoken;
+ CFDataGetBytes(sourceAppAuditToken,
+ CFRangeMake(0, CFDataGetLength(sourceAppAuditToken)),
+ (UInt8 *)&atoken);
+ nw_parameters_set_source_application(targetPrivate->parameters, atoken);
+ haveOpt = TRUE;
+ } else if (sourceAppBundleID != NULL) {
+ char *cBundleID = _SC_cfstring_to_cstring(sourceAppBundleID,
+ NULL,
+ 0,
+ kCFStringEncodingUTF8);
+ if (cBundleID != NULL) {
+ nw_parameters_set_source_application_by_bundle_id(targetPrivate->parameters,
+ cBundleID);
+ CFAllocatorDeallocate(NULL, (void *)cBundleID);
+ } else {
+ SC_log(LOG_WARNING, "failed to convert %@ to a C string", sourceAppBundleID);
+ }
+ haveOpt = TRUE;
+ }
+
if (haveOpt) {
const char *opt = "???";
pathEvaluator = nw_path_create_evaluator_for_endpoint(endpoint, targetPrivate->parameters);
path = nw_path_evaluator_copy_path(pathEvaluator);
- crazyIvanPath = __SCNetworkReachabilityCreateCrazyIvan46Path(path, endpoint, targetPrivate->parameters, FALSE);
- if (NULL != crazyIvanPath) {
- network_release(path);
- path = crazyIvanPath;
+ if (isReachabilityTypeAddress(targetPrivate->type)) {
+ crazyIvanPath = __SCNetworkReachabilityCreateCrazyIvan46Path(path, endpoint,
+ targetPrivate->parameters, FALSE);
+ if (NULL != crazyIvanPath) {
+ network_release(path);
+ path = crazyIvanPath;
+ }
}
*flags = __SCNetworkReachabilityGetFlagsFromPath(path, 0, nw_resolver_status_invalid, NULL, FALSE, 0);
if (targetPrivate &&
!targetPrivate->resolverBypass &&
isReachabilityTypeName(targetPrivate->type)) {
+ nw_resolver_t resolver;
CFRetain(targetPrivate);
if (NULL != targetPrivate->resolver) {
nw_resolver_cancel(targetPrivate->resolver);
}
- nw_resolver_t resolver = nw_resolver_create_with_endpoint(__SCNetworkReachabilityGetPrimaryEndpoint(targetPrivate), targetPrivate->lastPathParameters ? targetPrivate->lastPathParameters : targetPrivate->parameters);
+ if (targetPrivate->lastPath != NULL) {
+ resolver = nw_resolver_create_with_path(targetPrivate->lastPath);
+ } else {
+ resolver = nw_resolver_create_with_endpoint(__SCNetworkReachabilityGetPrimaryEndpoint(targetPrivate), targetPrivate->lastPathParameters ? targetPrivate->lastPathParameters : targetPrivate->parameters);
+ }
+ if (resolver == NULL) {
+ SC_log(LOG_ERR, "%sfailed to create a nw_resolver", targetPrivate->log_prefix);
+ targetPrivate->resolver = NULL;
+ CFRelease(targetPrivate);
+ return;
+ }
targetPrivate->resolver = resolver;
nw_resolver_set_cancel_handler(resolver, ^(void) {
MUTEX_LOCK(&targetPrivate->lock);
network_release(targetPrivate->lastPath);
targetPrivate->lastPath = nw_path_evaluator_copy_path(pathEvaluator);
- crazyIvanPath = __SCNetworkReachabilityCreateCrazyIvan46Path(targetPrivate->lastPath, endpoint,
- targetPrivate->parameters, FALSE);
- if (NULL != crazyIvanPath) {
- network_release(targetPrivate->lastPath);
- targetPrivate->lastPath = crazyIvanPath;
+ if (isReachabilityTypeAddress(targetPrivate->type)) {
+ crazyIvanPath = __SCNetworkReachabilityCreateCrazyIvan46Path(targetPrivate->lastPath, endpoint,
+ targetPrivate->parameters, FALSE);
+ if (NULL != crazyIvanPath) {
+ network_release(targetPrivate->lastPath);
+ targetPrivate->lastPath = crazyIvanPath;
+ }
}
network_release(targetPrivate->lastPathParameters);
network_release(targetPrivate->lastPath);
targetPrivate->lastPath = network_retain(path);
- crazyIvanPath = __SCNetworkReachabilityCreateCrazyIvan46Path(targetPrivate->lastPath,
+ if (isReachabilityTypeAddress(targetPrivate->type)) {
+ crazyIvanPath =
+ __SCNetworkReachabilityCreateCrazyIvan46Path(targetPrivate->lastPath,
endpoint,
targetPrivate->parameters,
TRUE);
- if (NULL != crazyIvanPath) {
- network_release(targetPrivate->lastPath);
- targetPrivate->lastPath = crazyIvanPath;
+ if (NULL != crazyIvanPath) {
+ network_release(targetPrivate->lastPath);
+ targetPrivate->lastPath = crazyIvanPath;
+ }
}
if (targetPrivate->lastResolverStatus == nw_resolver_status_complete) {
/*
- * Copyright (c) 2004-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
service = SCNetworkServiceCreate(setPrivate->prefs, interface);
if (service == NULL) {
- SC_log(LOG_INFO, "could not create service for \"%@\": %s",
+ SC_log(LOG_ERR, "could not create service for \"%@\": %s",
SCNetworkInterfaceGetLocalizedDisplayName(interface),
SCErrorString(SCError()));
ok = FALSE;
ok = SCNetworkServiceEstablishDefaultConfiguration(service);
if (!ok) {
- SC_log(LOG_INFO, "could not estabish default configuration for \"%@\": %s",
+ SC_log(LOG_ERR, "could not estabish default configuration for \"%@\": %s",
SCNetworkInterfaceGetLocalizedDisplayName(interface),
SCErrorString(SCError()));
SCNetworkServiceRemove(service);
ok = SCNetworkSetAddService(set, service);
if (!ok) {
- SC_log(LOG_INFO, "could not add service for \"%@\": %s",
+ SC_log(LOG_ERR, "could not add service for \"%@\": %s",
SCNetworkInterfaceGetLocalizedDisplayName(interface),
SCErrorString(SCError()));
SCNetworkServiceRemove(service);
+
/*!
@group
*/
extern const CFStringRef kSCProxiesNoGlobal;
+/*!
+ @function SCNetworkProxiesCreateProxyAgentData
+ @discussion
+
+ @param proxyConfig A dictionary representing a proxy configuration
+ @result returns a CFData representing a proxy configuration. This data is readable by all
+ "config-agents" (Agents with domain as "SystemConfig") via config_agent_copy_proxy_information().
+ You must release the returned value.
+ */
+CFDataRef
+SCNetworkProxiesCreateProxyAgentData(CFDictionaryRef proxyConfig) __OSX_AVAILABLE_STARTING(__MAC_10_12,__IPHONE_10_0/*SPI*/);
+
/*!
@function SCDynamicStoreCopyProxiesWithOptions
@discussion
CFDictionaryRef
SCDynamicStoreCopyProxiesWithOptions(SCDynamicStoreRef store, CFDictionaryRef options) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0/*SPI*/);
-
#pragma mark -
#pragma mark Reachability
return proxies;
}
+CFDataRef
+SCNetworkProxiesCreateProxyAgentData(CFDictionaryRef proxyConfig)
+{
+ CFDataRef result = NULL;
+ CFArrayRef newProxy = NULL;
+
+ if (!isA_CFDictionary(proxyConfig)) {
+ SC_log(LOG_ERR, "Invalid proxy configuration");
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+
+ newProxy = CFArrayCreate(NULL, (const void **)&proxyConfig, 1, &kCFTypeArrayCallBacks);
+ (void)_SCSerialize(newProxy, &result, NULL, NULL);
+ CFRelease(newProxy);
+
+ return result;
+}
+
CFArrayRef
SCNetworkProxiesCopyMatching(CFDictionaryRef globalConfiguration,
CFStringRef server,
const CFStringRef kSCValNetIPv6ConfigMethodRouterAdvertisement = CFSTR("RouterAdvertisement");
const CFStringRef kSCValNetIPv6ConfigMethod6to4 = CFSTR("6to4");
const CFStringRef kSCPropNetIPv6AdditionalRoutes = CFSTR("AdditionalRoutes");
+const CFStringRef kSCPropNetIPv6EnableCGA = CFSTR("EnableCGA");
const CFStringRef kSCPropNetIPv6ExcludedRoutes = CFSTR("ExcludedRoutes");
const CFStringRef kSCPropNetIPv6IncludedRoutes = CFSTR("IncludedRoutes");
const CFStringRef kSCPropNetIPv6RouteDestinationAddress = CFSTR("DestinationAddress");
/*
- * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
- * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* kSCEntNetIPv6 Entity Keys
*
* kSCPropNetIPv6AdditionalRoutes "AdditionalRoutes" CFArray[CFDictionary]
+ * kSCPropNetIPv6EnableCGA "EnableCGA" CFNumber (0 or 1)
* kSCPropNetIPv6ExcludedRoutes "ExcludedRoutes" CFArray[CFDictionary]
* kSCPropNetIPv6IncludedRoutes "IncludedRoutes" CFArray[CFDictionary]
*
extern const CFStringRef kSCPropNetIPv6AdditionalRoutes __OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0/*SPI*/);
#define kSCPropNetIPv6AdditionalRoutes kSCPropNetIPv6AdditionalRoutes
+/*!
+ @const kSCPropNetIPv6EnableCGA
+ @discussion Value is a CFNumber (0 or 1)
+ */
+extern const CFStringRef kSCPropNetIPv6EnableCGA __OSX_AVAILABLE_STARTING(__MAC_10_12,__IPHONE_10_0/*SPI*/);
+#define kSCPropNetIPv6EnableCGA kSCPropNetIPv6EnableCGA
+
/*!
@const kSCPropNetIPv6ExcludedRoutes
@discussion Value is a CFArray[CFDictionary]
/*
- * Copyright (c) 2003-2013, 2015, 2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2013, 2015-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
}
// add real interfaces that aren't part of a bond or bridge
- interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface();
+ interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface(FALSE);
if (interfaces != NULL) {
addAvailableInterfaces(available, interfaces, excluded);
CFRelease(interfaces);
/*
- * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
char copyright_string[] =
"/*\n"
-" * Copyright (c) 2000-2016 Apple Inc. All rights reserved.\n"
+" * Copyright (c) 2000-2017 Apple Inc. All rights reserved.\n"
" *\n"
" * @APPLE_LICENSE_HEADER_START@\n"
" *\n"
#define CCP "CCP"
#define CELLULAR "Cellular"
#define CERTIFICATE "Certificate"
+#define CGA "CGA"
#define CHAP "CHAP"
#define COMM "Comm"
#define COMPATIBLE "Compatible"
{ GROUP_PRIVATE, NETPROP IPV6, KEY_PREFIX NETENT IPV6 " Entity Keys", NULL, NULL },
{ SC_10_10_IPHONE_8_0_PRIVATE, NETPROP IPV6, ADDITIONAL ROUTES, NULL, CFARRAY_CFDICTIONARY },
+ { SC_10_12_IPHONE_10_0_PRIVATE, NETPROP IPV6, ENABLE CGA, NULL, CFNUMBER_BOOL },
{ SC_10_7_IPHONE_4_0_PRIVATE, NETPROP IPV6, EXCLUDED ROUTES, NULL, CFARRAY_CFDICTIONARY },
{ SC_10_7_IPHONE_4_0_PRIVATE, NETPROP IPV6, INCLUDED ROUTES, NULL, CFARRAY_CFDICTIONARY },
{ COMMENT_PRIVATE, "", NULL, NULL, NULL },
__BEGIN_DECLS
+#define kConfigAgentDomain "SystemConfig"
+
+#define kConfigAgentTypeProxy "ProxyAgent"
+#define kConfigAgentTypeDNS "DNSAgent"
+
/*
Returns true for agent with type DNSAgent and domain SystemConfig
*/
1558480607550D470046C2E9 /* PBXTargetDependency */,
1558480807550D470046C2E9 /* PBXTargetDependency */,
D6DDAC3D147A24BC00A2E902 /* PBXTargetDependency */,
+ 72C12CB11D6EA2CA000EE61C /* PBXTargetDependency */,
150ECB300D0042DA0065E94D /* PBXTargetDependency */,
);
name = configd_executables;
158317660CFB80D5006F62B9 /* PBXTargetDependency */,
157434210D4A8166002ACA73 /* PBXTargetDependency */,
1574341F0D4A815E002ACA73 /* PBXTargetDependency */,
+ 7271EA341D7660980055B1AA /* PBXTargetDependency */,
);
name = "configd_executables-Embedded";
productName = configd_executables;
1565D85018B847590097062B /* SCNetworkMigration.c in Sources */ = {isa = PBXBuildFile; fileRef = 55A3DB9D183C2A8200ED3DB7 /* SCNetworkMigration.c */; };
1565D85118B847F20097062B /* SCNetworkMigration.c in Sources */ = {isa = PBXBuildFile; fileRef = 55A3DB9D183C2A8200ED3DB7 /* SCNetworkMigration.c */; };
156BD6BC07E0DFA9008698FF /* SCPreferencesSetSpecificPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 156BD6BB07E0DFA9008698FF /* SCPreferencesSetSpecificPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 1572AA8C1D8235390021E093 /* plugin_shared.h in Headers */ = {isa = PBXBuildFile; fileRef = 1572AA8B1D8234500021E093 /* plugin_shared.h */; };
1572AA8D1D8235940021E093 /* plugin_shared.h in Headers */ = {isa = PBXBuildFile; fileRef = 1572AA8B1D8234500021E093 /* plugin_shared.h */; };
1572AA8E1D8235A40021E093 /* plugin_shared.h in Headers */ = {isa = PBXBuildFile; fileRef = 1572AA8B1D8234500021E093 /* plugin_shared.h */; };
1572AA8F1D82375A0021E093 /* plugin_shared.h in Headers */ = {isa = PBXBuildFile; fileRef = 1572AA8B1D8234500021E093 /* plugin_shared.h */; };
157A85290D56C91100B6F1A0 /* linkconfig.c in Sources */ = {isa = PBXBuildFile; fileRef = 159D53C107528B36004F8947 /* linkconfig.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, ); }; };
+ 1581BCD21E28673600F69B1E /* InterfaceNamerControlPrefs.h in Headers */ = {isa = PBXBuildFile; fileRef = 15FB1F891E27E9A000B4F809 /* InterfaceNamerControlPrefs.h */; };
+ 1581BCD31E28679A00F69B1E /* InterfaceNamerControlPrefs.h in Headers */ = {isa = PBXBuildFile; fileRef = 15FB1F891E27E9A000B4F809 /* InterfaceNamerControlPrefs.h */; };
+ 1581BCD41E2867A300F69B1E /* IPMonitorControlPrefs.h in Headers */ = {isa = PBXBuildFile; fileRef = F9A3780F16A4846E00C57CDC /* IPMonitorControlPrefs.h */; };
+ 1581BCD51E2867A500F69B1E /* IPMonitorControlPrefs.h in Headers */ = {isa = PBXBuildFile; fileRef = F9A3780F16A4846E00C57CDC /* IPMonitorControlPrefs.h */; };
+ 1581BCD61E2867AF00F69B1E /* IPMonitorControlPrefs.h in Headers */ = {isa = PBXBuildFile; fileRef = F9A3780F16A4846E00C57CDC /* IPMonitorControlPrefs.h */; };
+ 1581BCD71E2867B200F69B1E /* IPMonitorControlPrefs.h in Headers */ = {isa = PBXBuildFile; fileRef = F9A3780F16A4846E00C57CDC /* IPMonitorControlPrefs.h */; };
+ 1581BCD81E2867BA00F69B1E /* IPMonitorControlPrefs.h in Headers */ = {isa = PBXBuildFile; fileRef = F9A3780F16A4846E00C57CDC /* IPMonitorControlPrefs.h */; };
+ 1581BCD91E2867C100F69B1E /* IPMonitorControlPrefs.h in Headers */ = {isa = PBXBuildFile; fileRef = F9A3780F16A4846E00C57CDC /* IPMonitorControlPrefs.h */; };
+ 1581BCDD1E286E0000F69B1E /* InterfaceNamerControlPrefs.h in Headers */ = {isa = PBXBuildFile; fileRef = 15FB1F891E27E9A000B4F809 /* InterfaceNamerControlPrefs.h */; };
158317250CFB80A1006F62B9 /* configd.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69CF05C0722B0099E85F /* configd.h */; };
158317260CFB80A1006F62B9 /* _SCD.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D105C0722B0099E85F /* _SCD.h */; };
158317270CFB80A1006F62B9 /* configd_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CB69D305C0722B0099E85F /* configd_server.h */; };
15A5A2610D5B94190087BDA0 /* SCNetworkSignature.c in Sources */ = {isa = PBXBuildFile; fileRef = F95B8A420B03E07A00993BA3 /* SCNetworkSignature.c */; };
15A5A2630D5B94190087BDA0 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
15A6F7C40A4B266D00B907EA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 15A6F7C20A4B266D00B907EA /* Localizable.strings */; };
+ 15A9BDA81D8DEA67007024DB /* plugin_shared.h in Headers */ = {isa = PBXBuildFile; fileRef = 1572AA8B1D8234500021E093 /* plugin_shared.h */; };
15AAA7F4108E310700C2A607 /* VPNTunnelPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 15AAA7F1108E310700C2A607 /* VPNTunnelPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
15AAA7F5108E310700C2A607 /* VPNTunnel.h in Headers */ = {isa = PBXBuildFile; fileRef = 15AAA7F2108E310700C2A607 /* VPNTunnel.h */; settings = {ATTRIBUTES = (Private, ); }; };
15AAA7F6108E310700C2A607 /* VPNTunnel.c in Sources */ = {isa = PBXBuildFile; fileRef = 15AAA7F3108E310700C2A607 /* VPNTunnel.c */; };
15E1B05416EBAE3C00E5F06F /* scprefs_observer.c in Sources */ = {isa = PBXBuildFile; fileRef = D61AAEAD1522C99C0066B003 /* scprefs_observer.c */; };
15E1B05516EBAE3C00E5F06F /* IPMonitorControlPrefs.c in Sources */ = {isa = PBXBuildFile; fileRef = F9A3780E16A4846E00C57CDC /* IPMonitorControlPrefs.c */; };
15F21618110F823500E89CF7 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15BAA32207F0699A00D9EC95 /* libbsm.dylib */; };
+ 15FB1F8A1E27EA8700B4F809 /* InterfaceNamerControlPrefs.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FB1F881E27E9A000B4F809 /* InterfaceNamerControlPrefs.c */; };
+ 15FB1F8B1E27EA8900B4F809 /* InterfaceNamerControlPrefs.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FB1F881E27E9A000B4F809 /* InterfaceNamerControlPrefs.c */; };
15FBB54C17D6834C0035D752 /* libCrashReporterClient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 15FBB54B17D6834C0035D752 /* libCrashReporterClient.a */; };
15FC130B0CCEA59E0013872C /* monitor.c in Sources */ = {isa = PBXBuildFile; fileRef = 15FC130A0CCEA59E0013872C /* monitor.c */; };
15FC13180CCF74740013872C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15CB6A6F05C0722B0099E85F /* CoreFoundation.framework */; };
7214BCE41BEB392300A8F056 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 728015961BE16B6C009F4F60 /* NetworkExtension.framework */; };
72499BA41AC9B7AB0090C49F /* get-network-info in Resources */ = {isa = PBXBuildFile; fileRef = 72499BA31AC9B7AB0090C49F /* get-network-info */; };
72499BA51AC9B7AB0090C49F /* get-network-info in Resources */ = {isa = PBXBuildFile; fileRef = 72499BA31AC9B7AB0090C49F /* get-network-info */; };
+ 72573D291D667372004975AD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D281D667372004975AD /* main.m */; };
+ 72573D2E1D6673B6004975AD /* SCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D2D1D6673B6004975AD /* SCTest.m */; };
+ 72573D321D667686004975AD /* SCTestUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D311D667686004975AD /* SCTestUtils.m */; };
+ 72573D351D6680AA004975AD /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72573D331D66800C004975AD /* SystemConfiguration.framework */; };
+ 72573D3A1D6692BA004975AD /* SCTestOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D391D6692BA004975AD /* SCTestOptions.m */; };
+ 72573D3C1D6695B4004975AD /* SCTestDynamicStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D3B1D6695B4004975AD /* SCTestDynamicStore.m */; };
+ 72573D3E1D669AA6004975AD /* SCTestPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D3D1D669AA6004975AD /* SCTestPreferences.m */; };
+ 72573D401D67B2BE004975AD /* SCTestUnitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D3F1D67B2BE004975AD /* SCTestUnitTest.m */; };
+ 72573D421D6B798A004975AD /* SCTestConfigAgents.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D411D6B7989004975AD /* SCTestConfigAgents.m */; };
+ 72573D441D6BA051004975AD /* Network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 728015951BE16B6C009F4F60 /* Network.framework */; };
+ 72573D451D6BA976004975AD /* libnetwork.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 90507AAF1CE2F55B0067D16B /* libnetwork.dylib */; };
725CB7551BF439C6000C05A8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725CB7541BF439C6000C05A8 /* Foundation.framework */; };
725CB7561BF439D2000C05A8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725CB7541BF439C6000C05A8 /* Foundation.framework */; };
725CB7581BF514F2000C05A8 /* configAgentDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 725CB7571BF51476000C05A8 /* configAgentDefines.h */; };
7264C14614731A1F004FD76D /* CaptiveNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 15A1FF3010597F17004C9CC9 /* CaptiveNetwork.h */; settings = {ATTRIBUTES = (Public, ); }; };
726DB2F41BEA80E5001B2C6C /* config_agent_info.c in Sources */ = {isa = PBXBuildFile; fileRef = 726DB2F11BEA80E5001B2C6C /* config_agent_info.c */; };
726DB2F61BEA80E5001B2C6C /* config_agent_info.h in Headers */ = {isa = PBXBuildFile; fileRef = 726DB2F21BEA80E5001B2C6C /* config_agent_info.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 7271EA1E1D76600B0055B1AA /* SCTestDynamicStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D3B1D6695B4004975AD /* SCTestDynamicStore.m */; };
+ 7271EA1F1D76600B0055B1AA /* SCTestOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D391D6692BA004975AD /* SCTestOptions.m */; };
+ 7271EA201D76600B0055B1AA /* SCTestUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D311D667686004975AD /* SCTestUtils.m */; };
+ 7271EA211D76600B0055B1AA /* SCTestUnitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D3F1D67B2BE004975AD /* SCTestUnitTest.m */; };
+ 7271EA221D76600B0055B1AA /* SCTestReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 728E0E951D70229A00E0613A /* SCTestReachability.m */; };
+ 7271EA231D76600B0055B1AA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D281D667372004975AD /* main.m */; };
+ 7271EA241D76600B0055B1AA /* SCTestConfigAgents.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D411D6B7989004975AD /* SCTestConfigAgents.m */; };
+ 7271EA251D76600B0055B1AA /* SCTestPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D3D1D669AA6004975AD /* SCTestPreferences.m */; };
+ 7271EA261D76600B0055B1AA /* SCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 72573D2D1D6673B6004975AD /* SCTest.m */; };
+ 7271EA281D76600B0055B1AA /* libnetwork.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 90507AAF1CE2F55B0067D16B /* libnetwork.dylib */; };
+ 7271EA291D76600B0055B1AA /* Network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 728015951BE16B6C009F4F60 /* Network.framework */; };
+ 7271EA2A1D76600B0055B1AA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72573D331D66800C004975AD /* SystemConfiguration.framework */; };
+ 7271EA2B1D76600B0055B1AA /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 728015961BE16B6C009F4F60 /* NetworkExtension.framework */; };
+ 7271EA2D1D76600B0055B1AA /* npt_configd.plist in npt_configd.plist */ = {isa = PBXBuildFile; fileRef = 72C12CAA1D6E9ED4000EE61C /* npt_configd.plist */; };
727AF25419138699009AB153 /* VPNAppLayerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = B0A88CA616397A1200A60B3A /* VPNAppLayerPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
727AF255191386A0009AB153 /* VPNFlow.h in Headers */ = {isa = PBXBuildFile; fileRef = C4CDB8111631933400819B44 /* VPNFlow.h */; settings = {ATTRIBUTES = (Private, ); }; };
727AF257191386DA009AB153 /* VPNTunnel.h in Headers */ = {isa = PBXBuildFile; fileRef = 15AAA7F2108E310700C2A607 /* VPNTunnel.h */; settings = {ATTRIBUTES = (Private, ); }; };
7280159E1BE1812B009F4F60 /* proxyAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 7280157F1BE16833009F4F60 /* proxyAgent.h */; };
728CEAFF1BEA951A00F13F92 /* config_agent_info.c in Sources */ = {isa = PBXBuildFile; fileRef = 726DB2F11BEA80E5001B2C6C /* config_agent_info.c */; };
728CEB001BEA993100F13F92 /* config_agent_info.h in Headers */ = {isa = PBXBuildFile; fileRef = 726DB2F21BEA80E5001B2C6C /* config_agent_info.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 728E0E961D70229A00E0613A /* SCTestReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 728E0E951D70229A00E0613A /* SCTestReachability.m */; };
+ 728E0E971D70348D00E0613A /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 728015961BE16B6C009F4F60 /* NetworkExtension.framework */; };
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 */; };
+ 72C12CAB1D6E9F45000EE61C /* npt_configd.plist in npt_configd.plist */ = {isa = PBXBuildFile; fileRef = 72C12CAA1D6E9ED4000EE61C /* npt_configd.plist */; };
72D3E6611AE6EA3A00DB4C69 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72D3E6601AE6EA3A00DB4C69 /* main.swift */; };
72D3E66C1AE6EAF600DB4C69 /* test-objC.m in Sources */ = {isa = PBXBuildFile; fileRef = 72D3E66B1AE6EAF600DB4C69 /* test-objC.m */; };
90507AB01CE2F55B0067D16B /* libnetwork.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 90507AAF1CE2F55B0067D16B /* libnetwork.dylib */; };
remoteGlobalIDString = 15DAD63F07591A1A0084A6ED;
remoteInfo = SystemConfiguration.framework;
};
+ 7271EA331D7660980055B1AA /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7271EA1B1D76600B0055B1AA;
+ remoteInfo = "sctest-Embedded";
+ };
+ 72C12CB01D6EA2CA000EE61C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72573D251D667372004975AD;
+ remoteInfo = sctest;
+ };
72C4A47F1BE44D19009D570E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15CB6A7705C0722B0099E85F /* Project object */;
);
runOnlyForDeploymentPostprocessing = 1;
};
+ 72573D241D667372004975AD /* npt_configd.plist */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /AppleInternal/CoreOS/BATS/npt_tests;
+ dstSubfolderSpec = 0;
+ files = (
+ 72C12CAB1D6E9F45000EE61C /* npt_configd.plist in npt_configd.plist */,
+ );
+ name = npt_configd.plist;
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 7271EA2C1D76600B0055B1AA /* npt_configd.plist */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /AppleInternal/CoreOS/BATS/npt_tests;
+ dstSubfolderSpec = 0;
+ files = (
+ 7271EA2D1D76600B0055B1AA /* npt_configd.plist in npt_configd.plist */,
+ );
+ name = npt_configd.plist;
+ runOnlyForDeploymentPostprocessing = 1;
+ };
72D3E65C1AE6EA3900DB4C69 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
15DC346E0711D49400A3311C /* net_set.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = net_set.h; sourceTree = "<group>"; };
15E1B05916EBAE3C00E5F06F /* libIPMonitor_sim.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libIPMonitor_sim.a; sourceTree = BUILT_PRODUCTS_DIR; };
15E1B06116EBAE7800E5F06F /* IPMonitor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IPMonitor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+ 15FB1F881E27E9A000B4F809 /* InterfaceNamerControlPrefs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = InterfaceNamerControlPrefs.c; sourceTree = "<group>"; };
+ 15FB1F891E27E9A000B4F809 /* InterfaceNamerControlPrefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterfaceNamerControlPrefs.h; sourceTree = "<group>"; };
15FBB54B17D6834C0035D752 /* libCrashReporterClient.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libCrashReporterClient.a; path = /usr/local/lib/libCrashReporterClient.a; sourceTree = "<absolute>"; };
15FBB54E17D7899C0035D752 /* Info-EmbeddedSimulator.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-EmbeddedSimulator.plist"; sourceTree = "<group>"; };
15FBB55017D78A780035D752 /* update-mach-services */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "update-mach-services"; sourceTree = "<group>"; };
55A3DB9D183C2A8200ED3DB7 /* SCNetworkMigration.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SCNetworkMigration.c; sourceTree = "<group>"; };
720985431C580D9F00966D30 /* network_config_agent_info_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = network_config_agent_info_priv.h; path = nwi/network_config_agent_info_priv.h; sourceTree = "<group>"; };
72499BA31AC9B7AB0090C49F /* get-network-info */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "get-network-info"; sourceTree = SOURCE_ROOT; };
+ 72573D261D667372004975AD /* sctest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 72573D281D667372004975AD /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 72573D2D1D6673B6004975AD /* SCTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCTest.m; sourceTree = "<group>"; };
+ 72573D2F1D6673C6004975AD /* SCTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SCTest.h; sourceTree = "<group>"; };
+ 72573D301D6675AF004975AD /* SCTestUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SCTestUtils.h; sourceTree = "<group>"; };
+ 72573D311D667686004975AD /* SCTestUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCTestUtils.m; sourceTree = "<group>"; };
+ 72573D331D66800C004975AD /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+ 72573D361D668B3C004975AD /* genSCTestOptions.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = genSCTestOptions.c; path = sctest/genSCTestOptions.c; sourceTree = SOURCE_ROOT; };
+ 72573D381D6692BA004975AD /* SCTestOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCTestOptions.h; sourceTree = "<group>"; };
+ 72573D391D6692BA004975AD /* SCTestOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCTestOptions.m; sourceTree = "<group>"; };
+ 72573D3B1D6695B4004975AD /* SCTestDynamicStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCTestDynamicStore.m; sourceTree = "<group>"; };
+ 72573D3D1D669AA6004975AD /* SCTestPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCTestPreferences.m; sourceTree = "<group>"; };
+ 72573D3F1D67B2BE004975AD /* SCTestUnitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCTestUnitTest.m; sourceTree = "<group>"; };
+ 72573D411D6B7989004975AD /* SCTestConfigAgents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCTestConfigAgents.m; sourceTree = "<group>"; };
+ 72573D431D6B9E72004975AD /* sctest-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "sctest-entitlements.plist"; path = "sctest/sctest-entitlements.plist"; sourceTree = SOURCE_ROOT; };
725CB7541BF439C6000C05A8 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
725CB7571BF51476000C05A8 /* configAgentDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = configAgentDefines.h; sourceTree = "<group>"; };
725E53D51A92D2A5009997E1 /* com.apple.networking.IPMonitor */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.networking.IPMonitor; sourceTree = "<group>"; };
726DB2F11BEA80E5001B2C6C /* config_agent_info.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = config_agent_info.c; path = "config-agent-info/config_agent_info.c"; sourceTree = "<group>"; };
726DB2F21BEA80E5001B2C6C /* config_agent_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config_agent_info.h; path = "config-agent-info/config_agent_info.h"; sourceTree = "<group>"; };
+ 7271EA321D76600B0055B1AA /* sctest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sctest; sourceTree = BUILT_PRODUCTS_DIR; };
728015751BE16833009F4F60 /* agent-monitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = "agent-monitor.m"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
728015781BE16833009F4F60 /* configAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = configAgent.h; sourceTree = "<group>"; };
728015791BE16833009F4F60 /* configAgent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = configAgent.m; sourceTree = "<group>"; };
728015931BE1697E009F4F60 /* agent-monitor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "agent-monitor.h"; sourceTree = "<group>"; };
728015951BE16B6C009F4F60 /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = System/Library/PrivateFrameworks/Network.framework; sourceTree = SDKROOT; };
728015961BE16B6C009F4F60 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };
+ 728E0E951D70229A00E0613A /* SCTestReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCTestReachability.m; 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>"; };
+ 72C12CAA1D6E9ED4000EE61C /* npt_configd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = npt_configd.plist; sourceTree = "<group>"; };
72D3E6591AE6E8A900DB4C69 /* Modules */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Modules; path = SystemConfiguration.fproj/Modules; sourceTree = SOURCE_ROOT; };
72D3E65E1AE6EA3A00DB4C69 /* SCTest-Swift */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "SCTest-Swift"; sourceTree = BUILT_PRODUCTS_DIR; };
72D3E6601AE6EA3A00DB4C69 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 72573D231D667372004975AD /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72573D451D6BA976004975AD /* libnetwork.dylib in Frameworks */,
+ 72573D441D6BA051004975AD /* Network.framework in Frameworks */,
+ 72573D351D6680AA004975AD /* SystemConfiguration.framework in Frameworks */,
+ 728E0E971D70348D00E0613A /* NetworkExtension.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 7271EA271D76600B0055B1AA /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 7271EA281D76600B0055B1AA /* libnetwork.dylib in Frameworks */,
+ 7271EA291D76600B0055B1AA /* Network.framework in Frameworks */,
+ 7271EA2A1D76600B0055B1AA /* SystemConfiguration.framework in Frameworks */,
+ 7271EA2B1D76600B0055B1AA /* NetworkExtension.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
72D3E65B1AE6EA3900DB4C69 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
159D53C907528B36004F8947 /* common */ = {
isa = PBXGroup;
children = (
- F9A3780E16A4846E00C57CDC /* IPMonitorControlPrefs.c */,
+ 15FB1F891E27E9A000B4F809 /* InterfaceNamerControlPrefs.h */,
+ 15FB1F881E27E9A000B4F809 /* InterfaceNamerControlPrefs.c */,
F9A3780F16A4846E00C57CDC /* IPMonitorControlPrefs.h */,
+ F9A3780E16A4846E00C57CDC /* IPMonitorControlPrefs.c */,
159D53CA07528B36004F8947 /* cache.c */,
159D53CB07528B36004F8947 /* cache.h */,
1572AA8B1D8234500021E093 /* plugin_shared.h */,
15CB6A6E05C0722B0099E85F /* External Frameworks and Libraries */,
72D3E65F1AE6EA3A00DB4C69 /* SCTest-Swift */,
72D3E66A1AE6EAF600DB4C69 /* SCTest-ObjC */,
+ 72573D271D667372004975AD /* sctest */,
15CB690F05C0722B0099E85F /* Products */,
90507AAE1CE2F55B0067D16B /* Frameworks */,
);
155F49931C864F3700E47D08 /* QoSMarking.bundle */,
155F499C1C864F4E00E47D08 /* libQoSMarking.a */,
155F49A21C864F5400E47D08 /* QoSMarking.bundle */,
+ 72573D261D667372004975AD /* sctest */,
+ 7271EA321D76600B0055B1AA /* sctest */,
);
name = Products;
sourceTree = "<group>";
name = "Supporting Files";
sourceTree = "<group>";
};
+ 72573D271D667372004975AD /* sctest */ = {
+ isa = PBXGroup;
+ children = (
+ 72573D361D668B3C004975AD /* genSCTestOptions.c */,
+ 72573D381D6692BA004975AD /* SCTestOptions.h */,
+ 72573D391D6692BA004975AD /* SCTestOptions.m */,
+ 72573D301D6675AF004975AD /* SCTestUtils.h */,
+ 72573D311D667686004975AD /* SCTestUtils.m */,
+ 72573D2F1D6673C6004975AD /* SCTest.h */,
+ 72573D281D667372004975AD /* main.m */,
+ 72573D2D1D6673B6004975AD /* SCTest.m */,
+ 72573D3B1D6695B4004975AD /* SCTestDynamicStore.m */,
+ 72573D3D1D669AA6004975AD /* SCTestPreferences.m */,
+ 72573D411D6B7989004975AD /* SCTestConfigAgents.m */,
+ 728E0E951D70229A00E0613A /* SCTestReachability.m */,
+ 72573D3F1D67B2BE004975AD /* SCTestUnitTest.m */,
+ 72573D431D6B9E72004975AD /* sctest-entitlements.plist */,
+ 72C12CAA1D6E9ED4000EE61C /* npt_configd.plist */,
+ );
+ path = sctest;
+ sourceTree = "<group>";
+ };
725E53D41A92D289009997E1 /* Simulator */ = {
isa = PBXGroup;
children = (
90507AAE1CE2F55B0067D16B /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 72573D331D66800C004975AD /* SystemConfiguration.framework */,
90507AB11CE2F5720067D16B /* libnetwork.dylib */,
90507AAF1CE2F55B0067D16B /* libnetwork.dylib */,
);
155847520754FDCD0046C2E9 /* net_service.h in Headers */,
155847530754FDCD0046C2E9 /* net_set.h in Headers */,
72B43728113C7BFC00EBF1B6 /* nc.h in Headers */,
+ 1581BCD31E28679A00F69B1E /* InterfaceNamerControlPrefs.h in Headers */,
+ 1581BCD51E2867A500F69B1E /* IPMonitorControlPrefs.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
15732ABA16EA511900F3AC4C /* net_service.h in Headers */,
15732ABB16EA511900F3AC4C /* net_set.h in Headers */,
15732ABC16EA511900F3AC4C /* nc.h in Headers */,
+ 1581BCD91E2867C100F69B1E /* IPMonitorControlPrefs.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
157433FD0D4A8137002ACA73 /* net_service.h in Headers */,
157433FE0D4A8137002ACA73 /* net_set.h in Headers */,
72B4372A113C7BFC00EBF1B6 /* nc.h in Headers */,
+ 1581BCDD1E286E0000F69B1E /* InterfaceNamerControlPrefs.h in Headers */,
+ 1581BCD71E2867B200F69B1E /* IPMonitorControlPrefs.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
153ACCAC14E322D5005029A5 /* network_information_server.h in Headers */,
720A4C0A1C585C7D007436B8 /* configAgent.h in Headers */,
1596A7B514EDB73D00798C39 /* libSystemConfiguration_server.h in Headers */,
+ 1581BCD61E2867AF00F69B1E /* IPMonitorControlPrefs.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
- 1572AA8C1D8235390021E093 /* plugin_shared.h in Headers */,
+ 15A9BDA81D8DEA67007024DB /* plugin_shared.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
buildActionMask = 2147483647;
files = (
1572AA8F1D82375A0021E093 /* plugin_shared.h in Headers */,
+ 1581BCD21E28673600F69B1E /* InterfaceNamerControlPrefs.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
7280159D1BE1812B009F4F60 /* dnsAgent.h in Headers */,
7280159E1BE1812B009F4F60 /* proxyAgent.h in Headers */,
155D223B0AF13A7300D52ED0 /* dns-configuration.h in Headers */,
+ 1581BCD41E2867A300F69B1E /* IPMonitorControlPrefs.h in Headers */,
15D48EC00F67061700B4711E /* dnsinfo_create.h in Headers */,
725CB7581BF514F2000C05A8 /* configAgentDefines.h in Headers */,
E4F211D7137B0AF200BBB915 /* network_state_information_priv.h in Headers */,
15E1B04516EBAE3C00E5F06F /* network_state_information_priv.h in Headers */,
15E1B04616EBAE3C00E5F06F /* proxy-configuration.h in Headers */,
15E1B04816EBAE3C00E5F06F /* network_information_server.h in Headers */,
+ 1581BCD81E2867BA00F69B1E /* IPMonitorControlPrefs.h in Headers */,
15E1B04916EBAE3C00E5F06F /* libSystemConfiguration_server.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
productReference = 15FD72C90754DA7E001CC321 /* PreferencesMonitor.bundle */;
productType = "com.apple.product-type.bundle";
};
+ 72573D251D667372004975AD /* sctest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 72573D2A1D667372004975AD /* Build configuration list for PBXNativeTarget "sctest" */;
+ buildPhases = (
+ 72573D221D667372004975AD /* Sources */,
+ 72573D231D667372004975AD /* Frameworks */,
+ 72573D241D667372004975AD /* npt_configd.plist */,
+ 72C12CB21D6FEFBE000EE61C /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = sctest;
+ productName = sctest;
+ productReference = 72573D261D667372004975AD /* sctest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 7271EA1B1D76600B0055B1AA /* sctest-Embedded */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 7271EA2F1D76600B0055B1AA /* Build configuration list for PBXNativeTarget "sctest-Embedded" */;
+ buildPhases = (
+ 7271EA1D1D76600B0055B1AA /* Sources */,
+ 7271EA271D76600B0055B1AA /* Frameworks */,
+ 7271EA2C1D76600B0055B1AA /* npt_configd.plist */,
+ 7271EA2E1D76600B0055B1AA /* Fix plist ownership */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "sctest-Embedded";
+ productName = sctest;
+ productReference = 7271EA321D76600B0055B1AA /* sctest */;
+ productType = "com.apple.product-type.tool";
+ };
72D3E65D1AE6EA3900DB4C69 /* SCTest-Swift */ = {
isa = PBXNativeTarget;
buildConfigurationList = 72D3E6621AE6EA3A00DB4C69 /* Build configuration list for PBXNativeTarget "SCTest-Swift" */;
attributes = {
LastUpgradeCheck = 0800;
TargetAttributes = {
+ 72573D251D667372004975AD = {
+ CreatedOnToolsVersion = 8.0;
+ ProvisioningStyle = Automatic;
+ };
72D3E65D1AE6EA3900DB4C69 = {
CreatedOnToolsVersion = 7.0;
};
15E83104167F9AF600FD51EC /* EVERYTHING */,
72D3E65D1AE6EA3900DB4C69 /* SCTest-Swift */,
72D3E6681AE6EAF600DB4C69 /* SCTest-ObjC */,
+ 72573D251D667372004975AD /* sctest */,
+ 7271EA1B1D76600B0055B1AA /* sctest-Embedded */,
);
};
/* End PBXProject section */
shellScript = "if [ -x ${SCRIPT_INPUT_FILE_0} ]; then\n\t${SCRIPT_INPUT_FILE_0} com.apple.configd_sim.plist\nfi";
showEnvVarsInLog = 0;
};
+ 7271EA2E1D76600B0055B1AA /* Fix plist ownership */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Fix plist ownership";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "if [ ${UID} -eq 0 ]; then\n\tchown 0:0 \"${DSTROOT}/AppleInternal/CoreOS/BATS/npt_tests/npt_configd.plist\"\nfi\n\nexit 0";
+ };
+ 72C12CB21D6FEFBE000EE61C /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "if [ ${UID} -eq 0 ]; then\n\tchown 0:0 \"${DSTROOT}/AppleInternal/CoreOS/BATS/npt_tests/npt_configd.plist\"\nfi\n\nexit 0";
+ };
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
155847600754FDCD0046C2E9 /* net_service.c in Sources */,
155847610754FDCD0046C2E9 /* net_set.c in Sources */,
72B43729113C7BFC00EBF1B6 /* nc.c in Sources */,
+ 15FB1F8B1E27EA8900B4F809 /* InterfaceNamerControlPrefs.c in Sources */,
F9B50FF316A4CBB200CA274E /* IPMonitorControlPrefs.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
buildActionMask = 2147483647;
files = (
159D541607528DF1004F8947 /* ifnamer.c in Sources */,
+ 15FB1F8A1E27EA8700B4F809 /* InterfaceNamerControlPrefs.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
15D48EBF0F67061600B4711E /* dnsinfo_create.c in Sources */,
1522FCFB0FA7FE4B00B24128 /* dnsinfo_flatfile.c in Sources */,
150BEC1814CA24F900237116 /* dnsinfo_server.c in Sources */,
- F9B7AE6A186211D300C78D18 /* IPMonitorControlServer.c in Sources */,
159D541707528E05004F8947 /* ip_plugin.c in Sources */,
7280158D1BE16861009F4F60 /* dnsAgent.m in Sources */,
E49173E1137C4E4F0000089F /* network_state_information_priv.c in Sources */,
7280158C1BE1685D009F4F60 /* controller.m in Sources */,
D61AAEAF1522C99C0066B003 /* scprefs_observer.c in Sources */,
F9A3781016A4847700C57CDC /* IPMonitorControlPrefs.c in Sources */,
+ F9B7AE6A186211D300C78D18 /* IPMonitorControlServer.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 72573D221D667372004975AD /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72573D3C1D6695B4004975AD /* SCTestDynamicStore.m in Sources */,
+ 72573D3A1D6692BA004975AD /* SCTestOptions.m in Sources */,
+ 72573D321D667686004975AD /* SCTestUtils.m in Sources */,
+ 72573D401D67B2BE004975AD /* SCTestUnitTest.m in Sources */,
+ 728E0E961D70229A00E0613A /* SCTestReachability.m in Sources */,
+ 72573D291D667372004975AD /* main.m in Sources */,
+ 72573D421D6B798A004975AD /* SCTestConfigAgents.m in Sources */,
+ 72573D3E1D669AA6004975AD /* SCTestPreferences.m in Sources */,
+ 72573D2E1D6673B6004975AD /* SCTest.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 7271EA1D1D76600B0055B1AA /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 7271EA1E1D76600B0055B1AA /* SCTestDynamicStore.m in Sources */,
+ 7271EA1F1D76600B0055B1AA /* SCTestOptions.m in Sources */,
+ 7271EA201D76600B0055B1AA /* SCTestUtils.m in Sources */,
+ 7271EA211D76600B0055B1AA /* SCTestUnitTest.m in Sources */,
+ 7271EA221D76600B0055B1AA /* SCTestReachability.m in Sources */,
+ 7271EA231D76600B0055B1AA /* main.m in Sources */,
+ 7271EA241D76600B0055B1AA /* SCTestConfigAgents.m in Sources */,
+ 7271EA251D76600B0055B1AA /* SCTestPreferences.m in Sources */,
+ 7271EA261D76600B0055B1AA /* SCTest.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
72D3E65A1AE6EA3900DB4C69 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
target = 15DAD63F07591A1A0084A6ED /* SystemConfiguration.framework */;
targetProxy = 723050331AE6F29D004AC149 /* PBXContainerItemProxy */;
};
+ 7271EA341D7660980055B1AA /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7271EA1B1D76600B0055B1AA /* sctest-Embedded */;
+ targetProxy = 7271EA331D7660980055B1AA /* PBXContainerItemProxy */;
+ };
+ 72C12CB11D6EA2CA000EE61C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72573D251D667372004975AD /* sctest */;
+ targetProxy = 72C12CB01D6EA2CA000EE61C /* PBXContainerItemProxy */;
+ };
72C4A4801BE44D19009D570E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 155847430754FDCD0046C2E9 /* scutil */;
};
name = Release;
};
+ 72573D2B1D667372004975AD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CODE_SIGN_ENTITLEMENTS = "sctest/sctest-entitlements.plist";
+ CODE_SIGN_IDENTITY = "-";
+ FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+ HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+ INSTALL_PATH = /usr/local/bin;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ PLIST_FILE_OUTPUT_FORMAT = "same-as-input";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 72573D2C1D667372004975AD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CODE_SIGN_ENTITLEMENTS = "sctest/sctest-entitlements.plist";
+ CODE_SIGN_IDENTITY = "-";
+ FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+ HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+ INSTALL_PATH = /usr/local/bin;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PLIST_FILE_OUTPUT_FORMAT = "same-as-input";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 7271EA301D76600B0055B1AA /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CODE_SIGN_ENTITLEMENTS = "sctest/sctest-entitlements.plist";
+ CODE_SIGN_IDENTITY = "-";
+ FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+ HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+ INSTALL_PATH = /usr/local/bin;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ PLIST_FILE_OUTPUT_FORMAT = "same-as-input";
+ PRODUCT_NAME = sctest;
+ SDKROOT = iphoneos.internal;
+ SUPPORTED_PLATFORMS = iphoneos;
+ };
+ name = Debug;
+ };
+ 7271EA311D76600B0055B1AA /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CODE_SIGN_ENTITLEMENTS = "sctest/sctest-entitlements.plist";
+ CODE_SIGN_IDENTITY = "-";
+ FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+ HEADER_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+ INSTALL_PATH = /usr/local/bin;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PLIST_FILE_OUTPUT_FORMAT = "same-as-input";
+ PRODUCT_NAME = sctest;
+ SDKROOT = iphoneos.internal;
+ SUPPORTED_PLATFORMS = iphoneos;
+ };
+ name = Release;
+ };
72D3E6631AE6EA3A00DB4C69 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 72573D2A1D667372004975AD /* Build configuration list for PBXNativeTarget "sctest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 72573D2B1D667372004975AD /* Debug */,
+ 72573D2C1D667372004975AD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 7271EA2F1D76600B0055B1AA /* Build configuration list for PBXNativeTarget "sctest-Embedded" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 7271EA301D76600B0055B1AA /* Debug */,
+ 7271EA311D76600B0055B1AA /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
72D3E6621AE6EA3A00DB4C69 /* Build configuration list for PBXNativeTarget "SCTest-Swift" */ = {
isa = XCConfigurationList;
buildConfigurations = (
#!/bin/sh
-# Copyright (c) 2004-2015 Apple Inc.
+# Copyright (c) 2004-2017 Apple Inc.
#
# get-mobility-info
#
PATH=/bin:/usr/bin:/sbin:/usr/sbin
+OUTDIR=""
+NO_PCAP=0
+NO_TAR=0
+
+while getopts f:PT OPTION ; do
+ case ${OPTION} in
+ f)
+ OUTDIR="${OPTARG}"
+ if [ ! -d "${OUTDIR}" ]; then
+ echo "# ${PROGNAME}: \"${OUTDIR}\" is not a directory"
+ exit 1
+ fi
+ ;;
+ P)
+ NO_PCAP=1
+ ;;
+ T)
+ NO_TAR=1
+ ;;
+ \?)
+ ;;
+ esac
+done
+
#
# Disclaimer
#
fi
OUT="mobility-info-`date +'%Y.%m.%d.%H%M%S'`"
-OUTDIR="/var/tmp"
-if [ -d ~/Desktop ]; then
- OUTDIR=~/Desktop
-elif [ "`readlink /tmp`" = "private/var/tmp" ]; then
- OUTDIR=/Library/Logs/CrashReporter
- mkdir -p ${OUTDIR}
+
+if [ -z $OUTDIR ]; then
+ OUTDIR="/var/tmp"
+ if [ -d ~/Desktop ]; then
+ OUTDIR=~/Desktop
+ elif [ "`readlink /tmp`" = "private/var/tmp" ]; then
+ OUTDIR=/Library/Logs/CrashReporter
+ mkdir -p ${OUTDIR}
+ fi
fi
umask 077
exit 1
fi
-GZ_EXT=""
-GZ_OPT=""
-if [ -x /usr/bin/gzip ]; then
- GZ_EXT=".gz"
- GZ_OPT="-z"
-fi
+if [ $NO_TAR -eq 0 ]; then
+ GZ_EXT=""
+ GZ_OPT=""
+ if [ -x /usr/bin/gzip ]; then
+ GZ_EXT=".gz"
+ GZ_OPT="-z"
+ fi
-ARCHIVE=`mktemp -q "${OUTDIR}/${OUT}.tar${GZ_EXT}"`
-if [ $? -ne 0 ]; then
- echo "Could not create snapshot archive"
- rm -rf "${WORKDIR}"
- exit 1
+ ARCHIVE=`mktemp -q "${OUTDIR}/${OUT}.tar${GZ_EXT}"`
+ if [ $? -ne 0 ]; then
+ echo "Could not create snapshot archive"
+ rm -rf "${WORKDIR}"
+ exit 1
+ fi
fi
cd "${WORKDIR}"
echo "Please wait, collecting information and statistics"
echo ""
+#
+# collect packet capture with kernel ring buffer if available
+#
+if [ -x /usr/local/bin/netdiagnose -a ${NO_PCAP} -ne 1 ]; then
+ /usr/local/bin/netdiagnose -p "${WORKDIR}" start packetcapture 2>&1
+fi
+
#
# get-network-info
#
if [ -x /System/Library/Frameworks/SystemConfiguration.framework/Resources/get-network-info ]; then
- /System/Library/Frameworks/SystemConfiguration.framework/Resources/get-network-info -s -c "${WORKDIR}"
+ /System/Library/Frameworks/SystemConfiguration.framework/Resources/get-network-info -s -c -P "${WORKDIR}"
elif [ -x /System/Library/Frameworks/SystemConfiguration.framework/get-network-info ]; then
- /System/Library/Frameworks/SystemConfiguration.framework/get-network-info -s -c "${WORKDIR}"
+ /System/Library/Frameworks/SystemConfiguration.framework/get-network-info -s -c -P "${WORKDIR}"
elif [ -x /System/Library/PrivateFrameworks/SystemConfiguration.framework/get-network-info ]; then
- /System/Library/PrivateFrameworks/SystemConfiguration.framework/get-network-info -s -c "${WORKDIR}"
+ /System/Library/PrivateFrameworks/SystemConfiguration.framework/get-network-info -s -c -P "${WORKDIR}"
fi
#
wait
#
-# collect everything into a single archive
+# Stop the packet capture
#
-cd "${WORKDIR}/.."
-tar -c ${GZ_OPT} -f "${ARCHIVE}" "${OUT}"
-rm -rf "${WORKDIR}"
+if [ -x /usr/local/bin/netdiagnose -a ${NO_PCAP} -ne 1 ]; then
+ /usr/local/bin/netdiagnose stop packetcapture 2>&1
+fi
-if [ ${UID} -eq 0 ]; then
- if [ -n "${SUDO_UID}" -a -n "${SUDO_GID}" ]; then
- if [ ${UID} -ne ${SUDO_UID} ]; then
- chown ${SUDO_UID}:${SUDO_GID} "${ARCHIVE}"
+if [ $NO_TAR -eq 0 ]; then
+ #
+ # collect everything into a single archive
+ #
+ cd "${WORKDIR}/.."
+ tar -c ${GZ_OPT} -f "${ARCHIVE}" "${OUT}"
+ rm -rf "${WORKDIR}"
+
+ if [ ${UID} -eq 0 ]; then
+ if [ -n "${SUDO_UID}" -a -n "${SUDO_GID}" ]; then
+ if [ ${UID} -ne ${SUDO_UID} ]; then
+ chown ${SUDO_UID}:${SUDO_GID} "${ARCHIVE}"
+ fi
fi
fi
-fi
-echo "Network data collected to \"${ARCHIVE}\""
+ echo "Network data collected to \"${ARCHIVE}\""
+else
+ mv "${WORKDIR}" "${OUTDIR}"
+ if [ ${UID} -eq 0 ]; then
+ if [ -n "${SUDO_UID}" -a -n "${SUDO_GID}" ]; then
+ if [ ${UID} -ne ${SUDO_UID} ]; then
+ chown -R ${SUDO_UID}:${SUDO_GID} "${OUTDIR}/${OUT}"
+ fi
+ fi
+ fi
+ echo "Network data collected to \"${OUTDIR}/${OUT}\""
+fi
COLLECT_NDF_INFO="Y"
shift
;;
+ -P)
+ COLLECT_PCAP="N"
+ shift
+ ;;
-s)
COLLECT_SENSITIVE_INFO="Y"
shift
}
+start_pcap() {
+
+ #
+ # collect a packet capture if netdiagnose is available
+ #
+ if [ -x /usr/local/bin/netdiagnose ]; then
+ /usr/local/bin/netdiagnose -p "${REQUESTED_OUTDIR}" start sysdiagpcap 2>&1
+
+ PCAP_STARTED=1
+ fi
+}
+
+stop_pcap () {
+ if [ ${PCAP_STARTED} -ne 0 ]; then
+ /usr/local/bin/netdiagnose stop sysdiagpcap 2>&1
+ fi
+}
+
collect_ndf_info () {
run_lsof
}
collect_sensitive_info () {
+
+ if [ "${COLLECT_PCAP}" == "Y" ]; then
+ start_pcap
+ fi
+
collect_state_dump_sensitive
run_ndp
run_arp
if [ "${COLLECT_CONFIGURATION_FILES}" == "Y" ]; then
collect_configuration_files
fi
+
+ stop_pcap
}
# __COMMAND_ROUTINES_END__
echo "Usage: get-network-info [-c] [-n] [-s] <info-directory>"
echo " -c collects system configuration files"
echo " -n collects NDF information (lsof)"
+ echo " -P do not collect a packet capture"
echo " -s collects sensitive information (ARP/NDP/mDNS cache)"
echo " <info-directory> path to directory where all the information will be collected"
REQUESTED_OUTDIR=""
COLLECT_SENSITIVE_INFO=""
COLLECT_CONFIGURATION_FILES=""
+ COLLECT_PCAP="Y"
+ PCAP_STARTED=0
+
}
# __HELPER_ROUTINES_END__
#
# __MAIN__
#
-ARGS=`getopt cns $*`
+ARGS=`getopt cnPs $*`
if [ $? != 0 ]; then
usage
exit 1
--- /dev/null
+#
+# Makefile for generating the SCTestOptions.[mh] files
+#
+
+all: SCTestOptions.h SCTestOptions.m
+
+/tmp/genSCTestOptions: genSCTestOptions.c Makefile
+ cc -g -o /tmp/genSCTestOptions genSCTestOptions.c
+
+SCTestOptions.h: /tmp/genSCTestOptions
+ /tmp/genSCTestOptions header > SCTestOptions.h
+
+SCTestOptions.m: /tmp/genSCTestOptions
+ /tmp/genSCTestOptions mfile > SCTestOptions.m
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 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 SCTest_h
+#define SCTest_h
+
+#import <Foundation/Foundation.h>
+#import "SCTestOptions.h"
+#import "SCTestUtils.h"
+
+@interface SCTest : NSObject
+
+@property (atomic, retain) NSDictionary *options;
+@property (atomic) CPUUsageInfo *globalCPU;
+@property (atomic) timerInfo *globalTimer;
+
+- (instancetype)initWithOptions:(NSDictionary *)options;
+- (void)start;
+- (void)cleanupAndExitWithErrorCode:(int)error;
+- (BOOL)unitTest;
+- (void)waitFor:(double)seconds;
+
++ (NSString *)command;
++ (NSString *)commandDescription;
+
+@end
+
+#endif /* SCTest_h */
--- /dev/null
+/*
+ * Copyright (c) 2016 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@
+ */
+
+#import "SCTest.h"
+
+@implementation SCTest
+
+- (instancetype)initWithOptions:(NSDictionary *)options
+{
+ self = [super init];
+ if (self) {
+ self.options = options;
+ self.globalCPU = malloc(sizeof(CPUUsageInfo));
+ self.globalTimer = malloc(sizeof(timerInfo));
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ if (self.globalTimer != NULL) {
+ free(self.globalTimer);
+ }
+ if (self.globalCPU != NULL) {
+ free(self.globalCPU);
+ }
+}
+
++ (NSString *)command
+{
+ return @"sctest";
+}
+
++ (NSString *)commandDescription
+{
+ return @"This is a generic class";
+}
+
++ (NSString *)commandHelp
+{
+ return @"This is a generic help";
+}
+
+- (void)start
+{
+ return;
+}
+
+- (void)waitFor:(double)seconds
+{
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0);
+ dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
+ dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, 0);
+ dispatch_source_set_event_handler(timer, ^{
+ dispatch_semaphore_signal(sem);
+ });
+ dispatch_resume(timer);
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+}
+
+- (void)cleanupAndExitWithErrorCode:(int)error
+{
+ if (self.options[kSCTestGlobalOptionTime] != nil) {
+ timerEnd(self.globalTimer);
+ SCTestLog("Time: %@ s", createUsageStringForTimer(self.globalTimer));
+ }
+
+ if (self.options[kSCTestGlobalOptionCPU] != nil) {
+ cpuEnd(self.globalCPU);
+ SCTestLog("CPU: %@", createUsageStringForCPU(self.globalCPU));
+ }
+
+ if (self.options[kSCTestGlobalOptionWait] != nil) {
+ return;
+ }
+ exit(error);
+}
+
+- (BOOL)unitTest
+{
+ return YES;
+}
+
+@end
--- /dev/null
+/*
+ * Copyright (c) 2016 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@
+ */
+
+#import "SCTest.h"
+#import "SCTestUtils.h"
+#import <Network/Network_Private.h>
+#import <CoreFoundation/CFXPCBridge.h>
+#import <config_agent_info.h>
+
+#define TEST_DOMAIN "filemaker.com"
+#define PATH_QUIESCE_TIME 1.5 // seconds
+
+@interface SCTestConfigAgent : SCTest
+@property NSString *serviceID;
+@property NSString *proxyKey;
+@property NSString *dnsKey;
+@property NSArray<NSArray<NSDictionary *> *> *testProxy;
+@property NSArray<NWEndpoint *> *testDNS;
+@property SCDynamicStoreRef store;
+@property (copy) NSArray<NSArray<NSDictionary *> *> *pathProxy;
+@property (copy) NSArray<NWEndpoint *> *pathDNS;
+@end
+
+@implementation SCTestConfigAgent
+
+- (instancetype)initWithOptions:(NSDictionary *)options
+{
+ self = [super initWithOptions:options];
+ if (self) {
+ _serviceID = @"8F66B505-EAEF-4611-BD4D-C523FD9451F0";
+ _store = SCDynamicStoreCreate(kCFAllocatorDefault,
+ CFSTR("SCTest"),
+ NULL,
+ NULL);
+ _proxyKey = (__bridge_transfer NSString *)[self copyStateKeyWithServiceID:(__bridge CFStringRef)(self.serviceID) forEntity:kSCEntNetProxies];
+ _dnsKey = (__bridge_transfer NSString *)[self copyStateKeyWithServiceID:(__bridge CFStringRef)(self.serviceID) forEntity:kSCEntNetDNS];
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ if (self.store != NULL) {
+ CFRelease(self.store);
+ self.store = NULL;
+ }
+}
+
++ (NSString *)command
+{
+ return @"config_agent";
+}
+
++ (NSString *)commandDescription
+{
+ return @"Tests the Config Agent code path";
+}
+
+- (void)start
+{
+ if (self.options[kSCTestConfigAgentRemoveProxy]) {
+ [self removeFromSCDynamicStore:self.proxyKey];
+ }
+
+ if (self.options[kSCTestConfigAgentRemoveDNS]) {
+ [self removeFromSCDynamicStore:self.dnsKey];
+ }
+
+ NSDictionary *proxyConfig = [self parseProxyAgentOptions];
+ if (proxyConfig != nil) {
+ [self publishToSCDynamicStore:self.proxyKey value:proxyConfig];
+ self.testProxy = @[@[proxyConfig]];
+ }
+
+ NSDictionary *dnsConfig = [self parseDNSAgentOptions];
+ if (dnsConfig != nil) {
+ [self publishToSCDynamicStore:self.dnsKey value:dnsConfig];
+ self.testDNS = [self createDNSArray:dnsConfig];
+ }
+
+ [self cleanupAndExitWithErrorCode:0];
+}
+
+- (CFStringRef)copyStateKeyWithServiceID:(CFStringRef)serviceID
+ forEntity:(CFStringRef)entity
+{
+ return SCDynamicStoreKeyCreateNetworkServiceEntity(kCFAllocatorDefault,
+ kSCDynamicStoreDomainState,
+ serviceID,
+ entity);
+}
+
+- (NSArray<NWEndpoint *> *)createDNSArray:(NSDictionary *)dnsConfig
+{
+ NSArray<NSString *> *dnsServers;
+ NSMutableArray<NWEndpoint *> *dnsArray;
+
+ dnsServers = [dnsConfig objectForKey:(__bridge NSString *)kSCPropNetDNSServerAddresses];
+ if (dnsServers == nil || [dnsServers count] == 0) {
+ return nil;
+ }
+
+ dnsArray = [[NSMutableArray alloc] init];
+ for (NSString *server in dnsServers) {
+ NWEndpoint *endpoint = (NWEndpoint *)[NWAddressEndpoint endpointWithHostname:server port:@"0"];
+ [dnsArray addObject:endpoint];
+ }
+
+ return dnsArray;
+}
+
+- (void)publishToSCDynamicStore:(NSString *)key
+ value:(NSDictionary *)value
+{
+
+ BOOL ok = SCDynamicStoreSetValue(self.store, (__bridge CFStringRef)key, (__bridge CFPropertyListRef _Nonnull)(value));
+ if (!ok) {
+ int error = SCError();
+ if (error == kSCStatusNoKey) {
+ return;
+ }
+ SCTestLog("Could not set in SCDynamicStore: Error: %s", SCErrorString(error));
+ return;
+ }
+}
+
+- (void)removeFromSCDynamicStore:(NSString *)key
+{
+ BOOL ok = SCDynamicStoreRemoveValue(self.store, (__bridge CFStringRef)key);
+ if (!ok) {
+ int error = SCError();
+ if (error == kSCStatusNoKey) {
+ return;
+ }
+ SCTestLog("Could not remove key: %@, Error: %s", key, SCErrorString(error));
+ return;
+ }
+}
+
+- (NSDictionary *)parseProxyAgentOptions
+{
+ NSMutableDictionary *proxyConfig = [[NSMutableDictionary alloc] init];
+
+#define NS_NUMBER(x) [NSNumber numberWithInt:x]
+
+#define SET_PROXY_CONFIG(proxyType) \
+ do { \
+ if (self.options[kSCTestConfigAgent ## proxyType ## Proxy] != nil) { \
+ NSString *serverAndPortString = self.options[kSCTestConfigAgent ## proxyType ## Proxy]; \
+ NSArray<NSString *> *serverAndPortArray = [serverAndPortString componentsSeparatedByString:@":"]; \
+ if ([serverAndPortArray count] != 2) { \
+ SCTestLog("server address or port missing"); \
+ ERR_EXIT; \
+ } \
+ NSString *server = [serverAndPortArray objectAtIndex:0]; \
+ NSString *port = [serverAndPortArray objectAtIndex:1]; \
+ [proxyConfig setObject:server forKey:(__bridge NSString *)kSCPropNetProxies ## proxyType ## Proxy]; \
+ [proxyConfig setObject:NS_NUMBER(port.intValue) forKey:(__bridge NSString *)kSCPropNetProxies ## proxyType ## Port]; \
+ [proxyConfig setObject:NS_NUMBER(1) forKey:(__bridge NSString *)kSCPropNetProxies ## proxyType ## Enable]; \
+ } \
+ } while(0);
+
+ SET_PROXY_CONFIG(HTTP);
+ SET_PROXY_CONFIG(HTTPS);
+ SET_PROXY_CONFIG(FTP);
+ SET_PROXY_CONFIG(Gopher);
+ SET_PROXY_CONFIG(SOCKS);
+
+ if ([proxyConfig count] > 0) {
+ NSString *matchDomain = self.options[kSCTestConfigAgentProxyMatchDomain] ? self.options[kSCTestConfigAgentProxyMatchDomain] : @TEST_DOMAIN;
+ [proxyConfig setObject:@[matchDomain] forKey:(__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains];
+ } else {
+ proxyConfig = nil;
+ }
+
+ return proxyConfig;
+#undef SET_PROXY_CONFIG
+}
+
+- (NSDictionary *)parseDNSAgentOptions
+{
+ NSMutableDictionary *dnsConfig;
+ NSString *dnsServerString;
+ NSString *dnsDomainString;
+ NSArray<NSString *> *dnsServers;
+ NSArray<NSString *> *dnsDomains;
+
+ dnsConfig = [[NSMutableDictionary alloc] init];
+ dnsServerString = self.options[kSCTestConfigAgentDNSServers];
+ if (dnsServerString == nil) {
+ return nil;
+ }
+
+ dnsDomainString = self.options[kSCTestConfigAgentDNSDomains];
+ if (dnsDomainString == nil) {
+ dnsDomainString = @TEST_DOMAIN;
+ }
+
+ dnsServers = [dnsServerString componentsSeparatedByString:@","];
+ [dnsConfig setObject:dnsServers forKey:(__bridge NSString *)kSCPropNetDNSServerAddresses];
+
+ dnsDomains = [dnsDomainString componentsSeparatedByString:@","];
+ [dnsConfig setObject:dnsDomains forKey:(__bridge NSString *)kSCPropNetDNSSupplementalMatchDomains];
+
+ return dnsConfig;
+}
+
+- (void)cleanupAndExitWithErrorCode:(int)error
+{
+ CFRelease(self.store);
+ [super cleanupAndExitWithErrorCode:error];
+}
+
+- (BOOL)setup
+{
+ return YES;
+}
+
+- (BOOL)unitTest
+{
+ if(![self setup]) {
+ return NO;
+ }
+
+ BOOL allUnitTestsPassed = YES;
+ allUnitTestsPassed &= [self unitTestInstallProxy];
+ allUnitTestsPassed &= [self unitTestInstallProxyWithLargeConfig];
+ allUnitTestsPassed &= [self unitTestInstallProxyWithConflictingDomain];
+ allUnitTestsPassed &= [self unitTestInstallDNS];
+ allUnitTestsPassed &= [self unitTestInstallDNSWithConflictingDomain];
+
+ if(![self tearDown]) {
+ return NO;
+ }
+
+ return allUnitTestsPassed;
+}
+
+- (BOOL)unitTestInstallProxy
+{
+ BOOL success = NO;
+ SCTestConfigAgent *test;
+ NSDictionary *proxyConfig;
+ NSString *hostname;
+ NSNumber *port;
+ NWHostEndpoint *hostEndpoint;
+ NWPathEvaluator *pathEvaluator;
+ NSMutableDictionary *dict;
+
+ test = [[SCTestConfigAgent alloc] initWithOptions:self.options];
+ proxyConfig = [test parseProxyAgentOptions];
+ if (proxyConfig == nil) {
+ // Use default options
+ proxyConfig = @{(__bridge NSString *)kSCPropNetProxiesHTTPEnable:@(1),
+ (__bridge NSString *)kSCPropNetProxiesHTTPPort:@(80),
+ (__bridge NSString *)kSCPropNetProxiesHTTPProxy:@"10.10.10.100",
+ (__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains:@[@TEST_DOMAIN],
+ };
+ }
+
+ hostname = [[proxyConfig objectForKey:(__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains] objectAtIndex:0];
+ port = [proxyConfig objectForKey:(__bridge NSString *)kSCPropNetProxiesHTTPPort];
+ hostEndpoint = [NWHostEndpoint endpointWithHostname:hostname port:port.stringValue];
+ pathEvaluator = [[NWPathEvaluator alloc] initWithEndpoint:hostEndpoint parameters:NULL];
+ [pathEvaluator addObserver:test
+ forKeyPath:@"path"
+ options:NSKeyValueObservingOptionNew
+ context:nil];
+
+ do {
+ [test publishToSCDynamicStore:test.proxyKey value:proxyConfig];
+ dict = [NSMutableDictionary dictionaryWithDictionary:proxyConfig];
+ [dict removeObjectForKey:(__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains];
+ test.testProxy = @[@[dict]];
+
+ // Wait for the path changes to quiesce
+ [test waitFor:PATH_QUIESCE_TIME];
+ if (![test.testProxy isEqualToArray:test.pathProxy]) {
+ SCTestLog("test proxy and applied proxy do not match. Test: %@, Applied: %@", test.testProxy, test.pathProxy);
+ break;
+ }
+
+ SCTestLog("Verified the configured proxy is the same as applied proxy");
+ [test removeFromSCDynamicStore:test.proxyKey];
+ test.testProxy = nil;
+ // Wait for the path changes to quiesce
+ [test waitFor:PATH_QUIESCE_TIME];
+ if (test.pathProxy != nil) {
+ SCTestLog("proxy applied when there is no test proxy");
+ break;
+ }
+
+ success = YES;
+ } while(0);
+
+ [pathEvaluator removeObserver:test
+ forKeyPath:@"path"];
+
+ return success;
+}
+
+- (BOOL)unitTestInstallDNS
+{
+ BOOL success = NO;
+ SCTestConfigAgent *test;
+ NSDictionary *dnsConfig;
+ NSString *hostname;
+ NWHostEndpoint *hostEndpoint;
+ NWPathEvaluator *pathEvaluator;
+
+ test = [[SCTestConfigAgent alloc] initWithOptions:self.options];
+ dnsConfig = [test parseDNSAgentOptions];
+ if (dnsConfig == nil) {
+ dnsConfig = @{ (__bridge NSString *)kSCPropNetDNSServerAddresses:@[@"10.10.10.101", @"10.10.10.102", @"10.10.10.103"],
+ (__bridge NSString *)kSCPropNetDNSSupplementalMatchDomains:@[@TEST_DOMAIN],
+ };
+ }
+
+ hostname = [[dnsConfig objectForKey:(__bridge NSString *)kSCPropNetDNSSupplementalMatchDomains] objectAtIndex:0];
+ hostEndpoint = [NWHostEndpoint endpointWithHostname:hostname port:@"80"];
+ pathEvaluator = [[NWPathEvaluator alloc] initWithEndpoint:hostEndpoint parameters:NULL];
+ [pathEvaluator addObserver:test
+ forKeyPath:@"path"
+ options:NSKeyValueObservingOptionNew
+ context:nil];
+
+ do {
+ [test publishToSCDynamicStore:test.dnsKey value:dnsConfig];
+ test.testDNS = [test createDNSArray:dnsConfig];
+
+ // Wait for the path changes to quiesce
+ [test waitFor:PATH_QUIESCE_TIME];
+ if (![test.testDNS isEqualToArray:test.pathDNS]) {
+ SCTestLog("test DNS and applied DNS do not match. Test: %@, Applied: %@", test.testDNS, test.pathDNS);
+ break;
+ }
+
+ [test removeFromSCDynamicStore:test.dnsKey];
+ test.testDNS = nil;
+ [test waitFor:PATH_QUIESCE_TIME];
+
+ SCTestLog("Verified that the configured DNS is same as applied DNS for a domain");
+ success = YES;
+ } while (0);
+
+ [pathEvaluator removeObserver:test
+ forKeyPath:@"path"];
+
+ return success;
+}
+
+- (BOOL)unitTestInstallProxyWithLargeConfig
+{
+ BOOL success = NO;
+ SCTestConfigAgent *test;
+ NSString *str = @"0123456789";
+ NSMutableString *largeStr;
+ NSDictionary *proxyConfig;
+ NSString *hostname;
+ NSNumber *port;
+ NWHostEndpoint *hostEndpoint;
+ NWPathEvaluator *pathEvaluator;
+ NSMutableDictionary *dict;
+
+ test = [[SCTestConfigAgent alloc] initWithOptions:self.options];
+ largeStr = [[NSMutableString alloc] init];
+ for (int i = 0; i < 200; i++) {
+ [largeStr appendString:str];
+ }
+
+ // We imitate a proxy config worth 2K bytes.
+ proxyConfig = @{(__bridge NSString *)kSCPropNetProxiesHTTPEnable:@(1),
+ (__bridge NSString *)kSCPropNetProxiesHTTPPort:@(80),
+ (__bridge NSString *)kSCPropNetProxiesHTTPProxy:@"10.10.10.100",
+ (__bridge NSString *)kSCPropNetProxiesProxyAutoConfigJavaScript:largeStr,
+ (__bridge NSString *)kSCPropNetProxiesProxyAutoConfigEnable:@(1),
+ (__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains:@[@TEST_DOMAIN],
+ };
+
+ hostname = [[proxyConfig objectForKey:(__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains] objectAtIndex:0];
+ port = [proxyConfig objectForKey:(__bridge NSString *)kSCPropNetProxiesHTTPPort];
+ hostEndpoint = [NWHostEndpoint endpointWithHostname:hostname port:port.stringValue];
+ pathEvaluator = [[NWPathEvaluator alloc] initWithEndpoint:hostEndpoint parameters:NULL];
+ [pathEvaluator addObserver:test
+ forKeyPath:@"path"
+ options:NSKeyValueObservingOptionNew
+ context:nil];
+
+ do {
+ [test publishToSCDynamicStore:test.proxyKey value:proxyConfig];
+ dict = [NSMutableDictionary dictionaryWithDictionary:proxyConfig];
+ [dict removeObjectForKey:(__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains];
+ test.testProxy = @[@[dict]];
+
+ // Wait for the path changes to quiesce
+ [test waitFor:PATH_QUIESCE_TIME];
+ if ([test.testProxy isEqualToArray:test.pathProxy]) {
+ SCTestLog("applied proxy does not contain Out of Band Agent UUID");
+ break;
+ }
+
+ // Now we verify that we are able to fetch the proxy configuration from configd
+ for (NSArray<NSDictionary *> *config in test.pathProxy) {
+ xpc_object_t xpcConfig = _CFXPCCreateXPCObjectFromCFObject((__bridge CFArrayRef)config);
+ xpc_object_t fetchedConfig = config_agent_update_proxy_information(xpcConfig);
+ if (fetchedConfig != nil) {
+ NSArray *nsConfig = (__bridge_transfer NSArray *)(_CFXPCCreateCFObjectFromXPCObject(fetchedConfig));
+ test.pathProxy = @[nsConfig];
+ break;
+ }
+ }
+
+ if (![test.testProxy isEqualToArray:test.pathProxy]) {
+ SCTestLog("Could not fetch proxy configuration from configd. Test: %@, Applied: %@", test.testProxy, test.pathProxy);
+ break;
+ }
+
+ SCTestLog("Verified that the proxy configuration is successfully fetched from configd");
+ test.testProxy = nil;
+ [test removeFromSCDynamicStore:test.proxyKey];
+
+ // Wait for the path changes to quiesce
+ [test waitFor:PATH_QUIESCE_TIME];
+ if (test.pathProxy != nil) {
+ SCTestLog("proxy applied when there is no test proxy");
+ break;
+ }
+
+ success = YES;
+ } while (0);
+
+ [pathEvaluator removeObserver:test
+ forKeyPath:@"path"];
+
+ return success;
+}
+
+- (BOOL)unitTestInstallDNSWithConflictingDomain
+{
+ BOOL success = NO;
+ SCTestConfigAgent *test;
+ NSDictionary *dnsConfig;
+ NSString *hostname;
+ NWHostEndpoint *hostEndpoint;
+ NWPathEvaluator *pathEvaluator;
+
+ test = [[SCTestConfigAgent alloc] initWithOptions:self.options];
+ dnsConfig = @{ (__bridge NSString *)kSCPropNetDNSServerAddresses:@[@"10.10.10.101", @"10.10.10.102", @"10.10.10.103"],
+ (__bridge NSString *)kSCPropNetDNSSupplementalMatchDomains:@[@TEST_DOMAIN],
+ };
+
+ hostname = [[dnsConfig objectForKey:(__bridge NSString *)kSCPropNetDNSSupplementalMatchDomains] objectAtIndex:0];
+ hostEndpoint = [NWHostEndpoint endpointWithHostname:hostname port:@"80"];
+ pathEvaluator = [[NWPathEvaluator alloc] initWithEndpoint:hostEndpoint parameters:NULL];
+ [pathEvaluator addObserver:test
+ forKeyPath:@"path"
+ options:NSKeyValueObservingOptionNew
+ context:nil];
+
+ do {
+ NSDictionary *duplicateDnsConfig;
+ NSString *anotherFakeServiceID;
+ NSString *anotherDNSKey;
+ NSArray *array;
+ NSSet *testDNSSet;
+ NSSet *pathDNSSet;
+
+ [test publishToSCDynamicStore:test.dnsKey value:dnsConfig];
+ test.testDNS = [test createDNSArray:dnsConfig];
+
+ // Wait for the path changes to quiesce
+ [test waitFor:PATH_QUIESCE_TIME];
+ if (![test.testDNS isEqualToArray:test.pathDNS]) {
+ SCTestLog("test DNS and applied DNS do not match. Test: %@, Applied: %@", test.testDNS, test.pathDNS);
+ break;
+ }
+
+ // Now install the conflicting DNS configuration
+ duplicateDnsConfig = @{ (__bridge NSString *)kSCPropNetDNSServerAddresses:@[@"10.10.10.104", @"10.10.10.105", @"10.10.10.106"],
+ (__bridge NSString *)kSCPropNetDNSSupplementalMatchDomains:@[@TEST_DOMAIN],
+ };
+
+ anotherFakeServiceID = [NSUUID UUID].UUIDString;
+ anotherDNSKey = (__bridge_transfer NSString *)[self copyStateKeyWithServiceID:(__bridge CFStringRef)(anotherFakeServiceID) forEntity:kSCEntNetDNS];
+
+ [test publishToSCDynamicStore:anotherDNSKey value:duplicateDnsConfig];
+ array = [test.testDNS arrayByAddingObjectsFromArray:[test createDNSArray:duplicateDnsConfig]];
+ test.testDNS = array;
+
+ // Wait for the path changes to quiesce
+ [test waitFor:PATH_QUIESCE_TIME];
+
+ // Use NSSet for unordered comparison
+ testDNSSet = [NSSet setWithArray:test.testDNS];
+ pathDNSSet = [NSSet setWithArray:test.pathDNS];
+ success = [testDNSSet isEqualToSet:pathDNSSet];
+ [test removeFromSCDynamicStore:anotherDNSKey];
+ if (!success) {
+ SCTestLog("test DNS and applied DNS for duplicate domains do not match. Test: %@, Applied: %@", test.testDNS, test.pathDNS);
+ break;
+ }
+
+ [test removeFromSCDynamicStore:test.dnsKey];
+ test.testDNS = nil;
+ [test waitFor:PATH_QUIESCE_TIME];
+
+ SCTestLog("Verified that the configured DNS with duplicate domains is same as applied DNS for a domain");
+ success = YES;
+
+ } while (0);
+
+ [pathEvaluator removeObserver:test
+ forKeyPath:@"path"];
+
+ return success;
+}
+
+- (BOOL)unitTestInstallProxyWithConflictingDomain
+{
+ BOOL success = NO;
+ SCTestConfigAgent *test;
+ NSDictionary *proxyConfig;
+ NSString *hostname;
+ NSNumber *port;
+ NWHostEndpoint *hostEndpoint;
+ NWPathEvaluator *pathEvaluator;
+
+ test = [[SCTestConfigAgent alloc] initWithOptions:self.options];
+ proxyConfig = @{(__bridge NSString *)kSCPropNetProxiesHTTPEnable:@(1),
+ (__bridge NSString *)kSCPropNetProxiesHTTPPort:@(80),
+ (__bridge NSString *)kSCPropNetProxiesHTTPProxy:@"10.10.10.100",
+ (__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains:@[@TEST_DOMAIN],
+ };
+
+ hostname = [[proxyConfig objectForKey:(__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains] objectAtIndex:0];
+ port = [proxyConfig objectForKey:(__bridge NSString *)kSCPropNetProxiesHTTPPort];
+ hostEndpoint = [NWHostEndpoint endpointWithHostname:hostname port:port.stringValue];
+ pathEvaluator = [[NWPathEvaluator alloc] initWithEndpoint:hostEndpoint parameters:NULL];
+ [pathEvaluator addObserver:test
+ forKeyPath:@"path"
+ options:NSKeyValueObservingOptionNew
+ context:nil];
+
+ do {
+ NSMutableDictionary *dict;
+ NSMutableDictionary *dict2;
+ NSDictionary *duplicateProxyConfig;
+ NSString *anotherFakeServiceID;
+ NSString *anotherProxyKey;
+ NSSet *testProxySet;
+ NSSet *pathProxySet;
+
+ [test publishToSCDynamicStore:test.proxyKey value:proxyConfig];
+ dict = [NSMutableDictionary dictionaryWithDictionary:proxyConfig];
+ [dict removeObjectForKey:(__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains];
+ test.testProxy = @[@[dict]];
+
+ // Wait for the path changes to quiesce
+ [test waitFor:PATH_QUIESCE_TIME];
+ if (![test.testProxy isEqualToArray:test.pathProxy]) {
+ SCTestLog("test proxy and applied proxy do not match. Test: %@, Applied: %@", test.testProxy, test.pathProxy);
+ break;
+ }
+
+ // Now install the conflicting Proxy configuration
+ duplicateProxyConfig = @{(__bridge NSString *)kSCPropNetProxiesHTTPSEnable:@(1),
+ (__bridge NSString *)kSCPropNetProxiesHTTPSPort:@(8080),
+ (__bridge NSString *)kSCPropNetProxiesHTTPSProxy:@"10.10.10.101",
+ (__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains:@[@TEST_DOMAIN],
+ };
+ anotherFakeServiceID = [NSUUID UUID].UUIDString;
+ anotherProxyKey = (__bridge_transfer NSString *)[self copyStateKeyWithServiceID:(__bridge CFStringRef)(anotherFakeServiceID) forEntity:kSCEntNetProxies];
+
+ [test publishToSCDynamicStore:anotherProxyKey value:duplicateProxyConfig];;
+ dict2 = [NSMutableDictionary dictionaryWithDictionary:duplicateProxyConfig];
+ [dict2 removeObjectForKey:(__bridge NSString *)kSCPropNetProxiesSupplementalMatchDomains];
+ test.testProxy = @[@[dict],@[dict2]];
+
+ // Wait for the path changes to quiesce
+ [test waitFor:PATH_QUIESCE_TIME];
+
+ // Use NSSet for unordered comparison
+ testProxySet = [NSSet setWithArray:test.testProxy];
+ pathProxySet = [NSSet setWithArray:test.pathProxy];
+ success = [testProxySet isEqualToSet:pathProxySet];
+ [test removeFromSCDynamicStore:anotherProxyKey];
+ if (!success) {
+ SCTestLog("test proxy and applied proxy for duplicate domains do not match. Test: %@, Applied: %@", test.testDNS, test.pathDNS);
+ break;
+ }
+
+ SCTestLog("Verified the configured proxy with Duplicate domains is the same as applied proxy");
+
+ [test removeFromSCDynamicStore:test.proxyKey];
+ test.testProxy = nil;
+
+ // Wait for the path changes to quiesce
+ [test waitFor:PATH_QUIESCE_TIME];
+
+ if (test.pathProxy != nil) {
+ SCTestLog("proxy applied when there is no test proxy");
+ break;
+ }
+
+ success = YES;
+
+ } while(0);
+
+ [pathEvaluator removeObserver:test
+ forKeyPath:@"path"];
+
+ return success;
+}
+
+- (BOOL)tearDown
+{
+ [self removeFromSCDynamicStore:self.proxyKey];
+ [self removeFromSCDynamicStore:self.dnsKey];
+ return YES;
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+ ofObject:(id)object
+ change:(NSDictionary *)change
+ context:(void *)context
+{
+ NWPathEvaluator *pathEvaluator = (NWPathEvaluator *)object;
+ if ([keyPath isEqualToString:@"path"]) {
+ self.pathProxy = pathEvaluator.path.proxySettings;
+ self.pathDNS = pathEvaluator.path.dnsServers;
+ }
+}
+
+@end
--- /dev/null
+/*
+ * Copyright (c) 2016 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@
+ */
+
+#import "SCTest.h"
+#import "SCTestUtils.h"
+
+@interface SCTestDynamicStore : SCTest
+@property SCDynamicStoreRef store;
+@property dispatch_semaphore_t sem;
+@property int counter;
+@end
+
+@implementation SCTestDynamicStore
+
++ (NSString *)command
+{
+ return @"dynamic_store";
+}
+
++ (NSString *)commandDescription
+{
+ return @"Tests the SCDynamicStore code path";
+}
+
+- (instancetype)initWithOptions:(NSDictionary *)options
+{
+ self = [super initWithOptions:options];
+ if (self) {
+ _store = SCDynamicStoreCreate(kCFAllocatorDefault,
+ CFSTR("SCTest"),
+ NULL,
+ NULL);
+ if (_store == NULL) {
+ SCTestLog("Could not create session");
+ ERR_EXIT;
+ }
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ if (self.store != NULL) {
+ CFRelease(self.store);
+ self.store = NULL;
+ }
+}
+
+- (void)start
+{
+ CFStringRef key;
+ if (self.options[kSCTestDynamicStoreOptionDNS]) {
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetDNS);
+ CFPropertyListRef value = SCDynamicStoreCopyValue(self.store, key);
+ SCTestLog("%@ : %@", key, value);
+ CFRelease(key);
+ }
+
+ if (self.options[kSCTestDynamicStoreOptionIPv4]) {
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetIPv4);
+ CFPropertyListRef value = SCDynamicStoreCopyValue(self.store, key);
+ SCTestLog("%@ : %@", key, value);
+ CFRelease(key);
+ }
+
+ if (self.options[kSCTestDynamicStoreOptionIPv6]) {
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetIPv6);
+ CFPropertyListRef value = SCDynamicStoreCopyValue(self.store, key);
+ SCTestLog("%@ : %@", key, value);
+ CFRelease(key);
+ }
+
+ if (self.options[kSCTestDynamicStoreOptionProxies]) {
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetProxies);
+ CFPropertyListRef value = SCDynamicStoreCopyValue(self.store, key);
+ SCTestLog("%@ : %@", key, value);
+ CFRelease(key);
+ }
+
+ [self cleanupAndExitWithErrorCode:0];
+}
+
+- (void)cleanupAndExitWithErrorCode:(int)error
+{
+ [super cleanupAndExitWithErrorCode:error];
+}
+
+- (BOOL)setup
+{
+ return YES;
+}
+
+- (BOOL)unitTest
+{
+ if(![self setup]) {
+ return NO;
+ }
+
+ BOOL allUnitTestsPassed = YES;
+ allUnitTestsPassed &= [self unitTestSetAndRemoveValue];
+ allUnitTestsPassed &= [self unitTestCopyMultiple];
+ allUnitTestsPassed &= [self unitTestSCDynamicStoreCallbackStress];
+ allUnitTestsPassed &= [self unitTestSCDynamicStoreSetMultipleStress];
+
+ if(![self tearDown]) {
+ return NO;
+ }
+
+ return allUnitTestsPassed;
+}
+
+- (BOOL)tearDown
+{
+ return YES;
+}
+
+- (BOOL)unitTestSetAndRemoveValue
+{
+ int iterations = 1000;
+ NSDictionary *bogusValue;
+ SCTestDynamicStore *test;
+
+ test = [[SCTestDynamicStore alloc] initWithOptions:self.options];
+ bogusValue = @{@"Pretty":@"Useless"};
+
+ for (int i = 0; i < iterations; i++) {
+ NSUUID *uuid = [NSUUID UUID];
+ CFStringRef key;
+ BOOL ok;
+
+ key = SCDynamicStoreKeyCreateNetworkServiceEntity(kCFAllocatorDefault,
+ CFSTR("SCTest"),
+ (__bridge CFStringRef)uuid.UUIDString,
+ kSCEntNetDNS);
+ ok = SCDynamicStoreSetValue(test.store, key, (__bridge CFDictionaryRef)bogusValue);
+ if (!ok) {
+ SCTestLog("Failed to set value in SCDynamicStore. Error: %s", SCErrorString(SCError()));
+ CFRelease(key);
+ return NO;
+ }
+
+ ok = SCDynamicStoreRemoveValue(test.store, key);
+ if (!ok) {
+ SCTestLog("Failed to remove value from SCDynamicStore. Error: %s", SCErrorString(SCError()));
+ CFRelease(key);
+ return NO;
+ }
+
+ CFRelease(key);
+ }
+
+ SCTestLog("Successfully completed setAndRemove unit test");
+ return YES;
+}
+
+- (BOOL)unitTestCopyMultiple
+{
+ NSString *pattern;
+ SCTestDynamicStore *test;
+ CFArrayRef keyList;
+ int iterations = 1000;
+
+ test = [[SCTestDynamicStore alloc] initWithOptions:self.options];
+ pattern = (__bridge_transfer NSString *)SCDynamicStoreKeyCreate(kCFAllocatorDefault,
+ CFSTR("%@/%@/%@/%@/%@"),
+ kSCDynamicStoreDomainState,
+ kSCCompNetwork,
+ kSCCompInterface,
+ kSCCompAnyRegex,
+ kSCCompAnyRegex);
+
+ keyList = SCDynamicStoreCopyKeyList(test.store, (__bridge CFStringRef)pattern);
+ for (int i = 0; i < iterations; i++) {
+ CFDictionaryRef value = SCDynamicStoreCopyMultiple(test.store, keyList, NULL);
+ if (value == NULL) {
+ SCTestLog("Failed to copy multiple values from SCDynamicStore. Error: %s", SCErrorString(SCError()));
+ CFRelease(keyList);
+ return NO;
+ }
+ CFRelease(value);
+ }
+ CFRelease(keyList);
+
+ pattern = (__bridge_transfer NSString *)SCDynamicStoreKeyCreate(kCFAllocatorDefault,
+ CFSTR("%@/%@/%@/%@/%@"),
+ kSCDynamicStoreDomainSetup,
+ kSCCompNetwork,
+ kSCCompService,
+ kSCCompAnyRegex,
+ kSCCompAnyRegex);
+
+ keyList = SCDynamicStoreCopyKeyList(test.store, (__bridge CFStringRef)pattern);
+ for (int i = 0; i < iterations; i++) {
+ CFDictionaryRef value = SCDynamicStoreCopyMultiple(test.store, keyList, NULL);
+ if (value == NULL) {
+ SCTestLog("Failed to copy multiple values from SCDynamicStore. Error: %s", SCErrorString(SCError()));
+ CFRelease(keyList);
+ return NO;
+ }
+ CFRelease(value);
+ }
+ CFRelease(keyList);
+
+ SCTestLog("Successfully completed copyMultiple unit test");
+ return YES;
+}
+
+void
+myTestCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *ctx)
+{
+ SCTestDynamicStore *test = (__bridge SCTestDynamicStore *)ctx;
+ test.counter++;
+ if (test.sem != NULL) {
+ dispatch_semaphore_signal(test.sem);
+ }
+}
+
+- (BOOL)unitTestSCDynamicStoreCallbackStress
+{
+ SCTestDynamicStore *test;
+ int iterations = 100;
+ NSString *testKey = @"State:/myTestKey";
+ BOOL ok;
+ dispatch_queue_t callbackQ;
+
+ test = [[SCTestDynamicStore alloc] initWithOptions:self.options];
+ if (test.store != NULL) {
+ CFRelease(test.store);
+ test.store = NULL;
+ }
+
+ SCDynamicStoreContext ctx = {0, (__bridge void * _Nullable)(test), CFRetain, CFRelease, NULL};
+ test.store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("SCTest"), myTestCallback, &ctx);
+
+ ok = SCDynamicStoreSetNotificationKeys(test.store, (__bridge CFArrayRef)@[testKey], NULL);
+ if (!ok) {
+ SCTestLog("Failed to set notification keys. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ callbackQ = dispatch_queue_create("SCTestDynamicStore callback queue", NULL);
+ ok = SCDynamicStoreSetDispatchQueue(test.store, callbackQ);
+ if (!ok) {
+ SCTestLog("Failed to set dispatch queue. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ for (int i = 0; i < iterations; i++) {
+ NSUUID *uuid = [NSUUID UUID];
+ ok = SCDynamicStoreSetValue(test.store, (__bridge CFStringRef)testKey, (__bridge CFStringRef)uuid.UUIDString);
+ if (!ok) {
+ SCTestLog("Failed to set value. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+ // Perform a write to Dynamic Store every 10ms.
+ [test waitFor:0.01];
+ }
+
+ ok = SCDynamicStoreRemoveValue(test.store, (__bridge CFStringRef)testKey);
+ if (!ok) {
+ SCTestLog("Failed to remove value. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ if (test.counter < iterations) {
+ // Not all callbacks were received
+ SCTestLog("Not all SCDynamicStore callbacks were received (%d/%d). Something went wrong", test.counter, iterations);
+ return NO;
+ }
+
+ SCTestLog("Successfully completed SCDynamicStore callbacks unit test");
+ return YES;
+}
+
+- (BOOL)unitTestSCDynamicStoreSetMultipleStress
+{
+ SCTestDynamicStore *test;
+ int iterations = 100;
+ NSMutableArray *testKeyArray;
+ NSMutableDictionary *testSetDictionary;
+ int expectedCallbackCount = 0;
+ BOOL ok;
+ dispatch_queue_t callbackQ;
+ uint8_t waitTime = 1; // second
+
+ test = [[SCTestDynamicStore alloc] initWithOptions:self.options];
+ if (test.store != NULL) {
+ CFRelease(test.store);
+ test.store = NULL;
+ }
+
+ SCDynamicStoreContext ctx = {0, (__bridge void * _Nullable)(test), CFRetain, CFRelease, NULL};
+ test.store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("SCTest"), myTestCallback, &ctx);
+ test.sem = dispatch_semaphore_create(0);
+
+ testKeyArray = [[NSMutableArray alloc] init];
+
+ for (int i = 0; i < iterations; i++) {
+ NSUUID *uuid = [NSUUID UUID];
+ NSString *str = [NSString stringWithFormat:@"State:/%@", uuid];
+ [testKeyArray addObject:str];
+ }
+
+ testSetDictionary = [[NSMutableDictionary alloc] init];
+ for (NSString *key in testKeyArray) {
+ NSUUID *uuid = [NSUUID UUID];
+ [testSetDictionary setObject:@[uuid.UUIDString] forKey:key];
+ }
+
+ callbackQ = dispatch_queue_create("SCTestDynamicStore callback queue", NULL);
+ ok = SCDynamicStoreSetNotificationKeys(test.store, (__bridge CFArrayRef)testKeyArray, NULL);
+ if (!ok) {
+ SCTestLog("Failed to set notification keys. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ ok = SCDynamicStoreSetDispatchQueue(test.store, callbackQ);
+ if (!ok) {
+ SCTestLog("Failed to set dispatch queue. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ ok = SCDynamicStoreSetMultiple(test.store, (__bridge CFDictionaryRef)testSetDictionary, NULL, NULL);
+ if (!ok) {
+ SCTestLog("Failed to set multiple keys. Error: %s", SCErrorString(SCError()));
+ return NO;
+ } else {
+ expectedCallbackCount++; // One callback for set multiple
+ }
+
+ if(dispatch_semaphore_wait(test.sem, dispatch_time(DISPATCH_TIME_NOW, waitTime * NSEC_PER_SEC))) {
+ SCTestLog("Failed to get a callback when multiple keys are set");
+ return NO;
+ }
+
+ ok = SCDynamicStoreSetMultiple(test.store, NULL, NULL, (__bridge CFArrayRef)testKeyArray);
+ if (!ok) {
+ SCTestLog("Failed to set multiple keys. Error: %s", SCErrorString(SCError()));
+ return NO;
+ } else {
+ expectedCallbackCount++; // One callback for fake notification
+ }
+
+ if(dispatch_semaphore_wait(test.sem, dispatch_time(DISPATCH_TIME_NOW, waitTime * NSEC_PER_SEC))) {
+ SCTestLog("Failed to get a callback when multiple keys are notified");
+ return NO;
+ }
+
+ ok = SCDynamicStoreSetMultiple(test.store, NULL, (__bridge CFArrayRef)testKeyArray, NULL);
+ if (!ok) {
+ SCTestLog("Failed to set multiple keys. Error: %s", SCErrorString(SCError()));
+ return NO;
+ } else {
+ expectedCallbackCount++; // One callback for key removal
+ }
+
+ if(dispatch_semaphore_wait(test.sem, dispatch_time(DISPATCH_TIME_NOW, waitTime * NSEC_PER_SEC))) {
+ SCTestLog("Failed to get a callback when multiple keys are removed");
+ return NO;
+ }
+
+ if (test.counter < expectedCallbackCount) {
+ // Not all callbacks were received
+ SCTestLog("Not all SCDynamicStore callbacks were received (%d/%d). Something went wrong", test.counter, expectedCallbackCount);
+ return NO;
+ }
+
+ SCTestLog("Successfully completed SCDynamicStore set multiple unit test");
+ return YES;
+
+}
+
+
+@end
--- /dev/null
+//
+// This file is automatically generated. DO NOT EDIT!
+// To add options, see genSCTestOptions.c
+//
+#import <Foundation/Foundation.h>
+#import <getopt.h>
+
+extern const NSString * const kSCTestGlobalOptionCPU;
+extern const NSString * const kSCTestGlobalOptionHelp;
+extern const NSString * const kSCTestGlobalOptionTime;
+extern const NSString * const kSCTestGlobalOptionVerbose;
+extern const NSString * const kSCTestGlobalOptionWait;
+extern const NSString * const kSCTestDynamicStoreOptionDNS;
+extern const NSString * const kSCTestDynamicStoreOptionIPv4;
+extern const NSString * const kSCTestDynamicStoreOptionIPv6;
+extern const NSString * const kSCTestDynamicStoreOptionProxies;
+extern const NSString * const kSCTestPreferencesServiceList;
+extern const NSString * const kSCTestPreferencesServiceOrder;
+extern const NSString * const kSCTestConfigAgentDNSDomains;
+extern const NSString * const kSCTestConfigAgentDNSServers;
+extern const NSString * const kSCTestConfigAgentRemoveDNS;
+extern const NSString * const kSCTestConfigAgentFTPProxy;
+extern const NSString * const kSCTestConfigAgentGopherProxy;
+extern const NSString * const kSCTestConfigAgentHTTPProxy;
+extern const NSString * const kSCTestConfigAgentHTTPSProxy;
+extern const NSString * const kSCTestConfigAgentProxyMatchDomain;
+extern const NSString * const kSCTestConfigAgentRemoveProxy;
+extern const NSString * const kSCTestConfigAgentSOCKSProxy;
+extern const NSString * const kSCTestReachabilityAddress;
+extern const NSString * const kSCTestReachabilityHost;
+extern const NSString * const kSCTestReachabilityInterface;
+extern const NSString * const kSCTestReachabilityWatch;
+extern const NSString * const kSCTestUnitTestCommand;
+extern const NSString * const kSCTestUnitTestListTests;
+extern const NSString * const kSCTestUnitTestTestMethod;
+extern const NSString * const kSCTestUnitTestTestMethodList;
+
+
+
+#define kSCTestOptionEntries \
+ {"cpu", 0, NULL, 0}, \
+ {"help", 0, NULL, 0}, \
+ {"time", 0, NULL, 0}, \
+ {"verbose", 0, NULL, 0}, \
+ {"wait", 0, NULL, 0}, \
+ {"dns", 0, NULL, 0}, \
+ {"ipv4", 0, NULL, 0}, \
+ {"ipv6", 0, NULL, 0}, \
+ {"proxies", 0, NULL, 0}, \
+ {"service_list", 0, NULL, 0}, \
+ {"service_order", 0, NULL, 0}, \
+ {"dns_domain", 1, NULL, 0}, \
+ {"dns_servers", 1, NULL, 0}, \
+ {"remove_dns", 0, NULL, 0}, \
+ {"ftp_proxy", 1, NULL, 0}, \
+ {"gopher_proxy", 1, NULL, 0}, \
+ {"http_proxy", 1, NULL, 0}, \
+ {"https_proxy", 1, NULL, 0}, \
+ {"proxy_match_domain", 1, NULL, 0}, \
+ {"remove_proxy", 0, NULL, 0}, \
+ {"socks_proxy", 1, NULL, 0}, \
+ {"address", 1, NULL, 0}, \
+ {"host", 1, NULL, 0}, \
+ {"interface", 1, NULL, 0}, \
+ {"watch", 0, NULL, 0}, \
+ {"command", 1, NULL, 0}, \
+ {"list_tests", 0, NULL, 0}, \
+ {"test_method", 1, NULL, 0}, \
+ {"test_method_list", 0, NULL, 0}, \
+
+#define kSCTestOptionHelp \
+ "\n============== global options =============\n"\
+ "-cpu : Prints the CPU usage after the test completes\n"\
+ "-help : Prints this very useful help!\n"\
+ "-time : Prints the time elapsed since the test was launched\n"\
+ "-verbose : Enables verbose mode\n"\
+ "-wait : Results in a wait for 'sctest'\n"\
+ "\n============== dynamic_store options =============\n"\
+ "-dns : Prints the global DNS information from the SCDynamicStore\n"\
+ "-ipv4 : Prints the global IPv4 information from the SCDynamicStore\n"\
+ "-ipv6 : Prints the global IPv6 information from the SCDynamicStore\n"\
+ "-proxies : Prints the global Proxy information from the SCDynamicStore\n"\
+ "\n============== preferences options =============\n"\
+ "-service_list : Prints the Network Services list from the preferences\n"\
+ "-service_order : Prints the Network Service order from the preferences\n"\
+ "\n============== config_agent options =============\n"\
+ "-dns_domain : Configures the DNS Servers for certain domains. A comma-separated list of domains can be specified. Default is 'apple.com'\n"\
+ "-dns_servers : Configures the specified DNS Servers. A comma-separated list of IP Addresses can be specified\n"\
+ "-remove_dns : Remove a dns configuration, previously configured via 'sctest'\n"\
+ "-ftp_proxy : Add a proxy agent with FTP proxy. Format of the argument is 'server:port'\n"\
+ "-gopher_proxy : Add a proxy agent with Gopher proxy. Format of the argument is 'server:port'\n"\
+ "-http_proxy : Add a proxy agent with HTTP proxy. Format of the argument is 'server:port'\n"\
+ "-https_proxy : Add a proxy agent with HTTPS proxy. Format of the argument is 'server:port'\n"\
+ "-proxy_match_domain : Add a proxy agent for a match domain. If this option is not specified, 'apple.com' will be used\n"\
+ "-remove_proxy : Remove a proxy configuration, previously configured via 'sctest'\n"\
+ "-socks_proxy : Add a proxy agent with SOCKS proxy. Format of the argument is 'server:port'\n"\
+ "\n============== reachability options =============\n"\
+ "-address : Determine reachability to this address\n"\
+ "-host : Determine reachability to this host\n"\
+ "-interface : Determine reachability when scoped to this interface\n"\
+ "-watch : Watch for reachability changes\n"\
+ "\n============== unit_test options =============\n"\
+ "-command : Run a unit test for a specific command. If this option is not specified, unit-tests for all commands will be run\n"\
+ "-list_tests : List the test commands in a JSON format. This is for NPT compliance\n"\
+ "-test_method : Runs a specific unit test. List can be obtained by using the 'test_method_list' option\n"\
+ "-test_method_list : Lists all the unit tests. A specific one can be run using the 'test_method' option\n"\
--- /dev/null
+//
+// This file is automatically generated. DO NOT EDIT!
+// To add options, see genSCTestOptions.c
+//
+#import "SCTestOptions.h"
+
+const NSString * const kSCTestGlobalOptionCPU = @"cpu_Str";
+const NSString * const kSCTestGlobalOptionHelp = @"help_Str";
+const NSString * const kSCTestGlobalOptionTime = @"time_Str";
+const NSString * const kSCTestGlobalOptionVerbose = @"verbose_Str";
+const NSString * const kSCTestGlobalOptionWait = @"wait_Str";
+const NSString * const kSCTestDynamicStoreOptionDNS = @"dns_Str";
+const NSString * const kSCTestDynamicStoreOptionIPv4 = @"ipv4_Str";
+const NSString * const kSCTestDynamicStoreOptionIPv6 = @"ipv6_Str";
+const NSString * const kSCTestDynamicStoreOptionProxies = @"proxies_Str";
+const NSString * const kSCTestPreferencesServiceList = @"service_list_Str";
+const NSString * const kSCTestPreferencesServiceOrder = @"service_order_Str";
+const NSString * const kSCTestConfigAgentDNSDomains = @"dns_domain_Str";
+const NSString * const kSCTestConfigAgentDNSServers = @"dns_servers_Str";
+const NSString * const kSCTestConfigAgentRemoveDNS = @"remove_dns_Str";
+const NSString * const kSCTestConfigAgentFTPProxy = @"ftp_proxy_Str";
+const NSString * const kSCTestConfigAgentGopherProxy = @"gopher_proxy_Str";
+const NSString * const kSCTestConfigAgentHTTPProxy = @"http_proxy_Str";
+const NSString * const kSCTestConfigAgentHTTPSProxy = @"https_proxy_Str";
+const NSString * const kSCTestConfigAgentProxyMatchDomain = @"proxy_match_domain_Str";
+const NSString * const kSCTestConfigAgentRemoveProxy = @"remove_proxy_Str";
+const NSString * const kSCTestConfigAgentSOCKSProxy = @"socks_proxy_Str";
+const NSString * const kSCTestReachabilityAddress = @"address_Str";
+const NSString * const kSCTestReachabilityHost = @"host_Str";
+const NSString * const kSCTestReachabilityInterface = @"interface_Str";
+const NSString * const kSCTestReachabilityWatch = @"watch_Str";
+const NSString * const kSCTestUnitTestCommand = @"command_Str";
+const NSString * const kSCTestUnitTestListTests = @"list_tests_Str";
+const NSString * const kSCTestUnitTestTestMethod = @"test_method_Str";
+const NSString * const kSCTestUnitTestTestMethodList = @"test_method_list_Str";
--- /dev/null
+/*
+ * Copyright (c) 2016 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@
+ */
+
+#import "SCTest.h"
+#import "SCTestUtils.h"
+
+@interface SCTestPreferences : SCTest
+@property SCPreferencesRef prefs;
+@end
+
+@implementation SCTestPreferences
+
++ (NSString *)command
+{
+ return @"preferences";
+}
+
++ (NSString *)commandDescription
+{
+ return @"Tests the SCPreferences code path";
+}
+
+- (instancetype)initWithOptions:(NSDictionary *)options
+{
+ self = [super initWithOptions:options];
+ if (self) {
+ _prefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("SCTest"), NULL);
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ if (self.prefs != NULL) {
+ CFRelease(self.prefs);
+ self.prefs = NULL;
+ }
+}
+
+- (void)start
+{
+ if (self.options[kSCTestPreferencesServiceList]) {
+ NSDictionary *services = (__bridge NSDictionary *)SCPreferencesGetValue(self.prefs, kSCPrefNetworkServices);
+ if (services != nil) {
+ [self printNetworkServicesFromDict:services];
+ } else {
+ SCTestLog("No services present!");
+ }
+ }
+
+ if (self.options[kSCTestPreferencesServiceOrder]) {
+ SCNetworkSetRef set = SCNetworkSetCopyCurrent(self.prefs);
+ NSArray *serviceID = (__bridge NSArray *)SCNetworkSetGetServiceOrder(set);
+ NSDictionary *services = (__bridge NSDictionary *)SCPreferencesGetValue(self.prefs, kSCPrefNetworkServices);
+ int counter = 1;
+ SCTestLog("Network service order");
+ for (NSString *key in serviceID) {
+ NSDictionary *dict = [services objectForKey:key];
+ SCTestLog("\n%d: %@\n\tUserDefinedName: %@", counter++, key, [dict objectForKey:(__bridge NSString *)kSCPropNetServiceUserDefinedName]);
+ }
+ CFRelease(set);
+ }
+
+ [self cleanupAndExitWithErrorCode:0];
+}
+
+- (void)printNetworkServicesFromDict:(NSDictionary *)serviceDict
+{
+ int counter = 1;
+ SCTestLog("Network Services");
+ for (NSString *key in serviceDict) {
+ NSDictionary *dict = [serviceDict objectForKey:key];
+ SCTestLog("\n%d: %@\n\tUserDefinedName: %@", counter++, key, [dict objectForKey:(__bridge NSString *)kSCPropNetServiceUserDefinedName]);
+ }
+}
+
+- (BOOL)unitTest
+{
+ BOOL allUnitTestsPassed = YES;
+ allUnitTestsPassed &= [self unitTestNetworkServicesSanity];
+ allUnitTestsPassed &= [self unitTestPreferencesAPI];
+ allUnitTestsPassed &= [self unitTestPreferencesSession];
+ return allUnitTestsPassed;
+
+}
+
+- (BOOL)unitTestNetworkServicesSanity
+{
+ // We verify that every service has a unique name, an interface, an IPv4 config method and and IPv6 config method.
+ NSDictionary *services;
+ NSMutableArray *serviceNameArray;
+ SCTestPreferences *test;
+
+ test = [[SCTestPreferences alloc] initWithOptions:self.options];
+ services = (__bridge NSDictionary *)SCPreferencesGetValue(test.prefs, kSCPrefNetworkServices);
+ if (services == NULL) {
+ SCTestLog("No services present!");
+ return NO;
+ }
+
+ serviceNameArray = [[NSMutableArray alloc] init];
+ for (NSString *serviceID in services) {
+ NSDictionary *serviceDict;
+ NSString *serviceName;
+ NSDictionary *interfaceDict;
+ NSString *interfaceType;
+ NSDictionary *ipv4Dict;
+ NSDictionary *ipv6Dict;
+
+ serviceDict = [services objectForKey:serviceID];
+ if (![serviceDict isKindOfClass:[NSDictionary class]]) {
+ SCTestLog("Service is not a dictionary");
+ return NO;
+ }
+
+ serviceName = [serviceDict objectForKey:(__bridge NSString *)kSCPropNetServiceUserDefinedName];
+ if (serviceName != nil) {
+ // Check if the name is unique
+ BOOL namePresent = [serviceNameArray containsObject:serviceName];
+ if (!namePresent) {
+ [serviceNameArray addObject:serviceName];
+ } else {
+ SCTestLog("Duplicate services with name %@ exist", serviceName);
+ return NO;
+ }
+ } else {
+ SCTestLog("Service ID %@ does not have a name", serviceID);
+ return NO;
+ }
+
+ interfaceDict = [serviceDict objectForKey:(__bridge NSString *)kSCCompInterface];
+ if (interfaceDict == nil) {
+ SCTestLog("Service %@ does not have an interface", serviceName);
+ return NO;
+ }
+
+ interfaceType = [interfaceDict objectForKey:(__bridge NSString *)kSCPropNetInterfaceType];
+ if (interfaceType != nil && [interfaceType containsString:@"CommCenter"]) {
+ // CommCenter services typically do not have an ipv4/v6 data OR config method. Skip such services.
+ continue;
+ }
+
+ ipv4Dict = [serviceDict objectForKey:(__bridge NSString *)kSCEntNetIPv4];
+ ipv6Dict = [serviceDict objectForKey:(__bridge NSString *)kSCEntNetIPv6];
+
+ // Check that we have at least one IP config method
+ if (ipv4Dict == nil && ipv6Dict == nil) {
+ SCTestLog("Service %@ does not have an IP dictionary", serviceName);
+ return NO;
+ }
+
+ if ([ipv4Dict objectForKey:(__bridge NSString *)kSCPropNetIPv4ConfigMethod] == nil &&
+ [ipv6Dict objectForKey:(__bridge NSString *)kSCPropNetIPv6ConfigMethod] == nil) {
+ SCTestLog("Service %@ does not have an IP Config Method", serviceName);
+ return NO;
+ }
+ }
+
+ SCTestLog("Verified that the Network Services have valid configurations");
+
+ return YES;
+}
+
+- (BOOL)unitTestPreferencesSession
+{
+ SCPreferencesRef prefs;
+ prefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("SCTest"), NULL);
+ if (prefs == NULL) {
+ SCTestLog("Failed to create SCPreferences. Error: %s", SCErrorString(SCError()));
+ return NO;
+ } else {
+ CFRelease(prefs);
+ }
+
+ prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization, NULL);
+ if (prefs == NULL) {
+ SCTestLog("Failed to create SCPreferences w/options. Error: %s", SCErrorString(SCError()));
+ return NO;
+ } else {
+ CFRelease(prefs);
+ }
+
+ prefs = SCPreferencesCreateWithAuthorization(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization);
+ if (prefs == NULL) {
+ SCTestLog("Failed to create SCPreferences w/options. Error: %s", SCErrorString(SCError()));
+ return NO;
+ } else {
+ CFRelease(prefs);
+ }
+
+ SCTestLog("Verified that the preferences session can be created");
+ return YES;
+}
+
+- (BOOL)unitTestPreferencesAPI
+{
+ BOOL ok = NO;
+ int iterations = 1000;
+ NSDictionary *prefsOptions;
+ NSMutableArray *keys;
+ NSMutableArray *values;
+ SCTestPreferences *test;
+ NSArray *keyList;
+
+ test = [[SCTestPreferences alloc] initWithOptions:self.options];
+ if (test.prefs != NULL) {
+ CFRelease(test.prefs);
+ test.prefs = NULL;
+ }
+
+ prefsOptions = @{(__bridge NSString *)kSCPreferencesOptionRemoveWhenEmpty:(__bridge NSNumber *)kCFBooleanTrue};
+ test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
+ CFSTR("SCTest"),
+ CFSTR("SCTestPreferences.plist"),
+ kSCPreferencesUseEntitlementAuthorization,
+ (__bridge CFDictionaryRef)prefsOptions);
+ if (test.prefs == NULL) {
+ SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ keys = [[NSMutableArray alloc] init];
+ values = [[NSMutableArray alloc] init];
+ for (int i = 0; i < iterations; i++) {
+ NSUUID *uuidKey = [NSUUID UUID];
+ NSUUID *uuidValue = [NSUUID UUID];
+
+ ok = SCPreferencesLock(test.prefs, true);
+ if (!ok) {
+ SCTestLog("Failed to get preferences lock. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ ok = SCPreferencesSetValue(test.prefs, (__bridge CFStringRef)uuidKey.UUIDString, (__bridge CFStringRef)uuidValue.UUIDString);
+ if (!ok) {
+ SCTestLog("Failed to set preferences value. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ ok = SCPreferencesUnlock(test.prefs);
+ if (!ok) {
+ SCTestLog("Failed to release preferences lock. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ [keys addObject:uuidKey.UUIDString];
+ [values addObject:uuidValue.UUIDString];
+ }
+
+ ok = SCPreferencesCommitChanges(test.prefs);
+ if (!ok) {
+ SCTestLog("Failed to commit preferences. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ CFRelease(test.prefs);
+ test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
+ CFSTR("SCTest"),
+ CFSTR("SCTestPreferences.plist"),
+ kSCPreferencesUseEntitlementAuthorization,
+ (__bridge CFDictionaryRef)prefsOptions);
+ if (test.prefs == NULL) {
+ SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ keyList = (__bridge_transfer NSArray *)SCPreferencesCopyKeyList(test.prefs);
+ if ([keyList count] < [keys count]) {
+ SCTestLog("Failed to copy all keys from preferences. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ for (NSString *key in keys) {
+ NSString *valueString = (__bridge NSString *)SCPreferencesGetValue(test.prefs, (__bridge CFStringRef)key);
+ if (!valueString) {
+ SCTestLog("Failed to get value from preferences. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ BOOL ok = [values containsObject:valueString];
+ if (!ok) {
+ SCTestLog("Incorrect value fetched from preferences");
+ return NO;
+ }
+ }
+
+ ok = SCPreferencesRemoveAllValues(test.prefs);
+ if (!ok) {
+ SCTestLog("Failed to remove values preferences. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ ok = SCPreferencesCommitChanges(test.prefs);
+ if (!ok) {
+ SCTestLog("Failed to commit preferences. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ CFRelease(test.prefs);
+ test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
+ CFSTR("SCTest"),
+ CFSTR("SCTestPreferences.plist"),
+ kSCPreferencesUseEntitlementAuthorization,
+ (__bridge CFDictionaryRef)prefsOptions);
+ if (test.prefs == NULL) {
+ SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ keyList = (__bridge_transfer NSArray *)SCPreferencesCopyKeyList(test.prefs);
+ if ([keyList count] > 0) {
+ SCTestLog("Failed to remove all keys from preferences. Error: %s", SCErrorString(SCError()));
+ return NO;
+ }
+
+ SCTestLog("Verified that SCPreferences APIs behave as expected");
+ return ok;
+}
+
+- (void)cleanupAndExitWithErrorCode:(int)error
+{
+ [super cleanupAndExitWithErrorCode:error];
+}
+
+@end
--- /dev/null
+/*
+ * Copyright (c) 2016 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@
+ */
+
+#import "SCTest.h"
+#import "SCTestUtils.h"
+#import <arpa/inet.h>
+#import <NetworkExtension/NEPolicySession.h>
+#import <network_information.h>
+
+#define REACHABILITY_TEST_HOSTNAME "apple.com"
+
+@interface SCTestReachability : SCTest
+@property SCNetworkReachabilityRef target;
+@property dispatch_queue_t callbackQ;
+@end
+
+@implementation SCTestReachability
+
++ (NSString *)command
+{
+ return @"reachability";
+}
+
++ (NSString *)commandDescription
+{
+ return @"Tests the SCNetworkReachability code path";
+}
+
+- (instancetype)initWithOptions:(NSDictionary *)options
+{
+ self = [super initWithOptions:options];
+ if (self) {
+ NSMutableDictionary *reachOptions;
+ if (self.options[kSCTestReachabilityInterface] != nil) {
+ reachOptions = [[NSMutableDictionary alloc] init];
+ [reachOptions setObject:self.options[kSCTestReachabilityInterface] forKey:(__bridge NSString *)kSCNetworkReachabilityOptionInterface];
+ if (self.options[kSCTestReachabilityHost] != nil) {
+ [reachOptions setObject:self.options[kSCTestReachabilityHost] forKey:(__bridge NSString *)kSCNetworkReachabilityOptionNodeName];
+ } else if (self.options[kSCTestReachabilityAddress] != nil) {
+ NSData *data;
+ NSString *addressString = self.options[kSCTestReachabilityAddress];
+ struct sockaddr *sa = _SC_string_to_sockaddr(addressString.UTF8String, AF_INET, NULL, 0);
+ if (sa == NULL) {
+ sa = _SC_string_to_sockaddr(addressString.UTF8String, AF_INET6, NULL, 0);
+ if (sa == NULL) {
+ SCTestLog("Invalid address");
+ ERR_EXIT;
+ }
+ }
+ data = [NSData dataWithBytes:sa length:(sa->sa_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)];
+ [reachOptions setObject:data forKey:(__bridge NSString *)kSCNetworkReachabilityOptionRemoteAddress];
+ }
+
+
+ _target = SCNetworkReachabilityCreateWithOptions(kCFAllocatorDefault, (__bridge CFDictionaryRef)reachOptions);
+ } else if (self.options[kSCTestReachabilityHost]) {
+ NSString *host = self.options[kSCTestReachabilityHost];
+ _target = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, host.UTF8String);
+ } else if (self.options[kSCTestReachabilityAddress]) {
+ NSString *addressString = self.options[kSCTestReachabilityAddress];
+ struct sockaddr *sa = _SC_string_to_sockaddr(addressString.UTF8String, AF_INET, NULL, 0);
+ if (sa == NULL) {
+ sa = _SC_string_to_sockaddr(addressString.UTF8String, AF_INET6, NULL, 0);
+ if (sa == NULL) {
+ SCTestLog("Invalid address");
+ ERR_EXIT;
+ }
+ }
+ _target = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, sa);
+ }
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ if (self.target != NULL) {
+ CFRelease(self.target);
+ self.target = NULL;
+ }
+}
+
+void
+myReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
+{
+ struct tm tm_now;
+ struct timeval tv_now;
+ (void)gettimeofday(&tv_now, NULL);
+ (void)localtime_r(&tv_now.tv_sec, &tm_now);
+ SCTestLog("%2d:%02d:%02d.%03d Reachability changed: %#x", tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec, tv_now.tv_usec / 1000, flags);
+}
+
+- (void)start
+{
+ if (self.options[kSCTestReachabilityHost] != nil && self.options[kSCTestReachabilityAddress] != nil) {
+ SCTestLog("Please specify either a host or address");
+ ERR_EXIT;
+ }
+
+ if (self.options[kSCTestReachabilityWatch]) {
+ self.callbackQ = dispatch_queue_create("SCTestReachability callback queue", NULL);
+ SCNetworkReachabilitySetCallback(self.target, myReachabilityCallback, NULL);
+ SCNetworkReachabilitySetDispatchQueue(self.target, self.callbackQ);
+ } else {
+ SCNetworkReachabilityFlags flags;
+ SCNetworkReachabilityGetFlags(self.target, &flags);
+ SCTestLog("Reachability: %#x", flags);
+ [self cleanupAndExitWithErrorCode:0];
+ }
+}
+
+- (void)cleanupAndExitWithErrorCode:(int)error
+{
+ [super cleanupAndExitWithErrorCode:error];
+}
+
+- (NSString *)primaryInterfaceName
+{
+ const char *name;
+ NSString *nsName;
+ nwi_ifstate_t ifstate;
+ nwi_state_t nwi;
+
+ nwi = nwi_state_copy();
+ ifstate = nwi_state_get_first_ifstate(nwi, AF_INET);
+ if (ifstate == NULL) {
+ ifstate = nwi_state_get_first_ifstate(nwi, AF_INET6);
+ if (ifstate == NULL) {
+ // May be we are in airplane mode
+ SCTestLog("No primary interface found");
+ return nil;
+ }
+ }
+
+ name = nwi_ifstate_get_ifname(ifstate);
+ nsName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
+ nwi_state_release(nwi);
+
+ return nsName;
+}
+
+- (BOOL)setup
+{
+ return YES;
+}
+
+- (BOOL)unitTest
+{
+ if(![self setup]) {
+ return NO;
+ }
+
+ BOOL allUnitTestsPassed = YES;
+
+ allUnitTestsPassed &= [self unitTestBasicReachabilityCheck];
+ allUnitTestsPassed &= [self unitTestReachabilityWithPolicy];
+ allUnitTestsPassed &= [self unitTestScopedReachabilityWithPolicy];
+
+ if(![self tearDown]) {
+ return NO;
+ }
+
+ return allUnitTestsPassed;
+}
+
+- (BOOL)unitTestBasicReachabilityCheck
+{
+ SCNetworkReachabilityFlags flags;
+ SCTestReachability *test;
+
+ test = [[SCTestReachability alloc] initWithOptions:self.options];
+ if ([test primaryInterfaceName] == nil) {
+ return YES;
+ }
+
+ if (test.target == NULL) {
+ NSDictionary *options = @{kSCTestReachabilityHost:@REACHABILITY_TEST_HOSTNAME};
+ test = [[SCTestReachability alloc] initWithOptions:options];
+ }
+
+
+ SCNetworkReachabilityGetFlags(test.target, &flags);
+ if (flags == 0) {
+ SCTestLog("Reachability reported not reachable");
+ return NO;
+ }
+
+ SCTestLog("Verified that basic reachability check succeeds");
+ return YES;
+}
+
+- (BOOL)unitTestReachabilityWithPolicy
+{
+ NEPolicyCondition *condition1;
+ NEPolicyCondition *condition2;
+ SCNetworkReachabilityFlags flags;
+ BOOL ok;
+ NEPolicy *policy;
+ NSUInteger policyID;
+ NEPolicyResult *result;
+ NEPolicySession *session;
+ SCTestReachability *test;
+
+ test = [[SCTestReachability alloc] initWithOptions:self.options];
+ if ([test primaryInterfaceName] == nil) {
+ return YES;
+ }
+
+ if (test.target == NULL) {
+ NSDictionary *options = @{kSCTestReachabilityHost:@REACHABILITY_TEST_HOSTNAME};
+ test = [[SCTestReachability alloc] initWithOptions:options];
+ }
+
+ SCNetworkReachabilityGetFlags(test.target, &flags);
+ if (flags == 0) {
+ SCTestLog("Reachability reported not reachable");
+ return NO;
+ }
+
+ session = [[NEPolicySession alloc] init];
+ if (session == nil) {
+ SCTestLog("Failed to create NEPolicySession");
+ return NO;
+ }
+
+ result = [NEPolicyResult drop];
+ condition1 = [NEPolicyCondition allInterfaces];
+ condition2 = [NEPolicyCondition effectivePID:getpid()];
+ policy = [[NEPolicy alloc ] initWithOrder:10 result:result conditions:@[condition1, condition2]];
+ policyID = [session addPolicy:policy];
+ if (policyID == 0) {
+ SCTestLog("Failed to add policy");
+ return NO;
+ }
+
+ ok = [session apply];
+ if (!ok) {
+ SCTestLog("Failed to apply policy");
+ return NO;
+ }
+
+ SCNetworkReachabilityGetFlags(test.target, &flags);
+ if (flags != 0) {
+ SCTestLog("Reachability reported as reachable, in presence of a drop policy");
+ return NO;
+ }
+
+ ok = [session removeAllPolicies];
+ if (!ok) {
+ SCTestLog("Failed to remove policies from session");
+ return NO;
+ }
+
+ ok = [session apply];
+ if (!ok) {
+ SCTestLog("Failed to apply policy");
+ return NO;
+ }
+
+ SCNetworkReachabilityGetFlags(test.target, &flags);
+ if (flags == 0) {
+ SCTestLog("Reachability reported as not reachable, in absence of a drop policy");
+ return NO;
+ }
+
+ SCTestLog("Verified that SCNetworkReachability reports reachability corresponding to the NECP Policies");
+ return YES;
+}
+
+- (BOOL)unitTestScopedReachabilityWithPolicy
+{
+ NEPolicyCondition *condition1;
+ NEPolicyCondition *condition2;
+ SCNetworkReachabilityFlags flags;
+ BOOL ok;
+ NEPolicy *policy;
+ NSUInteger policyID;
+ NSString *primaryInterface;
+ NEPolicyResult *result;
+ NEPolicySession *session;
+ SCTestReachability *test;
+
+ test = [[SCTestReachability alloc] initWithOptions:self.options];
+ primaryInterface = [test primaryInterfaceName];
+ if (primaryInterface == nil) {
+ return YES;
+ }
+
+ if (test.target == NULL) {
+ NSDictionary *options = @{kSCTestReachabilityHost:@REACHABILITY_TEST_HOSTNAME,
+ kSCTestReachabilityInterface:primaryInterface};
+ test = [[SCTestReachability alloc] initWithOptions:options];
+ }
+
+ SCNetworkReachabilityGetFlags(test.target, &flags);
+ if (flags == 0) {
+ SCTestLog("Reachability reported not reachable");
+ return NO;
+ }
+
+ session = [[NEPolicySession alloc] init];
+ if (session == nil) {
+ SCTestLog("Failed to create NEPolicySession");
+ return NO;
+ }
+
+ result = [NEPolicyResult drop];
+ condition1 = [NEPolicyCondition scopedInterface:primaryInterface];
+ condition2 = [NEPolicyCondition effectivePID:getpid()];
+ policy = [[NEPolicy alloc ] initWithOrder:10 result:result conditions:@[condition1, condition2]];
+ policyID = [session addPolicy:policy];
+ if (policyID == 0) {
+ SCTestLog("Failed to add policy");
+ return NO;
+ }
+
+ ok = [session apply];
+ if (!ok) {
+ SCTestLog("Failed to apply policy");
+ return NO;
+ }
+
+ SCNetworkReachabilityGetFlags(test.target, &flags);
+ if (flags != 0) {
+ SCTestLog("Reachability reported as reachable, in presence of a drop policy");
+ return NO;
+ }
+
+ ok = [session removeAllPolicies];
+ if (!ok) {
+ SCTestLog("Failed to remove policies from session");
+ return NO;
+ }
+
+ ok = [session apply];
+ if (!ok) {
+ SCTestLog("Failed to apply policy");
+ return NO;
+ }
+
+ SCNetworkReachabilityGetFlags(test.target, &flags);
+ if (flags == 0) {
+ SCTestLog("Reachability reported as not reachable, in absence of a drop policy");
+ return NO;
+ }
+
+ SCTestLog("Verified that SCNetworkReachability for scoped queries report reachability corresponding to the NECP Policies");
+ return YES;
+}
+
+- (BOOL)tearDown
+{
+ return YES;
+}
+
+@end
--- /dev/null
+/*
+ * Copyright (c) 2016 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@
+ */
+
+#import "SCTest.h"
+#import "SCTestUtils.h"
+
+@interface SCTestUnitTest : SCTest
+@end
+
+@implementation SCTestUnitTest
+
++ (NSString *)command
+{
+ return @"unit_test";
+}
+
++ (NSString *)commandDescription
+{
+ return @"Runs the unit test for all commands";
+}
+
+- (void)listTests
+{
+ NSMutableDictionary *testDictionary;
+ NSMutableArray *testsArray;
+ NSString *thisClass;
+ NSArray<NSString *> *testClasses;
+ NSData *data;
+ NSString *jsonString;
+
+ testDictionary = [[NSMutableDictionary alloc] init];
+ [testDictionary setObject:@"SystemConfiguration Unit Tests" forKey:@"Name"];
+ [testDictionary setObject:@"These tests exercise 'configd' and the 'SystemConfiguration' framework" forKey:@"Description"];
+
+ testsArray = [[NSMutableArray alloc] init];
+ thisClass = NSStringFromClass([self class]);
+ testClasses = getTestClasses();
+ for (NSString *className in testClasses) {
+ Class testClass;
+ NSMutableDictionary *subTest;
+ NSArray *list;
+ NSMutableArray *subTestArray;
+
+ if ([className isEqualToString:thisClass] ) {
+ continue;
+ }
+
+ testClass = NSClassFromString(className);
+ list = getUnitTestListForClass(testClass);
+
+ subTest = [[NSMutableDictionary alloc] init];
+ [subTest setObject:@NO forKey:@"RequiresTCPDUMP"];
+ [subTest setObject:@YES forKey:@"RequiresNetwork"];
+ [subTest setObject:@NO forKey:@"RequiresRoot"];
+ [subTest setObject:@NO forKey:@"RequiresPowermetrics"];
+ [subTest setObject:[testClass command] forKey:@"Name"];
+ [subTest setObject:[testClass commandDescription] forKey:@"Description"];
+ subTestArray = [[NSMutableArray alloc] init];
+ for (NSString *unitTest in list) {
+ NSDictionary *testDict = @{@"Command":@[@"/usr/local/bin/sctest",
+ @"unit_test",
+ @"-test_method",
+ unitTest],
+ @"Name":[unitTest stringByReplacingOccurrencesOfString:@"unitTest" withString:@""],
+ @"Description":@"Unit test"
+ };
+ [subTestArray addObject:testDict];
+ }
+ [subTest setObject:subTestArray forKey:@"SubTests"];
+ [testsArray addObject:subTest];
+ }
+ [testDictionary setObject:testsArray forKey:@"Tests"];
+ data = [NSJSONSerialization dataWithJSONObject:testDictionary
+ options:NSJSONWritingPrettyPrinted
+ error:nil];
+ jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+ //SCTestLog("%@", jsonString);
+ SCPrint(TRUE, stderr, CFSTR("%@"), jsonString);
+}
+
+- (void)start
+{
+ NSArray<NSString *> *testClasses;
+ NSString *thisClass = NSStringFromClass([self class]);;
+ testClasses = getTestClasses();
+ BOOL errorOccured = NO;
+
+ if (self.options[kSCTestUnitTestListTests]) {
+ [self listTests];
+ } else if (self.options[kSCTestUnitTestTestMethodList]) {
+ SCTestLog("List of unit tests:");
+ for (NSString *className in testClasses) {
+ Class testClass;
+ NSArray *list;
+
+ if ([className isEqualToString:thisClass] ) {
+ continue;
+ }
+
+ testClass = NSClassFromString(className);
+ if (self.options[kSCTestUnitTestCommand] != nil) {
+ if (![self.options[kSCTestUnitTestCommand] isEqualToString:[testClass command]]) {
+ // Run unit test only for a specific command
+ continue;
+ }
+ }
+
+ SCTestLog("\n======= '%@' unit tests =======", [testClass command]);
+ list = getUnitTestListForClass(testClass);
+ for (NSString *unitTest in list) {
+ SCTestLog("%@", unitTest);
+ }
+ }
+
+ SCTestLog("\nEach of the unit tests can be run with the 'test_method' option\n");
+ } else if (self.options[kSCTestUnitTestTestMethod]) {
+ for (NSString *className in testClasses) {
+ Class testClass;
+ NSArray *list;
+
+ if ([className isEqualToString:thisClass] ) {
+ continue;
+ }
+
+ testClass = NSClassFromString(className);
+ if (self.options[kSCTestUnitTestCommand] != nil) {
+ if (![self.options[kSCTestUnitTestCommand] isEqualToString:[testClass command]]) {
+ // Run unit test only for a specific command
+ continue;
+ }
+ }
+
+ list = getUnitTestListForClass(testClass);
+ for (NSString *unitTest in list) {
+ if ([unitTest isEqualToString:self.options[kSCTestUnitTestTestMethod]]) {
+ id obj = [(SCTest *)[testClass alloc] initWithOptions:self.options];
+
+ SCTestLog("Running unit test %@ ...", unitTest);
+
+ SEL methodSelector = NSSelectorFromString(unitTest);
+ Boolean retVal = false;
+ if ([obj respondsToSelector:methodSelector]) {
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[obj methodSignatureForSelector:methodSelector]];
+ invocation.target = obj;
+ invocation.selector = methodSelector;
+ [invocation invoke];
+ [invocation getReturnValue:&retVal];
+ }
+
+ if (!retVal) {
+ SCTestLog("FAILED");
+ errorOccured = YES;
+ } else {
+ SCTestLog("PASSED");
+ }
+ break;
+ }
+ }
+ }
+ } else {
+ // This command runs unit tests for all commands.
+ for (NSString *className in testClasses) {
+ Class testClass;
+ id obj;
+
+ if ([className isEqualToString:thisClass] ) {
+ continue;
+ }
+
+ testClass = NSClassFromString(className);
+ if (self.options[kSCTestUnitTestCommand] != nil) {
+ if (![self.options[kSCTestUnitTestCommand] isEqualToString:[testClass command]]) {
+ // Run unit test only for a specific command
+ continue;
+ }
+ }
+
+ obj = [(SCTest *)[testClass alloc] initWithOptions:self.options];
+ if ([obj respondsToSelector:@selector(unitTest)]) {
+ SCTestLog("\n*** Running unit test for \"%@\" command ***\n", [testClass command]);
+ BOOL passed = [obj unitTest];
+ if (!passed) {
+ SCTestLog("FAILED");
+ errorOccured = YES;
+ }
+ }
+ }
+ }
+
+ [self cleanupAndExitWithErrorCode:errorOccured];
+}
+
+- (void)cleanupAndExitWithErrorCode:(int)error
+{
+ [super cleanupAndExitWithErrorCode:error];
+}
+
+@end
--- /dev/null
+/*
+ * Copyright (c) 2016 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 SCTestUtils_h
+#define SCTestUtils_h
+
+#import <Foundation/Foundation.h>
+#import <SystemConfiguration/SCPrivate.h>
+#import <objc/objc-runtime.h>
+
+#define SCTestLog(fmt, ...) SCPrint(TRUE, stdout, CFSTR(fmt "\n"), ##__VA_ARGS__)
+#define ERR_EXIT exit(1)
+
+typedef struct {
+ uint64_t user;
+ uint64_t sys;
+ uint64_t idle;
+} CPUUsageInfoInner;
+
+typedef struct {
+ CPUUsageInfoInner startCPU;
+ CPUUsageInfoInner endCPU;
+} CPUUsageInfo;
+
+typedef struct {
+ struct timespec startTime;
+ struct timespec endTime;
+} timerInfo;
+
+void timerStart(timerInfo *);
+void timerEnd(timerInfo *);
+NSString * createUsageStringForTimer(timerInfo *);
+
+void cpuStart(CPUUsageInfo *);
+void cpuEnd(CPUUsageInfo *);
+NSString * createUsageStringForCPU(CPUUsageInfo *cpu);
+
+NSArray<NSString *> *getTestClasses();
+NSArray<NSString *> *getUnitTestListForClass(Class base);
+NSDictionary *getOptionsDictionary(int argc, const char **argv);
+
+#endif /* SCTestUtils_h */
--- /dev/null
+/*
+ * Copyright (c) 2016 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@
+ */
+
+#import <Foundation/Foundation.h>
+#import "SCTest.h"
+#import "SCTestUtils.h"
+#import <mach/mach_time.h>
+
+NSArray<NSString *> *
+getTestClasses()
+{
+ static NSMutableArray *subclassNames = nil;
+ Class base;
+ unsigned int classListCount;
+ Class *classList;
+
+ if (subclassNames != nil) {
+ return subclassNames;
+ }
+
+ base = [SCTest class];
+ classListCount = 0;
+ classList = objc_copyClassList(&classListCount);
+ subclassNames = [[NSMutableArray alloc] init];
+
+ if (classList) {
+ for (unsigned int i = 0; i < classListCount; i++) {
+ Class superClass = class_getSuperclass(classList[i]);
+ while (superClass && superClass != base) {
+ superClass = class_getSuperclass(superClass);
+ }
+
+ if (superClass == base) {
+ [subclassNames addObject:@(class_getName(classList[i]))];
+ }
+ }
+ free(classList);
+ }
+
+ [subclassNames sortUsingComparator: ^(id obj1, id obj2) {
+ NSString *className1 = obj1;
+ NSString *className2 = obj2;
+ return [className1 compare:className2 options:NSCaseInsensitiveSearch];
+ }];
+
+ return subclassNames;
+}
+
+NSArray<NSString *> *
+getUnitTestListForClass(Class base)
+{
+ NSMutableArray<NSString *> *unitTestNames = nil;
+ unsigned int methodListCount = 0;
+ Method *methodList = NULL;
+
+ methodList = class_copyMethodList(base, &methodListCount);
+ if (methodList) {
+ unitTestNames = [[NSMutableArray alloc] initWithCapacity:methodListCount];
+ for (unsigned int i = 0; i < methodListCount; i++) {
+ NSString *name = @(sel_getName(method_getName(methodList[i])));
+ if ([name isEqualToString:@"unitTest"]) {
+ continue;
+ } else if (![name hasPrefix:@"unitTest"]) {
+ continue;
+ }
+
+ [unitTestNames addObject:name];
+ }
+ free(methodList);
+ }
+
+ return unitTestNames;
+}
+
+NSDictionary *
+getOptionsDictionary(int argc, const char **argv)
+{
+ NSMutableDictionary *options;
+ NSNumberFormatter *numberFormatter;
+ int ch;
+ int i;
+ struct option entries[] = {
+ kSCTestOptionEntries
+ };
+
+ options = [NSMutableDictionary dictionary];
+ optind = 0;
+ optreset = 1;
+ numberFormatter = [[NSNumberFormatter alloc] init];
+
+ while ((ch = getopt_long_only(argc, (char * const *)argv, "", entries, &i)) == 0) {
+ struct option opt = entries[i];
+ NSString *optKey = [NSString stringWithFormat:@"%s_Str", opt.name]; // ... "_Str" suffix is standardized across all keys.
+ id optVal = nil;
+
+ if (opt.has_arg) {
+ // Parse the optarg
+
+ // Attempt string
+ optVal = @(optarg);
+
+ if (optVal == nil) {
+ // Fall back to NSData
+ // WARNING: Doesn't work if it contains '\0'
+ optVal = [NSData dataWithBytes:optarg length:strlen(optarg)];
+ } else {
+ // Use NSNumber if the argument is a number
+ NSNumber *number = [numberFormatter numberFromString:optVal];
+ if (number) {
+ optVal = number;
+ }
+ }
+ } else {
+ optVal = @YES;
+ }
+
+ // Handle multiple option instances
+ id existingValue = options[optKey];
+ if (existingValue) {
+ if ([existingValue isKindOfClass:[NSMutableArray class]]) {
+ [(NSMutableArray *)existingValue addObject:optVal];
+ optVal = existingValue;
+ } else if ([existingValue isKindOfClass:[NSArray class]]) {
+ NSMutableArray *tempArray = [NSMutableArray arrayWithArray:existingValue];
+ [tempArray addObject:optVal];
+ optVal = tempArray;
+ } else {
+ optVal = @[existingValue, optVal];
+ }
+ }
+
+ options[optKey] = optVal;
+ }
+
+ if (ch > 0) {
+ return nil;
+ }
+
+ return options;
+}
+
+static void
+cpu_routine(CPUUsageInfoInner *usage)
+{
+ host_name_port_t host;
+ host_cpu_load_info_data_t host_load;
+ mach_msg_type_number_t count;
+ kern_return_t kret;
+
+ if (usage == NULL) {
+ return;
+ }
+
+ host = mach_host_self();
+ count = HOST_CPU_LOAD_INFO_COUNT;
+ kret = host_statistics(host, HOST_CPU_LOAD_INFO, (host_info_t)&host_load, &count);
+ if (kret) {
+ return;
+ }
+
+ // ms per tick. 1 tick is 10 ms.
+ usage->user = ((uint64_t)host_load.cpu_ticks[CPU_STATE_USER]) * 10;
+ usage->sys = ((uint64_t)host_load.cpu_ticks[CPU_STATE_SYSTEM]) * 10;
+ usage->idle = ((uint64_t)host_load.cpu_ticks[CPU_STATE_IDLE]) * 10;
+}
+
+void
+cpuStart(CPUUsageInfo *cpu)
+{
+ cpu_routine(&cpu->startCPU);
+}
+
+void
+cpuEnd(CPUUsageInfo *cpu)
+{
+ cpu_routine(&cpu->endCPU);
+}
+
+NSString *
+createUsageStringForCPU(CPUUsageInfo *cpu)
+{
+ uint64_t userelapsed = cpu->endCPU.user - cpu->startCPU.user;
+ uint64_t systemelapsed = cpu->endCPU.sys - cpu->startCPU.sys;
+ uint64_t idleelapsed = cpu->endCPU.idle - cpu->startCPU.idle;
+ uint64_t totalelapsed = userelapsed + systemelapsed + idleelapsed;
+ double u = ((double)userelapsed * 100)/totalelapsed;
+ double s = ((double)systemelapsed * 100)/totalelapsed;
+ double i = ((double)idleelapsed * 100)/totalelapsed;
+
+ return [NSString stringWithFormat:@"%1.02f%% user %1.02f%% sys %1.02f%% idle", u, s, i];
+}
+
+static void
+timer_routine(struct timespec *ts)
+{
+ uint64_t diff;
+ static uint32_t orwl_timebase_numer = 0;
+ static uint32_t orwl_timebase_denom = 0;
+ static uint64_t orwl_timestart = 0;
+ if (orwl_timestart == 0) {
+ mach_timebase_info_data_t tb = { 0, 0 };
+ mach_timebase_info(&tb);
+ orwl_timebase_numer = tb.numer;
+ orwl_timebase_denom = tb.denom;
+ orwl_timestart = mach_absolute_time();
+ }
+ if (0 == orwl_timebase_denom) {
+ orwl_timebase_denom = 1;
+ }
+ diff = ((mach_absolute_time() - orwl_timestart) * orwl_timebase_numer) / orwl_timebase_denom;
+ ts->tv_sec = (size_t)(diff / NSEC_PER_SEC);
+ ts->tv_nsec = (size_t)(diff - (ts->tv_sec * NSEC_PER_SEC));
+}
+
+void
+timerStart(timerInfo *timer)
+{
+ timer_routine(&timer->startTime);
+}
+
+void
+timerEnd(timerInfo *timer)
+{
+ timer_routine(&timer->endTime);
+}
+
+NSString *
+createUsageStringForTimer(timerInfo *timer)
+{
+ double elapsed;
+ int64_t nsecs = timer->endTime.tv_nsec - timer->startTime.tv_nsec;
+ uint64_t secs = timer->endTime.tv_sec - timer->startTime.tv_sec;
+ if (nsecs < 0) {
+ nsecs += NSEC_PER_SEC;
+ secs -= 1;
+ }
+
+ elapsed = (double)secs + (double)nsecs / NSEC_PER_SEC;
+ return [NSString stringWithFormat:@"%f", elapsed];
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <mach/boolean.h>
+#include <getopt.h>
+
+typedef struct {
+ const char *scope; // Either "global" or for a particular command
+ const char *optionString; // The option
+ const char *optionKey; // String representation of the key to be used to access this option's value from the "options" dictionary.
+ int hasArg; // no_argument, required_argument, optional_argument
+ const char *usageString; // help string
+} SCTestOption;
+
+// Add the options here and then once finished, go to ${SRCROOT}/sctest/ in Terminal and type "make".
+// The options should then be ready to use, through the "options" dictionary.
+SCTestOption testOptions[] = {
+ {"global", "cpu", "kSCTestGlobalOptionCPU", no_argument, "Prints the CPU usage after the test completes"},
+ {"global", "help", "kSCTestGlobalOptionHelp", no_argument, "Prints this very useful help!"},
+ {"global", "time", "kSCTestGlobalOptionTime", no_argument, "Prints the time elapsed since the test was launched"},
+ {"global", "verbose", "kSCTestGlobalOptionVerbose", no_argument, "Enables verbose mode"},
+ {"global", "wait", "kSCTestGlobalOptionWait", no_argument, "Results in a wait for 'sctest'"},
+
+ {"dynamic_store", "dns", "kSCTestDynamicStoreOptionDNS", no_argument, "Prints the global DNS information from the SCDynamicStore"},
+ {"dynamic_store", "ipv4", "kSCTestDynamicStoreOptionIPv4", no_argument, "Prints the global IPv4 information from the SCDynamicStore"},
+ {"dynamic_store", "ipv6", "kSCTestDynamicStoreOptionIPv6", no_argument, "Prints the global IPv6 information from the SCDynamicStore"},
+ {"dynamic_store", "proxies", "kSCTestDynamicStoreOptionProxies", no_argument, "Prints the global Proxy information from the SCDynamicStore"},
+
+ {"preferences", "service_list", "kSCTestPreferencesServiceList", no_argument, "Prints the Network Services list from the preferences"},
+ {"preferences", "service_order", "kSCTestPreferencesServiceOrder", no_argument, "Prints the Network Service order from the preferences"},
+
+ {"config_agent", "dns_domain", "kSCTestConfigAgentDNSDomains", required_argument, "Configures the DNS Servers for certain domains. A comma-separated list of domains can be specified. Default is 'apple.com'"},
+ {"config_agent", "dns_servers", "kSCTestConfigAgentDNSServers", required_argument, "Configures the specified DNS Servers. A comma-separated list of IP Addresses can be specified"},
+ {"config_agent", "remove_dns", "kSCTestConfigAgentRemoveDNS", no_argument, "Remove a dns configuration, previously configured via 'sctest'"},
+
+ {"config_agent", "ftp_proxy", "kSCTestConfigAgentFTPProxy", required_argument, "Add a proxy agent with FTP proxy. Format of the argument is 'server:port'"},
+ {"config_agent", "gopher_proxy", "kSCTestConfigAgentGopherProxy", required_argument, "Add a proxy agent with Gopher proxy. Format of the argument is 'server:port'"},
+ {"config_agent", "http_proxy", "kSCTestConfigAgentHTTPProxy", required_argument, "Add a proxy agent with HTTP proxy. Format of the argument is 'server:port'"},
+ {"config_agent", "https_proxy", "kSCTestConfigAgentHTTPSProxy", required_argument, "Add a proxy agent with HTTPS proxy. Format of the argument is 'server:port'"},
+ {"config_agent", "proxy_match_domain", "kSCTestConfigAgentProxyMatchDomain", required_argument, "Add a proxy agent for a match domain. If this option is not specified, 'apple.com' will be used"},
+ {"config_agent", "remove_proxy", "kSCTestConfigAgentRemoveProxy", no_argument, "Remove a proxy configuration, previously configured via 'sctest'"},
+ {"config_agent", "socks_proxy", "kSCTestConfigAgentSOCKSProxy", required_argument, "Add a proxy agent with SOCKS proxy. Format of the argument is 'server:port'"},
+
+ {"reachability", "address", "kSCTestReachabilityAddress", required_argument, "Determine reachability to this address"},
+ {"reachability", "host", "kSCTestReachabilityHost", required_argument, "Determine reachability to this host"},
+ {"reachability", "interface", "kSCTestReachabilityInterface", required_argument, "Determine reachability when scoped to this interface"},
+ {"reachability", "watch", "kSCTestReachabilityWatch", no_argument, "Watch for reachability changes"},
+
+ {"unit_test", "command", "kSCTestUnitTestCommand", required_argument, "Run a unit test for a specific command. If this option is not specified, unit-tests for all commands will be run"},
+ {"unit_test", "list_tests", "kSCTestUnitTestListTests", no_argument, "List the test commands in a JSON format. This is for NPT compliance"},
+ {"unit_test", "test_method", "kSCTestUnitTestTestMethod", required_argument, "Runs a specific unit test. List can be obtained by using the 'test_method_list' option"},
+ {"unit_test", "test_method_list", "kSCTestUnitTestTestMethodList", no_argument, "Lists all the unit tests. A specific one can be run using the 'test_method' option"},
+};
+
+static int testOptionsCount = (sizeof(testOptions) / sizeof(testOptions[0]));
+
+void
+printDeclarations()
+{
+ // Prints to SCTestOptions.h
+
+ const char *keyTemplate = "extern const NSString * const";
+ for (int i = 0; i < testOptionsCount; i++) {
+ char buffer[256] = {0};
+ snprintf(buffer, sizeof(buffer), "%s %s;", keyTemplate, testOptions[i].optionKey);
+ printf("%s\n", buffer);
+ }
+}
+
+void
+printOptionEntries()
+{
+ // Prints to SCTestOptions.h
+
+ const char *entryTemplate = "#define kSCTestOptionEntries";
+ printf("\n%s \\\n", entryTemplate);
+ for (int i = 0; i < testOptionsCount; i++) {
+ printf("\t\t{\"%s\", %d, NULL, 0}, \\", testOptions[i].optionString, testOptions[i].hasArg);
+ printf("\n");
+ }
+}
+
+void
+printUsage()
+{
+ // Prints to SCTestOptions.h
+
+ const char *usageTemplate = "#define kSCTestOptionHelp";
+ printf("\n%s \\\n", usageTemplate);
+ const char *last = "";
+ for (int i = 0; i < testOptionsCount; i++) {
+ if (strcmp(last, testOptions[i].scope)) {
+ last = testOptions[i].scope;
+ printf("\t\t\"\\n============== %s options =============\\n\"\\\n", testOptions[i].scope);
+ }
+
+ printf("\t\t\"-%-20s: %s\\n\"\\\n", testOptions[i].optionString, testOptions[i].usageString);
+ }
+}
+
+void
+printDefinitions()
+{
+ // Prints to SCTestOptions.m
+
+ const char *definitionTemplate = "const NSString * const";
+ for (int i = 0; i < testOptionsCount; i++) {
+ char buffer[256] = {0};
+ snprintf(buffer, sizeof(buffer), "%s %-50s= @\"%s_Str\";", definitionTemplate, testOptions[i].optionKey, testOptions[i].optionString);
+ printf("%s\n", buffer);
+ }
+}
+
+int
+main(int argc, char * argv[])
+{
+ char * type = "";
+
+ if (argc >= 2) {
+ type = argv[1];
+ }
+
+ if (strcmp(type, "header") == 0) {
+ // Preamble
+ printf("//\n");
+ printf("// This file is automatically generated. DO NOT EDIT!\n");
+ printf("// To add options, see genSCTestOptions.c\n");
+ printf("//\n");
+
+ // Import header files
+ printf("#import <Foundation/Foundation.h>\n");
+ printf("#import <getopt.h>");
+
+ printf("\n\n");
+
+ // Print the declarations
+ printDeclarations();
+
+ printf("\n\n");
+
+ // Print the option Entries
+ printOptionEntries();
+
+ // Print the usage
+ printUsage();
+ } else if (strcmp(type, "mfile") == 0) {
+ printf("//\n");
+ printf("// This file is automatically generated. DO NOT EDIT!\n");
+ printf("// To add options, see genSCTestOptions.c\n");
+ printf("//\n");
+
+ // Import header files
+ printf("#import \"SCTestOptions.h\"");
+
+ printf("\n\n");
+ printDefinitions();
+ }
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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@
+ */
+
+#import "SCTest.h"
+#import "SCTestUtils.h"
+
+static void
+usage()
+{
+ NSArray *testClasses = getTestClasses();
+ SCTestLog("\nUsage: sctest <command> <options>");
+ SCTestLog("\nCommands:");
+ for (NSString *testClassName in testClasses) {
+ Class testClass = NSClassFromString(testClassName);
+ SCTestLog(" %15s: %s", [testClass command].UTF8String, [testClass commandDescription].UTF8String);
+ }
+
+ SCTestLog("\n\nOptions:");
+ SCTestLog(kSCTestOptionHelp "\n");
+
+ ERR_EXIT;
+}
+
+int main(int argc, const char * argv[]) {
+ @autoreleasepool {
+ NSString *testCommand;
+ NSArray<NSString *> *testClasses;
+ BOOL commandValid = NO;
+ NSDictionary *options;
+ Class testClass;
+ SCTest *testClassObject;
+
+ if (argc == 1) {
+ usage();
+ }
+
+ testCommand = @(argv[1]);
+ // Check if the command is valid
+ testClasses = getTestClasses();
+ for (NSString *testClassName in testClasses) {
+ Class testClass = NSClassFromString(testClassName);
+ if ([[testClass command] isEqualToString:testCommand]) {
+ commandValid = YES;
+ break;
+ }
+
+ }
+
+ if (!commandValid) {
+ SCTestLog("Invalid command: %@", testCommand);
+ usage();
+ }
+
+ // Create the options dictionary
+ options = getOptionsDictionary(argc, argv);
+ if (options == nil) {
+ usage();
+ }
+
+ // Initialize the command
+ for (NSString *className in testClasses) {
+ Class commandClass = NSClassFromString(className);
+ if ([testCommand isEqualToString:[commandClass command]]) {
+ testClass = commandClass;
+ break;
+ }
+ }
+
+ testClassObject = [(SCTest *)[testClass alloc] initWithOptions:options];
+ if (testClassObject.options[kSCTestGlobalOptionCPU] != nil) {
+ cpuStart(testClassObject.globalCPU);
+ }
+
+ if (testClassObject.options[kSCTestGlobalOptionTime] != nil) {
+ timerStart(testClassObject.globalTimer);
+ }
+
+ [testClassObject start];
+
+ dispatch_main();
+ }
+
+ return 0;
+}
--- /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>ID</key>
+ <string>com.apple.npt.configd</string>
+ <key>CommandList</key>
+ <array>
+ <string>/usr/local/bin/sctest</string>
+ <string>unit_test</string>
+ <string>-list_tests</string>
+ </array>
+</dict>
+</plist>
--- /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>com.apple.private.nehelper.privileged</key>
+ <true/>
+ <key>com.apple.private.necp.policies</key>
+ <true/>
+ <key>com.apple.SystemConfiguration.SCPreferences-write-access</key>
+ <array>
+ <string>SCTestPreferences.plist</string>
+ </array>
+ <key>com.apple.SystemConfiguration.SCDynamicStore-write-access</key>
+ <true/>
+</dict>
+</plist>
/*
- * Copyright (c) 2003-2008, 2011-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2008, 2011-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* - initial revision
*/
+#include <TargetConditionals.h>
#include <dlfcn.h>
#include <unistd.h>
#include <sys/param.h>
/* -------------------- */
+#if !TARGET_OS_IPHONE
+
+#include "InterfaceNamerControlPrefs.h"
+
+static void
+allow_new_interfaces_usage(void)
+{
+ fprintf(stderr, "usage: scutil --allow-new-interfaces [on|off|default]\n");
+ return;
+}
+
+__private_extern__
+void
+do_ifnamer(char * pref, int argc, char **argv)
+{
+ Boolean allow = FALSE;
+
+ if (argc > 1) {
+ allow_new_interfaces_usage();
+ exit(1);
+ }
+
+ if (strcmp(pref, "allow-new-interfaces")) {
+ exit(0);
+ }
+
+ if (argc == 0) {
+ SCPrint(TRUE, stdout, CFSTR("AllowNewInterfaces is %s\n"),
+ on_off_str(InterfaceNamerControlPrefsAllowNewInterfaces()));
+ exit(0);
+ }
+
+ if ((strcasecmp(argv[0], "disable") == 0) ||
+ (strcasecmp(argv[0], "no" ) == 0) ||
+ (strcasecmp(argv[0], "off" ) == 0) ||
+ (strcasecmp(argv[0], "0" ) == 0)) {
+ allow = FALSE;
+ } else if ((strcasecmp(argv[0], "enable") == 0) ||
+ (strcasecmp(argv[0], "yes" ) == 0) ||
+ (strcasecmp(argv[0], "on" ) == 0) ||
+ (strcasecmp(argv[0], "1" ) == 0)) {
+ allow = TRUE;
+ } else if (strcasecmp(argv[0], "default") == 0) {
+ allow = FALSE;
+ } else {
+ allow_new_interfaces_usage();
+ exit(1);
+ }
+
+ if (!InterfaceNamerControlPrefsSetAllowNewInterfaces(allow)) {
+ SCPrint(TRUE, stderr, CFSTR("failed to set preferences\n"));
+ exit(2);
+ }
+
+ exit(0);
+ return;
+}
+
+#endif // !TARGET_OS_IPHONE
+
+/* -------------------- */
+
#include "IPMonitorControlPrefs.h"
__private_extern__
/*
- * Copyright (c) 2003, 2005-2007, 2012, 2013, 2015, 2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2003, 2005-2007, 2012, 2013, 2015-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#ifndef _PREFS_H
#define _PREFS_H
+#include <TargetConditionals.h>
#include <sys/cdefs.h>
#include <SystemConfiguration/SystemConfiguration.h>
void do_log (char *pref, int argc, char **argv);
void do_disable_until_needed (int argc, char **argv);
+
+#if !TARGET_OS_IPHONE
+void do_ifnamer (char *pref, int argc, char **argv);
+#endif // !TARGET_OS_IPHONE
+
__END_DECLS
#endif /* !_PREFS_H */
/*
- * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
{ "password", required_argument, NULL, 0 },
{ "secret", required_argument, NULL, 0 },
{ "log", required_argument, NULL, 0 },
- { "disable-until-needed", no_argument, NULL, 0 },
+#if !TARGET_OS_IPHONE
+ { "allow-new-interfaces", no_argument, NULL, 0 },
+#endif // !TARGET_OS_IPHONE
+ { "disable-until-needed", no_argument, NULL, 0 },
{ NULL, 0, NULL, 0 }
};
SCPrint(TRUE, stderr, CFSTR("\tmanage secondary interface demand.\n"));
}
+#if !TARGET_OS_IPHONE
+ SCPrint(TRUE, stderr, CFSTR("\n"));
+ SCPrint(TRUE, stderr, CFSTR(" or: %s --allow-new-interfaces [off|on]\n"), command);
+ SCPrint(TRUE, stderr, CFSTR("\tmanage new interface creation with screen locked.\n"));
+#endif // !TARGET_OS_IPHONE
+
if (getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) {
SCPrint(TRUE, stderr, CFSTR("\n"));
SCPrint(TRUE, stderr, CFSTR(" or: %s --net\n"), command);
int
main(int argc, char * const argv[])
{
- Boolean disableUntilNeeded = FALSE;
- Boolean doDNS = FALSE;
- Boolean doNet = FALSE;
- Boolean doNWI = FALSE;
- Boolean doPrefs = FALSE;
- Boolean doProxy = FALSE;
- Boolean doReach = FALSE;
- Boolean doSnap = FALSE;
- char *error = NULL;
- char *get = NULL;
- char *log = NULL;
+#if !TARGET_OS_IPHONE
+ Boolean allowNewInterfaces = FALSE;
+#endif // !TARGET_OS_IPHONE
+ Boolean disableUntilNeeded = FALSE;
+ Boolean doDNS = FALSE;
+ Boolean doNet = FALSE;
+ Boolean doNWI = FALSE;
+ Boolean doPrefs = FALSE;
+ Boolean doProxy = FALSE;
+ Boolean doReach = FALSE;
+ Boolean doSnap = FALSE;
+ char *error = NULL;
+ char *get = NULL;
+ char *log = NULL;
extern int optind;
int opt;
int opti;
- const char *prog = argv[0];
- char *renew = NULL;
- char *set = NULL;
- char *nc_cmd = NULL;
+ const char *prog = argv[0];
+ char *renew = NULL;
+ char *set = NULL;
+ char *nc_cmd = NULL;
InputRef src;
- int timeout = 15; /* default timeout (in seconds) */
- char *wait = NULL;
- Boolean watch = FALSE;
- int xStore = 0; /* non dynamic store command line options */
+ int timeout = 15; /* default timeout (in seconds) */
+ char *wait = NULL;
+ Boolean watch = FALSE;
+ int xStore = 0; /* non dynamic store command line options */
/* process any arguments */
} else if (strcmp(longopts[opti].name, "log") == 0) {
log = optarg;
xStore++;
+#if !TARGET_OS_IPHONE
+ } else if (strcmp(longopts[opti].name, "allow-new-interfaces") == 0) {
+ allowNewInterfaces = TRUE;
+ xStore++;
+#endif // !TARGET_OS_IPHONE
} else if (strcmp(longopts[opti].name, "disable-until-needed") == 0) {
disableUntilNeeded = TRUE;
xStore++;
/* NOT REACHED */
}
+#if !TARGET_OS_IPHONE
+ /* allowNewInterfaces */
+ if (allowNewInterfaces) {
+ do_ifnamer("allow-new-interfaces", argc, (char * *)argv);
+ /* NOT REACHED */
+ }
+#endif // !TARGET_OS_IPHONE
+
/* disableUntilNeeded */
if (disableUntilNeeded) {
do_disable_until_needed(argc, (char * *)argv);
/* NOT REACHED */
}
+
/* network connection commands */
if (nc_cmd) {
if (find_nc_cmd(nc_cmd) < 0) {