#include <CommonCrypto/CommonDigest.h>
#include "ip_plugin.h"
-#include "serviceIDNumber.h"
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
#include "network_state_information_logging.h"
#include "network_information_server.h"
#include <ppp/ppp_msg.h>
+
#if !TARGET_OS_SIMULATOR && !TEST_IPV4_ROUTELIST && !TEST_IPV6_ROUTELIST
#include "set-hostname.h"
#include "nat64-configuration.h"
typedef CF_ENUM(uint16_t, ControlFlags) {
kControlFlagsProcessed = 0x0001,
kControlFlagsAdded = 0x0002,
+ kControlFlagsForce = 0x0004,
};
+#if !TARGET_OS_SIMULATOR
+static inline ControlFlags
+ControlFlagsPreserve(ControlFlags flags)
+{
+ /* only preserve the "processed" and "added" flags */
+ return (flags & (kControlFlagsProcessed | kControlFlagsAdded));
+}
+#endif /* !TARGET_OS_SIMULATOR */
+
#define ROUTE_COMMON \
int prefix_length; \
IFIndex ifindex; \
IFIndex exclude_ifindex; \
Rank rank; \
RouteFlags flags; \
- ControlFlags control_flags; \
- serviceIDNumber sidn;
+ ControlFlags control_flags;
typedef struct {
ROUTE_COMMON
return (isA_CFArray(CFDictionaryGetValue(dict, key)));
}
-#if !TARGET_OS_SIMULATOR
-
-typedef CF_ENUM(uint16_t, PLATDiscoveryOption) {
- kPLATDiscoveryOptionStart,
- kPLATDiscoveryOptionUpdate,
- kPLATDiscoveryOptionCancel
-};
-
static void
my_CFSetAddValue(CFMutableSetRef * set_p, CFTypeRef value)
{
CFSetAddValue(*set_p, value);
}
+static Boolean
+my_CFSetContainsValue(CFSetRef set, CFTypeRef value)
+{
+ if (set == NULL) {
+ return (FALSE);
+ }
+ return (CFSetContainsValue(set, value));
+}
+
+#if !TARGET_OS_SIMULATOR
+
static void
my_CFSetRemoveValue(CFMutableSetRef * set_p, CFTypeRef value)
{
}
}
-static Boolean
-my_CFSetContainsValue(CFSetRef set, CFTypeRef value)
-{
- if (set == NULL) {
- return (FALSE);
- }
- return (CFSetContainsValue(set, value));
-}
+typedef CF_ENUM(uint16_t, PLATDiscoveryOption) {
+ kPLATDiscoveryOptionStart,
+ kPLATDiscoveryOptionUpdate,
+ kPLATDiscoveryOptionCancel
+};
// Note: must only accessed on __network_change_queue()
static CFMutableSetRef S_nat64_cancel_prefix_requests;
static RouteListRef
RouteListAddRoute(RouteListInfoRef info,
RouteListRef routes, int init_size,
- RouteRef this_route, Rank this_rank)
+ RouteRef this_route, Rank this_rank,
+ boolean_t force)
{
CFIndex i;
RouteRef first_scan = NULL;
}
}
else if (cmp == 0) {
- /* exact match */
/* exact match */
if (where != kCFNotFound
&& scan->ifindex == this_route->ifindex
ROUTELIST_DEBUG(kDebugFlag8, "Hit 5: preserved scope\n");
scan->flags |= kRouteFlagsIsScoped;
}
+ if (force) {
+ scan->control_flags |= kControlFlagsForce;
+ }
}
/* we're done */
goto done;
/* add/insert the new route */
this_route = RouteListAddRouteAtIndex(info, routes, this_route, where);
this_route->rank = this_rank;
+ if (force) {
+ this_route->control_flags |= kControlFlagsForce;
+ }
flags = 0;
if (RANK_ASSERTION_MASK(this_rank) == kRankAssertionNever) {
flags |= kRouteFlagsIsScoped;
static RouteListRef
RouteListAddRouteList(RouteListInfoRef info,
RouteListRef routes, int init_size,
- RouteListRef service_routes, Rank rank)
+ RouteListRef service_routes, Rank rank,
+ boolean_t force)
{
int i;
RouteRef scan;
else {
this_rank = RANK_INDEX_MASK(rank) | RANK_ASSERTION_MASK(scan->rank);
}
- routes = RouteListAddRoute(info, routes, init_size, scan, this_rank);
+ routes = RouteListAddRoute(info, routes, init_size, scan, this_rank,
+ force);
}
return (routes);
}
if ((r->flags & kRouteFlagsIsScoped) != 0) {
CFStringAppend(str, CFSTR(" [SCOPED]"));
}
+#ifndef TEST_ROUTELIST
+ if ((r->control_flags & kControlFlagsForce) != 0) {
+ CFStringAppend(str, CFSTR(" [force]"));
+ }
+#endif
}
return;
}
RouteLookupFlags lookup_flags)
{
RouteRef best_match = NULL;
- RouteRef candidate;
int i;
+ RouteRef scan;
- for (i = 0, candidate = RouteListGetFirstRoute(info, routes);
+ for (i = 0, scan = RouteListGetFirstRoute(info, routes);
i < routes->count;
- i++, candidate = RouteGetNextRoute(info, candidate)) {
- if (candidate->ifindex == 0 || candidate->exclude_ifindex != 0) {
+ i++, scan = RouteGetNextRoute(info, scan)) {
+ if (scan->ifindex == 0 || scan->exclude_ifindex != 0) {
/* ignore exclude routes */
continue;
}
if ((lookup_flags & kRouteLookupFlagsExcludeInterface) != 0) {
/* exclude interfaces with the same interface index */
- if (ifindex == candidate->ifindex) {
+ if (ifindex == scan->ifindex) {
continue;
}
}
- else if (ifindex != candidate->ifindex) {
+ else if (ifindex != scan->ifindex) {
continue;
}
- if ((candidate->flags & kRouteFlagsHasGateway) != 0
+ if ((scan->flags & kRouteFlagsHasGateway) != 0
&& RouteAddressCompare(info,
- (*info->route_gateway)(candidate),
+ (*info->route_gateway)(scan),
address) == 0) {
/* skip route whose gateway is the address we're looking for */
continue;
}
- if ((candidate->flags & kRouteFlagsIsHost) != 0) {
+ if ((scan->flags & kRouteFlagsIsHost) != 0) {
/* if host route and we're looking for an exact match */
if (n_bits == info->all_bits_set
&& RouteAddressCompare(info,
- (*info->route_destination)(candidate),
+ (*info->route_destination)(scan),
address) == 0) {
/* found exact match */
- best_match = candidate;
+ best_match = scan;
break;
}
/* skip it */
continue;
}
/* verify that address is on the same subnet */
- if ((*info->route_same_subnet)(candidate, address) == FALSE) {
+ if ((*info->route_same_subnet)(scan, address) == FALSE) {
/* different subnet */
continue;
}
- if (candidate->prefix_length == n_bits) {
+ if (scan->prefix_length == n_bits) {
/* exact match */
- best_match = candidate;
+ best_match = scan;
break;
}
- if (candidate->prefix_length > n_bits) {
+ if (scan->prefix_length > n_bits) {
/* matched too many bits */
continue;
}
if (best_match == NULL
- || candidate->prefix_length > best_match->prefix_length) {
- best_match = candidate;
+ || scan->prefix_length > best_match->prefix_length) {
+ best_match = scan;
}
}
return (best_match);
RouteRef old_route = NULL;
old_route = RouteListFindRoute(info, old_routes, scan);
- if (old_route != NULL && scan->sidn == old_route->sidn) {
- /* preserve the control state in the new route */
- scan->control_flags = old_route->control_flags;
+ if (old_route != NULL) {
+ if ((scan->control_flags & kControlFlagsForce) == 0) {
+ /* preserve the control state in the new route */
+ scan->control_flags
+ = ControlFlagsPreserve(old_route->control_flags);
+ }
+ else {
+ (*info->route_log)(LOG_NOTICE, (RouteRef)scan,
+ "Re-applying route");
+ }
}
}
}
(*info->route_destination)(scan),
scan->prefix_length, ifindex, flags);
if (route == NULL) {
- (*info->route_log)(LOG_NOTICE, (RouteRef)scan, "can't resolve excluded route");
+ (*info->route_log)(LOG_NOTICE, (RouteRef)scan,
+ "can't resolve excluded route");
}
else {
if ((S_IPMonitor_debug & kDebugFlag8) != 0) {
CFSTR(" Ifa " IP_FORMAT),
IP_LIST(&r->ifa));
}
-#if !TEST_IPV4_ROUTELIST
- CFStringAppendFormat(str, NULL,
- CFSTR(" <SID %ld>"),
- r->sidn);
-#endif
RouteAddFlagsToDescription((RouteRef)r, str);
return;
}
return ((IPv4RouteListRef)
RouteListAddRouteList(&IPv4RouteListInfo,
(RouteListRef)routes, init_size,
- (RouteListRef)service_routes, rank));
+ (RouteListRef)service_routes, rank,
+ FALSE));
}
#endif /* TEST_IPV4_ROUTELIST */
IPv4RouteRef * route_p;
Rank rank;
const char * descr;
- serviceIDNumber sidn;
} AddIPv4RouteContext, * AddIPv4RouteContextRef;
static void
}
r->rank = ctx->rank;
r->exclude_ifindex = ctx->exclude_ifindex;
- r->sidn = ctx->sidn;
if (ctx->ifindex != 0) {
r->ifindex = ctx->ifindex;
r->ifa = ctx->addr;
static IPv4RouteListRef
IPv4RouteListCreateWithDictionary(IPv4RouteListRef routes,
CFDictionaryRef dict,
- CFNumberRef rank_assertion,
- serviceIDNumber sidn)
+ CFNumberRef rank_assertion)
{
boolean_t add_broadcast_multicast = FALSE;
boolean_t add_default = FALSE;
if (add_default) {
/* add the default route */
routes->flags |= kRouteListFlagsHasDefault;
- r->sidn = sidn;
r->ifindex = ifindex;
r->ifa = addr;
r->flags = flags;
r->mask.s_addr = INADDR_BROADCAST;
r->prefix_length = IPV4_ROUTE_ALL_BITS_SET;
r->ifindex = ifindex;
- r->sidn = sidn;
r->ifa = addr;
r->rank = rank;
r++;
r->mask.s_addr = htonl(IN_CLASSD_NET);
r->prefix_length = PREFIX_LENGTH_IN_CLASSD;
r->ifindex = ifindex;
- r->sidn = sidn;
r->ifa = addr;
r->rank = rank;
r++;
r->flags |= kRouteFlagsIsNULL;
}
r->ifindex = ifindex;
- r->sidn = sidn;
r->gateway = addr;
r->dest = subnet;
r->mask = mask;
r->flags |= kRouteFlagsIsNULL;
}
r->ifindex = ifindex;
- r->sidn = sidn;
r->gateway = addr;
r->dest = router;
r->mask.s_addr = INADDR_BROADCAST;
context.ifindex = ifindex;
context.addr = addr;
context.descr = "AdditionalRoutes";
- context.sidn = sidn;
CFArrayApplyFunction(additional_routes,
CFRangeMake(0, additional_routes_count),
AddIPv4Route, &context);
/* exclude this interface */
context.ifindex = 0;
context.exclude_ifindex = ifindex;
- context.sidn = sidn;
CFArrayApplyFunction(excluded_routes,
CFRangeMake(0, excluded_routes_count),
AddIPv4Route, &context);
r->mask.s_addr = htonl(IN_CLASSC_NET);
r->prefix_length = PREFIX_LENGTH_IN_CLASSC;
r->ifindex = lo0_ifindex();
- r->sidn = kserviceIDNumberZero;
return (routes);
}
#endif /* !TARGET_OS_SIMULATOR */
CFStringAppend(str, CFSTR(" Ifa "));
string_append_in6_addr(str, &r->ifa);
}
-#if !TEST_IPV6_ROUTELIST
- CFStringAppendFormat(str, NULL,
- CFSTR(" <SID %ld>"),
- r->sidn);
-#endif
RouteAddFlagsToDescription((RouteRef)r, str);
return;
}
IPv6RouteRef * route_p;
Rank rank;
const char * descr;
- serviceIDNumber sidn;
} AddIPv6RouteContext, * AddIPv6RouteContextRef;
static void
}
r->rank = ctx->rank;
r->exclude_ifindex = ctx->exclude_ifindex;
- r->sidn = ctx->sidn;
if (ctx->ifindex != 0) {
r->ifindex = ctx->ifindex;
r->ifa = *ctx->addr;
static IPv6RouteListRef
IPv6RouteListCreateWithDictionary(IPv6RouteListRef routes,
CFDictionaryRef dict,
- CFNumberRef rank_assertion,
- serviceIDNumber sidn)
+ CFNumberRef rank_assertion)
{
boolean_t add_default = FALSE;
boolean_t add_prefix = FALSE;
/* add the default route */
routes->flags |= kRouteListFlagsHasDefault;
r->ifindex = ifindex;
- r->sidn = sidn;
r->ifa = addr;
r->flags = flags;
if ((flags & kRouteFlagsHasGateway) != 0) {
/* add IPv6LL route */
r->ifindex = ifindex;
- r->sidn = sidn;
r->dest.s6_addr[0] = 0xfe;
r->dest.s6_addr[1] = 0x80;
r->prefix_length = 64;
r->flags |= kRouteFlagsIsNULL;
}
r->ifindex = ifindex;
- r->sidn = sidn;
r->gateway = addr;
r->dest = addr;
in6_netaddr(&r->dest, prefix_length);
context.ifindex = ifindex;
context.addr = &addr;
context.descr = "AdditionalRoutes";
- context.sidn = sidn;
CFArrayApplyFunction(additional_routes,
CFRangeMake(0, additional_routes_count),
AddIPv6Route, &context);
context.ifindex = 0;
context.exclude_ifindex = ifindex;
context.addr = NULL;
- context.sidn = sidn;
CFArrayApplyFunction(excluded_routes,
CFRangeMake(0, excluded_routes_count),
AddIPv6Route, &context);
return ((IPv6RouteListRef)
RouteListAddRouteList(&IPv6RouteListInfo,
(RouteListRef)routes, init_size,
- (RouteListRef)service_routes, rank));
+ (RouteListRef)service_routes, rank,
+ FALSE));
}
#endif /* TEST_IPV6_ROUTELIST */
#endif /* !TARGET_OS_SIMULATOR */
/*
- * Function: parse_component
+ * Function: parseNetworkServiceString
* Purpose:
- * Given a string 'key' and a string prefix 'prefix',
- * return the next component in the slash '/' separated
- * key.
- *
- * Examples:
- * 1. key = "a/b/c" prefix = "a/"
- * returns "b"
- * 2. key = "a/b/c" prefix = "a/b/"
- * returns "c"
+ * Parse either of the following two formats:
+ * <domain>:/Network/Service/<serviceID>
+ * <domain>:/Network/Service/<serviceID>/<protocol>
+ * returning <serviceID>, and if available and required, <protocol>.
*/
static CF_RETURNS_RETAINED CFStringRef
-parse_component(CFStringRef key, CFStringRef prefix)
+parseNetworkServiceString(CFStringRef str, CFStringRef *ret_protocol)
{
- CFMutableStringRef comp;
- CFRange range;
+ CFArrayRef components;
+ CFIndex count;
+ CFStringRef protocol = NULL;
+ CFStringRef serviceID = NULL;
- if (!CFStringHasPrefix(key, prefix)) {
- return (NULL);
- }
- comp = CFStringCreateMutableCopy(NULL, 0, key);
- if (comp == NULL) {
- return (NULL);
+ /*
+ * str = "<domain>:/Network/Service/<serviceID>"
+ * OR
+ * str = "<domain>:/Network/Service/<serviceID>/<protocol>"
+ */
+ components = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR("/"));
+ count = CFArrayGetCount(components);
+ if (count >= 4) {
+ /* we have a serviceID */
+ serviceID = CFArrayGetValueAtIndex(components, 3);
+ CFRetain(serviceID);
+ if (count >= 5 && ret_protocol != NULL) {
+ /* we have and want a protocol */
+ protocol = CFArrayGetValueAtIndex(components, 4);
+ CFRetain(protocol);
+ }
}
- CFStringDelete(comp, CFRangeMake(0, CFStringGetLength(prefix)));
- range = CFStringFind(comp, CFSTR("/"), 0);
- if (range.location == kCFNotFound) {
- return (comp);
+ if (ret_protocol != NULL) {
+ *ret_protocol = protocol;
}
- range.length = CFStringGetLength(comp) - range.location;
- CFStringDelete(comp, range);
- return (comp);
+ my_CFRelease(&components);
+ return serviceID;
}
-
static boolean_t
ipdict_is_routable(CFDictionaryRef entity_dict)
{
log_service_entity(int level, CFStringRef serviceID, CFStringRef entity,
CFStringRef operation, CFTypeRef val)
{
- serviceIDNumber service_number;
CFMutableStringRef this_val = NULL;
if (val != NULL) {
if (val == NULL) {
val = CFSTR("<none>");
}
- if (serviceIDNumberGetIfPresent(serviceID, &service_number)) {
- my_log(level, "serviceID %@ <SID %ld> %@ %@ value = %@",
- serviceID, service_number, operation, entity, val);
- }
- else {
- my_log(level, "serviceID %@ %@ %@ value = %@",
- serviceID, operation, entity, val);
- }
+ my_log(level, "serviceID %@ %@ %@ value = %@",
+ serviceID, operation, entity, val);
+
my_CFRelease(&this_val);
return;
}
}
if (CFDictionaryGetCount(service_dict) == 0) {
CFDictionaryRemoveValue(S_service_state_dict, serviceID);
- serviceIDNumberRemove(serviceID);
}
else {
CFDictionarySetValue(S_service_state_dict, serviceID, service_dict);
routes->flags = 0;
static CFDataRef
-IPv4RouteListDataCreate(CFDictionaryRef dict, CFNumberRef rank_assertion,
- serviceIDNumber sidn)
+IPv4RouteListDataCreate(CFDictionaryRef dict, CFNumberRef rank_assertion)
{
IPv4RouteListRef r;
CFDataRef routes_data;
IPV4_ROUTES_BUF_DECL(routes);
- r = IPv4RouteListCreateWithDictionary(routes, dict, rank_assertion,
- sidn);
+ r = IPv4RouteListCreateWithDictionary(routes, dict, rank_assertion);
if (r != NULL) {
routes_data = CFDataCreate(NULL,
(const void *)r,
sizeof(uint32_t)) \
/ sizeof(uint32_t))
-#define IPV6_ROUTES_BUF_DECL(routes) \
+#define IPV6_ROUTES_BUF_DECL(routes) \
IPv6RouteListRef routes; \
uint32_t routes_buf[IPV6_ROUTES_ALIGN_BUF_SIZE_UINT32]; \
\
routes->flags = 0;
static CFDataRef
-IPv6RouteListDataCreate(CFDictionaryRef dict, CFNumberRef rank_assertion,
- serviceIDNumber sidn)
+IPv6RouteListDataCreate(CFDictionaryRef dict, CFNumberRef rank_assertion)
{
IPv6RouteListRef r;
CFDataRef routes_data;
IPV6_ROUTES_BUF_DECL(routes);
- r = IPv6RouteListCreateWithDictionary(routes, dict, rank_assertion,
- sidn);
+ r = IPv6RouteListCreateWithDictionary(routes, dict, rank_assertion);
if (r != NULL) {
routes_data = CFDataCreate(NULL,
(const void *)r,
static CFDictionaryRef
IPDictCreate(int af, _Nonnull CFDictionaryRef state_dict,
CFDictionaryRef setup_dict,
- CFNumberRef rank_assertion, CFStringRef serviceID)
+ CFNumberRef rank_assertion)
{
CFDictionaryRef aggregated_dict = NULL;
CFDictionaryRef dict;
CFMutableDictionaryRef modified_dict = NULL;
CFDataRef routes_data;
- serviceIDNumber sidn;
- sidn = serviceIDNumberGet(serviceID);
dict = state_dict;
if (setup_dict != NULL) {
/* look for keys in Setup: that override/merge with State: */
}
switch (af) {
case AF_INET:
- routes_data = IPv4RouteListDataCreate(dict, rank_assertion, sidn);
+ routes_data = IPv4RouteListDataCreate(dict, rank_assertion);
break;
default:
case AF_INET6:
- routes_data = IPv6RouteListDataCreate(dict, rank_assertion, sidn);
+ routes_data = IPv6RouteListDataCreate(dict, rank_assertion);
break;
}
if (routes_data != NULL) {
= CFDictionaryGetValue(service_options,
kServiceOptionRankAssertion);
}
- dict = IPDictCreate(AF_INET, state_dict, setup_dict, rank_assertion,
- serviceID);
+ dict = IPDictCreate(AF_INET, state_dict, setup_dict, rank_assertion);
done:
changed = service_dict_set(serviceID, kSCEntNetIPv4, dict);
kServiceOptionRankAssertion);
}
- dict = IPDictCreate(AF_INET6, state_dict, setup_dict, rank_assertion,
- serviceID);
+ dict = IPDictCreate(AF_INET6, state_dict, setup_dict, rank_assertion);
done:
CandidateRef other_candidate,
nwi_state_t nwi_state, int af,
RouteListRef * ret_routes,
- CFDictionaryRef services_info)
+ CFDictionaryRef services_info,
+ CFSetRef ip_service_changes)
{
CandidateRef primary = NULL;
Boolean primary_is_null = FALSE;
service_dict = service_dict_get(scan->serviceID, entity_name);
service_routes = ipdict_get_routelist(service_dict);
if (service_routes != NULL) {
+ boolean_t force;
Rank rank = scan->rank;
if (skip) {
/* routes are RankNever to prevent becoming primary */
rank = RankMake(rank, kRankAssertionNever);
}
+ force = my_CFSetContainsValue(ip_service_changes,
+ scan->serviceID);
routes = RouteListAddRouteList(info, routes, initial_size,
- service_routes, rank);
+ service_routes, rank, force);
if ((service_routes->flags & kRouteListFlagsExcludeNWI) != 0) {
skip = TRUE;
}
boolean_t dnsinfo_changed = FALSE;
boolean_t global_ipv4_changed = FALSE;
boolean_t global_ipv6_changed = FALSE;
+ CFMutableSetRef ipv4_service_changes = NULL;
+ CFMutableSetRef ipv6_service_changes = NULL;
keyChangeList keys;
CFIndex n;
boolean_t nat64_changed = FALSE;
keyChangeListInit(&keys);
service_changes = CFArrayCreateMutable(NULL, 0,
&kCFTypeArrayCallBacks);
-
for (CFIndex i = 0; i < count; i++) {
CFStringRef change;
#if !TARGET_OS_SIMULATOR && !TEST_IPV4_ROUTELIST && !TEST_IPV6_ROUTELIST
reachability_changed = TRUE;
}
else if (CFStringHasPrefix(change, S_state_service_prefix)) {
+ CFStringRef protocol = NULL;
CFStringRef serviceID;
- serviceID = parse_component(change, S_state_service_prefix);
+ serviceID = parseNetworkServiceString(change, &protocol);
if (serviceID != NULL) {
my_CFArrayAppendUniqueValue(service_changes, serviceID);
+ if (protocol != NULL) {
+ if (CFEqual(protocol, kSCEntNetIPv4)) {
+ /* IPv4 service changed, remember that */
+ my_CFSetAddValue(&ipv4_service_changes, serviceID);
+ }
+ else if (CFEqual(protocol, kSCEntNetIPv6)) {
+ /* IPv6 service changed, remember that */
+ my_CFSetAddValue(&ipv6_service_changes, serviceID);
+ }
+ }
CFRelease(serviceID);
}
+ my_CFRelease(&protocol);
}
else if (CFStringHasPrefix(change, S_setup_service_prefix)) {
CFStringRef serviceID;
- serviceID = parse_component(change, S_setup_service_prefix);
+ serviceID = parseNetworkServiceString(change, NULL);
if (serviceID != NULL) {
my_CFArrayAppendUniqueValue(service_changes, serviceID);
CFRelease(serviceID);
}
}
- /* process protocol (v4, v6, rank, ...) and configuration (dns, proxies, smb, ...) changes */
+ /*
+ * process protocol (v4, v6, rank, ...) and
+ * configuration (dns, proxies, smb, ...) changes
+ */
n = CFArrayGetCount(service_changes);
for (CFIndex i = 0; i < n; i++) {
uint32_t changes;
serviceID = CFArrayGetValueAtIndex(service_changes, i);
changes = service_changed(services_info, serviceID);
+ if (my_CFSetContainsValue(ipv4_service_changes, serviceID)) {
+ changes |= (1 << kEntityTypeIPv4);
+ }
+ if (my_CFSetContainsValue(ipv6_service_changes, serviceID)) {
+ changes |= (1 << kEntityTypeIPv6);
+ }
if ((changes & (1 << kEntityTypeServiceOptions)) != 0) {
/* if __Service__ (e.g. PrimaryRank) changed */
global_ipv4_changed = TRUE;
other_candidate,
S_nwi_state, AF_INET,
&new_routelist.common,
- services_info);
+ services_info,
+ ipv4_service_changes);
new_primary = (primary_candidate != NULL)
? primary_candidate->serviceID : NULL;
(void)set_new_primary(&S_primary_ipv4, new_primary, "IPv4");
other_candidate,
S_nwi_state, AF_INET6,
&new_routelist.common,
- services_info);
+ services_info,
+ ipv6_service_changes);
new_primary = (primary_candidate != NULL)
? primary_candidate->serviceID : NULL;
(void)set_new_primary(&S_primary_ipv6, new_primary, "IPv6");
}
my_CFRelease(&service_changes);
my_CFRelease(&services_info);
+ my_CFRelease(&ipv4_service_changes);
+ my_CFRelease(&ipv6_service_changes);
if (changes != 0) {
network_change_msg = CFStringCreateMutable(NULL, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
CFRelease(rls);
- serviceIDNumberInit();
-
/* initialize dns configuration */
(void)dns_configuration_set(NULL, NULL, NULL, NULL, NULL);
#if !TARGET_OS_IPHONE
= CFNumberCreate(NULL, kCFNumberSInt32Type, &rank_assertion);
}
}
- r = IPv4RouteListCreateWithDictionary(routes, dict, rank_assertion_cf, 0);
+ r = IPv4RouteListCreateWithDictionary(routes, dict, rank_assertion_cf);
my_CFRelease(&rank_assertion_cf);
if (r == NULL) {
fprintf(stderr, "IPv4RouteListCreateWithDictionary failed\n");
= CFNumberCreate(NULL, kCFNumberSInt32Type, &rank_assertion);
}
}
- r = IPv6RouteListCreateWithDictionary(routes, dict, rank_assertion_cf, 0);
+ r = IPv6RouteListCreateWithDictionary(routes, dict, rank_assertion_cf);
my_CFRelease(&rank_assertion_cf);
if (r == NULL) {
fprintf(stderr, "IPv6RouteListCreateWithDictionary failed\n");
+++ /dev/null
-/*
- * Copyright (c) 2019 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@
- */
-
-/*
- * serviceID_number.c
- * - assigns numbers to serviceID strings
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "serviceIDNumber.h"
-#include <CoreFoundation/CFDictionary.h>
-
-#if TEST_SERVICEID_NUMBER
-#include <SystemConfiguration/SCPrivate.h>
-#endif /* TEST_SERVICEID_NUMBER */
-
-
-/* dictionary to hold serviceIDNumber: key is the serviceID */
-static CFMutableDictionaryRef S_serviceID_to_number_dict;
-
-/* dictionary to hold serviceID: key is the serviceIDNumber */
-static CFMutableDictionaryRef S_number_to_serviceID_dict;
-
-static Boolean
-serviceIDNumberEqual(const void * ptr1, const void * ptr2)
-{
- return (((serviceIDNumber)ptr1) == ((serviceIDNumber)ptr2));
-}
-
-static CFStringRef
-serviceIDNumberCopyDescription(const void * ptr)
-{
- return CFStringCreateWithFormat(NULL, NULL, CFSTR("%ld"),
- (serviceIDNumber)ptr);
-}
-
-static CFHashCode
-serviceIDNumberHash(const void * ptr) {
- return (CFHashCode)((serviceIDNumber)ptr);
-}
-
-static const CFDictionaryValueCallBacks kserviceIDNumberValueCallBacks = {
- 0, NULL, NULL, serviceIDNumberCopyDescription, serviceIDNumberEqual
-};
-
-static const CFDictionaryKeyCallBacks kserviceIDNumberKeyCallBacks = {
- 0, NULL, NULL, serviceIDNumberCopyDescription, serviceIDNumberEqual,
- serviceIDNumberHash
-};
-
-/**
- ** S_serviceID_numbers
- **/
-
-__private_extern__ Boolean
-serviceIDNumberGetIfPresent(CFStringRef serviceID, serviceIDNumber *sidn)
-{
- Boolean has_number;
- const void * val;
-
- has_number = CFDictionaryGetValueIfPresent(S_serviceID_to_number_dict,
- serviceID, &val);
- if (has_number) {
- *sidn = (serviceIDNumber)val;
- }
- return (has_number);
-}
-
-/*
- * Function: serviceIDNumberGet
- * Purpose:
- * Return the currently assigned serviceIDNumber for the given serviceID.
- * If one is already assigned, return that. If one isn't assigned, check
- * the next integer value after 'current_sidn', but skip zero.
- * If that number is assigned, pick the next one.
- */
-static serviceIDNumber S_current_sidn;
-
-__private_extern__ serviceIDNumber
-serviceIDNumberGet(CFStringRef serviceID)
-{
- serviceIDNumber sidn;
-
- if (serviceIDNumberGetIfPresent(serviceID, &sidn)) {
- return (sidn);
- }
- while (1) {
- /* assign a number to the serviceID */
- S_current_sidn++;
- if (S_current_sidn == kserviceIDNumberZero) {
- /* skip zero */
- S_current_sidn++;
- }
- /* if it's in use, skip to the next value */
- if (CFDictionaryContainsKey(S_number_to_serviceID_dict,
- (const void *)S_current_sidn)) {
- continue;
- }
- /* it's not in use, use it */
- sidn = S_current_sidn;
- CFDictionarySetValue(S_serviceID_to_number_dict,
- serviceID, (const void *)sidn);
- CFDictionarySetValue(S_number_to_serviceID_dict,
- (const void *)sidn, serviceID);
- break;
- }
- return (sidn);
-}
-
-
-__private_extern__ void
-serviceIDNumberRemove(CFStringRef serviceID)
-{
- const void * val;
-
- if (CFDictionaryGetValueIfPresent(S_serviceID_to_number_dict, serviceID,
- &val)) {
-#if TEST_SERVICEID_NUMBER
- SCPrint(TRUE, stdout, CFSTR("Removing %@ %ld\n"),
- serviceID, (serviceIDNumber)val);
-#endif
- CFDictionaryRemoveValue(S_serviceID_to_number_dict, serviceID);
- CFDictionaryRemoveValue(S_number_to_serviceID_dict, val);
- }
-}
-
-__private_extern__ void
-serviceIDNumberInit(void)
-{
- S_serviceID_to_number_dict
- = CFDictionaryCreateMutable(NULL, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kserviceIDNumberValueCallBacks);
- S_number_to_serviceID_dict
- = CFDictionaryCreateMutable(NULL, 0,
- &kserviceIDNumberKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
-}
-
-#if TEST_SERVICEID_NUMBER
-
-static CFStringRef
-my_CFUUIDStringCreate(CFAllocatorRef alloc)
-{
- CFUUIDRef uuid;
- CFStringRef uuid_str;
-
- uuid = CFUUIDCreate(alloc);
- uuid_str = CFUUIDCreateString(alloc, uuid);
- CFRelease(uuid);
- return (uuid_str);
-}
-
-int
-main()
-{
-#define N_LIST 10
- CFStringRef serviceID_list[N_LIST];
-
- serviceIDNumberInit();
- for (int i = 0; i < N_LIST; i++) {
- CFStringRef serviceID = my_CFUUIDStringCreate(NULL);
- serviceIDNumber sidn;
-
- /* force a collision */
- S_current_sidn = -1;
-
- sidn = serviceIDNumberGet(serviceID);
- SCPrint(TRUE, stdout, CFSTR("%d: %@ %ld\n"),
- i, serviceID, sidn);
- serviceID_list[i] = serviceID;
-
- }
- for (int i = 0; i < N_LIST; i++) {
- CFStringRef serviceID = serviceID_list[i];
- serviceIDNumber sidn;
-
- if (!serviceIDNumberGetIfPresent(serviceID, &sidn)) {
- SCPrint(TRUE, stderr, CFSTR("Failed to find %@\n"),
- serviceID);
- exit(1);
- }
- SCPrint(TRUE, stdout, CFSTR("%@ => %ld\n"), serviceID, sidn);
- }
- {
- serviceIDNumber sidn;
-
- if (serviceIDNumberGetIfPresent(CFSTR("blah"), &sidn)) {
- fprintf(stderr,
- "Shouldn't have been able to look that up\n");
- exit(1);
- }
- }
-
- for (int i = 0; i < N_LIST / 2; i++) {
- CFStringRef serviceID = serviceID_list[i];
- serviceIDNumber sidn;
-
- serviceIDNumberRemove(serviceID);
- if (serviceIDNumberGetIfPresent(serviceID, &sidn)) {
- SCPrint(TRUE, stderr,
- CFSTR("Found %@, but shouldn't have\n"),
- serviceID);
- exit(1);
- }
- }
-
- for (int i = 0; i < N_LIST; i++) {
- CFStringRef serviceID = serviceID_list[i];
- serviceIDNumber sidn;
-
- sidn = serviceIDNumberGet(serviceID);
- SCPrint(TRUE, stdout, CFSTR("%d: %@ %ld\n"),
- i, serviceID, sidn);
- }
- exit(0);
-}
-#endif /* TEST_SERVICEID_NUMBER */