xref: /netbsd-src/external/apache2/mDNSResponder/dist/mDNSCore/mDNS.c (revision dd255ccea4286b0c44fa8fd48a9a19a768afe8e1)
1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * This code is completely 100% portable C. It does not depend on any external header files
18  * from outside the mDNS project -- all the types it expects to find are defined right here.
19  *
20  * The previous point is very important: This file does not depend on any external
21  * header files. It should compile on *any* platform that has a C compiler, without
22  * making *any* assumptions about availability of so-called "standard" C functions,
23  * routines, or types (which may or may not be present on any given platform).
24 
25  * Formatting notes:
26  * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion
27  * on C indentation can be found on the web, such as <http://www.kafejo.com/komp/1tbs.htm>,
28  * but for the sake of brevity here I will say just this: Curly braces are not syntactially
29  * part of an "if" statement; they are the beginning and ending markers of a compound statement;
30  * therefore common sense dictates that if they are part of a compound statement then they
31  * should be indented to the same level as everything else in that compound statement.
32  * Indenting curly braces at the same level as the "if" implies that curly braces are
33  * part of the "if", which is false. (This is as misleading as people who write "char* x,y;"
34  * thinking that variables x and y are both of type "char*" -- and anyone who doesn't
35  * understand why variable y is not of type "char*" just proves the point that poor code
36  * layout leads people to unfortunate misunderstandings about how the C language really works.)
37 
38     Change History (most recent first):
39 
40 Log: mDNS.c,v $
41 Revision 1.969.2.1  2009/07/23 23:41:25  cheshire
42 <rdar://problem/7086623> Sleep Proxy: Ten-second maintenance wake not long enough to reliably get network connectivity
43 
44 Revision 1.969  2009/06/30 21:18:19  cheshire
45 <rdar://problem/7020041> Plugging and unplugging the power cable shouldn't cause a network change event
46 Additional fixes:
47 1. Made mDNS_ActivateNetWake_internal and mDNS_DeactivateNetWake_internal more defensive against bad parameters
48 2. mDNS_DeactivateNetWake_internal also needs to stop any outstanding Sleep Proxy resolve operations
49 
50 Revision 1.968  2009/06/29 23:51:09  cheshire
51 <rdar://problem/6690034> Can't bind to Active Directory
52 
53 Revision 1.967  2009/06/27 00:25:27  cheshire
54 <rdar://problem/6959273> mDNSResponder taking up 13% CPU with 400 KBps incoming bonjour requests
55 Removed overly-complicate and ineffective multi-packet known-answer snooping code
56 (Bracketed it with "#if ENABLE_MULTI_PACKET_QUERY_SNOOPING" for now; will delete actual code later)
57 
58 Revision 1.966  2009/06/26 01:55:55  cheshire
59 <rdar://problem/6890712> mDNS: iChat's Buddy photo always appears as the "shadow person" over Bonjour
60 Additional refinements -- except for the case of explicit queries for record types we don't have (for names we own),
61 add additional NSEC records only when there's space to do that without having to generate an additional packet
62 
63 Revision 1.965  2009/06/24 22:14:21  cheshire
64 <rdar://problem/6911445> Plugging and unplugging the power cable shouldn't cause a network change event
65 
66 Revision 1.964  2009/06/03 23:07:13  cheshire
67 <rdar://problem/6890712> mDNS: iChat's Buddy photo always appears as the "shadow person" over Bonjour
68 Large records were not being added in cases where an NSEC record was also required
69 
70 Revision 1.963  2009/05/28 00:39:19  cheshire
71 <rdar://problem/6926465> Sleep is delayed by 10 seconds if BTMM is on
72 After receiving confirmation of wide-area record deletion, need to schedule another evaluation of whether we're ready to sleep yet
73 
74 Revision 1.962  2009/05/19 23:40:37  cheshire
75 <rdar://problem/6903507> Sleep Proxy: Retransmission logic not working reliably on quiet networks
76 Added m->NextScheduledSPRetry timer for scheduling Sleep Proxy registration retries
77 
78 Revision 1.961  2009/05/19 23:00:43  cheshire
79 Improved comments and debugging messages
80 
81 Revision 1.960  2009/05/13 17:25:33  mkrochma
82 <rdar://problem/6879926> Should not schedule maintenance wake when machine has no advertised services
83 Sleep proxy client should only look for services being advertised via Multicast
84 
85 Revision 1.959  2009/05/12 23:10:31  cheshire
86 <rdar://problem/6879926> Should not schedule maintenance wake when machine has no advertised services
87 Make new routine mDNSCoreHaveAdvertisedServices so daemon.c can tell whether it needs to schedule a maintenance wake
88 
89 Revision 1.958  2009/05/12 19:19:20  cheshire
90 <rdar://problem/6879925> Sleep Proxy delays sleep by ten seconds when logged in to VPN
91 
92 Revision 1.957  2009/05/07 23:56:25  cheshire
93 <rdar://problem/6601427> Retransmit and retry Sleep Proxy Server requests
94 To get negative answers for our AAAA query we need to set the ReturnIntermed flag on the NetWakeResolve question
95 
96 Revision 1.956  2009/05/07 23:46:27  cheshire
97 <rdar://problem/6601427> Retransmit and retry Sleep Proxy Server requests
98 
99 Revision 1.955  2009/05/07 23:40:54  cheshire
100 Minor code rearrangement in preparation for upcoming changes
101 
102 Revision 1.954  2009/05/01 21:28:34  cheshire
103 <rdar://problem/6721680> AppleConnectAgent's reachability checks delay sleep by 30 seconds
104 No longer suspend network operations after we've acknowledged that the machine is going to sleep,
105 because other software may not have yet acknowledged the sleep event, and may be still trying
106 to do unicast DNS queries or other Bonjour operations.
107 
108 Revision 1.953  2009/05/01 19:17:35  cheshire
109 <rdar://problem/6501561> Sleep Proxy: Reduce the frequency of maintenance wakes: ODD, fans, power
110 
111 Revision 1.952  2009/05/01 19:16:45  mcguire
112 <rdar://problem/6846322> Crash: mDNS_vsnprintf + 1844
113 
114 Revision 1.951  2009/04/28 23:48:19  jessic2
115 <rdar://problem/6830541> regservice_callback: instance->request is NULL 0
116 
117 Revision 1.950  2009/04/25 01:17:10  mcguire
118 Fix spurious TCP connect failures uncovered by <rdar://problem/6729406> PPP doesn't automatically reconnect on wake from sleep
119 
120 Revision 1.949  2009/04/25 01:11:02  mcguire
121 Refactor: create separate function: RestartRecordGetZoneData
122 
123 Revision 1.948  2009/04/24 21:25:16  cheshire
124 <rdar://problem/6601002> Special case Net Assistant port so Apple Remote Desktop doesn't wake up every machine on the network
125 
126 Revision 1.947  2009/04/24 19:41:12  mcguire
127 <rdar://problem/6791775> 4 second delay in DNS response
128 
129 Revision 1.946  2009/04/24 19:28:39  mcguire
130 <rdar://problem/6791775> 4 second delay in DNS response
131 
132 Revision 1.945  2009/04/24 00:30:30  cheshire
133 <rdar://problem/3476350> Return negative answers when host knows authoritatively that no answer exists
134 Added code to generate and process NSEC records
135 
136 Revision 1.944  2009/04/23 22:06:29  cheshire
137 Added CacheRecord and InterfaceID parameters to MakeNegativeCacheRecord, in preparation for:
138 <rdar://problem/3476350> Return negative answers when host knows authoritatively that no answer exists
139 
140 Revision 1.943  2009/04/22 01:19:56  jessic2
141 <rdar://problem/6814585> Daemon: mDNSResponder is logging garbage for error codes because it's using %ld for int 32
142 
143 Revision 1.942  2009/04/21 02:13:29  cheshire
144 <rdar://problem/5270176> Local hostname changed even though there really isn't a name conflict
145 Made code less susceptible to being tricked by stale packets echoed back from the network.
146 
147 Revision 1.941  2009/04/15 22:22:23  mcguire
148 <rdar://problem/6768947> uDNS: Treat RCODE 5 (Refused) responses as failures
149 Additional fix: protect against deref of NULL
150 
151 Revision 1.940  2009/04/15 20:42:51  mcguire
152 <rdar://problem/6768947> uDNS: Treat RCODE 5 (Refused) responses as failures
153 
154 Revision 1.939  2009/04/11 00:19:32  jessic2
155 <rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
156 
157 Revision 1.938  2009/04/06 23:44:57  cheshire
158 <rdar://problem/6757838> mDNSResponder thrashing kernel lock in the UDP close path, hurting SPECweb performance
159 
160 Revision 1.937  2009/04/04 00:14:49  mcguire
161 fix logging in BeginSleepProcessing
162 
163 Revision 1.936  2009/04/04 00:10:59  mcguire
164 don't ignore m->SystemWakeOnLANEnabled when going to sleep
165 
166 Revision 1.935  2009/04/01 17:50:11  mcguire
167 cleanup mDNSRandom
168 
169 Revision 1.934  2009/03/27 17:17:58  cheshire
170 Improved "Ignoring suspect uDNS response" debugging message
171 
172 Revision 1.933  2009/03/21 02:40:21  cheshire
173 <rdar://problem/6704514> uDNS: Need to create negative cache entries for "local" SOA
174 
175 Revision 1.932  2009/03/20 23:53:03  jessic2
176 <rdar://problem/6646228> SIGHUP should restart all in-progress queries
177 
178 Revision 1.931  2009/03/18 19:08:15  cheshire
179 Show old/new sleep sequence numbers in logical order
180 
181 Revision 1.930  2009/03/17 23:40:45  cheshire
182 For now only try the highest-ranked Sleep Proxy; fixed come compiler warnings
183 
184 Revision 1.929  2009/03/17 21:55:56  cheshire
185 Fixed mistake in logic for decided when we're ready to go to sleep
186 
187 Revision 1.928  2009/03/17 19:48:12  cheshire
188 <rdar://problem/6688927> Don't cache negative unicast answers for Multicast DNS names
189 
190 Revision 1.927  2009/03/17 01:22:56  cheshire
191 <rdar://problem/6601427> Sleep Proxy: Retransmit and retry Sleep Proxy Server requests
192 Initial support for resolving up to three Sleep Proxies in parallel
193 
194 Revision 1.926  2009/03/17 01:05:07  mcguire
195 <rdar://problem/6657640> Reachability fixes on DNS config change
196 
197 Revision 1.925  2009/03/13 01:35:36  mcguire
198 <rdar://problem/6657640> Reachability fixes on DNS config change
199 
200 Revision 1.924  2009/03/10 23:45:20  cheshire
201 Added comments explaining usage of SetSPSProxyListChanged()
202 
203 Revision 1.923  2009/03/09 21:53:02  cheshire
204 <rdar://problem/6650479> Sleep Proxy: Need to stop proxying when it sees an ARP probe from the client
205 
206 Revision 1.922  2009/03/09 21:30:17  cheshire
207 Improved some LogSPS messages; made RestartProbing() subroutine
208 
209 Revision 1.921  2009/03/06 22:53:31  cheshire
210 Don't bother registering with Sleep Proxy if we have no advertised services
211 
212 Revision 1.920  2009/03/06 20:08:55  cheshire
213 <rdar://problem/6601429> Sleep Proxy: Return error responses to clients
214 
215 Revision 1.919  2009/03/05 21:54:43  cheshire
216 Improved "Sleep Proxy Server started / stopped" message
217 
218 Revision 1.918  2009/03/04 01:37:14  cheshire
219 <rdar://problem/6601428> Limit maximum number of records that a Sleep Proxy Server will accept
220 
221 Revision 1.917  2009/03/03 23:14:25  cheshire
222 Got rid of code duplication by making subroutine "SetupOwnerOpt"
223 
224 Revision 1.916  2009/03/03 23:04:43  cheshire
225 For clarity, renamed "MAC" field to "HMAC" (Host MAC, as opposed to Interface MAC)
226 
227 Revision 1.915  2009/03/03 22:51:53  cheshire
228 <rdar://problem/6504236> Sleep Proxy: Waking on same network but different interface will cause conflicts
229 
230 Revision 1.914  2009/03/03 00:46:09  cheshire
231 Additional debugging information in ResolveSimultaneousProbe
232 
233 Revision 1.913  2009/02/27 03:08:47  cheshire
234 <rdar://problem/6547720> Crash while shutting down when "local" is in the user's DNS searchlist
235 
236 Revision 1.912  2009/02/27 02:31:28  cheshire
237 Improved "Record not found in list" debugging message
238 
239 Revision 1.911  2009/02/21 01:42:11  cheshire
240 Updated log messages
241 
242 Revision 1.910  2009/02/19 01:50:53  cheshire
243 Converted some LogInfo messages to LogSPS
244 
245 Revision 1.909  2009/02/14 00:04:59  cheshire
246 Left-justify interface names
247 
248 Revision 1.908  2009/02/13 19:40:07  cheshire
249 Improved alignment of LogSPS messages
250 
251 Revision 1.907  2009/02/13 18:16:05  cheshire
252 Fixed some compile warnings
253 
254 Revision 1.906  2009/02/13 06:10:17  cheshire
255 Convert LogOperation messages to LogInfo
256 
257 Revision 1.905  2009/02/12 20:57:24  cheshire
258 Renamed 'LogAllOperation' switch to 'LogClientOperations'; added new 'LogSleepProxyActions' switch
259 
260 Revision 1.904  2009/02/11 02:37:29  cheshire
261 m->p->SystemWakeForNetworkAccessEnabled renamed to m->SystemWakeOnLANEnabled
262 Moved code to send goodbye packets from mDNSCoreMachineSleep into BeginSleepProcessing,
263 so that it happens correctly even when we delay re-sleep due to a very short wakeup.
264 
265 Revision 1.903  2009/02/09 23:34:31  cheshire
266 Additional logging for debugging unknown packets
267 
268 Revision 1.902  2009/02/07 05:57:01  cheshire
269 Fixed debugging log message
270 
271 Revision 1.901  2009/02/07 02:57:31  cheshire
272 <rdar://problem/6084043> Sleep Proxy: Need to adopt IOPMConnection
273 
274 Revision 1.900  2009/02/02 21:29:24  cheshire
275 <rdar://problem/4786302> Implement logic to determine when to send dot-local lookups via Unicast
276 If Negative response for our special Microsoft Active Directory "local SOA" check has no
277 SOA record in the authority section, assume we should cache the negative result for 24 hours
278 
279 Revision 1.899  2009/01/31 00:37:50  cheshire
280 When marking cache records for deletion in response to a uDNS response,
281 make sure InterfaceID matches (i.e. it should be NULL for a uDNS cache record)
282 
283 Revision 1.898  2009/01/30 23:49:20  cheshire
284 Exclude mDNSInterface_Unicast from "InterfaceID ... not currently found" test
285 
286 Revision 1.897  2009/01/30 22:04:49  cheshire
287 Workaround to reduce load on root name servers when caching the SOA record for "."
288 
289 Revision 1.896  2009/01/30 22:00:05  cheshire
290 Made mDNS_StartQuery_internal pay attention to mDNSInterface_Unicast
291 
292 Revision 1.895  2009/01/30 17:46:39  cheshire
293 Improved debugging messages for working out why spurious name conflicts are happening
294 
295 Revision 1.894  2009/01/30 00:22:09  cheshire
296 <rdar://problem/6540743> No announcement after probing & no conflict notice
297 
298 Revision 1.893  2009/01/29 22:27:03  mcguire
299 <rdar://problem/6407429> Cleanup: Logs about Unknown DNS packet type 5450
300 
301 Revision 1.892  2009/01/24 01:38:23  cheshire
302 Fixed error in logic for targeted queries
303 
304 Revision 1.891  2009/01/22 02:14:25  cheshire
305 <rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
306 
307 Revision 1.890  2009/01/22 00:45:02  cheshire
308 Improved SPS debugging log messages; we are eligible to start answering ARP requests
309 after we send our first announcement, not after we send our last probe
310 
311 Revision 1.889  2009/01/21 03:43:56  mcguire
312 <rdar://problem/6511765> BTMM: Add support for setting kDNSServiceErr_NATPortMappingDisabled in DynamicStore
313 
314 Revision 1.888  2009/01/20 00:27:43  mcguire
315 <rdar://problem/6305725> when removing a uDNS record, if a dup exists, copy information to it
316 
317 Revision 1.887  2009/01/17 05:14:37  cheshire
318 Convert SendQueries Probe messages to LogSPS messages
319 
320 Revision 1.886  2009/01/17 03:43:09  cheshire
321 Added SPSLogging switch to facilitate Sleep Proxy Server debugging
322 
323 Revision 1.885  2009/01/16 22:44:18  cheshire
324 <rdar://problem/6402123> Sleep Proxy: Begin ARP Announcements sooner
325 
326 Revision 1.884  2009/01/16 21:43:52  cheshire
327 Let InitializeLastAPTime compute the correct interval, instead of having it passed in as a parameter
328 
329 Revision 1.883  2009/01/16 21:11:18  cheshire
330 When purging expired Sleep Proxy records, need to check DuplicateRecords list too
331 
332 Revision 1.882  2009/01/16 19:54:28  cheshire
333 Use symbols "SleepProxyServiceType" and "localdomain" instead of literal strings
334 
335 Revision 1.881  2009/01/14 01:38:38  mcguire
336 <rdar://problem/6492710> Write out DynamicStore per-interface SleepProxyServer info
337 
338 Revision 1.880  2009/01/10 01:51:19  cheshire
339 q->CurrentAnswers not being incremented/decremented when answering a question with a local AuthRecord
340 
341 Revision 1.879  2009/01/10 01:43:52  cheshire
342 Changed misleading function name 'AnsweredLOQ' to more informative 'AnsweredLocalQ'
343 
344 Revision 1.878  2009/01/10 01:38:10  cheshire
345 Changed misleading function name 'AnswerLocalOnlyQuestionWithResourceRecord' to more informative 'AnswerLocalQuestionWithLocalAuthRecord'
346 
347 Revision 1.877  2009/01/10 01:36:08  cheshire
348 Changed misleading function name 'AnswerLocalOnlyQuestions' to more informative 'AnswerAllLocalQuestionsWithLocalAuthRecord'
349 
350 Revision 1.876  2009/01/09 22:56:06  cheshire
351 Don't touch rr after calling mDNS_Deregister_internal -- the memory may have been free'd
352 
353 Revision 1.875  2009/01/09 22:54:46  cheshire
354 When tranferring record from DuplicateRecords list to ResourceRecords list,
355 need to copy across state of 'Answered Local-Only-Questions' flag
356 
357 Revision 1.874  2009/01/07 23:07:24  cheshire
358 <rdar://problem/6479416> SPS Client not canceling outstanding resolve call before sleeping
359 
360 Revision 1.873  2008/12/17 00:18:59  mkrochma
361 Change some LogMsg to LogOperation before submitting
362 
363 Revision 1.872  2008/12/12 01:30:40  cheshire
364 Update platform-layer BPF filters when we add or remove AddressProxy records
365 
366 Revision 1.871  2008/12/10 02:25:31  cheshire
367 Minor fixes to use of LogClientOperations symbol
368 
369 Revision 1.870  2008/12/10 02:11:41  cheshire
370 ARMv5 compiler doesn't like uncommented stuff after #endif
371 
372 Revision 1.869  2008/12/05 02:35:24  mcguire
373 <rdar://problem/6107390> Write to the DynamicStore when a Sleep Proxy server is available on the network
374 
375 Revision 1.868  2008/12/04 21:08:51  mcguire
376 <rdar://problem/6116863> mDNS: Provide mechanism to disable Multicast advertisements
377 
378 Revision 1.867  2008/11/26 21:19:36  cheshire
379 <rdar://problem/6374334> Sleeping Server should choose the best Sleep Proxy by using advertised metrics
380 
381 Revision 1.866  2008/11/26 20:32:46  cheshire
382 <rdar://problem/6374328> Sleep Proxy: Advertise BSP metrics in service name
383 Update advertised name when Sleep Proxy "intent" metric changes
384 
385 Revision 1.865  2008/11/26 19:49:25  cheshire
386 Record originally-requested port in sr->NATinfo.IntPort
387 
388 Revision 1.864  2008/11/26 19:02:37  cheshire
389 Don't answer ARP Probes from owner machine as it wakes up and rejoins the network
390 
391 Revision 1.863  2008/11/26 03:59:03  cheshire
392 Wait 30 seconds before starting ARP Announcements
393 
394 Revision 1.862  2008/11/25 23:43:07  cheshire
395 <rdar://problem/5745355> Crashes at ServiceRegistrationGotZoneData + 397
396 Made code more defensive to guard against ServiceRegistrationGotZoneData being called with invalid ServiceRecordSet object
397 
398 Revision 1.861  2008/11/25 22:46:30  cheshire
399 For ease of code searching, renamed ZoneData field of ServiceRecordSet_struct from "nta" to "srs_nta"
400 
401 Revision 1.860  2008/11/25 05:07:15  cheshire
402 <rdar://problem/6374328> Advertise Sleep Proxy metrics in service name
403 
404 Revision 1.859  2008/11/20 02:07:56  cheshire
405 <rdar://problem/6387470> Refresh our NAT mappings on wake from sleep
406 
407 Revision 1.858  2008/11/20 01:38:36  cheshire
408 For consistency with other parts of the code, changed code to only check
409 that the first 4 bytes of MAC address are zero, not the whole 6 bytes.
410 
411 Revision 1.857  2008/11/14 22:55:18  cheshire
412 Fixed log messages
413 
414 Revision 1.856  2008/11/14 21:08:28  cheshire
415 Only put owner option in query packet if we have a non-zero MAC address to put
416 Only process owner options in received query packets if the MAC address in the option is non-zero
417 
418 Revision 1.855  2008/11/14 02:29:54  cheshire
419 If Sleep Proxy client fails to renew proxy records before they expire, remove them from our m->ResourceRecords list
420 
421 Revision 1.854  2008/11/14 00:00:53  cheshire
422 After client machine wakes up, Sleep Proxy machine need to remove any records
423 it was temporarily holding as proxy for that client
424 
425 Revision 1.853  2008/11/13 19:07:30  cheshire
426 Added code to put OPT record, containing owner and lease lifetime, into SPS registration packet
427 
428 Revision 1.852  2008/11/12 23:23:11  cheshire
429 Before waking a host, check to see if it has an SRV record advertising
430 a service on the port in question, and if not, don't bother waking it.
431 
432 Revision 1.851  2008/11/12 01:54:15  cheshire
433 <rdar://problem/6338021> Add domain back to end of _services._dns-sd._udp PTR records
434 It turns out it is beneficial to have the domain on the end, because it allows better name compression
435 
436 Revision 1.850  2008/11/11 01:56:57  cheshire
437 Improved name conflict log messages
438 
439 Revision 1.849  2008/11/06 23:50:43  cheshire
440 Allow plain (non-SYN) ssh data packets to wake sleeping host
441 
442 Revision 1.848  2008/11/05 02:40:28  mkrochma
443 Change mDNS_SetFQDN syslog mesage to debugf
444 
445 Revision 1.847  2008/11/04 23:06:50  cheshire
446 Split RDataBody union definition into RDataBody and RDataBody2, and removed
447 SOA from the normal RDataBody union definition, saving 270 bytes per AuthRecord
448 
449 Revision 1.846  2008/11/04 22:21:44  cheshire
450 Changed zone field of AuthRecord_struct from domainname to pointer, saving 252 bytes per AuthRecord
451 
452 Revision 1.845  2008/11/03 23:52:05  cheshire
453 Improved ARP debugging messages to differentiate ARP Announcements from Requests
454 
455 Revision 1.844  2008/10/31 23:43:51  cheshire
456 Fixed compile error in Posix build
457 
458 Revision 1.843  2008/10/31 22:55:04  cheshire
459 Initial support for structured SPS names
460 
461 Revision 1.842  2008/10/30 00:12:07  cheshire
462 Fixed spin when PutSPSRec fails to put a record because it's too big to fit
463 
464 Revision 1.841  2008/10/29 23:23:38  cheshire
465 Refined cache size reporting to go in steps of 1000 when number is above 1000
466 
467 Revision 1.840  2008/10/29 21:34:10  cheshire
468 Removed some old debugging messages
469 
470 Revision 1.839  2008/10/29 21:31:32  cheshire
471 Five seconds not always enough time for machine to go to sleep -- increased to ten seconds
472 
473 Revision 1.838  2008/10/28 18:30:37  cheshire
474 Added debugging message in mDNSCoreReceiveRawPacket
475 
476 Revision 1.837  2008/10/24 23:58:05  cheshire
477 Wake up for Back to My Mac IPSEC packets, except NAT keepalive packets
478 
479 Revision 1.836  2008/10/24 23:18:18  cheshire
480 If we have a Sleep Proxy Server, don't remove service registrations from the DNS server
481 
482 Revision 1.835  2008/10/24 23:07:59  cheshire
483 Wake SPS client if we receive conflicting mDNS respoonse (record with same name as one of our unique records, but different rdata)
484 
485 Revision 1.834  2008/10/24 23:03:24  cheshire
486 Wake SPS client if we receive a conflicting ARP (some other machine claiming to own that IP address)
487 
488 Revision 1.833  2008/10/24 23:01:26  cheshire
489 To reduce spurious wakeups for now, we'll only wake for incoming TCP SYN packets
490 
491 Revision 1.832  2008/10/24 22:58:24  cheshire
492 For now, since we don't get IPv6 ND or data packets, don't advertise AAAA records for our SPS clients
493 
494 Revision 1.831  2008/10/24 22:50:41  cheshire
495 When waking SPS client, include interface name in syslog message
496 
497 Revision 1.830  2008/10/24 20:50:34  cheshire
498 Use "#if USE_SEPARATE_UDNS_SERVICE_LIST" instead of "#if defined(USE_SEPARATE_UDNS_SERVICE_LIST)"
499 
500 Revision 1.829  2008/10/23 23:55:57  cheshire
501 Fixed some missing "const" declarations
502 
503 Revision 1.828  2008/10/23 22:25:56  cheshire
504 Renamed field "id" to more descriptive "updateid"
505 
506 Revision 1.827  2008/10/23 03:06:25  cheshire
507 Fixed "Waking host" log message
508 
509 Revision 1.826  2008/10/22 23:21:30  cheshire
510 Make sure we have enough bytes before reading into the transport-level header
511 
512 Revision 1.825  2008/10/22 22:31:53  cheshire
513 Log SYN/FIN/RST bits from TCP header, and don't wake for FIN/RST
514 
515 Revision 1.824  2008/10/22 20:00:31  cheshire
516 If we ourselves go to sleep, stop advertising sleep proxy service, then re-advertise after we wake up
517 
518 Revision 1.823  2008/10/22 19:55:35  cheshire
519 Miscellaneous fixes; renamed FindFirstAnswerInCache to FindSPSInCache
520 
521 Revision 1.822  2008/10/22 01:41:39  cheshire
522 Set question->ThisQInterval back to -1 after we cancel our NetWakeResolve
523 
524 Revision 1.821  2008/10/22 01:12:53  cheshire
525 Answer ARP Requests for any IP address we're proxying for
526 
527 Revision 1.820  2008/10/21 01:11:11  cheshire
528 Added mDNSCoreReceiveRawPacket for handling raw packets received by platform layer
529 
530 Revision 1.819  2008/10/20 22:16:27  cheshire
531 Updated comments; increased cache shedding threshold from 3000 to 4000
532 
533 Revision 1.818  2008/10/16 22:01:54  cheshire
534 Fix last checkin: Should be "ar->resrec.rdata->u.data", not "ar->resrec.rdata.u.data"
535 
536 Revision 1.817  2008/10/16 21:40:49  cheshire
537 Need to set ar->resrec.rdlength correctly before calling mDNS_Register_internal()
538 
539 Revision 1.816  2008/10/15 23:12:36  cheshire
540 On receiving SPS registration from client, broadcast ARP Announcements claiming ownership of that IP address
541 
542 Revision 1.815  2008/10/15 20:46:38  cheshire
543 When transferring records to SPS, include Lease Option
544 
545 Revision 1.814  2008/10/15 19:51:27  cheshire
546 Change "NOTE:" to "Note:" so that BBEdit 9 stops putting those lines into the funtion popup menu
547 
548 Revision 1.813  2008/10/15 00:09:23  cheshire
549 When acting as Sleep Proxy Server, handle DNS Updates received from SPS clients on the network
550 
551 Revision 1.812  2008/10/15 00:01:40  cheshire
552 When going to sleep, discover and resolve SPS, and if successful, transfer records to it
553 
554 Revision 1.811  2008/10/14 23:51:57  cheshire
555 Created new routine GetRDLengthMem() to compute the in-memory storage requirements for particular rdata
556 
557 Revision 1.810  2008/10/14 21:37:55  cheshire
558 Removed unnecessary m->BeSleepProxyServer variable
559 
560 Revision 1.809  2008/10/10 23:45:48  cheshire
561 For ForceMCast records, SetTargetToHostName should use the dot-local multicast hostname,
562 not a wide-area unicast hostname
563 
564 Revision 1.808  2008/10/09 18:59:19  cheshire
565 Added NetWakeResolve code, removed unused m->SendDeregistrations and m->SendImmediateAnswers
566 
567 Revision 1.807  2008/10/07 15:56:58  cheshire
568 Fixed "unused variable" warnings in non-debug builds
569 
570 Revision 1.806  2008/10/04 00:53:37  cheshire
571 On interfaces that support Wake-On-LAN, browse to discover Sleep Proxy Servers
572 
573 Revision 1.805  2008/10/03 18:17:28  cheshire
574 <rdar://problem/6134215> Sleep Proxy: Mac with Internet Sharing should also offer Sleep Proxy service
575 Update advertised Sleep Proxy Server name if user changes computer name
576 
577 Revision 1.804  2008/10/03 01:26:06  mcguire
578 <rdar://problem/6266145> mDNS_FinalExit failed to send goodbye for duplicate uDNS records
579 Put back Duplicate Record check
580 
581 Revision 1.803  2008/10/02 23:38:56  mcguire
582 <rdar://problem/6266145> mDNS_FinalExit failed to send goodbye for duplicate uDNS records
583 
584 Revision 1.802  2008/10/02 23:13:48  cheshire
585 <rdar://problem/6134215> Sleep Proxy: Mac with Internet Sharing should also offer Sleep Proxy service
586 Need to drop lock before calling "mDNSCoreBeSleepProxyServer(m, mDNSfalse);"
587 
588 Revision 1.801  2008/10/02 22:51:04  cheshire
589 <rdar://problem/6134215> Sleep Proxy: Mac with Internet Sharing should also offer Sleep Proxy service
590 Added mDNSCoreBeSleepProxyServer() routine to start and stop Sleep Proxy Service
591 
592 Revision 1.800  2008/10/02 22:13:15  cheshire
593 <rdar://problem/6230680> 100ms delay on shutdown
594 Additional refinement: Also need to clear m->SuppressSending
595 
596 Revision 1.799  2008/09/29 20:12:37  cheshire
597 Rename 'AnswerLocalQuestions' to more descriptive 'AnswerLocalOnlyQuestions' and 'AnsweredLocalQ' to 'AnsweredLOQ'
598 
599 Revision 1.798  2008/09/26 19:53:14  cheshire
600 Fixed locking error: should not call mDNS_Deregister_internal within "mDNS_DropLock" section
601 
602 Revision 1.797  2008/09/25 20:40:59  cheshire
603 <rdar://problem/6245044> Stop using separate m->ServiceRegistrations list
604 In mDNS_SetFQDN, need to update all AutoTarget SRV records, even if m->MulticastHostname hasn't changed
605 
606 Revision 1.796  2008/09/25 20:17:10  cheshire
607 <rdar://problem/6245044> Stop using separate m->ServiceRegistrations list
608 Added defensive code to make sure *all* records of a ServiceRecordSet have
609 completed deregistering before we pass on the mStatus_MemFree message
610 
611 Revision 1.795  2008/09/25 00:30:11  cheshire
612 <rdar://problem/6245044> Stop using separate m->ServiceRegistrations list
613 
614 Revision 1.794  2008/09/24 23:48:05  cheshire
615 Don't need to pass whole ServiceRecordSet reference to GetServiceTarget;
616 it only needs to access the embedded SRV member of the set
617 
618 Revision 1.793  2008/09/23 04:11:53  cheshire
619 <rdar://problem/6238774> Remove "local" from the end of _services._dns-sd._udp PTR records
620 
621 Revision 1.792  2008/09/23 02:30:07  cheshire
622 Get rid of PutResourceRecordCappedTTL()
623 
624 Revision 1.791  2008/09/20 00:34:21  mcguire
625 <rdar://problem/6129039> BTMM: Add support for WANPPPConnection
626 
627 Revision 1.790  2008/09/18 22:46:34  cheshire
628 <rdar://problem/6230680> 100ms delay on shutdown
629 
630 Revision 1.789  2008/09/18 06:15:06  mkrochma
631 <rdar://problem/6117156> Cleanup: mDNSResponder logging debugging information to console
632 
633 Revision 1.788  2008/09/16 21:11:41  cheshire
634 <rdar://problem/6223969> mDNS: Duplicate TXT record queries being produced by iPhone Remote
635 
636 Revision 1.787  2008/09/05 22:53:24  cheshire
637 Improve "How is rr->resrec.rroriginalttl <= SecsSinceRcvd" debugging message
638 
639 Revision 1.786  2008/09/05 22:23:28  cheshire
640 Moved initialization of "question->LocalSocket" to more logical place
641 
642 Revision 1.785  2008/08/14 19:20:55  cheshire
643 <rdar://problem/6143846> Negative responses over TCP incorrectly rejected
644 
645 Revision 1.784  2008/08/13 00:47:53  mcguire
646 Handle failures when packet logging
647 
648 Revision 1.783  2008/07/25 07:09:51  mcguire
649 <rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
650 
651 Revision 1.782  2008/07/24 20:23:03  cheshire
652 <rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
653 
654 Revision 1.781  2008/07/18 21:37:35  mcguire
655 <rdar://problem/5736845> BTMM: alternate SSDP queries between multicast & unicast
656 
657 Revision 1.780  2008/07/18 02:24:36  cheshire
658 <rdar://problem/6041178> Only trigger reconfirm on hostname if both A and AAAA query fail to elicit a response
659 Additional fix: Don't want to do the ReconfirmAntecedents() stuff if q->RequestUnicast is set (that indicates
660 we're still on our first or second query after an interface registration or wake from sleep).
661 
662 Revision 1.779  2008/07/18 01:05:23  cheshire
663 <rdar://problem/6041178> Only trigger reconfirm on hostname if both A and AAAA query fail to elicit a response
664 
665 Revision 1.778  2008/06/26 17:24:11  mkrochma
666 <rdar://problem/5450912> BTMM: Stop listening on UDP 5351 for NAT Status Announcements
667 
668 Revision 1.777  2008/06/19 01:20:48  mcguire
669 <rdar://problem/4206534> Use all configured DNS servers
670 
671 Revision 1.776  2008/04/17 20:14:14  cheshire
672 <rdar://problem/5870023> CurrentAnswers/LargeAnswers/UniqueAnswers counter mismatch
673 
674 Revision 1.775  2008/03/26 01:53:34  mcguire
675 <rdar://problem/5820489> Can't resolve via uDNS when an interface is specified
676 
677 Revision 1.774  2008/03/17 17:46:08  mcguire
678 When activating an LLQ, reset all the important state and destroy any tcp connection,
679 so that everything will be restarted as if the question had just been asked.
680 Also reset servPort, so that the SOA query will be re-issued.
681 
682 Revision 1.773  2008/03/14 22:52:36  mcguire
683 <rdar://problem/5321824> write status to the DS
684 Update status when any unicast LLQ is started
685 
686 Revision 1.772  2008/03/06 02:48:34  mcguire
687 <rdar://problem/5321824> write status to the DS
688 
689 Revision 1.771  2008/02/26 22:04:44  cheshire
690 <rdar://problem/5661661> BTMM: Too many members.mac.com SOA queries
691 Additional fixes -- should not be calling uDNS_CheckCurrentQuestion on a
692 question while it's still in our 'm->NewQuestions' section of the list
693 
694 Revision 1.770  2008/02/22 23:09:02  cheshire
695 <rdar://problem/5338420> BTMM: Not processing additional records
696 Refinements:
697 1. Check rdatahash == namehash, to skip expensive SameDomainName check when possible
698 2. Once we decide a record is acceptable, we can break out of the loop
699 
700 Revision 1.769  2008/02/22 00:00:19  cheshire
701 <rdar://problem/5338420> BTMM: Not processing additional records
702 
703 Revision 1.768  2008/02/19 23:26:50  cheshire
704 <rdar://problem/5661661> BTMM: Too many members.mac.com SOA queries
705 
706 Revision 1.767  2007/12/22 02:25:29  cheshire
707 <rdar://problem/5661128> Records and Services sometimes not re-registering on wake from sleep
708 
709 Revision 1.766  2007/12/15 01:12:27  cheshire
710 <rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
711 
712 Revision 1.765  2007/12/15 00:18:51  cheshire
713 Renamed question->origLease to question->ReqLease
714 
715 Revision 1.764  2007/12/14 00:49:53  cheshire
716 Fixed crash in mDNS_StartExit -- the service deregistration loop needs to use
717 the CurrentServiceRecordSet mechanism to guard against services being deleted,
718 just like the record deregistration loop uses m->CurrentRecord.
719 
720 Revision 1.763  2007/12/13 20:20:17  cheshire
721 Minor efficiency tweaks -- converted IdenticalResourceRecord, IdenticalSameNameRecord, and
722 SameRData from functions to macros, which allows the code to be inlined (the compiler can't
723 inline a function defined in a different compilation unit) and therefore optimized better.
724 
725 Revision 1.762  2007/12/13 00:13:03  cheshire
726 Simplified RDataHashValue to take a single ResourceRecord pointer, instead of separate rdlength and RDataBody
727 
728 Revision 1.761  2007/12/13 00:03:31  cheshire
729 Improved efficiency in IdenticalResourceRecord() by doing SameRData() check before SameDomainName() check
730 
731 Revision 1.760  2007/12/08 00:36:19  cheshire
732 <rdar://problem/5636422> Updating TXT records is too slow
733 Remove unnecessary delays on announcing record updates, and on processing them on reception
734 
735 Revision 1.759  2007/12/07 22:41:29  cheshire
736 <rdar://problem/5526800> BTMM: Need to clean up registrations on shutdown
737 Further refinements -- records on the DuplicateRecords list were getting missed on shutdown
738 
739 Revision 1.758  2007/12/07 00:45:57  cheshire
740 <rdar://problem/5526800> BTMM: Need to clean up registrations on shutdown
741 
742 Revision 1.757  2007/12/06 00:22:27  mcguire
743 <rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
744 
745 Revision 1.756  2007/12/05 01:52:30  cheshire
746 <rdar://problem/5624763> BTMM: getaddrinfo_async_start returns EAI_NONAME when resolving BTMM hostname
747 Delay returning IPv4 address ("A") results for autotunnel names until after we've set up the tunnel (or tried to)
748 
749 Revision 1.755  2007/12/03 23:36:45  cheshire
750 <rdar://problem/5623140> mDNSResponder unicast DNS improvements
751 Need to check GetServerForName() result is non-null before dereferencing pointer
752 
753 Revision 1.754  2007/12/01 01:21:27  jgraessley
754 <rdar://problem/5623140> mDNSResponder unicast DNS improvements
755 
756 Revision 1.753  2007/12/01 00:44:15  cheshire
757 Fixed compile warnings, e.g. declaration of 'rr' shadows a previous local
758 
759 Revision 1.752  2007/11/14 01:10:51  cheshire
760 Fixed LogOperation() message wording
761 
762 Revision 1.751  2007/10/30 23:49:41  cheshire
763 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
764 LLQ state was not being transferred properly between duplicate questions
765 
766 Revision 1.750  2007/10/29 23:58:52  cheshire
767 <rdar://problem/5536979> BTMM: Need to create NAT port mapping for receiving LLQ events
768 Use standard "if (mDNSIPv4AddressIsOnes(....ExternalAddress))" mechanism to determine whether callback has been invoked yet
769 
770 Revision 1.749  2007/10/29 21:28:36  cheshire
771 Change "Correcting TTL" log message to LogOperation to suppress it in customer build
772 
773 Revision 1.748  2007/10/29 20:02:50  cheshire
774 <rdar://problem/5526813> BTMM: Wide-area records being announced via multicast
775 
776 Revision 1.747  2007/10/26 22:53:50  cheshire
777 Made mDNS_Register_internal and mDNS_Deregister_internal use AuthRecord_uDNS macro
778 instead of replicating the logic in both places
779 
780 Revision 1.746  2007/10/25 22:48:50  cheshire
781 Added LogOperation message saying when we restart GetZoneData for record and service registrations
782 
783 Revision 1.745  2007/10/25 20:48:47  cheshire
784 For naming consistency (with AuthRecord's UpdateServer) renamed 'ns' to 'SRSUpdateServer'
785 
786 Revision 1.744  2007/10/25 20:06:14  cheshire
787 Don't try to do SOA queries using private DNS (TLS over TCP) queries
788 
789 Revision 1.743  2007/10/25 00:12:46  cheshire
790 <rdar://problem/5496734> BTMM: Need to retry registrations after failures
791 Retrigger service registrations whenever a new network interface is added
792 
793 Revision 1.742  2007/10/24 22:40:06  cheshire
794 Renamed: RecordRegistrationCallback          -> RecordRegistrationGotZoneData
795 Renamed: ServiceRegistrationZoneDataComplete -> ServiceRegistrationGotZoneData
796 
797 Revision 1.741  2007/10/24 00:50:29  cheshire
798 <rdar://problem/5496734> BTMM: Need to retry registrations after failures
799 Retrigger record registrations whenever a new network interface is added
800 
801 Revision 1.740  2007/10/23 00:38:03  cheshire
802 When sending uDNS cache expiration query, need to increment rr->UnansweredQueries
803 or code will spin sending the same cache expiration query repeatedly
804 
805 Revision 1.739  2007/10/22 23:46:41  cheshire
806 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
807 Need to clear question->nta pointer after calling CancelGetZoneData()
808 
809 Revision 1.738  2007/10/19 22:08:49  cheshire
810 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
811 Additional fixes and refinements
812 
813 Revision 1.737  2007/10/18 23:06:42  cheshire
814 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
815 Additional fixes and refinements
816 
817 Revision 1.736  2007/10/18 20:23:17  cheshire
818 Moved SuspendLLQs into mDNS.c, since it's only called from one place
819 
820 Revision 1.735  2007/10/18 00:12:34  cheshire
821 Fixed "unused variable" compiler warning
822 
823 Revision 1.734  2007/10/17 22:49:54  cheshire
824 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
825 
826 Revision 1.733  2007/10/17 22:37:23  cheshire
827 <rdar://problem/5536979> BTMM: Need to create NAT port mapping for receiving LLQ events
828 
829 Revision 1.732  2007/10/17 21:53:51  cheshire
830 Improved debugging messages; renamed startLLQHandshakeCallback to LLQGotZoneData
831 
832 Revision 1.731  2007/10/17 18:37:50  cheshire
833 <rdar://problem/5539930> Goodbye packets not being sent for services on shutdown
834 Further refinement: pre-increment m->CurrentRecord before calling mDNS_Deregister_internal()
835 
836 Revision 1.730  2007/10/16 21:16:07  cheshire
837 <rdar://problem/5539930> Goodbye packets not being sent for services on shutdown
838 
839 Revision 1.729  2007/10/05 17:56:10  cheshire
840 Move CountLabels and SkipLeadingLabels to DNSCommon.c so they're callable from other files
841 
842 Revision 1.728  2007/10/04 23:18:14  cheshire
843 <rdar://problem/5523706> mDNSResponder flooding DNS servers with unreasonable query level
844 
845 Revision 1.727  2007/10/04 22:51:57  cheshire
846 Added debugging LogOperation message to show when we're sending cache expiration queries
847 
848 Revision 1.726  2007/10/03 00:14:24  cheshire
849 Removed write to null to generate stack trace for SetNextQueryTime locking failure
850 
851 Revision 1.725  2007/10/02 21:11:08  cheshire
852 <rdar://problem/5518270> LLQ refreshes don't work, which breaks BTMM browsing
853 
854 Revision 1.724  2007/10/02 20:10:23  cheshire
855 Additional debugging checks on shutdown -- list all records we didn't send a goodbye for, not just the first one
856 
857 Revision 1.723  2007/10/02 19:56:54  cheshire
858 <rdar://problem/5518310> Double-dispose causes crash changing Dynamic DNS hostname
859 
860 Revision 1.722  2007/10/01 22:59:46  cheshire
861 <rdar://problem/5516303> mDNSResponder did not shut down after 20 seconds
862 Need to shut down NATTraversals on exit
863 
864 Revision 1.721  2007/10/01 18:42:07  cheshire
865 To make packet logs appear in a more intuitive order, dump received packets *before* handling them, not after
866 
867 Revision 1.720  2007/09/29 20:40:19  cheshire
868 <rdar://problem/5513378> Crash in ReissueBlockedQuestions
869 
870 Revision 1.719  2007/09/27 22:23:56  cheshire
871 <rdar://problem/4947392> uDNS: Use SOA to determine TTL for negative answers
872 Need to clear m->rec.r.resrec.RecordType after we've finished using m->rec
873 
874 Revision 1.718  2007/09/27 22:02:33  cheshire
875 <rdar://problem/5464941> BTMM: Registered records in BTMM don't get removed from server after calling RemoveRecord
876 
877 Revision 1.717  2007/09/27 21:21:39  cheshire
878 Export CompleteDeregistration so it's callable from other files
879 
880 Revision 1.716  2007/09/27 02:12:21  cheshire
881 Updated GrantCacheExtensions degugging message to show new record lifetime
882 
883 Revision 1.715  2007/09/27 01:20:06  cheshire
884 <rdar://problem/5500077> BTMM: Need to refresh LLQs based on lease life and not TTL of response
885 
886 Revision 1.714  2007/09/27 00:37:01  cheshire
887 <rdar://problem/4947392> BTMM: Use SOA to determine TTL for negative answers
888 
889 Revision 1.713  2007/09/27 00:25:39  cheshire
890 Added ttl_seconds parameter to MakeNegativeCacheRecord in preparation for:
891 <rdar://problem/4947392> uDNS: Use SOA to determine TTL for negative answers
892 
893 Revision 1.712  2007/09/26 23:16:58  cheshire
894 <rdar://problem/5496399> BTMM: Leopard sending excessive LLQ registration requests to .Mac
895 
896 Revision 1.711  2007/09/26 22:06:02  cheshire
897 <rdar://problem/5507399> BTMM: No immediate failure notifications for BTMM names
898 
899 Revision 1.710  2007/09/26 00:49:46  cheshire
900 Improve packet logging to show sent and received packets,
901 transport protocol (UDP/TCP/TLS) and source/destination address:port
902 
903 Revision 1.709  2007/09/21 21:12:36  cheshire
904 <rdar://problem/5498009> BTMM: Need to log updates and query packet contents
905 
906 Revision 1.708  2007/09/20 23:13:37  cheshire
907 <rdar://problem/4038277> BTMM: Not getting LLQ remove events when logging out of VPN or disconnecting from network
908 Additional fix: If we have no DNS servers at all, then immediately purge all unicast cache records (including for LLQs)
909 
910 Revision 1.707  2007/09/20 02:29:37  cheshire
911 <rdar://problem/4038277> BTMM: Not getting LLQ remove events when logging out of VPN or disconnecting from network
912 
913 Revision 1.706  2007/09/20 01:13:19  cheshire
914 Export CacheGroupForName so it's callable from other files
915 
916 Revision 1.705  2007/09/20 01:12:06  cheshire
917 Moved HashSlot(X) from mDNS.c to DNSCommon.h so it's usable in other files
918 
919 Revision 1.704  2007/09/19 22:47:25  cheshire
920 <rdar://problem/5490182> Memory corruption freeing a "no such service" service record
921 
922 Revision 1.703  2007/09/14 01:46:59  cheshire
923 Fix Posix build (#ifdef _LEGACY_NAT_TRAVERSAL_ section included a closing curly brace it should not have)
924 
925 Revision 1.702  2007/09/13 22:06:46  cheshire
926 <rdar://problem/5480643> Tully's Free WiFi: DNS fails
927 Need to accept DNS responses where the query ID field matches, even if the source address does not
928 
929 Revision 1.701  2007/09/12 23:22:32  cheshire
930 <rdar://problem/5476979> Only accept NAT Port Mapping packets from our default gateway
931 
932 Revision 1.700  2007/09/12 23:03:08  cheshire
933 <rdar://problem/5476978> DNSServiceNATPortMappingCreate callback not giving correct interface index
934 
935 Revision 1.699  2007/09/12 22:19:28  cheshire
936 <rdar://problem/5476977> Need to listen for port 5350 NAT-PMP announcements
937 
938 Revision 1.698  2007/09/12 22:13:27  cheshire
939 Remove DynDNSHostNames cleanly on shutdown
940 
941 Revision 1.697  2007/09/12 01:44:47  cheshire
942 <rdar://problem/5475938> Eliminate "Correcting TTL" syslog messages for unicast DNS records
943 
944 Revision 1.696  2007/09/12 01:26:08  cheshire
945 Initialize LastNATReplyLocalTime to timenow, so that gateway uptime checks work more reliably
946 
947 Revision 1.695  2007/09/11 19:19:16  cheshire
948 Correct capitalization of "uPNP" to "UPnP"
949 
950 Revision 1.694  2007/09/10 22:06:51  cheshire
951 Rename uptime => upseconds and LastNATUptime => LastNATupseconds to make it clear these time values are in seconds
952 
953 Revision 1.693  2007/09/07 22:24:36  vazquez
954 <rdar://problem/5466301> Need to stop spewing mDNSResponderHelper logs
955 
956 Revision 1.692  2007/09/07 00:12:09  cheshire
957 <rdar://problem/5466010> Unicast DNS changes broke efficiency fix 3928456
958 
959 Revision 1.691  2007/09/05 22:25:01  vazquez
960 <rdar://problem/5400521> update_record mDNSResponder leak
961 
962 Revision 1.690  2007/09/05 21:48:01  cheshire
963 <rdar://problem/5385864> BTMM: mDNSResponder flushes wide-area Bonjour records after an hour for a zone.
964 Now that we're respecting the TTL of uDNS records in the cache, the LLQ maintenance code needs
965 to update the cache lifetimes of all relevant records every time it successfully renews an LLQ,
966 otherwise those records will expire and vanish from the cache.
967 
968 Revision 1.689  2007/09/05 02:29:06  cheshire
969 <rdar://problem/5457287> mDNSResponder taking up 100% CPU in ReissueBlockedQuestions
970 Additional fixes to code implementing "NoAnswer" logic
971 
972 Revision 1.688  2007/08/31 22:56:39  cheshire
973 <rdar://problem/5407080> BTMM: TTLs incorrect on cached BTMM records
974 
975 Revision 1.687  2007/08/31 19:53:14  cheshire
976 <rdar://problem/5431151> BTMM: IPv6 address lookup should not succeed if autotunnel cannot be setup
977 If AutoTunnel setup fails, the code now generates a fake NXDomain error saying that the requested AAAA record does not exist
978 
979 Revision 1.686  2007/08/30 00:01:56  cheshire
980 Added comment about SetTargetToHostName()
981 
982 Revision 1.685  2007/08/29 01:19:24  cheshire
983 <rdar://problem/5400181> BTMM: Tunneled services do not need NAT port mappings
984 Set AutoTarget to Target_AutoHostAndNATMAP for non-AutoTunnel wide-area services
985 
986 Revision 1.684  2007/08/28 23:58:42  cheshire
987 Rename HostTarget -> AutoTarget
988 
989 Revision 1.683  2007/08/28 23:53:21  cheshire
990 Rename serviceRegistrationCallback -> ServiceRegistrationZoneDataComplete
991 
992 Revision 1.682  2007/08/27 20:28:19  cheshire
993 Improve "suspect uDNS response" log message
994 
995 Revision 1.681  2007/08/24 23:37:23  cheshire
996 Added debugging message to show when ExtraResourceRecord callback gets invoked
997 
998 Revision 1.680  2007/08/24 00:15:19  cheshire
999 Renamed GetAuthInfoForName() to GetAuthInfoForName_internal() to make it clear that it may only be called with the lock held
1000 
1001 Revision 1.679  2007/08/23 21:47:09  vazquez
1002 <rdar://problem/5427316> BTMM: mDNSResponder sends NAT-PMP packets on public network
1003 make sure we clean up port mappings on base stations by sending a lease value of 0,
1004 and only send NAT-PMP packets on private networks; also save some memory by
1005 not using packet structs in NATTraversals.
1006 
1007 Revision 1.678  2007/08/01 16:09:13  cheshire
1008 Removed unused NATTraversalInfo substructure from AuthRecord; reduced structure sizecheck values accordingly
1009 
1010 Revision 1.677  2007/08/01 01:58:24  cheshire
1011 Added RecordType sanity check in mDNS_Register_internal
1012 
1013 Revision 1.676  2007/08/01 00:04:13  cheshire
1014 <rdar://problem/5261696> Crash in tcpKQSocketCallback
1015 Half-open TCP connections were not being cancelled properly
1016 
1017 Revision 1.675  2007/07/31 02:28:35  vazquez
1018 <rdar://problem/3734269> NAT-PMP: Detect public IP address changes and base station reboot
1019 
1020 Revision 1.674  2007/07/31 01:57:23  cheshire
1021 Adding code to respect TTL received in uDNS responses turned out to
1022 expose other problems; backing out change for now.
1023 
1024 Revision 1.673  2007/07/30 23:31:26  cheshire
1025 Code for respecting TTL received in uDNS responses should exclude LLQ-type responses
1026 
1027 Revision 1.672  2007/07/28 01:25:56  cheshire
1028 <rdar://problem/4780038> BTMM: Add explicit UDP event port to LLQ setup request, to fix LLQs not working behind NAT
1029 
1030 Revision 1.671  2007/07/27 22:32:54  cheshire
1031 When processing TTLs in uDNS responses, we'll currently impose a minimum effective TTL
1032 of 2 seconds, or other stuff breaks (e.g. we end up making a negative cache entry).
1033 
1034 Revision 1.670  2007/07/27 20:54:43  cheshire
1035 Fixed code to respect real record TTL received in uDNS responses
1036 
1037 Revision 1.669  2007/07/27 20:09:32  cheshire
1038 Don't need to dump out all received mDNS packets; they're easily viewed using mDNSNetMonitor
1039 
1040 Revision 1.668  2007/07/27 19:58:47  cheshire
1041 Use symbolic names QC_add and QC_rmv instead of mDNStrue/mDNSfalse
1042 
1043 Revision 1.667  2007/07/27 19:52:10  cheshire
1044 Don't increment m->rrcache_active for no-cache add events
1045 
1046 Revision 1.666  2007/07/27 19:30:39  cheshire
1047 Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
1048 to properly reflect tri-state nature of the possible responses
1049 
1050 Revision 1.665  2007/07/27 18:44:01  cheshire
1051 Rename "AnswerQuestionWithResourceRecord" to more informative "AnswerCurrentQuestionWithResourceRecord"
1052 
1053 Revision 1.664  2007/07/27 18:38:56  cheshire
1054 Rename "uDNS_CheckQuery" to more informative "uDNS_CheckCurrentQuestion"
1055 
1056 Revision 1.663  2007/07/25 03:05:02  vazquez
1057 Fixes for:
1058 <rdar://problem/5338913> LegacyNATTraversal: UPnP heap overflow
1059 <rdar://problem/5338933> LegacyNATTraversal: UPnP stack buffer overflow
1060 and a myriad of other security problems
1061 
1062 Revision 1.662  2007/07/24 20:22:46  cheshire
1063 Make sure all fields of main mDNS object are initialized correctly
1064 
1065 Revision 1.661  2007/07/21 00:54:45  cheshire
1066 <rdar://problem/5344576> Delay IPv6 address callback until AutoTunnel route and policy is configured
1067 
1068 Revision 1.660  2007/07/20 20:00:45  cheshire
1069 "Legacy Browse" is better called "Automatic Browse"
1070 
1071 Revision 1.659  2007/07/20 00:54:18  cheshire
1072 <rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
1073 
1074 Revision 1.658  2007/07/18 02:28:57  cheshire
1075 Don't set AutoTunnel settings in uDNS_RegisterService; should be done in GetServiceTarget
1076 
1077 Revision 1.657  2007/07/18 00:57:10  cheshire
1078 <rdar://problem/5303834> Automatically configure IPSec policy when resolving services
1079 Only need to call AddNewClientTunnel() for IPv6 addresses
1080 
1081 Revision 1.656  2007/07/16 23:54:48  cheshire
1082 <rdar://problem/5338850> Crash when removing or changing DNS keys
1083 
1084 Revision 1.655  2007/07/16 20:11:37  vazquez
1085 <rdar://problem/3867231> LegacyNATTraversal: Need complete rewrite
1086 Init LNT stuff and handle SSDP packets
1087 
1088 Revision 1.654  2007/07/12 23:30:23  cheshire
1089 Changed some 'LogOperation' calls to 'debugf' to reduce verbosity in syslog
1090 
1091 Revision 1.653  2007/07/12 02:51:27  cheshire
1092 <rdar://problem/5303834> Automatically configure IPSec policy when resolving services
1093 
1094 Revision 1.652  2007/07/11 23:43:42  cheshire
1095 Rename PurgeCacheResourceRecord to mDNS_PurgeCacheResourceRecord
1096 
1097 Revision 1.651  2007/07/11 22:44:40  cheshire
1098 <rdar://problem/5328801> SIGHUP should purge the cache
1099 
1100 Revision 1.650  2007/07/11 21:34:09  cheshire
1101 <rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
1102 Need to hold mDNS_Lock when calling mDNS_AddDynDNSHostName/mDNS_RemoveDynDNSHostName
1103 
1104 Revision 1.649  2007/07/11 02:52:52  cheshire
1105 <rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
1106 In uDNS_RegisterService, set HostTarget for AutoTunnel services
1107 
1108 Revision 1.648  2007/07/09 23:48:12  cheshire
1109 Add parentheses around bitwise operation for clarity
1110 
1111 Revision 1.647  2007/07/06 21:17:55  cheshire
1112 Initialize m->retryGetAddr to timenow + 0x78000000;
1113 
1114 Revision 1.646  2007/07/06 18:55:49  cheshire
1115 Initialize m->NextScheduledNATOp
1116 
1117 Revision 1.645  2007/06/29 22:55:54  cheshire
1118 Move declaration of DNSServer *s; Fixed incomplete comment.
1119 
1120 Revision 1.644  2007/06/29 00:07:29  vazquez
1121 <rdar://problem/5301908> Clean up NAT state machine (necessary for 6 other fixes)
1122 
1123 Revision 1.643  2007/06/20 01:10:12  cheshire
1124 <rdar://problem/5280520> Sync iPhone changes into main mDNSResponder code
1125 
1126 Revision 1.642  2007/06/15 21:54:50  cheshire
1127 <rdar://problem/4883206> Add packet logging to help debugging private browsing over TLS
1128 
1129 Revision 1.641  2007/05/25 00:30:24  cheshire
1130 When checking for duplicate questions, make sure privacy (or not) status, and long-lived (or not)
1131 status matches. This is particularly important when doing a private query for an SOA record,
1132 which will result in a call StartGetZoneData which does a non-private query for the same SOA record.
1133 If the latter is tagged as a duplicate of the former, then we have deadlock, and neither will complete.
1134 
1135 Revision 1.640  2007/05/25 00:25:44  cheshire
1136 <rdar://problem/5227737> Need to enhance putRData to output all current known types
1137 
1138 Revision 1.639  2007/05/23 00:51:33  cheshire
1139 Increase threshold for shedding cache records from 512 to 3000. The 512 figure was calculated when
1140 each cache entry took about 700 bytes; now they're only 164 bytes. Also, machines have more RAM these
1141 days, and there are more services being advertised using DNS-SD, so it makes sense to cache more.
1142 
1143 Revision 1.638  2007/05/23 00:43:16  cheshire
1144 If uDNS UDP response has TC (truncated) bit set, don't interpret it as being the entire RRSet
1145 
1146 Revision 1.637  2007/05/14 23:53:00  cheshire
1147 Export mDNS_StartQuery_internal and mDNS_StopQuery_internal so they can be called from uDNS.c
1148 
1149 Revision 1.636  2007/05/10 23:27:15  cheshire
1150 Update mDNS_Deregister_internal debugging messages
1151 
1152 Revision 1.635  2007/05/07 20:43:45  cheshire
1153 <rdar://problem/4241419> Reduce the number of queries and announcements
1154 
1155 Revision 1.634  2007/05/04 22:09:08  cheshire
1156 Only do "restarting exponential backoff sequence" for mDNS questions
1157 In mDNS_RegisterInterface, only retrigger mDNS questions
1158 In uDNS_SetupDNSConfig, use ActivateUnicastQuery() instead of just setting q->ThisQInterval directly
1159 
1160 Revision 1.633  2007/05/04 21:45:12  cheshire
1161 Get rid of unused q->RestartTime; Get rid of uDNS_Close (synonym for uDNS_Sleep)
1162 
1163 Revision 1.632  2007/05/04 20:20:50  cheshire
1164 <rdar://problem/5167331> RegisterRecord and RegisterService need to cancel StartGetZoneData
1165 Need to set srs->nta = mDNSNULL; when regState_NoTarget
1166 
1167 Revision 1.631  2007/05/04 00:39:42  cheshire
1168 <rdar://problem/4410011> Eliminate looping SOA lookups
1169 When creating a cascade of negative SOA cache entries, CacheGroup pointer cg needs to be updated
1170 each time round the loop to reference the right CacheGroup for each newly fabricated SOA name
1171 
1172 Revision 1.630  2007/05/03 22:40:38  cheshire
1173 <rdar://problem/4669229> mDNSResponder ignores bogus null target in SRV record
1174 
1175 Revision 1.629  2007/05/03 00:15:51  cheshire
1176 <rdar://problem/4410011> Eliminate looping SOA lookups
1177 
1178 Revision 1.628  2007/05/02 22:21:33  cheshire
1179 <rdar://problem/5167331> RegisterRecord and RegisterService need to cancel StartGetZoneData
1180 
1181 Revision 1.627  2007/04/30 19:29:13  cheshire
1182 Fix display of port number in "Updating DNS Server" message
1183 
1184 Revision 1.626  2007/04/30 04:21:13  cheshire
1185 Can't safely call AnswerLocalQuestions() from within mDNS_Deregister() -- need to defer it until mDNS_Execute time
1186 
1187 Revision 1.625  2007/04/28 01:34:21  cheshire
1188 Fixed crashing bug: We need to update rr->CRActiveQuestion pointers for *all* questions
1189 (Code was explicitly ignoring wide-area unicast questions, leading to stale pointers and crashes)
1190 
1191 Revision 1.624  2007/04/27 21:04:30  cheshire
1192 On network configuration change, need to call uDNS_RegisterSearchDomains
1193 
1194 Revision 1.623  2007/04/27 19:28:01  cheshire
1195 Any code that calls StartGetZoneData needs to keep a handle to the structure, so
1196 it can cancel it if necessary. (First noticed as a crash in Apple Remote Desktop
1197 -- it would start a query and then quickly cancel it, and then when
1198 StartGetZoneData completed, it had a dangling pointer and crashed.)
1199 
1200 Revision 1.622  2007/04/26 16:09:22  cheshire
1201 mDNS_StopQueryWithRemoves should ignore kDNSRecordTypePacketNegative records
1202 
1203 Revision 1.621  2007/04/26 15:43:22  cheshire
1204 Make sure DNSServer *s is non-null before using value in LogOperation
1205 
1206 Revision 1.620  2007/04/26 13:11:05  cheshire
1207 Fixed crash when logging out of VPN
1208 
1209 Revision 1.619  2007/04/26 00:35:15  cheshire
1210 <rdar://problem/5140339> uDNS: Domain discovery not working over VPN
1211 Fixes to make sure results update correctly when connectivity changes (e.g. a DNS server
1212 inside the firewall may give answers where a public one gives none, and vice versa.)
1213 
1214 Revision 1.618  2007/04/25 19:26:01  cheshire
1215 m->NextScheduledQuery was getting set too early in SendQueries()
1216 Improved "SendQueries didn't send all its queries" debugging message
1217 
1218 Revision 1.617  2007/04/25 17:48:22  cheshire
1219 Update debugging message
1220 
1221 Revision 1.616  2007/04/25 16:38:32  cheshire
1222 If negative cache entry already exists, reactivate it instead of creating a new one
1223 
1224 Revision 1.615  2007/04/25 02:14:38  cheshire
1225 <rdar://problem/4246187> uDNS: Identical client queries should reference a single shared core query
1226 Additional fixes to make LLQs work properly
1227 
1228 Revision 1.614  2007/04/23 21:52:45  cheshire
1229 <rdar://problem/5094009> IPv6 filtering in AirPort base station breaks Wide-Area Bonjour
1230 
1231 Revision 1.613  2007/04/23 04:58:20  cheshire
1232 <rdar://problem/5072548> Crash when setting extremely large TXT records
1233 
1234 Revision 1.612  2007/04/22 20:39:38  cheshire
1235 <rdar://problem/4633194> Add 20 to 120ms random delay to browses
1236 
1237 Revision 1.611  2007/04/22 18:16:29  cheshire
1238 Removed incorrect ActiveQuestion(q) check that was preventing suspended questions from getting reactivated
1239 
1240 Revision 1.610  2007/04/22 06:02:02  cheshire
1241 <rdar://problem/4615977> Query should immediately return failure when no server
1242 
1243 Revision 1.609  2007/04/20 21:17:24  cheshire
1244 For naming consistency, kDNSRecordTypeNegative should be kDNSRecordTypePacketNegative
1245 
1246 Revision 1.608  2007/04/20 19:45:31  cheshire
1247 In LogClientOperations mode, dump out unknown DNS packets in their entirety
1248 
1249 Revision 1.607  2007/04/19 23:56:25  cheshire
1250 Don't do cache-flush processing for LLQ answers
1251 
1252 Revision 1.606  2007/04/19 22:50:53  cheshire
1253 <rdar://problem/4246187> Identical client queries should reference a single shared core query
1254 
1255 Revision 1.605  2007/04/19 20:06:41  cheshire
1256 Rename field 'Private' (sounds like a boolean) to more informative 'AuthInfo' (it's a DomainAuthInfo pointer)
1257 
1258 Revision 1.604  2007/04/19 18:03:04  cheshire
1259 Add "const" declaration
1260 
1261 Revision 1.603  2007/04/06 21:00:25  cheshire
1262 Fix log message typo
1263 
1264 Revision 1.602  2007/04/05 22:55:35  cheshire
1265 <rdar://problem/5077076> Records are ending up in Lighthouse without expiry information
1266 
1267 Revision 1.601  2007/04/04 21:48:52  cheshire
1268 <rdar://problem/4720694> Combine unicast authoritative answer list with multicast list
1269 
1270 Revision 1.600  2007/04/04 01:31:33  cheshire
1271 Improve debugging message
1272 
1273 Revision 1.599  2007/04/04 00:03:26  cheshire
1274 <rdar://problem/5089862> DNSServiceQueryRecord is returning kDNSServiceErr_NoSuchRecord for empty rdata
1275 
1276 Revision 1.598  2007/04/03 19:43:16  cheshire
1277 Use mDNSSameIPPort (and similar) instead of accessing internal fields directly
1278 
1279 Revision 1.597  2007/03/31 00:32:32  cheshire
1280 After skipping OPT and TSIG, clear m->rec.r.resrec.RecordType
1281 
1282 Revision 1.596  2007/03/28 20:59:26  cheshire
1283 <rdar://problem/4743285> Remove inappropriate use of IsPrivateV4Addr()
1284 
1285 Revision 1.595  2007/03/26 23:48:16  cheshire
1286 <rdar://problem/4848295> Advertise model information via Bonjour
1287 Refinements to reduce unnecessary transmissions of the DeviceInfo TXT record
1288 
1289 Revision 1.594  2007/03/26 23:05:05  cheshire
1290 <rdar://problem/5089257> Don't cache TSIG records
1291 
1292 Revision 1.593  2007/03/23 17:40:08  cheshire
1293 <rdar://problem/4060169> Bug when auto-renaming Computer Name after name collision
1294 
1295 Revision 1.592  2007/03/22 18:31:48  cheshire
1296 Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
1297 
1298 Revision 1.591  2007/03/22 00:49:19  cheshire
1299 <rdar://problem/4848295> Advertise model information via Bonjour
1300 
1301 Revision 1.590  2007/03/21 23:05:59  cheshire
1302 Rename uDNS_HostnameInfo to HostnameInfo; deleted some unused fields
1303 
1304 Revision 1.589  2007/03/20 15:37:19  cheshire
1305 Delete unnecessary log message
1306 
1307 Revision 1.588  2007/03/20 00:24:44  cheshire
1308 <rdar://problem/4175213> Should deliver "name registered" callback slightly *before* announcing PTR record
1309 
1310 Revision 1.587  2007/03/16 22:10:56  cheshire
1311 <rdar://problem/4471307> mDNS: Query for *either* type A or AAAA should return both types
1312 
1313 Revision 1.586  2007/03/10 03:26:44  cheshire
1314 <rdar://problem/4961667> uDNS: LLQ refresh response packet causes cached records to be removed from cache
1315 
1316 Revision 1.585  2007/03/10 02:02:58  cheshire
1317 <rdar://problem/4961667> uDNS: LLQ refresh response packet causes cached records to be removed from cache
1318 Eliminate unnecessary "InternalResponseHndlr responseCallback" function pointer
1319 
1320 Revision 1.584  2007/02/28 01:51:27  cheshire
1321 Added comment about reverse-order IP address
1322 
1323 Revision 1.583  2007/01/27 03:19:33  cheshire
1324 Need to initialize question->sock
1325 
1326 Revision 1.582  2007/01/25 00:40:16  cheshire
1327 Unified CNAME-following functionality into cache management code (which means CNAME-following
1328 should now also work for mDNS queries too); deleted defunct pktResponseHndlr() routine.
1329 
1330 Revision 1.581  2007/01/23 02:56:11  cheshire
1331 Store negative results in the cache, instead of generating them out of pktResponseHndlr()
1332 
1333 Revision 1.580  2007/01/19 21:17:33  cheshire
1334 StartLLQPolling needs to call SetNextQueryTime() to cause query to be done in a timely fashion
1335 
1336 Revision 1.579  2007/01/19 18:39:10  cheshire
1337 Fix a bunch of parameters that should have been declared "const"
1338 
1339 Revision 1.578  2007/01/10 22:51:57  cheshire
1340 <rdar://problem/4917539> Add support for one-shot private queries as well as long-lived private queries
1341 
1342 Revision 1.577  2007/01/10 02:05:21  cheshire
1343 Delay uDNS_SetupDNSConfig() until *after* the platform layer
1344 has set up the interface list and security credentials
1345 
1346 Revision 1.576  2007/01/09 02:40:57  cheshire
1347 uDNS_SetupDNSConfig() shouldn't be called from mDNSMacOSX.c (platform support layer);
1348 moved it to mDNS_Init() in mDNS.c (core code)
1349 
1350 Revision 1.575  2007/01/09 00:17:25  cheshire
1351 Improve "ERROR m->CurrentRecord already set" debugging messages
1352 
1353 Revision 1.574  2007/01/05 08:30:41  cheshire
1354 Trim excessive "Log" checkin history from before 2006
1355 (checkin history still available via "cvs log ..." of course)
1356 
1357 Revision 1.573  2007/01/05 06:34:03  cheshire
1358 Improve "ERROR m->CurrentQuestion already set" debugging messages
1359 
1360 Revision 1.572  2007/01/04 23:11:11  cheshire
1361 <rdar://problem/4720673> uDNS: Need to start caching unicast records
1362 When an automatic browsing domain is removed, generate appropriate "remove" events for legacy queries
1363 
1364 Revision 1.571  2007/01/04 21:45:20  cheshire
1365 Added mDNS_DropLockBeforeCallback/mDNS_ReclaimLockAfterCallback macros,
1366 to do additional lock sanity checking around callback invocations
1367 
1368 Revision 1.570  2007/01/04 20:57:47  cheshire
1369 Rename ReturnCNAME to ReturnIntermed (for ReturnIntermediates)
1370 
1371 Revision 1.569  2007/01/04 20:27:27  cheshire
1372 Change a LogMsg() to debugf()
1373 
1374 Revision 1.568  2007/01/04 02:39:53  cheshire
1375 <rdar://problem/4030599> Hostname passed into DNSServiceRegister ignored for Wide-Area service registrations
1376 
1377 Revision 1.567  2006/12/21 00:01:37  cheshire
1378 Tidy up code alignment
1379 
1380 Revision 1.566  2006/12/20 04:07:34  cheshire
1381 Remove uDNS_info substructure from AuthRecord_struct
1382 
1383 Revision 1.565  2006/12/19 22:49:23  cheshire
1384 Remove uDNS_info substructure from ServiceRecordSet_struct
1385 
1386 Revision 1.564  2006/12/19 02:38:20  cheshire
1387 Get rid of unnecessary duplicate query ID field from DNSQuestion_struct
1388 
1389 Revision 1.563  2006/12/19 02:18:48  cheshire
1390 Get rid of unnecessary duplicate "void *context" field from DNSQuestion_struct
1391 
1392 Revision 1.562  2006/12/16 01:58:31  cheshire
1393 <rdar://problem/4720673> uDNS: Need to start caching unicast records
1394 
1395 Revision 1.561  2006/12/01 07:38:53  herscher
1396 Only perform cache workaround fix if query is wide-area
1397 
1398 Revision 1.560  2006/11/30 23:07:56  herscher
1399 <rdar://problem/4765644> uDNS: Sync up with Lighthouse changes for Private DNS
1400 
1401 Revision 1.559  2006/11/27 08:20:57  cheshire
1402 Preliminary support for unifying the uDNS and mDNS code, including caching of uDNS answers
1403 
1404 Revision 1.558  2006/11/10 07:44:03  herscher
1405 <rdar://problem/4825493> Fix Daemon locking failures while toggling BTMM
1406 
1407 Revision 1.557  2006/11/10 01:12:51  cheshire
1408 <rdar://problem/4829718> Incorrect TTL corrections
1409 
1410 Revision 1.556  2006/11/10 00:54:14  cheshire
1411 <rdar://problem/4816598> Changing case of Computer Name doesn't work
1412 
1413 Revision 1.555  2006/10/30 20:03:37  cheshire
1414 <rdar://problem/4456945> After service restarts on different port, for a few seconds DNS-SD may return stale port number
1415 
1416 Revision 1.554  2006/10/20 05:35:04  herscher
1417 <rdar://problem/4720713> uDNS: Merge unicast active question list with multicast list.
1418 
1419 Revision 1.553  2006/10/05 03:42:43  herscher
1420 Remove embedded uDNS_info struct in DNSQuestion_struct
1421 
1422 Revision 1.552  2006/09/15 21:20:15  cheshire
1423 Remove uDNS_info substructure from mDNS_struct
1424 
1425 Revision 1.551  2006/08/14 23:24:22  cheshire
1426 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
1427 
1428 Revision 1.550  2006/07/27 17:58:34  cheshire
1429 Improved text of "SendQueries didn't send all its queries; will try again" debugging message
1430 
1431 Revision 1.549  2006/07/20 22:07:31  mkrochma
1432 <rdar://problem/4633196> Wide-area browsing is currently broken in TOT
1433 More fixes for uninitialized variables
1434 
1435 Revision 1.548  2006/07/20 19:30:19  mkrochma
1436 <rdar://problem/4633196> Wide-area browsing sometimes doesn't work in TOT
1437 
1438 Revision 1.547  2006/07/15 02:31:30  cheshire
1439 <rdar://problem/4630812> Suppress log messages for certain old devices with inconsistent TXT RRSet TTLs
1440 
1441 Revision 1.546  2006/07/07 01:09:09  cheshire
1442 <rdar://problem/4472013> Add Private DNS server functionality to dnsextd
1443 Only use mallocL/freeL debugging routines when building mDNSResponder, not dnsextd
1444 
1445 Revision 1.545  2006/07/05 23:10:30  cheshire
1446 <rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
1447 Update mDNSSendDNSMessage() to use uDNS_TCPSocket type instead of "int"
1448 
1449 Revision 1.544  2006/06/29 07:42:14  cheshire
1450 <rdar://problem/3922989> Performance: Remove unnecessary SameDomainName() checks
1451 
1452 Revision 1.543  2006/06/29 01:38:43  cheshire
1453 <rdar://problem/4605285> Only request unicast responses on wake from sleep and network connection
1454 
1455 Revision 1.542  2006/06/27 23:40:29  cheshire
1456 Fix typo in comment: mis-spelled "compile"
1457 
1458 Revision 1.541  2006/06/27 19:46:24  cheshire
1459 Updated comments and debugging messages
1460 
1461 Revision 1.540  2006/06/15 21:35:16  cheshire
1462 Move definitions of mDNS_vsnprintf, mDNS_SetupResourceRecord, and some constants
1463 from mDNS.c to DNSCommon.c, so they can be accessed from dnsextd code
1464 
1465 Revision 1.539  2006/06/08 23:45:46  cheshire
1466 Change SimultaneousProbe messages from debugf() to LogOperation()
1467 
1468 Revision 1.538  2006/03/19 17:13:06  cheshire
1469 <rdar://problem/4483117> Need faster purging of stale records
1470 Shorten kDefaultReconfirmTimeForNoAnswer to five seconds
1471 and reconfirm whole chain of antecedents ot once
1472 
1473 Revision 1.537  2006/03/19 02:00:07  cheshire
1474 <rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
1475 
1476 Revision 1.536  2006/03/08 23:29:53  cheshire
1477 <rdar://problem/4468716> Improve "Service Renamed" log message
1478 
1479 Revision 1.535  2006/03/02 20:41:17  cheshire
1480 <rdar://problem/4111464> After record update, old record sometimes remains in cache
1481 Minor code tidying and comments to reduce the risk of similar programming errors in future
1482 
1483 Revision 1.534  2006/03/02 03:25:46  cheshire
1484 <rdar://problem/4111464> After record update, old record sometimes remains in cache
1485 Code to harmonize RRSet TTLs was inadvertently rescuing expiring records
1486 
1487 Revision 1.533  2006/02/26 00:54:41  cheshire
1488 Fixes to avoid code generation warning/error on FreeBSD 7
1489 
1490 */
1491 
1492 #include "DNSCommon.h"                  // Defines general DNS untility routines
1493 #include "uDNS.h"						// Defines entry points into unicast-specific routines
1494 
1495 // Disable certain benign warnings with Microsoft compilers
1496 #if(defined(_MSC_VER))
1497 	// Disable "conditional expression is constant" warning for debug macros.
1498 	// Otherwise, this generates warnings for the perfectly natural construct "while(1)"
1499 	// If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
1500 	#pragma warning(disable:4127)
1501 
1502 	// Disable "assignment within conditional expression".
1503 	// Other compilers understand the convention that if you place the assignment expression within an extra pair
1504 	// of parentheses, this signals to the compiler that you really intended an assignment and no warning is necessary.
1505 	// The Microsoft compiler doesn't understand this convention, so in the absense of any other way to signal
1506 	// to the compiler that the assignment is intentional, we have to just turn this warning off completely.
1507 	#pragma warning(disable:4706)
1508 #endif
1509 
1510 // Forward declarations
1511 mDNSlocal void BeginSleepProcessing(mDNS *const m);
1512 mDNSlocal void RetrySPSRegistrations(mDNS *const m);
1513 
1514 // ***************************************************************************
1515 #if COMPILER_LIKES_PRAGMA_MARK
1516 #pragma mark - Program Constants
1517 #endif
1518 
1519 #define NO_HINFO 1
1520 
1521 mDNSlocal const mDNSInterfaceID mDNSInterfaceMark = (mDNSInterfaceID)~0;
1522 
1523 // Any records bigger than this are considered 'large' records
1524 #define SmallRecordLimit 1024
1525 
1526 #define kMaxUpdateCredits 10
1527 #define kUpdateCreditRefreshInterval (mDNSPlatformOneSecond * 6)
1528 
1529 mDNSexport const char *const mDNS_DomainTypeNames[] =
1530 	{
1531 	 "b._dns-sd._udp.",		// Browse
1532 	"db._dns-sd._udp.",		// Default Browse
1533 	"lb._dns-sd._udp.",		// Automatic Browse
1534 	 "r._dns-sd._udp.",		// Registration
1535 	"dr._dns-sd._udp."		// Default Registration
1536 	};
1537 
1538 #ifdef UNICAST_DISABLED
1539 #define uDNS_IsActiveQuery(q, u) mDNSfalse
1540 #endif
1541 
1542 // ***************************************************************************
1543 #if COMPILER_LIKES_PRAGMA_MARK
1544 #pragma mark -
1545 #pragma mark - General Utility Functions
1546 #endif
1547 
1548 #define ActiveQuestion(Q) ((Q)->ThisQInterval > 0 && !(Q)->DuplicateOf)
1549 #define TimeToSendThisQuestion(Q,time) (ActiveQuestion(Q) && (time) - ((Q)->LastQTime + (Q)->ThisQInterval) >= 0)
1550 
1551 mDNSexport void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q)
1552 	{
1553 	if (m->mDNS_busy != m->mDNS_reentrancy+1)
1554 		LogMsg("SetNextQueryTime: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
1555 
1556 #if ForceAlerts
1557 	if (m->mDNS_busy != m->mDNS_reentrancy+1) *(long*)0 = 0;
1558 #endif
1559 
1560 	if (ActiveQuestion(q))
1561 		{
1562 		mDNSs32 sendtime = q->LastQTime + q->ThisQInterval;
1563 
1564 		// Don't allow sendtime to be earlier than SuppressStdPort53Queries
1565 		if (!mDNSOpaque16IsZero(q->TargetQID) && !q->LongLived && m->SuppressStdPort53Queries && (sendtime - m->SuppressStdPort53Queries < 0))
1566 			sendtime = m->SuppressStdPort53Queries;
1567 
1568 		if (m->NextScheduledQuery - sendtime > 0)
1569 			m->NextScheduledQuery = sendtime;
1570 		}
1571 	}
1572 
1573 mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name)
1574 	{
1575 	CacheGroup *cg;
1576 	for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
1577 		if (cg->namehash == namehash && SameDomainName(cg->name, name))
1578 			break;
1579 	return(cg);
1580 	}
1581 
1582 mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr)
1583 	{
1584 	return(CacheGroupForName(m, slot, rr->namehash, rr->name));
1585 	}
1586 
1587 mDNSlocal mDNSBool AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr)
1588 	{
1589 	NetworkInterfaceInfo *intf;
1590 
1591 	if (addr->type == mDNSAddrType_IPv4)
1592 		{
1593 		// Normally we resist touching the NotAnInteger fields, but here we're doing tricky bitwise masking so we make an exception
1594 		if (mDNSv4AddressIsLinkLocal(&addr->ip.v4)) return(mDNStrue);
1595 		for (intf = m->HostInterfaces; intf; intf = intf->next)
1596 			if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
1597 				if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0)
1598 					return(mDNStrue);
1599 		}
1600 
1601 	if (addr->type == mDNSAddrType_IPv6)
1602 		{
1603 		if (mDNSv6AddressIsLinkLocal(&addr->ip.v4)) return(mDNStrue);
1604 		for (intf = m->HostInterfaces; intf; intf = intf->next)
1605 			if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
1606 				if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) &&
1607 					(((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) &&
1608 					(((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) &&
1609 					(((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0))
1610 						return(mDNStrue);
1611 		}
1612 
1613 	return(mDNSfalse);
1614 	}
1615 
1616 mDNSlocal NetworkInterfaceInfo *FirstInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
1617 	{
1618 	NetworkInterfaceInfo *intf = m->HostInterfaces;
1619 	while (intf && intf->InterfaceID != InterfaceID) intf = intf->next;
1620 	return(intf);
1621 	}
1622 
1623 mDNSlocal char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
1624 	{
1625 	NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
1626 	return(intf ? intf->ifname : "<NULL InterfaceID>");
1627 	}
1628 
1629 // For a single given DNSQuestion, deliver an add/remove result for the single given AuthRecord
1630 // Used by AnswerAllLocalQuestionsWithLocalAuthRecord() and AnswerNewLocalOnlyQuestion()
1631 mDNSlocal void AnswerLocalQuestionWithLocalAuthRecord(mDNS *const m, DNSQuestion *q, AuthRecord *rr, QC_result AddRecord)
1632 	{
1633 	// Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it
1634 	if (AddRecord) rr->AnsweredLocalQ = mDNStrue;
1635 	mDNS_DropLockBeforeCallback();		// Allow client to legally make mDNS API calls from the callback
1636 	if (q->QuestionCallback && !q->NoAnswer)
1637 		{
1638 		q->CurrentAnswers += AddRecord ? 1 : -1;
1639 		q->QuestionCallback(m, q, &rr->resrec, AddRecord);
1640 		}
1641 	mDNS_ReclaimLockAfterCallback();	// Decrement mDNS_reentrancy to block mDNS API calls again
1642 	}
1643 
1644 // When a new local AuthRecord is created or deleted, AnswerAllLocalQuestionsWithLocalAuthRecord() runs though
1645 // all our local questions (both LocalOnlyQuestions and mDNSInterface_Any questions) delivering answers to each,
1646 // stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion().
1647 // If the AuthRecord is marked mDNSInterface_LocalOnly, then we also deliver it to any other questions we have using mDNSInterface_Any.
1648 // Used by AnswerForNewLocalRecords() and mDNS_Deregister_internal()
1649 mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord)
1650 	{
1651 	if (m->CurrentQuestion)
1652 		LogMsg("AnswerAllLocalQuestionsWithLocalAuthRecord ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
1653 
1654 	m->CurrentQuestion = m->LocalOnlyQuestions;
1655 	while (m->CurrentQuestion && m->CurrentQuestion != m->NewLocalOnlyQuestions)
1656 		{
1657 		DNSQuestion *q = m->CurrentQuestion;
1658 		m->CurrentQuestion = q->next;
1659 		if (ResourceRecordAnswersQuestion(&rr->resrec, q))
1660 			AnswerLocalQuestionWithLocalAuthRecord(m, q, rr, AddRecord);			// MUST NOT dereference q again
1661 		}
1662 
1663 	// If this AuthRecord is marked LocalOnly, then we want to deliver it to all local 'mDNSInterface_Any' questions
1664 	if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
1665 		{
1666 		m->CurrentQuestion = m->Questions;
1667 		while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
1668 			{
1669 			DNSQuestion *q = m->CurrentQuestion;
1670 			m->CurrentQuestion = q->next;
1671 			if (ResourceRecordAnswersQuestion(&rr->resrec, q))
1672 				AnswerLocalQuestionWithLocalAuthRecord(m, q, rr, AddRecord);		// MUST NOT dereference q again
1673 			}
1674 		}
1675 
1676 	m->CurrentQuestion = mDNSNULL;
1677 	}
1678 
1679 // ***************************************************************************
1680 #if COMPILER_LIKES_PRAGMA_MARK
1681 #pragma mark -
1682 #pragma mark - Resource Record Utility Functions
1683 #endif
1684 
1685 #define RRTypeIsAddressType(T) ((T) == kDNSType_A || (T) == kDNSType_AAAA)
1686 
1687 #define ResourceRecordIsValidAnswer(RR) ( ((RR)->             resrec.RecordType & kDNSRecordTypeActiveMask)  && \
1688 		((RR)->Additional1 == mDNSNULL || ((RR)->Additional1->resrec.RecordType & kDNSRecordTypeActiveMask)) && \
1689 		((RR)->Additional2 == mDNSNULL || ((RR)->Additional2->resrec.RecordType & kDNSRecordTypeActiveMask)) && \
1690 		((RR)->DependentOn == mDNSNULL || ((RR)->DependentOn->resrec.RecordType & kDNSRecordTypeActiveMask))  )
1691 
1692 #define ResourceRecordIsValidInterfaceAnswer(RR, INTID) \
1693 	(ResourceRecordIsValidAnswer(RR) && \
1694 	((RR)->resrec.InterfaceID == mDNSInterface_Any || (RR)->resrec.InterfaceID == (INTID)))
1695 
1696 #define DefaultProbeCountForTypeUnique ((mDNSu8)3)
1697 #define DefaultProbeCountForRecordType(X)      ((X) == kDNSRecordTypeUnique ? DefaultProbeCountForTypeUnique : (mDNSu8)0)
1698 
1699 #define InitialAnnounceCount ((mDNSu8)8)
1700 
1701 // Note that the announce intervals use exponential backoff, doubling each time. The probe intervals do not.
1702 // This means that because the announce interval is doubled after sending the first packet, the first
1703 // observed on-the-wire inter-packet interval between announcements is actually one second.
1704 // The half-second value here may be thought of as a conceptual (non-existent) half-second delay *before* the first packet is sent.
1705 #define DefaultProbeIntervalForTypeUnique (mDNSPlatformOneSecond/4)
1706 #define DefaultAnnounceIntervalForTypeShared (mDNSPlatformOneSecond/2)
1707 #define DefaultAnnounceIntervalForTypeUnique (mDNSPlatformOneSecond/2)
1708 
1709 #define DefaultAPIntervalForRecordType(X)  ((X) & (kDNSRecordTypeAdvisory | kDNSRecordTypeShared     ) ? DefaultAnnounceIntervalForTypeShared : \
1710 											(X) & (kDNSRecordTypeUnique                              ) ? DefaultProbeIntervalForTypeUnique    : \
1711 											(X) & (kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique) ? DefaultAnnounceIntervalForTypeUnique : 0)
1712 
1713 #define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0)
1714 #define TimeToSendThisRecord(RR,time) ((TimeToAnnounceThisRecord(RR,time) || (RR)->ImmedAnswer) && ResourceRecordIsValidAnswer(RR))
1715 #define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond)
1716 #define RRExpireTime(RR) ((RR)->TimeRcvd + TicksTTL(RR))
1717 
1718 #define MaxUnansweredQueries 4
1719 
1720 // SameResourceRecordSignature returns true if two resources records have the same name, type, and class, and may be sent
1721 // (or were received) on the same interface (i.e. if *both* records specify an interface, then it has to match).
1722 // TTL and rdata may differ.
1723 // This is used for cache flush management:
1724 // When sending a unique record, all other records matching "SameResourceRecordSignature" must also be sent
1725 // When receiving a unique record, all old cache records matching "SameResourceRecordSignature" are flushed
1726 
1727 // SameResourceRecordNameClassInterface is functionally the same as SameResourceRecordSignature, except rrtype does not have to match
1728 
1729 #define SameResourceRecordSignature(A,B) (A)->resrec.rrtype == (B)->resrec.rrtype && SameResourceRecordNameClassInterface((A),(B))
1730 
1731 mDNSlocal mDNSBool SameResourceRecordNameClassInterface(const AuthRecord *const r1, const AuthRecord *const r2)
1732 	{
1733 	if (!r1) { LogMsg("SameResourceRecordSignature ERROR: r1 is NULL"); return(mDNSfalse); }
1734 	if (!r2) { LogMsg("SameResourceRecordSignature ERROR: r2 is NULL"); return(mDNSfalse); }
1735 	if (r1->resrec.InterfaceID &&
1736 		r2->resrec.InterfaceID &&
1737 		r1->resrec.InterfaceID != r2->resrec.InterfaceID) return(mDNSfalse);
1738 	return(mDNSBool)(
1739 		r1->resrec.rrclass  == r2->resrec.rrclass &&
1740 		r1->resrec.namehash == r2->resrec.namehash &&
1741 		SameDomainName(r1->resrec.name, r2->resrec.name));
1742 	}
1743 
1744 // PacketRRMatchesSignature behaves as SameResourceRecordSignature, except that types may differ if our
1745 // authoratative record is unique (as opposed to shared). For unique records, we are supposed to have
1746 // complete ownership of *all* types for this name, so *any* record type with the same name is a conflict.
1747 // In addition, when probing we send our questions with the wildcard type kDNSQType_ANY,
1748 // so a response of any type should match, even if it is not actually the type the client plans to use.
1749 
1750 // For now, to make it easier to avoid false conflicts, we treat SPS Proxy records like shared records,
1751 // and require the rrtypes to match for the rdata to be considered potentially conflicting
1752 mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, const AuthRecord *const authrr)
1753 	{
1754 	if (!pktrr)  { LogMsg("PacketRRMatchesSignature ERROR: pktrr is NULL"); return(mDNSfalse); }
1755 	if (!authrr) { LogMsg("PacketRRMatchesSignature ERROR: authrr is NULL"); return(mDNSfalse); }
1756 	if (pktrr->resrec.InterfaceID &&
1757 		authrr->resrec.InterfaceID &&
1758 		pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse);
1759 	if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) || authrr->WakeUp.HMAC.l[0])
1760 		if (pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse);
1761 	return(mDNSBool)(
1762 		pktrr->resrec.rrclass == authrr->resrec.rrclass &&
1763 		pktrr->resrec.namehash == authrr->resrec.namehash &&
1764 		SameDomainName(pktrr->resrec.name, authrr->resrec.name));
1765 	}
1766 
1767 // CacheRecord *ka is the CacheRecord from the known answer list in the query.
1768 // This is the information that the requester believes to be correct.
1769 // AuthRecord *rr is the answer we are proposing to give, if not suppressed.
1770 // This is the information that we believe to be correct.
1771 // We've already determined that we plan to give this answer on this interface
1772 // (either the record is non-specific, or it is specific to this interface)
1773 // so now we just need to check the name, type, class, rdata and TTL.
1774 mDNSlocal mDNSBool ShouldSuppressKnownAnswer(const CacheRecord *const ka, const AuthRecord *const rr)
1775 	{
1776 	// If RR signature is different, or data is different, then don't suppress our answer
1777 	if (!IdenticalResourceRecord(&ka->resrec, &rr->resrec)) return(mDNSfalse);
1778 
1779 	// If the requester's indicated TTL is less than half the real TTL,
1780 	// we need to give our answer before the requester's copy expires.
1781 	// If the requester's indicated TTL is at least half the real TTL,
1782 	// then we can suppress our answer this time.
1783 	// If the requester's indicated TTL is greater than the TTL we believe,
1784 	// then that's okay, and we don't need to do anything about it.
1785 	// (If two responders on the network are offering the same information,
1786 	// that's okay, and if they are offering the information with different TTLs,
1787 	// the one offering the lower TTL should defer to the one offering the higher TTL.)
1788 	return(mDNSBool)(ka->resrec.rroriginalttl >= rr->resrec.rroriginalttl / 2);
1789 	}
1790 
1791 mDNSlocal void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const rr)
1792 	{
1793 	if (rr->resrec.RecordType == kDNSRecordTypeUnique)
1794 		{
1795 		//LogMsg("ProbeCount %d Next %ld %s", rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr));
1796 		if (m->NextScheduledProbe - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
1797 			m->NextScheduledProbe = (rr->LastAPTime + rr->ThisAPInterval);
1798 		}
1799 	else if (rr->AnnounceCount && ResourceRecordIsValidAnswer(rr))
1800 		{
1801 		if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
1802 			m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval);
1803 		}
1804 	}
1805 
1806 mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
1807 	{
1808 	// For reverse-mapping Sleep Proxy PTR records, probe interval is one second
1809 	rr->ThisAPInterval = rr->AddressProxy.type ? mDNSPlatformOneSecond : DefaultAPIntervalForRecordType(rr->resrec.RecordType);
1810 
1811 	// To allow us to aggregate probes when a group of services are registered together,
1812 	// the first probe is delayed 1/4 second. This means the common-case behaviour is:
1813 	// 1/4 second wait; probe
1814 	// 1/4 second wait; probe
1815 	// 1/4 second wait; probe
1816 	// 1/4 second wait; announce (i.e. service is normally announced exactly one second after being registered)
1817 
1818 	if (rr->ProbeCount)
1819 		{
1820 		// If we have no probe suppression time set, or it is in the past, set it now
1821 		if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0)
1822 			{
1823 			m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique);
1824 			// If we already have a *probe* scheduled to go out sooner, then use that time to get better aggregation
1825 			if (m->SuppressProbes - m->NextScheduledProbe >= 0)
1826 				m->SuppressProbes = m->NextScheduledProbe;
1827 			// If we already have a *query* scheduled to go out sooner, then use that time to get better aggregation
1828 			if (m->SuppressProbes - m->NextScheduledQuery >= 0)
1829 				m->SuppressProbes = m->NextScheduledQuery;
1830 			}
1831 		}
1832 
1833 	rr->LastAPTime      = m->SuppressProbes - rr->ThisAPInterval;
1834 	// Set LastMCTime to now, to inhibit multicast responses
1835 	// (no need to send additional multicast responses when we're announcing anyway)
1836 	rr->LastMCTime      = m->timenow;
1837 	rr->LastMCInterface = mDNSInterfaceMark;
1838 
1839 	// If this is a record type that's not going to probe, then delay its first announcement so that
1840 	// it will go out synchronized with the first announcement for the other records that *are* probing.
1841 	// This is a minor performance tweak that helps keep groups of related records synchronized together.
1842 	// The addition of "interval / 2" is to make sure that, in the event that any of the probes are
1843 	// delayed by a few milliseconds, this announcement does not inadvertently go out *before* the probing is complete.
1844 	// When the probing is complete and those records begin to announce, these records will also be picked up and accelerated,
1845 	// because they will meet the criterion of being at least half-way to their scheduled announcement time.
1846 	if (rr->resrec.RecordType != kDNSRecordTypeUnique)
1847 		rr->LastAPTime += DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
1848 
1849 	// The exception is unique records that have already been verified and are just being updated
1850 	// via mDNS_Update() -- for these we want to announce the new value immediately, without delay.
1851 	if (rr->resrec.RecordType == kDNSRecordTypeVerified)
1852 		rr->LastAPTime = m->timenow - rr->ThisAPInterval;
1853 
1854 	// For reverse-mapping Sleep Proxy PTR records we don't want to start probing instantly -- we
1855 	// wait one second to give the client a chance to go to sleep, and then start our ARP/NDP probing.
1856 	// After three probes one second apart with no answer, we conclude the client is now sleeping
1857 	// and we can begin broadcasting our announcements to take over ownership of that IP address.
1858 	// If we don't wait for the client to go to sleep, then when the client sees our ARP Announcements there's a risk
1859 	// (depending on the OS and networking stack it's using) that it might interpret it as a conflict and change its IP address.
1860 	if (rr->AddressProxy.type) rr->LastAPTime = m->timenow;
1861 
1862 	// For now, since we don't yet handle IPv6 ND or data packets, we send deletions for our SPS clients' AAAA records
1863 	if (rr->WakeUp.HMAC.l[0] && rr->resrec.rrtype == kDNSType_AAAA)
1864 		rr->LastAPTime = m->timenow - rr->ThisAPInterval + mDNSPlatformOneSecond * 10;
1865 
1866 	SetNextAnnounceProbeTime(m, rr);
1867 	}
1868 
1869 // Right now this only applies to mDNS (.local) services where the target host is always m->MulticastHostname
1870 // Eventually we should unify this with GetServiceTarget() in uDNS.c
1871 mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr)
1872 	{
1873 	domainname *const target = GetRRDomainNameTarget(&rr->resrec);
1874 	const domainname *newname = &m->MulticastHostname;
1875 
1876 	if (!target) debugf("SetTargetToHostName: Don't know how to set the target of rrtype %d", rr->resrec.rrtype);
1877 
1878 	if (!(rr->ForceMCast || rr->resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(&rr->namestorage)))
1879 		{
1880 		const domainname *const n = GetServiceTarget(m, rr);
1881 		if (n) newname = n;
1882 		}
1883 
1884 	if (target && SameDomainName(target, newname))
1885 		debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name->c, target->c);
1886 
1887 	if (target && !SameDomainName(target, newname))
1888 		{
1889 		AssignDomainName(target, newname);
1890 		SetNewRData(&rr->resrec, mDNSNULL, 0);		// Update rdlength, rdestimate, rdatahash
1891 
1892 		// If we're in the middle of probing this record, we need to start again,
1893 		// because changing its rdata may change the outcome of the tie-breaker.
1894 		// (If the record type is kDNSRecordTypeUnique (unconfirmed unique) then DefaultProbeCountForRecordType is non-zero.)
1895 		rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
1896 
1897 		// If we've announced this record, we really should send a goodbye packet for the old rdata before
1898 		// changing to the new rdata. However, in practice, we only do SetTargetToHostName for unique records,
1899 		// so when we announce them we'll set the kDNSClass_UniqueRRSet and clear any stale data that way.
1900 		if (rr->RequireGoodbye && rr->resrec.RecordType == kDNSRecordTypeShared)
1901 			debugf("Have announced shared record %##s (%s) at least once: should have sent a goodbye packet before updating",
1902 				rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1903 
1904 		rr->AnnounceCount  = InitialAnnounceCount;
1905 		rr->RequireGoodbye = mDNSfalse;
1906 		InitializeLastAPTime(m, rr);
1907 		}
1908 	}
1909 
1910 mDNSlocal void AcknowledgeRecord(mDNS *const m, AuthRecord *const rr)
1911 	{
1912 	if (rr->RecordCallback)
1913 		{
1914 		// CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
1915 		// is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
1916 		rr->Acknowledged = mDNStrue;
1917 		mDNS_DropLockBeforeCallback();		// Allow client to legally make mDNS API calls from the callback
1918 		rr->RecordCallback(m, rr, mStatus_NoError);
1919 		mDNS_ReclaimLockAfterCallback();	// Decrement mDNS_reentrancy to block mDNS API calls again
1920 		}
1921 	}
1922 
1923 mDNSlocal void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr)
1924 	{
1925 	rr->ProbeCount     = 0;
1926 	rr->AnnounceCount  = 0;
1927 	rr->ThisAPInterval = 5 * mDNSPlatformOneSecond;		// After doubling, first retry will happen after ten seconds
1928 	rr->LastAPTime     = m->timenow - rr->ThisAPInterval;
1929 	rr->state = regState_FetchingZoneData;
1930 	rr->uselease = mDNStrue;
1931 	}
1932 
1933 // Two records qualify to be local duplicates if the RecordTypes are the same, or if one is Unique and the other Verified
1934 #define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || \
1935 	((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified))
1936 #define RecordIsLocalDuplicate(A,B) \
1937 	((A)->resrec.InterfaceID == (B)->resrec.InterfaceID && RecordLDT((A),(B)) && IdenticalResourceRecord(&(A)->resrec, &(B)->resrec))
1938 
1939 // Exported so uDNS.c can call this
1940 mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
1941 	{
1942 	domainname *target = GetRRDomainNameTarget(&rr->resrec);
1943 	AuthRecord *r;
1944 	AuthRecord **p = &m->ResourceRecords;
1945 	AuthRecord **d = &m->DuplicateRecords;
1946 
1947 	if ((mDNSs32)rr->resrec.rroriginalttl <= 0)
1948 		{ LogMsg("mDNS_Register_internal: TTL must be 1 - 0x7FFFFFFF %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
1949 
1950 	if (!rr->resrec.RecordType)
1951 		{ LogMsg("mDNS_Register_internal: RecordType must be non-zero %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
1952 
1953 	if (m->ShutdownTime)
1954 		{ LogMsg("mDNS_Register_internal: Shutting down, can't register %s", ARDisplayString(m, rr)); return(mStatus_ServiceNotRunning); }
1955 
1956 	if (m->DivertMulticastAdvertisements && !AuthRecord_uDNS(rr))
1957 		{
1958 		mDNSInterfaceID previousID = rr->resrec.InterfaceID;
1959 		if (rr->resrec.InterfaceID == mDNSInterface_Any) rr->resrec.InterfaceID = mDNSInterface_LocalOnly;
1960 		if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
1961 			{
1962 			NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
1963 			if (intf && !intf->Advertise) rr->resrec.InterfaceID = mDNSInterface_LocalOnly;
1964 			}
1965 		if (rr->resrec.InterfaceID != previousID)
1966 			LogInfo("mDNS_Register_internal: Diverting record to local-only %s", ARDisplayString(m, rr));
1967 		}
1968 
1969 	while (*p && *p != rr) p=&(*p)->next;
1970 	while (*d && *d != rr) d=&(*d)->next;
1971 	if (*d || *p)
1972 		{
1973 		LogMsg("Error! Tried to register AuthRecord %p %##s (%s) that's already in the list",
1974 			rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1975 		return(mStatus_AlreadyRegistered);
1976 		}
1977 
1978 	if (rr->DependentOn)
1979 		{
1980 		if (rr->resrec.RecordType == kDNSRecordTypeUnique)
1981 			rr->resrec.RecordType =  kDNSRecordTypeVerified;
1982 		else
1983 			{
1984 			LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique",
1985 				rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1986 			return(mStatus_Invalid);
1987 			}
1988 		if (!(rr->DependentOn->resrec.RecordType & (kDNSRecordTypeUnique | kDNSRecordTypeVerified)))
1989 			{
1990 			LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn->RecordType bad type %X",
1991 				rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->DependentOn->resrec.RecordType);
1992 			return(mStatus_Invalid);
1993 			}
1994 		}
1995 
1996 	// If this resource record is referencing a specific interface, make sure it exists
1997 	if (rr->resrec.InterfaceID && rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
1998 		{
1999 		NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
2000 		if (!intf)
2001 			{
2002 			debugf("mDNS_Register_internal: Bogus InterfaceID %p in resource record", rr->resrec.InterfaceID);
2003 			return(mStatus_BadReferenceErr);
2004 			}
2005 		}
2006 
2007 	rr->next = mDNSNULL;
2008 
2009 	// Field Group 1: The actual information pertaining to this resource record
2010 	// Set up by client prior to call
2011 
2012 	// Field Group 2: Persistent metadata for Authoritative Records
2013 //	rr->Additional1       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
2014 //	rr->Additional2       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
2015 //	rr->DependentOn       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
2016 //	rr->RRSet             = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
2017 //	rr->Callback          = already set      in mDNS_SetupResourceRecord
2018 //	rr->Context           = already set      in mDNS_SetupResourceRecord
2019 //	rr->RecordType        = already set      in mDNS_SetupResourceRecord
2020 //	rr->HostTarget        = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
2021 //	rr->AllowRemoteQuery  = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
2022 	// Make sure target is not uninitialized data, or we may crash writing debugging log messages
2023 	if (rr->AutoTarget && target) target->c[0] = 0;
2024 
2025 	// Field Group 3: Transient state for Authoritative Records
2026 	rr->Acknowledged      = mDNSfalse;
2027 	rr->ProbeCount        = DefaultProbeCountForRecordType(rr->resrec.RecordType);
2028 	rr->AnnounceCount     = InitialAnnounceCount;
2029 	rr->RequireGoodbye    = mDNSfalse;
2030 	rr->AnsweredLocalQ    = mDNSfalse;
2031 	rr->IncludeInProbe    = mDNSfalse;
2032 	rr->ImmedUnicast      = mDNSfalse;
2033 	rr->SendNSECNow       = mDNSNULL;
2034 	rr->ImmedAnswer       = mDNSNULL;
2035 	rr->ImmedAdditional   = mDNSNULL;
2036 	rr->SendRNow          = mDNSNULL;
2037 	rr->v4Requester       = zerov4Addr;
2038 	rr->v6Requester       = zerov6Addr;
2039 	rr->NextResponse      = mDNSNULL;
2040 	rr->NR_AnswerTo       = mDNSNULL;
2041 	rr->NR_AdditionalTo   = mDNSNULL;
2042 	if (!rr->AutoTarget) InitializeLastAPTime(m, rr);
2043 //	rr->LastAPTime        = Set for us in InitializeLastAPTime()
2044 //	rr->LastMCTime        = Set for us in InitializeLastAPTime()
2045 //	rr->LastMCInterface   = Set for us in InitializeLastAPTime()
2046 	rr->NewRData          = mDNSNULL;
2047 	rr->newrdlength       = 0;
2048 	rr->UpdateCallback    = mDNSNULL;
2049 	rr->UpdateCredits     = kMaxUpdateCredits;
2050 	rr->NextUpdateCredit  = 0;
2051 	rr->UpdateBlocked     = 0;
2052 
2053 	// For records we're holding as proxy (except reverse-mapping PTR records) two announcements is sufficient
2054 	if (rr->WakeUp.HMAC.l[0] && !rr->AddressProxy.type) rr->AnnounceCount = 2;
2055 
2056 	// Field Group 4: Transient uDNS state for Authoritative Records
2057 	rr->state             = regState_Zero;
2058 	rr->uselease          = 0;
2059 	rr->expire            = 0;
2060 	rr->Private           = 0;
2061 	rr->updateid          = zeroID;
2062 	rr->zone              = rr->resrec.name;
2063 	rr->UpdateServer      = zeroAddr;
2064 	rr->UpdatePort        = zeroIPPort;
2065 	rr->nta               = mDNSNULL;
2066 	rr->tcp               = mDNSNULL;
2067 	rr->OrigRData         = 0;
2068 	rr->OrigRDLen         = 0;
2069 	rr->InFlightRData     = 0;
2070 	rr->InFlightRDLen     = 0;
2071 	rr->QueuedRData       = 0;
2072 	rr->QueuedRDLen       = 0;
2073 
2074 //	rr->resrec.interface         = already set in mDNS_SetupResourceRecord
2075 //	rr->resrec.name->c           = MUST be set by client
2076 //	rr->resrec.rrtype            = already set in mDNS_SetupResourceRecord
2077 //	rr->resrec.rrclass           = already set in mDNS_SetupResourceRecord
2078 //	rr->resrec.rroriginalttl     = already set in mDNS_SetupResourceRecord
2079 //	rr->resrec.rdata             = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set
2080 
2081 	if (rr->AutoTarget)
2082 		SetTargetToHostName(m, rr);	// Also sets rdlength and rdestimate for us, and calls InitializeLastAPTime();
2083 	else
2084 		{
2085 		rr->resrec.rdlength   = GetRDLength(&rr->resrec, mDNSfalse);
2086 		rr->resrec.rdestimate = GetRDLength(&rr->resrec, mDNStrue);
2087 		}
2088 
2089 	if (!ValidateDomainName(rr->resrec.name))
2090 		{ LogMsg("Attempt to register record with invalid name: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
2091 
2092 	// BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
2093 	// since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
2094 	// Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
2095 	if (rr->resrec.rrtype == kDNSType_TXT && rr->resrec.rdlength == 0) { rr->resrec.rdlength = 1; rr->resrec.rdata->u.txt.c[0] = 0; }
2096 
2097 	// Don't do this until *after* we've set rr->resrec.rdlength
2098 	if (!ValidateRData(rr->resrec.rrtype, rr->resrec.rdlength, rr->resrec.rdata))
2099 		{ LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
2100 
2101 	rr->resrec.namehash   = DomainNameHashValue(rr->resrec.name);
2102 	rr->resrec.rdatahash  = target ? DomainNameHashValue(target) : RDataHashValue(&rr->resrec);
2103 
2104 	if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
2105 		{
2106 		// If this is supposed to be unique, make sure we don't have any name conflicts
2107 		if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2108 			{
2109 			const AuthRecord *s1 = rr->RRSet ? rr->RRSet : rr;
2110 			for (r = m->ResourceRecords; r; r=r->next)
2111 				{
2112 				const AuthRecord *s2 = r->RRSet ? r->RRSet : r;
2113 				if (s1 != s2 && SameResourceRecordSignature(r, rr) && !IdenticalSameNameRecord(&r->resrec, &rr->resrec))
2114 					break;
2115 				}
2116 			if (r)	// If we found a conflict, set RecordType = kDNSRecordTypeDeregistering so we'll deliver the callback
2117 				{
2118 				debugf("Name conflict %p %##s (%s)", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
2119 				rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
2120 				rr->resrec.rroriginalttl = 0;
2121 				rr->ImmedAnswer          = mDNSInterfaceMark;
2122 				m->NextScheduledResponse = m->timenow;
2123 				}
2124 			}
2125 		}
2126 
2127 	// Now that we've finished building our new record, make sure it's not identical to one we already have
2128 	for (r = m->ResourceRecords; r; r=r->next) if (RecordIsLocalDuplicate(r, rr)) break;
2129 
2130 	if (r)
2131 		{
2132 		debugf("Adding to duplicate list %p %s", rr, ARDisplayString(m,rr));
2133 		*d = rr;
2134 		// If the previous copy of this record is already verified unique,
2135 		// then indicate that we should move this record promptly to kDNSRecordTypeUnique state.
2136 		// Setting ProbeCount to zero will cause SendQueries() to advance this record to
2137 		// kDNSRecordTypeVerified state and call the client callback at the next appropriate time.
2138 		if (rr->resrec.RecordType == kDNSRecordTypeUnique && r->resrec.RecordType == kDNSRecordTypeVerified)
2139 			rr->ProbeCount = 0;
2140 		}
2141 	else
2142 		{
2143 		debugf("Adding to active record list %p %s", rr, ARDisplayString(m,rr));
2144 		if (!m->NewLocalRecords) m->NewLocalRecords = rr;
2145 		*p = rr;
2146 		}
2147 
2148 	if (!AuthRecord_uDNS(rr))
2149 		{
2150 		// For records that are not going to probe, acknowledge them right away
2151 		if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering)
2152 			AcknowledgeRecord(m, rr);
2153 		}
2154 #ifndef UNICAST_DISABLED
2155 	else
2156 		{
2157 		if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
2158 		ActivateUnicastRegistration(m, rr);
2159 		}
2160 #endif
2161 
2162 	return(mStatus_NoError);
2163 	}
2164 
2165 mDNSlocal void RecordProbeFailure(mDNS *const m, const AuthRecord *const rr)
2166 	{
2167 	m->ProbeFailTime = m->timenow;
2168 	m->NumFailedProbes++;
2169 	// If we've had fifteen or more probe failures, rate-limit to one every five seconds.
2170 	// If a bunch of hosts have all been configured with the same name, then they'll all
2171 	// conflict and run through the same series of names: name-2, name-3, name-4, etc.,
2172 	// up to name-10. After that they'll start adding random increments in the range 1-100,
2173 	// so they're more likely to branch out in the available namespace and settle on a set of
2174 	// unique names quickly. If after five more tries the host is still conflicting, then we
2175 	// may have a serious problem, so we start rate-limiting so we don't melt down the network.
2176 	if (m->NumFailedProbes >= 15)
2177 		{
2178 		m->SuppressProbes = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5);
2179 		LogMsg("Excessive name conflicts (%lu) for %##s (%s); rate limiting in effect",
2180 			m->NumFailedProbes, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
2181 		}
2182 	}
2183 
2184 mDNSlocal void CompleteRDataUpdate(mDNS *const m, AuthRecord *const rr)
2185 	{
2186 	RData *OldRData = rr->resrec.rdata;
2187 	SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);	// Update our rdata
2188 	rr->NewRData = mDNSNULL;									// Clear the NewRData pointer ...
2189 	if (rr->UpdateCallback)
2190 		rr->UpdateCallback(m, rr, OldRData);					// ... and let the client know
2191 	}
2192 
2193 // Note: mDNS_Deregister_internal can call a user callback, which may change the record list and/or question list.
2194 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
2195 // Exported so uDNS.c can call this
2196 mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt)
2197 	{
2198 	AuthRecord *r2;
2199 	mDNSu8 RecordType = rr->resrec.RecordType;
2200 	AuthRecord **p = &m->ResourceRecords;	// Find this record in our list of active records
2201 
2202 	while (*p && *p != rr) p=&(*p)->next;
2203 
2204 	if (*p)
2205 		{
2206 		// We found our record on the main list. See if there are any duplicates that need special handling.
2207 		if (drt == mDNS_Dereg_conflict)		// If this was a conflict, see that all duplicates get the same treatment
2208 			{
2209 			// Scan for duplicates of rr, and mark them for deregistration at the end of this routine, after we've finished
2210 			// deregistering rr. We need to do this scan *before* we give the client the chance to free and reuse the rr memory.
2211 			for (r2 = m->DuplicateRecords; r2; r2=r2->next) if (RecordIsLocalDuplicate(r2, rr)) r2->ProbeCount = 0xFF;
2212 			}
2213 		else
2214 			{
2215 			// Before we delete the record (and potentially send a goodbye packet)
2216 			// first see if we have a record on the duplicate list ready to take over from it.
2217 			AuthRecord **d = &m->DuplicateRecords;
2218 			while (*d && !RecordIsLocalDuplicate(*d, rr)) d=&(*d)->next;
2219 			if (*d)
2220 				{
2221 				AuthRecord *dup = *d;
2222 				debugf("Duplicate record %p taking over from %p %##s (%s)",
2223 					dup, rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
2224 				*d        = dup->next;		// Cut replacement record from DuplicateRecords list
2225 				dup->next = rr->next;		// And then...
2226 				rr->next  = dup;			// ... splice it in right after the record we're about to delete
2227 				dup->resrec.RecordType        = rr->resrec.RecordType;
2228 				dup->ProbeCount      = rr->ProbeCount;
2229 				dup->AnnounceCount   = rr->AnnounceCount;
2230 				dup->RequireGoodbye  = rr->RequireGoodbye;
2231 				dup->AnsweredLocalQ  = rr->AnsweredLocalQ;
2232 				dup->ImmedAnswer     = rr->ImmedAnswer;
2233 				dup->ImmedUnicast    = rr->ImmedUnicast;
2234 				dup->ImmedAdditional = rr->ImmedAdditional;
2235 				dup->v4Requester     = rr->v4Requester;
2236 				dup->v6Requester     = rr->v6Requester;
2237 				dup->ThisAPInterval  = rr->ThisAPInterval;
2238 				dup->LastAPTime      = rr->LastAPTime;
2239 				dup->LastMCTime      = rr->LastMCTime;
2240 				dup->LastMCInterface = rr->LastMCInterface;
2241 				dup->UpdateServer    = rr->UpdateServer;
2242 				dup->UpdatePort      = rr->UpdatePort;
2243 				dup->Private         = rr->Private;
2244 				dup->state           = rr->state;
2245 				rr->RequireGoodbye = mDNSfalse;
2246 				rr->AnsweredLocalQ = mDNSfalse;
2247 				}
2248 			}
2249 		}
2250 	else
2251 		{
2252 		// We didn't find our record on the main list; try the DuplicateRecords list instead.
2253 		p = &m->DuplicateRecords;
2254 		while (*p && *p != rr) p=&(*p)->next;
2255 		// If we found our record on the duplicate list, then make sure we don't send a goodbye for it
2256 		if (*p) rr->RequireGoodbye = mDNSfalse;
2257 		if (*p) debugf("DNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)",
2258 			rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
2259 		}
2260 
2261 	if (!*p)
2262 		{
2263 		// No need to log an error message if we already know this is a potentially repeated deregistration
2264 		if (drt != mDNS_Dereg_repeat)
2265 			LogMsg("mDNS_Deregister_internal: Record %p not found in list %s", rr, ARDisplayString(m,rr));
2266 		return(mStatus_BadReferenceErr);
2267 		}
2268 
2269 	// If this is a shared record and we've announced it at least once,
2270 	// we need to retract that announcement before we delete the record
2271 
2272 	// If this is a record (including mDNSInterface_LocalOnly records) for which we've given local-only answers then
2273 	// it's tempting to just do "AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse)" here, but that would not not be safe.
2274 	// The AnswerAllLocalQuestionsWithLocalAuthRecord routine walks the question list invoking client callbacks, using the "m->CurrentQuestion"
2275 	// mechanism to cope with the client callback modifying the question list while that's happening.
2276 	// However, mDNS_Deregister could have been called from a client callback (e.g. from the domain enumeration callback FoundDomain)
2277 	// which means that the "m->CurrentQuestion" mechanism is already in use to protect that list, so we can't use it twice.
2278 	// More generally, if we invoke callbacks from within a client callback, then those callbacks could deregister other
2279 	// records, thereby invoking yet more callbacks, without limit.
2280 	// The solution is to defer delivering the "Remove" events until mDNS_Execute time, just like we do for sending
2281 	// actual goodbye packets.
2282 
2283 #ifndef UNICAST_DISABLED
2284 	if (AuthRecord_uDNS(rr) && rr->RequireGoodbye)
2285 		{
2286 		if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
2287 		rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
2288 		uDNS_DeregisterRecord(m, rr);
2289 		// At this point unconditionally we bail out
2290 		// Either uDNS_DeregisterRecord will have completed synchronously, and called CompleteDeregistration,
2291 		// which calls us back here with RequireGoodbye set to false, or it will have initiated the deregistration
2292 		// process and will complete asynchronously. Either way we don't need to do anything more here.
2293 		return(mStatus_NoError);
2294 		}
2295 #endif // UNICAST_DISABLED
2296 
2297 	if (RecordType == kDNSRecordTypeShared && (rr->RequireGoodbye || rr->AnsweredLocalQ))
2298 		{
2299 		verbosedebugf("mDNS_Deregister_internal: Sending deregister for %s", ARDisplayString(m, rr));
2300 		rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
2301 		rr->resrec.rroriginalttl = 0;
2302 		rr->ImmedAnswer          = mDNSInterfaceMark;
2303 		if (m->NextScheduledResponse - (m->timenow + mDNSPlatformOneSecond/10) >= 0)
2304 			m->NextScheduledResponse = (m->timenow + mDNSPlatformOneSecond/10);
2305 		}
2306 	else
2307 		{
2308 		*p = rr->next;					// Cut this record from the list
2309 		// If someone is about to look at this, bump the pointer forward
2310 		if (m->CurrentRecord   == rr) m->CurrentRecord   = rr->next;
2311 		if (m->NewLocalRecords == rr) m->NewLocalRecords = rr->next;
2312 		rr->next = mDNSNULL;
2313 
2314 		if      (RecordType == kDNSRecordTypeUnregistered)
2315 			LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeUnregistered", ARDisplayString(m, rr));
2316 		else if (RecordType == kDNSRecordTypeDeregistering)
2317 			LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeDeregistering", ARDisplayString(m, rr));
2318 		else
2319 			{
2320 			verbosedebugf("mDNS_Deregister_internal: Deleting record for %s", ARDisplayString(m, rr));
2321 			rr->resrec.RecordType = kDNSRecordTypeUnregistered;
2322 			}
2323 
2324 		if ((drt == mDNS_Dereg_conflict || drt == mDNS_Dereg_repeat) && RecordType == kDNSRecordTypeShared)
2325 			debugf("mDNS_Deregister_internal: Cannot have a conflict on a shared record! %##s (%s)",
2326 				rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
2327 
2328 		// If we have an update queued up which never executed, give the client a chance to free that memory
2329 		if (rr->NewRData) CompleteRDataUpdate(m, rr);	// Update our rdata, clear the NewRData pointer, and return memory to the client
2330 
2331 		if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
2332 		if (rr->tcp) { DisposeTCPConn(rr->tcp);       rr->tcp = mDNSNULL; }
2333 
2334 		// CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
2335 		// is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
2336 		// In this case the likely client action to the mStatus_MemFree message is to free the memory,
2337 		// so any attempt to touch rr after this is likely to lead to a crash.
2338 		if (drt != mDNS_Dereg_conflict)
2339 			{
2340 			mDNS_DropLockBeforeCallback();		// Allow client to legally make mDNS API calls from the callback
2341 			if (rr->RecordCallback)
2342 				rr->RecordCallback(m, rr, mStatus_MemFree);			// MUST NOT touch rr after this
2343 			mDNS_ReclaimLockAfterCallback();	// Decrement mDNS_reentrancy to block mDNS API calls again
2344 			}
2345 		else
2346 			{
2347 			RecordProbeFailure(m, rr);
2348 			mDNS_DropLockBeforeCallback();		// Allow client to legally make mDNS API calls from the callback
2349 			if (rr->RecordCallback)
2350 				rr->RecordCallback(m, rr, mStatus_NameConflict);	// MUST NOT touch rr after this
2351 			mDNS_ReclaimLockAfterCallback();	// Decrement mDNS_reentrancy to block mDNS API calls again
2352 			// Now that we've finished deregistering rr, check our DuplicateRecords list for any that we marked previously.
2353 			// Note that with all the client callbacks going on, by the time we get here all the
2354 			// records we marked may have been explicitly deregistered by the client anyway.
2355 			r2 = m->DuplicateRecords;
2356 			while (r2)
2357 				{
2358 				if (r2->ProbeCount != 0xFF) r2 = r2->next;
2359 				else { mDNS_Deregister_internal(m, r2, mDNS_Dereg_conflict); r2 = m->DuplicateRecords; }
2360 				}
2361 			}
2362 		}
2363 	return(mStatus_NoError);
2364 	}
2365 
2366 // ***************************************************************************
2367 #if COMPILER_LIKES_PRAGMA_MARK
2368 #pragma mark -
2369 #pragma mark - Packet Sending Functions
2370 #endif
2371 
2372 mDNSlocal void AddRecordToResponseList(AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *add)
2373 	{
2374 	if (rr->NextResponse == mDNSNULL && *nrpp != &rr->NextResponse)
2375 		{
2376 		**nrpp = rr;
2377 		// NR_AdditionalTo must point to a record with NR_AnswerTo set (and not NR_AdditionalTo)
2378 		// If 'add' does not meet this requirement, then follow its NR_AdditionalTo pointer to a record that does
2379 		// The referenced record will definitely be acceptable (by recursive application of this rule)
2380 		if (add && add->NR_AdditionalTo) add = add->NR_AdditionalTo;
2381 		rr->NR_AdditionalTo = add;
2382 		*nrpp = &rr->NextResponse;
2383 		}
2384 	debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
2385 	}
2386 
2387 mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseRecords, AuthRecord ***nrpp, const mDNSInterfaceID InterfaceID)
2388 	{
2389 	AuthRecord  *rr, *rr2;
2390 	for (rr=ResponseRecords; rr; rr=rr->NextResponse)			// For each record we plan to put
2391 		{
2392 		// (Note: This is an "if", not a "while". If we add a record, we'll find it again
2393 		// later in the "for" loop, and we will follow further "additional" links then.)
2394 		if (rr->Additional1 && ResourceRecordIsValidInterfaceAnswer(rr->Additional1, InterfaceID))
2395 			AddRecordToResponseList(nrpp, rr->Additional1, rr);
2396 
2397 		if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID))
2398 			AddRecordToResponseList(nrpp, rr->Additional2, rr);
2399 
2400 		// For SRV records, automatically add the Address record(s) for the target host
2401 		if (rr->resrec.rrtype == kDNSType_SRV)
2402 			{
2403 			for (rr2=m->ResourceRecords; rr2; rr2=rr2->next)					// Scan list of resource records
2404 				if (RRTypeIsAddressType(rr2->resrec.rrtype) &&					// For all address records (A/AAAA) ...
2405 					ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&	// ... which are valid for answer ...
2406 					rr->resrec.rdatahash == rr2->resrec.namehash &&			// ... whose name is the name of the SRV target
2407 					SameDomainName(&rr->resrec.rdata->u.srv.target, rr2->resrec.name))
2408 					AddRecordToResponseList(nrpp, rr2, rr);
2409 			}
2410 		else if (RRTypeIsAddressType(rr->resrec.rrtype))	// For A or AAAA, put counterpart as additional
2411 			{
2412 			for (rr2=m->ResourceRecords; rr2; rr2=rr2->next)					// Scan list of resource records
2413 				if (RRTypeIsAddressType(rr2->resrec.rrtype) &&					// For all address records (A/AAAA) ...
2414 					ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&	// ... which are valid for answer ...
2415 					rr->resrec.namehash == rr2->resrec.namehash &&				// ... and have the same name
2416 					SameDomainName(rr->resrec.name, rr2->resrec.name))
2417 					AddRecordToResponseList(nrpp, rr2, rr);
2418 			}
2419 		else if (rr->resrec.rrtype == kDNSType_PTR)			// For service PTR, see if we want to add DeviceInfo record
2420 			{
2421 			if (ResourceRecordIsValidInterfaceAnswer(&m->DeviceInfo, InterfaceID) &&
2422 				SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c))
2423 				AddRecordToResponseList(nrpp, &m->DeviceInfo, rr);
2424 			}
2425 		}
2426 	}
2427 
2428 mDNSlocal void SendDelayedUnicastResponse(mDNS *const m, const mDNSAddr *const dest, const mDNSInterfaceID InterfaceID)
2429 	{
2430 	AuthRecord *rr;
2431 	AuthRecord  *ResponseRecords = mDNSNULL;
2432 	AuthRecord **nrp             = &ResponseRecords;
2433 
2434 	// Make a list of all our records that need to be unicast to this destination
2435 	for (rr = m->ResourceRecords; rr; rr=rr->next)
2436 		{
2437 		// If we find we can no longer unicast this answer, clear ImmedUnicast
2438 		if (rr->ImmedAnswer == mDNSInterfaceMark               ||
2439 			mDNSSameIPv4Address(rr->v4Requester, onesIPv4Addr) ||
2440 			mDNSSameIPv6Address(rr->v6Requester, onesIPv6Addr)  )
2441 			rr->ImmedUnicast = mDNSfalse;
2442 
2443 		if (rr->ImmedUnicast && rr->ImmedAnswer == InterfaceID)
2444 			if ((dest->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->v4Requester, dest->ip.v4)) ||
2445 				(dest->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->v6Requester, dest->ip.v6)))
2446 				{
2447 				rr->ImmedAnswer  = mDNSNULL;				// Clear the state fields
2448 				rr->ImmedUnicast = mDNSfalse;
2449 				rr->v4Requester  = zerov4Addr;
2450 				rr->v6Requester  = zerov6Addr;
2451 				if (rr->NextResponse == mDNSNULL && nrp != &rr->NextResponse)	// rr->NR_AnswerTo
2452 					{ rr->NR_AnswerTo = (mDNSu8*)~0; *nrp = rr; nrp = &rr->NextResponse; }
2453 				}
2454 		}
2455 
2456 	AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID);
2457 
2458 	while (ResponseRecords)
2459 		{
2460 		mDNSu8 *responseptr = m->omsg.data;
2461 		mDNSu8 *newptr;
2462 		InitializeDNSMessage(&m->omsg.h, zeroID, ResponseFlags);
2463 
2464 		// Put answers in the packet
2465 		while (ResponseRecords && ResponseRecords->NR_AnswerTo)
2466 			{
2467 			rr = ResponseRecords;
2468 			if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2469 				rr->resrec.rrclass |= kDNSClass_UniqueRRSet;		// Temporarily set the cache flush bit so PutResourceRecord will set it
2470 			newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec);
2471 			rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;			// Make sure to clear cache flush bit back to normal state
2472 			if (!newptr && m->omsg.h.numAnswers) break;	// If packet full, send it now
2473 			if (newptr) responseptr = newptr;
2474 			ResponseRecords = rr->NextResponse;
2475 			rr->NextResponse    = mDNSNULL;
2476 			rr->NR_AnswerTo     = mDNSNULL;
2477 			rr->NR_AdditionalTo = mDNSNULL;
2478 			rr->RequireGoodbye  = mDNStrue;
2479 			}
2480 
2481 		// Add additionals, if there's space
2482 		while (ResponseRecords && !ResponseRecords->NR_AnswerTo)
2483 			{
2484 			rr = ResponseRecords;
2485 			if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2486 				rr->resrec.rrclass |= kDNSClass_UniqueRRSet;		// Temporarily set the cache flush bit so PutResourceRecord will set it
2487 			newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &rr->resrec);
2488 			rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;			// Make sure to clear cache flush bit back to normal state
2489 
2490 			if (newptr) responseptr = newptr;
2491 			if (newptr && m->omsg.h.numAnswers) rr->RequireGoodbye = mDNStrue;
2492 			else if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) rr->ImmedAnswer = mDNSInterfaceMark;
2493 			ResponseRecords = rr->NextResponse;
2494 			rr->NextResponse    = mDNSNULL;
2495 			rr->NR_AnswerTo     = mDNSNULL;
2496 			rr->NR_AdditionalTo = mDNSNULL;
2497 			}
2498 
2499 		if (m->omsg.h.numAnswers) mDNSSendDNSMessage(m, &m->omsg, responseptr, mDNSInterface_Any, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSNULL);
2500 		}
2501 	}
2502 
2503 mDNSexport void CompleteDeregistration(mDNS *const m, AuthRecord *rr)
2504 	{
2505 	// Clearing rr->RequireGoodbye signals mDNS_Deregister_internal() that
2506 	// it should go ahead and immediately dispose of this registration
2507 	rr->resrec.RecordType = kDNSRecordTypeShared;
2508 	rr->RequireGoodbye    = mDNSfalse;
2509 	if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse); rr->AnsweredLocalQ = mDNSfalse; }
2510 	mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);		// Don't touch rr after this
2511 	}
2512 
2513 // Note: DiscardDeregistrations calls mDNS_Deregister_internal which can call a user callback, which may change
2514 // the record list and/or question list.
2515 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
2516 mDNSlocal void DiscardDeregistrations(mDNS *const m)
2517 	{
2518 	if (m->CurrentRecord)
2519 		LogMsg("DiscardDeregistrations ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
2520 	m->CurrentRecord = m->ResourceRecords;
2521 
2522 	while (m->CurrentRecord)
2523 		{
2524 		AuthRecord *rr = m->CurrentRecord;
2525 		if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
2526 			CompleteDeregistration(m, rr);		// Don't touch rr after this
2527 		else
2528 			m->CurrentRecord = rr->next;
2529 		}
2530 	}
2531 
2532 mDNSlocal mStatus GetLabelDecimalValue(const mDNSu8 *const src, mDNSu8 *dst)
2533 	{
2534 	int i, val = 0;
2535 	if (src[0] < 1 || src[0] > 3) return(mStatus_Invalid);
2536 	for (i=1; i<=src[0]; i++)
2537 		{
2538 		if (src[i] < '0' || src[i] > '9') return(mStatus_Invalid);
2539 		val = val * 10 + src[i] - '0';
2540 		}
2541 	if (val > 255) return(mStatus_Invalid);
2542 	*dst = val;
2543 	return(mStatus_NoError);
2544 	}
2545 
2546 mDNSlocal mStatus GetIPv4FromName(mDNSAddr *const a, const domainname *const name)
2547 	{
2548 	int skip = CountLabels(name) - 6;
2549 	if (skip < 0) { LogMsg("GetIPFromName: Need six labels in IPv4 reverse mapping name %##s", name); return mStatus_Invalid; }
2550 	if (GetLabelDecimalValue(SkipLeadingLabels(name, skip+3)->c, &a->ip.v4.b[0]) ||
2551 		GetLabelDecimalValue(SkipLeadingLabels(name, skip+2)->c, &a->ip.v4.b[1]) ||
2552 		GetLabelDecimalValue(SkipLeadingLabels(name, skip+1)->c, &a->ip.v4.b[2]) ||
2553 		GetLabelDecimalValue(SkipLeadingLabels(name, skip+0)->c, &a->ip.v4.b[3])) return mStatus_Invalid;
2554 	a->type = mDNSAddrType_IPv4;
2555 	return(mStatus_NoError);
2556 	}
2557 
2558 #define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0'     ) :   \
2559 					((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) :   \
2560 					((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : -1)
2561 
2562 mDNSlocal mStatus GetIPv6FromName(mDNSAddr *const a, const domainname *const name)
2563 	{
2564 	int i, h, l;
2565 	const domainname *n;
2566 
2567 	int skip = CountLabels(name) - 34;
2568 	if (skip < 0) { LogMsg("GetIPFromName: Need 34 labels in IPv6 reverse mapping name %##s", name); return mStatus_Invalid; }
2569 
2570 	n = SkipLeadingLabels(name, skip);
2571 	for (i=0; i<16; i++)
2572 		{
2573 		if (n->c[0] != 1) return mStatus_Invalid;
2574 		l = HexVal(n->c[1]);
2575 		n = (const domainname *)(n->c + 2);
2576 
2577 		if (n->c[0] != 1) return mStatus_Invalid;
2578 		h = HexVal(n->c[1]);
2579 		n = (const domainname *)(n->c + 2);
2580 
2581 		if (l<0 || h<0) return mStatus_Invalid;
2582 		a->ip.v6.b[15-i] = (h << 4) | l;
2583 		}
2584 
2585 	a->type = mDNSAddrType_IPv6;
2586 	return(mStatus_NoError);
2587 	}
2588 
2589 mDNSlocal mDNSs32 ReverseMapDomainType(const domainname *const name)
2590 	{
2591 	int skip = CountLabels(name) - 2;
2592 	if (skip >= 0)
2593 		{
2594 		const domainname *suffix = SkipLeadingLabels(name, skip);
2595 		if (SameDomainName(suffix, (const domainname*)"\x7" "in-addr" "\x4" "arpa")) return mDNSAddrType_IPv4;
2596 		if (SameDomainName(suffix, (const domainname*)"\x3" "ip6"     "\x4" "arpa")) return mDNSAddrType_IPv6;
2597 		}
2598 	return(mDNSAddrType_None);
2599 	}
2600 
2601 mDNSlocal void SendARP(mDNS *const m, const mDNSu8 op, const AuthRecord *const rr,
2602 	const mDNSu8 *const spa, const mDNSu8 *const tha, const mDNSu8 *const tpa, const mDNSu8 *const dst)
2603 	{
2604 	int i;
2605 	mDNSu8 *ptr = m->omsg.data;
2606 	NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
2607 	if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found %s", rr->resrec.InterfaceID, ARDisplayString(m,rr)); return; }
2608 
2609 	// 0x00 Destination address
2610 	for (i=0; i<6; i++) *ptr++ = dst[i];
2611 
2612 	// 0x06 Source address (we just use zero -- driver/hardware will fill in real interface address)
2613 	for (i=0; i<6; i++) *ptr++ = 0x0;
2614 
2615 	// 0x0C ARP Ethertype (0x0806)
2616 	*ptr++ = 0x08; *ptr++ = 0x06;
2617 
2618 	// 0x0E ARP header
2619 	*ptr++ = 0x00; *ptr++ = 0x01;	// Hardware address space; Ethernet = 1
2620 	*ptr++ = 0x08; *ptr++ = 0x00;	// Protocol address space; IP = 0x0800
2621 	*ptr++ = 6;						// Hardware address length
2622 	*ptr++ = 4;						// Protocol address length
2623 	*ptr++ = 0x00; *ptr++ = op;		// opcode; Request = 1, Response = 2
2624 
2625 	// 0x16 Sender hardware address (our MAC address)
2626 	for (i=0; i<6; i++) *ptr++ = intf->MAC.b[i];
2627 
2628 	// 0x1C Sender protocol address
2629 	for (i=0; i<4; i++) *ptr++ = spa[i];
2630 
2631 	// 0x20 Target hardware address
2632 	for (i=0; i<6; i++) *ptr++ = tha[i];
2633 
2634 	// 0x26 Target protocol address
2635 	for (i=0; i<4; i++) *ptr++ = tpa[i];
2636 
2637 	// 0x2A Total ARP Packet length 42 bytes
2638 	mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID);
2639 	}
2640 
2641 mDNSlocal void SetupOwnerOpt(const mDNS *const m, const NetworkInterfaceInfo *const intf, rdataOPT *const owner)
2642 	{
2643 	owner->u.owner.vers     = 0;
2644 	owner->u.owner.seq      = m->SleepSeqNum;
2645 	owner->u.owner.HMAC     = m->PrimaryMAC;
2646 	owner->u.owner.IMAC     = intf->MAC;
2647 	owner->u.owner.password = zeroEthAddr;
2648 
2649 	// Don't try to compute the optlen until *after* we've set up the data fields
2650 	owner->opt              = kDNSOpt_Owner;
2651 	owner->optlen           = DNSOpt_Owner_Space(owner) - 4;
2652 	}
2653 
2654 mDNSlocal void GrantUpdateCredit(AuthRecord *rr)
2655 	{
2656 	if (++rr->UpdateCredits >= kMaxUpdateCredits) rr->NextUpdateCredit = 0;
2657 	else rr->NextUpdateCredit = NonZeroTime(rr->NextUpdateCredit + kUpdateCreditRefreshInterval);
2658 	}
2659 
2660 // Note about acceleration of announcements to facilitate automatic coalescing of
2661 // multiple independent threads of announcements into a single synchronized thread:
2662 // The announcements in the packet may be at different stages of maturity;
2663 // One-second interval, two-second interval, four-second interval, and so on.
2664 // After we've put in all the announcements that are due, we then consider
2665 // whether there are other nearly-due announcements that are worth accelerating.
2666 // To be eligible for acceleration, a record MUST NOT be older (further along
2667 // its timeline) than the most mature record we've already put in the packet.
2668 // In other words, younger records can have their timelines accelerated to catch up
2669 // with their elder bretheren; this narrows the age gap and helps them eventually get in sync.
2670 // Older records cannot have their timelines accelerated; this would just widen
2671 // the gap between them and their younger bretheren and get them even more out of sync.
2672 
2673 // Note: SendResponses calls mDNS_Deregister_internal which can call a user callback, which may change
2674 // the record list and/or question list.
2675 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
2676 mDNSlocal void SendResponses(mDNS *const m)
2677 	{
2678 	int pktcount = 0;
2679 	AuthRecord *rr, *r2;
2680 	mDNSs32 maxExistingAnnounceInterval = 0;
2681 	const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
2682 
2683 	m->NextScheduledResponse = m->timenow + 0x78000000;
2684 
2685 	if (m->SleepState == SleepState_Transferring) RetrySPSRegistrations(m);
2686 
2687 	for (rr = m->ResourceRecords; rr; rr=rr->next)
2688 		if (rr->ImmedUnicast)
2689 			{
2690 			mDNSAddr v4 = { mDNSAddrType_IPv4, {{{0}}} };
2691 			mDNSAddr v6 = { mDNSAddrType_IPv6, {{{0}}} };
2692 			v4.ip.v4 = rr->v4Requester;
2693 			v6.ip.v6 = rr->v6Requester;
2694 			if (!mDNSIPv4AddressIsZero(rr->v4Requester)) SendDelayedUnicastResponse(m, &v4, rr->ImmedAnswer);
2695 			if (!mDNSIPv6AddressIsZero(rr->v6Requester)) SendDelayedUnicastResponse(m, &v6, rr->ImmedAnswer);
2696 			if (rr->ImmedUnicast)
2697 				{
2698 				LogMsg("SendResponses: ERROR: rr->ImmedUnicast still set: %s", ARDisplayString(m, rr));
2699 				rr->ImmedUnicast = mDNSfalse;
2700 				}
2701 			}
2702 
2703 	// ***
2704 	// *** 1. Setup: Set the SendRNow and ImmedAnswer fields to indicate which interface(s) the records need to be sent on
2705 	// ***
2706 
2707 	// Run through our list of records, and decide which ones we're going to announce on all interfaces
2708 	for (rr = m->ResourceRecords; rr; rr=rr->next)
2709 		{
2710 		while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
2711 		if (TimeToAnnounceThisRecord(rr, m->timenow) && ResourceRecordIsValidAnswer(rr))
2712 			{
2713 			if (rr->AddressProxy.type)
2714 				{
2715 				rr->AnnounceCount--;
2716 				rr->ThisAPInterval *= 2;
2717 				rr->LastAPTime = m->timenow;
2718 				if (rr->AddressProxy.type == mDNSAddrType_IPv4)
2719 					{
2720 					LogSPS("ARP Announcement %d Capturing traffic for H-MAC %.6a I-MAC %.6a %s", rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr));
2721 					SendARP(m, 1, rr, rr->AddressProxy.ip.v4.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, onesEthAddr.b);
2722 					}
2723 				else if (rr->AddressProxy.type == mDNSAddrType_IPv6)
2724 					{
2725 					//LogSPS("NDP Announcement %d %s", rr->AnnounceCount, ARDisplayString(m,rr));
2726 					//SendARP(m, 1, rr, rr->AddressProxy.ip.v4.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, onesEthAddr.b);
2727 					}
2728 				}
2729 			else
2730 				{
2731 				rr->ImmedAnswer = mDNSInterfaceMark;		// Send on all interfaces
2732 				if (maxExistingAnnounceInterval < rr->ThisAPInterval)
2733 					maxExistingAnnounceInterval = rr->ThisAPInterval;
2734 				if (rr->UpdateBlocked) rr->UpdateBlocked = 0;
2735 				}
2736 			}
2737 		}
2738 
2739 	// Any interface-specific records we're going to send are marked as being sent on all appropriate interfaces (which is just one)
2740 	// Eligible records that are more than half-way to their announcement time are accelerated
2741 	for (rr = m->ResourceRecords; rr; rr=rr->next)
2742 		if ((rr->resrec.InterfaceID && rr->ImmedAnswer) ||
2743 			(rr->ThisAPInterval <= maxExistingAnnounceInterval &&
2744 			TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2) &&
2745 			!rr->AddressProxy.type && 					// Don't include ARP Annoucements when considering which records to accelerate
2746 			ResourceRecordIsValidAnswer(rr)))
2747 			rr->ImmedAnswer = mDNSInterfaceMark;		// Send on all interfaces
2748 
2749 	// When sending SRV records (particularly when announcing a new service) automatically add related Address record(s) as additionals
2750 	// Note: Currently all address records are interface-specific, so it's safe to set ImmedAdditional to their InterfaceID,
2751 	// which will be non-null. If by some chance there is an address record that's not interface-specific (should never happen)
2752 	// then all that means is that it won't get sent -- which would not be the end of the world.
2753 	for (rr = m->ResourceRecords; rr; rr=rr->next)
2754 		{
2755 		if (rr->ImmedAnswer && rr->resrec.rrtype == kDNSType_SRV)
2756 			for (r2=m->ResourceRecords; r2; r2=r2->next)				// Scan list of resource records
2757 				if (RRTypeIsAddressType(r2->resrec.rrtype) &&			// For all address records (A/AAAA) ...
2758 					ResourceRecordIsValidAnswer(r2) &&					// ... which are valid for answer ...
2759 					rr->LastMCTime - r2->LastMCTime >= 0 &&				// ... which we have not sent recently ...
2760 					rr->resrec.rdatahash == r2->resrec.namehash &&		// ... whose name is the name of the SRV target
2761 					SameDomainName(&rr->resrec.rdata->u.srv.target, r2->resrec.name) &&
2762 					(rr->ImmedAnswer == mDNSInterfaceMark || rr->ImmedAnswer == r2->resrec.InterfaceID))
2763 					r2->ImmedAdditional = r2->resrec.InterfaceID;		// ... then mark this address record for sending too
2764 		// We also make sure we send the DeviceInfo TXT record too, if necessary
2765 		// We check for RecordType == kDNSRecordTypeShared because we don't want to tag the
2766 		// DeviceInfo TXT record onto a goodbye packet (RecordType == kDNSRecordTypeDeregistering).
2767 		if (rr->ImmedAnswer && rr->resrec.RecordType == kDNSRecordTypeShared && rr->resrec.rrtype == kDNSType_PTR)
2768 			if (ResourceRecordIsValidAnswer(&m->DeviceInfo) && SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c))
2769 				{
2770 				if (!m->DeviceInfo.ImmedAnswer) m->DeviceInfo.ImmedAnswer = rr->ImmedAnswer;
2771 				else                            m->DeviceInfo.ImmedAnswer = mDNSInterfaceMark;
2772 				}
2773 		}
2774 
2775 	// If there's a record which is supposed to be unique that we're going to send, then make sure that we give
2776 	// the whole RRSet as an atomic unit. That means that if we have any other records with the same name/type/class
2777 	// then we need to mark them for sending too. Otherwise, if we set the kDNSClass_UniqueRRSet bit on a
2778 	// record, then other RRSet members that have not been sent recently will get flushed out of client caches.
2779 	// -- If a record is marked to be sent on a certain interface, make sure the whole set is marked to be sent on that interface
2780 	// -- If any record is marked to be sent on all interfaces, make sure the whole set is marked to be sent on all interfaces
2781 	for (rr = m->ResourceRecords; rr; rr=rr->next)
2782 		if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2783 			{
2784 			if (rr->ImmedAnswer)			// If we're sending this as answer, see that its whole RRSet is similarly marked
2785 				{
2786 				for (r2 = m->ResourceRecords; r2; r2=r2->next)
2787 					if (ResourceRecordIsValidAnswer(r2))
2788 						if (r2->ImmedAnswer != mDNSInterfaceMark &&
2789 							r2->ImmedAnswer != rr->ImmedAnswer && SameResourceRecordSignature(r2, rr))
2790 							r2->ImmedAnswer = !r2->ImmedAnswer ? rr->ImmedAnswer : mDNSInterfaceMark;
2791 				}
2792 			else if (rr->ImmedAdditional)	// If we're sending this as additional, see that its whole RRSet is similarly marked
2793 				{
2794 				for (r2 = m->ResourceRecords; r2; r2=r2->next)
2795 					if (ResourceRecordIsValidAnswer(r2))
2796 						if (r2->ImmedAdditional != rr->ImmedAdditional && SameResourceRecordSignature(r2, rr))
2797 							r2->ImmedAdditional = rr->ImmedAdditional;
2798 				}
2799 			}
2800 
2801 	// Now set SendRNow state appropriately
2802 	for (rr = m->ResourceRecords; rr; rr=rr->next)
2803 		{
2804 		if (rr->ImmedAnswer == mDNSInterfaceMark)		// Sending this record on all appropriate interfaces
2805 			{
2806 			rr->SendRNow = !intf ? mDNSNULL : (rr->resrec.InterfaceID) ? rr->resrec.InterfaceID : intf->InterfaceID;
2807 			rr->ImmedAdditional = mDNSNULL;				// No need to send as additional if sending as answer
2808 			rr->LastMCTime      = m->timenow;
2809 			rr->LastMCInterface = rr->ImmedAnswer;
2810 			// If we're announcing this record, and it's at least half-way to its ordained time, then consider this announcement done
2811 			if (TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2))
2812 				{
2813 				rr->AnnounceCount--;
2814 				rr->ThisAPInterval *= 2;
2815 				rr->LastAPTime = m->timenow;
2816 				debugf("Announcing %##s (%s) %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->AnnounceCount);
2817 				}
2818 			}
2819 		else if (rr->ImmedAnswer)						// Else, just respond to a single query on single interface:
2820 			{
2821 			rr->SendRNow        = rr->ImmedAnswer;		// Just respond on that interface
2822 			rr->ImmedAdditional = mDNSNULL;				// No need to send as additional too
2823 			rr->LastMCTime      = m->timenow;
2824 			rr->LastMCInterface = rr->ImmedAnswer;
2825 			}
2826 		SetNextAnnounceProbeTime(m, rr);
2827 		//if (rr->SendRNow) LogMsg("%-15.4a %s", &rr->v4Requester, ARDisplayString(m, rr));
2828 		}
2829 
2830 	// ***
2831 	// *** 2. Loop through interface list, sending records as appropriate
2832 	// ***
2833 
2834 	while (intf)
2835 		{
2836 		int numDereg    = 0;
2837 		int numAnnounce = 0;
2838 		int numAnswer   = 0;
2839 		mDNSu8 *responseptr = m->omsg.data;
2840 		mDNSu8 *newptr;
2841 		InitializeDNSMessage(&m->omsg.h, zeroID, ResponseFlags);
2842 
2843 		// First Pass. Look for:
2844 		// 1. Deregistering records that need to send their goodbye packet
2845 		// 2. Updated records that need to retract their old data
2846 		// 3. Answers and announcements we need to send
2847 		for (rr = m->ResourceRecords; rr; rr=rr->next)
2848 			{
2849 			if (rr->SendRNow == intf->InterfaceID)
2850 				{
2851 				newptr = mDNSNULL;
2852 				if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
2853 					{
2854 					newptr = PutResourceRecordTTL(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec, 0);
2855 					if (newptr) { responseptr = newptr; numDereg++; }
2856 					}
2857 				else if (rr->NewRData && !m->SleepState)					// If we have new data for this record
2858 					{
2859 					RData *OldRData     = rr->resrec.rdata;
2860 					mDNSu16 oldrdlength = rr->resrec.rdlength;
2861 					// See if we should send a courtesy "goodbye" for the old data before we replace it.
2862 					if (ResourceRecordIsValidAnswer(rr) && rr->RequireGoodbye)
2863 						{
2864 						newptr = PutResourceRecordTTL(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec, 0);
2865 						if (newptr) { responseptr = newptr; numDereg++; rr->RequireGoodbye = mDNSfalse; }
2866 						}
2867 					// Now try to see if we can fit the update in the same packet (not fatal if we can't)
2868 					SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);
2869 					if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2870 						rr->resrec.rrclass |= kDNSClass_UniqueRRSet;		// Temporarily set the cache flush bit so PutResourceRecord will set it
2871 					newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec);
2872 					rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;			// Make sure to clear cache flush bit back to normal state
2873 					if (newptr) { responseptr = newptr; rr->RequireGoodbye = mDNStrue; }
2874 					SetNewRData(&rr->resrec, OldRData, oldrdlength);
2875 					}
2876 				else
2877 					{
2878 					mDNSu8 active = (m->SleepState != SleepState_Sleeping || intf->SPSAddr[0].type || intf->SPSAddr[1].type || intf->SPSAddr[2].type);
2879 					if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2880 						rr->resrec.rrclass |= kDNSClass_UniqueRRSet;		// Temporarily set the cache flush bit so PutResourceRecord will set it
2881 					newptr = PutResourceRecordTTL(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec, active ? rr->resrec.rroriginalttl : 0);
2882 					rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;			// Make sure to clear cache flush bit back to normal state
2883 					if (newptr)
2884 						{
2885 						responseptr = newptr;
2886 						rr->RequireGoodbye = active;
2887 						if (rr->LastAPTime == m->timenow) numAnnounce++; else numAnswer++;
2888 						}
2889 
2890 					// The first time through (pktcount==0), if this record is verified unique
2891 					// (i.e. typically A, AAAA, SRV and TXT), set the flag to add an NSEC too.
2892 					if (!pktcount && active && rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->SendNSECNow) rr->SendNSECNow = (mDNSInterfaceID)1;
2893 					}
2894 
2895 				if (newptr)		// If succeeded in sending, advance to next interface
2896 					{
2897 					// If sending on all interfaces, go to next interface; else we're finished now
2898 					if (rr->ImmedAnswer == mDNSInterfaceMark && rr->resrec.InterfaceID == mDNSInterface_Any)
2899 						rr->SendRNow = GetNextActiveInterfaceID(intf);
2900 					else
2901 						rr->SendRNow = mDNSNULL;
2902 					}
2903 				}
2904 			}
2905 
2906 		// Second Pass. Add additional records, if there's space.
2907 		newptr = responseptr;
2908 		for (rr = m->ResourceRecords; rr; rr=rr->next)
2909 			if (rr->ImmedAdditional == intf->InterfaceID)
2910 				if (ResourceRecordIsValidAnswer(rr))
2911 					{
2912 					// If we have at least one answer already in the packet, then plan to add additionals too
2913 					mDNSBool SendAdditional = (m->omsg.h.numAnswers > 0);
2914 
2915 					// If we're not planning to send any additionals, but this record is a unique one, then
2916 					// make sure we haven't already sent any other members of its RRSet -- if we have, then they
2917 					// will have had the cache flush bit set, so now we need to finish the job and send the rest.
2918 					if (!SendAdditional && (rr->resrec.RecordType & kDNSRecordTypeUniqueMask))
2919 						{
2920 						const AuthRecord *a;
2921 						for (a = m->ResourceRecords; a; a=a->next)
2922 							if (a->LastMCTime      == m->timenow &&
2923 								a->LastMCInterface == intf->InterfaceID &&
2924 								SameResourceRecordSignature(a, rr)) { SendAdditional = mDNStrue; break; }
2925 						}
2926 					if (!SendAdditional)					// If we don't want to send this after all,
2927 						rr->ImmedAdditional = mDNSNULL;		// then cancel its ImmedAdditional field
2928 					else if (newptr)						// Else, try to add it if we can
2929 						{
2930 						// The first time through (pktcount==0), if this record is verified unique
2931 						// (i.e. typically A, AAAA, SRV and TXT), set the flag to add an NSEC too.
2932 						if (!pktcount && rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->SendNSECNow) rr->SendNSECNow = (mDNSInterfaceID)1;
2933 
2934 						if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2935 							rr->resrec.rrclass |= kDNSClass_UniqueRRSet;	// Temporarily set the cache flush bit so PutResourceRecord will set it
2936 						newptr = PutResourceRecord(&m->omsg, newptr, &m->omsg.h.numAdditionals, &rr->resrec);
2937 						rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;		// Make sure to clear cache flush bit back to normal state
2938 						if (newptr)
2939 							{
2940 							responseptr = newptr;
2941 							rr->ImmedAdditional = mDNSNULL;
2942 							rr->RequireGoodbye = mDNStrue;
2943 							// If we successfully put this additional record in the packet, we record LastMCTime & LastMCInterface.
2944 							// This matters particularly in the case where we have more than one IPv6 (or IPv4) address, because otherwise,
2945 							// when we see our own multicast with the cache flush bit set, if we haven't set LastMCTime, then we'll get
2946 							// all concerned and re-announce our record again to make sure it doesn't get flushed from peer caches.
2947 							rr->LastMCTime      = m->timenow;
2948 							rr->LastMCInterface = intf->InterfaceID;
2949 							}
2950 						}
2951 					}
2952 
2953 		// Third Pass. Add NSEC records, if there's space.
2954 		for (rr = m->ResourceRecords; rr; rr=rr->next)
2955 			if (rr->SendNSECNow == (mDNSInterfaceID)1 || rr->SendNSECNow == intf->InterfaceID)
2956 				{
2957 				AuthRecord nsec;
2958 				mDNS_SetupResourceRecord(&nsec, mDNSNULL, mDNSInterface_Any, kDNSType_NSEC, rr->resrec.rroriginalttl, kDNSRecordTypeUnique, mDNSNULL, mDNSNULL);
2959 				nsec.resrec.rrclass |= kDNSClass_UniqueRRSet;
2960 				AssignDomainName(&nsec.namestorage, rr->resrec.name);
2961 				mDNSPlatformMemZero(nsec.rdatastorage.u.nsec.bitmap, sizeof(nsec.rdatastorage.u.nsec.bitmap));
2962 				for (r2 = m->ResourceRecords; r2; r2=r2->next)
2963 					if (ResourceRecordIsValidAnswer(r2) && SameResourceRecordNameClassInterface(r2, rr))
2964 						{
2965 						if (r2->resrec.rrtype >= kDNSQType_ANY) { LogMsg("Can't create NSEC for record %s", ARDisplayString(m, r2)); break; }
2966 						else nsec.rdatastorage.u.nsec.bitmap[r2->resrec.rrtype >> 3] |= 128 >> (r2->resrec.rrtype & 7);
2967 						}
2968 				newptr = responseptr;
2969 				if (!r2)	// If we successfully built our NSEC record, add it to the packet now
2970 					{
2971 					newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &nsec.resrec);
2972 					if (newptr) responseptr = newptr;
2973 					}
2974 
2975 				// If we successfully put the NSEC record, clear the SendNSECNow flag
2976 				// If we consider this NSEC optional, then we unconditionally clear the SendNSECNow flag, even if we fail to put this additional record
2977 				if (newptr || rr->SendNSECNow == (mDNSInterfaceID)1)
2978 					{
2979 					rr->SendNSECNow = mDNSNULL;
2980 					// Run through remainder of list clearing SendNSECNow flag for all other records which would generate the same NSEC
2981 					for (r2 = rr->next; r2; r2=r2->next)
2982 						if (SameResourceRecordNameClassInterface(r2, rr))
2983 							if (r2->SendNSECNow == (mDNSInterfaceID)1 || r2->SendNSECNow == intf->InterfaceID)
2984 								r2->SendNSECNow = mDNSNULL;
2985 					}
2986 				}
2987 
2988 		if (m->omsg.h.numAnswers > 0 || m->omsg.h.numAdditionals)
2989 			{
2990 			debugf("SendResponses: Sending %d Deregistration%s, %d Announcement%s, %d Answer%s, %d Additional%s on %p",
2991 				numDereg,                 numDereg                 == 1 ? "" : "s",
2992 				numAnnounce,              numAnnounce              == 1 ? "" : "s",
2993 				numAnswer,                numAnswer                == 1 ? "" : "s",
2994 				m->omsg.h.numAdditionals, m->omsg.h.numAdditionals == 1 ? "" : "s", intf->InterfaceID);
2995 			if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL);
2996 			if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL);
2997 			if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10);
2998 			if (++pktcount >= 1000) { LogMsg("SendResponses exceeded loop limit %d: giving up", pktcount); break; }
2999 			// There might be more things to send on this interface, so go around one more time and try again.
3000 			}
3001 		else	// Nothing more to send on this interface; go to next
3002 			{
3003 			const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next);
3004 			#if MDNS_DEBUGMSGS && 0
3005 			const char *const msg = next ? "SendResponses: Nothing more on %p; moving to %p" : "SendResponses: Nothing more on %p";
3006 			debugf(msg, intf, next);
3007 			#endif
3008 			intf = next;
3009 			pktcount = 0;		// When we move to a new interface, reset packet count back to zero -- NSEC generation logic uses it
3010 			}
3011 		}
3012 
3013 	// ***
3014 	// *** 3. Cleanup: Now that everything is sent, call client callback functions, and reset state variables
3015 	// ***
3016 
3017 	if (m->CurrentRecord)
3018 		LogMsg("SendResponses ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
3019 	m->CurrentRecord = m->ResourceRecords;
3020 	while (m->CurrentRecord)
3021 		{
3022 		rr = m->CurrentRecord;
3023 		m->CurrentRecord = rr->next;
3024 
3025 		if (rr->SendRNow)
3026 			{
3027 			if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
3028 				LogMsg("SendResponses: No active interface to send: %02X %s", rr->resrec.RecordType, ARDisplayString(m, rr));
3029 			rr->SendRNow = mDNSNULL;
3030 			}
3031 
3032 		if (rr->ImmedAnswer)
3033 			{
3034 			if (rr->NewRData) CompleteRDataUpdate(m, rr);	// Update our rdata, clear the NewRData pointer, and return memory to the client
3035 
3036 			if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
3037 				CompleteDeregistration(m, rr);		// Don't touch rr after this
3038 			else
3039 				{
3040 				rr->ImmedAnswer  = mDNSNULL;
3041 				rr->ImmedUnicast = mDNSfalse;
3042 				rr->v4Requester  = zerov4Addr;
3043 				rr->v6Requester  = zerov6Addr;
3044 				}
3045 			}
3046 		}
3047 	verbosedebugf("SendResponses: Next in %ld ticks", m->NextScheduledResponse - m->timenow);
3048 	}
3049 
3050 // Calling CheckCacheExpiration() is an expensive operation because it has to look at the entire cache,
3051 // so we want to be lazy about how frequently we do it.
3052 // 1. If a cache record is currently referenced by *no* active questions,
3053 //    then we don't mind expiring it up to a minute late (who will know?)
3054 // 2. Else, if a cache record is due for some of its final expiration queries,
3055 //    we'll allow them to be late by up to 2% of the TTL
3056 // 3. Else, if a cache record has completed all its final expiration queries without success,
3057 //    and is expiring, and had an original TTL more than ten seconds, we'll allow it to be one second late
3058 // 4. Else, it is expiring and had an original TTL of ten seconds or less (includes explicit goodbye packets),
3059 //    so allow at most 1/10 second lateness
3060 // 5. For records with rroriginalttl set to zero, that means we really want to delete them immediately
3061 //    (we have a new record with DelayDelivery set, waiting for the old record to go away before we can notify clients).
3062 #define CacheCheckGracePeriod(RR) (                                                   \
3063 	((RR)->DelayDelivery                           ) ? (mDNSPlatformOneSecond/10)   : \
3064 	((RR)->CRActiveQuestion == mDNSNULL            ) ? (60 * mDNSPlatformOneSecond) : \
3065 	((RR)->UnansweredQueries < MaxUnansweredQueries) ? (TicksTTL(rr)/50)            : \
3066 	((RR)->resrec.rroriginalttl > 10               ) ? (mDNSPlatformOneSecond)      : \
3067 	((RR)->resrec.rroriginalttl > 0                ) ? (mDNSPlatformOneSecond/10)   : 0)
3068 
3069 // Note: MUST call SetNextCacheCheckTime any time we change:
3070 // rr->TimeRcvd
3071 // rr->resrec.rroriginalttl
3072 // rr->UnansweredQueries
3073 // rr->CRActiveQuestion
3074 // Also, any time we set rr->DelayDelivery we should call SetNextCacheCheckTime to ensure m->NextCacheCheck is set if necessary
3075 // Clearing rr->DelayDelivery does not require a call to SetNextCacheCheckTime
3076 mDNSlocal void SetNextCacheCheckTime(mDNS *const m, CacheRecord *const rr)
3077 	{
3078 	rr->NextRequiredQuery = RRExpireTime(rr);
3079 
3080 	// If we have an active question, then see if we want to schedule a refresher query for this record.
3081 	// Usually we expect to do four queries, at 80-82%, 85-87%, 90-92% and then 95-97% of the TTL.
3082 	if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
3083 		{
3084 		rr->NextRequiredQuery -= TicksTTL(rr)/20 * (MaxUnansweredQueries - rr->UnansweredQueries);
3085 		rr->NextRequiredQuery += mDNSRandom((mDNSu32)TicksTTL(rr)/50);
3086 		verbosedebugf("SetNextCacheCheckTime: %##s (%s) NextRequiredQuery in %ld sec CacheCheckGracePeriod %d ticks",
3087 			rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype),
3088 			(rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr));
3089 		}
3090 
3091 	if (m->NextCacheCheck - (rr->NextRequiredQuery + CacheCheckGracePeriod(rr)) > 0)
3092 		m->NextCacheCheck = (rr->NextRequiredQuery + CacheCheckGracePeriod(rr));
3093 
3094 	if (rr->DelayDelivery)
3095 		if (m->NextCacheCheck - rr->DelayDelivery > 0)
3096 			m->NextCacheCheck = rr->DelayDelivery;
3097 	}
3098 
3099 #define kMinimumReconfirmTime                     ((mDNSu32)mDNSPlatformOneSecond *  5)
3100 #define kDefaultReconfirmTimeForWake              ((mDNSu32)mDNSPlatformOneSecond *  5)
3101 #define kDefaultReconfirmTimeForNoAnswer          ((mDNSu32)mDNSPlatformOneSecond *  5)
3102 #define kDefaultReconfirmTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond * 30)
3103 
3104 mDNSlocal mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval)
3105 	{
3106 	if (interval < kMinimumReconfirmTime)
3107 		interval = kMinimumReconfirmTime;
3108 	if (interval > 0x10000000)	// Make sure interval doesn't overflow when we multiply by four below
3109 		interval = 0x10000000;
3110 
3111 	// If the expected expiration time for this record is more than interval+33%, then accelerate its expiration
3112 	if (RRExpireTime(rr) - m->timenow > (mDNSs32)((interval * 4) / 3))
3113 		{
3114 		// Add a 33% random amount to the interval, to avoid synchronization between multiple hosts
3115 		// For all the reconfirmations in a given batch, we want to use the same random value
3116 		// so that the reconfirmation questions can be grouped into a single query packet
3117 		if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(0x3FFFFFFF);
3118 		interval += m->RandomReconfirmDelay % ((interval/3) + 1);
3119 		rr->TimeRcvd          = m->timenow - (mDNSs32)interval * 3;
3120 		rr->resrec.rroriginalttl     = (interval * 4 + mDNSPlatformOneSecond - 1) / mDNSPlatformOneSecond;
3121 		SetNextCacheCheckTime(m, rr);
3122 		}
3123 	debugf("mDNS_Reconfirm_internal:%6ld ticks to go for %s %p",
3124 		RRExpireTime(rr) - m->timenow, CRDisplayString(m, rr), rr->CRActiveQuestion);
3125 	return(mStatus_NoError);
3126 	}
3127 
3128 #define MaxQuestionInterval         (3600 * mDNSPlatformOneSecond)
3129 
3130 // BuildQuestion puts a question into a DNS Query packet and if successful, updates the value of queryptr.
3131 // It also appends to the list of known answer records that need to be included,
3132 // and updates the forcast for the size of the known answer section.
3133 mDNSlocal mDNSBool BuildQuestion(mDNS *const m, DNSMessage *query, mDNSu8 **queryptr, DNSQuestion *q,
3134 	CacheRecord ***kalistptrptr, mDNSu32 *answerforecast)
3135 	{
3136 	mDNSBool ucast = (q->LargeAnswers || q->RequestUnicast) && m->CanReceiveUnicastOn5353;
3137 	mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
3138 	const mDNSu8 *const limit = query->data + NormalMaxDNSMessageData;
3139 	mDNSu8 *newptr = putQuestion(query, *queryptr, limit, &q->qname, q->qtype, (mDNSu16)(q->qclass | ucbit));
3140 	if (!newptr)
3141 		{
3142 		debugf("BuildQuestion: No more space in this packet for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
3143 		return(mDNSfalse);
3144 		}
3145 	else if (newptr + *answerforecast >= limit)
3146 		{
3147 		verbosedebugf("BuildQuestion: Retracting question %##s (%s) new forecast total %d",
3148 			q->qname.c, DNSTypeName(q->qtype), newptr + *answerforecast - query->data);
3149 		query->h.numQuestions--;
3150 		return(mDNSfalse);
3151 		}
3152 	else
3153 		{
3154 		mDNSu32 forecast = *answerforecast;
3155 		const mDNSu32 slot = HashSlot(&q->qname);
3156 		const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
3157 		CacheRecord *rr;
3158 		CacheRecord **ka = *kalistptrptr;	// Make a working copy of the pointer we're going to update
3159 
3160 		for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)				// If we have a resource record in our cache,
3161 			if (rr->resrec.InterfaceID == q->SendQNow &&					// received on this interface
3162 				rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList &&	// which is not already in the known answer list
3163 				rr->resrec.rdlength <= SmallRecordLimit &&					// which is small enough to sensibly fit in the packet
3164 				SameNameRecordAnswersQuestion(&rr->resrec, q) &&			// which answers our question
3165 				rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow >				// and its half-way-to-expiry time is at least 1 second away
3166 												mDNSPlatformOneSecond)		// (also ensures we never include goodbye records with TTL=1)
3167 				{
3168 				*ka = rr;	// Link this record into our known answer chain
3169 				ka = &rr->NextInKAList;
3170 				// We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
3171 				forecast += 12 + rr->resrec.rdestimate;
3172 				// If we're trying to put more than one question in this packet, and it doesn't fit
3173 				// then undo that last question and try again next time
3174 				if (query->h.numQuestions > 1 && newptr + forecast >= limit)
3175 					{
3176 					debugf("BuildQuestion: Retracting question %##s (%s) new forecast total %d",
3177 						q->qname.c, DNSTypeName(q->qtype), newptr + forecast - query->data);
3178 					query->h.numQuestions--;
3179 					ka = *kalistptrptr;		// Go back to where we started and retract these answer records
3180 					while (*ka) { CacheRecord *c = *ka; *ka = mDNSNULL; ka = &c->NextInKAList; }
3181 					return(mDNSfalse);		// Return false, so we'll try again in the next packet
3182 					}
3183 				}
3184 
3185 		// Success! Update our state pointers, increment UnansweredQueries as appropriate, and return
3186 		*queryptr        = newptr;				// Update the packet pointer
3187 		*answerforecast  = forecast;			// Update the forecast
3188 		*kalistptrptr    = ka;					// Update the known answer list pointer
3189 		if (ucast) q->ExpectUnicastResp = NonZeroTime(m->timenow);
3190 
3191 		for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)				// For every resource record in our cache,
3192 			if (rr->resrec.InterfaceID == q->SendQNow &&					// received on this interface
3193 				rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList &&	// which is not in the known answer list
3194 				SameNameRecordAnswersQuestion(&rr->resrec, q))				// which answers our question
3195 					{
3196 					rr->UnansweredQueries++;								// indicate that we're expecting a response
3197 					rr->LastUnansweredTime = m->timenow;
3198 					SetNextCacheCheckTime(m, rr);
3199 					}
3200 
3201 		return(mDNStrue);
3202 		}
3203 	}
3204 
3205 // When we have a query looking for a specified name, but there appear to be no answers with
3206 // that name, ReconfirmAntecedents() is called with depth=0 to start the reconfirmation process
3207 // for any records in our cache that reference the given name (e.g. PTR and SRV records).
3208 // For any such cache record we find, we also recursively call ReconfirmAntecedents() for *its* name.
3209 // We increment depth each time we recurse, to guard against possible infinite loops, with a limit of 5.
3210 // A typical reconfirmation scenario might go like this:
3211 // Depth 0: Name "myhost.local" has no address records
3212 // Depth 1: SRV "My Service._example._tcp.local." refers to "myhost.local"; may be stale
3213 // Depth 2: PTR "_example._tcp.local." refers to "My Service"; may be stale
3214 // Depth 3: PTR "_services._dns-sd._udp.local." refers to "_example._tcp.local."; may be stale
3215 // Currently depths 4 and 5 are not expected to occur; if we did get to depth 5 we'd reconfim any records we
3216 // found referring to the given name, but not recursively descend any further reconfirm *their* antecedents.
3217 mDNSlocal void ReconfirmAntecedents(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const int depth)
3218 	{
3219 	mDNSu32 slot;
3220 	CacheGroup *cg;
3221 	CacheRecord *cr;
3222 	debugf("ReconfirmAntecedents (depth=%d) for %##s", depth, name->c);
3223 	FORALL_CACHERECORDS(slot, cg, cr)
3224 		{
3225 		domainname *crtarget = GetRRDomainNameTarget(&cr->resrec);
3226 		if (crtarget && cr->resrec.rdatahash == namehash && SameDomainName(crtarget, name))
3227 			{
3228 			LogInfo("ReconfirmAntecedents: Reconfirming (depth=%d) %s", depth, CRDisplayString(m, cr));
3229 			mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
3230 			if (depth < 5) ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, depth+1);
3231 			}
3232 		}
3233 	}
3234 
3235 // If we get no answer for a AAAA query, then before doing an automatic implicit ReconfirmAntecedents
3236 // we check if we have an address record for the same name. If we do have an IPv4 address for a given
3237 // name but not an IPv6 address, that's okay (it just means the device doesn't do IPv6) so the failure
3238 // to get a AAAA response is not grounds to doubt the PTR/SRV chain that lead us to that name.
3239 mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const domainname *const name, const mDNSu32 namehash)
3240 	{
3241 	CacheGroup *const cg = CacheGroupForName(m, HashSlot(name), namehash, name);
3242 	const CacheRecord *cr = cg ? cg->members : mDNSNULL;
3243 	while (cr && !RRTypeIsAddressType(cr->resrec.rrtype)) cr=cr->next;
3244 	return(cr);
3245 	}
3246 
3247 mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *const q, const CacheRecord *const c0, const CacheRecord *const c1)
3248 	{
3249 	CacheGroup *const cg = CacheGroupForName(m, HashSlot(&q->qname), q->qnamehash, &q->qname);
3250 	const CacheRecord *cr, *bestcr = mDNSNULL;
3251 	mDNSu32 bestmetric = 1000000;
3252 	for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
3253 		if (cr->resrec.rrtype == kDNSType_PTR && cr->resrec.rdlength >= 6)						// If record is PTR type, with long enough name,
3254 			if (cr != c0 && cr != c1)															// that's not one we've seen before,
3255 				if (SameNameRecordAnswersQuestion(&cr->resrec, q))								// and answers our browse query,
3256 					if (!IdenticalSameNameRecord(&cr->resrec, &m->SPSRecords.RR_PTR.resrec))	// and is not our own advertised service...
3257 						{
3258 						mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c);
3259 						if (bestmetric > metric) { bestmetric = metric; bestcr = cr; }
3260 						}
3261 	return(bestcr);
3262 	}
3263 
3264 // Finds the three best Sleep Proxies we currently have in our cache
3265 mDNSexport void FindSPSInCache(mDNS *const m, const DNSQuestion *const q, const CacheRecord *sps[3])
3266 	{
3267 	sps[0] =                      FindSPSInCache1(m, q, mDNSNULL, mDNSNULL);
3268 	sps[1] = !sps[0] ? mDNSNULL : FindSPSInCache1(m, q, sps[0],   mDNSNULL);
3269 	sps[2] = !sps[1] ? mDNSNULL : FindSPSInCache1(m, q, sps[0],   sps[1]);
3270 	}
3271 
3272 // Only DupSuppressInfos newer than the specified 'time' are allowed to remain active
3273 mDNSlocal void ExpireDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time)
3274 	{
3275 	int i;
3276 	for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].Time - time < 0) ds[i].InterfaceID = mDNSNULL;
3277 	}
3278 
3279 mDNSlocal void ExpireDupSuppressInfoOnInterface(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time, mDNSInterfaceID InterfaceID)
3280 	{
3281 	int i;
3282 	for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].InterfaceID == InterfaceID && ds[i].Time - time < 0) ds[i].InterfaceID = mDNSNULL;
3283 	}
3284 
3285 mDNSlocal mDNSBool SuppressOnThisInterface(const DupSuppressInfo ds[DupSuppressInfoSize], const NetworkInterfaceInfo * const intf)
3286 	{
3287 	int i;
3288 	mDNSBool v4 = !intf->IPv4Available;		// If this interface doesn't do v4, we don't need to find a v4 duplicate of this query
3289 	mDNSBool v6 = !intf->IPv6Available;		// If this interface doesn't do v6, we don't need to find a v6 duplicate of this query
3290 	for (i=0; i<DupSuppressInfoSize; i++)
3291 		if (ds[i].InterfaceID == intf->InterfaceID)
3292 			{
3293 			if      (ds[i].Type == mDNSAddrType_IPv4) v4 = mDNStrue;
3294 			else if (ds[i].Type == mDNSAddrType_IPv6) v6 = mDNStrue;
3295 			if (v4 && v6) return(mDNStrue);
3296 			}
3297 	return(mDNSfalse);
3298 	}
3299 
3300 mDNSlocal int RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 Time, mDNSInterfaceID InterfaceID, mDNSs32 Type)
3301 	{
3302 	int i, j;
3303 
3304 	// See if we have this one in our list somewhere already
3305 	for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].InterfaceID == InterfaceID && ds[i].Type == Type) break;
3306 
3307 	// If not, find a slot we can re-use
3308 	if (i >= DupSuppressInfoSize)
3309 		{
3310 		i = 0;
3311 		for (j=1; j<DupSuppressInfoSize && ds[i].InterfaceID; j++)
3312 			if (!ds[j].InterfaceID || ds[j].Time - ds[i].Time < 0)
3313 				i = j;
3314 		}
3315 
3316 	// Record the info about this query we saw
3317 	ds[i].Time        = Time;
3318 	ds[i].InterfaceID = InterfaceID;
3319 	ds[i].Type        = Type;
3320 
3321 	return(i);
3322 	}
3323 
3324 mDNSlocal mDNSBool AccelerateThisQuery(mDNS *const m, DNSQuestion *q)
3325 	{
3326 	// If more than 90% of the way to the query time, we should unconditionally accelerate it
3327 	if (TimeToSendThisQuestion(q, m->timenow + q->ThisQInterval/10))
3328 		return(mDNStrue);
3329 
3330 	// If half-way to next scheduled query time, only accelerate if it will add less than 512 bytes to the packet
3331 	if (TimeToSendThisQuestion(q, m->timenow + q->ThisQInterval/2))
3332 		{
3333 		// We forecast: qname (n) type (2) class (2)
3334 		mDNSu32 forecast = (mDNSu32)DomainNameLength(&q->qname) + 4;
3335 		const mDNSu32 slot = HashSlot(&q->qname);
3336 		const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
3337 		const CacheRecord *rr;
3338 		for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)				// If we have a resource record in our cache,
3339 			if (rr->resrec.rdlength <= SmallRecordLimit &&					// which is small enough to sensibly fit in the packet
3340 				SameNameRecordAnswersQuestion(&rr->resrec, q) &&			// which answers our question
3341 				rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow >= 0 &&			// and it is less than half-way to expiry
3342 				rr->NextRequiredQuery - (m->timenow + q->ThisQInterval) > 0)// and we'll ask at least once again before NextRequiredQuery
3343 				{
3344 				// We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
3345 				forecast += 12 + rr->resrec.rdestimate;
3346 				if (forecast >= 512) return(mDNSfalse);	// If this would add 512 bytes or more to the packet, don't accelerate
3347 				}
3348 		return(mDNStrue);
3349 		}
3350 
3351 	return(mDNSfalse);
3352 	}
3353 
3354 // How Standard Queries are generated:
3355 // 1. The Question Section contains the question
3356 // 2. The Additional Section contains answers we already know, to suppress duplicate responses
3357 
3358 // How Probe Queries are generated:
3359 // 1. The Question Section contains queries for the name we intend to use, with QType=ANY because
3360 // if some other host is already using *any* records with this name, we want to know about it.
3361 // 2. The Authority Section contains the proposed values we intend to use for one or more
3362 // of our records with that name (analogous to the Update section of DNS Update packets)
3363 // because if some other host is probing at the same time, we each want to know what the other is
3364 // planning, in order to apply the tie-breaking rule to see who gets to use the name and who doesn't.
3365 
3366 mDNSlocal void SendQueries(mDNS *const m)
3367 	{
3368 	mDNSu32 slot;
3369 	CacheGroup *cg;
3370 	CacheRecord *cr;
3371 	AuthRecord *ar;
3372 	int pktcount = 0;
3373 	DNSQuestion *q;
3374 	// For explanation of maxExistingQuestionInterval logic, see comments for maxExistingAnnounceInterval
3375 	mDNSs32 maxExistingQuestionInterval = 0;
3376 	const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
3377 	CacheRecord *KnownAnswerList = mDNSNULL;
3378 
3379 	// 1. If time for a query, work out what we need to do
3380 	if (m->timenow - m->NextScheduledQuery >= 0)
3381 		{
3382 		CacheRecord *rr;
3383 
3384 		// We're expecting to send a query anyway, so see if any expiring cache records are close enough
3385 		// to their NextRequiredQuery to be worth batching them together with this one
3386 		FORALL_CACHERECORDS(slot, cg, rr)
3387 			if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
3388 				if (m->timenow + TicksTTL(rr)/50 - rr->NextRequiredQuery >= 0)
3389 					{
3390 					debugf("Sending %d%% cache expiration query for %s", 80 + 5 * rr->UnansweredQueries, CRDisplayString(m, rr));
3391 					q = rr->CRActiveQuestion;
3392 					ExpireDupSuppressInfoOnInterface(q->DupSuppress, m->timenow - TicksTTL(rr)/20, rr->resrec.InterfaceID);
3393 					// For uDNS queries (TargetQID non-zero) we adjust LastQTime,
3394 					// and bump UnansweredQueries so that we don't spin trying to send the same cache expiration query repeatedly
3395 					if      (q->Target.type)                        q->SendQNow = mDNSInterfaceMark;	// If targeted query, mark it
3396 					else if (!mDNSOpaque16IsZero(q->TargetQID))     { q->LastQTime = m->timenow - q->ThisQInterval; rr->UnansweredQueries++; }
3397 					else if (q->SendQNow == mDNSNULL)               q->SendQNow = rr->resrec.InterfaceID;
3398 					else if (q->SendQNow != rr->resrec.InterfaceID) q->SendQNow = mDNSInterfaceMark;
3399 					}
3400 
3401 		if (m->SuppressStdPort53Queries && m->timenow - m->SuppressStdPort53Queries >= 0)
3402 			m->SuppressStdPort53Queries = 0; // If suppression time has passed, clear it
3403 
3404 		// Scan our list of questions to see which:
3405 		//     *WideArea*  queries need to be sent
3406 		//     *unicast*   queries need to be sent
3407 		//     *multicast* queries we're definitely going to send
3408 		if (m->CurrentQuestion)
3409 			LogMsg("SendQueries ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
3410 		m->CurrentQuestion = m->Questions;
3411 		while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
3412 			{
3413 			q = m->CurrentQuestion;
3414 			if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID)) uDNS_CheckCurrentQuestion(m);
3415 			else if (mDNSOpaque16IsZero(q->TargetQID) && q->Target.type && (q->SendQNow || TimeToSendThisQuestion(q, m->timenow)))
3416 				{
3417 				mDNSu8       *qptr        = m->omsg.data;
3418 				const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data);
3419 
3420 				// If we fail to get a new on-demand socket (should only happen cases of the most extreme resource exhaustion), we'll try again next time
3421 				if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort);
3422 				if (q->LocalSocket)
3423 					{
3424 					InitializeDNSMessage(&m->omsg.h, q->TargetQID, QueryFlags);
3425 					qptr = putQuestion(&m->omsg, qptr, limit, &q->qname, q->qtype, q->qclass);
3426 					mDNSSendDNSMessage(m, &m->omsg, qptr, mDNSInterface_Any, q->LocalSocket, &q->Target, q->TargetPort, mDNSNULL, mDNSNULL);
3427 					q->ThisQInterval    *= QuestionIntervalStep;
3428 					}
3429 				if (q->ThisQInterval > MaxQuestionInterval)
3430 					q->ThisQInterval = MaxQuestionInterval;
3431 				q->LastQTime         = m->timenow;
3432 				q->LastQTxTime       = m->timenow;
3433 				q->RecentAnswerPkts  = 0;
3434 				q->SendQNow          = mDNSNULL;
3435 				q->ExpectUnicastResp = NonZeroTime(m->timenow);
3436 				}
3437 			else if (mDNSOpaque16IsZero(q->TargetQID) && !q->Target.type && TimeToSendThisQuestion(q, m->timenow))
3438 				{
3439 				//LogInfo("Time to send %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - (q->LastQTime + q->ThisQInterval));
3440 				q->SendQNow = mDNSInterfaceMark;		// Mark this question for sending on all interfaces
3441 				if (maxExistingQuestionInterval < q->ThisQInterval)
3442 					maxExistingQuestionInterval = q->ThisQInterval;
3443 				}
3444 			// If m->CurrentQuestion wasn't modified out from under us, advance it now
3445 			// We can't do this at the start of the loop because uDNS_CheckCurrentQuestion() depends on having
3446 			// m->CurrentQuestion point to the right question
3447 			if (q == m->CurrentQuestion) m->CurrentQuestion = m->CurrentQuestion->next;
3448 			}
3449 		m->CurrentQuestion = mDNSNULL;
3450 
3451 		// Scan our list of questions
3452 		// (a) to see if there are any more that are worth accelerating, and
3453 		// (b) to update the state variables for *all* the questions we're going to send
3454 		// Note: Don't set NextScheduledQuery until here, because uDNS_CheckCurrentQuestion in the loop above can add new questions to the list,
3455 		// which causes NextScheduledQuery to get (incorrectly) set to m->timenow. Setting it here is the right place, because the very
3456 		// next thing we do is scan the list and call SetNextQueryTime() for every question we find, so we know we end up with the right value.
3457 		m->NextScheduledQuery = m->timenow + 0x78000000;
3458 		for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
3459 			{
3460 			if (mDNSOpaque16IsZero(q->TargetQID) && (q->SendQNow ||
3461 				(!q->Target.type && ActiveQuestion(q) && q->ThisQInterval <= maxExistingQuestionInterval && AccelerateThisQuery(m,q))))
3462 				{
3463 				// If at least halfway to next query time, advance to next interval
3464 				// If less than halfway to next query time, then
3465 				// treat this as logically a repeat of the last transmission, without advancing the interval
3466 				if (m->timenow - (q->LastQTime + q->ThisQInterval/2) >= 0)
3467 					{
3468 					//LogInfo("Accelerating %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - (q->LastQTime + q->ThisQInterval));
3469 					q->SendQNow = mDNSInterfaceMark;	// Mark this question for sending on all interfaces
3470 					debugf("SendQueries: %##s (%s) next interval %d seconds RequestUnicast = %d",
3471 						q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval / InitialQuestionInterval, q->RequestUnicast);
3472 					q->ThisQInterval *= QuestionIntervalStep;
3473 					if (q->ThisQInterval > MaxQuestionInterval)
3474 						q->ThisQInterval = MaxQuestionInterval;
3475 					else if (q->CurrentAnswers == 0 && q->ThisQInterval == InitialQuestionInterval * QuestionIntervalStep3 && !q->RequestUnicast &&
3476 							!(RRTypeIsAddressType(q->qtype) && CacheHasAddressTypeForName(m, &q->qname, q->qnamehash)))
3477 						{
3478 						// Generally don't need to log this.
3479 						// It's not especially noteworthy if a query finds no results -- this usually happens for domain
3480 						// enumeration queries in the LL subdomain (e.g. "db._dns-sd._udp.0.0.254.169.in-addr.arpa")
3481 						// and when there simply happen to be no instances of the service the client is looking
3482 						// for (e.g. iTunes is set to look for RAOP devices, and the current network has none).
3483 						debugf("SendQueries: Zero current answers for %##s (%s); will reconfirm antecedents",
3484 							q->qname.c, DNSTypeName(q->qtype));
3485 						// Sending third query, and no answers yet; time to begin doubting the source
3486 						ReconfirmAntecedents(m, &q->qname, q->qnamehash, 0);
3487 						}
3488 					}
3489 
3490 				// Mark for sending. (If no active interfaces, then don't even try.)
3491 				q->SendOnAll = (q->SendQNow == mDNSInterfaceMark);
3492 				if (q->SendOnAll)
3493 					{
3494 					q->SendQNow  = !intf ? mDNSNULL : (q->InterfaceID) ? q->InterfaceID : intf->InterfaceID;
3495 					q->LastQTime = m->timenow;
3496 					}
3497 
3498 				// If we recorded a duplicate suppression for this question less than half an interval ago,
3499 				// then we consider it recent enough that we don't need to do an identical query ourselves.
3500 				ExpireDupSuppressInfo(q->DupSuppress, m->timenow - q->ThisQInterval/2);
3501 
3502 				q->LastQTxTime      = m->timenow;
3503 				q->RecentAnswerPkts = 0;
3504 				if (q->RequestUnicast) q->RequestUnicast--;
3505 				}
3506 			// For all questions (not just the ones we're sending) check what the next scheduled event will be
3507 			SetNextQueryTime(m,q);
3508 			}
3509 		}
3510 
3511 	// 2. Scan our authoritative RR list to see what probes we might need to send
3512 	if (m->timenow - m->NextScheduledProbe >= 0)
3513 		{
3514 		m->NextScheduledProbe = m->timenow + 0x78000000;
3515 
3516 		if (m->CurrentRecord)
3517 			LogMsg("SendQueries ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
3518 		m->CurrentRecord = m->ResourceRecords;
3519 		while (m->CurrentRecord)
3520 			{
3521 			AuthRecord *rr = m->CurrentRecord;
3522 			m->CurrentRecord = rr->next;
3523 			if (!AuthRecord_uDNS(rr) && rr->resrec.RecordType == kDNSRecordTypeUnique)	// For all records that are still probing...
3524 				{
3525 				// 1. If it's not reached its probe time, just make sure we update m->NextScheduledProbe correctly
3526 				if (m->timenow - (rr->LastAPTime + rr->ThisAPInterval) < 0)
3527 					{
3528 					SetNextAnnounceProbeTime(m, rr);
3529 					}
3530 				// 2. else, if it has reached its probe time, mark it for sending and then update m->NextScheduledProbe correctly
3531 				else if (rr->ProbeCount)
3532 					{
3533 					if (rr->AddressProxy.type == mDNSAddrType_IPv4)
3534 						{
3535 						LogSPS("SendQueries ARP Probe %d %s %s", rr->ProbeCount, InterfaceNameForID(m, rr->resrec.InterfaceID), ARDisplayString(m,rr));
3536 						SendARP(m, 1, rr, zerov4Addr.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, rr->WakeUp.IMAC.b);
3537 						}
3538 					else if (rr->AddressProxy.type == mDNSAddrType_IPv6)
3539 						{
3540 						//LogSPS("SendQueries NDP Probe %d %s", rr->ProbeCount, ARDisplayString(m,rr));
3541 						//SendARP(m, 1, rr, rr->AddressProxy.ip.v4.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, onesEthAddr.b);
3542 						}
3543 					// Mark for sending. (If no active interfaces, then don't even try.)
3544 					rr->SendRNow   = (!intf || rr->WakeUp.HMAC.l[0]) ? mDNSNULL : rr->resrec.InterfaceID ? rr->resrec.InterfaceID : intf->InterfaceID;
3545 					rr->LastAPTime = m->timenow;
3546 					// When we have a late conflict that resets a record to probing state we use a special marker value greater
3547 					// than DefaultProbeCountForTypeUnique. Here we detect that state and reset rr->ProbeCount back to the right value.
3548 					if (rr->ProbeCount > DefaultProbeCountForTypeUnique)
3549 						rr->ProbeCount = DefaultProbeCountForTypeUnique;
3550 					rr->ProbeCount--;
3551 					SetNextAnnounceProbeTime(m, rr);
3552 					if (rr->ProbeCount == 0)
3553 						{
3554 						// If this is the last probe for this record, then see if we have any matching records
3555 						// on our duplicate list which should similarly have their ProbeCount cleared to zero...
3556 						AuthRecord *r2;
3557 						for (r2 = m->DuplicateRecords; r2; r2=r2->next)
3558 							if (r2->resrec.RecordType == kDNSRecordTypeUnique && RecordIsLocalDuplicate(r2, rr))
3559 								r2->ProbeCount = 0;
3560 						// ... then acknowledge this record to the client.
3561 						// We do this optimistically, just as we're about to send the third probe.
3562 						// This helps clients that both advertise and browse, and want to filter themselves
3563 						// from the browse results list, because it helps ensure that the registration
3564 						// confirmation will be delivered 1/4 second *before* the browse "add" event.
3565 						// A potential downside is that we could deliver a registration confirmation and then find out
3566 						// moments later that there's a name conflict, but applications have to be prepared to handle
3567 						// late conflicts anyway (e.g. on connection of network cable, etc.), so this is nothing new.
3568 						if (!rr->Acknowledged) AcknowledgeRecord(m, rr);
3569 						}
3570 					}
3571 				// else, if it has now finished probing, move it to state Verified,
3572 				// and update m->NextScheduledResponse so it will be announced
3573 				else
3574 					{
3575 					if (!rr->Acknowledged) AcknowledgeRecord(m, rr);	// Defensive, just in case it got missed somehow
3576 					rr->resrec.RecordType     = kDNSRecordTypeVerified;
3577 					rr->ThisAPInterval = DefaultAnnounceIntervalForTypeUnique;
3578 					rr->LastAPTime     = m->timenow - DefaultAnnounceIntervalForTypeUnique;
3579 					SetNextAnnounceProbeTime(m, rr);
3580 					}
3581 				}
3582 			}
3583 		m->CurrentRecord = m->DuplicateRecords;
3584 		while (m->CurrentRecord)
3585 			{
3586 			AuthRecord *rr = m->CurrentRecord;
3587 			m->CurrentRecord = rr->next;
3588 			if (rr->resrec.RecordType == kDNSRecordTypeUnique && rr->ProbeCount == 0 && !rr->Acknowledged)
3589 				AcknowledgeRecord(m, rr);
3590 			}
3591 		}
3592 
3593 	// 3. Now we know which queries and probes we're sending,
3594 	// go through our interface list sending the appropriate queries on each interface
3595 	while (intf)
3596 		{
3597 		const int os = !intf->MAC.l[0] ? 0 : DNSOpt_Header_Space + (mDNSSameEthAddress(&m->PrimaryMAC, &intf->MAC) ? DNSOpt_OwnerData_ID_Space : DNSOpt_OwnerData_ID_Wake_Space);
3598 		int OwnerRecordSpace = 0;
3599 		AuthRecord *rr;
3600 		mDNSu8 *queryptr = m->omsg.data;
3601 		mDNSu8 *limit    = m->omsg.data + AbsoluteMaxDNSMessageData;
3602 		InitializeDNSMessage(&m->omsg.h, zeroID, QueryFlags);
3603 		if (KnownAnswerList) verbosedebugf("SendQueries:   KnownAnswerList set... Will continue from previous packet");
3604 		if (!KnownAnswerList)
3605 			{
3606 			// Start a new known-answer list
3607 			CacheRecord **kalistptr = &KnownAnswerList;
3608 			mDNSu32 answerforecast = 0;
3609 
3610 			// Put query questions in this packet
3611 			for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
3612 				{
3613 				if (mDNSOpaque16IsZero(q->TargetQID) && (q->SendQNow == intf->InterfaceID))
3614 					{
3615 					debugf("SendQueries: %s question for %##s (%s) at %d forecast total %d",
3616 						SuppressOnThisInterface(q->DupSuppress, intf) ? "Suppressing" : "Putting    ",
3617 						q->qname.c, DNSTypeName(q->qtype), queryptr - m->omsg.data, queryptr + answerforecast - m->omsg.data);
3618 
3619 					// If we're suppressing this question, or we successfully put it, update its SendQNow state
3620 					if (SuppressOnThisInterface(q->DupSuppress, intf) ||
3621 						BuildQuestion(m, &m->omsg, &queryptr, q, &kalistptr, &answerforecast))
3622 						q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
3623 
3624 					// Once we've put at least one question, cut back our limit to the normal single-packet size
3625 					if (m->omsg.h.numQuestions) limit = m->omsg.data + NormalMaxDNSMessageData;
3626 					}
3627 				}
3628 
3629 			// Put probe questions in this packet
3630 			for (rr = m->ResourceRecords; rr; rr=rr->next)
3631 				if (rr->SendRNow == intf->InterfaceID)
3632 					{
3633 					mDNSBool ucast = (rr->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353;
3634 					mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
3635 					mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit, rr->resrec.name, kDNSQType_ANY, (mDNSu16)(rr->resrec.rrclass | ucbit));
3636 					// We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
3637 					mDNSu32 forecast = answerforecast + 12 + rr->resrec.rdestimate;
3638 					if (newptr && newptr + forecast + os < limit)
3639 						{
3640 						queryptr         = newptr;
3641 						limit            = m->omsg.data + NormalMaxDNSMessageData;
3642 						answerforecast   = forecast;
3643 						OwnerRecordSpace = os;
3644 						rr->SendRNow = (rr->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
3645 						rr->IncludeInProbe = mDNStrue;
3646 						verbosedebugf("SendQueries:   Put Question %##s (%s) probecount %d",
3647 							rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->ProbeCount);
3648 						}
3649 					else
3650 						{
3651 						verbosedebugf("SendQueries:   Retracting Question %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
3652 						m->omsg.h.numQuestions--;
3653 						}
3654 					}
3655 			}
3656 
3657 		if (m->omsg.h.numQuestions) limit = m->omsg.data + NormalMaxDNSMessageData - OwnerRecordSpace;
3658 
3659 		// Put our known answer list (either new one from this question or questions, or remainder of old one from last time)
3660 		while (KnownAnswerList)
3661 			{
3662 			CacheRecord *ka = KnownAnswerList;
3663 			mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - ka->TimeRcvd)) / mDNSPlatformOneSecond;
3664 			mDNSu8 *newptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAnswers, &ka->resrec, ka->resrec.rroriginalttl - SecsSinceRcvd, limit);
3665 			if (newptr)
3666 				{
3667 				verbosedebugf("SendQueries:   Put %##s (%s) at %d - %d",
3668 					ka->resrec.name->c, DNSTypeName(ka->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data);
3669 				queryptr = newptr;
3670 				limit = m->omsg.data + NormalMaxDNSMessageData - OwnerRecordSpace;
3671 				KnownAnswerList = ka->NextInKAList;
3672 				ka->NextInKAList = mDNSNULL;
3673 				}
3674 			else
3675 				{
3676 				// If we ran out of space and we have more than one question in the packet, that's an error --
3677 				// we shouldn't have put more than one question if there was a risk of us running out of space.
3678 				if (m->omsg.h.numQuestions > 1)
3679 					LogMsg("SendQueries:   Put %d answers; No more space for known answers", m->omsg.h.numAnswers);
3680 				m->omsg.h.flags.b[0] |= kDNSFlag0_TC;
3681 				break;
3682 				}
3683 			}
3684 
3685 		for (rr = m->ResourceRecords; rr; rr=rr->next)
3686 			if (rr->IncludeInProbe)
3687 				{
3688 				mDNSu8 *newptr = PutResourceRecord(&m->omsg, queryptr, &m->omsg.h.numAuthorities, &rr->resrec);
3689 				rr->IncludeInProbe = mDNSfalse;
3690 				if (newptr) queryptr = newptr;
3691 				else LogMsg("SendQueries:   How did we fail to have space for the Update record %s", ARDisplayString(m,rr));
3692 				}
3693 
3694 		if (OwnerRecordSpace)
3695 			{
3696 			AuthRecord opt;
3697 			mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
3698 			opt.resrec.rrclass    = NormalMaxDNSMessageData;
3699 			opt.resrec.rdlength   = sizeof(rdataOPT);	// One option in this OPT record
3700 			opt.resrec.rdestimate = sizeof(rdataOPT);
3701 			SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
3702 			LogSPS("SendQueries putting %s", ARDisplayString(m, &opt));
3703 			queryptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAdditionals,
3704 				&opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
3705 			if (!queryptr)
3706 				LogMsg("SendQueries: How did we fail to have space for the OPT record (%d/%d/%d/%d) %s",
3707 					m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
3708 			}
3709 
3710 		if (queryptr > m->omsg.data)
3711 			{
3712 			if ((m->omsg.h.flags.b[0] & kDNSFlag0_TC) && m->omsg.h.numQuestions > 1)
3713 				LogMsg("SendQueries: Should not have more than one question (%d) in a truncated packet", m->omsg.h.numQuestions);
3714 			debugf("SendQueries:   Sending %d Question%s %d Answer%s %d Update%s on %p",
3715 				m->omsg.h.numQuestions,   m->omsg.h.numQuestions   == 1 ? "" : "s",
3716 				m->omsg.h.numAnswers,     m->omsg.h.numAnswers     == 1 ? "" : "s",
3717 				m->omsg.h.numAuthorities, m->omsg.h.numAuthorities == 1 ? "" : "s", intf->InterfaceID);
3718 			if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL);
3719 			if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL);
3720 			if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10);
3721 			if (++pktcount >= 1000)
3722 				{ LogMsg("SendQueries exceeded loop limit %d: giving up", pktcount); break; }
3723 			// There might be more records left in the known answer list, or more questions to send
3724 			// on this interface, so go around one more time and try again.
3725 			}
3726 		else	// Nothing more to send on this interface; go to next
3727 			{
3728 			const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next);
3729 			#if MDNS_DEBUGMSGS && 0
3730 			const char *const msg = next ? "SendQueries:   Nothing more on %p; moving to %p" : "SendQueries:   Nothing more on %p";
3731 			debugf(msg, intf, next);
3732 			#endif
3733 			intf = next;
3734 			}
3735 		}
3736 
3737 	// 4. Final housekeeping
3738 
3739 	// 4a. Debugging check: Make sure we announced all our records
3740 	for (ar = m->ResourceRecords; ar; ar=ar->next)
3741 		if (ar->SendRNow)
3742 			{
3743 			if (ar->resrec.InterfaceID != mDNSInterface_LocalOnly)
3744 				LogMsg("SendQueries: No active interface to send: %s", ARDisplayString(m, ar));
3745 			ar->SendRNow = mDNSNULL;
3746 			}
3747 
3748 	// 4b. When we have lingering cache records that we're keeping around for a few seconds in the hope
3749 	// that their interface which went away might come back again, the logic will want to send queries
3750 	// for those records, but we can't because their interface isn't here any more, so to keep the
3751 	// state machine ticking over we just pretend we did so.
3752 	// If the interface does not come back in time, the cache record will expire naturally
3753 	FORALL_CACHERECORDS(slot, cg, cr)
3754 		if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries && m->timenow - cr->NextRequiredQuery >= 0)
3755 			{
3756 			cr->UnansweredQueries++;
3757 			cr->CRActiveQuestion->SendQNow = mDNSNULL;
3758 			SetNextCacheCheckTime(m, cr);
3759 			}
3760 
3761 	// 4c. Debugging check: Make sure we sent all our planned questions
3762 	// Do this AFTER the lingering cache records check above, because that will prevent spurious warnings for questions
3763 	// we legitimately couldn't send because the interface is no longer available
3764 	for (q = m->Questions; q; q=q->next)
3765 		if (q->SendQNow)
3766 			{
3767 			LogMsg("SendQueries: No active interface to send: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
3768 			q->SendQNow = mDNSNULL;
3769 			}
3770 	}
3771 
3772 mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password)
3773 	{
3774 	int i, j;
3775 	mDNSu8 *ptr = m->omsg.data;
3776 
3777 	if (!InterfaceID) { LogMsg("SendWakeup: No InterfaceID specified"); return; }
3778 
3779 	// 0x00 Destination address
3780 	for (i=0; i<6; i++) *ptr++ = EthAddr->b[i];
3781 
3782 	// 0x06 Source address (we just use zero -- BPF will fill in real interface address)
3783 	for (i=0; i<6; i++) *ptr++ = 0x0;
3784 
3785 	// 0x0C Ethertype (0x0842)
3786 	*ptr++ = 0x08;
3787 	*ptr++ = 0x42;
3788 
3789 	// 0x0E Wakeup sync sequence
3790 	for (i=0; i<6; i++) *ptr++ = 0xFF;
3791 
3792 	// 0x14 Wakeup data
3793 	for (j=0; j<16; j++) for (i=0; i<6; i++) *ptr++ = EthAddr->b[i];
3794 
3795 	// 0x74 Password
3796 	for (i=0; i<6; i++) *ptr++ = password->b[i];
3797 
3798 	mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
3799 
3800 	// For Ethernet switches that don't flood-foward packets with unknown unicast destination MAC addresses,
3801 	// broadcast is the only reliable way to get a wakeup packet to the intended target machine.
3802 	// For 802.11 WPA networks, where a sleeping target machine may have missed a broadcast/multicast
3803 	// key rotation, unicast is the only way to get a wakeup packet to the intended target machine.
3804 	// So, we send one of each, unicast first, then broadcast second.
3805 	for (i=0; i<6; i++) m->omsg.data[i] = 0xFF;
3806 	mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
3807 	}
3808 
3809 // ***************************************************************************
3810 #if COMPILER_LIKES_PRAGMA_MARK
3811 #pragma mark -
3812 #pragma mark - RR List Management & Task Management
3813 #endif
3814 
3815 // Note: AnswerCurrentQuestionWithResourceRecord can call a user callback, which may change the record list and/or question list.
3816 // Any code walking either list must use the m->CurrentQuestion (and possibly m->CurrentRecord) mechanism to protect against this.
3817 // In fact, to enforce this, the routine will *only* answer the question currently pointed to by m->CurrentQuestion,
3818 // which will be auto-advanced (possibly to NULL) if the client callback cancels the question.
3819 mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord)
3820 	{
3821 	DNSQuestion *const q = m->CurrentQuestion;
3822 	mDNSBool followcname = rr->resrec.RecordType != kDNSRecordTypePacketNegative && AddRecord &&
3823 							rr->resrec.rrtype == kDNSType_CNAME && q->qtype != kDNSType_CNAME;
3824 	verbosedebugf("AnswerCurrentQuestionWithResourceRecord:%4lu %s TTL %d %s", q->CurrentAnswers, AddRecord ? "Add" : "Rmv", rr->resrec.rroriginalttl, CRDisplayString(m, rr));
3825 
3826 	// Note: Use caution here. In the case of records with rr->DelayDelivery set, AnswerCurrentQuestionWithResourceRecord(... mDNStrue)
3827 	// may be called twice, once when the record is received, and again when it's time to notify local clients.
3828 	// If any counters or similar are added here, care must be taken to ensure that they are not double-incremented by this.
3829 
3830 	rr->LastUsed = m->timenow;
3831 	if (AddRecord == QC_add && !q->DuplicateOf && rr->CRActiveQuestion != q)
3832 		{
3833 		if (!rr->CRActiveQuestion) m->rrcache_active++;	// If not previously active, increment rrcache_active count
3834 		debugf("AnswerCurrentQuestionWithResourceRecord: Updating CRActiveQuestion to %p for cache record %s", q, CRDisplayString(m,rr));
3835 		rr->CRActiveQuestion = q;						// We know q is non-null
3836 		SetNextCacheCheckTime(m, rr);
3837 		}
3838 
3839 	// If this is:
3840 	// (a) a no-cache add, where we've already done at least one 'QM' query, or
3841 	// (b) a normal add, where we have at least one unique-type answer,
3842 	// then there's no need to keep polling the network.
3843 	// (If we have an answer in the cache, then we'll automatically ask again in time to stop it expiring.)
3844 	// We do this for mDNS questions and uDNS one-shot questions, but not for
3845 	// uDNS LongLived questions, because that would mess up our LLQ lease renewal timing.
3846 	if ((AddRecord == QC_addnocache && !q->RequestUnicast) ||
3847 		(AddRecord == QC_add && (q->ExpectUnique || (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask))))
3848 		if (ActiveQuestion(q) && (mDNSOpaque16IsZero(q->TargetQID) || !q->LongLived))
3849 			{
3850 			q->LastQTime        = m->timenow;
3851 			q->LastQTxTime      = m->timenow;
3852 			q->RecentAnswerPkts = 0;
3853 			q->ThisQInterval    = MaxQuestionInterval;
3854 			q->RequestUnicast   = mDNSfalse;
3855 			debugf("AnswerCurrentQuestionWithResourceRecord: Set MaxQuestionInterval for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
3856 			}
3857 
3858 	if (rr->DelayDelivery) return;		// We'll come back later when CacheRecordDeferredAdd() calls us
3859 
3860 	// Only deliver negative answers if client has explicitly requested them
3861 	if (rr->resrec.RecordType == kDNSRecordTypePacketNegative || (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype)))
3862 		if (!AddRecord || !q->ReturnIntermed) return;
3863 
3864 	// For CNAME results to non-CNAME questions, only inform the client if they explicitly requested that
3865 	if (q->QuestionCallback && !q->NoAnswer && (!followcname || q->ReturnIntermed))
3866 		{
3867 		mDNS_DropLockBeforeCallback();		// Allow client (and us) to legally make mDNS API calls
3868 		if (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype))
3869 			{
3870 			CacheRecord neg;
3871 			MakeNegativeCacheRecord(m, &neg, &q->qname, q->qnamehash, q->qtype, q->qclass, 1, rr->resrec.InterfaceID);
3872 			q->QuestionCallback(m, q, &neg.resrec, AddRecord);
3873 			}
3874 		else
3875 			q->QuestionCallback(m, q, &rr->resrec, AddRecord);
3876 		mDNS_ReclaimLockAfterCallback();	// Decrement mDNS_reentrancy to block mDNS API calls again
3877 		}
3878 	// Note: Proceed with caution here because client callback function is allowed to do anything,
3879 	// including starting/stopping queries, registering/deregistering records, etc.
3880 
3881 	if (followcname && m->CurrentQuestion == q && q->CNAMEReferrals < 10)
3882 		{
3883 		const mDNSu32 c = q->CNAMEReferrals + 1;
3884 		// Right now we just stop and re-use the existing query. If we really wanted to be 100% perfect,
3885 		// and track CNAMEs coming and going, we should really create a subordinate query here,
3886 		// which we would subsequently cancel and retract if the CNAME referral record were removed.
3887 		// In reality this is such a corner case we'll ignore it until someone actually needs it.
3888 		LogInfo("AnswerCurrentQuestionWithResourceRecord: following CNAME referral for %s", CRDisplayString(m, rr));
3889 		mDNS_StopQuery_internal(m, q);								// Stop old query
3890 		AssignDomainName(&q->qname, &rr->resrec.rdata->u.name);		// Update qname
3891 		q->qnamehash = DomainNameHashValue(&q->qname);				// and namehash
3892 		mDNS_StartQuery_internal(m, q);								// start new query
3893 		q->CNAMEReferrals = c;										// and keep count of how many times we've done this
3894 		}
3895 	}
3896 
3897 mDNSlocal void CacheRecordDeferredAdd(mDNS *const m, CacheRecord *rr)
3898 	{
3899 	rr->DelayDelivery = 0;		// Note, only need to call SetNextCacheCheckTime() when DelayDelivery is set, not when it's cleared
3900 	if (m->CurrentQuestion)
3901 		LogMsg("CacheRecordDeferredAdd ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
3902 	m->CurrentQuestion = m->Questions;
3903 	while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
3904 		{
3905 		DNSQuestion *q = m->CurrentQuestion;
3906 		if (ResourceRecordAnswersQuestion(&rr->resrec, q))
3907 			AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
3908 		if (m->CurrentQuestion == q)	// If m->CurrentQuestion was not auto-advanced, do it ourselves now
3909 			m->CurrentQuestion = q->next;
3910 		}
3911 	m->CurrentQuestion = mDNSNULL;
3912 	}
3913 
3914 mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const mDNSu32 slot)
3915 	{
3916 	const mDNSs32 threshhold = m->timenow + mDNSPlatformOneSecond;	// See if there are any records expiring within one second
3917 	const mDNSs32 start      = m->timenow - 0x10000000;
3918 	mDNSs32 delay = start;
3919 	CacheGroup *cg = CacheGroupForName(m, slot, namehash, name);
3920 	const CacheRecord *rr;
3921 	for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
3922 		if (threshhold - RRExpireTime(rr) >= 0)		// If we have records about to expire within a second
3923 			if (delay - RRExpireTime(rr) < 0)		// then delay until after they've been deleted
3924 				delay = RRExpireTime(rr);
3925 	if (delay - start > 0) return(NonZeroTime(delay));
3926 	else return(0);
3927 	}
3928 
3929 // CacheRecordAdd is only called from mDNSCoreReceiveResponse, *never* directly as a result of a client API call.
3930 // If new questions are created as a result of invoking client callbacks, they will be added to
3931 // the end of the question list, and m->NewQuestions will be set to indicate the first new question.
3932 // rr is a new CacheRecord just received into our cache
3933 // (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique).
3934 // Note: CacheRecordAdd calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
3935 // which may change the record list and/or question list.
3936 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
3937 mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr)
3938 	{
3939 	DNSQuestion *q;
3940 
3941 	// We stop when we get to NewQuestions -- if we increment their CurrentAnswers/LargeAnswers/UniqueAnswers
3942 	// counters here we'll end up double-incrementing them when we do it again in AnswerNewQuestion().
3943 	for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
3944 		{
3945 		if (ResourceRecordAnswersQuestion(&rr->resrec, q))
3946 			{
3947 			// If this question is one that's actively sending queries, and it's received ten answers within one
3948 			// second of sending the last query packet, then that indicates some radical network topology change,
3949 			// so reset its exponential backoff back to the start. We must be at least at the eight-second interval
3950 			// to do this. If we're at the four-second interval, or less, there's not much benefit accelerating
3951 			// because we will anyway send another query within a few seconds. The first reset query is sent out
3952 			// randomized over the next four seconds to reduce possible synchronization between machines.
3953 			if (q->LastAnswerPktNum != m->PktNum)
3954 				{
3955 				q->LastAnswerPktNum = m->PktNum;
3956 				if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q) && ++q->RecentAnswerPkts >= 10 &&
3957 					q->ThisQInterval > InitialQuestionInterval * QuestionIntervalStep3 && m->timenow - q->LastQTxTime < mDNSPlatformOneSecond)
3958 					{
3959 					LogMsg("CacheRecordAdd: %##s (%s) got immediate answer burst (%d); restarting exponential backoff sequence (%d)",
3960 						q->qname.c, DNSTypeName(q->qtype), q->RecentAnswerPkts, q->ThisQInterval);
3961 					q->LastQTime      = m->timenow - InitialQuestionInterval + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*4);
3962 					q->ThisQInterval  = InitialQuestionInterval;
3963 					SetNextQueryTime(m,q);
3964 					}
3965 				}
3966 			verbosedebugf("CacheRecordAdd %p %##s (%s) %lu",
3967 				rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl);
3968 			q->CurrentAnswers++;
3969 			q->unansweredQueries = 0;
3970 			if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++;
3971 			if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++;
3972 			if (q->CurrentAnswers > 4000)
3973 				{
3974 				static int msgcount = 0;
3975 				if (msgcount++ < 10)
3976 					LogMsg("CacheRecordAdd: %##s (%s) has %d answers; shedding records to resist DOS attack",
3977 						q->qname.c, DNSTypeName(q->qtype), q->CurrentAnswers);
3978 				rr->resrec.rroriginalttl = 0;
3979 				rr->UnansweredQueries = MaxUnansweredQueries;
3980 				}
3981 			}
3982 		}
3983 
3984 	if (!rr->DelayDelivery)
3985 		{
3986 		if (m->CurrentQuestion)
3987 			LogMsg("CacheRecordAdd ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
3988 		m->CurrentQuestion = m->Questions;
3989 		while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
3990 			{
3991 			q = m->CurrentQuestion;
3992 			if (ResourceRecordAnswersQuestion(&rr->resrec, q))
3993 				AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
3994 			if (m->CurrentQuestion == q)	// If m->CurrentQuestion was not auto-advanced, do it ourselves now
3995 				m->CurrentQuestion = q->next;
3996 			}
3997 		m->CurrentQuestion = mDNSNULL;
3998 		}
3999 
4000 	SetNextCacheCheckTime(m, rr);
4001 	}
4002 
4003 // NoCacheAnswer is only called from mDNSCoreReceiveResponse, *never* directly as a result of a client API call.
4004 // If new questions are created as a result of invoking client callbacks, they will be added to
4005 // the end of the question list, and m->NewQuestions will be set to indicate the first new question.
4006 // rr is a new CacheRecord just received from the wire (kDNSRecordTypePacketAns/AnsUnique/Add/AddUnique)
4007 // but we don't have any place to cache it. We'll deliver question 'add' events now, but we won't have any
4008 // way to deliver 'remove' events in future, nor will we be able to include this in known-answer lists,
4009 // so we immediately bump ThisQInterval up to MaxQuestionInterval to avoid pounding the network.
4010 // Note: NoCacheAnswer calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
4011 // which may change the record list and/or question list.
4012 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
4013 mDNSlocal void NoCacheAnswer(mDNS *const m, CacheRecord *rr)
4014 	{
4015 	LogMsg("No cache space: Delivering non-cached result for %##s", m->rec.r.resrec.name->c);
4016 	if (m->CurrentQuestion)
4017 		LogMsg("NoCacheAnswer ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
4018 	m->CurrentQuestion = m->Questions;
4019 	// We do this for *all* questions, not stopping when we get to m->NewQuestions,
4020 	// since we're not caching the record and we'll get no opportunity to do this later
4021 	while (m->CurrentQuestion)
4022 		{
4023 		DNSQuestion *q = m->CurrentQuestion;
4024 		if (ResourceRecordAnswersQuestion(&rr->resrec, q))
4025 			AnswerCurrentQuestionWithResourceRecord(m, rr, QC_addnocache);	// QC_addnocache means "don't expect remove events for this"
4026 		if (m->CurrentQuestion == q)	// If m->CurrentQuestion was not auto-advanced, do it ourselves now
4027 			m->CurrentQuestion = q->next;
4028 		}
4029 	m->CurrentQuestion = mDNSNULL;
4030 	}
4031 
4032 // CacheRecordRmv is only called from CheckCacheExpiration, which is called from mDNS_Execute.
4033 // Note that CacheRecordRmv is *only* called for records that are referenced by at least one active question.
4034 // If new questions are created as a result of invoking client callbacks, they will be added to
4035 // the end of the question list, and m->NewQuestions will be set to indicate the first new question.
4036 // rr is an existing cache CacheRecord that just expired and is being deleted
4037 // (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique).
4038 // Note: CacheRecordRmv calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
4039 // which may change the record list and/or question list.
4040 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
4041 mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr)
4042 	{
4043 	if (m->CurrentQuestion)
4044 		LogMsg("CacheRecordRmv ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
4045 	m->CurrentQuestion = m->Questions;
4046 
4047 	// We stop when we get to NewQuestions -- for new questions their CurrentAnswers/LargeAnswers/UniqueAnswers counters
4048 	// will all still be zero because we haven't yet gone through the cache counting how many answers we have for them.
4049 	while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
4050 		{
4051 		DNSQuestion *q = m->CurrentQuestion;
4052 		if (ResourceRecordAnswersQuestion(&rr->resrec, q))
4053 			{
4054 			verbosedebugf("CacheRecordRmv %p %s", rr, CRDisplayString(m, rr));
4055 			q->FlappingInterface1 = mDNSNULL;
4056 			q->FlappingInterface2 = mDNSNULL;
4057 			if (q->CurrentAnswers == 0)
4058 				LogMsg("CacheRecordRmv ERROR: How can CurrentAnswers already be zero for %p %##s (%s)?",
4059 					q, q->qname.c, DNSTypeName(q->qtype));
4060 			else
4061 				{
4062 				q->CurrentAnswers--;
4063 				if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers--;
4064 				if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers--;
4065 				}
4066 			if (rr->resrec.rdata->MaxRDLength) // Never generate "remove" events for negative results
4067 				{
4068 				if (q->CurrentAnswers == 0)
4069 					{
4070 					LogInfo("CacheRecordRmv: Last answer for %##s (%s) expired from cache; will reconfirm antecedents",
4071 						q->qname.c, DNSTypeName(q->qtype));
4072 					ReconfirmAntecedents(m, &q->qname, q->qnamehash, 0);
4073 					}
4074 				AnswerCurrentQuestionWithResourceRecord(m, rr, QC_rmv);
4075 				}
4076 			}
4077 		if (m->CurrentQuestion == q)	// If m->CurrentQuestion was not auto-advanced, do it ourselves now
4078 			m->CurrentQuestion = q->next;
4079 		}
4080 	m->CurrentQuestion = mDNSNULL;
4081 	}
4082 
4083 mDNSlocal void ReleaseCacheEntity(mDNS *const m, CacheEntity *e)
4084 	{
4085 #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1
4086 	unsigned int i;
4087 	for (i=0; i<sizeof(*e); i++) ((char*)e)[i] = 0xFF;
4088 #endif
4089 	e->next = m->rrcache_free;
4090 	m->rrcache_free = e;
4091 	m->rrcache_totalused--;
4092 	}
4093 
4094 mDNSlocal void ReleaseCacheGroup(mDNS *const m, CacheGroup **cp)
4095 	{
4096 	CacheEntity *e = (CacheEntity *)(*cp);
4097 	//LogMsg("ReleaseCacheGroup:  Releasing CacheGroup for %p, %##s", (*cp)->name->c, (*cp)->name->c);
4098 	if ((*cp)->rrcache_tail != &(*cp)->members)
4099 		LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrcache_tail != &(*cp)->members)");
4100 	//if ((*cp)->name != (domainname*)((*cp)->namestorage))
4101 	//	LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage));
4102 	if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name);
4103 	(*cp)->name = mDNSNULL;
4104 	*cp = (*cp)->next;			// Cut record from list
4105 	ReleaseCacheEntity(m, e);
4106 	}
4107 
4108 mDNSlocal void ReleaseCacheRecord(mDNS *const m, CacheRecord *r)
4109 	{
4110 	//LogMsg("ReleaseCacheRecord: Releasing %s", CRDisplayString(m, r));
4111 	if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->smallrdatastorage) mDNSPlatformMemFree(r->resrec.rdata);
4112 	r->resrec.rdata = mDNSNULL;
4113 	ReleaseCacheEntity(m, (CacheEntity *)r);
4114 	}
4115 
4116 // Note: We want to be careful that we deliver all the CacheRecordRmv calls before delivering
4117 // CacheRecordDeferredAdd calls. The in-order nature of the cache lists ensures that all
4118 // callbacks for old records are delivered before callbacks for newer records.
4119 mDNSlocal void CheckCacheExpiration(mDNS *const m, CacheGroup *const cg)
4120 	{
4121 	CacheRecord **rp = &cg->members;
4122 
4123 	if (m->lock_rrcache) { LogMsg("CheckCacheExpiration ERROR! Cache already locked!"); return; }
4124 	m->lock_rrcache = 1;
4125 
4126 	while (*rp)
4127 		{
4128 		CacheRecord *const rr = *rp;
4129 		mDNSs32 event = RRExpireTime(rr);
4130 		if (m->timenow - event >= 0)	// If expired, delete it
4131 			{
4132 			*rp = rr->next;				// Cut it from the list
4133 			verbosedebugf("CheckCacheExpiration: Deleting%7d %4d %p %s",
4134 				m->timenow - rr->TimeRcvd, rr->resrec.rroriginalttl, rr->CRActiveQuestion, CRDisplayString(m, rr));
4135 			if (rr->CRActiveQuestion)	// If this record has one or more active questions, tell them it's going away
4136 				{
4137 				CacheRecordRmv(m, rr);
4138 				m->rrcache_active--;
4139 				}
4140 			ReleaseCacheRecord(m, rr);
4141 			}
4142 		else							// else, not expired; see if we need to query
4143 			{
4144 			if (rr->DelayDelivery && rr->DelayDelivery - m->timenow > 0)
4145 				event = rr->DelayDelivery;
4146 			else
4147 				{
4148 				if (rr->DelayDelivery) CacheRecordDeferredAdd(m, rr);
4149 				if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
4150 					{
4151 					if (m->timenow - rr->NextRequiredQuery < 0)		// If not yet time for next query
4152 						event = rr->NextRequiredQuery;				// then just record when we want the next query
4153 					else											// else trigger our question to go out now
4154 						{
4155 						// Set NextScheduledQuery to timenow so that SendQueries() will run.
4156 						// SendQueries() will see that we have records close to expiration, and send FEQs for them.
4157 						m->NextScheduledQuery = m->timenow;
4158 						// After sending the query we'll increment UnansweredQueries and call SetNextCacheCheckTime(),
4159 						// which will correctly update m->NextCacheCheck for us.
4160 						event = m->timenow + 0x3FFFFFFF;
4161 						}
4162 					}
4163 				}
4164 			verbosedebugf("CheckCacheExpiration:%6d %5d %s",
4165 				(event - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m, rr));
4166 			if (m->NextCacheCheck - (event + CacheCheckGracePeriod(rr)) > 0)
4167 				m->NextCacheCheck = (event + CacheCheckGracePeriod(rr));
4168 			rp = &rr->next;
4169 			}
4170 		}
4171 	if (cg->rrcache_tail != rp) verbosedebugf("CheckCacheExpiration: Updating CacheGroup tail from %p to %p", cg->rrcache_tail, rp);
4172 	cg->rrcache_tail = rp;
4173 	m->lock_rrcache = 0;
4174 	}
4175 
4176 mDNSlocal void AnswerNewQuestion(mDNS *const m)
4177 	{
4178 	mDNSBool ShouldQueryImmediately = mDNStrue;
4179 	DNSQuestion *q = m->NewQuestions;		// Grab the question we're going to answer
4180 	const mDNSu32 slot = HashSlot(&q->qname);
4181 	CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
4182 
4183 	verbosedebugf("AnswerNewQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
4184 
4185 	if (cg) CheckCacheExpiration(m, cg);
4186 	m->NewQuestions = q->next;				// Advance NewQuestions to the next *after* calling CheckCacheExpiration();
4187 
4188 	if (m->lock_rrcache) LogMsg("AnswerNewQuestion ERROR! Cache already locked!");
4189 	// This should be safe, because calling the client's question callback may cause the
4190 	// question list to be modified, but should not ever cause the rrcache list to be modified.
4191 	// If the client's question callback deletes the question, then m->CurrentQuestion will
4192 	// be advanced, and we'll exit out of the loop
4193 	m->lock_rrcache = 1;
4194 	if (m->CurrentQuestion)
4195 		LogMsg("AnswerNewQuestion ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
4196 	m->CurrentQuestion = q;		// Indicate which question we're answering, so we'll know if it gets deleted
4197 
4198 	if (q->NoAnswer == NoAnswer_Fail)
4199 		{
4200 		LogMsg("AnswerNewQuestion: NoAnswer_Fail %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
4201 		MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any);
4202 		q->NoAnswer = NoAnswer_Normal;		// Temporarily turn off answer suppression
4203 		AnswerCurrentQuestionWithResourceRecord(m, &m->rec.r, QC_addnocache);
4204 		q->NoAnswer = NoAnswer_Fail;		// Restore NoAnswer state
4205 		m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
4206 		}
4207 
4208 	// If 'mDNSInterface_Any' question, see if we want to tell it about LocalOnly records
4209 	if (m->CurrentQuestion == q && q->InterfaceID == mDNSInterface_Any)
4210 		{
4211 		if (m->CurrentRecord)
4212 			LogMsg("AnswerNewQuestion ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
4213 		m->CurrentRecord = m->ResourceRecords;
4214 		while (m->CurrentRecord && m->CurrentRecord != m->NewLocalRecords)
4215 			{
4216 			AuthRecord *rr = m->CurrentRecord;
4217 			m->CurrentRecord = rr->next;
4218 			if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
4219 				if (ResourceRecordAnswersQuestion(&rr->resrec, q))
4220 					{
4221 					AnswerLocalQuestionWithLocalAuthRecord(m, q, rr, mDNStrue);
4222 					if (m->CurrentQuestion != q) break;		// If callback deleted q, then we're finished here
4223 					}
4224 			}
4225 		m->CurrentRecord = mDNSNULL;
4226 		}
4227 
4228 	if (m->CurrentQuestion != q) debugf("AnswerNewQuestion: question deleted while giving LocalOnly record answers");
4229 
4230 	if (m->CurrentQuestion == q)
4231 		{
4232 		CacheRecord *rr;
4233 		for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
4234 			if (SameNameRecordAnswersQuestion(&rr->resrec, q))
4235 				{
4236 				// SecsSinceRcvd is whole number of elapsed seconds, rounded down
4237 				mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - rr->TimeRcvd)) / mDNSPlatformOneSecond;
4238 				if (rr->resrec.rroriginalttl <= SecsSinceRcvd)
4239 					{
4240 					LogMsg("AnswerNewQuestion: How is rr->resrec.rroriginalttl %lu <= SecsSinceRcvd %lu for %s %d %d",
4241 						rr->resrec.rroriginalttl, SecsSinceRcvd, CRDisplayString(m, rr), m->timenow, rr->TimeRcvd);
4242 					continue;	// Go to next one in loop
4243 					}
4244 
4245 				// If this record set is marked unique, then that means we can reasonably assume we have the whole set
4246 				// -- we don't need to rush out on the network and query immediately to see if there are more answers out there
4247 				if ((rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) || (q->ExpectUnique))
4248 					ShouldQueryImmediately = mDNSfalse;
4249 				q->CurrentAnswers++;
4250 				if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++;
4251 				if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++;
4252 				AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
4253 				if (m->CurrentQuestion != q) break;		// If callback deleted q, then we're finished here
4254 				}
4255 			else if (RRTypeIsAddressType(rr->resrec.rrtype) && RRTypeIsAddressType(q->qtype))
4256 				ShouldQueryImmediately = mDNSfalse;
4257 		}
4258 
4259 	if (m->CurrentQuestion != q) debugf("AnswerNewQuestion: question deleted while giving cache answers");
4260 
4261 	if (m->CurrentQuestion == q && ShouldQueryImmediately && ActiveQuestion(q))
4262 		{
4263 		debugf("AnswerNewQuestion: ShouldQueryImmediately %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
4264 		q->ThisQInterval  = InitialQuestionInterval;
4265 		q->LastQTime      = m->timenow - q->ThisQInterval;
4266 		if (mDNSOpaque16IsZero(q->TargetQID))		// For mDNS, spread packets to avoid a burst of simultaneous queries
4267 			{
4268 			// Compute random delay in the range 1-6 seconds, then divide by 50 to get 20-120ms
4269 			if (!m->RandomQueryDelay)
4270 				m->RandomQueryDelay = (mDNSPlatformOneSecond + mDNSRandom(mDNSPlatformOneSecond*5) - 1) / 50 + 1;
4271 			q->LastQTime += m->RandomQueryDelay;
4272 			}
4273 
4274 		if (m->NextScheduledQuery - (q->LastQTime + q->ThisQInterval) > 0)
4275 			m->NextScheduledQuery = (q->LastQTime + q->ThisQInterval);
4276 		}
4277 
4278 	m->CurrentQuestion = mDNSNULL;
4279 	m->lock_rrcache = 0;
4280 	}
4281 
4282 // When a NewLocalOnlyQuestion is created, AnswerNewLocalOnlyQuestion runs though our ResourceRecords delivering any
4283 // appropriate answers, stopping if it reaches a NewLocalRecord -- these will be handled by AnswerAllLocalQuestionsWithLocalAuthRecord
4284 mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m)
4285 	{
4286 	DNSQuestion *q = m->NewLocalOnlyQuestions;		// Grab the question we're going to answer
4287 	m->NewLocalOnlyQuestions = q->next;				// Advance NewLocalOnlyQuestions to the next (if any)
4288 
4289 	debugf("AnswerNewLocalOnlyQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
4290 
4291 	if (m->CurrentQuestion)
4292 		LogMsg("AnswerNewLocalOnlyQuestion ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
4293 	m->CurrentQuestion = q;		// Indicate which question we're answering, so we'll know if it gets deleted
4294 
4295 	if (m->CurrentRecord)
4296 		LogMsg("AnswerNewLocalOnlyQuestion ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
4297 	m->CurrentRecord = m->ResourceRecords;
4298 
4299 	while (m->CurrentRecord && m->CurrentRecord != m->NewLocalRecords)
4300 		{
4301 		AuthRecord *rr = m->CurrentRecord;
4302 		m->CurrentRecord = rr->next;
4303 		if (ResourceRecordAnswersQuestion(&rr->resrec, q))
4304 			{
4305 			AnswerLocalQuestionWithLocalAuthRecord(m, q, rr, mDNStrue);
4306 			if (m->CurrentQuestion != q) break;		// If callback deleted q, then we're finished here
4307 			}
4308 		}
4309 
4310 	m->CurrentQuestion = mDNSNULL;
4311 	m->CurrentRecord   = mDNSNULL;
4312 	}
4313 
4314 mDNSlocal CacheEntity *GetCacheEntity(mDNS *const m, const CacheGroup *const PreserveCG)
4315 	{
4316 	CacheEntity *e = mDNSNULL;
4317 
4318 	if (m->lock_rrcache) { LogMsg("GetFreeCacheRR ERROR! Cache already locked!"); return(mDNSNULL); }
4319 	m->lock_rrcache = 1;
4320 
4321 	// If we have no free records, ask the client layer to give us some more memory
4322 	if (!m->rrcache_free && m->MainCallback)
4323 		{
4324 		if (m->rrcache_totalused != m->rrcache_size)
4325 			LogMsg("GetFreeCacheRR: count mismatch: m->rrcache_totalused %lu != m->rrcache_size %lu",
4326 				m->rrcache_totalused, m->rrcache_size);
4327 
4328 		// We don't want to be vulnerable to a malicious attacker flooding us with an infinite
4329 		// number of bogus records so that we keep growing our cache until the machine runs out of memory.
4330 		// To guard against this, if our cache grows above 512kB (approx 3168 records at 164 bytes each),
4331 		// and we're actively using less than 1/32 of that cache, then we purge all the unused records
4332 		// and recycle them, instead of allocating more memory.
4333 		if (m->rrcache_size > 5000 && m->rrcache_size / 32 > m->rrcache_active)
4334 			LogInfo("Possible denial-of-service attack in progress: m->rrcache_size %lu; m->rrcache_active %lu",
4335 				m->rrcache_size, m->rrcache_active);
4336 		else
4337 			{
4338 			mDNS_DropLockBeforeCallback();		// Allow client to legally make mDNS API calls from the callback
4339 			m->MainCallback(m, mStatus_GrowCache);
4340 			mDNS_ReclaimLockAfterCallback();	// Decrement mDNS_reentrancy to block mDNS API calls again
4341 			}
4342 		}
4343 
4344 	// If we still have no free records, recycle all the records we can.
4345 	// Enumerating the entire cache is moderately expensive, so when we do it, we reclaim all the records we can in one pass.
4346 	if (!m->rrcache_free)
4347 		{
4348 		mDNSu32 oldtotalused = m->rrcache_totalused;
4349 		mDNSu32 slot;
4350 		for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
4351 			{
4352 			CacheGroup **cp = &m->rrcache_hash[slot];
4353 			while (*cp)
4354 				{
4355 				CacheRecord **rp = &(*cp)->members;
4356 				while (*rp)
4357 					{
4358 					// Records that answer still-active questions are not candidates for recycling
4359 					// Records that are currently linked into the CacheFlushRecords list may not be recycled, or we'll crash
4360 					if ((*rp)->CRActiveQuestion || (*rp)->NextInCFList)
4361 						rp=&(*rp)->next;
4362 					else
4363 						{
4364 						CacheRecord *rr = *rp;
4365 						*rp = (*rp)->next;			// Cut record from list
4366 						ReleaseCacheRecord(m, rr);
4367 						}
4368 					}
4369 				if ((*cp)->rrcache_tail != rp)
4370 					verbosedebugf("GetFreeCacheRR: Updating rrcache_tail[%lu] from %p to %p", slot, (*cp)->rrcache_tail, rp);
4371 				(*cp)->rrcache_tail = rp;
4372 				if ((*cp)->members || (*cp)==PreserveCG) cp=&(*cp)->next;
4373 				else ReleaseCacheGroup(m, cp);
4374 				}
4375 			}
4376 		LogInfo("GetCacheEntity recycled %d records to reduce cache from %d to %d",
4377 			oldtotalused - m->rrcache_totalused, oldtotalused, m->rrcache_totalused);
4378 		}
4379 
4380 	if (m->rrcache_free)	// If there are records in the free list, take one
4381 		{
4382 		e = m->rrcache_free;
4383 		m->rrcache_free = e->next;
4384 		if (++m->rrcache_totalused >= m->rrcache_report)
4385 			{
4386 			LogInfo("RR Cache now using %ld objects", m->rrcache_totalused);
4387 			if      (m->rrcache_report <  100) m->rrcache_report += 10;
4388 			else if (m->rrcache_report < 1000) m->rrcache_report += 100;
4389 			else                               m->rrcache_report += 1000;
4390 			}
4391 		mDNSPlatformMemZero(e, sizeof(*e));
4392 		}
4393 
4394 	m->lock_rrcache = 0;
4395 
4396 	return(e);
4397 	}
4398 
4399 mDNSlocal CacheRecord *GetCacheRecord(mDNS *const m, CacheGroup *cg, mDNSu16 RDLength)
4400 	{
4401 	CacheRecord *r = (CacheRecord *)GetCacheEntity(m, cg);
4402 	if (r)
4403 		{
4404 		r->resrec.rdata = (RData*)&r->smallrdatastorage;	// By default, assume we're usually going to be using local storage
4405 		if (RDLength > InlineCacheRDSize)			// If RDLength is too big, allocate extra storage
4406 			{
4407 			r->resrec.rdata = (RData*)mDNSPlatformMemAllocate(sizeofRDataHeader + RDLength);
4408 			if (r->resrec.rdata) r->resrec.rdata->MaxRDLength = r->resrec.rdlength = RDLength;
4409 			else { ReleaseCacheEntity(m, (CacheEntity*)r); r = mDNSNULL; }
4410 			}
4411 		}
4412 	return(r);
4413 	}
4414 
4415 mDNSlocal CacheGroup *GetCacheGroup(mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr)
4416 	{
4417 	mDNSu16 namelen = DomainNameLength(rr->name);
4418 	CacheGroup *cg = (CacheGroup*)GetCacheEntity(m, mDNSNULL);
4419 	if (!cg) { LogMsg("GetCacheGroup: Failed to allocate memory for %##s", rr->name->c); return(mDNSNULL); }
4420 	cg->next         = m->rrcache_hash[slot];
4421 	cg->namehash     = rr->namehash;
4422 	cg->members      = mDNSNULL;
4423 	cg->rrcache_tail = &cg->members;
4424 	cg->name         = (domainname*)cg->namestorage;
4425 	//LogMsg("GetCacheGroup: %-10s %d-byte cache name %##s",
4426 	//	(namelen > InlineCacheGroupNameSize) ? "Allocating" : "Inline", namelen, rr->name->c);
4427 	if (namelen > InlineCacheGroupNameSize) cg->name = mDNSPlatformMemAllocate(namelen);
4428 	if (!cg->name)
4429 		{
4430 		LogMsg("GetCacheGroup: Failed to allocate name storage for %##s", rr->name->c);
4431 		ReleaseCacheEntity(m, (CacheEntity*)cg);
4432 		return(mDNSNULL);
4433 		}
4434 	AssignDomainName(cg->name, rr->name);
4435 
4436 	if (CacheGroupForRecord(m, slot, rr)) LogMsg("GetCacheGroup: Already have CacheGroup for %##s", rr->name->c);
4437 	m->rrcache_hash[slot] = cg;
4438 	if (CacheGroupForRecord(m, slot, rr) != cg) LogMsg("GetCacheGroup: Not finding CacheGroup for %##s", rr->name->c);
4439 
4440 	return(cg);
4441 	}
4442 
4443 mDNSexport void mDNS_PurgeCacheResourceRecord(mDNS *const m, CacheRecord *rr)
4444 	{
4445 	if (m->mDNS_busy != m->mDNS_reentrancy+1)
4446 		LogMsg("mDNS_PurgeCacheResourceRecord: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
4447 	// Make sure we mark this record as thoroughly expired -- we don't ever want to give
4448 	// a positive answer using an expired record (e.g. from an interface that has gone away).
4449 	// We don't want to clear CRActiveQuestion here, because that would leave the record subject to
4450 	// summary deletion without giving the proper callback to any questions that are monitoring it.
4451 	// By setting UnansweredQueries to MaxUnansweredQueries we ensure it won't trigger any further expiration queries.
4452 	rr->TimeRcvd          = m->timenow - mDNSPlatformOneSecond * 60;
4453 	rr->UnansweredQueries = MaxUnansweredQueries;
4454 	rr->resrec.rroriginalttl     = 0;
4455 	SetNextCacheCheckTime(m, rr);
4456 	}
4457 
4458 mDNSexport mDNSs32 mDNS_TimeNow(const mDNS *const m)
4459 	{
4460 	mDNSs32 time;
4461 	mDNSPlatformLock(m);
4462 	if (m->mDNS_busy)
4463 		{
4464 		LogMsg("mDNS_TimeNow called while holding mDNS lock. This is incorrect. Code protected by lock should just use m->timenow.");
4465 		if (!m->timenow) LogMsg("mDNS_TimeNow: m->mDNS_busy is %ld but m->timenow not set", m->mDNS_busy);
4466 		}
4467 
4468 	if (m->timenow) time = m->timenow;
4469 	else            time = mDNS_TimeNow_NoLock(m);
4470 	mDNSPlatformUnlock(m);
4471 	return(time);
4472 	}
4473 
4474 // To avoid pointless CPU thrash, we use SetSPSProxyListChanged(X) to record the last interface that
4475 // had its Sleep Proxy client list change, and defer to actual BPF reconfiguration to mDNS_Execute().
4476 // (GetNextScheduledEvent() returns "now" when m->SPSProxyListChanged is set)
4477 #define SetSPSProxyListChanged(X) do { \
4478 	if (m->SPSProxyListChanged && m->SPSProxyListChanged != (X)) mDNSPlatformUpdateProxyList(m, m->SPSProxyListChanged); \
4479 	m->SPSProxyListChanged = (X); } while(0)
4480 
4481 // Called from mDNS_Execute() to expire stale proxy records
4482 mDNSlocal void CheckProxyRecords(mDNS *const m, AuthRecord *list)
4483 	{
4484 	m->CurrentRecord = list;
4485 	while (m->CurrentRecord)
4486 		{
4487 		AuthRecord *rr = m->CurrentRecord;
4488 		if (rr->WakeUp.HMAC.l[0])
4489 			{
4490 			if (m->timenow - rr->TimeExpire < 0)		// If proxy record not expired yet, update m->NextScheduledSPS
4491 				{
4492 				if (m->NextScheduledSPS - rr->TimeExpire > 0)
4493 					m->NextScheduledSPS = rr->TimeExpire;
4494 				}
4495 			else										// else proxy record expired, so remove it
4496 				{
4497 				LogSPS("mDNS_Execute: Removing %d H-MAC %.6a I-MAC %.6a %d %s",
4498 					m->ProxyRecords, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, ARDisplayString(m, rr));
4499 				SetSPSProxyListChanged(rr->resrec.InterfaceID);
4500 				mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
4501 				// Don't touch rr after this -- memory may have been free'd
4502 				}
4503 			}
4504 		// Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal,
4505 		// because the list may have been changed in that call.
4506 		if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
4507 			m->CurrentRecord = rr->next;
4508 		}
4509 	}
4510 
4511 mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
4512 	{
4513 	mDNS_Lock(m);	// Must grab lock before trying to read m->timenow
4514 
4515 	if (m->timenow - m->NextScheduledEvent >= 0)
4516 		{
4517 		int i;
4518 
4519 		verbosedebugf("mDNS_Execute");
4520 		if (m->CurrentQuestion)
4521 			LogMsg("mDNS_Execute: ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
4522 
4523 		// 1. If we're past the probe suppression time, we can clear it
4524 		if (m->SuppressProbes && m->timenow - m->SuppressProbes >= 0) m->SuppressProbes = 0;
4525 
4526 		// 2. If it's been more than ten seconds since the last probe failure, we can clear the counter
4527 		if (m->NumFailedProbes && m->timenow - m->ProbeFailTime >= mDNSPlatformOneSecond * 10) m->NumFailedProbes = 0;
4528 
4529 		// 3. Purge our cache of stale old records
4530 		if (m->rrcache_size && m->timenow - m->NextCacheCheck >= 0)
4531 			{
4532 			mDNSu32 slot;
4533 			m->NextCacheCheck = m->timenow + 0x3FFFFFFF;
4534 			for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
4535 				{
4536 				CacheGroup **cp = &m->rrcache_hash[slot];
4537 				while (*cp)
4538 					{
4539 					CheckCacheExpiration(m, *cp);
4540 					if ((*cp)->members) cp=&(*cp)->next;
4541 					else ReleaseCacheGroup(m, cp);
4542 					}
4543 				}
4544 			}
4545 
4546 		if (m->timenow - m->NextScheduledSPS >= 0)
4547 			{
4548 			m->NextScheduledSPS = m->timenow + 0x3FFFFFFF;
4549 			CheckProxyRecords(m, m->DuplicateRecords);	// Clear m->DuplicateRecords first, then m->ResourceRecords
4550 			CheckProxyRecords(m, m->ResourceRecords);
4551 			}
4552 
4553 		SetSPSProxyListChanged(mDNSNULL);		// Perform any deferred BPF reconfiguration now
4554 
4555 		if (m->DelaySleep && m->timenow - m->DelaySleep >= 0)
4556 			{
4557 			m->DelaySleep = 0;
4558 			if (m->SleepState == SleepState_Transferring)
4559 				{
4560 				LogSPS("Re-sleep delay passed; now checking for Sleep Proxy Servers");
4561 				BeginSleepProcessing(m);
4562 				}
4563 			}
4564 
4565 		// 4. See if we can answer any of our new local questions from the cache
4566 		for (i=0; m->NewQuestions && i<1000; i++)
4567 			{
4568 			if (m->NewQuestions->DelayAnswering && m->timenow - m->NewQuestions->DelayAnswering < 0) break;
4569 			AnswerNewQuestion(m);
4570 			}
4571 		if (i >= 1000) LogMsg("mDNS_Execute: AnswerNewQuestion exceeded loop limit");
4572 
4573 		for (i=0; m->NewLocalOnlyQuestions && i<1000; i++) AnswerNewLocalOnlyQuestion(m);
4574 		if (i >= 1000) LogMsg("mDNS_Execute: AnswerNewLocalOnlyQuestion exceeded loop limit");
4575 
4576 		for (i=0; i<1000 && m->NewLocalRecords && LocalRecordReady(m->NewLocalRecords); i++)
4577 			{
4578 			AuthRecord *rr = m->NewLocalRecords;
4579 			m->NewLocalRecords = m->NewLocalRecords->next;
4580 			AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNStrue);
4581 			}
4582 		if (i >= 1000) LogMsg("mDNS_Execute: AnswerForNewLocalRecords exceeded loop limit");
4583 
4584 		// 5. See what packets we need to send
4585 		if (m->mDNSPlatformStatus != mStatus_NoError || (m->SleepState == SleepState_Sleeping))
4586 			DiscardDeregistrations(m);
4587 		if (m->mDNSPlatformStatus == mStatus_NoError && (m->SuppressSending == 0 || m->timenow - m->SuppressSending >= 0))
4588 			{
4589 			// If the platform code is ready, and we're not suppressing packet generation right now
4590 			// then send our responses, probes, and questions.
4591 			// We check the cache first, because there might be records close to expiring that trigger questions to refresh them.
4592 			// We send queries next, because there might be final-stage probes that complete their probing here, causing
4593 			// them to advance to announcing state, and we want those to be included in any announcements we send out.
4594 			// Finally, we send responses, including the previously mentioned records that just completed probing.
4595 			m->SuppressSending = 0;
4596 
4597 			// 6. Send Query packets. This may cause some probing records to advance to announcing state
4598 			if (m->timenow - m->NextScheduledQuery >= 0 || m->timenow - m->NextScheduledProbe >= 0) SendQueries(m);
4599 			if (m->timenow - m->NextScheduledQuery >= 0)
4600 				{
4601 				DNSQuestion *q;
4602 				LogMsg("mDNS_Execute: SendQueries didn't send all its queries (%d - %d = %d) will try again in one second",
4603 					m->timenow, m->NextScheduledQuery, m->timenow - m->NextScheduledQuery);
4604 				m->NextScheduledQuery = m->timenow + mDNSPlatformOneSecond;
4605 				for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
4606 					if (ActiveQuestion(q) && q->LastQTime + q->ThisQInterval - m->timenow <= 0)
4607 						LogMsg("mDNS_Execute: SendQueries didn't send %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
4608 				}
4609 			if (m->timenow - m->NextScheduledProbe >= 0)
4610 				{
4611 				LogMsg("mDNS_Execute: SendQueries didn't send all its probes (%d - %d = %d) will try again in one second",
4612 					m->timenow, m->NextScheduledProbe, m->timenow - m->NextScheduledProbe);
4613 				m->NextScheduledProbe = m->timenow + mDNSPlatformOneSecond;
4614 				}
4615 
4616 			// 7. Send Response packets, including probing records just advanced to announcing state
4617 			if (m->timenow - m->NextScheduledResponse >= 0) SendResponses(m);
4618 			if (m->timenow - m->NextScheduledResponse >= 0)
4619 				{
4620 				LogMsg("mDNS_Execute: SendResponses didn't send all its responses; will try again in one second");
4621 				m->NextScheduledResponse = m->timenow + mDNSPlatformOneSecond;
4622 				}
4623 			}
4624 
4625 		// Clear RandomDelay values, ready to pick a new different value next time
4626 		m->RandomQueryDelay     = 0;
4627 		m->RandomReconfirmDelay = 0;
4628 		}
4629 
4630 	// Note about multi-threaded systems:
4631 	// On a multi-threaded system, some other thread could run right after the mDNS_Unlock(),
4632 	// performing mDNS API operations that change our next scheduled event time.
4633 	//
4634 	// On multi-threaded systems (like the current Windows implementation) that have a single main thread
4635 	// calling mDNS_Execute() (and other threads allowed to call mDNS API routines) it is the responsibility
4636 	// of the mDNSPlatformUnlock() routine to signal some kind of stateful condition variable that will
4637 	// signal whatever blocking primitive the main thread is using, so that it will wake up and execute one
4638 	// more iteration of its loop, and immediately call mDNS_Execute() again. The signal has to be stateful
4639 	// in the sense that if the main thread has not yet entered its blocking primitive, then as soon as it
4640 	// does, the state of the signal will be noticed, causing the blocking primitive to return immediately
4641 	// without blocking. This avoids the race condition between the signal from the other thread arriving
4642 	// just *before* or just *after* the main thread enters the blocking primitive.
4643 	//
4644 	// On multi-threaded systems (like the current Mac OS 9 implementation) that are entirely timer-driven,
4645 	// with no main mDNS_Execute() thread, it is the responsibility of the mDNSPlatformUnlock() routine to
4646 	// set the timer according to the m->NextScheduledEvent value, and then when the timer fires, the timer
4647 	// callback function should call mDNS_Execute() (and ignore the return value, which may already be stale
4648 	// by the time it gets to the timer callback function).
4649 
4650 #ifndef UNICAST_DISABLED
4651 	uDNS_Execute(m);
4652 #endif
4653 	mDNS_Unlock(m);		// Calling mDNS_Unlock is what gives m->NextScheduledEvent its new value
4654 	return(m->NextScheduledEvent);
4655 	}
4656 
4657 mDNSlocal void SuspendLLQs(mDNS *m)
4658 	{
4659 	DNSQuestion *q;
4660 	for (q = m->Questions; q; q = q->next)
4661 		if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->state == LLQ_Established)
4662 			{ q->ReqLease = 0; sendLLQRefresh(m, q); }
4663 	}
4664 
4665 // ActivateUnicastQuery() is called from three places:
4666 // 1. When a new question is created
4667 // 2. On wake from sleep
4668 // 3. When the DNS configuration changes
4669 // In case 1 we don't want to mess with our established ThisQInterval and LastQTime (ScheduleImmediately is false)
4670 // In cases 2 and 3 we do want to cause the question to be resent immediately (ScheduleImmediately is true)
4671 mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question, mDNSBool ScheduleImmediately)
4672 	{
4673 	// For now this AutoTunnel stuff is specific to Mac OS X.
4674 	// In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer
4675 #if APPLE_OSX_mDNSResponder
4676 	// Even though BTMM client tunnels are only useful for AAAA queries, we need to treat v4 and v6 queries equally.
4677 	// Otherwise we can get the situation where the A query completes really fast (with an NXDOMAIN result) and the
4678 	// caller then gives up waiting for the AAAA result while we're still in the process of setting up the tunnel.
4679 	// To level the playing field, we block both A and AAAA queries while tunnel setup is in progress, and then
4680 	// returns results for both at the same time.
4681 	if (RRTypeIsAddressType(question->qtype) && question->AuthInfo && question->AuthInfo->AutoTunnel && question->QuestionCallback != AutoTunnelCallback)
4682 		{
4683 		question->NoAnswer = NoAnswer_Suspended;
4684 		AddNewClientTunnel(m, question);
4685 		return;
4686 		}
4687 #endif // APPLE_OSX_mDNSResponder
4688 
4689 	if (!question->DuplicateOf)
4690 		{
4691 		debugf("ActivateUnicastQuery: %##s %s%s%s",
4692 			question->qname.c, DNSTypeName(question->qtype), question->AuthInfo ? " (Private)" : "", ScheduleImmediately ? " ScheduleImmediately" : "");
4693 		if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
4694 		if (question->LongLived)
4695 			{
4696 			question->state = LLQ_InitialRequest;
4697 			question->id = zeroOpaque64;
4698 			question->servPort = zeroIPPort;
4699 			if (question->tcp) { DisposeTCPConn(question->tcp); question->tcp = mDNSNULL; }
4700 			}
4701 		if (ScheduleImmediately)
4702 			{
4703 			question->ThisQInterval = InitialQuestionInterval;
4704 			question->LastQTime     = m->timenow - question->ThisQInterval;
4705 			SetNextQueryTime(m, question);
4706 			}
4707 		}
4708 	}
4709 
4710 mDNSexport void mDNSCoreRestartQueries(mDNS *const m)
4711 	{
4712 	DNSQuestion *q;
4713 
4714 #ifndef UNICAST_DISABLED
4715 	// Retrigger all our uDNS questions
4716 	if (m->CurrentQuestion)
4717 		LogMsg("mDNSCoreRestartQueries: ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
4718 	m->CurrentQuestion = m->Questions;
4719 	while (m->CurrentQuestion)
4720 		{
4721 		q = m->CurrentQuestion;
4722 		m->CurrentQuestion = m->CurrentQuestion->next;
4723 		if (!mDNSOpaque16IsZero(q->TargetQID)) ActivateUnicastQuery(m, q, mDNStrue);
4724 		}
4725 #endif
4726 
4727 	// Retrigger all our mDNS questions
4728 	for (q = m->Questions; q; q=q->next)				// Scan our list of questions
4729 		if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q))
4730 			{
4731 			q->ThisQInterval    = InitialQuestionInterval;	// MUST be > zero for an active question
4732 			q->RequestUnicast   = 2;						// Set to 2 because is decremented once *before* we check it
4733 			q->LastQTime        = m->timenow - q->ThisQInterval;
4734 			q->RecentAnswerPkts = 0;
4735 			ExpireDupSuppressInfo(q->DupSuppress, m->timenow);
4736 			m->NextScheduledQuery = m->timenow;
4737 			}
4738 	}
4739 
4740 // ***************************************************************************
4741 #if COMPILER_LIKES_PRAGMA_MARK
4742 #pragma mark -
4743 #pragma mark - Power Management (Sleep/Wake)
4744 #endif
4745 
4746 mDNSlocal void SendSPSRegistration(mDNS *const m, NetworkInterfaceInfo *intf, const mDNSOpaque16 id)
4747 	{
4748 	const int ownerspace = mDNSSameEthAddress(&m->PrimaryMAC, &intf->MAC) ? DNSOpt_OwnerData_ID_Space : DNSOpt_OwnerData_ID_Wake_Space;
4749 	const int optspace = DNSOpt_Header_Space + DNSOpt_LeaseData_Space + ownerspace;
4750 	const int sps = intf->NextSPSAttempt / 3;
4751 	AuthRecord *rr;
4752 
4753 	if (!intf->SPSAddr[sps].type)
4754 		{
4755 		intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond;
4756 		if (m->NextScheduledSPRetry - intf->NextSPSAttemptTime > 0)
4757 			m->NextScheduledSPRetry = intf->NextSPSAttemptTime;
4758 		LogSPS("SendSPSRegistration: %s SPS %d (%d) %##s not yet resolved", intf->ifname, intf->NextSPSAttempt, sps, intf->NetWakeResolve[sps].qname.c);
4759 		goto exit;
4760 		}
4761 
4762 	// Mark our mDNS records (not unicast records) for transfer to SPS
4763 	if (mDNSOpaque16IsZero(id))
4764 		for (rr = m->ResourceRecords; rr; rr=rr->next)
4765 			if (rr->resrec.RecordType > kDNSRecordTypeDeregistering)
4766 				if (rr->resrec.InterfaceID == intf->InterfaceID || (!rr->resrec.InterfaceID && (rr->ForceMCast || IsLocalDomain(rr->resrec.name))))
4767 					rr->SendRNow = mDNSInterfaceMark;	// mark it now
4768 
4769 	while (1)
4770 		{
4771 		mDNSu8 *p = m->omsg.data;
4772 		// To comply with RFC 2782, PutResourceRecord suppresses name compression for SRV records in unicast updates.
4773 		// For now we follow that same logic for SPS registrations too.
4774 		// If we decide to compress SRV records in SPS registrations in the future, we can achieve that by creating our
4775 		// initial DNSMessage with h.flags set to zero, and then update it to UpdateReqFlags right before sending the packet.
4776 		InitializeDNSMessage(&m->omsg.h, mDNSOpaque16IsZero(id) ? mDNS_NewMessageID(m) : id, UpdateReqFlags);
4777 
4778 		for (rr = m->ResourceRecords; rr; rr=rr->next)
4779 			if (rr->SendRNow || (!mDNSOpaque16IsZero(id) && !AuthRecord_uDNS(rr) && mDNSSameOpaque16(rr->updateid, id) && m->timenow - (rr->LastAPTime + rr->ThisAPInterval) >= 0))
4780 				{
4781 				mDNSu8 *newptr;
4782 				const mDNSu8 *const limit = m->omsg.data + (m->omsg.h.mDNS_numUpdates ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData) - optspace;
4783 				if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
4784 					rr->resrec.rrclass |= kDNSClass_UniqueRRSet;	// Temporarily set the 'unique' bit so PutResourceRecord will set it
4785 				newptr = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl, limit);
4786 				rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;		// Make sure to clear 'unique' bit back to normal state
4787 				if (!newptr)
4788 					LogSPS("SendSPSRegistration put %s FAILED %d/%d %s", intf->ifname, p - m->omsg.data, limit - m->omsg.data, ARDisplayString(m, rr));
4789 				else
4790 					{
4791 					LogSPS("SendSPSRegistration put %s %s", intf->ifname, ARDisplayString(m, rr));
4792 					rr->SendRNow       = mDNSNULL;
4793 					rr->ThisAPInterval = mDNSPlatformOneSecond;
4794 					rr->LastAPTime     = m->timenow;
4795 					rr->updateid       = m->omsg.h.id;
4796 					if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
4797 						m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval);
4798 					p = newptr;
4799 					}
4800 				}
4801 
4802 		if (!m->omsg.h.mDNS_numUpdates) break;
4803 		else
4804 			{
4805 			AuthRecord opt;
4806 			mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
4807 			opt.resrec.rrclass    = NormalMaxDNSMessageData;
4808 			opt.resrec.rdlength   = sizeof(rdataOPT) * 2;	// Two options in this OPT record
4809 			opt.resrec.rdestimate = sizeof(rdataOPT) * 2;
4810 			opt.resrec.rdata->u.opt[0].opt              = kDNSOpt_Lease;
4811 			opt.resrec.rdata->u.opt[0].optlen           = DNSOpt_LeaseData_Space - 4;
4812 			opt.resrec.rdata->u.opt[0].u.updatelease    = DEFAULT_UPDATE_LEASE;
4813 			SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[1]);
4814 			LogSPS("SendSPSRegistration put %s %s", intf->ifname, ARDisplayString(m, &opt));
4815 			p = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.numAdditionals, &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
4816 			if (!p)
4817 				LogMsg("SendSPSRegistration: Failed to put OPT record (%d updates) %s", m->omsg.h.mDNS_numUpdates, ARDisplayString(m, &opt));
4818 			else
4819 				{
4820 				mStatus err;
4821 				LogSPS("SendSPSRegistration: Sending Update %s %d (%d) id %5d with %d records %d bytes to %#a:%d", intf->ifname, intf->NextSPSAttempt, sps,
4822 					mDNSVal16(m->omsg.h.id), m->omsg.h.mDNS_numUpdates, p - m->omsg.data, &intf->SPSAddr[sps], mDNSVal16(intf->SPSPort[sps]));
4823 				// if (intf->NextSPSAttempt < 5) m->omsg.h.flags = zeroID;	// For simulating packet loss
4824 				err = mDNSSendDNSMessage(m, &m->omsg, p, intf->InterfaceID, mDNSNULL, &intf->SPSAddr[sps], intf->SPSPort[sps], mDNSNULL, mDNSNULL);
4825 				if (err) LogSPS("SendSPSRegistration: mDNSSendDNSMessage err %d", err);
4826 				if (err && intf->SPSAddr[sps].type == mDNSAddrType_IPv6 && intf->NetWakeResolve[sps].ThisQInterval == -1)
4827 					{
4828 					LogSPS("SendSPSRegistration %d %##s failed to send to IPv6 address; will try IPv4 instead", sps, intf->NetWakeResolve[sps].qname.c);
4829 					intf->NetWakeResolve[sps].qtype = kDNSType_A;
4830 					mDNS_StartQuery_internal(m, &intf->NetWakeResolve[sps]);
4831 					return;
4832 					}
4833 				}
4834 			}
4835 		}
4836 
4837 	intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond * 10;		// If successful, update NextSPSAttemptTime
4838 
4839 exit:
4840 	if (mDNSOpaque16IsZero(id) && intf->NextSPSAttempt < 8) intf->NextSPSAttempt++;
4841 	}
4842 
4843 // RetrySPSRegistrations is called from SendResponses, with the lock held
4844 mDNSlocal void RetrySPSRegistrations(mDNS *const m)
4845 	{
4846 	AuthRecord *rr;
4847 	NetworkInterfaceInfo *intf;
4848 
4849 	// First make sure none of our interfaces' NextSPSAttemptTimes are inadvertently set to m->timenow + mDNSPlatformOneSecond * 10
4850 	for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
4851 		if (intf->NextSPSAttempt && intf->NextSPSAttemptTime == m->timenow + mDNSPlatformOneSecond * 10)
4852 			intf->NextSPSAttemptTime++;
4853 
4854 	// Retry any record registrations that are due
4855 	for (rr = m->ResourceRecords; rr; rr=rr->next)
4856 		if (!AuthRecord_uDNS(rr) && !mDNSOpaque16IsZero(rr->updateid) && m->timenow - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
4857 			for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
4858 				if (!rr->resrec.InterfaceID || rr->resrec.InterfaceID == intf->InterfaceID)
4859 					{
4860 					LogSPS("RetrySPSRegistrations: %s", ARDisplayString(m, rr));
4861 					SendSPSRegistration(m, intf, rr->updateid);
4862 					}
4863 
4864 	// For interfaces where we did an SPS registration attempt, increment intf->NextSPSAttempt
4865 	for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
4866 		if (intf->NextSPSAttempt && intf->NextSPSAttemptTime == m->timenow + mDNSPlatformOneSecond * 10 && intf->NextSPSAttempt < 8)
4867 			intf->NextSPSAttempt++;
4868 	}
4869 
4870 mDNSlocal void NetWakeResolve(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
4871 	{
4872 	NetworkInterfaceInfo *intf = (NetworkInterfaceInfo *)question->QuestionContext;
4873 	int sps = question - intf->NetWakeResolve;
4874 	(void)m;			// Unused
4875 	LogSPS("NetWakeResolve: SPS: %d Add: %d %s", sps, AddRecord, RRDisplayString(m, answer));
4876 
4877 	if (!AddRecord) return;												// Don't care about REMOVE events
4878 	if (answer->rrtype != question->qtype) return;						// Don't care about CNAMEs
4879 
4880 	mDNS_StopQuery(m, question);
4881 	question->ThisQInterval = -1;
4882 
4883 	if (answer->rrtype == kDNSType_SRV)
4884 		{
4885 		intf->SPSPort[sps] = answer->rdata->u.srv.port;
4886 		AssignDomainName(&question->qname, &answer->rdata->u.srv.target);
4887 		question->qtype = kDNSType_AAAA;
4888 		mDNS_StartQuery(m, question);
4889 		}
4890 	else if (answer->rrtype == kDNSType_AAAA && answer->rdlength == sizeof(mDNSv6Addr) && mDNSv6AddressIsLinkLocal(&answer->rdata->u.ipv6))
4891 		{
4892 		intf->SPSAddr[sps].type = mDNSAddrType_IPv6;
4893 		intf->SPSAddr[sps].ip.v6 = answer->rdata->u.ipv6;
4894 		mDNS_Lock(m);
4895 		if (sps == intf->NextSPSAttempt/3) SendSPSRegistration(m, intf, zeroID);	// If we're ready for this result, use it now
4896 		mDNS_Unlock(m);
4897 		}
4898 	else if (answer->rrtype == kDNSType_AAAA && answer->rdlength == 0)	// If negative answer for IPv6, look for IPv4 addresses instead
4899 		{
4900 		LogSPS("NetWakeResolve: SPS %d %##s has no IPv6 address, will try IPv4 instead", sps, question->qname.c);
4901 		question->qtype = kDNSType_A;
4902 		mDNS_StartQuery(m, question);
4903 		}
4904 	else if (answer->rrtype == kDNSType_A && answer->rdlength == sizeof(mDNSv4Addr))
4905 		{
4906 		intf->SPSAddr[sps].type = mDNSAddrType_IPv4;
4907 		intf->SPSAddr[sps].ip.v4 = answer->rdata->u.ipv4;
4908 		mDNS_Lock(m);
4909 		if (sps == intf->NextSPSAttempt/3) SendSPSRegistration(m, intf, zeroID);	// If we're ready for this result, use it now
4910 		mDNS_Unlock(m);
4911 		}
4912 	}
4913 
4914 mDNSexport mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m)
4915 	{
4916 	AuthRecord *rr;
4917 	for (rr = m->ResourceRecords; rr; rr=rr->next)
4918 		if (rr->resrec.rrtype == kDNSType_SRV && !AuthRecord_uDNS(rr) && !mDNSSameIPPort(rr->resrec.rdata->u.srv.port, DiscardPort))
4919 			return mDNStrue;
4920 	return mDNSfalse;
4921 	}
4922 
4923 // BeginSleepProcessing is called, with the lock held, from either mDNS_Execute or mDNSCoreMachineSleep
4924 mDNSlocal void BeginSleepProcessing(mDNS *const m)
4925 	{
4926 	const CacheRecord *sps[3] = { mDNSNULL };
4927 
4928 	m->NextScheduledSPRetry = m->timenow;
4929 
4930 	if      (!m->SystemWakeOnLANEnabled)                  LogSPS("BeginSleepProcessing: m->SystemWakeOnLANEnabled is false");
4931 	else if (!mDNSCoreHaveAdvertisedMulticastServices(m)) LogSPS("BeginSleepProcessing: No advertised services");
4932 	else	// If we have at least one advertised service
4933 		{
4934 		NetworkInterfaceInfo *intf;
4935 		for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
4936 			{
4937 			if (!intf->NetWake) LogSPS("BeginSleepProcessing: %-6s not capable of magic packet wakeup", intf->ifname);
4938 			else
4939 				{
4940 				FindSPSInCache(m, &intf->NetWakeBrowse, sps);
4941 				if (!sps[0]) LogSPS("BeginSleepProcessing: %-6s %#a No Sleep Proxy Server found %d", intf->ifname, &intf->ip, intf->NetWakeBrowse.ThisQInterval);
4942 				else
4943 					{
4944 					int i;
4945 					intf->NextSPSAttempt = 0;
4946 					intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond;
4947 					// Don't need to set m->NextScheduledSPRetry here because we already set "m->NextScheduledSPRetry = m->timenow" above
4948 					for (i=0; i<3; i++)
4949 						{
4950 #if ForceAlerts
4951 						if (intf->SPSAddr[i].type)
4952 							{ LogMsg("BeginSleepProcessing: %s %d intf->SPSAddr[i].type %d", intf->ifname, i, intf->SPSAddr[i].type); *(long*)0 = 0; }
4953 						if (intf->NetWakeResolve[i].ThisQInterval >= 0)
4954 							{ LogMsg("BeginSleepProcessing: %s %d intf->NetWakeResolve[i].ThisQInterval %d", intf->ifname, i, intf->NetWakeResolve[i].ThisQInterval); *(long*)0 = 0; }
4955 #endif
4956 						intf->SPSAddr[i].type = mDNSAddrType_None;
4957 						if (intf->NetWakeResolve[i].ThisQInterval >= 0) mDNS_StopQuery(m, &intf->NetWakeResolve[i]);
4958 						intf->NetWakeResolve[i].ThisQInterval = -1;
4959 						if (sps[i])
4960 							{
4961 							LogSPS("BeginSleepProcessing: %-6s Found Sleep Proxy Server %d TTL %d %s", intf->ifname, i, sps[i]->resrec.rroriginalttl, CRDisplayString(m, sps[i]));
4962 							mDNS_SetupQuestion(&intf->NetWakeResolve[i], intf->InterfaceID, &sps[i]->resrec.rdata->u.name, kDNSType_SRV, NetWakeResolve, intf);
4963 							intf->NetWakeResolve[i].ReturnIntermed = mDNStrue;
4964 							mDNS_StartQuery_internal(m, &intf->NetWakeResolve[i]);
4965 							}
4966 						}
4967 					}
4968 				}
4969 			}
4970 		}
4971 
4972 	if (!sps[0])	// If we didn't find even one Sleep Proxy
4973 		{
4974 		AuthRecord *rr;
4975 		LogSPS("BeginSleepProcessing: Not registering with Sleep Proxy Server");
4976 		m->SleepState = SleepState_Sleeping;
4977 
4978 #ifndef UNICAST_DISABLED
4979 		SleepServiceRegistrations(m);
4980 		SleepRecordRegistrations(m);	// If we have no SPS, need to deregister our uDNS records
4981 #endif
4982 
4983 		// Mark all the records we need to deregister and send them
4984 		for (rr = m->ResourceRecords; rr; rr=rr->next)
4985 			if (rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye)
4986 				rr->ImmedAnswer = mDNSInterfaceMark;
4987 		SendResponses(m);
4988 		}
4989 	}
4990 
4991 // Call mDNSCoreMachineSleep(m, mDNStrue) when the machine is about to go to sleep.
4992 // Call mDNSCoreMachineSleep(m, mDNSfalse) when the machine is has just woken up.
4993 // Normally, the platform support layer below mDNSCore should call this, not the client layer above.
4994 mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep)
4995 	{
4996 	AuthRecord *rr;
4997 
4998 	mDNS_Lock(m);
4999 
5000 	LogSPS("%s (old state %d) at %ld", sleep ? "Sleeping" : "Waking", m->SleepState, m->timenow);
5001 
5002 	if (sleep && !m->SleepState)		// Going to sleep
5003 		{
5004 		// If we're going to sleep, need to stop advertising that we're a Sleep Proxy Server
5005 		if (m->SPSSocket)
5006 			{
5007 			mDNSu8 oldstate = m->SPSState;
5008 			mDNS_DropLockBeforeCallback();		// mDNS_DeregisterService expects to be called without the lock held, so we emulate that here
5009 			m->SPSState = 2;
5010 			if (oldstate == 1) mDNS_DeregisterService(m, &m->SPSRecords);
5011 			mDNS_ReclaimLockAfterCallback();
5012 			}
5013 
5014 		m->SleepState = SleepState_Transferring;
5015 		if (m->SystemWakeOnLANEnabled && m->DelaySleep)
5016 			{
5017 			// If we just woke up moments ago, allow ten seconds for networking to stabilize before going back to sleep
5018 			LogSPS("mDNSCoreMachineSleep: Re-sleeping immediately after waking; will delay for %d ticks", m->DelaySleep - m->timenow);
5019 			m->SleepLimit = m->DelaySleep + mDNSPlatformOneSecond * 10;
5020 			}
5021 		else
5022 			{
5023 			m->DelaySleep = 0;
5024 			m->SleepLimit = m->timenow + mDNSPlatformOneSecond * 10;
5025 			BeginSleepProcessing(m);
5026 			}
5027 
5028 #ifndef UNICAST_DISABLED
5029 		SuspendLLQs(m);
5030 #endif
5031 		LogSPS("mDNSCoreMachineSleep: m->SleepState %d (%s) seq %d", m->SleepState,
5032 			m->SleepState == SleepState_Transferring ? "Transferring" :
5033 			m->SleepState == SleepState_Sleeping     ? "Sleeping"     : "?", m->SleepSeqNum);
5034 		}
5035 	else if (!sleep)		// Waking up
5036 		{
5037 		mDNSu32 slot;
5038 		CacheGroup *cg;
5039 		CacheRecord *cr;
5040 		NetworkInterfaceInfo *intf;
5041 
5042 		// If we were previously sleeping, but now we're not, increment m->SleepSeqNum to indicate that we're entering a new period of wakefulness
5043 		if (m->SleepState != SleepState_Awake)
5044 			{
5045 			m->SleepState = SleepState_Awake;
5046 			m->SleepSeqNum++;
5047 			// If the machine wakes and then immediately tries to sleep again (e.g. a maintenance wake)
5048 			// then we enforce a minimum delay of 16 seconds before we begin sleep processing.
5049 			// This is to allow time for the Ethernet link to come up, DHCP to get an address, mDNS to issue queries, etc.,
5050 			// before we make our determination of whether there's a Sleep Proxy out there we should register with.
5051 			m->DelaySleep = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 16);
5052 			}
5053 
5054 		if (m->SPSState == 3)
5055 			{
5056 			mDNS_DropLockBeforeCallback();		// mDNS_DeregisterService expects to be called without the lock held, so we emulate that here
5057 			m->SPSState = 0;
5058 			mDNSCoreBeSleepProxyServer(m, m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower);
5059 			mDNS_ReclaimLockAfterCallback();
5060 			}
5061 
5062 		// In case we gave up waiting and went to sleep before we got an ack from the Sleep Proxy,
5063 		// on wake we go through our record list and clear updateid back to zero
5064 		for (rr = m->ResourceRecords; rr; rr=rr->next) rr->updateid = zeroID;
5065 
5066 		// ... and the same for NextSPSAttempt
5067 		for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) intf->NextSPSAttempt = -1;
5068 
5069 		// Restart unicast and multicast queries
5070 		mDNSCoreRestartQueries(m);
5071 
5072 		// and reactivtate service registrations
5073 		m->NextSRVUpdate = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
5074 		LogInfo("WakeServiceRegistrations %d %d", m->timenow, m->NextSRVUpdate);
5075 
5076 		// 2. Re-validate our cache records
5077 		m->NextCacheCheck  = m->timenow;
5078 		FORALL_CACHERECORDS(slot, cg, cr)
5079 			mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForWake);
5080 
5081 		// 3. Retrigger probing and announcing for all our authoritative records
5082 		for (rr = m->ResourceRecords; rr; rr=rr->next)
5083 			if (AuthRecord_uDNS(rr))
5084 				{
5085 				ActivateUnicastRegistration(m, rr);
5086 				}
5087 			else
5088 				{
5089 				if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
5090 				rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
5091 				rr->AnnounceCount  = InitialAnnounceCount;
5092 				InitializeLastAPTime(m, rr);
5093 				}
5094 
5095 		// 4. Refresh NAT mappings
5096 		// We don't want to have to assume that all hardware can necessarily keep accurate
5097 		// track of passage of time while asleep, so on wake we refresh our NAT mappings
5098 		m->retryIntervalGetAddr = NATMAP_INIT_RETRY;
5099 		m->retryGetAddr         = m->timenow;
5100 		RecreateNATMappings(m);
5101 		}
5102 
5103 	mDNS_Unlock(m);
5104 	}
5105 
5106 mDNSexport mDNSBool mDNSCoreReadyForSleep(mDNS *m)
5107 	{
5108 	DNSQuestion *q;
5109 	AuthRecord *rr;
5110 	ServiceRecordSet *srs;
5111 	NetworkInterfaceInfo *intf;
5112 
5113 	mDNS_Lock(m);
5114 
5115 	if (m->NextScheduledSPRetry - m->timenow > 0) goto notready;
5116 
5117 	m->NextScheduledSPRetry = m->timenow + 0x40000000UL;
5118 
5119 	if (m->DelaySleep) goto notready;
5120 
5121 	// See if we might need to retransmit any lost Sleep Proxy Registrations
5122 	for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
5123 		if (intf->NextSPSAttempt >= 0)
5124 			{
5125 			if (m->timenow - intf->NextSPSAttemptTime >= 0)
5126 				{
5127 				LogSPS("ReadyForSleep retrying SPS %s %d", intf->ifname, intf->NextSPSAttempt);
5128 				SendSPSRegistration(m, intf, zeroID);
5129 				}
5130 			else
5131 				if (m->NextScheduledSPRetry - intf->NextSPSAttemptTime > 0)
5132 					m->NextScheduledSPRetry = intf->NextSPSAttemptTime;
5133 			}
5134 
5135 	// Scan list of private LLQs, and make sure they've all completed their handshake with the server
5136 	for (q = m->Questions; q; q = q->next)
5137 		if (!mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->ReqLease == 0 && q->tcp)
5138 			{
5139 			LogSPS("ReadyForSleep waiting for LLQ %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
5140 			goto notready;
5141 			}
5142 
5143 	// Scan list of interfaces
5144 	for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
5145 		if (intf->NetWakeResolve[0].ThisQInterval >= 0)
5146 			{
5147 			LogSPS("ReadyForSleep waiting for SPS Resolve %s %##s (%s)", intf->ifname, intf->NetWakeResolve[0].qname.c, DNSTypeName(intf->NetWakeResolve[0].qtype));
5148 			goto notready;
5149 			}
5150 
5151 	// Scan list of registered records
5152 	for (rr = m->ResourceRecords; rr; rr = rr->next)
5153 		{
5154 		if (AuthRecord_uDNS(rr))
5155 			{
5156 			if (rr->state == regState_Refresh && rr->tcp)
5157 				{ LogSPS("ReadyForSleep waiting for Record Update ID %d %s", mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto notready; }
5158 			}
5159 		else
5160 			{
5161 			if (!mDNSOpaque16IsZero(rr->updateid))
5162 				{ LogSPS("ReadyForSleep waiting for SPS Update ID %d %s", mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto notready; }
5163 			}
5164 		}
5165 
5166 	// Scan list of registered services
5167 	for (srs = m->ServiceRegistrations; srs; srs = srs->uDNS_next)
5168 		if (srs->state == regState_NoTarget && srs->tcp) goto notready;
5169 
5170 	mDNS_Unlock(m);
5171 	return mDNStrue;
5172 
5173 notready:
5174 	mDNS_Unlock(m);
5175 	return mDNSfalse;
5176 	}
5177 
5178 mDNSexport mDNSs32 mDNSCoreIntervalToNextWake(mDNS *const m, mDNSs32 now)
5179 	{
5180 	AuthRecord *ar;
5181 
5182 	// Even when we have no wake-on-LAN-capable interfaces, or we failed to find a sleep proxy, or we have other
5183 	// failure scenarios, we still want to wake up in at most 120 minutes, to see if the network environment has changed.
5184 	// E.g. we might wake up and find no wireless network because the base station got rebooted just at that moment,
5185 	// and if that happens we don't want to just give up and go back to sleep and never try again.
5186 	mDNSs32 e = now + (120 * 60 * mDNSPlatformOneSecond);		// Sleep for at most 120 minutes
5187 
5188 	NATTraversalInfo *nat;
5189 	for (nat = m->NATTraversals; nat; nat=nat->next)
5190 		if (nat->Protocol && nat->ExpiryTime && nat->ExpiryTime - now > mDNSPlatformOneSecond*4)
5191 			{
5192 			mDNSs32 t = nat->ExpiryTime - (nat->ExpiryTime - now) / 10;		// Wake up when 90% of the way to the expiry time
5193 			if (e - t > 0) e = t;
5194 			LogSPS("ComputeWakeTime: %p %s Int %5d Ext %5d Err %d Retry %5d Interval %5d Expire %5d Wake %5d",
5195 				nat, nat->Protocol == NATOp_MapTCP ? "TCP" : "UDP",
5196 				mDNSVal16(nat->IntPort), mDNSVal16(nat->ExternalPort), nat->Result,
5197 				nat->retryPortMap ? (nat->retryPortMap - now) / mDNSPlatformOneSecond : 0,
5198 				nat->retryInterval / mDNSPlatformOneSecond,
5199 				nat->ExpiryTime ? (nat->ExpiryTime - now) / mDNSPlatformOneSecond : 0,
5200 				(t - now) / mDNSPlatformOneSecond);
5201 			}
5202 
5203 	// This loop checks both the time we need to renew wide-area registrations,
5204 	// and the time we need to renew Sleep Proxy registrations
5205 	for (ar = m->ResourceRecords; ar; ar = ar->next)
5206 		if (ar->expire && ar->expire - now > mDNSPlatformOneSecond*4)
5207 			{
5208 			mDNSs32 t = ar->expire - (ar->expire - now) / 10;		// Wake up when 90% of the way to the expiry time
5209 			if (e - t > 0) e = t;
5210 			LogSPS("ComputeWakeTime: %p Int %7d Next %7d Expire %7d Wake %7d %s",
5211 				ar, ar->ThisAPInterval / mDNSPlatformOneSecond,
5212 				(ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond,
5213 				ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
5214 				(t - now) / mDNSPlatformOneSecond, ARDisplayString(m, ar));
5215 			}
5216 
5217 	return(e - now);
5218 	}
5219 
5220 // ***************************************************************************
5221 #if COMPILER_LIKES_PRAGMA_MARK
5222 #pragma mark -
5223 #pragma mark - Packet Reception Functions
5224 #endif
5225 
5226 #define MustSendRecord(RR) ((RR)->NR_AnswerTo || (RR)->NR_AdditionalTo)
5227 
5228 mDNSlocal mDNSu8 *GenerateUnicastResponse(const DNSMessage *const query, const mDNSu8 *const end,
5229 	const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, DNSMessage *const response, AuthRecord *ResponseRecords)
5230 	{
5231 	mDNSu8          *responseptr     = response->data;
5232 	const mDNSu8    *const limit     = response->data + sizeof(response->data);
5233 	const mDNSu8    *ptr             = query->data;
5234 	AuthRecord  *rr;
5235 	mDNSu32          maxttl = 0x70000000;
5236 	int i;
5237 
5238 	// Initialize the response fields so we can answer the questions
5239 	InitializeDNSMessage(&response->h, query->h.id, ResponseFlags);
5240 
5241 	// ***
5242 	// *** 1. Write out the list of questions we are actually going to answer with this packet
5243 	// ***
5244 	if (LegacyQuery)
5245 		{
5246 		maxttl = 10;
5247 		for (i=0; i<query->h.numQuestions; i++)						// For each question...
5248 			{
5249 			DNSQuestion q;
5250 			ptr = getQuestion(query, ptr, end, InterfaceID, &q);	// get the question...
5251 			if (!ptr) return(mDNSNULL);
5252 
5253 			for (rr=ResponseRecords; rr; rr=rr->NextResponse)		// and search our list of proposed answers
5254 				{
5255 				if (rr->NR_AnswerTo == ptr)							// If we're going to generate a record answering this question
5256 					{												// then put the question in the question section
5257 					responseptr = putQuestion(response, responseptr, limit, &q.qname, q.qtype, q.qclass);
5258 					if (!responseptr) { debugf("GenerateUnicastResponse: Ran out of space for questions!"); return(mDNSNULL); }
5259 					break;		// break out of the ResponseRecords loop, and go on to the next question
5260 					}
5261 				}
5262 			}
5263 
5264 		if (response->h.numQuestions == 0) { LogMsg("GenerateUnicastResponse: ERROR! Why no questions?"); return(mDNSNULL); }
5265 		}
5266 
5267 	// ***
5268 	// *** 2. Write Answers
5269 	// ***
5270 	for (rr=ResponseRecords; rr; rr=rr->NextResponse)
5271 		if (rr->NR_AnswerTo)
5272 			{
5273 			mDNSu8 *p = PutResourceRecordTTL(response, responseptr, &response->h.numAnswers, &rr->resrec,
5274 				maxttl < rr->resrec.rroriginalttl ? maxttl : rr->resrec.rroriginalttl);
5275 			if (p) responseptr = p;
5276 			else { debugf("GenerateUnicastResponse: Ran out of space for answers!"); response->h.flags.b[0] |= kDNSFlag0_TC; }
5277 			}
5278 
5279 	// ***
5280 	// *** 3. Write Additionals
5281 	// ***
5282 	for (rr=ResponseRecords; rr; rr=rr->NextResponse)
5283 		if (rr->NR_AdditionalTo && !rr->NR_AnswerTo)
5284 			{
5285 			mDNSu8 *p = PutResourceRecordTTL(response, responseptr, &response->h.numAdditionals, &rr->resrec,
5286 				maxttl < rr->resrec.rroriginalttl ? maxttl : rr->resrec.rroriginalttl);
5287 			if (p) responseptr = p;
5288 			else debugf("GenerateUnicastResponse: No more space for additionals");
5289 			}
5290 
5291 	return(responseptr);
5292 	}
5293 
5294 // AuthRecord *our is our Resource Record
5295 // CacheRecord *pkt is the Resource Record from the response packet we've witnessed on the network
5296 // Returns 0 if there is no conflict
5297 // Returns +1 if there was a conflict and we won
5298 // Returns -1 if there was a conflict and we lost and have to rename
5299 mDNSlocal int CompareRData(const AuthRecord *const our, const CacheRecord *const pkt)
5300 	{
5301 	mDNSu8 ourdata[256], *ourptr = ourdata, *ourend;
5302 	mDNSu8 pktdata[256], *pktptr = pktdata, *pktend;
5303 	if (!our) { LogMsg("CompareRData ERROR: our is NULL"); return(+1); }
5304 	if (!pkt) { LogMsg("CompareRData ERROR: pkt is NULL"); return(+1); }
5305 
5306 	ourend = putRData(mDNSNULL, ourdata, ourdata + sizeof(ourdata), &our->resrec);
5307 	pktend = putRData(mDNSNULL, pktdata, pktdata + sizeof(pktdata), &pkt->resrec);
5308 	while (ourptr < ourend && pktptr < pktend && *ourptr == *pktptr) { ourptr++; pktptr++; }
5309 	if (ourptr >= ourend && pktptr >= pktend) return(0);			// If data identical, not a conflict
5310 
5311 	if (ourptr >= ourend) return(-1);								// Our data ran out first; We lost
5312 	if (pktptr >= pktend) return(+1);								// Packet data ran out first; We won
5313 	if (*pktptr > *ourptr) return(-1);								// Our data is numerically lower; We lost
5314 	if (*pktptr < *ourptr) return(+1);								// Packet data is numerically lower; We won
5315 
5316 	LogMsg("CompareRData ERROR: Invalid state");
5317 	return(-1);
5318 	}
5319 
5320 // See if we have an authoritative record that's identical to this packet record,
5321 // whose canonical DependentOn record is the specified master record.
5322 // The DependentOn pointer is typically used for the TXT record of service registrations
5323 // It indicates that there is no inherent conflict detection for the TXT record
5324 // -- it depends on the SRV record to resolve name conflicts
5325 // If we find any identical ResourceRecords in our authoritative list, then follow their DependentOn
5326 // pointer chain (if any) to make sure we reach the canonical DependentOn record
5327 // If the record has no DependentOn, then just return that record's pointer
5328 // Returns NULL if we don't have any local RRs that are identical to the one from the packet
5329 mDNSlocal mDNSBool MatchDependentOn(const mDNS *const m, const CacheRecord *const pktrr, const AuthRecord *const master)
5330 	{
5331 	const AuthRecord *r1;
5332 	for (r1 = m->ResourceRecords; r1; r1=r1->next)
5333 		{
5334 		if (IdenticalResourceRecord(&r1->resrec, &pktrr->resrec))
5335 			{
5336 			const AuthRecord *r2 = r1;
5337 			while (r2->DependentOn) r2 = r2->DependentOn;
5338 			if (r2 == master) return(mDNStrue);
5339 			}
5340 		}
5341 	for (r1 = m->DuplicateRecords; r1; r1=r1->next)
5342 		{
5343 		if (IdenticalResourceRecord(&r1->resrec, &pktrr->resrec))
5344 			{
5345 			const AuthRecord *r2 = r1;
5346 			while (r2->DependentOn) r2 = r2->DependentOn;
5347 			if (r2 == master) return(mDNStrue);
5348 			}
5349 		}
5350 	return(mDNSfalse);
5351 	}
5352 
5353 // Find the canonical RRSet pointer for this RR received in a packet.
5354 // If we find any identical AuthRecord in our authoritative list, then follow its RRSet
5355 // pointers (if any) to make sure we return the canonical member of this name/type/class
5356 // Returns NULL if we don't have any local RRs that are identical to the one from the packet
5357 mDNSlocal const AuthRecord *FindRRSet(const mDNS *const m, const CacheRecord *const pktrr)
5358 	{
5359 	const AuthRecord *rr;
5360 	for (rr = m->ResourceRecords; rr; rr=rr->next)
5361 		{
5362 		if (IdenticalResourceRecord(&rr->resrec, &pktrr->resrec))
5363 			{
5364 			while (rr->RRSet && rr != rr->RRSet) rr = rr->RRSet;
5365 			return(rr);
5366 			}
5367 		}
5368 	return(mDNSNULL);
5369 	}
5370 
5371 // PacketRRConflict is called when we've received an RR (pktrr) which has the same name
5372 // as one of our records (our) but different rdata.
5373 // 1. If our record is not a type that's supposed to be unique, we don't care.
5374 // 2a. If our record is marked as dependent on some other record for conflict detection, ignore this one.
5375 // 2b. If the packet rr exactly matches one of our other RRs, and *that* record's DependentOn pointer
5376 //     points to our record, ignore this conflict (e.g. the packet record matches one of our
5377 //     TXT records, and that record is marked as dependent on 'our', its SRV record).
5378 // 3. If we have some *other* RR that exactly matches the one from the packet, and that record and our record
5379 //    are members of the same RRSet, then this is not a conflict.
5380 mDNSlocal mDNSBool PacketRRConflict(const mDNS *const m, const AuthRecord *const our, const CacheRecord *const pktrr)
5381 	{
5382 	// If not supposed to be unique, not a conflict
5383 	if (!(our->resrec.RecordType & kDNSRecordTypeUniqueMask)) return(mDNSfalse);
5384 
5385 	// If a dependent record, not a conflict
5386 	if (our->DependentOn || MatchDependentOn(m, pktrr, our)) return(mDNSfalse);
5387 	else
5388 		{
5389 		// If the pktrr matches a member of ourset, not a conflict
5390 		const AuthRecord *ourset = our->RRSet ? our->RRSet : our;
5391 		const AuthRecord *pktset = FindRRSet(m, pktrr);
5392 		if (pktset == ourset) return(mDNSfalse);
5393 
5394 		// For records we're proxying, where we don't know the full
5395 		// relationship between the records, having any matching record
5396 		// in our AuthRecords list is sufficient evidence of non-conflict
5397 		if (our->WakeUp.HMAC.l[0] && pktset) return(mDNSfalse);
5398 		}
5399 
5400 	// Okay, this is a conflict
5401 	return(mDNStrue);
5402 	}
5403 
5404 // Note: ResolveSimultaneousProbe calls mDNS_Deregister_internal which can call a user callback, which may change
5405 // the record list and/or question list.
5406 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
5407 mDNSlocal void ResolveSimultaneousProbe(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end,
5408 	DNSQuestion *q, AuthRecord *our)
5409 	{
5410 	int i;
5411 	const mDNSu8 *ptr = LocateAuthorities(query, end);
5412 	mDNSBool FoundUpdate = mDNSfalse;
5413 
5414 	for (i = 0; i < query->h.numAuthorities; i++)
5415 		{
5416 		ptr = GetLargeResourceRecord(m, query, ptr, end, q->InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
5417 		if (!ptr) break;
5418 		if (ResourceRecordAnswersQuestion(&m->rec.r.resrec, q))
5419 			{
5420 			FoundUpdate = mDNStrue;
5421 			if (PacketRRConflict(m, our, &m->rec.r))
5422 				{
5423 				int result          = (int)our->resrec.rrclass - (int)m->rec.r.resrec.rrclass;
5424 				if (!result) result = (int)our->resrec.rrtype  - (int)m->rec.r.resrec.rrtype;
5425 				if (!result) result = CompareRData(our, &m->rec.r);
5426 				if (result)
5427 					{
5428 					const char *const msg = (result < 0) ? "lost:" : (result > 0) ? "won: " : "tie: ";
5429 					LogMsg("ResolveSimultaneousProbe: Pkt Record:        %08lX %s", m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
5430 					LogMsg("ResolveSimultaneousProbe: Our Record %d %s %08lX %s",   our->ProbeCount, msg, our->resrec.rdatahash, ARDisplayString(m, our));
5431 					}
5432 				// If we lost the tie-break for simultaneous probes, we don't immediately give up, because we might be seeing stale packets on the network.
5433 				// Instead we pause for one second, to give the other host (if real) a change to establish its name, and then try probing again.
5434 				// If there really is another live host out there with the same name, it will answer our probes and we'll then rename.
5435 				if (result < 0)
5436 					{
5437 					m->SuppressProbes   = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
5438 					our->ProbeCount     = DefaultProbeCountForTypeUnique;
5439 					our->AnnounceCount  = InitialAnnounceCount;
5440 					InitializeLastAPTime(m, our);
5441 					goto exit;
5442 					}
5443 				}
5444 #if 0
5445 			else
5446 				{
5447 				LogMsg("ResolveSimultaneousProbe: Pkt Record:      %08lX %s", m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
5448 				LogMsg("ResolveSimultaneousProbe: Our Record ign:  %08lX %s", our->resrec.rdatahash,     ARDisplayString(m, our));
5449 				}
5450 #endif
5451 			}
5452 		m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
5453 		}
5454 	if (!FoundUpdate)
5455 		LogInfo("ResolveSimultaneousProbe: %##s (%s): No Update Record found", our->resrec.name->c, DNSTypeName(our->resrec.rrtype));
5456 exit:
5457 	m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
5458 	}
5459 
5460 mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, const ResourceRecord *const pktrr)
5461 	{
5462 	mDNSu32 slot = HashSlot(pktrr->name);
5463 	CacheGroup *cg = CacheGroupForRecord(m, slot, pktrr);
5464 	CacheRecord *rr;
5465 	for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
5466 		if (pktrr->InterfaceID == rr->resrec.InterfaceID && IdenticalSameNameRecord(pktrr, &rr->resrec)) break;
5467 	return(rr);
5468 	}
5469 
5470 // Called from ProcessQuery when we get an mDNS packet with an owner record in it
5471 mDNSlocal void ClearProxyRecords(mDNS *const m, const OwnerOptData *const owner, AuthRecord *const thelist)
5472 	{
5473 	m->CurrentRecord = thelist;
5474 	while (m->CurrentRecord)
5475 		{
5476 		AuthRecord *const rr = m->CurrentRecord;
5477 		if (m->rec.r.resrec.InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&owner->HMAC, &rr->WakeUp.HMAC))
5478 			if (owner->seq != rr->WakeUp.seq || m->timenow - rr->TimeRcvd > mDNSPlatformOneSecond * 60)
5479 				{
5480 				LogSPS("ClearProxyRecords: Removing %3d H-MAC %.6a I-MAC %.6a %d %d %s",
5481 					m->ProxyRecords, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, owner->seq, ARDisplayString(m, rr));
5482 				mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
5483 				SetSPSProxyListChanged(m->rec.r.resrec.InterfaceID);
5484 				}
5485 		// Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal,
5486 		// because the list may have been changed in that call.
5487 		if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
5488 			m->CurrentRecord = rr->next;
5489 		}
5490 	}
5491 
5492 // ProcessQuery examines a received query to see if we have any answers to give
5493 mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end,
5494 	const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, mDNSBool QueryWasMulticast,
5495 	mDNSBool QueryWasLocalUnicast, DNSMessage *const response)
5496 	{
5497 	mDNSBool      FromLocalSubnet    = srcaddr && AddressIsLocalSubnet(m, InterfaceID, srcaddr);
5498 	AuthRecord   *ResponseRecords    = mDNSNULL;
5499 	AuthRecord  **nrp                = &ResponseRecords;
5500 	CacheRecord  *ExpectedAnswers    = mDNSNULL;			// Records in our cache we expect to see updated
5501 	CacheRecord **eap                = &ExpectedAnswers;
5502 	DNSQuestion  *DupQuestions       = mDNSNULL;			// Our questions that are identical to questions in this packet
5503 	DNSQuestion **dqp                = &DupQuestions;
5504 	mDNSs32       delayresponse      = 0;
5505 	mDNSBool      SendLegacyResponse = mDNSfalse;
5506 	const mDNSu8 *ptr;
5507 	mDNSu8       *responseptr        = mDNSNULL;
5508 	AuthRecord   *rr;
5509 	int i;
5510 
5511 	// ***
5512 	// *** 1. Look in Additional Section for an OPT record
5513 	// ***
5514 	ptr = LocateOptRR(query, end, DNSOpt_OwnerData_ID_Space);
5515 	if (ptr)
5516 		{
5517 		ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAdd, &m->rec);
5518 		if (m->rec.r.resrec.rrtype == kDNSType_OPT)
5519 			{
5520 			const rdataOPT *opt;
5521 			const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
5522 			// Find owner sub-option(s). We verify that the MAC is non-zero, otherwise we could inadvertently
5523 			// delete all our own AuthRecords (which are identified by having zero MAC tags on them).
5524 			for (opt = &m->rec.r.resrec.rdata->u.opt[0]; opt < e; opt++)
5525 				if (opt->opt == kDNSOpt_Owner && opt->u.owner.vers == 0 && opt->u.owner.HMAC.l[0])
5526 					{
5527 					ClearProxyRecords(m, &opt->u.owner, m->DuplicateRecords);
5528 					ClearProxyRecords(m, &opt->u.owner, m->ResourceRecords);
5529 					}
5530 			}
5531 		m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
5532 		}
5533 
5534 	// ***
5535 	// *** 2. Parse Question Section and mark potential answers
5536 	// ***
5537 	ptr = query->data;
5538 	for (i=0; i<query->h.numQuestions; i++)						// For each question...
5539 		{
5540 		mDNSBool QuestionNeedsMulticastResponse;
5541 		int NumAnswersForThisQuestion = 0;
5542 		AuthRecord *NSECAnswer = mDNSNULL;
5543 		DNSQuestion pktq, *q;
5544 		ptr = getQuestion(query, ptr, end, InterfaceID, &pktq);	// get the question...
5545 		if (!ptr) goto exit;
5546 
5547 		// The only queries that *need* a multicast response are:
5548 		// * Queries sent via multicast
5549 		// * from port 5353
5550 		// * that don't have the kDNSQClass_UnicastResponse bit set
5551 		// These queries need multicast responses because other clients will:
5552 		// * suppress their own identical questions when they see these questions, and
5553 		// * expire their cache records if they don't see the expected responses
5554 		// For other queries, we may still choose to send the occasional multicast response anyway,
5555 		// to keep our neighbours caches warm, and for ongoing conflict detection.
5556 		QuestionNeedsMulticastResponse = QueryWasMulticast && !LegacyQuery && !(pktq.qclass & kDNSQClass_UnicastResponse);
5557 		// Clear the UnicastResponse flag -- don't want to confuse the rest of the code that follows later
5558 		pktq.qclass &= ~kDNSQClass_UnicastResponse;
5559 
5560 		// Note: We use the m->CurrentRecord mechanism here because calling ResolveSimultaneousProbe
5561 		// can result in user callbacks which may change the record list and/or question list.
5562 		// Also note: we just mark potential answer records here, without trying to build the
5563 		// "ResponseRecords" list, because we don't want to risk user callbacks deleting records
5564 		// from that list while we're in the middle of trying to build it.
5565 		if (m->CurrentRecord)
5566 			LogMsg("ProcessQuery ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
5567 		m->CurrentRecord = m->ResourceRecords;
5568 		while (m->CurrentRecord)
5569 			{
5570 			rr = m->CurrentRecord;
5571 			m->CurrentRecord = rr->next;
5572 			if (AnyTypeRecordAnswersQuestion(&rr->resrec, &pktq) && (QueryWasMulticast || QueryWasLocalUnicast || rr->AllowRemoteQuery))
5573 				{
5574 				if (RRTypeAnswersQuestionType(&rr->resrec, pktq.qtype))
5575 					{
5576 					if (rr->resrec.RecordType == kDNSRecordTypeUnique)
5577 						ResolveSimultaneousProbe(m, query, end, &pktq, rr);
5578 					else if (ResourceRecordIsValidAnswer(rr))
5579 						{
5580 						NumAnswersForThisQuestion++;
5581 						// Note: We should check here if this is a probe-type query, and if so, generate an immediate
5582 						// unicast answer back to the source, because timeliness in answering probes is important.
5583 
5584 						// Notes:
5585 						// NR_AnswerTo pointing into query packet means "answer via immediate legacy unicast" (may *also* choose to multicast)
5586 						// NR_AnswerTo == (mDNSu8*)~1             means "answer via delayed unicast" (to modern querier; may promote to multicast instead)
5587 						// NR_AnswerTo == (mDNSu8*)~0             means "definitely answer via multicast" (can't downgrade to unicast later)
5588 						// If we're not multicasting this record because the kDNSQClass_UnicastResponse bit was set,
5589 						// but the multicast querier is not on a matching subnet (e.g. because of overlaid subnets on one link)
5590 						// then we'll multicast it anyway (if we unicast, the receiver will ignore it because it has an apparently non-local source)
5591 						if (QuestionNeedsMulticastResponse || (!FromLocalSubnet && QueryWasMulticast && !LegacyQuery))
5592 							{
5593 							// We only mark this question for sending if it is at least one second since the last time we multicast it
5594 							// on this interface. If it is more than a second, or LastMCInterface is different, then we may multicast it.
5595 							// This is to guard against the case where someone blasts us with queries as fast as they can.
5596 							if (m->timenow - (rr->LastMCTime + mDNSPlatformOneSecond) >= 0 ||
5597 								(rr->LastMCInterface != mDNSInterfaceMark && rr->LastMCInterface != InterfaceID))
5598 								rr->NR_AnswerTo = (mDNSu8*)~0;
5599 							}
5600 						else if (!rr->NR_AnswerTo) rr->NR_AnswerTo = LegacyQuery ? ptr : (mDNSu8*)~1;
5601 						}
5602 					}
5603 				else if (rr->resrec.RecordType == kDNSRecordTypeVerified)
5604 					{
5605 					// If we don't have any answers for this question, but we do own another record with the same name,
5606 					// then mark it to generate an NSEC record on this interface
5607 					if (!NSECAnswer) NSECAnswer = rr;
5608 					}
5609 				}
5610 			}
5611 
5612 		if (NumAnswersForThisQuestion == 0 && NSECAnswer)
5613 			{
5614 			NumAnswersForThisQuestion++;
5615 			NSECAnswer->SendNSECNow = InterfaceID;
5616 			m->NextScheduledResponse = m->timenow;
5617 			}
5618 
5619 		// If we couldn't answer this question, someone else might be able to,
5620 		// so use random delay on response to reduce collisions
5621 		if (NumAnswersForThisQuestion == 0) delayresponse = mDNSPlatformOneSecond;	// Divided by 50 = 20ms
5622 
5623 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
5624 		if (QuestionNeedsMulticastResponse)
5625 #else
5626 		// We only do the following accelerated cache expiration and duplicate question suppression processing
5627 		// for non-truncated multicast queries with multicast responses.
5628 		// For any query generating a unicast response we don't do this because we can't assume we will see the response.
5629 		// For truncated queries we don't do this because a response we're expecting might be suppressed by a subsequent
5630 		// known-answer packet, and when there's packet loss we can't safely assume we'll receive *all* known-answer packets.
5631 		if (QuestionNeedsMulticastResponse && !(query->h.flags.b[0] & kDNSFlag0_TC))
5632 #endif
5633 			{
5634 			const mDNSu32 slot = HashSlot(&pktq.qname);
5635 			CacheGroup *cg = CacheGroupForName(m, slot, pktq.qnamehash, &pktq.qname);
5636 			CacheRecord *cr;
5637 
5638 			// Make a list indicating which of our own cache records we expect to see updated as a result of this query
5639 			// Note: Records larger than 1K are not habitually multicast, so don't expect those to be updated
5640 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
5641 			if (!(query->h.flags.b[0] & kDNSFlag0_TC))
5642 #endif
5643 				for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
5644 					if (SameNameRecordAnswersQuestion(&cr->resrec, &pktq) && cr->resrec.rdlength <= SmallRecordLimit)
5645 						if (!cr->NextInKAList && eap != &cr->NextInKAList)
5646 							{
5647 							*eap = cr;
5648 							eap = &cr->NextInKAList;
5649 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
5650 							if (cr->MPUnansweredQ == 0 || m->timenow - cr->MPLastUnansweredQT >= mDNSPlatformOneSecond)
5651 								{
5652 								// Although MPUnansweredQ is only really used for multi-packet query processing,
5653 								// we increment it for both single-packet and multi-packet queries, so that it stays in sync
5654 								// with the MPUnansweredKA value, which by necessity is incremented for both query types.
5655 								cr->MPUnansweredQ++;
5656 								cr->MPLastUnansweredQT = m->timenow;
5657 								cr->MPExpectingKA = mDNStrue;
5658 								}
5659 #endif
5660 							}
5661 
5662 			// Check if this question is the same as any of mine.
5663 			// We only do this for non-truncated queries. Right now it would be too complicated to try
5664 			// to keep track of duplicate suppression state between multiple packets, especially when we
5665 			// can't guarantee to receive all of the Known Answer packets that go with a particular query.
5666 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
5667 			if (!(query->h.flags.b[0] & kDNSFlag0_TC))
5668 #endif
5669 				for (q = m->Questions; q; q=q->next)
5670 					if (!q->Target.type && ActiveQuestion(q) && m->timenow - q->LastQTxTime > mDNSPlatformOneSecond / 4)
5671 						if (!q->InterfaceID || q->InterfaceID == InterfaceID)
5672 							if (q->NextInDQList == mDNSNULL && dqp != &q->NextInDQList)
5673 								if (q->qtype == pktq.qtype &&
5674 									q->qclass == pktq.qclass &&
5675 									q->qnamehash == pktq.qnamehash && SameDomainName(&q->qname, &pktq.qname))
5676 									{ *dqp = q; dqp = &q->NextInDQList; }
5677 			}
5678 		}
5679 
5680 	// ***
5681 	// *** 3. Now we can safely build the list of marked answers
5682 	// ***
5683 	for (rr = m->ResourceRecords; rr; rr=rr->next)				// Now build our list of potential answers
5684 		if (rr->NR_AnswerTo)									// If we marked the record...
5685 			AddRecordToResponseList(&nrp, rr, mDNSNULL);		// ... add it to the list
5686 
5687 	// ***
5688 	// *** 4. Add additional records
5689 	// ***
5690 	AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID);
5691 
5692 	// ***
5693 	// *** 5. Parse Answer Section and cancel any records disallowed by Known-Answer list
5694 	// ***
5695 	for (i=0; i<query->h.numAnswers; i++)						// For each record in the query's answer section...
5696 		{
5697 		// Get the record...
5698 		CacheRecord *ourcacherr;
5699 		ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &m->rec);
5700 		if (!ptr) goto exit;
5701 
5702 		// See if this Known-Answer suppresses any of our currently planned answers
5703 		for (rr=ResponseRecords; rr; rr=rr->NextResponse)
5704 			if (MustSendRecord(rr) && ShouldSuppressKnownAnswer(&m->rec.r, rr))
5705 				{ rr->NR_AnswerTo = mDNSNULL; rr->NR_AdditionalTo = mDNSNULL; }
5706 
5707 		// See if this Known-Answer suppresses any previously scheduled answers (for multi-packet KA suppression)
5708 		for (rr=m->ResourceRecords; rr; rr=rr->next)
5709 			{
5710 			// If we're planning to send this answer on this interface, and only on this interface, then allow KA suppression
5711 			if (rr->ImmedAnswer == InterfaceID && ShouldSuppressKnownAnswer(&m->rec.r, rr))
5712 				{
5713 				if (srcaddr->type == mDNSAddrType_IPv4)
5714 					{
5715 					if (mDNSSameIPv4Address(rr->v4Requester, srcaddr->ip.v4)) rr->v4Requester = zerov4Addr;
5716 					}
5717 				else if (srcaddr->type == mDNSAddrType_IPv6)
5718 					{
5719 					if (mDNSSameIPv6Address(rr->v6Requester, srcaddr->ip.v6)) rr->v6Requester = zerov6Addr;
5720 					}
5721 				if (mDNSIPv4AddressIsZero(rr->v4Requester) && mDNSIPv6AddressIsZero(rr->v6Requester))
5722 					{
5723 					rr->ImmedAnswer  = mDNSNULL;
5724 					rr->ImmedUnicast = mDNSfalse;
5725 #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
5726 					LogMsg("Suppressed after%4d: %s", m->timenow - rr->ImmedAnswerMarkTime, ARDisplayString(m, rr));
5727 #endif
5728 					}
5729 				}
5730 			}
5731 
5732 		ourcacherr = FindIdenticalRecordInCache(m, &m->rec.r.resrec);
5733 
5734 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
5735 		// See if this Known-Answer suppresses any answers we were expecting for our cache records. We do this always,
5736 		// even if the TC bit is not set (the TC bit will *not* be set in the *last* packet of a multi-packet KA list).
5737 		if (ourcacherr && ourcacherr->MPExpectingKA && m->timenow - ourcacherr->MPLastUnansweredQT < mDNSPlatformOneSecond)
5738 			{
5739 			ourcacherr->MPUnansweredKA++;
5740 			ourcacherr->MPExpectingKA = mDNSfalse;
5741 			}
5742 #endif
5743 
5744 		// Having built our ExpectedAnswers list from the questions in this packet, we then remove
5745 		// any records that are suppressed by the Known Answer list in this packet.
5746 		eap = &ExpectedAnswers;
5747 		while (*eap)
5748 			{
5749 			CacheRecord *cr = *eap;
5750 			if (cr->resrec.InterfaceID == InterfaceID && IdenticalResourceRecord(&m->rec.r.resrec, &cr->resrec))
5751 				{ *eap = cr->NextInKAList; cr->NextInKAList = mDNSNULL; }
5752 			else eap = &cr->NextInKAList;
5753 			}
5754 
5755 		// See if this Known-Answer is a surprise to us. If so, we shouldn't suppress our own query.
5756 		if (!ourcacherr)
5757 			{
5758 			dqp = &DupQuestions;
5759 			while (*dqp)
5760 				{
5761 				DNSQuestion *q = *dqp;
5762 				if (ResourceRecordAnswersQuestion(&m->rec.r.resrec, q))
5763 					{ *dqp = q->NextInDQList; q->NextInDQList = mDNSNULL; }
5764 				else dqp = &q->NextInDQList;
5765 				}
5766 			}
5767 		m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
5768 		}
5769 
5770 	// ***
5771 	// *** 6. Cancel any additionals that were added because of now-deleted records
5772 	// ***
5773 	for (rr=ResponseRecords; rr; rr=rr->NextResponse)
5774 		if (rr->NR_AdditionalTo && !MustSendRecord(rr->NR_AdditionalTo))
5775 			{ rr->NR_AnswerTo = mDNSNULL; rr->NR_AdditionalTo = mDNSNULL; }
5776 
5777 	// ***
5778 	// *** 7. Mark the send flags on the records we plan to send
5779 	// ***
5780 	for (rr=ResponseRecords; rr; rr=rr->NextResponse)
5781 		{
5782 		if (rr->NR_AnswerTo)
5783 			{
5784 			mDNSBool SendMulticastResponse = mDNSfalse;		// Send modern multicast response
5785 			mDNSBool SendUnicastResponse   = mDNSfalse;		// Send modern unicast response (not legacy unicast response)
5786 
5787 			// If it's been a while since we multicast this, then send a multicast response for conflict detection, etc.
5788 			if (m->timenow - (rr->LastMCTime + TicksTTL(rr)/4) >= 0)
5789 				{
5790 				SendMulticastResponse = mDNStrue;
5791 				// If this record was marked for modern (delayed) unicast response, then mark it as promoted to
5792 				// multicast response instead (don't want to end up ALSO setting SendUnicastResponse in the check below).
5793 				// If this record was marked for legacy unicast response, then we mustn't change the NR_AnswerTo value.
5794 				if (rr->NR_AnswerTo == (mDNSu8*)~1) rr->NR_AnswerTo = (mDNSu8*)~0;
5795 				}
5796 
5797 			// If the client insists on a multicast response, then we'd better send one
5798 			if      (rr->NR_AnswerTo == (mDNSu8*)~0) SendMulticastResponse = mDNStrue;
5799 			else if (rr->NR_AnswerTo == (mDNSu8*)~1) SendUnicastResponse   = mDNStrue;
5800 			else if (rr->NR_AnswerTo)                SendLegacyResponse    = mDNStrue;
5801 
5802 			if (SendMulticastResponse || SendUnicastResponse)
5803 				{
5804 #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
5805 				rr->ImmedAnswerMarkTime = m->timenow;
5806 #endif
5807 				m->NextScheduledResponse = m->timenow;
5808 				// If we're already planning to send this on another interface, just send it on all interfaces
5809 				if (rr->ImmedAnswer && rr->ImmedAnswer != InterfaceID)
5810 					rr->ImmedAnswer = mDNSInterfaceMark;
5811 				else
5812 					{
5813 					rr->ImmedAnswer = InterfaceID;			// Record interface to send it on
5814 					if (SendUnicastResponse) rr->ImmedUnicast = mDNStrue;
5815 					if (srcaddr->type == mDNSAddrType_IPv4)
5816 						{
5817 						if      (mDNSIPv4AddressIsZero(rr->v4Requester))                rr->v4Requester = srcaddr->ip.v4;
5818 						else if (!mDNSSameIPv4Address(rr->v4Requester, srcaddr->ip.v4)) rr->v4Requester = onesIPv4Addr;
5819 						}
5820 					else if (srcaddr->type == mDNSAddrType_IPv6)
5821 						{
5822 						if      (mDNSIPv6AddressIsZero(rr->v6Requester))                rr->v6Requester = srcaddr->ip.v6;
5823 						else if (!mDNSSameIPv6Address(rr->v6Requester, srcaddr->ip.v6)) rr->v6Requester = onesIPv6Addr;
5824 						}
5825 					}
5826 				}
5827 			// If TC flag is set, it means we should expect that additional known answers may be coming in another packet,
5828 			// so we allow roughly half a second before deciding to reply (we've observed inter-packet delays of 100-200ms on 802.11)
5829 			// else, if record is a shared one, spread responses over 100ms to avoid implosion of simultaneous responses
5830 			// else, for a simple unique record reply, we can reply immediately; no need for delay
5831 			if      (query->h.flags.b[0] & kDNSFlag0_TC)            delayresponse = mDNSPlatformOneSecond * 20;	// Divided by 50 = 400ms
5832 			else if (rr->resrec.RecordType == kDNSRecordTypeShared) delayresponse = mDNSPlatformOneSecond;		// Divided by 50 = 20ms
5833 			}
5834 		else if (rr->NR_AdditionalTo && rr->NR_AdditionalTo->NR_AnswerTo == (mDNSu8*)~0)
5835 			{
5836 			// Since additional records are an optimization anyway, we only ever send them on one interface at a time
5837 			// If two clients on different interfaces do queries that invoke the same optional additional answer,
5838 			// then the earlier client is out of luck
5839 			rr->ImmedAdditional = InterfaceID;
5840 			// No need to set m->NextScheduledResponse here
5841 			// We'll send these additional records when we send them, or not, as the case may be
5842 			}
5843 		}
5844 
5845 	// ***
5846 	// *** 8. If we think other machines are likely to answer these questions, set our packet suppression timer
5847 	// ***
5848 	if (delayresponse && (!m->SuppressSending || (m->SuppressSending - m->timenow) < (delayresponse + 49) / 50))
5849 		{
5850 #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
5851 		mDNSs32 oldss = m->SuppressSending;
5852 		if (oldss && delayresponse)
5853 			LogMsg("Current SuppressSending delay%5ld; require%5ld", m->SuppressSending - m->timenow, (delayresponse + 49) / 50);
5854 #endif
5855 		// Pick a random delay:
5856 		// We start with the base delay chosen above (typically either 1 second or 20 seconds),
5857 		// and add a random value in the range 0-5 seconds (making 1-6 seconds or 20-25 seconds).
5858 		// This is an integer value, with resolution determined by the platform clock rate.
5859 		// We then divide that by 50 to get the delay value in ticks. We defer the division until last
5860 		// to get better results on platforms with coarse clock granularity (e.g. ten ticks per second).
5861 		// The +49 before dividing is to ensure we round up, not down, to ensure that even
5862 		// on platforms where the native clock rate is less than fifty ticks per second,
5863 		// we still guarantee that the final calculated delay is at least one platform tick.
5864 		// We want to make sure we don't ever allow the delay to be zero ticks,
5865 		// because if that happens we'll fail the Bonjour Conformance Test.
5866 		// Our final computed delay is 20-120ms for normal delayed replies,
5867 		// or 400-500ms in the case of multi-packet known-answer lists.
5868 		m->SuppressSending = m->timenow + (delayresponse + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*5) + 49) / 50;
5869 		if (m->SuppressSending == 0) m->SuppressSending = 1;
5870 #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
5871 		if (oldss && delayresponse)
5872 			LogMsg("Set     SuppressSending to   %5ld", m->SuppressSending - m->timenow);
5873 #endif
5874 		}
5875 
5876 	// ***
5877 	// *** 9. If query is from a legacy client, or from a new client requesting a unicast reply, then generate a unicast response too
5878 	// ***
5879 	if (SendLegacyResponse)
5880 		responseptr = GenerateUnicastResponse(query, end, InterfaceID, LegacyQuery, response, ResponseRecords);
5881 
5882 exit:
5883 	m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
5884 
5885 	// ***
5886 	// *** 10. Finally, clear our link chains ready for use next time
5887 	// ***
5888 	while (ResponseRecords)
5889 		{
5890 		rr = ResponseRecords;
5891 		ResponseRecords = rr->NextResponse;
5892 		rr->NextResponse    = mDNSNULL;
5893 		rr->NR_AnswerTo     = mDNSNULL;
5894 		rr->NR_AdditionalTo = mDNSNULL;
5895 		}
5896 
5897 	while (ExpectedAnswers)
5898 		{
5899 		CacheRecord *cr = ExpectedAnswers;
5900 		ExpectedAnswers = cr->NextInKAList;
5901 		cr->NextInKAList = mDNSNULL;
5902 
5903 		// For non-truncated queries, we can definitively say that we should expect
5904 		// to be seeing a response for any records still left in the ExpectedAnswers list
5905 		if (!(query->h.flags.b[0] & kDNSFlag0_TC))
5906 			if (cr->UnansweredQueries == 0 || m->timenow - cr->LastUnansweredTime >= mDNSPlatformOneSecond)
5907 				{
5908 				cr->UnansweredQueries++;
5909 				cr->LastUnansweredTime = m->timenow;
5910 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
5911 				if (cr->UnansweredQueries > 1)
5912 					debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s",
5913 						cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
5914 #endif
5915 				SetNextCacheCheckTime(m, cr);
5916 				}
5917 
5918 		// If we've seen multiple unanswered queries for this record,
5919 		// then mark it to expire in five seconds if we don't get a response by then.
5920 		if (cr->UnansweredQueries >= MaxUnansweredQueries)
5921 			{
5922 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
5923 			// Only show debugging message if this record was not about to expire anyway
5924 			if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond)
5925 				debugf("ProcessQuery: (Max) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
5926 					cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
5927 #endif
5928 			mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
5929 			}
5930 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
5931 		// Make a guess, based on the multi-packet query / known answer counts, whether we think we
5932 		// should have seen an answer for this. (We multiply MPQ by 4 and MPKA by 5, to allow for
5933 		// possible packet loss of up to 20% of the additional KA packets.)
5934 		else if (cr->MPUnansweredQ * 4 > cr->MPUnansweredKA * 5 + 8)
5935 			{
5936 			// We want to do this conservatively.
5937 			// If there are so many machines on the network that they have to use multi-packet known-answer lists,
5938 			// then we don't want them to all hit the network simultaneously with their final expiration queries.
5939 			// By setting the record to expire in four minutes, we achieve two things:
5940 			// (a) the 90-95% final expiration queries will be less bunched together
5941 			// (b) we allow some time for us to witness enough other failed queries that we don't have to do our own
5942 			mDNSu32 remain = (mDNSu32)(RRExpireTime(cr) - m->timenow) / 4;
5943 			if (remain > 240 * (mDNSu32)mDNSPlatformOneSecond)
5944 				remain = 240 * (mDNSu32)mDNSPlatformOneSecond;
5945 
5946 			// Only show debugging message if this record was not about to expire anyway
5947 			if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond)
5948 				debugf("ProcessQuery: (MPQ) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
5949 					cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
5950 
5951 			if (remain <= 60 * (mDNSu32)mDNSPlatformOneSecond)
5952 				cr->UnansweredQueries++;	// Treat this as equivalent to one definite unanswered query
5953 			cr->MPUnansweredQ  = 0;			// Clear MPQ/MPKA statistics
5954 			cr->MPUnansweredKA = 0;
5955 			cr->MPExpectingKA  = mDNSfalse;
5956 
5957 			if (remain < kDefaultReconfirmTimeForNoAnswer)
5958 				remain = kDefaultReconfirmTimeForNoAnswer;
5959 			mDNS_Reconfirm_internal(m, cr, remain);
5960 			}
5961 #endif
5962 		}
5963 
5964 	while (DupQuestions)
5965 		{
5966 		DNSQuestion *q = DupQuestions;
5967 		DupQuestions = q->NextInDQList;
5968 		q->NextInDQList = mDNSNULL;
5969 		i = RecordDupSuppressInfo(q->DupSuppress, m->timenow, InterfaceID, srcaddr->type);
5970 		debugf("ProcessQuery: Recorded DSI for %##s (%s) on %p/%s %d", q->qname.c, DNSTypeName(q->qtype), InterfaceID,
5971 			srcaddr->type == mDNSAddrType_IPv4 ? "v4" : "v6", i);
5972 		}
5973 
5974 	return(responseptr);
5975 	}
5976 
5977 mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
5978 	const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
5979 	const mDNSInterfaceID InterfaceID)
5980 	{
5981 	mDNSu8    *responseend = mDNSNULL;
5982 	mDNSBool   QueryWasLocalUnicast = srcaddr && dstaddr &&
5983 		!mDNSAddrIsDNSMulticast(dstaddr) && AddressIsLocalSubnet(m, InterfaceID, srcaddr);
5984 
5985 	if (!InterfaceID && dstaddr && mDNSAddrIsDNSMulticast(dstaddr))
5986 		{
5987 		LogMsg("Ignoring Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with "
5988 			"%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s (Multicast, but no InterfaceID)",
5989 			srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID,
5990 			msg->h.numQuestions,   msg->h.numQuestions   == 1 ? ", " : "s,",
5991 			msg->h.numAnswers,     msg->h.numAnswers     == 1 ? ", " : "s,",
5992 			msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y,  " : "ies,",
5993 			msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s");
5994 		return;
5995 		}
5996 
5997 	verbosedebugf("Received Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with "
5998 		"%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s",
5999 		srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID,
6000 		msg->h.numQuestions,   msg->h.numQuestions   == 1 ? ", " : "s,",
6001 		msg->h.numAnswers,     msg->h.numAnswers     == 1 ? ", " : "s,",
6002 		msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y,  " : "ies,",
6003 		msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s");
6004 
6005 	responseend = ProcessQuery(m, msg, end, srcaddr, InterfaceID,
6006 		!mDNSSameIPPort(srcport, MulticastDNSPort), mDNSAddrIsDNSMulticast(dstaddr), QueryWasLocalUnicast, &m->omsg);
6007 
6008 	if (responseend)	// If responseend is non-null, that means we built a unicast response packet
6009 		{
6010 		debugf("Unicast Response: %d Question%s, %d Answer%s, %d Additional%s to %#-15a:%d on %p/%ld",
6011 			m->omsg.h.numQuestions,   m->omsg.h.numQuestions   == 1 ? "" : "s",
6012 			m->omsg.h.numAnswers,     m->omsg.h.numAnswers     == 1 ? "" : "s",
6013 			m->omsg.h.numAdditionals, m->omsg.h.numAdditionals == 1 ? "" : "s",
6014 			srcaddr, mDNSVal16(srcport), InterfaceID, srcaddr->type);
6015 		mDNSSendDNSMessage(m, &m->omsg, responseend, InterfaceID, mDNSNULL, srcaddr, srcport, mDNSNULL, mDNSNULL);
6016 		}
6017 	}
6018 
6019 #if 0
6020 mDNSlocal mDNSBool TrustedSource(const mDNS *const m, const mDNSAddr *const srcaddr)
6021 	{
6022 	DNSServer *s;
6023 	(void)m; // Unused
6024 	(void)srcaddr; // Unused
6025 	for (s = m->DNSServers; s; s = s->next)
6026 		if (mDNSSameAddress(srcaddr, &s->addr)) return(mDNStrue);
6027 	return(mDNSfalse);
6028 	}
6029 #endif
6030 
6031 struct UDPSocket_struct
6032 	{
6033 	mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
6034 	};
6035 
6036 mDNSlocal DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *const m, const mDNSIPPort port, const mDNSOpaque16 id, const DNSQuestion *const question)
6037 	{
6038 	DNSQuestion *q;
6039 	for (q = m->Questions; q; q=q->next)
6040 		if (q->LocalSocket &&
6041 			mDNSSameIPPort  (q->LocalSocket->port, port)     &&
6042 			mDNSSameOpaque16(q->TargetQID,         id)       &&
6043 			q->qtype                  == question->qtype     &&
6044 			q->qclass                 == question->qclass    &&
6045 			q->qnamehash              == question->qnamehash &&
6046 			SameDomainName(&q->qname, &question->qname))
6047 			return(q);
6048 	return(mDNSNULL);
6049 	}
6050 
6051 mDNSlocal mDNSBool ExpectingUnicastResponseForRecord(mDNS *const m, const mDNSAddr *const srcaddr, const mDNSBool SrcLocal, const mDNSIPPort port, const mDNSOpaque16 id, const CacheRecord *const rr)
6052 	{
6053 	DNSQuestion *q;
6054 	(void)id;
6055 	(void)srcaddr;
6056 	for (q = m->Questions; q; q=q->next)
6057 		if (!q->DuplicateOf && ResourceRecordAnswersQuestion(&rr->resrec, q))
6058 			{
6059 			if (!mDNSOpaque16IsZero(q->TargetQID))
6060 				{
6061 				debugf("ExpectingUnicastResponseForRecord msg->h.id %d q->TargetQID %d for %s", mDNSVal16(id), mDNSVal16(q->TargetQID), CRDisplayString(m, rr));
6062 				if (mDNSSameOpaque16(q->TargetQID, id))
6063 					{
6064 					if (q->LocalSocket && mDNSSameIPPort(q->LocalSocket->port, port)) return(mDNStrue);
6065 				//	if (mDNSSameAddress(srcaddr, &q->Target))                   return(mDNStrue);
6066 				//	if (q->LongLived && mDNSSameAddress(srcaddr, &q->servAddr)) return(mDNStrue); Shouldn't need this now that we have LLQType checking
6067 				//	if (TrustedSource(m, srcaddr))                              return(mDNStrue);
6068 					LogInfo("WARNING: Ignoring suspect uDNS response for %##s (%s) [q->Target %#a:%d] from %#a:%d %s",
6069 						q->qname.c, DNSTypeName(q->qtype), &q->Target, mDNSVal16(q->LocalSocket ? q->LocalSocket->port : zeroIPPort), srcaddr, mDNSVal16(port), CRDisplayString(m, rr));
6070 					return(mDNSfalse);
6071 					}
6072 				}
6073 			else
6074 				{
6075 				if (SrcLocal && q->ExpectUnicastResp && (mDNSu32)(m->timenow - q->ExpectUnicastResp) < (mDNSu32)(mDNSPlatformOneSecond*2))
6076 					return(mDNStrue);
6077 				}
6078 			}
6079 	return(mDNSfalse);
6080 	}
6081 
6082 // Certain data types need more space for in-memory storage than their in-packet rdlength would imply
6083 // Currently this applies only to rdata types containing more than one domainname,
6084 // or types where the domainname is not the last item in the structure.
6085 // In addition, NSEC currently requires less space for in-memory storage than its in-packet representation.
6086 mDNSlocal mDNSu16 GetRDLengthMem(const ResourceRecord *const rr)
6087 	{
6088 	switch (rr->rrtype)
6089 		{
6090 		case kDNSType_SOA: return sizeof(rdataSOA);
6091 		case kDNSType_RP:  return sizeof(rdataRP);
6092 		case kDNSType_PX:  return sizeof(rdataPX);
6093 		case kDNSType_NSEC:return sizeof(rdataNSEC);
6094 		default:           return rr->rdlength;
6095 		}
6096 	}
6097 
6098 mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg)
6099 	{
6100 	CacheRecord *rr = mDNSNULL;
6101 	mDNSu16 RDLength = GetRDLengthMem(&m->rec.r.resrec);
6102 
6103 	if (!m->rec.r.resrec.InterfaceID) debugf("CreateNewCacheEntry %s", CRDisplayString(m, &m->rec.r));
6104 
6105 	//if (RDLength > InlineCacheRDSize)
6106 	//	LogInfo("Rdata len %4d > InlineCacheRDSize %d %s", RDLength, InlineCacheRDSize, CRDisplayString(m, &m->rec.r));
6107 
6108 	if (!cg) cg = GetCacheGroup(m, slot, &m->rec.r.resrec);	// If we don't have a CacheGroup for this name, make one now
6109 	if (cg)  rr = GetCacheRecord(m, cg, RDLength);	// Make a cache record, being careful not to recycle cg
6110 	if (!rr) NoCacheAnswer(m, &m->rec.r);
6111 	else
6112 		{
6113 		RData *saveptr = rr->resrec.rdata;		// Save the rr->resrec.rdata pointer
6114 		*rr = m->rec.r;							// Block copy the CacheRecord object
6115 		rr->resrec.rdata = saveptr;				// Restore rr->resrec.rdata after the structure assignment
6116 		rr->resrec.name  = cg->name;			// And set rr->resrec.name to point into our CacheGroup header
6117 
6118 		// If this is an oversized record with external storage allocated, copy rdata to external storage
6119 		if      (rr->resrec.rdata == (RData*)&rr->smallrdatastorage && RDLength > InlineCacheRDSize)
6120 			LogMsg("rr->resrec.rdata == &rr->rdatastorage but length > InlineCacheRDSize %##s", m->rec.r.resrec.name->c);
6121 		else if (rr->resrec.rdata != (RData*)&rr->smallrdatastorage && RDLength <= InlineCacheRDSize)
6122 			LogMsg("rr->resrec.rdata != &rr->rdatastorage but length <= InlineCacheRDSize %##s", m->rec.r.resrec.name->c);
6123 		if (RDLength > InlineCacheRDSize)
6124 			mDNSPlatformMemCopy(rr->resrec.rdata, m->rec.r.resrec.rdata, sizeofRDataHeader + RDLength);
6125 
6126 		rr->next = mDNSNULL;					// Clear 'next' pointer
6127 		*(cg->rrcache_tail) = rr;				// Append this record to tail of cache slot list
6128 		cg->rrcache_tail = &(rr->next);			// Advance tail pointer
6129 		if (rr->resrec.RecordType == kDNSRecordTypePacketNegative)
6130 			rr->DelayDelivery = NonZeroTime(m->timenow);
6131 		else if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask &&			// If marked unique,
6132 			rr->resrec.rdata->MaxRDLength != 0)										// and non-negative, assume we may have
6133 			rr->DelayDelivery = NonZeroTime(m->timenow + mDNSPlatformOneSecond);	// to delay delivery of this 'add' event
6134 		else
6135 			rr->DelayDelivery = CheckForSoonToExpireRecords(m, rr->resrec.name, rr->resrec.namehash, slot);
6136 
6137 		CacheRecordAdd(m, rr);	// CacheRecordAdd calls SetNextCacheCheckTime(m, rr); for us
6138 		}
6139 	return(rr);
6140 	}
6141 
6142 mDNSlocal void RefreshCacheRecord(mDNS *const m, CacheRecord *rr, mDNSu32 ttl)
6143 	{
6144 	rr->TimeRcvd             = m->timenow;
6145 	rr->resrec.rroriginalttl = ttl;
6146 	rr->UnansweredQueries = 0;
6147 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
6148 	rr->MPUnansweredQ     = 0;
6149 	rr->MPUnansweredKA    = 0;
6150 	rr->MPExpectingKA     = mDNSfalse;
6151 #endif
6152 	SetNextCacheCheckTime(m, rr);
6153 	}
6154 
6155 mDNSexport void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease)
6156 	{
6157 	CacheRecord *rr;
6158 	const mDNSu32 slot = HashSlot(&q->qname);
6159 	CacheGroup *cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
6160 	for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
6161 		if (rr->CRActiveQuestion == q)
6162 			{
6163 			//LogInfo("GrantCacheExtensions: new lease %d / %s", lease, CRDisplayString(m, rr));
6164 			RefreshCacheRecord(m, rr, lease);
6165 			}
6166 	}
6167 
6168 mDNSlocal mDNSu32 GetEffectiveTTL(const uDNS_LLQType LLQType, mDNSu32 ttl)		// TTL in seconds
6169 	{
6170 	if      (LLQType == uDNS_LLQ_Entire) ttl = kLLQ_DefLease;
6171 	else if (LLQType == uDNS_LLQ_Events)
6172 		{
6173 		// If the TTL is -1 for uDNS LLQ event packet, that means "remove"
6174 		if (ttl == 0xFFFFFFFF) ttl = 0;
6175 		else                   ttl = kLLQ_DefLease;
6176 		}
6177 	else	// else not LLQ (standard uDNS response)
6178 		{
6179 		// The TTL is already capped to a maximum value in GetLargeResourceRecord, but just to be extra safe we
6180 		// also do this check here to make sure we can't get integer overflow below
6181 		if (ttl > 0x8000000UL) ttl = 0x8000000UL;
6182 
6183 		// Adjustment factor to avoid race condition:
6184 		// Suppose real record as TTL of 3600, and our local caching server has held it for 3500 seconds, so it returns an aged TTL of 100.
6185 		// If we do our normal refresh at 80% of the TTL, our local caching server will return 20 seconds, so we'll do another
6186 		// 80% refresh after 16 seconds, and then the server will return 4 seconds, and so on, in the fashion of Zeno's paradox.
6187 		// To avoid this, we extend the record's effective TTL to give it a little extra grace period.
6188 		// We adjust the 100 second TTL to 126. This means that when we do our 80% query at 101 seconds,
6189 		// the cached copy at our local caching server will already have expired, so the server will be forced
6190 		// to fetch a fresh copy from the authoritative server, and then return a fresh record with the full TTL of 3600 seconds.
6191 		ttl += ttl/4 + 2;
6192 
6193 		// For mDNS, TTL zero means "delete this record"
6194 		// For uDNS, TTL zero means: this data is true at this moment, but don't cache it.
6195 		// For the sake of network efficiency, we impose a minimum effective TTL of 15 seconds.
6196 		// If we allow a TTL of less than 2 seconds things really break (e.g. we end up making a negative cache entry).
6197 		// In the future we may want to revisit this and consider properly supporting non-cached (TTL=0) uDNS answers.
6198 		if (ttl < 15) ttl = 15;
6199 		}
6200 
6201 	return ttl;
6202 	}
6203 
6204 // Note: mDNSCoreReceiveResponse calls mDNS_Deregister_internal which can call a user callback, which may change
6205 // the record list and/or question list.
6206 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
6207 // InterfaceID non-NULL tells us the interface this multicast response was received on
6208 // InterfaceID NULL tells us this was a unicast response
6209 // dstaddr NULL tells us we received this over an outgoing TCP connection we made
6210 mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
6211 	const DNSMessage *const response, const mDNSu8 *end,
6212 	const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
6213 	const mDNSInterfaceID InterfaceID)
6214 	{
6215 	int i;
6216 	mDNSBool ResponseMCast    = dstaddr && mDNSAddrIsDNSMulticast(dstaddr);
6217 	mDNSBool ResponseSrcLocal = !srcaddr || AddressIsLocalSubnet(m, InterfaceID, srcaddr);
6218 	uDNS_LLQType LLQType      = uDNS_recvLLQResponse(m, response, end, srcaddr, srcport);
6219 
6220 	// "(CacheRecord*)1" is a special (non-zero) end-of-list marker
6221 	// We use this non-zero marker so that records in our CacheFlushRecords list will always have NextInCFList
6222 	// set non-zero, and that tells GetCacheEntity() that they're not, at this moment, eligible for recycling.
6223 	CacheRecord *CacheFlushRecords = (CacheRecord*)1;
6224 	CacheRecord **cfp = &CacheFlushRecords;
6225 
6226 	// All records in a DNS response packet are treated as equally valid statements of truth. If we want
6227 	// to guard against spoof responses, then the only credible protection against that is cryptographic
6228 	// security, e.g. DNSSEC., not worring about which section in the spoof packet contained the record
6229 	int firstauthority  =                   response->h.numAnswers;
6230 	int firstadditional = firstauthority  + response->h.numAuthorities;
6231 	int totalrecords    = firstadditional + response->h.numAdditionals;
6232 	const mDNSu8 *ptr   = response->data;
6233 
6234 	debugf("Received Response from %#-15a addressed to %#-15a on %p with "
6235 		"%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s LLQType %d",
6236 		srcaddr, dstaddr, InterfaceID,
6237 		response->h.numQuestions,   response->h.numQuestions   == 1 ? ", " : "s,",
6238 		response->h.numAnswers,     response->h.numAnswers     == 1 ? ", " : "s,",
6239 		response->h.numAuthorities, response->h.numAuthorities == 1 ? "y,  " : "ies,",
6240 		response->h.numAdditionals, response->h.numAdditionals == 1 ? "" : "s", LLQType);
6241 
6242 	// According to RFC 2181 <http://www.ietf.org/rfc/rfc2181.txt>
6243 	//    When a DNS client receives a reply with TC
6244 	//    set, it should ignore that response, and query again, using a
6245 	//    mechanism, such as a TCP connection, that will permit larger replies.
6246 	// It feels wrong to be throwing away data after the network went to all the trouble of delivering it to us, but
6247 	// delivering some records of the RRSet first and then the remainder a couple of milliseconds later was causing
6248 	// failures in our Microsoft Active Directory client, which expects to get the entire set of answers at once.
6249 	// <rdar://problem/6690034> Can't bind to Active Directory
6250 	// In addition, if the client immediately canceled its query after getting the initial partial response, then we'll
6251 	// abort our TCP connection, and not complete the operation, and end up with an incomplete RRSet in our cache.
6252 	// Next time there's a query for this RRSet we'll see answers in our cache, and assume we have the whole RRSet already,
6253 	// and not even do the TCP query.
6254 	// Accordingly, if we get a uDNS reply with kDNSFlag0_TC set, we bail out and wait for the TCP response containing the entire RRSet.
6255 	if (!InterfaceID && (response->h.flags.b[0] & kDNSFlag0_TC)) return;
6256 
6257 	if (LLQType == uDNS_LLQ_Ignore) return;
6258 
6259 	// 1. We ignore questions (if any) in mDNS response packets
6260 	// 2. If this is an LLQ response, we handle it much the same
6261 	// 3. If we get a uDNS UDP response with the TC (truncated) bit set, then we can't treat this
6262 	//    answer as being the authoritative complete RRSet, and respond by deleting all other
6263 	//    matching cache records that don't appear in this packet.
6264 	// Otherwise, this is a authoritative uDNS answer, so arrange for any stale records to be purged
6265 	if (ResponseMCast || LLQType == uDNS_LLQ_Events || (response->h.flags.b[0] & kDNSFlag0_TC))
6266 		ptr = LocateAnswers(response, end);
6267 	// Otherwise, for one-shot queries, any answers in our cache that are not also contained
6268 	// in this response packet are immediately deemed to be invalid.
6269 	else
6270 		{
6271 		mDNSu8 rcode = (mDNSu8)(response->h.flags.b[1] & kDNSFlag1_RC_Mask);
6272 		mDNSBool failure = !(rcode == kDNSFlag1_RC_NoErr || rcode == kDNSFlag1_RC_NXDomain || rcode == kDNSFlag1_RC_NotAuth);
6273 		mDNSBool returnEarly = mDNSfalse;
6274 		// We could possibly combine this with the similar loop at the end of this function --
6275 		// instead of tagging cache records here and then rescuing them if we find them in the answer section,
6276 		// we could instead use the "m->PktNum" mechanism to tag each cache record with the packet number in
6277 		// which it was received (or refreshed), and then at the end if we find any cache records which
6278 		// answer questions in this packet's question section, but which aren't tagged with this packet's
6279 		// packet number, then we deduce they are old and delete them
6280 		for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++)
6281 			{
6282 			DNSQuestion q, *qptr = mDNSNULL;
6283 			ptr = getQuestion(response, ptr, end, InterfaceID, &q);
6284 			if (ptr && (!dstaddr || (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q))))
6285 				{
6286 				if (!failure)
6287 					{
6288 					CacheRecord *rr;
6289 					const mDNSu32 slot = HashSlot(&q.qname);
6290 					CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname);
6291 					for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
6292 						if (q.InterfaceID == rr->resrec.InterfaceID && SameNameRecordAnswersQuestion(&rr->resrec, &q))
6293 							{
6294 							debugf("uDNS marking %p %##s (%s) %p %s", q.InterfaceID, q.qname.c, DNSTypeName(q.qtype),
6295 								rr->resrec.InterfaceID, CRDisplayString(m, rr));
6296 							// Don't want to disturb rroriginalttl here, because code below might need it for the exponential backoff doubling algorithm
6297 							rr->TimeRcvd          = m->timenow - TicksTTL(rr) - 1;
6298 							rr->UnansweredQueries = MaxUnansweredQueries;
6299 							}
6300 					}
6301 				else
6302 					{
6303 					if (qptr)
6304 						{
6305 						LogInfo("Server %p responded with code %d to query %##s (%s)", qptr->qDNSServer, rcode, q.qname.c, DNSTypeName(q.qtype));
6306 						PushDNSServerToEnd(m, qptr);
6307 						}
6308 					returnEarly = mDNStrue;
6309 					}
6310 				}
6311 			}
6312 		if (returnEarly)
6313 			{
6314 			LogInfo("Ignoring %2d Answer%s %2d Authorit%s %2d Additional%s",
6315 				response->h.numAnswers,     response->h.numAnswers     == 1 ? ", " : "s,",
6316 				response->h.numAuthorities, response->h.numAuthorities == 1 ? "y,  " : "ies,",
6317 				response->h.numAdditionals, response->h.numAdditionals == 1 ? "" : "s");
6318 			// not goto exit because we won't have any CacheFlushRecords and we do not want to
6319 			// generate negative cache entries (we want to query the next server)
6320 			return;
6321 			}
6322 		}
6323 
6324 	for (i = 0; i < totalrecords && ptr && ptr < end; i++)
6325 		{
6326 		// All responses sent via LL multicast are acceptable for caching
6327 		// All responses received over our outbound TCP connections are acceptable for caching
6328 		mDNSBool AcceptableResponse = ResponseMCast || !dstaddr || LLQType;
6329 		// (Note that just because we are willing to cache something, that doesn't necessarily make it a trustworthy answer
6330 		// to any specific question -- any code reading records from the cache needs to make that determination for itself.)
6331 
6332 		const mDNSu8 RecordType =
6333 			(i < firstauthority ) ? (mDNSu8)kDNSRecordTypePacketAns  :
6334 			(i < firstadditional) ? (mDNSu8)kDNSRecordTypePacketAuth : (mDNSu8)kDNSRecordTypePacketAdd;
6335 		ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, RecordType, &m->rec);
6336 		if (!ptr) goto exit;		// Break out of the loop and clean up our CacheFlushRecords list before exiting
6337 
6338 		// Don't want to cache OPT or TSIG pseudo-RRs
6339 		if (m->rec.r.resrec.rrtype == kDNSType_OPT || m->rec.r.resrec.rrtype == kDNSType_TSIG)
6340 			{ m->rec.r.resrec.RecordType = 0; continue; }
6341 
6342 		// When we receive uDNS LLQ responses, we assume a long cache lifetime --
6343 		// In the case of active LLQs, we'll get remove events when the records actually do go away
6344 		// In the case of polling LLQs, we assume the record remains valid until the next poll
6345 		if (!mDNSOpaque16IsZero(response->h.id))
6346 			m->rec.r.resrec.rroriginalttl = GetEffectiveTTL(LLQType, m->rec.r.resrec.rroriginalttl);
6347 
6348 		// If response was not sent via LL multicast,
6349 		// then see if it answers a recent query of ours, which would also make it acceptable for caching.
6350 		if (!AcceptableResponse) AcceptableResponse = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r);
6351 
6352 		// 1. Check that this packet resource record does not conflict with any of ours
6353 		if (mDNSOpaque16IsZero(response->h.id) && m->rec.r.resrec.rrtype != kDNSType_NSEC)
6354 			{
6355 			if (m->CurrentRecord)
6356 				LogMsg("mDNSCoreReceiveResponse ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
6357 			m->CurrentRecord = m->ResourceRecords;
6358 			while (m->CurrentRecord)
6359 				{
6360 				AuthRecord *rr = m->CurrentRecord;
6361 				m->CurrentRecord = rr->next;
6362 				// We accept all multicast responses, and unicast responses resulting from queries we issued
6363 				// For other unicast responses, this code accepts them only for responses with an
6364 				// (apparently) local source address that pertain to a record of our own that's in probing state
6365 				if (!AcceptableResponse && !(ResponseSrcLocal && rr->resrec.RecordType == kDNSRecordTypeUnique)) continue;
6366 
6367 				if (PacketRRMatchesSignature(&m->rec.r, rr))		// If interface, name, type (if shared record) and class match...
6368 					{
6369 					// ... check to see if type and rdata are identical
6370 					if (IdenticalSameNameRecord(&m->rec.r.resrec, &rr->resrec))
6371 						{
6372 						// If the RR in the packet is identical to ours, just check they're not trying to lower the TTL on us
6373 						if (m->rec.r.resrec.rroriginalttl >= rr->resrec.rroriginalttl/2 || m->SleepState)
6374 							{
6375 							// If we were planning to send on this -- and only this -- interface, then we don't need to any more
6376 							if      (rr->ImmedAnswer == InterfaceID) { rr->ImmedAnswer = mDNSNULL; rr->ImmedUnicast = mDNSfalse; }
6377 							}
6378 						else
6379 							{
6380 							if      (rr->ImmedAnswer == mDNSNULL)    { rr->ImmedAnswer = InterfaceID;       m->NextScheduledResponse = m->timenow; }
6381 							else if (rr->ImmedAnswer != InterfaceID) { rr->ImmedAnswer = mDNSInterfaceMark; m->NextScheduledResponse = m->timenow; }
6382 							}
6383 						}
6384 					// else, the packet RR has different type or different rdata -- check to see if this is a conflict
6385 					else if (m->rec.r.resrec.rroriginalttl > 0 && PacketRRConflict(m, rr, &m->rec.r))
6386 						{
6387 						LogInfo("mDNSCoreReceiveResponse: Pkt Record: %08lX %s", m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r));
6388 						LogInfo("mDNSCoreReceiveResponse: Our Record: %08lX %s", rr->     resrec.rdatahash, ARDisplayString(m, rr));
6389 
6390 						// If this record is marked DependentOn another record for conflict detection purposes,
6391 						// then *that* record has to be bumped back to probing state to resolve the conflict
6392 						if (rr->DependentOn)
6393 							{
6394 							while (rr->DependentOn) rr = rr->DependentOn;
6395 							LogInfo("mDNSCoreReceiveResponse: Dep Record: %08lX %s", rr->     resrec.rdatahash, ARDisplayString(m, rr));
6396 							}
6397 
6398 						// If we've just whacked this record's ProbeCount, don't need to do it again
6399 						if (rr->ProbeCount > DefaultProbeCountForTypeUnique)
6400 							LogInfo("mDNSCoreReceiveResponse: Already reset to Probing: %s", ARDisplayString(m, rr));
6401 						else if (rr->ProbeCount == DefaultProbeCountForTypeUnique)
6402 							LogMsg("mDNSCoreReceiveResponse: Ignoring response received before we even began probing: %s", ARDisplayString(m, rr));
6403 						else
6404 							{
6405 							LogMsg("mDNSCoreReceiveResponse: Received from %#a:%d %s", srcaddr, mDNSVal16(srcport), CRDisplayString(m, &m->rec.r));
6406 							// If we'd previously verified this record, put it back to probing state and try again
6407 							if (rr->resrec.RecordType == kDNSRecordTypeVerified)
6408 								{
6409 								LogMsg("mDNSCoreReceiveResponse: Reseting to Probing: %s", ARDisplayString(m, rr));
6410 								rr->resrec.RecordType     = kDNSRecordTypeUnique;
6411 								// We set ProbeCount to one more than the usual value so we know we've already touched this record.
6412 								// This is because our single probe for "example-name.local" could yield a response with (say) two A records and
6413 								// three AAAA records in it, and we don't want to call RecordProbeFailure() five times and count that as five conflicts.
6414 								// This special value is recognised and reset to DefaultProbeCountForTypeUnique in SendQueries().
6415 								rr->ProbeCount     = DefaultProbeCountForTypeUnique + 1;
6416 								rr->AnnounceCount  = InitialAnnounceCount;
6417 								InitializeLastAPTime(m, rr);
6418 								RecordProbeFailure(m, rr);	// Repeated late conflicts also cause us to back off to the slower probing rate
6419 								}
6420 							// If we're probing for this record, we just failed
6421 							else if (rr->resrec.RecordType == kDNSRecordTypeUnique)
6422 								{
6423 								LogMsg("mDNSCoreReceiveResponse: ProbeCount %d; will rename %s", rr->ProbeCount, ARDisplayString(m, rr));
6424 								mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
6425 								}
6426 							// We assumed this record must be unique, but we were wrong. (e.g. There are two mDNSResponders on the same machine giving
6427 							// different answers for the reverse mapping record.) This is simply a misconfiguration, and we don't try to recover from it.
6428 							else if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique)
6429 								{
6430 								LogMsg("mDNSCoreReceiveResponse: Unexpected conflict discarding %s", ARDisplayString(m, rr));
6431 								mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
6432 								}
6433 							else
6434 								LogMsg("mDNSCoreReceiveResponse: Unexpected record type %X %s", rr->resrec.RecordType, ARDisplayString(m, rr));
6435 							}
6436 						}
6437 					// Else, matching signature, different type or rdata, but not a considered a conflict.
6438 					// If the packet record has the cache-flush bit set, then we check to see if we
6439 					// have any record(s) of the same type that we should re-assert to rescue them
6440 					// (see note about "multi-homing and bridged networks" at the end of this function).
6441 					else if (m->rec.r.resrec.rrtype == rr->resrec.rrtype)
6442 						if ((m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && m->timenow - rr->LastMCTime > mDNSPlatformOneSecond/2)
6443 							{ rr->ImmedAnswer = mDNSInterfaceMark; m->NextScheduledResponse = m->timenow; }
6444 					}
6445 				}
6446 			}
6447 
6448 		if (!AcceptableResponse)
6449 			{
6450 			const CacheRecord *cr;
6451 			for (cr = CacheFlushRecords; cr != (CacheRecord*)1; cr = cr->NextInCFList)
6452 				{
6453 				domainname *target = GetRRDomainNameTarget(&cr->resrec);
6454 				if (target && cr->resrec.rdatahash == m->rec.r.resrec.namehash && SameDomainName(target, m->rec.r.resrec.name))
6455 					{ AcceptableResponse = mDNStrue; break; }
6456 				}
6457 			}
6458 
6459 		// 2. See if we want to add this packet resource record to our cache
6460 		// We only try to cache answers if we have a cache to put them in
6461 		// Also, we ignore any apparent attempts at cache poisoning unicast to us that do not answer any outstanding active query
6462 		if (!AcceptableResponse) debugf("mDNSCoreReceiveResponse ignoring %s", CRDisplayString(m, &m->rec.r));
6463 		if (m->rrcache_size && AcceptableResponse)
6464 			{
6465 			const mDNSu32 slot = HashSlot(m->rec.r.resrec.name);
6466 			CacheGroup *cg = CacheGroupForRecord(m, slot, &m->rec.r.resrec);
6467 			CacheRecord *rr;
6468 
6469 			// 2a. Check if this packet resource record is already in our cache
6470 			for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
6471 				{
6472 				// If we found this exact resource record, refresh its TTL
6473 				if (rr->resrec.InterfaceID == InterfaceID && IdenticalSameNameRecord(&m->rec.r.resrec, &rr->resrec))
6474 					{
6475 					if (m->rec.r.resrec.rdlength > InlineCacheRDSize)
6476 						verbosedebugf("Found record size %5d interface %p already in cache: %s",
6477 							m->rec.r.resrec.rdlength, InterfaceID, CRDisplayString(m, &m->rec.r));
6478 					rr->TimeRcvd  = m->timenow;
6479 
6480 					if (m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask)
6481 						{
6482 						// If this packet record has the kDNSClass_UniqueRRSet flag set, then add it to our cache flushing list
6483 						if (rr->NextInCFList == mDNSNULL && cfp != &rr->NextInCFList && LLQType != uDNS_LLQ_Events)
6484 							{ *cfp = rr; cfp = &rr->NextInCFList; *cfp = (CacheRecord*)1; }
6485 
6486 						// If this packet record is marked unique, and our previous cached copy was not, then fix it
6487 						if (!(rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask))
6488 							{
6489 							DNSQuestion *q;
6490 							for (q = m->Questions; q; q=q->next) if (ResourceRecordAnswersQuestion(&rr->resrec, q)) q->UniqueAnswers++;
6491 							rr->resrec.RecordType = m->rec.r.resrec.RecordType;
6492 							}
6493 						}
6494 
6495 					if (!mDNSPlatformMemSame(m->rec.r.resrec.rdata->u.data, rr->resrec.rdata->u.data, m->rec.r.resrec.rdlength))
6496 						{
6497 						// If the rdata of the packet record differs in name capitalization from the record in our cache
6498 						// then mDNSPlatformMemSame will detect this. In this case, throw the old record away, so that clients get
6499 						// a 'remove' event for the record with the old capitalization, and then an 'add' event for the new one.
6500 						rr->resrec.rroriginalttl = 0;
6501 						rr->UnansweredQueries = MaxUnansweredQueries;
6502 						SetNextCacheCheckTime(m, rr);
6503 						// DO NOT break out here -- we want to continue as if we never found it
6504 						}
6505 					else if (m->rec.r.resrec.rroriginalttl > 0)
6506 						{
6507 						//if (rr->resrec.rroriginalttl == 0) LogMsg("uDNS rescuing %s", CRDisplayString(m, rr));
6508 						RefreshCacheRecord(m, rr, m->rec.r.resrec.rroriginalttl);
6509 						break;
6510 						}
6511 					else
6512 						{
6513 						// If the packet TTL is zero, that means we're deleting this record.
6514 						// To give other hosts on the network a chance to protest, we push the deletion
6515 						// out one second into the future. Also, we set UnansweredQueries to MaxUnansweredQueries.
6516 						// Otherwise, we'll do final queries for this record at 80% and 90% of its apparent
6517 						// lifetime (800ms and 900ms from now) which is a pointless waste of network bandwidth.
6518 						debugf("DE for %s", CRDisplayString(m, rr));
6519 						rr->resrec.rroriginalttl = 1;
6520 						rr->UnansweredQueries = MaxUnansweredQueries;
6521 						SetNextCacheCheckTime(m, rr);
6522 						break;
6523 						}
6524 					}
6525 				}
6526 
6527 			// If packet resource record not in our cache, add it now
6528 			// (unless it is just a deletion of a record we never had, in which case we don't care)
6529 			if (!rr && m->rec.r.resrec.rroriginalttl > 0)
6530 				{
6531 				rr = CreateNewCacheEntry(m, slot, cg);
6532 				if (rr && (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) && LLQType != uDNS_LLQ_Events)
6533 					{ *cfp = rr; cfp = &rr->NextInCFList; *cfp = (CacheRecord*)1; }
6534 				}
6535 			}
6536 		m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
6537 		}
6538 
6539 exit:
6540 	m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
6541 
6542 	// If we've just received one or more records with their cache flush bits set,
6543 	// then scan that cache slot to see if there are any old stale records we need to flush
6544 	while (CacheFlushRecords != (CacheRecord*)1)
6545 		{
6546 		CacheRecord *r1 = CacheFlushRecords, *r2;
6547 		const mDNSu32 slot = HashSlot(r1->resrec.name);
6548 		const CacheGroup *cg = CacheGroupForRecord(m, slot, &r1->resrec);
6549 		CacheFlushRecords = CacheFlushRecords->NextInCFList;
6550 		r1->NextInCFList = mDNSNULL;
6551 
6552 		// Look for records in the cache with the same signature as this new one with the cache flush
6553 		// bit set, and either (a) if they're fresh, just make sure the whole RRSet has the same TTL
6554 		// (as required by DNS semantics) or (b) if they're old, mark them for deletion in one second.
6555 		// We make these TTL adjustments *only* for records that still have *more* than one second
6556 		// remaining to live. Otherwise, a record that we tagged for deletion half a second ago
6557 		// (and now has half a second remaining) could inadvertently get its life extended, by either
6558 		// (a) if we got an explicit goodbye packet half a second ago, the record would be considered
6559 		// "fresh" and would be incorrectly resurrected back to the same TTL as the rest of the RRSet,
6560 		// or (b) otherwise, the record would not be fully resurrected, but would be reset to expire
6561 		// in one second, thereby inadvertently delaying its actual expiration, instead of hastening it.
6562 		// If this were to happen repeatedly, the record's expiration could be deferred indefinitely.
6563 		// To avoid this, we need to ensure that the cache flushing operation will only act to
6564 		// *decrease* a record's remaining lifetime, never *increase* it.
6565 		for (r2 = cg ? cg->members : mDNSNULL; r2; r2=r2->next)
6566 			if (r1->resrec.InterfaceID == r2->resrec.InterfaceID &&
6567 				r1->resrec.rrtype      == r2->resrec.rrtype &&
6568 				r1->resrec.rrclass     == r2->resrec.rrclass)
6569 				{
6570 				// If record is recent, just ensure the whole RRSet has the same TTL (as required by DNS semantics)
6571 				// else, if record is old, mark it to be flushed
6572 				if (m->timenow - r2->TimeRcvd < mDNSPlatformOneSecond && RRExpireTime(r2) - m->timenow > mDNSPlatformOneSecond)
6573 					{
6574 					// If we find mismatched TTLs in an RRSet, correct them.
6575 					// We only do this for records with a TTL of 2 or higher. It's possible to have a
6576 					// goodbye announcement with the cache flush bit set (or a case change on record rdata,
6577 					// which we treat as a goodbye followed by an addition) and in that case it would be
6578 					// inappropriate to synchronize all the other records to a TTL of 0 (or 1).
6579 					// We suppress the message for the specific case of correcting from 240 to 60 for type TXT,
6580 					// because certain early Bonjour devices are known to have this specific mismatch, and
6581 					// there's no point filling syslog with messages about something we already know about.
6582 					// We also don't log this for uDNS responses, since a caching name server is obliged
6583 					// to give us an aged TTL to correct for how long it has held the record,
6584 					// so our received TTLs are expected to vary in that case
6585 					if (r2->resrec.rroriginalttl != r1->resrec.rroriginalttl && r1->resrec.rroriginalttl > 1)
6586 						{
6587 						if (!(r2->resrec.rroriginalttl == 240 && r1->resrec.rroriginalttl == 60 && r2->resrec.rrtype == kDNSType_TXT) &&
6588 							mDNSOpaque16IsZero(response->h.id))
6589 							LogInfo("Correcting TTL from %4d to %4d for %s",
6590 								r2->resrec.rroriginalttl, r1->resrec.rroriginalttl, CRDisplayString(m, r2));
6591 						r2->resrec.rroriginalttl = r1->resrec.rroriginalttl;
6592 						}
6593 					r2->TimeRcvd = m->timenow;
6594 					}
6595 				else				// else, if record is old, mark it to be flushed
6596 					{
6597 					verbosedebugf("Cache flush %p X %p %s", r1, r2, CRDisplayString(m, r2));
6598 					// We set stale records to expire in one second.
6599 					// This gives the owner a chance to rescue it if necessary.
6600 					// This is important in the case of multi-homing and bridged networks:
6601 					//   Suppose host X is on Ethernet. X then connects to an AirPort base station, which happens to be
6602 					//   bridged onto the same Ethernet. When X announces its AirPort IP address with the cache-flush bit
6603 					//   set, the AirPort packet will be bridged onto the Ethernet, and all other hosts on the Ethernet
6604 					//   will promptly delete their cached copies of the (still valid) Ethernet IP address record.
6605 					//   By delaying the deletion by one second, we give X a change to notice that this bridging has
6606 					//   happened, and re-announce its Ethernet IP address to rescue it from deletion from all our caches.
6607 
6608 					// We set UnansweredQueries to MaxUnansweredQueries to avoid expensive and unnecessary
6609 					// final expiration queries for this record.
6610 
6611 					// If a record is deleted twice, first with an explicit DE record, then a second time by virtue of the cache
6612 					// flush bit on the new record replacing it, then we allow the record to be deleted immediately, without the usual
6613 					// one-second grace period. This improves responsiveness for mDNS_Update(), as used for things like iChat status updates.
6614 					if (r2->TimeRcvd == m->timenow && r2->resrec.rroriginalttl <= 1 && r2->UnansweredQueries == MaxUnansweredQueries)
6615 						{
6616 						debugf("Cache flush for DE record %s", CRDisplayString(m, r2));
6617 						r2->resrec.rroriginalttl = 0;
6618 						m->NextCacheCheck = m->timenow;
6619 						m->NextScheduledEvent = m->timenow;
6620 						}
6621 					else if (RRExpireTime(r2) - m->timenow > mDNSPlatformOneSecond)
6622 						{
6623 						// We only set a record to expire in one second if it currently has *more* than a second to live
6624 						// If it's already due to expire in a second or less, we just leave it alone
6625 						r2->resrec.rroriginalttl = 1;
6626 						r2->UnansweredQueries = MaxUnansweredQueries;
6627 						r2->TimeRcvd = m->timenow - 1;
6628 						// We use (m->timenow - 1) instead of m->timenow, because we use that to identify records
6629 						// that we marked for deletion via an explicit DE record
6630 						}
6631 					}
6632 				SetNextCacheCheckTime(m, r2);
6633 				}
6634 		if (r1->DelayDelivery)	// If we were planning to delay delivery of this record, see if we still need to
6635 			{
6636 			// Note, only need to call SetNextCacheCheckTime() when DelayDelivery is set, not when it's cleared
6637 			r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, slot);
6638 			if (!r1->DelayDelivery) CacheRecordDeferredAdd(m, r1);
6639 			}
6640 		}
6641 
6642 	// See if we need to generate negative cache entries for unanswered unicast questions
6643 	ptr = response->data;
6644 	for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++)
6645 		{
6646 		DNSQuestion q;
6647 		ptr = getQuestion(response, ptr, end, InterfaceID, &q);
6648 		if (ptr && (!dstaddr || ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q)))
6649 			{
6650 			// When we're doing parallel unicast and multicast queries for dot-local names (for supporting Microsoft
6651 			// Active Directory sites) we don't want to waste memory making negative cache entries for all the unicast answers.
6652 			// Otherwise we just fill up our cache with negative entries for just about every single multicast name we ever look up
6653 			// (since the Microsoft Active Directory server is going to assert that pretty much every single multicast name doesn't exist).
6654 			// This is not only a waste of memory, but there's also the problem of those negative entries confusing us later -- e.g. we
6655 			// suppress sending our mDNS query packet because we think we already have a valid (negative) answer to that query in our cache.
6656 			// The one exception is that we *DO* want to make a negative cache entry for "local. SOA", for the (common) case where we're
6657 			// *not* on a Microsoft Active Directory network, and there is no authoritative server for "local". Note that this is not
6658 			// in conflict with the mDNS spec, because that spec says, "Multicast DNS Zones have no SOA record," so it's okay to cache
6659 			// negative answers for "local. SOA" from a uDNS server, because the mDNS spec already says that such records do not exist :-)
6660 			if (!InterfaceID && q.qtype != kDNSType_SOA && IsLocalDomain(&q.qname))
6661 				LogInfo("Not generating negative cache entry for %##s (%s)", q.qname.c, DNSTypeName(q.qtype));
6662 			else
6663 				{
6664 				CacheRecord *rr, *neg = mDNSNULL;
6665 				mDNSu32 slot = HashSlot(&q.qname);
6666 				CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname);
6667 				for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
6668 					if (SameNameRecordAnswersQuestion(&rr->resrec, &q))
6669 						{
6670 						// 1. If we got a fresh answer to this query, then don't need to generate a negative entry
6671 						if (rr->TimeRcvd + TicksTTL(rr) - m->timenow > 0) break;
6672 						// 2. If we already had a negative entry, keep track of it so we can resurrect it instead of creating a new one
6673 						if (rr->resrec.RecordType == kDNSRecordTypePacketNegative) neg = rr;
6674 						}
6675 
6676 				if (!rr)
6677 					{
6678 					// We start off assuming a negative caching TTL of 60 seconds
6679 					// but then look to see if we can find an SOA authority record to tell us a better value we should be using
6680 					mDNSu32 negttl = 60;
6681 					int repeat = 0;
6682 					const domainname *name = &q.qname;
6683 					mDNSu32           hash = q.qnamehash;
6684 
6685 					// Special case for our special Microsoft Active Directory "local SOA" check.
6686 					// Some cheap home gateways don't include an SOA record in the authority section when
6687 					// they send negative responses, so we don't know how long to cache the negative result.
6688 					// Because we don't want to keep hitting the root name servers with our query to find
6689 					// if we're on a network using Microsoft Active Directory using "local" as a private
6690 					// internal top-level domain, we make sure to cache the negative result for at least one day.
6691 					if (q.qtype == kDNSType_SOA && SameDomainName(&q.qname, &localdomain)) negttl = 60 * 60 * 24;
6692 
6693 					// If we're going to make (or update) a negative entry, then look for the appropriate TTL from the SOA record
6694 					if (response->h.numAuthorities && (ptr = LocateAuthorities(response, end)) != mDNSNULL)
6695 						{
6696 						ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
6697 						if (ptr && m->rec.r.resrec.rrtype == kDNSType_SOA)
6698 							{
6699 							const rdataSOA *const soa = (const rdataSOA *)m->rec.r.resrec.rdata->u.data;
6700 							mDNSu32 ttl_s = soa->min;
6701 							// We use the lesser of the SOA.MIN field and the SOA record's TTL, *except*
6702 							// for the SOA record for ".", where the record is reported as non-cacheable
6703 							// (TTL zero) for some reason, so in this case we just take the SOA record's TTL as-is
6704 							if (ttl_s > m->rec.r.resrec.rroriginalttl && m->rec.r.resrec.name->c[0])
6705 								ttl_s = m->rec.r.resrec.rroriginalttl;
6706 							if (negttl < ttl_s) negttl = ttl_s;
6707 
6708 							// Special check for SOA queries: If we queried for a.b.c.d.com, and got no answer,
6709 							// with an Authority Section SOA record for d.com, then this is a hint that the authority
6710 							// is d.com, and consequently SOA records b.c.d.com and c.d.com don't exist either.
6711 							// To do this we set the repeat count so the while loop below will make a series of negative cache entries for us
6712 							if (q.qtype == kDNSType_SOA)
6713 								{
6714 								int qcount = CountLabels(&q.qname);
6715 								int scount = CountLabels(m->rec.r.resrec.name);
6716 								if (qcount - 1 > scount)
6717 									if (SameDomainName(SkipLeadingLabels(&q.qname, qcount - scount), m->rec.r.resrec.name))
6718 										repeat = qcount - 1 - scount;
6719 								}
6720 							}
6721 						m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
6722 						}
6723 
6724 					// If we already had a negative entry in the cache, then we double our existing negative TTL. This is to avoid
6725 					// the case where the record doesn't exist (e.g. particularly for things like our lb._dns-sd._udp.<domain> query),
6726 					// and the server returns no SOA record (or an SOA record with a small MIN TTL) so we assume a TTL
6727 					// of 60 seconds, and we end up polling the server every minute for a record that doesn't exist.
6728 					// With this fix in place, when this happens, we double the effective TTL each time (up to one hour),
6729 					// so that we back off our polling rate and don't keep hitting the server continually.
6730 					if (neg)
6731 						{
6732 						if (negttl < neg->resrec.rroriginalttl * 2)
6733 							negttl = neg->resrec.rroriginalttl * 2;
6734 						if (negttl > 3600)
6735 							negttl = 3600;
6736 						}
6737 
6738 					negttl = GetEffectiveTTL(LLQType, negttl);	// Add 25% grace period if necessary
6739 
6740 					// If we already had a negative cache entry just update it, else make one or more new negative cache entries
6741 					if (neg)
6742 						{
6743 						debugf("Renewing negative TTL from %d to %d %s", neg->resrec.rroriginalttl, negttl, CRDisplayString(m, neg));
6744 						RefreshCacheRecord(m, neg, negttl);
6745 						}
6746 					else while (1)
6747 						{
6748 						debugf("mDNSCoreReceiveResponse making negative cache entry TTL %d for %##s (%s)", negttl, name->c, DNSTypeName(q.qtype));
6749 						MakeNegativeCacheRecord(m, &m->rec.r, name, hash, q.qtype, q.qclass, negttl, mDNSInterface_Any);
6750 						CreateNewCacheEntry(m, slot, cg);
6751 						m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
6752 						if (!repeat) break;
6753 						repeat--;
6754 						name = (const domainname *)(name->c + 1 + name->c[0]);
6755 						hash = DomainNameHashValue(name);
6756 						slot = HashSlot(name);
6757 						cg   = CacheGroupForName(m, slot, hash, name);
6758 						}
6759 					}
6760 				}
6761 			}
6762 		}
6763 	}
6764 
6765 mDNSlocal void SPSRecordCallback(mDNS *const m, AuthRecord *const ar, mStatus result)
6766 	{
6767 	if (result && result != mStatus_MemFree)
6768 		LogInfo("SPS Callback %d %s", result, ARDisplayString(m, ar));
6769 
6770 	if (result == mStatus_NameConflict)
6771 		{
6772 		LogMsg("Received Conflicting mDNS -- waking %s %.6a %s",
6773 			InterfaceNameForID(m, ar->resrec.InterfaceID), &ar->WakeUp.HMAC, ARDisplayString(m, ar));
6774 		SendWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.IMAC, &ar->WakeUp.password);
6775 		}
6776 	else if (result == mStatus_MemFree)
6777 		{
6778 		m->ProxyRecords--;
6779 		mDNSPlatformMemFree(ar);
6780 		}
6781 	}
6782 
6783 mDNSlocal void mDNSCoreReceiveUpdate(mDNS *const m,
6784 	const DNSMessage *const msg, const mDNSu8 *end,
6785 	const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
6786 	const mDNSInterfaceID InterfaceID)
6787 	{
6788 	int i;
6789 	AuthRecord opt;
6790 	mDNSu8 *p = m->omsg.data;
6791 	OwnerOptData owner;
6792 	mDNSu32 updatelease = 0;
6793 	const mDNSu8 *ptr;
6794 
6795 	LogSPS("Received Update from %#-15a:%-5d to %#-15a:%-5d on 0x%p with "
6796 		"%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s",
6797 		srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID,
6798 		msg->h.numQuestions,   msg->h.numQuestions   == 1 ? ", " : "s,",
6799 		msg->h.numAnswers,     msg->h.numAnswers     == 1 ? ", " : "s,",
6800 		msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y,  " : "ies,",
6801 		msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s");
6802 
6803 	if (!InterfaceID || !m->SPSSocket || !mDNSSameIPPort(dstport, m->SPSSocket->port)) return;
6804 
6805 	if (mDNS_PacketLoggingEnabled)
6806 		DumpPacket(m, mStatus_NoError, mDNSfalse, "UDP", srcaddr, srcport, dstaddr, dstport, msg, end);
6807 
6808 	ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space + DNSOpt_OwnerData_ID_Space);
6809 	if (ptr)
6810 		{
6811 		ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
6812 		if (ptr && m->rec.r.resrec.rrtype == kDNSType_OPT)
6813 			{
6814 			const rdataOPT *o;
6815 			const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
6816 			for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++)
6817 				{
6818 				if      (o->opt == kDNSOpt_Lease)                         updatelease = o->u.updatelease;
6819 				else if (o->opt == kDNSOpt_Owner && o->u.owner.vers == 0) owner       = o->u.owner;
6820 				}
6821 			}
6822 		m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
6823 		}
6824 
6825 	InitializeDNSMessage(&m->omsg.h, msg->h.id, UpdateRespFlags);
6826 
6827 	if (!updatelease || !owner.HMAC.l[0])
6828 		{
6829 		static int msgs = 0;
6830 		if (msgs < 100)
6831 			{
6832 			msgs++;
6833 			LogMsg("Refusing sleep proxy registration from %#a:%d:%s%s", srcaddr, mDNSVal16(srcport),
6834 				!updatelease ? " No lease" : "", !owner.HMAC.l[0] ? " No owner" : "");
6835 			}
6836 		m->omsg.h.flags.b[1] |= kDNSFlag1_RC_FormErr;
6837 		}
6838 	else if (m->ProxyRecords + msg->h.mDNS_numUpdates > MAX_PROXY_RECORDS)
6839 		{
6840 		static int msgs = 0;
6841 		if (msgs < 100)
6842 			{
6843 			msgs++;
6844 			LogMsg("Refusing sleep proxy registration from %#a:%d: Too many records %d + %d = %d > %d", srcaddr, mDNSVal16(srcport),
6845 				m->ProxyRecords, msg->h.mDNS_numUpdates, m->ProxyRecords + msg->h.mDNS_numUpdates, MAX_PROXY_RECORDS);
6846 			}
6847 		m->omsg.h.flags.b[1] |= kDNSFlag1_RC_Refused;
6848 		}
6849 	else
6850 		{
6851 		LogSPS("Received Update for H-MAC %.6a I-MAC %.6a Password %.6a seq %d", &owner.HMAC, &owner.IMAC, &owner.password, owner.seq);
6852 
6853 		if (updatelease > 24 * 60 * 60)
6854 			updatelease = 24 * 60 * 60;
6855 
6856 		if (updatelease > 0x40000000UL / mDNSPlatformOneSecond)
6857 			updatelease = 0x40000000UL / mDNSPlatformOneSecond;
6858 
6859 		ptr = LocateAuthorities(msg, end);
6860 		for (i = 0; i < msg->h.mDNS_numUpdates && ptr && ptr < end; i++)
6861 			{
6862 			ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
6863 			if (ptr)
6864 				{
6865 				mDNSu16 RDLengthMem = GetRDLengthMem(&m->rec.r.resrec);
6866 				AuthRecord *ar = mDNSPlatformMemAllocate(sizeof(AuthRecord) - sizeof(RDataBody) + RDLengthMem);
6867 				if (!ar) { m->omsg.h.flags.b[1] |= kDNSFlag1_RC_Refused; break; }
6868 				else
6869 					{
6870 					mDNSu8 RecordType = m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask ? kDNSRecordTypeUnique : kDNSRecordTypeShared;
6871 					m->rec.r.resrec.rrclass &= ~kDNSClass_UniqueRRSet;
6872 					mDNS_SetupResourceRecord(ar, mDNSNULL, InterfaceID, m->rec.r.resrec.rrtype, m->rec.r.resrec.rroriginalttl, RecordType, SPSRecordCallback, ar);
6873 					AssignDomainName(&ar->namestorage, m->rec.r.resrec.name);
6874 					ar->resrec.rdlength = GetRDLength(&m->rec.r.resrec, mDNSfalse);
6875 					ar->resrec.rdata->MaxRDLength = RDLengthMem;
6876 					mDNSPlatformMemCopy(ar->resrec.rdata->u.data, m->rec.r.resrec.rdata->u.data, RDLengthMem);
6877 					ar->WakeUp = owner;
6878 					if (m->rec.r.resrec.rrtype == kDNSType_PTR)
6879 						{
6880 						mDNSs32 t = ReverseMapDomainType(m->rec.r.resrec.name);
6881 						if      (t == mDNSAddrType_IPv4) GetIPv4FromName(&ar->AddressProxy, m->rec.r.resrec.name);
6882 						else if (t == mDNSAddrType_IPv6) GetIPv6FromName(&ar->AddressProxy, m->rec.r.resrec.name);
6883 						debugf("mDNSCoreReceiveUpdate: PTR %d %d %#a %s", t, ar->AddressProxy.type, &ar->AddressProxy, ARDisplayString(m, ar));
6884 						if (ar->AddressProxy.type) SetSPSProxyListChanged(InterfaceID);
6885 						}
6886 					ar->TimeRcvd   = m->timenow;
6887 					ar->TimeExpire = m->timenow + updatelease * mDNSPlatformOneSecond;
6888 					if (m->NextScheduledSPS - ar->TimeExpire > 0)
6889 						m->NextScheduledSPS = ar->TimeExpire;
6890 					mDNS_Register_internal(m, ar);
6891 					// For now, since we don't get IPv6 ND or data packets, we don't advertise AAAA records for our SPS clients
6892 					if (ar->resrec.rrtype == kDNSType_AAAA) ar->resrec.rroriginalttl = 0;
6893 					m->ProxyRecords++;
6894 					LogSPS("SPS Registered %4d %X %s", m->ProxyRecords, RecordType, ARDisplayString(m,ar));
6895 					}
6896 				}
6897 			m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
6898 			}
6899 
6900 		if (m->omsg.h.flags.b[1] & kDNSFlag1_RC_Mask)
6901 			{
6902 			LogMsg("Refusing sleep proxy registration from %#a:%d: Out of memory", srcaddr, mDNSVal16(srcport));
6903 			ClearProxyRecords(m, &owner, m->DuplicateRecords);
6904 			ClearProxyRecords(m, &owner, m->ResourceRecords);
6905 			}
6906 		else
6907 			{
6908 			mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
6909 			opt.resrec.rrclass    = NormalMaxDNSMessageData;
6910 			opt.resrec.rdlength   = sizeof(rdataOPT);	// One option in this OPT record
6911 			opt.resrec.rdestimate = sizeof(rdataOPT);
6912 			opt.resrec.rdata->u.opt[0].opt           = kDNSOpt_Lease;
6913 			opt.resrec.rdata->u.opt[0].u.updatelease = updatelease;
6914 			p = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.numAdditionals, &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
6915 			}
6916 		}
6917 
6918 	if (p) mDNSSendDNSMessage(m, &m->omsg, p, InterfaceID, m->SPSSocket, srcaddr, srcport, mDNSNULL, mDNSNULL);
6919 	}
6920 
6921 mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end, const mDNSInterfaceID InterfaceID)
6922 	{
6923 	if (InterfaceID)
6924 		{
6925 		AuthRecord *rr;
6926 		mDNSu32 updatelease = 60 * 60;		// If SPS fails to indicate lease time, assume one hour
6927 		const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space);
6928 		if (ptr)
6929 			{
6930 			ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
6931 			if (ptr && m->rec.r.resrec.rrtype == kDNSType_OPT)
6932 				{
6933 				const rdataOPT *o;
6934 				const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
6935 				for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++)
6936 					if (o->opt == kDNSOpt_Lease)
6937 						{
6938 						updatelease = o->u.updatelease;
6939 						LogSPS("Sleep Proxy granted lease time %4d seconds", updatelease);
6940 						}
6941 				}
6942 			m->rec.r.resrec.RecordType = 0;		// Clear RecordType to show we're not still using it
6943 			}
6944 
6945 		for (rr = m->ResourceRecords; rr; rr=rr->next)
6946 			if (rr->resrec.InterfaceID == InterfaceID || (!rr->resrec.InterfaceID && (rr->ForceMCast || IsLocalDomain(rr->resrec.name))))
6947 				if (mDNSSameOpaque16(rr->updateid, msg->h.id))
6948 					{
6949 					rr->updateid = zeroID;
6950 					rr->expire   = NonZeroTime(m->timenow + updatelease * mDNSPlatformOneSecond);
6951 					LogSPS("Sleep Proxy registered record %5d %s", updatelease, ARDisplayString(m,rr));
6952 					}
6953 
6954 		}
6955 	// If we were waiting to go to sleep, then this SPS registration or wide-area record deletion
6956 	// may have been the thing we were waiting for, so schedule another check to see if we can sleep now.
6957 	if (m->SleepLimit) m->NextScheduledSPRetry = m->timenow;
6958 	}
6959 
6960 mDNSexport void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr,
6961 	const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds, mDNSInterfaceID InterfaceID)
6962 	{
6963 	if (cr == &m->rec.r && m->rec.r.resrec.RecordType)
6964 		{
6965 		LogMsg("MakeNegativeCacheRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r));
6966 #if ForceAlerts
6967 		*(long*)0 = 0;
6968 #endif
6969 		}
6970 
6971 	// Create empty resource record
6972 	cr->resrec.RecordType    = kDNSRecordTypePacketNegative;
6973 	cr->resrec.InterfaceID   = InterfaceID;
6974 	cr->resrec.name          = name;	// Will be updated to point to cg->name when we call CreateNewCacheEntry
6975 	cr->resrec.rrtype        = rrtype;
6976 	cr->resrec.rrclass       = rrclass;
6977 	cr->resrec.rroriginalttl = ttl_seconds;
6978 	cr->resrec.rdlength      = 0;
6979 	cr->resrec.rdestimate    = 0;
6980 	cr->resrec.namehash      = namehash;
6981 	cr->resrec.rdatahash     = 0;
6982 	cr->resrec.rdata = (RData*)&cr->smallrdatastorage;
6983 	cr->resrec.rdata->MaxRDLength = 0;
6984 
6985 	cr->NextInKAList       = mDNSNULL;
6986 	cr->TimeRcvd           = m->timenow;
6987 	cr->DelayDelivery      = 0;
6988 	cr->NextRequiredQuery  = m->timenow;
6989 	cr->LastUsed           = m->timenow;
6990 	cr->CRActiveQuestion   = mDNSNULL;
6991 	cr->UnansweredQueries  = 0;
6992 	cr->LastUnansweredTime = 0;
6993 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
6994 	cr->MPUnansweredQ      = 0;
6995 	cr->MPLastUnansweredQT = 0;
6996 	cr->MPUnansweredKA     = 0;
6997 	cr->MPExpectingKA      = mDNSfalse;
6998 #endif
6999 	cr->NextInCFList       = mDNSNULL;
7000 	}
7001 
7002 mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *const end,
7003 	const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport,
7004 	const mDNSInterfaceID InterfaceID)
7005 	{
7006 	mDNSInterfaceID ifid = InterfaceID;
7007 	DNSMessage  *msg  = (DNSMessage *)pkt;
7008 	const mDNSu8 StdQ = kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery;
7009 	const mDNSu8 StdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery;
7010 	const mDNSu8 UpdQ = kDNSFlag0_QR_Query    | kDNSFlag0_OP_Update;
7011 	const mDNSu8 UpdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update;
7012 	mDNSu8 QR_OP;
7013 	mDNSu8 *ptr = mDNSNULL;
7014 	mDNSBool TLS = (dstaddr == (mDNSAddr *)1);	// For debug logs: dstaddr = 0 means TCP; dstaddr = 1 means TLS
7015 	if (TLS) dstaddr = mDNSNULL;
7016 
7017 #ifndef UNICAST_DISABLED
7018 	if (mDNSSameAddress(srcaddr, &m->Router))
7019 		{
7020 #ifdef _LEGACY_NAT_TRAVERSAL_
7021 		if (mDNSSameIPPort(srcport, SSDPPort) || (m->SSDPSocket && mDNSSameIPPort(dstport, m->SSDPSocket->port)))
7022 			{
7023 			mDNS_Lock(m);
7024 			LNT_ConfigureRouterInfo(m, InterfaceID, pkt, (mDNSu16)(end - (mDNSu8 *)pkt));
7025 			mDNS_Unlock(m);
7026 			return;
7027 			}
7028 #endif
7029 		if (mDNSSameIPPort(srcport, NATPMPPort))
7030 			{
7031 			mDNS_Lock(m);
7032 			uDNS_ReceiveNATPMPPacket(m, InterfaceID, pkt, (mDNSu16)(end - (mDNSu8 *)pkt));
7033 			mDNS_Unlock(m);
7034 			return;
7035 			}
7036 		}
7037 #ifdef _LEGACY_NAT_TRAVERSAL_
7038 	else if (m->SSDPSocket && mDNSSameIPPort(dstport, m->SSDPSocket->port)) { debugf("Ignoring SSDP response from %#a:%d", srcaddr, mDNSVal16(srcport)); return; }
7039 #endif
7040 
7041 #endif
7042 	if ((unsigned)(end - (mDNSu8 *)pkt) < sizeof(DNSMessageHeader)) { LogMsg("DNS Message too short"); return; }
7043 	QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask);
7044 	// Read the integer parts which are in IETF byte-order (MSB first, LSB second)
7045 	ptr = (mDNSu8 *)&msg->h.numQuestions;
7046 	msg->h.numQuestions   = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]);
7047 	msg->h.numAnswers     = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]);
7048 	msg->h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]);
7049 	msg->h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] << 8 | ptr[7]);
7050 
7051 	if (!m) { LogMsg("mDNSCoreReceive ERROR m is NULL"); return; }
7052 
7053 	// We use zero addresses and all-ones addresses at various places in the code to indicate special values like "no address"
7054 	// If we accept and try to process a packet with zero or all-ones source address, that could really mess things up
7055 	if (srcaddr && !mDNSAddressIsValid(srcaddr)) { debugf("mDNSCoreReceive ignoring packet from %#a", srcaddr); return; }
7056 
7057 	mDNS_Lock(m);
7058 	m->PktNum++;
7059 #ifndef UNICAST_DISABLED
7060 	if (!dstaddr || (!mDNSAddressIsAllDNSLinkGroup(dstaddr) && (QR_OP == StdR || QR_OP == UpdR)))
7061 		if (!mDNSOpaque16IsZero(msg->h.id)) // uDNS_ReceiveMsg only needs to get real uDNS responses, not "QU" mDNS responses
7062 			{
7063 			ifid = mDNSInterface_Any;
7064 			if (mDNS_PacketLoggingEnabled)
7065 				DumpPacket(m, mStatus_NoError, mDNSfalse, TLS ? "TLS" : !dstaddr ? "TCP" : "UDP", srcaddr, srcport, dstaddr, dstport, msg, end);
7066 			uDNS_ReceiveMsg(m, msg, end, srcaddr, srcport);
7067 			// Note: mDNSCore also needs to get access to received unicast responses
7068 			}
7069 #endif
7070 	if      (QR_OP == StdQ) mDNSCoreReceiveQuery   (m, msg, end, srcaddr, srcport, dstaddr, dstport, ifid);
7071 	else if (QR_OP == StdR) mDNSCoreReceiveResponse(m, msg, end, srcaddr, srcport, dstaddr, dstport, ifid);
7072 	else if (QR_OP == UpdQ) mDNSCoreReceiveUpdate  (m, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID);
7073 	else if (QR_OP == UpdR) mDNSCoreReceiveUpdateR (m, msg, end,                                     InterfaceID);
7074 	else
7075 		{
7076 		LogMsg("Unknown DNS packet type %02X%02X from %#-15a:%-5d to %#-15a:%-5d length %d on %p (ignored)",
7077 			msg->h.flags.b[0], msg->h.flags.b[1], srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), end-(mDNSu8 *)pkt, InterfaceID);
7078 		if (mDNS_LoggingEnabled)
7079 			{
7080 			int i = 0;
7081 			while (i<end-(mDNSu8 *)pkt)
7082 				{
7083 				char buffer[128];
7084 				char *p = buffer + mDNS_snprintf(buffer, sizeof(buffer), "%04X", i);
7085 				do if (i<end-(mDNSu8 *)pkt) p += mDNS_snprintf(p, sizeof(buffer), " %02X", ((mDNSu8 *)pkt)[i]); while (++i & 15);
7086 				LogInfo("%s", buffer);
7087 				}
7088 			}
7089 		}
7090 	// Packet reception often causes a change to the task list:
7091 	// 1. Inbound queries can cause us to need to send responses
7092 	// 2. Conflicing response packets received from other hosts can cause us to need to send defensive responses
7093 	// 3. Other hosts announcing deletion of shared records can cause us to need to re-assert those records
7094 	// 4. Response packets that answer questions may cause our client to issue new questions
7095 	mDNS_Unlock(m);
7096 	}
7097 
7098 // ***************************************************************************
7099 #if COMPILER_LIKES_PRAGMA_MARK
7100 #pragma mark -
7101 #pragma mark - Searcher Functions
7102 #endif
7103 
7104 // Targets are considered the same if both queries are untargeted, or
7105 // if both are targeted to the same address+port
7106 // (If Target address is zero, TargetPort is undefined)
7107 #define SameQTarget(A,B) (((A)->Target.type == mDNSAddrType_None && (B)->Target.type == mDNSAddrType_None) || \
7108 	(mDNSSameAddress(&(A)->Target, &(B)->Target) && mDNSSameIPPort((A)->TargetPort, (B)->TargetPort)))
7109 
7110 // Note: We explicitly disallow making a public query be a duplicate of a private one. This is to avoid the
7111 // circular deadlock where a client does a query for something like "dns-sd -Q _dns-query-tls._tcp.company.com SRV"
7112 // and we have a key for company.com, so we try to locate the private query server for company.com, which necessarily entails
7113 // doing a standard DNS query for the _dns-query-tls._tcp SRV record for company.com. If we make the latter (public) query
7114 // a duplicate of the former (private) query, then it will block forever waiting for an answer that will never come.
7115 
7116 // If IsLLQ(Q) is true, it means the question is both:
7117 // (a) long-lived and
7118 // (b) being performed by a unicast DNS long-lived query (either full LLQ, or polling)
7119 // for multicast questions, we don't want to treat LongLived as anything special
7120 #define IsLLQ(Q) ((Q)->LongLived && !mDNSOpaque16IsZero((Q)->TargetQID))
7121 
7122 mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuestion *const question)
7123 	{
7124 	DNSQuestion *q;
7125 	// Note: A question can only be marked as a duplicate of one that occurs *earlier* in the list.
7126 	// This prevents circular references, where two questions are each marked as a duplicate of the other.
7127 	// Accordingly, we break out of the loop when we get to 'question', because there's no point searching
7128 	// further in the list.
7129 	for (q = m->Questions; q && q != question; q=q->next)		// Scan our list for another question
7130 		if (q->InterfaceID == question->InterfaceID &&			// with the same InterfaceID,
7131 			SameQTarget(q, question)                &&			// and same unicast/multicast target settings
7132 			q->qtype      == question->qtype        &&			// type,
7133 			q->qclass     == question->qclass       &&			// class,
7134 			IsLLQ(q)      == IsLLQ(question)        &&			// and long-lived status matches
7135 			(!q->AuthInfo || question->AuthInfo)    &&			// to avoid deadlock, don't make public query dup of a private one
7136 			q->qnamehash  == question->qnamehash    &&
7137 			SameDomainName(&q->qname, &question->qname))		// and name
7138 			return(q);
7139 	return(mDNSNULL);
7140 	}
7141 
7142 // This is called after a question is deleted, in case other identical questions were being suppressed as duplicates
7143 mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const question)
7144 	{
7145 	DNSQuestion *q;
7146 	for (q = m->Questions; q; q=q->next)		// Scan our list of questions
7147 		if (q->DuplicateOf == question)			// To see if any questions were referencing this as their duplicate
7148 			if ((q->DuplicateOf = FindDuplicateQuestion(m, q)) == mDNSNULL)
7149 				{
7150 				// If q used to be a duplicate, but now is not,
7151 				// then inherit the state from the question that's going away
7152 				q->LastQTime         = question->LastQTime;
7153 				q->ThisQInterval     = question->ThisQInterval;
7154 				q->ExpectUnicastResp = question->ExpectUnicastResp;
7155 				q->LastAnswerPktNum  = question->LastAnswerPktNum;
7156 				q->RecentAnswerPkts  = question->RecentAnswerPkts;
7157 				q->RequestUnicast    = question->RequestUnicast;
7158 				q->LastQTxTime       = question->LastQTxTime;
7159 				q->CNAMEReferrals    = question->CNAMEReferrals;
7160 				q->nta               = question->nta;
7161 				q->servAddr          = question->servAddr;
7162 				q->servPort          = question->servPort;
7163 				q->qDNSServer        = question->qDNSServer;
7164 				q->unansweredQueries = question->unansweredQueries;
7165 
7166 				q->TargetQID         = question->TargetQID;
7167 				q->LocalSocket       = question->LocalSocket;
7168 
7169 				q->state             = question->state;
7170 			//	q->tcp               = question->tcp;
7171 				q->ReqLease          = question->ReqLease;
7172 				q->expire            = question->expire;
7173 				q->ntries            = question->ntries;
7174 				q->id                = question->id;
7175 
7176 				question->LocalSocket = mDNSNULL;
7177 				question->nta        = mDNSNULL;	// If we've got a GetZoneData in progress, transfer it to the newly active question
7178 			//	question->tcp        = mDNSNULL;
7179 
7180 				if (q->LocalSocket)
7181 					debugf("UpdateQuestionDuplicates transferred LocalSocket pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
7182 
7183 				if (q->nta)
7184 					{
7185 					LogInfo("UpdateQuestionDuplicates transferred nta pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
7186 					q->nta->ZoneDataContext = q;
7187 					}
7188 
7189 				// Need to work out how to safely transfer this state too -- appropriate context pointers need to be updated or the code will crash
7190 				if (question->tcp) LogInfo("UpdateQuestionDuplicates did not transfer tcp pointer");
7191 
7192 				if (question->state == LLQ_Established)
7193 					{
7194 					LogInfo("UpdateQuestionDuplicates transferred LLQ state for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
7195 					question->state = 0;	// Must zero question->state, or mDNS_StopQuery_internal will clean up and cancel our LLQ from the server
7196 					}
7197 
7198 				SetNextQueryTime(m,q);
7199 				}
7200 	}
7201 
7202 // Look up a DNS Server, matching by name in split-dns configurations.
7203 mDNSexport DNSServer *GetServerForName(mDNS *m, const domainname *name)
7204     {
7205 	DNSServer *curmatch = mDNSNULL, *p;
7206 	int curmatchlen = -1, ncount = name ? CountLabels(name) : 0;
7207 
7208 	for (p = m->DNSServers; p; p = p->next)
7209 		{
7210 		int scount = CountLabels(&p->domain);
7211 		if (!(p->flags & DNSServer_FlagDelete) && ncount >= scount && scount > curmatchlen)
7212 			if (SameDomainName(SkipLeadingLabels(name, ncount - scount), &p->domain))
7213 				{ curmatch = p; curmatchlen = scount; }
7214 		}
7215 	return(curmatch);
7216 	}
7217 
7218 #define ValidQuestionTarget(Q) (((Q)->Target.type == mDNSAddrType_IPv4 || (Q)->Target.type == mDNSAddrType_IPv6) && \
7219 	(mDNSSameIPPort((Q)->TargetPort, UnicastDNSPort) || mDNSSameIPPort((Q)->TargetPort, MulticastDNSPort)))
7220 
7221 // Called in normal client context (lock not held)
7222 mDNSlocal void LLQNATCallback(mDNS *m, NATTraversalInfo *n)
7223 	{
7224 	DNSQuestion *q;
7225 	(void)n;    // Unused
7226 	mDNS_Lock(m);
7227 	LogInfo("LLQNATCallback external address:port %.4a:%u", &n->ExternalAddress, mDNSVal16(n->ExternalPort));
7228 	for (q = m->Questions; q; q=q->next)
7229 		if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID) && q->LongLived)
7230 			startLLQHandshake(m, q);	// If ExternalPort is zero, will do StartLLQPolling instead
7231 #if APPLE_OSX_mDNSResponder
7232 	UpdateAutoTunnelDomainStatuses(m);
7233 #endif
7234 	mDNS_Unlock(m);
7235 	}
7236 
7237 mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const question)
7238 	{
7239 	if (question->Target.type && !ValidQuestionTarget(question))
7240 		{
7241 		LogMsg("Warning! Target.type = %ld port = %u (Client forgot to initialize before calling mDNS_StartQuery?)",
7242 			question->Target.type, mDNSVal16(question->TargetPort));
7243 		question->Target.type = mDNSAddrType_None;
7244 		}
7245 
7246 	if (!question->Target.type) question->TargetPort = zeroIPPort;	// If question->Target specified clear TargetPort
7247 
7248 	question->TargetQID =
7249 #ifndef UNICAST_DISABLED
7250 		(question->Target.type || (question->InterfaceID == mDNSInterface_Unicast) ||
7251 		(question->InterfaceID != mDNSInterface_LocalOnly && !question->ForceMCast && !IsLocalDomain(&question->qname)))
7252 		? mDNS_NewMessageID(m) :
7253 #endif // UNICAST_DISABLED
7254 		zeroID;
7255 
7256 	debugf("mDNS_StartQuery: %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
7257 
7258 	if (m->rrcache_size == 0)	// Can't do queries if we have no cache space allocated
7259 		return(mStatus_NoCache);
7260 	else
7261 		{
7262 		int i;
7263 		DNSQuestion **q;
7264 
7265 		if (!ValidateDomainName(&question->qname))
7266 			{
7267 			LogMsg("Attempt to start query with invalid qname %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
7268 			return(mStatus_Invalid);
7269 			}
7270 
7271 		// Note: It important that new questions are appended at the *end* of the list, not prepended at the start
7272 		q = &m->Questions;
7273 		if (question->InterfaceID == mDNSInterface_LocalOnly) q = &m->LocalOnlyQuestions;
7274 		while (*q && *q != question) q=&(*q)->next;
7275 
7276 		if (*q)
7277 			{
7278 			LogMsg("Error! Tried to add a question %##s (%s) %p that's already in the active list",
7279 				question->qname.c, DNSTypeName(question->qtype), question);
7280 			return(mStatus_AlreadyRegistered);
7281 			}
7282 
7283 		*q = question;
7284 
7285 		// If this question is referencing a specific interface, verify it exists
7286 		if (question->InterfaceID && question->InterfaceID != mDNSInterface_LocalOnly && question->InterfaceID != mDNSInterface_Unicast)
7287 			{
7288 			NetworkInterfaceInfo *intf = FirstInterfaceForID(m, question->InterfaceID);
7289 			if (!intf)
7290 				LogMsg("Note: InterfaceID %p for question %##s (%s) not currently found in active interface list",
7291 					question->InterfaceID, question->qname.c, DNSTypeName(question->qtype));
7292 			}
7293 
7294 		// Note: In the case where we already have the answer to this question in our cache, that may be all the client
7295 		// wanted, and they may immediately cancel their question. In this case, sending an actual query on the wire would
7296 		// be a waste. For that reason, we schedule our first query to go out in half a second (InitialQuestionInterval).
7297 		// If AnswerNewQuestion() finds that we have *no* relevant answers currently in our cache, then it will accelerate
7298 		// that to go out immediately.
7299 		question->next              = mDNSNULL;
7300 		question->qnamehash         = DomainNameHashValue(&question->qname);	// MUST do this before FindDuplicateQuestion()
7301 		question->DelayAnswering    = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, HashSlot(&question->qname));
7302 		question->LastQTime         = m->timenow;
7303 		question->ThisQInterval     = InitialQuestionInterval;					// MUST be > zero for an active question
7304 		question->ExpectUnicastResp = 0;
7305 		question->LastAnswerPktNum  = m->PktNum;
7306 		question->RecentAnswerPkts  = 0;
7307 		question->CurrentAnswers    = 0;
7308 		question->LargeAnswers      = 0;
7309 		question->UniqueAnswers     = 0;
7310 		question->FlappingInterface1 = mDNSNULL;
7311 		question->FlappingInterface2 = mDNSNULL;
7312 		question->AuthInfo          = GetAuthInfoForQuestion(m, question);		// Must do this before calling FindDuplicateQuestion()
7313 		question->DuplicateOf       = FindDuplicateQuestion(m, question);
7314 		question->NextInDQList      = mDNSNULL;
7315 		question->SendQNow          = mDNSNULL;
7316 		question->SendOnAll         = mDNSfalse;
7317 		question->RequestUnicast    = 0;
7318 		question->LastQTxTime       = m->timenow;
7319 		question->CNAMEReferrals    = 0;
7320 
7321 		// We'll create our question->LocalSocket on demand, if needed.
7322 		// We won't need one for duplicate questions, or from questions answered immediately out of the cache.
7323 		// We also don't need one for LLQs because (when we're using NAT) we want them all to share a single
7324 		// NAT mapping for receiving inbound add/remove events.
7325 		question->LocalSocket       = mDNSNULL;
7326 		question->qDNSServer        = mDNSNULL;
7327 		question->unansweredQueries = 0;
7328 		question->nta               = mDNSNULL;
7329 		question->servAddr          = zeroAddr;
7330 		question->servPort          = zeroIPPort;
7331 		question->tcp               = mDNSNULL;
7332 		question->NoAnswer          = NoAnswer_Normal;
7333 
7334 		question->state             = LLQ_InitialRequest;
7335 		question->ReqLease          = 0;
7336 		question->expire            = 0;
7337 		question->ntries            = 0;
7338 		question->id                = zeroOpaque64;
7339 
7340 		if (question->DuplicateOf) question->AuthInfo = question->DuplicateOf->AuthInfo;
7341 
7342 		for (i=0; i<DupSuppressInfoSize; i++)
7343 			question->DupSuppress[i].InterfaceID = mDNSNULL;
7344 
7345 		debugf("mDNS_StartQuery: Question %##s (%s) Interface %p Now %d Send in %d Answer in %d (%p) %s (%p)",
7346 			question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, m->timenow,
7347 			question->LastQTime + question->ThisQInterval - m->timenow,
7348 			question->DelayAnswering ? question->DelayAnswering - m->timenow : 0,
7349 			question, question->DuplicateOf ? "duplicate of" : "not duplicate", question->DuplicateOf);
7350 
7351 		if (question->InterfaceID == mDNSInterface_LocalOnly)
7352 			{
7353 			if (!m->NewLocalOnlyQuestions) m->NewLocalOnlyQuestions = question;
7354 			}
7355 		else
7356 			{
7357 			if (!m->NewQuestions) m->NewQuestions = question;
7358 
7359 			// If the question's id is non-zero, then it's Wide Area
7360 			// MUST NOT do this Wide Area setup until near the end of
7361 			// mDNS_StartQuery_internal -- this code may itself issue queries (e.g. SOA,
7362 			// NS, etc.) and if we haven't finished setting up our own question and setting
7363 			// m->NewQuestions if necessary then we could end up recursively re-entering
7364 			// this routine with the question list data structures in an inconsistent state.
7365 			if (!mDNSOpaque16IsZero(question->TargetQID))
7366 				{
7367 				question->qDNSServer = GetServerForName(m, &question->qname);
7368 				ActivateUnicastQuery(m, question, mDNSfalse);
7369 
7370 				// If long-lived query, and we don't have our NAT mapping active, start it now
7371 				if (question->LongLived && !m->LLQNAT.clientContext)
7372 					{
7373 					m->LLQNAT.Protocol       = NATOp_MapUDP;
7374 					m->LLQNAT.IntPort        = m->UnicastPort4;
7375 					m->LLQNAT.RequestedPort  = m->UnicastPort4;
7376 					m->LLQNAT.clientCallback = LLQNATCallback;
7377 					m->LLQNAT.clientContext  = (void*)1; // Means LLQ NAT Traversal is active
7378 					mDNS_StartNATOperation_internal(m, &m->LLQNAT);
7379 					}
7380 
7381 #if APPLE_OSX_mDNSResponder
7382 				if (question->LongLived)
7383 					UpdateAutoTunnelDomainStatuses(m);
7384 #endif
7385 
7386 				}
7387 			SetNextQueryTime(m,question);
7388 			}
7389 
7390 		return(mStatus_NoError);
7391 		}
7392 	}
7393 
7394 // CancelGetZoneData is an internal routine (i.e. must be called with the lock already held)
7395 mDNSexport void CancelGetZoneData(mDNS *const m, ZoneData *nta)
7396 	{
7397 	debugf("CancelGetZoneData %##s (%s)", nta->question.qname.c, DNSTypeName(nta->question.qtype));
7398 	mDNS_StopQuery_internal(m, &nta->question);
7399 	mDNSPlatformMemFree(nta);
7400 	}
7401 
7402 mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question)
7403 	{
7404 	const mDNSu32 slot = HashSlot(&question->qname);
7405 	CacheGroup *cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname);
7406 	CacheRecord *rr;
7407 	DNSQuestion **qp = &m->Questions;
7408 
7409 	//LogInfo("mDNS_StopQuery_internal %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
7410 
7411 	if (question->InterfaceID == mDNSInterface_LocalOnly) qp = &m->LocalOnlyQuestions;
7412 	while (*qp && *qp != question) qp=&(*qp)->next;
7413 	if (*qp) *qp = (*qp)->next;
7414 	else
7415 		{
7416 #if !ForceAlerts
7417 		if (question->ThisQInterval >= 0)	// Only log error message if the query was supposed to be active
7418 #endif
7419 			LogMsg("mDNS_StopQuery_internal: Question %##s (%s) not found in active list",
7420 				question->qname.c, DNSTypeName(question->qtype));
7421 #if ForceAlerts
7422 		*(long*)0 = 0;
7423 #endif
7424 		return(mStatus_BadReferenceErr);
7425 		}
7426 
7427 	// Take care to cut question from list *before* calling UpdateQuestionDuplicates
7428 	UpdateQuestionDuplicates(m, question);
7429 	// But don't trash ThisQInterval until afterwards.
7430 	question->ThisQInterval = -1;
7431 
7432 	// If there are any cache records referencing this as their active question, then see if there is any
7433 	// other question that is also referencing them, else their CRActiveQuestion needs to get set to NULL.
7434 	for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
7435 		{
7436 		if (rr->CRActiveQuestion == question)
7437 			{
7438 			DNSQuestion *q;
7439 			for (q = m->Questions; q; q=q->next)		// Scan our list of questions
7440 				if (ActiveQuestion(q) && ResourceRecordAnswersQuestion(&rr->resrec, q))
7441 					break;
7442 			debugf("mDNS_StopQuery_internal: Updating CRActiveQuestion to %p for cache record %s", q, CRDisplayString(m,rr));
7443 			rr->CRActiveQuestion = q;		// Question used to be active; new value may or may not be null
7444 			if (!q) m->rrcache_active--;	// If no longer active, decrement rrcache_active count
7445 			}
7446 		}
7447 
7448 	// If we just deleted the question that CacheRecordAdd() or CacheRecordRmv() is about to look at,
7449 	// bump its pointer forward one question.
7450 	if (m->CurrentQuestion == question)
7451 		{
7452 		debugf("mDNS_StopQuery_internal: Just deleted the currently active question: %##s (%s)",
7453 			question->qname.c, DNSTypeName(question->qtype));
7454 		m->CurrentQuestion = question->next;
7455 		}
7456 
7457 	if (m->NewQuestions == question)
7458 		{
7459 		debugf("mDNS_StopQuery_internal: Just deleted a new question that wasn't even answered yet: %##s (%s)",
7460 			question->qname.c, DNSTypeName(question->qtype));
7461 		m->NewQuestions = question->next;
7462 		}
7463 
7464 	if (m->NewLocalOnlyQuestions == question) m->NewLocalOnlyQuestions = question->next;
7465 
7466 	// Take care not to trash question->next until *after* we've updated m->CurrentQuestion and m->NewQuestions
7467 	question->next = mDNSNULL;
7468 
7469 	// LogMsg("mDNS_StopQuery_internal: Question %##s (%s) removed", question->qname.c, DNSTypeName(question->qtype));
7470 
7471 	// And finally, cancel any associated GetZoneData operation that's still running.
7472 	// Must not do this until last, because there's a good chance the GetZoneData question is the next in the list,
7473 	// so if we delete it earlier in this routine, we could find that our "question->next" pointer above is already
7474 	// invalid before we even use it. By making sure that we update m->CurrentQuestion and m->NewQuestions if necessary
7475 	// *first*, then they're all ready to be updated a second time if necessary when we cancel our GetZoneData query.
7476 	if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
7477 	if (question->tcp) { DisposeTCPConn(question->tcp); question->tcp = mDNSNULL; }
7478 	if (question->LocalSocket) { mDNSPlatformUDPClose(question->LocalSocket); question->LocalSocket = mDNSNULL; }
7479 	if (!mDNSOpaque16IsZero(question->TargetQID) && question->LongLived)
7480 		{
7481 		// Scan our list to see if any more wide-area LLQs remain. If not, stop our NAT Traversal.
7482 		DNSQuestion *q;
7483 		for (q = m->Questions; q; q=q->next)
7484 			if (!mDNSOpaque16IsZero(q->TargetQID) && q->LongLived) break;
7485 		if (!q)
7486 			{
7487 			if (!m->LLQNAT.clientContext)		// Should never happen, but just in case...
7488 				LogMsg("mDNS_StopQuery ERROR LLQNAT.clientContext NULL");
7489 			else
7490 				{
7491 				LogInfo("Stopping LLQNAT");
7492 				mDNS_StopNATOperation_internal(m, &m->LLQNAT);
7493 				m->LLQNAT.clientContext = mDNSNULL; // Means LLQ NAT Traversal not running
7494 				}
7495 			}
7496 
7497 		// If necessary, tell server it can delete this LLQ state
7498 		if (question->state == LLQ_Established)
7499 			{
7500 			question->ReqLease = 0;
7501 			sendLLQRefresh(m, question);
7502 			// If we need need to make a TCP connection to cancel the LLQ, that's going to take a little while.
7503 			// We clear the tcp->question backpointer so that when the TCP connection completes, it doesn't
7504 			// crash trying to access our cancelled question, but we don't cancel the TCP operation itself --
7505 			// we let that run out its natural course and complete asynchronously.
7506 			if (question->tcp)
7507 				{
7508 				question->tcp->question = mDNSNULL;
7509 				question->tcp           = mDNSNULL;
7510 				}
7511 			}
7512 #if APPLE_OSX_mDNSResponder
7513 		UpdateAutoTunnelDomainStatuses(m);
7514 #endif
7515 		}
7516 
7517 	return(mStatus_NoError);
7518 	}
7519 
7520 mDNSexport mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question)
7521 	{
7522 	mStatus status;
7523 	mDNS_Lock(m);
7524 	status = mDNS_StartQuery_internal(m, question);
7525 	mDNS_Unlock(m);
7526 	return(status);
7527 	}
7528 
7529 mDNSexport mStatus mDNS_StopQuery(mDNS *const m, DNSQuestion *const question)
7530 	{
7531 	mStatus status;
7532 	mDNS_Lock(m);
7533 	status = mDNS_StopQuery_internal(m, question);
7534 	mDNS_Unlock(m);
7535 	return(status);
7536 	}
7537 
7538 // Note that mDNS_StopQueryWithRemoves() does not currently implement the full generality of the other APIs
7539 // Specifically, question callbacks invoked as a result of this call cannot themselves make API calls.
7540 // We invoke the callback without using mDNS_DropLockBeforeCallback/mDNS_ReclaimLockAfterCallback
7541 // specifically to catch and report if the client callback does try to make API calls
7542 mDNSexport mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const question)
7543 	{
7544 	mStatus status;
7545 	DNSQuestion *qq;
7546 	mDNS_Lock(m);
7547 
7548 	// Check if question is new -- don't want to give remove events for a question we haven't even answered yet
7549 	for (qq = m->NewQuestions; qq; qq=qq->next) if (qq == question) break;
7550 
7551 	status = mDNS_StopQuery_internal(m, question);
7552 	if (status == mStatus_NoError && !qq)
7553 		{
7554 		const CacheRecord *rr;
7555 		const mDNSu32 slot = HashSlot(&question->qname);
7556 		CacheGroup *const cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname);
7557 		LogInfo("Generating terminal removes for %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
7558 		for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
7559 			if (rr->resrec.RecordType != kDNSRecordTypePacketNegative && SameNameRecordAnswersQuestion(&rr->resrec, question))
7560 				{
7561 				// Don't use mDNS_DropLockBeforeCallback() here, since we don't allow API calls
7562 				if (question->QuestionCallback)
7563 					question->QuestionCallback(m, question, &rr->resrec, mDNSfalse);
7564 				}
7565 		}
7566 	mDNS_Unlock(m);
7567 	return(status);
7568 	}
7569 
7570 mDNSexport mStatus mDNS_Reconfirm(mDNS *const m, CacheRecord *const cr)
7571 	{
7572 	mStatus status;
7573 	mDNS_Lock(m);
7574 	status = mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
7575 	if (status == mStatus_NoError) ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, 0);
7576 	mDNS_Unlock(m);
7577 	return(status);
7578 	}
7579 
7580 mDNSexport mStatus mDNS_ReconfirmByValue(mDNS *const m, ResourceRecord *const rr)
7581 	{
7582 	mStatus status = mStatus_BadReferenceErr;
7583 	CacheRecord *cr;
7584 	mDNS_Lock(m);
7585 	cr = FindIdenticalRecordInCache(m, rr);
7586 	debugf("mDNS_ReconfirmByValue: %p %s", cr, RRDisplayString(m, rr));
7587 	if (cr) status = mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
7588 	if (status == mStatus_NoError) ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, 0);
7589 	mDNS_Unlock(m);
7590 	return(status);
7591 	}
7592 
7593 mDNSlocal mStatus mDNS_StartBrowse_internal(mDNS *const m, DNSQuestion *const question,
7594 	const domainname *const srv, const domainname *const domain,
7595 	const mDNSInterfaceID InterfaceID, mDNSBool ForceMCast, mDNSQuestionCallback *Callback, void *Context)
7596 	{
7597 	question->InterfaceID      = InterfaceID;
7598 	question->Target           = zeroAddr;
7599 	question->qtype            = kDNSType_PTR;
7600 	question->qclass           = kDNSClass_IN;
7601 	question->LongLived        = mDNSfalse;
7602 	question->ExpectUnique     = mDNSfalse;
7603 	question->ForceMCast       = ForceMCast;
7604 	question->ReturnIntermed   = mDNSfalse;
7605 	question->QuestionCallback = Callback;
7606 	question->QuestionContext  = Context;
7607 	if (!ConstructServiceName(&question->qname, mDNSNULL, srv, domain)) return(mStatus_BadParamErr);
7608 
7609 #ifndef UNICAST_DISABLED
7610     if (Question_uDNS(question))
7611 		{
7612 		question->LongLived     = mDNStrue;
7613 		question->ThisQInterval = InitialQuestionInterval;
7614 		question->LastQTime     = m->timenow - question->ThisQInterval;
7615 		}
7616 #endif // UNICAST_DISABLED
7617 	return(mDNS_StartQuery_internal(m, question));
7618 	}
7619 
7620 mDNSexport mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
7621 	const domainname *const srv, const domainname *const domain,
7622 	const mDNSInterfaceID InterfaceID, mDNSBool ForceMCast, mDNSQuestionCallback *Callback, void *Context)
7623 	{
7624 	mStatus status;
7625 	mDNS_Lock(m);
7626 	status = mDNS_StartBrowse_internal(m, question, srv, domain, InterfaceID, ForceMCast, Callback, Context);
7627 	mDNS_Unlock(m);
7628 	return(status);
7629 	}
7630 
7631 mDNSlocal mDNSBool MachineHasActiveIPv6(mDNS *const m)
7632 	{
7633 	NetworkInterfaceInfo *intf;
7634 	for (intf = m->HostInterfaces; intf; intf = intf->next)
7635 	if (intf->ip.type == mDNSAddrType_IPv6) return(mDNStrue);
7636 	return(mDNSfalse);
7637 	}
7638 
7639 mDNSlocal void FoundServiceInfoSRV(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
7640 	{
7641 	ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
7642 	mDNSBool PortChanged = !mDNSSameIPPort(query->info->port, answer->rdata->u.srv.port);
7643 	if (!AddRecord) return;
7644 	if (answer->rrtype != kDNSType_SRV) return;
7645 
7646 	query->info->port = answer->rdata->u.srv.port;
7647 
7648 	// If this is our first answer, then set the GotSRV flag and start the address query
7649 	if (!query->GotSRV)
7650 		{
7651 		query->GotSRV             = mDNStrue;
7652 		query->qAv4.InterfaceID   = answer->InterfaceID;
7653 		AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target);
7654 		query->qAv6.InterfaceID   = answer->InterfaceID;
7655 		AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target);
7656 		mDNS_StartQuery(m, &query->qAv4);
7657 		// Only do the AAAA query if this machine actually has IPv6 active
7658 		if (MachineHasActiveIPv6(m)) mDNS_StartQuery(m, &query->qAv6);
7659 		}
7660 	// If this is not our first answer, only re-issue the address query if the target host name has changed
7661 	else if ((query->qAv4.InterfaceID != query->qSRV.InterfaceID && query->qAv4.InterfaceID != answer->InterfaceID) ||
7662 		!SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target))
7663 		{
7664 		mDNS_StopQuery(m, &query->qAv4);
7665 		if (query->qAv6.ThisQInterval >= 0) mDNS_StopQuery(m, &query->qAv6);
7666 		if (SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target) && !PortChanged)
7667 			{
7668 			// If we get here, it means:
7669 			// 1. This is not our first SRV answer
7670 			// 2. The interface ID is different, but the target host and port are the same
7671 			// This implies that we're seeing the exact same SRV record on more than one interface, so we should
7672 			// make our address queries at least as broad as the original SRV query so that we catch all the answers.
7673 			query->qAv4.InterfaceID = query->qSRV.InterfaceID;	// Will be mDNSInterface_Any, or a specific interface
7674 			query->qAv6.InterfaceID = query->qSRV.InterfaceID;
7675 			}
7676 		else
7677 			{
7678 			query->qAv4.InterfaceID   = answer->InterfaceID;
7679 			AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target);
7680 			query->qAv6.InterfaceID   = answer->InterfaceID;
7681 			AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target);
7682 			}
7683 		debugf("FoundServiceInfoSRV: Restarting address queries for %##s (%s)", query->qAv4.qname.c, DNSTypeName(query->qAv4.qtype));
7684 		mDNS_StartQuery(m, &query->qAv4);
7685 		// Only do the AAAA query if this machine actually has IPv6 active
7686 		if (MachineHasActiveIPv6(m)) mDNS_StartQuery(m, &query->qAv6);
7687 		}
7688 	else if (query->ServiceInfoQueryCallback && query->GotADD && query->GotTXT && PortChanged)
7689 		{
7690 		if (++query->Answers >= 100)
7691 			debugf("**** WARNING **** Have given %lu answers for %##s (SRV) %##s %u",
7692 				query->Answers, query->qSRV.qname.c, answer->rdata->u.srv.target.c,
7693 				mDNSVal16(answer->rdata->u.srv.port));
7694 		query->ServiceInfoQueryCallback(m, query);
7695 		}
7696 	// CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
7697 	// callback function is allowed to do anything, including deleting this query and freeing its memory.
7698 	}
7699 
7700 mDNSlocal void FoundServiceInfoTXT(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
7701 	{
7702 	ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
7703 	if (!AddRecord) return;
7704 	if (answer->rrtype != kDNSType_TXT) return;
7705 	if (answer->rdlength > sizeof(query->info->TXTinfo)) return;
7706 
7707 	query->GotTXT       = mDNStrue;
7708 	query->info->TXTlen = answer->rdlength;
7709 	query->info->TXTinfo[0] = 0;		// In case answer->rdlength is zero
7710 	mDNSPlatformMemCopy(query->info->TXTinfo, answer->rdata->u.txt.c, answer->rdlength);
7711 
7712 	verbosedebugf("FoundServiceInfoTXT: %##s GotADD=%d", query->info->name.c, query->GotADD);
7713 
7714 	// CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
7715 	// callback function is allowed to do anything, including deleting this query and freeing its memory.
7716 	if (query->ServiceInfoQueryCallback && query->GotADD)
7717 		{
7718 		if (++query->Answers >= 100)
7719 			debugf("**** WARNING **** have given %lu answers for %##s (TXT) %#s...",
7720 				query->Answers, query->qSRV.qname.c, answer->rdata->u.txt.c);
7721 		query->ServiceInfoQueryCallback(m, query);
7722 		}
7723 	}
7724 
7725 mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
7726 	{
7727 	ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
7728 	//LogInfo("FoundServiceInfo %d %s", AddRecord, RRDisplayString(m, answer));
7729 	if (!AddRecord) return;
7730 
7731 	if (answer->rrtype == kDNSType_A)
7732 		{
7733 		query->info->ip.type = mDNSAddrType_IPv4;
7734 		query->info->ip.ip.v4 = answer->rdata->u.ipv4;
7735 		}
7736 	else if (answer->rrtype == kDNSType_AAAA)
7737 		{
7738 		query->info->ip.type = mDNSAddrType_IPv6;
7739 		query->info->ip.ip.v6 = answer->rdata->u.ipv6;
7740 		}
7741 	else
7742 		{
7743 		debugf("FoundServiceInfo: answer %##s type %d (%s) unexpected", answer->name->c, answer->rrtype, DNSTypeName(answer->rrtype));
7744 		return;
7745 		}
7746 
7747 	query->GotADD = mDNStrue;
7748 	query->info->InterfaceID = answer->InterfaceID;
7749 
7750 	verbosedebugf("FoundServiceInfo v%ld: %##s GotTXT=%d", query->info->ip.type, query->info->name.c, query->GotTXT);
7751 
7752 	// CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
7753 	// callback function is allowed to do anything, including deleting this query and freeing its memory.
7754 	if (query->ServiceInfoQueryCallback && query->GotTXT)
7755 		{
7756 		if (++query->Answers >= 100)
7757 			debugf(answer->rrtype == kDNSType_A ?
7758 				"**** WARNING **** have given %lu answers for %##s (A) %.4a" :
7759 				"**** WARNING **** have given %lu answers for %##s (AAAA) %.16a",
7760 				query->Answers, query->qSRV.qname.c, &answer->rdata->u.data);
7761 		query->ServiceInfoQueryCallback(m, query);
7762 		}
7763 	}
7764 
7765 // On entry, the client must have set the name and InterfaceID fields of the ServiceInfo structure
7766 // If the query is not interface-specific, then InterfaceID may be zero
7767 // Each time the Callback is invoked, the remainder of the fields will have been filled in
7768 // In addition, InterfaceID will be updated to give the interface identifier corresponding to that response
7769 mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
7770 	ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context)
7771 	{
7772 	mStatus status;
7773 	mDNS_Lock(m);
7774 
7775 	query->qSRV.ThisQInterval       = -1;		// So that mDNS_StopResolveService() knows whether to cancel this question
7776 	query->qSRV.InterfaceID         = info->InterfaceID;
7777 	query->qSRV.Target              = zeroAddr;
7778 	AssignDomainName(&query->qSRV.qname, &info->name);
7779 	query->qSRV.qtype               = kDNSType_SRV;
7780 	query->qSRV.qclass              = kDNSClass_IN;
7781 	query->qSRV.LongLived           = mDNSfalse;
7782 	query->qSRV.ExpectUnique        = mDNStrue;
7783 	query->qSRV.ForceMCast          = mDNSfalse;
7784 	query->qSRV.ReturnIntermed      = mDNSfalse;
7785 	query->qSRV.QuestionCallback    = FoundServiceInfoSRV;
7786 	query->qSRV.QuestionContext     = query;
7787 
7788 	query->qTXT.ThisQInterval       = -1;		// So that mDNS_StopResolveService() knows whether to cancel this question
7789 	query->qTXT.InterfaceID         = info->InterfaceID;
7790 	query->qTXT.Target              = zeroAddr;
7791 	AssignDomainName(&query->qTXT.qname, &info->name);
7792 	query->qTXT.qtype               = kDNSType_TXT;
7793 	query->qTXT.qclass              = kDNSClass_IN;
7794 	query->qTXT.LongLived           = mDNSfalse;
7795 	query->qTXT.ExpectUnique        = mDNStrue;
7796 	query->qTXT.ForceMCast          = mDNSfalse;
7797 	query->qTXT.ReturnIntermed      = mDNSfalse;
7798 	query->qTXT.QuestionCallback    = FoundServiceInfoTXT;
7799 	query->qTXT.QuestionContext     = query;
7800 
7801 	query->qAv4.ThisQInterval       = -1;		// So that mDNS_StopResolveService() knows whether to cancel this question
7802 	query->qAv4.InterfaceID         = info->InterfaceID;
7803 	query->qAv4.Target              = zeroAddr;
7804 	query->qAv4.qname.c[0]          = 0;
7805 	query->qAv4.qtype               = kDNSType_A;
7806 	query->qAv4.qclass              = kDNSClass_IN;
7807 	query->qAv4.LongLived           = mDNSfalse;
7808 	query->qAv4.ExpectUnique        = mDNStrue;
7809 	query->qAv4.ForceMCast          = mDNSfalse;
7810 	query->qAv4.ReturnIntermed      = mDNSfalse;
7811 	query->qAv4.QuestionCallback    = FoundServiceInfo;
7812 	query->qAv4.QuestionContext     = query;
7813 
7814 	query->qAv6.ThisQInterval       = -1;		// So that mDNS_StopResolveService() knows whether to cancel this question
7815 	query->qAv6.InterfaceID         = info->InterfaceID;
7816 	query->qAv6.Target              = zeroAddr;
7817 	query->qAv6.qname.c[0]          = 0;
7818 	query->qAv6.qtype               = kDNSType_AAAA;
7819 	query->qAv6.qclass              = kDNSClass_IN;
7820 	query->qAv6.LongLived           = mDNSfalse;
7821 	query->qAv6.ExpectUnique        = mDNStrue;
7822 	query->qAv6.ForceMCast          = mDNSfalse;
7823 	query->qAv6.ReturnIntermed      = mDNSfalse;
7824 	query->qAv6.QuestionCallback    = FoundServiceInfo;
7825 	query->qAv6.QuestionContext     = query;
7826 
7827 	query->GotSRV                   = mDNSfalse;
7828 	query->GotTXT                   = mDNSfalse;
7829 	query->GotADD                   = mDNSfalse;
7830 	query->Answers                  = 0;
7831 
7832 	query->info                     = info;
7833 	query->ServiceInfoQueryCallback = Callback;
7834 	query->ServiceInfoQueryContext  = Context;
7835 
7836 //	info->name      = Must already be set up by client
7837 //	info->interface = Must already be set up by client
7838 	info->ip        = zeroAddr;
7839 	info->port      = zeroIPPort;
7840 	info->TXTlen    = 0;
7841 
7842 	// We use mDNS_StartQuery_internal here because we're already holding the lock
7843 	status = mDNS_StartQuery_internal(m, &query->qSRV);
7844 	if (status == mStatus_NoError) status = mDNS_StartQuery_internal(m, &query->qTXT);
7845 	if (status != mStatus_NoError) mDNS_StopResolveService(m, query);
7846 
7847 	mDNS_Unlock(m);
7848 	return(status);
7849 	}
7850 
7851 mDNSexport void    mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *q)
7852 	{
7853 	mDNS_Lock(m);
7854 	// We use mDNS_StopQuery_internal here because we're already holding the lock
7855 	if (q->qSRV.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qSRV);
7856 	if (q->qTXT.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qTXT);
7857 	if (q->qAv4.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qAv4);
7858 	if (q->qAv6.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qAv6);
7859 	mDNS_Unlock(m);
7860 	}
7861 
7862 mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom,
7863 	const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context)
7864 	{
7865 	question->InterfaceID      = InterfaceID;
7866 	question->Target           = zeroAddr;
7867 	question->qtype            = kDNSType_PTR;
7868 	question->qclass           = kDNSClass_IN;
7869 	question->LongLived        = mDNSfalse;
7870 	question->ExpectUnique     = mDNSfalse;
7871 	question->ForceMCast       = mDNSfalse;
7872 	question->ReturnIntermed   = mDNSfalse;
7873 	question->QuestionCallback = Callback;
7874 	question->QuestionContext  = Context;
7875 	if (DomainType > mDNS_DomainTypeMax) return(mStatus_BadParamErr);
7876 	if (!MakeDomainNameFromDNSNameString(&question->qname, mDNS_DomainTypeNames[DomainType])) return(mStatus_BadParamErr);
7877 	if (!dom) dom = &localdomain;
7878 	if (!AppendDomainName(&question->qname, dom)) return(mStatus_BadParamErr);
7879 	return(mDNS_StartQuery(m, question));
7880 	}
7881 
7882 // ***************************************************************************
7883 #if COMPILER_LIKES_PRAGMA_MARK
7884 #pragma mark -
7885 #pragma mark - Responder Functions
7886 #endif
7887 
7888 mDNSexport mStatus mDNS_Register(mDNS *const m, AuthRecord *const rr)
7889 	{
7890 	mStatus status;
7891 	mDNS_Lock(m);
7892 	status = mDNS_Register_internal(m, rr);
7893 	mDNS_Unlock(m);
7894 	return(status);
7895 	}
7896 
7897 mDNSexport mStatus mDNS_Update(mDNS *const m, AuthRecord *const rr, mDNSu32 newttl,
7898 	const mDNSu16 newrdlength, RData *const newrdata, mDNSRecordUpdateCallback *Callback)
7899 	{
7900 #ifndef UNICAST_DISABLED
7901 	mDNSBool unicast = !(rr->resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(rr->resrec.name));
7902 #else
7903 	mDNSBool unicast = mDNSfalse;
7904 #endif
7905 
7906 	if (!ValidateRData(rr->resrec.rrtype, newrdlength, newrdata))
7907 		{
7908 		LogMsg("Attempt to update record with invalid rdata: %s", GetRRDisplayString_rdb(&rr->resrec, &newrdata->u, m->MsgBuffer));
7909 		return(mStatus_Invalid);
7910 		}
7911 
7912 	mDNS_Lock(m);
7913 
7914 	// If TTL is unspecified, leave TTL unchanged
7915 	if (newttl == 0) newttl = rr->resrec.rroriginalttl;
7916 
7917 	// If we already have an update queued up which has not gone through yet,
7918 	// give the client a chance to free that memory
7919 	if (!unicast && rr->NewRData)
7920 		{
7921 		RData *n = rr->NewRData;
7922 		rr->NewRData = mDNSNULL;			// Clear the NewRData pointer ...
7923 		if (rr->UpdateCallback)
7924 			rr->UpdateCallback(m, rr, n);	// ...and let the client free this memory, if necessary
7925 		}
7926 
7927 	rr->NewRData             = newrdata;
7928 	rr->newrdlength          = newrdlength;
7929 	rr->UpdateCallback       = Callback;
7930 
7931 	if (unicast) { mStatus status = uDNS_UpdateRecord(m, rr); mDNS_Unlock(m); return(status); }
7932 
7933 	if (rr->resrec.rroriginalttl == newttl &&
7934 		rr->resrec.rdlength == newrdlength && mDNSPlatformMemSame(rr->resrec.rdata->u.data, newrdata->u.data, newrdlength))
7935 		CompleteRDataUpdate(m, rr);
7936 	else
7937 		{
7938 		domainlabel name;
7939 		domainname type, domain;
7940 		DeconstructServiceName(rr->resrec.name, &name, &type, &domain);
7941 		rr->AnnounceCount = InitialAnnounceCount;
7942 		// iChat often does suprious record updates where no data has changed. For the _presence service type, using
7943 		// name/value pairs, the mDNSPlatformMemSame() check above catches this and correctly suppresses the wasteful
7944 		// update. For the _ichat service type, the XML encoding introduces spurious noise differences into the data
7945 		// even though there's no actual semantic change, so the mDNSPlatformMemSame() check doesn't help us.
7946 		// To work around this, we simply unilaterally limit all legacy _ichat-type updates to a single announcement.
7947 		if (SameDomainLabel(type.c, (mDNSu8*)"\x6_ichat")) rr->AnnounceCount = 1;
7948 		InitializeLastAPTime(m, rr);
7949 		while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
7950 		if (!rr->UpdateBlocked && rr->UpdateCredits) rr->UpdateCredits--;
7951 		if (!rr->NextUpdateCredit) rr->NextUpdateCredit = NonZeroTime(m->timenow + kUpdateCreditRefreshInterval);
7952 		if (rr->AnnounceCount > rr->UpdateCredits + 1) rr->AnnounceCount = (mDNSu8)(rr->UpdateCredits + 1);
7953 		if (rr->UpdateCredits <= 5)
7954 			{
7955 			mDNSu32 delay = 6 - rr->UpdateCredits;		// Delay 1 second, then 2, then 3, etc. up to 6 seconds maximum
7956 			if (!rr->UpdateBlocked) rr->UpdateBlocked = NonZeroTime(m->timenow + (mDNSs32)delay * mDNSPlatformOneSecond);
7957 			rr->ThisAPInterval *= 4;
7958 			rr->LastAPTime = rr->UpdateBlocked - rr->ThisAPInterval;
7959 			LogMsg("Excessive update rate for %##s; delaying announcement by %ld second%s",
7960 				rr->resrec.name->c, delay, delay > 1 ? "s" : "");
7961 			}
7962 		rr->resrec.rroriginalttl = newttl;
7963 		}
7964 
7965 	mDNS_Unlock(m);
7966 	return(mStatus_NoError);
7967 	}
7968 
7969 // Note: mDNS_Deregister calls mDNS_Deregister_internal which can call a user callback, which may change
7970 // the record list and/or question list.
7971 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
7972 mDNSexport mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr)
7973 	{
7974 	mStatus status;
7975 	mDNS_Lock(m);
7976 	status = mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
7977 	mDNS_Unlock(m);
7978 	return(status);
7979 	}
7980 
7981 // Circular reference: AdvertiseInterface references mDNS_HostNameCallback, which calls mDNS_SetFQDN, which call AdvertiseInterface
7982 mDNSlocal void mDNS_HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
7983 
7984 mDNSlocal NetworkInterfaceInfo *FindFirstAdvertisedInterface(mDNS *const m)
7985 	{
7986 	NetworkInterfaceInfo *intf;
7987 	for (intf = m->HostInterfaces; intf; intf = intf->next)
7988 		if (intf->Advertise) break;
7989 	return(intf);
7990 	}
7991 
7992 mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
7993 	{
7994 	char buffer[MAX_REVERSE_MAPPING_NAME];
7995 	NetworkInterfaceInfo *primary = FindFirstAdvertisedInterface(m);
7996 	if (!primary) primary = set; // If no existing advertised interface, this new NetworkInterfaceInfo becomes our new primary
7997 
7998 	// Send dynamic update for non-linklocal IPv4 Addresses
7999 	mDNS_SetupResourceRecord(&set->RR_A,     mDNSNULL, set->InterfaceID, kDNSType_A,     kHostNameTTL, kDNSRecordTypeUnique,      mDNS_HostNameCallback, set);
8000 	mDNS_SetupResourceRecord(&set->RR_PTR,   mDNSNULL, set->InterfaceID, kDNSType_PTR,   kHostNameTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
8001 	mDNS_SetupResourceRecord(&set->RR_HINFO, mDNSNULL, set->InterfaceID, kDNSType_HINFO, kHostNameTTL, kDNSRecordTypeUnique,      mDNSNULL, mDNSNULL);
8002 
8003 #if ANSWER_REMOTE_HOSTNAME_QUERIES
8004 	set->RR_A    .AllowRemoteQuery  = mDNStrue;
8005 	set->RR_PTR  .AllowRemoteQuery  = mDNStrue;
8006 	set->RR_HINFO.AllowRemoteQuery  = mDNStrue;
8007 #endif
8008 	// 1. Set up Address record to map from host name ("foo.local.") to IP address
8009 	// 2. Set up reverse-lookup PTR record to map from our address back to our host name
8010 	AssignDomainName(&set->RR_A.namestorage, &m->MulticastHostname);
8011 	if (set->ip.type == mDNSAddrType_IPv4)
8012 		{
8013 		set->RR_A.resrec.rrtype = kDNSType_A;
8014 		set->RR_A.resrec.rdata->u.ipv4 = set->ip.ip.v4;
8015 		// Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
8016 		mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.",
8017 			set->ip.ip.v4.b[3], set->ip.ip.v4.b[2], set->ip.ip.v4.b[1], set->ip.ip.v4.b[0]);
8018 		}
8019 	else if (set->ip.type == mDNSAddrType_IPv6)
8020 		{
8021 		int i;
8022 		set->RR_A.resrec.rrtype = kDNSType_AAAA;
8023 		set->RR_A.resrec.rdata->u.ipv6 = set->ip.ip.v6;
8024 		for (i = 0; i < 16; i++)
8025 			{
8026 			static const char hexValues[] = "0123456789ABCDEF";
8027 			buffer[i * 4    ] = hexValues[set->ip.ip.v6.b[15 - i] & 0x0F];
8028 			buffer[i * 4 + 1] = '.';
8029 			buffer[i * 4 + 2] = hexValues[set->ip.ip.v6.b[15 - i] >> 4];
8030 			buffer[i * 4 + 3] = '.';
8031 			}
8032 		mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa.");
8033 		}
8034 
8035 	MakeDomainNameFromDNSNameString(&set->RR_PTR.namestorage, buffer);
8036 	set->RR_PTR.AutoTarget = Target_AutoHost;	// Tell mDNS that the target of this PTR is to be kept in sync with our host name
8037 	set->RR_PTR.ForceMCast = mDNStrue;			// This PTR points to our dot-local name, so don't ever try to write it into a uDNS server
8038 
8039 	set->RR_A.RRSet = &primary->RR_A;			// May refer to self
8040 
8041 	mDNS_Register_internal(m, &set->RR_A);
8042 	mDNS_Register_internal(m, &set->RR_PTR);
8043 
8044 	if (!NO_HINFO && m->HIHardware.c[0] > 0 && m->HISoftware.c[0] > 0 && m->HIHardware.c[0] + m->HISoftware.c[0] <= 254)
8045 		{
8046 		mDNSu8 *p = set->RR_HINFO.resrec.rdata->u.data;
8047 		AssignDomainName(&set->RR_HINFO.namestorage, &m->MulticastHostname);
8048 		set->RR_HINFO.DependentOn = &set->RR_A;
8049 		mDNSPlatformMemCopy(p, &m->HIHardware, 1 + (mDNSu32)m->HIHardware.c[0]);
8050 		p += 1 + (int)p[0];
8051 		mDNSPlatformMemCopy(p, &m->HISoftware, 1 + (mDNSu32)m->HISoftware.c[0]);
8052 		mDNS_Register_internal(m, &set->RR_HINFO);
8053 		}
8054 	else
8055 		{
8056 		debugf("Not creating HINFO record: platform support layer provided no information");
8057 		set->RR_HINFO.resrec.RecordType = kDNSRecordTypeUnregistered;
8058 		}
8059 	}
8060 
8061 mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
8062 	{
8063 	NetworkInterfaceInfo *intf;
8064 
8065     // If we still have address records referring to this one, update them
8066 	NetworkInterfaceInfo *primary = FindFirstAdvertisedInterface(m);
8067 	AuthRecord *A = primary ? &primary->RR_A : mDNSNULL;
8068 	for (intf = m->HostInterfaces; intf; intf = intf->next)
8069 		if (intf->RR_A.RRSet == &set->RR_A)
8070 			intf->RR_A.RRSet = A;
8071 
8072 	// Unregister these records.
8073 	// When doing the mDNS_Exit processing, we first call DeadvertiseInterface for each interface, so by the time the platform
8074 	// support layer gets to call mDNS_DeregisterInterface, the address and PTR records have already been deregistered for it.
8075 	// Also, in the event of a name conflict, one or more of our records will have been forcibly deregistered.
8076 	// To avoid unnecessary and misleading warning messages, we check the RecordType before calling mDNS_Deregister_internal().
8077 	if (set->RR_A.    resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_A,     mDNS_Dereg_normal);
8078 	if (set->RR_PTR.  resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_PTR,   mDNS_Dereg_normal);
8079 	if (set->RR_HINFO.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_HINFO, mDNS_Dereg_normal);
8080 	}
8081 
8082 mDNSexport void mDNS_SetFQDN(mDNS *const m)
8083 	{
8084 	domainname newmname;
8085 	NetworkInterfaceInfo *intf;
8086 	AuthRecord *rr;
8087 	newmname.c[0] = 0;
8088 
8089 	if (!AppendDomainLabel(&newmname, &m->hostlabel))  { LogMsg("ERROR: mDNS_SetFQDN: Cannot create MulticastHostname"); return; }
8090 	if (!AppendLiteralLabelString(&newmname, "local")) { LogMsg("ERROR: mDNS_SetFQDN: Cannot create MulticastHostname"); return; }
8091 
8092 	mDNS_Lock(m);
8093 
8094 	if (SameDomainNameCS(&m->MulticastHostname, &newmname)) debugf("mDNS_SetFQDN - hostname unchanged");
8095 	else
8096 		{
8097 		AssignDomainName(&m->MulticastHostname, &newmname);
8098 
8099 		// 1. Stop advertising our address records on all interfaces
8100 		for (intf = m->HostInterfaces; intf; intf = intf->next)
8101 			if (intf->Advertise) DeadvertiseInterface(m, intf);
8102 
8103 		// 2. Start advertising our address records using the new name
8104 		for (intf = m->HostInterfaces; intf; intf = intf->next)
8105 			if (intf->Advertise) AdvertiseInterface(m, intf);
8106 		}
8107 
8108 	// 3. Make sure that any AutoTarget SRV records (and the like) get updated
8109 	for (rr = m->ResourceRecords;  rr; rr=rr->next) if (rr->AutoTarget) SetTargetToHostName(m, rr);
8110 	for (rr = m->DuplicateRecords; rr; rr=rr->next) if (rr->AutoTarget) SetTargetToHostName(m, rr);
8111 
8112 	mDNS_Unlock(m);
8113 	}
8114 
8115 mDNSlocal void mDNS_HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
8116 	{
8117 	(void)rr;	// Unused parameter
8118 
8119 	#if MDNS_DEBUGMSGS
8120 		{
8121 		char *msg = "Unknown result";
8122 		if      (result == mStatus_NoError)      msg = "Name registered";
8123 		else if (result == mStatus_NameConflict) msg = "Name conflict";
8124 		debugf("mDNS_HostNameCallback: %##s (%s) %s (%ld)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), msg, result);
8125 		}
8126 	#endif
8127 
8128 	if (result == mStatus_NoError)
8129 		{
8130 		// Notify the client that the host name is successfully registered
8131 		if (m->MainCallback)
8132 			m->MainCallback(m, mStatus_NoError);
8133 		}
8134 	else if (result == mStatus_NameConflict)
8135 		{
8136 		domainlabel oldlabel = m->hostlabel;
8137 
8138 		// 1. First give the client callback a chance to pick a new name
8139 		if (m->MainCallback)
8140 			m->MainCallback(m, mStatus_NameConflict);
8141 
8142 		// 2. If the client callback didn't do it, add (or increment) an index ourselves
8143 		// This needs to be case-INSENSITIVE compare, because we need to know that the name has been changed so as to
8144 		// remedy the conflict, and a name that differs only in capitalization will just suffer the exact same conflict again.
8145 		if (SameDomainLabel(m->hostlabel.c, oldlabel.c))
8146 			IncrementLabelSuffix(&m->hostlabel, mDNSfalse);
8147 
8148 		// 3. Generate the FQDNs from the hostlabel,
8149 		// and make sure all SRV records, etc., are updated to reference our new hostname
8150 		mDNS_SetFQDN(m);
8151 		LogMsg("Local Hostname %#s.local already in use; will try %#s.local instead", oldlabel.c, m->hostlabel.c);
8152 		}
8153 	else if (result == mStatus_MemFree)
8154 		{
8155 		// .local hostnames do not require goodbyes - we ignore the MemFree (which is sent directly by
8156 		// mDNS_Deregister_internal), and allow the caller to deallocate immediately following mDNS_DeadvertiseInterface
8157 		debugf("mDNS_HostNameCallback: MemFree (ignored)");
8158 		}
8159 	else
8160 		LogMsg("mDNS_HostNameCallback: Unknown error %d for registration of record %s", result,  rr->resrec.name->c);
8161 	}
8162 
8163 mDNSlocal void UpdateInterfaceProtocols(mDNS *const m, NetworkInterfaceInfo *active)
8164 	{
8165 	NetworkInterfaceInfo *intf;
8166 	active->IPv4Available = mDNSfalse;
8167 	active->IPv6Available = mDNSfalse;
8168 	for (intf = m->HostInterfaces; intf; intf = intf->next)
8169 		if (intf->InterfaceID == active->InterfaceID)
8170 			{
8171 			if (intf->ip.type == mDNSAddrType_IPv4 && intf->McastTxRx) active->IPv4Available = mDNStrue;
8172 			if (intf->ip.type == mDNSAddrType_IPv6 && intf->McastTxRx) active->IPv6Available = mDNStrue;
8173 			}
8174 	}
8175 
8176 mDNSlocal void RestartRecordGetZoneData(mDNS * const m)
8177 	{
8178 	AuthRecord *rr;
8179 	ServiceRecordSet *s;
8180 
8181 	for (rr = m->ResourceRecords; rr; rr=rr->next)
8182 		if (AuthRecord_uDNS(rr))
8183 			{
8184 			debugf("RestartRecordGetZoneData: StartGetZoneData for %##s", rr->resrec.name->c);
8185 			if (rr->nta) CancelGetZoneData(m, rr->nta);
8186 			rr->nta = StartGetZoneData(m, rr->resrec.name, ZoneServiceUpdate, RecordRegistrationGotZoneData, rr);
8187 			}
8188 
8189 	for (s = m->ServiceRegistrations; s; s = s->uDNS_next)
8190 		{
8191 		debugf("RestartRecordGetZoneData: StartGetZoneData for %##s", s->RR_SRV.resrec.name->c);
8192 		if (s->srs_nta) CancelGetZoneData(m, s->srs_nta);
8193 		s->srs_nta = StartGetZoneData(m, s->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, s);
8194 		}
8195 	}
8196 
8197 mDNSlocal void InitializeNetWakeState(mDNS *const m, NetworkInterfaceInfo *set)
8198 	{
8199 	int i;
8200 	set->NetWakeBrowse.ThisQInterval = -1;
8201 	for (i=0; i<3; i++)
8202 		{
8203 		set->NetWakeResolve[i].ThisQInterval = -1;
8204 		set->SPSAddr[i].type = mDNSAddrType_None;
8205 		}
8206 	set->NextSPSAttempt     = -1;
8207 	set->NextSPSAttemptTime = m->timenow;
8208 	}
8209 
8210 mDNSexport void mDNS_ActivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set)
8211 	{
8212 	NetworkInterfaceInfo *p = m->HostInterfaces;
8213 	while (p && p != set) p=p->next;
8214 	if (!p) { LogMsg("mDNS_ActivateNetWake_internal: NetworkInterfaceInfo %p not found in active list", set); return; }
8215 
8216 	if (set->InterfaceActive)
8217 		{
8218 		LogSPS("ActivateNetWake for %s (%#a)", set->ifname, &set->ip);
8219 		mDNS_StartBrowse_internal(m, &set->NetWakeBrowse, &SleepProxyServiceType, &localdomain, set->InterfaceID, mDNSfalse, m->SPSBrowseCallback, set);
8220 		}
8221 	}
8222 
8223 mDNSexport void mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set)
8224 	{
8225 	NetworkInterfaceInfo *p = m->HostInterfaces;
8226 	while (p && p != set) p=p->next;
8227 	if (!p) { LogMsg("mDNS_DeactivateNetWake_internal: NetworkInterfaceInfo %p not found in active list", set); return; }
8228 
8229 	if (set->NetWakeBrowse.ThisQInterval >= 0)
8230 		{
8231 		int i;
8232 		LogSPS("DeactivateNetWake for %s (%#a)", set->ifname, &set->ip);
8233 
8234 		// Stop our browse and resolve operations
8235 		mDNS_StopQuery_internal(m, &set->NetWakeBrowse);
8236 		for (i=0; i<3; i++) if (set->NetWakeResolve[i].ThisQInterval >= 0) mDNS_StopQuery_internal(m, &set->NetWakeResolve[i]);
8237 
8238 		// Make special call to the browse callback to let it know it can to remove all records for this interface
8239 		if (m->SPSBrowseCallback) m->SPSBrowseCallback(m, &set->NetWakeBrowse, mDNSNULL, mDNSfalse);
8240 
8241 		// Reset our variables back to initial state, so we're ready for when NetWake is turned back on
8242 		// (includes resetting NetWakeBrowse.ThisQInterval back to -1)
8243 		InitializeNetWakeState(m, set);
8244 		}
8245 	}
8246 
8247 mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping)
8248 	{
8249 	AuthRecord *rr;
8250 	mDNSBool FirstOfType = mDNStrue;
8251 	NetworkInterfaceInfo **p = &m->HostInterfaces;
8252 
8253 	if (!set->InterfaceID)
8254 		{ LogMsg("Error! Tried to register a NetworkInterfaceInfo %#a with zero InterfaceID", &set->ip); return(mStatus_Invalid); }
8255 
8256 	if (!mDNSAddressIsValidNonZero(&set->mask))
8257 		{ LogMsg("Error! Tried to register a NetworkInterfaceInfo %#a with invalid mask %#a", &set->ip, &set->mask); return(mStatus_Invalid); }
8258 
8259 	mDNS_Lock(m);
8260 
8261 	// Assume this interface will be active now, unless we find a duplicate already in the list
8262 	set->InterfaceActive = mDNStrue;
8263 	set->IPv4Available   = (set->ip.type == mDNSAddrType_IPv4 && set->McastTxRx);
8264 	set->IPv6Available   = (set->ip.type == mDNSAddrType_IPv6 && set->McastTxRx);
8265 
8266 	InitializeNetWakeState(m, set);
8267 
8268 	// Scan list to see if this InterfaceID is already represented
8269 	while (*p)
8270 		{
8271 		if (*p == set)
8272 			{
8273 			LogMsg("Error! Tried to register a NetworkInterfaceInfo that's already in the list");
8274 			mDNS_Unlock(m);
8275 			return(mStatus_AlreadyRegistered);
8276 			}
8277 
8278 		if ((*p)->InterfaceID == set->InterfaceID)
8279 			{
8280 			// This InterfaceID already represented by a different interface in the list, so mark this instance inactive for now
8281 			set->InterfaceActive = mDNSfalse;
8282 			if (set->ip.type == (*p)->ip.type) FirstOfType = mDNSfalse;
8283 			if (set->ip.type == mDNSAddrType_IPv4 && set->McastTxRx) (*p)->IPv4Available = mDNStrue;
8284 			if (set->ip.type == mDNSAddrType_IPv6 && set->McastTxRx) (*p)->IPv6Available = mDNStrue;
8285 			}
8286 
8287 		p=&(*p)->next;
8288 		}
8289 
8290 	set->next = mDNSNULL;
8291 	*p = set;
8292 
8293 	if (set->Advertise)
8294 		AdvertiseInterface(m, set);
8295 
8296 	LogInfo("mDNS_RegisterInterface: InterfaceID %p %s (%#a) %s", set->InterfaceID, set->ifname, &set->ip,
8297 		set->InterfaceActive ?
8298 			"not represented in list; marking active and retriggering queries" :
8299 			"already represented in list; marking inactive for now");
8300 
8301 	if (set->NetWake) mDNS_ActivateNetWake_internal(m, set);
8302 
8303 	// In early versions of OS X the IPv6 address remains on an interface even when the interface is turned off,
8304 	// giving the false impression that there's an active representative of this interface when there really isn't.
8305 	// Therefore, when registering an interface, we want to re-trigger our questions and re-probe our Resource Records,
8306 	// even if we believe that we previously had an active representative of this interface.
8307 	if (set->McastTxRx && ((m->KnownBugs & mDNS_KnownBug_PhantomInterfaces) || FirstOfType || set->InterfaceActive))
8308 		{
8309 		DNSQuestion *q;
8310 		// If flapping, delay between first and second queries is eight seconds instead of one
8311 		mDNSs32 delay    = flapping ? mDNSPlatformOneSecond   * 5 : 0;
8312 		mDNSu8  announce = flapping ? (mDNSu8)1                   : InitialAnnounceCount;
8313 		mDNSs32 newSS    = 0;
8314 
8315 		// Use a small amount of randomness:
8316 		// In the case of a network administrator turning on an Ethernet hub so that all the
8317 		// connected machines establish link at exactly the same time, we don't want them all
8318 		// to go and hit the network with identical queries at exactly the same moment.
8319 		newSS = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval);
8320 #if APPLE_OSX_mDNSResponder
8321 		// We set this to at least 2 seconds, because the MacOSX platform layer typically gets lots
8322 		// of network change notifications in a row, and we don't know when we're done getting notified.
8323 		// Note that this will not be set if the interface doesn't do multicast (set->McastTxRx).
8324 		newSS += mDNSPlatformOneSecond * 2;
8325 #endif
8326 		if (!m->SuppressSending || newSS - m->SuppressSending < 0) m->SuppressSending = newSS;
8327 
8328 		if (flapping)
8329 			{
8330 			LogMsg("Note: RegisterInterface: Frequent transitions for interface %s (%#a); network traffic reduction measures in effect",
8331 				set->ifname, &set->ip);
8332 			if (!m->SuppressProbes ||
8333 				m->SuppressProbes - (m->timenow + delay) < 0)
8334 				m->SuppressProbes = (m->timenow + delay);
8335 			}
8336 
8337 		for (q = m->Questions; q; q=q->next)								// Scan our list of questions
8338 			if (mDNSOpaque16IsZero(q->TargetQID))
8339 				if (!q->InterfaceID || q->InterfaceID == set->InterfaceID)		// If non-specific Q, or Q on this specific interface,
8340 					{															// then reactivate this question
8341 					mDNSBool dodelay = flapping && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID);
8342 					mDNSs32 initial  = dodelay ? InitialQuestionInterval * QuestionIntervalStep2 : InitialQuestionInterval;
8343 					mDNSs32 qdelay   = dodelay ? mDNSPlatformOneSecond * 5 : 0;
8344 					if (dodelay) LogInfo("No cache records expired for %##s (%s); okay to delay questions a little", q->qname.c, DNSTypeName(q->qtype));
8345 
8346 					if (!q->ThisQInterval || q->ThisQInterval > initial)
8347 						{
8348 						q->ThisQInterval = initial;
8349 						q->RequestUnicast = 2; // Set to 2 because is decremented once *before* we check it
8350 						}
8351 					q->LastQTime = m->timenow - q->ThisQInterval + qdelay;
8352 					q->RecentAnswerPkts = 0;
8353 					SetNextQueryTime(m,q);
8354 					}
8355 
8356 		// For all our non-specific authoritative resource records (and any dormant records specific to this interface)
8357 		// we now need them to re-probe if necessary, and then re-announce.
8358 		for (rr = m->ResourceRecords; rr; rr=rr->next)
8359 			if (!AuthRecord_uDNS(rr))
8360 				if (!rr->resrec.InterfaceID || rr->resrec.InterfaceID == set->InterfaceID)
8361 					{
8362 					if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
8363 					rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
8364 					if (rr->AnnounceCount < announce) rr->AnnounceCount  = announce;
8365 					InitializeLastAPTime(m, rr);
8366 					}
8367 		}
8368 
8369 	RestartRecordGetZoneData(m);
8370 
8371 	mDNS_Unlock(m);
8372 	return(mStatus_NoError);
8373 	}
8374 
8375 // Note: mDNS_DeregisterInterface calls mDNS_Deregister_internal which can call a user callback, which may change
8376 // the record list and/or question list.
8377 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
8378 mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping)
8379 	{
8380 	NetworkInterfaceInfo **p = &m->HostInterfaces;
8381 
8382 	mDNSBool revalidate = mDNSfalse;
8383 	// If this platform has the "phantom interfaces" known bug (e.g. Jaguar), we have to revalidate records every
8384 	// time an interface goes away. Otherwise, when you disconnect the Ethernet cable, the system reports that it
8385 	// still has an IPv6 address, and if we don't revalidate those records don't get deleted in a timely fashion.
8386 	if (m->KnownBugs & mDNS_KnownBug_PhantomInterfaces) revalidate = mDNStrue;
8387 
8388 	mDNS_Lock(m);
8389 
8390 	// Find this record in our list
8391 	while (*p && *p != set) p=&(*p)->next;
8392 	if (!*p) { debugf("mDNS_DeregisterInterface: NetworkInterfaceInfo not found in list"); mDNS_Unlock(m); return; }
8393 
8394 	mDNS_DeactivateNetWake_internal(m, set);
8395 
8396 	// Unlink this record from our list
8397 	*p = (*p)->next;
8398 	set->next = mDNSNULL;
8399 
8400 	if (!set->InterfaceActive)
8401 		{
8402 		// If this interface not the active member of its set, update the v4/v6Available flags for the active member
8403 		NetworkInterfaceInfo *intf;
8404 		for (intf = m->HostInterfaces; intf; intf = intf->next)
8405 			if (intf->InterfaceActive && intf->InterfaceID == set->InterfaceID)
8406 				UpdateInterfaceProtocols(m, intf);
8407 		}
8408 	else
8409 		{
8410 		NetworkInterfaceInfo *intf = FirstInterfaceForID(m, set->InterfaceID);
8411 		if (intf)
8412 			{
8413 			LogInfo("mDNS_DeregisterInterface: Another representative of InterfaceID %p %s (%#a) exists;"
8414 				" making it active", set->InterfaceID, set->ifname, &set->ip);
8415 			if (intf->InterfaceActive)
8416 				LogMsg("mDNS_DeregisterInterface: ERROR intf->InterfaceActive already set for %s (%#a)", set->ifname, &set->ip);
8417 			intf->InterfaceActive = mDNStrue;
8418 			UpdateInterfaceProtocols(m, intf);
8419 
8420 			if (intf->NetWake) mDNS_ActivateNetWake_internal(m, intf);
8421 
8422 			// See if another representative *of the same type* exists. If not, we mave have gone from
8423 			// dual-stack to v6-only (or v4-only) so we need to reconfirm which records are still valid.
8424 			for (intf = m->HostInterfaces; intf; intf = intf->next)
8425 				if (intf->InterfaceID == set->InterfaceID && intf->ip.type == set->ip.type)
8426 					break;
8427 			if (!intf) revalidate = mDNStrue;
8428 			}
8429 		else
8430 			{
8431 			mDNSu32 slot;
8432 			CacheGroup *cg;
8433 			CacheRecord *rr;
8434 			DNSQuestion *q;
8435 			DNSServer *s;
8436 
8437 			LogInfo("mDNS_DeregisterInterface: Last representative of InterfaceID %p %s (%#a) deregistered;"
8438 				" marking questions etc. dormant", set->InterfaceID, set->ifname, &set->ip);
8439 
8440 			if (flapping)
8441 				LogMsg("Note: DeregisterInterface: Frequent transitions for interface %s (%#a); network traffic reduction measures in effect",
8442 					set->ifname, &set->ip);
8443 
8444 			// 1. Deactivate any questions specific to this interface, and tag appropriate questions
8445 			// so that mDNS_RegisterInterface() knows how swiftly it needs to reactivate them
8446 			for (q = m->Questions; q; q=q->next)
8447 				{
8448 				if (q->InterfaceID == set->InterfaceID) q->ThisQInterval = 0;
8449 				if (!q->InterfaceID || q->InterfaceID == set->InterfaceID)
8450 					{
8451 					q->FlappingInterface2 = q->FlappingInterface1;
8452 					q->FlappingInterface1 = set->InterfaceID;		// Keep history of the last two interfaces to go away
8453 					}
8454 				}
8455 
8456 			// 2. Flush any cache records received on this interface
8457 			revalidate = mDNSfalse;		// Don't revalidate if we're flushing the records
8458 			FORALL_CACHERECORDS(slot, cg, rr)
8459 				if (rr->resrec.InterfaceID == set->InterfaceID)
8460 					{
8461 					// If this interface is deemed flapping,
8462 					// postpone deleting the cache records in case the interface comes back again
8463 					if (!flapping) mDNS_PurgeCacheResourceRecord(m, rr);
8464 					else
8465 						{
8466 						// We want these record to go away in 30 seconds
8467 						// We set UnansweredQueries = MaxUnansweredQueries so we don't waste time doing any queries for them --
8468 						// if the interface does come back, any relevant questions will be reactivated anyway
8469 						mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface);
8470 						rr->UnansweredQueries = MaxUnansweredQueries;
8471 						}
8472 					}
8473 
8474 			// 3. Any DNS servers specific to this interface are now unusable
8475 			for (s = m->DNSServers; s; s = s->next)
8476 				if (s->interface == set->InterfaceID)
8477 					{
8478 					s->interface = mDNSInterface_Any;
8479 					s->teststate = DNSServer_Disabled;
8480 					}
8481 			}
8482 		}
8483 
8484 	// If we were advertising on this interface, deregister those address and reverse-lookup records now
8485 	if (set->Advertise) DeadvertiseInterface(m, set);
8486 
8487 	// If we have any cache records received on this interface that went away, then re-verify them.
8488 	// In some versions of OS X the IPv6 address remains on an interface even when the interface is turned off,
8489 	// giving the false impression that there's an active representative of this interface when there really isn't.
8490 	// Don't need to do this when shutting down, because *all* interfaces are about to go away
8491 	if (revalidate && !m->ShutdownTime)
8492 		{
8493 		mDNSu32 slot;
8494 		CacheGroup *cg;
8495 		CacheRecord *rr;
8496 		m->NextCacheCheck = m->timenow;
8497 		FORALL_CACHERECORDS(slot, cg, rr)
8498 			if (rr->resrec.InterfaceID == set->InterfaceID)
8499 				mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface);
8500 		}
8501 
8502 	mDNS_Unlock(m);
8503 	}
8504 
8505 mDNSlocal void ServiceCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
8506 	{
8507 	ServiceRecordSet *sr = (ServiceRecordSet *)rr->RecordContext;
8508 	(void)m;	// Unused parameter
8509 
8510 	#if MDNS_DEBUGMSGS
8511 		{
8512 		char *msg = "Unknown result";
8513 		if      (result == mStatus_NoError)      msg = "Name Registered";
8514 		else if (result == mStatus_NameConflict) msg = "Name Conflict";
8515 		else if (result == mStatus_MemFree)      msg = "Memory Free";
8516 		debugf("ServiceCallback: %##s (%s) %s (%d)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), msg, result);
8517 		}
8518 	#endif
8519 
8520 	// Only pass on the NoError acknowledgement for the SRV record (when it finishes probing)
8521 	if (result == mStatus_NoError && rr != &sr->RR_SRV) return;
8522 
8523 	// If we got a name conflict on either SRV or TXT, forcibly deregister this service, and record that we did that
8524 	if (result == mStatus_NameConflict)
8525 		{
8526 		sr->Conflict = mDNStrue;				// Record that this service set had a conflict
8527 		mDNS_DeregisterService(m, sr);			// Unlink the records from our list
8528 		return;
8529 		}
8530 
8531 	if (result == mStatus_MemFree)
8532 		{
8533 		// If the SRV/TXT/PTR records, or the _services._dns-sd._udp record, or any of the subtype PTR records,
8534 		// are still in the process of deregistering, don't pass on the NameConflict/MemFree message until
8535 		// every record is finished cleaning up.
8536 		mDNSu32 i;
8537 		if (sr->RR_SRV.resrec.RecordType != kDNSRecordTypeUnregistered) return;
8538 		if (sr->RR_TXT.resrec.RecordType != kDNSRecordTypeUnregistered) return;
8539 		if (sr->RR_PTR.resrec.RecordType != kDNSRecordTypeUnregistered) return;
8540 		if (sr->RR_ADV.resrec.RecordType != kDNSRecordTypeUnregistered) return;
8541 		for (i=0; i<sr->NumSubTypes; i++) if (sr->SubTypes[i].resrec.RecordType != kDNSRecordTypeUnregistered) return;
8542 
8543 		// If this ServiceRecordSet was forcibly deregistered, and now its memory is ready for reuse,
8544 		// then we can now report the NameConflict to the client
8545 		if (sr->Conflict) result = mStatus_NameConflict;
8546 
8547 		if (sr->srs_nta)
8548 			{
8549 			LogMsg("ServiceCallback ERROR Got mStatus_MemFree with srs_nta still set for %s", ARDisplayString(m, &sr->RR_SRV));
8550 			CancelGetZoneData(m, sr->srs_nta);
8551 			sr->srs_nta = mDNSNULL;
8552 			}
8553 		}
8554 
8555 	// CAUTION: MUST NOT do anything more with sr after calling sr->Callback(), because the client's callback
8556 	// function is allowed to do anything, including deregistering this service and freeing its memory.
8557 	if (sr->ServiceCallback)
8558 		sr->ServiceCallback(m, sr, result);
8559 	}
8560 
8561 mDNSlocal void NSSCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
8562 	{
8563 	ServiceRecordSet *sr = (ServiceRecordSet *)rr->RecordContext;
8564 	if (sr->ServiceCallback)
8565 		sr->ServiceCallback(m, sr, result);
8566 	}
8567 
8568 #if !defined(UNICAST_DISABLED) && USE_SEPARATE_UDNS_SERVICE_LIST
8569 mDNSlocal mStatus uDNS_RegisterService(mDNS *const m, ServiceRecordSet *srs)
8570 	{
8571 	mDNSu32 i;
8572 	ServiceRecordSet **p = &m->ServiceRegistrations;
8573 	while (*p && *p != srs) p=&(*p)->uDNS_next;
8574 	if (*p) { LogMsg("uDNS_RegisterService: %p %##s already in list", srs, srs->RR_SRV.resrec.name->c); return(mStatus_AlreadyRegistered); }
8575 
8576 	srs->uDNS_next = mDNSNULL;
8577 	*p = srs;
8578 
8579 	srs->RR_SRV.resrec.rroriginalttl = kHostNameTTL;
8580 	srs->RR_TXT.resrec.rroriginalttl = kStandardTTL;
8581 	srs->RR_PTR.resrec.rroriginalttl = kStandardTTL;
8582 	for (i = 0; i < srs->NumSubTypes;i++) srs->SubTypes[i].resrec.rroriginalttl = kStandardTTL;
8583 
8584 	srs->srs_uselease = mDNStrue;
8585 
8586 	if (srs->RR_SRV.AutoTarget)
8587 		{
8588 		// For autotunnel services pointing at our IPv6 ULA we don't need or want a NAT mapping, but for all other
8589 		// advertised services referencing our uDNS hostname, we want NAT mappings automatically created as appropriate,
8590 		// with the port number in our advertised SRV record automatically tracking the external mapped port.
8591 		DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, srs->RR_SRV.resrec.name);
8592 		if (!AuthInfo || !AuthInfo->AutoTunnel) srs->RR_SRV.AutoTarget = Target_AutoHostAndNATMAP;
8593 		}
8594 
8595 	if (!GetServiceTarget(m, &srs->RR_SRV))
8596 		{
8597 		// defer registration until we've got a target
8598 		LogInfo("uDNS_RegisterService - no target for %##s", srs->RR_SRV.resrec.name->c);
8599 		srs->state   = regState_NoTarget;
8600 		return mStatus_NoError;
8601 		}
8602 
8603 	ActivateUnicastRegistration(m, &srs->RR_SRV);
8604 	srs->state = regState_FetchingZoneData;
8605 	return mStatus_NoError;
8606 	}
8607 #endif
8608 
8609 // Note:
8610 // Name is first label of domain name (any dots in the name are actual dots, not label separators)
8611 // Type is service type (e.g. "_ipp._tcp.")
8612 // Domain is fully qualified domain name (i.e. ending with a null label)
8613 // We always register a TXT, even if it is empty (so that clients are not
8614 // left waiting forever looking for a nonexistent record.)
8615 // If the host parameter is mDNSNULL or the root domain (ASCII NUL),
8616 // then the default host name (m->MulticastHostname) is automatically used
8617 // If the optional target host parameter is set, then the storage it points to must remain valid for the lifetime of the service registration
8618 mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
8619 	const domainlabel *const name, const domainname *const type, const domainname *const domain,
8620 	const domainname *const host, mDNSIPPort port, const mDNSu8 txtinfo[], mDNSu16 txtlen,
8621 	AuthRecord *SubTypes, mDNSu32 NumSubTypes,
8622 	const mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context)
8623 	{
8624 	mStatus err;
8625 	mDNSu32 i;
8626 
8627 	sr->state                  = regState_Zero;
8628 	sr->srs_uselease           = 0;
8629 	sr->TestForSelfConflict    = 0;
8630 	sr->Private                = 0;
8631 	sr->id                     = zeroID;
8632 	sr->zone.c[0]              = 0;
8633 	sr->SRSUpdateServer        = zeroAddr;
8634 	sr->SRSUpdatePort          = zeroIPPort;
8635 	mDNSPlatformMemZero(&sr->NATinfo, sizeof(sr->NATinfo));
8636 	sr->NATinfo.IntPort        = port;		// Record originally-requested port
8637 	sr->ClientCallbackDeferred = 0;
8638 	sr->DeferredStatus         = 0;
8639 	sr->SRVUpdateDeferred      = 0;
8640 	sr->SRVChanged             = 0;
8641 	sr->tcp                    = mDNSNULL;
8642 
8643 	sr->ServiceCallback = Callback;
8644 	sr->ServiceContext  = Context;
8645 	sr->Conflict        = mDNSfalse;
8646 
8647 	sr->Extras          = mDNSNULL;
8648 	sr->NumSubTypes     = NumSubTypes;
8649 	sr->SubTypes        = SubTypes;
8650 
8651 	// Initialize the AuthRecord objects to sane values
8652 	// Need to initialize everything correctly *before* making the decision whether to do a RegisterNoSuchService and bail out
8653 	mDNS_SetupResourceRecord(&sr->RR_ADV, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeAdvisory, ServiceCallback, sr);
8654 	mDNS_SetupResourceRecord(&sr->RR_PTR, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared,   ServiceCallback, sr);
8655 	mDNS_SetupResourceRecord(&sr->RR_SRV, mDNSNULL, InterfaceID, kDNSType_SRV, kHostNameTTL, kDNSRecordTypeUnique,   ServiceCallback, sr);
8656 	mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, InterfaceID, kDNSType_TXT, kStandardTTL, kDNSRecordTypeUnique,   ServiceCallback, sr);
8657 
8658 	// If port number is zero, that means the client is really trying to do a RegisterNoSuchService
8659 	if (mDNSIPPortIsZero(port))
8660 		return(mDNS_RegisterNoSuchService(m, &sr->RR_SRV, name, type, domain, mDNSNULL, mDNSInterface_Any, NSSCallback, sr));
8661 
8662 	// If the client is registering an oversized TXT record,
8663 	// it is the client's responsibility to alloate a ServiceRecordSet structure that is large enough for it
8664 	if (sr->RR_TXT.resrec.rdata->MaxRDLength < txtlen)
8665 		sr->RR_TXT.resrec.rdata->MaxRDLength = txtlen;
8666 
8667 	// Set up the record names
8668 	// For now we only create an advisory record for the main type, not for subtypes
8669 	// We need to gain some operational experience before we decide if there's a need to create them for subtypes too
8670 	if (ConstructServiceName(&sr->RR_ADV.namestorage, (const domainlabel*)"\x09_services", (const domainname*)"\x07_dns-sd\x04_udp", domain) == mDNSNULL)
8671 		return(mStatus_BadParamErr);
8672 	if (ConstructServiceName(&sr->RR_PTR.namestorage, mDNSNULL, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
8673 	if (ConstructServiceName(&sr->RR_SRV.namestorage, name,     type, domain) == mDNSNULL) return(mStatus_BadParamErr);
8674 	AssignDomainName(&sr->RR_TXT.namestorage, sr->RR_SRV.resrec.name);
8675 
8676 	// 1. Set up the ADV record rdata to advertise our service type
8677 	AssignDomainName(&sr->RR_ADV.resrec.rdata->u.name, sr->RR_PTR.resrec.name);
8678 
8679 	// 2. Set up the PTR record rdata to point to our service name
8680 	// We set up two additionals, so when a client asks for this PTR we automatically send the SRV and the TXT too
8681 	AssignDomainName(&sr->RR_PTR.resrec.rdata->u.name, sr->RR_SRV.resrec.name);
8682 	sr->RR_PTR.Additional1 = &sr->RR_SRV;
8683 	sr->RR_PTR.Additional2 = &sr->RR_TXT;
8684 
8685 	// 2a. Set up any subtype PTRs to point to our service name
8686 	// If the client is using subtypes, it is the client's responsibility to have
8687 	// already set the first label of the record name to the subtype being registered
8688 	for (i=0; i<NumSubTypes; i++)
8689 		{
8690 		domainname st;
8691 		AssignDomainName(&st, sr->SubTypes[i].resrec.name);
8692 		st.c[1+st.c[0]] = 0;			// Only want the first label, not the whole FQDN (particularly for mDNS_RenameAndReregisterService())
8693 		AppendDomainName(&st, type);
8694 		mDNS_SetupResourceRecord(&sr->SubTypes[i], mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, ServiceCallback, sr);
8695 		if (ConstructServiceName(&sr->SubTypes[i].namestorage, mDNSNULL, &st, domain) == mDNSNULL) return(mStatus_BadParamErr);
8696 		AssignDomainName(&sr->SubTypes[i].resrec.rdata->u.name, &sr->RR_SRV.namestorage);
8697 		sr->SubTypes[i].Additional1 = &sr->RR_SRV;
8698 		sr->SubTypes[i].Additional2 = &sr->RR_TXT;
8699 		}
8700 
8701 	// 3. Set up the SRV record rdata.
8702 	sr->RR_SRV.resrec.rdata->u.srv.priority = 0;
8703 	sr->RR_SRV.resrec.rdata->u.srv.weight   = 0;
8704 	sr->RR_SRV.resrec.rdata->u.srv.port     = port;
8705 
8706 	// Setting AutoTarget tells DNS that the target of this SRV is to be automatically kept in sync with our host name
8707 	if (host && host->c[0]) AssignDomainName(&sr->RR_SRV.resrec.rdata->u.srv.target, host);
8708 	else { sr->RR_SRV.AutoTarget = Target_AutoHost; sr->RR_SRV.resrec.rdata->u.srv.target.c[0] = '\0'; }
8709 
8710 	// 4. Set up the TXT record rdata,
8711 	// and set DependentOn because we're depending on the SRV record to find and resolve conflicts for us
8712 	if (txtinfo == mDNSNULL) sr->RR_TXT.resrec.rdlength = 0;
8713 	else if (txtinfo != sr->RR_TXT.resrec.rdata->u.txt.c)
8714 		{
8715 		sr->RR_TXT.resrec.rdlength = txtlen;
8716 		if (sr->RR_TXT.resrec.rdlength > sr->RR_TXT.resrec.rdata->MaxRDLength) return(mStatus_BadParamErr);
8717 		mDNSPlatformMemCopy(sr->RR_TXT.resrec.rdata->u.txt.c, txtinfo, txtlen);
8718 		}
8719 	sr->RR_TXT.DependentOn = &sr->RR_SRV;
8720 
8721 	sr->srs_nta = mDNSNULL;
8722 
8723 #if !defined(UNICAST_DISABLED) && USE_SEPARATE_UDNS_SERVICE_LIST
8724 	// If the client has specified an explicit InterfaceID,
8725 	// then we do a multicast registration on that interface, even for unicast domains.
8726 	if (!(InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(&sr->RR_SRV.namestorage)))
8727 		{
8728 		mStatus status;
8729 		mDNS_Lock(m);
8730 		// BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
8731 		// since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
8732 		// Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
8733 		// (We have to duplicate this check here because uDNS_RegisterService() bypasses the usual mDNS_Register_internal() bottleneck)
8734 		if (!sr->RR_TXT.resrec.rdlength) { sr->RR_TXT.resrec.rdlength = 1; sr->RR_TXT.resrec.rdata->u.txt.c[0] = 0; }
8735 
8736 		status = uDNS_RegisterService(m, sr);
8737 		mDNS_Unlock(m);
8738 		return(status);
8739 		}
8740 #endif
8741 
8742 	mDNS_Lock(m);
8743 	err = mDNS_Register_internal(m, &sr->RR_SRV);
8744 	if (!err) err = mDNS_Register_internal(m, &sr->RR_TXT);
8745 	// We register the RR_PTR last, because we want to be sure that in the event of a forced call to
8746 	// mDNS_StartExit, the RR_PTR will be the last one to be forcibly deregistered, since that is what triggers
8747 	// the mStatus_MemFree callback to ServiceCallback, which in turn passes on the mStatus_MemFree back to
8748 	// the client callback, which is then at liberty to free the ServiceRecordSet memory at will. We need to
8749 	// make sure we've deregistered all our records and done any other necessary cleanup before that happens.
8750 	if (!err) err = mDNS_Register_internal(m, &sr->RR_ADV);
8751 	for (i=0; i<NumSubTypes; i++) if (!err) err = mDNS_Register_internal(m, &sr->SubTypes[i]);
8752 	if (!err) err = mDNS_Register_internal(m, &sr->RR_PTR);
8753 
8754 	mDNS_Unlock(m);
8755 
8756 	if (err) mDNS_DeregisterService(m, sr);
8757 	return(err);
8758 	}
8759 
8760 mDNSlocal void DummyCallback(mDNS *const m, AuthRecord *rr, mStatus result)
8761 	{
8762 	(void)m;		// Unused
8763 	(void)rr;		// Unused
8764 	(void)result;	// Unused
8765 	LogInfo("DummyCallback %d %s", result, ARDisplayString(m, rr));
8766 	}
8767 
8768 mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr,
8769 	ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl)
8770 	{
8771 	ExtraResourceRecord **e;
8772 	mStatus status;
8773 
8774 	extra->next = mDNSNULL;
8775 	mDNS_SetupResourceRecord(&extra->r, rdata, sr->RR_PTR.resrec.InterfaceID,
8776 		extra->r.resrec.rrtype, ttl, kDNSRecordTypeUnique, ServiceCallback, sr);
8777 	AssignDomainName(&extra->r.namestorage, sr->RR_SRV.resrec.name);
8778 
8779 	mDNS_Lock(m);
8780 	e = &sr->Extras;
8781 	while (*e) e = &(*e)->next;
8782 
8783 	if (ttl == 0) ttl = kStandardTTL;
8784 
8785 	extra->r.DependentOn = &sr->RR_SRV;
8786 
8787 	debugf("mDNS_AddRecordToService adding record to %##s %s %d",
8788 		extra->r.resrec.name->c, DNSTypeName(extra->r.resrec.rrtype), extra->r.resrec.rdlength);
8789 
8790 	status = mDNS_Register_internal(m, &extra->r);
8791 	if (status == mStatus_NoError)
8792 		{
8793 		*e = extra;
8794 #ifndef UNICAST_DISABLED
8795 		if (AuthRecord_uDNS(&sr->RR_SRV))
8796 			{
8797 			extra->r.resrec.RecordType = kDNSRecordTypeShared;	// don't want it to conflict with the service name (???)
8798 			extra->r.RecordCallback = DummyCallback;	// don't generate callbacks for extra RRs for unicast services (WHY NOT????)
8799 			if (sr->state != regState_Registered && sr->state != regState_Refresh) extra->r.state = regState_ExtraQueued;
8800 			}
8801 #endif
8802 		}
8803 
8804 	mDNS_Unlock(m);
8805 	return(status);
8806 	}
8807 
8808 mDNSexport mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra,
8809 	mDNSRecordCallback MemFreeCallback, void *Context)
8810 	{
8811 	ExtraResourceRecord **e;
8812 	mStatus status;
8813 
8814 	mDNS_Lock(m);
8815 	e = &sr->Extras;
8816 	while (*e && *e != extra) e = &(*e)->next;
8817 	if (!*e)
8818 		{
8819 		debugf("mDNS_RemoveRecordFromService failed to remove record from %##s", extra->r.resrec.name->c);
8820 		status = mStatus_BadReferenceErr;
8821 		}
8822 	else
8823 		{
8824 		debugf("mDNS_RemoveRecordFromService removing record from %##s", extra->r.resrec.name->c);
8825 		extra->r.RecordCallback = MemFreeCallback;
8826 		extra->r.RecordContext  = Context;
8827 		*e = (*e)->next;
8828 		status = mDNS_Deregister_internal(m, &extra->r, mDNS_Dereg_normal);
8829 		}
8830 	mDNS_Unlock(m);
8831 	return(status);
8832 	}
8833 
8834 mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname)
8835 	{
8836 	// Note: Don't need to use mDNS_Lock(m) here, because this code is just using public routines
8837 	// mDNS_RegisterService() and mDNS_AddRecordToService(), which do the right locking internally.
8838 	domainlabel name1, name2;
8839 	domainname type, domain;
8840 	const domainname *host = sr->RR_SRV.AutoTarget ? mDNSNULL : &sr->RR_SRV.resrec.rdata->u.srv.target;
8841 	ExtraResourceRecord *extras = sr->Extras;
8842 	mStatus err;
8843 
8844 	DeconstructServiceName(sr->RR_SRV.resrec.name, &name1, &type, &domain);
8845 	if (!newname)
8846 		{
8847 		name2 = name1;
8848 		IncrementLabelSuffix(&name2, mDNStrue);
8849 		newname = &name2;
8850 		}
8851 
8852 	if (SameDomainName(&domain, &localdomain))
8853 		debugf("%##s service renamed from \"%#s\" to \"%#s\"", type.c, name1.c, newname->c);
8854 	else debugf("%##s service (domain %##s) renamed from \"%#s\" to \"%#s\"",type.c, domain.c, name1.c, newname->c);
8855 
8856 	err = mDNS_RegisterService(m, sr, newname, &type, &domain,
8857 		host, sr->RR_SRV.resrec.rdata->u.srv.port, sr->RR_TXT.resrec.rdata->u.txt.c, sr->RR_TXT.resrec.rdlength,
8858 		sr->SubTypes, sr->NumSubTypes,
8859 		sr->RR_PTR.resrec.InterfaceID, sr->ServiceCallback, sr->ServiceContext);
8860 
8861 	// mDNS_RegisterService() just reset sr->Extras to NULL.
8862 	// Fortunately we already grabbed ourselves a copy of this pointer (above), so we can now run
8863 	// through the old list of extra records, and re-add them to our freshly created service registration
8864 	while (!err && extras)
8865 		{
8866 		ExtraResourceRecord *e = extras;
8867 		extras = extras->next;
8868 		err = mDNS_AddRecordToService(m, sr, e, e->r.resrec.rdata, e->r.resrec.rroriginalttl);
8869 		}
8870 
8871 	return(err);
8872 	}
8873 
8874 // Note: mDNS_DeregisterService calls mDNS_Deregister_internal which can call a user callback,
8875 // which may change the record list and/or question list.
8876 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
8877 mDNSexport mStatus mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr)
8878 	{
8879 	// If port number is zero, that means this was actually registered using mDNS_RegisterNoSuchService()
8880 	if (mDNSIPPortIsZero(sr->RR_SRV.resrec.rdata->u.srv.port)) return(mDNS_DeregisterNoSuchService(m, &sr->RR_SRV));
8881 
8882 #if !defined(UNICAST_DISABLED) && USE_SEPARATE_UDNS_SERVICE_LIST
8883 	if (!(sr->RR_SRV.resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(sr->RR_SRV.resrec.name)))
8884 		{
8885 		mStatus status;
8886 		mDNS_Lock(m);
8887 		status = uDNS_DeregisterService(m, sr);
8888 		mDNS_Unlock(m);
8889 		return(status);
8890 		}
8891 #endif
8892 	if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeUnregistered)
8893 		{
8894 		debugf("Service set for %##s already deregistered", sr->RR_SRV.resrec.name->c);
8895 		return(mStatus_BadReferenceErr);
8896 		}
8897 	else if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeDeregistering)
8898 		{
8899 		debugf("Service set for %##s already in the process of deregistering", sr->RR_SRV.resrec.name->c);
8900 		// Avoid race condition:
8901 		// If a service gets a conflict, then we set the Conflict flag to tell us to generate
8902 		// an mStatus_NameConflict message when we get the mStatus_MemFree for our PTR record.
8903 		// If the client happens to deregister the service in the middle of that process, then
8904 		// we clear the flag back to the normal state, so that we deliver a plain mStatus_MemFree
8905 		// instead of incorrectly promoting it to mStatus_NameConflict.
8906 		// This race condition is exposed particularly when the conformance test generates
8907 		// a whole batch of simultaneous conflicts across a range of services all advertised
8908 		// using the same system default name, and if we don't take this precaution then
8909 		// we end up incrementing m->nicelabel multiple times instead of just once.
8910 		// <rdar://problem/4060169> Bug when auto-renaming Computer Name after name collision
8911 		sr->Conflict = mDNSfalse;
8912 		return(mStatus_NoError);
8913 		}
8914 	else
8915 		{
8916 		mDNSu32 i;
8917 		mStatus status;
8918 		ExtraResourceRecord *e;
8919 		mDNS_Lock(m);
8920 		e = sr->Extras;
8921 
8922 		// We use mDNS_Dereg_repeat because, in the event of a collision, some or all of the
8923 		// SRV, TXT, or Extra records could have already been automatically deregistered, and that's okay
8924 		mDNS_Deregister_internal(m, &sr->RR_SRV, mDNS_Dereg_repeat);
8925 		mDNS_Deregister_internal(m, &sr->RR_TXT, mDNS_Dereg_repeat);
8926 
8927 		mDNS_Deregister_internal(m, &sr->RR_ADV, mDNS_Dereg_normal);
8928 
8929 		// We deregister all of the extra records, but we leave the sr->Extras list intact
8930 		// in case the client wants to do a RenameAndReregister and reinstate the registration
8931 		while (e)
8932 			{
8933 			mDNS_Deregister_internal(m, &e->r, mDNS_Dereg_repeat);
8934 			e = e->next;
8935 			}
8936 
8937 		for (i=0; i<sr->NumSubTypes; i++)
8938 			mDNS_Deregister_internal(m, &sr->SubTypes[i], mDNS_Dereg_normal);
8939 
8940 		// Be sure to deregister the PTR last!
8941 		// Deregistering this record is what triggers the mStatus_MemFree callback to ServiceCallback,
8942 		// which in turn passes on the mStatus_MemFree (or mStatus_NameConflict) back to the client callback,
8943 		// which is then at liberty to free the ServiceRecordSet memory at will. We need to make sure
8944 		// we've deregistered all our records and done any other necessary cleanup before that happens.
8945 		status = mDNS_Deregister_internal(m, &sr->RR_PTR, mDNS_Dereg_normal);
8946 		mDNS_Unlock(m);
8947 		return(status);
8948 		}
8949 	}
8950 
8951 // Create a registration that asserts that no such service exists with this name.
8952 // This can be useful where there is a given function is available through several protocols.
8953 // For example, a printer called "Stuart's Printer" may implement printing via the "pdl-datastream" and "IPP"
8954 // protocols, but not via "LPR". In this case it would be prudent for the printer to assert the non-existence of an
8955 // "LPR" service called "Stuart's Printer". Without this precaution, another printer than offers only "LPR" printing
8956 // could inadvertently advertise its service under the same name "Stuart's Printer", which might be confusing for users.
8957 mDNSexport mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr,
8958 	const domainlabel *const name, const domainname *const type, const domainname *const domain,
8959 	const domainname *const host,
8960 	const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context)
8961 	{
8962 	mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, kDNSType_SRV, kHostNameTTL, kDNSRecordTypeUnique, Callback, Context);
8963 	if (ConstructServiceName(&rr->namestorage, name, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
8964 	rr->resrec.rdata->u.srv.priority    = 0;
8965 	rr->resrec.rdata->u.srv.weight      = 0;
8966 	rr->resrec.rdata->u.srv.port        = zeroIPPort;
8967 	if (host && host->c[0]) AssignDomainName(&rr->resrec.rdata->u.srv.target, host);
8968 	else rr->AutoTarget = Target_AutoHost;
8969 	return(mDNS_Register(m, rr));
8970 	}
8971 
8972 mDNSexport mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr,
8973 	mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname)
8974 	{
8975 	mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, mDNSNULL, mDNSNULL);
8976 	if (!MakeDomainNameFromDNSNameString(&rr->namestorage, mDNS_DomainTypeNames[DomainType])) return(mStatus_BadParamErr);
8977 	if (!MakeDomainNameFromDNSNameString(&rr->resrec.rdata->u.name, domname))                 return(mStatus_BadParamErr);
8978 	return(mDNS_Register(m, rr));
8979 	}
8980 
8981 mDNSexport mDNSOpaque16 mDNS_NewMessageID(mDNS * const m)
8982 	{
8983 	mDNSOpaque16 id;
8984 	int i;
8985 	for (i=0; i<10; i++)
8986 		{
8987 		AuthRecord *r;
8988 		DNSQuestion *q;
8989 		id = mDNSOpaque16fromIntVal(1 + mDNSRandom(0xFFFE));
8990 		for (r = m->ResourceRecords; r; r=r->next) if (mDNSSameOpaque16(id, r->updateid )) continue;
8991 		for (q = m->Questions;       q; q=q->next) if (mDNSSameOpaque16(id, q->TargetQID)) continue;
8992 		break;
8993 		}
8994 	debugf("mDNS_NewMessageID: %5d", mDNSVal16(id));
8995 	return id;
8996 	}
8997 
8998 // ***************************************************************************
8999 #if COMPILER_LIKES_PRAGMA_MARK
9000 #pragma mark -
9001 #pragma mark - Sleep Proxy Server
9002 #endif
9003 
9004 mDNSlocal void RestartProbing(mDNS *const m, AuthRecord *const rr)
9005 	{
9006 	// We reset ProbeCount, so we'll suppress our own answers for a while, to avoid generating ARP conflicts with a waking machine.
9007 	// If the machine does wake properly then we'll discard our records when we see the first new mDNS probe from that machine.
9008 	// If it does not wake (perhaps we just picked up a stray delayed packet sent before it went to sleep)
9009 	// then we'll transition out of probing state and start answering ARPs again.
9010 	rr->resrec.RecordType = kDNSRecordTypeUnique;
9011 	rr->ProbeCount        = DefaultProbeCountForTypeUnique;
9012 	rr->AnnounceCount     = InitialAnnounceCount;
9013 	InitializeLastAPTime(m, rr);
9014 	}
9015 
9016 mDNSexport void mDNSCoreReceiveRawPacket(mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID)
9017 	{
9018 	static const mDNSOpaque16 Ethertype_IP = { { 0x08, 0x00 } };
9019 	static const mDNSOpaque32 ARP_EthIP_h0 = { { 0x08, 0x06, 0x00, 0x01 } };	// Ethertype (ARP = 0x0806), Hardware address space (Ethernet = 1)
9020 	static const mDNSOpaque32 ARP_EthIP_h1 = { { 0x08, 0x00, 0x06, 0x04 } };	// Protocol address space (IP = 0x0800), hlen, plen
9021 	static const mDNSOpaque16 ARP_op_request = { { 0, 1 } };
9022 	const EthernetHeader *const eth = (const EthernetHeader *)p;
9023 	const ARP_EthIP      *const arp = (const ARP_EthIP      *)(eth+1);
9024 	const IPv4Header     *const v4  = (const IPv4Header     *)(eth+1);
9025 	const IPv6Header     *const v6  = (const IPv6Header     *)(eth+1);
9026 	if (end >= p+42 && *(mDNSu32*)(p+12) == ARP_EthIP_h0.NotAnInteger && *(mDNSu32*)(p+16) == ARP_EthIP_h1.NotAnInteger)
9027 		{
9028 		AuthRecord *rr;
9029 		NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
9030 		if (!intf) return;
9031 
9032 		debugf("Got ARP from %.4a/%.6a for %.4a", &arp->spa, &arp->sha, &arp->tpa);
9033 
9034 		mDNS_Lock(m);
9035 
9036 		// Pass 1:
9037 		// Process ARP Requests and Probes (but not Announcements), and generate an ARP Reply if necessary.
9038 		// We also process and answer ARPs from our own kernel (no special treatment for localhost).
9039 		// We ignore ARP Announcements here -- Announcements are not questions, they're assertions, so we don't need to answer them.
9040 		// The only time we might need to respond to an ARP Announcement is if it's a conflict -- and we check for that in Pass 2 below.
9041 		if (mDNSSameOpaque16(arp->op, ARP_op_request) && !mDNSSameIPv4Address(arp->spa, arp->tpa))
9042 			for (rr = m->ResourceRecords; rr; rr=rr->next)
9043 				if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->AddressProxy.ip.v4, arp->tpa))
9044 					{
9045 					static const char msg1[] = "ARP Req from owner -- re-probing";
9046 					static const char msg2[] = "Ignoring  ARP Request from      ";
9047 					static const char msg3[] = "Creating Local ARP Cache entry  ";
9048 					static const char msg4[] = "Answering ARP Request from      ";
9049 					const char *const msg = mDNSSameEthAddress(&arp->sha, &rr->WakeUp.IMAC) ? msg1 :
9050 											(rr->AnnounceCount == InitialAnnounceCount)     ? msg2 :
9051 											mDNSSameEthAddress(&arp->sha, &intf->MAC)       ? msg3 : msg4;
9052 					LogSPS("%-7s %s %.6a %.4a for %.4a -- H-MAC %.6a I-MAC %.6a %s",
9053 						InterfaceNameForID(m, InterfaceID), msg, &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
9054 					if      (msg == msg1) RestartProbing(m, rr);
9055 					else if (msg == msg3) mDNSPlatformSetLocalARP(&arp->tpa, &rr->WakeUp.IMAC, InterfaceID);
9056 					else if (msg == msg4) SendARP(m, 2, rr, arp->tpa.b, arp->sha.b, arp->spa.b, arp->sha.b);
9057 					}
9058 
9059 		// Pass 2:
9060 		// For all types of ARP packet we check the Sender IP address to make sure it doesn't conflict with any AddressProxy record we're holding.
9061 		// (Strictly speaking we're only checking Announcement/Request/Reply packets, since ARP Probes have zero Sender IP address,
9062 		// so by definition (and by design) they can never conflict with any real (i.e. non-zero) IP address).
9063 		// We ignore ARPs we sent ourselves (Sender MAC address is our MAC address) because our own proxy ARPs do not constitute a conflict that we need to handle.
9064 		// If we see an apparently conflicting ARP, we check the sender hardware address:
9065 		//   If the sender hardware address is the original owner this is benign, so we just suppress our own proxy answering for a while longer.
9066 		//   If the sender hardware address is *not* the original owner, then this is a conflict, and we need to wake the sleeping machine to handle it.
9067 		if (mDNSSameEthAddress(&arp->sha, &intf->MAC))
9068 			debugf("ARP from self for %.4a", &arp->tpa);
9069 		else
9070 			{
9071 			if (!mDNSSameIPv4Address(arp->spa, zerov4Addr))
9072 				for (rr = m->ResourceRecords; rr; rr=rr->next)
9073 					if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->AddressProxy.ip.v4, arp->spa))
9074 						{
9075 						RestartProbing(m, rr);
9076 						if (mDNSSameEthAddress(&arp->sha, &rr->WakeUp.IMAC))
9077 							LogSPS("%-7s ARP %s from owner %.6a %.4a for %-15.4a -- re-starting probing for %s",
9078 								InterfaceNameForID(m, InterfaceID),
9079 								mDNSSameIPv4Address(arp->spa, arp->tpa) ? "Announcement" : mDNSSameOpaque16(arp->op, ARP_op_request) ? "Request     " : "Response    ",
9080 								&arp->sha, &arp->spa, &arp->tpa, ARDisplayString(m, rr));
9081 						else
9082 							{
9083 							LogMsg("%-7s Conflicting ARP from %.6a %.4a for %.4a -- waking H-MAC %.6a I-MAC %.6a %s",
9084 								InterfaceNameForID(m, InterfaceID), &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
9085 							SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password);
9086 							}
9087 						}
9088 			}
9089 
9090 		mDNS_Unlock(m);
9091 		}
9092 	else if (end >= p+34 && mDNSSameOpaque16(eth->ethertype, Ethertype_IP) && (v4->flagsfrags.b[0] & 0x1F) == 0 && v4->flagsfrags.b[1] == 0)
9093 		{
9094 		const mDNSu8 *const trans = p + 14 + (v4->vlen & 0xF) * 4;
9095 		const mDNSu8 *const required = trans + (v4->protocol == 1 ? 4 : v4->protocol == 6 ? 20 : v4->protocol == 17 ? 8 : 0);
9096 		debugf("Got IPv4 from %.4a to %.4a", &v4->src, &v4->dst);
9097 		if (end >= required)
9098 			{
9099 			#define SSH_AsNumber 22
9100 			#define ARD_AsNumber 3283
9101 			#define IPSEC_AsNumber 4500
9102 			static const mDNSIPPort SSH   = { { SSH_AsNumber   >> 8, SSH_AsNumber   & 0xFF } };
9103 			static const mDNSIPPort ARD   = { { ARD_AsNumber   >> 8, ARD_AsNumber   & 0xFF } };
9104 			static const mDNSIPPort IPSEC = { { IPSEC_AsNumber >> 8, IPSEC_AsNumber & 0xFF } };
9105 
9106 			mDNSBool wake = mDNSfalse;
9107 			mDNSIPPort port = zeroIPPort;
9108 
9109 			switch (v4->protocol)
9110 				{
9111 				#define XX wake ? "Received" : "Ignoring", end-p
9112 				case  1:	LogSPS("%s %d-byte ICMP from %.4a to %.4a", XX, &v4->src, &v4->dst);
9113 							break;
9114 
9115 				case  6:	{
9116 							const TCPHeader *const tcp = (const TCPHeader *)trans;
9117 							port = tcp->dst;
9118 
9119 							// Plan to wake if
9120 							// (a) RST is not set, AND
9121 							// (b) packet is SYN, SYN+FIN, or plain data packet (no SYN or FIN). We won't wake for FIN alone.
9122 							wake = (!(tcp->flags & 4) && (tcp->flags & 3) != 1);
9123 
9124 							// For now, to reduce spurious wakeups, we wake only for TCP SYN,
9125 							// except for ssh connections, where we'll wake for plain data packets too
9126 							if (!mDNSSameIPPort(port, SSH) && !(tcp->flags & 2)) wake = mDNSfalse;
9127 
9128 							LogSPS("%s %d-byte TCP from %.4a:%d to %.4a:%d%s%s%s", XX,
9129 								&v4->src, mDNSVal16(tcp->src), &v4->dst, mDNSVal16(port),
9130 								(tcp->flags & 2) ? " SYN" : "",
9131 								(tcp->flags & 1) ? " FIN" : "",
9132 								(tcp->flags & 4) ? " RST" : "");
9133 							}
9134 							break;
9135 
9136 				case 17:	{
9137 							const UDPHeader *const udp = (const UDPHeader *)trans;
9138 							mDNSu16 len = (mDNSu16)((mDNSu16)trans[4] << 8 | trans[5]);
9139 							port = udp->dst;
9140 							wake = mDNStrue;
9141 
9142 							// For Back to My Mac UDP port 4500 (IPSEC) packets, we specially ignore NAT keepalive packets
9143 							if (mDNSSameIPPort(port, IPSEC)) wake = (len != 9 || end < trans + 9 || trans[8] != 0xFF);
9144 
9145 							// For now, because we haven't yet worked out a clean elegant way to do this, we just special-case the
9146 							// Apple Remote Desktop port number -- we ignore all packets to UDP 3283 (the "Net Assistant" port),
9147 							// except for Apple Remote Desktop's explicit manual wakeup packet, which looks like this:
9148 							// UDP header (8 bytes) 13 88 00 6a 41 4e 41 20 (8 bytes) ffffffffffff (6 bytes) 16xMAC (96 bytes) = 118 bytes total
9149 							if (mDNSSameIPPort(port, ARD)) wake = (len >= 118 && end >= trans+10 && trans[8] == 0x13 && trans[9] == 0x88);
9150 
9151 							LogSPS("%s %d-byte UDP from %.4a:%d to %.4a:%d", XX, &v4->src, mDNSVal16(udp->src), &v4->dst, mDNSVal16(port));
9152 							}
9153 							break;
9154 
9155 				default:	LogSPS("%s %d-byte IP packet unknown protocol %d from %.4a to %.4a", XX, v4->protocol, &v4->src, &v4->dst);
9156 							break;
9157 				}
9158 
9159 			if (wake)
9160 				{
9161 				AuthRecord *rr, *r2;
9162 
9163 				mDNS_Lock(m);
9164 				for (rr = m->ResourceRecords; rr; rr=rr->next)
9165 					if (rr->resrec.InterfaceID == InterfaceID &&
9166 						rr->AddressProxy.type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->AddressProxy.ip.v4, v4->dst))
9167 						{
9168 						const mDNSu8 *const tp = (v4->protocol == 6) ? (mDNSu8 *)"\x4_tcp" : (mDNSu8 *)"\x4_udp";
9169 						for (r2 = m->ResourceRecords; r2; r2=r2->next)
9170 							if (r2->resrec.InterfaceID == InterfaceID && mDNSSameEthAddress(&r2->WakeUp.HMAC, &rr->WakeUp.HMAC) &&
9171 								r2->resrec.rrtype == kDNSType_SRV && mDNSSameIPPort(r2->resrec.rdata->u.srv.port, port) &&
9172 								SameDomainLabel(SkipLeadingLabels(r2->resrec.name, 2)->c, tp))
9173 								break;
9174 						if (!r2 && mDNSSameIPPort(port, IPSEC)) r2 = rr;	// So that we wake for BTMM IPSEC packets, even without a matching SRV record
9175 						if (r2)
9176 							{
9177 							rr->AnnounceCount = 0;
9178 							LogMsg("Waking host at %s %.4a H-MAC %.6a I-MAC %.6a for %s",
9179 								InterfaceNameForID(m, rr->resrec.InterfaceID), &v4->dst, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, r2));
9180 							SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password);
9181 							}
9182 						else
9183 							LogSPS("Sleeping host at %s %.4a %.6a has no service on %#s %d",
9184 								InterfaceNameForID(m, rr->resrec.InterfaceID), &v4->dst, &rr->WakeUp.HMAC, tp, mDNSVal16(port));
9185 						}
9186 				mDNS_Unlock(m);
9187 				}
9188 			}
9189 		}
9190 	else if (end >= p+34 && mDNSSameOpaque16(eth->ethertype, Ethertype_IP) && (v4->flagsfrags.b[0] & 0x1F) == 0 && v4->flagsfrags.b[1] == 0)
9191 		{
9192 		debugf("Got IPv6 from %.16a to %.16a", &v4->src, &v6->dst);
9193 		(void)v6;
9194 		}
9195 	}
9196 
9197 mDNSlocal void ConstructSleepProxyServerName(mDNS *const m, domainlabel *name)
9198 	{
9199 	name->c[0] = mDNS_snprintf((char*)name->c+1, 62, "%d-%d-%d-%d %#s",
9200 		m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower, &m->nicelabel);
9201 	}
9202 
9203 mDNSlocal void SleepProxyServerCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
9204 	{
9205 	if (result == mStatus_NameConflict)
9206 		mDNS_RenameAndReregisterService(m, srs, mDNSNULL);
9207 	else if (result == mStatus_MemFree)
9208 		{
9209 		if (m->SleepState)
9210 			m->SPSState = 3;
9211 		else
9212 			{
9213 			m->SPSState = (m->SPSSocket != mDNSNULL);
9214 			if (m->SPSState)
9215 				{
9216 				domainlabel name;
9217 				ConstructSleepProxyServerName(m, &name);
9218 				mDNS_RegisterService(m, srs,
9219 					&name, &SleepProxyServiceType, &localdomain,
9220 					mDNSNULL, m->SPSSocket->port,				// Host, port
9221 					(mDNSu8 *)"", 1,							// TXT data, length
9222 					mDNSNULL, 0,								// Subtypes (none)
9223 					mDNSInterface_Any,							// Interface ID
9224 					SleepProxyServerCallback, mDNSNULL);		// Callback and context
9225 				}
9226 			LogSPS("Sleep Proxy Server %#s %s", srs->RR_SRV.resrec.name->c, m->SPSState ? "started" : "stopped");
9227 			}
9228 		}
9229 	}
9230 
9231 mDNSexport void mDNSCoreBeSleepProxyServer(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower)
9232 	{
9233 	// If turning off SPS, close our socket
9234 	// (Do this first, BEFORE calling mDNS_DeregisterService below)
9235 	if (!sps && m->SPSSocket) { mDNSPlatformUDPClose(m->SPSSocket); m->SPSSocket = mDNSNULL; }
9236 
9237 	// If turning off, or changing type, deregister old name
9238 	if (m->SPSState == 1 && sps != m->SPSType)
9239 		{ m->SPSState = 2; mDNS_DeregisterService(m, &m->SPSRecords); }
9240 
9241 	// Record our new SPS parameters
9242 	m->SPSType          = sps;
9243 	m->SPSPortability   = port;
9244 	m->SPSMarginalPower = marginalpower;
9245 	m->SPSTotalPower    = totpower;
9246 
9247 	// If turning on, open socket and advertise service
9248 	if (sps)
9249 		{
9250 		if (!m->SPSSocket)
9251 			{
9252 			m->SPSSocket = mDNSPlatformUDPSocket(m, zeroIPPort);
9253 			if (!m->SPSSocket) { LogMsg("mDNSCoreBeSleepProxyServer: Failed to allocate SPSSocket"); return; }
9254 			}
9255 		if (m->SPSState == 0) SleepProxyServerCallback(m, &m->SPSRecords, mStatus_MemFree);
9256 		}
9257 	}
9258 
9259 // ***************************************************************************
9260 #if COMPILER_LIKES_PRAGMA_MARK
9261 #pragma mark -
9262 #pragma mark - Startup and Shutdown
9263 #endif
9264 
9265 mDNSlocal void mDNS_GrowCache_internal(mDNS *const m, CacheEntity *storage, mDNSu32 numrecords)
9266 	{
9267 	if (storage && numrecords)
9268 		{
9269 		mDNSu32 i;
9270 		debugf("Adding cache storage for %d more records (%d bytes)", numrecords, numrecords*sizeof(CacheEntity));
9271 		for (i=0; i<numrecords; i++) storage[i].next = &storage[i+1];
9272 		storage[numrecords-1].next = m->rrcache_free;
9273 		m->rrcache_free = storage;
9274 		m->rrcache_size += numrecords;
9275 		}
9276 	}
9277 
9278 mDNSexport void mDNS_GrowCache(mDNS *const m, CacheEntity *storage, mDNSu32 numrecords)
9279 	{
9280 	mDNS_Lock(m);
9281 	mDNS_GrowCache_internal(m, storage, numrecords);
9282 	mDNS_Unlock(m);
9283 	}
9284 
9285 mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
9286 	CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
9287 	mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context)
9288 	{
9289 	mDNSu32 slot;
9290 	mDNSs32 timenow;
9291 	mStatus result;
9292 
9293 	if (!rrcachestorage) rrcachesize = 0;
9294 
9295 	m->p                             = p;
9296 	m->KnownBugs                     = 0;
9297 	m->CanReceiveUnicastOn5353       = mDNSfalse; // Assume we can't receive unicasts on 5353, unless platform layer tells us otherwise
9298 	m->AdvertiseLocalAddresses       = AdvertiseLocalAddresses;
9299 	m->DivertMulticastAdvertisements = mDNSfalse;
9300 	m->mDNSPlatformStatus            = mStatus_Waiting;
9301 	m->UnicastPort4                  = zeroIPPort;
9302 	m->UnicastPort6                  = zeroIPPort;
9303 	m->PrimaryMAC                    = zeroEthAddr;
9304 	m->MainCallback                  = Callback;
9305 	m->MainContext                   = Context;
9306 	m->rec.r.resrec.RecordType       = 0;
9307 
9308 	// For debugging: To catch and report locking failures
9309 	m->mDNS_busy               = 0;
9310 	m->mDNS_reentrancy         = 0;
9311 	m->ShutdownTime            = 0;
9312 	m->lock_rrcache            = 0;
9313 	m->lock_Questions          = 0;
9314 	m->lock_Records            = 0;
9315 
9316 	// Task Scheduling variables
9317 	result = mDNSPlatformTimeInit();
9318 	if (result != mStatus_NoError) return(result);
9319 	m->timenow_adjust = (mDNSs32)mDNSRandom(0xFFFFFFFF);
9320 	timenow = mDNS_TimeNow_NoLock(m);
9321 
9322 	m->timenow                 = 0;		// MUST only be set within mDNS_Lock/mDNS_Unlock section
9323 	m->timenow_last            = timenow;
9324 	m->NextScheduledEvent      = timenow;
9325 	m->SuppressSending         = timenow;
9326 	m->NextCacheCheck          = timenow + 0x78000000;
9327 	m->NextScheduledQuery      = timenow + 0x78000000;
9328 	m->NextScheduledProbe      = timenow + 0x78000000;
9329 	m->NextScheduledResponse   = timenow + 0x78000000;
9330 	m->NextScheduledNATOp      = timenow + 0x78000000;
9331 	m->NextScheduledSPS        = timenow + 0x78000000;
9332 	m->RandomQueryDelay        = 0;
9333 	m->RandomReconfirmDelay    = 0;
9334 	m->PktNum                  = 0;
9335 	m->SleepState              = SleepState_Awake;
9336 	m->SleepSeqNum             = 0;
9337 	m->SystemWakeOnLANEnabled  = mDNSfalse;
9338 	m->DelaySleep              = 0;
9339 	m->SleepLimit              = 0;
9340 
9341 	// These fields only required for mDNS Searcher...
9342 	m->Questions               = mDNSNULL;
9343 	m->NewQuestions            = mDNSNULL;
9344 	m->CurrentQuestion         = mDNSNULL;
9345 	m->LocalOnlyQuestions      = mDNSNULL;
9346 	m->NewLocalOnlyQuestions   = mDNSNULL;
9347 	m->rrcache_size            = 0;
9348 	m->rrcache_totalused       = 0;
9349 	m->rrcache_active          = 0;
9350 	m->rrcache_report          = 10;
9351 	m->rrcache_free            = mDNSNULL;
9352 
9353 	for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) m->rrcache_hash[slot] = mDNSNULL;
9354 
9355 	mDNS_GrowCache_internal(m, rrcachestorage, rrcachesize);
9356 
9357 	// Fields below only required for mDNS Responder...
9358 	m->hostlabel.c[0]          = 0;
9359 	m->nicelabel.c[0]          = 0;
9360 	m->MulticastHostname.c[0]  = 0;
9361 	m->HIHardware.c[0]         = 0;
9362 	m->HISoftware.c[0]         = 0;
9363 	m->ResourceRecords         = mDNSNULL;
9364 	m->DuplicateRecords        = mDNSNULL;
9365 	m->NewLocalRecords         = mDNSNULL;
9366 	m->CurrentRecord           = mDNSNULL;
9367 	m->HostInterfaces          = mDNSNULL;
9368 	m->ProbeFailTime           = 0;
9369 	m->NumFailedProbes         = 0;
9370 	m->SuppressProbes          = 0;
9371 
9372 #ifndef UNICAST_DISABLED
9373 	m->NextuDNSEvent            = timenow + 0x78000000;
9374 	m->NextSRVUpdate            = timenow + 0x78000000;
9375 	m->SuppressStdPort53Queries = 0;
9376 
9377 	m->ServiceRegistrations     = mDNSNULL;
9378 	m->DNSServers               = mDNSNULL;
9379 
9380 	m->Router                   = zeroAddr;
9381 	m->AdvertisedV4             = zeroAddr;
9382 	m->AdvertisedV6             = zeroAddr;
9383 
9384 	m->AuthInfoList             = mDNSNULL;
9385 
9386 	m->ReverseMap.ThisQInterval = -1;
9387 	m->StaticHostname.c[0]      = 0;
9388 	m->FQDN.c[0]                = 0;
9389 	m->Hostnames                = mDNSNULL;
9390 	m->AutoTunnelHostAddr.b[0]  = 0;
9391 	m->AutoTunnelHostAddrActive = mDNSfalse;
9392 	m->AutoTunnelLabel.c[0]     = 0;
9393 
9394 	m->RegisterSearchDomains    = mDNSfalse;
9395 
9396 	// NAT traversal fields
9397 	m->NATTraversals            = mDNSNULL;
9398 	m->CurrentNATTraversal      = mDNSNULL;
9399 	m->retryIntervalGetAddr     = 0;	// delta between time sent and retry
9400 	m->retryGetAddr             = timenow + 0x78000000;	// absolute time when we retry
9401 	m->ExternalAddress          = zerov4Addr;
9402 
9403 	m->NATMcastRecvskt          = mDNSNULL;
9404 	m->LastNATupseconds         = 0;
9405 	m->LastNATReplyLocalTime    = timenow;
9406 	m->LastNATMapResultCode     = NATErr_None;
9407 
9408 	m->UPnPInterfaceID          = 0;
9409 	m->SSDPSocket               = mDNSNULL;
9410 	m->SSDPWANPPPConnection     = mDNSfalse;
9411 	m->UPnPRouterPort           = zeroIPPort;
9412 	m->UPnPSOAPPort             = zeroIPPort;
9413 	m->UPnPRouterURL            = mDNSNULL;
9414 	m->UPnPWANPPPConnection     = mDNSfalse;
9415 	m->UPnPSOAPURL              = mDNSNULL;
9416 	m->UPnPRouterAddressString  = mDNSNULL;
9417 	m->UPnPSOAPAddressString    = mDNSNULL;
9418 	m->SPSType                  = 0;
9419 	m->SPSPortability           = 0;
9420 	m->SPSMarginalPower         = 0;
9421 	m->SPSTotalPower            = 0;
9422 	m->SPSState                 = 0;
9423 	m->SPSProxyListChanged      = mDNSNULL;
9424 	m->SPSSocket                = mDNSNULL;
9425 	m->SPSBrowseCallback        = mDNSNULL;
9426 	m->ProxyRecords             = 0;
9427 
9428 #endif
9429 
9430 #if APPLE_OSX_mDNSResponder
9431 	m->TunnelClients            = mDNSNULL;
9432 #endif
9433 
9434 	result = mDNSPlatformInit(m);
9435 
9436 #ifndef UNICAST_DISABLED
9437 	// It's better to do this *after* the platform layer has set up the
9438 	// interface list and security credentials
9439 	uDNS_SetupDNSConfig(m);						// Get initial DNS configuration
9440 #endif
9441 
9442 	return(result);
9443 	}
9444 
9445 mDNSexport void mDNS_ConfigChanged(mDNS *const m)
9446 	{
9447 	if (m->SPSState == 1)
9448 		{
9449 		domainlabel name, newname;
9450 		domainname type, domain;
9451 		DeconstructServiceName(m->SPSRecords.RR_SRV.resrec.name, &name, &type, &domain);
9452 		ConstructSleepProxyServerName(m, &newname);
9453 		if (!SameDomainLabelCS(name.c, newname.c))
9454 			{
9455 			LogSPS("Renaming SPS from “%#s” to “%#s”", name.c, newname.c);
9456 			// When SleepProxyServerCallback gets the mStatus_MemFree message,
9457 			// it will reregister the service under the new name
9458 			m->SPSState = 2;
9459 			mDNS_DeregisterService(m, &m->SPSRecords);
9460 			}
9461 		}
9462 
9463 	if (m->MainCallback)
9464 		m->MainCallback(m, mStatus_ConfigChanged);
9465 	}
9466 
9467 mDNSlocal void DynDNSHostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
9468 	{
9469 	(void)m;	// unused
9470 	debugf("NameStatusCallback: result %d for registration of name %##s", result, rr->resrec.name->c);
9471 	mDNSPlatformDynDNSHostNameStatusChanged(rr->resrec.name, result);
9472 	}
9473 
9474 mDNSlocal void PurgeOrReconfirmCacheRecord(mDNS *const m, CacheRecord *cr, const DNSServer * const ptr, mDNSBool lameduck)
9475 	{
9476 	mDNSBool purge = cr->resrec.RecordType == kDNSRecordTypePacketNegative ||
9477 					 cr->resrec.rrtype     == kDNSType_A ||
9478 					 cr->resrec.rrtype     == kDNSType_AAAA ||
9479 					 cr->resrec.rrtype     == kDNSType_SRV;
9480 
9481 	(void) lameduck;
9482 	(void) ptr;
9483 	debugf("uDNS_SetupDNSConfig: %s cache record due to %s server %p %#a:%d (%##s): %s", purge ? "purging" : "reconfirming", lameduck ? "lame duck" : "new", ptr, &ptr->addr, mDNSVal16(ptr->port), ptr->domain.c, CRDisplayString(m, cr));
9484 
9485 	if (purge) mDNS_PurgeCacheResourceRecord(m, cr);
9486 	else mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
9487 	}
9488 
9489 mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
9490 	{
9491 	mDNSu32 slot;
9492 	CacheGroup *cg;
9493 	CacheRecord *cr;
9494 
9495 	mDNSAddr     v4, v6, r;
9496 	domainname   fqdn;
9497 	DNSServer   *ptr, **p = &m->DNSServers;
9498 	const DNSServer *oldServers = m->DNSServers;
9499 	DNSQuestion *q;
9500 
9501 	debugf("uDNS_SetupDNSConfig: entry");
9502 
9503 	if (m->RegisterSearchDomains) uDNS_RegisterSearchDomains(m);
9504 
9505 	mDNS_Lock(m);
9506 
9507 	// Let the platform layer get the current DNS information
9508 	// The m->RegisterSearchDomains boolean is so that we lazily get the search domain list only on-demand
9509 	// (no need to hit the network with domain enumeration queries until we actually need that information).
9510 	for (ptr = m->DNSServers; ptr; ptr = ptr->next) ptr->flags |= DNSServer_FlagDelete;
9511 
9512 	mDNSPlatformSetDNSConfig(m, mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL);
9513 
9514 	// Update our qDNSServer pointers before we go and free the DNSServer object memory
9515 	for (q = m->Questions; q; q=q->next)
9516 		if (!mDNSOpaque16IsZero(q->TargetQID))
9517 			{
9518 			DNSServer *s = GetServerForName(m, &q->qname);
9519 			DNSServer *t = q->qDNSServer;
9520 			if (t != s)
9521 				{
9522 				// If DNS Server for this question has changed, reactivate it
9523 				debugf("uDNS_SetupDNSConfig: Updating DNS Server from %p %#a:%d (%##s) to %p %#a:%d (%##s) for %##s (%s)",
9524 					t, t ? &t->addr : mDNSNULL, mDNSVal16(t ? t->port : zeroIPPort), t ? t->domain.c : (mDNSu8*)"",
9525 					s, s ? &s->addr : mDNSNULL, mDNSVal16(s ? s->port : zeroIPPort), s ? s->domain.c : (mDNSu8*)"",
9526 					q->qname.c, DNSTypeName(q->qtype));
9527 				q->qDNSServer = s;
9528 				q->unansweredQueries = 0;
9529 				ActivateUnicastQuery(m, q, mDNStrue);
9530 				}
9531 			}
9532 
9533 	// Flush all records that match a new resolver
9534 	FORALL_CACHERECORDS(slot, cg, cr)
9535 		{
9536 		ptr = GetServerForName(m, cr->resrec.name);
9537 		if (ptr && (ptr->flags & DNSServer_FlagNew) && !cr->resrec.InterfaceID)
9538 			PurgeOrReconfirmCacheRecord(m, cr, ptr, mDNSfalse);
9539 		}
9540 
9541 	while (*p)
9542 		{
9543 		if (((*p)->flags & DNSServer_FlagDelete) != 0)
9544 			{
9545 			// Scan our cache, looking for uDNS records that we would have queried this server for.
9546 			// We reconfirm any records that match, because in this world of split DNS, firewalls, etc.
9547 			// different DNS servers can give different answers to the same question.
9548 			ptr = *p;
9549 			ptr->flags &= ~DNSServer_FlagDelete;	// Clear del so GetServerForName will (temporarily) find this server again before it's finally deleted
9550 			FORALL_CACHERECORDS(slot, cg, cr)
9551 				if (!cr->resrec.InterfaceID && GetServerForName(m, cr->resrec.name) == ptr)
9552 					PurgeOrReconfirmCacheRecord(m, cr, ptr, mDNStrue);
9553 			*p = (*p)->next;
9554 			debugf("uDNS_SetupDNSConfig: Deleting server %p %#a:%d (%##s)", ptr, &ptr->addr, mDNSVal16(ptr->port), ptr->domain.c);
9555 			mDNSPlatformMemFree(ptr);
9556 			}
9557 		else
9558 			{
9559 			(*p)->flags &= ~DNSServer_FlagNew;
9560 			p = &(*p)->next;
9561 			}
9562 		}
9563 
9564 	// If we now have no DNS servers at all and we used to have some, then immediately purge all unicast cache records (including for LLQs).
9565 	// This is important for giving prompt remove events when the user disconnects the Ethernet cable or turns off wireless.
9566 	// Otherwise, stale data lingers for 5-10 seconds, which is not the user-experience people expect from Bonjour.
9567 	// Similarly, if we now have some DNS servers and we used to have none, we want to purge any fake negative results we may have generated.
9568 	if ((m->DNSServers != mDNSNULL) != (oldServers != mDNSNULL))
9569 		{
9570 		int count = 0;
9571 		FORALL_CACHERECORDS(slot, cg, cr) if (!cr->resrec.InterfaceID) { mDNS_PurgeCacheResourceRecord(m, cr); count++; }
9572 		LogInfo("uDNS_SetupDNSConfig: %s available; purged %d unicast DNS records from cache",
9573 			m->DNSServers ? "DNS server became" : "No DNS servers", count);
9574 		}
9575 
9576 	// If we no longer have any DNS servers, we need to force anything that needs to get zone data
9577 	// to get that information again (which will fail, since we have no more DNS servers)
9578 	if ((m->DNSServers == mDNSNULL) && (oldServers != mDNSNULL))	RestartRecordGetZoneData(m);
9579 
9580 	// Did our FQDN change?
9581 	if (!SameDomainName(&fqdn, &m->FQDN))
9582 		{
9583 		if (m->FQDN.c[0]) mDNS_RemoveDynDNSHostName(m, &m->FQDN);
9584 
9585 		AssignDomainName(&m->FQDN, &fqdn);
9586 
9587 		if (m->FQDN.c[0])
9588 			{
9589 			mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1);
9590 			mDNS_AddDynDNSHostName(m, &m->FQDN, DynDNSHostNameCallback, mDNSNULL);
9591 			}
9592 		}
9593 
9594 	mDNS_Unlock(m);
9595 
9596 	// handle router and primary interface changes
9597 	v4 = v6 = r = zeroAddr;
9598 	v4.type = r.type = mDNSAddrType_IPv4;
9599 
9600 	if (mDNSPlatformGetPrimaryInterface(m, &v4, &v6, &r) == mStatus_NoError && !mDNSv4AddressIsLinkLocal(&v4.ip.v4))
9601 		{
9602 		mDNS_SetPrimaryInterfaceInfo(m,
9603 			!mDNSIPv4AddressIsZero(v4.ip.v4) ? &v4 : mDNSNULL,
9604 			!mDNSIPv6AddressIsZero(v6.ip.v6) ? &v6 : mDNSNULL,
9605 			!mDNSIPv4AddressIsZero(r .ip.v4) ? &r  : mDNSNULL);
9606 		}
9607 	else
9608 		{
9609 		mDNS_SetPrimaryInterfaceInfo(m, mDNSNULL, mDNSNULL, mDNSNULL);
9610 		if (m->FQDN.c[0]) mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1);	// Set status to 1 to indicate temporary failure
9611 		}
9612 
9613 	return mStatus_NoError;
9614 	}
9615 
9616 mDNSexport void mDNSCoreInitComplete(mDNS *const m, mStatus result)
9617 	{
9618 	m->mDNSPlatformStatus = result;
9619 	if (m->MainCallback)
9620 		{
9621 		mDNS_Lock(m);
9622 		mDNS_DropLockBeforeCallback();		// Allow client to legally make mDNS API calls from the callback
9623 		m->MainCallback(m, mStatus_NoError);
9624 		mDNS_ReclaimLockAfterCallback();	// Decrement mDNS_reentrancy to block mDNS API calls again
9625 		mDNS_Unlock(m);
9626 		}
9627 	}
9628 
9629 extern ServiceRecordSet *CurrentServiceRecordSet;
9630 
9631 mDNSlocal void DeregLoop(mDNS *const m, AuthRecord *const start)
9632 	{
9633 	m->CurrentRecord = start;
9634 	while (m->CurrentRecord)
9635 		{
9636 		AuthRecord *rr = m->CurrentRecord;
9637 		if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
9638 			{
9639 			LogInfo("DeregLoop: Deregistering %p %02X %s", rr, rr->resrec.RecordType, ARDisplayString(m, rr));
9640 			mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
9641 			}
9642 		// Note: We mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because
9643 		// the list may have been changed in that call.
9644 		if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
9645 			m->CurrentRecord = rr->next;
9646 		}
9647 	}
9648 
9649 mDNSexport void mDNS_StartExit(mDNS *const m)
9650 	{
9651 	NetworkInterfaceInfo *intf;
9652 	AuthRecord *rr;
9653 
9654 	mDNS_Lock(m);
9655 
9656 	m->ShutdownTime = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5);
9657 
9658 	mDNS_DropLockBeforeCallback();		// mDNSCoreBeSleepProxyServer expects to be called without the lock held, so we emulate that here
9659 	mDNSCoreBeSleepProxyServer(m, 0, 0, 0, 0);
9660 	mDNS_ReclaimLockAfterCallback();
9661 
9662 #ifndef UNICAST_DISABLED
9663 	{
9664 	SearchListElem *s;
9665 	SuspendLLQs(m);
9666 	// Don't need to do SleepRecordRegistrations() or SleepServiceRegistrations() here,
9667 	// because we deregister all records and services later in this routine
9668 	while (m->Hostnames) mDNS_RemoveDynDNSHostName(m, &m->Hostnames->fqdn);
9669 
9670 	// For each member of our SearchList, deregister any records it may have created, and cut them from the list.
9671 	// Otherwise they'll be forcibly deregistered for us (without being cut them from the appropriate list)
9672 	// and we may crash because the list still contains dangling pointers.
9673 	for (s = SearchList; s; s = s->next)
9674 		while (s->AuthRecs)
9675 			{
9676 			ARListElem *dereg = s->AuthRecs;
9677 			s->AuthRecs = s->AuthRecs->next;
9678 			mDNS_Deregister_internal(m, &dereg->ar, mDNS_Dereg_normal);	// Memory will be freed in the FreeARElemCallback
9679 			}
9680 	}
9681 #endif
9682 
9683 	for (intf = m->HostInterfaces; intf; intf = intf->next)
9684 		if (intf->Advertise)
9685 			DeadvertiseInterface(m, intf);
9686 
9687 	// Shut down all our active NAT Traversals
9688 	while (m->NATTraversals)
9689 		{
9690 		NATTraversalInfo *t = m->NATTraversals;
9691 		mDNS_StopNATOperation_internal(m, t);		// This will cut 't' from the list, thereby advancing m->NATTraversals in the process
9692 
9693 		// After stopping the NAT Traversal, we zero out the fields.
9694 		// This has particularly important implications for our AutoTunnel records --
9695 		// when we deregister our AutoTunnel records below, we don't want their mStatus_MemFree
9696 		// handlers to just turn around and attempt to re-register those same records.
9697 		// Clearing t->ExternalPort will cause the mStatus_MemFree callback handlers to not do this.
9698 		t->ExternalAddress = zerov4Addr;
9699 		t->ExternalPort    = zeroIPPort;
9700 		t->Lifetime        = 0;
9701 		t->Result          = mStatus_NoError;
9702 		}
9703 
9704 	// Make sure there are nothing but deregistering records remaining in the list
9705 	if (m->CurrentRecord)
9706 		LogMsg("mDNS_StartExit: ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
9707 
9708 	// We're in the process of shutting down, so queries, etc. are no longer available.
9709 	// Consequently, determining certain information, e.g. the uDNS update server's IP
9710 	// address, will not be possible.  The records on the main list are more likely to
9711 	// already contain such information, so we deregister the duplicate records first.
9712 	LogInfo("mDNS_StartExit: Deregistering duplicate resource records");
9713 	DeregLoop(m, m->DuplicateRecords);
9714 	LogInfo("mDNS_StartExit: Deregistering resource records");
9715 	DeregLoop(m, m->ResourceRecords);
9716 
9717 	// If we scheduled a response to send goodbye packets, we set NextScheduledResponse to now. Normally when deregistering records,
9718 	// we allow up to 100ms delay (to help improve record grouping) but when shutting down we don't want any such delay.
9719 	if (m->NextScheduledResponse - m->timenow < mDNSPlatformOneSecond)
9720 		{
9721 		m->NextScheduledResponse = m->timenow;
9722 		m->SuppressSending = 0;
9723 		}
9724 
9725 #if !defined(UNICAST_DISABLED) && USE_SEPARATE_UDNS_SERVICE_LIST
9726 	CurrentServiceRecordSet = m->ServiceRegistrations;
9727 	while (CurrentServiceRecordSet)
9728 		{
9729 		ServiceRecordSet *srs = CurrentServiceRecordSet;
9730 		LogInfo("mDNS_StartExit: Deregistering uDNS service %##s", srs->RR_SRV.resrec.name->c);
9731 		uDNS_DeregisterService(m, srs);
9732 		if (CurrentServiceRecordSet == srs)
9733 			CurrentServiceRecordSet = srs->uDNS_next;
9734 		}
9735 #endif
9736 
9737 	if (m->ResourceRecords) LogInfo("mDNS_StartExit: Sending final record deregistrations");
9738 	else                    LogInfo("mDNS_StartExit: No deregistering records remain");
9739 
9740 	if (m->ServiceRegistrations) LogInfo("mDNS_StartExit: Sending final uDNS service deregistrations");
9741 	else                         LogInfo("mDNS_StartExit: No deregistering uDNS services remain");
9742 
9743 	for (rr = m->DuplicateRecords; rr; rr = rr->next)
9744 		LogMsg("mDNS_StartExit: Should not still have Duplicate Records remaining: %02X %s", rr->resrec.RecordType, ARDisplayString(m, rr));
9745 
9746 	// If any deregistering records remain, send their deregistration announcements before we exit
9747 	if (m->mDNSPlatformStatus != mStatus_NoError) DiscardDeregistrations(m);
9748 
9749 	mDNS_Unlock(m);
9750 
9751 	LogInfo("mDNS_StartExit: done");
9752 	}
9753 
9754 mDNSexport void mDNS_FinalExit(mDNS *const m)
9755 	{
9756 	mDNSu32 rrcache_active = 0;
9757 	mDNSu32 rrcache_totalused = 0;
9758 	mDNSu32 slot;
9759 	AuthRecord *rr;
9760 	ServiceRecordSet *srs;
9761 
9762 	LogInfo("mDNS_FinalExit: mDNSPlatformClose");
9763 	mDNSPlatformClose(m);
9764 
9765 	rrcache_totalused = m->rrcache_totalused;
9766 	for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
9767 		{
9768 		while (m->rrcache_hash[slot])
9769 			{
9770 			CacheGroup *cg = m->rrcache_hash[slot];
9771 			while (cg->members)
9772 				{
9773 				CacheRecord *cr = cg->members;
9774 				cg->members = cg->members->next;
9775 				if (cr->CRActiveQuestion) rrcache_active++;
9776 				ReleaseCacheRecord(m, cr);
9777 				}
9778 			cg->rrcache_tail = &cg->members;
9779 			ReleaseCacheGroup(m, &m->rrcache_hash[slot]);
9780 			}
9781 		}
9782 	debugf("mDNS_FinalExit: RR Cache was using %ld records, %lu active", rrcache_totalused, rrcache_active);
9783 	if (rrcache_active != m->rrcache_active)
9784 		LogMsg("*** ERROR *** rrcache_active %lu != m->rrcache_active %lu", rrcache_active, m->rrcache_active);
9785 
9786 	for (rr = m->ResourceRecords; rr; rr = rr->next)
9787 		LogMsg("mDNS_FinalExit failed to send goodbye for: %p %02X %s", rr, rr->resrec.RecordType, ARDisplayString(m, rr));
9788 
9789 	for (srs = m->ServiceRegistrations; srs; srs = srs->uDNS_next)
9790 		LogMsg("mDNS_FinalExit failed to deregister service: %p %##s", srs, srs->RR_SRV.resrec.name->c);
9791 
9792 	LogInfo("mDNS_FinalExit: done");
9793 	}
9794