From 272360946778648e9090941ad1aa43b60d5031a3 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 19 Sep 2018 08:57:22 +0200 Subject: mDNSResponder: Update to v878.30.4 The sources can be obtained via: https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-878.30.4.tar.gz Close #3522. --- mDNSResponder/Makefile | 2 +- mDNSResponder/mDNSCore/mDNS.c | 15 +- mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h | 6 +- mDNSResponder/mDNSCore/uDNS.c | 15 +- mDNSResponder/mDNSMacOSX/Metrics.h | 18 +- mDNSResponder/mDNSMacOSX/Metrics.m | 973 +++++++++++++++++++++---------- mDNSResponder/mDNSMacOSX/daemon.c | 33 +- mDNSResponder/mDNSMacOSX/helper.c | 19 +- mDNSResponder/mDNSMacOSX/mDNSMacOSX.c | 54 +- mDNSResponder/mDNSShared/dns_sd.h | 2 +- 10 files changed, 782 insertions(+), 355 deletions(-) (limited to 'mDNSResponder') diff --git a/mDNSResponder/Makefile b/mDNSResponder/Makefile index 1c7c63ac..9d975334 100644 --- a/mDNSResponder/Makefile +++ b/mDNSResponder/Makefile @@ -16,7 +16,7 @@ include $(MAKEFILEPATH)/pb_makefiles/platform.make -MVERS = "mDNSResponder-878.20.3" +MVERS = "mDNSResponder-878.30.4" VER = ifneq ($(strip $(GCC_VERSION)),) diff --git a/mDNSResponder/mDNSCore/mDNS.c b/mDNSResponder/mDNSCore/mDNS.c index 0d4d8ae4..72375d94 100755 --- a/mDNSResponder/mDNSCore/mDNS.c +++ b/mDNSResponder/mDNSCore/mDNS.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2015 Apple Inc. All rights reserved. + * Copyright (c) 2002-2017 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -4170,12 +4170,12 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco responseLatencyMs = 0; } - MetricsUpdateUDNSQueryStats(queryName, q->qtype, &rr->resrec, q->metrics.querySendCount, responseLatencyMs, isForCellular); + MetricsUpdateDNSQueryStats(queryName, q->qtype, &rr->resrec, q->metrics.querySendCount, responseLatencyMs, isForCellular); q->metrics.answered = mDNStrue; } if (q->metrics.querySendCount > 0) { - MetricsUpdateUDNSResolveStats(queryName, &rr->resrec, isForCellular); + MetricsUpdateDNSResolveStats(queryName, &rr->resrec, isForCellular); } } #endif @@ -8944,6 +8944,13 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, response->h.numAuthorities, response->h.numAuthorities == 1 ? "y, " : "ies,", response->h.numAdditionals, response->h.numAdditionals == 1 ? " " : "s", end - response->data, LLQType); +#if AWD_METRICS + if (mDNSSameIPPort(srcport, UnicastDNSPort)) + { + MetricsUpdateDNSResponseSize((mDNSu32)(end - (mDNSu8 *)response)); + } +#endif + // According to RFC 2181 // When a DNS client receives a reply with TC // set, it should ignore that response, and query again, using a @@ -12127,7 +12134,7 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que queryName = question->metrics.originalQName ? question->metrics.originalQName : &question->qname; isForCell = (question->qDNSServer && question->qDNSServer->cellIntf); durationMs = ((m->timenow - question->metrics.firstQueryTime) * 1000) / mDNSPlatformOneSecond; - MetricsUpdateUDNSQueryStats(queryName, question->qtype, mDNSNULL, question->metrics.querySendCount, durationMs, isForCell); + MetricsUpdateDNSQueryStats(queryName, question->qtype, mDNSNULL, question->metrics.querySendCount, durationMs, isForCell); } #endif // Take care to cut question from list *before* calling UpdateQuestionDuplicates diff --git a/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h b/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h index 0e96058d..72ff7ca1 100755 --- a/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h +++ b/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2015 Apple Inc. All rights reserved. + * Copyright (c) 2002-2017 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1896,7 +1896,7 @@ typedef enum { DNSSECValNotRequired = 0, DNSSECValRequired, DNSSECValInProgress, // RFC 4122 defines it to be 16 bytes #define UUID_SIZE 16 -#define AWD_METRICS (USE_AWD && TARGET_OS_EMBEDDED) +#define AWD_METRICS (USE_AWD && TARGET_OS_IOS) #if AWD_METRICS typedef struct @@ -2039,7 +2039,7 @@ struct DNSQuestion_struct domainname *qnameOrig; // Copy of the original question name if it is not fully qualified mDNSQuestionCallback *QuestionCallback; void *QuestionContext; -#if TARGET_OS_EMBEDDED +#if AWD_METRICS uDNSMetrics metrics; // Data used for collecting unicast DNS query metrics. #endif #if USE_DNS64 diff --git a/mDNSResponder/mDNSCore/uDNS.c b/mDNSResponder/mDNSCore/uDNS.c index dc87724c..4d011427 100755 --- a/mDNSResponder/mDNSCore/uDNS.c +++ b/mDNSResponder/mDNSCore/uDNS.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2015 Apple Inc. All rights reserved. + * Copyright (c) 2002-2017 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,10 @@ #endif #include "uDNS.h" +#if AWD_METRICS +#include "Metrics.h" +#endif + #if (defined(_MSC_VER)) // Disable "assignment within conditional expression". // Other compilers understand the convention that if you place the assignment expression within an extra pair @@ -1329,6 +1333,12 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs err = mDNSSendDNSMessage(m, &tcpInfo->request, end, mDNSInterface_Any, mDNSNULL, &tcpInfo->Addr, tcpInfo->Port, sock, AuthInfo, mDNSfalse); if (err) { debugf("ERROR: tcpCallback: mDNSSendDNSMessage - %d", err); err = mStatus_UnknownErr; goto exit; } +#if AWD_METRICS + if (mDNSSameIPPort(tcpInfo->Port, UnicastDNSPort)) + { + MetricsUpdateDNSQuerySize((mDNSu32)(end - (mDNSu8 *)&tcpInfo->request)); + } +#endif // Record time we sent this question if (q) @@ -4758,9 +4768,10 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) else { err = mDNSSendDNSMessage(m, &m->omsg, end, q->qDNSServer->interface, q->LocalSocket, &q->qDNSServer->addr, q->qDNSServer->port, mDNSNULL, mDNSNULL, q->UseBackgroundTrafficClass); -#if TARGET_OS_EMBEDDED +#if AWD_METRICS if (!err) { + MetricsUpdateDNSQuerySize((mDNSu32)(end - (mDNSu8 *)&m->omsg)); if (q->metrics.answered) { q->metrics.querySendCount = 0; diff --git a/mDNSResponder/mDNSMacOSX/Metrics.h b/mDNSResponder/mDNSMacOSX/Metrics.h index dbe6196a..ff419fd8 100644 --- a/mDNSResponder/mDNSMacOSX/Metrics.h +++ b/mDNSResponder/mDNSMacOSX/Metrics.h @@ -1,6 +1,5 @@ -/* -*- Mode: C; tab-width: 4 -*- - * - * Copyright (c) 2016 Apple Inc. All rights reserved. +/* + * Copyright (c) 2016-2017 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,19 +14,22 @@ * limitations under the License. */ -#include "mDNSEmbeddedAPI.h" - #ifndef __Metrics_h #define __Metrics_h +#include "mDNSEmbeddedAPI.h" +#include + #ifdef __cplusplus extern "C" { #endif -#if TARGET_OS_EMBEDDED +#if TARGET_OS_IOS mStatus MetricsInit(void); -void MetricsUpdateUDNSQueryStats(const domainname *inQueryName, mDNSu16 inType, const ResourceRecord *inRR, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCell); -void MetricsUpdateUDNSResolveStats(const domainname *inQueryName, const ResourceRecord *inRR, mDNSBool inForCell); +void MetricsUpdateDNSQueryStats(const domainname *inQueryName, mDNSu16 inType, const ResourceRecord *inRR, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCell); +void MetricsUpdateDNSResolveStats(const domainname *inQueryName, const ResourceRecord *inRR, mDNSBool inForCell); +void MetricsUpdateDNSQuerySize(mDNSu32 inSize); +void MetricsUpdateDNSResponseSize(mDNSu32 inSize); void LogMetrics(void); #endif diff --git a/mDNSResponder/mDNSMacOSX/Metrics.m b/mDNSResponder/mDNSMacOSX/Metrics.m index f8a3ae73..e540f3be 100644 --- a/mDNSResponder/mDNSMacOSX/Metrics.m +++ b/mDNSResponder/mDNSMacOSX/Metrics.m @@ -1,6 +1,5 @@ -/* -*- Mode: C; tab-width: 4 -*- - * - * Copyright (c) 2016 Apple Inc. All rights reserved. +/* + * Copyright (c) 2016-2017 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,18 +16,19 @@ #import "Metrics.h" -#if (TARGET_OS_EMBEDDED) +#if (TARGET_OS_IOS) #import #import +#import #import #import #import #import #import #import +#import #import #import -#import #import "DNSCommon.h" #import "mDNSMacOSX.h" @@ -40,25 +40,45 @@ SOFT_LINK_FRAMEWORK(PrivateFrameworks, WirelessDiagnostics) -SOFT_LINK_CLASS(WirelessDiagnostics, AWDDNSDomainStats) +// AWDServerConnection class + +SOFT_LINK_CLASS(WirelessDiagnostics, AWDServerConnection) + +#define AWDServerConnectionSoft getAWDServerConnectionClass() + +// Classes for query stats + SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderDNSStatistics) +SOFT_LINK_CLASS(WirelessDiagnostics, AWDDNSDomainStats) + +#define AWDMDNSResponderDNSStatisticsSoft getAWDMDNSResponderDNSStatisticsClass() +#define AWDDNSDomainStatsSoft getAWDDNSDomainStatsClass() + +// Classes for resolve stats + SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStats) SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsDNSServer) SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsDomain) SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsHostname) SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsResult) -SOFT_LINK_CLASS(WirelessDiagnostics, AWDServerConnection) -SOFT_LINK_CLASS(WirelessDiagnostics, AWDMetricManager) -#define AWDDNSDomainStatsSoft getAWDDNSDomainStatsClass() -#define AWDMDNSResponderDNSStatisticsSoft getAWDMDNSResponderDNSStatisticsClass() #define AWDMDNSResponderResolveStatsSoft getAWDMDNSResponderResolveStatsClass() -#define AWDMDNSResponderResolveStatsResultSoft getAWDMDNSResponderResolveStatsResultClass() #define AWDMDNSResponderResolveStatsDNSServerSoft getAWDMDNSResponderResolveStatsDNSServerClass() #define AWDMDNSResponderResolveStatsDomainSoft getAWDMDNSResponderResolveStatsDomainClass() #define AWDMDNSResponderResolveStatsHostnameSoft getAWDMDNSResponderResolveStatsHostnameClass() -#define AWDServerConnectionSoft getAWDServerConnectionClass() -#define AWDMetricManagerSoft getAWDMetricManagerClass() +#define AWDMDNSResponderResolveStatsResultSoft getAWDMDNSResponderResolveStatsResultClass() + +// Classes for services stats + +SOFT_LINK_CLASS(WirelessDiagnostics, AWDMetricManager) + +#define AWDMetricManagerSoft getAWDMetricManagerClass() + +// Classes for DNS message size stats + +SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderDNSMessageSizeStats) + +#define AWDMDNSResponderDNSMessageSizeStatsSoft getAWDMDNSResponderDNSMessageSizeStatsClass() //=========================================================================================================================== // Macros @@ -82,31 +102,26 @@ SOFT_LINK_CLASS(WirelessDiagnostics, AWDMetricManager) // Data structures //=========================================================================================================================== -typedef struct -{ - const char * cstr; // Name of domain as a c-string. - const domainname * name; // Name of domain as length-prefixed labels. - int labelCount; // Number of labels in domain name. Used for domain name comparisons. +// Data structures for query stats. -} Domain; +typedef struct QueryStats QueryStats; +typedef struct DNSHistSet DNSHistSet; +typedef mDNSBool (*QueryNameTest_f)(const QueryStats *inStats, const domainname *inQueryName); -// Important: Do not add to this list without getting privacy approval beforehand. See . -// If you get approval and do add a domain to this list, make sure it passes ValidateDNSStatsDomains() below. - -static const Domain kQueryStatsDomains[] = +struct QueryStats { - { ".", (domainname *)"", 0 }, - { "apple.com.", (domainname *)"\x5" "apple" "\x3" "com", 2 }, - { "icloud.com.", (domainname *)"\x6" "icloud" "\x3" "com", 2 }, - { "mzstatic.com.", (domainname *)"\x8" "mzstatic" "\x3" "com", 2 }, - { "google.com.", (domainname *)"\x6" "google" "\x3" "com", 2 }, - { "facebook.com.", (domainname *)"\x8" "facebook" "\x3" "com", 2 }, - { "baidu.com.", (domainname *)"\x5" "baidu" "\x3" "com", 2 }, - { "yahoo.com.", (domainname *)"\x5" "yahoo" "\x3" "com", 2 }, - { "qq.com.", (domainname *)"\x2" "qq" "\x3" "com", 2 }, + QueryStats * next; // Pointer to next domain stats in list. + const char * domainStr; // Domain (see below) as a C string. + uint8_t * domain; // Domain for which these stats are collected. + const char * altDomainStr; // Alt domain string to use in the AWD version of the stats instead of domainStr. + DNSHistSet * nonCellular; // Query stats for queries sent over non-cellular interfaces. + DNSHistSet * cellular; // Query stats for queries sent over cellular interfaces. + QueryNameTest_f test; // Function that tests whether a given query's stats belong based on the query name. + int labelCount; // Number of labels in domain name. Used for domain name comparisons. + mDNSBool terminal; // If true and test passes, then no other QueryStats on the list should be visited. }; -check_compile_time(countof(kQueryStatsDomains) == 9); +check_compile_time(sizeof(QueryStats) <= 64); // DNSHist contains the per domain per network type histogram data that goes in a DNSDomainStats protobuf message. See // MDNSResponder.proto update. @@ -164,30 +179,29 @@ check_compile_time(countof_field(DNSHist, unansweredQueryDurationBins) == (count check_compile_time(countof_field(DNSHist, responseLatencyBins) == (countof(kResponseLatencyMsLimits) + 1)); check_compile_time(countof_field(DNSHist, negResponseLatencyBins) == (countof(kResponseLatencyMsLimits) + 1)); -typedef struct +struct DNSHistSet { DNSHist * histA; // Histogram data for queries for A resource records. DNSHist * histAAAA; // Histogram data for queries for AAAA resource records. +}; -} DNSHistSet; - -typedef struct DNSDomainStats DNSDomainStats; -struct DNSDomainStats +typedef struct { - DNSDomainStats * next; // Pointer to next domain stats in list. - const Domain * domain; // Domain for which these stats are collected. - DNSHistSet * nonCellular; // Query stats for queries sent over non-cellular interfaces. - DNSHistSet * cellular; // Query stats for queries sent over cellular interfaces. -}; + const char * domainStr; + const char * altDomainStr; + QueryNameTest_f test; + mDNSBool terminal; + +} QueryStatsArgs; -check_compile_time(sizeof(struct DNSDomainStats) <= 32); +// Data structures for resolve stats. -static const Domain kResolveStatsDomains[] = +static const char * const kResolveStatsDomains[] = { - { "apple.com.", (domainname *)"\x5" "apple" "\x3" "com", 2 }, - { "icloud.com.", (domainname *)"\x6" "icloud" "\x3" "com", 2 }, - { "mzstatic.com.", (domainname *)"\x8" "mzstatic" "\x3" "com", 2 }, - { "me.com.", (domainname *)"\x2" "me" "\x3" "com", 2 }, + "apple.com.", + "icloud.com.", + "mzstatic.com.", + "me.com." }; check_compile_time(countof(kResolveStatsDomains) == 4); @@ -202,10 +216,14 @@ typedef struct ResolveStatsNegAAAASet ResolveStatsNegAAAASet; struct ResolveStatsDomain { ResolveStatsDomain * next; // Next domain object in list. + const char * domainStr; + uint8_t * domain; // Domain for which these stats are collected. + int labelCount; // Number of labels in domain name. Used for domain name comparisons. ResolveStatsHostname * hostnameList; // List of hostname objects in this domain. - const Domain * domainInfo; // Pointer to domain info. }; +check_compile_time(sizeof(ResolveStatsDomain) <= 40); + struct ResolveStatsHostname { ResolveStatsHostname * next; // Next hostname object in list. @@ -290,27 +308,52 @@ typedef struct } Response; -//=========================================================================================================================== -// Globals -//=========================================================================================================================== +// Data structures for DNS message size stats. -static DNSDomainStats * gDomainStatsList = NULL; -static ResolveStatsDomain * gResolveStatsList = NULL; -static ResolveStatsDNSServer * gResolveStatsServerList = NULL; -static unsigned int gResolveStatsNextServerID = 0; -static int gResolveStatsObjCount = 0; -static AWDServerConnection * gAWDServerConnection = nil; +#define kQuerySizeBinWidth 16 +#define kQuerySizeBinMax 512 +#define kQuerySizeBinCount ((kQuerySizeBinMax / kQuerySizeBinWidth) + 1) + +check_compile_time(kQuerySizeBinWidth > 0); +check_compile_time(kQuerySizeBinCount > 0); +check_compile_time((kQuerySizeBinMax % kQuerySizeBinWidth) == 0); + +#define kResponseSizeBinWidth 16 +#define kResponseSizeBinMax 512 +#define kResponseSizeBinCount ((kResponseSizeBinMax / kResponseSizeBinWidth) + 1) + +check_compile_time(kResponseSizeBinWidth > 0); +check_compile_time(kResponseSizeBinCount > 0); +check_compile_time((kResponseSizeBinMax % kResponseSizeBinWidth) == 0); + +typedef struct +{ + uint16_t querySizeBins[kQuerySizeBinCount]; + uint16_t responseSizeBins[kResponseSizeBinCount]; + +} DNSMessageSizeStats; + +check_compile_time(sizeof(DNSMessageSizeStats) <= 132); //=========================================================================================================================== // Local Prototypes //=========================================================================================================================== -mDNSlocal mStatus DNSDomainStatsCreate(const Domain *inDomain, DNSDomainStats **outStats); -mDNSlocal void DNSDomainStatsFree(DNSDomainStats *inStats); -mDNSlocal void DNSDomainStatsFreeList(DNSDomainStats *inList); -mDNSlocal mStatus DNSDomainStatsUpdate(DNSDomainStats *inStats, int inType, const ResourceRecord *inRR, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs, mDNSBool inForCell); +// Query stats + +mDNSlocal mStatus QueryStatsCreate(const char *inDomainStr, const char *inAltDomainStr, QueryNameTest_f inTest, mDNSBool inTerminal, QueryStats **outStats); +mDNSlocal void QueryStatsFree(QueryStats *inStats); +mDNSlocal void QueryStatsFreeList(QueryStats *inList); +mDNSlocal mStatus QueryStatsUpdate(QueryStats *inStats, int inType, const ResourceRecord *inRR, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs, mDNSBool inForCell); +mDNSlocal const char * QueryStatsGetDomainString(const QueryStats *inStats); +mDNSlocal mDNSBool QueryStatsDomainTest(const QueryStats *inStats, const domainname *inQueryName); +mDNSlocal mDNSBool QueryStatsHostnameTest(const QueryStats *inStats, const domainname *inQueryName); +mDNSlocal mDNSBool QueryStatsContentiCloudTest(const QueryStats *inStats, const domainname *inQueryName); +mDNSlocal mDNSBool QueryStatsCourierPushTest(const QueryStats *inStats, const domainname *inQueryName); -mDNSlocal mStatus ResolveStatsDomainCreate(const Domain *inDomain, ResolveStatsDomain **outDomain); +// Resolve stats + +mDNSlocal mStatus ResolveStatsDomainCreate(const char *inDomainStr, ResolveStatsDomain **outDomain); mDNSlocal void ResolveStatsDomainFree(ResolveStatsDomain *inDomain); mDNSlocal mStatus ResolveStatsDomainUpdate(ResolveStatsDomain *inDomain, const domainname *inHostname, const Response *inResp, const mDNSAddr *inDNSAddr, mDNSBool inForCell); mDNSlocal mStatus ResolveStatsDomainCreateAWDVersion(const ResolveStatsDomain *inDomain, AWDMDNSResponderResolveStatsDomain **outDomain); @@ -334,22 +377,58 @@ mDNSlocal mStatus ResolveStatsNegAAAASetCreate(ResolveStatsNegAAAASet **outSet mDNSlocal void ResolveStatsNegAAAASetFree(ResolveStatsNegAAAASet *inSet); mDNSlocal mStatus ResolveStatsGetServerID(const mDNSAddr *inServerAddr, mDNSBool inForCell, uint8_t *outServerID); -mDNSlocal mStatus CreateDomainStatsList(DNSDomainStats **outList); +// DNS message size stats + +mDNSlocal mStatus DNSMessageSizeStatsCreate(DNSMessageSizeStats **outStats); +mDNSlocal void DNSMessageSizeStatsFree(DNSMessageSizeStats *inStats); + +mDNSlocal mStatus CreateQueryStatsList(QueryStats **outList); mDNSlocal mStatus CreateResolveStatsList(ResolveStatsDomain **outList); mDNSlocal void FreeResolveStatsList(ResolveStatsDomain *inList); mDNSlocal void FreeResolveStatsServerList(ResolveStatsDNSServer *inList); mDNSlocal mStatus SubmitAWDMetric(UInt32 inMetricID); mDNSlocal mStatus SubmitAWDMetricQueryStats(void); mDNSlocal mStatus SubmitAWDMetricResolveStats(void); +mDNSlocal mStatus SubmitAWDMetricDNSMessageSizeStats(void); mDNSlocal mStatus CreateAWDDNSDomainStats(DNSHist *inHist, const char *inDomain, mDNSBool inForCell, AWDDNSDomainStats_RecordType inType, AWDDNSDomainStats **outStats); -mDNSlocal mStatus AddAWDDNSDomainStats(AWDMDNSResponderDNSStatistics *inMetric, DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell); mDNSlocal void LogDNSHistSet(const DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell); mDNSlocal void LogDNSHist(const DNSHist *inHist, const char *inDomain, mDNSBool inForCell, const char *inType); mDNSlocal void LogDNSHistSendCounts(const uint16_t inSendCountBins[kQueryStatsSendCountBinCount]); mDNSlocal void LogDNSHistLatencies(const uint16_t inLatencyBins[kQueryStatsLatencyBinCount]); -#if (METRICS_VALIDATE_DNS_STATS_DOMAINS) -mDNSlocal void ValidateDNSStatsDomains(void); -#endif +mDNSlocal void LogDNSMessageSizeStats(const uint16_t *inBins, size_t inBinCount, unsigned int inBinWidth); + +mDNSlocal size_t CopyHistogramBins(uint32_t *inDstBins, uint16_t *inSrcBins, size_t inBinCount); + +//=========================================================================================================================== +// Globals +//=========================================================================================================================== + +static AWDServerConnection * gAWDServerConnection = nil; +static QueryStats * gQueryStatsList = NULL; +static ResolveStatsDomain * gResolveStatsList = NULL; +static ResolveStatsDNSServer * gResolveStatsServerList = NULL; +static unsigned int gResolveStatsNextServerID = 0; +static int gResolveStatsObjCount = 0; +static DNSMessageSizeStats * gDNSMessageSizeStats = NULL; + +// Important: Do not add to this list without getting privacy approval. See . + +static const QueryStatsArgs kQueryStatsArgs[] = +{ + { ".", NULL, QueryStatsDomainTest, mDNSfalse }, + { "", "alt:*-courier.push.apple.com.", QueryStatsCourierPushTest, mDNSfalse }, + { "apple.com.", NULL, QueryStatsDomainTest, mDNStrue }, + { "gateway.icloud.com.", "alt:gateway.icloud.com", QueryStatsHostnameTest, mDNSfalse }, + { "", "alt:*-content.icloud.com.", QueryStatsContentiCloudTest, mDNSfalse }, + { "icloud.com.", NULL, QueryStatsDomainTest, mDNStrue }, + { "mzstatic.com.", NULL, QueryStatsDomainTest, mDNStrue }, + { "google.com.", NULL, QueryStatsDomainTest, mDNStrue }, + { "baidu.com.", NULL, QueryStatsDomainTest, mDNStrue }, + { "yahoo.com.", NULL, QueryStatsDomainTest, mDNStrue }, + { "qq.com.", NULL, QueryStatsDomainTest, mDNStrue } +}; + +check_compile_time(countof(kQueryStatsArgs) == 11); //=========================================================================================================================== // MetricsInit @@ -357,10 +436,6 @@ mDNSlocal void ValidateDNSStatsDomains(void); mStatus MetricsInit(void) { -#if (METRICS_VALIDATE_DNS_STATS_DOMAINS) - ValidateDNSStatsDomains(); -#endif - @autoreleasepool { gAWDServerConnection = [[AWDServerConnectionSoft alloc] @@ -389,6 +464,13 @@ mStatus MetricsInit(void) SubmitAWDMetric(inMetricID); } forIdentifier: (UInt32)AWDMetricId_MDNSResponder_ServicesStats]; + + [gAWDServerConnection + registerQueriableMetricCallback: ^(UInt32 inMetricID) + { + SubmitAWDMetric(inMetricID); + } + forIdentifier: (UInt32)AWDMetricId_MDNSResponder_DNSMessageSizeStats]; } else { @@ -398,56 +480,33 @@ mStatus MetricsInit(void) if( gAWDServerConnection ) { - CreateDomainStatsList(&gDomainStatsList); + CreateQueryStatsList(&gQueryStatsList); CreateResolveStatsList(&gResolveStatsList); + DNSMessageSizeStatsCreate(&gDNSMessageSizeStats); } return (mStatus_NoError); } //=========================================================================================================================== -// MetricsUpdateUDNSQueryStats +// MetricsUpdateDNSQueryStats //=========================================================================================================================== -mDNSexport void MetricsUpdateUDNSQueryStats(const domainname *inQueryName, mDNSu16 inType, const ResourceRecord *inRR, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCell) +mDNSexport void MetricsUpdateDNSQueryStats(const domainname *inQueryName, mDNSu16 inType, const ResourceRecord *inRR, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCell) { - DNSDomainStats * stats; - int queryLabelCount; - const domainname * queryParentDomain; - mDNSBool isQueryInDomain; - int skipCount; - int skipCountLast = -1; + QueryStats * stats; + mDNSBool match; require_quiet(gAWDServerConnection, exit); require_quiet((inType == kDNSType_A) || (inType == kDNSType_AAAA), exit); - queryLabelCount = CountLabels(inQueryName); - - for (stats = gDomainStatsList; stats; stats = stats->next) + for (stats = gQueryStatsList; stats; stats = stats->next) { - isQueryInDomain = mDNSfalse; - if (strcmp(stats->domain->cstr, ".") == 0) - { - // All queries are in the root domain. - isQueryInDomain = mDNStrue; - } - else - { - skipCount = queryLabelCount - stats->domain->labelCount; - if (skipCount >= 0) - { - if (skipCount != skipCountLast) - { - queryParentDomain = SkipLeadingLabels(inQueryName, skipCount); - skipCountLast = skipCount; - } - isQueryInDomain = SameDomainName(queryParentDomain, stats->domain->name); - } - } - - if (isQueryInDomain) + match = stats->test(stats, inQueryName); + if (match) { - DNSDomainStatsUpdate(stats, inType, inRR, inSendCount, inLatencyMs, inForCell); + QueryStatsUpdate(stats, inType, inRR, inSendCount, inLatencyMs, inForCell); + if (stats->terminal) break; } } @@ -456,12 +515,12 @@ exit: } //=========================================================================================================================== -// MetricsUpdateUDNSResolveStats +// MetricsUpdateDNSResolveStats //=========================================================================================================================== -mDNSexport void MetricsUpdateUDNSResolveStats(const domainname *inQueryName, const ResourceRecord *inRR, mDNSBool inForCell) +mDNSexport void MetricsUpdateDNSResolveStats(const domainname *inQueryName, const ResourceRecord *inRR, mDNSBool inForCell) { - ResolveStatsDomain * domain; + ResolveStatsDomain * domainStats; domainname hostname; size_t hostnameLen; mDNSBool isQueryInDomain; @@ -477,10 +536,10 @@ mDNSexport void MetricsUpdateUDNSResolveStats(const domainname *inQueryName, con queryLabelCount = CountLabels(inQueryName); - for (domain = gResolveStatsList; domain; domain = domain->next) + for (domainStats = gResolveStatsList; domainStats; domainStats = domainStats->next) { isQueryInDomain = mDNSfalse; - skipCount = queryLabelCount - domain->domainInfo->labelCount; + skipCount = queryLabelCount - domainStats->labelCount; if (skipCount >= 0) { if (skipCount != skipCountLast) @@ -488,7 +547,7 @@ mDNSexport void MetricsUpdateUDNSResolveStats(const domainname *inQueryName, con queryParentDomain = SkipLeadingLabels(inQueryName, skipCount); skipCountLast = skipCount; } - isQueryInDomain = SameDomainName(queryParentDomain, domain->domainInfo->name); + isQueryInDomain = SameDomainName(queryParentDomain, (const domainname *)domainStats->domain); } if (!isQueryInDomain) continue; @@ -508,20 +567,52 @@ mDNSexport void MetricsUpdateUDNSResolveStats(const domainname *inQueryName, con response.type = (inRR->rrtype == kDNSType_A) ? kResponseType_IPv4Addr : kResponseType_IPv6Addr; response.data = (inRR->rrtype == kDNSType_A) ? inRR->rdata->u.ipv4.b : inRR->rdata->u.ipv6.b; } - ResolveStatsDomainUpdate(domain, &hostname, &response, &inRR->rDNSServer->addr, inForCell); + ResolveStatsDomainUpdate(domainStats, &hostname, &response, &inRR->rDNSServer->addr, inForCell); } exit: return; } +//=========================================================================================================================== +// MetricsUpdateDNSQuerySize +//=========================================================================================================================== + +mDNSlocal void UpdateMessageSizeCounts(uint16_t *inBins, size_t inBinCount, unsigned int inBinWidth, uint32_t inSize); + +mDNSexport void MetricsUpdateDNSQuerySize(mDNSu32 inSize) +{ + if (!gDNSMessageSizeStats) return; + UpdateMessageSizeCounts(gDNSMessageSizeStats->querySizeBins, kQuerySizeBinCount, kQuerySizeBinWidth, inSize); +} + +mDNSlocal void UpdateMessageSizeCounts(uint16_t *inBins, size_t inBinCount, unsigned int inBinWidth, uint32_t inSize) +{ + size_t i; + + if (inSize == 0) return; + i = (inSize - 1) / inBinWidth; + if (i >= inBinCount) i = inBinCount - 1; + increment_saturate(inBins[i], UINT16_MAX); +} + +//=========================================================================================================================== +// MetricsUpdateDNSResponseSize +//=========================================================================================================================== + +mDNSexport void MetricsUpdateDNSResponseSize(mDNSu32 inSize) +{ + if (!gDNSMessageSizeStats) return; + UpdateMessageSizeCounts(gDNSMessageSizeStats->responseSizeBins, kResponseSizeBinCount, kResponseSizeBinWidth, inSize); +} + //=========================================================================================================================== // LogMetrics //=========================================================================================================================== mDNSexport void LogMetrics(void) { - DNSDomainStats * stats; + QueryStats * stats; const ResolveStatsDomain * domain; const ResolveStatsHostname * hostname; const ResolveStatsDNSServer * server; @@ -538,15 +629,15 @@ mDNSexport void LogMetrics(void) LogMsgNoIdent("gAWDServerConnection %p", gAWDServerConnection); LogMsgNoIdent("---- DNS query stats by domain -----"); - for (stats = gDomainStatsList; stats; stats = stats->next) + for (stats = gQueryStatsList; stats; stats = stats->next) { if (!stats->nonCellular && !stats->cellular) { - LogMsgNoIdent("No data for %s", stats->domain->cstr); + LogMsgNoIdent("No data for %s", QueryStatsGetDomainString(stats)); continue; } - if (stats->nonCellular) LogDNSHistSet(stats->nonCellular, stats->domain->cstr, mDNSfalse); - if (stats->cellular) LogDNSHistSet(stats->cellular, stats->domain->cstr, mDNStrue); + if (stats->nonCellular) LogDNSHistSet(stats->nonCellular, QueryStatsGetDomainString(stats), mDNSfalse); + if (stats->cellular) LogDNSHistSet(stats->cellular, QueryStatsGetDomainString(stats), mDNStrue); } LogMsgNoIdent("---- DNS resolve stats by domain -----"); @@ -565,7 +656,7 @@ mDNSexport void LogMetrics(void) for (hostname = domain->hostnameList; hostname; hostname = hostname->next) { hostnameCount++; } hostnameObjCount += hostnameCount; - LogMsgNoIdent("%##s (%d hostname%s)", domain->domainInfo->name, hostnameCount, (hostnameCount == 1) ? "" : "s"); + LogMsgNoIdent("%s (%d hostname%s)", domain->domainStr, hostnameCount, (hostnameCount == 1) ? "" : "s"); for (hostname = domain->hostnameList; hostname; hostname = hostname->next) { @@ -622,39 +713,96 @@ mDNSexport void LogMetrics(void) } LogMsgNoIdent("Total object count: %3d (server %d hostname %d address %d)", serverObjCount + hostnameObjCount + addrObjCount, serverObjCount, hostnameObjCount, addrObjCount); - + LogMsgNoIdent("---- Num of Services Registered -----"); LogMsgNoIdent("Current_number_of_services_registered :[%d], Max_number_of_services_registered :[%d]", curr_num_regservices, max_num_regservices); + + if (gDNSMessageSizeStats) + { + LogMsgNoIdent("---- DNS query size stats ---"); + LogDNSMessageSizeStats(gDNSMessageSizeStats->querySizeBins, kQuerySizeBinCount, kQuerySizeBinWidth); + + LogMsgNoIdent("-- DNS response size stats --"); + LogDNSMessageSizeStats(gDNSMessageSizeStats->responseSizeBins, kResponseSizeBinCount, kResponseSizeBinWidth); + } + else + { + LogMsgNoIdent("No DNS message size stats."); + } } //=========================================================================================================================== -// DNSDomainStatsCreate +// QueryStatsCreate //=========================================================================================================================== -mDNSlocal mStatus DNSDomainStatsCreate(const Domain *inDomain, DNSDomainStats **outStats) +mDNSlocal mStatus StringToDomainName(const char *inString, uint8_t **outDomainName); + +mDNSlocal mStatus QueryStatsCreate(const char *inDomainStr, const char *inAltDomainStr, QueryNameTest_f inTest, mDNSBool inTerminal, QueryStats **outStats) { - mStatus err; - DNSDomainStats * obj; + mStatus err; + QueryStats * obj; - obj = (DNSDomainStats *)calloc(1, sizeof(*obj)); + obj = (QueryStats *)calloc(1, sizeof(*obj)); require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); - obj->domain = inDomain; + obj->domainStr = inDomainStr; + err = StringToDomainName(obj->domainStr, &obj->domain); + require_noerr_quiet(err, exit); + + obj->altDomainStr = inAltDomainStr; + obj->test = inTest; + obj->labelCount = CountLabels((const domainname *)obj->domain); + obj->terminal = inTerminal; *outStats = obj; + obj = NULL; err = mStatus_NoError; exit: + if (obj) QueryStatsFree(obj); return (err); } +mDNSlocal mStatus StringToDomainName(const char *inString, uint8_t **outDomainName) +{ + mStatus err; + uint8_t * domainPtr = NULL; + size_t domainLen; + const mDNSu8 * ptr; + domainname domain; + + if (strcmp(inString, ".") == 0) + { + domain.c[0] = 0; + } + else + { + ptr = MakeDomainNameFromDNSNameString(&domain, inString); + require_action_quiet(ptr, exit, err = mStatus_BadParamErr); + } + domainLen = DomainNameLength(&domain); + + domainPtr = (uint8_t *)malloc(domainLen); + require_action_quiet(domainPtr, exit, err = mStatus_NoMemoryErr); + + memcpy(domainPtr, domain.c, domainLen); + + *outDomainName = domainPtr; + domainPtr = NULL; + err = mStatus_NoError; + +exit: + return(err); +} + //=========================================================================================================================== -// DNSDomainStatsFree +// QueryStatsFree //=========================================================================================================================== -mDNSlocal void DNSDomainStatsFree(DNSDomainStats *inStats) +mDNSlocal void QueryStatsFree(QueryStats *inStats) { + ForgetMem(&inStats->domain); if (inStats->nonCellular) { ForgetMem(&inStats->nonCellular->histA); @@ -673,25 +821,25 @@ mDNSlocal void DNSDomainStatsFree(DNSDomainStats *inStats) } //=========================================================================================================================== -// DNSDomainStatsFreeList +// QueryStatsFreeList //=========================================================================================================================== -mDNSlocal void DNSDomainStatsFreeList(DNSDomainStats *inList) +mDNSlocal void QueryStatsFreeList(QueryStats *inList) { - DNSDomainStats * stats; + QueryStats * stats; while ((stats = inList) != NULL) { inList = stats->next; - DNSDomainStatsFree(stats); + QueryStatsFree(stats); } } //=========================================================================================================================== -// DNSDomainStatsUpdate +// QueryStatsUpdate //=========================================================================================================================== -mDNSlocal mStatus DNSDomainStatsUpdate(DNSDomainStats *inStats, int inType, const ResourceRecord *inRR, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs, mDNSBool inForCell) +mDNSlocal mStatus QueryStatsUpdate(QueryStats *inStats, int inType, const ResourceRecord *inRR, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs, mDNSBool inForCell) { mStatus err; DNSHistSet * set; @@ -750,11 +898,142 @@ exit: return (err); } +//=========================================================================================================================== +// QueryStatsGetDomainString +//=========================================================================================================================== + +mDNSlocal const char * QueryStatsGetDomainString(const QueryStats *inStats) +{ + return (inStats->altDomainStr ? inStats->altDomainStr : inStats->domainStr); +} + +//=========================================================================================================================== +// QueryStatsDomainTest +//=========================================================================================================================== + +mDNSlocal mDNSBool QueryStatsDomainTest(const QueryStats *inStats, const domainname *inQueryName) +{ + const domainname * parentDomain; + int labelCount; + + if (inStats->domain[0] == 0) return (mDNStrue); + + labelCount = CountLabels(inQueryName); + if (labelCount < inStats->labelCount) return (mDNSfalse); + + parentDomain = SkipLeadingLabels(inQueryName, labelCount - inStats->labelCount); + return (SameDomainName(parentDomain, (const domainname *)inStats->domain)); +} + +//=========================================================================================================================== +// QueryStatsHostnameTest +//=========================================================================================================================== + +mDNSlocal mDNSBool QueryStatsHostnameTest(const QueryStats *inStats, const domainname *inQueryName) +{ + return (SameDomainName(inQueryName, (const domainname *)inStats->domain)); +} + +//=========================================================================================================================== +// QueryStatsContentiCloudTest +//=========================================================================================================================== + +mDNSlocal const uint8_t *LocateLabelSuffix(const uint8_t *inLabel, const uint8_t *inSuffixPtr, size_t inSuffixLen); + +#define kContentSuffixStr "-content" + +mDNSlocal mDNSBool QueryStatsContentiCloudTest(const QueryStats *inStats, const domainname *inQueryName) +{ + const mDNSu8 * const firstLabel = inQueryName->c; + const uint8_t * suffix; + const domainname * parentDomain; + int labelCount; + + (void) inStats; // Unused. + + labelCount = CountLabels(inQueryName); + if (labelCount != 3) return (mDNSfalse); + + suffix = LocateLabelSuffix(firstLabel, (const uint8_t *)kContentSuffixStr, sizeof_string(kContentSuffixStr)); + if (suffix && (suffix > &firstLabel[1])) + { + parentDomain = SkipLeadingLabels(inQueryName, 1); + if (SameDomainName(parentDomain, (const domainname *)"\x6" "icloud" "\x3" "com")) + { + return (mDNStrue); + } + } + + return (mDNSfalse); +} + +mDNSlocal const uint8_t *LocateLabelSuffix(const uint8_t *inLabel, const uint8_t *inSuffixPtr, size_t inSuffixLen) +{ + const uint8_t * ptr; + const uint8_t * lp; + const uint8_t * sp; + size_t len; + const size_t labelLen = inLabel[0]; + + if (labelLen < inSuffixLen) return (NULL); + + ptr = &inLabel[1 + labelLen - inSuffixLen]; + lp = ptr; + sp = inSuffixPtr; + for (len = inSuffixLen; len > 0; --len) + { + if (tolower(*lp) != tolower(*sp)) return (NULL); + ++lp; + ++sp; + } + + return (ptr); +} + +//=========================================================================================================================== +// QueryStatsCourierPushTest +//=========================================================================================================================== + +#define kCourierSuffixStr "-courier" + +mDNSlocal mDNSBool QueryStatsCourierPushTest(const QueryStats *inStats, const domainname *inQueryName) +{ + const mDNSu8 * const firstLabel = inQueryName->c; + const uint8_t * suffix; + const uint8_t * ptr; + const domainname * parentDomain; + int labelCount; + + (void) inStats; // Unused. + + labelCount = CountLabels(inQueryName); + if (labelCount != 4) return (mDNSfalse); + + suffix = LocateLabelSuffix(firstLabel, (const mDNSu8 *)kCourierSuffixStr, sizeof_string(kCourierSuffixStr)); + if (suffix && (suffix > &firstLabel[1])) + { + for (ptr = &firstLabel[1]; ptr < suffix; ++ptr) + { + if (!isdigit(*ptr)) break; + } + if (ptr == suffix) + { + parentDomain = SkipLeadingLabels(inQueryName, 1); + if (SameDomainName(parentDomain, (const domainname *)"\x4" "push" "\x5" "apple" "\x3" "com")) + { + return (mDNStrue); + } + } + } + + return (mDNSfalse); +} + //=========================================================================================================================== // ResolveStatsDomainCreate //=========================================================================================================================== -mDNSlocal mStatus ResolveStatsDomainCreate(const Domain *inDomain, ResolveStatsDomain **outDomain) +mDNSlocal mStatus ResolveStatsDomainCreate(const char *inDomainStr, ResolveStatsDomain **outDomain) { mStatus err; ResolveStatsDomain * obj; @@ -762,12 +1041,18 @@ mDNSlocal mStatus ResolveStatsDomainCreate(const Domain *inDomain, ResolveStatsD obj = (ResolveStatsDomain *)calloc(1, sizeof(*obj)); require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); - obj->domainInfo = inDomain; + obj->domainStr = inDomainStr; + err = StringToDomainName(obj->domainStr, &obj->domain); + require_noerr_quiet(err, exit); + + obj->labelCount = CountLabels((const domainname *)obj->domain); *outDomain = obj; + obj = NULL; err = mStatus_NoError; exit: + if (obj) ResolveStatsDomainFree(obj); return (err); } @@ -779,6 +1064,7 @@ mDNSlocal void ResolveStatsDomainFree(ResolveStatsDomain *inDomain) { ResolveStatsHostname * hostname; + ForgetMem(&inDomain->domain); while ((hostname = inDomain->hostnameList) != NULL) { inDomain->hostnameList = hostname->next; @@ -862,7 +1148,7 @@ mDNSlocal mStatus ResolveStatsDomainCreateAWDVersion(const ResolveStatsDomain *i domain = [[AWDMDNSResponderResolveStatsDomainSoft alloc] init]; require_action_quiet(domain, exit, err = mStatus_UnknownErr); - name = [[NSString alloc] initWithUTF8String:inDomain->domainInfo->cstr]; + name = [[NSString alloc] initWithUTF8String:inDomain->domainStr]; require_action_quiet(name, exit, err = mStatus_UnknownErr); domain.name = name; @@ -1357,7 +1643,7 @@ mDNSlocal mStatus ResolveStatsGetServerID(const mDNSAddr *inServerAddr, mDNSBool require_noerr_quiet(err, exit); gResolveStatsObjCount++; - server->id = gResolveStatsNextServerID++; + server->id = (uint8_t)gResolveStatsNextServerID++; server->next = gResolveStatsServerList; gResolveStatsServerList = server; } @@ -1376,21 +1662,50 @@ exit: } //=========================================================================================================================== -// CreateDomainStatsList +// DNSMessageSizeStatsCreate //=========================================================================================================================== -mDNSlocal mStatus CreateDomainStatsList(DNSDomainStats **outList) +mDNSlocal mStatus DNSMessageSizeStatsCreate(DNSMessageSizeStats **outStats) { - mStatus err; - int i; - DNSDomainStats * stats; - DNSDomainStats ** p; - DNSDomainStats * list = NULL; + mStatus err; + DNSMessageSizeStats * stats; + + stats = (DNSMessageSizeStats *)calloc(1, sizeof(*stats)); + require_action_quiet(stats, exit, err = mStatus_NoMemoryErr); + + *outStats = stats; + err = mStatus_NoError; + +exit: + return (err); +} + +//=========================================================================================================================== +// DNSMessageSizeStatsFree +//=========================================================================================================================== + +mDNSlocal void DNSMessageSizeStatsFree(DNSMessageSizeStats *inStats) +{ + free(inStats); +} + +//=========================================================================================================================== +// CreateQueryStatsList +//=========================================================================================================================== + +mDNSlocal mStatus CreateQueryStatsList(QueryStats **outList) +{ + mStatus err; + QueryStats ** p; + QueryStats * stats; + const QueryStatsArgs * args; + const QueryStatsArgs * const end = kQueryStatsArgs + countof(kQueryStatsArgs); + QueryStats * list = NULL; p = &list; - for (i = 0; i < (int)countof(kQueryStatsDomains); ++i) + for (args = kQueryStatsArgs; args < end; ++args) { - err = DNSDomainStatsCreate(&kQueryStatsDomains[i], &stats); + err = QueryStatsCreate(args->domainStr, args->altDomainStr, args->test, args->terminal, &stats); require_noerr_quiet(err, exit); *p = stats; @@ -1399,9 +1714,10 @@ mDNSlocal mStatus CreateDomainStatsList(DNSDomainStats **outList) *outList = list; list = NULL; + err = mStatus_NoError; exit: - DNSDomainStatsFreeList(list); + QueryStatsFreeList(list); return (err); } @@ -1412,15 +1728,15 @@ exit: mDNSlocal mStatus CreateResolveStatsList(ResolveStatsDomain **outList) { mStatus err; - int i; + unsigned int i; ResolveStatsDomain * domain; ResolveStatsDomain ** p; ResolveStatsDomain * list = NULL; p = &list; - for (i = 0; i < (int)countof(kResolveStatsDomains); ++i) + for (i = 0; i < (unsigned int)countof(kResolveStatsDomains); ++i) { - err = ResolveStatsDomainCreate(&kResolveStatsDomains[i], &domain); + err = ResolveStatsDomainCreate(kResolveStatsDomains[i], &domain); require_noerr_quiet(err, exit); *p = domain; @@ -1429,6 +1745,7 @@ mDNSlocal mStatus CreateResolveStatsList(ResolveStatsDomain **outList) *outList = list; list = NULL; + err = mStatus_NoError; exit: FreeResolveStatsList(list); @@ -1491,7 +1808,11 @@ mDNSlocal mStatus SubmitAWDMetric(UInt32 inMetricID) KQueueUnlock("SubmitAWDSimpleMetricServiceStats"); err = mStatus_NoError; break; - + + case AWDMetricId_MDNSResponder_DNSMessageSizeStats: + err = SubmitAWDMetricDNSMessageSizeStats(); + break; + default: err = mStatus_UnsupportedErr; break; @@ -1505,22 +1826,25 @@ mDNSlocal mStatus SubmitAWDMetric(UInt32 inMetricID) // SubmitAWDMetricQueryStats //=========================================================================================================================== +mDNSlocal mStatus AddQueryStats(AWDMDNSResponderDNSStatistics *inMetric, const QueryStats *inStats); +mDNSlocal mStatus AddDNSHistSet(AWDMDNSResponderDNSStatistics *inMetric, DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell); + mDNSlocal mStatus SubmitAWDMetricQueryStats(void) { mStatus err; BOOL success; - DNSDomainStats * stats; - DNSDomainStats * newDomainStatsList; - DNSDomainStats * domainStatsList = NULL; - AWDMetricContainer * container = nil; - AWDMDNSResponderDNSStatistics * metric = nil; + QueryStats * stats; + QueryStats * statsList; + QueryStats * newStatsList; + AWDMetricContainer * container = nil; + AWDMDNSResponderDNSStatistics * metric = nil; - err = CreateDomainStatsList(&newDomainStatsList); - require_noerr_quiet(err, exit); + newStatsList = NULL; + CreateQueryStatsList(&newStatsList); KQueueLock(); - domainStatsList = gDomainStatsList; - gDomainStatsList = newDomainStatsList; + statsList = gQueryStatsList; + gQueryStatsList = newStatsList; KQueueUnlock("SubmitAWDMetricQueryStats"); container = [gAWDServerConnection newMetricContainerWithIdentifier:AWDMetricId_MDNSResponder_DNSStatistics]; @@ -1529,31 +1853,71 @@ mDNSlocal mStatus SubmitAWDMetricQueryStats(void) metric = [[AWDMDNSResponderDNSStatisticsSoft alloc] init]; require_action_quiet(metric, exit, err = mStatus_UnknownErr); - while ((stats = domainStatsList) != NULL) + while ((stats = statsList) != NULL) { - if (stats->nonCellular) - { - err = AddAWDDNSDomainStats(metric, stats->nonCellular, stats->domain->cstr, mDNSfalse); - require_noerr_quiet(err, exit); - } - if (stats->cellular) - { - err = AddAWDDNSDomainStats(metric, stats->cellular, stats->domain->cstr, mDNStrue); - require_noerr_quiet(err, exit); - } - domainStatsList = stats->next; - DNSDomainStatsFree(stats); + err = AddQueryStats(metric, stats); + require_noerr_quiet(err, exit); + + statsList = stats->next; + QueryStatsFree(stats); } container.metric = metric; success = [gAWDServerConnection submitMetric:container]; - LogMsg("SubmitAWDMetricQueryStats: metric submission %s.", success ? "succeeded" : "failed" ); + LogMsg("SubmitAWDMetricQueryStats: metric submission %s.", success ? "succeeded" : "failed"); err = success ? mStatus_NoError : mStatus_UnknownErr; exit: [metric release]; [container release]; - DNSDomainStatsFreeList(domainStatsList); + QueryStatsFreeList(statsList); + return (err); +} + +mDNSlocal mStatus AddQueryStats(AWDMDNSResponderDNSStatistics *inMetric, const QueryStats *inStats) +{ + mStatus err; + + if (inStats->nonCellular) + { + err = AddDNSHistSet(inMetric, inStats->nonCellular, QueryStatsGetDomainString(inStats), mDNSfalse); + require_noerr_quiet(err, exit); + } + if (inStats->cellular) + { + err = AddDNSHistSet(inMetric, inStats->cellular, QueryStatsGetDomainString(inStats), mDNStrue); + require_noerr_quiet(err, exit); + } + err = mStatus_NoError; + +exit: + return (err); +} + +mDNSlocal mStatus AddDNSHistSet(AWDMDNSResponderDNSStatistics *inMetric, DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell) +{ + mStatus err; + AWDDNSDomainStats * awdStats; + + if (inSet->histA) + { + err = CreateAWDDNSDomainStats(inSet->histA, inDomain, inForCell, AWDDNSDomainStats_RecordType_A, &awdStats); + require_noerr_quiet(err, exit); + + [inMetric addStats:awdStats]; + [awdStats release]; + } + if (inSet->histAAAA) + { + err = CreateAWDDNSDomainStats(inSet->histAAAA, inDomain, inForCell, AWDDNSDomainStats_RecordType_AAAA, &awdStats); + require_noerr_quiet(err, exit); + + [inMetric addStats:awdStats]; + [awdStats release]; + } + err = mStatus_NoError; + +exit: return (err); } @@ -1619,7 +1983,7 @@ mDNSlocal mStatus SubmitAWDMetricResolveStats(void) container.metric = metric; success = [gAWDServerConnection submitMetric:container]; - LogMsg("SubmitAWDMetricResolveStats: metric submission %s.", success ? "succeeded" : "failed" ); + LogMsg("SubmitAWDMetricResolveStats: metric submission %s.", success ? "succeeded" : "failed"); err = success ? mStatus_NoError : mStatus_UnknownErr; exit: @@ -1630,6 +1994,61 @@ exit: return (err); } +//=========================================================================================================================== +// SubmitAWDMetricDNSMessageSizeStats +//=========================================================================================================================== + +mDNSlocal mStatus SubmitAWDMetricDNSMessageSizeStats(void) +{ + mStatus err; + DNSMessageSizeStats * stats; + DNSMessageSizeStats * newStats; + AWDMetricContainer * container; + AWDMDNSResponderDNSMessageSizeStats * metric = nil; + BOOL success; + + newStats = NULL; + DNSMessageSizeStatsCreate(&newStats); + + KQueueLock(); + stats = gDNSMessageSizeStats; + gDNSMessageSizeStats = newStats; + KQueueUnlock("SubmitAWDMetricDNSMessageSizeStats"); + + container = [gAWDServerConnection newMetricContainerWithIdentifier:AWDMetricId_MDNSResponder_DNSMessageSizeStats]; + require_action_quiet(container, exit, err = mStatus_UnknownErr); + + metric = [[AWDMDNSResponderDNSMessageSizeStatsSoft alloc] init]; + require_action_quiet(metric, exit, err = mStatus_UnknownErr); + + if (stats) + { + size_t binCount; + uint32_t bins[Max(kQuerySizeBinCount, kResponseSizeBinCount)]; + + // Set query size counts. + + binCount = CopyHistogramBins(bins, stats->querySizeBins, kQuerySizeBinCount); + [metric setQuerySizeCounts:bins count:(NSUInteger)binCount]; + + // Set response size counts. + + binCount = CopyHistogramBins(bins, stats->responseSizeBins, kResponseSizeBinCount); + [metric setResponseSizeCounts:bins count:(NSUInteger)binCount]; + } + + container.metric = metric; + success = [gAWDServerConnection submitMetric:container]; + LogMsg("SubmitAWDMetricDNSMessageSizeStats: metric submission %s.", success ? "succeeded" : "failed"); + err = success ? mStatus_NoError : mStatus_UnknownErr; + +exit: + [metric release]; + [container release]; + if (stats) DNSMessageSizeStatsFree(stats); + return (err); +} + //=========================================================================================================================== // CreateAWDDNSDomainStats //=========================================================================================================================== @@ -1639,12 +2058,9 @@ mDNSlocal mStatus CreateAWDDNSDomainStats(DNSHist *inHist, const char *inDomain, mStatus err; AWDDNSDomainStats * awdStats = nil; NSString * domain = nil; + size_t binCount; uint32_t sendCountBins[kQueryStatsSendCountBinCount]; uint32_t latencyBins[kQueryStatsLatencyBinCount]; - int i; - unsigned int totalAnswered; - unsigned int totalNegAnswered; - unsigned int totalUnanswered; awdStats = [[AWDDNSDomainStatsSoft alloc] init]; require_action_quiet(awdStats, exit, err = mStatus_UnknownErr); @@ -1656,55 +2072,40 @@ mDNSlocal mStatus CreateAWDDNSDomainStats(DNSHist *inHist, const char *inDomain, awdStats.networkType = inForCell ? AWDDNSDomainStats_NetworkType_Cellular : AWDDNSDomainStats_NetworkType_NonCellular; awdStats.recordType = inType; - totalAnswered = 0; - for (i = 0; i < kQueryStatsSendCountBinCount; ++i) - { - sendCountBins[i] = inHist->answeredQuerySendCountBins[i]; - totalAnswered += inHist->answeredQuerySendCountBins[i]; - } - [awdStats setAnsweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount]; + // Positively answered query send counts - totalNegAnswered = 0; - for (i = 0; i < kQueryStatsSendCountBinCount; ++i) - { - sendCountBins[i] = inHist->negAnsweredQuerySendCountBins[i]; - totalNegAnswered += inHist->negAnsweredQuerySendCountBins[i]; - } - [awdStats setNegAnsweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount]; + binCount = CopyHistogramBins(sendCountBins, inHist->answeredQuerySendCountBins, kQueryStatsSendCountBinCount); + [awdStats setAnsweredQuerySendCounts:sendCountBins count:(NSUInteger)binCount]; - totalUnanswered = 0; - for (i = 0; i < kQueryStatsSendCountBinCount; ++i) - { - sendCountBins[i] = inHist->unansweredQuerySendCountBins[i]; - totalUnanswered += inHist->unansweredQuerySendCountBins[i]; - } - [awdStats setUnansweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount]; + // binCount > 1 means that at least one of the non-zero send count bins had a non-zero count, i.e., at least one query + // was sent out on the wire. In that case, include the associated latency bins as well. - if (totalAnswered > inHist->answeredQuerySendCountBins[0]) + if (binCount > 1) { - for (i = 0; i < kQueryStatsLatencyBinCount; ++i) - { - latencyBins[i] = inHist->responseLatencyBins[i]; - } - [awdStats setResponseLatencyMs:latencyBins count:kQueryStatsLatencyBinCount]; + binCount = CopyHistogramBins(latencyBins, inHist->responseLatencyBins, kQueryStatsLatencyBinCount); + [awdStats setResponseLatencyMs:latencyBins count:(NSUInteger)binCount]; } - if (totalNegAnswered > inHist->negAnsweredQuerySendCountBins[0]) + // Negatively answered query send counts + + binCount = CopyHistogramBins(sendCountBins, inHist->negAnsweredQuerySendCountBins, kQueryStatsSendCountBinCount); + [awdStats setNegAnsweredQuerySendCounts:sendCountBins count:(NSUInteger)binCount]; + + if (binCount > 1) { - for (i = 0; i < kQueryStatsLatencyBinCount; ++i) - { - latencyBins[i] = inHist->negResponseLatencyBins[i]; - } - [awdStats setNegResponseLatencyMs:latencyBins count:kQueryStatsLatencyBinCount]; + binCount = CopyHistogramBins(latencyBins, inHist->negResponseLatencyBins, kQueryStatsLatencyBinCount); + [awdStats setNegResponseLatencyMs:latencyBins count:(NSUInteger)binCount]; } - if (totalUnanswered > 0) + // Unanswered query send counts + + binCount = CopyHistogramBins(sendCountBins, inHist->unansweredQuerySendCountBins, kQueryStatsSendCountBinCount); + [awdStats setUnansweredQuerySendCounts:sendCountBins count:(NSUInteger)binCount]; + + if (binCount > 1) { - for (i = 0; i < kQueryStatsLatencyBinCount; ++i) - { - latencyBins[i] = inHist->unansweredQueryDurationBins[i]; - } - [awdStats setUnansweredQueryDurationMs:latencyBins count:kQueryStatsLatencyBinCount]; + binCount = CopyHistogramBins(latencyBins, inHist->unansweredQueryDurationBins, kQueryStatsLatencyBinCount); + [awdStats setUnansweredQueryDurationMs:latencyBins count:(NSUInteger)binCount]; } *outStats = awdStats; @@ -1717,37 +2118,6 @@ exit: return (err); } -//=========================================================================================================================== -// AddAWDDNSDomainStats -//=========================================================================================================================== - -mDNSlocal mStatus AddAWDDNSDomainStats(AWDMDNSResponderDNSStatistics *inMetric, DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell) -{ - mStatus err; - AWDDNSDomainStats * awdStats; - - if (inSet->histA) - { - err = CreateAWDDNSDomainStats(inSet->histA, inDomain, inForCell, AWDDNSDomainStats_RecordType_A, &awdStats); - require_noerr_quiet(err, exit); - - [inMetric addStats:awdStats]; - [awdStats release]; - } - if (inSet->histAAAA) - { - err = CreateAWDDNSDomainStats(inSet->histAAAA, inDomain, inForCell, AWDDNSDomainStats_RecordType_AAAA, &awdStats); - require_noerr_quiet(err, exit); - - [inMetric addStats:awdStats]; - [awdStats release]; - } - err = mStatus_NoError; - -exit: - return (err); -} - //=========================================================================================================================== // LogDNSHistSet //=========================================================================================================================== @@ -1762,7 +2132,7 @@ mDNSlocal void LogDNSHistSet(const DNSHistSet *inSet, const char *inDomain, mDNS // LogDNSHist //=========================================================================================================================== -#define Percent(N, D) ((N) * 100) / (D), (((N) * 10000) / (D)) % 100 +#define Percent(N, D) (((N) * 100) / (D)), ((((N) * 10000) / (D)) % 100) #define PercentFmt "%3u.%02u" #define LogStat(LABEL, COUNT, ACCUMULATOR, TOTAL) \ LogMsgNoIdent("%s %5u " PercentFmt " " PercentFmt, (LABEL), (COUNT), Percent(COUNT, TOTAL), Percent(ACCUMULATOR, TOTAL)) @@ -1903,63 +2273,72 @@ mDNSlocal void LogDNSHistLatencies(const uint16_t inLatencyBins[kQueryStatsLaten } //=========================================================================================================================== -// ValidateDNSStatsDomains +// LogDNSMessageSizeStats //=========================================================================================================================== -#if (METRICS_VALIDATE_DNS_STATS_DOMAINS) -#warning "Do not include ValidateDNSStatsDomains() in customer release!" -mDNSlocal void ValidateDNSStatsDomains(void) +mDNSlocal void LogDNSMessageSizeStats(const uint16_t *inBins, size_t inBinCount, unsigned int inBinWidth) { - int i; - const Domain * domain; - mDNSu8 * ptr; - domainname domainNameExpected; - int labelCountExpected; - mDNSBool domainNamesEqual; - mDNSBool failed = mDNSfalse; + size_t i; + uint32_t total; - for (i = 0; i < countof(kQueryStatsDomains); ++i) + total = 0; + for (i = 0; i < inBinCount; ++i) { - domain = &kQueryStatsDomains[i]; + total += inBins[i]; + } - if (strcmp(domain->cstr, ".") == 0) - { - domainNameExpected.c[0] = 0; - } - else - { - ptr = MakeDomainNameFromDNSNameString(&domainNameExpected, domain->cstr); - if (!ptr) - { - LogMsg("ValidateDNSStatsDomains: Failed to make domain name for \"%s\".", domain->cstr); - failed = mDNStrue; - goto exit; - } - } + if (total > 0) + { + uint32_t accumulator; + unsigned int lower, upper; + char label[16]; - domainNamesEqual = SameDomainName(domain->name, &domainNameExpected); - labelCountExpected = CountLabels(&domainNameExpected); - if (domainNamesEqual && (domain->labelCount == labelCountExpected)) - { - LogMsg("ValidateDNSStatsDomains: \"%s\" passed.", domain->cstr); - } - else + accumulator = 0; + upper = 0; + for (i = 0; i < inBinCount; ++i) { - if (!domainNamesEqual) + accumulator += inBins[i]; + lower = upper + 1; + if (i < (inBinCount - 1)) { - LogMsg("ValidateDNSStatsDomains: \"%s\" failed: incorrect domain name.", domain->cstr); + upper += inBinWidth; + snprintf(label, sizeof(label), "%3u - %-3u", lower, upper); } - if (domain->labelCount != labelCountExpected) + else { - LogMsg("ValidateDNSStatsDomains: \"%s\" failed: incorrect label count. Actual %d, expected %d.", - domain->cstr, domain->labelCount, labelCountExpected); + snprintf(label, sizeof(label), "%3u+ ", lower); } - failed = mDNStrue; + LogStat(label, inBins[i], accumulator, total); + if (accumulator == total) break; } } + else + { + LogMsgNoIdent("No data."); + } +} -exit: - if (failed) abort(); +//=========================================================================================================================== +// CopyHistogramBins +// +// Note: The return value is the size (in number of elements) of the smallest contiguous sub-array that contains the first +// bin and all bins with non-zero values. +//=========================================================================================================================== + +mDNSlocal size_t CopyHistogramBins(uint32_t *inDstBins, uint16_t *inSrcBins, size_t inBinCount) +{ + size_t i; + size_t minCount; + + if (inBinCount == 0) return (0); + + minCount = 1; + for (i = 0; i < inBinCount; ++i) + { + inDstBins[i] = inSrcBins[i]; + if (inDstBins[i] > 0) minCount = i + 1; + } + + return (minCount); } -#endif -#endif // TARGET_OS_EMBEDDED +#endif // TARGET_OS_IOS diff --git a/mDNSResponder/mDNSMacOSX/daemon.c b/mDNSResponder/mDNSMacOSX/daemon.c index 5dece763..fa192b6a 100644 --- a/mDNSResponder/mDNSMacOSX/daemon.c +++ b/mDNSResponder/mDNSMacOSX/daemon.c @@ -45,7 +45,7 @@ #include "xpc_services.h" // Interface to XPC services #include "helper.h" -#if TARGET_OS_EMBEDDED +#if AWD_METRICS #include "Metrics.h" #endif @@ -558,7 +558,7 @@ mDNSexport void INFOCallback(void) LogMsgNoIdent("%##s", mDNSStorage.FQDN.c); } -#if TARGET_OS_EMBEDDED +#if AWD_METRICS LogMetrics(); #endif LogMsgNoIdent("Timenow 0x%08lX (%d)", (mDNSu32)now, now); @@ -1360,9 +1360,10 @@ mDNSlocal void * KQueueLoop(void *m_param) { if (events_found > kEventsToReadAtOnce || (events_found < 0 && errno != EINTR)) { + const int kevent_errno = errno; // Not sure what to do here, our kqueue has failed us - this isn't ideal - LogMsg("ERROR: KQueueLoop - kevent failed errno %d (%s)", errno, strerror(errno)); - exit(errno); + LogMsg("ERROR: KQueueLoop - kevent failed errno %d (%s)", kevent_errno, strerror(kevent_errno)); + exit(kevent_errno); } numevents += events_found; @@ -1390,7 +1391,7 @@ mDNSlocal size_t LaunchdCheckin(void) { // Ask launchd for our socket int result = launch_activate_socket("Listeners", &launchd_fds, &launchd_fds_count); - if (result != 0) { LogMsg("launch_activate_socket() failed errno %d (%s)", errno, strerror(errno)); } + if (result != 0) { LogMsg("launch_activate_socket() failed error %d (%s)", result, strerror(result)); } return launchd_fds_count; } @@ -1620,14 +1621,26 @@ mDNSexport int main(int argc, char **argv) // Create the kqueue, mutex and thread to support KQSockets KQueueFD = kqueue(); - if (KQueueFD == -1) { LogMsg("kqueue() failed errno %d (%s)", errno, strerror(errno)); status = errno; goto exit; } + if (KQueueFD == -1) + { + const int kqueue_errno = errno; + LogMsg("kqueue() failed errno %d (%s)", kqueue_errno, strerror(kqueue_errno)); + status = kqueue_errno; + goto exit; + } i = pthread_mutex_init(&PlatformStorage.BigMutex, NULL); - if (i == -1) { LogMsg("pthread_mutex_init() failed errno %d (%s)", errno, strerror(errno)); status = errno; goto exit; } + if (i != 0) { LogMsg("pthread_mutex_init() failed error %d (%s)", i, strerror(i)); status = i; goto exit; } int fdpair[2] = {0, 0}; i = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair); - if (i == -1) { LogMsg("socketpair() failed errno %d (%s)", errno, strerror(errno)); status = errno; goto exit; } + if (i == -1) + { + const int socketpair_errno = errno; + LogMsg("socketpair() failed errno %d (%s)", socketpair_errno, strerror(socketpair_errno)); + status = socketpair_errno; + goto exit; + } // Socket pair returned us two identical sockets connected to each other // We will use the first socket to send the second socket. The second socket @@ -1644,7 +1657,7 @@ mDNSexport int main(int argc, char **argv) #endif SandboxProcess(); -#if TARGET_OS_EMBEDDED +#if AWD_METRICS status = MetricsInit(); if (status) { LogMsg("Daemon start: MetricsInit failed (%d)", status); } #endif @@ -1666,7 +1679,7 @@ mDNSexport int main(int argc, char **argv) // Start the kqueue thread pthread_t KQueueThread; i = pthread_create(&KQueueThread, NULL, KQueueLoop, &mDNSStorage); - if (i == -1) { LogMsg("pthread_create() failed errno %d (%s)", errno, strerror(errno)); status = errno; goto exit; } + if (i != 0) { LogMsg("pthread_create() failed error %d (%s)", i, strerror(i)); status = i; goto exit; } if (status == 0) { CFRunLoopRun(); diff --git a/mDNSResponder/mDNSMacOSX/helper.c b/mDNSResponder/mDNSMacOSX/helper.c index f5b4f3b2..dc90b35d 100644 --- a/mDNSResponder/mDNSMacOSX/helper.c +++ b/mDNSResponder/mDNSMacOSX/helper.c @@ -1456,15 +1456,17 @@ void RetrieveTCPInfo(int family, const v6addr_t laddr, uint16_t lport, const v6a sz = sizeof(mib)/sizeof(mib[0]); if (sysctlnametomib("net.inet.tcp.info", mib, &sz) == -1) { - os_log(log_handle, "RetrieveTCPInfo: sysctlnametomib failed %d, %s", errno, strerror(errno)); - *err = errno; + const int sysctl_errno = errno; + os_log(log_handle, "RetrieveTCPInfo: sysctlnametomib failed %d, %s", sysctl_errno, strerror(sysctl_errno)); + *err = sysctl_errno; } miblen = (unsigned int)sz; len = sizeof(struct tcp_info); if (sysctl(mib, miblen, &ti, &len, &itpl, sizeof(struct info_tuple)) == -1) { - os_log(log_handle, "RetrieveTCPInfo: sysctl failed %d, %s", errno, strerror(errno)); - *err = errno; + const int sysctl_errno = errno; + os_log(log_handle, "RetrieveTCPInfo: sysctl failed %d, %s", sysctl_errno, strerror(sysctl_errno)); + *err = sysctl_errno; } *seq = ti.tcpi_snd_nxt - 1; @@ -1745,8 +1747,9 @@ static int startRacoon(void) } else if (result < 0) { - os_log_debug(log_handle, "select returned %d errno %d %s", result, errno, strerror(errno)); - if (errno != EINTR) break; + const int select_errno = errno; + os_log_debug(log_handle, "select returned %d errno %d %s", result, select_errno, strerror(select_errno)); + if (select_errno != EINTR) break; } } @@ -1827,7 +1830,7 @@ static int setupTunnelRoute(const v6addr_t local, const v6addr_t remote) /* send message, ignore error when route already exists */ if (0 > write(s, &msg, msg.hdr.rtm_msglen)) { - int errno_ = errno; + const int errno_ = errno; os_log_info(log_handle,"write to routing socket failed: %s", strerror(errno_)); if (EEXIST != errno_) @@ -1872,7 +1875,7 @@ static int teardownTunnelRoute(const v6addr_t remote) memcpy(&msg.dst.sin6_addr, remote, sizeof(msg.dst.sin6_addr)); if (0 > write(s, &msg, msg.hdr.rtm_msglen)) { - int errno_ = errno; + const int errno_ = errno; os_log_debug(log_handle,"write to routing socket failed: %s", strerror(errno_)); diff --git a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c index ced72a69..3bb4ec69 100644 --- a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c +++ b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c @@ -661,6 +661,7 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms struct sockaddr_storage to; int s = -1, err; mStatus result = mStatus_NoError; + int sendto_errno; if (InterfaceID) { @@ -736,9 +737,10 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms err = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &info->scope_id, sizeof(info->scope_id)); if (err < 0) { + const int setsockopt_errno = errno; char name[IFNAMSIZ]; if (if_indextoname(info->scope_id, name) != NULL) - LogMsg("setsockopt - IPV6_MULTICAST_IF error %d errno %d (%s)", err, errno, strerror(errno)); + LogMsg("setsockopt - IPV6_MULTICAST_IF error %d errno %d (%s)", err, setsockopt_errno, strerror(setsockopt_errno)); else LogInfo("setsockopt - IPV6_MUTLICAST_IF scopeid %d, not a valid interface", info->scope_id); } @@ -779,6 +781,7 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms setTrafficClass(s, useBackgroundTrafficClass); err = sendto(s, msg, (UInt8*)end - (UInt8*)msg, 0, (struct sockaddr *)&to, to.ss_len); + sendto_errno = (err < 0) ? errno : 0; // set traffic class back to default value if (useBackgroundTrafficClass) @@ -788,30 +791,30 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms { static int MessageCount = 0; LogInfo("mDNSPlatformSendUDP -> sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu", - s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow)); + s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, sendto_errno, strerror(sendto_errno), (mDNSu32)(m->timenow)); if (!mDNSAddressIsAllDNSLinkGroup(dst)) { - if (errno == EHOSTUNREACH) return(mStatus_HostUnreachErr); - if (errno == EHOSTDOWN || errno == ENETDOWN || errno == ENETUNREACH) return(mStatus_TransientErr); + if (sendto_errno == EHOSTUNREACH) return(mStatus_HostUnreachErr); + if (sendto_errno == EHOSTDOWN || sendto_errno == ENETDOWN || sendto_errno == ENETUNREACH) return(mStatus_TransientErr); } // Don't report EHOSTUNREACH in the first three minutes after boot // This is because mDNSResponder intentionally starts up early in the boot process (See ) // but this means that sometimes it starts before configd has finished setting up the multicast routing entries. - if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr); + if (sendto_errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr); // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change - if (errno == EADDRNOTAVAIL && m->NetworkChanged) return(mStatus_TransientErr); - if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN) + if (sendto_errno == EADDRNOTAVAIL && m->NetworkChanged) return(mStatus_TransientErr); + if (sendto_errno == EHOSTUNREACH || sendto_errno == EADDRNOTAVAIL || sendto_errno == ENETDOWN) LogInfo("mDNSPlatformSendUDP sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu", - s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow)); + s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, sendto_errno, strerror(sendto_errno), (mDNSu32)(m->timenow)); else { MessageCount++; if (MessageCount < 50) // Cap and ensure NO spamming of LogMsgs LogMsg("mDNSPlatformSendUDP: sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu MessageCount is %d", - s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow), MessageCount); + s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, sendto_errno, strerror(sendto_errno), (mDNSu32)(m->timenow), MessageCount); else // If logging is enabled, remove the cap and log aggressively LogInfo("mDNSPlatformSendUDP: sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu MessageCount is %d", - s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow), MessageCount); + s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, sendto_errno, strerror(sendto_errno), (mDNSu32)(m->timenow), MessageCount); } result = mStatus_UnknownErr; @@ -1071,7 +1074,7 @@ mDNSexport void myKQSocketCallBack(int s1, short filter, void *context, mDNSBool // Find out about other socket parameter that can help understand why select() says the socket is ready for read // All of this is racy, as data may have arrived after the call to select() static unsigned int numLogMessages = 0; - int save_errno = errno; + const int save_errno = errno; int so_error = -1; int so_nread = -1; int fionread = -1; @@ -1912,6 +1915,7 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa mStatus err = mStatus_NoError; char *errstr = mDNSNULL; const int mtu = 0; + int saved_errno; cp->closeFlag = mDNSNULL; @@ -2044,12 +2048,13 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa return(mStatus_NoError); fail: + saved_errno = errno; // For "bind" failures, only write log messages for our shared mDNS port, or for binding to zero if (strcmp(errstr, "bind") || mDNSSameIPPort(port, MulticastDNSPort) || mDNSIPPortIsZero(port)) - LogMsg("%s skt %d port %d error %d errno %d (%s)", errstr, skt, mDNSVal16(port), err, errno, strerror(errno)); + LogMsg("%s skt %d port %d error %d errno %d (%s)", errstr, skt, mDNSVal16(port), err, saved_errno, strerror(saved_errno)); // If we got a "bind" failure of EADDRINUSE, inform the caller as it might need to try another random port - if (!strcmp(errstr, "bind") && errno == EADDRINUSE) + if (!strcmp(errstr, "bind") && saved_errno == EADDRINUSE) { err = EADDRINUSE; if (mDNSSameIPPort(port, MulticastDNSPort)) @@ -2325,8 +2330,9 @@ cp += len; \ sock = socket(PF_ROUTE, SOCK_RAW, 0); if (sock < 0) { - LogMsg("getMACAddress: Can not open the socket - %s", strerror(errno)); - return errno; + const int socket_errno = errno; + LogMsg("getMACAddress: Can not open the socket - %s", strerror(socket_errno)); + return socket_errno; } rtm->rtm_addrs |= RTA_DST | RTA_GATEWAY; @@ -2358,9 +2364,10 @@ cp += len; \ if (write(sock, (char *)&m_rtmsg, rlen) < 0) { - LogMsg("getMACAddress: writing to routing socket: %s", strerror(errno)); + const int write_errno = errno; + LogMsg("getMACAddress: writing to routing socket: %s", strerror(write_errno)); close(sock); - return errno; + return write_errno; } do @@ -3235,7 +3242,11 @@ mDNSlocal mDNSBool InterfaceSupportsKeepAlive(NetworkInterfaceInfo *const intf) mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i) { // We only use Sleep Proxy Service on multicast-capable interfaces, except loopback and D2D. - if (!SPSInterface(i)) return(mDNSfalse); + if (!MulticastInterface(i) || (i->ifa_flags & IFF_LOOPBACK) || i->D2DInterface) + { + LogSPS("NetWakeInterface: returning false for %s", i->ifinfo.ifname); + return(mDNSfalse); + } // If the interface supports TCPKeepalive, it is capable of waking up for a magic packet // This check is needed since the SIOCGIFWAKEFLAGS ioctl returns wrong values for WOMP capability @@ -3253,15 +3264,16 @@ mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i) strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name)); if (ioctl(s, SIOCGIFWAKEFLAGS, &ifr) < 0) { + const int ioctl_errno = errno; // For some strange reason, in /usr/include/sys/errno.h, EOPNOTSUPP is defined to be // 102 when compiling kernel code, and 45 when compiling user-level code. Since this // error code is being returned from the kernel, we need to use the kernel version. #define KERNEL_EOPNOTSUPP 102 - if (errno != KERNEL_EOPNOTSUPP) // "Operation not supported on socket", the expected result on Leopard and earlier - LogMsg("NetWakeInterface SIOCGIFWAKEFLAGS %s errno %d (%s)", i->ifinfo.ifname, errno, strerror(errno)); + if (ioctl_errno != KERNEL_EOPNOTSUPP) // "Operation not supported on socket", the expected result on Leopard and earlier + LogMsg("NetWakeInterface SIOCGIFWAKEFLAGS %s errno %d (%s)", i->ifinfo.ifname, ioctl_errno, strerror(ioctl_errno)); // If on Leopard or earlier, we get EOPNOTSUPP, so in that case // we enable WOL if this interface is not AirPort and "Wake for Network access" is turned on. - ifr.ifr_wake_flags = (errno == KERNEL_EOPNOTSUPP && !(i)->BSSID.l[0] && i->m->SystemWakeOnLANEnabled) ? IF_WAKE_ON_MAGIC_PACKET : 0; + ifr.ifr_wake_flags = (ioctl_errno == KERNEL_EOPNOTSUPP && !(i)->BSSID.l[0] && i->m->SystemWakeOnLANEnabled) ? IF_WAKE_ON_MAGIC_PACKET : 0; } close(s); diff --git a/mDNSResponder/mDNSShared/dns_sd.h b/mDNSResponder/mDNSShared/dns_sd.h index 41a2bc39..0b47c394 100644 --- a/mDNSResponder/mDNSShared/dns_sd.h +++ b/mDNSResponder/mDNSShared/dns_sd.h @@ -66,7 +66,7 @@ */ #ifndef _DNS_SD_H -#define _DNS_SD_H 8782003 +#define _DNS_SD_H 8783004 #ifdef __cplusplus extern "C" { -- cgit v1.2.3