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