From 009a3e7e772ccf5711a441a5c27f6615ef3ccd4d Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 2 Feb 2012 16:15:31 +0000 Subject: [PATCH] configd-395.10.tar.gz --- Makefile | 18 + Plugins/IPMonitor/Info.plist | 2 +- Plugins/InterfaceNamer/Info.plist | 2 +- Plugins/KernelEventMonitor/Info.plist | 2 +- Plugins/LinkConfiguration/Info.plist | 2 +- Plugins/Logger/Info-Embedded.plist | 2 +- Plugins/Logger/Info.plist | 2 +- Plugins/NetworkIdentification/Info.plist | 2 +- Plugins/PreferencesMonitor/Info.plist | 2 +- SCMonitor/Info.plist | 2 +- SystemConfiguration.fproj/Info-Embedded.plist | 2 +- SystemConfiguration.fproj/Info.plist | 2 +- .../SCNetworkReachability.c | 493 ++++++++++++++++-- SystemConfiguration.fproj/SCPrivate.h | 1 + SystemConfiguration.fproj/dy_framework.c | 3 +- SystemConfiguration.fproj/dy_framework.h | 3 +- .../helper/SCHelper_server.c | 3 +- configd.tproj/session.c | 5 +- 18 files changed, 476 insertions(+), 72 deletions(-) diff --git a/Makefile b/Makefile index d65e129..1102fd3 100644 --- a/Makefile +++ b/Makefile @@ -39,3 +39,21 @@ snow : -release $(shell cat /usr/share/buildit/.releaseName) \ -othercflags "\"$(SNOW_CFLAGS)\"" \ +#---------------------------------------------------------------------- +# +# Build for Lion, SULionXXX, ... +# +#---------------------------------------------------------------------- + +LION_CFLAGS= + +lion : + /usr/local/bin/buildit . \ + -noinstallsrc -noinstallhdrs -noverify -nosum \ + -arch i386 -arch x86_64 \ + -target All \ + -project ${PROJECT}-${VERSION} \ + -configuration Debug \ + -release $(shell cat /usr/share/buildit/.releaseName) \ + -othercflags "$(LION_CFLAGS)" \ + diff --git a/Plugins/IPMonitor/Info.plist b/Plugins/IPMonitor/Info.plist index 52c80f5..a29cf26 100644 --- a/Plugins/IPMonitor/Info.plist +++ b/Plugins/IPMonitor/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.11.1 + 1.11.2 CFBundleSignature ???? CFBundleVersion diff --git a/Plugins/InterfaceNamer/Info.plist b/Plugins/InterfaceNamer/Info.plist index 244ec1a..ee235fc 100644 --- a/Plugins/InterfaceNamer/Info.plist +++ b/Plugins/InterfaceNamer/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.11.1 + 1.11.2 CFBundleSignature ???? CFBundleVersion diff --git a/Plugins/KernelEventMonitor/Info.plist b/Plugins/KernelEventMonitor/Info.plist index 024f038..146c74e 100644 --- a/Plugins/KernelEventMonitor/Info.plist +++ b/Plugins/KernelEventMonitor/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.11.1 + 1.11.2 CFBundleSignature ???? CFBundleVersion diff --git a/Plugins/LinkConfiguration/Info.plist b/Plugins/LinkConfiguration/Info.plist index 21adc60..8655cee 100644 --- a/Plugins/LinkConfiguration/Info.plist +++ b/Plugins/LinkConfiguration/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.11.1 + 1.11.2 CFBundleSignature ???? CFBundleVersion diff --git a/Plugins/Logger/Info-Embedded.plist b/Plugins/Logger/Info-Embedded.plist index db9e629..c0eed04 100644 --- a/Plugins/Logger/Info-Embedded.plist +++ b/Plugins/Logger/Info-Embedded.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.11.1 + 1.11.2 CFBundleSignature ???? CFBundleVersion diff --git a/Plugins/Logger/Info.plist b/Plugins/Logger/Info.plist index b8c904d..1f56695 100644 --- a/Plugins/Logger/Info.plist +++ b/Plugins/Logger/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.11.1 + 1.11.2 CFBundleSignature ???? CFBundleVersion diff --git a/Plugins/NetworkIdentification/Info.plist b/Plugins/NetworkIdentification/Info.plist index db066bd..b025a55 100644 --- a/Plugins/NetworkIdentification/Info.plist +++ b/Plugins/NetworkIdentification/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.11.1 + 1.11.2 CFBundleSignature ???? CFBundleVersion diff --git a/Plugins/PreferencesMonitor/Info.plist b/Plugins/PreferencesMonitor/Info.plist index 59113e5..609f4eb 100644 --- a/Plugins/PreferencesMonitor/Info.plist +++ b/Plugins/PreferencesMonitor/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.11.1 + 1.11.2 CFBundleSignature ???? CFBundleVersion diff --git a/SCMonitor/Info.plist b/SCMonitor/Info.plist index 1889870..5a07d4d 100644 --- a/SCMonitor/Info.plist +++ b/SCMonitor/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.11.1 + 1.11.2 CFBundleSignature ???? CFBundleVersion diff --git a/SystemConfiguration.fproj/Info-Embedded.plist b/SystemConfiguration.fproj/Info-Embedded.plist index 9112621..40e8929 100644 --- a/SystemConfiguration.fproj/Info-Embedded.plist +++ b/SystemConfiguration.fproj/Info-Embedded.plist @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.11.1 + 1.11.2 CFBundleSignature ???? CFBundleVersion diff --git a/SystemConfiguration.fproj/Info.plist b/SystemConfiguration.fproj/Info.plist index 9112621..40e8929 100644 --- a/SystemConfiguration.fproj/Info.plist +++ b/SystemConfiguration.fproj/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.11.1 + 1.11.2 CFBundleSignature ???? CFBundleVersion diff --git a/SystemConfiguration.fproj/SCNetworkReachability.c b/SystemConfiguration.fproj/SCNetworkReachability.c index 7cc048c..4b6ebd0 100644 --- a/SystemConfiguration.fproj/SCNetworkReachability.c +++ b/SystemConfiguration.fproj/SCNetworkReachability.c @@ -86,6 +86,8 @@ #endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000)) && !TARGET_IPHONE_SIMULATOR && !TARGET_OS_EMBEDDED_OTHER + + #ifdef HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL /* Libinfo SPI */ mach_port_t @@ -104,6 +106,9 @@ _getaddrinfo_interface_async_call(const char *nodename, #define N_QUICK 64 +typedef enum { NO = 0, YES, UNKNOWN } lazyBoolean; + + typedef enum { reachabilityTypeAddress, reachabilityTypeAddressPair, @@ -111,6 +116,14 @@ typedef enum { } addressType; +// how long (minimum time, us) to wait before retrying DNS query after EAI_NONAME +#define EAI_NONAME_RETRY_DELAY_USEC 250000 + +// how long (maximum time, us) after DNS configuration change we accept EAI_NONAME +// without question. +#define EAI_NONAME_RETRY_LIMIT_USEC 2500000 + + static CFStringRef __SCNetworkReachabilityCopyDescription (CFTypeRef cf); static void __SCNetworkReachabilityDeallocate (CFTypeRef cf); static void rlsPerform(void *info); @@ -185,6 +198,12 @@ typedef struct { CFMachPortRef dnsPort; CFRunLoopSourceRef dnsRLS; struct timeval dnsQueryStart; + struct timeval dnsQueryEnd; + dispatch_source_t dnsRetry; // != NULL if DNS retry request queued + int dnsRetryCount; // number of retry attempts + + /* [async] processing info */ + struct timeval last_dns; /* on demand info */ Boolean onDemandBypass; @@ -193,6 +212,7 @@ typedef struct { SCNetworkReachabilityRef onDemandServer; CFStringRef onDemandServiceID; + /* logging */ char log_prefix[32]; @@ -221,6 +241,9 @@ static const ReachabilityInfo NOT_REPORTED = { 0xFFFFFFFF, 0, FALSE }; static int rtm_seq = 0; +static const struct timeval TIME_ZERO = { 0, 0 }; + + #if !TARGET_OS_IPHONE /* * Power capabilities (sleep/wake) @@ -263,22 +286,37 @@ isA_SCNetworkReachability(CFTypeRef obj) static void -__log_query_time(SCNetworkReachabilityRef target, Boolean found, Boolean async, struct timeval *start) +__dns_query_start(struct timeval *dnsQueryStart, + struct timeval *dnsQueryEnd) +{ + (void) gettimeofday(dnsQueryStart, NULL); + *dnsQueryEnd = TIME_ZERO; + + return; +} + + +static void +__dns_query_end(SCNetworkReachabilityRef target, + Boolean found, + Boolean async, + struct timeval *dnsQueryStart, + struct timeval *dnsQueryEnd) { - struct timeval dnsQueryComplete; struct timeval dnsQueryElapsed; SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + (void) gettimeofday(dnsQueryEnd, NULL); + if (!_sc_debug) { return; } - if (start->tv_sec == 0) { + if (dnsQueryStart->tv_sec == 0) { return; } - (void) gettimeofday(&dnsQueryComplete, NULL); - timersub(&dnsQueryComplete, start, &dnsQueryElapsed); + timersub(dnsQueryEnd, dnsQueryStart, &dnsQueryElapsed); SCLog(TRUE, LOG_INFO, CFSTR("%s%ssync DNS complete%s (query time = %d.%3.3d)"), targetPrivate->log_prefix, @@ -294,13 +332,23 @@ __log_query_time(SCNetworkReachabilityRef target, Boolean found, Boolean async, static __inline__ Boolean __reach_equal(ReachabilityInfo *r1, ReachabilityInfo *r2) { - if ((r1->flags == r2->flags ) && - (r1->if_index == r2->if_index) && - (r1->sleeping == r2->sleeping)) { - return TRUE; + if (r1->flags != r2->flags) { + // if the reachability flags changed + return FALSE; } - return FALSE; + if (r1->if_index != r2->if_index) { + // if the target interface changed + return FALSE; + } + + if ((r1->sleeping != r2->sleeping) && !r2->sleeping) { + // if our sleep/wake status changed and if we + // are no longer sleeping + return FALSE; + } + + return TRUE; } @@ -1712,6 +1760,9 @@ __SCNetworkReachabilityDeallocate(CFTypeRef cf) { SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)cf; + SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%srelease"), + targetPrivate->log_prefix); + /* release resources */ pthread_mutex_destroy(&targetPrivate->lock); @@ -1759,6 +1810,56 @@ static void __SCNetworkReachabilityInitialize(void) { __kSCNetworkReachabilityTypeID = _CFRuntimeRegisterClass(&__SCNetworkReachabilityClass); + + // provide a way to enable SCNetworkReachability logging without + // having to set _sc_debug=1. + if (getenv("REACH_LOGGING") != NULL) { + _sc_debug = TRUE; + } + + return; +} + + +/* + * __SCNetworkReachabilityPerformInline + * + * Calls rlsPerform() + * - caller must be holding a reference to the target + * - caller must *not* be holding the target lock + */ +static __inline__ void +__SCNetworkReachabilityPerformInline(SCNetworkReachabilityRef target, Boolean needResolve) +{ + dispatch_queue_t queue; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + pthread_mutex_lock(&targetPrivate->lock); + + if (needResolve) { + // allow the DNS query to be [re-]started + targetPrivate->needResolve = TRUE; + } + + queue = targetPrivate->dispatchQueue; + if (queue != NULL) { + dispatch_retain(queue); + + pthread_mutex_unlock(&targetPrivate->lock); + + dispatch_sync(queue, ^{ + rlsPerform((void *)target); + dispatch_release(queue); + }); + } else { + if (targetPrivate->rls != NULL) { + CFRunLoopSourceSignal(targetPrivate->rls); + _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList); + } + + pthread_mutex_unlock(&targetPrivate->lock); + } + return; } @@ -1837,6 +1938,12 @@ __SCNetworkReachabilityCreatePrivate(CFAllocatorRef allocator) targetPrivate->dnsMP = MACH_PORT_NULL; targetPrivate->dnsPort = NULL; targetPrivate->dnsRLS = NULL; + targetPrivate->dnsQueryStart = TIME_ZERO; + targetPrivate->dnsQueryEnd = TIME_ZERO; + targetPrivate->dnsRetry = NULL; + targetPrivate->dnsRetryCount = 0; + + targetPrivate->last_dns = TIME_ZERO; targetPrivate->onDemandBypass = FALSE; targetPrivate->onDemandName = NULL; @@ -1844,6 +1951,7 @@ __SCNetworkReachabilityCreatePrivate(CFAllocatorRef allocator) targetPrivate->onDemandServer = NULL; targetPrivate->onDemandServiceID = NULL; + targetPrivate->log_prefix[0] = '\0'; if (_sc_log > 0) { snprintf(targetPrivate->log_prefix, @@ -1926,6 +2034,10 @@ SCNetworkReachabilityCreateWithAddress(CFAllocatorRef allocator, targetPrivate->remoteAddress = CFAllocatorAllocate(NULL, address->sa_len, 0); bcopy(address, targetPrivate->remoteAddress, address->sa_len); + SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%screate w/address %@"), + targetPrivate->log_prefix, + targetPrivate); + return (SCNetworkReachabilityRef)targetPrivate; } @@ -1975,6 +2087,10 @@ SCNetworkReachabilityCreateWithAddressPair(CFAllocatorRef allocator, bcopy(remoteAddress, targetPrivate->remoteAddress, remoteAddress->sa_len); } + SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%screate w/address pair %@"), + targetPrivate->log_prefix, + targetPrivate); + return (SCNetworkReachabilityRef)targetPrivate; } @@ -2037,10 +2153,16 @@ SCNetworkReachabilityCreateWithName(CFAllocatorRef allocator, targetPrivate->needResolve = TRUE; targetPrivate->info.flags |= kSCNetworkReachabilityFlagsFirstResolvePending; + SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%screate w/name %@"), + targetPrivate->log_prefix, + targetPrivate); + return (SCNetworkReachabilityRef)targetPrivate; } + + SCNetworkReachabilityRef SCNetworkReachabilityCreateWithOptions(CFAllocatorRef allocator, CFDictionaryRef options) @@ -2117,6 +2239,7 @@ SCNetworkReachabilityCreateWithOptions(CFAllocatorRef allocator, return NULL; } + if ((nodename != NULL) || (servname != NULL)) { const char *name; @@ -2167,10 +2290,15 @@ SCNetworkReachabilityCreateWithOptions(CFAllocatorRef allocator, } } + if (bypass != NULL) { targetPrivate->onDemandBypass = CFBooleanGetValue(bypass); } + SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%s + options %@"), + targetPrivate->log_prefix, + targetPrivate); + return (SCNetworkReachabilityRef)targetPrivate; } @@ -2279,10 +2407,11 @@ __SCNetworkReachabilityCallbackSetResolvedAddress(int32_t status, struct addrinf SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)context; SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; - __log_query_time(target, - ((status == 0) && (res != NULL)), // if successful query - TRUE, // async - &targetPrivate->dnsQueryStart); // start time + __dns_query_end(target, + ((status == 0) && (res != NULL)), // if successful query + TRUE, // async + &targetPrivate->dnsQueryStart, // start time + &targetPrivate->dnsQueryEnd); // end time __SCNetworkReachabilitySetResolvedAddress(status, res, target); return; @@ -3129,7 +3258,7 @@ startAsyncDNSQuery(SCNetworkReachabilityRef target) { Boolean ok; SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; - (void) gettimeofday(&targetPrivate->dnsQueryStart, NULL); + __dns_query_start(&targetPrivate->dnsQueryStart, &targetPrivate->dnsQueryEnd); #ifdef HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL if (targetPrivate->if_index == 0) { @@ -3164,6 +3293,63 @@ startAsyncDNSQuery(SCNetworkReachabilityRef target) { } +#pragma mark - + + +static Boolean +enqueueAsyncDNSRetry(SCNetworkReachabilityRef target) +{ + int64_t delay; + dispatch_source_t source; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, + 0, + 0, + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + if (source == NULL) { + SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability retry dispatch_source_create() failed")); + return FALSE; + } + + // retain the target ... and release it when the [timer] source is released + CFRetain(target); + dispatch_set_context(source, (void *)target); + dispatch_set_finalizer_f(source, (dispatch_function_t)CFRelease); + + dispatch_source_set_event_handler(source, ^(void) { + __SCNetworkReachabilityPerformInline(target, TRUE); + }); + + // start a one-shot timer + delay = targetPrivate->dnsRetryCount * EAI_NONAME_RETRY_DELAY_USEC * NSEC_PER_USEC; + dispatch_source_set_timer(source, + dispatch_time(DISPATCH_TIME_NOW, delay), // start + 0, // interval + 10 * NSEC_PER_MSEC); // leeway + + targetPrivate->dnsRetry = source; + dispatch_resume(source); + + return TRUE; +} + + +static void +dequeueAsyncDNSRetry(SCNetworkReachabilityRef target) +{ + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + if (targetPrivate->dnsRetry != NULL) { + dispatch_source_cancel(targetPrivate->dnsRetry); + dispatch_release(targetPrivate->dnsRetry); + targetPrivate->dnsRetry = NULL; + } + + return; +} + + #pragma mark - #pragma mark OnDemand @@ -3540,6 +3726,7 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef store_info, case reachabilityTypeName : { struct timeval dnsQueryStart; + struct timeval dnsQueryEnd; int error; SCNetworkReachabilityFlags ns_flags; struct addrinfo *res; @@ -3550,9 +3737,115 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef store_info, if (!async) { /* if not an async request */ goto checkResolvedAddress; - } else if ((targetPrivate->dnsPort == NULL) && !targetPrivate->needResolve) { - /* if async request, no query active, and no query needed */ - goto checkResolvedAddress; + } else if ((targetPrivate->dnsMP == MACH_PORT_NULL) && !targetPrivate->needResolve) { + struct timeval elapsed; + const struct timeval retry_limit = { EAI_NONAME_RETRY_LIMIT_USEC / USEC_PER_SEC, + EAI_NONAME_RETRY_LIMIT_USEC % USEC_PER_SEC }; + + /* + * if this is an async request (i.e. someone is watching the reachability + * of this target), if no query active, and if no query is needed + */ + + if ((error != EAI_NONAME) +#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) + && (error != EAI_NODATA) +#endif + ) { + /* if not "host not found" */ + goto checkResolvedAddress; + } + + /* + * if our last DNS query returned EAI_NONAME then we + * "may" want to retry. + * + * Specifically, if the [DNS] configuration was updated a while + * back then we'll trust the EAI_NONAME reply. Otherwise, we + * want to try again to ensure that we didn't get caught in a + * race between the time when the configuration was changed and + * when mDNSResponder is really ready to handle the query. + * + * Retry handling details : + * + * Compare the time when the DNS configuration was last changed and + * when our DNS reply was started (->last_dns vs ->dnsQueryStart). + * + * Expected: 0 < last_dns (t1) < dnsQueryStart (t2) + * + * last start end description action + * ==== ===== ==== ================================= ======== + * 0 N/A N/A no change, query error no retry + * 0 N/A N/A no change, query complete no retry + * N/A N/A 0 changed, query in-flight or error no retry + * t1 > t2 query started, then [DNS] changed no retry + * t1 == t2 changed & query started together no retry + * t1 < t2 changed, then query started retry + */ + + if (!timerisset(&targetPrivate->last_dns)) { + /* + * if we have not yet seen a DNS configuration + * change + */ + goto checkResolvedAddress; + } + + if (!timerisset(&targetPrivate->dnsQueryEnd)) { + /* + * if no query end time (new request in flight) + */ + goto checkResolvedAddress; + } + + if (timercmp(&targetPrivate->last_dns, + &targetPrivate->dnsQueryStart, + >=)) { + /* + * if our DNS query started and then, a + * short time later, the DNS configuration + * was changed we don't need to retry + * because we will be re-issuing (and not + * retrying) the query. + */ + goto checkResolvedAddress; + } + + timersub(&targetPrivate->dnsQueryStart, + &targetPrivate->last_dns, + &elapsed); + if (timercmp(&elapsed, &retry_limit, >)) { + /* + * if the DNS query started after mDNSResponder + * had a chance to apply the last configuration + * then we should trust the EAI_NONAME reply. + */ + goto checkResolvedAddress; + } + + /* retry the DNS query */ + + if (targetPrivate->dnsRetry != NULL) { + // no need to schedule if we already have a + // retry query in flight + break; + } + + targetPrivate->dnsRetryCount++; + + SCLog(_sc_debug, LOG_INFO, + CFSTR("%sretry [%d] DNS query for %s%s%s%s%s"), + targetPrivate->log_prefix, + targetPrivate->dnsRetryCount, + targetPrivate->name != NULL ? "name = " : "", + targetPrivate->name != NULL ? targetPrivate->name : "", + targetPrivate->name != NULL && targetPrivate->serv != NULL ? ", " : "", + targetPrivate->serv != NULL ? "serv = " : "", + targetPrivate->serv != NULL ? targetPrivate->serv : ""); + + enqueueAsyncDNSRetry(target); + + break; } } @@ -3637,6 +3930,11 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef store_info, break; } + if (targetPrivate->dnsRetry != NULL) { + /* if we already have a "retry" queued */ + break; + } + SCLog(_sc_debug, LOG_INFO, CFSTR("%sstart DNS query for %s%s%s%s%s"), targetPrivate->log_prefix, @@ -3671,9 +3969,7 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef store_info, * OK, all of the DNS name servers are available. Let's * resolve the nodename into an address. */ - if (_sc_debug) { - (void) gettimeofday(&dnsQueryStart, NULL); - } + __dns_query_start(&dnsQueryStart, &dnsQueryEnd); #ifdef HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL if (targetPrivate->if_index == 0) { @@ -3692,10 +3988,11 @@ __SCNetworkReachabilityGetFlags(ReachabilityStoreInfoRef store_info, } #endif // HAVE_GETADDRINFO_INTERFACE_ASYNC_CALL - __log_query_time(target, + __dns_query_end(target, ((error == 0) && (res != NULL)), // if successful query FALSE, // sync - &dnsQueryStart); // start time + &dnsQueryStart, // start time + &dnsQueryEnd); // end time __SCNetworkReachabilitySetResolvedAddress(error, res, target); @@ -3986,11 +4283,15 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) { +#if !TARGET_OS_IPHONE + Boolean cpuStatusChanged = FALSE; +#endif // !TARGET_OS_IPHONE Boolean dnsConfigChanged = FALSE; CFIndex i; CFStringRef key; CFIndex nChanges = CFArrayGetCount(changedKeys); CFIndex nTargets; + struct timeval now; #if !TARGET_OS_IPHONE Boolean powerStatusChanged = FALSE; #endif // !TARGET_OS_IPHONE @@ -4011,6 +4312,9 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef store, goto done; } + /* grab the current time */ + (void)gettimeofday(&now, NULL); + #if !TARGET_OS_IPHONE key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@%@"), kSCDynamicStoreDomainState, @@ -4022,7 +4326,24 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef store, if (num != NULL) { if (isA_CFNumber(num) && CFNumberGetValue(num, kCFNumberSInt32Type, &power_capabilities)) { + static Boolean haveCPU_old = TRUE; + Boolean haveCPU_new; + powerStatusChanged = TRUE; + + haveCPU_new = (power_capabilities & kIOPMSystemPowerStateCapabilityCPU) != 0; + if ((haveCPU_old != haveCPU_new) && haveCPU_new) { + /* + * if the power state now shows CPU availability + * then we will assume that the DNS configuration + * has changed. This will force us to re-issue + * our DNS queries since mDNSResponder does not + * attempt to resolve names when "sleeping". + */ + cpuStatusChanged = TRUE; + dnsConfigChanged = TRUE; + } + haveCPU_old = haveCPU_new; } CFRelease(num); @@ -4040,13 +4361,35 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef store, CFRelease(key); if (_sc_debug) { - int changes = 0; - const char *str; + unsigned int changes = 0; + static const char *change_strings[] = { + // with no "power" status change + "", + "network ", + "DNS ", + "network and DNS ", +#if !TARGET_OS_IPHONE + // with "power" status change + "power ", + "network and power ", + "DNS and power ", + "network, DNS, and power ", + + // with no "power" status change (including CPU "on") + "power* ", + "network and power* ", + "DNS and power* ", + "network, DNS, and power* ", +#endif // !TARGET_OS_IPHONE + }; #if !TARGET_OS_IPHONE #define PWR 4 if (powerStatusChanged) { changes |= PWR; + if (cpuStatusChanged) { + changes += PWR; + } nChanges -= 1; } #endif // !TARGET_OS_IPHONE @@ -4062,21 +4405,9 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef store, changes |= NET; } - switch (changes) { - case 0 : str = ""; break; - case NET : str = "network "; break; - case DNS : str = "DNS "; break; - case DNS|NET : str = "network and DNS "; break; -#if !TARGET_OS_IPHONE - case PWR : str = "power "; break; - case PWR|NET : str = "network and power "; break; - case PWR|DNS : str = "DNS and power "; break; - case PWR|DNS|NET : str = "network, DNS, and power "; break; -#endif // !TARGET_OS_IPHONE - default : str = "??? "; - } - - SCLog(TRUE, LOG_INFO, CFSTR("process %sconfiguration change"), str); + SCLog(TRUE, LOG_INFO, + CFSTR("process %sconfiguration change"), + change_strings[changes]); } initReachabilityStoreInfo(&store_info); @@ -4090,6 +4421,11 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef store, pthread_mutex_lock(&targetPrivate->lock); + if (dnsConfigChanged) { + targetPrivate->last_dns = now; + targetPrivate->dnsRetryCount = 0; + } + if (targetPrivate->type == reachabilityTypeName) { Boolean dnsChanged = dnsConfigChanged; @@ -4147,6 +4483,11 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef store, getaddrinfo_async_cancel(mp); } + if (targetPrivate->dnsRetry != NULL) { + /* cancel the outstanding DNS retry */ + dequeueAsyncDNSRetry(target); + } + /* schedule request to resolve the name again */ targetPrivate->needResolve = TRUE; } @@ -4168,7 +4509,15 @@ __SCNetworkReachabilityHandleChanges(SCDynamicStoreRef store, #if !TARGET_OS_IPHONE -static __inline__ Boolean + +static Boolean +darkWakeNotify(SCNetworkReachabilityRef target) +{ + return FALSE; +} + + +static Boolean systemIsAwake(IOPMSystemPowerStateCapabilities power_capabilities) { @@ -4194,6 +4543,7 @@ systemIsAwake(IOPMSystemPowerStateCapabilities power_capabilities) return TRUE; } + #endif // !TARGET_OS_IPHONE @@ -4216,6 +4566,11 @@ rlsPerform(void *info) pthread_mutex_lock(&targetPrivate->lock); + if (targetPrivate->dnsRetry != NULL) { + // cancel DNS retry + dequeueAsyncDNSRetry(target); + } + if (!targetPrivate->scheduled) { // if not currently scheduled pthread_mutex_unlock(&targetPrivate->lock); @@ -4248,21 +4603,38 @@ rlsPerform(void *info) * don't report the change if the new reachability flags are * the same or "better" */ - defer = TRUE; + defer = !darkWakeNotify(target); } else if (__reach_equal(&targetPrivate->last_notify, &reach_info)) { - /* if we have already posted this change */ - defer = TRUE; + /* + * if we have already posted this change + */ + defer = !darkWakeNotify(target); } } #endif // !TARGET_OS_IPHONE if (__reach_equal(&targetPrivate->info, &reach_info)) { - SCLog(_sc_debug, LOG_INFO, - CFSTR("%sflags/interface match (now 0x%08x/%hu%s)"), - targetPrivate->log_prefix, - reach_info.flags, - reach_info.if_index, - reach_info.sleeping ? "*" : ""); + if (_sc_debug) { + if (targetPrivate->info.sleeping == reach_info.sleeping) { + SCLog(TRUE, LOG_INFO, + CFSTR("%sflags/interface match (now 0x%08x/%hu%s)"), + targetPrivate->log_prefix, + reach_info.flags, + reach_info.if_index, + reach_info.sleeping ? ", z" : ""); + } else { + SCLog(TRUE, LOG_INFO, + CFSTR("%sflags/interface equiv (was 0x%08x/%hu%s, now 0x%08x/%hu%s)"), + targetPrivate->log_prefix, + targetPrivate->info.flags, + targetPrivate->info.if_index, + targetPrivate->info.sleeping ? ", z" : "", + reach_info.flags, + reach_info.if_index, + reach_info.sleeping ? ", z" : ""); + } + + } pthread_mutex_unlock(&targetPrivate->lock); return; } @@ -4272,21 +4644,21 @@ rlsPerform(void *info) targetPrivate->log_prefix, targetPrivate->info.flags, targetPrivate->info.if_index, - targetPrivate->info.sleeping ? "*" : "", + targetPrivate->info.sleeping ? ", z" : "", reach_info.flags, reach_info.if_index, - reach_info.sleeping ? "*" : "", + reach_info.sleeping ? ", z" : "", defer ? ", deferred" : ""); - /* update flags / interface */ - targetPrivate->info = reach_info; - /* as needed, defer the notification */ if (defer) { pthread_mutex_unlock(&targetPrivate->lock); return; } + /* update flags / interface */ + targetPrivate->info = reach_info; + /* save last notification info */ targetPrivate->last_notify = reach_info; @@ -4504,6 +4876,9 @@ __SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target, __SCNetworkReachabilityScheduleWithRunLoop(targetPrivate->onDemandServer, runLoop, runLoopMode, queue, TRUE); } + SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%sscheduled"), + targetPrivate->log_prefix); + ok = TRUE; done : @@ -4595,6 +4970,11 @@ __SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef target, dequeueAsyncDNSQuery(target); getaddrinfo_async_cancel(mp); } + + if (targetPrivate->dnsRetry != NULL) { + // if we have an outstanding DNS retry + dequeueAsyncDNSRetry(target); + } } if (runLoop == NULL) { @@ -4621,6 +5001,9 @@ __SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef target, dns_configuration_unwatch(); } + SCLog((_sc_debug && (_sc_log > 0)), LOG_INFO, CFSTR("%sunscheduled"), + targetPrivate->log_prefix); + ok = TRUE; done : diff --git a/SystemConfiguration.fproj/SCPrivate.h b/SystemConfiguration.fproj/SCPrivate.h index ba073c4..96d5a39 100644 --- a/SystemConfiguration.fproj/SCPrivate.h +++ b/SystemConfiguration.fproj/SCPrivate.h @@ -127,6 +127,7 @@ extern int _sc_log; /* 0 if SC messages should be written to stdout/stderr, */ #define kSCNetworkReachabilityOptionConnectionOnDemandByPass CFSTR("ConnectionOnDemandByPass") + /*! @group */ diff --git a/SystemConfiguration.fproj/dy_framework.c b/SystemConfiguration.fproj/dy_framework.c index e35580e..3bfe8e0 100644 --- a/SystemConfiguration.fproj/dy_framework.c +++ b/SystemConfiguration.fproj/dy_framework.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2008, 2010 Apple Inc. All rights reserved. + * Copyright (c) 2002-2008, 2010, 2011 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -487,6 +487,7 @@ _SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeychainAttri return dyfunc ? dyfunc(itemRef, attrList, length, data) : -1; } + __private_extern__ OSStatus _SecTrustedApplicationCreateFromPath(const char *path, SecTrustedApplicationRef *app) { diff --git a/SystemConfiguration.fproj/dy_framework.h b/SystemConfiguration.fproj/dy_framework.h index 84e3d10..e1c928f 100644 --- a/SystemConfiguration.fproj/dy_framework.h +++ b/SystemConfiguration.fproj/dy_framework.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2008, 2010 Apple Inc. All rights reserved. + * Copyright (c) 2002-2008, 2010, 2011 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -300,6 +300,7 @@ _SecKeychainItemModifyContent ( ); #define SecKeychainItemModifyContent _SecKeychainItemModifyContent + OSStatus _SecTrustedApplicationCreateFromPath ( const char *path, diff --git a/SystemConfiguration.fproj/helper/SCHelper_server.c b/SystemConfiguration.fproj/helper/SCHelper_server.c index c7efc4c..62957bd 100644 --- a/SystemConfiguration.fproj/helper/SCHelper_server.c +++ b/SystemConfiguration.fproj/helper/SCHelper_server.c @@ -1251,7 +1251,8 @@ copyEntitlement(SCHelperSessionRef session, CFStringRef entitlement) CFIndex code = CFErrorGetCode(error); CFStringRef domain = CFErrorGetDomain(error); - if (!CFEqual(domain, kCFErrorDomainMach) || (code != kIOReturnNotFound)) { + if (!CFEqual(domain, kCFErrorDomainMach) || + ((code != kIOReturnInvalid) && (code != kIOReturnNotFound))) { // if unexpected error SCLog(TRUE, LOG_ERR, CFSTR("SecTaskCopyValueForEntitlement(,\"%@\",) failed, error = %@ : %@"), diff --git a/configd.tproj/session.c b/configd.tproj/session.c index ccce9b3..1b77827 100644 --- a/configd.tproj/session.c +++ b/configd.tproj/session.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, 2003-2005, 2007-2010 Apple Inc. All rights reserved. + * Copyright (c) 2000, 2001, 2003-2005, 2007-2011 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -391,8 +391,7 @@ hasEntitlement(serverSessionRef session, CFStringRef entitlement) CFSTR("hasEntitlement SecTaskCopyValueForEntitlement() %s, error domain=%@, error code=%lx"), (value == NULL) ? "failed" : "warned", CFErrorGetDomain(error), - CFErrorGetCode(error), - sessionName(session)); + CFErrorGetCode(error)); CFRelease(error); } -- 2.47.2