1 | /* -*- Mode: C; tab-width: 4 -*- |
---|
2 | * |
---|
3 | * Copyright (c) 2016 Apple Inc. All rights reserved. |
---|
4 | * |
---|
5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
---|
6 | * you may not use this file except in compliance with the License. |
---|
7 | * You may obtain a copy of the License at |
---|
8 | * |
---|
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
---|
10 | * |
---|
11 | * Unless required by applicable law or agreed to in writing, software |
---|
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
---|
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
---|
14 | * See the License for the specific language governing permissions and |
---|
15 | * limitations under the License. |
---|
16 | */ |
---|
17 | |
---|
18 | #import "Metrics.h" |
---|
19 | |
---|
20 | #if (TARGET_OS_EMBEDDED) |
---|
21 | #import <CoreUtils/SoftLinking.h> |
---|
22 | #import <WirelessDiagnostics/AWDDNSDomainStats.h> |
---|
23 | #import <WirelessDiagnostics/AWDMDNSResponderDNSStatistics.h> |
---|
24 | #import <WirelessDiagnostics/AWDMDNSResponderResolveStats.h> |
---|
25 | #import <WirelessDiagnostics/AWDMDNSResponderResolveStatsDNSServer.h> |
---|
26 | #import <WirelessDiagnostics/AWDMDNSResponderResolveStatsDomain.h> |
---|
27 | #import <WirelessDiagnostics/AWDMDNSResponderResolveStatsHostname.h> |
---|
28 | #import <WirelessDiagnostics/AWDMDNSResponderResolveStatsResult.h> |
---|
29 | #import <WirelessDiagnostics/AWDMetricIds_MDNSResponder.h> |
---|
30 | #import <WirelessDiagnostics/WirelessDiagnostics.h> |
---|
31 | #import <WirelessDiagnostics/AWDMDNSResponderServicesStats.h> |
---|
32 | |
---|
33 | #import "DNSCommon.h" |
---|
34 | #import "mDNSMacOSX.h" |
---|
35 | #import "DebugServices.h" |
---|
36 | |
---|
37 | //=========================================================================================================================== |
---|
38 | // External Frameworks |
---|
39 | //=========================================================================================================================== |
---|
40 | |
---|
41 | SOFT_LINK_FRAMEWORK(PrivateFrameworks, WirelessDiagnostics) |
---|
42 | |
---|
43 | SOFT_LINK_CLASS(WirelessDiagnostics, AWDDNSDomainStats) |
---|
44 | SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderDNSStatistics) |
---|
45 | SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStats) |
---|
46 | SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsDNSServer) |
---|
47 | SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsDomain) |
---|
48 | SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsHostname) |
---|
49 | SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsResult) |
---|
50 | SOFT_LINK_CLASS(WirelessDiagnostics, AWDServerConnection) |
---|
51 | SOFT_LINK_CLASS(WirelessDiagnostics, AWDMetricManager) |
---|
52 | |
---|
53 | #define AWDDNSDomainStatsSoft getAWDDNSDomainStatsClass() |
---|
54 | #define AWDMDNSResponderDNSStatisticsSoft getAWDMDNSResponderDNSStatisticsClass() |
---|
55 | #define AWDMDNSResponderResolveStatsSoft getAWDMDNSResponderResolveStatsClass() |
---|
56 | #define AWDMDNSResponderResolveStatsResultSoft getAWDMDNSResponderResolveStatsResultClass() |
---|
57 | #define AWDMDNSResponderResolveStatsDNSServerSoft getAWDMDNSResponderResolveStatsDNSServerClass() |
---|
58 | #define AWDMDNSResponderResolveStatsDomainSoft getAWDMDNSResponderResolveStatsDomainClass() |
---|
59 | #define AWDMDNSResponderResolveStatsHostnameSoft getAWDMDNSResponderResolveStatsHostnameClass() |
---|
60 | #define AWDServerConnectionSoft getAWDServerConnectionClass() |
---|
61 | #define AWDMetricManagerSoft getAWDMetricManagerClass() |
---|
62 | |
---|
63 | //=========================================================================================================================== |
---|
64 | // Macros |
---|
65 | //=========================================================================================================================== |
---|
66 | |
---|
67 | #define countof(X) (sizeof(X) / sizeof(X[0])) |
---|
68 | #define countof_field(TYPE, FIELD) countof(((TYPE *)0)->FIELD) |
---|
69 | #define increment_saturate(VAR, MAX) do {if ((VAR) < (MAX)) {++(VAR);}} while (0) |
---|
70 | #define ForgetMem(X) do {if(*(X)) {free(*(X)); *(X) = NULL;}} while(0) |
---|
71 | |
---|
72 | //=========================================================================================================================== |
---|
73 | // Constants |
---|
74 | //=========================================================================================================================== |
---|
75 | |
---|
76 | #define kQueryStatsMaxQuerySendCount 10 |
---|
77 | #define kQueryStatsSendCountBinCount (kQueryStatsMaxQuerySendCount + 1) |
---|
78 | #define kQueryStatsLatencyBinCount 55 |
---|
79 | #define kResolveStatsMaxObjCount 2000 |
---|
80 | |
---|
81 | //=========================================================================================================================== |
---|
82 | // Data structures |
---|
83 | //=========================================================================================================================== |
---|
84 | |
---|
85 | typedef struct |
---|
86 | { |
---|
87 | const char * cstr; // Name of domain as a c-string. |
---|
88 | const domainname * name; // Name of domain as length-prefixed labels. |
---|
89 | int labelCount; // Number of labels in domain name. Used for domain name comparisons. |
---|
90 | |
---|
91 | } Domain; |
---|
92 | |
---|
93 | // Important: Do not add to this list without getting privacy approval beforehand. See <rdar://problem/24155761&26397203>. |
---|
94 | // If you get approval and do add a domain to this list, make sure it passes ValidateDNSStatsDomains() below. |
---|
95 | |
---|
96 | static const Domain kQueryStatsDomains[] = |
---|
97 | { |
---|
98 | { ".", (domainname *)"", 0 }, |
---|
99 | { "apple.com.", (domainname *)"\x5" "apple" "\x3" "com", 2 }, |
---|
100 | { "icloud.com.", (domainname *)"\x6" "icloud" "\x3" "com", 2 }, |
---|
101 | { "mzstatic.com.", (domainname *)"\x8" "mzstatic" "\x3" "com", 2 }, |
---|
102 | { "me.com.", (domainname *)"\x2" "me" "\x3" "com", 2 }, |
---|
103 | { "google.com.", (domainname *)"\x6" "google" "\x3" "com", 2 }, |
---|
104 | { "youtube.com.", (domainname *)"\x7" "youtube" "\x3" "com", 2 }, |
---|
105 | { "facebook.com.", (domainname *)"\x8" "facebook" "\x3" "com", 2 }, |
---|
106 | { "baidu.com.", (domainname *)"\x5" "baidu" "\x3" "com", 2 }, |
---|
107 | { "yahoo.com.", (domainname *)"\x5" "yahoo" "\x3" "com", 2 }, |
---|
108 | { "qq.com.", (domainname *)"\x2" "qq" "\x3" "com", 2 }, |
---|
109 | }; |
---|
110 | |
---|
111 | check_compile_time(countof(kQueryStatsDomains) == 11); |
---|
112 | |
---|
113 | // DNSHist contains the per domain per network type histogram data that goes in a DNSDomainStats protobuf message. See |
---|
114 | // <rdar://problem/23980546> MDNSResponder.proto update. |
---|
115 | // |
---|
116 | // answeredQuerySendCountBins |
---|
117 | // |
---|
118 | // An array of 11 histogram bins. The value at index i, for 0 <= i <= 9, is the number of times that an answered DNS query |
---|
119 | // was sent i times. The value at index 10 is the number of times that an answered query was sent 10+ times. |
---|
120 | // |
---|
121 | // unansweredQuerySendCountBins |
---|
122 | // |
---|
123 | // An array of 11 histogram bins. The value at index i, for 0 <= i <= 9, is the number of times that an unanswered DNS query |
---|
124 | // was sent i times. The value at index 10 is the number of times that an unanswered query was sent 10+ times. |
---|
125 | // |
---|
126 | // responseLatencyBins |
---|
127 | // |
---|
128 | // An array of 55 histogram bins. Each array value is the number of DNS queries that were answered in a paricular time |
---|
129 | // interval. The 55 consecutive non-overlapping time intervals have the following non-inclusive upper bounds (all values are |
---|
130 | // in milliseconds): 1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, |
---|
131 | // 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000, 1500, 2000, 2500, 3000, 3500, 4000, |
---|
132 | // 4500, 5000, 6000, 7000, 8000, 9000, 10000, â. |
---|
133 | |
---|
134 | typedef struct |
---|
135 | { |
---|
136 | uint16_t unansweredQuerySendCountBins[kQueryStatsSendCountBinCount]; |
---|
137 | uint16_t unansweredQueryDurationBins[kQueryStatsLatencyBinCount]; |
---|
138 | uint16_t answeredQuerySendCountBins[kQueryStatsSendCountBinCount]; |
---|
139 | uint16_t responseLatencyBins[kQueryStatsLatencyBinCount]; |
---|
140 | uint16_t negAnsweredQuerySendCountBins[kQueryStatsSendCountBinCount]; |
---|
141 | uint16_t negResponseLatencyBins[kQueryStatsLatencyBinCount]; |
---|
142 | |
---|
143 | } DNSHist; |
---|
144 | |
---|
145 | check_compile_time(sizeof(DNSHist) <= 512); |
---|
146 | check_compile_time(countof_field(DNSHist, unansweredQuerySendCountBins) == (kQueryStatsMaxQuerySendCount + 1)); |
---|
147 | check_compile_time(countof_field(DNSHist, answeredQuerySendCountBins) == (kQueryStatsMaxQuerySendCount + 1)); |
---|
148 | check_compile_time(countof_field(DNSHist, negAnsweredQuerySendCountBins) == (kQueryStatsMaxQuerySendCount + 1)); |
---|
149 | |
---|
150 | // Important: Do not modify kResponseLatencyMsLimits because the code used to generate AWD reports expects the response |
---|
151 | // latency histogram bins to observe these time interval upper bounds. |
---|
152 | |
---|
153 | static const mDNSu32 kResponseLatencyMsLimits[] = |
---|
154 | { |
---|
155 | 1, 2, 3, 4, 5, |
---|
156 | 10, 20, 30, 40, 50, 60, 70, 80, 90, |
---|
157 | 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, |
---|
158 | 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, |
---|
159 | 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, |
---|
160 | 5000, 6000, 7000, 8000, 9000, |
---|
161 | 10000 |
---|
162 | }; |
---|
163 | |
---|
164 | check_compile_time(countof(kResponseLatencyMsLimits) == 54); |
---|
165 | check_compile_time(countof_field(DNSHist, unansweredQueryDurationBins) == (countof(kResponseLatencyMsLimits) + 1)); |
---|
166 | check_compile_time(countof_field(DNSHist, responseLatencyBins) == (countof(kResponseLatencyMsLimits) + 1)); |
---|
167 | check_compile_time(countof_field(DNSHist, negResponseLatencyBins) == (countof(kResponseLatencyMsLimits) + 1)); |
---|
168 | |
---|
169 | typedef struct |
---|
170 | { |
---|
171 | DNSHist * histAny; // Histogram data for queries of any resource record type. |
---|
172 | DNSHist * histA; // Histogram data for queries for A resource records. |
---|
173 | DNSHist * histAAAA; // Histogram data for queries for AAAA resource records. |
---|
174 | |
---|
175 | } DNSHistSet; |
---|
176 | |
---|
177 | typedef struct DNSDomainStats DNSDomainStats; |
---|
178 | struct DNSDomainStats |
---|
179 | { |
---|
180 | DNSDomainStats * next; // Pointer to next domain stats in list. |
---|
181 | const Domain * domain; // Domain for which these stats are collected. |
---|
182 | DNSHistSet * nonCellular; // Query stats for queries sent over non-cellular interfaces. |
---|
183 | DNSHistSet * cellular; // Query stats for queries sent over cellular interfaces. |
---|
184 | }; |
---|
185 | |
---|
186 | check_compile_time(sizeof(struct DNSDomainStats) <= 32); |
---|
187 | |
---|
188 | static const Domain kResolveStatsDomains[] = |
---|
189 | { |
---|
190 | { "apple.com.", (domainname *)"\x5" "apple" "\x3" "com", 2 }, |
---|
191 | { "icloud.com.", (domainname *)"\x6" "icloud" "\x3" "com", 2 }, |
---|
192 | { "mzstatic.com.", (domainname *)"\x8" "mzstatic" "\x3" "com", 2 }, |
---|
193 | { "me.com.", (domainname *)"\x2" "me" "\x3" "com", 2 }, |
---|
194 | }; |
---|
195 | |
---|
196 | check_compile_time(countof(kResolveStatsDomains) == 4); |
---|
197 | |
---|
198 | typedef struct ResolveStatsDomain ResolveStatsDomain; |
---|
199 | typedef struct ResolveStatsHostname ResolveStatsHostname; |
---|
200 | typedef struct ResolveStatsDNSServer ResolveStatsDNSServer; |
---|
201 | typedef struct ResolveStatsIPv4AddrSet ResolveStatsIPv4AddrSet; |
---|
202 | typedef struct ResolveStatsIPv6Addr ResolveStatsIPv6Addr; |
---|
203 | typedef struct ResolveStatsNegAAAASet ResolveStatsNegAAAASet; |
---|
204 | |
---|
205 | struct ResolveStatsDomain |
---|
206 | { |
---|
207 | ResolveStatsDomain * next; // Next domain object in list. |
---|
208 | ResolveStatsHostname * hostnameList; // List of hostname objects in this domain. |
---|
209 | const Domain * domainInfo; // Pointer to domain info. |
---|
210 | }; |
---|
211 | |
---|
212 | struct ResolveStatsHostname |
---|
213 | { |
---|
214 | ResolveStatsHostname * next; // Next hostname object in list. |
---|
215 | ResolveStatsIPv4AddrSet * addrV4List; // List of IPv4 addresses to which this hostname resolved. |
---|
216 | ResolveStatsIPv6Addr * addrV6List; // List of IPv6 addresses to which this hostname resolved. |
---|
217 | ResolveStatsNegAAAASet * negV6List; // List of negative AAAA response objects. |
---|
218 | uint8_t name[1]; // Variable length storage for hostname as length-prefixed labels. |
---|
219 | }; |
---|
220 | |
---|
221 | check_compile_time(sizeof(ResolveStatsHostname) <= 64); |
---|
222 | |
---|
223 | struct ResolveStatsDNSServer |
---|
224 | { |
---|
225 | ResolveStatsDNSServer * next; // Next DNS server object in list. |
---|
226 | uint8_t id; // 8-bit ID assigned to this DNS server used by IP address objects. |
---|
227 | mDNSBool isForCell; // True if this DNS server belongs to a cellular interface. |
---|
228 | mDNSBool isAddrV6; // True if this DNS server has an IPv6 address instead of IPv4. |
---|
229 | uint8_t addrBytes[1]; // Variable length storage for DNS server's IP address. |
---|
230 | }; |
---|
231 | |
---|
232 | check_compile_time(sizeof(ResolveStatsDNSServer) <= 32); |
---|
233 | |
---|
234 | typedef struct |
---|
235 | { |
---|
236 | uint16_t count; // Number of times this IPv4 address was provided as a resolution result. |
---|
237 | uint8_t serverID; // 8-bit ID of the DNS server from which this IPv4 address came. |
---|
238 | uint8_t isNegative; |
---|
239 | uint8_t addrBytes[4]; // IPv4 address bytes. |
---|
240 | |
---|
241 | } IPv4AddrCounter; |
---|
242 | |
---|
243 | check_compile_time(sizeof(IPv4AddrCounter) <= 8); |
---|
244 | |
---|
245 | struct ResolveStatsIPv4AddrSet |
---|
246 | { |
---|
247 | ResolveStatsIPv4AddrSet * next; // Next set of IPv4 address counters in list. |
---|
248 | IPv4AddrCounter counters[3]; // Array of IPv4 address counters. |
---|
249 | }; |
---|
250 | |
---|
251 | check_compile_time(sizeof(ResolveStatsIPv4AddrSet) <= 32); |
---|
252 | |
---|
253 | struct ResolveStatsIPv6Addr |
---|
254 | { |
---|
255 | ResolveStatsIPv6Addr * next; // Next IPv6 address object in list. |
---|
256 | uint16_t count; // Number of times this IPv6 address was provided as a resolution result. |
---|
257 | uint8_t serverID; // 8-bit ID of the DNS server from which this IPv6 address came. |
---|
258 | uint8_t addrBytes[16]; // IPv6 address bytes. |
---|
259 | }; |
---|
260 | |
---|
261 | check_compile_time(sizeof(ResolveStatsIPv6Addr) <= 32); |
---|
262 | |
---|
263 | typedef struct |
---|
264 | { |
---|
265 | uint16_t count; // Number of times that a negative response was returned by a DNS server. |
---|
266 | uint8_t serverID; // 8-bit ID of the DNS server that sent the negative responses. |
---|
267 | |
---|
268 | } NegAAAACounter; |
---|
269 | |
---|
270 | check_compile_time(sizeof(NegAAAACounter) <= 4); |
---|
271 | |
---|
272 | struct ResolveStatsNegAAAASet |
---|
273 | { |
---|
274 | ResolveStatsNegAAAASet * next; // Next set of negative AAAA response counters in list. |
---|
275 | NegAAAACounter counters[6]; // Array of negative AAAA response counters. |
---|
276 | }; |
---|
277 | |
---|
278 | check_compile_time(sizeof(ResolveStatsNegAAAASet) <= 32); |
---|
279 | |
---|
280 | typedef enum |
---|
281 | { |
---|
282 | kResponseType_IPv4Addr = 1, |
---|
283 | kResponseType_IPv6Addr = 2, |
---|
284 | kResponseType_NegA = 3, |
---|
285 | kResponseType_NegAAAA = 4 |
---|
286 | |
---|
287 | } ResponseType; |
---|
288 | |
---|
289 | typedef struct |
---|
290 | { |
---|
291 | ResponseType type; |
---|
292 | const uint8_t * data; |
---|
293 | |
---|
294 | } Response; |
---|
295 | |
---|
296 | //=========================================================================================================================== |
---|
297 | // Globals |
---|
298 | //=========================================================================================================================== |
---|
299 | |
---|
300 | extern mDNS mDNSStorage; |
---|
301 | |
---|
302 | static DNSDomainStats * gDomainStatsList = NULL; |
---|
303 | static ResolveStatsDomain * gResolveStatsList = NULL; |
---|
304 | static ResolveStatsDNSServer * gResolveStatsServerList = NULL; |
---|
305 | static unsigned int gResolveStatsNextServerID = 0; |
---|
306 | static int gResolveStatsObjCount = 0; |
---|
307 | static AWDServerConnection * gAWDServerConnection = nil; |
---|
308 | |
---|
309 | //=========================================================================================================================== |
---|
310 | // Local Prototypes |
---|
311 | //=========================================================================================================================== |
---|
312 | |
---|
313 | mDNSlocal mStatus DNSDomainStatsCreate(const Domain *inDomain, DNSDomainStats **outStats); |
---|
314 | mDNSlocal void DNSDomainStatsFree(DNSDomainStats *inStats); |
---|
315 | mDNSlocal void DNSDomainStatsFreeList(DNSDomainStats *inList); |
---|
316 | mDNSlocal mStatus DNSDomainStatsUpdate(DNSDomainStats *inStats, uint16_t inType, const ResourceRecord *inRR, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs, mDNSBool inForCell); |
---|
317 | |
---|
318 | mDNSlocal mStatus ResolveStatsDomainCreate(const Domain *inDomain, ResolveStatsDomain **outDomain); |
---|
319 | mDNSlocal void ResolveStatsDomainFree(ResolveStatsDomain *inDomain); |
---|
320 | mDNSlocal mStatus ResolveStatsDomainUpdate(ResolveStatsDomain *inDomain, const domainname *inHostname, const Response *inResp, const mDNSAddr *inDNSAddr, mDNSBool inForCell); |
---|
321 | mDNSlocal mStatus ResolveStatsDomainCreateAWDVersion(const ResolveStatsDomain *inDomain, AWDMDNSResponderResolveStatsDomain **outDomain); |
---|
322 | |
---|
323 | mDNSlocal mStatus ResolveStatsHostnameCreate(const domainname *inName, ResolveStatsHostname **outHostname); |
---|
324 | mDNSlocal void ResolveStatsHostnameFree(ResolveStatsHostname *inHostname); |
---|
325 | mDNSlocal mStatus ResolveStatsHostnameUpdate(ResolveStatsHostname *inHostname, const Response *inResp, uint8_t inServerID); |
---|
326 | mDNSlocal mStatus ResolveStatsHostnameCreateAWDVersion(const ResolveStatsHostname *inHostname, AWDMDNSResponderResolveStatsHostname **outHostname); |
---|
327 | |
---|
328 | mDNSlocal mStatus ResolveStatsDNSServerCreate(const mDNSAddr *inAddr, mDNSBool inForCell, ResolveStatsDNSServer **outServer); |
---|
329 | mDNSlocal void ResolveStatsDNSServerFree(ResolveStatsDNSServer *inServer); |
---|
330 | mDNSlocal mStatus ResolveStatsDNSServerCreateAWDVersion(const ResolveStatsDNSServer *inServer, AWDMDNSResponderResolveStatsDNSServer **outServer); |
---|
331 | |
---|
332 | mDNSlocal mStatus ResolveStatsIPv4AddrSetCreate(ResolveStatsIPv4AddrSet **outSet); |
---|
333 | mDNSlocal void ResolveStatsIPv4AddrSetFree(ResolveStatsIPv4AddrSet *inSet); |
---|
334 | |
---|
335 | mDNSlocal mStatus ResolveStatsIPv6AddressCreate(uint8_t inServerID, const uint8_t inAddrBytes[16], ResolveStatsIPv6Addr **outAddr); |
---|
336 | mDNSlocal void ResolveStatsIPv6AddressFree(ResolveStatsIPv6Addr *inAddr); |
---|
337 | |
---|
338 | mDNSlocal mStatus ResolveStatsNegAAAASetCreate(ResolveStatsNegAAAASet **outSet); |
---|
339 | mDNSlocal void ResolveStatsNegAAAASetFree(ResolveStatsNegAAAASet *inSet); |
---|
340 | mDNSlocal mStatus ResolveStatsGetServerID(const mDNSAddr *inServerAddr, mDNSBool inForCell, uint8_t *outServerID); |
---|
341 | |
---|
342 | mDNSlocal mStatus CreateDomainStatsList(DNSDomainStats **outList); |
---|
343 | mDNSlocal mStatus CreateResolveStatsList(ResolveStatsDomain **outList); |
---|
344 | mDNSlocal void FreeResolveStatsList(ResolveStatsDomain *inList); |
---|
345 | mDNSlocal void FreeResolveStatsServerList(ResolveStatsDNSServer *inList); |
---|
346 | mDNSlocal mStatus SubmitAWDMetric(UInt32 inMetricID); |
---|
347 | mDNSlocal mStatus SubmitAWDMetricQueryStats(void); |
---|
348 | mDNSlocal mStatus SubmitAWDMetricResolveStats(void); |
---|
349 | mDNSlocal mStatus CreateAWDDNSDomainStats(DNSHist *inHist, const char *inDomain, mDNSBool inForCell, AWDDNSDomainStats_RecordType inType, AWDDNSDomainStats **outStats); |
---|
350 | mDNSlocal mStatus AddAWDDNSDomainStats(AWDMDNSResponderDNSStatistics *inMetric, DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell); |
---|
351 | mDNSlocal void LogDNSHistSet(const DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell); |
---|
352 | mDNSlocal void LogDNSHist(const DNSHist *inHist, const char *inDomain, mDNSBool inForCell, const char *inType); |
---|
353 | mDNSlocal void LogDNSHistSendCounts(const uint16_t inSendCountBins[kQueryStatsSendCountBinCount]); |
---|
354 | mDNSlocal void LogDNSHistLatencies(const uint16_t inLatencyBins[kQueryStatsLatencyBinCount]); |
---|
355 | #if (METRICS_VALIDATE_DNS_STATS_DOMAINS) |
---|
356 | mDNSlocal void ValidateDNSStatsDomains(void); |
---|
357 | #endif |
---|
358 | |
---|
359 | //=========================================================================================================================== |
---|
360 | // MetricsInit |
---|
361 | //=========================================================================================================================== |
---|
362 | |
---|
363 | mStatus MetricsInit(void) |
---|
364 | { |
---|
365 | mStatus err; |
---|
366 | |
---|
367 | #if (METRICS_VALIDATE_DNS_STATS_DOMAINS) |
---|
368 | ValidateDNSStatsDomains(); |
---|
369 | #endif |
---|
370 | |
---|
371 | err = CreateDomainStatsList(&gDomainStatsList); |
---|
372 | require_noerr_quiet(err, exit); |
---|
373 | |
---|
374 | err = CreateResolveStatsList(&gResolveStatsList); |
---|
375 | require_noerr_quiet(err, exit); |
---|
376 | |
---|
377 | @autoreleasepool |
---|
378 | { |
---|
379 | gAWDServerConnection = [[AWDServerConnectionSoft alloc] |
---|
380 | initWithComponentId: AWDComponentId_MDNSResponder |
---|
381 | andBlockOnConfiguration: NO]; |
---|
382 | |
---|
383 | if (gAWDServerConnection) |
---|
384 | { |
---|
385 | [gAWDServerConnection |
---|
386 | registerQueriableMetricCallback: ^(UInt32 inMetricID) |
---|
387 | { |
---|
388 | SubmitAWDMetric(inMetricID); |
---|
389 | } |
---|
390 | forIdentifier: (UInt32)AWDMetricId_MDNSResponder_DNSStatistics]; |
---|
391 | |
---|
392 | [gAWDServerConnection |
---|
393 | registerQueriableMetricCallback: ^(UInt32 inMetricID) |
---|
394 | { |
---|
395 | SubmitAWDMetric(inMetricID); |
---|
396 | } |
---|
397 | forIdentifier: (UInt32)AWDMetricId_MDNSResponder_ResolveStats]; |
---|
398 | |
---|
399 | [gAWDServerConnection |
---|
400 | registerQueriableMetricCallback: ^(UInt32 inMetricID) |
---|
401 | { |
---|
402 | SubmitAWDMetric(inMetricID); |
---|
403 | } |
---|
404 | forIdentifier: (UInt32)AWDMetricId_MDNSResponder_ServicesStats]; |
---|
405 | } |
---|
406 | else |
---|
407 | { |
---|
408 | LogMsg("MetricsInit: failed to create AWD server connection."); |
---|
409 | } |
---|
410 | } |
---|
411 | exit: |
---|
412 | return (err); |
---|
413 | } |
---|
414 | |
---|
415 | //=========================================================================================================================== |
---|
416 | // MetricsUpdateUDNSQueryStats |
---|
417 | //=========================================================================================================================== |
---|
418 | |
---|
419 | mDNSexport void MetricsUpdateUDNSQueryStats(const domainname *inQueryName, mDNSu16 inType, const ResourceRecord *inRR, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCell) |
---|
420 | { |
---|
421 | DNSDomainStats * stats; |
---|
422 | int queryLabelCount; |
---|
423 | const domainname * queryParentDomain; |
---|
424 | mDNSBool isQueryInDomain; |
---|
425 | int skipCount; |
---|
426 | int skipCountLast = -1; |
---|
427 | |
---|
428 | queryLabelCount = CountLabels(inQueryName); |
---|
429 | |
---|
430 | for (stats = gDomainStatsList; stats; stats = stats->next) |
---|
431 | { |
---|
432 | isQueryInDomain = mDNSfalse; |
---|
433 | if (strcmp(stats->domain->cstr, ".") == 0) |
---|
434 | { |
---|
435 | // All queries are in the root domain. |
---|
436 | isQueryInDomain = mDNStrue; |
---|
437 | } |
---|
438 | else |
---|
439 | { |
---|
440 | skipCount = queryLabelCount - stats->domain->labelCount; |
---|
441 | if (skipCount >= 0) |
---|
442 | { |
---|
443 | if (skipCount != skipCountLast) |
---|
444 | { |
---|
445 | queryParentDomain = SkipLeadingLabels(inQueryName, skipCount); |
---|
446 | skipCountLast = skipCount; |
---|
447 | } |
---|
448 | isQueryInDomain = SameDomainName(queryParentDomain, stats->domain->name); |
---|
449 | } |
---|
450 | } |
---|
451 | |
---|
452 | if (isQueryInDomain) |
---|
453 | { |
---|
454 | DNSDomainStatsUpdate(stats, inType, inRR, inSendCount, inLatencyMs, inForCell); |
---|
455 | } |
---|
456 | } |
---|
457 | |
---|
458 | } |
---|
459 | |
---|
460 | //=========================================================================================================================== |
---|
461 | // MetricsUpdateUDNSResolveStats |
---|
462 | //=========================================================================================================================== |
---|
463 | |
---|
464 | mDNSexport void MetricsUpdateUDNSResolveStats(const domainname *inQueryName, const ResourceRecord *inRR, mDNSBool inForCell) |
---|
465 | { |
---|
466 | ResolveStatsDomain * domain; |
---|
467 | domainname hostname; |
---|
468 | size_t hostnameLen; |
---|
469 | mDNSBool isQueryInDomain; |
---|
470 | int skipCount; |
---|
471 | int skipCountLast = -1; |
---|
472 | int queryLabelCount; |
---|
473 | const domainname * queryParentDomain; |
---|
474 | Response response; |
---|
475 | |
---|
476 | require_quiet((inRR->rrtype == kDNSType_A) || (inRR->rrtype == kDNSType_AAAA), exit); |
---|
477 | require_quiet(inRR->rDNSServer, exit); |
---|
478 | |
---|
479 | queryLabelCount = CountLabels(inQueryName); |
---|
480 | |
---|
481 | for (domain = gResolveStatsList; domain; domain = domain->next) |
---|
482 | { |
---|
483 | isQueryInDomain = mDNSfalse; |
---|
484 | skipCount = queryLabelCount - domain->domainInfo->labelCount; |
---|
485 | if (skipCount >= 0) |
---|
486 | { |
---|
487 | if (skipCount != skipCountLast) |
---|
488 | { |
---|
489 | queryParentDomain = SkipLeadingLabels(inQueryName, skipCount); |
---|
490 | skipCountLast = skipCount; |
---|
491 | } |
---|
492 | isQueryInDomain = SameDomainName(queryParentDomain, domain->domainInfo->name); |
---|
493 | } |
---|
494 | if (!isQueryInDomain) continue; |
---|
495 | |
---|
496 | hostnameLen = (size_t)(queryParentDomain->c - inQueryName->c); |
---|
497 | if (hostnameLen >= sizeof(hostname.c)) continue; |
---|
498 | |
---|
499 | memcpy(hostname.c, inQueryName->c, hostnameLen); |
---|
500 | hostname.c[hostnameLen] = 0; |
---|
501 | |
---|
502 | if (inRR->RecordType == kDNSRecordTypePacketNegative) |
---|
503 | { |
---|
504 | response.type = (inRR->rrtype == kDNSType_A) ? kResponseType_NegA : kResponseType_NegAAAA; |
---|
505 | response.data = NULL; |
---|
506 | } |
---|
507 | else |
---|
508 | { |
---|
509 | response.type = (inRR->rrtype == kDNSType_A) ? kResponseType_IPv4Addr : kResponseType_IPv6Addr; |
---|
510 | response.data = (inRR->rrtype == kDNSType_A) ? inRR->rdata->u.ipv4.b : inRR->rdata->u.ipv6.b; |
---|
511 | } |
---|
512 | ResolveStatsDomainUpdate(domain, &hostname, &response, &inRR->rDNSServer->addr, inForCell); |
---|
513 | } |
---|
514 | |
---|
515 | exit: |
---|
516 | return; |
---|
517 | } |
---|
518 | |
---|
519 | //=========================================================================================================================== |
---|
520 | // LogMetrics |
---|
521 | //=========================================================================================================================== |
---|
522 | |
---|
523 | mDNSexport void LogMetrics(void) |
---|
524 | { |
---|
525 | DNSDomainStats * stats; |
---|
526 | const ResolveStatsDomain * domain; |
---|
527 | const ResolveStatsHostname * hostname; |
---|
528 | const ResolveStatsDNSServer * server; |
---|
529 | const ResolveStatsIPv4AddrSet * addrV4; |
---|
530 | const ResolveStatsIPv6Addr * addrV6; |
---|
531 | const ResolveStatsNegAAAASet * negV6; |
---|
532 | int hostnameCount; |
---|
533 | int i; |
---|
534 | unsigned int serverID; |
---|
535 | int serverObjCount = 0; |
---|
536 | int hostnameObjCount = 0; |
---|
537 | int addrObjCount = 0; |
---|
538 | |
---|
539 | LogMsgNoIdent("---- DNS query stats by domain -----"); |
---|
540 | |
---|
541 | for (stats = gDomainStatsList; stats; stats = stats->next) |
---|
542 | { |
---|
543 | if (!stats->nonCellular && !stats->cellular) |
---|
544 | { |
---|
545 | LogMsgNoIdent("No data for %s", stats->domain->cstr); |
---|
546 | continue; |
---|
547 | } |
---|
548 | if (stats->nonCellular) LogDNSHistSet(stats->nonCellular, stats->domain->cstr, mDNSfalse); |
---|
549 | if (stats->cellular) LogDNSHistSet(stats->cellular, stats->domain->cstr, mDNStrue); |
---|
550 | } |
---|
551 | |
---|
552 | LogMsgNoIdent("---- DNS resolve stats by domain -----"); |
---|
553 | |
---|
554 | LogMsgNoIdent("Servers:"); |
---|
555 | for (server = gResolveStatsServerList; server; server = server->next) |
---|
556 | { |
---|
557 | serverObjCount++; |
---|
558 | LogMsgNoIdent(server->isAddrV6 ? "%2u: %s %.16a" : "%2u: %s %.4a", |
---|
559 | server->id, server->isForCell ? " C" : "NC", server->addrBytes); |
---|
560 | } |
---|
561 | |
---|
562 | for (domain = gResolveStatsList; domain; domain = domain->next) |
---|
563 | { |
---|
564 | hostnameCount = 0; |
---|
565 | for (hostname = domain->hostnameList; hostname; hostname = hostname->next) { hostnameCount++; } |
---|
566 | hostnameObjCount += hostnameCount; |
---|
567 | |
---|
568 | LogMsgNoIdent("%##s (%d hostname%s)", domain->domainInfo->name, hostnameCount, (hostnameCount == 1) ? "" : "s"); |
---|
569 | |
---|
570 | for (hostname = domain->hostnameList; hostname; hostname = hostname->next) |
---|
571 | { |
---|
572 | LogMsgNoIdent(" %##s", hostname->name); |
---|
573 | for (serverID = 0; serverID < gResolveStatsNextServerID; ++serverID) |
---|
574 | { |
---|
575 | for (addrV4 = hostname->addrV4List; addrV4; addrV4 = addrV4->next) |
---|
576 | { |
---|
577 | if (serverID == 0) addrObjCount++; |
---|
578 | for (i = 0; i < (int)countof(addrV4->counters); ++i) |
---|
579 | { |
---|
580 | const IPv4AddrCounter * counter; |
---|
581 | |
---|
582 | counter = &addrV4->counters[i]; |
---|
583 | if (counter->count == 0) break; |
---|
584 | if (counter->serverID == serverID) |
---|
585 | { |
---|
586 | if (counter->isNegative) |
---|
587 | { |
---|
588 | LogMsgNoIdent("%10u: %3u negative A", counter->serverID, counter->count); |
---|
589 | } |
---|
590 | else |
---|
591 | { |
---|
592 | LogMsgNoIdent("%10u: %3u %.4a", counter->serverID, counter->count, counter->addrBytes); |
---|
593 | } |
---|
594 | } |
---|
595 | } |
---|
596 | } |
---|
597 | for (addrV6 = hostname->addrV6List; addrV6; addrV6 = addrV6->next) |
---|
598 | { |
---|
599 | if (serverID == 0) addrObjCount++; |
---|
600 | if (addrV6->serverID == serverID) |
---|
601 | { |
---|
602 | LogMsgNoIdent("%10u: %3u %.16a", addrV6->serverID, addrV6->count, addrV6->addrBytes); |
---|
603 | } |
---|
604 | } |
---|
605 | for (negV6 = hostname->negV6List; negV6; negV6 = negV6->next) |
---|
606 | { |
---|
607 | if (serverID == 0) addrObjCount++; |
---|
608 | for (i = 0; i < (int)countof(negV6->counters); ++i) |
---|
609 | { |
---|
610 | const NegAAAACounter * counter; |
---|
611 | |
---|
612 | counter = &negV6->counters[i]; |
---|
613 | if (counter->count == 0) break; |
---|
614 | if (counter->serverID == serverID) |
---|
615 | { |
---|
616 | LogMsgNoIdent("%10u: %3u negative AAAA", counter->serverID, counter->count); |
---|
617 | } |
---|
618 | } |
---|
619 | } |
---|
620 | } |
---|
621 | } |
---|
622 | } |
---|
623 | LogMsgNoIdent("Total object count: %3d (server %d hostname %d address %d)", |
---|
624 | serverObjCount + hostnameObjCount + addrObjCount, serverObjCount, hostnameObjCount, addrObjCount); |
---|
625 | |
---|
626 | LogMsgNoIdent("---- Num of Services Registered -----"); |
---|
627 | LogMsgNoIdent("Current_number_of_services_registered :[%d], Max_number_of_services_registered :[%d]", |
---|
628 | curr_num_regservices, max_num_regservices); |
---|
629 | } |
---|
630 | |
---|
631 | //=========================================================================================================================== |
---|
632 | // DNSDomainStatsCreate |
---|
633 | //=========================================================================================================================== |
---|
634 | |
---|
635 | mDNSlocal mStatus DNSDomainStatsCreate(const Domain *inDomain, DNSDomainStats **outStats) |
---|
636 | { |
---|
637 | mStatus err; |
---|
638 | DNSDomainStats * obj; |
---|
639 | |
---|
640 | obj = (DNSDomainStats *)calloc(1, sizeof(*obj)); |
---|
641 | require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); |
---|
642 | |
---|
643 | obj->domain = inDomain; |
---|
644 | |
---|
645 | *outStats = obj; |
---|
646 | err = mStatus_NoError; |
---|
647 | |
---|
648 | exit: |
---|
649 | return (err); |
---|
650 | } |
---|
651 | |
---|
652 | //=========================================================================================================================== |
---|
653 | // DNSDomainStatsFree |
---|
654 | //=========================================================================================================================== |
---|
655 | |
---|
656 | mDNSlocal void DNSDomainStatsFree(DNSDomainStats *inStats) |
---|
657 | { |
---|
658 | if (inStats->nonCellular) |
---|
659 | { |
---|
660 | ForgetMem(&inStats->nonCellular->histAny); |
---|
661 | ForgetMem(&inStats->nonCellular->histA); |
---|
662 | ForgetMem(&inStats->nonCellular->histAAAA); |
---|
663 | free(inStats->nonCellular); |
---|
664 | inStats->nonCellular = NULL; |
---|
665 | } |
---|
666 | if (inStats->cellular) |
---|
667 | { |
---|
668 | ForgetMem(&inStats->cellular->histAny); |
---|
669 | ForgetMem(&inStats->cellular->histA); |
---|
670 | ForgetMem(&inStats->cellular->histAAAA); |
---|
671 | free(inStats->cellular); |
---|
672 | inStats->cellular = NULL; |
---|
673 | } |
---|
674 | free(inStats); |
---|
675 | } |
---|
676 | |
---|
677 | //=========================================================================================================================== |
---|
678 | // DNSDomainStatsFreeList |
---|
679 | //=========================================================================================================================== |
---|
680 | |
---|
681 | mDNSlocal void DNSDomainStatsFreeList(DNSDomainStats *inList) |
---|
682 | { |
---|
683 | DNSDomainStats * stats; |
---|
684 | |
---|
685 | while ((stats = inList) != NULL) |
---|
686 | { |
---|
687 | inList = stats->next; |
---|
688 | DNSDomainStatsFree(stats); |
---|
689 | } |
---|
690 | } |
---|
691 | |
---|
692 | //=========================================================================================================================== |
---|
693 | // DNSDomainStatsUpdate |
---|
694 | //=========================================================================================================================== |
---|
695 | |
---|
696 | mDNSlocal mStatus DNSDomainStatsUpdate(DNSDomainStats *inStats, uint16_t inType, const ResourceRecord *inRR, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs, mDNSBool inForCell) |
---|
697 | { |
---|
698 | mStatus err; |
---|
699 | DNSHistSet ** p; |
---|
700 | DNSHistSet * set; |
---|
701 | DNSHist * histAny; |
---|
702 | DNSHist * hist; |
---|
703 | int i; |
---|
704 | |
---|
705 | require_action_quiet(inRR || (inQuerySendCount > 0), exit, err = mStatus_NoError); |
---|
706 | |
---|
707 | p = inForCell ? &inStats->cellular : &inStats->nonCellular; |
---|
708 | if ((set = *p) == NULL) |
---|
709 | { |
---|
710 | set = (DNSHistSet *)calloc(1, sizeof(*set)); |
---|
711 | require_action_quiet(set, exit, err = mStatus_NoMemoryErr); |
---|
712 | *p = set; |
---|
713 | } |
---|
714 | if ((histAny = set->histAny) == NULL) |
---|
715 | { |
---|
716 | histAny = (DNSHist *)calloc(1, sizeof(*histAny)); |
---|
717 | require_action_quiet(histAny, exit, err = mStatus_NoMemoryErr); |
---|
718 | set->histAny = histAny; |
---|
719 | } |
---|
720 | if (inType == kDNSType_A) |
---|
721 | { |
---|
722 | if ((hist = set->histA) == NULL) |
---|
723 | { |
---|
724 | hist = (DNSHist *)calloc(1, sizeof(*hist)); |
---|
725 | require_action_quiet(hist, exit, err = mStatus_NoMemoryErr); |
---|
726 | set->histA = hist; |
---|
727 | } |
---|
728 | } |
---|
729 | else if (inType == kDNSType_AAAA) |
---|
730 | { |
---|
731 | if ((hist = set->histAAAA) == NULL) |
---|
732 | { |
---|
733 | hist = (DNSHist *)calloc(1, sizeof(*hist)); |
---|
734 | require_action_quiet(hist, exit, err = mStatus_NoMemoryErr); |
---|
735 | set->histAAAA = hist; |
---|
736 | } |
---|
737 | } |
---|
738 | else |
---|
739 | { |
---|
740 | hist = NULL; |
---|
741 | } |
---|
742 | |
---|
743 | if (inRR) |
---|
744 | { |
---|
745 | uint16_t * sendCountBins; |
---|
746 | uint16_t * latencyBins; |
---|
747 | const mDNSBool isNegative = (inRR->RecordType == kDNSRecordTypePacketNegative); |
---|
748 | |
---|
749 | i = Min(inQuerySendCount, kQueryStatsMaxQuerySendCount); |
---|
750 | |
---|
751 | sendCountBins = isNegative ? histAny->negAnsweredQuerySendCountBins : histAny->answeredQuerySendCountBins; |
---|
752 | increment_saturate(sendCountBins[i], UINT16_MAX); |
---|
753 | if (hist) |
---|
754 | { |
---|
755 | sendCountBins = isNegative ? hist->negAnsweredQuerySendCountBins : hist->answeredQuerySendCountBins; |
---|
756 | increment_saturate(sendCountBins[i], UINT16_MAX); |
---|
757 | } |
---|
758 | |
---|
759 | if (inQuerySendCount > 0) |
---|
760 | { |
---|
761 | for (i = 0; (i < (int)countof(kResponseLatencyMsLimits)) && (inLatencyMs >= kResponseLatencyMsLimits[i]); ++i) {} |
---|
762 | latencyBins = isNegative ? histAny->negResponseLatencyBins : histAny->responseLatencyBins; |
---|
763 | increment_saturate(latencyBins[i], UINT16_MAX); |
---|
764 | if (hist) |
---|
765 | { |
---|
766 | latencyBins = isNegative ? hist->negResponseLatencyBins : hist->responseLatencyBins; |
---|
767 | increment_saturate(latencyBins[i], UINT16_MAX); |
---|
768 | } |
---|
769 | } |
---|
770 | } |
---|
771 | else |
---|
772 | { |
---|
773 | i = Min(inQuerySendCount, kQueryStatsMaxQuerySendCount); |
---|
774 | increment_saturate(histAny->unansweredQuerySendCountBins[i], UINT16_MAX); |
---|
775 | if (hist) increment_saturate(hist->unansweredQuerySendCountBins[i], UINT16_MAX); |
---|
776 | |
---|
777 | for (i = 0; (i < (int)countof(kResponseLatencyMsLimits)) && (inLatencyMs >= kResponseLatencyMsLimits[i]); ++i) {} |
---|
778 | increment_saturate(histAny->unansweredQueryDurationBins[i], UINT16_MAX); |
---|
779 | if (hist) increment_saturate(hist->unansweredQueryDurationBins[i], UINT16_MAX); |
---|
780 | } |
---|
781 | err = mStatus_NoError; |
---|
782 | |
---|
783 | exit: |
---|
784 | return (err); |
---|
785 | } |
---|
786 | |
---|
787 | //=========================================================================================================================== |
---|
788 | // ResolveStatsDomainCreate |
---|
789 | //=========================================================================================================================== |
---|
790 | |
---|
791 | mDNSlocal mStatus ResolveStatsDomainCreate(const Domain *inDomain, ResolveStatsDomain **outDomain) |
---|
792 | { |
---|
793 | mStatus err; |
---|
794 | ResolveStatsDomain * obj; |
---|
795 | |
---|
796 | obj = (ResolveStatsDomain *)calloc(1, sizeof(*obj)); |
---|
797 | require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); |
---|
798 | |
---|
799 | obj->domainInfo = inDomain; |
---|
800 | |
---|
801 | *outDomain = obj; |
---|
802 | err = mStatus_NoError; |
---|
803 | |
---|
804 | exit: |
---|
805 | return (err); |
---|
806 | } |
---|
807 | |
---|
808 | //=========================================================================================================================== |
---|
809 | // ResolveStatsDomainFree |
---|
810 | //=========================================================================================================================== |
---|
811 | |
---|
812 | mDNSlocal void ResolveStatsDomainFree(ResolveStatsDomain *inDomain) |
---|
813 | { |
---|
814 | ResolveStatsHostname * hostname; |
---|
815 | |
---|
816 | while ((hostname = inDomain->hostnameList) != NULL) |
---|
817 | { |
---|
818 | inDomain->hostnameList = hostname->next; |
---|
819 | ResolveStatsHostnameFree(hostname); |
---|
820 | } |
---|
821 | free(inDomain); |
---|
822 | } |
---|
823 | |
---|
824 | //=========================================================================================================================== |
---|
825 | // ResolveStatsDomainUpdate |
---|
826 | //=========================================================================================================================== |
---|
827 | |
---|
828 | mDNSlocal mStatus ResolveStatsDomainUpdate(ResolveStatsDomain *inDomain, const domainname *inHostname, const Response *inResp, const mDNSAddr *inDNSAddr, mDNSBool inForCell) |
---|
829 | { |
---|
830 | mStatus err; |
---|
831 | ResolveStatsHostname ** p; |
---|
832 | ResolveStatsHostname * hostname; |
---|
833 | uint8_t serverID; |
---|
834 | |
---|
835 | for (p = &inDomain->hostnameList; (hostname = *p) != NULL; p = &hostname->next) |
---|
836 | { |
---|
837 | if (SameDomainName((domainname *)hostname->name, inHostname)) break; |
---|
838 | } |
---|
839 | |
---|
840 | if (!hostname) |
---|
841 | { |
---|
842 | require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused); |
---|
843 | err = ResolveStatsHostnameCreate(inHostname, &hostname); |
---|
844 | require_noerr_quiet(err, exit); |
---|
845 | gResolveStatsObjCount++; |
---|
846 | *p = hostname; |
---|
847 | } |
---|
848 | |
---|
849 | err = ResolveStatsGetServerID(inDNSAddr, inForCell, &serverID); |
---|
850 | require_noerr_quiet(err, exit); |
---|
851 | |
---|
852 | err = ResolveStatsHostnameUpdate(hostname, inResp, serverID); |
---|
853 | require_noerr_quiet(err, exit); |
---|
854 | |
---|
855 | exit: |
---|
856 | return (err); |
---|
857 | } |
---|
858 | |
---|
859 | //=========================================================================================================================== |
---|
860 | // ResolveStatsHostnameCreate |
---|
861 | //=========================================================================================================================== |
---|
862 | |
---|
863 | mDNSlocal mStatus ResolveStatsHostnameCreate(const domainname *inName, ResolveStatsHostname **outHostname) |
---|
864 | { |
---|
865 | mStatus err; |
---|
866 | ResolveStatsHostname * obj; |
---|
867 | size_t nameLen; |
---|
868 | |
---|
869 | nameLen = DomainNameLength(inName); |
---|
870 | require_action_quiet(nameLen > 0, exit, err = mStatus_Invalid); |
---|
871 | |
---|
872 | obj = (ResolveStatsHostname *)calloc(1, sizeof(*obj) - 1 + nameLen); |
---|
873 | require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); |
---|
874 | |
---|
875 | memcpy(obj->name, inName, nameLen); |
---|
876 | |
---|
877 | *outHostname = obj; |
---|
878 | err = mStatus_NoError; |
---|
879 | |
---|
880 | exit: |
---|
881 | return (err); |
---|
882 | } |
---|
883 | |
---|
884 | //=========================================================================================================================== |
---|
885 | // ResolveStatsDomainCreateAWDVersion |
---|
886 | //=========================================================================================================================== |
---|
887 | |
---|
888 | mDNSlocal mStatus ResolveStatsDomainCreateAWDVersion(const ResolveStatsDomain *inDomain, AWDMDNSResponderResolveStatsDomain **outDomain) |
---|
889 | { |
---|
890 | mStatus err; |
---|
891 | AWDMDNSResponderResolveStatsDomain * domain; |
---|
892 | ResolveStatsHostname * hostname; |
---|
893 | AWDMDNSResponderResolveStatsHostname * awdHostname; |
---|
894 | NSString * name; |
---|
895 | |
---|
896 | domain = [[AWDMDNSResponderResolveStatsDomainSoft alloc] init]; |
---|
897 | require_action_quiet(domain, exit, err = mStatus_UnknownErr); |
---|
898 | |
---|
899 | name = [[NSString alloc] initWithUTF8String:inDomain->domainInfo->cstr]; |
---|
900 | require_action_quiet(name, exit, err = mStatus_UnknownErr); |
---|
901 | |
---|
902 | domain.name = name; |
---|
903 | [name release]; |
---|
904 | name = nil; |
---|
905 | |
---|
906 | for (hostname = inDomain->hostnameList; hostname; hostname = hostname->next) |
---|
907 | { |
---|
908 | err = ResolveStatsHostnameCreateAWDVersion(hostname, &awdHostname); |
---|
909 | require_noerr_quiet(err, exit); |
---|
910 | |
---|
911 | [domain addHostname:awdHostname]; |
---|
912 | [awdHostname release]; |
---|
913 | awdHostname = nil; |
---|
914 | } |
---|
915 | |
---|
916 | *outDomain = domain; |
---|
917 | domain = nil; |
---|
918 | err = mStatus_NoError; |
---|
919 | |
---|
920 | exit: |
---|
921 | [domain release]; |
---|
922 | return (err); |
---|
923 | } |
---|
924 | |
---|
925 | //=========================================================================================================================== |
---|
926 | // ResolveStatsHostnameFree |
---|
927 | //=========================================================================================================================== |
---|
928 | |
---|
929 | mDNSlocal void ResolveStatsHostnameFree(ResolveStatsHostname *inHostname) |
---|
930 | { |
---|
931 | ResolveStatsIPv4AddrSet * addrV4; |
---|
932 | ResolveStatsIPv6Addr * addrV6; |
---|
933 | ResolveStatsNegAAAASet * negV6; |
---|
934 | |
---|
935 | while ((addrV4 = inHostname->addrV4List) != NULL) |
---|
936 | { |
---|
937 | inHostname->addrV4List = addrV4->next; |
---|
938 | ResolveStatsIPv4AddrSetFree(addrV4); |
---|
939 | } |
---|
940 | while ((addrV6 = inHostname->addrV6List) != NULL) |
---|
941 | { |
---|
942 | inHostname->addrV6List = addrV6->next; |
---|
943 | ResolveStatsIPv6AddressFree(addrV6); |
---|
944 | } |
---|
945 | while ((negV6 = inHostname->negV6List) != NULL) |
---|
946 | { |
---|
947 | inHostname->negV6List = negV6->next; |
---|
948 | ResolveStatsNegAAAASetFree(negV6); |
---|
949 | } |
---|
950 | free(inHostname); |
---|
951 | } |
---|
952 | |
---|
953 | //=========================================================================================================================== |
---|
954 | // ResolveStatsHostnameUpdate |
---|
955 | //=========================================================================================================================== |
---|
956 | |
---|
957 | mDNSlocal mStatus ResolveStatsHostnameUpdate(ResolveStatsHostname *inHostname, const Response *inResp, uint8_t inServerID) |
---|
958 | { |
---|
959 | mStatus err; |
---|
960 | |
---|
961 | if ((inResp->type == kResponseType_IPv4Addr) || (inResp->type == kResponseType_NegA)) |
---|
962 | { |
---|
963 | ResolveStatsIPv4AddrSet ** p; |
---|
964 | ResolveStatsIPv4AddrSet * addrV4; |
---|
965 | int i; |
---|
966 | IPv4AddrCounter * counter; |
---|
967 | |
---|
968 | for (p = &inHostname->addrV4List; (addrV4 = *p) != NULL; p = &addrV4->next) |
---|
969 | { |
---|
970 | for (i = 0; i < (int)countof(addrV4->counters); ++i) |
---|
971 | { |
---|
972 | counter = &addrV4->counters[i]; |
---|
973 | if (counter->count == 0) break; |
---|
974 | if (counter->serverID != inServerID) continue; |
---|
975 | if (inResp->type == kResponseType_NegA) |
---|
976 | { |
---|
977 | if (counter->isNegative) break; |
---|
978 | } |
---|
979 | else |
---|
980 | { |
---|
981 | if (memcmp(counter->addrBytes, inResp->data, 4) == 0) break; |
---|
982 | } |
---|
983 | } |
---|
984 | if (i < (int)countof(addrV4->counters)) break; |
---|
985 | } |
---|
986 | if (!addrV4) |
---|
987 | { |
---|
988 | require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused); |
---|
989 | err = ResolveStatsIPv4AddrSetCreate(&addrV4); |
---|
990 | require_noerr_quiet(err, exit); |
---|
991 | gResolveStatsObjCount++; |
---|
992 | |
---|
993 | *p = addrV4; |
---|
994 | counter = &addrV4->counters[0]; |
---|
995 | } |
---|
996 | if (counter->count == 0) |
---|
997 | { |
---|
998 | counter->serverID = inServerID; |
---|
999 | if (inResp->type == kResponseType_NegA) |
---|
1000 | { |
---|
1001 | counter->isNegative = 1; |
---|
1002 | } |
---|
1003 | else |
---|
1004 | { |
---|
1005 | counter->isNegative = 0; |
---|
1006 | memcpy(counter->addrBytes, inResp->data, 4); |
---|
1007 | } |
---|
1008 | } |
---|
1009 | increment_saturate(counter->count, UINT16_MAX); |
---|
1010 | err = mStatus_NoError; |
---|
1011 | } |
---|
1012 | else if (inResp->type == kResponseType_IPv6Addr) |
---|
1013 | { |
---|
1014 | ResolveStatsIPv6Addr ** p; |
---|
1015 | ResolveStatsIPv6Addr * addrV6; |
---|
1016 | |
---|
1017 | for (p = &inHostname->addrV6List; (addrV6 = *p) != NULL; p = &addrV6->next) |
---|
1018 | { |
---|
1019 | if ((addrV6->serverID == inServerID) && (memcmp(addrV6->addrBytes, inResp->data, 16) == 0)) break; |
---|
1020 | } |
---|
1021 | if (!addrV6) |
---|
1022 | { |
---|
1023 | require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused); |
---|
1024 | err = ResolveStatsIPv6AddressCreate(inServerID, inResp->data, &addrV6); |
---|
1025 | require_noerr_quiet(err, exit); |
---|
1026 | gResolveStatsObjCount++; |
---|
1027 | |
---|
1028 | *p = addrV6; |
---|
1029 | } |
---|
1030 | increment_saturate(addrV6->count, UINT16_MAX); |
---|
1031 | err = mStatus_NoError; |
---|
1032 | } |
---|
1033 | else if (inResp->type == kResponseType_NegAAAA) |
---|
1034 | { |
---|
1035 | ResolveStatsNegAAAASet ** p; |
---|
1036 | ResolveStatsNegAAAASet * negV6; |
---|
1037 | int i; |
---|
1038 | NegAAAACounter * counter; |
---|
1039 | |
---|
1040 | for (p = &inHostname->negV6List; (negV6 = *p) != NULL; p = &negV6->next) |
---|
1041 | { |
---|
1042 | for (i = 0; i < (int)countof(negV6->counters); ++i) |
---|
1043 | { |
---|
1044 | counter = &negV6->counters[i]; |
---|
1045 | if ((counter->count == 0) || (counter->serverID == inServerID)) break; |
---|
1046 | } |
---|
1047 | if (i < (int)countof(negV6->counters)) break; |
---|
1048 | } |
---|
1049 | if (!negV6) |
---|
1050 | { |
---|
1051 | require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused); |
---|
1052 | err = ResolveStatsNegAAAASetCreate(&negV6); |
---|
1053 | require_noerr_quiet(err, exit); |
---|
1054 | gResolveStatsObjCount++; |
---|
1055 | |
---|
1056 | *p = negV6; |
---|
1057 | counter = &negV6->counters[0]; |
---|
1058 | } |
---|
1059 | if (counter->count == 0) counter->serverID = inServerID; |
---|
1060 | increment_saturate(counter->count, UINT16_MAX); |
---|
1061 | err = mStatus_NoError; |
---|
1062 | } |
---|
1063 | else |
---|
1064 | { |
---|
1065 | err = mStatus_Invalid; |
---|
1066 | } |
---|
1067 | |
---|
1068 | exit: |
---|
1069 | return (err); |
---|
1070 | } |
---|
1071 | |
---|
1072 | //=========================================================================================================================== |
---|
1073 | // ResolveStatsHostnameCreateAWDVersion |
---|
1074 | //=========================================================================================================================== |
---|
1075 | |
---|
1076 | mDNSlocal mStatus ResolveStatsHostnameCreateAWDVersion(const ResolveStatsHostname *inHostname, AWDMDNSResponderResolveStatsHostname **outHostname) |
---|
1077 | { |
---|
1078 | mStatus err; |
---|
1079 | AWDMDNSResponderResolveStatsHostname * hostname; |
---|
1080 | NSString * name; |
---|
1081 | char nameBuf[MAX_ESCAPED_DOMAIN_NAME]; |
---|
1082 | const char * ptr; |
---|
1083 | ResolveStatsIPv4AddrSet * addrV4; |
---|
1084 | ResolveStatsIPv6Addr * addrV6; |
---|
1085 | ResolveStatsNegAAAASet * negV6; |
---|
1086 | AWDMDNSResponderResolveStatsResult * result = nil; |
---|
1087 | int i; |
---|
1088 | |
---|
1089 | hostname = [[AWDMDNSResponderResolveStatsHostnameSoft alloc] init]; |
---|
1090 | require_action_quiet(hostname, exit, err = mStatus_UnknownErr); |
---|
1091 | |
---|
1092 | ptr = ConvertDomainNameToCString((domainname *)inHostname->name, nameBuf); |
---|
1093 | require_action_quiet(ptr, exit, err = mStatus_UnknownErr); |
---|
1094 | |
---|
1095 | name = [[NSString alloc] initWithUTF8String:nameBuf]; |
---|
1096 | require_action_quiet(name, exit, err = mStatus_UnknownErr); |
---|
1097 | |
---|
1098 | hostname.name = name; |
---|
1099 | [name release]; |
---|
1100 | name = nil; |
---|
1101 | |
---|
1102 | for (addrV4 = inHostname->addrV4List; addrV4; addrV4 = addrV4->next) |
---|
1103 | { |
---|
1104 | for (i = 0; i < (int)countof(addrV4->counters); ++i) |
---|
1105 | { |
---|
1106 | const IPv4AddrCounter * counter; |
---|
1107 | NSData * addrBytes; |
---|
1108 | |
---|
1109 | counter = &addrV4->counters[i]; |
---|
1110 | if (counter->count == 0) break; |
---|
1111 | |
---|
1112 | result = [[AWDMDNSResponderResolveStatsResultSoft alloc] init]; |
---|
1113 | require_action_quiet(result, exit, err = mStatus_UnknownErr); |
---|
1114 | |
---|
1115 | if (counter->isNegative) |
---|
1116 | { |
---|
1117 | result.type = AWDMDNSResponderResolveStatsResult_ResultType_NegA; |
---|
1118 | } |
---|
1119 | else |
---|
1120 | { |
---|
1121 | addrBytes = [[NSData alloc] initWithBytes:counter->addrBytes length:4]; |
---|
1122 | require_action_quiet(addrBytes, exit, err = mStatus_UnknownErr); |
---|
1123 | |
---|
1124 | result.type = AWDMDNSResponderResolveStatsResult_ResultType_IPv4Addr; |
---|
1125 | result.data = addrBytes; |
---|
1126 | [addrBytes release]; |
---|
1127 | } |
---|
1128 | result.count = counter->count; |
---|
1129 | result.serverID = counter->serverID; |
---|
1130 | |
---|
1131 | [hostname addResult:result]; |
---|
1132 | [result release]; |
---|
1133 | result = nil; |
---|
1134 | } |
---|
1135 | } |
---|
1136 | |
---|
1137 | for (addrV6 = inHostname->addrV6List; addrV6; addrV6 = addrV6->next) |
---|
1138 | { |
---|
1139 | NSData * addrBytes; |
---|
1140 | |
---|
1141 | result = [[AWDMDNSResponderResolveStatsResultSoft alloc] init]; |
---|
1142 | require_action_quiet(result, exit, err = mStatus_UnknownErr); |
---|
1143 | |
---|
1144 | addrBytes = [[NSData alloc] initWithBytes:addrV6->addrBytes length:16]; |
---|
1145 | require_action_quiet(addrBytes, exit, err = mStatus_UnknownErr); |
---|
1146 | |
---|
1147 | result.type = AWDMDNSResponderResolveStatsResult_ResultType_IPv6Addr; |
---|
1148 | result.count = addrV6->count; |
---|
1149 | result.serverID = addrV6->serverID; |
---|
1150 | result.data = addrBytes; |
---|
1151 | |
---|
1152 | [addrBytes release]; |
---|
1153 | |
---|
1154 | [hostname addResult:result]; |
---|
1155 | [result release]; |
---|
1156 | result = nil; |
---|
1157 | } |
---|
1158 | |
---|
1159 | for (negV6 = inHostname->negV6List; negV6; negV6 = negV6->next) |
---|
1160 | { |
---|
1161 | for (i = 0; i < (int)countof(negV6->counters); ++i) |
---|
1162 | { |
---|
1163 | const NegAAAACounter * counter; |
---|
1164 | |
---|
1165 | counter = &negV6->counters[i]; |
---|
1166 | if (counter->count == 0) break; |
---|
1167 | |
---|
1168 | result = [[AWDMDNSResponderResolveStatsResultSoft alloc] init]; |
---|
1169 | require_action_quiet(result, exit, err = mStatus_UnknownErr); |
---|
1170 | |
---|
1171 | result.type = AWDMDNSResponderResolveStatsResult_ResultType_NegAAAA; |
---|
1172 | result.count = counter->count; |
---|
1173 | result.serverID = counter->serverID; |
---|
1174 | |
---|
1175 | [hostname addResult:result]; |
---|
1176 | [result release]; |
---|
1177 | result = nil; |
---|
1178 | } |
---|
1179 | } |
---|
1180 | |
---|
1181 | *outHostname = hostname; |
---|
1182 | hostname = nil; |
---|
1183 | err = mStatus_NoError; |
---|
1184 | |
---|
1185 | exit: |
---|
1186 | [result release]; |
---|
1187 | [hostname release]; |
---|
1188 | return (err); |
---|
1189 | } |
---|
1190 | |
---|
1191 | //=========================================================================================================================== |
---|
1192 | // ResolveStatsDNSServerCreate |
---|
1193 | //=========================================================================================================================== |
---|
1194 | |
---|
1195 | mDNSlocal mStatus ResolveStatsDNSServerCreate(const mDNSAddr *inAddr, mDNSBool inForCell, ResolveStatsDNSServer **outServer) |
---|
1196 | { |
---|
1197 | mStatus err; |
---|
1198 | ResolveStatsDNSServer * obj; |
---|
1199 | size_t addrLen; |
---|
1200 | |
---|
1201 | require_action_quiet((inAddr->type == mDNSAddrType_IPv4) || (inAddr->type == mDNSAddrType_IPv6), exit, err = mStatus_Invalid); |
---|
1202 | |
---|
1203 | addrLen = (inAddr->type == mDNSAddrType_IPv4) ? 4 : 16; |
---|
1204 | obj = (ResolveStatsDNSServer *)calloc(1, sizeof(*obj) - 1 + addrLen); |
---|
1205 | require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); |
---|
1206 | |
---|
1207 | obj->isForCell = inForCell; |
---|
1208 | if (inAddr->type == mDNSAddrType_IPv4) |
---|
1209 | { |
---|
1210 | obj->isAddrV6 = mDNSfalse; |
---|
1211 | memcpy(obj->addrBytes, inAddr->ip.v4.b, addrLen); |
---|
1212 | } |
---|
1213 | else |
---|
1214 | { |
---|
1215 | obj->isAddrV6 = mDNStrue; |
---|
1216 | memcpy(obj->addrBytes, inAddr->ip.v6.b, addrLen); |
---|
1217 | } |
---|
1218 | |
---|
1219 | *outServer = obj; |
---|
1220 | err = mStatus_NoError; |
---|
1221 | |
---|
1222 | exit: |
---|
1223 | return (err); |
---|
1224 | } |
---|
1225 | |
---|
1226 | //=========================================================================================================================== |
---|
1227 | // ResolveStatsDNSServerFree |
---|
1228 | //=========================================================================================================================== |
---|
1229 | |
---|
1230 | mDNSlocal void ResolveStatsDNSServerFree(ResolveStatsDNSServer *inServer) |
---|
1231 | { |
---|
1232 | free(inServer); |
---|
1233 | } |
---|
1234 | |
---|
1235 | //=========================================================================================================================== |
---|
1236 | // ResolveStatsDNSServerCreateAWDVersion |
---|
1237 | //=========================================================================================================================== |
---|
1238 | |
---|
1239 | mDNSlocal mStatus ResolveStatsDNSServerCreateAWDVersion(const ResolveStatsDNSServer *inServer, AWDMDNSResponderResolveStatsDNSServer **outServer) |
---|
1240 | { |
---|
1241 | mStatus err; |
---|
1242 | AWDMDNSResponderResolveStatsDNSServer * server; |
---|
1243 | NSData * addrBytes = nil; |
---|
1244 | |
---|
1245 | server = [[AWDMDNSResponderResolveStatsDNSServerSoft alloc] init]; |
---|
1246 | require_action_quiet(server, exit, err = mStatus_UnknownErr); |
---|
1247 | |
---|
1248 | addrBytes = [[NSData alloc] initWithBytes:inServer->addrBytes length:(inServer->isAddrV6 ? 16 : 4)]; |
---|
1249 | require_action_quiet(addrBytes, exit, err = mStatus_UnknownErr); |
---|
1250 | |
---|
1251 | server.serverID = inServer->id; |
---|
1252 | server.address = addrBytes; |
---|
1253 | if (inServer->isForCell) |
---|
1254 | { |
---|
1255 | server.networkType = AWDMDNSResponderResolveStatsDNSServer_NetworkType_Cellular; |
---|
1256 | } |
---|
1257 | else |
---|
1258 | { |
---|
1259 | server.networkType = AWDMDNSResponderResolveStatsDNSServer_NetworkType_NonCellular; |
---|
1260 | } |
---|
1261 | |
---|
1262 | *outServer = server; |
---|
1263 | server = nil; |
---|
1264 | err = mStatus_NoError; |
---|
1265 | |
---|
1266 | exit: |
---|
1267 | [addrBytes release]; |
---|
1268 | [server release]; |
---|
1269 | return (err); |
---|
1270 | } |
---|
1271 | |
---|
1272 | //=========================================================================================================================== |
---|
1273 | // ResolveStatsIPv4AddrSetCreate |
---|
1274 | //=========================================================================================================================== |
---|
1275 | |
---|
1276 | mDNSlocal mStatus ResolveStatsIPv4AddrSetCreate(ResolveStatsIPv4AddrSet **outSet) |
---|
1277 | { |
---|
1278 | mStatus err; |
---|
1279 | ResolveStatsIPv4AddrSet * obj; |
---|
1280 | |
---|
1281 | obj = (ResolveStatsIPv4AddrSet *)calloc(1, sizeof(*obj)); |
---|
1282 | require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); |
---|
1283 | |
---|
1284 | *outSet = obj; |
---|
1285 | err = mStatus_NoError; |
---|
1286 | |
---|
1287 | exit: |
---|
1288 | return (err); |
---|
1289 | } |
---|
1290 | |
---|
1291 | //=========================================================================================================================== |
---|
1292 | // ResolveStatsIPv4AddrSetFree |
---|
1293 | //=========================================================================================================================== |
---|
1294 | |
---|
1295 | mDNSlocal void ResolveStatsIPv4AddrSetFree(ResolveStatsIPv4AddrSet *inSet) |
---|
1296 | { |
---|
1297 | free(inSet); |
---|
1298 | } |
---|
1299 | |
---|
1300 | //=========================================================================================================================== |
---|
1301 | // ResolveStatsIPv6AddressCreate |
---|
1302 | //=========================================================================================================================== |
---|
1303 | |
---|
1304 | mDNSlocal mStatus ResolveStatsIPv6AddressCreate(uint8_t inServerID, const uint8_t inAddrBytes[16], ResolveStatsIPv6Addr **outAddr) |
---|
1305 | { |
---|
1306 | mStatus err; |
---|
1307 | ResolveStatsIPv6Addr * obj; |
---|
1308 | |
---|
1309 | obj = (ResolveStatsIPv6Addr *)calloc(1, sizeof(*obj)); |
---|
1310 | require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); |
---|
1311 | |
---|
1312 | obj->serverID = inServerID; |
---|
1313 | memcpy(obj->addrBytes, inAddrBytes, 16); |
---|
1314 | |
---|
1315 | *outAddr = obj; |
---|
1316 | err = mStatus_NoError; |
---|
1317 | |
---|
1318 | exit: |
---|
1319 | return (err); |
---|
1320 | } |
---|
1321 | |
---|
1322 | //=========================================================================================================================== |
---|
1323 | // ResolveStatsIPv6AddressFree |
---|
1324 | //=========================================================================================================================== |
---|
1325 | |
---|
1326 | mDNSlocal void ResolveStatsIPv6AddressFree(ResolveStatsIPv6Addr *inAddr) |
---|
1327 | { |
---|
1328 | free(inAddr); |
---|
1329 | } |
---|
1330 | |
---|
1331 | //=========================================================================================================================== |
---|
1332 | // ResolveStatsNegAAAASetCreate |
---|
1333 | //=========================================================================================================================== |
---|
1334 | |
---|
1335 | mDNSlocal mStatus ResolveStatsNegAAAASetCreate(ResolveStatsNegAAAASet **outSet) |
---|
1336 | { |
---|
1337 | mStatus err; |
---|
1338 | ResolveStatsNegAAAASet * obj; |
---|
1339 | |
---|
1340 | obj = (ResolveStatsNegAAAASet *)calloc(1, sizeof(*obj)); |
---|
1341 | require_action_quiet(obj, exit, err = mStatus_NoMemoryErr); |
---|
1342 | |
---|
1343 | *outSet = obj; |
---|
1344 | err = mStatus_NoError; |
---|
1345 | |
---|
1346 | exit: |
---|
1347 | return (err); |
---|
1348 | } |
---|
1349 | |
---|
1350 | //=========================================================================================================================== |
---|
1351 | // ResolveStatsNegAAAASetFree |
---|
1352 | //=========================================================================================================================== |
---|
1353 | |
---|
1354 | mDNSlocal void ResolveStatsNegAAAASetFree(ResolveStatsNegAAAASet *inSet) |
---|
1355 | { |
---|
1356 | free(inSet); |
---|
1357 | } |
---|
1358 | |
---|
1359 | //=========================================================================================================================== |
---|
1360 | // ResolveStatsGetServerID |
---|
1361 | //=========================================================================================================================== |
---|
1362 | |
---|
1363 | mDNSlocal mStatus ResolveStatsGetServerID(const mDNSAddr *inServerAddr, mDNSBool inForCell, uint8_t *outServerID) |
---|
1364 | { |
---|
1365 | mStatus err; |
---|
1366 | ResolveStatsDNSServer ** p; |
---|
1367 | ResolveStatsDNSServer * server; |
---|
1368 | |
---|
1369 | require_action_quiet((inServerAddr->type == mDNSAddrType_IPv4) || (inServerAddr->type == mDNSAddrType_IPv6), exit, err = mStatus_Invalid); |
---|
1370 | |
---|
1371 | for (p = &gResolveStatsServerList; (server = *p) != NULL; p = &server->next) |
---|
1372 | { |
---|
1373 | if ((inForCell && server->isForCell) || (!inForCell && !server->isForCell)) |
---|
1374 | { |
---|
1375 | if (inServerAddr->type == mDNSAddrType_IPv4) |
---|
1376 | { |
---|
1377 | if (!server->isAddrV6 && (memcmp(server->addrBytes, inServerAddr->ip.v4.b, 4) == 0)) break; |
---|
1378 | } |
---|
1379 | else |
---|
1380 | { |
---|
1381 | if (server->isAddrV6 && (memcmp(server->addrBytes, inServerAddr->ip.v6.b, 16) == 0)) break; |
---|
1382 | } |
---|
1383 | } |
---|
1384 | } |
---|
1385 | |
---|
1386 | if (!server) |
---|
1387 | { |
---|
1388 | require_action_quiet(gResolveStatsNextServerID <= UINT8_MAX, exit, err = mStatus_Refused); |
---|
1389 | require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused); |
---|
1390 | err = ResolveStatsDNSServerCreate(inServerAddr, inForCell, &server); |
---|
1391 | require_noerr_quiet(err, exit); |
---|
1392 | gResolveStatsObjCount++; |
---|
1393 | |
---|
1394 | server->id = gResolveStatsNextServerID++; |
---|
1395 | server->next = gResolveStatsServerList; |
---|
1396 | gResolveStatsServerList = server; |
---|
1397 | } |
---|
1398 | else if (gResolveStatsServerList != server) |
---|
1399 | { |
---|
1400 | *p = server->next; |
---|
1401 | server->next = gResolveStatsServerList; |
---|
1402 | gResolveStatsServerList = server; |
---|
1403 | } |
---|
1404 | |
---|
1405 | *outServerID = server->id; |
---|
1406 | err = mStatus_NoError; |
---|
1407 | |
---|
1408 | exit: |
---|
1409 | return (err); |
---|
1410 | } |
---|
1411 | |
---|
1412 | //=========================================================================================================================== |
---|
1413 | // CreateDomainStatsList |
---|
1414 | //=========================================================================================================================== |
---|
1415 | |
---|
1416 | mDNSlocal mStatus CreateDomainStatsList(DNSDomainStats **outList) |
---|
1417 | { |
---|
1418 | mStatus err; |
---|
1419 | int i; |
---|
1420 | DNSDomainStats * stats; |
---|
1421 | DNSDomainStats ** p; |
---|
1422 | DNSDomainStats * list = NULL; |
---|
1423 | |
---|
1424 | p = &list; |
---|
1425 | for (i = 0; i < (int)countof(kQueryStatsDomains); ++i) |
---|
1426 | { |
---|
1427 | err = DNSDomainStatsCreate(&kQueryStatsDomains[i], &stats); |
---|
1428 | require_noerr_quiet(err, exit); |
---|
1429 | |
---|
1430 | *p = stats; |
---|
1431 | p = &stats->next; |
---|
1432 | } |
---|
1433 | |
---|
1434 | *outList = list; |
---|
1435 | list = NULL; |
---|
1436 | |
---|
1437 | exit: |
---|
1438 | DNSDomainStatsFreeList(list); |
---|
1439 | return (err); |
---|
1440 | } |
---|
1441 | |
---|
1442 | //=========================================================================================================================== |
---|
1443 | // CreateResolveStatsList |
---|
1444 | //=========================================================================================================================== |
---|
1445 | |
---|
1446 | mDNSlocal mStatus CreateResolveStatsList(ResolveStatsDomain **outList) |
---|
1447 | { |
---|
1448 | mStatus err; |
---|
1449 | int i; |
---|
1450 | ResolveStatsDomain * domain; |
---|
1451 | ResolveStatsDomain ** p; |
---|
1452 | ResolveStatsDomain * list = NULL; |
---|
1453 | |
---|
1454 | p = &list; |
---|
1455 | for (i = 0; i < (int)countof(kResolveStatsDomains); ++i) |
---|
1456 | { |
---|
1457 | err = ResolveStatsDomainCreate(&kResolveStatsDomains[i], &domain); |
---|
1458 | require_noerr_quiet(err, exit); |
---|
1459 | |
---|
1460 | *p = domain; |
---|
1461 | p = &domain->next; |
---|
1462 | } |
---|
1463 | |
---|
1464 | *outList = list; |
---|
1465 | list = NULL; |
---|
1466 | |
---|
1467 | exit: |
---|
1468 | FreeResolveStatsList(list); |
---|
1469 | return (err); |
---|
1470 | } |
---|
1471 | |
---|
1472 | //=========================================================================================================================== |
---|
1473 | // FreeResolveStatsList |
---|
1474 | //=========================================================================================================================== |
---|
1475 | |
---|
1476 | mDNSlocal void FreeResolveStatsList(ResolveStatsDomain *inList) |
---|
1477 | { |
---|
1478 | ResolveStatsDomain * domain; |
---|
1479 | |
---|
1480 | while ((domain = inList) != NULL) |
---|
1481 | { |
---|
1482 | inList = domain->next; |
---|
1483 | ResolveStatsDomainFree(domain); |
---|
1484 | } |
---|
1485 | } |
---|
1486 | |
---|
1487 | //=========================================================================================================================== |
---|
1488 | // FreeResolveStatsServerList |
---|
1489 | //=========================================================================================================================== |
---|
1490 | |
---|
1491 | mDNSlocal void FreeResolveStatsServerList(ResolveStatsDNSServer *inList) |
---|
1492 | { |
---|
1493 | ResolveStatsDNSServer * server; |
---|
1494 | |
---|
1495 | while ((server = inList) != NULL) |
---|
1496 | { |
---|
1497 | inList = server->next; |
---|
1498 | ResolveStatsDNSServerFree(server); |
---|
1499 | } |
---|
1500 | } |
---|
1501 | |
---|
1502 | //=========================================================================================================================== |
---|
1503 | // SubmitAWDMetric |
---|
1504 | //=========================================================================================================================== |
---|
1505 | |
---|
1506 | mDNSlocal mStatus SubmitAWDMetric(UInt32 inMetricID) |
---|
1507 | { |
---|
1508 | mStatus err = mStatus_NoError; |
---|
1509 | |
---|
1510 | switch (inMetricID) |
---|
1511 | { |
---|
1512 | case AWDMetricId_MDNSResponder_DNSStatistics: |
---|
1513 | err = SubmitAWDMetricQueryStats(); |
---|
1514 | break; |
---|
1515 | |
---|
1516 | case AWDMetricId_MDNSResponder_ResolveStats: |
---|
1517 | err = SubmitAWDMetricResolveStats(); |
---|
1518 | break; |
---|
1519 | |
---|
1520 | case AWDMetricId_MDNSResponder_ServicesStats: |
---|
1521 | [AWDMetricManagerSoft postMetricWithId:AWDMetricId_MDNSResponder_ServicesStats integerValue:max_num_regservices]; |
---|
1522 | KQueueLock(&mDNSStorage); |
---|
1523 | // reset the no of max services since we want to collect the max no of services registered per AWD submission period |
---|
1524 | max_num_regservices = curr_num_regservices; |
---|
1525 | KQueueUnlock(&mDNSStorage, "SubmitAWDSimpleMetricServiceStats"); |
---|
1526 | break; |
---|
1527 | |
---|
1528 | default: |
---|
1529 | err = mStatus_UnsupportedErr; |
---|
1530 | break; |
---|
1531 | } |
---|
1532 | |
---|
1533 | if (err) |
---|
1534 | LogMsg("SubmitAWDMetric for metric ID 0x%08X failed with error %d", inMetricID, err); |
---|
1535 | return (err); |
---|
1536 | } |
---|
1537 | |
---|
1538 | //=========================================================================================================================== |
---|
1539 | // SubmitAWDMetricQueryStats |
---|
1540 | //=========================================================================================================================== |
---|
1541 | |
---|
1542 | mDNSlocal mStatus SubmitAWDMetricQueryStats(void) |
---|
1543 | { |
---|
1544 | mStatus err; |
---|
1545 | BOOL success; |
---|
1546 | DNSDomainStats * stats; |
---|
1547 | DNSDomainStats * newDomainStatsList; |
---|
1548 | DNSDomainStats * domainStatsList = NULL; |
---|
1549 | AWDMetricContainer * container = nil; |
---|
1550 | AWDMDNSResponderDNSStatistics * metric = nil; |
---|
1551 | |
---|
1552 | err = CreateDomainStatsList(&newDomainStatsList); |
---|
1553 | require_noerr_quiet(err, exit); |
---|
1554 | |
---|
1555 | domainStatsList = gDomainStatsList; |
---|
1556 | |
---|
1557 | KQueueLock(&mDNSStorage); |
---|
1558 | gDomainStatsList = newDomainStatsList; |
---|
1559 | KQueueUnlock(&mDNSStorage, "SubmitAWDMetricQueryStats"); |
---|
1560 | |
---|
1561 | container = [gAWDServerConnection newMetricContainerWithIdentifier:AWDMetricId_MDNSResponder_DNSStatistics]; |
---|
1562 | require_action_quiet(container, exit, err = mStatus_UnknownErr); |
---|
1563 | |
---|
1564 | metric = [[AWDMDNSResponderDNSStatisticsSoft alloc] init]; |
---|
1565 | require_action_quiet(metric, exit, err = mStatus_UnknownErr); |
---|
1566 | |
---|
1567 | while ((stats = domainStatsList) != NULL) |
---|
1568 | { |
---|
1569 | if (stats->nonCellular) |
---|
1570 | { |
---|
1571 | err = AddAWDDNSDomainStats(metric, stats->nonCellular, stats->domain->cstr, mDNSfalse); |
---|
1572 | require_noerr_quiet(err, exit); |
---|
1573 | } |
---|
1574 | if (stats->cellular) |
---|
1575 | { |
---|
1576 | err = AddAWDDNSDomainStats(metric, stats->cellular, stats->domain->cstr, mDNStrue); |
---|
1577 | require_noerr_quiet(err, exit); |
---|
1578 | } |
---|
1579 | domainStatsList = stats->next; |
---|
1580 | DNSDomainStatsFree(stats); |
---|
1581 | } |
---|
1582 | |
---|
1583 | container.metric = metric; |
---|
1584 | success = [gAWDServerConnection submitMetric:container]; |
---|
1585 | LogMsg("SubmitAWDMetricQueryStats: metric submission %s.", success ? "succeeded" : "failed" ); |
---|
1586 | err = success ? mStatus_NoError : mStatus_UnknownErr; |
---|
1587 | |
---|
1588 | exit: |
---|
1589 | [metric release]; |
---|
1590 | [container release]; |
---|
1591 | DNSDomainStatsFreeList(domainStatsList); |
---|
1592 | return (err); |
---|
1593 | } |
---|
1594 | |
---|
1595 | //=========================================================================================================================== |
---|
1596 | // SubmitAWDMetricResolveStats |
---|
1597 | //=========================================================================================================================== |
---|
1598 | |
---|
1599 | mDNSlocal mStatus SubmitAWDMetricResolveStats(void) |
---|
1600 | { |
---|
1601 | mStatus err; |
---|
1602 | ResolveStatsDomain * newResolveStatsList; |
---|
1603 | ResolveStatsDomain * domainList = NULL; |
---|
1604 | ResolveStatsDNSServer * serverList = NULL; |
---|
1605 | AWDMetricContainer * container = nil; |
---|
1606 | AWDMDNSResponderResolveStats * metric = nil; |
---|
1607 | ResolveStatsDNSServer * server; |
---|
1608 | ResolveStatsDomain * domain; |
---|
1609 | BOOL success; |
---|
1610 | |
---|
1611 | err = CreateResolveStatsList(&newResolveStatsList); |
---|
1612 | require_noerr_quiet(err, exit); |
---|
1613 | |
---|
1614 | domainList = gResolveStatsList; |
---|
1615 | serverList = gResolveStatsServerList; |
---|
1616 | |
---|
1617 | KQueueLock(&mDNSStorage); |
---|
1618 | gResolveStatsList = newResolveStatsList; |
---|
1619 | gResolveStatsServerList = NULL; |
---|
1620 | gResolveStatsNextServerID = 0; |
---|
1621 | gResolveStatsObjCount = 0; |
---|
1622 | KQueueUnlock(&mDNSStorage, "SubmitAWDMetricResolveStats"); |
---|
1623 | |
---|
1624 | container = [gAWDServerConnection newMetricContainerWithIdentifier:AWDMetricId_MDNSResponder_ResolveStats]; |
---|
1625 | require_action_quiet(container, exit, err = mStatus_UnknownErr); |
---|
1626 | |
---|
1627 | metric = [[AWDMDNSResponderResolveStatsSoft alloc] init]; |
---|
1628 | require_action_quiet(metric, exit, err = mStatus_UnknownErr); |
---|
1629 | |
---|
1630 | while ((server = serverList) != NULL) |
---|
1631 | { |
---|
1632 | AWDMDNSResponderResolveStatsDNSServer * awdServer; |
---|
1633 | |
---|
1634 | serverList = server->next; |
---|
1635 | err = ResolveStatsDNSServerCreateAWDVersion(server, &awdServer); |
---|
1636 | ResolveStatsDNSServerFree(server); |
---|
1637 | require_noerr_quiet(err, exit); |
---|
1638 | |
---|
1639 | [metric addServer:awdServer]; |
---|
1640 | [awdServer release]; |
---|
1641 | } |
---|
1642 | |
---|
1643 | while ((domain = domainList) != NULL) |
---|
1644 | { |
---|
1645 | AWDMDNSResponderResolveStatsDomain * awdDomain; |
---|
1646 | |
---|
1647 | domainList = domain->next; |
---|
1648 | err = ResolveStatsDomainCreateAWDVersion(domain, &awdDomain); |
---|
1649 | ResolveStatsDomainFree(domain); |
---|
1650 | require_noerr_quiet(err, exit); |
---|
1651 | |
---|
1652 | [metric addDomain:awdDomain]; |
---|
1653 | [awdDomain release]; |
---|
1654 | } |
---|
1655 | |
---|
1656 | container.metric = metric; |
---|
1657 | success = [gAWDServerConnection submitMetric:container]; |
---|
1658 | LogMsg("SubmitAWDMetricResolveStats: metric submission %s.", success ? "succeeded" : "failed" ); |
---|
1659 | err = success ? mStatus_NoError : mStatus_UnknownErr; |
---|
1660 | |
---|
1661 | exit: |
---|
1662 | [metric release]; |
---|
1663 | [container release]; |
---|
1664 | FreeResolveStatsList(domainList); |
---|
1665 | FreeResolveStatsServerList(serverList); |
---|
1666 | return (err); |
---|
1667 | } |
---|
1668 | |
---|
1669 | //=========================================================================================================================== |
---|
1670 | // CreateAWDDNSDomainStats |
---|
1671 | //=========================================================================================================================== |
---|
1672 | |
---|
1673 | mDNSlocal mStatus CreateAWDDNSDomainStats(DNSHist *inHist, const char *inDomain, mDNSBool inForCell, AWDDNSDomainStats_RecordType inType, AWDDNSDomainStats **outStats) |
---|
1674 | { |
---|
1675 | mStatus err; |
---|
1676 | AWDDNSDomainStats * awdStats = nil; |
---|
1677 | NSString * domain = nil; |
---|
1678 | uint32_t sendCountBins[kQueryStatsSendCountBinCount]; |
---|
1679 | uint32_t latencyBins[kQueryStatsLatencyBinCount]; |
---|
1680 | int i; |
---|
1681 | unsigned int totalAnswered; |
---|
1682 | unsigned int totalNegAnswered; |
---|
1683 | unsigned int totalUnanswered; |
---|
1684 | |
---|
1685 | awdStats = [[AWDDNSDomainStatsSoft alloc] init]; |
---|
1686 | require_action_quiet(awdStats, exit, err = mStatus_UnknownErr); |
---|
1687 | |
---|
1688 | domain = [[NSString alloc] initWithUTF8String:inDomain]; |
---|
1689 | require_action_quiet(domain, exit, err = mStatus_UnknownErr); |
---|
1690 | |
---|
1691 | awdStats.domain = domain; |
---|
1692 | awdStats.networkType = inForCell ? AWDDNSDomainStats_NetworkType_Cellular : AWDDNSDomainStats_NetworkType_NonCellular; |
---|
1693 | awdStats.recordType = inType; |
---|
1694 | |
---|
1695 | totalAnswered = 0; |
---|
1696 | for (i = 0; i < kQueryStatsSendCountBinCount; ++i) |
---|
1697 | { |
---|
1698 | sendCountBins[i] = inHist->answeredQuerySendCountBins[i]; |
---|
1699 | totalAnswered += inHist->answeredQuerySendCountBins[i]; |
---|
1700 | } |
---|
1701 | [awdStats setAnsweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount]; |
---|
1702 | |
---|
1703 | totalNegAnswered = 0; |
---|
1704 | for (i = 0; i < kQueryStatsSendCountBinCount; ++i) |
---|
1705 | { |
---|
1706 | sendCountBins[i] = inHist->negAnsweredQuerySendCountBins[i]; |
---|
1707 | totalNegAnswered += inHist->negAnsweredQuerySendCountBins[i]; |
---|
1708 | } |
---|
1709 | [awdStats setNegAnsweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount]; |
---|
1710 | |
---|
1711 | totalUnanswered = 0; |
---|
1712 | for (i = 0; i < kQueryStatsSendCountBinCount; ++i) |
---|
1713 | { |
---|
1714 | sendCountBins[i] = inHist->unansweredQuerySendCountBins[i]; |
---|
1715 | totalUnanswered += inHist->unansweredQuerySendCountBins[i]; |
---|
1716 | } |
---|
1717 | [awdStats setUnansweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount]; |
---|
1718 | |
---|
1719 | if (totalAnswered > inHist->answeredQuerySendCountBins[0]) |
---|
1720 | { |
---|
1721 | for (i = 0; i < kQueryStatsLatencyBinCount; ++i) |
---|
1722 | { |
---|
1723 | latencyBins[i] = inHist->responseLatencyBins[i]; |
---|
1724 | } |
---|
1725 | [awdStats setResponseLatencyMs:latencyBins count:kQueryStatsLatencyBinCount]; |
---|
1726 | } |
---|
1727 | |
---|
1728 | if (totalNegAnswered > inHist->negAnsweredQuerySendCountBins[0]) |
---|
1729 | { |
---|
1730 | for (i = 0; i < kQueryStatsLatencyBinCount; ++i) |
---|
1731 | { |
---|
1732 | latencyBins[i] = inHist->negResponseLatencyBins[i]; |
---|
1733 | } |
---|
1734 | [awdStats setNegResponseLatencyMs:latencyBins count:kQueryStatsLatencyBinCount]; |
---|
1735 | } |
---|
1736 | |
---|
1737 | if (totalUnanswered > 0) |
---|
1738 | { |
---|
1739 | for (i = 0; i < kQueryStatsLatencyBinCount; ++i) |
---|
1740 | { |
---|
1741 | latencyBins[i] = inHist->unansweredQueryDurationBins[i]; |
---|
1742 | } |
---|
1743 | [awdStats setUnansweredQueryDurationMs:latencyBins count:kQueryStatsLatencyBinCount]; |
---|
1744 | } |
---|
1745 | |
---|
1746 | *outStats = awdStats; |
---|
1747 | awdStats = nil; |
---|
1748 | err = mStatus_NoError; |
---|
1749 | |
---|
1750 | exit: |
---|
1751 | [domain release]; |
---|
1752 | [awdStats release]; |
---|
1753 | return (err); |
---|
1754 | } |
---|
1755 | |
---|
1756 | //=========================================================================================================================== |
---|
1757 | // AddAWDDNSDomainStats |
---|
1758 | //=========================================================================================================================== |
---|
1759 | |
---|
1760 | mDNSlocal mStatus AddAWDDNSDomainStats(AWDMDNSResponderDNSStatistics *inMetric, DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell) |
---|
1761 | { |
---|
1762 | mStatus err; |
---|
1763 | AWDDNSDomainStats * awdStats; |
---|
1764 | |
---|
1765 | if (inSet->histAny) |
---|
1766 | { |
---|
1767 | err = CreateAWDDNSDomainStats(inSet->histAny, inDomain, inForCell, AWDDNSDomainStats_RecordType_Any, &awdStats); |
---|
1768 | require_noerr_quiet(err, exit); |
---|
1769 | |
---|
1770 | [inMetric addStats:awdStats]; |
---|
1771 | [awdStats release]; |
---|
1772 | } |
---|
1773 | if (inSet->histA) |
---|
1774 | { |
---|
1775 | err = CreateAWDDNSDomainStats(inSet->histA, inDomain, inForCell, AWDDNSDomainStats_RecordType_A, &awdStats); |
---|
1776 | require_noerr_quiet(err, exit); |
---|
1777 | |
---|
1778 | [inMetric addStats:awdStats]; |
---|
1779 | [awdStats release]; |
---|
1780 | } |
---|
1781 | if (inSet->histAAAA) |
---|
1782 | { |
---|
1783 | err = CreateAWDDNSDomainStats(inSet->histAAAA, inDomain, inForCell, AWDDNSDomainStats_RecordType_AAAA, &awdStats); |
---|
1784 | require_noerr_quiet(err, exit); |
---|
1785 | |
---|
1786 | [inMetric addStats:awdStats]; |
---|
1787 | [awdStats release]; |
---|
1788 | } |
---|
1789 | err = mStatus_NoError; |
---|
1790 | |
---|
1791 | exit: |
---|
1792 | return (err); |
---|
1793 | } |
---|
1794 | |
---|
1795 | //=========================================================================================================================== |
---|
1796 | // LogDNSHistSet |
---|
1797 | //=========================================================================================================================== |
---|
1798 | |
---|
1799 | mDNSlocal void LogDNSHistSet(const DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell) |
---|
1800 | { |
---|
1801 | if (inSet->histAny) LogDNSHist(inSet->histAny, inDomain, inForCell, "Any"); |
---|
1802 | if (inSet->histA) LogDNSHist(inSet->histA, inDomain, inForCell, "A"); |
---|
1803 | if (inSet->histAAAA) LogDNSHist(inSet->histAAAA, inDomain, inForCell, "AAAA"); |
---|
1804 | } |
---|
1805 | |
---|
1806 | //=========================================================================================================================== |
---|
1807 | // LogDNSHist |
---|
1808 | //=========================================================================================================================== |
---|
1809 | |
---|
1810 | #define Percent(N, D) ((N) * 100) / (D), (((N) * 10000) / (D)) % 100 |
---|
1811 | #define PercentFmt "%3u.%02u" |
---|
1812 | #define LogStat(LABEL, COUNT, ACCUMULATOR, TOTAL) \ |
---|
1813 | LogMsgNoIdent("%s %5u " PercentFmt " " PercentFmt, (LABEL), (COUNT), Percent(COUNT, TOTAL), Percent(ACCUMULATOR, TOTAL)) |
---|
1814 | |
---|
1815 | mDNSlocal void LogDNSHist(const DNSHist *inHist, const char *inDomain, mDNSBool inForCell, const char *inType) |
---|
1816 | { |
---|
1817 | unsigned int totalAnswered; |
---|
1818 | unsigned int totalNegAnswered; |
---|
1819 | unsigned int totalUnanswered; |
---|
1820 | int i; |
---|
1821 | |
---|
1822 | totalAnswered = 0; |
---|
1823 | for (i = 0; i < kQueryStatsSendCountBinCount; ++i) |
---|
1824 | { |
---|
1825 | totalAnswered += inHist->answeredQuerySendCountBins[i]; |
---|
1826 | } |
---|
1827 | |
---|
1828 | totalNegAnswered = 0; |
---|
1829 | for (i = 0; i < kQueryStatsSendCountBinCount; ++i) |
---|
1830 | { |
---|
1831 | totalNegAnswered += inHist->negAnsweredQuerySendCountBins[i]; |
---|
1832 | } |
---|
1833 | |
---|
1834 | totalUnanswered = 0; |
---|
1835 | for (i = 0; i < kQueryStatsSendCountBinCount; ++i) |
---|
1836 | { |
---|
1837 | totalUnanswered += inHist->unansweredQuerySendCountBins[i]; |
---|
1838 | } |
---|
1839 | |
---|
1840 | LogMsgNoIdent("Domain: %s (%s, %s)", inDomain, inForCell ? "C" : "NC", inType); |
---|
1841 | LogMsgNoIdent("Answered questions %4u", totalAnswered); |
---|
1842 | LogMsgNoIdent("Negatively answered questions %4u", totalNegAnswered); |
---|
1843 | LogMsgNoIdent("Unanswered questions %4u", totalUnanswered); |
---|
1844 | LogMsgNoIdent("-- Query send counts ---------"); |
---|
1845 | LogDNSHistSendCounts(inHist->answeredQuerySendCountBins); |
---|
1846 | LogMsgNoIdent("-- Query send counts (NAQs) --"); |
---|
1847 | LogDNSHistSendCounts(inHist->negAnsweredQuerySendCountBins); |
---|
1848 | |
---|
1849 | if (totalAnswered > inHist->answeredQuerySendCountBins[0]) |
---|
1850 | { |
---|
1851 | LogMsgNoIdent("--- Response times -----------"); |
---|
1852 | LogDNSHistLatencies(inHist->responseLatencyBins); |
---|
1853 | } |
---|
1854 | |
---|
1855 | if (totalNegAnswered > inHist->negAnsweredQuerySendCountBins[0]) |
---|
1856 | { |
---|
1857 | LogMsgNoIdent("--- Response times (NAQs) ----"); |
---|
1858 | LogDNSHistLatencies(inHist->negResponseLatencyBins); |
---|
1859 | } |
---|
1860 | |
---|
1861 | if (totalUnanswered > 0) |
---|
1862 | { |
---|
1863 | LogMsgNoIdent("--- Unanswered query times ---"); |
---|
1864 | LogDNSHistLatencies(inHist->unansweredQueryDurationBins); |
---|
1865 | } |
---|
1866 | } |
---|
1867 | |
---|
1868 | //=========================================================================================================================== |
---|
1869 | // LogDNSHistSendCounts |
---|
1870 | //=========================================================================================================================== |
---|
1871 | |
---|
1872 | mDNSlocal void LogDNSHistSendCounts(const uint16_t inSendCountBins[kQueryStatsSendCountBinCount]) |
---|
1873 | { |
---|
1874 | uint32_t total; |
---|
1875 | char label[16]; |
---|
1876 | int i; |
---|
1877 | |
---|
1878 | total = 0; |
---|
1879 | for (i = 0; i < kQueryStatsSendCountBinCount; ++i) |
---|
1880 | { |
---|
1881 | total += inSendCountBins[i]; |
---|
1882 | } |
---|
1883 | |
---|
1884 | if (total > 0) |
---|
1885 | { |
---|
1886 | uint32_t accumulator = 0; |
---|
1887 | |
---|
1888 | for (i = 0; i < kQueryStatsSendCountBinCount; ++i) |
---|
1889 | { |
---|
1890 | accumulator += inSendCountBins[i]; |
---|
1891 | if (i < (kQueryStatsSendCountBinCount - 1)) |
---|
1892 | { |
---|
1893 | snprintf(label, sizeof(label), "%2d ", i); |
---|
1894 | } |
---|
1895 | else |
---|
1896 | { |
---|
1897 | snprintf(label, sizeof(label), "%2d+", i); |
---|
1898 | } |
---|
1899 | LogStat(label, inSendCountBins[i], accumulator, total); |
---|
1900 | if (accumulator == total) break; |
---|
1901 | } |
---|
1902 | } |
---|
1903 | else |
---|
1904 | { |
---|
1905 | LogMsgNoIdent("No data."); |
---|
1906 | } |
---|
1907 | } |
---|
1908 | |
---|
1909 | //=========================================================================================================================== |
---|
1910 | // LogDNSHistLatencies |
---|
1911 | //=========================================================================================================================== |
---|
1912 | |
---|
1913 | mDNSlocal void LogDNSHistLatencies(const uint16_t inLatencyBins[kQueryStatsLatencyBinCount]) |
---|
1914 | { |
---|
1915 | uint32_t total; |
---|
1916 | int i; |
---|
1917 | char label[16]; |
---|
1918 | |
---|
1919 | total = 0; |
---|
1920 | for (i = 0; i < kQueryStatsLatencyBinCount; ++i) |
---|
1921 | { |
---|
1922 | total += inLatencyBins[i]; |
---|
1923 | } |
---|
1924 | |
---|
1925 | if (total > 0) |
---|
1926 | { |
---|
1927 | uint32_t accumulator = 0; |
---|
1928 | |
---|
1929 | for (i = 0; i < kQueryStatsLatencyBinCount; ++i) |
---|
1930 | { |
---|
1931 | accumulator += inLatencyBins[i]; |
---|
1932 | if (i < (int)countof(kResponseLatencyMsLimits)) |
---|
1933 | { |
---|
1934 | snprintf(label, sizeof(label), "< %5u ms", kResponseLatencyMsLimits[i]); |
---|
1935 | } |
---|
1936 | else |
---|
1937 | { |
---|
1938 | snprintf(label, sizeof(label), "< â ms"); |
---|
1939 | } |
---|
1940 | LogStat(label, inLatencyBins[i], accumulator, total); |
---|
1941 | if (accumulator == total) break; |
---|
1942 | } |
---|
1943 | } |
---|
1944 | else |
---|
1945 | { |
---|
1946 | LogMsgNoIdent("No data."); |
---|
1947 | } |
---|
1948 | } |
---|
1949 | |
---|
1950 | //=========================================================================================================================== |
---|
1951 | // ValidateDNSStatsDomains |
---|
1952 | //=========================================================================================================================== |
---|
1953 | |
---|
1954 | #if (METRICS_VALIDATE_DNS_STATS_DOMAINS) |
---|
1955 | #warning "Do not include ValidateDNSStatsDomains() in customer release!" |
---|
1956 | mDNSlocal void ValidateDNSStatsDomains(void) |
---|
1957 | { |
---|
1958 | int i; |
---|
1959 | const Domain * domain; |
---|
1960 | mDNSu8 * ptr; |
---|
1961 | domainname domainNameExpected; |
---|
1962 | int labelCountExpected; |
---|
1963 | mDNSBool domainNamesEqual; |
---|
1964 | mDNSBool failed = mDNSfalse; |
---|
1965 | |
---|
1966 | for (i = 0; i < countof(kQueryStatsDomains); ++i) |
---|
1967 | { |
---|
1968 | domain = &kQueryStatsDomains[i]; |
---|
1969 | |
---|
1970 | if (strcmp(domain->cstr, ".") == 0) |
---|
1971 | { |
---|
1972 | domainNameExpected.c[0] = 0; |
---|
1973 | } |
---|
1974 | else |
---|
1975 | { |
---|
1976 | ptr = MakeDomainNameFromDNSNameString(&domainNameExpected, domain->cstr); |
---|
1977 | if (!ptr) |
---|
1978 | { |
---|
1979 | LogMsg("ValidateDNSStatsDomains: Failed to make domain name for \"%s\".", domain->cstr); |
---|
1980 | failed = mDNStrue; |
---|
1981 | goto exit; |
---|
1982 | } |
---|
1983 | } |
---|
1984 | |
---|
1985 | domainNamesEqual = SameDomainName(domain->name, &domainNameExpected); |
---|
1986 | labelCountExpected = CountLabels(&domainNameExpected); |
---|
1987 | if (domainNamesEqual && (domain->labelCount == labelCountExpected)) |
---|
1988 | { |
---|
1989 | LogMsg("ValidateDNSStatsDomains: \"%s\" passed.", domain->cstr); |
---|
1990 | } |
---|
1991 | else |
---|
1992 | { |
---|
1993 | if (!domainNamesEqual) |
---|
1994 | { |
---|
1995 | LogMsg("ValidateDNSStatsDomains: \"%s\" failed: incorrect domain name.", domain->cstr); |
---|
1996 | } |
---|
1997 | if (domain->labelCount != labelCountExpected) |
---|
1998 | { |
---|
1999 | LogMsg("ValidateDNSStatsDomains: \"%s\" failed: incorrect label count. Actual %d, expected %d.", |
---|
2000 | domain->cstr, domain->labelCount, labelCountExpected); |
---|
2001 | } |
---|
2002 | failed = mDNStrue; |
---|
2003 | } |
---|
2004 | } |
---|
2005 | |
---|
2006 | exit: |
---|
2007 | if (failed) abort(); |
---|
2008 | } |
---|
2009 | #endif |
---|
2010 | #endif // TARGET_OS_EMBEDDED |
---|